diff --git a/go.mod b/go.mod index 9f2386da42..40282ab490 100644 --- a/go.mod +++ b/go.mod @@ -5,143 +5,123 @@ go 1.19 require ( github.com/blang/semver/v4 v4.0.0 github.com/go-bindata/go-bindata/v3 v3.1.3 - github.com/go-logr/logr v1.2.3 + github.com/go-logr/logr v1.2.4 github.com/golang/mock v1.6.0 github.com/googleapis/gnostic v0.5.5 github.com/grpc-ecosystem/grpc-health-probe v0.4.11 github.com/maxbrunsfeld/counterfeiter/v6 v6.4.1 github.com/mikefarah/yq/v3 v3.0.0-20201202084205-8846255d1c37 - github.com/onsi/ginkgo/v2 v2.1.6 + github.com/onsi/ginkgo/v2 v2.9.5 github.com/openshift/api v3.9.0+incompatible - github.com/operator-framework/api v0.17.3 + github.com/operator-framework/api v0.17.6 github.com/operator-framework/operator-lifecycle-manager v0.0.0-00010101000000-000000000000 github.com/operator-framework/operator-registry v1.17.5 - github.com/sirupsen/logrus v1.8.1 - github.com/spf13/cobra v1.4.0 - github.com/stretchr/testify v1.8.0 + github.com/sirupsen/logrus v1.9.2 + github.com/spf13/cobra v1.7.0 + github.com/stretchr/testify v1.8.3 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 - google.golang.org/protobuf v1.28.0 + google.golang.org/protobuf v1.30.0 gopkg.in/yaml.v2 v2.4.0 - helm.sh/helm/v3 v3.9.0 - k8s.io/api v0.25.3 - k8s.io/apimachinery v0.25.3 - k8s.io/client-go v0.25.3 - k8s.io/code-generator v0.25.3 - k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 - k8s.io/utils v0.0.0-20220823124924-e9cbc92d1a73 - sigs.k8s.io/controller-runtime v0.13.0 + helm.sh/helm/v3 v3.11.1 + k8s.io/api v0.27.2 + k8s.io/apimachinery v0.27.2 + k8s.io/client-go v0.27.2 + k8s.io/code-generator v0.27.2 + k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f + k8s.io/utils v0.0.0-20230209194617-a36077c30491 + sigs.k8s.io/controller-runtime v0.15.0 sigs.k8s.io/controller-tools v0.8.0 ) replace google.golang.org/grpc => google.golang.org/grpc v1.40.0 -replace ( - go.opentelemetry.io/contrib => go.opentelemetry.io/contrib v0.20.0 - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp => go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0 - go.opentelemetry.io/otel/exporters/otlp => go.opentelemetry.io/otel/exporters/otlp v0.20.0 - go.opentelemetry.io/otel/metric => go.opentelemetry.io/otel/metric v0.20.0 - go.opentelemetry.io/otel/oteltest => go.opentelemetry.io/otel/oteltest v0.20.0 - go.opentelemetry.io/otel/sdk/export/metric => go.opentelemetry.io/otel/sdk/export/metric v0.20.0 - go.opentelemetry.io/otel/sdk/metric => go.opentelemetry.io/otel/sdk/metric v0.20.0 - go.opentelemetry.io/otel/trace => go.opentelemetry.io/otel/trace v0.20.0 - go.opentelemetry.io/proto/otlp => go.opentelemetry.io/proto/otlp v0.7.0 -) - require ( - cloud.google.com/go v0.99.0 // indirect - github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect - github.com/Azure/go-autorest v14.2.0+incompatible // indirect - github.com/Azure/go-autorest/autorest v0.11.27 // indirect - github.com/Azure/go-autorest/autorest/adal v0.9.20 // indirect - github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect - github.com/Azure/go-autorest/logger v0.2.1 // indirect - github.com/Azure/go-autorest/tracing v0.6.0 // indirect - github.com/BurntSushi/toml v1.0.0 // indirect - github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd // indirect + github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect + github.com/BurntSushi/toml v1.2.1 // indirect + github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect - github.com/Masterminds/semver/v3 v3.1.1 // indirect - github.com/Masterminds/sprig/v3 v3.2.2 // indirect - github.com/Masterminds/squirrel v1.5.2 // indirect + github.com/Masterminds/semver/v3 v3.2.0 // indirect + github.com/Masterminds/sprig/v3 v3.2.3 // indirect + github.com/Masterminds/squirrel v1.5.3 // indirect github.com/Masterminds/vcs v1.13.3 // indirect - github.com/Microsoft/go-winio v0.5.1 // indirect - github.com/Microsoft/hcsshim v0.9.2 // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/Microsoft/hcsshim v0.9.6 // indirect github.com/NYTimes/gziphandler v1.1.1 // indirect - github.com/PuerkitoBio/purell v1.1.1 // indirect - github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect github.com/adrg/xdg v0.4.0 // indirect - github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220418222510-f25a4f6275ed // indirect + github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df // indirect github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/blang/semver v3.5.1+incompatible // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect - github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 // indirect - github.com/containerd/cgroups v1.0.3 // indirect - github.com/containerd/containerd v1.6.3 // indirect - github.com/containerd/continuity v0.2.2 // indirect + github.com/cenkalti/backoff/v4 v4.2.0 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/chai2010/gettext-go v1.0.2 // indirect + github.com/containerd/cgroups v1.0.4 // indirect + github.com/containerd/containerd v1.6.18 // indirect + github.com/containerd/continuity v0.3.0 // indirect github.com/containerd/ttrpc v1.1.0 // indirect github.com/coreos/go-semver v0.3.0 // indirect - github.com/coreos/go-systemd/v22 v22.3.2 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect + github.com/coreos/go-systemd/v22 v22.4.0 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/cyphar/filepath-securejoin v0.2.3 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/distribution/distribution v2.7.1+incompatible // indirect - github.com/docker/cli v20.10.12+incompatible // indirect - github.com/docker/distribution v2.8.1+incompatible // indirect - github.com/docker/docker v20.10.14+incompatible // indirect - github.com/docker/docker-credential-helpers v0.6.4 // indirect + github.com/docker/cli v20.10.21+incompatible // indirect + github.com/docker/distribution v2.8.2+incompatible // indirect + github.com/docker/docker v20.10.24+incompatible // indirect + github.com/docker/docker-credential-helpers v0.7.0 // indirect github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-metrics v0.0.1 // indirect - github.com/docker/go-units v0.4.0 // indirect - github.com/emicklei/go-restful/v3 v3.8.0 // indirect - github.com/evanphx/json-patch v4.12.0+incompatible // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/emicklei/go-restful/v3 v3.9.0 // indirect + github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect github.com/fatih/color v1.13.0 // indirect - github.com/felixge/httpsnoop v1.0.1 // indirect - github.com/fsnotify/fsnotify v1.5.4 // indirect + github.com/felixge/httpsnoop v1.0.3 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/fvbommel/sortorder v1.0.1 // indirect github.com/ghodss/yaml v1.0.0 // indirect github.com/go-air/gini v1.0.4 // indirect - github.com/go-errors/errors v1.0.1 // indirect + github.com/go-errors/errors v1.4.2 // indirect github.com/go-git/gcfg v1.5.0 // indirect github.com/go-git/go-billy/v5 v5.1.0 // indirect github.com/go-git/go-git/v5 v5.3.0 // indirect github.com/go-gorp/gorp/v3 v3.0.2 // indirect - github.com/go-logr/zapr v1.2.3 // indirect - github.com/go-openapi/jsonpointer v0.19.5 // indirect - github.com/go-openapi/jsonreference v0.19.5 // indirect - github.com/go-openapi/swag v0.19.14 // indirect - github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-logr/zapr v1.2.4 // indirect + github.com/go-openapi/jsonpointer v0.19.6 // indirect + github.com/go-openapi/jsonreference v0.20.1 // indirect + github.com/go-openapi/swag v0.22.3 // indirect + github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/gobuffalo/flect v0.2.3 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/goccy/go-yaml v1.8.1 // indirect github.com/gofrs/flock v0.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt/v4 v4.2.0 // indirect - github.com/golang-migrate/migrate/v4 v4.6.2 // indirect + github.com/golang-migrate/migrate/v4 v4.16.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/google/btree v1.0.1 // indirect - github.com/google/cel-go v0.12.5 // indirect + github.com/google/cel-go v0.15.3 // indirect github.com/google/gnostic v0.5.7-v3refs // indirect - github.com/google/go-cmp v0.5.8 // indirect + github.com/google/go-cmp v0.5.9 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/google/uuid v1.2.0 // indirect + github.com/google/uuid v1.3.0 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/gosuri/uitable v0.0.4 // indirect github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect - github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect github.com/h2non/filetype v1.1.1 // indirect github.com/h2non/go-is-svg v0.0.0-20160927212452-35e8c4b0612c // indirect - github.com/huandu/xstrings v1.3.2 // indirect + github.com/huandu/xstrings v1.3.3 // indirect github.com/imdario/mergo v0.3.12 // indirect - github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/itchyny/astgen-go v0.0.0-20200519013840-cf3ea398f645 // indirect github.com/itchyny/gojq v0.11.0 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/jmoiron/sqlx v1.3.4 // indirect + github.com/jmoiron/sqlx v1.3.5 // indirect github.com/joelanford/ignore v0.0.0-20210607151042-0d25dc18b62d // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -151,14 +131,14 @@ require ( github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect github.com/lestrrat-go/strftime v1.0.1 // indirect - github.com/lib/pq v1.10.4 // indirect + github.com/lib/pq v1.10.7 // indirect github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect - github.com/mailru/easyjson v0.7.6 // indirect + github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-isatty v0.0.14 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect - github.com/mattn/go-sqlite3 v1.14.10 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect + github.com/mattn/go-sqlite3 v1.14.16 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-wordwrap v1.0.0 // indirect github.com/mitchellh/hashstructure v1.0.0 // indirect @@ -167,27 +147,26 @@ require ( github.com/moby/locker v1.0.1 // indirect github.com/moby/spdystream v0.2.0 // indirect github.com/moby/sys/mountinfo v0.5.0 // indirect - github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect + github.com/moby/term v0.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect github.com/morikuni/aec v1.0.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/onsi/gomega v1.20.1 // indirect + github.com/onsi/gomega v1.27.7 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect + github.com/opencontainers/image-spec v1.1.0-rc2 // indirect github.com/openshift/client-go v0.0.0-20220525160904-9e1acff93e4a // indirect github.com/otiai10/copy v1.2.0 // indirect github.com/pbnjay/strptime v0.0.0-20140226051138-5c05b0d668c9 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.12.2 // indirect - github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.32.1 // indirect - github.com/prometheus/procfs v0.7.3 // indirect - github.com/rubenv/sql-migrate v1.1.1 // indirect - github.com/russross/blackfriday v1.5.2 // indirect + github.com/prometheus/client_golang v1.15.1 // indirect + github.com/prometheus/client_model v0.4.0 // indirect + github.com/prometheus/common v0.42.0 // indirect + github.com/prometheus/procfs v0.9.0 // indirect + github.com/rubenv/sql-migrate v1.2.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/shopspring/decimal v1.2.0 // indirect github.com/spf13/cast v1.4.1 // indirect @@ -197,64 +176,65 @@ require ( github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect - github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca // indirect + github.com/xlab/treeprint v1.1.0 // indirect github.com/zeebo/errs v1.3.0 // indirect go.etcd.io/bbolt v1.3.6 // indirect - go.etcd.io/etcd/api/v3 v3.5.4 // indirect - go.etcd.io/etcd/client/pkg/v3 v3.5.4 // indirect - go.etcd.io/etcd/client/v3 v3.5.4 // indirect - go.opencensus.io v0.23.0 // indirect - go.opentelemetry.io/contrib v1.3.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.28.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0 // indirect - go.opentelemetry.io/otel v1.3.0 // indirect - go.opentelemetry.io/otel/exporters/otlp v0.20.0 // indirect - go.opentelemetry.io/otel/metric v0.20.0 // indirect - go.opentelemetry.io/otel/sdk v1.3.0 // indirect - go.opentelemetry.io/otel/sdk/export/metric v0.20.0 // indirect - go.opentelemetry.io/otel/sdk/metric v0.20.0 // indirect - go.opentelemetry.io/otel/trace v1.3.0 // indirect - go.opentelemetry.io/proto/otlp v0.12.0 // indirect + go.etcd.io/etcd/api/v3 v3.5.7 // indirect + go.etcd.io/etcd/client/pkg/v3 v3.5.7 // indirect + go.etcd.io/etcd/client/v3 v3.5.7 // indirect + go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.35.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.35.1 // indirect + go.opentelemetry.io/otel v1.12.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.12.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.12.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.12.0 // indirect + go.opentelemetry.io/otel/metric v0.31.0 // indirect + go.opentelemetry.io/otel/sdk v1.12.0 // indirect + go.opentelemetry.io/otel/trace v1.12.0 // indirect + go.opentelemetry.io/proto/otlp v0.19.0 // indirect go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect - go.uber.org/zap v1.21.0 // indirect - golang.org/x/crypto v0.0.0-20220408190544-5352b0902921 // indirect + go.uber.org/zap v1.24.0 // indirect + golang.org/x/crypto v0.7.0 // indirect + golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0 // indirect golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect - golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect - golang.org/x/net v0.4.0 // indirect - golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 // indirect - golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect - golang.org/x/sys v0.3.0 // indirect - golang.org/x/term v0.3.0 // indirect - golang.org/x/text v0.5.0 // indirect - golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect - golang.org/x/tools v0.1.12 // indirect - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect - gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect + golang.org/x/mod v0.10.0 // indirect + golang.org/x/net v0.10.0 // indirect + golang.org/x/oauth2 v0.5.0 // indirect + golang.org/x/sync v0.2.0 // indirect + golang.org/x/sys v0.8.0 // indirect + golang.org/x/term v0.8.0 // indirect + golang.org/x/text v0.9.0 // indirect + golang.org/x/time v0.3.0 // indirect + golang.org/x/tools v0.9.1 // indirect + golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect + gomodules.xyz/jsonpatch/v2 v2.3.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 // indirect - google.golang.org/grpc v1.47.0 // indirect + google.golang.org/genproto v0.0.0-20230525154841-bd750badd5c6 // indirect + google.golang.org/grpc v1.54.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.25.3 // indirect - k8s.io/apiserver v0.25.3 // indirect - k8s.io/cli-runtime v0.24.0 // indirect - k8s.io/component-base v0.25.3 // indirect - k8s.io/gengo v0.0.0-20211129171323-c02415ce4185 // indirect + k8s.io/apiextensions-apiserver v0.27.2 // indirect + k8s.io/apiserver v0.27.2 // indirect + k8s.io/cli-runtime v0.27.1 // indirect + k8s.io/component-base v0.27.2 // indirect + k8s.io/gengo v0.0.0-20220902162205-c0856e24416d // indirect k8s.io/klog v1.0.0 // indirect - k8s.io/klog/v2 v2.80.1 // indirect + k8s.io/klog/v2 v2.90.1 // indirect + k8s.io/kms v0.27.2 // indirect k8s.io/kube-aggregator v0.25.3 // indirect - k8s.io/kubectl v0.24.0 // indirect - oras.land/oras-go v1.1.0 // indirect - sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.33 // indirect - sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect - sigs.k8s.io/kustomize/api v0.11.4 // indirect - sigs.k8s.io/kustomize/kyaml v0.13.6 // indirect + k8s.io/kubectl v0.27.1 // indirect + oras.land/oras-go v1.2.2 // indirect + sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/kustomize/api v0.13.2 // indirect + sigs.k8s.io/kustomize/kyaml v0.14.1 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect sigs.k8s.io/yaml v1.3.0 // indirect ) @@ -263,9 +243,6 @@ replace ( // latest tag resolves to a very old version. this is only used for spinning up local test registries github.com/docker/distribution => github.com/docker/distribution v0.0.0-20191216044856-a8371794149d - // pin to ginkgo v1 version of gomega (v1.18+ relies on ginkgo v2) - github.com/onsi/gomega => github.com/onsi/gomega v1.17.0 - // controller runtime github.com/openshift/api => github.com/openshift/api v0.0.0-20210517065120-b325f58df679 github.com/openshift/client-go => github.com/openshift/client-go v0.0.0-20200326155132-2a6cd50aedd0 // release-4.5 @@ -275,9 +252,6 @@ replace ( github.com/operator-framework/operator-lifecycle-manager => ./staging/operator-lifecycle-manager github.com/operator-framework/operator-registry => ./staging/operator-registry - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc => go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0 - go.opentelemetry.io/otel => go.opentelemetry.io/otel v0.20.0 - go.opentelemetry.io/otel/sdk => go.opentelemetry.io/otel/sdk v0.20.0 // this should be removeable once https://issues.redhat.com/browse/CLOUDBLD-11068 is resolved k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.25.0 diff --git a/go.sum b/go.sum index 335654b5f6..0e81ee8b3e 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,5 @@ bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= -bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= @@ -20,21 +18,15 @@ cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmW cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= -cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= -cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= -cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= -cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= -cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= -cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= -cloud.google.com/go v0.99.0 h1:y/cM2iqGgGi5D5DQZl6D9STN/3dR/Vx5Mp8s752oJTY= -cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= +cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/compute v1.19.0 h1:+9zda3WGgW1ZSTlVppLCYFIr48Pa35q1uG2N1itbCEQ= +cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= @@ -50,57 +42,43 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= -github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= -github.com/Azure/go-autorest/autorest v0.11.27 h1:F3R3q42aWytozkV8ihzcgMO4OA4cuqr3bNlsEuF6//A= -github.com/Azure/go-autorest/autorest v0.11.27/go.mod h1:7l8ybrIdUmGqZMTD0sRtAr8NvbHjfofbf8RSP2q7w7U= github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= -github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= -github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= -github.com/Azure/go-autorest/autorest/adal v0.9.20 h1:gJ3E98kMpFB1MFqQCvA1yFab8vthOeD4VlFRQULxahg= -github.com/Azure/go-autorest/autorest/adal v0.9.20/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= -github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/autorest/mocks v0.4.2 h1:PGN4EDXnuQbojHbU0UWoNvmu9AGVwYHG9/fkDYhtAfw= -github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= -github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= -github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU= -github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= +github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= -github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd h1:sjQovDkwrZp8u+gxLtPgKGjk5hCxuy2hrRejBTA9xFU= -github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= +github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= +github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= -github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= -github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= -github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= -github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8= -github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= -github.com/Masterminds/squirrel v1.5.2 h1:UiOEi2ZX4RCSkpiNDQN5kro/XIBpSRk9iTqdIRPzUXE= -github.com/Masterminds/squirrel v1.5.2/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= +github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= +github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/Masterminds/sprig/v3 v3.2.0/go.mod h1:tWhwTbUTndesPNeF0C900vKoq283u6zp4APT9vaF3SI= +github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= +github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= +github.com/Masterminds/squirrel v1.5.3 h1:YPpoceAcxuzIljlr5iWpNKaql7hLeG1KLSrhvdHpkZc= +github.com/Masterminds/squirrel v1.5.3/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= github.com/Masterminds/vcs v1.13.3 h1:IIA2aBdXvfbIM+yl/eTnL4hb1XwdpvuQLglAix1gweE= github.com/Masterminds/vcs v1.13.3/go.mod h1:TiE7xuEjl1N4j016moRd6vezp6e6Lz23gypeXfzXeW8= github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= @@ -111,8 +89,8 @@ github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugX github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY= -github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= @@ -121,25 +99,20 @@ github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2 github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= -github.com/Microsoft/hcsshim v0.9.2 h1:wB06W5aYFfUB3IvootYAY2WnOmIdgPGfqSI6tufQNnY= -github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= +github.com/Microsoft/hcsshim v0.9.6 h1:VwnDOgLeoi2du6dAznfmspNqTiwczvjv4K7NxuY9jsY= +github.com/Microsoft/hcsshim v0.9.6/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= -github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= -github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= -github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls= github.com/adrg/xdg v0.4.0/go.mod h1:N6ag73EX4wyxeaoeHctc1mas01KZgsj5tYiAIwqJE/E= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= @@ -147,13 +120,11 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220418222510-f25a4f6275ed h1:ue9pVfIcP+QMEjfgo/Ez4ZjNZfonGgR6NgjMaJMu1Cg= -github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220418222510-f25a4f6275ed/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= -github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df h1:7RFfzj4SSt6nnvCPbCqijJi1nWCd+TqAT3bYCStRC18= +github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= @@ -164,8 +135,6 @@ github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:l github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 h1:4daAzAu0S6Vi7/lbWECcX0j45yZReDZ56BQsrVBOEEY= github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= -github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -174,12 +143,10 @@ github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+Ce github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= -github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= @@ -193,13 +160,15 @@ github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0Bsq github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= github.com/bugsnag/panicwrap v1.2.0 h1:OzrKrRvXis8qEvOkfcxNcYbOd2O7xXS2nnKMEMABFQA= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4= +github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 h1:7aWHqerlJ41y6FOsEUvknqgXnGmJyJSbjhAWq5pO4F8= -github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= +github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= @@ -212,8 +181,6 @@ github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJ github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= -github.com/cockroachdb/cockroach-go v0.0.0-20181001143604-e0a95dfd547c/go.mod h1:XGLbWH/ujMcbPbhZq52Nv6UrCghb1yGn//133kEsvDk= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= @@ -229,14 +196,13 @@ github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4S github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= -github.com/containerd/cgroups v1.0.3 h1:ADZftAkglvCiD44c77s5YmMqaP2pzVCFZvBmAlBdAP4= -github.com/containerd/cgroups v1.0.3/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8= +github.com/containerd/cgroups v1.0.4 h1:jN/mbWBEaz+T1pi5OFtnkQ+8qnmEbAr1Oo1FRm5B0dA= +github.com/containerd/cgroups v1.0.4/go.mod h1:nLNQtsF7Sl2HxNebu77i1R0oDlhiTG+kO4JTrUzo6IA= github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= -github.com/containerd/containerd v1.2.7/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= @@ -251,8 +217,8 @@ github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09Zvgq github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g= github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c= -github.com/containerd/containerd v1.6.3 h1:JfgUEIAH07xDWk6kqz0P3ArZt+KJ9YeihSC9uyFtSKg= -github.com/containerd/containerd v1.6.3/go.mod h1:gCVGrYRYFm2E8GmuUIbj/NGD7DLZQLzSJQazjVKDOig= +github.com/containerd/containerd v1.6.18 h1:qZbsLvmyu+Vlty0/Ex5xc0z2YtKpIsb5n45mAMI+2Ns= +github.com/containerd/containerd v1.6.18/go.mod h1:1RdCUu95+gc2v9t3IL+zIlpClSmew7/0YS8O5eQZrOw= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= @@ -260,8 +226,8 @@ github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cE github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ= github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= -github.com/containerd/continuity v0.2.2 h1:QSqfxcn8c+12slxwu00AtzXrsami0MJb/MQs9lOLHLA= -github.com/containerd/continuity v0.2.2/go.mod h1:pWygW9u7LtS1o4N/Tn0FoCFDIXZ7rxcMX7HX1Dmibvk= +github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= +github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= @@ -321,64 +287,48 @@ github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7 github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= -github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/go-systemd/v22 v22.4.0 h1:y9YHcjnjynCd/DVbg5j9L/33jQM3MxJlbj/zWskzfGU= +github.com/coreos/go-systemd/v22 v22.4.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU= -github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= -github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI= github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= -github.com/cznic/b v0.0.0-20180115125044-35e9bbe41f07/go.mod h1:URriBxXwVq5ijiJ12C7iIZqlA69nTlI+LgI6/pwftG8= -github.com/cznic/fileutil v0.0.0-20180108211300-6a051e75936f/go.mod h1:8S58EK26zhXSxzv7NQFpnliaOQsmDUxvoQO3rt154Vg= -github.com/cznic/golex v0.0.0-20170803123110-4ab7c5e190e4/go.mod h1:+bmmJDNmKlhWNG+gwWCkaBoTy39Fs+bzRxVBzoTQbIc= -github.com/cznic/internal v0.0.0-20180608152220-f44710a21d00/go.mod h1:olo7eAdKwJdXxb55TKGLiJ6xt1H0/tiiRCWKVLmtjY4= -github.com/cznic/lldb v1.1.0/go.mod h1:FIZVUmYUVhPwRiPzL8nD/mpFcJ/G7SSXjjXYG4uRI3A= -github.com/cznic/mathutil v0.0.0-20180504122225-ca4c9f2c1369/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM= -github.com/cznic/ql v1.2.0/go.mod h1:FbpzhyZrqr0PVlK6ury+PoW3T0ODUV22OeWIxcaOrSE= -github.com/cznic/sortutil v0.0.0-20150617083342-4c7342852e65/go.mod h1:q2w6Bg5jeox1B+QkJ6Wp/+Vn0G/bo3f1uY7Fn3vivIQ= -github.com/cznic/strutil v0.0.0-20171016134553-529a34b1c186/go.mod h1:AHHPPPXTw0h6pVabbcbyGRK1DckRn7r/STdZEeIDzZc= -github.com/cznic/zappy v0.0.0-20160723133515-2533cb5b45cc/go.mod h1:Y1SNZ4dRUOKXshKUbwUapqNncRrho4mkjQebgEHZLj8= github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8= github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I= -github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7hqDjlFjiygg= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE= -github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM= github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/dhui/dktest v0.3.0/go.mod h1:cyzIUfGsBEbZ6BT7tnXqAShHSXCZhSNmFl70sZ7c1yc= github.com/distribution/distribution v2.7.1+incompatible h1:aGFx4EvJWKEh//lHPLwFhFgwFHKH06TzNVPamrMn04M= github.com/distribution/distribution v2.7.1+incompatible/go.mod h1:EgLm2NgWtdKgzF9NpMzUKgzmR7AMmb0VQi2B+ZzDRjc= -github.com/distribution/distribution/v3 v3.0.0-20211118083504-a29a3c99a684 h1:DBZ2sN7CK6dgvHVpQsQj4sRMCbWTmd17l+5SUCjnQSY= +github.com/distribution/distribution/v3 v3.0.0-20221208165359-362910506bc2 h1:aBfCb7iqHmDEIp6fBvC/hQUddQfg+3qdYjwzaiP9Hnc= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/cli v20.10.12+incompatible h1:lZlz0uzG+GH+c0plStMUdF/qk3ppmgnswpR5EbqzVGA= -github.com/docker/cli v20.10.12+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v20.10.21+incompatible h1:qVkgyYUnOLQ98LtXBrwd/duVqPT2X4SHndOuGsfwyhU= +github.com/docker/cli v20.10.21+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v0.0.0-20191216044856-a8371794149d h1:jC8tT/S0OGx2cswpeUTn4gOIea8P08lD3VFQT0cOZ50= github.com/docker/distribution v0.0.0-20191216044856-a8371794149d/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= -github.com/docker/docker v0.7.3-0.20190103212154-2b7e084dc98b/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v0.7.3-0.20190817195342-4760db040282/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v20.10.14+incompatible h1:+T9/PRYWNDo5SZl5qS1r9Mo/0Q8AwxKKPtu9S1yxM0w= -github.com/docker/docker v20.10.14+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.24+incompatible h1:Ugvxm7a8+Gz6vqQYQQ2W7GYq5EUPaAiuPgIfVyI3dYE= +github.com/docker/docker v20.10.24+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= -github.com/docker/docker-credential-helpers v0.6.4 h1:axCks+yV+2MR3/kZhAmy07yC56WZ2Pwu/fKWtKuZB0o= -github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c= +github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= +github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= @@ -387,9 +337,9 @@ github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6Uezg github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= -github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= @@ -397,53 +347,42 @@ github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3 github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= -github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= -github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= -github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= 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.8.0 h1:eCZ8ulSerjdAiaNpF7GxXIE7ZCMo1moN1qX+S609eVw= -github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= +github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= -github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= +github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239 h1:Ghm4eQYC0nEPnSJdVkTrXpu9KtoVCSo1hg7mtI7G9KU= github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239/go.mod h1:Gdwt2ce0yfBxPvZrHkprdPPTTS3N5rwmLE8T22KBXlw= -github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= -github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= +github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c= -github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= 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/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= -github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/fsouza/fake-gcs-server v1.7.0/go.mod h1:5XIRs4YvwNbNoz+1JF8j6KLAyDh7RHGAyAK3EP2EsNk= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= +github.com/fvbommel/sortorder v1.0.1 h1:dSnXLt4mJYH25uDDGa3biZNQsozaUWDSWeKJ0qqFfzE= github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= github.com/garyburd/redigo v1.6.0 h1:0VruCpn7yAIIu7pWVClQC8wxCJEcG3nyzpMSHKi1PQc= -github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -452,8 +391,8 @@ github.com/go-air/gini v1.0.4 h1:lteMAxHKNOAjIqazL/klOJJmxq6YxxSuJ17MnMXny+s= github.com/go-air/gini v1.0.4/go.mod h1:dd8RvT1xcv6N1da33okvBd8DhMh1/A4siGy6ErjTljs= github.com/go-bindata/go-bindata/v3 v3.1.3 h1:F0nVttLC3ws0ojc7p60veTurcOm//D4QBODNM7EGrCI= github.com/go-bindata/go-bindata/v3 v3.1.3/go.mod h1:1/zrpXsLD8YDIbhZRqXzm1Ghc7NhEvIN9+Z6R5/xH4I= -github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= -github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= @@ -470,7 +409,6 @@ github.com/go-gorp/gorp/v3 v3.0.2/go.mod h1:BJ3q1ejpV8cVALtcXvXaXyTOlMmJhWDxTmnc github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= @@ -479,37 +417,39 @@ github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTg github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro= -github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= -github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= +github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA= github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM= -github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= +github.com/go-openapi/jsonreference v0.20.1 h1:FBLnyygC4/IZZr893oiomc9XaghoveYTrLC1F86HID8= +github.com/go-openapi/jsonreference v0.20.1/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= github.com/go-openapi/spec v0.19.5/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng= -github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/gobuffalo/flect v0.2.3 h1:f/ZukRnSNA/DUpSNDadko7Qc0PhGvsew35p/2tu+CRY= github.com/gobuffalo/flect v0.2.3/go.mod h1:vmkQwuZYhN5Pc4ljYQZzP+1sq+NEkK+lh20jmEmX3jc= github.com/gobuffalo/logger v1.0.6 h1:nnZNpxYo0zx+Aj9RfMPBm+x9zAU2OayFh/xrAWi34HU= @@ -522,7 +462,6 @@ github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/goccy/go-yaml v1.8.1 h1:JuZRFlqLM5cWF6A+waL8AKVuCcqvKOuhJtUQI+L3ez0= github.com/goccy/go-yaml v1.8.1/go.mod h1:wS4gNoLalDSJxo/SpngzPQ2BN4uuZVLCmbM4S3vd4+Y= -github.com/gocql/gocql v0.0.0-20190301043612-f6df8288f9b4/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0= github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= @@ -535,20 +474,19 @@ github.com/gofrs/uuid v3.3.0+incompatible h1:8K4tyRfvU1CYPgJsveYFQMhpFd/wXNM7iK6 github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= -github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang-migrate/migrate/v4 v4.6.2 h1:LDDOHo/q1W5UDj6PbkxdCv7lv9yunyZHXvxuwDkGo3k= -github.com/golang-migrate/migrate/v4 v4.6.2/go.mod h1:JYi6reN3+Z734VZ0akNuyOJNcrg45ZL7LDBMW3WGJL0= +github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs= +github.com/golang-migrate/migrate/v4 v4.16.1 h1:O+0C55RbMN66pWm5MjO6mw0px6usGpY0+bkSGW9zCo0= +github.com/golang-migrate/migrate/v4 v4.16.1/go.mod h1:qXiwa/3Zeqaltm1MxOCZDYysW/F6folYiBgBG03l9hc= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= +github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -582,20 +520,16 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/gomodule/redigo v1.8.2 h1:H5XSIre1MB5NbPYFp+i1NBbb5qN1W8Y8YAQoAYbkm8k= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= -github.com/google/cel-go v0.12.5 h1:DmzaiSgoaqGCjtpPQWl26/gND+yRpim56H1jCVev6d8= -github.com/google/cel-go v0.12.5/go.mod h1:Jk7ljRzLBhkmiAwBoUxB1sZSCVBAzkqPF25olK/iRDw= +github.com/google/cel-go v0.15.3 h1:W1wIeGuEs81+lBVU+cQRg1hkRT58Q6bNxvM5yn008S8= +github.com/google/cel-go v0.15.3/go.mod h1:YzWEoI07MC/a/wj9in8GeVatqfypkldgBlwXh9bCwqY= github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -610,11 +544,9 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0= -github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= -github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= @@ -622,7 +554,6 @@ github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -634,8 +565,6 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= @@ -644,25 +573,20 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3 github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= -github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= -github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw= github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= -github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= @@ -684,22 +608,25 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 h1:BZHcxBETFHIdVyhyEfOvn/RdU/QGdLI4y34qQGjGWO0= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= github.com/grpc-ecosystem/grpc-health-probe v0.4.11 h1:eKVQDIIJhRkfJHjQzTmu+RangfB8/MyrthCCnsvne/s= github.com/grpc-ecosystem/grpc-health-probe v0.4.11/go.mod h1:Ew6du240dK067iM38yVbni1pLpWUFnuyc0PefrB81Uc= github.com/h2non/filetype v1.1.1 h1:xvOwnXKAckvtLWsN398qS9QhlxlnVXBjXBydK2/UFB4= github.com/h2non/filetype v1.1.1/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY= github.com/h2non/go-is-svg v0.0.0-20160927212452-35e8c4b0612c h1:fEE5/5VNnYUoBOj2I9TP8Jc+a7lge3QWn9DKE7NCwfc= github.com/h2non/go-is-svg v0.0.0-20160927212452-35e8c4b0612c/go.mod h1:ObS/W+h8RYb1Y7fYivughjxojTmIu5iAIjSrSLCLeqE= -github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= @@ -708,6 +635,7 @@ github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= @@ -716,8 +644,9 @@ github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/J github.com/hokaccha/go-prettyjson v0.0.0-20190818114111-108c894c2c0e/go.mod h1:pFlLw2CfqZiIBOx6BuCeRLCrfxBJipTY0nIOF/VbGcI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4= +github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= @@ -726,16 +655,15 @@ github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/itchyny/astgen-go v0.0.0-20200519013840-cf3ea398f645 h1:3gyXljUyTWWTv/NMFPvwgxJSdE9Mamg2r3x8HMBl+Uo= github.com/itchyny/astgen-go v0.0.0-20200519013840-cf3ea398f645/go.mod h1:296z3W7Xsrp2mlIY88ruDKscuvrkL6zXCNRtaYVshzw= github.com/itchyny/go-flags v1.5.0/go.mod h1:lenkYuCobuxLBAd/HGFE4LRoW8D3B6iXRQfWYJ+MNbA= github.com/itchyny/gojq v0.11.0 h1:z7HnaKZ6erVzxPo3BkhJBG7jHmzKdAW8Hcse5N6YAic= github.com/itchyny/gojq v0.11.0/go.mod h1:my6D2qN2Sm6qa+/5GsPDUZlCWGR+U8Qsa9he76sudv0= github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= -github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ= -github.com/jackc/pgx v3.2.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 h1:IPJ3dvxmJ4uczJe5YQdrYB16oTJlGSC/OyZDqUk9xX4= @@ -744,18 +672,15 @@ github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJS github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmoiron/sqlx v1.3.4 h1:wv+0IJZfL5z0uZoUjlpKgHkgaFSYD+r9CfrXjEXsO7w= -github.com/jmoiron/sqlx v1.3.4/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= +github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= +github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= github.com/joelanford/ignore v0.0.0-20210607151042-0d25dc18b62d h1:A2/B900ip/Z20TzkLeGRNy1s6J2HmH9AmGt+dHyqb4I= github.com/joelanford/ignore v0.0.0-20210607151042-0d25dc18b62d/go.mod h1:7HQupe4vyNxMKXmM5DFuwXHsqwMyglcYmZBtlDPIcZ8= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= -github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -767,9 +692,7 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1 github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA= -github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= github.com/karrick/godirwalk v1.16.1 h1:DynhcF+bztK8gooS0+NDJFrdNZjJ3gzVzC545UNA9iw= github.com/karrick/godirwalk v1.16.1/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk= github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= @@ -790,14 +713,13 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= 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= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kshvakov/clickhouse v1.3.5/go.mod h1:DMzX7FxRymoNkVgizH0DWAL8Cur7wHLgx3MUnGwJqpE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw= @@ -809,23 +731,21 @@ github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2t github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is= github.com/lestrrat-go/strftime v1.0.1 h1:o7qz5pmLzPDLyGW4lG6JvTKPUfTFXwe+vOamIYWtnVU= github.com/lestrrat-go/strftime v1.0.1/go.mod h1:E1nN3pCbtMSu1yjSVeyuRFVm/U0xoR76fd03sz+Qz4g= -github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk= -github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= +github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo= -github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= -github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/markbates/errx v1.1.0 h1:QDFeR+UP95dO12JgW+tgi2UVfo0V8YBHiUIOaeBPiEI= github.com/markbates/errx v1.1.0/go.mod h1:PLa46Oex9KNbVDZhKel8v1OT7hD5JZ2eI7AHhA0wswc= github.com/markbates/oncer v1.0.0 h1:E83IaVAHygyndzPimgUYJjbshhDTALZyXxvk9FOlQRY= @@ -850,20 +770,20 @@ github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9 github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-oci8 v0.1.1/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= -github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/mattn/go-sqlite3 v1.14.10 h1:MLn+5bFRlWMGoSRmJour3CL1w/qL96mvipqpwQW/Sfk= -github.com/mattn/go-sqlite3 v1.14.10/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= +github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= github.com/maxbrunsfeld/counterfeiter/v6 v6.4.1 h1:hZD/8vBuw7x1WqRXD/WGjVjipbbo/HcDBgySYYbrUSk= github.com/maxbrunsfeld/counterfeiter/v6 v6.4.1/go.mod h1:DK1Cjkc0E49ShgRVs5jy5ASrM15svSnem3K/hiSGD8o= @@ -873,7 +793,7 @@ github.com/mikefarah/yq/v3 v3.0.0-20201202084205-8846255d1c37 h1:lPmsut5Sk7eK2Bm github.com/mikefarah/yq/v3 v3.0.0-20201202084205-8846255d1c37/go.mod h1:dYWq+UWoFCDY1TndvFUQuhBbIYmZpjreC8adEAx93zE= github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/cli v1.1.2/go.mod h1:6iaV0fGdElS6dPBx0EApTxHrcWvmJphyh2n8YBLPPZ4= +github.com/mitchellh/cli v1.1.4/go.mod h1:vTLESy5mRhKOs9KDp0/RATawxP1UqBmdrpVRMnpcvKQ= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= @@ -904,8 +824,8 @@ github.com/moby/sys/mountinfo v0.5.0 h1:2Ks8/r6lopsxWi9m58nlwjaeSzUX9iiL1vj5qB/9 github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= -github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc= -github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -915,7 +835,6 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= -github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= @@ -923,34 +842,36 @@ github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8m github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8/go.mod h1:86wM1zFnC6/uDBfZGNwB65O+pR2OFi5q/YQaEUid1qA= github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo/v2 v2.1.6 h1:Fx2POJZfKRQcM1pH49qSZiYeu319wji004qX+GDovrU= -github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= -github.com/onsi/gomega v1.17.0 h1:9Luw4uT5HTjHTN8+aNcSThgH1vdXnmdJ8xIfZ4wyTRE= -github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q= +github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k= +github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +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= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= +github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= +github.com/onsi/gomega v1.11.0/go.mod h1:azGKhqFUon9Vuj0YmTfLSmx0FUwqXYSTl5re8lQLTUg= +github.com/onsi/gomega v1.27.7 h1:fVih9JD6ogIiHUN6ePK7HJidyEDpWGVB5mzM7cWNXoU= +github.com/onsi/gomega v1.27.7/go.mod h1:1p8OOlwo2iUUDsHnOrjE5UKYJ+e3W8eQ3qSlRahPmr4= github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= @@ -959,8 +880,8 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 h1:rc3tiVYb5z54aKaDfakKn0dDjIyPpTtszkjuMzyt7ec= -github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034= +github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= @@ -983,7 +904,6 @@ github.com/openshift/api v0.0.0-20210517065120-b325f58df679/go.mod h1:dZ4kytOo3s github.com/openshift/build-machinery-go v0.0.0-20210209125900-0da259a2c359/go.mod h1:b1BuldmJlbA/xYtdZvKi+7j5YGB44qJUJDZ9zwiNCfE= github.com/openshift/client-go v0.0.0-20200326155132-2a6cd50aedd0 h1:kMiuiZXH1GdfbiMwsuAQOqGaMxlo9NCUk0wT4XAdfNM= github.com/openshift/client-go v0.0.0-20200326155132-2a6cd50aedd0/go.mod h1:uUQ4LClRO+fg5MF/P6QxjMCb1C9f7Oh4RKepftDnEJE= -github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/otiai10/copy v1.2.0 h1:HvG945u96iNadPoG2/Ja2+AUJeW5YuFQMixq9yirC+k= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= @@ -999,8 +919,7 @@ github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrap github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc= -github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -1016,36 +935,29 @@ github.com/poy/onpar v0.0.0-20190519213022-ee068f8ea4d1/go.mod h1:nSbFQvMj97ZyhF github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.12.2 h1:51L9cDoUHVrXx4zWYlcLQIZ+d+VXHgqnYKkIuq4g/34= -github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.15.1 h1:8tXpTmJbyH5lydzFPoxSIJ0J46jdh3tylbvM1xCv0LI= +github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= +github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= +github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -1055,18 +967,16 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= +github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= -github.com/rubenv/sql-migrate v1.1.1 h1:haR5Hn8hbW9/SpAICrXoZqXnywS7Q5WijwkQENPeNWY= -github.com/rubenv/sql-migrate v1.1.1/go.mod h1:/7TZymwxN8VWumcIxw1jjHEcR1djpdkMHQPT4FWdnbQ= -github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= -github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rubenv/sql-migrate v1.2.0 h1:fOXMPLMd41sK7Tg75SXDec15k3zg5WNV6SjuDRiNfcU= +github.com/rubenv/sql-migrate v1.2.0/go.mod h1:Z5uVnq7vrIrPmHbVFfR4YLHRZquxeHpckCnRq0P/K9Y= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 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= @@ -1080,7 +990,6 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= 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/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= @@ -1091,8 +1000,9 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.2 h1:oxx1eChJGI6Uks2ZC4W1zpLlVgqB8ner4EuQwV4Ik1Y= +github.com/sirupsen/logrus v1.9.2/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= @@ -1101,7 +1011,6 @@ github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= @@ -1111,8 +1020,8 @@ github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKv github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= -github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= -github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= +github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= @@ -1132,8 +1041,9 @@ github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -1143,8 +1053,10 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= @@ -1152,11 +1064,9 @@ github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= github.com/tebeka/strftime v0.1.3 h1:5HQXOqWKYRFfNyBMNVc9z5+QzuBtIXy03psIhtdJYto= github.com/tebeka/strftime v0.1.3/go.mod h1:7wJm3dZlpr4l/oVK0t1HYIc4rMzQ2XJlOMIUJUJH6XQ= -github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA= -github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= +github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 h1:6fotK7otjonDflCTK0BCfls4SPy3NcCVb5dqqmbRknE= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= @@ -1170,10 +1080,7 @@ github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17 github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= -github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs= github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= -github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= -github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= @@ -1183,8 +1090,8 @@ github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17 github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI= -github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= +github.com/xlab/treeprint v1.1.0 h1:G/1DjNkPpfZCFt9CSh6b5/nY4VimlbHF3Rh4obvtzDk= +github.com/xlab/treeprint v1.1.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -1192,7 +1099,7 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= github.com/yvasiyarov/go-metrics v0.0.0-20150112132944-c25f46c4b940 h1:p7OofyZ509h8DmPLh8Hn+EIIZm/xYhdZHJ9GnXHdr6U= github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= @@ -1204,7 +1111,6 @@ github.com/zeebo/errs v1.3.0 h1:hmiaKqgYZzcVgRL1Vkc1Mn2914BbzB0IBxs+ebeutGs= github.com/zeebo/errs v1.3.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4= github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs= github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= -gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= @@ -1213,71 +1119,64 @@ go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489 h1:1JFLBqwIgdyHN1ZtgjTBwO+blA6gVOmZurpiMEsETKo= go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/api/v3 v3.5.4 h1:OHVyt3TopwtUQ2GKdd5wu3PmmipR4FTwCqoEjSyRdIc= -go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A= +go.etcd.io/etcd/api/v3 v3.5.7 h1:sbcmosSVesNrWOJ58ZQFitHMdncusIifYcrBfwrlJSY= +go.etcd.io/etcd/api/v3 v3.5.7/go.mod h1:9qew1gCdDDLu+VwmeG+iFpL+QlpHTo7iubavdVDgCAA= go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/pkg/v3 v3.5.4 h1:lrneYvz923dvC14R54XcA7FXoZ3mlGZAgmwhfm7HqOg= -go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/pkg/v3 v3.5.7 h1:y3kf5Gbp4e4q7egZdn5T7W9TSHUvkClN6u+Rq9mEOmg= +go.etcd.io/etcd/client/pkg/v3 v3.5.7/go.mod h1:o0Abi1MK86iad3YrWhgUsbGx1pmTS+hrORWc2CamuhY= go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= -go.etcd.io/etcd/client/v2 v2.305.4 h1:Dcx3/MYyfKcPNLpR4VVQUP5KgYrBeJtktBwEKkw08Ao= -go.etcd.io/etcd/client/v3 v3.5.4 h1:p83BUL3tAYS0OT/r0qglgc3M1JjhM0diV8DSWAhVXv4= -go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY= -go.etcd.io/etcd/pkg/v3 v3.5.4 h1:V5Dvl7S39ZDwjkKqJG2BfXgxZ3QREqqKifWQgIw5IM0= -go.etcd.io/etcd/raft/v3 v3.5.4 h1:YGrnAgRfgXloBNuqa+oBI/aRZMcK/1GS6trJePJ/Gqc= -go.etcd.io/etcd/server/v3 v3.5.4 h1:CMAZd0g8Bn5NRhynW6pKhc4FRg41/0QYy3d7aNm9874= -go.mongodb.org/mongo-driver v1.1.0/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.etcd.io/etcd/client/v2 v2.305.7 h1:AELPkjNR3/igjbO7CjyF1fPuVPjrblliiKj+Y6xSGOU= +go.etcd.io/etcd/client/v3 v3.5.7 h1:u/OhpiuCgYY8awOHlhIhmGIGpxfBU/GZBUP3m/3/Iz4= +go.etcd.io/etcd/client/v3 v3.5.7/go.mod h1:sOWmj9DZUMyAngS7QQwCyAXXAL6WhgTOPLNS/NabQgw= +go.etcd.io/etcd/pkg/v3 v3.5.7 h1:obOzeVwerFwZ9trMWapU/VjDcYUJb5OfgC1zqEGWO/0= +go.etcd.io/etcd/raft/v3 v3.5.7 h1:aN79qxLmV3SvIq84aNTliYGmjwsW6NqJSnqmI1HLJKc= +go.etcd.io/etcd/server/v3 v3.5.7 h1:BTBD8IJUV7YFgsczZMHhMTS67XuA4KpRquL0MFOJGRk= go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= -go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opentelemetry.io/contrib v0.20.0 h1:ubFQUn0VCZ0gPwIoJfBJVpeBlyRMxu8Mm/huKWYd9p0= -go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0 h1:sO4WKdPAudZGKPcpZT4MJn6JaDmpyLrMPDGGyA1SttE= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0 h1:Q3C9yzW6I9jqEc8sawxzxZmY48fs9u220KXq6d5s3XU= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= -go.opentelemetry.io/otel v0.20.0 h1:eaP0Fqu7SXHwvjiqDq83zImeehOHX8doTvU9AwXON8g= -go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= -go.opentelemetry.io/otel/exporters/otlp v0.20.0 h1:PTNgq9MRmQqqJY0REVbZFvwkYOA85vbdQU/nVfxDyqg= -go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= -go.opentelemetry.io/otel/metric v0.20.0 h1:4kzhXFP+btKm4jwxpjIqjs41A7MakRFUS86bqLHTIw8= -go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= -go.opentelemetry.io/otel/oteltest v0.20.0 h1:HiITxCawalo5vQzdHfKeZurV8x7ljcqAgiWzF6Vaeaw= -go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= -go.opentelemetry.io/otel/sdk v0.20.0 h1:JsxtGXd06J8jrnya7fdI/U/MR6yXA5DtbZy+qoHQlr8= -go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= -go.opentelemetry.io/otel/sdk/export/metric v0.20.0 h1:c5VRjxCXdQlx1HjzwGdQHzZaVI82b5EbBgOu2ljD92g= -go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= -go.opentelemetry.io/otel/sdk/metric v0.20.0 h1:7ao1wpzHRVKf0OQ7GIxiQJA6X7DLX9o14gmVon7mMK8= -go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= -go.opentelemetry.io/otel/trace v0.20.0 h1:1DL6EXUdcg95gukhuRRvLDO/4X5THh/5dIV52lqtnbw= -go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= -go.opentelemetry.io/proto/otlp v0.7.0 h1:rwOQPCuKAKmwGKq2aVNnYIibI6wnV7EvzgfTCzcdGg8= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.35.0 h1:xFSRQBbXF6VvYRf2lqMJXxoB72XI1K/azav8TekHHSw= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.35.0/go.mod h1:h8TWwRAhQpOd0aM5nYsRD8+flnkj+526GEIVlarH7eY= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.35.1 h1:sxoY9kG1s1WpSYNyzm24rlwH4lnRYFXUVVBmKMBfRgw= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.35.1/go.mod h1:9NiG9I2aHTKkcxqCILhjtyNA1QEiCjdBACv4IvrFQ+c= +go.opentelemetry.io/otel v1.12.0 h1:IgfC7kqQrRccIKuB7Cl+SRUmsKbEwSGPr0Eu+/ht1SQ= +go.opentelemetry.io/otel v1.12.0/go.mod h1:geaoz0L0r1BEOR81k7/n9W4TCXYCJ7bPO7K374jQHG0= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.12.0 h1:UfDENi+LTcLjQ/JhaXimjlIgn7wWjwbEMmdREm2Gyng= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.12.0/go.mod h1:rqbht/LlhVBgn5+k3M5QK96K5Xb0DvXpMJ5SFQpY6uw= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.12.0 h1:ZVqtSAxrR4+ofzayuww0/EKamCjjnwnXTMRZzMudJoU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.12.0/go.mod h1:IlaGLENJkAl9+Xoo3J0unkdOwtL+rmqZ3ryMjUtYA94= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.12.0 h1:+tsVdWosoqDfX6cdHAeacZozjQS94ySBd+aUXFwnNKA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.12.0/go.mod h1:jSqjV+Knu1Jyvh+l3fx7V210Ev3HHgNQAi8YqpXaQP8= +go.opentelemetry.io/otel/metric v0.31.0 h1:6SiklT+gfWAwWUR0meEMxQBtihpiEs4c+vL9spDTqUs= +go.opentelemetry.io/otel/metric v0.31.0/go.mod h1:ohmwj9KTSIeBnDBm/ZwH2PSZxZzoOaG2xZeekTRzL5A= +go.opentelemetry.io/otel/sdk v1.12.0 h1:8npliVYV7qc0t1FKdpU08eMnOjgPFMnriPhn0HH4q3o= +go.opentelemetry.io/otel/sdk v1.12.0/go.mod h1:WYcvtgquYvgODEvxOry5owO2y9MyciW7JqMz6cpXShE= +go.opentelemetry.io/otel/trace v1.12.0 h1:p28in++7Kd0r2d8gSt931O57fdjUyWxkVbESuILAeUc= +go.opentelemetry.io/otel/trace v1.12.0/go.mod h1:pHlgBynn6s25qJ2szD+Bv+iwKJttjHSI3lUAyf0GNuQ= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw= +go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 h1:+FNtrFTmVw0YZGpBGX56XDee331t6JAXeK2bcyhLOOc= go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= -go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= +go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1286,7 +1185,6 @@ golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -1301,10 +1199,9 @@ golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220408190544-5352b0902921 h1:iU7T1X1J6yxDr0rda54sWGkHgOp5XJrqm79gcNlC2VM= -golang.org/x/crypto v0.0.0-20220408190544-5352b0902921/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1315,6 +1212,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0 h1:pVgRXcIictcr+lBQIFeiwuwtDIs4eL21OuM9nyAADmo= +golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -1341,24 +1240,21 @@ golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hM golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= +golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181108082009-03003ca0c849/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190424112056-4829fb13d2c6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= @@ -1385,9 +1281,11 @@ golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -1397,19 +1295,13 @@ golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLd golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU= -golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= -golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1420,13 +1312,9 @@ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 h1:OSnWWcOd/CtWQC2cYSBgbTSJv3ciqd8r54ySIW2y3RE= -golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.5.0 h1:HuArIo48skDwlrvM3sEdHXElYslAMsf3KwRkkW4MC4s= +golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1438,8 +1326,9 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= +golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1447,15 +1336,12 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190102155601-82a175fd1598/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190426135247-a129542de9ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1500,12 +1386,10 @@ golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1521,7 +1405,6 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1535,30 +1418,25 @@ golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI= -golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1569,17 +1447,17 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220609170525-579cf78fd858 h1:Dpdu/EMxGMFgq0CeYMh4fazTD2vtlZRYE7wyynxJb9U= -golang.org/x/time v0.0.0-20220609170525-579cf78fd858/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1590,7 +1468,6 @@ golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190425222832-ad9eeb80039a/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= @@ -1603,7 +1480,6 @@ golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1638,29 +1514,25 @@ golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4X golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= -golang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= -golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= +golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gomodules.xyz/jsonpatch/v2 v2.2.0 h1:4pT439QV83L+G9FkcCriY6EkpcK6r6bK+A5FBUMI7qY= -gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +gomodules.xyz/jsonpatch/v2 v2.3.0 h1:8NFhfS6gzxNqjLIYnZxg319wZ5Qjnx4m/CcX+Klzazc= +gomodules.xyz/jsonpatch/v2 v2.3.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= -google.golang.org/api v0.3.2/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -1683,16 +1555,6 @@ google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjR google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= -google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= -google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= -google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= -google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= -google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= -google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= -google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= -google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= @@ -1703,7 +1565,6 @@ google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1748,27 +1609,10 @@ google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= -google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 h1:hrbNEivu7Zn1pxvHk6MBrq9iE22woVILTHqexqBxe6I= -google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20230525154841-bd750badd5c6 h1:62QuyPXKEkZpjZesyj5K5jABl6MnSnWl+vNuT5oz90E= +google.golang.org/genproto v0.0.0-20230525154841-bd750badd5c6/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 h1:M1YKkFIboKNieVO5DLUEVzQfGwJD30Nv2jfUgzb5UcE= @@ -1787,8 +1631,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1801,6 +1645,7 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v9 v9.30.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= @@ -1843,8 +1688,8 @@ gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81 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= -helm.sh/helm/v3 v3.9.0 h1:qDSWViuF6SzZX5s5AB/NVRGWmdao7T5j4S4ebIkMGag= -helm.sh/helm/v3 v3.9.0/go.mod h1:fzZfyslcPAWwSdkXrXlpKexFeE2Dei8N27FFQWt+PN0= +helm.sh/helm/v3 v3.11.1 h1:cmL9fFohOoNQf+wnp2Wa0OhNFH0KFnSzEkVxi3fcc3I= +helm.sh/helm/v3 v3.11.1/go.mod h1:z/Bu/BylToGno/6dtNGuSmjRqxKq5gaH+FU0BPO+AQ8= 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= @@ -1857,46 +1702,40 @@ k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8= k8s.io/api v0.21.0-rc.0/go.mod h1:Dkc/ZauWJrgZhjOjeBgW89xZQiTBJA2RaBKYHXPsi2Y= -k8s.io/api v0.24.0/go.mod h1:5Jl90IUrJHUJYEMANRURMiVvJ0g7Ax7r3R1bqO8zx8I= -k8s.io/api v0.25.3 h1:Q1v5UFfYe87vi5H7NU0p4RXC26PPMT8KOpr1TLQbCMQ= -k8s.io/api v0.25.3/go.mod h1:o42gKscFrEVjHdQnyRenACrMtbuJsVdP+WVjqejfzmI= -k8s.io/apiextensions-apiserver v0.25.3 h1:bfI4KS31w2f9WM1KLGwnwuVlW3RSRPuIsfNF/3HzR0k= -k8s.io/apiextensions-apiserver v0.25.3/go.mod h1:ZJqwpCkxIx9itilmZek7JgfUAM0dnTsA48I4krPqRmo= +k8s.io/api v0.27.2 h1:+H17AJpUMvl+clT+BPnKf0E3ksMAzoBBg7CntpSuADo= +k8s.io/api v0.27.2/go.mod h1:ENmbocXfBT2ADujUXcBhHV55RIT31IIEvkntP6vZKS4= +k8s.io/apiextensions-apiserver v0.27.2 h1:iwhyoeS4xj9Y7v8YExhUwbVuBhMr3Q4bd/laClBV6Bo= +k8s.io/apiextensions-apiserver v0.27.2/go.mod h1:Oz9UdvGguL3ULgRdY9QMUzL2RZImotgxvGjdWRq6ZXQ= k8s.io/apimachinery v0.18.0/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA= k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc= k8s.io/apimachinery v0.21.0-rc.0/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY= -k8s.io/apimachinery v0.24.0/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= -k8s.io/apimachinery v0.25.3 h1:7o9ium4uyUOM76t6aunP0nZuex7gDf8VGwkR5RcJnQc= -k8s.io/apimachinery v0.25.3/go.mod h1:jaF9C/iPNM1FuLl7Zuy5b9v+n35HGSh6AQ4HYRkCqwo= +k8s.io/apimachinery v0.27.2 h1:vBjGaKKieaIreI+oQwELalVG4d8f3YAMNpWLzDXkxeg= +k8s.io/apimachinery v0.27.2/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E= k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM= k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= -k8s.io/apiserver v0.25.3 h1:m7+xGuG5+KYAnEsqaFtDyWMkmMMEOFYlu+NlWv5qSBI= -k8s.io/apiserver v0.25.3/go.mod h1:9bT47iM2fzRuhICJpM/RcQR9sqDDfZ7Yw60h0p3JW08= -k8s.io/cli-runtime v0.24.0 h1:ot3Qf49T852uEyNApABO1UHHpFIckKK/NqpheZYN2gM= -k8s.io/cli-runtime v0.24.0/go.mod h1:9XxoZDsEkRFUThnwqNviqzljtT/LdHtNWvcNFrAXl0A= +k8s.io/apiserver v0.27.2 h1:p+tjwrcQEZDrEorCZV2/qE8osGTINPuS5ZNqWAvKm5E= +k8s.io/apiserver v0.27.2/go.mod h1:EsOf39d75rMivgvvwjJ3OW/u9n1/BmUMK5otEOJrb1Y= +k8s.io/cli-runtime v0.27.1 h1:MMzp5Q/Xmr5L1Lrowuc+Y/r95XINC6c6/fE3aN7JDRM= +k8s.io/cli-runtime v0.27.1/go.mod h1:tEbTB1XP/nTH3wujsi52bw91gWpErtWiS15R6CwYsAI= k8s.io/client-go v0.18.0/go.mod h1:uQSYDYs4WhVZ9i6AIoEZuwUggLVEF64HOD37boKAtF8= k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k= k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0= -k8s.io/client-go v0.24.0/go.mod h1:VFPQET+cAFpYxh6Bq6f4xyMY80G6jKKktU6G0m00VDw= -k8s.io/client-go v0.25.3 h1:oB4Dyl8d6UbfDHD8Bv8evKylzs3BXzzufLiO27xuPs0= -k8s.io/client-go v0.25.3/go.mod h1:t39LPczAIMwycjcXkVc+CB+PZV69jQuNx4um5ORDjQA= +k8s.io/client-go v0.27.2 h1:vDLSeuYvCHKeoQRhCXjxXO45nHVv2Ip4Fe0MfioMrhE= +k8s.io/client-go v0.27.2/go.mod h1:tY0gVmUsHrAmjzHX9zs7eCjxcBsf8IiNe7KQ52biTcQ= k8s.io/code-generator v0.18.0/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc= k8s.io/code-generator v0.19.7/go.mod h1:lwEq3YnLYb/7uVXLorOJfxg+cUu2oihFhHZ0n9NIla0= k8s.io/code-generator v0.21.0-rc.0/go.mod h1:hUlps5+9QaTrKx+jiM4rmq7YmH8wPOIko64uZCHDh6Q= -k8s.io/code-generator v0.24.0/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w= -k8s.io/code-generator v0.25.3 h1:BEH+wDi90bGyrYcY4abGtUqaOX7G94RRrEu8l+SvIeo= -k8s.io/code-generator v0.25.3/go.mod h1:9F5fuVZOMWRme7MYj2YT3L9ropPWPokd9VRhVyD3+0w= +k8s.io/code-generator v0.27.2 h1:RmK0CnU5qRaK6WRtSyWNODmfTZNoJbrizpVcsgbtrvI= +k8s.io/code-generator v0.27.2/go.mod h1:DPung1sI5vBgn4AGKtlPRQAyagj/ir/4jI55ipZHVww= k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI= k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM= -k8s.io/component-base v0.24.0/go.mod h1:Dgazgon0i7KYUsS8krG8muGiMVtUZxG037l1MKyXgrA= -k8s.io/component-base v0.25.3 h1:UrsxciGdrCY03ULT1h/S/gXFCOPnLhUVwSyx+hM/zq4= -k8s.io/component-base v0.25.3/go.mod h1:WYoS8L+IlTZgU7rhAl5Ctpw0WdMxDfCC5dkxcEFa/TI= -k8s.io/component-helpers v0.24.0/go.mod h1:Q2SlLm4h6g6lPTC9GMMfzdywfLSvJT2f1hOnnjaWD8c= +k8s.io/component-base v0.27.2 h1:neju+7s/r5O4x4/txeUONNTS9r1HsPbyoPBAtHsDCpo= +k8s.io/component-base v0.27.2/go.mod h1:5UPk7EjfgrfgRIuDBFtsEFAe4DAvP3U+M8RTzoSJkpo= k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM= k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= @@ -1907,9 +1746,8 @@ k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8 k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/gengo v0.0.0-20211129171323-c02415ce4185 h1:TT1WdmqqXareKxZ/oNXEUSwKlLiHzPMyB0t8BaFeBYI= -k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/gengo v0.0.0-20220902162205-c0856e24416d h1:U9tB195lKdzwqicbJvyJeOXV7Klv+wNAWENRnXEGi08= +k8s.io/gengo v0.0.0-20220902162205-c0856e24416d/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= @@ -1918,58 +1756,50 @@ k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= -k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= -k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw= +k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kms v0.27.2 h1:wCdmPCa3kubcVd3AssOeaVjLQSu45k5g/vruJ3iqwDU= +k8s.io/kms v0.27.2/go.mod h1:dahSqjI05J55Fo5qipzvHSRbm20d7llrSeQjjl86A7c= k8s.io/kube-aggregator v0.25.3 h1:eOG9S4GPICAXWIFeQDHjnhqYaYPpgLIC1NunJu9pZCs= k8s.io/kube-aggregator v0.25.3/go.mod h1:w87nqmzJMf7S73FRYcnexqfYW0AFiLJiCkvVCwM3feE= k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE= -k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= -k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk= -k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 h1:MQ8BAZPZlWk3S9K4a9NCkIFQtZShWqoha7snGixVgEA= -k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU= -k8s.io/kubectl v0.24.0 h1:nA+WtMLVdXUs4wLogGd1mPTAesnLdBpCVgCmz3I7dXo= -k8s.io/kubectl v0.24.0/go.mod h1:pdXkmCyHiRTqjYfyUJiXtbVNURhv0/Q1TyRhy2d5ic0= +k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f h1:2kWPakN3i/k81b0gvD5C5FJ2kxm1WrQFanWchyKuqGg= +k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f/go.mod h1:byini6yhqGC14c3ebc/QwanvYwhuMWF6yz2F8uwW8eg= +k8s.io/kubectl v0.27.1 h1:9T5c5KdpburYiW8XKQSH0Uly1kMNE90aGSnbYUZNdcA= +k8s.io/kubectl v0.27.1/go.mod h1:QsAkSmrRsKTPlAFzF8kODGDl4p35BIwQnc9XFhkcsy8= k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= -k8s.io/metrics v0.24.0/go.mod h1:jrLlFGdKl3X+szubOXPG0Lf2aVxuV3QJcbsgVRAM6fI= k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20220823124924-e9cbc92d1a73 h1:H9TCJUUx+2VA0ZiD9lvtaX8fthFsMoD+Izn93E/hm8U= -k8s.io/utils v0.0.0-20220823124924-e9cbc92d1a73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -oras.land/oras-go v1.1.0 h1:tfWM1RT7PzUwWphqHU6ptPU3ZhwVnSw/9nEGf519rYg= -oras.land/oras-go v1.1.0/go.mod h1:1A7vR/0KknT2UkJVWh+xMi95I/AhK8ZrxrnUSmXN0bQ= +k8s.io/utils v0.0.0-20230209194617-a36077c30491 h1:r0BAOLElQnnFhE/ApUsg3iHdVYYPBjNSSOMowRZxxsY= +k8s.io/utils v0.0.0-20230209194617-a36077c30491/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +oras.land/oras-go v1.2.2 h1:0E9tOHUfrNH7TCDk5KU0jVBEzCqbfdyuVfGmJ7ZeRPE= +oras.land/oras-go v1.2.2/go.mod h1:Apa81sKoZPpP7CDciE006tSZ0x3Q3+dOoBcMZ/aNxvw= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.33 h1:LYqFq+6Cj2D0gFfrJvL7iElD4ET6ir3VDdhDdTK7rgc= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.33/go.mod h1:soWkSNf2tZC7aMibXEqVhCd73GOY5fJikn8qbdzemB0= -sigs.k8s.io/controller-runtime v0.13.0 h1:iqa5RNciy7ADWnIc8QxCbOX5FEKVR3uxVxKHRMc2WIQ= -sigs.k8s.io/controller-runtime v0.13.0/go.mod h1:Zbz+el8Yg31jubvAEyglRZGdLAjplZl+PgtYNI6WNTI= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2 h1:trsWhjU5jZrx6UvFu4WzQDrN7Pga4a7Qg+zcfcj64PA= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2/go.mod h1:+qG7ISXqCDVVcyO8hLn12AKVYYUjM7ftlqsqmrhMZE0= +sigs.k8s.io/controller-runtime v0.15.0 h1:ML+5Adt3qZnMSYxZ7gAverBLNPSMQEibtzAgp0UPojU= +sigs.k8s.io/controller-runtime v0.15.0/go.mod h1:7ngYvp1MLT+9GeZ+6lH3LOlcHkp/+tzA/fmHa4iq9kk= sigs.k8s.io/controller-tools v0.8.0 h1:uUkfTGEwrguqYYfcI2RRGUnC8mYdCFDqfwPKUcNJh1o= sigs.k8s.io/controller-tools v0.8.0/go.mod h1:qE2DXhVOiEq5ijmINcFbqi9GZrrUjzB1TuJU0xa6eoY= -sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/kustomize/api v0.11.4 h1:/0Mr3kfBBNcNPOW5Qwk/3eb8zkswCwnqQxxKtmrTkRo= -sigs.k8s.io/kustomize/api v0.11.4/go.mod h1:k+8RsqYbgpkIrJ4p9jcdPqe8DprLxFUUO0yNOq8C+xI= -sigs.k8s.io/kustomize/cmd/config v0.10.6/go.mod h1:/S4A4nUANUa4bZJ/Edt7ZQTyKOY9WCER0uBS1SW2Rco= -sigs.k8s.io/kustomize/kustomize/v4 v4.5.4/go.mod h1:Zo/Xc5FKD6sHl0lilbrieeGeZHVYCA4BzxeAaLI05Bg= -sigs.k8s.io/kustomize/kyaml v0.13.6 h1:eF+wsn4J7GOAXlvajv6OknSunxpcOBQQqsnPxObtkGs= -sigs.k8s.io/kustomize/kyaml v0.13.6/go.mod h1:yHP031rn1QX1lr/Xd934Ri/xdVNG8BE2ECa78Ht/kEg= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/kustomize/api v0.13.2 h1:kejWfLeJhUsTGioDoFNJET5LQe/ajzXhJGYoU+pJsiA= +sigs.k8s.io/kustomize/api v0.13.2/go.mod h1:DUp325VVMFVcQSq+ZxyDisA8wtldwHxLZbr1g94UHsw= +sigs.k8s.io/kustomize/kyaml v0.14.1 h1:c8iibius7l24G2wVAGZn/Va2wNys03GXLjYVIcFVxKA= +sigs.k8s.io/kustomize/kyaml v0.14.1/go.mod h1:AN1/IpawKilWD7V+YvQwRGUvuUOOWpjsHu6uHwonSF4= sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.1.0/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= diff --git a/manifests/0000_50_olm_00-catalogsources.crd.yaml b/manifests/0000_50_olm_00-catalogsources.crd.yaml index ee5d2eee3d..37d2d38a53 100644 --- a/manifests/0000_50_olm_00-catalogsources.crd.yaml +++ b/manifests/0000_50_olm_00-catalogsources.crd.yaml @@ -73,6 +73,467 @@ spec: description: GrpcPodConfig exposes different overrides for the pod spec of the CatalogSource Pod. Only used when SourceType = SourceTypeGrpc and Image is set. type: object properties: + affinity: + description: Affinity is the catalog source's pod's affinity. + type: object + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the pod. + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node matches the corresponding matchExpressions; the node(s) with the highest sum are the most preferred. + type: array + items: + description: An empty preferred scheduling term matches all objects with implicit weight 0 (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). + type: object + required: + - preference + - weight + properties: + preference: + description: A node selector term, associated with the corresponding weight. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + weight: + description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to an update), the system may or may not try to eventually evict the pod from its node. + type: object + required: + - nodeSelectorTerms + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The terms are ORed. + type: array + items: + description: A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + weight: + description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. + type: array + items: + description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes that satisfy the anti-affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + weight: + description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the anti-affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. + type: array + items: + description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string nodeSelector: description: NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node's labels for the pod to be scheduled on that node. type: object @@ -129,6 +590,9 @@ spec: type: integer publisher: type: string + runAsRoot: + description: RunAsRoot allows admins to indicate that they wish to run the CatalogSource pod in a privileged pod as root. This should only be enabled when running older catalog images which could not be run as non-root. + type: boolean secrets: description: Secrets represent set of secrets that can be used to access the contents of the catalog. It is best to keep this list small, since each will need to be tried for every catalog entry. type: array diff --git a/manifests/0000_50_olm_00-clusterserviceversions.crd.yaml b/manifests/0000_50_olm_00-clusterserviceversions.crd.yaml index dd46e2b939..078947711d 100644 --- a/manifests/0000_50_olm_00-clusterserviceversions.crd.yaml +++ b/manifests/0000_50_olm_00-clusterserviceversions.crd.yaml @@ -121,7 +121,7 @@ spec: resources: type: array items: - description: APIResourceReference is a Kubernetes resource type used by a custom resource + description: APIResourceReference is a reference to a Kubernetes resource type that the referrer utilizes. type: object required: - kind @@ -129,10 +129,13 @@ spec: - version properties: kind: + description: Kind of the referenced resource type. type: string name: + description: Plural name of the referenced resource type (CustomResourceDefinition.Spec.Names[].Plural). Empty string if the referenced resource type is not a custom resource. type: string version: + description: API Version of the referenced resource type. type: string specDescriptors: type: array @@ -231,7 +234,7 @@ spec: resources: type: array items: - description: APIResourceReference is a Kubernetes resource type used by a custom resource + description: APIResourceReference is a reference to a Kubernetes resource type that the referrer utilizes. type: object required: - kind @@ -239,10 +242,13 @@ spec: - version properties: kind: + description: Kind of the referenced resource type. type: string name: + description: Plural name of the referenced resource type (CustomResourceDefinition.Spec.Names[].Plural). Empty string if the referenced resource type is not a custom resource. type: string version: + description: API Version of the referenced resource type. type: string specDescriptors: type: array @@ -345,7 +351,7 @@ spec: resources: type: array items: - description: APIResourceReference is a Kubernetes resource type used by a custom resource + description: APIResourceReference is a reference to a Kubernetes resource type that the referrer utilizes. type: object required: - kind @@ -353,10 +359,13 @@ spec: - version properties: kind: + description: Kind of the referenced resource type. type: string name: + description: Plural name of the referenced resource type (CustomResourceDefinition.Spec.Names[].Plural). Empty string if the referenced resource type is not a custom resource. type: string version: + description: API Version of the referenced resource type. type: string specDescriptors: type: array @@ -447,7 +456,7 @@ spec: resources: type: array items: - description: APIResourceReference is a Kubernetes resource type used by a custom resource + description: APIResourceReference is a reference to a Kubernetes resource type that the referrer utilizes. type: object required: - kind @@ -455,10 +464,13 @@ spec: - version properties: kind: + description: Kind of the referenced resource type. type: string name: + description: Plural name of the referenced resource type (CustomResourceDefinition.Spec.Names[].Plural). Empty string if the referenced resource type is not a custom resource. type: string version: + description: API Version of the referenced resource type. type: string specDescriptors: type: array @@ -507,10 +519,13 @@ spec: version: type: string description: + description: Description of the operator. Can include the features, limitations or use-cases of the operator. type: string displayName: + description: The name of the operator in display format. type: string icon: + description: The icon for this operator. type: array items: type: object @@ -674,7 +689,7 @@ spec: description: Type of deployment. Can be "Recreate" or "RollingUpdate". Default is RollingUpdate. type: string template: - description: Template describes the pods that will be created. + description: Template describes the pods that will be created. The only allowed template.spec.restartPolicy value is "Always". type: object properties: metadata: @@ -1327,7 +1342,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -1392,7 +1407,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -1442,7 +1457,7 @@ spec: type: integer format: int32 grpc: - description: GRPC specifies an action involving a GRPC port. This is a beta field and requires enabling GRPCContainerProbe feature gate. + description: GRPC specifies an action involving a GRPC port. type: object required: - port @@ -1474,7 +1489,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -1578,7 +1593,7 @@ spec: type: integer format: int32 grpc: - description: GRPC specifies an action involving a GRPC port. This is a beta field and requires enabling GRPCContainerProbe feature gate. + description: GRPC specifies an action involving a GRPC port. type: object required: - port @@ -1610,7 +1625,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -1662,10 +1677,42 @@ spec: description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' type: integer format: int32 + resizePolicy: + description: Resources resize policy for the container. + type: array + items: + description: ContainerResizePolicy represents resource resize policy for the container. + type: object + required: + - resourceName + - restartPolicy + properties: + resourceName: + description: 'Name of the resource to which this resource resize policy applies. Supported values: cpu, memory.' + type: string + restartPolicy: + description: Restart policy to apply when specified resource is resized. If not specified, it defaults to NotRequired. + type: string + x-kubernetes-list-type: atomic resources: description: 'Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers." + type: array + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + type: object + required: + - name + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object @@ -1676,7 +1723,7 @@ spec: - type: string x-kubernetes-int-or-string: true requests: - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object additionalProperties: pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ @@ -1789,7 +1836,7 @@ spec: type: integer format: int32 grpc: - description: GRPC specifies an action involving a GRPC port. This is a beta field and requires enabling GRPCContainerProbe feature gate. + description: GRPC specifies an action involving a GRPC port. type: object required: - port @@ -1821,7 +1868,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -2139,7 +2186,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -2204,7 +2251,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -2254,7 +2301,7 @@ spec: type: integer format: int32 grpc: - description: GRPC specifies an action involving a GRPC port. This is a beta field and requires enabling GRPCContainerProbe feature gate. + description: GRPC specifies an action involving a GRPC port. type: object required: - port @@ -2286,7 +2333,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -2390,7 +2437,7 @@ spec: type: integer format: int32 grpc: - description: GRPC specifies an action involving a GRPC port. This is a beta field and requires enabling GRPCContainerProbe feature gate. + description: GRPC specifies an action involving a GRPC port. type: object required: - port @@ -2422,7 +2469,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -2474,10 +2521,42 @@ spec: description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' type: integer format: int32 + resizePolicy: + description: Resources resize policy for the container. + type: array + items: + description: ContainerResizePolicy represents resource resize policy for the container. + type: object + required: + - resourceName + - restartPolicy + properties: + resourceName: + description: 'Name of the resource to which this resource resize policy applies. Supported values: cpu, memory.' + type: string + restartPolicy: + description: Restart policy to apply when specified resource is resized. If not specified, it defaults to NotRequired. + type: string + x-kubernetes-list-type: atomic resources: description: Resources are not allowed for ephemeral containers. Ephemeral containers use spare resources already allocated to the pod. type: object properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers." + type: array + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + type: object + required: + - name + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object @@ -2488,7 +2567,7 @@ spec: - type: string x-kubernetes-int-or-string: true requests: - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object additionalProperties: pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ @@ -2601,7 +2680,7 @@ spec: type: integer format: int32 grpc: - description: GRPC specifies an action involving a GRPC port. This is a beta field and requires enabling GRPCContainerProbe feature gate. + description: GRPC specifies an action involving a GRPC port. type: object required: - port @@ -2633,7 +2712,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -2962,7 +3041,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -3027,7 +3106,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -3077,7 +3156,7 @@ spec: type: integer format: int32 grpc: - description: GRPC specifies an action involving a GRPC port. This is a beta field and requires enabling GRPCContainerProbe feature gate. + description: GRPC specifies an action involving a GRPC port. type: object required: - port @@ -3109,7 +3188,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -3213,7 +3292,7 @@ spec: type: integer format: int32 grpc: - description: GRPC specifies an action involving a GRPC port. This is a beta field and requires enabling GRPCContainerProbe feature gate. + description: GRPC specifies an action involving a GRPC port. type: object required: - port @@ -3245,7 +3324,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -3297,10 +3376,42 @@ spec: description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' type: integer format: int32 + resizePolicy: + description: Resources resize policy for the container. + type: array + items: + description: ContainerResizePolicy represents resource resize policy for the container. + type: object + required: + - resourceName + - restartPolicy + properties: + resourceName: + description: 'Name of the resource to which this resource resize policy applies. Supported values: cpu, memory.' + type: string + restartPolicy: + description: Restart policy to apply when specified resource is resized. If not specified, it defaults to NotRequired. + type: string + x-kubernetes-list-type: atomic resources: description: 'Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers." + type: array + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + type: object + required: + - name + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object @@ -3311,7 +3422,7 @@ spec: - type: string x-kubernetes-int-or-string: true requests: - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object additionalProperties: pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ @@ -3424,7 +3535,7 @@ spec: type: integer format: int32 grpc: - description: GRPC specifies an action involving a GRPC port. This is a beta field and requires enabling GRPCContainerProbe feature gate. + description: GRPC specifies an action involving a GRPC port. type: object required: - port @@ -3456,7 +3567,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -3619,8 +3730,33 @@ spec: conditionType: description: ConditionType refers to a condition in the pod's condition list with matching type. type: string + resourceClaims: + description: "ResourceClaims defines which ResourceClaims must be allocated and reserved before the Pod is allowed to start. The resources will be made available to those containers which consume them by name. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable." + type: array + items: + description: PodResourceClaim references exactly one ResourceClaim through a ClaimSource. It adds a name to it that uniquely identifies the ResourceClaim inside the Pod. Containers that need access to the ResourceClaim reference it with this name. + type: object + required: + - name + properties: + name: + description: Name uniquely identifies this resource claim inside the pod. This must be a DNS_LABEL. + type: string + source: + description: Source describes where to find the ResourceClaim. + type: object + properties: + resourceClaimName: + description: ResourceClaimName is the name of a ResourceClaim object in the same namespace as this pod. + type: string + resourceClaimTemplateName: + description: "ResourceClaimTemplateName is the name of a ResourceClaimTemplate object in the same namespace as this pod. \n The template will be used to create a new ResourceClaim, which will be bound to this pod. When this pod is deleted, the ResourceClaim will also be deleted. The name of the ResourceClaim will be -, where is the PodResourceClaim.Name. Pod validation will reject the pod if the concatenated name is not valid for a ResourceClaim (e.g. too long). \n An existing ResourceClaim with that name that is not owned by the pod will not be used for the pod to avoid using an unrelated resource by mistake. Scheduling and pod startup are then blocked until the unrelated ResourceClaim is removed. \n This field is immutable and no changes will be made to the corresponding ResourceClaim by the control plane after creating the ResourceClaim." + type: string + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map restartPolicy: - description: 'Restart policy for all containers within the pod. One of Always, OnFailure, Never. Default to Always. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy' + description: 'Restart policy for all containers within the pod. One of Always, OnFailure, Never. In some contexts, only a subset of those values may be permitted. Default to Always. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy' type: string runtimeClassName: description: 'RuntimeClassName refers to a RuntimeClass object in the node.k8s.io group, which should be used to run this pod. If no RuntimeClass resource matches the named class, the pod will not be run. If unset or empty, the "legacy" RuntimeClass will be used, which is an implicit class with an empty definition that uses the default runtime handler. More info: https://git.k8s.io/enhancements/keps/sig-node/585-runtime-class' @@ -3628,6 +3764,21 @@ spec: schedulerName: description: If specified, the pod will be dispatched by specified scheduler. If not specified, the pod will be dispatched by default scheduler. type: string + schedulingGates: + description: "SchedulingGates is an opaque list of values that if specified will block scheduling the pod. If schedulingGates is not empty, the pod will stay in the SchedulingGated state and the scheduler will not attempt to schedule the pod. \n SchedulingGates can only be set at pod creation time, and be removed only afterwards. \n This is a beta feature enabled by the PodSchedulingReadiness feature gate." + type: array + items: + description: PodSchedulingGate is associated to a Pod to guard its scheduling. + type: object + required: + - name + properties: + name: + description: Name of the scheduling gate. Each scheduling gate must have a unique name field. + type: string + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map securityContext: description: 'SecurityContext holds pod-level security attributes and common container settings. Optional: Defaults to empty. See type description for default values of each field.' type: object @@ -3679,7 +3830,7 @@ spec: description: "type indicates which kind of seccomp profile will be applied. Valid options are: \n Localhost - a profile defined in a file on the node should be used. RuntimeDefault - the container runtime default profile should be used. Unconfined - no profile should be applied." type: string supplementalGroups: - description: A list of groups applied to the first process run in each container, in addition to the container's primary GID. If unspecified, no groups will be added to any container. Note that this field cannot be set when spec.os.name is windows. + description: A list of groups applied to the first process run in each container, in addition to the container's primary GID, the fsGroup (if specified), and group memberships defined in the container image for the uid of the container process. If unspecified, no additional groups are added to any container. Note that group memberships defined in the container image for the uid of the container process are still effective, even if they are not included in this list. Note that this field cannot be set when spec.os.name is windows. type: array items: type: integer @@ -3800,7 +3951,7 @@ spec: additionalProperties: type: string matchLabelKeys: - description: MatchLabelKeys is a set of pod label keys to select the pods over which spreading will be calculated. The keys are used to lookup values from the incoming pod labels, those key-value labels are ANDed with labelSelector to select the group of existing pods over which spreading will be calculated for the incoming pod. Keys that don't exist in the incoming pod labels will be ignored. A null or empty list means only match against labelSelector. + description: "MatchLabelKeys is a set of pod label keys to select the pods over which spreading will be calculated. The keys are used to lookup values from the incoming pod labels, those key-value labels are ANDed with labelSelector to select the group of existing pods over which spreading will be calculated for the incoming pod. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. MatchLabelKeys cannot be set when LabelSelector isn't set. Keys that don't exist in the incoming pod labels will be ignored. A null or empty list means only match against labelSelector. \n This is a beta field and requires the MatchLabelKeysInPodTopologySpread feature gate to be enabled (enabled by default)." type: array items: type: string @@ -3814,10 +3965,10 @@ spec: type: integer format: int32 nodeAffinityPolicy: - description: "NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector when calculating pod topology spread skew. Options are: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. \n If this value is nil, the behavior is equivalent to the Honor policy. This is a alpha-level feature enabled by the NodeInclusionPolicyInPodTopologySpread feature flag." + description: "NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector when calculating pod topology spread skew. Options are: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. \n If this value is nil, the behavior is equivalent to the Honor policy. This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag." type: string nodeTaintsPolicy: - description: "NodeTaintsPolicy indicates how we will treat node taints when calculating pod topology spread skew. Options are: - Honor: nodes without taints, along with tainted nodes for which the incoming pod has a toleration, are included. - Ignore: node taints are ignored. All nodes are included. \n If this value is nil, the behavior is equivalent to the Ignore policy. This is a alpha-level feature enabled by the NodeInclusionPolicyInPodTopologySpread feature flag." + description: "NodeTaintsPolicy indicates how we will treat node taints when calculating pod topology spread skew. Options are: - Honor: nodes without taints, along with tainted nodes for which the incoming pod has a toleration, are included. - Ignore: node taints are ignored. All nodes are included. \n If this value is nil, the behavior is equivalent to the Ignore policy. This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag." type: string topologyKey: description: TopologyKey is the key of node labels. Nodes that have a label with this key and identical values are considered to be in the same topology. We consider each as a "bucket", and try to put balanced number of pods into each bucket. We define a domain as a particular instance of a topology. Also, we define an eligible domain as a domain whose nodes meet the requirements of nodeAffinityPolicy and nodeTaintsPolicy. e.g. If TopologyKey is "kubernetes.io/hostname", each Node is a domain of that topology. And, if TopologyKey is "topology.kubernetes.io/zone", each zone is a domain of that topology. It's a required field. @@ -4074,7 +4225,7 @@ spec: description: 'medium represents what type of storage medium should back this directory. The default is "" which means to use the node''s default medium. Must be an empty string (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' type: string sizeLimit: - description: 'sizeLimit is the total amount of local storage required for this EmptyDir volume. The size limit is also applicable for memory medium. The maximum usage on memory medium EmptyDir would be the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the limit is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir' + description: 'sizeLimit is the total amount of local storage required for this EmptyDir volume. The size limit is also applicable for memory medium. The maximum usage on memory medium EmptyDir would be the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ anyOf: - type: integer @@ -4103,7 +4254,7 @@ spec: items: type: string dataSource: - description: 'dataSource field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. If the AnyVolumeDataSource feature gate is enabled, this field will always have the same contents as the DataSourceRef field.' + description: 'dataSource field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef, and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. If the namespace is specified, then dataSourceRef will not be copied to dataSource.' type: object required: - kind @@ -4119,7 +4270,7 @@ spec: description: Name is the name of resource being referenced type: string dataSourceRef: - description: 'dataSourceRef specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any local object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the DataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, both fields (DataSource and DataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. There are two important differences between DataSource and DataSourceRef: * While DataSource only allows two specific types of objects, DataSourceRef allows any non-core object, as well as PersistentVolumeClaim objects. * While DataSource ignores disallowed values (dropping them), DataSourceRef preserves all values, and generates an error if a disallowed value is specified. (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled.' + description: 'dataSourceRef specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the dataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, when namespace isn''t specified in dataSourceRef, both fields (dataSource and dataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. When namespace is specified in dataSourceRef, dataSource isn''t set to the same value and must be empty. There are three important differences between dataSource and dataSourceRef: * While dataSource only allows two specific types of objects, dataSourceRef allows any non-core object, as well as PersistentVolumeClaim objects. * While dataSource ignores disallowed values (dropping them), dataSourceRef preserves all values, and generates an error if a disallowed value is specified. * While dataSource only allows local objects, dataSourceRef allows objects in any namespaces. (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled. (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled.' type: object required: - kind @@ -4134,10 +4285,28 @@ spec: name: description: Name is the name of resource being referenced type: string + namespace: + description: Namespace is the namespace of resource being referenced Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled. + type: string resources: description: 'resources represents the minimum resources the volume should have. If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' type: object properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers." + type: array + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + type: object + required: + - name + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object @@ -4148,7 +4317,7 @@ spec: - type: string x-kubernetes-int-or-string: true requests: - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object additionalProperties: pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ @@ -4807,6 +4976,7 @@ spec: description: InstallModeType is a supported type of install mode for CSV installation type: string keywords: + description: A list of keywords describing the operator. type: array items: type: string @@ -4816,6 +4986,7 @@ spec: additionalProperties: type: string links: + description: A list of links related to the operator. type: array items: type: object @@ -4825,6 +4996,7 @@ spec: url: type: string maintainers: + description: A list of organizational entities maintaining the operator. type: array items: type: object @@ -4854,6 +5026,7 @@ spec: version: type: string provider: + description: The publishing entity behind the operator. type: object properties: name: @@ -4992,22 +5165,26 @@ spec: type: array items: type: string + x-kubernetes-list-type: atomic apiVersions: description: APIVersions is the API versions the resources belong to. '*' is all versions. If '*' is present, the length of the slice must be one. Required. type: array items: type: string + x-kubernetes-list-type: atomic operations: description: Operations is the operations the admission hook cares about - CREATE, UPDATE, DELETE, CONNECT or * for all of those operations and any future admission operations that are added. If '*' is present, the length of the slice must be one. Required. type: array items: description: OperationType specifies an operation for a request. type: string + x-kubernetes-list-type: atomic resources: description: "Resources is a list of resources this rule applies to. \n For example: 'pods' means pods. 'pods/log' means the log subresource of pods. '*' means all resources, but not subresources. 'pods/*' means all subresources of pods. '*/scale' means all scale subresources. '*/*' means all resources and their subresources. \n If wildcard is present, the validation rule will ensure resources do not overlap with each other. \n Depending on the enclosing object, subresources might not be allowed. Required." type: array items: type: string + x-kubernetes-list-type: atomic scope: description: scope specifies the scope of this rule. Valid values are "Cluster", "Namespaced", and "*" "Cluster" means that only cluster-scoped resources will match this rule. Namespace API objects are cluster-scoped. "Namespaced" means that only namespaced resources will match this rule. "*" means that there are no scope restrictions. Subresources match the scope of their parent resource. Default is "*". type: string diff --git a/manifests/0000_50_olm_00-subscriptions.crd.yaml b/manifests/0000_50_olm_00-subscriptions.crd.yaml index 8618f9d66b..6b51d9fa19 100644 --- a/manifests/0000_50_olm_00-subscriptions.crd.yaml +++ b/manifests/0000_50_olm_00-subscriptions.crd.yaml @@ -645,6 +645,21 @@ spec: description: 'Resources represents compute resources required by this container. Immutable. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' type: object properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers." + type: array + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + type: object + required: + - name + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object @@ -655,7 +670,7 @@ spec: - type: string x-kubernetes-int-or-string: true requests: - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object additionalProperties: pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ @@ -989,7 +1004,7 @@ spec: description: 'medium represents what type of storage medium should back this directory. The default is "" which means to use the node''s default medium. Must be an empty string (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' type: string sizeLimit: - description: 'sizeLimit is the total amount of local storage required for this EmptyDir volume. The size limit is also applicable for memory medium. The maximum usage on memory medium EmptyDir would be the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the limit is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir' + description: 'sizeLimit is the total amount of local storage required for this EmptyDir volume. The size limit is also applicable for memory medium. The maximum usage on memory medium EmptyDir would be the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ anyOf: - type: integer @@ -1018,7 +1033,7 @@ spec: items: type: string dataSource: - description: 'dataSource field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. If the AnyVolumeDataSource feature gate is enabled, this field will always have the same contents as the DataSourceRef field.' + description: 'dataSource field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef, and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. If the namespace is specified, then dataSourceRef will not be copied to dataSource.' type: object required: - kind @@ -1034,7 +1049,7 @@ spec: description: Name is the name of resource being referenced type: string dataSourceRef: - description: 'dataSourceRef specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any local object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the DataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, both fields (DataSource and DataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. There are two important differences between DataSource and DataSourceRef: * While DataSource only allows two specific types of objects, DataSourceRef allows any non-core object, as well as PersistentVolumeClaim objects. * While DataSource ignores disallowed values (dropping them), DataSourceRef preserves all values, and generates an error if a disallowed value is specified. (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled.' + description: 'dataSourceRef specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the dataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, when namespace isn''t specified in dataSourceRef, both fields (dataSource and dataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. When namespace is specified in dataSourceRef, dataSource isn''t set to the same value and must be empty. There are three important differences between dataSource and dataSourceRef: * While dataSource only allows two specific types of objects, dataSourceRef allows any non-core object, as well as PersistentVolumeClaim objects. * While dataSource ignores disallowed values (dropping them), dataSourceRef preserves all values, and generates an error if a disallowed value is specified. * While dataSource only allows local objects, dataSourceRef allows objects in any namespaces. (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled. (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled.' type: object required: - kind @@ -1049,10 +1064,28 @@ spec: name: description: Name is the name of resource being referenced type: string + namespace: + description: Namespace is the namespace of resource being referenced Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled. + type: string resources: description: 'resources represents the minimum resources the volume should have. If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' type: object properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers." + type: array + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + type: object + required: + - name + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object @@ -1063,7 +1096,7 @@ spec: - type: string x-kubernetes-int-or-string: true requests: - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object additionalProperties: pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ diff --git a/manifests/0000_90_olm_00-service-monitor.yaml b/manifests/0000_90_olm_00-service-monitor.yaml index 710a551cf1..2ea19f4a64 100644 --- a/manifests/0000_90_olm_00-service-monitor.yaml +++ b/manifests/0000_90_olm_00-service-monitor.yaml @@ -78,7 +78,6 @@ metadata: include.release.openshift.io/ibm-cloud-managed: "true" include.release.openshift.io/self-managed-high-availability: "true" spec: - jobLabel: k8s-app endpoints: - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token interval: 30s diff --git a/pkg/manifests/csv.yaml b/pkg/manifests/csv.yaml index 897fbeecef..a4c35314dc 100644 --- a/pkg/manifests/csv.yaml +++ b/pkg/manifests/csv.yaml @@ -5,7 +5,7 @@ metadata: name: packageserver namespace: openshift-operator-lifecycle-manager labels: - olm.version: 0.19.0 + olm.version: 0.0.0-e17b6a389771f79426879e9feeae14d959b90e48 olm.clusteroperator.name: operator-lifecycle-manager-packageserver annotations: include.release.openshift.io/self-managed-high-availability: "true" @@ -159,7 +159,7 @@ spec: - packageserver topologyKey: "kubernetes.io/hostname" maturity: alpha - version: 0.19.0 + version: 0.0.0-e17b6a389771f79426879e9feeae14d959b90e48 apiservicedefinitions: owned: - group: packages.operators.coreos.com diff --git a/scripts/sync.sh b/scripts/sync.sh index 72340c4e93..769eac96f6 100755 --- a/scripts/sync.sh +++ b/scripts/sync.sh @@ -38,13 +38,15 @@ candidates() { for remote in "${UPSTREAM_REMOTES[@]}"; do "${ROOT_DIR}"/scripts/sync_get_candidates.sh "$remote" done + + # Create uber cherry-pick list + cat *.cherrypick | sort > all.cherrypick + echo "Number of commits to cherrypick: $(cat all.cherrypick | wc -l)" } pop() { echo "Applying all upstream commit candidates" - for remote in "${UPSTREAM_REMOTES[@]}"; do - "${ROOT_DIR}"/scripts/sync_pop_candidate.sh -a "${remote}" - done + "${ROOT_DIR}"/scripts/sync_pop_candidate.sh -a "all" } check_local_branch_commit_diff() { diff --git a/scripts/sync_get_candidates.sh b/scripts/sync_get_candidates.sh index c92996fd23..fb23005e29 100755 --- a/scripts/sync_get_candidates.sh +++ b/scripts/sync_get_candidates.sh @@ -28,7 +28,7 @@ cherrypick_set="${remote}.cherrypick" : > "${cherrypick_set}" # clear existing file for rc in "${remote_commits[@]}"; do if [[ -z $(git log -n 1 --no-merges --grep "${rc}" HEAD) && -z $(grep "${rc}" "${remote}.blacklist") ]]; then - printf '%s\n' "${rc}" >> "${cherrypick_set}" + git show -s --format="%cI ${remote} %H" "${rc}" >> "${cherrypick_set}" (( ++picked )) fi done diff --git a/scripts/sync_pop_candidate.sh b/scripts/sync_pop_candidate.sh index e371806d4c..f8680788f9 100755 --- a/scripts/sync_pop_candidate.sh +++ b/scripts/sync_pop_candidate.sh @@ -2,6 +2,7 @@ set -o errexit set -o pipefail +#set -x ROOT_DIR=$(dirname "${BASH_SOURCE[@]}")/.. # shellcheck disable=SC1091 @@ -30,33 +31,50 @@ function pop() { printf 'nothing to pick' exit fi + readarray -t rcs < <(echo "$rc" | tr " " "\n") + remote="${rcs[1]}" + subtree_dir="staging/${remote}" + rc="${rcs[2]}" printf 'popping: %s\n' "${rc}" if ! git cherry-pick --allow-empty --keep-redundant-commits -Xsubtree="${subtree_dir}" "${rc}"; then # Always blast away the vendor directory given OLM/registry still commit it into source control. git rm -rf "${subtree_dir}"/vendor 2>/dev/null || true + # Look for any deleted by us + readarray -t deletes < <(git status --porcelain| grep -oP "^DU \K.*") + for d in "${deletes[@]}"; do + git rm "${d}" + done + echo "Done with deletes" + + # Handle other conflicts num_conflicts=$(git diff --name-only --diff-filter=U --relative | wc -l) while [[ $num_conflicts != 0 ]] ; do - file=$(git diff --name-only --diff-filter=U --relative) - - if [[ $file == *"go.mod"* ]]; then - git diff "${subtree_dir}"/go.mod - - git checkout --theirs "${subtree_dir}"/go.mod - pushd "${subtree_dir}" - go mod tidy - git add go.mod go.sum - popd - else - git checkout --theirs "$file" - git diff "$file" - git add "$file" - fi + readarray -t files < <(git diff --name-only --diff-filter=U --relative) + + for f in "${files[@]}"; do + + # Note that this can be a problem if there are regressions! (e.g. 1.2 -> 1.1) + if [[ ${f} == *"go.mod"* ]]; then + git diff "${subtree_dir}"/go.mod + + git checkout --theirs "${subtree_dir}"/go.mod + pushd "${subtree_dir}" + go mod tidy + git add go.mod go.sum + popd + else + git checkout --theirs "${f}" + git diff "${f}" + git add "${f}" + fi + done num_conflicts=$(git diff --name-only --diff-filter=U --relative | wc -l) echo "Number of merge conflicts remaining: $num_conflicts" done + echo "Done with conflicts" if [[ -z $(git status --porcelain) ]]; then git commit --allow-empty @@ -66,16 +84,36 @@ function pop() { fi fi + # Did go.mod change? + if ! git diff --quiet HEAD^ "${subtree_dir}"/go.mod; then + git diff HEAD^ "${subtree_dir}"/go.mod + pushd "${subtree_dir}" + echo "Running BASH subshell: go.mod has changed, check for regressions!" + echo -n ' to continue, ^C to quit: ' + read + popd + fi # 1. Pop next commit off cherrypick set # 2. Cherry-pick # 3. Ammend commit # 4. Remove from cherrypick set - make vendor - make manifests + if ! make vendor; then + echo "Running BASH subshell: fix make vendor" + echo -n ' to continue, ^C to quit: ' + read + fi git add "${subtree_dir}" "${ROOT_GENERATED_PATHS[@]}" git status git commit --amend --allow-empty --no-edit --trailer "Upstream-repository: ${remote}" --trailer "Upstream-commit: ${rc}" + if ! make manifests; then + echo "Running BASH subshell: fix make manifests" + echo -n ' to continue, ^C to quit: ' + read + fi + git add "${subtree_dir}" "${ROOT_GENERATED_PATHS[@]}" + git status + git commit --amend --allow-empty --no-edit tmp_set=$(mktemp) tail -n +2 "${cherrypick_set}" > "${tmp_set}"; cat "${tmp_set}" > "${cherrypick_set}" diff --git a/staging/api/.github/workflows/go.yaml b/staging/api/.github/workflows/go.yaml index 3fa8fbcb6a..2da8edbf35 100644 --- a/staging/api/.github/workflows/go.yaml +++ b/staging/api/.github/workflows/go.yaml @@ -13,9 +13,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 id: go - name: Check out code into the Go module directory uses: actions/checkout@v2 @@ -29,7 +29,12 @@ jobs: restore-keys: | ${{ runner.os }}-go- - name: unit-test - run: go test -v ./... + run: go test -v ./... -coverprofile cover.out + - uses: codecov/codecov-action@v3 + with: + files: cover.out + fail_ci_if_error: true + functionalities: fixes go-apidiff: name: go-apidiff @@ -37,9 +42,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Set up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v3 with: - go-version: 1.18 + go-version: 1.19 id: go - name: Print out Go env run: go env diff --git a/staging/api/.github/workflows/verify.yml b/staging/api/.github/workflows/verify.yml index 11fa0edfe6..b5771af1c6 100644 --- a/staging/api/.github/workflows/verify.yml +++ b/staging/api/.github/workflows/verify.yml @@ -12,9 +12,9 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - uses: actions/setup-go@v2 + - uses: actions/setup-go@v3 with: - go-version: '~1.18' + go-version: '~1.19' - name: Run the verify target run: | export GOPATH=$(go env GOPATH) diff --git a/staging/api/.gitignore b/staging/api/.gitignore index d6395083f0..48684a7b8b 100644 --- a/staging/api/.gitignore +++ b/staging/api/.gitignore @@ -20,3 +20,5 @@ .idea/* vendor/ bin/ + +.vscode diff --git a/staging/api/Makefile b/staging/api/Makefile index b5fdf9d55c..31ff7bd135 100644 --- a/staging/api/Makefile +++ b/staging/api/Makefile @@ -22,7 +22,6 @@ help: ## Show this help screen @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z0-9_-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) .PHONY: install - install: ## Build & install operator-verify $(Q)go install \ -gcflags "all=-trimpath=${GOPATH}" \ @@ -42,7 +41,7 @@ format: ## Format the source code $(Q)go fmt $(PKGS) tidy: ## Update dependencies - $(Q)go mod tidy -v + $(Q)go mod tidy $(Q)go mod verify clean: ## Clean up the build artifacts @@ -59,17 +58,17 @@ manifests: yq controller-gen ## Generate manifests e.g. CRD, RBAC etc $(CONTROLLER_GEN) schemapatch:manifests=./crds output:dir=./crds paths=./pkg/operators/... @# Add missing defaults in embedded core API schemas - $(Q)$(YQ) w --inplace ./crds/operators.coreos.com_clusterserviceversions.yaml spec.versions[0].schema.openAPIV3Schema.properties.spec.properties.install.properties.spec.properties.deployments.items.properties.spec.properties.template.properties.spec.properties.containers.items.properties.ports.items.properties.protocol.default TCP - $(Q)$(YQ) w --inplace ./crds/operators.coreos.com_clusterserviceversions.yaml spec.versions[0].schema.openAPIV3Schema.properties.spec.properties.install.properties.spec.properties.deployments.items.properties.spec.properties.template.properties.spec.properties.initContainers.items.properties.ports.items.properties.protocol.default TCP + $(YQ) --inplace '.spec.versions[0].schema.openAPIV3Schema.properties.spec.properties.install.properties.spec.properties.deployments.items.properties.spec.properties.template.properties.spec.properties.containers.items.properties.ports.items.properties.protocol.default="TCP"' ./crds/operators.coreos.com_clusterserviceversions.yaml + $(Q)$(YQ) --inplace '.spec.versions[0].schema.openAPIV3Schema.properties.spec.properties.install.properties.spec.properties.deployments.items.properties.spec.properties.template.properties.spec.properties.initContainers.items.properties.ports.items.properties.protocol.default="TCP"' ./crds/operators.coreos.com_clusterserviceversions.yaml @# Preserve fields for embedded metadata fields - $(Q)$(YQ) w --inplace ./crds/operators.coreos.com_clusterserviceversions.yaml spec.versions[0].schema.openAPIV3Schema.properties.spec.properties.install.properties.spec.properties.deployments.items.properties.spec.properties.template.properties.metadata.x-kubernetes-preserve-unknown-fields true + $(Q)$(YQ) --inplace '.spec.versions[0].schema.openAPIV3Schema.properties.spec.properties.install.properties.spec.properties.deployments.items.properties.spec.properties.template.properties.metadata.x-kubernetes-preserve-unknown-fields=true' ./crds/operators.coreos.com_clusterserviceversions.yaml @# Remove OperatorCondition.spec.overrides[*].lastTransitionTime requirement - $(Q)$(YQ) delete --inplace ./crds/operators.coreos.com_operatorconditions.yaml 'spec.versions[*].schema.openAPIV3Schema.properties.spec.properties.overrides.items.required(.==lastTransitionTime)' + $(Q)$(YQ) --inplace 'del(.spec.versions[].schema.openAPIV3Schema.properties.spec.properties.overrides.items.required[] | select(. == "lastTransitionTime"))' ./crds/operators.coreos.com_operatorconditions.yaml @# Remove status subresource from the CRD manifests to ensure server-side apply works - $(Q)for f in ./crds/*.yaml ; do $(YQ) d --inplace $$f status; done + $(Q)for f in ./crds/*.yaml ; do $(YQ) --inplace 'del(.status)' $$f; done @# Update embedded CRD files. $(Q)go generate ./crds/... @@ -102,7 +101,8 @@ CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen YQ ?= $(LOCALBIN)/yq ## Tool Versions -CONTROLLER_TOOLS_VERSION ?= v0.8.0 +CONTROLLER_TOOLS_VERSION ?= v0.9.0 +YQ_VERSION ?= v4.28.1 .PHONY: controller-gen controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary. @@ -112,4 +112,4 @@ $(CONTROLLER_GEN): $(LOCALBIN) .PHONY: yq yq: $(YQ) ## Download yq locally if necessary. $(YQ): $(LOCALBIN) - GOBIN=$(LOCALBIN) go install $(GO_INSTALL_OPTS) github.com/mikefarah/yq/v3@latest + GOBIN=$(LOCALBIN) go install $(GO_INSTALL_OPTS) github.com/mikefarah/yq/v4@$(YQ_VERSION) diff --git a/staging/api/OWNERS b/staging/api/OWNERS index cb3e6f7ea5..79add35148 100644 --- a/staging/api/OWNERS +++ b/staging/api/OWNERS @@ -9,6 +9,7 @@ approvers: - joelanford - jmrodri - perdasilva + - grokspawn # review == this code is good /lgtm reviewers: - ecordell @@ -25,3 +26,5 @@ reviewers: - ankitathomas - jmrodri - perdasilva + - grokspawn + - oceanc80 diff --git a/staging/api/crds/operators.coreos.com_catalogsources.yaml b/staging/api/crds/operators.coreos.com_catalogsources.yaml index 2836d66fed..e42010c7ad 100644 --- a/staging/api/crds/operators.coreos.com_catalogsources.yaml +++ b/staging/api/crds/operators.coreos.com_catalogsources.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.8.0 + controller-gen.kubebuilder.io/version: v0.9.0 creationTimestamp: null name: catalogsources.operators.coreos.com spec: @@ -71,6 +71,467 @@ spec: description: GrpcPodConfig exposes different overrides for the pod spec of the CatalogSource Pod. Only used when SourceType = SourceTypeGrpc and Image is set. type: object properties: + affinity: + description: Affinity is the catalog source's pod's affinity. + type: object + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the pod. + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node matches the corresponding matchExpressions; the node(s) with the highest sum are the most preferred. + type: array + items: + description: An empty preferred scheduling term matches all objects with implicit weight 0 (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). + type: object + required: + - preference + - weight + properties: + preference: + description: A node selector term, associated with the corresponding weight. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + weight: + description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to an update), the system may or may not try to eventually evict the pod from its node. + type: object + required: + - nodeSelectorTerms + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The terms are ORed. + type: array + items: + description: A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + weight: + description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. + type: array + items: + description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes that satisfy the anti-affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + weight: + description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the anti-affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. + type: array + items: + description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string nodeSelector: description: NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node's labels for the pod to be scheduled on that node. type: object @@ -127,6 +588,9 @@ spec: type: integer publisher: type: string + runAsRoot: + description: RunAsRoot allows admins to indicate that they wish to run the CatalogSource pod in a privileged pod as root. This should only be enabled when running older catalog images which could not be run as non-root. + type: boolean secrets: description: Secrets represent set of secrets that can be used to access the contents of the catalog. It is best to keep this list small, since each will need to be tried for every catalog entry. type: array @@ -152,7 +616,7 @@ spec: description: Represents the state of a CatalogSource. Note that Message and Reason represent the original status information, which may be migrated to be conditions based in the future. Any new features introduced will use conditions. type: array items: - description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" type: object required: - lastTransitionTime diff --git a/staging/api/crds/operators.coreos.com_clusterserviceversions.yaml b/staging/api/crds/operators.coreos.com_clusterserviceversions.yaml index 37b41c4608..e5a35991bd 100644 --- a/staging/api/crds/operators.coreos.com_clusterserviceversions.yaml +++ b/staging/api/crds/operators.coreos.com_clusterserviceversions.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.8.0 + controller-gen.kubebuilder.io/version: v0.9.0 creationTimestamp: null name: clusterserviceversions.operators.coreos.com spec: @@ -119,7 +119,7 @@ spec: resources: type: array items: - description: APIResourceReference is a Kubernetes resource type used by a custom resource + description: APIResourceReference is a reference to a Kubernetes resource type that the referrer utilizes. type: object required: - kind @@ -127,10 +127,13 @@ spec: - version properties: kind: + description: Kind of the referenced resource type. type: string name: + description: Plural name of the referenced resource type (CustomResourceDefinition.Spec.Names[].Plural). Empty string if the referenced resource type is not a custom resource. type: string version: + description: API Version of the referenced resource type. type: string specDescriptors: type: array @@ -229,7 +232,7 @@ spec: resources: type: array items: - description: APIResourceReference is a Kubernetes resource type used by a custom resource + description: APIResourceReference is a reference to a Kubernetes resource type that the referrer utilizes. type: object required: - kind @@ -237,10 +240,13 @@ spec: - version properties: kind: + description: Kind of the referenced resource type. type: string name: + description: Plural name of the referenced resource type (CustomResourceDefinition.Spec.Names[].Plural). Empty string if the referenced resource type is not a custom resource. type: string version: + description: API Version of the referenced resource type. type: string specDescriptors: type: array @@ -343,7 +349,7 @@ spec: resources: type: array items: - description: APIResourceReference is a Kubernetes resource type used by a custom resource + description: APIResourceReference is a reference to a Kubernetes resource type that the referrer utilizes. type: object required: - kind @@ -351,10 +357,13 @@ spec: - version properties: kind: + description: Kind of the referenced resource type. type: string name: + description: Plural name of the referenced resource type (CustomResourceDefinition.Spec.Names[].Plural). Empty string if the referenced resource type is not a custom resource. type: string version: + description: API Version of the referenced resource type. type: string specDescriptors: type: array @@ -445,7 +454,7 @@ spec: resources: type: array items: - description: APIResourceReference is a Kubernetes resource type used by a custom resource + description: APIResourceReference is a reference to a Kubernetes resource type that the referrer utilizes. type: object required: - kind @@ -453,10 +462,13 @@ spec: - version properties: kind: + description: Kind of the referenced resource type. type: string name: + description: Plural name of the referenced resource type (CustomResourceDefinition.Spec.Names[].Plural). Empty string if the referenced resource type is not a custom resource. type: string version: + description: API Version of the referenced resource type. type: string specDescriptors: type: array @@ -505,10 +517,13 @@ spec: version: type: string description: + description: Description of the operator. Can include the features, limitations or use-cases of the operator. type: string displayName: + description: The name of the operator in display format. type: string icon: + description: The icon for this operator. type: array items: type: object @@ -550,7 +565,7 @@ spec: - verbs properties: apiGroups: - description: APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of the enumerated resources in any API group will be allowed. + description: APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of the enumerated resources in any API group will be allowed. "" represents the core API group and "*" represents all API groups. type: array items: type: string @@ -672,7 +687,7 @@ spec: description: Type of deployment. Can be "Recreate" or "RollingUpdate". Default is RollingUpdate. type: string template: - description: Template describes the pods that will be created. + description: Template describes the pods that will be created. The only allowed template.spec.restartPolicy value is "Always". type: object properties: metadata: @@ -1325,7 +1340,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -1390,7 +1405,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -1440,7 +1455,7 @@ spec: type: integer format: int32 grpc: - description: GRPC specifies an action involving a GRPC port. This is a beta field and requires enabling GRPCContainerProbe feature gate. + description: GRPC specifies an action involving a GRPC port. type: object required: - port @@ -1472,7 +1487,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -1528,7 +1543,7 @@ spec: description: Name of the container specified as a DNS_LABEL. Each container in a pod must have a unique name (DNS_LABEL). Cannot be updated. type: string ports: - description: List of ports to expose from the container. Exposing a port here gives the system additional information about the network connections a container uses, but is primarily informational. Not specifying a port here DOES NOT prevent that port from being exposed. Any port which is listening on the default "0.0.0.0" address inside a container will be accessible from the network. Cannot be updated. + description: List of ports to expose from the container. Not specifying a port here DOES NOT prevent that port from being exposed. Any port which is listening on the default "0.0.0.0" address inside a container will be accessible from the network. Modifying this array with strategic merge patch may corrupt the data. For more information See https://github.com/kubernetes/kubernetes/issues/108255. Cannot be updated. type: array items: description: ContainerPort represents a network port in a single container. @@ -1576,7 +1591,7 @@ spec: type: integer format: int32 grpc: - description: GRPC specifies an action involving a GRPC port. This is a beta field and requires enabling GRPCContainerProbe feature gate. + description: GRPC specifies an action involving a GRPC port. type: object required: - port @@ -1608,7 +1623,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -1660,10 +1675,42 @@ spec: description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' type: integer format: int32 + resizePolicy: + description: Resources resize policy for the container. + type: array + items: + description: ContainerResizePolicy represents resource resize policy for the container. + type: object + required: + - resourceName + - restartPolicy + properties: + resourceName: + description: 'Name of the resource to which this resource resize policy applies. Supported values: cpu, memory.' + type: string + restartPolicy: + description: Restart policy to apply when specified resource is resized. If not specified, it defaults to NotRequired. + type: string + x-kubernetes-list-type: atomic resources: description: 'Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers." + type: array + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + type: object + required: + - name + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object @@ -1674,7 +1721,7 @@ spec: - type: string x-kubernetes-int-or-string: true requests: - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object additionalProperties: pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ @@ -1787,7 +1834,7 @@ spec: type: integer format: int32 grpc: - description: GRPC specifies an action involving a GRPC port. This is a beta field and requires enabling GRPCContainerProbe feature gate. + description: GRPC specifies an action involving a GRPC port. type: object required: - port @@ -1819,7 +1866,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -1966,10 +2013,10 @@ spec: description: 'EnableServiceLinks indicates whether information about services should be injected into pod''s environment variables, matching the syntax of Docker links. Optional: Defaults to true.' type: boolean ephemeralContainers: - description: List of ephemeral containers run in this pod. Ephemeral containers may be run in an existing pod to perform user-initiated actions such as debugging. This list cannot be specified when creating a pod, and it cannot be modified by updating the pod spec. In order to add an ephemeral container to an existing pod, use the pod's ephemeralcontainers subresource. This field is beta-level and available on clusters that haven't disabled the EphemeralContainers feature gate. + description: List of ephemeral containers run in this pod. Ephemeral containers may be run in an existing pod to perform user-initiated actions such as debugging. This list cannot be specified when creating a pod, and it cannot be modified by updating the pod spec. In order to add an ephemeral container to an existing pod, use the pod's ephemeralcontainers subresource. type: array items: - description: "An EphemeralContainer is a temporary container that you may add to an existing Pod for user-initiated activities such as debugging. Ephemeral containers have no resource or scheduling guarantees, and they will not be restarted when they exit or when a Pod is removed or restarted. The kubelet may evict a Pod if an ephemeral container causes the Pod to exceed its resource allocation. \n To add an ephemeral container, use the ephemeralcontainers subresource of an existing Pod. Ephemeral containers may not be removed or restarted. \n This is a beta feature available on clusters that haven't disabled the EphemeralContainers feature gate." + description: "An EphemeralContainer is a temporary container that you may add to an existing Pod for user-initiated activities such as debugging. Ephemeral containers have no resource or scheduling guarantees, and they will not be restarted when they exit or when a Pod is removed or restarted. The kubelet may evict a Pod if an ephemeral container causes the Pod to exceed its resource allocation. \n To add an ephemeral container, use the ephemeralcontainers subresource of an existing Pod. Ephemeral containers may not be removed or restarted." type: object required: - name @@ -2137,7 +2184,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -2202,7 +2249,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -2252,7 +2299,7 @@ spec: type: integer format: int32 grpc: - description: GRPC specifies an action involving a GRPC port. This is a beta field and requires enabling GRPCContainerProbe feature gate. + description: GRPC specifies an action involving a GRPC port. type: object required: - port @@ -2284,7 +2331,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -2388,7 +2435,7 @@ spec: type: integer format: int32 grpc: - description: GRPC specifies an action involving a GRPC port. This is a beta field and requires enabling GRPCContainerProbe feature gate. + description: GRPC specifies an action involving a GRPC port. type: object required: - port @@ -2420,7 +2467,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -2472,10 +2519,42 @@ spec: description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' type: integer format: int32 + resizePolicy: + description: Resources resize policy for the container. + type: array + items: + description: ContainerResizePolicy represents resource resize policy for the container. + type: object + required: + - resourceName + - restartPolicy + properties: + resourceName: + description: 'Name of the resource to which this resource resize policy applies. Supported values: cpu, memory.' + type: string + restartPolicy: + description: Restart policy to apply when specified resource is resized. If not specified, it defaults to NotRequired. + type: string + x-kubernetes-list-type: atomic resources: description: Resources are not allowed for ephemeral containers. Ephemeral containers use spare resources already allocated to the pod. type: object properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers." + type: array + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + type: object + required: + - name + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object @@ -2486,7 +2565,7 @@ spec: - type: string x-kubernetes-int-or-string: true requests: - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object additionalProperties: pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ @@ -2599,7 +2678,7 @@ spec: type: integer format: int32 grpc: - description: GRPC specifies an action involving a GRPC port. This is a beta field and requires enabling GRPCContainerProbe feature gate. + description: GRPC specifies an action involving a GRPC port. type: object required: - port @@ -2631,7 +2710,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -2772,6 +2851,9 @@ spec: hostPID: description: 'Use the host''s pid namespace. Optional: Default to false.' type: boolean + hostUsers: + description: 'Use the host''s user namespace. Optional: Default to true. If set to true or not present, the pod will be run in the host user namespace, useful for when the pod needs a feature only available to the host user namespace, such as loading a kernel module with CAP_SYS_MODULE. When set to false, a new userns is created for the pod. Setting false is useful for mitigating container breakout vulnerabilities even allowing users to run their containers as root without actually having root privileges on the host. This field is alpha-level and is only honored by servers that enable the UserNamespacesSupport feature.' + type: boolean hostname: description: Specifies the hostname of the Pod If not specified, the pod's hostname will be set to a system-defined value. type: string @@ -2957,7 +3039,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -3022,7 +3104,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -3072,7 +3154,7 @@ spec: type: integer format: int32 grpc: - description: GRPC specifies an action involving a GRPC port. This is a beta field and requires enabling GRPCContainerProbe feature gate. + description: GRPC specifies an action involving a GRPC port. type: object required: - port @@ -3104,7 +3186,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -3160,7 +3242,7 @@ spec: description: Name of the container specified as a DNS_LABEL. Each container in a pod must have a unique name (DNS_LABEL). Cannot be updated. type: string ports: - description: List of ports to expose from the container. Exposing a port here gives the system additional information about the network connections a container uses, but is primarily informational. Not specifying a port here DOES NOT prevent that port from being exposed. Any port which is listening on the default "0.0.0.0" address inside a container will be accessible from the network. Cannot be updated. + description: List of ports to expose from the container. Not specifying a port here DOES NOT prevent that port from being exposed. Any port which is listening on the default "0.0.0.0" address inside a container will be accessible from the network. Modifying this array with strategic merge patch may corrupt the data. For more information See https://github.com/kubernetes/kubernetes/issues/108255. Cannot be updated. type: array items: description: ContainerPort represents a network port in a single container. @@ -3208,7 +3290,7 @@ spec: type: integer format: int32 grpc: - description: GRPC specifies an action involving a GRPC port. This is a beta field and requires enabling GRPCContainerProbe feature gate. + description: GRPC specifies an action involving a GRPC port. type: object required: - port @@ -3240,7 +3322,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -3292,10 +3374,42 @@ spec: description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' type: integer format: int32 + resizePolicy: + description: Resources resize policy for the container. + type: array + items: + description: ContainerResizePolicy represents resource resize policy for the container. + type: object + required: + - resourceName + - restartPolicy + properties: + resourceName: + description: 'Name of the resource to which this resource resize policy applies. Supported values: cpu, memory.' + type: string + restartPolicy: + description: Restart policy to apply when specified resource is resized. If not specified, it defaults to NotRequired. + type: string + x-kubernetes-list-type: atomic resources: description: 'Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers." + type: array + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + type: object + required: + - name + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object @@ -3306,7 +3420,7 @@ spec: - type: string x-kubernetes-int-or-string: true requests: - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object additionalProperties: pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ @@ -3419,7 +3533,7 @@ spec: type: integer format: int32 grpc: - description: GRPC specifies an action involving a GRPC port. This is a beta field and requires enabling GRPCContainerProbe feature gate. + description: GRPC specifies an action involving a GRPC port. type: object required: - port @@ -3451,7 +3565,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -3575,7 +3689,7 @@ spec: type: string x-kubernetes-map-type: atomic os: - description: "Specifies the OS of the containers in the pod. Some pod and container fields are restricted if this is set. \n If the OS field is set to linux, the following fields must be unset: -securityContext.windowsOptions \n If the OS field is set to windows, following fields must be unset: - spec.hostPID - spec.hostIPC - spec.securityContext.seLinuxOptions - spec.securityContext.seccompProfile - spec.securityContext.fsGroup - spec.securityContext.fsGroupChangePolicy - spec.securityContext.sysctls - spec.shareProcessNamespace - spec.securityContext.runAsUser - spec.securityContext.runAsGroup - spec.securityContext.supplementalGroups - spec.containers[*].securityContext.seLinuxOptions - spec.containers[*].securityContext.seccompProfile - spec.containers[*].securityContext.capabilities - spec.containers[*].securityContext.readOnlyRootFilesystem - spec.containers[*].securityContext.privileged - spec.containers[*].securityContext.allowPrivilegeEscalation - spec.containers[*].securityContext.procMount - spec.containers[*].securityContext.runAsUser - spec.containers[*].securityContext.runAsGroup This is a beta field and requires the IdentifyPodOS feature" + description: "Specifies the OS of the containers in the pod. Some pod and container fields are restricted if this is set. \n If the OS field is set to linux, the following fields must be unset: -securityContext.windowsOptions \n If the OS field is set to windows, following fields must be unset: - spec.hostPID - spec.hostIPC - spec.hostUsers - spec.securityContext.seLinuxOptions - spec.securityContext.seccompProfile - spec.securityContext.fsGroup - spec.securityContext.fsGroupChangePolicy - spec.securityContext.sysctls - spec.shareProcessNamespace - spec.securityContext.runAsUser - spec.securityContext.runAsGroup - spec.securityContext.supplementalGroups - spec.containers[*].securityContext.seLinuxOptions - spec.containers[*].securityContext.seccompProfile - spec.containers[*].securityContext.capabilities - spec.containers[*].securityContext.readOnlyRootFilesystem - spec.containers[*].securityContext.privileged - spec.containers[*].securityContext.allowPrivilegeEscalation - spec.containers[*].securityContext.procMount - spec.containers[*].securityContext.runAsUser - spec.containers[*].securityContext.runAsGroup" type: object required: - name @@ -3614,8 +3728,33 @@ spec: conditionType: description: ConditionType refers to a condition in the pod's condition list with matching type. type: string + resourceClaims: + description: "ResourceClaims defines which ResourceClaims must be allocated and reserved before the Pod is allowed to start. The resources will be made available to those containers which consume them by name. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable." + type: array + items: + description: PodResourceClaim references exactly one ResourceClaim through a ClaimSource. It adds a name to it that uniquely identifies the ResourceClaim inside the Pod. Containers that need access to the ResourceClaim reference it with this name. + type: object + required: + - name + properties: + name: + description: Name uniquely identifies this resource claim inside the pod. This must be a DNS_LABEL. + type: string + source: + description: Source describes where to find the ResourceClaim. + type: object + properties: + resourceClaimName: + description: ResourceClaimName is the name of a ResourceClaim object in the same namespace as this pod. + type: string + resourceClaimTemplateName: + description: "ResourceClaimTemplateName is the name of a ResourceClaimTemplate object in the same namespace as this pod. \n The template will be used to create a new ResourceClaim, which will be bound to this pod. When this pod is deleted, the ResourceClaim will also be deleted. The name of the ResourceClaim will be -, where is the PodResourceClaim.Name. Pod validation will reject the pod if the concatenated name is not valid for a ResourceClaim (e.g. too long). \n An existing ResourceClaim with that name that is not owned by the pod will not be used for the pod to avoid using an unrelated resource by mistake. Scheduling and pod startup are then blocked until the unrelated ResourceClaim is removed. \n This field is immutable and no changes will be made to the corresponding ResourceClaim by the control plane after creating the ResourceClaim." + type: string + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map restartPolicy: - description: 'Restart policy for all containers within the pod. One of Always, OnFailure, Never. Default to Always. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy' + description: 'Restart policy for all containers within the pod. One of Always, OnFailure, Never. In some contexts, only a subset of those values may be permitted. Default to Always. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy' type: string runtimeClassName: description: 'RuntimeClassName refers to a RuntimeClass object in the node.k8s.io group, which should be used to run this pod. If no RuntimeClass resource matches the named class, the pod will not be run. If unset or empty, the "legacy" RuntimeClass will be used, which is an implicit class with an empty definition that uses the default runtime handler. More info: https://git.k8s.io/enhancements/keps/sig-node/585-runtime-class' @@ -3623,6 +3762,21 @@ spec: schedulerName: description: If specified, the pod will be dispatched by specified scheduler. If not specified, the pod will be dispatched by default scheduler. type: string + schedulingGates: + description: "SchedulingGates is an opaque list of values that if specified will block scheduling the pod. If schedulingGates is not empty, the pod will stay in the SchedulingGated state and the scheduler will not attempt to schedule the pod. \n SchedulingGates can only be set at pod creation time, and be removed only afterwards. \n This is a beta feature enabled by the PodSchedulingReadiness feature gate." + type: array + items: + description: PodSchedulingGate is associated to a Pod to guard its scheduling. + type: object + required: + - name + properties: + name: + description: Name of the scheduling gate. Each scheduling gate must have a unique name field. + type: string + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map securityContext: description: 'SecurityContext holds pod-level security attributes and common container settings. Optional: Defaults to empty. See type description for default values of each field.' type: object @@ -3674,7 +3828,7 @@ spec: description: "type indicates which kind of seccomp profile will be applied. Valid options are: \n Localhost - a profile defined in a file on the node should be used. RuntimeDefault - the container runtime default profile should be used. Unconfined - no profile should be applied." type: string supplementalGroups: - description: A list of groups applied to the first process run in each container, in addition to the container's primary GID. If unspecified, no groups will be added to any container. Note that this field cannot be set when spec.os.name is windows. + description: A list of groups applied to the first process run in each container, in addition to the container's primary GID, the fsGroup (if specified), and group memberships defined in the container image for the uid of the container process. If unspecified, no additional groups are added to any container. Note that group memberships defined in the container image for the uid of the container process are still effective, even if they are not included in this list. Note that this field cannot be set when spec.os.name is windows. type: array items: type: integer @@ -3794,16 +3948,28 @@ spec: type: object additionalProperties: type: string + matchLabelKeys: + description: "MatchLabelKeys is a set of pod label keys to select the pods over which spreading will be calculated. The keys are used to lookup values from the incoming pod labels, those key-value labels are ANDed with labelSelector to select the group of existing pods over which spreading will be calculated for the incoming pod. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. MatchLabelKeys cannot be set when LabelSelector isn't set. Keys that don't exist in the incoming pod labels will be ignored. A null or empty list means only match against labelSelector. \n This is a beta field and requires the MatchLabelKeysInPodTopologySpread feature gate to be enabled (enabled by default)." + type: array + items: + type: string + x-kubernetes-list-type: atomic maxSkew: description: 'MaxSkew describes the degree to which pods may be unevenly distributed. When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference between the number of matching pods in the target topology and the global minimum. The global minimum is the minimum number of matching pods in an eligible domain or zero if the number of eligible domains is less than MinDomains. For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same labelSelector spread as 2/2/1: In this case, the global minimum is 1. | zone1 | zone2 | zone3 | | P P | P P | P | - if MaxSkew is 1, incoming pod can only be scheduled to zone3 to become 2/2/2; scheduling it onto zone1(zone2) would make the ActualSkew(3-1) on zone1(zone2) violate MaxSkew(1). - if MaxSkew is 2, incoming pod can be scheduled onto any zone. When `whenUnsatisfiable=ScheduleAnyway`, it is used to give higher precedence to topologies that satisfy it. It''s a required field. Default value is 1 and 0 is not allowed.' type: integer format: int32 minDomains: - description: "MinDomains indicates a minimum number of eligible domains. When the number of eligible domains with matching topology keys is less than minDomains, Pod Topology Spread treats \"global minimum\" as 0, and then the calculation of Skew is performed. And when the number of eligible domains with matching topology keys equals or greater than minDomains, this value has no effect on scheduling. As a result, when the number of eligible domains is less than minDomains, scheduler won't schedule more than maxSkew Pods to those domains. If value is nil, the constraint behaves as if MinDomains is equal to 1. Valid values are integers greater than 0. When value is not nil, WhenUnsatisfiable must be DoNotSchedule. \n For example, in a 3-zone cluster, MaxSkew is set to 2, MinDomains is set to 5 and pods with the same labelSelector spread as 2/2/2: | zone1 | zone2 | zone3 | | P P | P P | P P | The number of domains is less than 5(MinDomains), so \"global minimum\" is treated as 0. In this situation, new pod with the same labelSelector cannot be scheduled, because computed skew will be 3(3 - 0) if new Pod is scheduled to any of the three zones, it will violate MaxSkew. \n This is an alpha field and requires enabling MinDomainsInPodTopologySpread feature gate." + description: "MinDomains indicates a minimum number of eligible domains. When the number of eligible domains with matching topology keys is less than minDomains, Pod Topology Spread treats \"global minimum\" as 0, and then the calculation of Skew is performed. And when the number of eligible domains with matching topology keys equals or greater than minDomains, this value has no effect on scheduling. As a result, when the number of eligible domains is less than minDomains, scheduler won't schedule more than maxSkew Pods to those domains. If value is nil, the constraint behaves as if MinDomains is equal to 1. Valid values are integers greater than 0. When value is not nil, WhenUnsatisfiable must be DoNotSchedule. \n For example, in a 3-zone cluster, MaxSkew is set to 2, MinDomains is set to 5 and pods with the same labelSelector spread as 2/2/2: | zone1 | zone2 | zone3 | | P P | P P | P P | The number of domains is less than 5(MinDomains), so \"global minimum\" is treated as 0. In this situation, new pod with the same labelSelector cannot be scheduled, because computed skew will be 3(3 - 0) if new Pod is scheduled to any of the three zones, it will violate MaxSkew. \n This is a beta field and requires the MinDomainsInPodTopologySpread feature gate to be enabled (enabled by default)." type: integer format: int32 + nodeAffinityPolicy: + description: "NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector when calculating pod topology spread skew. Options are: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. \n If this value is nil, the behavior is equivalent to the Honor policy. This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag." + type: string + nodeTaintsPolicy: + description: "NodeTaintsPolicy indicates how we will treat node taints when calculating pod topology spread skew. Options are: - Honor: nodes without taints, along with tainted nodes for which the incoming pod has a toleration, are included. - Ignore: node taints are ignored. All nodes are included. \n If this value is nil, the behavior is equivalent to the Ignore policy. This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag." + type: string topologyKey: - description: TopologyKey is the key of node labels. Nodes that have a label with this key and identical values are considered to be in the same topology. We consider each as a "bucket", and try to put balanced number of pods into each bucket. We define a domain as a particular instance of a topology. Also, we define an eligible domain as a domain whose nodes match the node selector. e.g. If TopologyKey is "kubernetes.io/hostname", each Node is a domain of that topology. And, if TopologyKey is "topology.kubernetes.io/zone", each zone is a domain of that topology. It's a required field. + description: TopologyKey is the key of node labels. Nodes that have a label with this key and identical values are considered to be in the same topology. We consider each as a "bucket", and try to put balanced number of pods into each bucket. We define a domain as a particular instance of a topology. Also, we define an eligible domain as a domain whose nodes meet the requirements of nodeAffinityPolicy and nodeTaintsPolicy. e.g. If TopologyKey is "kubernetes.io/hostname", each Node is a domain of that topology. And, if TopologyKey is "topology.kubernetes.io/zone", each zone is a domain of that topology. It's a required field. type: string whenUnsatisfiable: description: 'WhenUnsatisfiable indicates how to deal with a pod if it doesn''t satisfy the spread constraint. - DoNotSchedule (default) tells the scheduler not to schedule it. - ScheduleAnyway tells the scheduler to schedule the pod in any location, but giving higher precedence to topologies that would help reduce the skew. A constraint is considered "Unsatisfiable" for an incoming pod if and only if every possible node assignment for that pod would violate "MaxSkew" on some topology. For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same labelSelector spread as 3/1/1: | zone1 | zone2 | zone3 | | P P P | P | P | If WhenUnsatisfiable is set to DoNotSchedule, incoming pod can only be scheduled to zone2(zone3) to become 3/2/1(3/1/2) as ActualSkew(2-1) on zone2(zone3) satisfies MaxSkew(1). In other words, the cluster can still be imbalanced, but scheduler won''t make it *more* imbalanced. It''s a required field.' @@ -4057,7 +4223,7 @@ spec: description: 'medium represents what type of storage medium should back this directory. The default is "" which means to use the node''s default medium. Must be an empty string (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' type: string sizeLimit: - description: 'sizeLimit is the total amount of local storage required for this EmptyDir volume. The size limit is also applicable for memory medium. The maximum usage on memory medium EmptyDir would be the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the limit is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir' + description: 'sizeLimit is the total amount of local storage required for this EmptyDir volume. The size limit is also applicable for memory medium. The maximum usage on memory medium EmptyDir would be the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ anyOf: - type: integer @@ -4086,7 +4252,7 @@ spec: items: type: string dataSource: - description: 'dataSource field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. If the AnyVolumeDataSource feature gate is enabled, this field will always have the same contents as the DataSourceRef field.' + description: 'dataSource field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef, and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. If the namespace is specified, then dataSourceRef will not be copied to dataSource.' type: object required: - kind @@ -4102,7 +4268,7 @@ spec: description: Name is the name of resource being referenced type: string dataSourceRef: - description: 'dataSourceRef specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any local object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the DataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, both fields (DataSource and DataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. There are two important differences between DataSource and DataSourceRef: * While DataSource only allows two specific types of objects, DataSourceRef allows any non-core object, as well as PersistentVolumeClaim objects. * While DataSource ignores disallowed values (dropping them), DataSourceRef preserves all values, and generates an error if a disallowed value is specified. (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled.' + description: 'dataSourceRef specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the dataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, when namespace isn''t specified in dataSourceRef, both fields (dataSource and dataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. When namespace is specified in dataSourceRef, dataSource isn''t set to the same value and must be empty. There are three important differences between dataSource and dataSourceRef: * While dataSource only allows two specific types of objects, dataSourceRef allows any non-core object, as well as PersistentVolumeClaim objects. * While dataSource ignores disallowed values (dropping them), dataSourceRef preserves all values, and generates an error if a disallowed value is specified. * While dataSource only allows local objects, dataSourceRef allows objects in any namespaces. (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled. (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled.' type: object required: - kind @@ -4117,10 +4283,28 @@ spec: name: description: Name is the name of resource being referenced type: string + namespace: + description: Namespace is the namespace of resource being referenced Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled. + type: string resources: description: 'resources represents the minimum resources the volume should have. If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' type: object properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers." + type: array + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + type: object + required: + - name + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object @@ -4131,7 +4315,7 @@ spec: - type: string x-kubernetes-int-or-string: true requests: - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object additionalProperties: pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ @@ -4746,7 +4930,7 @@ spec: - verbs properties: apiGroups: - description: APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of the enumerated resources in any API group will be allowed. + description: APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of the enumerated resources in any API group will be allowed. "" represents the core API group and "*" represents all API groups. type: array items: type: string @@ -4790,6 +4974,7 @@ spec: description: InstallModeType is a supported type of install mode for CSV installation type: string keywords: + description: A list of keywords describing the operator. type: array items: type: string @@ -4799,6 +4984,7 @@ spec: additionalProperties: type: string links: + description: A list of links related to the operator. type: array items: type: object @@ -4808,6 +4994,7 @@ spec: url: type: string maintainers: + description: A list of organizational entities maintaining the operator. type: array items: type: object @@ -4837,6 +5024,7 @@ spec: version: type: string provider: + description: The publishing entity behind the operator. type: object properties: name: @@ -4975,22 +5163,26 @@ spec: type: array items: type: string + x-kubernetes-list-type: atomic apiVersions: description: APIVersions is the API versions the resources belong to. '*' is all versions. If '*' is present, the length of the slice must be one. Required. type: array items: type: string + x-kubernetes-list-type: atomic operations: description: Operations is the operations the admission hook cares about - CREATE, UPDATE, DELETE, CONNECT or * for all of those operations and any future admission operations that are added. If '*' is present, the length of the slice must be one. Required. type: array items: description: OperationType specifies an operation for a request. type: string + x-kubernetes-list-type: atomic resources: description: "Resources is a list of resources this rule applies to. \n For example: 'pods' means pods. 'pods/log' means the log subresource of pods. '*' means all resources, but not subresources. 'pods/*' means all subresources of pods. '*/scale' means all scale subresources. '*/*' means all resources and their subresources. \n If wildcard is present, the validation rule will ensure resources do not overlap with each other. \n Depending on the enclosing object, subresources might not be allowed. Required." type: array items: type: string + x-kubernetes-list-type: atomic scope: description: scope specifies the scope of this rule. Valid values are "Cluster", "Namespaced", and "*" "Cluster" means that only cluster-scoped resources will match this rule. Namespace API objects are cluster-scoped. "Namespaced" means that only namespaced resources will match this rule. "*" means that there are no scope restrictions. Subresources match the scope of their parent resource. Default is "*". type: string diff --git a/staging/api/crds/operators.coreos.com_installplans.yaml b/staging/api/crds/operators.coreos.com_installplans.yaml index 8e9b85e371..b85b77c562 100644 --- a/staging/api/crds/operators.coreos.com_installplans.yaml +++ b/staging/api/crds/operators.coreos.com_installplans.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.8.0 + controller-gen.kubebuilder.io/version: v0.9.0 creationTimestamp: null name: installplans.operators.coreos.com spec: diff --git a/staging/api/crds/operators.coreos.com_olmconfigs.yaml b/staging/api/crds/operators.coreos.com_olmconfigs.yaml index 44dfcd937e..c6ebe96815 100644 --- a/staging/api/crds/operators.coreos.com_olmconfigs.yaml +++ b/staging/api/crds/operators.coreos.com_olmconfigs.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.8.0 + controller-gen.kubebuilder.io/version: v0.9.0 creationTimestamp: null name: olmconfigs.operators.coreos.com spec: @@ -50,7 +50,7 @@ spec: conditions: type: array items: - description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" type: object required: - lastTransitionTime diff --git a/staging/api/crds/operators.coreos.com_operatorconditions.yaml b/staging/api/crds/operators.coreos.com_operatorconditions.yaml index aa6bd41955..ef4b7bef73 100644 --- a/staging/api/crds/operators.coreos.com_operatorconditions.yaml +++ b/staging/api/crds/operators.coreos.com_operatorconditions.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.8.0 + controller-gen.kubebuilder.io/version: v0.9.0 creationTimestamp: null name: operatorconditions.operators.coreos.com spec: @@ -45,7 +45,7 @@ spec: overrides: type: array items: - description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" type: object required: - message @@ -95,7 +95,7 @@ spec: conditions: type: array items: - description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" type: object required: - lastTransitionTime @@ -162,7 +162,7 @@ spec: conditions: type: array items: - description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" type: object required: - lastTransitionTime @@ -209,7 +209,7 @@ spec: overrides: type: array items: - description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" type: object required: - message @@ -259,7 +259,7 @@ spec: conditions: type: array items: - description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" type: object required: - lastTransitionTime diff --git a/staging/api/crds/operators.coreos.com_operatorgroups.yaml b/staging/api/crds/operators.coreos.com_operatorgroups.yaml index b62f3996a9..f6794075b9 100644 --- a/staging/api/crds/operators.coreos.com_operatorgroups.yaml +++ b/staging/api/crds/operators.coreos.com_operatorgroups.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.8.0 + controller-gen.kubebuilder.io/version: v0.9.0 creationTimestamp: null name: operatorgroups.operators.coreos.com spec: @@ -99,7 +99,7 @@ spec: description: Conditions is an array of the OperatorGroup's conditions. type: array items: - description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" type: object required: - lastTransitionTime diff --git a/staging/api/crds/operators.coreos.com_operators.yaml b/staging/api/crds/operators.coreos.com_operators.yaml index e7dce32925..73b202874f 100644 --- a/staging/api/crds/operators.coreos.com_operators.yaml +++ b/staging/api/crds/operators.coreos.com_operators.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.8.0 + controller-gen.kubebuilder.io/version: v0.9.0 creationTimestamp: null name: operators.operators.coreos.com spec: diff --git a/staging/api/crds/operators.coreos.com_subscriptions.yaml b/staging/api/crds/operators.coreos.com_subscriptions.yaml index 3523401502..31e7ae877a 100644 --- a/staging/api/crds/operators.coreos.com_subscriptions.yaml +++ b/staging/api/crds/operators.coreos.com_subscriptions.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.8.0 + controller-gen.kubebuilder.io/version: v0.9.0 creationTimestamp: null name: subscriptions.operators.coreos.com spec: @@ -643,6 +643,21 @@ spec: description: 'Resources represents compute resources required by this container. Immutable. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' type: object properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers." + type: array + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + type: object + required: + - name + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object @@ -653,7 +668,7 @@ spec: - type: string x-kubernetes-int-or-string: true requests: - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object additionalProperties: pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ @@ -987,7 +1002,7 @@ spec: description: 'medium represents what type of storage medium should back this directory. The default is "" which means to use the node''s default medium. Must be an empty string (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' type: string sizeLimit: - description: 'sizeLimit is the total amount of local storage required for this EmptyDir volume. The size limit is also applicable for memory medium. The maximum usage on memory medium EmptyDir would be the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the limit is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir' + description: 'sizeLimit is the total amount of local storage required for this EmptyDir volume. The size limit is also applicable for memory medium. The maximum usage on memory medium EmptyDir would be the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ anyOf: - type: integer @@ -1016,7 +1031,7 @@ spec: items: type: string dataSource: - description: 'dataSource field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. If the AnyVolumeDataSource feature gate is enabled, this field will always have the same contents as the DataSourceRef field.' + description: 'dataSource field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef, and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. If the namespace is specified, then dataSourceRef will not be copied to dataSource.' type: object required: - kind @@ -1032,7 +1047,7 @@ spec: description: Name is the name of resource being referenced type: string dataSourceRef: - description: 'dataSourceRef specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any local object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the DataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, both fields (DataSource and DataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. There are two important differences between DataSource and DataSourceRef: * While DataSource only allows two specific types of objects, DataSourceRef allows any non-core object, as well as PersistentVolumeClaim objects. * While DataSource ignores disallowed values (dropping them), DataSourceRef preserves all values, and generates an error if a disallowed value is specified. (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled.' + description: 'dataSourceRef specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the dataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, when namespace isn''t specified in dataSourceRef, both fields (dataSource and dataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. When namespace is specified in dataSourceRef, dataSource isn''t set to the same value and must be empty. There are three important differences between dataSource and dataSourceRef: * While dataSource only allows two specific types of objects, dataSourceRef allows any non-core object, as well as PersistentVolumeClaim objects. * While dataSource ignores disallowed values (dropping them), dataSourceRef preserves all values, and generates an error if a disallowed value is specified. * While dataSource only allows local objects, dataSourceRef allows objects in any namespaces. (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled. (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled.' type: object required: - kind @@ -1047,10 +1062,28 @@ spec: name: description: Name is the name of resource being referenced type: string + namespace: + description: Namespace is the namespace of resource being referenced Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled. + type: string resources: description: 'resources represents the minimum resources the volume should have. If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' type: object properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers." + type: array + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + type: object + required: + - name + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object @@ -1061,7 +1094,7 @@ spec: - type: string x-kubernetes-int-or-string: true requests: - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object additionalProperties: pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ diff --git a/staging/api/crds/zz_defs.go b/staging/api/crds/zz_defs.go index ea65d5c73e..6a98bd4bd7 100644 --- a/staging/api/crds/zz_defs.go +++ b/staging/api/crds/zz_defs.go @@ -85,7 +85,7 @@ func (fi bindataFileInfo) Sys() interface{} { return nil } -var _operatorsCoreosCom_catalogsourcesYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb4\x7b\x6b\x73\xdc\xb6\x92\xf6\x77\xff\x8a\x2e\xbd\x6f\x95\xa4\xec\x0c\x65\x25\xa7\xb2\x27\xb3\xb9\x94\x22\xdb\x59\x55\x62\x5b\x65\xd9\xde\xda\x63\x79\xd7\x18\xb2\x87\x83\x08\x04\x68\x00\x94\x34\x39\x75\xfe\xfb\x56\x37\x00\x92\x73\xe1\xcc\x48\x71\xf4\xc5\x16\x88\x6b\x5f\x9f\x7e\x00\x89\x5a\xbe\x47\xeb\xa4\xd1\x13\x10\xb5\xc4\x7b\x8f\x9a\x7e\x73\xd9\xcd\xdf\x5d\x26\xcd\xc9\xed\xe9\x93\x1b\xa9\x8b\x09\x9c\x37\xce\x9b\xea\x0d\x3a\xd3\xd8\x1c\x9f\xe1\x4c\x6a\xe9\xa5\xd1\x4f\x2a\xf4\xa2\x10\x5e\x4c\x9e\x00\x08\xad\x8d\x17\xd4\xec\xe8\x57\x80\xdc\x68\x6f\x8d\x52\x68\xc7\x25\xea\xec\xa6\x99\xe2\xb4\x91\xaa\x40\xcb\x93\xa7\xa5\x6f\x9f\x66\xdf\x65\x4f\x9f\x00\xe4\x16\x79\xf8\x5b\x59\xa1\xf3\xa2\xaa\x27\xa0\x1b\xa5\x9e\x00\x68\x51\xe1\x04\x72\xe1\x85\x32\x65\xd8\x84\xcb\x4c\x8d\x56\x78\x63\x5d\x96\x1b\x8b\x86\xfe\xa9\x9e\xb8\x1a\x73\x5a\xbd\xb4\xa6\xa9\x27\xb0\xb1\x4f\x98\x2f\x6d\x52\x78\x2c\x8d\x95\xe9\x77\x80\x31\x18\x55\xf1\xff\xe3\xe1\xc3\xb2\x57\xbc\x2c\xb7\x2b\xe9\xfc\xaf\xeb\xdf\x7e\x93\xce\xf3\xf7\x5a\x35\x56\xa8\xd5\x0d\xf3\x27\x37\x37\xd6\xbf\xea\x96\xa7\xe5\x72\xe1\x9d\xcd\xc3\x67\xa9\xcb\x46\x09\xbb\x32\xf6\x09\x80\xcb\x4d\x8d\x13\xe0\xa1\xb5\xc8\xb1\x78\x02\x10\x45\x18\xa7\x1a\x83\x28\x0a\x56\x8b\x50\x97\x56\x6a\x8f\xf6\xdc\xa8\xa6\xd2\xed\x52\xd4\xa7\x40\x97\x5b\x59\x7b\x16\xfd\xdb\x39\x42\x6d\xd1\xfb\x05\x8b\x04\xcc\x0c\xfc\x1c\xd3\xda\xed\x28\x80\xdf\x9d\xd1\x97\xc2\xcf\x27\x90\x91\x84\xb3\x42\xba\x5a\x89\x05\xed\xa6\xd7\x2b\xa8\xe9\x59\xf8\xd6\x6b\xf7\x0b\xda\xba\xf3\x56\xea\x72\xdb\x56\xa8\xdf\xfe\x7b\x08\xa2\x79\xbb\xa8\xd7\xb7\xb0\xd2\xb8\xef\xfa\x75\x33\x55\xd2\xcd\xd1\xee\xbf\x89\x76\xc8\xda\x1e\x2e\x37\x7c\x19\xd8\x48\x6f\xd2\xe4\x50\xd9\x9a\x33\xac\x2d\x70\x56\xae\x9f\xb1\x10\x3e\x35\x86\x4e\xb7\xa7\x42\xd5\x73\x71\x1a\x1b\x5d\x3e\xc7\x4a\x74\xf6\x60\x6a\xd4\x67\x97\x17\xef\xbf\xb9\x5a\xf9\x00\xcb\xd2\x59\xb2\x73\x90\x0e\x04\x58\xac\x8d\x93\xde\xd8\x05\x49\xeb\xfc\xea\xbd\x1b\xc1\xf9\x9b\x67\x6e\x04\x42\x17\xad\xe3\x41\x2d\xf2\x1b\x51\xa2\xcb\xd6\xf6\x6a\xa6\xbf\x63\xee\x7b\xcd\x16\x3f\x37\xd2\x62\xd1\xdf\x05\x89\x27\xc9\x64\xa5\x99\xe4\xdf\x6b\xaa\x2d\xad\xe9\x7b\x8e\x1c\x7e\x7a\x51\x6e\xa9\x7d\xe5\x84\x87\x24\x86\xd0\x0f\x0a\x0a\x70\xe8\xd8\x04\xa2\x8f\x61\x11\x65\x17\x4c\x43\x3a\x3a\xbf\x45\x87\x3a\x84\x3c\x6a\x16\x3a\x9e\x29\x83\x2b\xb4\x34\x90\xdc\xbd\x51\x05\x45\xc2\x5b\xb4\x1e\x2c\xe6\xa6\xd4\xf2\x8f\x76\x36\x07\xde\xf0\x32\x4a\x78\x74\x1e\xd8\x6b\xb5\x50\x70\x2b\x54\x83\x41\x94\x95\x58\x80\x45\x9a\x17\x1a\xdd\x9b\x81\xbb\xb8\x0c\x5e\x1a\x8b\x20\xf5\xcc\x4c\x60\xee\x7d\xed\x26\x27\x27\xa5\xf4\x29\x86\xe7\xa6\xaa\x1a\x2d\xfd\xe2\x84\xc3\xb1\x9c\x36\x14\x0e\x4f\x0a\xbc\x45\x75\xe2\x64\x39\x16\x36\x9f\x4b\x8f\xb9\x6f\x2c\x9e\x88\x5a\x8e\x79\xb3\x9a\xe3\x78\x56\x15\xff\xcf\xc6\xa8\xef\x0e\x57\xc4\xb7\xd1\x98\x21\x85\xcd\xad\xb2\xa6\xe0\x19\xac\x28\x0c\x0f\x67\xe9\x44\x4a\x4d\x24\x95\x37\xcf\xaf\xde\x42\xda\x40\x10\x7b\x90\x70\xd7\xd5\x75\xc2\x26\x41\x49\x3d\x43\x1b\x7a\xce\xac\xa9\x78\x16\xd4\x45\x6d\xa4\xf6\xc1\xa5\x95\x44\xed\xc1\x35\xd3\x4a\x7a\xc7\x36\x87\xce\x93\x1e\x32\x38\xe7\x14\x06\x53\x84\xa6\x26\x4f\x2a\x32\xb8\xd0\x70\x2e\x2a\x54\xe7\xc2\xe1\x5f\x2e\x6a\x92\xa8\x1b\x93\xf8\xf6\x17\x76\x3f\x03\xaf\x0f\x58\xf3\x31\x80\x94\x21\xf7\xea\x3c\xe4\x94\x10\x3c\x70\x53\x04\x86\x2d\xbe\x48\x3f\xa2\x28\x2c\xba\x0d\x1f\xd6\x1c\x32\x74\x0c\x76\x32\x37\x8e\xf4\x27\x3c\xbc\xfe\xed\x25\xe4\x42\x43\xe3\x90\x9c\x27\x37\x5a\x93\x41\x78\x03\x82\x72\xd9\x18\xef\xa5\x63\x03\xb2\x58\x4a\xe7\xed\x22\x83\x17\xc6\x56\xc2\x4f\xe0\xfb\xd4\x34\xe6\xe9\x8c\x05\x59\xff\x38\xf9\xbe\x36\xd6\xff\x08\xaf\xb5\x5a\xd0\xa4\x05\xdc\xcd\x51\xc3\x55\x7b\x36\xf8\xa1\xf7\xcb\x2f\xb6\xce\x33\xb8\x28\xb5\xb1\xa9\x27\x59\xd5\x45\x25\x4a\x84\x99\x44\xc5\x76\xed\xd0\x67\xab\x1a\xdc\xaa\x45\x08\x70\x69\x26\xcb\x97\xa2\xde\x29\x9a\xf3\xd4\x93\xd6\xa2\xe5\xfb\xc9\xbb\xfb\xe8\x0d\x9b\x32\x1d\x89\xfe\x2b\xf2\x1b\x10\x71\x95\x4a\xd4\x63\xc7\x6e\xd3\x13\xd3\x7e\x12\x38\x4f\x13\x90\xfc\xba\xe6\x8b\x18\xb9\xb2\x87\x1e\xbb\x7f\xb2\x07\x8f\xed\x60\xc8\x4e\xa1\xbd\xdc\x94\x45\xf6\x58\xa3\xb4\x75\x7e\x69\x8a\x70\xec\x9d\xab\xfc\xd2\xef\x0d\x78\x5f\x1b\x87\x0e\x0a\x39\x9b\xa1\xa5\xb8\x63\x6e\xd1\x5a\x59\xa0\x83\x99\xb1\xac\xaf\xda\x14\xec\x93\xad\xfe\x96\x52\xed\xa5\x29\xf6\x55\x0c\x2d\xcd\x09\x23\x18\x63\x34\xc3\xc1\xe3\x6e\xf4\x76\xd8\xe1\xbc\xf4\xa3\x4d\x81\x57\xa8\x30\xf7\xc6\x6e\xee\xb1\x22\x93\x57\xbd\x01\x31\xea\xa7\xdf\xee\xe6\x32\x9f\x43\xd5\x38\x8e\xba\xde\x36\xb8\x24\x17\x6f\x60\x26\x3d\x18\x0d\x82\x97\xa5\x58\xbf\x3e\xb2\x12\x3e\x9f\xc7\x1e\x87\x0e\x94\x98\xa2\x72\xab\xf3\x4c\x91\x53\x6e\xd1\x28\x2c\x68\x42\x8e\x25\x3c\xe7\xc0\x11\x76\x48\x09\x42\x28\x6b\xf1\xf6\x76\x99\xc1\x2e\x2b\x0b\x82\x97\xc6\x4a\xbf\x38\x57\xc2\xb9\x21\x9b\x5e\x93\xee\xc5\x8c\xcd\x47\xce\x24\x16\x23\x90\xba\x90\x54\xd2\xb8\x74\xf6\x43\xd7\xce\x9b\x51\x5f\x4a\x70\xbd\xfe\x49\x42\xa9\x0f\xdc\x49\xa5\x48\x58\x05\xce\x44\xa3\x38\x48\xfe\x81\xd6\x80\x64\xeb\xb4\x6c\x57\xda\xa4\xcf\xdb\x85\xb7\xe5\xac\x0e\xf3\x86\xcf\x6a\xb4\xc7\x7b\x3f\xec\x5d\x6b\xe7\x3d\xb8\xda\x34\x94\x53\xc2\x14\xc1\x68\x0e\x84\x9f\x14\x96\x22\x5f\x7c\xa2\xed\x7f\xb2\x48\x1b\xc9\x3d\x16\x9f\x32\xc6\xf9\x4b\x2e\x46\x02\x32\x1c\xb5\x51\xd2\x09\x41\x6a\x52\x39\x39\x9b\xf4\x73\x16\x90\x95\xe5\xdc\x53\xaf\x58\x78\x2c\x6f\x80\x7d\xae\xfd\x48\xa9\x5f\x48\x8d\xf6\xc3\x57\x1f\xd7\x7a\x06\xc8\xc6\xb9\x4a\x29\x73\xd7\xb7\x4f\xdb\x68\x90\x9a\xfc\x1d\xd2\x01\xe1\xac\xa8\xa4\x63\x44\x7a\x74\x79\x75\x76\xbc\x74\x12\xa8\x4c\x81\x23\x3a\x5f\x61\xd0\xe9\x43\x4f\xde\x4e\x13\x3a\x4c\xcb\x08\x4f\xcb\x90\x4d\x44\x6f\xc9\x05\xe5\xcc\xb8\x26\x09\xcc\x50\x60\x99\x62\xbb\xf8\xd5\x19\x7c\x9a\x0a\x87\x4a\x6a\x0c\xb2\xab\xad\xbc\x95\x0a\x4b\x5a\x51\xa7\xda\xd3\x65\x70\xde\x58\x8a\x67\x6a\x11\x0d\x03\x36\x6b\x45\x3a\x68\xf4\x8a\xb9\x25\xcb\x0a\x98\xaf\xaf\x2c\xea\xed\x08\x75\x5d\xf1\x88\x05\x65\x71\x91\xfa\xb1\x6e\xfc\x5c\xe8\x41\xe5\x12\x52\xa4\x89\xa5\x0e\xa3\x64\x11\xa0\x39\x5a\x6b\x6c\x06\xff\x45\xb1\xb3\xa1\x0a\x1b\x8c\x2a\xd0\xa6\xea\x0e\x24\xc5\x4b\x37\x4a\x42\x62\xc4\x1e\x71\x60\x14\xcc\x06\xc1\x0f\x9f\x39\x62\x7e\x0a\x38\xc8\xb8\x24\xed\x37\x83\x6b\x4d\x80\x52\xc0\xac\x21\x08\x98\x6a\x8b\xe0\x73\x7d\xd1\x24\x27\x4c\x13\xf4\x96\x1f\xb5\xdb\xae\x84\x8c\xa6\xd6\xd6\x19\x36\x10\x2c\x34\x97\x6c\xcf\xe7\x82\x21\x8b\x76\x39\x33\x03\x53\x57\x21\x02\xba\xa6\x26\xf8\xe3\xe8\xa4\x9a\x44\x93\x2f\xa5\x9f\xda\x14\x6e\xa3\x00\x68\x5b\xb5\xc5\x5a\xd8\x36\x62\x3b\x84\x7c\x2e\x34\xd5\x7a\x74\xd0\x16\x2b\x13\xf6\xa2\x65\xc5\xd4\x34\x9e\x6d\x2c\xfa\xea\xcc\x34\xba\x00\x0a\x2a\x1d\x9c\xbe\x69\xa6\x68\x35\x7a\x64\x44\x5d\x98\xdc\x11\x98\xce\xb1\xf6\xee\x24\x79\xd3\x49\x6d\x8a\x71\xfa\x65\x2c\x92\x93\x9c\x1c\x1e\x3c\x36\x1a\x41\x92\xfc\x04\x82\xae\x06\x7a\xa1\x6e\xaa\xe1\x00\x3f\xde\x3e\x98\x3a\x74\x62\xdc\xd8\xc9\x1b\x45\x65\x73\xc7\xe9\x6c\xda\x68\x9f\xb4\xe8\xfa\x03\x69\xa2\xc7\x59\x44\x70\x1e\xa2\xdb\xa1\xeb\x4f\xbd\x3d\x68\x0b\x6b\xc5\xd0\x11\xa4\xc7\x6a\x4b\x86\x5b\x27\x54\x28\xb6\x51\x2d\xd6\x6d\x94\x01\x80\xf7\x82\x72\x31\x17\xbf\xe1\x0b\x85\x2b\xbd\x00\xb2\xe7\x88\xf3\x39\xab\xc7\x3c\xe6\xad\xac\x15\xc2\xf7\x37\xb8\x18\x85\xca\x18\x67\x33\xcc\xfd\x8f\xd1\x9f\xa9\x0f\xf7\x67\xe7\x4e\xd4\xc3\xf7\xe9\x7f\x3f\x0e\x9d\x78\xaf\x2c\xbf\x1b\x11\x85\x9f\xb0\xa5\x6d\x3d\x56\x24\xf4\x9c\x07\xac\xa4\xec\x20\x81\x30\x17\xc9\x87\x8f\x95\xc1\xf3\xaa\xf6\x0b\xa8\x50\x68\x97\xf0\x0e\xc5\x8c\x5e\x67\x17\x23\x5c\x2f\xda\x72\x92\x69\x99\x02\xb6\x90\x57\xe6\x2a\xa2\xa0\x11\x5c\x5a\x9c\xa1\xed\x5a\x38\x91\xbd\x32\xcf\xef\x31\x6f\xfc\x20\x2e\xea\xcb\x6d\xab\x4b\xd1\xcf\x0d\x2e\x1e\x20\x90\x5f\x71\x91\x2a\x9a\x70\xb2\x1b\x5c\x04\x63\xe0\xa6\xce\x86\x44\x5d\x2b\x89\xa1\x68\xdf\x26\x99\x1b\x5c\x38\x46\x3d\x34\xfe\x26\xcc\x8e\xd4\x7f\xd4\x59\x49\x02\x9f\xcf\xa9\x6e\x74\xff\x11\xec\x35\x37\xd5\x54\xea\xb0\x58\x98\x3a\xa9\x82\x67\x4f\x02\xd5\x05\xff\xca\xcb\x7c\x09\x71\xa5\x4d\x3d\x40\x66\xaf\xd3\x39\x3a\x46\x04\x04\xed\xe8\xd0\x81\x45\x15\x3c\x7e\x2e\xeb\x44\x34\xf1\xd6\x33\x78\x4f\xe9\xb1\xa3\xc7\xd9\x36\x82\x04\xf8\x54\xcf\x3f\x37\x42\x65\xf0\x2c\x44\x45\x3e\x7d\x6c\x8a\x9d\x48\x90\x9f\x1b\x79\x2b\x14\x55\x35\xde\x50\xca\x2a\x72\x61\x0b\xce\x06\x91\xbd\x72\x26\x68\x4f\xb4\x80\x23\x79\x7b\xa7\x23\xc7\xcc\x19\xd4\xc2\x7a\x99\x37\x4a\xd8\xc4\xc8\x2f\xbe\x88\x44\x3b\xa3\xb9\xc2\xdc\xe8\x62\xab\x07\x0f\x46\xd7\x38\xb6\x2f\x63\x86\x51\x68\xa5\x29\xb8\x70\x93\x15\xae\x1a\xe9\xd1\x72\x71\x63\x66\xc9\xab\x5b\x17\x1b\x05\x54\x73\x27\x5d\x24\xb7\x5a\x02\x41\x06\x82\xe1\xb8\x17\x1e\x5b\xaf\xc8\xe0\xe7\x45\xca\x57\x23\x90\x3e\x20\x72\xc6\x7f\x09\xc3\x24\x93\x8d\xc2\xee\x1c\x6a\x66\x2c\x52\xd1\x7f\x54\x18\x1e\x83\xb7\x32\xf7\xc7\x19\xfc\x83\x20\x3e\x29\x5e\x63\x29\xbc\xbc\x6d\x31\x64\x42\x22\xde\xa2\x20\x4c\x2c\x1c\x3c\x85\x23\x1e\x06\xb2\xaa\xb0\x90\xc2\xa3\x5a\x1c\xc3\x74\xc1\xcb\xb8\x85\xf3\x58\xed\xa3\x3a\xa9\x3d\x96\x4b\xec\xf8\xfa\xcf\x2c\x12\x37\x52\xfb\x6f\xff\xb6\xa5\x27\x6f\xf6\x01\x9a\x7d\xcf\x90\x72\x29\xd4\x04\x94\xb9\xa2\xc2\x36\x07\x99\x36\x8a\xb4\x71\x43\xba\xe8\x0b\xa3\xce\xaf\x7a\xd8\x2f\x85\x99\x56\xc1\xbf\x93\x1d\x08\xb0\xc8\x17\x3c\xd1\x72\xff\x84\x8d\xcb\x7c\x1b\x61\x32\x98\xd1\x86\xf9\x3c\x60\x84\x42\xf0\xff\xdb\xbf\x0d\x10\x25\x81\x8d\x27\x9d\xaf\x73\x7e\xb0\x47\xa2\xec\x26\x1f\x52\xd6\x4e\xb7\x6e\x97\x7f\xd4\x0c\x0c\xf5\x77\x92\x38\x2d\x81\x42\x25\x52\xd4\xf7\x38\xf1\x64\xd0\x56\x78\x61\x36\x0a\x7e\x52\x3b\x2f\xb4\x97\x1c\xd9\x5a\x46\x2d\x31\x6c\x04\xbf\x1f\x42\xe2\xb0\xad\xc5\x40\x13\x8c\x2b\x72\xa6\x6b\xf1\xe1\xc1\x64\x5b\x2a\xf3\x77\xb3\xaf\x97\x89\x10\x08\x6b\x0a\xe7\x64\x49\x28\x13\xee\x90\xab\xe1\x98\x4e\x96\xd1\x66\xa8\x0a\x78\xa0\xfc\x83\xbd\xa9\x6a\x93\x80\xf4\x09\xf7\xe7\x46\xbb\xa6\xc2\x22\xc5\x8c\x02\x6b\xd4\x05\xea\x7c\xc1\x5c\xbf\xba\x45\x9b\xc1\x3b\x47\x9a\x82\xff\x94\x25\xd5\x7d\x71\xd1\x3e\x54\x62\x54\x40\xa9\x7a\x79\x07\xd2\x91\xe8\x66\x68\x2d\x16\xcc\xb6\x01\x61\xa0\x34\x03\x16\x2b\xfd\x1d\x14\x0d\xdf\x40\xac\x6e\xa2\x21\x39\x04\xba\xc0\x52\x51\x93\xe8\xb9\x96\x28\x09\x0e\x4f\x47\x2a\x4d\xb8\x6b\xe0\xfb\x30\x8a\x9d\xde\x74\x71\x54\x06\x82\xb8\x9d\x43\x6a\xff\xcd\xd7\x61\xde\xe5\x42\x98\x09\xec\x95\xc3\x70\xe1\xd6\xe8\x20\x7c\xec\xb3\x34\x29\xcc\x3c\x0d\x53\x6d\x1a\xc7\xe1\x58\x54\xab\x5b\xee\x62\xba\x15\xfa\x06\x0b\x50\x78\x2f\x73\x53\x5a\x51\xcf\x65\x2e\x94\x5a\xb0\x9b\x32\x49\x26\xbd\xe3\xaa\x7f\x0b\x99\x3d\x14\xc6\xdb\x8b\xd1\x07\x93\xba\x0e\x73\x8b\x7e\xf7\x05\xc1\x55\xe8\xd7\x25\x65\x2e\x97\xcd\x2c\x4d\x10\x6c\x24\xda\x5c\x62\xc1\x45\x9e\x93\x23\xb1\xe9\x52\xd5\x1e\x01\x48\xcf\x94\x33\xb8\xe0\x94\x3a\x45\xc7\x56\x7e\x83\x58\x07\x4b\x53\xd2\x79\x70\x15\x73\x2a\x4e\xea\x1c\x01\x45\x3e\x0f\xe2\xd4\x88\x89\x66\xf4\x56\x62\x80\x41\x94\x6a\x17\xad\x6e\x50\xfb\xcd\xa0\x66\x7b\xdd\xb5\xa5\xe6\xda\x2e\xc6\x36\xa6\xec\x96\x64\x17\x8b\x52\x4e\x8c\x37\xf1\xae\x7b\xf4\xf0\x80\xa5\xc3\xed\xd9\x95\x27\xf0\x51\xee\x8e\x35\xef\x96\xba\xb7\xb7\xaf\x73\x73\x97\xee\xe1\xd6\x9c\x9c\x19\x9b\xa4\xdb\x42\xba\x9c\x3c\x1d\x0b\x38\x37\xda\x31\x3e\x0d\xd7\xb1\x7c\x9d\x7a\x2b\x54\x30\x85\x34\x71\x6d\x94\x62\x97\x6f\x52\x39\x41\x38\x5e\x03\x56\x53\x2c\x0a\x2c\xe8\x58\x61\x2b\x03\x69\xee\x4f\x12\xe8\x29\x3f\x5c\x1a\xa5\xb6\x67\xb1\xad\x75\xe9\x3e\x55\x69\x12\xc0\x36\x6c\xb4\x9c\xfa\x92\xc4\x22\x17\x47\x36\x5d\xa0\x47\x5b\x49\x1d\xe1\x11\x41\xdd\x56\xb0\x53\xf4\x77\x88\x1a\xf2\x39\xe6\x37\xad\x2b\xc5\xdb\xec\x15\xad\x45\xfe\x69\x39\x62\x75\x0f\x05\x8c\x52\x5c\x68\x38\x44\x90\x54\x13\x68\xbc\xeb\x73\x56\x1b\xd2\x0d\xa5\xe8\x5b\x21\x95\x98\x2a\xe4\xac\xd9\xfe\x36\x5a\xba\x55\x4f\xf9\xbc\x6e\x94\x22\x10\xab\x0b\x28\xdf\x5c\x9e\x83\xb7\x62\x36\x93\x39\x7d\x2a\xa4\x0d\xac\xef\xf2\x85\xfc\xf2\x82\xdb\xe0\xda\xa0\x47\x38\x2f\x7c\xb3\xa6\xa3\x2d\x0a\xde\xa6\x58\xaa\x43\xe4\x20\x41\xb4\xa4\xca\x37\xcb\xc5\x0a\x6d\x03\x43\xb1\xb5\xc4\x7f\x67\xf0\xca\x70\x8d\x20\x3c\xbc\x44\x47\x69\x97\x05\xf4\x06\x85\x33\xba\x17\x5d\x19\xfd\x5a\x59\x4a\x2d\x54\x3c\x54\x9f\xdf\x6b\x6b\x0f\xc1\x94\x72\x25\x4b\x2b\x7c\x1b\x14\xbb\x7d\xc7\xec\x12\xf3\x62\x60\x42\x33\x38\xd3\x0b\xd6\xf7\x0c\x05\x35\xd0\xcc\xde\x9a\xa2\xc9\x99\x87\x57\x8a\xaf\x7b\xbb\x49\xbe\x68\x18\x5d\xbe\x5e\x38\x4f\x8b\x24\xa0\xe7\xc8\x01\x84\x8c\x57\x4a\x46\x23\x08\x57\x53\x1d\x97\x6c\x32\x50\xe1\x9d\x80\x39\x59\x9c\x5d\x5e\x40\x7a\x30\x97\xc1\x78\x3c\x86\xb7\xd4\xec\xbc\x6d\x72\xce\x2f\xe4\x42\xba\x88\x99\x22\x58\x1f\x1f\x52\x30\xec\xe4\x63\x40\x64\x3e\x02\x04\xab\x85\x9f\x43\x16\x04\x9f\xf5\x44\x01\xf0\x82\x72\xcd\xbd\xa8\x6a\xb2\xfb\x6b\x1d\xa2\xf7\x0b\x63\xae\x82\x92\xc2\x9a\xff\x84\x93\x93\x55\x9b\x30\x53\x82\xa8\x91\x40\x64\xd3\x98\x19\x73\xe8\x96\x8f\x94\xd1\xc0\x5f\xb5\xb9\xd3\x9b\x56\xe7\xb5\x84\xc5\x09\x5c\x1f\x9c\x25\xef\xbb\x3e\x18\xc1\xf5\xc1\xa5\x35\x25\xc1\x56\xa9\x4b\x6a\x20\xa3\xba\x3e\x78\x86\xa5\x15\x05\x16\xd7\x07\x34\xed\xbf\xd5\x54\x61\xbd\x44\x5b\xe2\xaf\xb8\xf8\x81\x27\x6b\x9b\x53\x46\xf8\xa1\xa2\xef\xdc\x4e\x29\x98\xf2\xd4\x0f\x95\xa8\xdb\x86\x97\xa2\x6e\x07\x9f\x77\x76\xf6\xe1\x63\x85\x5e\xdc\x9e\x66\x9d\x46\x3f\xfd\xee\x8c\x9e\x5c\x1f\x74\xfb\x1f\x99\x8a\x2c\xa3\xf6\x8b\xeb\x03\x58\x5a\x75\x72\x7d\xc0\xeb\xa6\xf6\xb4\xc9\xc9\xf5\x01\xad\x44\xcd\xd6\x78\x33\x6d\x66\x93\xeb\x83\xe9\xc2\xa3\x1b\x9d\x8e\x2c\xd6\x23\x02\x4c\x3f\x74\x2b\x5c\x1f\x7c\x22\x9d\x9c\x9c\xc4\x2b\x0c\x56\xa6\x83\x7f\x6d\x26\xab\x77\xc6\xfd\xed\xf5\x1b\x93\xd0\xc2\xf9\xb7\x56\x68\x27\xd3\xfb\xb1\xc1\xae\x55\xf0\xf7\xc1\xef\x96\x63\xc0\xe0\xe7\x60\x0d\x83\x9f\x07\xb2\xe7\x3e\x99\x6b\xfd\x0c\x7b\xb2\xce\xeb\x03\x13\xa4\xa1\x2f\x1d\x4f\xd3\xea\x87\x72\x40\xec\x4d\xbe\x48\x38\x9e\x5c\x3c\xc6\x37\x42\x8c\x9a\xf5\x96\x45\xff\x6d\x0b\xfc\xf6\xed\x47\xa3\x0b\xb4\x8a\x2f\xab\xba\x59\xc3\x4d\x48\x91\x41\xe0\x0d\x44\xcb\xd2\xdc\x90\x23\x71\x76\xd2\x3d\xf2\x9a\xf7\xd5\xce\x48\xb1\x23\xf8\x7c\x9c\x86\x13\x5d\x9e\x63\xed\x39\xd3\x3d\xfe\x8a\x19\x7a\xa4\x0a\x21\xab\xb1\x1f\x36\x8f\x68\x1c\x7b\x0a\x3e\xf6\x8e\xaf\x75\x9a\x4a\x50\xea\x10\x05\xed\xb7\xfb\x16\xca\xb7\x50\x6e\x85\x90\x1a\x2e\x85\x02\xc7\x9f\xf4\x10\x45\x1d\x13\x09\x03\xb3\xda\x2f\x76\x32\x26\x7b\x1d\xbe\x12\xf7\xbf\xa1\x2e\xfd\x7c\x02\xdf\x7c\xfd\xef\xdf\xfe\x7d\xa0\x63\x08\x8c\x58\xfc\x82\x3a\x72\x41\x7b\x8a\x61\x7d\xe0\x2a\x69\xd8\x3d\xf1\x2c\xbb\x3e\x2d\xc9\xdd\x59\xd0\x9d\xe0\x07\x1c\x31\x5d\x36\x35\xc9\x85\x02\x7d\xe0\x1a\x72\x1c\x11\x48\xda\x38\x99\x6c\x03\xb8\x5a\xc0\xe9\xd7\x23\x98\x46\x11\xaf\x87\xef\x0f\xf7\x1f\xb3\x0d\x5b\x96\x0e\xbe\x1b\xad\xec\x47\x3a\x20\x55\x99\x19\x1b\x4e\x28\x31\x2d\x86\x4c\x98\xc8\x80\xf5\x4c\x88\xed\x7e\x77\x29\x6e\x17\x1f\xb8\x1f\x17\x58\x49\x2d\xab\xa6\x9a\xc0\xd3\x81\x2e\x21\xa4\xed\xa9\xcd\xd0\xb9\x03\x02\x82\x42\x57\x69\x45\x45\x90\x27\x07\x59\xa0\xf6\x72\x26\xf9\xd1\x40\x6b\xda\x5c\xee\x87\x81\xe9\x0d\x4a\x2b\x45\x7e\x9e\x42\x71\xa8\x67\xec\x97\x01\xe7\x58\xce\xc0\xf1\xf6\x26\xef\x07\xa8\x45\x8d\xc1\x1b\x42\x01\x03\x78\x5f\x07\xa8\xda\xbb\x86\xa8\x50\x68\xa9\xcb\xf4\xec\x25\x71\xc9\x21\xeb\xde\xcd\x31\xde\x9e\x63\xff\x2e\x28\xa7\x62\xa9\xe0\xba\x49\x40\xd9\x08\x2b\xb4\xa7\x32\xf6\xec\xf2\x22\x60\xf4\x55\x4e\x53\x74\x6f\x21\x93\x37\x06\x57\x0d\xc1\x8a\xb6\x18\xef\xcd\xd9\x63\xbf\x9c\xab\x9e\x3e\xfd\x7a\xab\xca\xdb\x7e\xc3\x57\x78\xc2\x7b\xb4\x7a\x02\xff\xf3\xe1\x6c\xfc\x0f\x31\xfe\xe3\xe3\x51\xfc\xcf\xd3\xf1\x77\xff\x3b\x9a\x7c\xfc\xaa\xf7\xeb\xc7\xe3\x9f\xfe\xff\xc0\x4c\x9b\xc1\xfc\x80\xf9\xc4\x24\x92\x70\x62\xd2\xe8\x28\xbd\x52\x79\x6b\x1b\x1c\xc1\x0b\xa1\x1c\x8e\xe0\x9d\xe6\xd4\xf0\x27\x85\xb6\xfd\x86\x9a\xb2\xf2\x01\xad\x3a\x74\x53\x1e\xbb\xf0\x96\xb6\xf7\x89\xdb\xdd\x56\xbe\xee\x27\xa4\x44\x35\xf4\x22\x4d\xef\xcd\x2d\x3f\xd2\x24\x47\x32\x59\x44\xb8\x59\x6e\xaa\x93\xde\x9b\x5c\x82\xd6\x2f\x85\x5e\x40\x17\xd6\x02\x28\x5d\xb5\x74\xe7\x29\x36\x89\xdc\x1a\xe7\xda\x47\xc5\x0e\x94\xbc\x41\x38\xeb\xea\x46\x0a\x96\x53\xcc\x05\x63\x71\x3b\x95\xde\x8a\x40\xfa\x26\x5c\xd9\x31\x4a\xb3\x46\xc1\x11\x95\xab\x19\x3f\x24\x5b\x8b\xae\xc7\x91\xbd\x9d\x4a\x25\xfd\x22\x94\xd2\xb9\xd1\x33\x25\x63\x09\x50\xd5\xc6\x7a\xa1\x7d\xe4\x19\xb1\xc4\x7b\x90\xdd\xd5\xb7\x74\x70\x54\x68\x77\x7a\xfa\xf5\x37\x57\xcd\xb4\x30\x95\x90\xfa\x45\xe5\x4f\x8e\x7f\x3a\xfa\xdc\x08\xc5\xb7\xbc\xaf\x44\x85\x2f\x2a\x7f\xfc\xe5\xd2\xe2\xe9\xb7\x7b\x78\xd1\xd1\x87\xe0\x2b\x1f\x8f\x3e\x8c\xe3\xff\xbe\x4a\x4d\xc7\x3f\x1d\x5d\x67\x5b\xbf\x1f\x7f\x45\x67\xe8\x79\xe0\xc7\x0f\xe3\xce\xfd\xb2\x8f\x5f\x1d\xff\xd4\xfb\x76\xbc\xc9\x19\xef\xc7\xdd\x53\x91\x31\x55\x01\xe3\x4a\xd4\xe3\x1b\x5c\x0c\x38\xe7\x20\x1c\x5d\x9f\x28\x48\xac\x12\xf5\xa6\xea\x3b\xbc\xad\x7d\x83\xfc\x9e\x33\xdf\x68\xe4\x7f\xf2\x06\x46\x8b\x01\x48\x36\xee\x5e\x60\x3d\x82\x75\xa2\xbc\x13\x98\xb6\x6d\x70\x7a\x0f\x6b\xd9\x0f\x3f\xea\x2d\xef\x17\x77\x2e\xd2\x9e\xf3\xd1\x33\x24\xff\x1e\xf8\xd3\x8f\xbd\xe7\x69\xe4\x60\xa5\xb5\xcc\x61\x5e\x3c\x0b\xd0\x97\x43\x0f\xc3\xb9\xb9\xa1\x3a\xaf\xd1\xf2\x73\x83\x70\xf1\x2c\xc6\xa3\x11\x48\x9d\xab\xa6\x20\xa4\xf0\xee\xdd\xc5\x33\xaa\xdf\x7f\x8e\xe1\xe6\x0e\xa1\x30\xfa\xd0\xc3\xeb\x57\xbf\xfd\x37\x93\x01\xdc\x63\x14\x12\x7a\xb8\x8f\x12\x4a\x86\xbf\x1a\x49\x09\x18\x7e\xc6\xf0\x4e\x8e\x57\xce\x45\xdd\xf2\x27\x1c\xee\xf8\x85\x95\xaa\x09\x40\xdc\x20\xb8\xc6\xc6\xdd\xd1\xc4\xe1\xc6\x97\x64\x0d\xf1\x3e\xb8\x44\xcf\x46\xae\xf8\xaf\x1f\x1e\x23\xb4\xf8\x1e\x5f\x1a\x7d\x45\x28\xf0\x2f\xf0\x0f\x32\xe4\xd7\x11\xb3\xf2\x1a\x8f\x70\x86\x2d\x7f\x84\xb0\xf3\x84\x10\x9d\xe9\x3c\x9c\xf4\x2f\xf7\xa4\xb5\xf3\x3e\x6a\xc5\xc0\x67\xf2\xcd\xe6\x9b\x1d\xfc\xf3\xda\x33\xae\xe5\xd2\x79\xe5\x6f\xc1\x98\x5b\x6d\x2f\x47\xe7\xc2\xc1\x14\x51\x33\x9d\x1b\xd8\x3f\xd4\xd1\xea\xb0\x23\x62\x9b\x7a\xec\xcd\xb8\xd8\xac\xbc\x1d\x92\xdb\x2d\xb5\x2d\x95\xeb\xd2\xd9\xce\x1e\x5c\xa8\xde\xcd\x17\x9b\x64\xe0\x02\x9d\xc9\x0f\x87\x12\x06\x79\xe8\xc1\x86\x0b\x93\x15\x56\x97\x2b\x8b\x48\x6a\xc4\x3a\x63\x7d\x4b\x54\x3d\x2e\x31\x1b\xde\xf0\x6d\xde\x32\xb3\xf7\xf0\x3d\x06\x35\x5f\xa1\xbd\x95\x8f\x4a\x7e\xbb\x1c\x33\x0f\xef\x4c\xce\xfe\x7a\xb7\x22\xe8\xf5\xe8\x45\x98\xfa\xcb\xcd\x8e\xeb\x9b\xad\xef\xdf\x59\x82\xdb\x5e\xf9\x3f\x64\x8e\x87\x26\xcb\x10\x4d\x26\xfc\x17\x17\xa9\xc9\x1b\xcb\x57\xee\xfd\xb6\x66\xda\x02\xe5\x6e\xf6\x58\x03\xc1\x3f\xff\xf5\xe4\xff\x02\x00\x00\xff\xff\x4a\xcc\x94\x67\x43\x3e\x00\x00") +var _operatorsCoreosCom_catalogsourcesYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\xfb\x73\xdc\x36\x92\xff\xef\xfe\x2b\xba\xf4\xfd\x56\x49\xca\xcd\x50\x76\xb2\x95\xdb\xd5\xe6\x51\x5a\x39\xce\xa9\x12\xdb\x2a\xcb\xc9\xd6\xad\xe5\x3b\x63\xc8\x1e\x0e\x22\x12\x60\x00\x50\xf2\x24\x95\xff\xfd\xaa\x1b\x00\xc9\x79\x3f\x64\xc7\x76\x2d\xf9\x8b\x35\x24\x9e\x8d\x46\xf7\xa7\x1f\x80\x45\x25\x7f\x46\x63\xa5\x56\xa7\x20\x2a\x89\x6f\x1d\x2a\xfa\x65\x93\x9b\xbf\xda\x44\xea\x93\xdb\x47\x0f\x6e\xa4\xca\x4e\xe1\xbc\xb6\x4e\x97\x2f\xd0\xea\xda\xa4\xf8\x18\xc7\x52\x49\x27\xb5\x7a\x50\xa2\x13\x99\x70\xe2\xf4\x01\x80\x50\x4a\x3b\x41\xaf\x2d\xfd\x04\x48\xb5\x72\x46\x17\x05\x9a\x61\x8e\x2a\xb9\xa9\x47\x38\xaa\x65\x91\xa1\xe1\xc6\x63\xd7\xb7\x0f\x93\xbf\x25\x0f\x1f\x00\xa4\x06\xb9\xfa\x4b\x59\xa2\x75\xa2\xac\x4e\x41\xd5\x45\xf1\x00\x40\x89\x12\x4f\x21\x15\x4e\x14\x3a\xf7\x83\xb0\x89\xae\xd0\x08\xa7\x8d\x4d\x52\x6d\x50\xd3\x3f\xe5\x03\x5b\x61\x4a\xbd\xe7\x46\xd7\xd5\x29\x2c\x2d\xe3\xdb\x8b\x83\x14\x0e\x73\x6d\x64\xfc\x0d\x30\x04\x5d\x94\xfc\x77\x98\xbc\xef\xf6\x8a\xbb\xe5\xf7\x85\xb4\xee\x87\xc5\x6f\x3f\x4a\xeb\xf8\x7b\x55\xd4\x46\x14\xf3\x03\xe6\x4f\x76\xa2\x8d\x7b\xd6\x76\x4f\xdd\xa5\xc2\x59\x93\xfa\xcf\x52\xe5\x75\x21\xcc\x5c\xdd\x07\x00\x36\xd5\x15\x9e\x02\x57\xad\x44\x8a\xd9\x03\x80\x40\xc2\xd0\xd4\x10\x44\x96\xf1\xb2\x88\xe2\xd2\x48\xe5\xd0\x9c\xeb\xa2\x2e\x55\xd3\x15\x95\xc9\xd0\xa6\x46\x56\x8e\x49\xff\x72\x82\x50\x19\x74\x6e\xca\x24\x01\x3d\x06\x37\xc1\xd8\x77\x53\x0b\xe0\x17\xab\xd5\xa5\x70\x93\x53\x48\x88\xc2\x49\x26\x6d\x55\x88\x29\x8d\xa6\x53\xca\x2f\xd3\x63\xff\xad\xf3\xde\x4d\x69\xe8\xd6\x19\xa9\xf2\x75\x43\xa1\x72\xdb\x8f\xc1\x93\xe6\xe5\xb4\x5a\x1c\xc2\xdc\xcb\x6d\xfb\xaf\xea\x51\x21\xed\x04\xcd\xf6\x83\x68\xaa\x2c\x8c\xe1\x72\xc9\x97\x15\x03\xe9\x34\x1a\x37\x54\xb2\xb0\x19\x16\x3a\x38\xcb\x17\xe7\x98\x09\x17\x5f\xfa\x42\xb7\x8f\x44\x51\x4d\xc4\xa3\xf0\xd2\xa6\x13\x2c\x45\xcb\x0f\xba\x42\x75\x76\x79\xf1\xf3\x17\x57\x73\x1f\x60\x96\x3a\x33\x7c\x0e\xd2\x82\x00\x83\x95\xb6\xd2\x69\x33\x25\x6a\x9d\x5f\xfd\x6c\x07\x70\xfe\xe2\xb1\x1d\x80\x50\x59\xb3\xf1\xa0\x12\xe9\x8d\xc8\xd1\x26\x0b\x63\xd5\xa3\x5f\x30\x75\x9d\xd7\x06\x7f\xad\xa5\xc1\xac\x3b\x0a\x22\x4f\xa4\xc9\xdc\x6b\xa2\x7f\xe7\x55\x65\xa8\x4f\xd7\xd9\xc8\xfe\xe9\x48\xb9\x99\xf7\x73\x33\x3c\x24\x32\xf8\x72\x90\x91\x80\x43\xcb\x2c\x10\xf6\x18\x66\x81\x76\x9e\x35\xa4\xa5\xf9\x1b\xb4\xa8\xbc\xc8\xa3\xd7\x42\x85\x39\x25\x70\x85\x86\x2a\xd2\x76\xaf\x8b\x8c\x24\xe1\x2d\x1a\x07\x06\x53\x9d\x2b\xf9\x5b\xd3\x9a\x05\xa7\xb9\x9b\x42\x38\xb4\x0e\x78\xd7\x2a\x51\xc0\xad\x28\x6a\xf4\xa4\x2c\xc5\x14\x0c\x52\xbb\x50\xab\x4e\x0b\x5c\xc4\x26\xf0\x54\x1b\x04\xa9\xc6\xfa\x14\x26\xce\x55\xf6\xf4\xe4\x24\x97\x2e\xca\xf0\x54\x97\x65\xad\xa4\x9b\x9e\xb0\x38\x96\xa3\x9a\xc4\xe1\x49\x86\xb7\x58\x9c\x58\x99\x0f\x85\x49\x27\xd2\x61\xea\x6a\x83\x27\xa2\x92\x43\x1e\xac\x62\x39\x9e\x94\xd9\xff\x33\x41\xea\xdb\xc3\x39\xf2\x2d\x65\x66\x88\x62\x73\x2d\xad\x49\x78\x7a\x2e\xf2\xd5\xfd\x5c\x5a\x92\xd2\x2b\xa2\xca\x8b\xef\xae\x5e\x42\x1c\x80\x27\xbb\xa7\x70\x5b\xd4\xb6\xc4\x26\x42\x49\x35\x46\xe3\x4b\x8e\x8d\x2e\xb9\x15\x54\x59\xa5\xa5\x72\x7e\x4b\x17\x12\x95\x03\x5b\x8f\x4a\xe9\x2c\xf3\x1c\x5a\x47\xeb\x90\xc0\x39\xab\x30\x18\x21\xd4\x15\xed\xa4\x2c\x81\x0b\x05\xe7\xa2\xc4\xe2\x5c\x58\x7c\xef\xa4\x26\x8a\xda\x21\x91\x6f\x7b\x62\x77\x35\xf0\x62\x85\x85\x3d\x06\x10\x35\xe4\x56\x85\x57\x6d\x4a\xf0\x3b\x70\x99\x04\x86\x35\x7b\x91\x1e\x91\x65\x06\xed\x92\x0f\x0b\x1b\xd2\x17\xf4\x7c\x32\xd1\x96\xd6\x4f\x38\x78\xfe\xe3\x53\x48\x85\x82\xda\x22\x6d\x9e\x54\x2b\x45\x0c\xe1\x34\x08\xd2\x65\x43\x7c\x2b\x2d\x33\x90\xc1\x5c\x5a\x67\xa6\x09\x3c\xd1\xa6\x14\xee\x14\xbe\x8a\xaf\x86\xdc\x9c\x36\x20\xab\x6f\x4e\xbf\xaa\xb4\x71\xdf\xc0\x73\x55\x4c\xa9\xd1\x0c\xee\x26\xa8\xe0\xaa\x99\x1b\x7c\xdd\xf9\xf1\xbd\xa9\xd2\x04\x2e\x72\xa5\x4d\x2c\x49\x5c\x75\x51\x8a\x1c\x61\x2c\xb1\x60\xbe\xb6\xe8\x92\xf9\x15\x5c\xbb\x8a\xe0\xe1\xd2\x58\xe6\x4f\x45\xb5\x91\x34\xe7\xb1\x24\xf5\x45\xdd\x77\x95\x77\xfb\xd1\x69\x66\x65\x9a\x12\xfd\x29\xd2\x1b\x10\xa1\x97\x52\x54\x43\xcb\xdb\xa6\x43\xa6\xed\x28\x70\x1e\x1b\x20\xfa\xb5\xaf\x2f\x82\xe4\x4a\x76\x9d\x76\x77\x66\x3b\xd7\x6d\x61\xc8\x46\xa2\x3d\x5d\xa6\x45\xb6\xe8\x23\x37\x55\x7a\xa9\x33\x3f\xed\x8d\xbd\x7c\xdf\x2d\x0d\xf8\xb6\xd2\x16\x2d\x64\x72\x3c\x46\x43\x72\x47\xdf\xa2\x31\x32\x43\x0b\x63\x6d\x78\xbd\x2a\x9d\xf1\x9e\x6c\xd6\x6f\x46\xd5\x5e\xea\x6c\xdb\x85\xa1\xae\x59\x61\x78\x66\x0c\x6c\xb8\x72\xba\x4b\x77\x3b\x6c\xd8\xbc\xf4\x88\x31\xc3\xff\xe9\xf2\xaf\x73\xf4\x38\x0b\x85\x23\xa7\x06\x44\x15\x44\xc7\xa1\xa5\xe9\x1f\xda\xa6\xcd\x65\xc3\xdd\x62\xc8\xdb\x0c\x9b\x1e\xa5\x33\x3c\xdb\x30\xfc\x85\x29\x3c\xe6\x1f\x23\xb4\x5c\xbd\x19\x2a\x6b\xf0\xac\x2e\x58\xd4\xd4\xc5\xec\x8a\xae\x9a\xc7\x96\x73\xd9\x76\x3e\xbe\x1c\x8e\xd1\x18\xcc\x1e\xd7\xc4\xbf\x57\xcd\xa8\x82\x90\xf2\xaf\xbf\x7b\x8b\x69\xbd\x6a\x8f\xad\x9c\x3a\x81\xe2\x30\x4d\x34\x70\x27\x8b\x22\x74\x47\x02\x25\x7e\xa0\xf9\x32\x8e\x21\xf2\x58\x2f\xa4\xad\x70\xd2\x8e\xa7\x4c\x8e\x86\x60\xf8\x96\x74\x36\x5b\x2c\xcc\xf1\x72\x2c\x31\x83\xd1\x34\xa8\x6b\x12\x9e\x03\x18\xd5\x0e\xa4\x63\x5d\x9e\x4e\xb4\xb6\x08\xc2\xd3\x9d\xdb\xbd\x95\x9a\x91\x12\x68\x85\x24\x7f\x4a\x52\xc8\x61\xe3\x74\x9a\x4f\x78\xe4\x6d\x35\x69\xa1\x24\x89\xdf\xd0\x2a\xb2\x23\x35\x73\x27\xdd\x84\x7f\xe4\x04\xb9\x09\x85\xd9\xba\xa4\x46\xef\x50\xe6\x13\x67\x07\x20\x13\x4c\x78\x75\x51\xa4\x93\x4e\xb3\x25\xa2\xb3\x20\x8a\x22\x0e\xa1\xcb\x12\x5e\x6f\x96\x04\x51\xe0\xa8\xc1\x30\x01\x6f\x0c\x1a\xbd\x3a\xbf\x6a\x4b\xc9\x35\x00\x74\x69\x72\x3c\x80\x54\x97\x55\xed\x88\x26\x34\xc6\xd1\x14\xa4\x23\x9c\xed\xf1\x92\xd1\x75\xee\x67\x82\x45\xe8\x38\x82\x55\xaf\x99\x48\x38\x90\x8d\xa8\x72\x38\xf0\x93\x3b\x88\xf8\x93\x9a\x93\x7e\x12\x3c\xbf\x52\xb8\x74\x12\x20\x70\xaa\x8d\x41\x5b\x69\xc5\x35\xf9\xcb\x77\xed\xd8\xfe\xde\x54\x3a\xb2\xc7\x2d\x31\x27\x32\x9f\x44\x5a\x0a\x83\xfc\x6e\x76\x0d\xd6\xed\x91\x76\x9f\x08\x63\x66\x6c\xc9\x65\x8f\x74\x58\x6e\xd8\x25\x0b\xac\x7d\xa6\x00\xcb\xca\x4d\x3b\x3c\xd1\x59\x3d\x87\xa6\x6c\x68\xc0\x0b\xcc\xdb\xd5\xfa\xf9\xc9\xb2\x2a\x64\x2a\x5d\xe0\x10\x78\x08\x47\xcc\x22\xd2\x91\x28\x03\xa5\x87\xba\x3a\x4e\xe0\x8c\xdd\x17\x5b\x74\xa0\x74\xd3\x7e\x68\x88\x3a\xb5\xba\x6d\x6b\xe3\xdc\xb6\x14\x2a\xfe\x59\x8d\xe9\x16\x9f\x61\x18\x3f\xaa\x74\x1e\xe5\x2d\x2f\xee\x69\xb2\xb1\xe8\xb6\xe2\x2d\x96\x8e\x63\xd8\xa6\xf4\xfc\x52\x7b\x96\xb6\x58\x60\x4a\x26\x29\xd1\x7e\x00\xc2\x5a\x9d\x4a\x42\xf9\x2d\xd3\xce\x72\xba\x9f\xc9\x66\xda\xc3\xae\xf4\x87\x9d\xe7\x4f\xcf\xfc\xc6\xdb\xb6\xde\x02\x35\x0a\x49\xe0\x77\x3c\x47\x95\x19\x81\x35\x9a\xf2\xd7\x43\x0b\x85\x18\x61\x61\xb7\x23\x02\xec\xb4\x6b\xdb\x67\xcb\xfd\xbb\x72\x42\x2b\x27\x12\x6c\xcc\x66\xe1\x49\x68\x93\x6d\x26\xa4\xb2\xc1\x7e\x1e\x80\x80\x1b\x9c\x7a\x53\x9b\x2c\xf8\xe8\xb8\xe0\xc2\x06\xbd\xba\x21\xe6\xb8\xc1\x29\x17\x0a\x76\xf7\x0e\xc3\xdd\x99\x39\xfc\xb3\xcb\x36\x6d\x9f\x21\x0d\x74\xc7\x1a\x71\xd2\x3b\x54\xdb\x9d\x7f\xfd\x73\x83\x6b\x91\xd7\xb2\x67\x01\x92\x30\x4f\xf2\x7a\xf0\x22\xb1\xfe\x8a\x6b\x2c\xaa\xaa\x90\xc8\xf6\xfc\x8e\xdd\xac\xb5\x02\xd6\x3d\x91\x7a\xf7\x9a\xd7\x8b\xc6\xa1\xe1\x19\xf2\xd0\x7a\xe6\xa3\x9d\x3e\x91\x95\xb7\x6f\x2d\xf2\xc6\x8d\x9e\x9f\x9f\x45\x21\x5b\x57\x9b\x65\x3d\x7b\xa1\x06\xf0\x4c\x3b\xfa\xe7\x3b\xb2\x84\xed\x00\x1e\x6b\xb4\xcf\xb4\xe3\x9f\x09\x7c\xef\x3c\xaf\xff\xb8\xa5\x64\x7b\x07\x04\xf2\xe3\xbd\x17\x79\xce\x94\x97\x29\x34\xfd\xae\xcf\xc8\x26\x70\xe1\x61\x4b\xb3\x71\xa5\x85\x0b\x45\xe0\x30\x90\x81\xbd\x78\x5c\x36\x34\x51\xd6\x96\x9d\x3c\x4a\xab\x21\x63\x80\xa5\x6d\x78\xea\x51\x3b\x5d\xfa\xad\x69\x6e\x75\x53\xdf\xb3\xaf\xe1\xc7\x95\x95\x27\xe2\x96\x21\x9d\x54\x79\xd1\x80\xb7\x01\xdc\x4d\x64\x3a\xf1\xa8\x7b\x84\xde\x35\x58\x19\x24\x85\x25\x2c\x89\x2a\x7a\x93\xa3\x21\xb0\x2b\x63\x7b\xde\x31\x59\x88\x14\x33\xc8\x18\x5a\x7a\x27\x9b\x70\x98\xcb\x14\x4a\x34\x39\x42\x45\x9a\x64\xbf\xd5\xdf\x4d\xb0\xfb\x67\x67\xf1\xde\xed\x70\x27\x76\x63\x15\xf9\x84\xb0\xee\x9f\xa4\x1d\x19\x57\xf7\xda\xb1\xd7\x8e\x73\x4f\xaf\x1d\x9b\xa7\xd7\x8e\x1b\x9e\x5e\x3b\xf6\xda\xf1\xbd\x6b\x47\x6f\xcb\xee\x61\x3c\xff\xd3\xbb\x38\xe6\xad\x65\xd6\xb4\x31\x4c\x37\x6b\x36\x93\xbe\xb9\x0a\x02\xe7\x25\x9b\xda\xd2\x07\x49\x8c\x50\x39\xc2\xa3\xe1\xa3\x87\x0f\x77\x31\xaa\xc3\x42\x6e\x55\x63\x1c\x22\x3d\x52\xb9\x2f\x3e\x5f\x5b\x63\x95\xff\xed\x1d\x78\x4d\x03\x8f\x37\x8e\xbc\x19\xec\xb0\xc2\xf1\xc9\xd2\x49\x69\x07\x25\x3a\x10\x6e\xc6\x55\x24\x4b\x1c\x34\xa1\x02\x66\xf8\x10\xa5\x8c\x1e\xd8\x0c\xb4\x0a\x7e\x3c\x22\x7e\xb2\xdf\x08\x52\x14\x3e\xa4\x36\xc2\x66\x14\xba\xa4\x5e\xa5\x72\x71\xbb\xd0\x10\x30\x52\x05\x8e\x30\xc9\x13\xc8\x6a\xae\x26\x54\x08\x9b\x1e\xfb\xd1\xda\xa9\x75\x58\xb2\x27\x57\x1b\xfe\x87\x86\xed\xcc\x94\x0a\xe3\x2d\x2a\x57\x8b\xa2\x98\x02\xde\xca\xd4\x35\xf3\xe3\xa8\xad\x74\xde\xd9\xbe\x9d\x8b\x70\x2b\xe8\xb0\x3d\x5c\x18\x2e\x70\xb0\xdd\x50\x67\x17\x6d\xbf\xd0\xf6\x36\x7b\x72\x4e\x17\xfa\x99\x24\x2b\xc1\xaa\xa3\x76\xbd\x0f\x9c\xff\x64\xe6\x7a\xfe\x62\xb3\xcb\x15\x76\x96\x64\x3b\x48\xaf\x79\x58\x5a\x17\x05\x31\x86\xf7\xc2\x2e\x4e\x60\x89\x77\xd4\x4f\x69\x86\x99\xbd\xe3\xdd\xbb\x98\xcf\x9e\x3d\x26\xaa\x50\x99\x97\xba\xd2\x85\xce\xa7\x5d\x4a\xfb\xf4\x22\x59\x56\xd1\x39\x2e\xc0\xd6\xa3\x00\x1a\x88\xfd\x9e\xcd\x2d\x4d\xef\xf9\xeb\x3d\x7f\xbd\x6d\xb3\xf0\xf4\xb6\x4d\xf3\xf4\xb6\xcd\x86\xa7\xb7\x6d\x7a\xdb\xa6\xf7\xfc\x41\xaf\x1d\xd7\xd0\xa4\xd7\x8e\xd0\x6b\xc7\x95\xf3\xea\xb5\xe3\x5a\xf2\xf4\xda\xb1\xd7\x8e\xcb\x9e\x4a\x67\xf7\x48\x74\xac\x74\xb6\x26\xcf\xd1\x7b\x7d\x52\x3d\x2c\x74\x2a\x5c\xc8\xcb\xa7\x2a\xc1\xcf\x67\x45\xe9\x1d\x51\x03\xf8\x4d\x2b\xf4\xc9\x6b\xb4\x36\xec\x4e\xd2\x6e\x82\x86\x8a\x1f\xd9\xe3\xb5\x89\x4d\x7d\x9e\x64\x9f\x27\xf9\xd1\xe7\x49\x4e\x84\xf5\xeb\xea\x85\xd2\xea\xb4\xc9\xce\x86\x7c\x89\xa6\xfc\x44\xb3\x26\x89\x5d\xc2\x72\xf3\x89\xa7\x76\x49\xfd\xcc\xb3\x10\x2f\xc0\xec\x72\x76\xbe\x01\x2f\xf3\xa4\x44\x96\x61\x06\x15\x9a\xa1\x67\x11\x0d\x63\xa9\xb2\x25\x73\x8d\xf4\xf9\xa0\xd9\x8f\xb3\xf3\xf8\x80\x29\x90\xb3\x03\xd9\xc3\xe7\xda\x75\x1c\xcf\x48\xf8\x8f\x22\x21\x72\x57\x54\x3f\x04\x17\x9c\xbc\x3f\x6c\x89\xeb\x77\x87\xe6\x0c\xa8\xa3\x4b\x78\x7f\xbb\x92\x61\xf9\xaf\x35\x9a\x29\x9f\xff\x68\x01\x6b\x73\xb6\x2e\xc4\xc8\xa4\x85\x54\x58\xaf\x29\x76\x35\x2d\x77\x34\xa3\xf6\xb3\x53\xf6\xf7\x44\xc3\x3c\x5d\xe6\x9b\xf2\x36\x69\xb4\xc1\x3d\xcd\x96\x1a\xe1\x4b\xa2\x00\xad\xf7\x7f\xa7\xf1\xec\x0b\xdd\xf6\x02\x6e\x4b\x99\xe2\x23\x36\xce\x61\x7f\x03\x1d\xf6\x36\xd2\x61\x2f\x43\x1d\xf6\x35\xd6\xe1\x1e\x06\x3b\xec\x67\xb4\xc3\x3c\x2b\xd0\x0a\x05\x94\xf5\x7e\xec\x77\xb8\x8f\x89\x0a\xf7\xb0\xe3\x61\x7e\xaa\x0d\x9b\x9a\xf7\x65\xd4\x33\xaf\xcf\xd8\xf5\x7f\x36\xb1\xf6\xb3\xe9\x61\x9e\x54\xc1\x18\x96\x6c\xd0\x7e\x22\x16\xfe\x9f\x62\x6e\xc3\xbd\x4c\x6e\xd8\xdf\xec\x86\xfd\x39\x83\x55\xdd\x8f\x1c\x4e\xbd\xaf\xc2\xf4\xad\x78\x15\xc1\x67\x70\xc7\xf0\x3b\x69\x02\x5e\x97\x3f\xa0\x12\xd2\x58\xc2\x77\xc1\x67\xd2\xfd\x16\xac\xf3\x6e\x33\xa5\x3f\x42\x4c\xa2\xfa\x56\x14\xa4\x7b\x7c\x1e\x47\xb0\x8b\xa8\xf5\x79\x35\x3d\x80\xbb\x09\x59\x9b\x24\xa5\x9a\xf3\xce\x07\x37\x38\x3d\x18\x2c\x30\xd2\xc1\x85\x3a\xf0\x3a\x6a\x81\x75\x1a\x85\xa6\x55\x31\x85\x03\xfe\x76\xf0\xae\x35\xfb\x1e\x8a\xab\x7b\x85\xca\xbe\x7a\x61\x0f\x2e\x51\xf1\x5a\x97\x77\x0f\x36\xbd\x16\xf1\x81\x8d\xd8\x8b\x6d\x15\x0c\xa7\x5a\x74\x94\x4b\x93\x35\xc2\x3c\xc6\xef\xb3\x68\xfc\xd6\x2a\xdc\x74\x11\xcf\x9c\x87\xc6\xbc\x92\x5a\x4c\x69\x0a\x0b\xaf\x15\x5a\x06\x76\xd8\xb8\x88\x3a\x95\xb9\x6c\xe2\xd3\x41\x5a\x6d\xa7\xb2\xf9\x04\x91\xb6\x06\x63\xc4\x12\x85\xb2\x70\x10\x7d\x4f\x87\xb6\x2d\x71\x90\xb4\xa7\xfb\x9a\x16\x8f\x7e\xff\xe3\x78\xe6\x44\x5f\xdb\x60\x8f\xb4\x7b\xa4\xdd\x23\xed\x1d\x6a\xf5\x48\x7b\xf5\xd3\x23\xed\x1d\x9e\x1e\x69\xf7\x48\x7b\x5d\xc7\x3d\xd2\xee\x91\xf6\xe6\xce\xf7\x43\xda\xfb\xe6\x09\x75\x71\x6f\x08\xce\xf9\x8b\xcc\x84\x93\x69\x9b\x43\x14\x4b\xf9\xbf\xde\x2d\xde\xee\x62\xe9\xe5\x68\xbb\x8b\xc8\x17\x6c\x8b\x64\x03\xb4\x6e\xc0\xf7\x42\xcd\xf5\xa8\xfb\xe3\xca\x85\xda\x83\x37\x3a\x01\x85\x3d\x99\xe3\x65\x0c\x85\x87\x8b\xff\x46\xd8\xc6\xc9\x33\x38\x8a\x11\x97\x63\x22\xbe\xd2\x6e\xf6\xa3\x72\x72\xd8\x96\x68\x62\x30\x1c\x5e\x9c\x39\x6f\x33\x13\x96\x68\xa2\xee\x4d\xa4\xb8\x5d\x4f\x12\x21\x68\x66\xc6\x20\x6d\xb8\xde\x90\xb3\x25\x4c\xad\x14\xb5\xaa\x55\x0c\x1f\x7b\x99\xe3\xef\xe3\x0b\x9c\xe7\xc1\x12\x8f\x87\x11\x53\x4b\xa5\x4e\xbc\x53\x38\x7f\x05\x62\x48\xe5\xd7\x2a\x44\x44\xe9\x4d\x8c\xfa\x46\xa6\xe4\x19\xc9\xa6\xf7\x04\xbe\x63\x3e\xec\x36\x2c\x2d\xd3\x47\x14\x85\xbe\xdb\x45\x24\xfd\x59\xc7\xa2\xee\x76\x3e\x16\x35\x17\xbf\xeb\x4f\x45\xfd\x9b\x9c\x8a\xe2\x8f\x7e\x0b\xbd\xf3\xe3\x51\xf0\xcf\x70\x01\xa1\x41\x26\x55\x59\x17\x4e\x56\x6d\xae\x94\xf5\x5d\x15\x1e\x65\x8e\x43\xe6\xc9\x2c\x5f\x52\x6f\x22\x9d\xcc\xf3\x27\xb7\xc7\xb9\x55\x96\x37\x6d\xc8\xee\x10\x45\x11\xce\x14\x45\x48\xea\x53\x58\xe4\x87\xce\x4c\x78\x1c\xee\x6c\x6d\xac\x19\x16\x32\x47\x24\x0b\x0b\x5a\x50\x92\x6a\x6b\x84\xa8\x37\x8a\x6e\x31\xaa\xde\x5c\xde\xa2\x6a\x25\xe9\x91\x3d\x3e\x8e\x3a\xfc\x9d\x4a\xf8\xf7\x22\xa1\xbf\xea\x48\xd2\x6f\xb6\x91\xd1\x3c\xa1\x46\x4a\xb7\xe4\x6b\x65\xf4\x87\x4c\xc1\xd8\x25\xce\xbf\x9b\x8f\x61\x8f\xf8\xfe\x9f\x18\xdb\xff\x74\x4e\x96\x7d\x60\x0f\xe3\x87\xc8\xad\xff\xe8\xbd\x8a\x7d\x72\x7d\xfb\xdc\x37\xb9\xfe\xbd\x7b\x0e\x3f\x6c\x8e\xfd\x27\xe0\x2d\xfc\x90\x39\xf6\xbd\x87\x70\xed\xa2\x7c\x6c\xa9\xef\xb3\xcf\x5e\x1e\xc1\xde\x1b\xb8\xb7\x16\xde\x51\xe1\xdc\xd7\x0b\xb8\x23\x47\xec\x19\x67\xef\x63\xec\x7f\x4e\x8c\xbd\x47\xbc\x5b\x3e\x3d\xe2\x5d\x49\x94\x1e\xf1\x42\x8f\x78\x37\x4d\xaf\x47\xbc\x6b\xc9\xd3\x23\xde\xb5\x8b\xd2\x23\xde\x1e\xf1\xc2\xa7\x86\x78\xf7\xb9\xa5\xab\x8f\x75\xdf\x2b\xd6\xbd\xab\xb4\xd8\x49\x46\xec\xc8\x07\x3b\xc7\xb6\xfb\xb8\xf6\xc7\x12\xd7\xde\xfa\xc0\xbf\x72\xf2\xbe\x87\xfe\xbb\x6b\xb5\xea\xe4\xbf\xb8\xd5\x32\x83\xaa\x76\xe1\x3c\x75\x7f\xfa\xff\x5d\x9c\xfe\x9f\xa1\x7c\x7f\x05\xc0\x56\x57\x00\xac\xa2\x59\x7f\x0f\x40\x7f\x0f\xc0\x3b\x0e\x42\xf7\xf7\x00\xf4\xf7\x00\xf4\xf7\x00\xc4\xa7\x3f\x9d\x04\xfd\xe9\xa4\xad\x9e\xfe\x74\xd2\xea\xa7\x3f\x9d\xf4\xd1\x7a\x5f\xa1\x3f\x9d\xf4\x71\x7b\x62\xa1\x3f\x9d\xd4\x7b\x67\xb7\x5c\xa8\x4f\xf0\x74\x52\x7f\x0f\xc0\xc7\x9a\xa3\x00\x3d\xd2\xee\x91\x76\x8f\xb4\x7b\xa4\xbd\xfe\xe9\x91\xf6\x0e\x4f\x8f\xb4\x7b\xa4\xbd\xae\xe3\x1e\x69\xf7\x48\x7b\x73\xe7\xfd\x3d\x00\x9f\x50\x6e\x04\xf4\xf7\x00\xf4\xf9\x12\xfd\x3d\x00\xff\xbe\xf7\x00\xcc\xc4\xee\x3f\xdc\x65\x00\xbb\x0f\xa3\xbf\x11\xa0\xbf\x11\xa0\xbf\x11\xa0\xbf\x11\x20\x3e\xfd\x8d\x00\xfe\xf9\x98\x7c\x8d\xfd\xf9\xa8\x95\x44\xe9\xcf\x47\x41\x7f\x3e\x6a\xd3\xf4\x3e\x01\xbf\x61\x7f\x3e\xea\x23\xf4\x15\xf6\xe7\xa3\x7a\xbf\xe0\xfc\xe2\x7c\x22\xe7\xa3\xfa\x1b\x01\x3e\xc6\x68\x7b\x8f\x78\xb7\x7c\x7a\xc4\xbb\x92\x28\x3d\xe2\x85\x1e\xf1\x6e\x9a\x5e\x8f\x78\xd7\x92\xa7\x47\xbc\x6b\x17\xa5\x47\xbc\x3d\xe2\x85\x4f\x0d\xf1\xf6\x37\x02\xf4\x37\x02\xf4\x37\x02\x7c\x8a\x11\xee\x8d\x2b\x4d\x23\xdb\x64\xd0\xce\x2c\xe7\xb3\x4e\x85\x39\xf0\x1e\x4e\x34\x07\xdd\xea\x4c\x8d\x7c\xc0\x3b\xc6\x1f\xf9\xd8\xae\x6b\xe9\x9a\xc0\xd5\x92\x9a\x4c\xbe\x50\xe2\xd0\x7a\x42\xdb\xf9\x76\xe6\xe2\xb5\x9e\xd6\xdc\xe6\x8a\x29\x6c\x21\x6e\x77\x13\xae\x1b\x09\x5b\x19\xa9\x8d\x74\xd3\xf3\x42\x58\xfb\x4c\x94\xb8\x15\x75\x2f\xc6\x2d\xd3\x0e\x40\xaa\x4c\xa6\x8d\x75\xe3\x05\x49\x6c\x97\x01\x10\xf1\x43\xa7\x7c\xa4\x50\x2c\xe3\x03\xdc\x23\x24\xf6\x16\x75\xe1\x68\x8b\xfd\x86\x46\x87\x03\xe9\x06\x3d\x4f\xc5\xcf\xeb\x89\xb7\x66\xae\x16\xd3\x9a\xe7\xaa\x95\xc3\xb7\xee\x5c\xab\xb1\xcc\xb7\x9a\xef\xc1\xd5\xb2\xaa\x90\x0a\x45\xc3\xe6\x0b\x09\xc6\xf0\xa6\xc0\x5c\xa4\xd3\x37\x34\xfc\x37\x06\x69\x20\xb4\x67\xde\x78\xa5\x70\x2e\x9c\x28\x74\x7e\xc5\x11\xb3\xc3\x70\xc3\x84\x05\x94\x7c\x81\x84\x54\xbf\xf8\x0d\xd6\xc8\x0e\xc3\x79\x18\x95\xce\x12\xa2\x5c\x32\x37\x76\x96\xea\xcd\xc7\x00\x00\xd0\xbc\xfa\xec\xf5\x42\xc9\x00\x15\x08\x8c\xd0\x96\xec\xf2\xa7\xa9\x15\xc9\xa0\x4b\x9d\x41\x9c\x20\x9c\x65\xa5\x64\x74\x02\x47\x97\x57\x67\xc7\x33\x33\x81\x92\xaf\xc1\xd0\x06\x32\x8d\x56\x1d\x3a\xb6\x1b\xdc\x04\x6d\x8b\x48\x78\xe7\x73\x40\xd0\xef\x16\x8e\x08\xc6\x3e\x89\x60\x0c\x52\x46\xd8\x74\x7e\x75\x06\x6f\x46\xc2\x62\x21\x15\x7a\xda\x55\x46\xde\xca\x02\x73\xea\xb1\xe3\x5f\x81\xf3\xda\x18\x54\xae\x98\xc6\x9b\x0a\x96\xaf\x8a\xb4\x50\xab\x39\x76\x8b\x9c\xd5\x48\xc7\x66\xb1\xa8\xb4\xc5\x2c\x81\x2b\xae\x31\xf5\x50\x3a\x94\xe3\xb5\x71\x13\xa1\x56\x2e\x2e\x18\xb4\xd4\xb0\x54\xbe\x96\xcc\xd8\xb2\x02\x34\x86\x54\x33\x67\x2f\xd4\x96\x05\x75\x91\xa1\x81\xd4\xb3\x01\xc8\x52\xe4\x5e\xca\x33\x91\x58\xe5\x84\x14\x8f\x40\x98\x25\x84\x5f\x3d\xe7\x56\x69\xf1\x8a\xe8\x66\xbc\x09\x5c\x2b\x32\x5a\x04\x8c\x6b\x57\x1b\x84\x5b\x34\xbc\xba\xbc\xe7\xba\xa4\x89\x9b\x30\x36\xd0\xe9\x7e\xd0\x0c\xbb\x14\x32\xb0\x9a\x8d\x7d\x1a\x1c\xd5\xb2\x60\xb4\x22\x9b\xf9\x59\xcf\xc8\xa2\xe9\x4e\x8f\x41\x57\x65\xb8\x26\xa4\xae\x2a\x6d\x5c\xab\xc3\xd2\xee\xde\x08\x3a\x66\x09\x01\x68\x58\x95\xc1\x8a\x70\x6c\x90\xb4\x16\x21\x9d\x08\x95\x13\x7b\x5c\x2b\x78\xaa\x39\xa5\xc3\xe7\x05\x51\xb7\x62\xa4\x6b\xc7\x3c\x16\xf6\xea\x58\xd7\x2a\x03\x12\x2a\xa7\x30\x71\xae\xb2\xa7\x27\x27\x37\xf5\x08\x8d\x42\x87\x36\x91\xfa\x24\xd3\xa9\x3d\x49\xb5\x4a\xb1\x72\xf6\x24\xee\xa6\x93\x4a\x67\xc3\xf8\x63\x28\xe2\x26\x39\x39\x3c\xd8\x57\x1a\x41\xa4\xfc\x29\xf8\xb5\x5a\x51\x0a\x55\xbd\xe6\x52\x84\xe1\xfa\xca\x54\xa0\x25\xe3\xd2\x42\x4e\x17\x7c\x85\xc8\x1a\x4f\xe1\x2c\x50\x6a\xcb\x37\x57\x79\x44\xf6\xb0\x1d\xe9\x76\x68\xbb\x4d\xaf\x17\xda\xeb\x00\xe4\x06\xc8\xb8\x70\x8d\x07\xcb\x36\x02\x73\xed\x40\x19\x00\x38\x27\xf8\x22\x0f\x42\xe3\xfe\x0b\x89\x2b\x35\x05\xe2\x67\x17\x6e\x75\xe9\x5c\x73\xe2\x0c\xe7\x19\x7d\xd5\x58\x7d\x03\x1c\x8f\x31\x75\xdf\x84\xfd\xdc\xd8\x7f\xbc\xb9\xa3\xa5\xf6\x55\xfc\xeb\x9b\xd5\xc8\x67\x2b\xa3\x6a\x3b\xb7\x98\x1f\xd2\x7a\xb8\x3b\x43\xa1\xef\xb8\xc2\x9c\xca\xf6\x14\xf0\x6d\x11\x7d\x78\x5a\x11\xdb\x79\x23\x21\xe0\x1d\x92\x19\x9d\xc2\x36\x48\xb8\x8e\xb4\x0d\xb8\xaf\xb5\x50\x11\x9e\xe9\x90\x70\x87\x03\xb8\xe4\x3b\x50\xda\x37\xac\xc8\x9e\x69\x9f\x7a\xb7\x12\x17\x75\xe9\xb6\xd1\x1e\xd8\xe8\x18\x9c\x21\xc8\x0f\xad\x1b\xd0\xcf\x6c\xc6\x0d\xd8\x72\xf0\x8c\x95\xb7\x8e\x32\x37\x38\x6d\x5d\x47\xc1\xc9\xc8\x96\xd9\xa0\xe5\x92\x08\x3e\xbd\x27\xe8\xef\x21\x77\x46\x97\x23\xa9\x7c\x67\xbe\xe9\xb8\x14\xdc\x7a\x24\xa8\xca\xf8\x27\x77\xf3\x2e\xc8\xb5\x9d\xb7\x71\x86\x66\xcf\x77\xf0\x2d\x36\xde\x8a\xe5\x5e\xc5\x8e\x2b\xf1\xbb\x5f\x6b\x51\x24\xf0\xd8\x4b\x45\x9e\x7d\x78\x15\x0a\x2d\x78\x57\xee\x64\x91\xa5\xc2\x64\xac\x0d\xfc\x1e\x05\xab\xfd\xea\x89\x06\x70\xc4\xdd\xde\xae\x91\xbf\xe3\x07\x2a\x61\x9c\x4c\xeb\x42\xb0\xda\xc2\x5c\x9b\xe9\x3b\xa1\x68\xcb\x34\x57\x98\x6a\x95\x6d\x30\x78\x57\x48\xd7\x50\xb7\x4b\x63\x86\x51\x68\x64\x48\x65\x93\x25\xce\x33\xe9\xd1\xac\x71\xa3\xc7\x71\x57\x37\x5b\x6c\xe0\x51\xcd\x9d\x64\x58\xd6\xf8\x1b\xa4\x05\xe9\x73\x61\x8f\x3b\xe2\xb1\xd9\x15\x09\xfc\x63\x1a\xf5\xd5\x00\xa4\x8b\x56\x9e\x45\x17\x31\x4c\x64\xd9\x40\xec\x76\x43\x8d\xb5\xc1\x5b\x34\x70\x94\x69\xae\xc3\xe9\x9e\xc7\x09\xfc\x8b\x20\x3e\x7b\x27\x30\xf7\x99\x89\x81\xc5\x23\x12\x71\x7c\x29\x17\x5b\xbb\x0f\xe1\xc8\x67\x89\xca\xb2\xc4\x4c\x0a\x87\xc5\xf4\xd8\x07\x0a\x63\x9e\xe9\x36\x4b\xb7\x4d\x72\x71\x27\xa9\xf8\xcb\xbf\xac\x29\xc9\x83\xdd\x61\x65\x7f\x66\x48\x39\x23\x6a\x3c\xca\x9c\x5b\xc2\x46\x07\xe9\x35\xce\xe3\x8e\xb3\xb8\x83\xfd\xa2\x98\x69\x16\xf8\x17\xe2\x03\x01\x06\x73\xe6\x72\xcf\xb9\xf7\xe0\x71\x99\x2e\x4f\x8e\xde\xa0\xd1\xd6\xc7\x9f\x86\x40\xf0\xff\xcb\xbf\x64\xc2\x89\x15\x05\xfc\x9a\x4f\x2b\x5c\xf2\x7d\x93\xa2\x6c\x1b\x5f\xb5\x58\x1b\xb7\x75\xd3\xfd\x5e\x2d\x30\xd4\x5f\x56\x73\xd6\xa4\xa6\x52\x21\x1e\x11\xd7\x7b\x68\x30\x97\xd6\x99\xc6\xc5\x4b\x96\x22\x97\x73\x1a\xa4\xb2\x4e\x28\x27\x59\xb2\x41\x2c\x39\xb4\x68\x6e\xf9\xd6\x3e\x37\x49\xe0\x39\xd9\x5a\x64\xde\xc0\x1d\xa9\x69\x0f\xb0\x5f\x4e\x2b\x84\xaf\x3b\x3f\xbe\x37\x55\xca\xbc\x16\x04\x8d\x67\x2e\x91\x65\x06\xed\xa2\x7c\x58\xc6\x3e\x6b\xe7\x1f\xcd\xfc\x8d\x24\x38\xbc\x8c\x0e\x81\xe0\x03\xb5\x56\xe6\x84\x32\xe3\xa9\x84\xa0\x4e\x66\xd1\xa6\xb7\x0a\xb8\xa2\xfc\x8d\x77\x53\xd9\x28\x01\xe9\x22\xee\x4f\xb5\xb2\x75\x19\x93\x0b\xc8\xea\xa9\x50\x65\xa8\xd2\x29\xa7\xb1\x16\xb7\x68\x12\xf8\xc9\xd2\x4a\xc1\x7f\xc9\x9c\xec\xbe\xd0\x69\x17\x2a\xc5\xec\xe8\xb9\x11\x48\xdb\xb9\xdb\x8d\xd3\x25\x08\x03\xc5\x16\x30\x9b\x2b\x6f\x63\xc8\x66\x7e\x10\x9c\x5c\x1f\x1c\xf7\x7c\x7a\x22\xb8\xdf\x1a\x47\x89\xdf\xf0\x34\xa5\x5c\xfb\x44\xf9\x4a\x5b\x19\xb3\xba\x1b\x39\x3a\x73\x02\x43\x8f\xfd\xf9\x08\xdf\xee\xac\x21\xcc\xb1\xbf\xb9\xc9\xb0\xe1\x56\x2b\x4f\x7c\xec\x7a\x69\xa2\x98\x79\xe8\x9b\x5a\x56\xcf\xc5\x0b\x33\x67\x87\xdc\xca\x74\x23\xd4\x0d\x66\x50\xe0\x5b\x99\xea\xdc\x88\x6a\x22\x53\x3e\x04\x40\xdb\x94\x9d\x64\x9c\xfa\x2f\x4a\x4c\x0e\x57\x32\xda\x2a\x31\x5e\xd5\xa3\x42\xda\x09\x2e\xc5\x32\x6b\x79\xd4\x62\x6a\xd0\x2d\x95\x20\x33\x2c\x7a\xe5\xcb\xb5\x4a\x39\x46\x4e\x43\x03\x21\x33\xc0\xf3\x1c\x6f\x3c\x22\x71\x9a\xd2\x46\xf2\x47\x67\x94\x6b\x2f\x66\x6c\x68\x98\xc0\x05\xab\xd4\x11\x5a\xe6\xf2\x1b\xc4\xca\x73\x1a\xbb\xf0\x6d\xc9\x3e\x15\x2b\x55\x8a\xfe\x28\x83\x3f\x12\x82\x18\xdd\x8c\xce\x48\xf4\x30\x88\x54\xed\xb4\x59\x1b\x54\x6e\x39\xa8\x59\x6f\x77\xad\xb1\xb9\xd6\x93\xb1\x91\x29\x9b\x29\xd9\xca\xa2\xa8\x13\xe9\x6f\x22\x25\x7f\xd9\x75\x05\xfd\xc9\x93\x2b\x1f\x02\xdd\x2c\x6b\x7e\x9a\x29\x1e\x1c\xeb\x16\x26\xfa\x2e\xb4\x34\xbf\x69\x83\xc7\x26\xae\x6d\x26\x6d\x4a\x3b\x1d\x33\x38\xd7\xca\xc6\xe3\x27\x42\xf9\x13\x25\xb7\xa2\xf0\xac\x10\x1b\xae\x74\xc1\x27\x7b\xb2\x3a\x9a\x13\x3e\x4b\x04\xcb\x11\xf2\xb5\x91\x36\x0e\x65\x85\x9a\xdb\xa0\x62\x37\x69\xc1\xa8\x1f\x2e\x75\x51\xac\xd7\x62\x6b\xed\xd2\x6d\xac\xd2\x48\x80\xad\xaf\xec\xbd\x88\x14\x0b\xbe\x38\xe2\xe9\x0c\x1d\x9a\x52\xaa\x00\x8f\x08\xea\x36\x84\x1d\xa1\xbb\x43\x54\x90\x4e\x30\xbd\xb1\x6d\xac\x83\x2f\x70\x9d\x5b\xb5\xe0\x7f\x9a\x95\x58\x0d\x9e\xa2\x55\x61\x43\xc3\x22\x82\x24\x9b\x40\xe1\x5d\xd7\x67\xb5\x44\xdd\x90\x8a\xbe\x15\xb2\x10\xa3\xc2\x1f\xbb\x6a\x7e\x0d\xba\xe3\x90\x51\x9f\x57\x75\x51\xa0\x0f\xe8\xe5\x2f\x2e\xcf\xc1\x19\x31\x1e\xcb\x94\xc3\x39\xd2\x78\xaf\x6f\x50\x6c\x4b\xa7\xb0\xf9\x52\xe1\x25\x3b\xc2\x3a\xe1\xea\x85\x35\x5a\xb3\xc0\xeb\x16\x96\xec\x10\xb9\xd2\x41\x34\x77\x15\xe7\x8c\xb1\x42\xc3\x40\x6f\x6c\xcd\xf8\xbf\x13\x78\xa6\x5d\xb8\x49\xf7\x29\x5a\x52\xbb\x4c\xa0\x17\x28\xac\x56\x1d\xe9\xca\xe8\xd7\xc8\x5c\x2a\x51\x84\x49\x75\xfd\x7b\x8d\xed\x21\xd8\xa5\x5c\xca\xdc\x08\xd7\x08\xc5\x76\xdc\x41\xbb\x04\xbd\xe8\x3d\xa1\x09\x9c\xa9\x29\xaf\xf7\x18\x05\xbd\xa0\x96\x9d\xd1\x59\x9d\x62\x38\x73\x57\xdb\x6e\x23\xef\x54\x8c\xce\x86\x17\xce\x63\x27\x6d\x2c\x3f\x43\x27\x64\x08\x29\x69\x85\x20\x6c\x45\x76\x5c\xe4\x49\xef\x0a\x6f\x09\xcc\xca\xe2\xec\xf2\x02\x5e\x84\x43\x39\x09\x0c\x87\x43\x1f\xd5\xb4\xce\xd4\x29\xeb\x17\xda\x42\x2a\x0b\x9a\xc2\x73\x1f\x4f\x52\x74\xd2\x60\x82\xe7\xc3\x43\xb0\x4a\xb8\x09\x24\x9e\xf0\x49\x87\x14\x00\x4f\x48\xd7\xbc\x15\x65\x45\x7c\x7f\xad\xbc\xf4\x7e\xa2\xf5\x95\x5f\x24\xdf\xe7\xef\x70\x72\x32\xcf\x13\x7a\x44\x10\x35\x38\x10\x99\x35\xc6\x5a\x1f\xda\xd9\x29\x25\x54\xf1\x07\xa5\xef\xd4\xb2\xde\xb9\x2f\x61\xf0\x14\xae\x0f\xce\xe2\xee\xbb\x3e\x18\xc0\xf5\xc1\xa5\xd1\x39\xa7\x57\xa8\xfc\x3a\xe4\x4b\x5c\x1f\x3c\xc6\xdc\x88\x0c\xb3\xeb\x03\x6a\xf6\x3f\x38\x2f\xe6\x29\x9a\x1c\x7f\xc0\xe9\xd7\xdc\x58\xf3\x3a\x6a\x84\xaf\x7d\x0a\x0d\xbd\x27\x15\x4c\x7a\xea\xeb\x52\x54\xcd\x8b\xa7\xa2\x6a\x2a\x9f\xb7\x7c\xf6\xea\x75\x89\x4e\xdc\x3e\x4a\xda\x15\x7d\xf3\x8b\xd5\xea\xf4\xfa\xa0\x1d\xff\x40\x97\xc4\x19\x95\x9b\x5e\x1f\xc0\x4c\xaf\xa7\xd7\x07\xdc\x6f\x7c\x1f\x07\x79\x7a\x7d\x40\x3d\xd1\x6b\xa3\x9d\x1e\xd5\xe3\xd3\xeb\x83\xd1\xd4\xa1\x1d\x3c\x1a\x18\xac\x06\x04\x98\xbe\x6e\x7b\xb8\x3e\x78\x43\x6b\x72\x72\x12\x42\x18\xe1\x92\xe2\x3f\x96\x3b\xab\x37\xca\xfd\x4d\xf9\x83\x43\x28\x84\x75\x2f\x8d\x50\x96\xfb\x7f\x29\xcb\x65\x2a\x0c\x82\x2d\xc7\xfb\x7d\xe5\x77\xc3\x32\x60\xe5\x67\xcf\x0d\x2b\x3f\xaf\xd0\x9e\xdb\x68\xae\xc5\x39\x6c\xe9\x75\x5e\xac\xd8\x26\x16\x12\x9e\x8b\x7e\x9a\x66\x7d\x48\x07\x84\xd2\x18\x0e\xbc\xd2\x16\x0f\xf2\x8d\xd3\x86\x78\xdd\x42\xca\x57\x6b\xe0\xdf\x85\xc3\xb0\x50\xab\x0c\x4d\xc1\xc1\xaa\xb6\x55\x1f\x09\xc9\x12\xf0\x7e\x03\xd1\x78\x69\x6e\x68\x23\xb1\x76\x52\x1d\xe7\x35\x8f\xab\x69\x91\x64\x47\x38\x0f\xec\x9b\x61\x45\x97\xa6\x58\x39\xd6\x74\xfb\x87\x98\xa1\xe3\x54\x21\x64\x35\x74\xab\xd9\x23\x30\xc7\x96\x84\x0f\xa5\x7d\x7c\x7f\x52\x97\x82\x54\x87\xc8\x68\xbc\xed\x37\x6f\xbe\x79\x73\xcb\x8b\x54\x1f\x14\xf2\x3e\xfe\xb8\x0e\x81\xd4\x41\x91\x88\x26\xf1\x7b\x83\xc7\x64\xab\xc9\x97\xe2\xed\x8f\xa8\x72\x37\x39\x85\x2f\x3e\xff\xcf\x2f\xff\xba\xa2\xa0\x17\x8c\x98\x7d\x8f\x2a\xf8\x82\xb6\x24\xc3\x62\xc5\x79\xa7\x61\x42\x52\x29\x13\x4e\x24\x79\x5b\xa6\x71\x72\xb7\x1c\x74\x27\x2c\x1b\x34\x5e\x5d\xd6\x15\xd1\xe5\x09\x27\xaa\x58\x27\x54\x8a\x03\x02\x49\x4b\x1b\x93\x8d\x00\x2f\xa6\xf0\xe8\x73\x7f\x99\x3f\x77\xbd\x20\xbe\x5f\xbd\x7d\x9d\x2c\x19\xb2\xb4\xf0\xb7\xc1\xdc\x78\xa4\x05\x5a\x2a\x3d\x66\xc6\xf1\x26\xa6\x41\xaf\x09\xa3\x33\x60\x51\x13\x62\x33\xde\x4d\x0b\xb7\xc9\x1f\xb8\x9d\x2f\xb0\x94\x4a\x96\x75\x79\x0a\x0f\x57\x14\xf1\x22\x6d\xcb\xd5\xf4\x85\x5b\x20\x20\x48\x74\xe5\x46\x94\x25\xa7\xa4\xc9\x0c\x95\x93\x63\xc9\x49\x03\x0d\x6b\xb3\xb9\xef\x2b\xc6\x1c\x94\x86\x8a\x9c\x9e\x42\x72\xa8\xc3\xec\x97\x1e\xe7\x18\xd6\xc0\x21\x7a\x93\x76\x05\xd4\xb4\x42\xbf\x1b\xbc\x01\x03\xf8\xb6\xf2\x50\xb5\x13\x86\x28\x51\x28\xa9\xf2\x98\xf6\xd2\xfe\x47\x0e\xf4\xf1\x6e\x82\x21\x7a\x8e\xdd\x58\x50\x4a\xc6\x52\xc6\x76\x93\x80\xbc\x16\x46\x28\x47\x66\xec\xd9\xe5\x85\xc7\xe8\xf3\x3e\x4d\x42\x8e\x25\x16\xe7\xc2\x62\xdc\x8d\x7e\xab\x7a\x61\x15\x6f\x15\x68\xb2\x64\xdf\xd9\x56\x7d\xf4\xf0\xf3\xb5\x4b\xde\x94\x5b\x1d\xc2\x13\xce\xa1\x51\xa7\xf0\x3f\xaf\xce\x86\xff\x12\xc3\xdf\x5e\x1f\x85\x3f\x1e\x0e\xff\xf6\xbf\x83\xd3\xd7\x9f\x75\x7e\xbe\x3e\xfe\xf6\xff\xaf\x68\x69\x39\x98\x5f\xc1\x3e\x41\x89\x44\x9c\x18\x57\x74\x10\xb3\x54\x5e\x9a\x1a\x07\xf0\x44\x14\x16\x07\xf0\x93\x62\xd5\x70\x4f\xa2\xad\x8f\x50\x93\x56\x3e\xa0\x5e\x57\x45\xca\x43\x11\x1e\xd2\xfa\x32\x61\xb8\xeb\xcc\xd7\xed\x88\x14\x5d\x0d\x1d\x49\xa3\x3a\x7c\xe6\x53\xf3\xc6\x5a\x27\x01\xe1\x26\xa9\x2e\x4f\x9a\xef\x1e\x5a\x3f\x15\x6a\x0a\xad\x58\xf3\xa0\x74\x9e\xd3\xad\x23\xd9\x24\x52\xa3\xad\x6d\xcf\xcb\x43\x21\x6f\x10\xce\x5a\xbb\x91\x84\xe5\x08\x53\xc1\x58\xdc\x8c\xa4\x33\xc2\x3b\x7d\x23\xae\x6c\x3d\x4a\xe3\xba\x80\x23\x32\x57\x13\x4e\x24\x5b\x90\xae\xe1\xee\x0d\x31\x92\x05\xff\x17\x08\x64\x4a\xa7\x5a\x8d\x0b\x19\x4c\x80\xb2\xd2\xc6\x09\xe5\x62\x82\x70\x8e\x6f\xfd\xff\xba\xe2\xc3\x0e\xd2\xc2\x51\xa6\xec\xa3\x47\x9f\x7f\x71\x55\x8f\x32\x5d\x0a\xa9\x9e\x94\xee\xe4\xf8\xdb\xa3\x5f\x6b\x51\x70\x94\xf7\x99\x28\xf1\x49\xe9\x56\xff\xff\x15\x3b\xab\xc5\x47\x5f\x6e\xb1\x8b\x8e\x5e\xf9\xbd\xf2\xfa\xe8\xd5\x30\xfc\xf5\x59\x7c\x75\xfc\xed\xd1\x75\xb2\xf6\xfb\xf1\x67\x34\x87\xce\x0e\x7c\xfd\x6a\xd8\x6e\xbf\xe4\xf5\x67\xc7\xdf\x76\xbe\x1d\x2f\xdb\x8c\x6f\x87\x6d\xaa\xc8\x90\xac\x80\x61\x29\xaa\xe1\x0d\x4e\x57\x6c\xce\x95\x70\x74\xb1\x21\x4f\xb1\x52\x54\xcb\xac\xef\xb1\xcc\x9f\x8a\xea\x05\x8e\xd1\xa0\x4a\x97\x32\xf9\x3d\x23\x30\x64\x3f\xac\xf9\xc4\x19\x58\x7b\x78\x9d\x48\xef\x78\x4f\xdb\x3a\x38\xbd\x05\xb7\x6c\x87\x1f\xd5\x9a\xfc\xc5\xcd\x29\xa6\x71\x9e\x7b\xb7\x10\xf7\xf7\xcf\xde\x7f\xb4\x77\x3b\xb5\x5c\x69\x69\xcd\xfa\x30\x2f\x1e\x7b\xe8\xcb\xa2\x87\xe1\xdc\x44\x93\x9d\x57\x2b\xf9\x6b\x8d\x70\xf1\xb8\x39\x9a\x26\x55\x5a\xd4\x7c\x19\xce\x4f\x3f\x5d\x3c\x26\xfb\xfd\x1f\x41\xdc\xdc\x21\x64\x5a\x1d\x3a\x78\xfe\xec\xc7\xff\x66\x67\x00\x97\x18\x78\x85\x1e\xce\xc7\x14\x52\x78\x37\x59\x50\xc0\xf0\x0f\xf4\x79\x72\xdc\x73\x2a\xaa\xc6\x7f\xc2\xe2\x8e\x33\xac\x8a\x8a\x00\xc4\x0d\x82\xad\x4d\x18\x1d\x35\xec\x23\xbe\x9c\x45\x1f\xe2\xc1\x39\xf2\x59\xba\x71\x21\xdc\xea\x7c\xe1\xb5\x44\x4b\xb5\x52\x98\x72\xd0\x9c\x50\xe0\x7b\xd8\x1f\xc4\xc8\xcf\x03\x66\xe5\x3e\xf6\xd8\x0c\x21\xa0\xb6\x37\x5b\xd0\x18\xce\xfd\x4c\xdf\xfb\x4e\x5a\x98\xef\x5e\x3d\x7a\x7f\x26\x47\x36\x5f\x6c\xf0\x3f\x2f\xa4\x71\xcd\x9a\xce\x33\xde\xc3\xe0\x5b\x6d\x82\xa3\x13\x61\x61\x84\xa8\xd8\x9d\xeb\xbd\x7f\xa8\x02\xd7\x61\xeb\x88\xad\xab\xa1\xd3\xc3\x6c\xf9\xe2\x6d\xa0\xdc\x66\xaa\xad\xb1\x5c\xe7\x4e\x99\xee\x6a\xa8\xde\x4d\xa6\xcb\x68\x60\xdb\x4b\x77\x1a\x0c\xb2\xeb\xc4\x56\x1b\x26\x73\x5e\x5d\xb6\x2c\x82\x53\x23\xd8\x19\x8b\x43\x22\xeb\x71\xc6\xb3\xe1\x34\x47\xf3\x66\x3d\x7b\xbb\x8f\xd1\x2f\xf3\x15\x9a\x5b\xb9\x97\xf2\xdb\xb4\x31\x53\x9f\x67\x72\xf6\xfe\xb7\x15\x41\xaf\xbd\x3b\x61\xd7\x5f\xaa\x37\x84\x6f\xd6\xe6\xbf\x33\x05\xd7\x65\xf9\xef\xd2\xc6\xae\xca\xd2\x4b\x93\x53\x3e\x71\x11\x5f\x39\x6d\x38\xe4\xde\x7d\x57\x8f\x1a\xa0\xdc\xb6\x1e\x6c\x20\xf8\xfd\x8f\x07\xff\x17\x00\x00\xff\xff\x25\x01\x0e\x3b\xe7\xe7\x00\x00") func operatorsCoreosCom_catalogsourcesYamlBytes() ([]byte, error) { return bindataRead( @@ -105,7 +105,7 @@ func operatorsCoreosCom_catalogsourcesYaml() (*asset, error) { return a, nil } -var _operatorsCoreosCom_clusterserviceversionsYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xfd\x7b\x77\xe3\xb6\xb5\x30\x8c\xff\xdf\x4f\x81\xe5\xe4\x3c\xb2\x1b\x49\x9e\x69\x7b\xfa\x6b\xe7\xd7\xf7\x64\xf9\xd8\x4e\xe2\x37\x33\x1e\x2d\xdb\x99\x3c\x5d\x49\x4e\x0a\x91\x5b\x12\x6a\x12\x60\x01\x50\xb6\xfa\xe4\xf9\xee\xef\xc2\x06\xc0\x8b\x2e\xb6\x44\x72\xc6\xb2\x07\xe8\x5a\xcd\x58\x24\x41\x70\x63\x63\xdf\x2f\x34\x63\x1f\x40\x2a\x26\xf8\x1b\x42\x33\x06\xf7\x1a\xb8\xf9\x4b\x0d\x6f\xff\xa2\x86\x4c\x1c\xcf\x5f\xff\xee\x96\xf1\xf8\x0d\x39\xcd\x95\x16\xe9\x15\x28\x91\xcb\x08\xce\x60\xc2\x38\xd3\x4c\xf0\xdf\xa5\xa0\x69\x4c\x35\x7d\xf3\x3b\x42\x28\xe7\x42\x53\xf3\xb3\x32\x7f\x12\x12\x09\xae\xa5\x48\x12\x90\x83\x29\xf0\xe1\x6d\x3e\x86\x71\xce\x92\x18\x24\x4e\xee\x5f\x3d\x7f\x35\xfc\xcb\xf0\xd5\xef\x08\x89\x24\xe0\xe3\x37\x2c\x05\xa5\x69\x9a\xbd\x21\x3c\x4f\x92\xdf\x11\xc2\x69\x0a\x6f\x48\x94\xe4\x4a\x83\x54\x20\xe7\x2c\x02\xf7\xbc\x1a\x8a\x0c\x24\xd5\x42\xaa\x61\x24\x24\x08\xf3\x9f\xf4\x77\x2a\x83\xc8\xac\x62\x2a\x45\x9e\xbd\x21\x6b\xef\xb1\xf3\xfa\xc5\x52\x0d\x53\x21\x99\xff\x9b\x90\x01\x11\x49\x8a\xff\x76\x40\xb0\xaf\xbf\xb6\xaf\x77\x90\xc3\xeb\x09\x53\xfa\xfb\xcd\xf7\xbc\x65\x4a\xe3\x7d\x59\x92\x4b\x9a\x6c\xfa\x10\xbc\x45\xcd\x84\xd4\x97\xe5\xb2\xcc\x32\x22\x35\xaf\xfe\xdb\xdd\xc8\xf8\x34\x4f\xa8\xdc\x30\xdb\xef\x08\x51\x91\xc8\xe0\x0d\xc1\xc9\x32\x1a\x41\xfc\x3b\x42\xfc\xbb\xec\xe4\x03\x42\xe3\x18\x37\x92\x26\x23\xc9\xb8\x06\x79\x2a\x92\x3c\xe5\xc5\xcb\xcd\x3d\x31\xa8\x48\xb2\x4c\xe3\x66\xdd\xcc\x00\xa1\x46\xc4\x84\xe8\x19\x90\xd3\xeb\x0f\xc5\xad\x84\xfc\x53\x09\x3e\xa2\x7a\xf6\x86\x0c\xcd\x06\x0c\x63\xa6\xb2\x84\x2e\xcc\x12\x2a\x77\xd9\xdd\x3c\xb3\xd7\x2a\xbf\xeb\x85\x59\xaf\xd2\x92\xf1\xe9\x43\xef\x77\x1f\xb1\xdd\x12\xe6\x95\x7d\xaa\xbe\xfe\xc3\xca\xef\xdb\xbe\xde\x7f\x3e\x35\x6f\x26\x7a\x46\x35\xd1\x33\xa6\x88\xe0\x40\x24\x64\x09\x8d\x40\x3d\xb0\xa0\x35\xb7\xd8\x15\x5d\xad\x5e\xd8\xb0\xa4\xea\x94\x9a\xea\x5c\x0d\xb3\x19\x55\xab\x20\x1e\x2d\xfd\xba\x66\x3a\x7b\xe3\xfc\x35\x4d\xb2\x19\x7d\xed\x7e\x54\xd1\x0c\x52\x5a\xe2\x80\xc8\x80\x9f\x8c\x2e\x3e\xfc\xf1\x7a\xe9\x02\xa9\x43\x67\x2d\xf6\x13\xa6\x0c\xa8\x90\x82\x10\x4f\x42\x70\xef\x16\x19\x90\x7f\xac\x7d\xe6\x3a\x83\xe8\x1f\xc3\x95\x95\x8b\xf1\x3f\x21\xd2\x95\x9f\x25\xfc\x2b\x67\x12\xe2\xea\x8a\x0c\x80\x3c\x59\x5a\xfa\xd9\xc0\xbf\xf2\x53\x26\x0d\x59\xd0\x95\x23\x6f\x47\x85\x2e\xd6\x7e\x5f\xfa\xda\x9e\x01\x89\xfb\xc6\xd8\x90\x44\x50\x88\x8f\x0e\xe3\x20\x76\x70\xb4\x78\xca\x94\x41\x0e\x09\x0a\xb8\x25\x92\x88\x42\xdc\x7d\xd3\x90\x18\x00\x80\x54\x86\x00\xe4\x49\x6c\x68\xe7\x1c\xa4\x26\x12\x22\x31\xe5\xec\xdf\xc5\x6c\x8a\x68\x81\xaf\x49\xa8\x06\xa5\x09\x9e\x5a\x4e\x13\x32\xa7\x49\x0e\x7d\x42\x79\x4c\x52\xba\x20\x12\xcc\xbc\x24\xe7\x95\x19\xf0\x16\x35\x24\xef\x84\x04\xc2\xf8\x44\xbc\x21\x33\xad\x33\xf5\xe6\xf8\x78\xca\xb4\xa7\xfa\x91\x48\xd3\x9c\x33\xbd\x38\x46\x02\xce\xc6\xb9\x21\x9c\xc7\x31\xcc\x21\x39\x56\x6c\x3a\xa0\x32\x9a\x31\x0d\x91\xce\x25\x1c\xd3\x8c\x0d\x70\xb1\x1c\x29\xff\x30\x8d\xbf\x90\x6e\x93\x55\x6f\x09\x7c\x6b\xd1\x99\x78\x02\xfb\x20\xac\x0d\x79\xb5\x98\x64\x1f\xb7\xdf\x52\x82\xd4\xfc\x64\xa0\x72\x75\x7e\x7d\x43\xfc\x02\xdc\xb9\x44\x08\x97\xb7\xaa\x12\xd8\x06\x50\x8c\x4f\x40\xda\x3b\x27\x52\xa4\x38\x0b\xf0\x38\x13\x8c\x6b\xfc\x23\x4a\x18\x70\x4d\x54\x3e\x4e\x99\x56\x88\x73\xa0\xb4\xd9\x87\x21\x39\x45\xa6\x47\xc6\x40\xf2\x2c\xa6\x1a\xe2\x21\xb9\xe0\xe4\x94\xa6\x90\x9c\x52\x05\x1f\x1d\xd4\x06\xa2\x6a\x60\xc0\xb7\x3d\xb0\xab\x3c\x7b\xf5\x81\x95\x33\x46\x88\xe7\xa5\x1b\x77\x67\xe3\x19\x26\x31\x44\x09\x95\x56\x28\x20\x1a\x92\x84\xbc\x7f\xfb\x8e\xcc\xc4\x9d\xc1\x62\xc6\x95\xa6\x49\x82\xa7\xc0\xf1\x67\x4b\x4e\x23\xca\x49\x4a\x39\x9d\x02\xa1\x59\xa6\xc8\x44\x48\x42\xc9\x94\xcd\x81\xfb\xd3\x35\xdc\x76\xf1\x9b\x88\x04\xb1\xc4\x7d\x2d\x83\xf2\x57\xdd\x02\x97\xae\x6c\x22\x1b\x66\xac\xc8\x40\x0f\x40\xed\xa4\xbc\x17\x31\x9b\x93\x9c\x2b\x2d\x73\xdc\xec\x98\xdc\xc2\xc2\x21\x79\x4a\x33\xa2\xb4\x30\x3f\xde\x31\x3d\x23\xb4\x8a\xe0\x54\x23\x16\x8f\x81\x28\xd0\x64\xbc\x20\x46\x8c\x43\x82\xa0\x85\x48\x90\x5a\xe0\xb3\x48\x18\x24\x68\xc9\x60\x0e\x84\xca\x31\xd3\x92\xca\x45\x81\x0d\xcb\x00\x7d\x04\xa8\xf8\xb1\x15\xe1\x61\x33\x48\xc8\x43\xb8\x48\x2c\xb9\x75\xb2\x4b\x5c\x08\x96\x5b\x40\x6f\x74\xe1\xf0\xad\x14\x47\x95\xc3\x37\x50\xc4\xe0\x95\x93\x0f\x0a\xb9\x16\xdf\xe4\x10\x2b\x26\x42\x16\x98\x61\xc0\x56\x45\xc2\x31\x18\x72\x22\x29\x37\x17\xd6\x22\x77\x03\x68\x3d\x84\x36\x66\x88\x3b\xbe\x0e\x47\xab\x73\x53\x29\x6b\x02\x53\x75\x30\x0d\xe9\x86\x99\x1f\x84\x5d\xf1\xb3\x59\xe0\x9c\xc5\x60\x80\xa8\x29\xb3\xa8\x63\x4e\x2b\x1d\x8b\x5c\x5b\xd8\xb9\x5b\x62\x32\x67\x94\xd0\xe9\x54\xc2\x14\x11\x78\xe3\x6b\x1f\x81\x89\x1d\x9b\x0f\x68\x39\x06\x56\x92\x7f\xf0\x0e\x43\x06\x1f\xbc\x81\xaf\x3b\xe6\xd5\x1b\x56\x85\xc5\xfa\x78\x6c\x0f\xed\xa0\x91\x81\x89\x07\xad\x90\x0f\xde\xbc\xcd\xde\xda\xf1\xc8\x0e\xdb\x51\xdf\xe7\xa5\x85\xb8\xab\x63\x73\x3e\x4a\xd2\x6c\xc8\x01\xde\x58\x12\xdf\x31\x90\x0c\xe4\x44\xc8\xd4\x1c\x14\x4e\x28\x89\xac\xfc\x56\x10\x1e\x24\x8d\x3c\x7a\x08\x9c\x64\xdb\xfd\xb7\x63\x1b\x2c\xb0\x63\x40\x32\xaa\x67\x8f\xdc\xb6\xdd\x56\xd9\x51\x05\xda\xa3\x37\x3f\x42\xcd\x56\xe6\x2e\x39\x4c\xe7\x73\x1b\x30\x74\x3e\x29\xf2\x9c\x6d\x66\xad\xa1\xda\x15\xbd\x7b\x07\x4a\x19\x96\x8d\x52\x9a\xa4\x77\x04\x78\x24\x0c\xb1\xf8\x7f\xaf\xdf\x5f\xda\x69\x87\xe4\x42\x13\x96\x66\x09\xa4\x46\x10\x23\xef\xa8\x54\x33\x9a\x80\x44\xee\xf4\x03\x4f\x6b\x7f\x3b\x4c\xcc\x15\xc4\x86\x16\xc5\x90\xd0\x85\x9d\x2c\x86\x48\xc4\x86\x46\x0b\x49\x32\x23\xe0\xa6\x59\xae\x81\x50\x7b\x15\xdf\xcb\xf8\x74\x1d\x91\x6e\x05\x1a\x62\x24\x91\x94\xea\x37\x64\xbc\xd0\x8f\xa1\x3e\x21\xf7\x83\x78\x5b\x1a\x50\x5d\xcc\xe3\x94\xc0\x8e\xad\xe8\x41\x75\xe2\x47\xbf\xd2\x08\xa1\x94\x71\x90\x23\x21\xf5\x36\x44\xcb\x28\x1f\x53\x90\x0f\xde\xe9\x41\xc6\xb8\xfe\xe3\x1f\x1e\xb8\x33\x86\x2c\x11\x0b\x83\x17\x8f\x9f\x95\x2d\xbf\x67\xeb\x73\xbd\xed\x7c\xdb\x9e\xe5\x2d\xe7\xb3\xc6\xa9\x2e\x66\x5a\xa7\x40\x35\x9a\x88\x77\xf5\x6d\x85\x12\xf8\x64\xcc\x6f\x74\xe1\xad\x0d\x57\x30\x01\x09\x3c\x72\xb4\xe9\xfb\x7c\x0c\x92\x83\x06\x55\x11\xa4\x17\x99\xa3\x34\x46\x16\x5c\x66\x77\x4f\xc3\xe5\x1e\x91\x67\xfc\x6d\x8f\x48\x35\xfe\xb6\xc7\x64\x1b\x3b\x76\x61\x9b\x8f\x23\x9d\x1d\x3b\xd1\xd8\xc7\x11\xb0\xc1\xa4\xf3\xf5\xe6\x9c\x16\xf3\x1a\x9d\x78\x0f\x24\xbc\xeb\xda\x32\x6a\xf2\xdd\x84\x41\x12\x13\x66\x84\x37\xb3\x58\x32\x4e\x44\x74\xeb\xec\x96\x57\x67\x44\x09\x2b\xee\x19\x09\xdf\x30\xda\x48\x70\x95\xa7\x40\xd8\x63\x18\x1c\x44\xba\x20\xd2\x05\x91\xee\xb9\x88\x74\xd6\x3f\xb0\x0f\x94\x6a\x69\x21\x1b\x69\x15\xde\x17\xa8\xd5\x43\x23\x50\x2b\x1c\x81\x5a\x3d\x32\x9e\x1d\xb5\xda\x4a\x4e\x7b\x74\xae\xc7\x0e\x72\x30\xa6\x06\x63\x6a\x30\xa6\xba\x11\x78\x99\x1b\x81\x97\x05\x5e\x16\x8c\xa9\x0f\x4d\x19\x8c\xa9\x3b\x4e\x14\x8c\xa9\xc1\x98\x1a\x8c\xa9\xc1\x98\xfa\xd8\xc7\x04\x91\x2e\x88\x74\x41\xa4\xdb\x76\x31\xc1\x98\x1a\x8c\xa9\x0f\x8d\x40\xad\x2a\x23\x50\xab\x07\xc6\xcb\xa6\x56\xed\x8d\xa9\x51\x02\x94\xaf\x57\xaa\x96\xe2\xbf\xf1\x3e\x14\x8d\xd8\x84\xb9\x3c\x08\xf7\x34\x19\xc3\x8c\xce\x99\xc8\x25\xb9\x9b\x01\xf7\x29\x3b\x64\x0a\x5a\x19\x2c\x00\x0d\xeb\x04\xf3\x47\x68\xcd\xc3\xf4\x65\x40\x80\xd3\x71\xb2\x76\xe2\xc7\x48\x89\x7b\xf2\x61\xe3\xf1\x58\x08\xf3\x75\xab\x10\x43\x55\xc7\x6b\x3a\xbb\xc4\x33\x1f\x6c\xca\xb1\x5b\x1f\xd4\x7c\x7a\x75\xd6\x55\x28\x33\xf9\x99\x93\x8b\x62\x56\x82\x96\x69\x4c\x94\x30\x3c\xc4\xfc\xfa\xfe\x8e\x43\x8c\x49\x6e\x7d\xc2\xb4\xb9\xc1\x1c\x7a\x16\x31\x9d\x2c\x8a\x17\x0f\x0f\x76\xdf\xc4\x3d\x0a\x89\x3e\xbd\x3a\xdb\xde\x7c\xef\x37\xe0\x53\x58\xea\x83\x1d\x3e\xd8\xe1\x8b\x11\xc4\xa0\x86\x93\x06\x31\xe8\x81\xf1\xb2\xc5\xa0\x7d\xb7\x5b\x07\x6b\x33\x09\xd6\xe6\x87\x6f\x0b\xd6\xe6\x60\x6d\x0e\xf6\x9b\x0d\x23\x08\x2e\x38\x82\xe0\xf2\xc8\x78\x76\x82\x4b\xb0\x36\x07\x6a\x15\xa8\x55\xa0\x56\xcf\x83\x5a\x3d\xc7\xd0\xdd\x60\xf4\x0b\x46\xbf\x60\xf4\x0b\xdc\x28\x70\xa3\x47\xc6\xb3\xe3\x46\xc1\xe8\xb7\xeb\x44\xc1\xe8\xb7\x76\x04\xa3\xdf\x23\x23\x18\xfd\x82\xd1\x6f\xc3\x08\x82\x4b\xc3\x49\x83\xe0\xf2\xc0\x78\xd9\x82\x4b\x30\xfa\x05\x6a\x15\xa8\x55\xa0\x56\xcf\x83\x5a\xb5\x37\xfa\x3d\x72\x92\x1e\x7e\xf6\xe1\x93\xf2\xe0\xb3\x2c\x7a\xe8\x85\x9b\x20\xfa\x00\x04\x1f\x25\x5c\x8f\x91\xab\x01\x19\x53\x05\x7f\xfe\xd3\x4a\xdd\xf2\xea\x2d\x29\xc4\x8c\x9a\x57\xad\xbd\xe3\x71\x12\x56\xbe\x62\xf3\x9e\x6d\xb1\xf7\xc5\x32\x1a\xce\xe2\x0a\x2b\x3f\x1a\x14\x6b\xb6\x36\xbe\xb0\x37\x5f\x6b\x49\x35\x4c\x17\x95\x42\xde\x68\x93\x2d\x39\x0f\xdf\x50\x80\xbe\x50\x1a\xef\x66\x20\x01\x1f\xf2\xa5\xa7\x95\x9f\x94\xa9\x22\x7a\x39\x6e\x50\xdc\xf7\xb1\x70\x64\xff\x9e\x35\x97\x1f\xdb\xb4\x75\xd5\xb7\xd7\x02\xcb\x03\xe8\xcc\x5a\xaf\xcf\x8a\x14\xe0\x65\x88\x65\x54\x1a\x0a\xe9\xad\xdc\xc8\xb4\x2b\x77\x2f\xc1\x7b\x13\x51\xdc\x82\x53\x3f\xce\xa1\x07\x95\x4c\xe5\x4d\x96\xf5\x6d\x18\xb3\xeb\x81\x31\x02\x99\x32\xa5\x36\x05\x5c\xd7\x97\xfe\x18\xd9\xdc\x82\x5c\x6e\x80\xbf\xff\xa2\xca\x72\x0a\xf1\x09\x77\x40\x8e\x69\x44\x64\x9e\x18\x61\x8a\xc7\xc4\x95\xbf\x26\x34\x8a\x44\xce\x35\xe1\x00\xb1\xb5\x6c\xac\xc3\xd5\x2d\x88\xed\x16\xf2\xd3\xb6\xd2\xd3\xc0\xae\xf3\xd1\xbb\xdc\x37\x9c\xd8\x4f\x58\x5b\x50\xbd\x3a\xb6\x97\xb6\xf0\xf5\x8f\x73\xad\x5d\x58\xe1\xd6\x8c\xb0\xb6\xbf\x23\x91\xb0\x68\x71\x95\x27\x40\x66\x22\x89\x15\x96\xf5\x37\xdc\xbd\x70\x38\x54\x45\xe4\x0c\xef\xc6\xd5\xf7\xc9\x38\xd7\x24\x16\xa0\x08\x17\xda\x17\x06\xa8\x3d\x6e\x5d\x4c\x77\x33\xdb\xda\xc1\x3c\x44\x68\x96\x25\x98\x4a\x21\x8c\xd0\x72\x37\x63\xd1\xcc\xf6\xab\xc9\x68\x04\xeb\x6e\xdb\x5e\x7a\xd9\x4a\xbc\x26\x3b\x89\xd8\xc4\xdb\xac\xc6\x8f\xa1\x0a\xd9\x51\xd6\x26\xb6\x44\xfc\xb7\x52\xe4\xd9\x96\xb7\xaf\x5a\x16\xed\xd3\x86\xca\xeb\xa5\x06\x36\xfe\xa2\x73\x19\xd9\xbd\xb1\xb7\x15\x26\xd1\x21\x21\x17\x13\x92\xe6\x89\x66\x59\x82\x8f\xd8\x6a\x03\x8a\x50\x09\x25\xdf\xe8\x13\xca\x17\xde\x03\xe5\xda\x44\x40\x4c\xe8\xd4\xcc\xa8\xb1\x3f\x8c\x2f\x49\xcf\xf3\x14\xcc\x69\x8e\xcb\x97\xa0\x3a\xc5\x17\xe5\xec\xe4\x8e\x25\x89\x91\x67\x69\x92\x88\xbb\xf5\x6c\x69\xdd\xd8\x4d\x28\x24\xbb\x09\x86\x64\x77\x11\x98\x10\x2e\xb8\x37\xed\xfe\x70\xf5\xb6\xd9\x26\x5e\xd6\xe7\x70\xbd\x40\x40\x1b\x90\x66\x54\x6a\x46\x13\x92\xcb\x44\xd9\x7d\xa4\x46\x09\x90\xbe\x99\xca\x8c\xa2\x67\x30\x02\x65\xbb\x76\x90\xdf\xdb\x9d\x73\x80\xb5\xe7\x53\xf0\x64\x41\xa8\xdd\xf9\x49\x9e\x24\x7d\x32\x61\x9c\x1a\xb2\x0b\x99\xcf\x84\x31\xfa\x13\xb9\x66\x3c\x02\xf3\x4d\x83\x42\xb0\xc0\x15\x99\x19\xcd\xf9\x2e\x0e\x69\xdc\x77\x6d\x45\xac\xb6\xac\xdc\x2b\xcc\x81\x8d\xe8\x38\x01\xec\x6b\xe1\x44\x96\x2b\x91\xa0\x79\xdb\x19\xbe\x63\xdb\x8b\x84\x56\x2f\xff\x37\xe3\xa8\xa4\x90\x2b\x64\x1c\x46\xd9\x01\xa6\x67\x46\xf7\xc9\xb2\x64\x61\x08\x85\xc1\x9d\x12\xa1\x0e\x55\x1e\xcd\xcc\x27\x1d\x64\x22\x56\x07\x86\x8c\x1c\x28\x88\x24\x68\x75\x70\x64\xfe\x5a\xfe\x06\xfc\xbe\xea\x73\xc7\x34\x63\x07\x47\x7d\x82\x00\xc2\x46\x27\x42\xcf\x9e\x2f\x1e\xfa\x6f\xad\xf5\xd7\x7a\x6c\xd4\xb5\xd6\xea\x0c\xae\x6b\x87\xc8\x6c\x13\x0c\x43\xa3\x35\x60\x9e\x94\x41\x4a\x44\x03\xdf\x1e\x6a\x95\x58\x13\x72\xc2\x09\xa4\x99\x5e\x20\x16\xa7\x40\xb9\xbb\x1b\xe6\x20\x17\x7a\x66\xb4\x55\xa6\x9e\xff\xe1\xdf\xd2\xb1\x54\x8e\xb5\x00\x77\x07\xde\x03\xb7\x44\x72\xdb\x59\x69\x19\xb8\xbd\xdf\xf7\xaa\x52\xaf\x11\x9f\x4a\x6a\xfe\x6c\x41\x89\xec\xb5\x11\x18\x3f\x98\x27\xeb\x20\xb4\x3f\x59\x6a\x59\xd0\x8f\xb7\x6f\x6d\x17\x25\x07\xab\xef\x19\x8f\x55\x51\xc9\x28\xb6\x64\xd0\xc1\x7b\x2d\x90\x71\x85\xcf\x11\xc0\xab\xe2\xeb\xb6\x22\xe7\x23\xd3\x57\xf4\x9b\x7d\x50\x49\xb0\x2b\x53\x4d\xca\x31\x74\xaa\x6f\x5d\x4e\x46\x17\x49\xe8\x18\x12\xdb\x72\xc9\x5c\x2d\x97\x4f\x4e\xde\xbe\x2b\xba\x93\x49\xa0\x8f\xd8\xb3\x3e\x82\x22\xb2\x85\xe3\x74\xa5\xc7\xdb\xea\xd8\x5e\xf6\x44\x50\xec\x66\x0c\x26\xd7\xa0\xed\x31\x4b\x69\x66\x4e\x99\x9d\x63\xad\x2d\xf3\x2d\x42\xfa\xf1\xc3\xb2\x93\xcc\xbe\x7d\x4f\xa6\x75\x2f\xd9\xea\xa8\x6c\xe7\xf1\xdd\xe5\xec\x3d\x60\xe1\x28\x47\x0d\xcc\x4b\x08\xed\xe4\x7a\x27\x89\x47\x45\x7f\x3d\x8b\xc1\xca\x26\x46\xdb\x34\x74\xe9\x7f\x2f\xa7\xe8\x78\x0b\x76\x51\x9a\x8c\xde\x9c\x40\xa4\xc5\xc3\x65\xdf\xfc\xcd\x1a\xd2\x2c\x79\xec\xe4\x91\x9d\x15\xac\x94\xf1\x2b\xa0\xf1\xe2\x1a\x22\xc1\xe3\x2d\x09\x6c\x6d\x3f\xde\x31\xce\xd2\x3c\x25\x3c\x4f\xc7\x80\x20\x56\x76\x2e\x24\x24\x56\x79\xa5\x84\xc3\x5d\xb2\x70\xc4\x23\x26\x99\x88\x3d\x3d\x19\x1b\x65\x8b\xc6\x0b\xec\x6f\x86\x05\x52\xf9\xc2\x4c\xc2\x74\xc9\x7d\x24\x89\x24\x55\x46\x2c\xea\xe3\xa4\x4c\x1b\x8e\x35\x06\xf4\x2d\xb1\x18\xcc\x1e\xd3\x39\x65\x89\x11\xad\x87\xe4\x0c\x26\x34\x4f\xb0\x4d\x1f\x79\x45\x0e\xcd\xcb\xbc\x3e\xb5\xee\x01\x23\xee\x2a\x61\x34\x71\xe5\x72\xdc\x71\x41\x47\x3b\x58\xcb\xb7\xa9\xdf\xe7\xc7\xb6\x75\xfc\xfc\xc8\x68\xae\xb6\x55\xc3\x6b\x1b\x73\xc1\x63\x73\x1e\xaa\x92\x68\x85\xa4\x33\xe5\x66\xde\x8e\x65\x3f\x5c\xfb\x60\xcd\xaa\xa5\x98\x4a\x50\xea\x0c\x68\x9c\x30\x0e\xcd\xf1\xeb\x66\x06\x24\xa5\xf7\x88\x63\x9a\xa5\x60\x24\x91\x2a\x86\xd1\xea\x57\x69\x41\x52\x7a\x0b\xc5\xeb\xc9\x18\x26\xd8\x86\x11\x3f\xb8\xb2\xfb\x16\x7f\x26\x94\x25\x10\x0f\xf1\x1d\x95\x59\xca\xee\xc5\x16\x71\xcc\xdf\x8c\xe7\x60\x9e\xca\xa4\x40\x65\xd2\x3e\x5a\xe5\xf1\xc8\x43\xa9\xb9\xd9\xd2\x61\xdf\xb1\x6f\xb4\x04\x8a\xf3\xfb\xc8\x1a\xf9\x24\x50\x85\xb7\x59\xdc\x54\xb9\x9c\x18\xd5\xd1\x6b\x9c\x95\x05\xb9\x56\xaf\xe4\x52\x68\xd7\xf8\xaf\xf8\x40\x7c\xda\x35\xa2\x04\xa5\x59\x8a\x07\x2c\xce\xa5\x6f\x8b\x89\x30\xa3\xeb\xb7\xbe\x76\x54\xfe\xfc\xea\xd5\x96\xf2\xdb\xc7\x47\x7a\x09\xa8\x29\x37\xc1\x97\xcb\x82\x0e\x79\xf2\x6f\x54\x60\xb3\xc7\xcc\x89\xc1\xd8\xdf\x13\x24\xfa\x09\x99\xd2\x8c\x4f\x73\xa6\x66\x64\x0c\xfa\x0e\x80\x13\xb8\xb7\x15\x2e\xc8\xbf\x41\x0a\xdc\x54\x03\xde\xd2\x45\x50\x03\xda\xeb\xfd\x81\xd8\x9c\x29\x26\xf8\x77\x4c\x69\x21\x17\x6f\x59\xca\x1e\x29\x3d\xea\xc7\x6a\x97\xe3\x02\x82\x22\x89\xb1\x37\x31\x8b\xe8\x35\xd8\x0f\x96\x80\x16\x4c\x2d\xac\x7a\x4a\xcc\x39\x19\xd3\xe8\xf6\xa3\x01\xf8\xd5\xbe\x40\xd8\xb3\xeb\x06\x50\x45\x79\xaf\x98\x00\xc9\x96\x45\xca\xf3\x7b\x0b\x9f\x1a\x94\xef\x66\x42\x01\xde\x60\x8d\x8c\xf8\x98\x77\x0a\x30\x55\x10\x0c\x73\xba\x05\x07\x45\xe8\x64\x52\xbf\xa3\x3c\xec\x28\x79\xa6\xb9\xd2\x24\xa5\x3a\x9a\x59\x53\x96\x88\x0b\x71\xa2\xa7\x9c\xd8\xbf\x0b\x94\xb7\x36\x22\xef\x6e\xee\x25\x76\x9d\xe7\xf7\x46\xb7\x7c\xd4\x9b\x53\x1f\x35\x90\x2f\x4f\x53\xd7\x80\x93\xfa\x86\x38\xb9\x2d\xb5\x2d\x82\x6f\xd0\x00\x5c\xfe\x82\xbb\x70\x72\x79\xb6\xbd\x29\xa6\x89\x82\xbb\xb3\x8a\xbb\x6c\xea\x7e\xe0\xa3\xbc\xc9\xd4\x5d\xa9\xdb\xbb\x6d\x6b\xe8\x3e\xa1\xe4\x16\x16\xb6\x8b\xf4\x4a\x5b\x5e\x09\x89\x93\x24\x00\xbb\xd3\x9a\x9b\x5c\x4b\xe9\x1d\xd6\xbb\x33\xf6\xd8\xb1\x9b\x2b\xc2\x8f\x81\x59\xe8\x8e\x4f\xf8\x8f\xde\xe1\xb1\xdd\x11\xdc\x8e\x5b\x58\xec\xf6\xc0\xd2\x76\x9b\x5d\x70\xba\x8f\xdd\x77\xf3\x43\x21\xe8\x15\x5b\xbd\x9b\x8f\xa8\x3a\x76\x36\x51\xf9\xe1\x81\xd8\xea\xf3\x0a\xf4\xab\x5a\x99\xcc\x37\xf6\x94\x45\x46\x73\xa6\x67\x2c\x43\x46\xe4\x9d\x01\xbe\xc9\xf9\x07\x9a\xb0\xb8\x98\xc2\x9e\xdf\x0b\xde\x37\xe2\x93\xf9\x0f\x12\x5d\x2b\xae\x9d\x09\x50\x97\x42\xe3\x2f\x9f\x0c\x40\x76\x99\xad\xc0\x63\xa7\x70\x56\x68\xa4\x32\xa8\x78\x55\xfa\xa3\xab\xa1\xaf\xec\x55\x80\x92\x29\x72\xc1\x89\x90\x1e\x0e\xd8\xb1\xde\x4e\x64\xa7\x40\x3e\x31\xb6\x0e\x0e\xb4\x4f\xaf\x9d\xc3\x81\x4f\xc8\x1a\xf4\x1e\x98\xce\x4d\x85\xf2\x81\xbd\x62\x3b\xe2\x27\x28\xed\x3a\x51\x95\x7a\x27\x37\x8b\x48\x0a\x72\x8a\x1e\x97\x68\x6b\x8f\x43\x7d\x53\x76\xa3\xbb\x76\xec\x4c\x7d\xab\x2f\xdc\x09\x0b\x90\x35\x59\x13\x50\x1b\xe6\x66\x67\xa8\x99\x9c\xfe\x8f\xa1\xe0\xb8\x07\xff\x97\x64\x94\x49\x35\x24\x27\x44\x31\x3e\x4d\xa0\x76\xcd\x69\x18\xd5\x69\xcc\x0c\x4c\x11\x43\x6a\xe7\x34\x71\xba\x14\xe5\x04\xac\xcd\xca\xcc\xbe\xcc\x52\xfb\x4e\x52\x31\x94\xa7\x70\x74\x1d\xdc\xc2\xe2\xa0\xbf\x82\x34\x07\x17\xfc\xc0\xf2\x96\x15\x34\x29\x18\x11\xfa\xc8\x0e\xf0\xda\x41\x97\x5c\x78\x47\x86\xd3\xd4\x8e\x56\x7f\xe9\xd6\x18\xe1\x63\x3b\x1a\x0a\xeb\x35\x2d\xd1\x45\x34\x69\x41\x72\x05\x56\x5a\xc7\x53\x46\xc0\xcb\x99\x28\x55\xa2\x62\xca\xe1\x0e\xa5\xc7\xbd\x11\xfc\x8c\x26\xc1\xf8\xf4\x87\x2c\xa6\x7a\xab\xa0\x52\x3b\x6a\x10\xe9\x5d\xd9\x49\x48\x8e\xb3\x18\xdc\x9a\xb0\x29\xc9\xa8\xa4\xa9\x1a\x92\x91\xab\x6e\x88\x98\xc6\x26\x55\x5b\xa2\x83\xdd\xcd\x22\x03\xf2\xff\x90\xab\xea\x5a\x86\x64\x30\x18\x90\x9b\xf7\x67\xef\xdf\x10\xfb\x8b\x95\xb2\xb5\x20\x13\x81\x4a\x90\xc8\xa5\x79\xd5\x1c\x38\x2a\xfe\x46\xbe\x17\x1c\xde\x4f\xcc\x09\xa1\x1a\xe6\x20\xc9\x9d\xd9\xaa\x88\xc5\x50\x58\xaf\x86\xbd\x8f\x8b\xc7\xcd\x24\x93\x94\xde\x5f\xe7\x72\xba\xc3\x06\x90\x95\x4d\xa8\x9a\x6c\x4a\x65\x12\x51\xaf\x9a\x9d\xab\xa2\x19\xc4\x79\x02\x31\xa1\x63\x31\x87\x9a\xc9\xb6\xfe\x18\xb2\xf4\x1c\xfc\x83\x86\xe7\x8d\x95\x48\x72\x5d\x28\xab\x87\x70\xff\x86\xfc\x27\xba\xb6\x29\xc9\x40\x46\xc0\x35\x9d\xc2\xb2\x19\xc0\xde\xf7\xfa\xd5\x7f\x1c\x39\x7e\x64\x66\x74\xd6\x93\x57\x06\x23\xde\xd1\xfb\x1f\x78\x69\x1a\x64\x8a\xbc\x1a\x92\x93\xa5\x97\xe1\x73\x49\x94\x27\x68\x6b\x41\x77\x7d\xe5\x95\xe3\x05\x91\x22\x47\x87\x3d\xc9\xb3\xba\x36\xfb\x87\xff\xfc\x0f\xa3\xf4\xd1\x34\x4b\xe0\x8d\x2f\x8a\x6a\xd5\x66\x23\xc3\x68\x41\xfe\xf8\xea\x3f\x2c\xf5\x34\xe7\xb3\xd4\x0a\x4b\x98\x51\x03\xb0\x3c\x23\x2c\xb5\xa1\x98\x90\x2c\xca\xea\xaa\xb2\x8e\xfe\x4a\x53\xa9\x55\x9f\xa0\x57\xbf\x10\x0e\xb5\xd0\x34\x59\xd2\xf2\x51\x0b\x87\x3b\x0b\xa4\x58\x20\x4c\x00\x0d\x55\xe4\xf5\x1f\x5f\xfd\xc7\xaa\x39\xe5\x3d\x8f\x00\x9f\xc4\x27\x30\xcc\x62\x6c\x94\xfb\x5b\x96\x24\x10\xf7\x1f\x5d\xfe\x24\x97\x7a\x06\xb2\x4f\x80\x2b\x6f\xac\x32\xeb\x5b\x5a\x1b\xce\x2e\x73\xce\x51\x46\xb0\xd6\x61\xb4\x68\x55\x2c\x5c\xee\x63\x0d\x23\xd4\x24\x15\x4a\xaf\x5f\xf2\xf6\xc7\xcd\x0c\xca\x17\xef\x27\xbb\x8a\x03\x83\x06\x66\x88\xd5\xa7\x1b\x88\x94\xf7\x83\xdb\x22\x53\x72\xc0\xb8\x1e\x08\x39\xb0\xd3\xbc\x21\x5a\xe6\x8f\x7b\x0d\xca\x91\xd6\x4e\xc0\x27\x20\x03\x79\xe5\xbc\xad\xec\xea\x47\x39\xf9\xcd\xcf\x73\x2c\xee\xf8\x66\xca\x81\x84\xd3\xd1\x8c\x86\xa7\xbe\x6e\x71\x5b\x3a\x36\xe6\xed\xe6\xee\xff\xdf\x2a\x76\xef\x40\x0e\xdc\xd9\x2d\x4e\xbb\x91\xab\xd0\xe3\xd1\xdf\xe2\xed\xc5\xb1\xb5\x9c\xcf\xda\x9c\xcc\x0d\xf6\x35\x6b\x28\xd7\xca\x09\x5f\x43\x81\xec\x3a\x4a\x87\x8c\xc6\x88\x02\x73\xce\xd5\xc6\x83\x9e\x00\x55\x7a\x1d\x28\xc2\x41\x7f\x7c\x3c\x1c\xc0\xbf\x3c\xea\x42\xa7\x91\x90\x10\xe4\xa5\x8d\xf1\xd4\x22\xca\xc1\x15\x58\x0f\x9f\x0d\x38\xab\x09\x51\x07\xc5\x91\x30\xfb\x57\x97\xaf\x3e\x56\xd8\x8c\x37\x72\x36\x11\xad\xdd\xa3\x95\xc0\x5e\x67\x3a\x75\xc4\xab\xf0\x28\x5a\x97\xe6\xde\x48\xd1\x29\x68\xfa\x70\x92\xc7\xf2\xa8\x13\xed\x6b\x4d\x79\x4c\x65\xec\x56\xd9\xeb\xa9\x62\xca\x21\x79\x87\xbe\x34\x3e\x11\x6f\xc8\x4c\xeb\x4c\xbd\x39\x3e\x9e\x32\x3d\xbc\xfd\x8b\x1a\x32\x71\x1c\x89\x34\xcd\x39\xd3\x8b\x63\x74\xa0\xb1\x71\xae\x85\x54\xc7\x31\xcc\x21\x39\x56\x6c\x3a\xa0\x32\x9a\x31\x0d\x91\xce\x25\x1c\xd3\x8c\x0d\x4a\x99\x59\x0d\xd3\xf8\x0b\xff\xa2\x8f\x2c\x18\xd7\xce\x10\x5a\x97\xe4\x1c\x06\x39\xbf\xe5\xe2\x8e\x0f\x50\x93\x55\x3b\x9d\xa6\xed\xa2\x18\xfc\x58\x82\xf7\x2e\x81\x0b\x99\x88\x3f\xfa\x26\x98\x8f\x19\x50\x1e\x0f\xac\xd3\xf1\x23\xef\x45\x13\xdb\xee\xa0\x0c\x0c\xd8\x26\xe2\xdc\x8e\x66\xda\x10\x8d\x34\x9b\x43\x23\x27\xb6\x1f\xb5\xed\x7e\xef\x03\x46\xe3\x5c\xda\x1d\xaf\x78\xb3\xbd\x6f\x26\xa5\x0b\x94\x75\xf0\xdd\x44\x58\x56\xce\x45\x0c\xce\xf2\x39\x47\xd5\xfe\xda\x30\xf3\x1b\x23\x0a\x3b\x1f\x37\xda\x7d\x17\x4a\x43\x6a\x89\x93\x7d\x3e\x59\x10\x2d\x17\xd6\x31\x2e\x6f\x8d\xf2\xe9\x3c\xd7\x46\xe2\xbf\xc5\xfb\x94\x12\x11\x43\xd1\xa7\x84\xab\x97\xbb\xbc\x0d\x8f\x92\x4c\x28\x86\xef\x76\x3c\x6f\x37\xcb\x5c\x73\x76\x59\x71\xd3\xfd\xf9\x4f\xbb\x6c\xdd\x04\xdb\x28\xec\x68\x65\xaf\x47\x50\x4c\xaa\x11\xfe\x6e\x7b\x7a\xca\x2b\xae\x46\x2c\x89\x04\x57\x5a\x52\xb6\x39\x87\x69\xfd\x68\xe8\x0a\x69\xee\x6f\x20\x88\x41\x27\x8d\x80\x42\x56\x63\xb0\x3c\x53\x44\xb4\xf4\xa0\xae\x02\xc6\xa6\x38\xf9\x58\x42\x43\xb8\x1a\x9a\x56\x1b\xc0\x88\xb4\x82\x93\x7d\x1a\x26\x20\x25\xc4\x67\x28\x7d\x5e\x17\xdf\x75\x31\xe5\xa2\xf8\xf9\xfc\x1e\xa2\x7c\xdb\x4c\xf0\xd5\xb1\x62\xcb\xf3\x06\x11\x17\x76\x62\x17\x61\x8e\xae\xbf\xe0\xe4\x0f\x81\x60\x77\x82\x88\xa2\x9a\xa9\x89\xcd\x17\x2b\x36\x02\x2a\x8e\xcf\x02\x85\x0b\xf7\x30\xb2\x38\x9b\xfa\xc0\x34\x92\x9b\x68\x26\x84\x32\xa7\x1c\xf7\x13\xe7\x9d\x33\x61\x7d\x7e\x98\xbc\x22\x49\x6a\x68\x8c\x4f\x62\x29\xa7\xb7\x86\xda\xf2\x31\xa6\xac\x0a\x5e\x40\xd0\x7b\xa9\xcc\x34\x68\x78\x34\x7f\x4c\x51\x6a\x52\x9a\xa8\x3c\x35\x93\xde\x01\x9b\xce\xb4\xea\x13\x36\x84\x21\x62\x0d\xd0\x68\x56\x99\x36\x05\xd0\xb5\x2e\x28\x55\x54\xab\x5a\x89\x0f\x8b\xac\x06\x97\x86\xd3\x2f\x78\xcc\xf2\x5e\xae\x05\x57\x9f\x80\x8e\x86\x47\x7d\x52\x26\x8a\x9b\x35\x8e\x17\x84\x69\x30\x34\x1b\x75\x11\x29\xf2\xa9\xfd\x12\xf0\x31\x9d\xb8\xae\x22\xe5\x03\xbd\xa8\x31\xea\x8c\x07\xf6\xe3\x0e\xcc\xbe\xe1\xca\xf3\xd4\xe8\x8b\x05\x51\x47\xb3\xba\x6f\x9c\x23\xa4\x04\x95\x09\xab\x6d\x2e\x1b\xdc\xff\xff\xc5\x43\x87\xea\xa8\x04\xe6\x8c\x4d\x67\x1e\x96\xd4\x31\x82\xfa\x1e\xec\x7e\xf6\x48\x2b\x5f\x8a\x1d\x0d\x3d\x2a\x76\xd4\x7d\xdb\x3e\x5f\xa2\xc4\xaa\xca\xfe\x6b\x90\x69\x01\x45\x44\x11\x24\x19\xce\xce\xed\x1b\xd6\x38\x1c\x23\xaf\xc8\x21\x22\x19\xd3\x3d\x85\x08\x3f\x10\xd9\xd1\x90\x9c\x10\x9e\x17\x67\xee\xa1\x17\x70\x51\xcc\xef\x26\x32\x2f\x55\xa2\x9c\xab\xe1\x17\xb7\x22\x77\x76\x34\xf3\x94\x57\xc7\xc0\x41\x00\x1e\x2f\x8b\xf8\xd0\x24\x16\xd6\x0d\x27\x68\x47\xba\xfd\x1c\xfe\x2b\x9a\xcf\xb1\x12\x60\x81\xc7\xb5\x8c\xa2\x00\x99\xf6\xab\xd2\x53\x71\x20\xeb\xa7\xd8\xc2\xa2\x29\x56\x90\x6e\x30\x83\x74\x04\x57\xd2\x2a\x42\x67\xfd\x58\x0e\x63\xf1\x59\x54\x35\x68\xd7\x88\xfc\x78\x81\x57\x77\x0c\x5e\xda\x3c\xda\x52\xba\x72\xb4\xa2\x79\xe5\x78\x10\xf1\xf6\x2f\xb0\x67\xfd\xe8\x08\x6d\xed\x68\x4f\xda\xca\xb1\x7b\x68\xd0\xa6\x79\x1a\x04\x0c\xad\x1f\x5d\x9d\x4d\x3b\x1a\x04\x17\xad\x1f\x2b\x22\xea\xc7\x89\x35\x5a\x3f\x1a\x1b\x49\xd7\x8f\xa6\x71\x49\xeb\xc7\x52\xaa\xe2\x47\x0a\x52\xea\xd7\x23\x94\xc8\xb7\xda\x9e\xe3\xb7\xad\xf8\x49\x39\x3a\x06\x71\xb3\xc8\xa6\xf5\x63\x59\x00\x7c\x26\x51\x4e\x6b\xa6\xfa\x56\x9b\x69\xde\x6e\x7c\xd8\xe6\xa8\xfb\x38\x1d\xa7\x50\xf4\x5d\xea\x8c\xb7\x33\x63\x44\x75\x26\x01\xcb\x0a\x60\xd8\x97\xb7\xc3\x7c\x9a\xc0\xaa\xf5\xa3\x3b\xc6\x69\x47\x47\xec\xd3\x8e\xce\x90\x1b\x05\x9e\x6f\xac\x5d\xf8\x09\x65\x1d\x6b\x99\x0e\xb2\x4e\x90\x75\x76\x18\x41\xd6\xd9\x76\x04\x59\x67\xd3\x08\xb2\xce\x9a\x11\x64\x9d\x20\xeb\xb4\x1a\xfb\x27\xeb\x58\x4b\x55\x67\x06\xb3\x1f\xad\xc1\x75\xd9\x42\x86\xd2\x94\x0f\xe9\xa9\x9b\xca\x0c\xef\xbf\x76\x24\xf6\x06\xcd\x6b\x2e\x52\x5d\x52\x3e\x05\xf2\x7a\xf0\xfa\xd5\x96\xe9\x80\xeb\x47\x9b\xa0\x9d\xea\xd8\x35\x75\x70\x79\x6c\xf2\x48\x7c\x34\xef\x92\x3b\xa9\x85\xc3\xa3\x26\x61\x6e\x70\x10\x15\x55\xad\x52\xd0\x84\xea\x9a\x41\x9c\xa5\x50\x38\x44\x6b\x29\xc8\x65\x4c\xaf\xe0\xce\xdf\x61\x36\x75\xd8\x6c\x05\x11\x50\x1b\xc7\x3e\x86\x62\x15\x22\x05\x9b\x60\xea\x0f\xbd\x59\x02\x78\x58\x91\x43\x18\x4e\x87\x24\xb6\xc9\xda\x94\xbb\x98\xb1\xa3\x7e\xd5\x3d\x9e\x1a\xe2\x2a\xf1\x3f\x66\xd9\xce\x3f\x0e\x73\xe0\x3a\xa7\x49\xb2\x20\x30\x67\x91\x2e\xbe\x0f\x03\x02\x99\xb6\xce\xce\x36\xae\x94\x16\xe2\x61\x5b\x91\x70\xb0\x72\xb6\x76\xf3\x57\xfb\xd1\x5e\x76\x5b\x59\x47\x73\x7a\xb3\x24\x97\x58\x08\x0d\x37\xaa\x55\xda\xbc\xcd\xfa\x2b\xf1\x9f\x88\xe0\xef\xaf\x9a\xba\xc7\x48\x47\x3c\xa1\x35\x1f\x58\x56\xa0\xf2\x24\x31\xe8\x6d\x3d\x66\xab\x20\x58\xe3\xc9\x5a\x93\x6d\x63\xdd\xac\x69\x25\xeb\x06\xef\xb9\x11\x99\x48\xc4\x74\x51\xdd\x41\xdb\x91\xa5\x52\xde\x86\x12\x95\x8f\x9d\x08\x68\x0e\xd1\xe5\xd2\x96\x07\x5f\xc8\xc6\x11\x7c\x21\x2b\x23\xd8\x07\x96\x47\xb0\x0f\xec\x30\x82\x7d\x60\xcd\x08\xf6\x81\xd5\x11\xec\x03\xc1\x3e\xd0\x66\xbc\x7c\xfb\x00\x09\xbe\x90\x4d\x23\xc8\x3a\xe5\x08\xb2\xce\xf6\x23\xc8\x3a\xab\x23\xc8\x3a\x41\xd6\x09\xb2\x4e\x90\x75\x9a\x8e\x16\xc8\x9d\x89\xb8\xf3\x14\x99\x4c\xc4\x0f\x64\xc8\x58\x7b\x75\x24\x06\x89\x88\x8a\xca\x22\xe6\x11\xe7\xf9\x50\x34\xb5\x26\xf4\x3e\xf9\xb7\xe0\x60\xd3\x13\x6c\xc9\xda\x14\x88\xc0\x26\x10\x99\x88\x0f\xd5\x51\x83\xc0\xf3\x90\x61\x13\x32\x6c\x3e\x83\x0c\x9b\x19\x55\xae\xf0\x11\x92\xd6\xcd\x09\x37\x95\xe3\x7f\x03\x32\xfd\x6c\xf3\x6d\x0c\xc2\x39\x84\xc1\x1e\x71\x25\x52\x58\xd8\xc5\xce\xb7\x0b\xf1\xa8\x0e\x31\xa7\x97\xd9\x16\x3b\x71\x0c\x31\xc9\x40\x0e\x2c\x92\x09\x32\x61\xae\xfe\xd7\x12\xfe\x3a\x08\x3f\xf3\xbc\x99\x3a\x24\x9e\x75\xf2\x4c\xfd\x53\x3a\xf3\x4d\x55\x5d\x74\x35\xae\xf8\xec\x52\x69\xba\xd1\x4a\x07\x44\x3b\x77\xda\xf7\xad\xf4\xd2\xae\x94\x48\x54\xf2\xae\x77\x2a\x73\xbc\x79\xac\x2d\x4e\xfb\xaf\x1c\xe4\x82\x88\x39\xc8\x52\x31\x2a\xba\xf3\xf4\x8b\x26\x33\x11\x75\x05\x90\xbb\x31\xf0\x74\x62\x8a\xe8\x52\x53\xef\xda\x6b\x48\xf6\xac\xfa\xf1\xe6\xd1\xad\xe2\xd0\xa1\xda\xf0\xdc\x6a\x29\x6f\x1e\x9d\x9a\xdf\x48\xc7\x26\x38\xd2\xa1\x19\x8e\x74\x6b\x8a\x23\x9d\x9b\xe3\x48\x97\x26\x39\xf2\xc9\x2b\x40\x6f\x1e\x1d\x9b\x8f\x48\xe7\x56\x3a\xf2\x0c\xeb\x49\x6f\x1e\x1f\x01\xdc\x5d\x5a\xec\x48\xa8\x4e\xdd\x7a\x74\x6d\x50\x23\x5d\x1b\xd5\x48\xd7\x78\xd8\xa8\x0a\xf6\xe6\x11\xea\x63\x7f\x04\x39\xad\x33\x21\xa2\x6d\x4d\xed\xc7\x16\xda\x01\x4e\x16\xbd\x7b\x3f\x95\x02\x64\xb9\x74\xd9\x30\xd6\xbc\xbb\xd2\xab\x0b\x43\x35\xab\x8d\x4d\x7d\xdc\x2a\x62\x34\xfe\x1e\x7b\x83\x57\xce\x2b\xc5\xe3\x2a\x93\xad\xb4\x8e\x29\x4d\x67\x45\xf3\x18\xa3\x14\x94\x4d\xa7\x2a\x0f\xe3\xbd\x43\x1b\x4e\x5a\x4a\x13\x3c\x5e\x0e\x30\x2d\x9f\x40\xfd\xc2\xb6\xb3\x3d\xf0\x76\xec\x9e\x2a\xef\x38\x18\x56\x3b\xdf\xba\x19\x0f\xff\xcf\xff\x3d\xaa\x55\x6f\x29\x27\x0c\xda\xdf\xd6\x23\x68\x7f\xad\x46\xd0\xfe\x36\x8e\xa0\xfd\xb5\x18\x41\xfb\xdb\x6e\x04\xed\x6f\xf3\x08\xda\x5f\xd0\xfe\x1a\x8c\xa0\xfd\x05\xed\xaf\xe9\xf8\x8c\xb5\xbf\x6e\xa3\x9a\xab\xba\x98\x0b\x12\x41\xf9\x51\x53\xcd\xa2\x32\xe2\xd9\xdf\x65\xff\xd5\xad\x0e\x58\xd5\xef\xd6\x6b\x80\x55\x2d\x71\x45\x0b\x1e\x3e\xa2\xee\x15\x0a\xe1\xca\x93\x0f\x6b\x82\x2f\x2d\x72\xbb\x33\x4c\xac\xb8\x84\x3b\x45\xc5\x1b\x1f\x58\x56\x36\x5e\x2f\xa2\xce\x62\x72\xe8\x7d\xf1\xd8\x48\x85\x0b\x5d\xbf\xc8\x35\x1b\x94\x77\x14\xde\x79\x0c\xaa\xa9\xe5\xf3\xd7\x5c\xc8\x45\x0c\x5b\x11\x1f\x55\x62\x8f\x21\x8f\x20\x6b\x6b\xc0\xc6\xb5\x13\xc6\x6d\xa4\xa3\x6f\xfa\x23\xb8\x0f\x9a\xb2\xf4\x14\x29\xa0\xc7\x73\x2b\xfa\xe2\x7a\x50\xfe\x2d\x61\x57\x89\xf2\xa1\x78\xc8\x28\x77\xc9\xb0\x82\xfb\xae\xf4\xb6\xd3\x7c\x29\x2f\x17\xbd\x54\x8a\xb7\x0f\xc9\x39\x62\x7d\x75\x62\xa6\x10\x3e\xd4\xf6\x3f\xe9\x06\x91\xf7\xab\x70\xc3\xdd\xce\x85\x1b\x96\x22\x46\x42\xdd\x86\x50\xb7\xa1\x55\xdd\x06\xbc\x68\x0f\x77\xe7\x05\x1c\xc8\x8f\xae\x3d\x92\x04\x04\x55\x9a\x27\x9a\x65\x65\x04\xb6\xb2\xaf\x4a\xac\x26\x31\x71\x91\xa0\x75\x7c\x37\x6f\xa3\xd1\x6c\x19\xef\x71\x3e\x8c\xd8\x56\x48\x4e\x5c\xb4\x25\x36\x33\xc2\x8a\x03\x5e\xed\xb0\x21\xa5\xec\xf9\x47\x0a\x9e\x21\xc1\x56\xa5\xd6\x6c\x7b\x6d\x19\x3a\x9f\x18\x94\x30\x14\xfb\x01\x06\x51\x6d\x68\x81\x51\xab\x6c\x0e\xbc\xe4\x12\x87\xea\xe8\xc8\x4b\x43\x9d\x72\xaf\x8f\xc2\x7d\xfe\x56\xe1\x12\xff\xb5\x0d\xff\xc1\x0f\x2a\x38\x50\x09\xbe\x92\xff\x3c\xef\x90\xc8\xf6\xd1\x6d\x5d\x58\xe4\x3a\x8b\x6a\x7b\xf2\x88\xb6\xcf\xa9\xf6\xc5\x5e\xfa\x30\xf6\x4e\xeb\x78\x19\x7e\x8b\x90\x30\xba\xfd\x78\x0e\x09\xa3\x4f\xe4\x9b\x78\x3e\x79\xa3\xcf\xd6\x1f\xf1\x5c\xf2\x46\x83\x0f\x62\xa7\xf1\x52\xd3\x39\xeb\xa3\x43\x9f\x43\xf0\x37\x74\x2c\x53\x75\xc2\xfc\x3f\x8e\x9f\xa1\x13\xfc\xeb\x34\xba\x2c\x44\x96\x3d\x65\x64\x59\xd0\xc2\x82\x16\x56\x1f\x41\x0b\x5b\x19\x41\x0b\xdb\x61\x04\x2d\x6c\xf3\x08\x5a\xd8\xea\x08\x5a\x58\xd0\xc2\xb6\x18\x41\x0b\x0b\x5a\xd8\xb6\xe3\x33\xd3\xc2\xba\xab\xb7\x1e\x22\xbc\x3e\x42\x84\x57\x37\x94\xb0\x03\xfa\xd7\x09\xd6\x75\x14\xd1\x15\xa2\xb9\xf6\x3b\x9a\xab\x65\xd9\x39\xae\xd9\xc7\x29\x3d\x57\xdd\xed\x4d\xf5\xe7\xe8\x5c\xb0\x98\x64\xb9\x76\xd5\xb7\x42\x0d\xba\x7d\xae\x41\x57\xdb\xd1\x50\x88\x6e\xab\x42\x74\x9b\x60\x16\xaa\xd1\x6d\x18\xfb\x13\x63\x16\xaa\xd1\xed\x3a\x42\x35\xba\xf5\x23\x54\xa3\x7b\x60\x84\x6a\x74\xa1\x1a\x5d\xa8\x47\xd0\x62\x84\x7a\x04\x6b\x46\xa8\x47\xd0\x7c\x84\x7a\x04\x5b\x8d\x50\x8f\x20\xd4\x23\xa8\x8f\xe0\x85\x6a\x37\x42\x3d\x82\x96\x23\x78\xa6\x42\x3d\x82\x56\x13\x86\x6a\x74\x2f\x2a\x66\x90\x04\xed\x2f\x68\x7f\x5b\x8f\xa0\xfd\x6d\x1c\x41\xfb\x6b\x31\x82\xf6\xb7\xdd\x08\xda\xdf\xe6\x11\xb4\xbf\xa0\xfd\x35\x18\x41\xfb\x0b\xda\x5f\xd3\xf1\x19\x6b\x7f\xa1\x1a\xdd\xde\xc7\x2a\x92\x7d\xcc\x48\x0a\xd5\xe8\x42\xfc\x62\xa3\xed\x0e\xd5\xe8\x1e\x1f\x9f\x7d\x35\xba\x5a\x2c\xdd\xd3\x95\xa4\xdb\x7d\x19\xa1\x2e\x5d\xa8\x4b\x17\xea\xd2\x85\xba\x74\xa1\x2e\x5d\xa8\x4b\xb7\xfd\xd8\x7f\x6f\xc6\xde\xe9\x1f\x2f\xc3\x83\x11\x2a\x22\x6c\x3f\x42\x45\x84\x8d\x23\x54\x44\x08\x15\x11\x82\x37\xa2\xc9\x08\x15\x11\x76\x1c\xc1\xf3\x10\x2a\x22\xec\x34\x42\x5d\xba\x17\x13\x63\x16\xb4\xb0\xa0\x85\xd5\x47\xd0\xc2\x56\x46\xd0\xc2\x76\x18\x41\x0b\xdb\x3c\x82\x16\xb6\x3a\x82\x16\x16\xb4\xb0\x2d\x46\xd0\xc2\x82\x16\xb6\xed\xf8\xcc\xb4\xb0\x50\x97\x6e\xaf\x63\xbd\x42\x5d\xba\x35\x23\xc4\x75\xed\x77\x5c\x57\x43\x5c\xa1\xb9\x16\xa9\xc8\xb9\xbe\x06\x39\x67\x11\x9c\x44\x91\xf9\xeb\x46\xdc\xc2\x8e\xb1\x44\x75\x35\xf4\x81\x69\x09\xe3\x31\x8b\x50\x91\xbc\x9b\x01\x96\x95\x33\xf2\x2d\xde\x47\xa8\xbd\x91\x68\xbc\xb3\x44\x2f\x5c\xa7\x21\x6a\x18\x60\x83\x53\xef\x0a\x2f\x0b\xa1\xb1\x10\x09\x50\xbe\xc3\x93\x8e\x1b\x82\xdc\xf1\x34\xd7\x00\xf2\xd6\x91\xe2\x72\x32\x32\x86\x44\xf0\xa9\x8b\xe7\x71\x27\x60\x48\x4e\xcb\x1b\x22\xca\xf1\xf0\xe4\x52\x02\xd7\xc9\x02\xe1\x80\x05\xae\x50\x6b\x48\xc5\x1c\x62\x24\xd9\x18\x46\x64\xe5\x48\xaa\x49\x02\xd4\xbc\x8b\x43\xf9\x32\x73\x78\x28\x19\xe1\xfc\x76\xd2\x31\xb8\xd0\xa6\x46\x40\xdc\x9d\x36\x36\xa2\x86\x4b\x96\x0d\x27\x36\x21\x5f\x8a\x50\x3f\xaa\x7c\x21\x1e\xcd\x85\xc8\xc9\x1d\xb5\x92\x92\xcc\x39\x1e\x66\xfc\x74\x03\xda\x1d\x5f\xde\x42\x26\x69\x6e\x7e\x18\x20\x55\xdb\xf1\xb1\x36\xe6\x00\x2a\xa7\x8d\x98\x54\x6d\x6b\x7a\x27\x72\x9a\x5b\x91\xd0\xa1\x32\x70\x2d\x17\x18\x6f\x67\x65\x8a\x0a\x26\xa6\x74\x0a\xbd\x9e\x22\xa7\xef\xce\x0c\xf9\xcb\x95\xa1\xd6\xae\xca\x9e\x23\x87\x99\x14\x73\x16\x1b\xe4\xfe\x40\x25\xa3\xe3\xc4\xc8\x9d\x13\x90\xc0\x8d\x58\xf0\xe5\xe1\x87\x93\xab\x5f\x2f\x4f\xde\x9d\x1f\xa1\x04\x0a\xf7\x19\xe5\xe6\x54\xe4\xaa\x0c\x14\x75\xaf\x33\x2f\x02\x3e\x67\x52\x70\xb3\x3e\xd4\xd5\x28\x99\xfb\x59\xa3\xe2\x30\x48\x50\x22\x99\x43\x6c\xe5\xe4\xe2\x6d\x9e\xeb\x30\x9e\xe5\xda\xeb\x8e\x18\xbe\x68\x0e\x10\x8f\x66\x94\x4f\xcd\x3a\xcf\x44\x6e\xe6\xfb\xf2\x4b\x5c\x91\x84\x38\x8f\xac\xe4\x44\x3d\xd6\x7e\xd9\xf7\x9c\xc2\xd0\x7a\x65\x4b\x22\xaa\x88\x66\x7e\xcd\xd5\xcf\x52\x0b\xae\xe9\xfd\x1b\x1b\xbf\x77\xf0\x65\xe5\xd2\x81\x2f\x27\x29\xcc\x2b\x2c\xbf\xb1\xab\x4a\xb0\x92\x61\x42\x0e\xaa\x77\x0f\xc9\xb9\x79\x07\xc4\x55\x00\xda\xf0\x4b\x98\x83\x44\xcd\xd3\x81\xaf\x4f\x24\x4c\xa9\x8c\x13\x50\x18\x78\xe8\x69\xb3\xd5\x0e\x1c\xc0\xa0\xd0\x6b\xb9\xd0\xeb\x88\x09\x79\x27\x30\x08\x71\x22\xde\x90\x99\xd6\x99\x7a\x73\x7c\x7c\x9b\x8f\x41\x72\xd0\xa0\x86\x4c\x1c\xc7\x22\x52\xc7\x9a\xaa\x5b\x75\xcc\xb8\x39\x5c\x83\x98\x6a\x3a\xa8\x9c\xea\x63\xcb\xb9\x07\x91\x48\x53\xca\xe3\x01\x75\xd8\x35\x28\xb6\xf5\xf8\x0b\xc7\x53\x07\xb4\xb8\x8b\xf1\x01\x1d\xa8\x19\x24\x49\xaf\x01\x3e\xb7\x93\xf9\x5a\xc8\x7a\xad\x64\x3c\xf7\xed\xed\x0f\xf0\x79\x71\x5e\x2d\x0c\x86\xe4\x52\x68\x17\x1f\xeb\x42\xb1\x91\x8e\x22\x7c\x37\x1e\xe9\xf3\xcb\x9b\xab\xbf\x8f\xde\x5f\x5c\xde\x84\x93\x1d\x4e\x76\x38\xd9\x2d\x4e\x36\xf0\x79\xeb\x53\xed\x65\xce\xca\x31\x29\xf6\x1b\x39\xb5\x02\xed\x8f\x41\xb1\x01\xad\x25\x44\x3b\x9e\x0c\xea\x35\x08\x9c\xf3\xf9\x07\x5a\xb7\xb0\xf3\xb5\xe0\x20\xee\x06\x2b\x28\x17\x32\x78\x9b\xf8\xf8\x16\xd6\xac\xb6\xee\xab\x46\x52\xa4\x1d\xed\x5d\x4b\xe6\xd5\xcd\x0d\x0d\xb5\xed\xbb\xa4\x69\x59\xa1\x7a\xcd\xae\x0d\xc9\x3b\xaf\xf6\x90\xd3\x5f\x2f\xce\xce\x2f\x6f\x2e\xbe\xb9\x38\xbf\x6a\xae\x47\x77\x60\x71\x41\x9b\x42\x47\x00\xe8\x35\xe4\x92\x99\x84\x39\x13\xb9\x4a\x16\x85\x15\x64\x3d\x11\x58\x3e\xfd\xce\xef\xbb\x28\xf4\xf1\xb5\x8f\x05\x66\xdb\x2d\xb3\x3d\x83\x09\xcd\x13\xab\x3d\x1d\x1c\x0c\x9b\x70\x39\x3b\xba\x42\xdf\x6f\xa4\x68\x51\x81\xb9\x86\xc2\xd7\xb6\x76\xfb\x44\xc8\x8d\xc7\xb8\xe7\xa2\x0f\x6a\xac\xc7\x09\x8f\xd6\x42\xe7\xa4\x47\xeb\x24\x6b\x09\x9d\x96\x5e\x86\x6e\x7c\xef\x91\xe0\x13\x36\x7d\x47\xb3\xef\x61\x71\x05\x93\x76\x66\xe2\x3a\xbc\xd1\xfa\xe8\x5c\xc9\x68\xab\x34\xec\xcc\xbe\xac\x9d\x9b\xa6\x33\x27\x4d\x57\xd1\x19\xed\x23\x33\xba\x0b\xa4\xe8\x24\x88\x62\xa5\x1e\xbe\xb5\x43\x3b\x8b\x72\x57\x31\x36\x9d\x78\xee\xdb\x71\x79\x3f\xea\xcc\xae\xca\xee\x1d\x9d\xd5\xdb\xaa\x1d\x91\xe0\x11\x64\x5a\x1d\x8b\xb9\xe1\x5c\x70\x77\x7c\x27\xe4\xad\xd1\x23\x8c\xee\x3a\xb0\x58\xab\x8e\xd1\x67\x70\xfc\x85\x75\x83\xdd\xbc\x3f\x7b\xff\x86\x9c\xc4\xb1\x6b\x6e\x92\x2b\x98\xe4\x89\x6b\x27\x30\x24\x34\x63\x1f\x40\x2a\x26\x78\x9f\xdc\x32\x1e\xf7\x49\xce\xe2\xaf\x9b\x13\x67\x3f\x3a\xdc\x05\x91\x59\x57\x67\xc7\x3b\x71\x8d\x3e\x96\x45\x8d\x77\x15\x44\xc4\x70\x2d\xa6\x15\xe2\xa6\xb7\x3a\x3b\x21\xa3\x23\xd0\xec\x6e\xa2\x5f\x1e\xb8\x85\xdd\xd2\xd5\x5e\x49\x58\xad\x8b\xd3\x21\x6a\x26\xe2\x37\x44\xe5\x59\x26\xa4\x56\x24\x05\x4d\x8d\xd2\x3b\x34\x18\xd6\xaf\xff\x89\xbe\xaa\x3e\xf9\x47\xf1\x23\x3a\x9c\xd4\x4f\xbd\xde\xdf\xbe\x3f\xff\xfb\x7f\xf5\x7a\xbf\xfc\xa3\x7a\x15\x59\xa1\x8d\x02\xaa\xdf\xa2\x32\x88\x86\x5c\xc4\x70\x89\xef\xc0\x3f\x55\xcd\xcd\xe2\x2e\x68\xaa\x73\x35\x9c\x09\xa5\x2f\x46\xc5\x9f\x99\x88\x97\xff\x52\x2d\x24\x0e\xb2\x9f\x8c\x01\xb7\x68\x44\xf5\x6c\x4f\xd8\x43\x49\x4b\x3a\x3e\xaa\x6e\xd6\x6a\x13\x9d\x94\xe2\x3f\xbf\xf1\x20\x30\xd2\xd3\x9d\x64\x5a\xa3\xeb\xcd\xa5\x82\x8b\x49\xdf\x9c\xda\x52\xec\x9c\xbf\x6e\x5d\x1f\xa5\x53\xd2\x56\xec\x60\xc7\x00\x43\x88\x38\x68\xd9\x83\x5c\x30\xd8\x55\x17\xf3\xc9\xe8\x82\xcc\x2d\x84\xf7\x06\x38\x3e\xbd\xf7\x9b\x8f\x4a\xe3\x8a\xa6\x4b\x0e\x54\x85\x86\xf8\xc6\x06\x05\x15\x49\xc6\x24\x61\x29\x73\xb1\x86\xae\x41\x93\x22\x87\xf6\xc7\x61\x94\xe5\x7d\x77\xc3\x30\x85\x54\xc8\x45\xf1\x27\x64\x33\x48\x8d\xa6\x35\x50\x5a\x48\x3a\x85\x7e\xf1\xb8\x7d\xac\xf8\xcb\x3e\x58\x7b\xc1\xea\xd3\x56\x15\x2e\x5d\xa5\x8e\x22\x43\xfc\xf2\x68\x9b\x07\xfd\x9e\x90\xb6\x02\x33\x2e\x3f\x82\x48\x58\x58\xe2\xac\xc0\x59\x40\x11\xf5\xc9\xb9\x48\xf2\x14\x54\xbf\x10\x83\xac\x35\x80\xcf\x8d\x66\xa9\xf6\x4a\x50\x8b\xd9\x9c\xa9\x2e\xc2\x88\xd7\xc8\x69\xcc\x45\xe4\x8b\x5c\x67\xb9\x76\xf5\x66\x2a\x8d\xdd\x84\x42\xbb\x45\x51\x14\xa0\x46\xf6\x5f\x1f\xb4\x8f\x46\xa7\x5a\x83\xe4\x6f\xc8\xff\x1c\xfe\xfc\xd5\x6f\x83\xa3\xaf\x0f\x0f\x7f\x7a\x35\xf8\xeb\x2f\x5f\x1d\xfe\x3c\xc4\x7f\xfc\xfe\xe8\xeb\xa3\xdf\xfc\x1f\x5f\x1d\x1d\x1d\x1e\xfe\xf4\xfd\xbb\x6f\x6f\x46\xe7\xbf\xb0\xa3\xdf\x7e\xe2\x79\x7a\x6b\xff\xfa\xed\xf0\x27\x38\xff\x65\xcb\x49\x8e\x8e\xbe\xfe\xb2\xf5\xd2\x29\x5f\xbc\x6f\x49\x40\xed\x18\x74\x56\x2e\x68\x79\xc6\x8e\xe2\xac\xef\x07\xa5\xd2\x34\x60\x5c\x0f\x84\x1c\xd8\xa9\xdf\x10\x2d\xf3\x76\xc4\xa4\x64\x4a\x5d\x9f\x7f\xdf\xbd\xeb\x4d\xc9\x90\x0a\x76\xbd\x37\x07\x5c\x41\x24\x41\x7f\x0a\x4b\x8e\x7d\x93\x97\x53\x96\x62\x1e\x5f\x1a\x9f\xfb\x1c\x8c\x3b\x45\xc8\x20\xee\x6b\x29\x89\x4e\xa4\x48\x87\xa4\xe2\xde\x98\x63\xc2\x87\xbb\xef\x16\x5a\x58\x41\xfd\x08\xc6\xa0\x60\x0c\xda\x30\x1e\x35\x06\x5d\x5b\x3c\xdc\x5b\x4b\x10\xf0\x79\x53\x17\xc6\x5a\x0f\xba\xd7\x75\xb4\x20\x99\xc8\xf2\x84\xea\x0d\x9e\xb1\x35\xee\x74\x77\xd4\xcb\x78\xe4\x32\x98\xc6\x32\xb4\x74\xbd\x0f\x93\x9c\x24\x09\x61\xdc\x1e\x7c\x9c\xc0\x3b\xcc\x24\x58\xd5\x86\x50\xeb\xcf\x9e\x9b\x25\xdc\xb9\xb2\x72\xd5\xb8\x1c\x45\x94\xa6\x52\x63\xec\x31\x96\x9d\xb3\xac\xc4\x79\x9f\x18\x2f\x8b\xcf\x15\xc2\x61\x91\x0b\xb2\xb6\x33\x66\x42\x95\xf6\xcb\xc6\xd5\x68\x7a\x8b\xde\xc6\x08\x62\xe0\x11\x60\x62\x5a\x0e\xe5\xb7\x8e\x8d\xde\x46\xce\xf9\xdc\xce\x41\x49\x9c\xdb\x60\x10\x4b\xfe\xd6\xcf\xf1\xb2\x02\x10\x0c\x22\x5e\xfb\x06\xc6\x45\x1c\x02\x52\xfd\x42\xc3\x2e\xf2\xfb\x0a\x2b\xab\x7a\x9a\xc8\x83\xf6\x3c\xb3\xf0\x6c\xb5\x12\x86\x56\x98\x65\x69\x7e\xae\x33\xc9\x97\xe0\x0c\x6c\xcf\x3e\x3f\x3b\xd6\xd9\x11\xdb\xec\x86\x65\xee\xe0\x3b\xe9\x92\x4d\x76\xe1\x2c\xc9\x24\x4c\xd8\x7d\x47\xe7\xf4\x84\x97\x96\x18\x16\x03\xd7\x6c\xc2\x6c\xcf\xfb\x4c\x42\x06\x3c\x2e\x0a\x97\x62\x72\x38\xaf\xc3\x66\x2f\x83\x79\xac\xc0\xdd\x2d\x29\xbb\x5e\x27\xec\x07\x3a\x46\x02\x1d\x6b\x3c\x3e\x11\x1d\x73\x98\xbb\x3f\x44\x0c\x23\xcf\xdb\x47\xbf\x9f\xd6\x43\xd9\x11\x91\x77\x46\xb4\x32\xb3\xeb\x18\x67\x51\x36\x4b\xb2\x48\xc3\x2e\x48\xa3\x16\x36\x78\x8d\xcc\xd8\xd4\x40\x36\x81\x39\x24\x4e\x6e\x22\x29\xe5\x74\x6a\xf3\xbb\xb5\xf0\xa6\x5a\xa3\x68\x19\x3c\x96\x2c\x5e\x89\xbb\x47\x39\xde\xe0\x76\x22\x68\x8c\x17\xa5\x48\x12\x90\x8a\x24\xec\x16\xc8\x19\x64\x89\x58\xb8\x74\x6d\x1e\x93\x6b\x4d\xb5\xc1\xea\x6b\xd0\xcd\xdc\xbe\xad\x30\x16\x57\x3c\xca\x93\x64\x24\x12\x16\x35\x32\xaa\xd4\x77\xee\x02\xf7\x2b\xcb\x93\x84\x64\x38\xe5\x90\xbc\xe7\x48\x34\x4e\x92\x3b\xba\x50\x7d\x72\x09\x73\x90\x7d\x72\x31\xb9\x14\x7a\x64\xa5\xef\x7a\xc0\x9d\xbd\x91\xb0\x09\x79\x83\xd5\x6d\x34\xd1\x74\x8a\xba\x93\x77\x03\xf6\x0d\xfc\xab\x13\x58\xfa\x70\xc7\xd4\x5a\x65\xa5\x35\xe2\x7c\x81\x33\x19\x5a\x65\xff\xfe\xe4\xdb\x94\xb0\x09\x44\x8b\x28\x69\x7f\xb4\x4e\x22\x0c\x60\x28\x33\xce\x2b\xf8\xed\xaa\xa9\xbb\x1c\x4f\xd4\x02\x19\x27\xb6\xcc\xb9\xad\xdf\x5e\xa2\x7a\xb1\x22\xab\xed\xaa\x4e\x95\xc4\xc6\xcc\xb3\x2d\xdb\xcc\x84\xd2\xd7\x46\x43\xef\xa4\x18\x7a\x6f\xe4\xa7\x23\x58\xf2\x39\x49\x20\x26\x2c\x4d\x21\x36\x5a\x7c\xb2\x20\x74\xa2\x31\xd7\xb6\x66\x21\x88\x24\x58\xac\x75\x55\x4c\x66\x94\xc7\x09\x48\x32\xa1\x2c\x71\xf6\x80\xda\xfd\x1a\x64\xca\x38\x9a\x05\xac\x47\x16\x4d\x0c\xe6\xaf\x28\x12\xd2\x97\xa7\x67\x5a\xf9\x4b\xe5\xc1\x44\x3e\x52\x41\x80\x65\xd7\x32\x19\x27\x22\xba\x55\x24\xe7\x9a\x25\x76\x31\x42\xdc\x92\x48\xa4\x59\x82\x47\xa7\xc5\xc9\x2a\xfe\x39\x28\x50\x69\x60\x66\x57\xc7\x5f\x94\x97\xf0\x87\xa6\x0c\xbd\x03\x41\xac\x0b\x31\x0c\xee\x21\xea\x2c\xcf\xff\xfc\x1e\xa2\x4a\x61\x09\xec\xc7\x80\x27\x1a\xf3\x3c\xe9\x2d\xbc\xa0\x4a\x76\x2d\x72\xe9\xaa\xa3\x06\xbf\x53\x3b\xa7\x2f\x84\xe5\x5e\x41\x12\xc6\x91\xbe\xb9\xfc\x3a\xc2\xb8\x32\x9c\xbd\x76\x18\xec\xd1\x73\x42\x2b\x89\x99\xc4\x2a\x08\x8b\x22\x90\xda\xcf\x85\x05\x06\x84\xd0\xe4\xb0\x77\xdc\x3b\x5a\xb1\x3f\xf6\x8c\x04\x92\x80\xa5\xb5\x3e\x71\xaf\x58\x94\x62\x69\x96\x2c\x70\x1d\xbd\xb8\x4f\x98\xf6\x91\xd6\x32\xe7\x7e\x55\x2e\xe9\xaf\x4f\x94\x20\x5a\x52\x5f\x5d\xc5\xfe\x6a\x6e\xd2\x32\x77\x54\xfe\xb0\xf7\x5b\xaf\x4f\x40\x47\x47\xe4\x4e\xf0\x9e\xc6\xe5\x0f\xc9\x8d\x30\xa2\x74\x39\xd1\x42\xe4\x84\x83\x0d\xec\x87\xfb\x2c\x61\x11\xd3\xc9\x02\x29\x16\x11\xb9\xb6\x39\xc4\x54\xfb\x64\xc3\xf3\x7b\xa6\x5d\xbc\x9a\x21\x19\xaf\x10\x9a\x96\x6a\x11\x6a\xc4\x9c\x39\x1c\xcf\x80\x26\x7a\x66\x83\x44\xb8\xe0\x83\x7f\x83\x14\x98\x83\xc8\xdd\x95\x17\x57\xf5\xaf\x13\xcd\xc1\x10\xd1\x6f\xa1\xbb\x26\x3e\xdf\xdd\xdc\x8c\xbe\x05\xbd\x44\x32\xcc\x5b\x7c\xe8\x0e\x5a\x03\x40\x4e\x84\x4c\xf7\x80\x76\x74\xe3\xac\x1c\x90\x4c\xc8\x7d\x20\x61\x33\xa1\x5a\xed\x25\x59\xd9\x4f\xa1\x34\x6a\x43\x4e\x1a\xe3\x10\x99\x1d\xac\xc7\x90\xf8\x3e\x37\x17\xa3\x21\xf9\xbb\xc8\xcd\xd7\x8c\xe9\x38\x59\x14\x95\x18\x14\x68\x72\x60\xa6\x3a\x30\xe4\xc9\x60\xc3\x77\x40\x63\xa3\xa2\x18\xea\x01\x74\x3f\xfa\x59\x11\x77\x1e\xdc\xda\xba\xe5\x03\xb9\xd2\x22\x25\x33\xf7\xd9\xf5\xd4\x4b\x77\x32\x86\x78\x7a\x7c\x5e\x93\x84\xcc\x52\x38\xf7\xcc\x8b\xa3\x5f\x2b\x74\xc3\xc2\xdd\xfd\x3e\xc6\x32\x56\x51\x15\x6c\xae\xa1\x93\x4d\x0c\xe2\x16\x58\x06\xd5\xa0\x99\xab\xa4\x3a\xf6\xb8\xf6\x68\xe3\x44\xce\xe5\x89\xd0\xa9\xd7\x3e\xd6\xab\xd3\xca\xa3\xdd\xc4\x0d\x90\x75\x46\x56\x87\x33\xd6\xfa\xd2\x11\x10\x3f\x4e\xe9\xcb\x4f\x01\x80\x6e\x36\x9f\x74\x09\x81\xac\x83\xd0\xee\xd5\xc0\x6e\x2d\x8c\x1e\x8a\xa9\x97\x96\xb8\x22\x99\x50\x20\xe7\x4d\x93\xb9\xcb\xd1\xdd\xa7\x8b\xe6\x1a\xbf\x1f\x6b\xf2\xa4\x25\xe1\x79\x3a\x06\x59\x66\xa6\x48\xbd\x0a\x90\x4a\x64\xc2\xa5\xbd\xdd\x9b\x73\xeb\xed\x13\xcd\x93\x7f\xfe\xcf\xff\xfc\xe3\x7f\x0e\xed\xf4\x45\x94\x02\x27\x17\x27\x97\x27\xbf\x5e\x7f\x38\xc5\xe4\xd8\xb6\x50\xed\x28\x04\xb3\xeb\x00\xcc\x4e\xc3\x2f\x3f\x6a\xf0\x25\xa6\x7c\xb4\xa6\x22\x75\xdb\x3f\x4e\x69\x30\xc0\xe8\x6d\x46\xe3\x74\xb2\x5f\xa5\x58\x99\x91\x35\xeb\x86\x54\x73\xd4\xf6\xe2\x8c\xe9\x28\xbb\x16\xd1\x6d\x87\x7a\xcd\x19\x64\x12\x22\x6b\x27\xbb\x39\x1d\xd9\xd9\x8d\x7e\x79\xf9\xfe\xa6\x4c\x35\xc0\x78\x1c\xf2\xd6\xdb\x97\xbe\x73\x96\x34\xa3\x93\xde\x42\xa6\x0b\xd5\x7d\x4c\xa3\xdb\x3b\x2a\x63\xb4\x6c\x51\xcd\xc6\x2c\x61\xb6\xf8\xaf\x6f\x0a\xc9\x85\x0d\xf8\xb3\x45\xce\xc4\x64\xb9\xb4\x66\x69\x0e\x45\x93\x95\x8d\xa3\x99\x50\x96\xa0\x05\x35\xe7\x9a\xa5\xe0\x22\x82\xa2\xac\x30\xe9\x55\x6d\xda\x41\xf9\xf2\x63\x6f\x95\xaf\xde\x7b\xef\xd5\xdb\x59\x0f\x6b\x1b\x97\xb8\xc7\xac\xce\xb1\x38\x9b\x10\x12\x58\xdd\x67\xc1\xea\x32\x09\xd7\x5a\x64\x1d\x79\x49\xec\x64\x1b\x7c\x24\x63\x98\x08\x43\x84\x37\x3a\x3d\x7c\x8f\x60\x8e\xc9\x81\xde\xaa\x25\x6a\x8e\x0d\x1b\x91\xa9\xf2\x68\xe6\x0d\x94\x1c\x94\x3a\x46\x77\x48\x9e\x59\xad\x15\xc9\x75\x2e\xa1\x6f\xbe\x0e\x52\x5c\x5d\xbf\xcc\x72\x30\xaf\x07\x6e\x7f\x04\x1d\x59\xcb\x6d\x85\x90\x63\x61\x50\xb7\xfc\x65\x37\x4a\x24\xa9\x9a\x01\x96\x17\x81\x7b\xe6\xbb\xa1\x8c\x44\xdc\xeb\x95\x9f\x62\x18\xcb\x54\xd2\x08\x48\x06\x92\x09\xc3\x8c\x72\xae\x63\x71\xc7\xc9\x18\xa6\x8c\x2b\x0f\x0a\x33\xb7\x87\x19\xfa\x63\x98\x2a\x0a\xc3\x0d\xc9\x55\xad\xd8\x89\x4b\x43\x8a\x44\x79\x34\xdd\x9a\x97\x3d\x49\xc8\xb1\x2a\x2d\x93\x0b\x08\xfb\xf0\x58\xbd\xc5\x92\x0f\x73\x8e\x6f\x8e\x21\xa1\x0b\x1b\x6d\x3a\x61\x9c\x26\xec\xdf\x20\xd5\x51\x07\x1e\x27\x03\xc2\xf2\xda\xc6\x75\x60\xa9\x7e\x1a\xcd\xda\x39\x7f\x83\x8b\x6a\xcb\x11\x5c\x54\x6d\x26\x09\x2e\xaa\xe0\xa2\x7a\x64\x04\x17\x55\x70\x51\x2d\x8d\xbd\xd5\x92\x82\x8b\xaa\xf1\x08\x2e\xaa\x87\x47\x70\x51\x6d\x31\x82\x8b\x6a\xcb\x11\x5c\x54\xc1\x45\x15\x5c\x54\xc1\x45\xf5\x19\xd9\xed\xfc\x08\x2e\xaa\x95\x49\x82\x8b\x2a\xb8\xa8\xb6\x1e\x7b\xab\x7c\x05\x17\x95\x1d\xc1\x45\x55\x1f\x9f\x17\xab\xf3\x0e\x9e\x91\x51\xf5\xda\xe7\xb4\x8d\xd0\xa9\xc0\x22\xe7\x27\xaa\x36\x8d\x2b\x5e\x55\xe9\x13\x57\x29\x0b\xe2\x53\x71\x9c\x47\xa8\xf4\x33\xad\xcd\x97\xda\xd5\x55\xe1\x93\x0c\xd5\x71\x26\xec\xff\x95\x8e\x8a\x8a\x87\xc2\x2a\xbc\xcd\x73\xd6\x9e\x2c\x1b\xab\x8d\x5b\xe2\xd3\xb8\x24\xf6\xc4\x7f\xd3\x81\x1b\x22\xb8\x20\x5e\x9c\x0b\xe2\xe5\x74\xcd\x75\x9e\xf9\x9b\x99\x04\x35\x13\x49\x63\x44\xaf\x21\xf9\x3b\xc6\x59\x9a\xa7\x06\xe7\x94\xc1\x67\x36\x2f\x42\x00\x54\x81\xae\x96\x62\x5b\x2b\xa2\xb9\x91\xc5\x80\xc5\x4e\x29\x4b\xcc\x36\x62\xfe\xe6\x8c\xce\x0d\xae\xab\x3c\x8a\x00\xb0\x95\x5a\x55\xc3\xf9\xe3\xb0\x78\x53\xd1\x3a\xe3\x75\x3b\x7a\xd3\x8e\x89\xdb\x72\xa4\x38\xcb\x1f\xff\xd0\x68\x8e\xa9\xcc\xba\xa1\xcb\xdf\x5e\x8d\x4e\xab\x6d\xb2\xb9\x27\xcb\x8c\xcf\x45\x32\xb7\x1d\xf6\xf1\x26\x23\xac\xb9\x66\xfc\xd8\xcc\x7d\x0c\x9a\x56\x74\x1b\xa7\x16\x28\x02\x9c\x8e\x13\xf3\x9c\x79\xaa\xe0\xc8\x23\xcb\x77\x81\xea\x5c\x02\x99\x52\xfd\x94\x04\xbf\xbd\x0a\xd3\x4a\x7d\xe9\x82\xdf\xb4\x95\xd0\xeb\x36\x38\x23\x87\xd7\xad\x50\x53\xc4\x0b\x5b\x41\x7f\x6b\x39\xbc\x35\xa5\x6c\x2f\x1b\xb7\x3f\x5a\x04\x4b\xdc\xe0\x87\x77\x06\xe0\x03\xd7\xf2\xd9\xb3\xf3\xaa\x12\xe4\xbb\x4a\x69\x41\xb2\x84\x96\x7d\xa1\x70\x07\xbe\x43\x1e\x74\x3a\x83\xe8\xf6\xca\x79\x62\x0f\x15\x40\x21\x9b\x4e\x99\x9e\xe5\xe3\x61\x24\xd2\x63\x43\x12\xec\xff\x8d\x13\x31\x3e\x4e\xa9\xd2\x20\x8d\xb8\xea\x58\xdc\x20\x32\xb3\x30\x3e\x1d\xa6\xf1\xd1\x90\xfc\xcc\x6d\x76\x7b\xd9\x87\xb2\x52\xdb\xc1\xbc\xdf\xd7\xd9\x18\x83\xa1\xae\x42\x56\xdb\x87\x8f\x17\xb8\xbc\x61\x9b\x42\xc9\xad\x59\x52\x4b\x2f\xf8\xa7\xf7\x80\x07\xca\x45\x3a\x30\xb8\x3c\x37\x4f\x77\x67\x11\x1f\x1d\x78\xb8\xf7\xc8\xbb\xbd\x37\xa2\xf1\xbe\x78\xb4\xf7\xb0\xda\x74\x07\x0e\xd8\x2e\x3c\xd8\xdd\x79\xaf\x3f\x42\x51\xe6\x8f\xe3\xb5\xee\xd0\xb4\xd7\x91\xb7\xfa\x53\x78\xaa\x3b\xf9\xea\xb6\x1e\xea\x4f\xe7\x9d\xee\xe6\x73\xbb\x54\x04\x9e\xab\x47\xba\x03\x13\x7d\x97\xe6\xf9\xce\x4c\xf3\x1f\xcd\x03\xdd\xde\xfb\xbc\x07\x9e\xe7\xd6\x40\x66\x9c\x69\x46\x93\x33\x48\xe8\xe2\x1a\x22\xc1\xe3\xc6\x1c\x66\xa9\x4a\x67\x71\x7e\x94\x9d\xd6\xd9\xa9\xea\x89\x16\x33\xea\x8a\x91\x1b\x8d\xca\x26\x96\x78\x5f\x86\x13\x28\xd0\xab\x6c\x57\xb9\x97\xde\x09\xb2\x37\x06\x31\x9b\x75\xd2\xe5\x26\x7e\x27\xee\x88\x98\x68\xe0\xe4\x90\x71\xbf\x8f\x47\x15\x35\xb0\xb4\x4e\x16\x68\x6d\xae\xbe\x7e\xe5\x6f\x7e\x79\x66\x47\x34\xb0\x2a\xf5\xf1\xad\xc0\xee\x45\x8f\x9b\x81\xdd\x8d\x93\x3c\xa9\x9b\x82\xad\x79\xb8\x4e\x6f\x5e\x97\xe5\x94\x5f\xe3\xbc\xc5\x69\xa3\x3c\x26\x2e\x13\xed\xe5\x6d\x5a\xeb\xb8\x9a\xba\xe8\x57\xc4\xd1\x3c\x66\x35\xbe\x39\x1d\x59\xa3\x71\x30\x97\xec\x8b\xb9\xe4\x89\x62\x53\xf6\x50\xd0\x7d\xa6\xf1\x28\x41\xd0\xdd\x61\x54\x72\x53\xbf\x95\x34\x82\x51\xe7\x32\x82\x3f\x4e\x24\xce\x25\x75\x04\xb0\x10\xf9\xfc\xe1\xe1\x00\xb1\x3d\x4d\x45\x3e\x2f\x66\xca\x4e\xf2\x24\x59\x90\x3c\x13\xbc\x9e\xfd\x6c\x7d\xed\xcb\xc9\xb4\x68\x92\x5f\xf3\x96\x52\xb0\xcc\xa4\x70\x3c\x53\xe6\x9c\x1b\x1a\x5c\xf6\x44\x43\x41\x12\xcb\x34\xd3\x5a\xca\xae\x62\x53\xb3\x7c\xc3\xff\x30\x9b\xb7\x0c\x40\xac\x4d\x68\x9e\x9e\x08\x19\xb1\x71\xb2\x20\x33\x9a\x14\x0d\x70\x28\xb9\x65\x49\xe2\xa6\x19\x92\x6b\xd0\xd6\xa5\x60\x79\x67\x22\xf8\x14\x17\x47\xb9\x6f\xbc\x08\x91\x79\x36\x4a\x80\xf2\x3c\xb3\xef\x33\x9c\x78\x21\x72\xe9\xdf\x37\x2c\x1c\x13\x05\x07\xe6\x2c\xe9\x57\xda\xbb\x3d\xb8\xb1\x45\xec\x4f\xae\x8c\x00\xf0\xde\x97\xa5\xee\x57\xe7\xf4\x95\xc3\x55\xa5\xb9\x4f\x26\xc5\x9c\xc5\xd6\xbb\xe1\xc1\x86\x8d\xa4\x6d\x03\x9f\xe2\x3c\x73\xc1\x07\x1c\xa6\x14\x05\x15\x77\x8a\xec\x9e\xd9\x79\x6c\x04\x01\x8f\xb1\xa5\x8f\x91\xf0\x45\x56\x4b\xa7\x9f\x33\xdb\x8c\xb8\x02\x39\x72\xc8\x05\x11\x18\x8f\x9a\x73\xa6\x6d\x83\xfb\x59\xae\x49\x2c\xee\xf8\xd1\x4e\x5e\x57\x74\xb4\xde\xac\x05\x50\xdd\xfd\xba\x4e\xce\xb1\xdf\xfb\x30\x78\x99\x72\xa6\xcf\x09\xc9\xb9\x82\x96\xec\xbd\x33\xe1\xe8\xcf\x7f\x6a\x46\x23\x58\x0a\x22\xd7\x9f\x44\xfb\xbb\x9b\xb1\x68\x56\x15\x66\x59\x0a\x8a\x88\x7c\x49\x2d\x7e\xed\x1e\x5b\xbf\x43\x41\x05\x5c\x37\x9a\x1a\x76\xd7\x58\xbf\x96\xcb\x21\x94\x9d\xaf\x31\x4e\xfc\xec\xf2\xfa\xd7\xb7\x27\xff\x7d\xfe\x76\x48\xce\x69\x34\xab\xd6\xc4\xe0\x84\x22\xd1\x40\x42\x31\xa3\x73\x20\x94\xe4\x9c\xfd\x2b\x77\x0e\xdf\xc3\xe2\xd9\xa3\x4e\x6b\xb5\x37\xe4\xbe\xd8\x9d\xbf\xb3\x76\x70\xb6\xd7\xbf\x8d\xcb\x12\x0a\xb0\x81\xcb\xb2\xf8\x74\x6e\x2e\x59\xe5\x00\x45\x2d\x0c\x9c\x9f\xb2\xb9\x23\xc3\xae\xf8\x3d\x8d\x8b\x48\x31\x83\xe7\x06\x2d\x0c\xab\xa2\x63\x8c\xf0\x9a\x01\xe1\xa0\x0d\x5a\x17\x36\x26\xc1\x55\xad\x38\x49\xae\x40\xf5\xc9\x38\xc7\x98\xb4\x4c\xb2\x94\x4a\x96\x2c\xaa\x93\x19\x5e\x75\x59\xb8\xbc\x17\xcb\x4b\x3a\x7b\x7f\x7e\x8d\x39\x02\x99\xb4\x65\x4b\x30\xa8\x0c\xaf\xe3\x67\x8d\xc1\x3c\xe1\xda\x08\x0f\xc9\x09\x5f\xd8\x8b\xf6\x80\x33\x45\x12\xa6\x34\x20\x0b\x76\x32\xa4\x77\xa6\x1f\xbc\x1a\xe2\xff\x0e\xcc\x57\x4a\x23\x64\x16\xb1\x72\xd1\x4a\xf0\xaa\x15\x43\xd9\x38\xa9\x40\xd3\x7d\xfb\x8b\x6a\x08\x57\x06\x09\x19\x20\x56\x1a\xc2\xd1\x62\xab\x11\xbc\xb6\x41\x20\xe3\xd3\xa4\x8a\x55\xcd\xc8\x7e\x5b\xdd\xb2\xad\x66\x39\x28\xbf\x60\xd4\x54\xc1\xec\xa4\x31\x5d\xb9\x86\x8e\xda\x39\x95\xdc\xcf\xab\x53\x8e\x22\x88\x6a\x87\xde\x8b\x91\x3f\x01\x4e\xba\x49\x97\xda\xba\x66\x65\x4c\x52\x9f\xbc\x22\x7f\x23\xf7\xe4\x6f\xa8\x5e\xfd\xb9\x6d\xf3\xab\xb6\x8a\x4f\x17\x21\x46\x46\xab\xbf\x18\x75\x04\xf1\x1f\x0d\x75\x32\x33\x1a\xa8\x6a\x41\xc6\xcc\x89\xf3\x70\xaf\x41\x1a\x3a\xea\x76\xe2\x49\xdb\x86\x99\x05\x7e\x42\x34\xb3\xee\x86\x8b\x49\x3d\xac\x69\x37\x44\x33\x8f\x7f\x27\x94\xbe\x74\x54\xa8\xde\x00\xa7\x9c\x2d\xa5\x3a\x9a\xd5\xc9\x98\x11\xd4\x94\x2e\x0f\x98\x22\xb1\xc0\x28\x2b\x1b\xbe\x3c\x63\x2d\x82\x27\xf6\x07\x8d\xdb\xf9\xd3\x6b\xfb\xf9\xd0\x4e\x2d\x19\x50\x50\xf3\x71\x82\x55\xa5\x32\x56\x26\x62\x27\x93\x99\x65\xc5\x15\x9e\xf1\x80\x50\xe6\x6c\x35\x85\x95\x19\x71\xc9\x9c\xa7\x88\x72\x9b\x40\x32\x01\x29\x6d\xc4\xf9\x78\xe1\x83\xf5\x5a\x6f\x5e\xab\x93\x94\x49\xa1\x45\x24\x5a\x74\x36\xab\xfb\xb8\xdd\x74\x08\x04\x1b\xe5\xeb\xcd\xe4\x3f\x9c\x8d\xfa\xe4\xe6\x74\x84\xdd\x9e\xae\x4f\x6f\x46\x75\x4d\xe5\xe0\xe6\x74\x74\xf0\xa4\xa0\x20\x5e\xb2\x42\xc3\x74\x83\x49\x6a\x86\x27\x23\xb6\x0d\x52\x9a\x0d\x6e\x61\xd1\x90\xa7\x76\xc1\xd7\x07\xc5\x0e\x77\xf2\x41\x16\xcc\x29\xcd\x76\x9e\x4d\x02\x8d\xd9\x27\xca\xe2\xf2\x61\xb0\xc5\x3b\xd7\xa7\x73\xa5\x62\x0e\xb1\x15\x87\xfd\x13\xc0\xe3\x4c\x30\x23\x2f\x86\x1c\xaf\xdd\x9f\x0e\x39\x5e\x5b\x8f\x90\xe3\x15\x72\xbc\x56\xc7\xde\x04\xb2\x86\x1c\xaf\x97\xe5\xb7\x0f\x39\x5e\x9f\xb9\xeb\x3f\xe4\x78\xad\x1f\x21\xc7\x2b\xe4\x78\x6d\x37\x42\x8e\xd7\xee\x63\xef\x82\x96\x42\x8e\xd7\x4e\x23\xe4\x78\xad\x8e\x90\xe3\xb5\x61\x84\x1c\xaf\x0d\x23\xe4\x78\x85\x1c\xaf\x90\xe3\x15\x42\x5f\x1f\x9d\x6b\x3f\x43\x5f\x49\xc8\xf1\x72\x23\xe4\x78\xbd\x88\x00\x3f\x12\x72\xbc\xb6\x1a\x21\xc7\x2b\xe4\x78\x35\x19\x21\xc7\xeb\xa5\x98\x4b\x42\x8e\x57\xc8\xf1\xfa\x7c\x04\xdd\x90\xe3\x15\x72\xbc\x42\x8e\x57\xc8\xf1\x7a\x70\x15\x21\xc7\xeb\x25\xa8\x80\xbe\x0f\x70\xfb\x9c\xa5\xde\xa9\x48\xb3\x5c\x03\xb9\xf2\x53\x16\x52\xa4\x25\x0c\x4c\x55\x25\x82\xf6\x21\x84\x91\xe0\x13\x36\x75\x94\xfd\xd8\x36\xdf\x1d\x14\xdf\x33\xa8\x34\xbc\x7d\x86\xf1\x83\x09\x4b\x59\xb3\x44\x32\xb2\xb2\x31\x6f\x71\xae\x8a\x5f\xc6\x9c\xa4\x94\xde\xe3\x11\xa1\xa9\xc8\x6d\xc3\xe2\xc8\xed\x5f\x01\x42\xeb\xbd\xda\xbb\x9d\x21\xdd\xa8\x38\x65\x46\xdc\xa8\x8b\xb0\x12\xaa\x35\x48\xfe\x86\xfc\xcf\xe1\xcf\x5f\xfd\x36\x38\xfa\xfa\xf0\xf0\xa7\x57\x83\xbf\xfe\xf2\xd5\xe1\xcf\x43\xfc\xc7\xef\x8f\xbe\x3e\xfa\xcd\xff\xf1\xd5\xd1\xd1\xe1\xe1\x4f\xdf\xbf\xfb\xf6\x66\x74\xfe\x0b\x3b\xfa\xed\x27\x9e\xa7\xb7\xf6\xaf\xdf\x0e\x7f\x82\xf3\x5f\xb6\x9c\xe4\xe8\xe8\xeb\x2f\x1b\x2f\xb9\xb5\x48\xdc\x9d\x40\xdc\x91\x38\xfc\x51\x84\x61\xe7\xd0\xed\xe8\x2c\xba\x60\x94\x95\xd3\xe8\x18\xd6\x43\xa7\xd1\x53\x53\x14\xf3\x8a\x79\x98\x22\x22\x65\xda\x08\x87\x46\x1e\xa4\xd5\x70\x56\xa6\x6b\x4a\xa9\xa3\x03\x18\xd0\x4d\xb5\x6d\xaf\x5e\x84\x82\x56\x82\x58\x84\x97\xfc\x5c\xff\x79\x96\x66\x09\xb6\x35\xc7\xf3\x3c\xf0\xb1\x2c\xc8\x5c\x03\x6d\x78\x7c\x04\xda\xf0\x12\x69\x83\x82\x28\x97\x4c\x2f\x4e\x05\xd7\x70\xdf\xc8\xc2\x52\x27\x0d\xd7\xf5\x09\x5d\xcc\x98\xcb\xe2\x76\xd7\x88\xc8\x6c\xdc\xf7\x52\x3a\xfd\x4c\xe4\x49\x8c\xc9\x1c\x39\x47\x05\xd3\x66\xe9\x81\xb6\xda\x1f\xea\x3d\x18\xca\xbd\xfc\x12\xaf\xcf\x59\x35\xf3\x5f\x39\x9b\xd3\xc4\x68\xbb\xe5\x13\x23\xd4\x60\xaa\x0f\x6d\x7b\xe6\x35\x55\xb7\xe5\x81\x87\x81\x91\xa1\x8b\x35\x1f\xfb\x4f\xc2\x9f\xe0\x5e\x3f\x47\x29\x0d\x05\xa4\x91\x64\x73\x96\xc0\x14\xce\x55\x44\x13\xa4\x6b\xdd\xf0\x8a\x93\x0d\xb3\xe3\xc6\x4b\x91\x28\x72\x37\x03\x43\xab\x09\xf5\x26\x00\xcc\xb0\x9b\x52\xc6\x49\x6a\xb6\x28\xf3\x0f\x2b\x6b\x4b\x30\xe4\x3f\xa3\xd2\x6c\x70\x61\x33\x40\x15\x79\x2c\x44\xe2\x32\x1e\x92\x45\x39\xbf\xcb\xfd\xe1\xe2\x57\x0e\x77\xbf\x9a\xd9\x14\x99\x24\x74\x5a\x98\x0a\x14\xe8\x15\x6b\x5f\x39\xf5\xc6\x0f\xc0\x74\x82\x1c\x08\x4d\xee\xe8\x42\x95\x86\x93\x4a\xdd\x07\xf5\x86\xbc\x3e\x42\x74\xa6\x8a\x14\x73\xc4\xe4\x0f\x47\xe8\xfe\x3b\x3d\x19\xfd\x7a\xfd\xf7\xeb\x5f\x4f\xce\xde\x5d\x5c\x92\x4b\xa1\xc1\x32\xb5\x4a\x73\xc0\xa8\xd0\x30\xcc\x2a\xf1\x1d\xa8\xa5\x0b\x35\x44\xdb\x25\x53\xe4\x8e\xf1\x58\xdc\xa9\xc6\x36\x5a\x8b\x7e\x06\x78\x40\x79\xa3\x39\x22\x9a\x51\xec\x79\xd8\x82\xc3\xac\x44\x98\x54\x27\x45\x1e\x1e\xc7\xc7\xb1\x14\x99\x05\x82\x37\x72\x95\xac\xb6\xae\x46\x57\x63\x58\x71\x7f\x27\xf5\x09\xa7\x92\x72\x5d\x5a\x7b\xca\x3d\x73\xcd\x16\x87\xad\xb7\xe3\x79\x67\x34\xd1\xb8\xbb\x6c\xa6\x93\x38\x86\xb8\x06\xfe\x17\x17\x39\x78\xea\x3f\x6e\x51\x56\xa9\x20\xa3\xf7\xd7\x17\xff\x7b\x09\x8f\x17\x59\xbb\x40\xa9\x6e\x32\x63\xa5\xc8\x3a\xdb\xdd\x2b\x97\x79\x19\xf6\x77\x2f\xf6\xb7\xe0\x96\xdd\xb8\xe7\xaf\x72\x5e\x2f\x64\x54\xce\x4f\x52\x11\xc3\x90\x8c\x0a\x3f\x41\xfd\x6a\xa5\xc0\x01\x95\x40\xcc\x2d\x5c\x33\x9a\x24\x8b\xaa\x88\xa6\x85\xcd\x42\xac\xd5\x66\xa8\x12\xf2\x09\x4d\xd4\x53\x53\xe3\x36\xbc\xd1\xc8\x11\xef\x8c\x3e\xdc\xc9\x76\x14\xb3\x91\x18\xb8\xd0\x4e\xb0\x36\xab\xc4\x7a\x17\x52\x44\xc4\x2a\xdf\x95\x60\xac\x1a\x7f\x53\xd6\x57\xe1\x59\x23\x53\x1e\xd8\xa3\x62\x66\x6b\xa8\xce\x15\x2c\x0b\xe8\xbe\x0f\x71\xa1\x8e\x9b\xd9\x25\xd0\x58\xf0\x64\x81\x91\x97\x36\x96\x22\xa5\xea\x16\x62\xfb\x83\x13\xcd\x0a\x4f\x85\x99\xb1\x78\xd5\x8d\x59\xb7\x77\x4b\xa0\x48\x66\x23\x3c\xd0\x9d\x01\xf1\x13\xef\x7a\x8b\x43\x68\x80\xf2\x9e\x27\x8b\x2b\x21\xf4\x37\x45\x1a\x6d\x27\x18\xf0\xa3\x93\x96\xeb\xa6\x68\x14\x27\x29\xbe\x77\x80\xbb\x81\x87\xaa\x9a\xc1\x7b\x56\xee\xf8\x73\x3f\x52\x32\xe7\x27\xea\x5b\x29\xf2\xc6\x4c\x6c\x45\xd8\xfc\xf6\xe2\x0c\x49\x51\xee\x5c\x95\x5c\xcb\x05\x96\x0e\x58\xad\xfa\x56\x28\x06\x3f\x38\x67\x6b\xf5\x4c\x94\x7e\x31\xf2\x8e\x2e\x08\x4d\x94\xf0\xb0\x64\x7c\xad\x16\xea\x54\x5c\x73\x79\x2c\xf4\x6c\x45\xb7\x35\x07\x6a\xf5\xb9\x7e\xc5\x73\x59\x96\xa1\x63\x7c\xe5\x71\x4d\x6f\x41\x91\x4c\x42\x04\x31\xf0\xe8\xa9\xb7\xfd\xa9\x1d\x7e\x88\x3a\x97\x82\x9b\x83\xd9\x09\xf2\x5c\x14\x9e\x5e\x07\xd2\x2a\xaa\xa0\xcf\xd8\x69\x7f\x14\x3d\xc7\x78\x2c\x73\x05\xd2\xba\xb9\x65\x0e\x76\x27\xbf\xcf\xc7\x90\x18\xc8\x1b\x95\xd4\x75\x8a\xb7\xe6\x0c\x96\xd2\x29\x10\xaa\x0b\x4c\xd3\x82\x00\x57\x86\x62\x5a\x03\xa8\x26\xb1\x80\x32\xfb\x9e\x2a\xf2\xc3\xc5\x19\x79\x45\x0e\xcd\xbb\x8e\x10\x7f\xb0\x91\xbc\x16\x36\xc8\x6d\x59\x47\x9d\xf8\x29\x70\x49\x88\xbc\x44\x48\x4b\x24\xfa\x84\x0b\xa2\xf2\x68\x56\xed\x5e\xef\xd5\x66\x17\x08\x89\xae\x95\xfd\xc4\xf5\xa7\xa5\x50\x3f\x28\x90\x9d\x11\xa8\x1f\x1a\x10\xa8\xaa\x18\x65\x70\xae\x0e\x3d\x8b\x58\x29\x68\x1a\x53\x4d\x1d\xe1\xf2\x37\xec\xed\x96\x7e\xde\xe4\x4b\xc1\x5b\xc6\xf3\x7b\x1b\x78\xd4\x9d\xa9\xe5\xfa\x1c\xa7\x25\x91\x87\x3a\xee\x3a\xcd\xb2\x84\xd9\x6a\x1b\x4b\x81\x70\x17\x35\x5c\xe9\x6f\x10\x13\x91\x4e\xd0\x24\x11\x86\x3e\x1a\xe1\x84\xf2\x58\xa4\x2b\x2f\x33\x42\x24\xd4\xea\xa5\x0e\x49\xc0\xbe\xfa\xd8\x13\xa3\x50\x02\x73\x68\x51\x5b\x6c\xb9\x3e\xac\x99\xcd\x00\xc7\x63\x04\x4e\x4f\x12\x3a\x86\xc4\xc2\xd8\x62\xa0\x5a\xc5\xc0\xa7\x8e\x46\x95\x22\xe9\x2e\x7d\xe6\x4a\x24\x60\xc3\xbb\x3c\x20\xcc\xf4\xcf\x02\x0e\x38\x49\x57\x70\x40\x6d\xb0\x06\x07\xd4\x6b\x9f\x03\x1c\xf2\x16\xac\x9e\x2c\xc3\xc1\xc8\x0d\x75\x38\x20\xf3\xde\x77\x38\x28\x88\x22\x91\x66\x23\x29\x8c\xda\xd9\x19\x6f\x72\xd3\x96\x3e\x43\x6b\xd8\x58\x13\x8c\x85\xbc\xa0\x7e\x33\x95\x95\xc0\x4e\xaa\x2d\x93\xf0\xd1\x9d\xff\xab\xc2\xb3\x90\xf4\x2c\x33\x32\x3f\x4b\xcd\xbd\x68\x9e\x74\x17\x9e\x33\x3b\xe8\x22\x37\xa2\x85\xb1\xb3\x13\x6e\x24\x22\x9a\x60\xed\xd8\x76\x28\x47\x96\xd1\x6e\x79\xe2\x4a\x38\x2f\xfa\x28\xf1\x37\x1f\x40\x82\x65\x44\xf1\x17\x67\xc2\xe4\x22\x86\x8a\x2f\xdb\xc6\x21\xdf\xd8\xb0\x4f\xbc\xcf\x47\x12\x1b\xb9\xc2\xbb\x95\xe3\xda\xd3\x5a\xb8\x0a\x68\xef\x8a\x8a\xb4\x66\x81\xc0\x63\xc6\xa7\x68\x57\xeb\x13\x09\x89\x8d\x41\x76\x44\xe0\xd6\x6a\x90\x3d\x3c\x12\x7e\x52\x7f\x1e\xfc\xab\x51\x16\x63\x82\xbb\x99\xd1\x52\xe4\x25\xac\x89\x25\xb7\x4c\x91\x83\xb7\x1e\x00\x2d\x4a\x78\xee\x23\x87\x39\xb0\x5f\x58\xec\xa6\xb5\x74\xde\x32\x1e\xbb\x70\xdd\x1a\xb0\x8a\x62\xeb\x56\x0e\xc6\x40\x70\x16\x57\x69\xcb\x1b\xf2\x33\x27\x05\xb0\xc8\xa0\x31\x7a\x5c\x59\x91\xd9\xdb\xe8\x06\x0f\x1b\x5e\x8b\x97\x2c\x4f\xf3\x03\xc7\xbd\x37\xef\x1d\x18\xcd\x7d\xf5\x3e\xff\x2d\x4f\x5a\xba\xc7\x51\xbf\xae\xb5\x98\x1f\xed\xb4\x5e\xa4\x8f\x0c\x5a\x6b\xc6\xa7\xaa\xaa\xc9\xd0\x24\xa9\x19\xc3\xd7\xa9\x32\x7e\x87\x8b\xd2\xfa\xab\x2a\xc4\x52\x9a\xc1\x73\x51\x43\x12\x23\x4e\x3c\x73\x25\x64\x9a\x2a\x7a\x2a\x0d\x24\x34\xa3\xc9\x75\xd6\xbc\x44\x29\x59\x29\x87\xf7\xee\xfa\xa4\x3e\x35\x32\x6b\xec\xfc\x60\xf6\xca\x5c\x27\x34\x4e\x99\x52\x68\x08\x83\xf1\x4c\x88\x5b\x72\xb8\xa6\x1e\x57\x25\x4e\x4b\xb1\xa9\x3a\x76\x38\x3f\x30\xab\x3f\x22\x8c\x27\x45\x54\x14\xea\xc1\x5c\x2b\x6f\xc8\xc1\x97\x44\xc5\x2a\x70\x0f\x5d\xdd\x6a\x17\xac\xb0\xba\x4c\x5b\xa9\xda\x60\xc1\x93\x13\xec\xd5\xed\xb9\x6c\x59\x76\xe5\x91\x2d\xba\x74\xb8\xbd\x5c\x59\x6d\x2d\x1c\xad\xf4\xf8\xe4\x40\x72\xc2\x45\x04\xaa\xbb\x82\x4e\xdf\x95\x73\x92\x18\x6c\x16\x0f\x60\xf4\x13\xdd\x18\x64\x87\x76\xe9\x1e\x26\x83\xba\x47\x7b\x55\x89\xfa\xa6\x24\x2e\x46\x1f\x49\xb2\x19\x1d\x58\x25\xdd\x50\x34\x24\x81\x5e\x84\x98\x09\x2e\x5c\x92\x84\x61\xa2\x82\x23\x4a\x23\x89\xb2\xde\x3c\xdc\x13\x47\xa2\x2b\x4b\x3d\x2d\xbd\xc4\x55\x47\x20\x26\x93\xd9\xfa\x11\xe5\x1a\xee\x98\x9e\xf9\x4e\x2f\x35\xaf\x21\xae\x44\x82\x42\x07\x0c\x27\x20\xa5\x90\x2e\x20\xcb\xdb\xad\x71\x26\xa4\xe4\x18\xd1\x65\x90\x84\x9a\xbf\x7a\xaa\xea\xa8\x2e\x4b\xc1\x63\xbc\xa2\xc1\x26\x98\x4c\x20\x42\x41\xab\x0a\x60\x4b\xb5\x0f\xcb\xc2\xb7\x2e\xcb\xc0\x20\x98\x2b\x25\x9f\xb2\x7b\xf3\x96\xea\x53\x55\x97\xb8\x2b\x38\xbb\xfe\xf2\xd1\x90\x90\x0b\x5e\x44\xf0\xf6\xcd\x2e\x56\xef\xf4\xa1\x67\xda\x7c\x62\xb5\x0f\x01\x7e\x40\xd5\x70\x66\xa4\x43\x99\x77\x80\xf1\x6d\xcc\xe1\xa4\x6a\x12\xef\x94\x1c\xa0\x69\xdc\x4d\x6a\xb6\xde\xcb\x00\x6d\x4c\xe5\xe6\x96\x8f\x65\x2e\x7f\x1e\x0e\x10\xd2\x96\xce\xb9\x6a\x0a\x1d\x15\x87\xbf\xae\xcc\x56\x91\xde\x0b\x87\xdb\x48\xc4\xb6\x9a\x4a\x51\x0d\x02\x7b\x3a\x61\x75\x17\xf6\x6f\x2f\x9f\x95\x32\x1e\x17\x36\x3b\xa0\x5a\x66\xc5\x95\xd4\x8e\x89\x11\xb5\x13\x6f\x5b\x48\xb3\x04\x30\x8b\xb3\x32\x73\x99\xa0\x5a\xa9\x26\xdf\x2f\x16\x52\x16\xa4\x77\xc5\x5d\xfa\xe4\x9f\x78\x28\x8b\x40\x54\x5f\x77\x62\x54\x3c\x6e\x35\x44\xa6\x7c\x6b\x09\xcc\xb0\xd4\xc2\x9b\x2e\x48\xcc\x26\x13\xf0\x01\xaf\x46\x73\xa4\x92\xa6\x86\xc4\x2b\xe2\x40\x30\x86\x29\xb3\x01\x91\x05\x61\xeb\x19\x71\xcf\xe5\xfa\xf5\x2d\x31\x64\x9a\xa4\x6c\x3a\xb3\x88\x42\x28\x66\xe8\x12\xef\x54\x4c\x04\x8d\x09\xe2\xb6\x90\xe4\x8e\xca\xd4\xf0\x0d\x1a\xcd\xd0\x43\x49\x39\x89\x73\x89\x55\x96\x35\xd0\x78\x31\x50\x9a\x6a\x23\x29\x83\x74\x0a\xa5\x5f\x7f\x28\xa9\xff\xe0\x08\x25\xf5\xb7\x1c\xa1\xa4\x7e\x28\xa9\xbf\x3a\xf6\x26\x3a\x34\x94\xd4\x7f\x59\x65\x92\x42\x49\xfd\xa7\xf6\x26\x84\x92\xfa\xa1\xa4\xfe\x43\x23\x94\xd4\x7f\x64\x84\x92\xfa\x0d\xc6\x0b\xa0\x5c\xa1\xa4\x7e\x83\x11\x4a\xea\xaf\x1f\xa1\xa4\xfe\xea\x08\x25\xf5\x37\x8e\x50\x52\xbf\xf1\x08\x25\xf5\x43\x49\xfd\x50\x69\x74\xb7\xb9\xf6\xb3\xd2\x28\x09\x25\xf5\xdd\x08\x25\xf5\x5f\x44\x3d\x45\x12\x4a\xea\x6f\x35\x42\x49\xfd\x50\x52\xbf\xc9\x08\x25\xf5\x5f\x8a\xb9\x24\x94\xd4\x0f\x25\xf5\x3f\x1f\x41\x37\x94\xd4\x0f\x25\xf5\x43\x49\xfd\x50\x52\xff\xc1\x55\x84\x92\xfa\x2f\x41\x05\x54\x3a\x66\x8d\x2a\x80\x6e\x53\xac\xc8\x05\xa1\x57\x6a\x03\x8c\xf3\xc9\x04\x24\x52\x2e\x7c\xf3\x4a\xf0\x54\x59\x97\x71\xd9\xc9\x0a\xba\x8f\x75\x8f\x5c\xbe\xce\x86\xc7\x5d\x31\x02\xac\xd4\x59\x46\x8a\x9f\xbf\xff\x66\x4d\x65\xa4\xc6\x51\x85\x4d\x63\xa4\x71\xcd\xef\x79\x33\xff\xf8\x06\x80\xaf\xcb\x1f\x73\x70\x8f\x12\xa1\x5c\x84\x3b\x02\x2b\x9a\x51\xce\xc1\xeb\x7b\x4c\xa3\x1d\x65\x0c\xc0\x89\xc8\xc0\x79\xa7\x29\x51\x8c\x4f\x13\x20\x54\x6b\x1a\xcd\x86\xe6\x4d\xdc\x03\xbb\x8c\x46\x77\xbf\x28\x2d\x81\xa6\x3e\x2e\x3f\xa5\xcc\x4e\x45\x68\x24\x85\x52\x24\xcd\x13\xcd\xb2\x62\x32\xa2\x00\x13\x6a\x2c\xa3\x2a\x80\x81\x51\x71\x65\x08\x7b\xbf\x7c\x9b\x5b\x96\xa8\x96\xa6\x43\x6d\xb3\x8f\xf5\xc0\xd3\x4c\x2f\x8a\x38\x5e\x20\x13\x26\x95\x26\x51\xc2\x90\x5b\xe3\x1b\x6d\xee\x34\xce\xd7\xf7\xbc\x9a\xbb\x95\x2a\xb7\x54\x1e\xa3\xd8\x9a\x69\x65\xa3\x62\xcb\x09\xdd\x54\x31\x53\x4e\xcc\x57\x7d\x42\x7d\xdd\x34\x0b\x68\xbf\x52\x04\xb5\xe7\x2c\x76\x76\xf7\x53\x65\xba\x4a\xbd\xd8\x32\x6c\xb8\x44\x74\x4c\x71\xf0\xc8\xd9\xaf\x65\x73\x94\x02\x05\x46\xe9\xad\x1c\x03\xdc\x00\x0e\x73\x83\x03\x10\x81\xe1\xaf\x74\x03\xd6\x7f\x72\xa4\xaf\x30\xc5\x77\xa0\x14\x9d\xc2\xa8\xa1\xa3\x61\x93\x46\x86\xbe\x86\x72\x63\x10\x15\x12\x9b\x5d\x5b\xfc\x52\x46\x67\xd6\xc5\x20\x92\xda\x35\x15\xc2\xcf\x9d\x64\x5a\x03\x6e\x2a\x56\xd8\x43\x5f\xe5\x72\x02\x7e\x6f\x29\xc6\xf3\x9d\x9f\xa4\x7c\xd8\x10\x75\x1e\xdb\x88\xcb\x31\x90\xb1\x64\x30\x21\x13\x86\x61\x9c\x18\x58\xd9\xb7\x05\x97\xa8\xb5\x02\x28\x65\xf4\x5d\xc1\xbd\x2c\xeb\xd7\x35\x24\x3f\xba\x85\x69\x99\xf3\x88\x56\x6a\xd9\x62\x86\x29\x9b\x90\x29\x06\x66\x3a\x69\xf1\x4f\xaf\xfe\xfa\x67\x32\x5e\x18\x96\x86\x92\x95\x16\x9a\x26\xc5\x47\x26\xc0\xa7\x06\x56\xf6\x78\xd6\x73\x24\x0b\x08\x60\x37\x0f\xbb\xf0\xd7\x7f\xb8\x1d\xd7\x79\xec\x71\x0c\xf3\xe3\x0a\xfc\x06\x89\x98\xae\xeb\x8f\xd2\x3c\x64\xbb\xa1\x4a\xb4\x06\xcd\x44\xc2\xa2\x45\x6b\x44\xf3\x95\xbf\xc8\x4c\xdc\x59\x59\x7f\x0d\xf6\x94\xe9\x56\x99\xc8\xf2\xc4\x1a\x9d\xbf\x29\xb2\x8b\x73\x05\xab\x39\x80\x6b\xcf\x05\x9a\x49\xdd\x14\xcb\x75\xd3\x6d\x3c\xae\x7f\xa5\x70\xb9\x25\xce\x90\x57\x14\x00\x43\x45\xe8\x1b\x9a\x24\x63\x1a\xdd\xde\x88\xb7\x62\xaa\xde\xf3\x73\x29\x85\xac\xaf\x25\xa1\x86\x5a\xce\x72\x7e\x6b\x3b\x38\x14\x25\x12\xc4\xd4\x88\x56\x59\xae\x7d\x22\xc3\xba\x0f\xb6\xf9\xf2\x9e\x08\x7b\x35\xa8\x9c\x05\xee\x59\xa9\xeb\xb8\x54\x2d\x8b\x91\xd5\xf9\x55\x15\xd9\xfe\xf0\xea\x4f\x7f\xb1\xa8\x4b\x84\x24\x7f\x79\x85\x31\xdb\xaa\x6f\x0f\x31\xd2\x36\xc3\x28\x52\x9a\x24\x46\x6d\xa8\x22\xa5\x01\xf4\x3a\x24\xfc\xe4\x38\xa8\xdb\xa3\xdb\xd6\xa2\xd4\xcd\xcd\xdf\x51\x8e\x62\x5a\x41\x32\xe9\xdb\xac\xa4\x42\xad\xe9\x21\x63\xe8\x39\xea\x83\xa9\x61\x7b\x20\x00\xcd\x45\x92\xa7\x70\x06\x73\xd6\x45\x13\xa7\xda\x6c\x5e\xd5\x4f\x98\xc2\x04\xb0\x71\x22\xa2\x5b\x12\xbb\x8b\x95\xc8\x93\xe5\x4a\xe0\xcd\xa1\xd0\x34\x06\xa7\x45\xec\xcd\xc6\xef\xaf\x45\xdd\xa4\x34\xcb\x8a\x1c\x21\x49\xef\x6a\xc0\xc0\x33\x89\xe5\x0a\x5a\xd6\x93\x69\x6d\x66\x6e\x6b\x64\x1e\xb8\x2f\x32\x74\xb3\xf1\x14\x8d\xa3\x4e\xda\xdb\xa8\xcb\xd5\x37\x37\x4c\xd6\x10\xa2\x9c\xd0\x9f\x86\x0c\xff\x6d\xb3\x4a\x56\xb2\x22\x8b\xc4\xba\x02\x31\xac\x00\x60\xd0\x07\x49\x72\x73\x83\x6b\x07\xd6\xcd\x76\x21\x47\x35\xb8\xf0\xc2\xaa\x9c\x52\xed\x04\x42\x6f\xbe\xa6\x24\x03\xa9\x98\x32\x7c\xf9\x03\x1e\xa8\xd3\x84\xb2\xb4\x62\x02\x7c\x1a\x20\xd8\xc3\x8d\xe5\x93\xdb\x53\xca\x91\x88\xdd\x84\x48\x0a\x6d\xe9\xe8\x35\x62\x6d\x5d\xaa\xed\x90\xa1\x3e\x35\xa9\xfc\x50\x42\xb3\x4e\x29\xcd\x2f\x05\xa9\xb4\x77\xbd\x24\x02\x89\xdf\xf7\x5c\xe9\x63\xb1\xf8\x8e\xc8\x00\x12\x46\xb7\xb9\x75\x4a\x58\x53\x1e\xed\x41\xa9\x88\xf4\x4e\x0f\x1c\x12\xeb\x05\x37\x67\xc2\x3d\x4a\x7a\x6f\x7a\x4f\x4a\x24\x2d\x88\xa4\xc8\xe8\xb4\x55\x2f\x9f\x25\x48\x2d\x4f\x5b\x2d\x34\x61\xd4\x20\xbc\x5e\x94\x5d\xc3\xbb\x20\x2e\xeb\xe8\x60\x95\x24\xeb\x1d\xf5\x00\x76\x0a\x82\xcd\xc7\xbe\xa3\x0b\x42\xa5\xc8\x79\xec\xec\x4b\x85\x81\xef\xdd\xd2\x8b\x2f\x05\x07\x6f\x38\x5f\xae\x53\x81\x16\x7d\xc6\xc9\xeb\xe1\xeb\x57\x2f\x85\x53\xe1\x17\x2e\x71\xaa\xcb\x82\x53\x59\xfa\xf4\xa4\xdf\xea\x2b\xde\x77\xf4\xbd\xef\x9c\x89\xa5\x2c\x68\xcf\x7c\xb9\x6c\xfc\xe9\x4e\x32\x0d\x95\x1e\x7f\x87\xa8\xb8\x18\xfd\xb0\x52\x95\xe1\x68\x5d\x27\x89\x96\x40\x6a\x57\x06\x43\xe5\xe3\x8f\x48\xb7\x1c\x81\xc2\xe3\xb6\xce\xc2\xa5\x1e\x20\x61\x55\x40\x1d\x1c\x90\x43\x7b\x67\xcf\x26\x34\x1f\x3d\x29\x6a\x39\xa0\x9d\xdf\x67\x2d\x6a\x6c\x2e\xe5\xce\x67\x14\x6d\x70\x59\x87\x10\xfc\x6f\x98\xd1\x39\x60\x22\x37\x4b\xa8\x4c\xd0\xe7\x78\x6d\xd7\x4e\xc6\xb9\x26\xc0\xe7\x4c\x0a\x9e\x02\xd7\x64\x4e\x25\xc3\xaa\x38\x12\xb0\xb2\x83\xd1\x45\xbf\x3c\xfc\x70\x72\x85\x01\x0d\x47\xae\x24\x85\x5b\x65\xae\x7c\xf9\x9a\xea\x4a\x2a\xd3\x3d\xba\x7d\x7e\x1d\x06\x86\x48\x73\xfd\xba\xcc\x7b\xd2\x5c\xe7\xb6\x2d\xcb\x7d\x94\xe4\x8a\xcd\x9f\x8a\x92\xb8\x0c\xfb\x33\xd6\x68\x9f\x97\xb2\xfd\x4b\x40\xad\x24\xee\xa3\x69\x7d\x4d\x82\xde\x8a\xc3\xa4\xa7\x8a\xa4\xbd\xaa\x0f\xdc\x99\x9e\x5c\x2d\x0d\x1b\x3e\xe7\x2b\x2e\xae\x88\x10\x58\x37\xe6\x69\x8d\x50\x31\x57\xa7\xb8\xc2\xdd\xc0\x5a\x0f\x48\xae\xe5\xf1\x9d\x5d\x5e\x57\x8b\x90\x58\x75\x49\xc4\x43\x32\x2a\x7f\x2c\x2b\xd5\x60\xfd\xb4\x42\x89\x04\x39\x2d\x8b\x8a\x4f\x81\x83\x44\x21\xc1\x4c\x59\x6b\xab\x4a\xc6\x54\x59\x27\xcf\xd9\xe5\xb5\xb5\xd9\xee\x06\xb3\xc6\x62\x76\x73\x09\xd5\x70\x7c\x9b\xc6\xd0\x40\xb8\xad\xf7\x4c\x2b\x0c\x56\x06\x30\xa8\x94\xda\x89\xc9\xc5\x88\xd0\x38\x96\xe8\xf6\x71\xa2\x4f\xa5\x52\x65\xe1\x5b\xc0\xaa\x30\x54\x41\x75\x4d\x15\x70\x23\x89\x2b\x01\x4b\xce\xf2\x2c\x61\xd6\x8d\x50\x7d\xa0\xac\x66\x83\x4d\xbe\x76\x47\xda\x36\x6a\x5e\x63\x25\xaf\x05\x15\x12\x4d\x8b\x52\x3e\xb0\x7b\x12\x94\x48\xe6\x65\x41\xe1\xa5\x5d\x73\x27\x02\x4d\xe2\xc5\xae\xf9\x1a\x94\x5b\xed\x18\x70\x2d\xcd\xd1\x5c\xde\x2d\xec\x62\x9f\xe4\x78\x9a\x8a\x09\xd9\x1c\xd0\x3f\xee\xca\x6f\xba\x32\x6e\x65\x89\x63\xeb\x1b\xb6\x55\xa6\x81\x4a\x4f\xd1\x70\x55\x0d\x4f\x22\x79\x2a\x44\x58\x36\x76\x9c\x5d\x5e\x5b\x4a\x68\x3f\xbe\xe8\x4e\xbb\x6e\x97\x4a\xaa\xd6\x18\x03\x9f\xac\xca\x50\x1b\xcd\x63\xa9\xb9\x9f\x6b\xd7\xdd\x2a\x90\xa5\x85\xf8\xd7\x2a\xd9\xae\xc5\xdb\x15\x50\x19\xcd\x9a\xc0\xff\x01\x42\x60\x27\x25\xb1\xb0\x91\x00\x13\x21\x51\x25\x1e\x20\x79\x4f\x84\xb8\xcd\xb3\x6d\x28\xba\x9b\xc6\x36\x5c\xdb\x8a\x40\xd4\x9e\xf8\xac\x68\x7a\xcc\x55\x13\x7f\x6f\x5d\xf6\x01\x6d\x25\x1e\x9c\xa8\x4c\xa0\x10\xcb\x7a\xd3\x69\x92\x2b\x0d\xf2\x1b\x26\x95\x3e\xf0\xf5\xa2\x11\x83\xad\x4d\xa4\x57\xbd\xe1\x47\xa6\x67\xae\x74\x63\xaf\x5f\xbf\x64\xfe\x76\x13\xf7\x8c\x4e\xdb\xbb\x14\x1c\x7a\xc3\x65\xb1\xab\x20\xe5\x05\x59\xdb\xc8\x53\xdc\xd2\x15\x24\x36\x5e\x14\x2f\x54\x70\xe5\xc6\x95\xad\x34\x6f\xf0\xf4\x4f\x81\x26\x14\x4b\xc4\xe1\xdd\xb3\xb2\xcc\xa4\xad\x1b\x65\xeb\x64\x0a\x27\xe8\x2d\xaa\x20\xaa\x94\x92\xd2\x62\xf3\x67\x37\x91\xe7\x76\xc6\x00\x5b\x7e\xd4\xd5\x0b\x79\xcb\xf8\xed\x8e\xe8\x57\x8f\x2e\x39\x5f\x99\xad\x56\x4f\xdc\xfa\x68\x19\xb7\xc1\x77\x86\xc5\xd0\xb1\xc8\xb5\xaf\x49\xa2\x2a\x8a\x23\xe3\xff\xb4\x7b\x81\xf6\xf6\xcc\x56\xec\x5b\xa7\x23\xaa\xbe\x35\xfa\x78\x25\x50\x2d\xb8\xa6\x58\x5b\xf4\x4c\x44\xb7\x20\x49\x62\x96\x31\x24\x65\xe0\x4b\xad\x9a\xa5\xcc\x61\xc7\xa8\x8b\xa6\x96\x0e\xc8\x66\x90\x82\xa4\x49\x59\xd4\xb5\x05\xa8\xdf\x3a\xc2\x59\xcc\x5a\x8d\x49\xb1\x45\xd1\x5c\x19\x46\x73\x0e\xcf\xd7\xdd\x95\xd2\x85\xaf\x74\xcb\x38\x86\x1b\xdc\x33\x85\x66\xfd\x4c\xc4\xd5\xc4\xb3\x5c\x81\x1c\x14\x69\x81\x2e\xf7\x46\x15\x81\x38\x31\x8c\xf3\xe9\x94\xf1\xa9\xa3\xce\x48\xd3\x2b\xe5\xb6\x0b\x4d\x07\x23\xbd\x23\x09\xb6\xe0\x2c\x4a\x0f\x36\xbe\x8c\x55\xef\x4f\x45\x6c\x6f\x1f\x2f\xac\x36\xe8\x77\xb6\x0c\x90\xbe\xe0\x44\x48\x57\x1a\x81\xc6\x31\xae\x7d\xf5\x0b\xf1\x6a\xfd\xab\xfa\x45\x1c\x87\x8d\xec\x2e\x9e\xaa\x80\x45\xe5\x63\x23\xec\xe4\x32\x82\x75\xb6\xd3\x4a\x89\x5f\x3a\xa7\x2c\x41\x3b\x85\xe0\x24\xb2\xa7\xd8\xc5\x9a\x99\xd3\xcf\x7b\x18\x05\x87\xcd\x3a\xf1\x9d\xe7\xab\x18\xd0\xa2\x44\x55\x53\x3e\xd3\x88\xc7\xd4\xcb\x0b\x9d\xf0\x35\xdf\x62\x03\xc6\x35\xa4\x99\x90\x54\x2e\x96\x3d\xa6\x86\x26\x1a\x8c\x33\xfb\xb5\xb4\x31\x23\x11\x23\xdb\x58\x83\x67\x73\xdb\x38\x78\x0d\xaa\xad\x45\x69\x24\xba\x5c\x10\xbf\x81\x86\x3d\xa8\x68\x06\x71\x8e\xc1\xea\xd3\x9c\x62\x63\x73\x43\x34\x9c\x6d\x7d\xe1\xa2\x00\x2d\xee\x15\xf1\x85\x45\x56\xc2\x02\x63\x72\xb0\xe8\xa7\xf9\x05\x8b\x87\xda\x48\x44\xdb\xd7\x19\x7b\xbc\x16\x41\x89\x37\x65\xab\x09\xfc\x58\x98\xb3\x48\xfb\x87\x26\x9b\xf0\x34\xa2\x45\x3b\xd9\x91\x70\xc5\x06\x23\x30\xb4\x4f\xab\xf2\x53\x5c\x10\x0b\x96\x13\xfd\x99\x1b\x9e\xb4\x19\xf5\x4b\x3c\x7f\x04\xc3\x51\x8c\xaf\x6f\xc5\x03\xd4\xa2\x80\xd2\xba\x6f\x37\x6b\x5a\xca\x1b\x70\xb8\xdd\xf9\x39\xd9\xb5\x0e\x54\x0b\x7d\xa3\xb9\x33\xb1\x91\x13\xb0\x8d\x6a\x43\xe5\xb4\xbd\x1a\xd8\x3b\x91\xd3\x3c\xb5\xe5\xc9\xc5\x52\x85\x68\x8b\xdf\x68\xb2\x33\xdc\xf8\xf4\xdd\x59\x35\x3b\xa3\x1a\x76\xee\x73\x5b\x8c\x94\xd7\xd2\x94\xbb\x6c\xcb\xbd\x30\x7a\x67\x61\x20\x2e\xd9\x86\x53\x50\x9d\xb1\xb2\x78\x9b\x57\xd0\x19\xcf\x8c\xa0\x81\xe2\x51\x69\xae\xe4\xd1\x8c\xf2\x29\x5a\xf8\x45\x6e\xe6\xfb\xf2\x4b\x5c\x91\x84\x38\x8f\x5c\x4b\x0c\x1f\xda\xfd\xa5\x37\x6c\xba\xea\x44\xd8\x99\x4f\x45\x34\xf3\x6b\xae\x7e\x96\x95\x42\xde\x10\x36\x84\x21\x39\xf8\xb2\x72\xe9\xc0\xbe\x3d\x93\xc2\xbc\xc2\x45\x85\xe3\xaa\x12\xa6\xf1\xd0\x1d\x54\xef\x1e\x92\x73\xf3\x0e\x74\xf6\x14\x00\xac\x04\x2e\x8f\x4b\xf0\xf5\x89\x84\x29\x95\x71\x82\xc9\x84\x93\x42\xde\xb2\x29\x47\x0e\x60\x78\xd2\x31\x54\x90\x0b\xbd\xce\xf0\xba\x65\xc6\x87\xa6\xea\x56\x1d\x5b\x29\x6d\x10\x53\x4d\x07\xd8\x46\xc4\x12\xa8\x63\x6b\x39\x18\xb8\x02\xae\x03\xea\x70\x6a\x50\x6c\xeb\xf1\x17\x2e\x69\x6c\x40\x8b\xbb\x18\x1f\xd0\x01\x96\x52\x6d\x1e\x06\xfb\x04\x11\x13\xad\x94\xf8\x16\x75\x7c\x97\x25\xef\xa2\x8e\x3b\xc2\x00\xbb\xa0\x94\x75\xbb\x8b\xe0\x0c\x57\xaa\xb6\x76\x90\xcf\x2f\x6f\xae\xfe\x3e\x7a\x7f\x71\x79\x13\xce\x73\x38\xcf\xe1\x3c\xb7\x38\xcf\xc0\xe7\xad\xcf\x72\xa1\xda\xad\xd3\x76\x97\xea\xe6\x55\x92\xc5\x5f\x50\xdc\xd9\x39\x9f\x7f\xa0\x46\xb8\xcc\x24\x28\x94\x45\x8c\x8c\xba\xce\x41\xec\x6e\xb0\x8d\xc4\x4e\x9f\x7d\xe0\xd9\x13\x86\x8d\x75\x18\x8e\x73\x59\xa9\x71\xb0\x6e\xd7\xaa\x9d\xfb\x4e\x7f\xbd\x38\x3b\xbf\xbc\xb9\xf8\xe6\xe2\xfc\xea\x49\xe3\x28\x5a\xd6\xad\xab\x73\xe3\x86\x5c\x32\x93\x30\x67\x22\x57\xc9\xa2\x28\x7d\xbb\x9e\x08\xac\x86\xe2\x71\xa3\x0a\x2e\x8a\xea\xbe\x6b\x1f\x0b\xcc\xb6\x5b\x66\x5b\x0f\x2b\x69\x51\xb2\xa4\x2b\xf4\xfd\x46\x8a\xb4\x23\x14\xbe\xb6\xe6\x01\x6f\xcd\x5f\x87\x4f\x3d\x57\xdd\xa0\xc6\x7a\x9c\xf0\x58\x96\x52\x30\x52\x68\x9a\xe9\x16\x7d\x0d\x3a\xa9\x54\xda\x4d\x51\x4f\x1b\x82\xf1\x8e\x66\xdf\xc3\xe2\x0a\x5a\x56\x46\x59\xf2\xa2\x24\x10\x19\x46\x47\x6e\x61\x61\x9d\xab\xa7\xfe\x65\x6d\x2a\xb8\xec\x65\xa1\xd7\x5b\x68\x53\x84\xb7\xcb\x0a\xad\xb7\xd0\x22\x26\xd3\x8f\x95\x5a\xa5\x66\x0b\x51\x4e\x33\x7b\xda\x6e\xf7\x48\xb7\xd5\x59\x3f\x42\x45\xda\x5e\x95\xdd\x3b\x3a\xab\x77\x2e\x1c\x21\xe6\x86\x73\xc1\xdd\xb1\x8b\x47\x1b\x18\x8d\x75\x60\xb1\x56\x1d\x63\xd0\xcd\xf1\x17\xf8\x1f\x72\xf3\xfe\xec\xfd\x1b\x72\x12\xc7\x2e\x2e\x3a\x57\x30\xc9\x13\x6b\xa5\x57\x43\x42\x33\xf6\x01\xa4\xc2\xc6\x70\xb7\x8c\xc7\x7d\x92\xb3\xf8\xeb\x36\xf5\xa4\xec\xe8\x70\x17\x84\xf7\x45\x75\xbb\x13\xd7\xce\xd5\x58\xe5\x5d\x05\x11\x21\x36\xe9\x11\x71\xd3\x97\x96\x71\x42\x46\x47\xa0\x69\xdb\x03\x8f\xd8\x2d\xec\x96\xae\xf6\x4a\xc2\x6a\xdd\x38\x45\xed\xad\xf8\x0d\x51\x39\xd6\xc0\x51\x45\xe3\x3a\x6c\x05\xdb\xaf\xff\xa9\x32\x1a\x41\x9f\xfc\xa3\xf8\x11\x5b\xcd\xab\x9f\x7a\xbd\xbf\x7d\x7f\xfe\xf7\xff\xea\xf5\x7e\xf9\x47\xf5\x2a\xb2\x42\xd4\x9a\x97\x6e\x41\xd7\x15\x17\x31\x5c\xe2\x3b\xf0\x4f\x27\xae\x9d\x44\x91\xc8\xb9\x76\x17\x30\x61\x79\x38\x13\x4a\x5f\x8c\x8a\x3f\x33\x11\x2f\xff\xa5\x5a\x15\x49\xdb\x4b\xc6\x80\x5b\xd4\x22\xf1\xc6\x8e\xee\xd8\x43\x49\x4b\x3a\x3e\xaa\x6e\xd6\xa2\x29\x47\x34\x83\xd4\x96\x69\xfa\xc6\x83\x00\x9b\xeb\xfa\xca\x08\x1c\xd3\xc9\x8d\x64\x5a\xaf\x98\x77\x30\x7f\xdd\xaa\x0b\xb9\x1d\x1d\x92\xb6\x62\x07\x3b\x06\x18\x42\xc4\x41\xcb\x1e\xe4\x82\xc1\x7a\x2d\xa5\x74\x34\x9f\x8c\x2e\xc8\xdc\x42\x78\x6f\x80\xe3\x3d\x6e\xdf\x7c\x54\x1a\x57\xf5\xeb\xd5\x34\xc4\x37\xb6\x17\xad\xbf\xee\x4a\x08\xa8\xa2\xaa\x17\x18\xc5\xe6\xd0\xfe\x38\x8c\xb2\xbc\xef\x6e\x18\xa6\x90\x0a\xb9\x28\xfe\x2c\xfc\x89\x03\xa5\x85\xa4\x53\x4c\x39\xb1\x8f\xdb\xc7\x8a\xbf\xec\x83\xb5\x17\xac\x3e\x6d\x55\xe1\x28\x97\x46\x68\x48\x16\x9e\x22\x37\x2c\x85\x51\x8e\x3d\xa4\x6d\x1e\xf4\x7b\x42\xda\x0a\xcc\x68\xdb\x71\xd6\x8e\x3a\x42\x96\x41\x01\x28\x70\x16\x50\x44\x7d\xd2\xa5\xd4\xf6\x0b\x31\xc8\x5a\x03\xf8\xdc\x68\x96\x8d\x8b\x82\x95\xa3\x43\x6a\x16\xb3\x39\x53\xa2\x45\x62\x4d\x31\xd1\xe6\x6c\x01\x57\xd5\xc3\xc6\x44\x15\x66\xb3\xfb\x0c\xeb\x20\x15\xe7\x75\x89\xec\xbf\x6e\xd3\x0a\xc9\x8e\x8c\x6a\x0d\x92\xbf\x21\xff\x73\xf8\xf3\x57\xbf\x0d\x8e\xbe\x3e\x3c\xfc\xe9\xd5\xe0\xaf\xbf\x7c\x75\xf8\xf3\x10\xff\xf1\xfb\xa3\xaf\x8f\x7e\xf3\x7f\x7c\x75\x74\x74\x78\xf8\xd3\xf7\xef\xbe\xbd\x19\x9d\xff\xc2\x8e\x7e\xfb\x89\xe7\xe9\xad\xfd\xeb\xb7\xc3\x9f\xe0\xfc\x97\x2d\x27\x39\x3a\xfa\xfa\xcb\xd6\x4b\xef\xa0\x2c\xa9\x1d\x5d\x16\x27\xad\xcf\xd8\x09\xfa\x7d\xc4\x8a\xfc\x76\x78\xf4\xea\xfa\xfc\xfb\xc0\xe8\x37\x25\x43\x2a\xd8\xf5\xde\x1c\x70\x05\x91\x04\xfd\x29\x2c\x39\xf6\x4d\x95\xe2\x08\x3d\x45\x0a\xd5\xe2\xa5\xf1\xb9\xcf\xc1\xb8\x53\xf4\xd2\xc3\x7d\x2d\x25\xd1\x89\x14\xa9\x4f\x78\x47\xf7\x06\x36\xd8\xf7\xf7\xdd\x42\xab\xee\xae\x76\x04\x63\x50\x30\x06\x6d\x18\x8f\x1a\x83\xae\x2d\x1e\xee\xad\x25\x08\xf8\xbc\xa9\x0b\x63\xad\x07\xdd\xeb\x3a\xd5\xea\x70\xdb\x39\xd4\x86\xfe\xa8\x97\x4d\x28\xcb\x10\x1a\xcb\xd0\xd2\xf5\x3e\x4c\x72\x82\xcd\xa6\xed\xc1\xc7\x09\xca\x8c\x12\xab\xda\xb8\xe2\x85\x30\x37\x4b\x28\xaa\x5f\xd7\xea\x5c\x62\x50\x25\x86\xb9\xfe\x68\xa3\x4e\x6f\x6d\x20\xaa\x51\xd2\x18\x2f\x2b\x84\x16\xc2\x61\x59\x56\x9a\x2a\x25\x22\x1b\x40\x5b\xe4\x37\x60\xd1\x3a\xb7\x6c\x5c\x0d\x76\xb8\xcf\x24\x44\x10\x03\x8f\xc0\x95\x9c\xae\x35\xdc\xa4\x9c\x9c\xf3\xb9\x2f\xbb\x1d\xfb\x6c\x19\x5c\xc9\xfa\x39\x5e\x56\x00\x82\x41\x44\xe7\x04\xab\xc4\x21\x20\xd5\x2f\x23\x67\x31\x14\x43\x4c\x4a\x2b\x6b\xb3\x9e\x7c\xad\xb9\x78\x7b\x9e\x59\x78\xb6\x5a\x09\x43\x2b\xcc\xb2\x34\x3f\xd7\x99\xe4\x4b\x70\x06\xb6\x67\x9f\x9f\x1d\xeb\xec\x88\x6d\x76\xc3\x32\x77\xf0\x9d\x74\xc9\x26\xbb\x70\x96\x64\x12\x26\xec\xbe\xa3\x73\x7a\xc2\x4b\x4b\x0c\x8b\x81\x6b\x36\x61\x36\x7b\x26\x93\x90\x01\xb7\x19\x09\x34\x9a\x21\xed\x77\x9c\xb2\x74\x4e\xef\x63\x30\x8f\x15\xb8\xbb\x25\x65\xd7\xeb\x84\xfd\x40\xc7\x48\xa0\x63\x8d\xc7\x27\xa2\x63\x0e\x73\xf7\x87\x88\x61\xe4\x79\xfb\x98\xf7\xd3\x7a\x19\x19\x44\xe4\x9d\x11\xad\x4c\x71\x3a\xc6\x59\x1a\x19\xa0\x5b\xe1\x03\xbe\x76\x94\x27\x49\x47\xa5\xb7\x7b\x17\x08\x8d\x2c\x4f\x12\x97\x71\x3c\x24\xef\x39\x1e\xc9\x13\x6c\xf1\xd0\x27\x97\x30\x07\xd9\x27\x17\x93\x4b\xa1\x47\x56\xb6\xad\x87\xb3\xd9\x1b\x09\x9b\x90\x37\x46\x6b\x52\x9a\x68\x5b\x66\xbf\x52\x14\x48\xc8\xda\x04\x65\xbd\xb1\x16\x61\xe8\x9b\xb7\xe5\x0b\x9f\x0b\x3a\x78\xa2\x6d\x2a\xfa\x98\x74\xa0\x9e\xba\x99\x7c\x80\x1c\x06\x45\x3a\xef\xc8\xba\x84\xde\x67\x58\x63\x23\x13\x4a\x5f\x1b\x2d\xb6\x9b\x1e\x37\x23\x3f\x1d\xb6\x8d\xa0\x49\x02\x71\xad\xc9\x91\x6d\xce\x41\xeb\x5a\x34\xa6\x1a\x17\xbd\x22\x80\xcc\x28\x8f\x13\x90\x58\xef\x5d\x2d\x17\xb5\x62\x65\x83\x83\xa2\x25\x85\x4f\x06\xa5\x51\x24\x64\xec\x9a\xcb\xba\xa4\x4c\x5c\x4c\x71\xbc\x90\xd6\xa6\x94\xd3\x29\xa0\x65\x61\xa5\x6a\x30\xd6\x92\x56\x95\xbe\x16\x33\x21\x6e\x49\x24\xd2\x2c\xc1\x03\xd0\xe2\x7c\x94\x6d\x75\x0a\x14\x1d\x98\xd9\xd5\x71\xa5\xe3\x0e\xfe\xd0\xae\xe1\x4e\x2b\x61\xa5\x0b\x51\x05\xee\x21\xea\xac\x25\xdf\xf9\x3d\x44\x95\x9e\x92\x66\x4b\x5c\x53\x49\x2d\xd0\xb6\xd1\xbe\x55\x70\x6b\xb3\x7c\x57\xa6\xf0\x16\x59\x66\xd5\xb1\x54\x43\x0e\xe7\xf4\x25\xb3\xdd\x2b\xb0\xfb\x80\xcd\x60\xc6\xcc\x33\x5f\x45\xbb\x76\x18\xec\xd1\x5b\x29\x3c\x57\x04\x1b\xfb\xb9\x30\xcf\x5a\x08\x4d\x0e\x7b\xc7\xbd\xa3\x15\x1b\xdd\x52\xdd\xe5\x9b\xca\x93\x0c\x0b\x0d\x66\x58\xb5\x0f\xa2\x5e\xdc\x27\x4c\x7b\x62\x6b\xeb\x1d\xe0\xaa\x5c\x3a\x5c\x9f\x28\x41\xb4\xa4\x31\x73\x5a\x10\xfe\x6a\x6e\xd2\x32\x77\xc5\x0e\x0e\x7b\xbf\xf5\xfa\x04\x74\x74\x44\xee\x04\xef\x69\x5c\x3e\x56\x06\xc9\x55\x65\xa2\x85\xc8\xb1\x01\x9f\x05\x41\x51\xe6\xc3\x50\x2c\x22\x72\xdb\xad\x67\x46\xb5\x4f\xc3\x3b\xbf\x67\xda\x77\xa8\x10\x13\xf2\xca\x36\x0b\x02\xea\xac\x84\x09\x9b\xc3\xf1\x0c\x68\xa2\x67\x36\x90\x82\x0b\x3e\xb0\xfd\xde\x0c\x29\x71\x57\xda\xfa\x14\xda\x99\xdc\xaa\xa3\x85\xf9\x6d\x75\x41\x2d\xa5\x6b\x43\x44\xbf\x6d\xde\x84\x96\xac\xf4\x67\xbe\xb9\x19\x7d\x5b\x6b\x43\x8b\x54\x5c\xeb\xcc\x87\xb7\x54\x4a\x66\xec\x01\xed\xe8\xc6\xa1\xd7\xaa\x1f\x2d\xe9\x90\x84\xb5\xed\x4b\x4b\x56\xfb\x6d\xef\xd6\x90\x96\xfc\x5d\xe4\xd8\x48\x8f\x8e\x93\x05\xb9\xa3\x5c\xfb\x54\xbc\x03\x33\xd5\x81\x21\x4f\x06\x1b\xbe\x03\x1a\x83\x54\x48\x3d\x80\x36\x2e\x0d\xe6\x47\x67\x8e\xa6\xca\xda\xba\xe5\x03\xb9\xd2\x22\x25\x33\xf7\xd9\xf5\xf4\x44\x77\x32\x86\x78\x7a\x7c\xee\x8f\x84\xcc\x52\x38\xf7\xcc\x8b\xa3\x5f\x2b\x74\xc3\xc2\xbd\x56\x42\x3f\xaa\x82\xad\xda\x68\x85\x71\x0b\x2c\xdb\x22\xb1\x23\x5a\xda\x41\x80\x00\xe9\x30\x48\x80\xb4\x4b\x76\x5c\x9e\x08\x1d\x5f\xed\xe3\xa1\x3a\x8b\x3b\x20\x9d\xf9\xd6\xc9\x3a\x43\xa4\xc3\x19\x1b\x05\xdb\x11\x10\x3b\xf5\x68\x93\xf6\xe9\x94\xd5\xf1\x30\x00\xba\xd9\x7c\xd2\x25\x04\xb2\x0e\xc2\x9f\x57\x83\x9f\x57\x1a\x85\x23\x99\xb0\xa5\x68\xf7\x86\xcb\xb4\xed\x9a\x4e\xd6\xe7\x12\x4b\xc2\x8b\x26\xb7\xfa\x59\x74\x4e\x27\xdd\x85\x29\x76\x1d\xa4\xd8\x69\x88\xe2\x47\x0d\x50\xc4\xb4\x88\xd6\x54\xa4\x6e\x1f\xc7\x29\x0d\x06\x18\xbd\xcd\x68\x9c\x4e\xf6\x73\xd6\x1d\xdf\x88\xa3\x6e\x0e\x35\x47\x6d\x2f\xce\x98\x8e\xb2\x6b\x11\xdd\x76\xa8\xd7\x9c\x41\x26\x21\xb2\x76\xb2\x9b\xd3\x91\x9d\xdd\xe8\x97\x97\xef\x6f\xca\x70\x7c\x8c\x59\x29\x0d\x97\xdf\x39\x4b\x9a\xd1\x49\x6f\x21\xd3\x85\xea\x3e\xa6\xd1\xed\x1d\x95\x31\x5a\xb6\xa8\x66\x63\x96\x30\xbd\x40\xe5\x5c\x02\xc6\xfa\x73\x61\x83\xe2\x6c\xfd\x47\xe1\xbb\xb8\x16\x2d\xc6\x0b\x1b\x16\x5a\xc8\x5c\xf4\xcc\x84\x32\xa3\x8f\x17\xad\x7a\x6d\xd4\x4c\x94\x15\x26\xbd\xaa\x65\x3a\x28\x5f\x7e\xec\xad\xf2\x55\x69\x43\xbb\xab\x1e\xd6\x36\x76\x6f\x8f\x59\x9d\x63\x71\xb2\xe8\xb2\x16\x58\x5d\x47\xf3\xed\x2f\xab\xcb\x24\x5c\x6b\x91\x75\xe4\x25\xb1\x93\x6d\xf0\x91\x8c\x61\x22\x0c\x11\xde\xe8\xf4\x88\x73\x70\xa5\x39\x4f\x46\x17\x85\x55\x4b\xd4\x1c\x1b\x36\x6a\xd1\xd7\xe3\x4c\xd8\x1c\x38\x28\x75\x8c\xee\x90\x3c\xb3\x5a\xab\x6f\xa8\xdb\x37\x5f\x07\x29\xae\xae\x5f\x66\x02\xb8\x76\xbe\xf8\x23\xe8\xc8\x5a\x6e\x2b\x84\x1c\x3b\x85\xb9\xe5\x2f\xbb\x51\x22\x49\xd5\xcc\xb6\xba\x85\x7b\xa6\x5d\xbb\xe6\x91\x2d\x0f\x5c\xed\xb8\x3b\x95\x34\x02\x92\x81\x64\xc2\x30\xa3\x9c\xeb\x58\xdc\x71\x32\x86\x29\xe3\xca\x83\x02\x2b\x6e\x3a\x98\xa1\x3f\x86\xa9\xa2\x64\xda\x90\x5c\xd5\x0a\x82\xb8\x54\x9d\x48\x94\x47\xd3\xad\x79\xd9\x93\x84\x1c\x0b\xe1\x64\x1b\xc7\x14\x10\xae\xf6\xd2\x79\x6c\xc9\x87\x39\xc7\x37\xc7\x90\xd0\x85\x8d\xc8\xc4\x36\xd8\xec\xdf\x20\xd5\x51\x07\x1e\x27\xdb\x0d\xca\x5f\xdb\xb8\x0e\x2c\x75\x4a\xa3\x59\x3b\x17\x6e\x70\x51\x6d\x39\x82\x8b\xaa\xcd\x24\xc1\x45\x15\x5c\x54\x8f\x8c\xe0\xa2\x0a\x2e\xaa\xa5\xb1\xb7\x5a\x52\x70\x51\x35\x1e\xc1\x45\xf5\xf0\x08\x2e\xaa\x2d\x46\x70\x51\x6d\x39\x82\x8b\x2a\xb8\xa8\x82\x8b\x2a\xb8\xa8\x3e\x23\xbb\x9d\x1f\xc1\x45\xb5\x32\x49\x70\x51\x05\x17\xd5\xd6\x63\x6f\x95\xaf\xe0\xa2\xb2\x23\xb8\xa8\xea\xe3\xf3\x62\x75\xde\xc1\x33\x32\xaa\x5e\xfb\x1e\xc3\xa8\x30\x3a\x1a\xfb\x22\xd3\x9e\xda\xd8\xff\x3f\x8d\xed\x7f\x4f\x1c\x25\x1d\xd8\xfb\x83\xad\xff\xc5\xd9\xfa\xbb\xb1\x93\x75\x60\x23\x6b\x4d\x93\x9d\x0b\xfc\x66\x26\x41\xcd\x44\xd2\x18\xd1\x6b\x48\xfe\x8e\x71\x96\xe6\xa9\xc1\x39\x65\xf0\x99\xcd\x0b\x5f\xbb\x2a\x1b\x2f\xa3\x0b\xde\x9a\xeb\xcc\x8d\x2c\x06\xac\xbc\x49\x59\x62\xb6\x11\x13\x25\x67\x74\x6e\x70\x5d\xe5\x51\x04\x80\x7d\xbd\xaa\xaa\xc4\x1f\x87\xc5\x9b\x8a\x3e\x0e\xaf\xdb\xd1\x9b\x76\xdc\xd2\xd6\xc6\xc4\x59\xfe\xf8\x87\x46\x73\x4c\x65\xd6\x0d\x5d\xfe\xf6\x6a\x74\x5a\xa1\xcb\x94\x7b\xb2\xcc\xf8\x5c\x24\x73\xdb\xd8\x16\x6f\x32\x52\xd1\x70\xa5\x25\x66\xa1\x44\x38\xf9\x5b\xd9\x0e\xcc\xe6\x39\xf3\x54\x91\xd2\x3e\xb2\x81\x14\x8d\xbb\xc3\x96\xa3\x03\x82\xdf\x5e\x57\x68\xa5\x27\x74\xc1\x6f\xda\x8a\xc2\x75\x39\xc6\x08\xbc\x75\x73\xcf\x14\xf1\xc2\x96\x73\xdf\x5a\xe0\x6d\x4d\x29\xdb\x0b\xa1\xed\x8f\x16\xc1\x7a\x2b\xf8\xe1\x9d\x01\xf8\xc0\xb5\x10\xf7\xec\xbc\xaa\x6d\xf8\x16\x47\x5a\x90\x2c\xa1\x65\x93\x22\xdc\x81\xef\x90\x07\x9d\xce\x20\xba\xbd\x72\x2e\xcf\x43\x05\x50\xc4\xab\x4c\x99\x9e\xe5\xe3\x61\x24\xd2\x63\x43\x12\xec\xff\x8d\x13\x31\x3e\x4e\xa9\xd2\x20\x8f\x63\x11\x39\x16\x37\x88\xcc\x2c\x8c\x4f\x87\x69\x7c\x84\xed\x6d\x2f\xea\x4d\x11\x2b\xa5\x10\xcc\xfb\x9d\x32\x48\xc6\x60\xa8\xab\x40\x85\xbf\x52\x4f\xcd\x2c\x6f\xe7\xc6\xb5\xd5\xd1\x9a\x25\xb5\x74\x37\x7f\x7a\x57\x73\xa0\x5c\xa4\x03\xcb\xc6\x73\x73\x29\x77\x16\x5a\xd1\x81\x2b\x79\x8f\xdc\xc8\x7b\x23\x1a\xef\x8b\xeb\x78\x0f\x4b\x1f\x77\xe0\xe9\xec\xc2\x55\xdc\x9d\x9b\xf8\x23\x54\x08\xfe\x38\xee\xe1\x0e\x6d\x68\x1d\xb9\x85\x3f\x85\x4b\xb8\x93\xaf\x6e\xeb\x0a\xfe\x74\x6e\xe0\x6e\x3e\xb7\x4b\x45\xe0\xb9\xba\x7e\x3b\xb0\x85\x77\x69\x07\xef\xcc\x06\xfe\xd1\x5c\xbd\xed\xdd\xbc\x7b\xe0\xe2\x6d\x0d\x64\xc6\x99\x66\x34\x39\x83\x84\x2e\xae\x21\x12\x3c\x6e\xcc\x61\x96\x4a\x46\x16\xe7\x47\xd9\x69\x9d\x9d\xaa\x9e\xd1\x30\xa3\xae\x32\xb6\xd1\xa8\x6c\x06\x87\xf7\x4f\x38\x81\x02\x5d\x0b\x76\x95\x4d\x8a\xce\xdd\x09\x79\x9b\x08\x1a\xab\xe3\x4c\xd8\xff\x2b\xf3\x15\x2a\x89\x0a\xf6\x5d\xed\x32\x15\x9e\xda\x20\x66\xd3\x3b\xba\xdc\xc4\xef\xc4\x1d\x11\x13\x0d\x9c\x1c\x32\xee\xf7\xf1\xa8\xa2\x06\x96\xd6\xc9\x02\xad\xcd\xd5\xd7\xaf\xfc\xcd\x2f\xcf\xec\x88\x06\x56\xa5\x3e\xbe\x15\xd8\xbd\xe8\x71\x33\xb0\xbb\x71\x92\x27\x75\x53\xb0\x35\x0f\xd7\xe9\xcd\xeb\xb2\xb6\xef\x6b\x9c\xb7\x38\x6d\x94\xc7\xc4\xa5\x7c\xbd\xbc\x4d\x6b\x1d\xc0\x52\x17\xfd\x8a\x80\x95\xc7\xac\xc6\x37\xa7\x23\x6b\x34\x0e\xe6\x92\x7d\x31\x97\x3c\x51\x10\xc8\x1e\x0a\xba\xcf\x34\xf0\x23\x08\xba\x3b\x8c\x4a\x12\xe8\xb7\x92\x46\x30\xea\x5c\x46\xf0\xc7\x89\xc4\xb9\xa4\x8e\x00\x16\x22\x9f\x3f\x3c\x1c\x20\xb6\xa7\xa9\x48\x9c\xc5\x94\xd4\x49\x9e\x24\x0b\x92\x67\x82\xd7\xd3\x8c\xad\xaf\x7d\x39\x6b\x15\x4d\xf2\x6b\xde\x52\x0a\x96\x99\x14\x8e\x67\xca\x9c\x73\x43\x83\xcb\x06\x5d\x28\x48\x62\x55\x63\x5a\xcb\x8d\x55\x6c\x6a\x96\x6f\xf8\x1f\xa6\xcd\x96\x91\x7e\xb5\x09\xcd\xd3\x13\x21\x23\x36\x4e\x16\x64\x46\x93\xa2\x1b\x0b\x25\xb7\x2c\x49\xdc\x34\x43\x72\x0d\xda\xba\x14\x2c\xef\x4c\x04\x9f\xe2\xe2\x28\xf7\x5d\x00\x21\x32\xcf\x46\x09\x50\x9e\x67\xf6\x7d\x86\x13\x2f\x44\x2e\xfd\xfb\x86\x85\x63\xa2\xec\xba\xcf\x92\x7e\xa5\xd7\xd8\x83\x1b\x5b\xf4\xa7\xc9\x95\x11\x00\xde\xfb\x2a\xce\xfd\xea\x9c\x62\x0e\x52\xb2\xd8\xd9\xf9\xed\x6f\x99\x14\x73\x16\x5b\xef\x86\x07\x1b\x76\x35\xb6\xdd\x64\x8a\xf3\xcc\x05\x1f\x70\x98\x52\x14\x54\xdc\x29\xb2\x7b\x66\xe7\xb1\x11\x04\x3c\xc6\xfe\x32\x46\xc2\x17\x59\x2d\x6f\x7d\xce\x6c\x67\xdc\x0a\xe4\xc8\x21\x17\x44\x60\xe0\x67\xce\x99\xb6\xdd\xd6\x67\xb9\x26\xb1\xb8\xe3\x47\x3b\x79\x5d\xd1\xd1\x7a\xb3\x16\x40\x75\xf7\xeb\x3a\x39\xc7\x7e\xef\xc3\xe0\x65\xca\x99\x3e\x27\x24\xe7\x0a\x5a\xb2\xf7\xce\x84\xa3\x3f\xff\xa9\x19\x8d\x60\x29\x88\x5c\x7f\x12\xed\xef\x6e\xc6\xa2\x59\x55\x98\x65\x29\x28\x22\xf2\x25\xb5\xf8\xb5\x7b\x6c\xfd\x0e\x05\x15\x70\xdd\x68\x6a\xd8\x5d\x63\xfd\x72\x0d\x4b\x57\xe3\xf7\x2a\x0d\x99\x31\x34\xfb\xec\xf2\xfa\xd7\xb7\x27\xff\x7d\xfe\xd6\x9d\x4f\x5e\x65\xfa\x39\x67\xff\xca\x81\xd0\x54\x18\x59\x38\xa9\x86\x01\xf6\x51\xa3\xaf\xfc\x80\x27\xb9\xdb\x80\xc1\x86\x0c\x19\xbb\xc7\xb7\x0f\x8b\xc4\x1e\xf4\x1f\x3f\x2a\xf2\xa9\xbb\x6a\x95\xc1\x2d\x46\x6e\xac\x74\xd5\xa2\x84\x83\x36\x27\xcf\x4a\x94\xb6\xcb\x1a\xe3\xd3\xa4\x2a\x4c\x36\x23\x57\x6d\x75\xa2\xb6\x1a\xd1\xa0\xfc\x82\x51\x53\xc5\xa8\x93\xee\x5e\xe5\x1a\x3a\xea\x89\x53\x52\x6d\xaf\x06\xd8\xa6\xc5\x5e\x0d\xb0\xa2\xc7\xc5\x88\xd0\x38\x96\x28\xa6\xe0\xa9\x4f\x97\x7a\x63\x66\x65\x2c\x4d\x9f\xbc\x22\x7f\x23\xf7\xe4\x6f\xa8\x16\xfc\xb9\x6d\x07\xa1\xb6\x02\x7b\x17\xa1\x31\x46\x1b\xbd\x18\x75\x04\xf1\x1f\x67\x54\xe3\x8c\x06\xaa\x5a\x90\x31\x73\x62\x28\xdc\x6b\x90\x46\x2c\x72\x3b\xf1\xa4\xbd\x97\xcc\x02\x3f\x21\x9a\x59\x33\xf9\xc5\xa4\x1e\x8e\xb3\x1b\xa2\x99\xc7\x8d\x7e\x7f\xe9\xa8\x50\xbd\xcf\x49\x39\x5b\x4a\x75\x34\xab\x93\x31\x23\x60\xa8\x1a\x73\x8a\x05\x92\x71\x1b\x76\x3b\x63\x2d\x9c\xfe\xfb\x83\xc6\xed\xfc\xc0\xb5\xfd\x7c\x68\xa7\x96\x14\x7f\xe4\xf3\x4e\x30\xa8\x94\x4e\xca\x44\x3c\x24\xe7\x34\x9a\xe1\xb2\xe2\x0a\xcf\x30\x1a\x08\x4e\x36\xa3\x73\xb3\xf1\xee\x59\xdb\x17\x08\xa5\x95\xc2\x3a\x8a\xb8\x64\xce\x53\x44\xb9\x6d\xce\x39\x01\x29\x6d\xa4\xf4\x78\xe1\x83\xcc\x5a\x6f\x5e\xab\x93\x94\x49\xa1\x45\x24\x5a\xb4\x87\x5a\xce\xbe\xc0\xe9\x10\x08\x36\x3a\xd5\x9b\x77\x7f\x38\x1b\xf5\xc9\xcd\xe9\x08\x9b\xfa\x5c\x9f\xde\x8c\xea\x12\xf6\xc1\xcd\xe9\xe8\xe0\x49\x41\x41\xbc\x99\x0d\x0d\xaa\x0d\x26\xa9\x19\x4c\x12\xa6\xf4\x20\xa5\xd9\xe0\x16\x16\x0d\x79\x6a\x17\x7c\x7d\x50\xec\x70\x27\x1f\x64\xc1\x9c\xd2\x6c\xe7\xd9\x24\xd0\x98\x85\x34\x9f\xed\x47\x48\xf3\xd9\x72\x84\x34\x9f\x90\xe6\xb3\x3a\xf6\x26\x96\x31\xa4\xf9\xbc\x2c\xd7\x6d\x48\xf3\xf9\xcc\xbd\xbf\x21\xcd\x67\xfd\x08\x69\x3e\x21\xcd\x67\xbb\x11\xd2\x7c\x76\x1f\x7b\x17\xb7\x12\xd2\x7c\x76\x1a\x21\xcd\x67\x75\x84\x34\x9f\x0d\x23\xa4\xf9\x6c\x18\x21\xcd\x27\xa4\xf9\x84\x34\x9f\x10\xfd\xf8\xe8\x5c\xfb\x19\xfd\x48\x42\x9a\x8f\x1b\x21\xcd\xe7\x45\xc4\x78\x91\x90\xe6\xb3\xd5\x08\x69\x3e\x21\xcd\xa7\xc9\x08\x69\x3e\x2f\xc5\x5c\x12\xd2\x7c\x42\x9a\xcf\xe7\x23\xe8\x86\x34\x9f\x90\xe6\x13\xd2\x7c\x42\x9a\xcf\x83\xab\x08\x69\x3e\x2f\x41\x05\xf4\x3d\x57\xdb\xe7\xa8\x5c\xf9\x99\xb6\x0f\xeb\x23\xe7\x6b\x7e\x45\x4b\x88\xca\xcc\x24\xb2\x9c\x32\x91\x40\xe3\x05\x4e\x89\x7d\x1e\x2a\x42\xd6\x33\x8c\x0e\x4c\x58\xca\x9a\xa5\x05\x91\x95\x43\xf3\x16\xe7\xaa\x78\x5d\x0c\x58\x52\x7a\x8f\x07\x80\xa6\x22\xb7\xad\x5f\x23\x91\x66\xb9\xae\xc3\x14\xb7\xa7\x49\xd7\xd6\x09\x9b\x3a\x8e\x7a\x6c\x1b\xcc\x0e\x8a\x69\x07\x95\xa6\xae\x4f\xd8\xaa\x95\xc6\x3e\x6a\x6e\xd4\x45\xd0\x08\xd5\x1a\x24\x7f\x43\xfe\xe7\xf0\xe7\xaf\x7e\x1b\x1c\x7d\x7d\x78\xf8\xd3\xab\xc1\x5f\x7f\xf9\xea\xf0\xe7\x21\xfe\xe3\xf7\x47\x5f\x1f\xfd\xe6\xff\xf8\xea\xe8\xe8\xf0\xf0\xa7\xef\xdf\x7d\x7b\x33\x3a\xff\x85\x1d\xfd\xf6\x13\xcf\xd3\x5b\xfb\xd7\x6f\x87\x3f\xc1\xf9\x2f\x5b\x4e\x72\x74\xf4\xf5\x97\x8d\x97\xdc\x5a\xe0\xed\x4e\xdc\xed\x48\xd8\xfd\x28\xa2\xae\x73\xd7\x76\x74\x16\x5d\xa8\xc9\xca\x69\x74\xec\xe8\xa1\xd3\xe8\x35\x6e\x14\xe2\x8a\x79\x98\x22\x22\x65\x5a\x3b\x2a\x4a\xab\xc1\xaa\x4c\xd7\x54\x4e\x47\x07\xb0\x21\x36\xd5\xb6\x51\x75\x11\xe8\x59\x09\x51\x11\x5e\xae\x73\x9d\xbc\x59\x9a\x25\xd8\x20\x1a\xcf\xf3\xc0\x47\xaa\x20\xeb\x0c\xb4\xe1\xf1\x11\x68\xc3\x4b\xa4\x0d\x0a\xa2\x5c\x32\xbd\x38\x15\x5c\xc3\x7d\x23\xfb\xc9\x26\x03\xd2\x75\x7d\x6a\x17\x1b\xa6\x5c\x4c\x9b\xbd\x46\x44\x66\xe3\xbb\x37\x66\x4e\xcf\x44\x9e\xc4\x98\x97\x94\x73\x54\x29\x6d\x8a\x1b\x68\xab\xef\xa1\xa6\x83\xc1\xdb\xcb\xaf\xf3\x1a\x9c\x9d\xfa\x5f\x39\x9b\xd3\xc4\xe8\xb7\xe5\x13\x23\xd4\x59\xaa\x0f\x35\x32\x62\x3d\xb1\x8c\x85\xe2\xcd\x48\xb2\x39\x4b\x60\x0a\xe7\x2a\xa2\x09\x52\xa5\x6e\x28\xfd\xc9\x86\xd9\x71\x8b\xa4\x48\x14\xb9\x9b\x01\x76\xe0\xa7\x5e\x3d\xc7\x44\xb2\x29\x65\x9c\xa4\x86\xa8\x66\xfe\x61\x65\xf5\x7c\x43\xbc\x8d\xd4\xcb\x75\xa9\xcf\xa3\xfa\x3a\x16\x22\x71\xd9\x08\xc9\xa2\x9c\x9f\x59\xd3\x1b\x17\xbf\x72\xb8\xfb\xd5\xcc\xa6\xc8\x24\xa1\xd3\x42\x8d\x57\xa0\x57\x2c\x71\xe5\xd4\x1b\x3f\x00\x43\xfd\x73\x20\x34\xb9\xa3\x0b\x55\x1a\x35\xca\x39\x98\x7a\x43\x5e\x1f\x21\xe2\x51\x45\x8a\x39\x62\xf2\x87\x23\x74\xcd\x9d\x9e\x8c\x7e\xbd\xfe\xfb\xf5\xaf\x27\x67\xef\x2e\x2e\xc9\xa5\xd0\x60\x59\x52\xa5\x49\x5a\x44\xb9\xd1\x10\xdc\x2a\xf1\x1d\xa8\x41\x0b\x35\x44\xbb\x22\x53\xe4\x8e\xf1\x58\xdc\xa9\xc6\xf6\x53\x8b\x7e\x06\x78\x40\x79\xa3\x39\x22\x9a\x51\xec\xfd\xd6\x82\x3f\xac\x44\x7f\x54\x27\x45\x0e\x1c\xc7\xc7\xb1\x14\x99\x05\x82\x37\x40\x55\x95\xa4\xb3\x25\xbb\xb2\x8f\x2f\xc5\xfd\x9d\xd4\x27\x9c\x4a\xca\x75\x69\x89\x29\xf7\xcc\x35\x9d\x1b\xb6\xde\x8e\xe7\x9d\x6d\x44\xe3\xee\x32\x8d\x4e\xe2\x18\xe2\x1a\xf8\x5f\x5c\x54\xdf\xa9\xff\xb8\x45\x59\x8c\x81\x8c\xde\x5f\x5f\xfc\xef\x25\x3c\x5e\x64\xed\x82\x98\xba\x49\x00\x95\x22\xeb\x6c\x77\xaf\x20\x15\xf3\xb0\xbf\xfb\xb2\xbf\x05\xb7\xec\xc6\x75\x7e\x95\xf3\x2a\x43\xe3\x95\xf9\x49\x2a\x62\x18\x92\x51\x61\xc3\xaf\x5f\xad\x16\x99\x91\x40\xcc\x2d\x5c\x33\x9a\x24\x8b\xaa\x30\xa5\x85\xcd\x10\xac\x95\x20\xa8\x12\xf2\x09\x4d\xd4\x53\x53\xe3\x36\xbc\xd1\xc8\x11\xef\x8c\x36\xdb\xc9\x76\x14\xb3\x91\x18\xb8\xd0\x4e\x18\x36\xab\xc4\xb2\x0e\x52\x44\xc4\xaa\xce\x95\x40\xa9\x1a\x7f\x53\xd6\x8f\xe0\x59\x23\x53\x1e\xd8\xa3\x62\x66\x6b\x44\xce\x15\xa8\xf5\xac\xb1\x54\xa6\xcd\xec\x12\x68\x2c\x78\xb2\xc0\xa8\x48\x1b\xe7\x90\x52\x75\x0b\xb1\xfd\xc1\x89\x66\x85\x17\xc1\xcc\x58\xbc\xea\xc6\xac\xdb\xbb\x0c\x50\x24\xb3\xd1\x17\xe8\x6a\x30\x1a\xfe\x93\xee\x7a\x8b\x43\x68\x80\xf2\x9e\x27\x8b\x2b\x21\xf4\x37\x45\x8a\x6b\x27\x18\xf0\xa3\x93\x96\x11\x20\xf5\x48\x2f\x8a\xef\x1d\xe0\x6e\xe0\xa1\xaa\x66\xd7\x9e\x95\x3b\xfe\xdc\x8f\x94\xcc\xf9\x89\xfa\x56\x8a\xbc\x31\x13\x5b\x11\x36\xbf\xbd\x38\x43\x52\x94\x3b\x37\x22\xd7\x72\x91\x09\x66\x6d\x50\x1b\x14\x83\x1f\x9c\x23\xb4\x7a\x26\x4a\x9f\x15\x79\x47\x17\x84\x26\x4a\x78\x58\x32\xbe\x4e\x5f\x24\x4e\x19\x35\x97\xc7\x42\xcf\x56\xb4\x50\x73\xa0\x56\x9f\xeb\x57\xbc\x8a\x65\x6d\x30\xc6\x57\x1e\xd7\xf4\x16\x14\xc9\x24\x44\x10\x03\x8f\x9e\x7a\xdb\x9f\xda\x19\x87\xa8\x73\x29\xb8\x39\x98\x9d\x20\xcf\x45\xe1\x85\x75\x20\xad\xa2\x0a\xfa\x73\x9d\xf6\x47\xd1\xab\x8b\xc7\x32\x57\x20\xad\x0b\x5a\xe6\x60\x77\xf2\xfb\x7c\x0c\x89\x81\xbc\x51\x49\x5d\xc7\x6c\x6b\x78\x60\x29\x9d\x02\xa1\xba\xc0\x34\x2d\x08\x70\x65\x28\xa6\x35\x5f\x6a\x12\x0b\x28\x33\xe3\xa9\x22\x3f\x5c\x9c\x91\x57\xe4\xd0\xbc\xeb\x08\xf1\x07\x1b\x6a\x6b\x61\x03\xd0\x96\x75\xd4\x89\x9f\x02\x97\x84\xc8\x4b\x84\xb4\x44\xa2\x4f\xb8\x20\x2a\x8f\x66\xd5\x2e\xde\x5e\x6d\x76\x41\x8a\xe8\x18\xd9\x4f\x5c\x7f\x5a\x0a\xf5\x83\x02\xd9\x19\x81\xfa\xa1\x01\x81\xaa\x8a\x51\x06\xe7\xea\xd0\xb3\x88\x95\x82\xa6\x31\xd5\xd4\x11\xae\xa2\xab\xfa\xbe\x6e\xe9\xe7\x4d\xbe\x14\xbc\x65\x3c\xbf\xb7\x26\xd2\xee\x4c\x2d\xd7\xe7\x38\x2d\xe2\x10\x42\x1d\x77\x9d\x66\x59\xc2\x4a\x07\x72\x25\x48\xed\xa2\x86\x2b\xfd\x0d\x62\x22\xd2\x09\xef\x87\x36\xc2\x09\xe5\xb1\x48\x57\x5e\x86\x4e\x6f\x1a\xcd\xaa\x2f\x08\xd8\x57\x1f\x7b\x62\x14\x4a\x60\x0e\x2d\x4a\x68\x2d\x61\xde\x5b\x33\x9b\x01\x8e\xc7\x08\x9c\x9e\x24\x74\x0c\x89\x85\xb1\xc5\x40\xb5\x8a\x81\x4f\x1d\x29\x2a\x45\xd2\x5d\x6a\xcb\x95\x48\xc0\x86\x5e\x79\x40\x98\xe9\x9f\x05\x1c\x70\x92\xae\xe0\x80\xda\x60\x0d\x0e\xa8\xd7\x3e\x07\x38\xe4\x2d\x58\x3d\x59\x86\x83\x91\x1b\xea\x70\x40\xe6\xbd\xef\x70\x50\x10\x45\x22\xcd\x46\x52\x18\xb5\xb3\x33\xde\xe4\xa6\x2d\xfd\x7c\xd6\xb0\x81\x76\xfb\xaa\x06\xec\xbc\x7a\xf5\x9b\xa9\xac\x04\x5d\x52\x6d\x99\x84\x8f\xbc\xfc\x5f\x15\x9e\x85\xa4\x67\x99\x91\xf9\x59\x6a\x8e\x40\xf3\xa4\xbb\xf0\x9c\xd9\x41\x17\x79\x0b\x2d\x8c\x9d\x9d\x70\x23\x11\xd1\x04\x4b\xa4\xb6\x43\x39\xb2\x8c\x76\xcb\x13\x57\x42\x6d\xd1\x47\x89\xbf\xf9\xf0\x0f\xac\x96\x89\xbf\x38\x13\x26\x17\x31\x54\xbc\xce\x36\x46\xf8\xc6\x86\x64\xe2\x7d\x3e\xca\xd7\xc8\x15\x2e\x0a\x04\xe2\xda\xd3\x5a\xb8\xea\x64\xef\x8a\xc2\xab\x66\x81\xc0\x63\xc6\xa7\x68\x57\xeb\x13\x09\x89\x8d\x0f\x76\x44\xe0\xd6\x6a\x90\x3d\x3c\x12\x7e\x52\x7f\x1e\xfc\xab\x51\x16\x63\x82\xbb\x99\xd1\x52\xe4\x25\xac\x89\x25\xb7\x4c\x91\x83\xb7\x1e\x00\x2d\x2a\x55\xee\x23\x87\x39\xb0\x5f\x58\xec\xa6\xb5\x74\xde\x32\x1e\xbb\x50\xda\x1a\xb0\xbc\x9e\xeb\xe4\x60\x0c\xd2\x66\x71\x95\xb6\xbc\x21\x3f\x73\x52\x00\x8b\x0c\x1a\xa3\xc7\x95\x15\x99\xbd\x8d\x6e\xf0\xb0\xe1\xb5\x78\xc9\xf2\x34\x3f\x70\xdc\x7b\xf3\xde\x81\xd1\xdc\x57\xef\xf3\xdf\xf2\xa4\x65\x75\x1c\xf5\xeb\x5a\x8b\xf9\xd1\x4e\xeb\x45\xfa\xc8\xa0\xb5\x66\x7c\xaa\xaa\x9a\x4c\xbd\x1e\xfe\x7a\x55\xc6\xef\xf0\x44\x0a\x9b\x82\xb9\xaa\x42\x2c\xa5\x00\x3c\x17\x35\x24\x31\xe2\xc4\x33\x57\x42\xa6\xa9\xa2\xa7\xd2\x40\x42\x33\x9a\x5c\x67\xcd\xcb\x87\x92\x95\x52\x75\xef\xae\x4f\xea\x53\x23\xb3\x9e\x81\xb4\xbc\xdf\x5c\x27\x34\x4e\x99\x52\x68\x08\x83\xf1\x4c\x88\x5b\x72\xb8\xa6\x56\x56\x25\xca\x4a\xb1\xa9\x3a\x76\x38\x3f\x30\xab\x3f\x22\x8c\x27\x45\x24\x13\xea\xc1\x5c\x2b\x6f\xc8\xc1\x97\x44\xc5\x2a\x70\x0f\x5d\x79\x66\x17\xac\xb0\xba\x4c\x5b\x90\xd9\x60\xc1\x93\x13\xec\xd5\xed\xb9\x6c\x59\x12\xe5\x91\x2d\xba\x74\xb8\xbd\x5c\xf5\x6c\x2d\x1c\xad\xf4\xf8\xe4\x40\x72\xc2\x45\x04\xaa\xbb\x62\x4b\xdf\x95\x73\x92\x18\x6c\x86\x0d\x60\xf4\x13\xdd\x18\x0e\x87\x76\xe9\x1e\x26\x6a\xba\x47\x7b\x55\x89\xfa\xa6\x24\x2e\x46\x1f\x49\xb2\x19\x1d\x58\x25\xdd\x50\x34\x24\x81\x5e\x84\x98\x09\x2e\xa4\x45\x51\xc3\x44\x05\x47\x94\x46\x12\x65\xbd\x79\xb8\x27\x8e\x44\x57\x96\x7a\x5a\x7a\x89\xab\x8e\x40\x4c\xf4\xb2\xb5\x1d\xca\x35\xdc\x31\x3d\xc3\x1a\xac\xb3\x25\xaf\x21\xae\x44\x82\x42\x07\x0c\x27\x20\xa5\x90\x2e\x20\xcb\xdb\xad\x71\x26\xa4\xe4\x18\xd1\x65\x90\x84\x9a\xbf\x7a\xaa\xea\xa8\x2e\x2b\x9e\x63\x8c\xa1\xc1\x26\x98\x4c\x20\x42\x41\xab\x0a\x60\x4b\xb5\x0f\xcb\xa2\xb4\x3e\x85\x43\x0b\x5f\x31\x3d\x65\xf7\xe6\x2d\xd5\xa7\x96\xfa\xae\x70\xc1\x07\xeb\x2f\x1f\x0d\x09\xb9\xe0\x45\xfc\x6d\xdf\xec\x62\xf5\x4e\x1f\x7a\xa6\xcd\x27\x56\xcb\xed\xe3\x07\x54\x0d\x67\x46\x3a\x94\x79\x07\x18\xdf\xc6\x1c\x4e\xaa\x26\xf1\x4e\xc9\x01\x9a\xc6\xdd\xa4\x66\xeb\xbd\x0c\xd0\xc6\x54\x6e\x6e\xf9\x58\xe6\xf2\xe7\xe1\x00\x21\x6d\xe9\x9c\xab\x74\x10\x6a\xa0\x6f\x37\x42\x0d\xf4\x2d\x47\xa8\x81\x1e\x6a\xa0\xaf\x8e\xbd\x09\x19\x0c\x35\xd0\x5f\x56\x5d\x9b\x50\x03\xfd\xa9\x4d\xcc\xa1\x06\x7a\xa8\x81\xfe\xd0\x08\x35\xd0\x1f\x19\xa1\x06\x7a\x83\xf1\x02\x28\x57\xa8\x81\xde\x60\x84\x1a\xe8\xeb\x47\xa8\x81\xbe\x3a\x42\x0d\xf4\x8d\x23\xd4\x40\x6f\x3c\x42\x0d\xf4\x50\x03\x3d\x94\x86\xdc\x6d\xae\xfd\x2c\x0d\x49\x42\x0d\x74\x37\x42\x0d\xf4\x17\x51\x00\x8f\x84\x1a\xe8\x5b\x8d\x50\x03\x3d\xd4\x40\x6f\x32\x42\x0d\xf4\x97\x62\x2e\x09\x35\xd0\x43\x0d\xf4\xcf\x47\xd0\x0d\x35\xd0\x43\x0d\xf4\x50\x03\x3d\xd4\x40\x7f\x70\x15\xa1\x06\xfa\x4b\x50\x01\x95\x8e\x59\xa3\xb2\x90\xdb\x54\xb0\x71\x91\xc9\x95\x84\xf1\x71\x3e\x99\x80\x44\xca\x85\x6f\x5e\x09\x9e\x2a\x8b\xf5\x2d\x3b\x59\x41\xf7\xb1\x18\x8e\x4b\xe2\xd8\xf0\xb8\xcb\x50\xc7\xf2\x8d\x65\xf8\xf0\xf9\xfb\x6f\xd6\x94\xcb\x69\x1c\x55\xd8\x34\x70\x16\xd7\xfc\x9e\x37\xf3\x8f\x6f\x00\xf8\xba\xa4\x22\x07\xf7\x28\x11\xca\x85\x3d\x23\xb0\xa2\x19\xe5\x1c\xbc\xbe\xc7\x34\xda\x51\xc6\x00\x9c\x88\x0c\x9c\x77\x9a\x12\xc5\xf8\x34\x01\x42\xb5\xa6\xd1\x6c\x68\xde\xc4\x3d\xb0\xcb\x10\x65\xf7\x8b\xd2\x12\x68\xea\x83\xb5\x53\xca\xec\x54\x84\x46\x52\x28\x45\xd2\x3c\xd1\x2c\x2b\x26\x23\x0a\x30\xcb\xc2\x32\xaa\x02\x18\x18\x15\x57\xc6\x35\xf7\xcb\xb7\xb9\x65\x89\x6a\xbd\x32\xd4\x36\xfb\x58\xe2\x39\xcd\xf4\x82\x98\x4f\x4e\x5c\xd9\x57\xa9\x34\x89\x12\x86\xdc\x1a\xdf\x68\x13\x6a\x71\xbe\xbe\xe7\xd5\xdc\xad\x54\xb9\xa5\xf2\x18\xc5\xd6\x4c\x2b\x82\x61\xc0\xe5\x84\x6e\xaa\x98\x29\x27\xe6\xab\x3e\xa1\xbe\x98\x96\x05\xb4\x5f\x29\x82\xda\x73\x16\x3b\xbb\xfb\xa9\x32\x5d\xa5\x88\xa8\xc1\x4d\x6b\xc0\x2a\x11\x1d\xe3\xde\x3d\x72\xf6\x6b\x21\xfe\xa5\x40\x81\x51\x7a\x2b\xc7\x00\x37\x80\xc3\xdc\xe0\x00\x44\x60\xf8\x2b\xdd\x80\xf5\x9f\x1c\xe9\x35\x95\x53\xd0\x45\x3c\x53\xd3\x58\xf1\x7a\x58\x48\xb5\xdc\x6f\x55\x11\x29\x41\x86\xd0\x19\x89\x18\x53\x7e\xca\xbc\xaa\x75\xf5\x84\xed\x0a\x5d\x19\xb5\x75\x37\x78\xc1\xc8\x86\x68\x16\x2f\x55\x19\x8d\x40\x91\xc3\x8b\xd1\x69\x9f\x8c\x2e\xce\x5c\x1c\xa6\x98\xac\xcb\x63\x76\x34\xcc\x62\xe0\xa6\xca\xc6\x45\x85\xb6\xca\xf4\x95\xdc\x4f\xf7\xee\x51\x21\x5f\xfd\xcc\x5d\x78\xe9\x32\x05\x40\x91\xab\xa8\x6e\x4e\x54\x8e\x22\x92\xb3\x09\xb1\x22\x31\xc3\x21\x1f\x94\xe9\x88\xbe\xee\x90\x7f\xa2\x58\x88\x83\x92\xcb\xba\xf0\xbe\x6e\x24\xb0\xc8\xaf\x57\x52\x3b\x30\x14\xd4\xc5\xbd\x34\x8a\x77\x69\xa5\x21\x55\x44\xb1\x77\xa0\x14\x9d\xc2\xa8\xa1\x7b\x6b\x93\x1d\x00\x3d\x5c\x25\x39\x40\x02\x94\xd8\x44\xdf\xe2\x97\x32\x26\xb8\x2e\x7c\x93\xd4\xae\xa9\xc0\xac\x3b\xc9\xb4\x06\x24\x25\x58\xec\x0f\x37\x7b\xb9\x16\x40\x6f\x29\xb2\xf8\x9d\x9f\xa4\x7c\xd8\x88\x12\x3c\xb6\x71\xbe\x63\x20\x63\xc9\x60\x42\x26\x0c\x83\x87\x31\x9c\xb7\x6f\x6b\x3f\x51\x6b\x7b\x52\x0a\x24\xae\xc7\x69\x50\x7e\x5d\x43\xf2\xa3\x5b\x98\x96\x39\xb7\x4d\x47\x9c\x70\x8f\xc9\xae\x6c\x42\xa6\x18\x0e\xec\x74\x94\x3f\xbd\xfa\xeb\x9f\xc9\x78\x61\x04\x29\x44\x48\x2d\x34\x4d\x8a\x8f\x4c\x80\x4f\x0d\xac\x2c\x53\xa8\xa7\x6b\x16\x10\xc0\xb6\x20\x76\xe1\xaf\xff\x70\x3b\xae\x4b\x76\xc7\x31\xcc\x8f\x2b\xf0\x1b\x24\x62\x3a\x24\xa7\x45\x76\x64\x9e\xc5\x68\xe7\x6f\x5e\xaa\xbb\x3b\x34\x13\x09\x8b\x16\xad\x11\xcd\x17\x21\x23\x33\x71\x67\x35\xcc\x35\xd8\x53\x66\x7e\x65\x22\xcb\x13\xeb\xea\xf8\xa6\x48\x74\xce\x15\xac\xa6\x23\xae\x3d\x17\x68\x9c\x77\x53\x2c\xd1\x51\x17\x05\xee\x5f\x29\x5c\x9a\x8b\x33\x1f\x17\xb5\xc8\x90\x98\x7c\x43\x93\x64\x4c\xa3\xdb\x1b\xf1\x56\x4c\xd5\x7b\x7e\x2e\xa5\x90\xf5\xb5\x24\xd4\xf0\xe8\x59\xce\x6f\x6d\x2b\x88\xa2\x5a\x83\x98\x1a\x81\x3e\xcb\xb5\x2f\xee\xbd\xee\x83\x6d\xea\xbe\x67\xfd\x5e\xf9\x2e\x67\x81\x7b\x56\x6a\xd8\x2e\x6b\xcc\x62\x64\x75\x7e\x55\x45\xb6\x3f\xbc\xfa\xd3\x5f\x2c\xea\x12\x21\xc9\x5f\x5e\x61\xa6\x80\xea\xdb\x43\x8c\x1c\xd5\x88\x27\x29\x4d\x12\x43\xc8\xab\x48\x69\x00\xbd\x0e\x09\x3f\x39\x0e\xea\xf6\xe8\xb6\xb5\x00\x7f\x73\xf3\x77\xe4\x22\x4c\x2b\x48\x26\x7d\x9b\x20\x55\x28\xd3\x3d\x14\x47\x7a\x8e\xfa\x60\x96\xda\x1e\x88\xdd\x73\x91\xe4\x29\x9c\xc1\x9c\x75\xd1\xeb\xa9\x36\x9b\x37\x30\x25\x4c\x21\x1f\x1c\x27\x22\xba\x25\xb1\xbb\x58\x89\x77\x5a\x2e\x4a\xde\x1c\x0a\x4d\x23\xbf\x5a\x44\x7c\x6d\xfc\xfe\x5a\xac\x57\x4a\xb3\xcc\xc8\x00\x98\x87\x29\xe9\x5d\x0d\x18\x78\x26\xb1\x72\x42\xcb\xd2\x36\xad\x9d\x1b\x6d\x5d\x1b\x03\xf7\x45\x86\x6e\x36\x9e\xa2\x71\xac\x53\x7b\xcf\x48\xb9\xfa\xe6\xe6\xf0\x1a\x42\x94\x13\xfa\xd3\x90\xe1\xbf\x6d\x2e\xd3\x8a\x60\x5e\x14\xd5\x2c\x10\xc3\x0a\x00\x06\x7d\x90\x24\x37\x37\xf3\x77\x60\x53\x6f\x17\xe8\x56\x83\x0b\x2f\x7c\x19\x29\xd5\x4e\x20\xf4\xba\x0a\x25\x19\x48\xc5\x94\xe1\xcb\x1f\xf0\x40\x9d\x26\x94\xa5\x15\xc3\xf3\xd3\x00\xc1\x1e\x6e\xac\xe4\xdc\x9e\x52\x1a\x3d\xc5\x4e\x88\xa4\xd0\x56\xb1\x5e\x23\xd6\xd6\xa5\xda\xeb\x7c\x8c\xf8\x83\xb7\xef\xd2\x50\xaf\x43\x4e\xfc\xd4\x34\xf6\x43\xb9\x0d\x75\x12\x6b\x7e\x29\x68\xac\xbd\xeb\x25\x51\x56\xfc\xbe\xe7\x4a\x58\x8b\xc5\x77\x44\x3f\x90\xa2\xba\xcd\xad\x93\xd0\x9a\xd6\x69\x4f\x58\x45\x17\x70\x0a\xe4\x90\xd8\xa0\x0d\x73\x26\xdc\xa3\xa4\xf7\xa6\xf7\xa4\xd4\xd5\x82\x48\x8a\x8c\x4e\x5b\xf5\x23\x5a\x82\xd4\xf2\xb4\xd5\x62\x19\x46\x7f\xaa\x90\x92\xcc\xdd\x65\x28\x89\xaf\x05\x84\x95\x9e\xac\x33\xdf\x03\xd8\x69\x16\xd8\x2f\x8e\xdc\xd1\x05\xa1\x52\xe4\x3c\x76\xe6\xd0\xc2\x1e\xfd\x6e\xe9\xc5\x97\x82\x83\xf7\xf3\x2c\xd7\xda\x40\x07\x14\xe3\xe4\xf5\xf0\xf5\xab\x97\xc2\xe2\xf0\x0b\x97\x58\xdc\x65\xc1\xe2\x2c\x7d\x7a\xd2\x6f\xf5\x55\xfb\x3b\xfa\xde\x77\xce\x36\x53\x16\xe5\x67\xbe\xe4\x37\xfe\x74\x27\x99\x86\x4a\x97\xc1\x43\xd4\x78\x8c\x62\x59\xa9\x2c\x71\xb4\xae\x1b\x46\x4b\x20\xb5\x2b\xe5\xa1\xf2\xf1\x47\xa4\x5b\x8e\x40\xe1\x71\x5b\x67\x1a\x53\x0f\x90\xb0\x2a\xa0\x0e\x0e\xc8\xa1\xbd\xb3\x67\xf3\xef\x8f\x9e\x14\xb5\x1c\xd0\xce\xef\xb3\x16\x75\x42\x97\x4a\x3d\x64\x14\x8d\x77\x59\x87\x10\xfc\x6f\x98\xd1\x39\x60\xdd\x01\x96\x50\x99\xa0\x8b\xfc\xda\xae\x9d\x8c\x73\x4d\x80\xcf\x99\x14\x1c\xed\xc4\x73\x2a\x19\x56\xf6\x91\x30\x01\x09\xdc\x28\xb1\x5f\x1e\x7e\x38\xb9\xc2\xf8\x9b\x23\xdb\xf5\xc5\xaf\x32\x57\xbe\x04\x4f\x75\x25\x95\xe9\x1e\xdd\x3e\xbf\x0e\x03\x43\xa4\xb9\x7e\x5d\xe6\x3d\x69\xae\x73\xdb\x5a\xe6\x3e\x4a\x72\xc5\xe6\x4f\x45\x49\x5c\x41\x88\x33\xd6\x68\x9f\x97\x8a\x53\x94\x80\x5a\xa9\x33\x51\xba\x09\x1e\x29\xc3\xdd\x53\x45\x8e\x69\x35\x64\xc3\xd9\xac\x48\xca\xa6\x33\xed\xa2\x3d\x97\x3c\x07\x15\x17\x54\x8a\x66\xde\xa7\xb4\x5e\x19\xb6\x7b\x92\x30\xaa\x76\x15\xb9\x56\x12\x19\xdd\x2c\x18\xe8\xc1\x5d\xad\x3f\x9a\x14\x46\x19\xf3\x22\x6b\xa9\xbc\x18\x39\x0f\x9a\x87\x1b\xe3\xff\xb4\x81\x35\x85\x5a\x62\x03\x65\xec\x23\xd6\xdc\x38\x21\x95\xa2\x40\x3e\xa0\x04\x89\x3f\x56\xa2\x42\x8d\x84\x0b\x3e\x98\x55\x8a\x36\x65\x22\xde\x31\xc9\xaf\xa9\xe2\xd1\x48\xe5\x58\x0f\x41\x32\x13\x49\xec\x7b\x68\x5b\x5b\xce\x18\xf4\x1d\x00\x27\x17\x23\x84\x9f\xf9\x44\xf4\x08\x6d\x80\xa2\x75\x2b\x60\x79\xa6\x8a\x2a\x5b\x83\xe7\xae\x08\xd6\x42\x2b\x69\x23\xd2\x17\x5f\xda\xfa\xcc\x7f\x57\xc0\xcc\x47\x64\xd3\xb1\x98\x03\x82\x34\x8e\x25\xa8\x16\xe5\x8d\x9e\x40\x4f\x6d\x45\x4a\x59\xa3\xf6\x3e\x75\xc7\x48\x01\x36\x6f\x5a\x42\xf1\x1d\x8f\x2a\x22\xde\x27\xa6\x60\x17\xa3\xd3\x16\xd4\xab\xf7\x83\xf3\x8b\x98\xa9\x7a\x3d\x45\x58\x16\x95\x3e\xd7\x21\x29\xdd\x8d\x95\x44\x09\x2b\x31\xee\xe6\xeb\x6a\x2a\x26\x56\x88\x5a\x4b\x22\x4d\xb8\x9d\xc6\x90\x15\x97\x24\xed\xcc\x39\xe8\x74\xc8\x44\x8c\xfd\x97\x4a\x68\x28\xff\x44\x15\x20\x3e\x58\xc2\x12\x79\x17\x3a\xd2\x2f\x82\x90\x97\x08\x13\x9a\xde\x7d\xf8\x61\x85\x8a\xaf\x00\xf3\x93\xc1\x72\x74\x71\xd6\x25\xba\x64\x2c\xde\x3b\x74\xd9\x5d\xbf\xac\xa7\xc4\xd5\x2b\x49\xb8\x09\xfd\x61\x1f\x89\x78\x83\x98\x54\x32\x1a\xbc\xbf\xda\x09\x58\x0b\x42\x89\xb5\x2f\x2e\xf5\x78\x6f\x00\x94\x9d\xa9\x04\x8a\x5a\xa3\x3c\x49\xae\x21\x92\xb0\xab\x5d\xb5\xbe\xff\x17\x4b\x73\x6d\x12\x79\x2a\xf2\x3b\x96\x27\x70\x37\xf3\xb2\x08\x66\x25\xb0\xa3\x4c\x3e\xcc\xf2\x04\x63\x61\x29\x5f\x78\x80\xe3\xea\x55\xc5\x89\xc5\x94\x0f\xab\xb1\x61\x5c\xb5\x5d\x50\x50\xbc\xac\xe8\x29\x45\x95\xb2\xae\x56\xc6\x63\x36\x67\x71\x4e\x13\x7c\x11\x4a\xa1\xd5\xfe\xfb\x05\x87\x4c\x7d\x51\xd7\x06\x2d\xf8\x7d\x8f\x7d\xbb\xee\x2f\xec\xf2\x16\x8c\x4f\x07\xf8\x8b\x79\xb1\x5b\xe1\x40\xf0\x01\x1d\x18\xb4\x79\x26\x82\x1a\x96\x25\x7f\x8f\x92\xd0\x95\xdf\x5f\x2f\xd2\x1b\xc5\x4b\xe4\xd3\x19\x02\x4b\xa6\xd4\x57\x08\x4c\x40\x63\xf1\x37\xe7\xc0\xb5\x51\x3b\xee\xd9\xd8\x89\x55\xd5\x62\x78\x75\xdc\x78\x26\xc2\x5a\x53\x8b\xd6\x52\xf4\x71\x85\xcc\x38\x18\xe9\x9d\x31\x50\xcc\x41\xce\x19\xdc\x1d\x3b\x56\x37\x30\x6a\xfc\xc0\x42\x44\x1d\x23\x60\x8f\xbf\xb0\xe2\xe0\xcd\xfb\xb3\xf7\xd8\x49\xd9\x99\x19\x73\x05\x93\x3c\x71\xbd\xe8\x87\x84\x66\xec\x03\x48\x85\xb5\x62\x6f\x19\x8f\xfb\x24\x67\xf1\xd7\x9f\x30\xc2\x85\x71\x56\x86\xed\xb5\xa2\x5a\x6f\x1d\x55\x72\x69\xc3\xec\xdf\x65\xbb\x78\x17\x05\x34\x86\x44\xf0\x69\x25\xe9\x19\xc5\x81\x0b\xce\xf4\x4a\xd3\x59\x5b\xc0\x11\x55\x5a\x21\x63\x0c\x8e\x64\x42\xd6\xec\xb7\x66\x3e\x2c\x6b\x57\x09\xb1\x34\x24\x8d\xd5\xe6\xc3\xb8\x15\x55\x30\x0f\x62\x23\x1f\x7c\x7e\xa4\xaf\xfa\xeb\xcb\xe5\xd9\xea\x8d\x33\xca\x63\xfc\x33\x8a\x84\x8c\xdd\x7a\x99\x2e\xe2\x39\x6d\xf4\x8f\x0d\x39\x41\x36\x64\x28\x1a\xe5\xcb\x6f\x46\x8d\x51\xa6\xb5\xd8\x3f\x2f\xa6\xe4\x9c\xfd\x2b\x07\x42\x53\x61\x08\xf1\x72\x6d\xfb\x25\x88\xa4\x74\x81\xbc\x10\x97\xfa\xd6\xc7\xa7\xbb\xa4\x42\xd5\x27\x57\x40\x63\x56\xc9\x8b\xee\x93\xb7\xf5\x44\xe9\xbe\x59\xcb\xb5\xcd\xe0\x74\x3f\xd9\xd5\x4b\x50\x22\x97\x11\x5c\x59\xa7\x4e\xea\x03\x88\x56\x3f\xc6\xec\x8a\xa6\xb7\xc0\xad\x12\x6d\x40\x83\x7e\xab\x5c\xe2\x1e\x44\x33\x88\x73\xe4\x2a\xe3\x05\x99\x30\xdb\xf0\x02\x59\x3b\x9b\xce\x40\x69\x2f\x0c\x1e\x63\x50\x4e\xd9\x3b\xcc\x2f\x00\xd1\xb7\x12\xbd\x5b\x9a\x9d\x52\x8a\xe5\x98\xf1\xc8\x52\xed\x13\x54\xac\x8e\xa5\xf2\xd4\x9f\xe5\x65\x48\xab\x21\x79\x6b\x5e\x65\xf1\xa9\xd2\x48\x80\x2d\x01\x17\x9d\x6a\xce\x6e\x46\x26\x54\xcd\xb0\xcd\xc6\xf2\x16\xb8\x1a\xfd\x51\x2e\x0d\xc1\xb0\xa5\xb3\x29\xb6\x47\xc7\x56\xba\xd8\x49\x7b\x9d\xa1\xa5\x65\x42\x82\x59\xec\xa0\xc2\xef\x9e\x0b\x13\x3b\x29\x02\xcc\x0d\xe0\xa3\x25\x4a\x60\x77\xd2\x30\x2c\x5f\x62\x4a\xe6\xbc\xf4\x70\x1a\xaa\xf0\xe9\x58\x52\x73\x7f\x66\x23\x3f\x64\x1b\x0e\x48\xe5\xb4\xbd\xa5\xa2\x77\x22\xa7\xb9\x3d\xe8\x8e\x0a\x97\x85\xb6\x87\x4b\x81\xc6\x28\x4c\x19\x0d\xe4\xf4\xdd\x59\x35\xb3\xa9\x9a\xb2\xe1\xf3\xc2\x86\xe4\x43\x5b\xbb\xf2\xb2\x61\xd9\x10\xf4\xd2\x5a\x5d\xb6\xc9\x30\x44\x23\x99\x7b\x95\xa0\x78\x9b\x97\x7c\x19\xcf\x72\xed\x38\x61\xa9\x24\xf2\x68\x46\xf9\x14\xf5\x42\x91\x9b\xf9\xbe\xfc\x12\x57\x24\x21\xce\x23\xd7\x63\xc4\x63\xed\x97\xde\xca\xea\x2a\x7b\x21\xb9\x52\x11\xcd\xfc\x9a\xab\x9f\xf5\xff\xb1\xf7\x3f\xde\x71\xdb\x46\xbf\x30\xfe\xaf\xe0\xa8\x3d\x5f\x69\x93\xdd\xb5\x9d\xb4\x7d\x52\xdf\x7c\x9b\xa3\x48\x72\xaa\x1b\x5b\xd6\x23\xc9\xc9\xdb\x37\xce\xd3\x62\x49\xec\x2e\x2a\x12\x60\x08\x50\xf2\xf6\xfa\xfe\xef\xef\xc1\x0c\x00\x02\xdc\x95\x2c\x91\x94\x77\xa5\x2c\x7b\x4e\x63\x71\x49\x90\x1c\x0c\x06\xf3\xf3\x33\x6a\x21\x34\xfd\xf0\x92\xf0\x31\x1b\x93\x9d\x3f\x06\x3f\xed\xe0\xd3\x8b\x52\x9a\x47\xd8\x8a\x0a\x78\xab\x8c\x6b\xc8\x6c\xd8\x09\xaf\x1e\x93\x23\xf3\x0c\x88\x3c\x79\x02\x06\x49\xff\x93\x9a\x7c\x43\x52\xb2\x19\x2d\xd3\xcc\x7a\x48\xae\x83\x4a\x11\x4f\x30\xf6\x81\x2b\xad\x70\x1b\xd2\x1d\x84\x93\xa6\xea\xd2\x88\x22\xb3\xb8\x46\x29\xd5\x74\x14\xac\xea\x67\x68\x6a\x8d\x2c\xf8\xf1\x88\x5a\xee\xaa\xa5\xd6\xb3\x3f\xd8\x82\xcb\x11\xf5\x57\x71\xa3\x94\x03\x0c\x71\x7b\x55\xe7\xb1\xb9\xc5\x3a\x60\x60\xc7\x0b\xf8\xa8\x06\xc6\x07\x1a\x40\x5b\x99\x5a\x65\xf2\x72\xd4\xc2\x3c\xdf\xb0\xa4\x8f\x4e\x2e\xce\xfe\x71\xfa\xf6\xf8\xe4\x62\xbb\xb2\xb7\x2b\x7b\xbb\xb2\x3b\xac\x6c\x26\xae\x3a\xaf\x6a\x67\x3d\xad\x0a\xd4\x36\xd1\x27\x83\x9a\xa3\x27\x94\x0e\x77\x24\xae\x7e\xa2\x46\x99\x2e\x4a\xa6\x40\x3f\x81\x28\xd3\x8a\xb8\xb5\xbd\x00\x55\xf7\x83\x47\x9f\x0f\xb7\xc6\x6c\xb6\x1e\xb3\x84\x42\xc7\xca\xaa\x59\x0b\x9b\x22\x1e\xfc\xf3\xf8\xf0\xe8\xe4\xe2\xf8\xd5\xf1\xd1\xd9\x5a\xd3\x3b\x3a\xa2\x3f\xc6\xfb\x72\xcb\x5d\xb2\x28\xd9\x15\x97\x95\xca\x16\x1e\x40\x7a\xb5\x10\x58\xce\x10\x14\x29\x78\x3c\x1c\x46\xf6\xca\xdb\xb6\x9b\x6d\xbf\x9b\x6d\x9c\xed\xd2\x01\xf8\xa7\x2f\xf6\x7d\x55\xca\xbc\x27\x16\x3e\x47\x5f\x8c\x0b\x61\xaf\xe2\xa7\x5d\x8b\x11\x12\x6d\x3d\x56\x79\xac\x01\x49\x8c\x3e\x9a\x17\xba\x43\x77\x90\x5e\xf0\x7e\xfb\x81\xc6\xc5\x0c\x9b\x37\xb4\xf8\x91\x2d\xce\x58\x47\x7c\xa1\x98\xde\x2c\x63\x89\xd9\xe8\xc8\x25\x5b\x60\x3a\xe5\x81\x7b\x58\x17\x1c\xa4\x8d\x84\x4b\xbe\x64\x5d\xa0\xac\xfb\xc4\x39\xbe\x64\x1d\x52\x45\xdd\xb1\x84\xf8\x6b\xa6\x10\xf4\x34\x33\xa7\xdd\x66\x8f\xf4\x8b\x71\xfc\x00\xb8\xce\x4f\x37\x8e\x12\x1f\x3d\xce\x82\x0b\xdf\xf6\x3c\x13\x18\x49\x5f\x44\x7b\x97\x17\x22\x04\x8b\x38\x81\x37\x5d\xe8\xc1\x2a\x19\x3d\x91\xa6\x6b\x7b\x41\x82\x53\xd8\xaf\x5c\xdd\xad\x05\x2b\x66\xe6\x7b\x04\xbb\xf4\xa5\x03\x3d\x50\xbe\x27\x20\x74\xd9\x1d\xc6\x7f\x42\x60\x74\x48\xfe\xe5\x4f\x42\x17\x7f\xf5\xcb\xee\xee\xb7\x3f\x1e\xfd\xe3\x6f\xbb\xbb\xbf\xfe\x2b\xfc\x15\xb6\x42\x0c\x6f\xc7\x97\x00\x82\x83\x90\x29\x3b\x81\x67\xc0\x9f\x56\x5d\xdb\xc7\x10\x8a\xfd\x01\x0a\xb0\xc7\x98\x6b\xe4\xff\x2c\x64\xda\xfc\x4b\x75\x82\x1a\xdc\xc8\x8d\x01\xa6\xa8\x43\x3d\x10\x1e\xfd\x6d\x0f\xb5\x2c\xe9\x79\xa9\xda\x51\x7d\x6b\x9b\x64\xce\x72\x04\x3b\x7b\xe5\x48\x00\x7d\x8b\x1d\xd2\x83\x80\xf2\x78\xa3\x99\xc6\xb8\x93\x3b\x57\x2f\x3a\x35\x78\xc7\xa3\x47\xd1\xe6\x67\xb0\x67\x82\x01\x45\x2c\xb5\x70\x21\xfb\x0d\xd6\xa7\xb9\xf8\xbe\x9a\xfb\xa7\xc7\xe4\x0a\x29\xbc\x31\xc4\x71\xe1\xcd\x57\x0f\x2a\xe3\x7c\x10\xb5\x59\x86\xfb\x12\x33\x98\xdd\xef\x16\x12\x41\x79\x6c\x3c\x66\x0c\x9b\x3d\x3c\x39\x4e\x8a\x6a\x68\x2f\x18\xe7\x2c\x97\xe5\xc2\xff\xe9\x4b\x31\x47\x4a\xcb\x92\xce\xa0\x12\x06\x6f\xc7\xdb\xfc\x5f\x78\x63\xf4\x80\xe5\xbb\xd1\x14\xae\x63\xa9\x56\x22\xb7\x84\xf6\xa8\x8f\x0d\x94\x6d\x8e\xf4\x1b\x22\xda\x92\xae\x00\x4d\xf1\x11\x33\xa4\xf7\xc4\xa1\xc2\xe9\xa9\x08\xf6\xa4\x2d\x11\x1e\xd6\x59\x6c\xe0\x0d\x10\x57\xc6\xb2\x6c\x0d\xad\x57\x1f\x3d\x4a\xb3\x94\x5f\x71\x25\x3b\xd4\xfb\xf8\x81\x6e\xce\x78\xb4\x28\x25\x98\xc5\xe5\xdd\x66\x1f\x0a\x40\x13\xf3\xeb\xb5\x21\xf6\x5f\x74\x69\x28\x86\x47\x41\xb5\x66\xa5\x78\x49\xfe\x67\xef\xfd\x97\x1f\x47\x83\xef\xf6\xf6\x7e\x79\x3e\xfa\xeb\xaf\x5f\xee\xbd\x1f\xc3\x3f\xbe\x18\x7c\x37\xf8\xe8\xfe\xf8\x72\x30\xd8\xdb\xfb\xe5\xc7\x37\x3f\x5c\x9c\x1e\xfd\xca\x07\x1f\x7f\x11\x55\x7e\x89\x7f\x7d\xdc\xfb\x85\x1d\xfd\x7a\xc7\x41\x06\x83\xef\xfe\xd8\xf9\xd5\x7b\x00\xf7\xc5\xa3\x4f\x88\xdf\x78\xc4\x5e\xd8\xef\x01\xfb\x5a\xe0\xe1\xd8\xab\xef\xf5\x7f\xe6\xa4\x66\x90\xd5\xe3\xb6\xeb\x8d\x59\xe0\x98\x16\xfa\x39\x3c\x39\xf8\xa4\xb8\x42\xc6\x9b\x16\x4f\x6d\x9f\xfb\x3d\x38\x77\x7c\x47\x4a\x98\xd7\x5a\x13\x9d\x96\x32\x77\x75\xf8\x10\xde\xc0\x8a\x31\x7b\xdd\x25\xeb\xd4\x23\x19\x8f\xad\x33\x68\xeb\x0c\xba\xe1\xf8\xa4\x33\x08\x8b\x08\x36\xd7\x13\xc4\xc4\x55\xdb\x10\xc6\xca\x08\xba\xb3\x75\x42\xb4\xbb\xbb\x05\xd4\xc6\x6e\xa9\xd7\xad\x5c\xeb\x64\x1a\xdc\xd0\xf2\xd5\x31\x4c\xb2\x0f\x2d\xdb\x71\xe1\xc3\x00\x1e\x4d\x94\xa1\x69\xe3\xaa\x26\xaf\xcc\x2b\x78\x0c\xf9\x08\x2d\x16\x72\x8b\xb9\x98\x59\xfc\x09\xdc\x4a\x6c\xf4\x89\x8b\x1a\x67\xd7\x2b\x87\x35\x38\x3b\x55\x4a\x26\xd0\x05\x09\x61\xf1\x3c\x08\x9f\x7d\x6d\x78\x1b\x4d\x2f\x21\xda\x98\xb0\x94\x89\x84\x59\xe0\xf6\xa8\x6d\x2d\x15\xe4\x48\x5c\x39\xf0\xfa\xb4\xc2\x64\x10\x14\x7f\xab\xc7\x78\x5a\x09\x08\x86\x11\x6d\x10\x2c\xc8\x43\x00\xa9\xef\x2d\x6c\x0a\xa9\x18\x72\x5a\x7b\x59\xdb\x75\xb6\xec\xbc\x8b\x77\xdf\x33\x7d\x64\xab\x93\x32\xb4\xb4\x59\xd6\xee\xe7\x78\x93\x7c\x0a\xc1\xc0\xee\xdb\xe7\xef\x6e\xeb\xec\x69\xdb\xec\x67\xcb\xbc\x47\xec\xa4\xcf\x6d\xb2\x8f\x60\x49\x51\xb2\x29\xff\xd0\xd3\x3a\xdd\x0f\xea\x09\x79\xca\x84\xe6\x53\x8e\xcd\x7b\x8b\x92\x15\x4c\x80\xab\x15\x4a\x34\x8c\xec\xb7\x3b\x65\x1d\x9c\xde\xc4\x64\x1e\x54\xb8\xfb\x15\x65\xe7\xab\x94\xfd\xad\x1c\x23\x5b\x39\xd6\xfa\xf8\x4c\x72\xcc\x72\xee\xe6\x08\x31\xc8\x3c\xef\x9e\xfd\x7e\x10\xa7\xb2\x03\x23\x77\x2f\x21\x6e\xc0\xb8\x79\xd1\xa8\x25\x26\xaf\x61\x1d\x5b\x49\x32\x76\xc5\x32\xab\x37\x91\x9c\x0a\x3a\x43\xec\x7d\x2d\x3d\x5a\x8f\x2c\x7d\xff\xa4\x66\xde\x3d\xe8\xf1\xae\xc4\x0b\x7e\x2c\x65\x96\xb1\x52\x91\x8c\x5f\x32\x72\xc8\x8a\x4c\x2e\x72\x9b\xfb\x9a\x92\x73\x4d\xb5\xe1\xea\x73\xa6\xdb\x85\x7d\xbb\xc1\x78\xb8\x2a\xf4\x9e\xc0\xce\xb1\xac\x1d\x8a\xc2\x49\x61\x2b\x28\xdf\x0a\x10\x1a\xfb\xd0\xca\x65\x48\x4e\xd8\x15\x2b\x87\xe4\x78\x7a\x22\xf5\x29\x6a\xdf\x71\xc2\x1d\x5e\x48\xf8\x94\xbc\x34\x76\x9d\xd2\x44\x63\x3b\x8d\xa0\x40\x5d\x96\xd1\x00\x35\x50\x5b\x1f\xf5\x79\xcb\xb5\xe7\x30\x92\xaf\x3c\x6f\x15\xc9\xe8\x34\x4d\xbe\x5f\x51\xe7\x09\xda\xc7\x7a\xd2\x1a\xbb\x37\xe0\x6f\xc4\x55\x70\xd0\x63\x60\x05\x72\x41\x4a\xa6\x0a\x29\x14\x8b\x71\x15\xfd\x1b\xa1\xb5\xdb\x2f\x68\x6b\xeb\xcd\xb3\xeb\xb6\x59\x48\xa5\xa1\x84\xb6\x9f\x2e\x58\xa7\x6e\x38\xa8\x48\xa6\x59\xc6\xd2\xa8\x0d\x1a\xb6\xef\xa1\xb1\x87\x20\x81\x76\x0c\xa9\x6f\xe8\x81\x85\xca\x51\x8d\x73\x74\xbd\x6f\xa9\xe7\x9a\xd6\xb8\x7e\xca\x37\x55\x36\xd7\x0b\x13\xf6\x91\x80\x01\x96\x10\x9e\x01\xf7\x5b\x05\x9d\x6f\xe6\x52\x5e\x92\x44\xe6\x45\x06\x4b\xa7\xc3\xca\xaa\x1b\x6f\x79\x56\x1a\x99\xd1\xd5\xb3\xa0\x27\x17\x9c\xe8\xd6\x92\xab\x93\x22\xd6\x87\x1a\xc6\x3e\xb0\xa4\xb7\xa6\x9d\x47\x1f\x58\x12\x74\x9d\x05\x0c\xaa\xc4\x21\x44\x98\x15\xdb\xbd\x99\x78\xe7\x90\x43\x5f\x6e\xfe\x0e\xb5\x74\xe1\xd1\x80\xed\x83\x31\x1d\xbc\xb9\x7d\x04\x74\x8a\x00\x5b\x08\xeb\xeb\x42\x18\x0d\xcf\x8c\xb8\xf4\x96\xb0\xfe\x7c\x22\xb5\x1b\x0b\x7a\x42\x49\xa9\xc9\xde\xee\xb3\xdd\xc1\x92\xff\xb1\x81\x91\x7d\x11\xdc\xc9\x01\xdb\xb1\x00\xa0\x44\x96\xec\xa6\x43\xc2\xb5\xcb\xb4\xc6\x86\x45\xf0\x56\xb6\xe8\x6f\x48\x94\x24\xba\xa4\x29\xb7\x6a\x0c\x9c\x35\x17\xe9\xb2\xb2\x52\x7e\x6f\xf7\xe3\xae\xed\x65\x74\x2d\xc5\xae\x86\xd7\x1f\x93\x0b\xc4\x89\xf1\x03\x2d\x64\x05\x2d\x3a\x91\x04\x45\xc6\x13\xae\xb3\x05\x48\x2c\x22\x2b\xec\xe7\x65\xf6\x0b\x5b\x6c\x78\xf4\x81\x6b\xd7\x4d\x44\x4e\xc9\x73\x6c\x27\xc6\xa8\xf5\x80\x66\xfc\x8a\x3d\x9b\x33\x9a\xe9\x39\x26\x89\x08\x29\x46\xd8\x11\xd2\x88\x12\xfb\x4b\xd7\x78\x49\x37\x77\x62\x78\x74\x70\x2d\x2e\xbf\x50\x47\xcb\xc1\x08\xd1\x1f\xda\xb7\xa9\x26\x4b\x70\x5d\x17\x17\xa7\x3f\x44\x8d\xaa\x41\x8a\x6b\x5d\xb8\xd4\x9d\xa0\x9b\xfb\x06\xc8\x8e\x7e\x82\x95\x9d\x3a\x56\x93\x1e\x45\x58\xd7\xce\xd5\x64\x35\xfc\xda\xdd\x5b\x56\x93\x7f\xc8\x0a\xc0\x40\xe8\x24\x5b\x78\x24\x06\xc5\x34\xd9\x31\x43\xed\x18\xf1\x64\xb8\xe1\xef\x8c\xa6\x08\x94\xa1\x34\xa3\xad\x54\xb7\xf0\xe8\x2d\x88\x16\xbc\x5b\xbf\xfb\x40\xa5\xb4\xcc\xc9\xdc\x7e\x76\x5c\x7a\x69\x57\xc6\x18\x56\x8f\xab\x6b\x2a\x59\x81\x12\xce\xde\xf3\xe4\xe4\xd7\x92\xdc\x40\xba\x47\x5d\x0b\x92\x90\x6c\x61\x53\x1c\x2e\x90\x58\x88\x3b\xd3\x93\x2c\xed\x21\xf9\x81\xf4\x98\x00\x41\xba\x15\x72\x36\x07\x82\xa0\x5e\xf7\x5c\xaf\xde\x72\x2a\x48\x6f\x79\x03\x64\x95\x93\xd5\xf2\x0c\x7a\x5f\x7a\x22\x62\xaf\xd1\x7a\xd2\xbd\x54\x34\x3c\x6e\x27\x40\x3f\x93\x4f\xfa\xa4\x40\xd1\x43\x6a\xf7\x72\x62\x37\xc2\x48\x41\xe9\x25\x0a\x57\x10\x13\x8a\x95\x57\x6d\x8b\xb9\xeb\xa3\xbf\x4f\x97\xed\x2d\x7e\x77\xac\xa8\x93\x2e\x89\xf0\x6d\xb0\x1d\xac\xe9\x32\x41\x82\xcc\x04\xdb\x35\xdb\xb9\x73\xdd\x76\x44\xc5\x8c\x91\x17\xe6\xce\xbf\xfc\xf9\xcf\x5f\xff\x79\x8c\xc3\xfb\x2c\x05\x41\x8e\xf7\x4f\xf6\xff\x79\xfe\xd3\x01\x14\xc7\x76\xa5\x6a\x4f\x29\x98\x7d\x27\x60\xf6\x9a\x7e\xf9\xa0\xc9\x97\x50\xf2\xd1\x59\x8a\xc4\xbe\x7f\x18\x32\xc4\xf7\xb4\xba\x5f\x80\xb3\x67\x74\xcd\xd8\x91\x6a\x96\xda\x46\xac\x31\x9d\x14\xe7\x32\xb9\xec\xd1\xae\x39\x64\x45\xc9\x12\xf4\x93\x5d\x1c\x9c\xe2\xe8\xc6\xbe\x3c\x79\x7b\x51\x97\x1a\x40\x3e\x4e\x0d\xa6\xf7\x77\xeb\x49\x33\x36\xe9\x25\x2b\xb4\x37\xdd\x27\x34\xb9\xbc\xa6\x65\x0a\x9e\x2d\xaa\xf9\x84\x67\x5c\x23\xf6\x5f\xc9\x6c\xdf\x2a\x4c\xf8\x43\x90\x33\xd7\x17\x18\x65\x39\x3a\x10\x9c\x3b\x14\x5c\x56\x98\x47\x33\xa5\x3c\x03\x0f\xaa\x6d\xc9\x8b\x19\x41\x49\xe1\x5d\x7a\xa1\x4f\x7b\x6b\x7c\xb9\x63\x63\x8d\xaf\xa0\x65\xf0\x7d\xed\xb0\xae\x79\x89\x1b\xbc\xd5\xd9\x2d\xae\x8c\xba\x77\x6f\xb7\xba\x1e\xc6\xdb\xdc\xad\xae\x28\xd9\xb9\x96\xad\x5a\x00\x90\xe5\x28\x09\x0e\x76\x43\x8c\x64\xc2\xa6\xd2\x08\xe1\x1b\x83\x1e\x69\x05\x8b\x90\x0a\x28\x0e\x74\x5e\x2d\x19\x05\x36\x30\x23\xd3\xf5\xcb\xce\x2c\x70\xea\x33\x15\xa2\xa5\xba\xe6\xc7\x43\xf3\x75\x2c\x87\xb7\x1b\xd6\x55\x0e\xb6\xf5\x32\x9c\x64\x3a\x41\xcf\x6d\x20\xc8\x01\x39\xd4\xbe\x7e\x33\x8c\x92\x94\x54\xcd\xb1\x2d\x31\xfb\xc0\x5d\x7f\xfa\x53\x99\x36\x9b\x89\xcf\x4a\x9a\x30\x52\xb0\x92\x4b\xb3\x19\x55\x42\xa7\xf2\x5a\x90\x09\x9b\x71\xa1\x1c\x29\x00\x3c\xdd\xd2\x0c\xe2\x31\x5c\x79\x60\xb8\x31\x39\x8b\xc0\x4e\x6c\x19\x52\x22\xeb\xa5\x69\xdf\xb9\x19\x49\x82\x1d\x0b\xe8\x84\xbd\x7a\x3c\x85\xc3\xf6\x45\x9f\x7a\xe5\xbd\x4a\xc0\x93\x53\x96\xd1\x05\x66\x9b\x42\xcb\x72\xfe\x1f\x56\xaa\x41\x0f\x11\x27\x6c\xc0\xe5\x7e\xbb\xf1\x3d\xb8\x22\x25\xa3\xc9\xbc\x5b\xf0\x77\x1b\xa2\xba\xe3\xb1\x0d\x51\x75\x19\x64\x1b\xa2\xda\x86\xa8\x3e\x71\x6c\x43\x54\xdb\x10\x55\xe3\xd8\x58\x2b\x69\x1b\xa2\x6a\x7d\x6c\x43\x54\xb7\x1f\xdb\x10\xd5\x1d\x8e\x6d\x88\xea\x8e\xc7\x36\x44\xb5\x0d\x51\x6d\x43\x54\xdb\x10\xd5\xef\xc8\x6f\xe7\x8e\x6d\x88\x6a\x69\x90\x6d\x88\x6a\x1b\xa2\xba\xf3\xb1\xb1\xc6\xd7\x36\x44\x85\xc7\x36\x44\x15\x1f\xbf\xaf\xad\xce\x05\x78\x4e\x8d\xa9\xd7\xbd\xa6\xed\x14\x82\x0a\x3c\xb1\x71\x22\x39\x8d\xea\xa0\xf0\x51\xe3\xba\x47\x45\x00\x0b\xe2\x4a\x71\x6c\x44\xa8\x8e\x33\xad\xac\x97\xea\xd8\x47\xae\x90\x69\x1d\xa8\x08\x22\x14\x68\xf0\xb6\xaf\x59\x5b\x5b\x35\x56\x97\xb0\xc4\xe7\x09\x49\x6c\x48\xfc\xa6\x87\x30\xc4\x36\x04\xf1\xe4\x42\x10\xfd\xb8\xef\x7a\x70\xdd\x75\xde\x2a\x6c\x64\xfe\x62\x5e\x32\x35\x97\x59\x6b\x46\x8f\x98\xfc\x0d\x17\x3c\xaf\x72\xe8\x14\x6b\xf8\x99\x5f\xf9\x14\x00\xdf\xbe\xda\x4a\x6c\xf4\x22\x06\x2d\x65\x5d\x2b\x59\xa8\xdf\x9c\xd3\x2b\x68\x8f\x5a\x25\x09\x63\x69\xd0\x94\x1e\x34\xac\xaf\xc7\xfe\x49\xbe\x75\xc6\x8b\x6e\xf2\xa6\xdb\x26\x8e\x70\xa4\x30\xca\xd7\x5f\xb5\x1a\x63\x56\x16\xfd\xc8\xe5\x1f\xce\x4e\x0f\x02\xb9\x4c\x85\x13\xcb\x5c\x5c\xc9\x0c\xa8\x4a\xf1\x22\xa3\xac\x8d\xb1\x7e\x9f\x1b\x83\x69\xc2\x34\x0d\x6c\x1b\x6b\x16\x28\xc2\x04\x9d\x40\x87\x5a\x73\x97\xdf\x91\x4f\x71\xdf\x65\x54\x57\x25\x23\x33\xaa\xd7\x29\xf0\xbb\x9b\x30\x9d\xcc\x97\x3e\xf6\x9b\xae\x1a\x7a\xec\x83\x33\x7a\x78\xec\x85\x9a\x01\x5f\x20\x82\xfe\x9d\xf5\xf0\xce\x92\xb2\xbb\x6e\xdc\x7d\x69\x11\x80\xb8\x81\x0f\xef\x8d\xc0\x3b\xe7\xb6\x75\x94\xdd\xce\x43\x23\xc8\x75\x95\xd2\x92\x14\x19\xad\xfb\x42\xc1\x0c\xfc\x1d\xf6\xa0\x83\x39\x4b\x2e\xcf\x6c\x24\x76\x4f\x31\xe6\x75\xd3\x19\xd7\xf3\x6a\x32\x4e\x64\xfe\xcc\x88\x04\xfc\xbf\x49\x26\x27\xcf\x72\xaa\x34\x2b\x8d\xba\x6a\xb7\xb8\x51\x62\x46\xe1\x62\x36\xce\xd3\xc1\x98\xbc\x17\x58\xdd\x5e\xf7\xa1\x0c\xb0\x1d\xcc\xf3\x1d\xce\xc6\x84\x19\xe9\x2a\xc1\x0f\x11\x40\xd8\x99\xd7\x1b\x77\x01\x4a\xee\xbc\x25\x75\x8c\x82\x7f\xfe\x08\xf8\x56\x72\x91\x1e\x1c\x2e\x8f\x2d\xd2\xdd\x5b\xc6\x47\x0f\x11\xee\x0d\x8a\x6e\x6f\x8c\x6a\xbc\x29\x11\xed\x0d\x44\x9b\xee\x21\x00\xdb\x47\x04\xbb\xbf\xe8\xf5\x03\x80\x32\x3f\x4c\xd4\xba\x47\xd7\x5e\x4f\xd1\xea\xcf\x11\xa9\xee\xe5\xab\xbb\x46\xa8\x3f\x5f\x74\xba\x9f\xcf\xed\xd3\x10\x78\xac\x11\xe9\x1e\x5c\xf4\x7d\xba\xe7\x7b\x73\xcd\x3f\x58\x04\xba\x7b\xf4\x79\x03\x22\xcf\x9d\x89\xcc\x05\xd7\x9c\x66\x87\x2c\xa3\x8b\x73\x96\x48\x91\xb6\xde\x61\x1a\x28\x9d\x7e\xfd\x28\x1c\xd6\xfa\xa9\xe2\x42\x8b\x39\xb5\x60\xe4\xc6\xa2\xc2\xc2\x12\x17\xcb\xb0\x0a\x05\x44\x95\xf1\x2d\x37\x32\x3a\x41\x36\xc6\x21\x86\x55\x27\x7d\x4e\xe2\xdf\xe5\x35\x91\x53\xcd\x04\xd9\xe3\xc2\xcd\xe3\x20\x30\x03\x6b\xef\xa4\x67\x6b\xf3\xeb\x8b\xe7\xee\xe2\xa7\xe7\x76\x04\x07\xab\x52\x0f\xef\x05\xb6\x0f\xfa\xb4\x1b\xd8\x5e\x38\xad\xb2\xd8\x15\x8c\xee\xe1\x58\xde\xbc\xa8\xe1\x94\x5f\xc0\xb8\x7e\xb5\x51\x91\x12\x5b\x89\xf6\xf4\x26\xad\x73\x5e\x4d\xac\xfa\xf9\x3c\x9a\x4f\x79\x8d\x2f\x0e\x4e\xd1\x69\xbc\x75\x97\x6c\x8a\xbb\x64\x4d\xb9\x29\x1b\xa8\xe8\x3e\xd2\x7c\x94\xad\xa2\x7b\x8f\x23\xa8\x4d\xfd\xa1\xa4\x09\x3b\xed\x5d\x47\x70\xcb\x89\xa4\x55\x49\xad\x00\xf4\x2a\x9f\x5b\x3c\x82\xb1\x14\x57\x93\xaf\xe7\x85\x4a\xd9\x69\x95\x65\x0b\x52\x15\x52\xc4\xd5\xcf\x18\x6b\x6f\x16\xd3\x82\x4b\x7e\xc5\x53\x6a\xc5\xb2\x28\xa5\xdd\x33\xcb\x4a\x08\x23\x83\xeb\x9e\x68\xa0\x48\x02\x4c\x33\x8d\x4a\x76\x15\x9f\x99\xd7\x37\xfb\x1f\x54\xf3\xd6\x09\x88\xd1\x80\xe6\xee\xa9\x2c\x13\x3e\xc9\x16\x64\x4e\x33\xdf\x00\x87\x92\x4b\x9e\x65\x76\x98\x31\x39\x67\x1a\x43\x0a\xb8\x77\x66\x52\xcc\xe0\xe5\xa8\x70\x8d\x17\x59\x62\xee\x4d\x32\x46\x45\x55\xe0\xf3\xcc\x4e\xbc\x90\x55\xe9\x9e\x37\xf6\x81\x09\xbf\x03\x0b\x9e\x0d\x83\xf6\x6e\xb7\x4e\xac\xcf\xfd\xa9\x94\x51\x00\xde\x3a\x58\xea\x61\x38\xa6\x43\x0e\x57\x41\x73\x9f\xa2\x94\x57\x3c\xc5\xe8\x86\x23\x1b\x34\x92\xc6\x06\x3e\x7e\x3d\x0b\x29\x46\x82\xcd\x28\x28\x2a\x76\x15\xe1\x9c\xe1\x38\x98\x41\x20\x52\x68\xe9\x63\x34\x7c\x59\x44\xe5\xf4\x57\x1c\x9b\x11\x07\x94\x23\x7b\x42\x12\x09\xf9\xa8\x95\xe0\x1a\x1b\xdc\xcf\x2b\x4d\x52\x79\x2d\x06\xf7\x8a\xba\x42\xa0\xf5\x62\x25\x81\xe2\xf0\xeb\x2a\x3d\x07\xbf\xf7\x76\xf2\x72\x65\x5d\x9f\x53\x52\x09\xc5\x3a\x6e\xef\xbd\x29\x47\x7f\xf9\x53\x3b\x19\xc1\x73\x26\x2b\xfd\x59\xac\xbf\xeb\x39\x4f\xe6\xa1\x32\xcb\x73\xa6\x88\xac\x1a\x66\xf1\x0b\x7b\xdb\xea\x19\xda\x9a\x80\xab\x8e\xb6\x8e\xdd\x15\xde\xaf\x26\x1c\x42\xdd\xf9\x1a\xf2\xc4\x0f\x4f\xce\xff\xf9\x7a\xff\xfb\xa3\xd7\x63\x72\x44\x93\x79\x88\x89\x21\x08\x05\xa1\x01\x82\x62\x4e\xaf\x18\xa1\xa4\x12\xfc\xb7\xca\x06\x7c\xf7\xfc\xbd\x83\x5e\xb1\xda\x5b\xee\xbe\xd0\x9d\xbf\xb7\x76\x70\xd8\xeb\x1f\xf3\xb2\xa4\x62\xd0\xc0\xa5\xa9\x3e\x1d\x99\x9f\xd0\x38\x00\x55\x0b\x12\xe7\x67\xfc\xca\x8a\x61\x0b\x7e\x4f\x53\x9f\x29\x66\xf8\xdc\xb0\x85\xd9\xaa\xe8\x04\x32\xbc\xe6\x8c\x08\xa6\x0d\x5b\x7b\x1f\x93\x14\x2a\x02\x27\xa9\x14\x53\x43\x32\xa9\x20\x27\xad\x28\x79\x4e\x4b\x9e\x2d\xc2\xc1\xcc\x5e\x75\xe2\x43\xde\x8b\xe6\x2b\x1d\xbe\x3d\x3a\x87\x1a\x81\xa2\x44\xd8\x12\x48\x2a\x83\xdf\xe1\xb3\x26\xcc\xdc\x61\xdb\x08\x8f\xc9\xbe\x58\xe0\x8f\xb8\xc0\xb9\x22\x19\x57\x9a\xc1\x16\x6c\x75\x48\x17\x4c\xdf\x79\x3e\x86\xff\xed\x98\xaf\x2c\x8d\x92\xe9\x73\xe5\x92\xa5\xe4\x55\x54\x43\xf9\x24\x0b\xa8\x69\xbf\xfd\x49\x35\x84\xab\x93\x84\x0c\x11\x83\x86\x70\xd4\x4f\x35\x90\x17\x1b\x04\x72\x31\xcb\x42\xae\x6a\x27\xf6\xbb\xda\x96\x5d\x2d\xcb\x51\xfd\x05\xa7\x6d\x0d\xcc\x5e\x1a\xd3\xd5\xef\xd0\x53\x3b\xa7\x7a\xf7\x73\xe6\x94\x95\x08\x32\xec\xd0\x7b\x7c\xea\x56\x80\xd5\x6e\xf2\x46\x5b\xd7\xa2\xce\x49\x1a\x92\xe7\xe4\x5b\xf2\x81\x7c\x0b\xe6\xd5\x5f\xba\x36\xbf\xea\x6a\xf8\xf4\x91\x62\x64\xac\xfa\xe3\xd3\x9e\x28\xfe\xb3\x91\x4e\x66\x44\x43\x55\x2d\xc9\x84\x5b\x75\x9e\x7d\xd0\xac\x34\x72\xd4\xce\xc4\x5a\xdb\x86\x99\x17\xfc\x8c\x6c\x86\xe1\x86\xe3\x69\x9c\xd6\x74\x3f\x46\x33\xb7\xff\x5d\x2a\x7d\x62\xa5\x50\xdc\x00\xa7\x1e\x2d\xa7\x3a\x99\xc7\x62\xcc\x28\x6a\x4a\xd7\x0b\x4c\x91\x54\x42\x96\x15\xa6\x2f\xcf\x79\x87\xe4\x89\xcd\x61\xe3\x6e\xf1\xf4\x68\x3e\x6f\x9b\xa9\x86\x03\x05\x2c\x1f\xab\x58\x05\xc8\x58\x85\x4c\xad\x4e\x66\x5e\x2b\x0d\xf6\x8c\x5b\x94\x32\xeb\xab\xf1\x5e\x66\xe0\x25\xb3\x9e\x12\x2a\xb0\x80\x64\xca\xca\x12\x33\xce\x27\x0b\x97\xac\xd7\x79\xf2\x3a\xad\xa4\xa2\x94\x5a\x26\xb2\x43\x67\xb3\x38\xc6\x6d\x87\x03\x22\x60\x96\xaf\x73\x93\xbf\x3b\x3c\x1d\x92\x8b\x83\x53\xe8\xf6\x74\x7e\x70\x71\x1a\x5b\x2a\x3b\x17\x07\xa7\x3b\x6b\x25\x05\x71\x9a\x15\x38\xa6\x5b\x0c\x12\x39\x9e\x8c\xda\x36\xca\x69\x31\xba\x64\x8b\x96\x7b\x6a\x1f\xfb\xfa\xc8\xcf\x70\x2f\x1f\x84\x64\xce\x69\x71\xef\xd1\x4a\x46\x53\xfe\x99\xaa\xb8\x5c\x1a\xac\x7f\xe6\xea\x72\xae\x5c\x5e\xb1\x14\xd5\x61\x77\x07\x13\x69\x21\xb9\xd1\x17\xb7\x35\x5e\xf7\xbf\x7b\x5b\xe3\x75\xe7\x63\x5b\xe3\xb5\xad\xf1\x5a\x3e\x36\x26\x91\x75\x5b\xe3\xf5\xb4\xe2\xf6\xdb\x1a\xaf\xdf\x79\xe8\x7f\x5b\xe3\xb5\xfa\xd8\xd6\x78\x6d\x6b\xbc\xee\x76\x6c\x6b\xbc\xee\x7f\x6c\x5c\xd2\xd2\xb6\xc6\xeb\x5e\xc7\xb6\xc6\x6b\xf9\xd8\xd6\x78\xdd\x70\x6c\x6b\xbc\x6e\x38\xb6\x35\x5e\xdb\x1a\xaf\x6d\x8d\xd7\x36\xf5\xf5\x93\x63\x6d\x66\xea\x2b\xd9\xd6\x78\xd9\x63\x5b\xe3\xf5\x24\x12\xfc\xc8\xb6\xc6\xeb\x4e\xc7\xb6\xc6\x6b\x5b\xe3\xd5\xe6\xd8\xd6\x78\x3d\x15\x77\xc9\xb6\xc6\x6b\x5b\xe3\xf5\xfb\x51\x74\xb7\x35\x5e\xdb\x1a\xaf\x6d\x8d\xd7\xb6\xc6\xeb\xd6\xb7\xd8\xd6\x78\x3d\x05\x13\xd0\xf5\x01\xee\x5e\xb3\xb4\x7b\x20\xf3\xa2\xd2\x8c\x9c\xb9\x21\xbd\x16\x89\x82\x81\xab\x50\x23\xe8\x9e\x42\x98\x48\x31\xe5\x33\x2b\xd9\x9f\x61\xf3\xdd\x91\xff\x9e\x51\xd0\xf0\xf6\x11\xe6\x0f\x66\x3c\xe7\xed\x0a\xc9\xc8\xd2\xc4\xbc\x86\xb1\x82\xb8\x8c\x59\x49\x39\xfd\x00\x4b\x84\xe6\xb2\xc2\x86\xc5\x89\x9d\x3f\x4f\x42\x8c\x5e\x6d\xdc\xcc\x90\x7e\x4c\x9c\xba\x22\xee\xb4\x8f\xb4\x12\xaa\x35\x2b\xc5\x4b\xf2\x3f\x7b\xef\xbf\xfc\x38\x1a\x7c\xb7\xb7\xf7\xcb\xf3\xd1\x5f\x7f\xfd\x72\xef\xfd\x18\xfe\xf1\xc5\xe0\xbb\xc1\x47\xf7\xc7\x97\x83\xc1\xde\xde\x2f\x3f\xbe\xf9\xe1\xe2\xf4\xe8\x57\x3e\xf8\xf8\x8b\xa8\xf2\x4b\xfc\xeb\xe3\xde\x2f\xec\xe8\xd7\x3b\x0e\x32\x18\x7c\xf7\xc7\xd6\xaf\xdc\x59\x25\xee\x4f\x21\xee\x49\x1d\x7e\x10\x65\xd8\x06\x74\x7b\x5a\x8b\x36\x19\x65\x69\x35\xda\x0d\xeb\xb6\xd5\xe8\xa4\x29\xa8\x79\x7e\x1c\xae\x88\xcc\xb9\x36\xca\xa1\xd1\x07\x69\x98\xce\xca\x75\x64\x94\x5a\x39\x00\x09\xdd\x54\x63\x7b\x75\x9f\x0a\x1a\x24\xb1\x48\xa7\xf9\xd9\xfe\xf3\x3c\x2f\x32\x68\x6b\x0e\xeb\x79\xe4\x72\x59\x60\x73\xdd\xca\x86\x4f\x1f\x5b\xd9\xf0\x14\x65\x83\x62\x49\x55\x72\xbd\x38\x90\x42\xb3\x0f\xad\x3c\x2c\xb1\x68\x38\x8f\x07\xb4\x39\x63\xb6\x8a\xdb\xfe\x46\x64\x81\x79\xdf\x8d\x72\xfa\xb9\xac\xb2\x14\x8a\x39\x2a\x01\x06\x26\x56\xe9\x31\x8d\xd6\x1f\xd8\x3d\x90\xca\xdd\x7c\x88\xb3\xe7\xd0\xcc\xfc\xad\xe2\x57\x34\x33\xd6\x6e\x7d\xc7\x29\x58\x30\xe1\x4d\x77\x5d\xf3\x9a\xaa\xcb\x7a\xc1\xb3\x91\xd1\xa1\xfd\x3b\x3f\x73\x9f\x04\xa7\xd8\x07\xfd\x18\xb5\x34\x50\x90\x4e\x4b\x7e\xc5\x33\x36\x63\x47\x2a\xa1\x19\xc8\xb5\x7e\xf6\x8a\xfd\x1b\x46\x87\x89\x2f\x65\xa6\xc8\xf5\x9c\x19\x59\x4d\xa8\x73\x01\x40\x85\xdd\x8c\x72\x41\x72\x33\x45\x85\xbb\x59\xa1\x2f\xc1\x88\xff\x82\x96\x66\x82\xbd\xcf\x00\x4c\xe4\x89\x94\x99\xad\x78\xc8\x16\xf5\xf8\xb6\xf6\x47\xc8\x7f\x0a\x76\xfd\x4f\x33\x9a\x22\xd3\x8c\xce\xbc\xab\x40\x31\xbd\xe4\xed\xab\x87\xbe\xf1\x03\xa0\x9c\xa0\x62\x84\x66\xd7\x74\xa1\x6a\xc7\x49\x80\xfb\xa0\x5e\x92\x17\x03\x60\x67\xaa\x88\x1f\x23\x25\x5f\x0d\x20\xfc\x77\xb0\x7f\xfa\xcf\xf3\x7f\x9c\xff\x73\xff\xf0\xcd\xf1\x09\x39\x91\x9a\xe1\xa6\x16\x34\x07\x4c\xbc\x85\x61\xde\x12\x9e\x01\x56\xba\x54\x63\xf0\x5d\x72\x45\xae\xb9\x48\xe5\xb5\x6a\xed\xa3\x45\xf6\x33\xc4\x63\x54\xb4\x1a\x23\xa1\x05\x85\x9e\x87\x1d\x76\x98\xa5\x0c\x93\x70\x50\xd8\xc3\xd3\xf4\x59\x5a\xca\x02\x89\xe0\x9c\x5c\xf5\x56\x1b\x9b\xd1\x61\x0e\x2b\xcc\xef\x34\x1e\x70\x56\x52\xa1\x6b\x6f\x4f\x3d\x67\xb6\xd9\xe2\xb8\xf3\x74\x3c\xee\x8a\x26\x9a\xf6\x57\xcd\xb4\x9f\xa6\x2c\x8d\xc8\xff\xe4\x32\x07\x0f\xdc\xc7\x2d\x6a\x94\x0a\x72\xfa\xf6\xfc\xf8\xff\x69\xf0\xf1\xa2\xe8\x96\x28\xd5\x4f\x65\x6c\x29\x8b\xde\x66\xf7\xcc\x56\x5e\x6e\xe7\x77\x23\xe6\xd7\xef\x96\xfd\x84\xe7\xcf\x2a\x11\x03\x19\xd5\xe3\x93\x5c\xa6\x6c\x4c\x4e\x7d\x9c\x20\xfe\x35\x00\x38\xa0\x25\x23\xe6\x12\xa1\x39\xcd\xb2\x45\xa8\xa2\x69\x89\x55\x88\x11\x36\x43\x28\xc8\xa7\x34\x53\xeb\x96\xc6\x5d\xf6\x46\xa3\x47\xbc\x31\xf6\x70\x2f\xd3\xe1\x47\x23\x29\x13\x52\x5b\xc5\xda\xbc\x25\xe0\x5d\x94\x32\x21\x68\x7c\x07\xc9\x58\xd1\xfe\xa6\x30\x56\xe1\xb6\x46\xae\x1c\xb1\x4f\xfd\xc8\xe8\xa8\xae\x14\x6b\x2a\xe8\xae\x0f\xb1\x37\xc7\xcd\xe8\x25\xa3\xa9\x14\xd9\x02\x32\x2f\x31\x97\x22\xa7\xea\x92\xa5\x78\xc2\xaa\x66\x3e\x52\x61\x46\xf4\x8f\xba\x30\xef\xed\xc2\x12\xa0\x92\x61\x86\x07\x84\x33\x58\xba\xe6\x59\xef\xb0\x08\x0d\x51\xde\x8a\x6c\x71\x26\xa5\x7e\xe5\xcb\x68\x7b\xe1\x80\x9f\xad\xb6\x1c\xbb\xa2\x41\x9d\xa4\xf0\xdc\x11\xcc\x06\x2c\xaa\xb0\x82\xf7\xb0\x9e\xf1\xc7\xbe\xa4\xca\x4a\xec\xab\x1f\x4a\x59\xb5\xde\xc4\x96\x94\xcd\x1f\x8e\x0f\x41\x14\x55\x36\x54\x29\x74\xb9\x00\xe8\x80\x65\xd4\x37\x6f\x18\xbc\xb3\xc1\xd6\x70\x4d\xd4\x71\x31\xf2\x86\x2e\x08\xcd\x94\x74\xb4\xe4\x62\xa5\x15\x6a\x4d\x5c\xf3\xf3\x44\xea\xf9\x92\x6d\x6b\x16\xd4\xf2\x7d\xc3\x20\x72\x59\xc3\xd0\x71\xb1\x74\xbb\xa6\x97\x4c\x91\xa2\x64\x09\x4b\x99\x48\xd6\x3d\xed\xeb\x0e\xf8\x01\xeb\x9c\x48\x61\x16\x66\x2f\xcc\x73\xec\x23\xbd\x96\xa4\x21\xab\x40\xcc\xd8\x5a\x7f\x14\x22\xc7\xb0\x2c\x2b\xc5\x4a\x0c\x73\x97\x15\xc3\x99\xfc\xb1\x9a\xb0\xcc\x50\xde\x98\xa4\xb6\x53\x3c\xba\x33\x78\x4e\x67\x8c\x50\xed\x39\x4d\x4b\xc2\x84\x32\x12\x13\x1d\xa0\x9a\xa4\x92\xd5\xd5\xf7\x54\x91\x77\xc7\x87\xe4\x39\xd9\x33\xcf\x1a\x00\xff\x40\x23\x79\x2d\x31\xc9\xad\x69\xa3\x4e\xdd\x10\xf0\x4a\xc0\xbc\x44\x96\x28\x24\x86\x44\x48\xa2\xaa\x64\x1e\x76\xaf\x77\x66\xb3\x4d\x84\x84\xd0\xca\x66\xf2\xfa\x7a\x25\xd4\x3b\xc5\xca\xde\x04\xd4\xbb\x16\x02\x2a\x54\xa3\x0c\xcf\xc5\xd4\x43\xc6\xca\x99\xa6\x29\xd5\xd4\x0a\x2e\x77\xc1\xc6\x4e\xe9\xef\x5b\x7c\x29\xf6\x9a\x8b\xea\x03\x26\x1e\xf5\xe7\x6a\x39\x3f\x82\x61\x49\xe2\xa8\x0e\xb3\x4e\x8b\x22\xe3\x88\xb6\xd1\x48\x84\x3b\x8e\x78\x65\x78\x83\x9a\x08\x72\x82\x66\x99\x34\xf2\xd1\x28\x27\x54\xa4\x32\x5f\x7a\x98\x51\x22\x59\x84\x97\x3a\x26\x5b\xee\x8b\x8f\x0d\x71\x0a\x65\xec\x8a\x75\xc0\x16\x6b\xe2\xc3\x9a\xd1\x0c\x71\x1c\x47\xc0\xf0\x24\xa3\x13\x96\x21\x8d\x91\x03\xd5\x32\x07\xae\x3b\x1b\xb5\x94\x59\x7f\xe5\x33\x67\x32\x63\x98\xde\xe5\x08\x61\x86\x7f\x14\x74\x80\x41\xfa\xa2\x03\x58\x83\x11\x1d\xc0\xae\x7d\x0c\x74\xa8\x3a\x6c\xf5\xa4\x49\x07\xa3\x37\xc4\x74\x80\xcd\x7b\xd3\xe9\xa0\x58\x92\xc8\xbc\x38\x2d\xa5\x31\x3b\x7b\xdb\x9b\xec\xb0\x75\xcc\x10\x1d\x1b\x2b\x92\xb1\x60\x2f\x88\x2f\xa6\x65\x90\xd8\x49\x35\x6e\x12\x2e\xbb\xf3\xff\x17\xec\x59\x20\x7a\x9a\x1b\x99\x1b\x25\x0a\x2f\x9a\x3b\xed\x0f\x8f\x79\x3b\xe8\xa3\x36\xa2\x83\xb3\xb3\x97\xdd\x48\x26\x34\x03\xec\xd8\x6e\x2c\x47\x9a\x6c\xd7\x1c\x38\x48\xe7\x85\x18\x25\x9c\x73\x09\x24\x00\x23\x0a\x67\xac\x0b\x53\xc8\x94\x05\xb1\x6c\xcc\x43\xbe\xc0\xb4\x4f\xb8\xce\x65\x12\x1b\xbd\xc2\x85\x95\xd3\xe8\x6e\x2d\x2d\x02\xda\x1b\x8f\x48\x6b\x5e\x90\x89\x94\x8b\x19\xf8\xd5\x86\xa4\x64\x19\xe6\x20\x5b\x21\x70\x89\x16\xe4\x2e\x2c\x09\x37\xa8\x5b\x0f\xee\xd1\xa0\x8b\x71\x29\xec\xc8\xe0\x29\x72\x1a\xd6\x14\xc5\x2d\x57\x64\xe7\xb5\x23\x40\x07\x08\xcf\x4d\xdc\x61\x76\xf0\x0b\xfd\x6c\xa2\xa7\xf3\x92\x8b\xd4\xa6\xeb\x46\xc4\xf2\x60\xeb\xa8\x07\x43\x22\x38\x4f\x43\xd9\xf2\x92\xbc\x17\xc4\x13\x8b\x8c\x5a\xb3\xc7\x19\xaa\xcc\xce\x47\x37\xba\xdd\xf1\xea\x1f\xd2\x1c\xe6\x9d\x80\xb9\x37\xcf\x1d\x19\xcb\x7d\xf9\x3a\xf7\x2d\x6b\x85\xee\xb1\xd2\xaf\x6f\x2b\xe6\x67\x1c\xd6\xa9\xf4\x89\x61\x6b\xcd\xc5\x4c\x85\x96\x0c\xcd\xb2\xc8\x19\xbe\xca\x94\x71\x33\xec\xa1\xf5\x97\x4d\x88\x46\x99\xc1\x63\x31\x43\x32\xa3\x4e\x3c\x72\x23\x64\x96\x2b\x7a\x50\x1a\x4a\x68\x4e\xb3\xf3\xa2\x3d\x44\x29\x59\x82\xc3\x7b\x73\xbe\x1f\x0f\x0d\x9b\x35\x74\x7e\x30\x73\x65\x7e\x27\x34\xcd\xb9\x52\xe0\x08\x63\x93\xb9\x94\x97\x64\x6f\x05\x1e\x57\x90\xa7\xa5\xf8\x4c\x3d\xb3\x3c\x3f\x32\x6f\x3f\x20\x5c\x64\x3e\x2b\x0a\xec\x60\xa1\x95\x73\xe4\xc0\x43\x12\xff\x16\x30\x87\x16\xb7\xda\x26\x2b\x2c\xbf\x26\x22\x55\x1b\x2e\x58\xbb\xc0\x5e\x9e\x9e\x93\x8e\xb0\x2b\x9f\x98\xa2\x13\xcb\xdb\x4d\x64\xb5\x95\x74\x44\xed\x71\xed\x44\xb2\xca\x45\xc2\x54\x7f\x80\x4e\x7f\xaf\xc7\x24\x29\xc3\x2a\x1e\x06\xd9\x4f\xf4\xc6\x24\x3b\xf0\x4b\xef\x42\x31\xa8\xbd\x75\x37\xd4\xa8\x2f\x6a\xe1\x62\xec\x91\xac\x98\xd3\x11\x1a\xe9\x46\xa2\x81\x08\x74\x2a\xc4\x5c\x0a\x69\x8b\x24\xcc\x26\x2a\x05\xb0\x34\x88\x28\x8c\xe6\xc1\x9c\x58\x11\x1d\xbc\xea\x41\x1d\x25\x0e\x03\x81\x50\x4c\x86\xf8\x11\xf5\x3b\x5c\x73\x3d\x77\x9d\x5e\xa2\xa8\x21\xbc\x49\xc9\x14\x04\x60\x04\x61\x65\x29\x4b\x9b\x90\xe5\xfc\xd6\x30\x12\x48\x72\xc8\xe8\x32\x4c\x42\xcd\x5f\xbb\x2a\x0c\x54\xd7\x50\xf0\x90\xaf\x68\xb8\x89\x4d\xa7\x2c\x01\x45\x2b\x24\x30\x4a\xed\xbd\x1a\xf8\xd6\x56\x19\x18\x06\xb3\x50\xf2\x39\xff\x60\x9e\x12\xde\x15\x86\xc4\x2d\xe0\xec\xea\x9f\x07\x63\x42\x8e\x85\xcf\xe0\x1d\x9a\x59\x0c\xaf\x74\xa9\x67\xda\x7c\x62\xd8\x87\x00\x3e\x20\x74\x9c\x19\xed\xb0\xac\x7a\xe0\xf8\x2e\xee\x70\x12\xba\xc4\x7b\x15\x07\xe0\x1a\xb7\x83\x9a\xa9\x77\x3a\x40\x17\x57\xb9\xb9\xe4\xa1\xdc\xe5\x8f\x23\x00\x42\xba\xca\x39\x8b\xa6\xd0\x13\x38\xfc\x79\x30\x5a\xa0\xbd\xfb\x80\xdb\xa9\x4c\x11\x4d\xc5\xa3\x41\x40\x4f\x27\x40\x77\xe1\xff\x71\xfa\x59\xad\xe3\x09\x89\xd5\x01\x21\xcc\x8a\x85\xd4\x4e\x89\x51\xb5\x33\xe7\x5b\xc8\x8b\x8c\x41\x15\x67\x30\x72\x5d\xa0\x1a\xa0\xc9\x0f\xfd\x8b\xd4\x80\xf4\x16\xdc\x65\x48\xfe\x0d\x8b\xd2\x27\xa2\x3a\xdc\x89\x53\x7f\x3b\x5a\x88\x5c\xb9\xd6\x12\x50\x61\xa9\xa5\x73\x5d\x90\x94\x4f\xa7\xcc\x25\xbc\x1a\xcb\x91\x96\x34\x37\x22\x5e\x11\x4b\x82\x09\x9b\x71\x4c\x88\xf4\x82\x6d\xd7\xa8\x7b\xb6\xd6\x6f\x88\xc2\x90\x6b\x92\xf3\xd9\x1c\x19\x85\x50\xa8\xd0\x25\x2e\xa8\x98\x49\x9a\x12\xe0\x6d\x59\x92\x6b\x5a\xe6\x66\xdf\xa0\xc9\x1c\x22\x94\x54\x90\xb4\x2a\x01\x65\x59\x33\x9a\x2e\x46\x4a\x53\x6d\x34\x65\x56\x5a\x83\xd2\xbd\xff\x16\x52\xff\xd6\x63\x0b\xa9\x7f\xc7\x63\x0b\xa9\xbf\x85\xd4\x5f\x3e\x36\x26\x3b\x74\x0b\xa9\xff\xb4\x60\x92\xb6\x90\xfa\xeb\x8e\x26\x6c\x21\xf5\xb7\x90\xfa\xb7\x1d\x5b\x48\xfd\x4f\x1c\x5b\x48\xfd\x16\xc7\x13\x90\x5c\x5b\x48\xfd\x16\xc7\x16\x52\x7f\xf5\xb1\x85\xd4\x5f\x3e\xb6\x90\xfa\x37\x1e\x5b\x48\xfd\xd6\xc7\x16\x52\x7f\x0b\xa9\xbf\x45\x1a\xbd\xdf\x58\x9b\x89\x34\x4a\xb6\x90\xfa\xf6\xd8\x42\xea\x3f\x09\x3c\x45\xb2\x85\xd4\xbf\xd3\xb1\x85\xd4\xdf\x42\xea\xb7\x39\xb6\x90\xfa\x4f\xc5\x5d\xb2\x85\xd4\xdf\x42\xea\xff\x7e\x14\xdd\x2d\xa4\xfe\x16\x52\x7f\x0b\xa9\xbf\x85\xd4\xbf\xf5\x2d\xb6\x90\xfa\x4f\xc1\x04\x54\x3a\xe5\xad\x10\x40\xef\x02\x56\x64\x93\xd0\x03\x6c\x80\x49\x35\x9d\xb2\x12\x24\x17\x3c\x79\x29\x79\xaa\xc6\x65\x6c\x06\x59\x99\x1e\x02\xee\x91\xad\xd7\xb9\xe1\x76\x0b\x46\x00\x48\x9d\x75\xa6\xf8\xd1\xdb\x57\x2b\x90\x91\x5a\x67\x15\xb6\xcd\x91\x86\x77\x7e\x2b\xda\xc5\xc7\x6f\x20\xf8\xaa\xfa\x31\x4b\xf7\x24\x93\xca\x66\xb8\x03\xb1\x92\x39\x15\x82\x39\x7b\x8f\x6b\xf0\xa3\x4c\x18\x13\x44\x16\xcc\x46\xa7\x29\x51\x5c\xcc\x32\x46\xa8\xd6\x34\x99\x8f\xcd\x93\x84\x23\x76\x9d\x8d\x6e\xcf\x28\x5d\x32\x9a\xbb\xbc\xfc\x9c\x72\x1c\x8a\xd0\xa4\x94\x4a\x91\xbc\xca\x34\x2f\xfc\x60\x44\x31\x28\xa8\xc1\x8d\xca\x13\x03\xb2\xe2\xea\x14\xf6\x61\xfd\x34\xfb\x5a\x32\x84\xa6\x03\x6b\x73\x08\x78\xe0\x79\xa1\x17\x3e\x8f\x97\x91\x29\x2f\x95\x26\x49\xc6\x61\xb7\x86\x27\x62\xed\x34\x8c\x37\x74\x7b\xb5\xb0\x6f\xaa\xec\xab\x8a\x14\xd4\xd6\x42\x2b\xcc\x8a\xad\x07\xb4\x43\xa5\x5c\x59\x35\x5f\x0d\x09\x75\xb8\x69\x48\x68\xf7\xa6\x40\x6a\xb7\xb3\xe0\xe8\xf6\x54\x30\x5c\x80\x17\x5b\xa7\x0d\xd7\x8c\x0e\x25\x0e\x8e\x39\x87\x51\x35\x47\xad\x50\x40\x96\xde\xd2\x32\x80\x09\x10\xec\xca\xf0\x00\x4b\x98\xd9\x5f\xe9\x0d\x5c\xff\xd9\x99\x3e\xd8\x14\xdf\x30\xa5\xe8\x8c\x9d\xb6\x0c\x34\xdc\x64\x91\x41\xac\xa1\x9e\x18\x60\x85\x0c\xab\x6b\xfd\x99\x3a\x3b\x33\x56\x83\x48\x8e\xef\xe4\x95\x9f\xeb\x92\x6b\xcd\x60\x52\x01\x61\x0f\x62\x95\xcd\x02\xfc\xdd\x46\x8e\xe7\x1b\x37\x48\x7d\xb3\x11\xea\x22\xc5\x8c\xcb\x09\x23\x93\x92\xb3\x29\x99\x72\x48\xe3\x84\xc4\xca\x21\x02\x2e\x51\xf4\x02\x28\x65\xec\x5d\x29\x9c\x2e\xeb\xde\x6b\x4c\x7e\xb6\x2f\xa6\xcb\x4a\x24\x34\xc0\xb2\x85\x0a\x53\x3e\x25\x33\x48\xcc\xb4\xda\xe2\x9f\x9e\xff\xf5\x2f\x64\xb2\x30\x5b\x1a\x68\x56\x5a\x6a\x9a\xf9\x8f\xcc\x98\x98\x19\x5a\xe1\xf2\x8c\x6b\x24\x3d\x05\xa0\x9b\x07\xbe\xf8\x8b\xaf\x2e\x27\xf1\x1e\xfb\x2c\x65\x57\xcf\x02\xfa\x8d\x32\x39\x5b\xd5\x1f\xa5\x7d\xca\x76\x4b\x93\x68\x05\x9b\xc9\x8c\x27\x8b\xce\x8c\xe6\x90\xbf\xc8\x5c\x5e\xa3\xae\xbf\x82\x7b\xea\x72\xab\x42\x16\x55\x86\x4e\xe7\x57\xbe\xba\xb8\x52\x6c\xb9\x06\x70\xe5\xba\x00\x37\xa9\x1d\xa2\x89\x9b\x8e\xf9\xb8\xee\x91\xd2\xd6\x96\x58\x47\x9e\x07\x00\x03\x43\xe8\x15\xcd\xb2\x09\x4d\x2e\x2f\xe4\x6b\x39\x53\x6f\xc5\x51\x59\xca\x32\x7e\x97\x8c\x1a\x69\x39\xaf\xc4\x25\x76\x70\xf0\x10\x09\x72\x66\x54\xab\xa2\xd2\xae\x90\x61\xd5\x07\x63\xbd\xbc\x13\xc2\xce\x0c\xaa\x47\x61\x1f\x78\x6d\xeb\xd8\x52\x2d\xe4\xc8\x70\x7c\x15\x32\xdb\x57\xcf\xff\xf4\x0d\xb2\x2e\x91\x25\xf9\xe6\x39\xe4\x6c\xab\x21\x2e\x62\x90\x6d\x66\xa3\xc8\x69\x96\x19\xb3\x21\x64\x4a\x43\xe8\x55\x4c\xf8\xd9\x79\x50\x77\x67\xb7\x3b\xab\x52\x17\x17\xff\x00\x3d\x8a\x6b\xc5\xb2\xe9\x10\xab\x92\xbc\x59\xb3\x0b\x1b\xc3\xae\x95\x3e\x50\x1a\xb6\x01\x0a\xd0\x95\xcc\xaa\x9c\x1d\xb2\x2b\xde\x47\x13\xa7\x68\x34\x67\xea\x67\x5c\x41\x01\xd8\x24\x93\xc9\x25\x49\xed\x8f\x41\xe6\x49\x13\x09\xbc\x3d\x15\xda\xe6\xe0\x74\xc8\xbd\xb9\xf1\xfb\xa3\xac\x9b\x9c\x16\x85\xaf\x11\x2a\xe9\x75\x44\x0c\x58\x93\x00\x57\xd0\x11\x4f\xa6\xb3\x9b\xb9\xab\x93\x79\x64\xbf\xc8\xc8\xcd\xd6\x43\xb4\xce\x3a\xe9\xee\xa3\xae\xdf\xbe\xbd\x63\x32\x62\x88\x7a\x40\xb7\x1a\x0a\xf8\x37\x56\x95\x2c\x55\x45\xfa\xc2\x3a\xcf\x18\xa8\x00\x18\xf6\x01\x91\xdc\xde\xe1\xda\x83\x77\xb3\x5b\xca\x51\x44\x17\xe1\xbd\xca\x39\xd5\x56\x21\x74\xee\x6b\x4a\x0a\x56\x2a\xae\xcc\xbe\xfc\x13\x2c\xa8\x83\x8c\xf2\x3c\x70\x01\xae\x87\x08\xb8\xb8\x01\x3e\xb9\xbb\xa4\x3c\x95\xa9\x1d\x10\x44\x21\x42\x47\xaf\x50\x6b\x63\xad\xb6\xc7\x0d\x75\xdd\xa2\xf2\xa7\x9a\x9a\xb1\xa4\x34\x67\xbc\xa8\xc4\xab\x9e\x92\x80\x84\xef\x7b\xac\xf2\xd1\xbf\x7c\x4f\x62\x00\x04\xa3\x9d\xdc\x58\x12\x46\xc6\x23\x2e\x94\x40\xa5\xb7\x76\xe0\x98\x60\x14\xdc\xac\x09\x7b\x2b\xd9\x7d\xb9\xbb\x56\x21\x89\x24\x2a\x65\x41\x67\x9d\x7a\xf9\x34\x28\xd5\x1c\x36\x04\x9a\x30\x66\x10\xfc\xee\x61\xd7\xe0\x2a\x96\xd6\x38\x3a\x80\x92\x84\xd1\x51\x47\x60\x6b\x20\x60\x3d\xf6\x35\x5d\x10\x5a\xca\x4a\xa4\xd6\xbf\xe4\x1d\x7c\x6f\x1a\x0f\x3e\x91\x82\x39\xc7\x79\x13\xa7\x02\x3c\xfa\x5c\x90\x17\xe3\x17\xcf\x9f\xca\x4e\x05\x5f\xd8\xd8\xa9\x4e\xfc\x4e\x85\xf2\x69\xad\xdf\xea\x10\xef\x7b\xfa\xde\x37\xd6\xc5\x52\x03\xda\x73\x07\x97\x0d\xa7\xae\x4b\xae\x59\xd0\xe3\x6f\x0f\x0c\x17\x63\x1f\x06\xa8\x0c\x83\x55\x9d\x24\x3a\x12\xa9\x1b\x0c\x86\xaa\x26\x0f\x28\xb7\xac\x80\x82\xe5\xb6\xca\xc3\xa5\x6e\x11\x61\x21\xa1\x76\x76\xc8\x1e\x5e\xb9\x8b\x05\xcd\x83\xb5\xb2\x96\x25\xda\xd1\x87\xa2\x03\xc6\x66\xa3\x76\xbe\xa0\xe0\x83\x2b\x7a\xa4\xe0\xf7\x6c\x4e\xaf\x18\x14\x72\xf3\x8c\x96\x19\xc4\x1c\xcf\xf1\xdd\xc9\xa4\xd2\x84\x89\x2b\x5e\x4a\x91\x33\xa1\xc9\x15\x2d\x39\xa0\xe2\x94\x0c\x90\x1d\x8c\x2d\xfa\xc7\xbd\x9f\xf6\xcf\x20\xa1\x61\x60\x21\x29\xec\x5b\x56\xca\xc1\xd7\x84\x6f\x12\x0c\xf7\xc9\xe9\x73\xef\x61\x68\x08\x32\xd7\xbd\x97\x79\x4e\x5e\xe9\x0a\xdb\xb2\x7c\x48\xb2\x4a\xf1\xab\x75\x49\x12\x5b\x61\x7f\xc8\x5b\xcd\x73\xa3\xda\xbf\x26\xd4\x52\xe1\x3e\xb8\xd6\x57\x14\xe8\x2d\x05\x4c\x76\x95\x2f\xda\x0b\x63\xe0\xd6\xf5\x64\xb1\x34\x30\x7d\xce\x21\x2e\x2e\xa9\x10\x80\x1b\xb3\x5e\x27\x94\x90\x29\xbb\x3f\xea\x4e\x9c\xde\x63\x87\xc0\x98\x79\x50\xc1\xa7\x92\x39\x4b\x2b\x80\x77\xe2\x0a\xc1\x51\x8d\xf9\x40\x6b\x14\x3e\x01\x5d\x82\x8e\xa7\x1e\xd2\x40\x8c\xc0\x39\x88\x34\x77\xf7\x97\x0e\x00\xc1\x9d\x50\x8d\x11\xc1\x28\x35\x63\x0d\x09\x55\xaa\xca\x71\x49\x60\x03\x84\x29\xd7\xca\xf7\x98\x75\xda\xb1\x59\x18\xf7\x2c\xa8\xea\x40\xdf\x73\x96\x01\x73\x75\xa0\xf1\xee\x49\x30\x0e\x12\x5a\xb9\xbf\x2c\xc3\xd9\x84\x09\x88\xb6\xf9\x3c\x4e\x09\x5e\xd2\x29\x87\x26\x4a\xd4\xd2\xfb\x7c\xc5\x9d\xa8\x3a\xe0\x15\x00\x0f\x43\x27\x2c\x53\xcd\x81\x26\xf5\xa4\x58\x54\x52\x4b\xf8\x8e\x5d\x72\xa9\x52\x7c\x26\xa0\x7f\xa6\x19\xed\x9e\x9d\x32\x5b\xdb\x4c\x7d\x74\xc1\x6d\x2d\xd5\xa2\x2c\xac\x9c\x16\x23\x6b\xf5\x6a\x99\xf3\xe4\x1e\x23\xc9\x7b\xbe\x72\xa3\x56\x3a\xaa\xc1\x7d\x7b\xbe\xe4\xf1\x51\x81\x57\x63\x4c\xce\x65\x6e\x53\x9c\x44\xd0\xc5\xcb\x35\x53\x35\x3b\x46\xc9\x0c\x2d\x20\xf1\x88\xd7\xd1\x78\xe8\x7a\xe3\xaa\xa0\xe1\x39\x5e\x25\xb7\x61\x5c\x80\x9f\xb4\xcd\x5c\x65\x96\xc9\x6b\x48\x2c\xc6\x71\x1d\x6f\x43\x0a\xcc\x4b\x32\x6a\x74\xa6\x1d\xc7\xa0\xa1\xb7\x3f\xc7\x5e\x3b\xfc\xf4\x53\x30\x3f\x07\xe0\xf8\x8e\x0f\xc3\x3f\x8f\x4f\x0f\xdc\x9f\xcd\x37\x89\x9b\x30\xdc\x7c\x55\x08\x87\x7d\xd3\x55\x53\xec\x63\xf4\x89\x9f\x0f\xe6\x54\xb8\xb8\xd5\x8d\xcf\x5b\xa8\x44\x67\xf5\xeb\xcc\x69\xc9\x2c\x5c\x9c\x11\xdc\xaa\xa0\xc9\x8d\x6f\xe1\xb1\xd9\x6e\xbd\xe0\xd6\x37\x55\x55\xe1\xfa\x6b\x67\x70\xa1\x7f\x93\x9a\xcb\x7e\xf9\xe2\xd7\x3b\x12\xf3\x53\xf7\xac\x22\xed\xed\xf7\x44\x5d\xfa\xee\x74\xc7\xea\x1e\x5e\x77\xbb\x37\x68\x83\x77\xa7\xeb\x6f\x6a\xc1\x7b\xd7\xa7\xb9\xd6\x6d\x77\xfb\xb0\xe6\x6c\xdf\xe1\x72\x9c\xfb\x4f\x67\xcd\x99\x05\x79\x0c\x88\x9b\xd3\xc5\xa9\x4c\xcd\xda\xc4\x14\xb9\xfb\x01\x1b\xb4\x96\xf6\x6d\x3d\x63\x2d\xfc\x59\xed\xfd\x58\xed\xfc\x02\x0d\x5d\xe1\x06\xd4\x53\x8b\xc8\x26\x66\x24\xc2\x99\xaa\xca\x92\x09\xe8\x90\x5f\x41\x52\xa4\xeb\x7c\x8f\xf2\x1c\xe4\xb2\xc5\xf4\x44\x60\x7a\xb2\xef\xb7\x4d\x9b\x2c\x97\x53\xc0\xf9\x0c\x70\xad\xa7\x15\xe4\x3e\xc2\x2e\x81\xb8\x75\x52\x98\xf7\x78\xb9\x0a\x4c\x43\x16\x4c\x04\x6d\xf1\xad\x82\x3d\x32\xfc\x17\xc1\x6b\xa0\xce\x30\xce\xd3\x3f\x14\x19\xd5\x53\x59\xe6\x23\xa7\x49\x8e\x22\x7d\x82\x1c\x40\x16\x8e\x72\xa6\x18\xa6\xc2\x22\xfe\xa6\x48\x33\x16\x6c\xfc\xfe\x53\x45\x8a\x68\x55\xa4\x12\x25\x4b\xe4\x4c\xf0\xff\xd4\x84\x80\x2d\xd0\xfb\x91\xa8\x32\x9b\x2e\x11\x55\x96\xdd\x3f\x65\xa1\xa5\xbe\x20\xaf\x58\x39\x67\xf4\x9e\xcc\xdb\xc8\x7e\xb1\x63\xd4\x6d\x4a\x95\x85\x1f\xb0\xda\xb1\x7b\x88\xd1\xa2\x65\x02\x65\x70\x18\x8d\x77\x39\xce\x14\xf6\x7e\xa3\x14\x52\x32\xe3\x57\x4c\x38\x74\xf2\x83\x8c\xfa\x56\xdb\x0e\x90\xd5\x22\xa4\x57\x5a\xfa\xfc\x06\x42\x75\x80\x91\x0c\xe9\x50\x36\xb4\x1a\x8e\x13\x5c\x62\x1b\x75\x67\xae\x29\xda\x5d\xae\x84\x14\x03\xec\x12\x39\xac\x3f\x29\x77\x6e\xd8\x08\x84\x93\x24\x90\x08\xe3\xac\x16\x9b\x00\xf3\xe9\x47\xd8\xec\x35\x23\x83\x56\x0d\x63\x35\x6b\x8f\x16\x5b\x13\x36\x33\x5b\xc7\x02\xf5\xa1\xe3\x69\xfc\x24\x1e\xe1\xf3\x43\x99\x14\x68\xea\xb5\xe9\x78\x2a\x53\xa3\xb0\x0d\x89\x9f\xca\xb0\x4f\xb9\x0d\xcd\xe0\x9a\x0c\x16\x23\xea\x73\x65\xc9\x54\x21\xb1\x4d\x40\xf8\xd8\x61\xe0\x2a\xe3\x3a\xca\xcb\xc3\x86\x6f\x7e\x69\x20\x90\xdb\x7f\x58\x29\x57\xaa\xfb\x33\xae\xc7\x97\xdf\x80\xae\xcf\xc4\x9c\x8a\x04\xcd\xac\x67\x97\xac\x50\xcf\x14\x9f\xa1\x6a\xff\x97\x6f\xbe\x01\x3d\xdf\x91\xe4\xd9\xd9\xd1\xfe\xe1\x9b\xa3\x71\x9e\x3e\x22\xa5\xbf\xa0\x5a\xb3\x52\xbc\x24\xff\xb3\xf7\xfe\xcb\x8f\xa3\xc1\x77\x7b\x7b\xbf\x3c\x1f\xfd\xf5\xd7\x2f\xf7\xde\x8f\xe1\x1f\x5f\x0c\xbe\x1b\x7c\x74\x7f\x7c\x39\x18\xec\xed\xfd\xf2\xe3\x9b\x1f\x2e\x4e\x8f\x7e\xe5\x83\x8f\xbf\x88\x2a\xbf\xc4\xbf\x3e\xee\xfd\xc2\x8e\x7e\xbd\xe3\x20\x83\xc1\x77\x7f\xbc\xe7\x8b\xb6\x2c\x61\xe9\x5a\xb6\xd2\xa9\x54\xa5\xc7\xf2\x94\xa2\x64\x2c\x07\xf1\xd7\x26\xb1\x2b\x76\xa8\x36\x86\x72\x1b\xac\xfd\xcb\xc8\x44\xf7\x34\x31\x33\x62\x52\xa1\xe8\xcc\xe4\x35\x24\x63\x72\x69\x14\xa7\x31\x79\x0b\xfb\x20\x39\x61\x57\xac\x1c\xba\x51\x5f\x9b\x8b\x4e\xfd\x35\xa1\xc7\x6e\xd5\x15\x2d\xcb\x01\x5a\xce\x89\x7b\xf7\x0e\xc4\xc3\x16\x27\xf6\xe5\x41\x3e\x8d\xc9\x4f\xb4\xe4\xb2\x52\x56\x17\x09\x91\xc1\x31\xdb\xcc\xef\x24\xe0\xc0\xb0\xb1\x20\x3f\x88\x2f\x22\x73\xe1\x20\x4f\x9b\x7d\x2f\xaf\x0f\x56\x6f\x09\x5c\x9b\x99\xba\x72\x8f\x2a\x5d\x56\xec\x12\xa8\x38\x6e\x06\x2b\xe5\xbf\xdb\xd1\x54\xf8\xa2\x30\x8c\x7b\x0f\x90\xad\x46\x13\xc3\x51\xe6\x7c\xe6\x72\xaf\xe1\xfb\xd1\xd2\x0d\xce\x7a\x0e\x69\x31\xa5\x6d\x96\x69\xdb\x12\x80\xa2\xf9\x7d\x1d\xd8\x22\x86\x5e\x0e\xd1\x9b\x5d\xf1\x51\xbd\x6e\x76\x90\x4f\x60\x13\x19\x25\x25\xd7\x3c\xa1\xd9\x0e\x6c\x4e\xee\xa7\x24\xab\x8c\x9e\x18\xfe\x5a\x32\xa2\xaf\x25\x3e\x85\x66\xe4\x92\x2d\xae\x65\x99\xba\xfd\xd9\x3d\xb1\x9e\x0b\xa5\xdd\x23\x8d\x2d\x08\x0b\x18\x3d\x12\x65\xce\x4a\x32\x61\xce\xd9\xde\xb8\x78\x31\x26\xfb\x62\x61\x23\x95\x22\xac\x47\x0c\x40\xdc\x40\x47\x40\x2d\x2a\x62\x12\xbb\x89\xb9\xa7\x51\xac\x14\xbd\xc9\x11\x6d\x14\x30\xbf\x0a\xdc\xee\xef\x3c\xd1\xb2\xb4\x05\x51\xb0\x3a\x4a\x2c\xe7\x92\xee\xe7\xcf\x22\x2d\x8c\x7e\xc3\x05\x53\xea\x07\x33\x95\x5d\xd4\xd5\x98\x3b\x28\xa8\x25\x76\x6c\x28\xaa\xaa\xb3\x8f\x99\x59\x52\x18\x4e\x36\x62\x58\xa6\xf5\x95\x63\xb2\x0f\x27\x20\x7d\xde\x68\x5e\x50\x70\x67\x06\xe3\x5a\x35\xfb\xd0\xe3\x15\xfb\x27\x87\x2e\xcd\x19\x35\x05\x15\x23\xab\xa3\xca\x1c\xbf\x09\x68\x7a\x36\xd9\x96\xfd\x56\x51\x68\xa9\xbb\x73\x51\x56\x6c\xa7\x9d\xaa\x84\x98\xfd\xcf\xfe\xfc\xcd\x73\xd0\x96\xfc\xf3\x46\xf0\xbc\x36\xaa\xd2\xfd\xd3\x69\x5a\x25\xd2\x34\x73\x88\xce\x42\x7e\x70\x04\x77\x76\x87\x8d\x6f\x41\x19\x30\x4c\x93\xa7\x79\x2b\x2f\x6c\xab\xb4\x99\xf6\x09\x33\xa3\xfa\x75\x2f\xee\xdf\xee\xac\x4b\xae\x4b\xf4\xdc\x3e\x02\x62\xf5\x68\x38\x2b\x0a\xa7\xc4\x3f\x27\x70\x02\x63\x57\x0c\x7b\x1a\x32\x67\x41\x70\x41\x00\x01\xc4\xe3\xa2\xe8\x90\x25\xdc\x42\xde\x40\x51\x4c\x67\xfd\x6e\xf7\x0c\x07\x22\x45\xad\xd0\x2d\x15\x3b\xf8\x60\x30\xe8\x1d\x56\x95\xdb\x87\xca\xb1\x21\x79\x2b\x5e\x61\x2a\xfd\x10\xb5\xbb\x08\xa8\x04\x2f\xea\xb5\xa2\xf0\xd9\x1f\xec\xb7\x8f\xf0\x95\xdb\x08\x85\xfb\x93\x3b\xb0\x1c\x3b\xee\xfe\xbb\x67\x8d\xb1\x22\xd6\x8b\x2c\x63\xbb\x43\xf2\xba\x4d\x9a\x15\x9f\x64\x56\xca\xaa\x70\x41\xd7\xb8\xe7\x59\xdd\xe8\x03\x63\x85\xd8\x12\x58\xc8\x78\x68\xef\xfc\x00\x06\x66\xb5\xd7\x2c\x25\x09\x9a\xc7\x6e\xd7\xc5\x82\x29\xf4\x20\x94\x95\x88\x5b\xa2\x07\x61\xcb\x9d\x8c\xcd\x68\xb2\xd8\x89\x9f\xb3\x2a\x48\xcc\xa1\x8e\x87\xe7\x88\xad\x8e\xcf\xab\xcb\x1f\xa0\x4a\x02\xf4\x07\x5c\x6b\xa0\x1a\x54\xca\xbe\xa2\xdb\xf2\x5d\xfd\x1e\x7a\xb6\xca\x0e\x96\xf9\x9f\xbf\xf9\xf3\xc8\xf9\xde\xe0\x55\x3e\x0b\x43\xf9\x20\x6f\xaf\xba\x64\x34\x67\x46\x41\xe2\xaa\x80\xf9\x05\x4d\xac\xde\xce\xfd\xd3\x6f\x53\xb7\x56\x0f\xe2\x26\xa0\x1e\xe2\xb3\x90\x2b\xf6\xc0\x77\x59\x7e\xcd\x0e\x31\x73\x99\xa5\xb0\x50\x6c\x1f\x27\xf7\x28\x42\xb5\x2e\xf9\xa4\xd2\xd6\x4d\x9a\xc8\x3c\x8f\xcb\x2b\x6d\x2f\xbd\x31\xa9\xeb\xeb\x42\x13\x16\x38\x79\x4c\xc8\x39\x63\xd8\x47\x32\x78\x0f\x90\xb3\x8e\x94\xd6\xdb\x2a\xa7\xd8\xf4\x1b\x8d\xb0\xcf\xe4\x16\x6a\xbf\x1d\xdb\x40\x5c\x47\xaf\xfd\xce\xbe\xb7\x52\xc2\x78\x19\x0a\xb8\xa5\xd6\xbe\x8d\x9d\x09\x32\x8f\xeb\x00\xad\x4d\x44\x32\xb4\x50\x08\x27\x0b\xbc\xfc\x23\xb6\x01\x85\x2c\x4b\x88\x1a\xa2\x6f\xf2\xda\x0c\x31\xe7\x05\xda\xd4\x54\xfb\xdb\x21\xde\x6f\x7e\x0e\x51\x1a\xa0\xaf\xe5\x0b\x34\x6a\xe5\x35\x78\x85\x7f\x38\x3e\xf4\x6b\xc4\x5c\xf5\xea\x1c\x43\x42\x5f\x8d\x6d\x97\x5e\x3d\xe3\x29\x99\x60\x8e\x87\x91\x97\x7b\x82\x5d\x63\xd6\xb8\x75\x9c\x7a\xbd\xfa\xca\x65\x53\xe3\x68\xfe\xe1\x76\xc8\x01\xf9\xda\xf6\x4b\x65\xa5\xb3\xca\x27\xdc\x66\x95\xbe\x3d\xdb\x75\xee\xea\xeb\x51\x79\x3d\x1a\x8d\x46\x36\x14\x0c\x52\x7a\x18\xd1\xc0\x0b\xf3\x5c\xa6\x7c\xba\x68\x50\xc2\xb0\x79\xfd\x08\xe0\x48\x2a\x16\xf6\xed\xba\xb7\xf6\xbd\x3f\x92\x77\x37\x77\x5c\x17\xe4\x86\x15\x61\xe6\xae\xf1\xa9\x55\x91\x6b\xb4\x93\x55\x0d\x80\x2e\xa7\xc8\xa4\x90\x68\x7f\xc3\xc4\x38\x2f\x90\xe5\x1a\x0b\xeb\x87\x56\x3a\xfb\x50\x48\x04\x0d\x86\x42\x16\x68\xee\xd6\x0c\x4f\x40\xf2\xa8\x59\x55\x90\x8f\x17\xad\x1a\xab\x50\x60\x44\xcc\x11\x81\x4c\xa8\x19\xd2\xbf\xce\x5e\x83\x4f\x06\x63\x72\x6c\x59\x0b\x0c\x42\x21\x6d\x8b\x38\x22\x05\x61\xc5\x9c\xe5\xac\xa4\x59\xfc\x20\x5b\xd0\xfb\xd2\x88\xdb\xd2\x70\x29\x86\x00\x72\x5a\xa0\xb4\x05\xe1\x99\xf2\xd2\xb5\x98\x0d\x42\x73\x3b\x6f\xc5\x99\x94\xfa\x0d\x57\xa0\xbb\x58\x67\x08\x6a\x9a\x3b\xab\x36\x34\xf7\x5b\x9d\x1d\xdd\x95\x93\x3f\x5b\xfc\x8b\xb8\x36\x71\x7d\xc8\x5a\x23\x41\x8c\xd0\xba\x6f\x27\xb8\x77\x16\xef\x27\x6a\xb8\xeb\x7d\xb1\xab\xfa\xbc\x2d\x35\x79\xfb\xcc\x5d\xde\x6c\x02\x17\xd5\x11\xb0\xd6\xe7\xee\x4c\xbe\x3e\xe9\x05\x2c\x73\x22\x61\x9d\x74\x64\x9a\xe3\xe5\xe6\x72\x35\x8b\x80\xbb\xcf\x77\xcd\x14\x52\x8c\xa0\xd9\x53\xa5\x5c\xe0\xb2\x74\x2e\xdf\x68\x03\xb2\x1d\x28\x71\xdb\xc4\x2e\x82\xb4\x56\xe9\x8d\xea\x24\x54\x55\x32\x9f\xcc\x98\x4a\x56\x37\x7e\xa2\x8a\xbc\x3b\x3e\x24\xcf\xc9\x1e\x24\xf2\xfa\x62\x6e\x84\xaf\x30\xa6\x6c\x23\xdb\x74\xea\x86\x88\x4d\x17\x8b\x1d\x21\x24\xca\x22\xd7\x15\x53\x0a\xbf\x0d\x5b\x0c\xce\x1b\x7a\x19\xae\x9b\xc7\xdb\xf2\x63\xbb\x74\x7d\x9f\x21\xd3\x83\x0c\x7a\xd7\x42\x06\x85\x8a\x75\x1f\x9d\x28\xd7\x3d\x7b\xbf\x77\x09\x15\x27\xb9\xf5\xc0\x54\xe7\x47\x30\x20\xe2\x46\x7c\xd0\x56\x8d\xbf\x67\x9b\xf3\x65\x7c\x20\x0b\x92\xe4\xa1\x04\x4a\x2a\x52\x99\x2f\x3d\xcd\xcc\x26\x18\x6f\xc1\x6c\x6e\xd9\xee\xa6\xa3\x53\xb5\x67\xb7\x62\x49\xb0\xf1\x7b\xa8\x92\x7d\x0d\xbe\x02\xae\x3c\x27\xa0\xf3\x00\xf2\xc7\x97\xcc\xd6\xce\x20\x0a\x9d\x8b\x86\x4a\x99\xb5\xac\xbb\x8b\xbe\xfa\x4c\x66\xb6\xde\xc1\x7d\xb6\x19\x78\x63\xbf\x5a\xb7\x0c\x13\x34\xc5\xcb\xa2\x68\x7c\x35\xb8\x73\x36\xf5\xab\xab\x56\xbb\x34\x69\x7e\x35\xa4\xc3\x46\x5f\x0d\xfb\xee\x26\x7e\x75\x9c\xfd\xdc\xc3\x66\x62\x07\x24\xd2\xe6\x60\xdb\xa6\x03\x4d\x3c\x94\x3a\x43\x12\x9c\x50\x8f\x4b\x8e\x76\xa9\x98\xc7\x44\xa7\xcf\x2d\xba\x65\x42\xb3\x39\xb6\x7c\x6f\x37\xcf\xa4\x39\xd7\xcd\x21\x83\x64\x0c\x6a\xde\x16\xce\x05\x29\x85\x14\xc1\x9c\x64\x1d\x90\x69\x04\x5f\xac\x9b\xce\xde\xe9\xb2\x21\xcc\xfe\x5b\x67\x38\x86\x77\x6b\x69\xbb\xd0\x3a\xd0\x78\x0a\x2f\xc8\x30\x5f\xb1\xa0\x7a\x3e\x24\x25\xcb\x10\x07\xd6\xae\xb3\x4b\x34\xa5\x76\xa3\xb4\x49\xc7\xb1\xee\xd1\xa0\xb0\x40\x17\x6a\x18\x19\x5c\x3e\x4e\x0d\x99\xa2\xfc\xe2\x8a\xec\xbc\x76\x04\xd8\x79\xcc\x02\x7a\x07\xbf\xc7\xcf\x1d\x7a\xb1\x2e\xb9\x48\x2d\x40\x6a\x44\x1a\x9f\xa2\x8b\xba\xa1\xf3\x30\xb9\xb5\x4e\x4b\x06\xce\x5e\x4f\x1a\x32\x6a\xcd\x0c\x36\x14\xe6\x02\xa2\xa3\x1b\x94\x4c\xe7\x53\x71\x0f\x69\x0e\xf3\x4e\xc0\x4c\x0b\xa8\x9d\x10\x72\xc5\x75\xee\x5b\xda\x35\x4b\xec\x22\x7a\x97\x8a\x5c\x3a\x8a\xdf\x7d\x0f\x4b\x35\xc3\x9a\x99\x40\x85\xaf\xa1\x2b\xad\x5d\x68\x3b\x41\x37\x54\xef\x21\xcc\x8e\xcd\x77\x5d\xda\x9d\x30\xbd\x2a\xa7\xe5\x82\xfc\x70\x7c\x88\x1a\x78\x64\x08\x08\xe9\x1e\xed\x39\x25\xb5\xe8\x84\x54\x2c\x36\x40\x71\x6e\x87\x10\xd3\x1a\x1f\xa6\x2b\xf2\x6e\x27\x33\x11\x4b\xb8\x3a\xf2\xd4\xb9\x2d\x04\x9b\xcb\x2c\x25\xd4\x33\x98\x70\x45\x60\xa9\x7b\x0e\x06\xd0\x83\xea\xcf\xb1\x31\xbe\x6c\x70\xba\x12\x75\xa5\x88\xbb\x7e\xaf\xa9\x12\xb8\x35\x3d\xb0\xa5\xd0\xce\x33\x95\xd1\x4a\x24\xf3\xdf\x0b\xcb\xac\xa0\xbe\x0f\x75\x50\x72\xc9\x4a\xc1\x32\x52\xd0\x92\xe6\x4c\xfb\x66\x87\x8a\xb5\x81\xfe\xe9\x88\x1c\xd4\x0d\x37\xa8\x03\xe6\x4f\xfb\xa6\x85\x5d\xd1\x82\xba\x60\xb0\xac\xe8\xe4\x36\xc5\xdd\xd1\xbc\xd2\xc2\x36\xf8\x6c\x39\x78\x67\x60\x8c\x4e\x6d\x08\x63\x10\x2c\x44\xf0\xdf\x88\x6f\x8b\xcb\x7c\x7b\xb0\x6e\x7e\xc6\x01\x6b\x3c\x02\x97\xc9\x70\x5f\x77\x99\x53\x99\x96\x51\xc0\x76\xd5\x92\x2b\x2a\x6e\x99\xf0\x99\x7d\xe5\xad\xe5\x2e\xd4\x01\x3e\x2a\x0f\xd7\x2c\x57\xf4\xa0\x64\x50\x71\x4a\xb3\xf3\x82\xb5\x6c\xe2\x1f\xb7\xf0\x7f\x73\xbe\x1f\x0f\x0a\x9b\x12\x24\x5b\x9b\x39\x31\xbf\x07\x25\x03\xd7\x6c\x32\x97\xf2\x92\xec\xad\x28\x7b\x0c\xaa\x5c\x14\x9f\xa9\x67\x96\xbd\x47\xe6\xbd\x07\x84\x0b\x80\xb2\x5d\x86\x00\x76\x0f\x49\xfc\x5b\xc0\x5c\xd9\x9c\x35\xbb\x0d\x2f\xbf\x26\xc8\x28\xcc\xa8\x59\x87\x81\xb3\x3c\x19\xf7\xcf\xf7\x72\xc7\x27\x26\xe4\xa6\xf2\xd7\x95\x54\x43\x87\xc6\x5a\x48\x62\xcd\x6d\xa3\xbe\xf7\x40\x87\xbf\xd7\xa3\x85\xc8\x6b\x7c\x1a\x81\xc2\xd7\x86\x92\x0f\x56\xee\x42\x73\x2a\x7b\xeb\x6e\xa8\xd5\xc7\xd0\x69\x34\x2b\xe6\xd4\xa6\x86\x61\x39\xb0\xcb\xa0\x98\x30\x32\x97\x42\x96\xb6\xcc\xa1\x2e\xe4\x01\x31\x83\x75\x37\x30\x03\x56\xde\x06\xaf\x7a\x50\x7b\x90\x5c\xbf\x94\x69\x46\x67\xd0\xdc\xa6\x51\x8d\x03\xc2\x55\x56\x18\xd5\x0c\x2f\x76\x25\x8b\xae\x71\x03\xe0\x46\x2b\x94\x62\x2e\x98\x69\xcb\x36\x20\x0b\x64\xdf\xbc\xb7\x21\xcb\xa9\x4b\x66\x76\xaf\x00\x6e\x0a\x5f\xb4\xa9\x0c\xef\x60\xfe\x06\xbf\x62\x11\x81\x51\xf2\xee\x39\xd4\x1a\x8d\x49\x56\xb8\x5f\xc0\xfd\x94\xe4\xfc\x83\x79\x4a\x78\x57\x58\x6d\x20\x52\x88\x12\xaf\xfe\x79\x60\x8c\xb1\xda\x72\x1b\x9a\x59\x0c\xaf\x0c\x9a\x2a\x08\xf8\xe1\x04\xcb\x05\xf0\x03\xc2\x48\x8b\xed\x8f\xd0\x85\xbf\xdb\xa3\x9a\xf9\x50\x69\x4f\x4b\x1d\x42\xa6\x76\x38\x33\xd1\x6e\xfb\xee\x12\x42\x35\x97\xf4\x11\x46\x5d\xde\xa3\x3f\xfb\xd6\xfe\x39\x65\x98\x62\xe5\x15\x4f\xd8\x7e\x92\xc8\x4a\x74\xca\x42\x3d\x64\xe6\x13\xa8\x66\xe9\x79\x34\x26\x7a\xdc\x53\xf8\x15\x2b\xd1\x69\xc6\x29\x22\x12\xc5\x57\x62\x91\x5d\x3d\x0e\x78\xec\x1b\x6f\x68\x59\x46\x69\x46\xdb\x65\x94\x76\xa4\x50\xd7\x54\xf9\xe5\x2f\x5e\xb5\xc3\x35\x28\x68\x9d\xf5\x4b\x69\xf0\x77\xab\x41\xd0\x54\x5d\xd6\x38\x4d\x0c\xca\x90\xfc\x62\x0a\xce\xdb\x0f\x1d\x51\x7c\x6a\x2b\xec\xa6\x16\xd4\xd5\x46\xee\x99\x8f\xdf\x57\xaf\xfe\xfb\xf0\xa4\x5b\xe6\xb8\x6f\x51\x83\xf5\x2d\x73\x3b\xb4\x57\xd5\xc3\xb2\xfc\xb0\x3c\xd1\x3c\x79\x48\x4a\x6a\xd1\xf7\x6d\xe7\xb5\x8c\x51\xf4\xa9\x90\xbd\x20\x53\x7f\x30\x36\x32\xbd\x8e\x96\xa3\xa8\xb7\x8d\xd2\x72\x46\x85\x0a\x4a\x50\x19\x0c\xed\xb2\x62\xfd\xfb\xe0\x46\x68\x67\xdb\x7a\x0f\xf6\x9c\xd3\x35\xbe\x42\xe9\xb2\x4a\x34\xa9\xb4\x32\xe7\xf1\xe1\x4e\x60\xde\xe1\xf1\x25\x9b\x71\xa5\xcb\x85\x6b\xe1\x36\x0d\x5e\xc2\x7a\x85\xfc\x25\x97\x6c\x41\xfe\xfe\xe3\xd1\x3f\xfe\xf9\xfa\xed\xc1\xfe\xeb\x7f\xbe\xd9\x3f\xf8\xfb\xf1\xc9\xd1\xfb\xf7\xe7\xff\x38\xbf\x38\x7a\xf3\xfe\xfd\x01\x22\x8c\xd8\x72\xdc\x73\xa6\xdf\xbf\xb7\x9c\xaa\xde\xbf\xbf\x48\x0a\x5e\xbc\x7f\x7f\xea\x7c\x20\xd8\x9c\xe1\xbf\x0f\x4f\x40\x7e\x62\x55\x98\x4f\x7b\x82\xbd\x15\x89\x0e\xef\x3d\xa7\xaa\x4e\xb2\x8c\xea\x6d\x5a\x00\x7a\xb6\xdd\xee\x56\xc2\x29\x75\x5a\xec\x66\xc0\xba\xab\x92\x73\xf1\x7a\x2f\x1d\x99\x30\x7d\xcd\x6c\x19\xe3\x4a\xbc\x2e\x1a\x14\x46\x07\x10\x5c\xab\x3a\xb7\xa0\x72\x26\xc9\x15\x67\xd7\x88\x39\x81\x4d\xf2\xea\xf6\x41\x50\xd6\x8c\xa5\xad\xcb\xa8\x60\xa0\x24\x15\x32\xf5\xad\x92\x1a\x7e\xe9\x25\x9f\x74\x54\x46\x83\xb8\x6f\x2c\x25\xa7\xc7\x87\xe4\xc5\x18\x95\x9c\xe3\x43\x84\xa1\x5c\x89\x52\xe5\x2c\x55\xb3\xa1\xe2\xee\xbb\xa2\xea\xa0\x66\x80\x36\xc2\xa8\x05\x07\x54\x93\x54\xe6\xf4\xbe\x4d\xd1\x3e\x51\xbf\x82\x2d\x2b\x7f\xab\x68\x86\x3a\xc0\xa9\x4c\x97\x25\xd3\xce\xb7\xee\xd4\xdf\xc6\xdf\xfa\xf7\xf8\xdb\xf8\x5b\x68\x86\xe9\xc8\xf6\xb7\xb1\xba\x4a\xc6\xdf\xda\x02\x69\x62\x2f\x5a\x99\x23\xbc\x54\xed\x64\xf5\x59\xbc\x07\x9e\x4d\x41\xdf\xfd\x2c\xe5\x2e\x3d\x76\x15\xed\xb9\x97\x28\x6a\x81\x50\x7b\x9d\x94\x8c\x62\xaa\x39\x49\x59\xc6\x6a\x1c\x98\x0d\x68\x66\x79\x73\x77\x4f\x17\x6b\x8b\x7a\x9f\x86\xbe\x29\xaf\x2f\xfd\xee\x5b\xa4\x86\x06\xc3\xd7\x75\xc7\xf9\x16\x0b\xa0\x23\x52\xc3\xbd\xc2\x46\x5a\x66\x0c\xe7\xa7\xcb\x4a\x59\x59\x57\xb7\xab\xc2\xd1\xdb\x10\x62\x1d\xd5\xe8\x17\x0e\xc8\xd4\x70\xc4\x85\x7f\x7f\xb0\x34\xb0\xf5\x1f\x06\x57\xf1\x17\xa8\x76\x5b\x10\xb3\x6b\x69\xf4\x64\x84\x15\xa2\xba\x84\x26\x85\xdf\x5e\xb2\xc5\x10\x01\x3d\x50\x09\xf9\x5b\x80\xc8\xec\x4b\xa2\x11\x78\x4d\x96\xe4\x5b\xf7\xaf\xbf\xdd\xd7\x5a\xeb\xe0\x47\xed\xe2\x45\xc5\x8f\xea\x1c\xf9\x3a\xc2\x2a\x98\x18\xe1\x03\x29\x6b\x0b\x64\xb4\x44\x72\x8d\xc9\x11\xd4\xbd\xa2\x46\x6a\x51\x69\xb3\x2c\xba\x58\xb9\x0e\x93\x11\x3a\x04\xf8\x5f\x82\xea\x98\x13\x79\x6e\x2b\x33\x01\x66\x67\xca\xca\xfa\x0c\x08\x98\x13\x79\xf4\x81\x25\x95\xfe\x9c\xd5\xea\x78\x5c\xb2\xee\x3d\xbf\x7e\x64\x1e\x82\x08\x69\x63\xb4\x70\x5f\x99\x50\xaf\xce\x20\x39\xed\x76\xda\x5e\xb2\x85\xf2\x20\x6b\x97\x38\xba\xad\x6a\xf6\xfc\xeb\x36\xb2\xa3\x0f\x5c\x69\xf5\xbf\x5c\xc3\xb1\x7c\x52\xb7\x7a\xa3\x98\x25\x56\x8f\x1e\x00\xec\x99\x3f\xe1\x31\x9f\x9b\xe0\xee\x03\x3a\x53\xfd\xad\xa3\x44\x00\xa1\x47\xcd\x37\xed\x2a\x9b\x9e\x24\x05\x14\xaa\x85\x58\x6c\x75\x62\x0d\xde\x8c\xfc\x89\x34\x04\xba\x1c\x19\x25\x2f\xde\x66\xec\x29\x7b\x11\x07\x54\x11\x7e\x45\x33\x26\x2c\x8a\x6d\x96\x26\xb4\xc4\x10\xbd\x05\x14\x52\x16\x08\xdb\x22\x69\x98\x3d\xce\x4a\xb2\x7a\x96\x95\x0d\xe5\xd1\x52\xf3\xa4\xca\x68\x49\xcc\x7a\x9c\xc9\xf2\x9e\xb8\x43\x78\x74\x6b\x7c\xe7\x59\xb4\x43\x3f\xe8\x58\xbe\x37\x47\x6c\x02\x1d\x5a\xed\xc5\x98\x4c\x50\x5f\x13\x2f\x94\xbd\x18\x48\x5b\x4e\x9d\x6c\xf2\x82\x22\x84\xca\xd3\x91\x73\x9c\xcf\xc0\xff\x3d\x08\x36\x0f\xbf\x32\xc7\xe4\x7b\x5f\x2d\x3e\x24\xb5\xcf\x18\x6a\x52\xed\x33\xed\xb2\xb1\xd3\x55\x2f\xea\xa9\x2c\xa1\x8b\xe1\x5e\x2a\xe1\x1e\x76\xc5\x13\x3d\x18\x93\xff\xd7\x68\x8a\xe0\x44\x76\xea\xa4\x5d\x66\xbe\x0e\xb7\x06\xec\x7b\x4e\xf6\xe0\xb6\x50\x95\x1c\xb8\x40\x91\x45\x02\x7d\x64\xd9\x30\x1d\x22\xdc\x2b\xa2\xdb\x91\x18\x45\x4d\xb1\xc1\x1a\x7e\xe7\x97\x5e\x42\x7a\x99\xc8\x95\x5d\xa5\x91\xe7\xd6\xc7\x59\x9c\x08\xf5\x8c\xf3\x6f\xf0\xd1\x93\x92\xcd\x60\xfd\xe1\xea\xf9\x8c\xab\x4f\xcb\x42\x66\x72\xb6\x38\x2f\x4a\x46\xd3\x03\x29\x94\x2e\x41\x34\x74\xc1\x77\xbb\x69\xcc\xa0\x71\xd6\x5c\x5e\x13\x6a\xcb\xd9\xe5\x14\x11\xf2\x64\x35\x9b\x63\xab\x00\xb8\xd1\x35\x99\x75\xaf\x68\x8d\x4e\x35\x26\xe7\xbe\x15\x00\x30\xb8\xef\x2c\x00\xa3\x80\xc3\xe3\x9a\x2e\xec\x62\xa2\x13\x9e\x32\x15\xe4\x28\xbb\x97\xc1\xd0\xcf\x8d\xdf\x0f\x52\x79\xff\xe4\xf0\xbe\xfd\x17\xd6\xa8\xd0\xde\xf0\x29\x5e\x33\x42\xaa\xd7\xf4\xf5\x1a\x29\xd0\x8d\xe6\xd2\x6a\xaa\x88\xe5\xea\x28\xf3\x19\x75\xd3\x2e\xe0\x4b\x39\xfd\x70\x7e\xc9\xae\x5b\xdc\xe9\x3e\xf4\x47\x76\xff\x54\xb0\x11\xd8\xa3\xef\x84\xa2\x9a\xab\x29\x34\x6a\xf9\x8c\xfa\x38\x14\x1d\xb4\xeb\x27\x81\x47\x5c\xbb\x13\x8e\xe6\x8a\xc2\x3d\xde\x62\xc4\x2c\x36\xff\xaf\xb6\x83\x70\x03\xc4\x22\x08\xdf\x8a\xc2\xac\xa0\xc4\xb6\x67\xd2\xb2\x8e\x43\x63\xa4\xa2\xca\x27\xac\xf4\x6b\x1f\x9d\x01\xbc\x6c\x40\xd3\x36\xd6\x7e\x7b\xc1\xd8\x3a\x13\xae\x6b\x5a\x19\x90\xe7\xe8\x83\xd1\x3c\x54\xbb\x44\x25\x3c\xe2\xee\x6a\x8d\x41\x31\x3c\xe6\x12\x38\x1b\xd3\x10\x75\x39\x01\xb3\x37\x3c\xd3\x56\xce\xd5\x47\xb7\xfe\x8c\xa4\x5b\x8f\x46\xb2\x22\x51\xfa\xc6\xcf\x6f\xb4\x4a\x09\x0b\xfe\xac\x53\x48\x0d\x51\x81\x47\x07\x36\x15\xf5\xc6\x6e\xdb\xe6\x67\x5e\x9b\x33\x46\x91\xb9\x08\xef\xeb\xda\x08\xa9\x43\x8f\x47\xd2\x43\x9f\x47\x02\xb2\xec\xb2\x85\x04\x0c\xef\x77\xc4\x6a\x3d\x48\xf7\x8e\x8f\xa4\xbd\x41\x5d\x1f\x11\x43\x5d\xd6\xa6\x35\x72\x56\x64\x5a\xd7\xc2\xae\x36\xac\x3b\x3d\xbb\x87\x36\x68\xa4\xa3\x8d\x5b\x1f\x11\x21\xe4\x3d\xac\x5d\x0a\x01\x26\x39\x75\xab\x63\xa5\xcd\x7b\x2c\x86\xe4\x44\x6a\xf3\x9f\xc0\xfc\x3d\x94\x4c\x9d\x48\x0d\x67\x36\x82\x94\xf8\x09\x3d\x12\xd2\xb5\x11\x00\xbc\x37\x90\x9b\x36\x44\x6b\x76\x3c\x47\xb0\x15\x86\xc5\xb1\x20\xb2\x74\x14\xf3\xd6\x85\xb2\x43\x84\x61\x05\x8b\xb1\x75\xa3\x71\x62\xc6\x09\xe9\x7c\xcb\x70\x76\x28\xc8\xfe\xc2\x5f\x00\x3c\xb5\xc8\xa0\x40\x20\xad\x4a\xc4\xb0\x35\xba\xa6\x66\x33\x9e\x90\x9c\x95\x33\x68\x1b\x9d\xcc\xfb\x98\xbe\x2e\xfb\x0a\x1e\x1d\x77\x97\xf0\x65\x3a\xf0\x12\x6c\xd9\xa0\x62\xf5\xa8\x02\xe0\x78\xb8\xad\xe5\x14\x2c\xa9\xff\xe3\x7d\xd0\xff\x97\x14\x94\x97\x80\x79\x6b\x63\xc7\xe1\x6f\x36\xfa\x12\x0e\x63\x46\x58\xf2\x2d\x51\x41\x18\x56\x32\x99\xd1\x9b\x8a\xc7\x90\x5c\xcf\xa5\xc2\xcd\xd0\xbb\x3f\x76\x2e\xd9\x62\x67\xb8\xc4\x7a\x3b\xc7\x62\xa7\x0e\x0c\x47\xcc\xe6\x37\x61\xc8\x20\xdc\x81\xdf\x76\x1e\x4e\x57\xe9\xb4\xd9\xf6\xd1\x31\xa0\xf9\x42\x2d\xf9\xca\xda\x3c\x9d\x35\xff\xdd\x37\x38\x50\x60\x9f\x63\x4c\x70\x56\x32\x2c\xc6\x04\x53\x1a\x14\x75\xdb\xdd\xa5\x12\xec\x8a\x99\xc9\x4a\xb9\xb2\x78\x80\x2e\xc5\xe0\x5f\x4b\x26\xd1\xff\xff\x50\x9e\x48\xed\xac\xf6\x7f\x39\xb7\x17\xf2\xdf\x07\x9e\x57\x39\xe2\x66\x69\x63\x29\xa4\x7c\xea\x80\x80\x5d\x66\x43\x6c\x2f\xc4\x66\xab\xe5\x63\x4d\xcb\x19\x64\x38\x5a\x7b\xc1\xb1\xd9\x2c\x93\x13\x9a\x91\x9c\x0b\xf3\x18\x1b\xbc\x8c\xce\xf9\x37\xb1\x7f\xde\xf2\x20\x58\x0b\x7c\xc6\x27\x19\xb3\x06\x49\x03\x63\x3b\xb8\xb9\x71\x21\x2c\xd2\x8c\x29\x85\xf1\xc6\x37\x5c\x1c\x3a\x6f\xc6\x2b\x59\x12\xf6\x81\xe6\x45\xc6\xb0\x44\x8f\x7c\x3d\xfa\x8f\x14\x8c\xd8\x00\xfd\x90\xb8\xe9\xa9\xfb\x96\xbd\xc0\x85\x54\x37\x16\xf0\xd9\x17\x91\x4d\xe8\x3d\x29\x8a\x7c\xf5\xec\xab\x67\x2f\x5e\x9a\x3d\x04\xdd\xf4\x54\x59\x08\xa2\x65\x6a\xbc\x18\x93\x8f\xc4\xbc\xc1\x0b\xfb\xdf\xaf\xec\x7f\xbf\x26\x1f\xc9\x47\x42\x4e\xc9\x29\x09\xff\x6b\xfe\x43\x3e\x92\x91\x21\x42\xf0\xaa\x2f\xcc\xd7\x24\x32\xb7\x14\x04\x1f\xb4\x2f\xb8\xf5\x7d\x03\xb5\xb4\x43\x43\xb5\x53\x22\x73\x06\xaf\xfa\xd5\xff\x72\xd7\x40\xa8\x58\x63\x6b\x47\x78\xa9\x3d\x78\xa5\x01\xb9\x06\xa7\x5a\x4e\x2f\xd1\xa0\xdc\x4f\x74\x45\x33\xf3\xf0\xbd\xaf\x47\x2f\x06\x44\x8a\xf8\xf2\x2b\x2e\x8d\xf2\xee\xde\x70\xef\xc5\x60\xbc\xf4\xca\x5f\xad\x78\xe5\x46\x97\x43\x5b\xee\x68\x06\xbd\x99\xdf\x1d\xab\xef\x8b\xc5\x35\x5d\x78\x86\x77\x06\xf5\x8c\x5f\x79\xb4\xff\x00\x84\x04\xa2\x8d\xc0\xbf\xdc\xe1\x4a\xe1\xa0\x0b\xc2\xf5\x98\x1c\xeb\xdd\x5d\xd7\x53\xd3\xe8\xfa\xae\x2d\xc1\x61\x88\x97\x09\x84\x07\xde\x78\xde\xc8\x46\x6e\x81\xce\xd6\xab\x5b\xf7\x5e\x7d\x05\xf0\xc8\xfd\x2a\xe9\x2c\xe2\x76\xea\x15\x17\x55\xb3\x2f\xaf\xfa\xe6\xc2\xf5\x89\x53\xb7\xae\xee\x06\xea\xb5\x13\x43\x97\x6c\xd1\x58\xf9\xf5\x37\x0d\x21\x87\xc7\x79\xed\x08\xba\xed\xd0\x55\xaf\xc8\xfb\x9d\x78\x5d\xbe\xdf\x01\xe7\xbd\xdf\x3f\x6d\x1f\x1f\x9a\x25\x95\x6d\x00\x27\xa7\xc4\xb1\x71\x80\xd0\xb5\x2f\xd2\x3a\x65\xa2\xe5\xfb\x03\x84\x3d\xe8\x8c\x33\x88\x23\x94\xcb\x5f\x12\xa4\x55\x44\x59\x78\x66\x15\xd6\xeb\x78\x4c\xf6\x91\x81\x15\x04\x3f\xee\xf2\x5e\x37\xd2\xae\x6e\x07\x7b\x2d\xc5\x6e\x0d\xbc\x4b\x72\x89\x10\x69\xc2\x6d\x8f\xd6\x57\x25\x89\x06\x55\xc5\x4f\xeb\xf1\x74\x45\x1e\x4c\xed\x20\x46\xf0\x49\xc3\x24\x50\x37\x11\xf2\x4f\x80\xea\xff\x62\x05\x12\xa3\x5d\x2e\x2a\x26\xd7\x73\xcb\x48\xf5\x33\xa5\xc6\xe7\xfe\xdc\x94\x1f\x5e\xf9\x8e\xf6\x4d\x68\x99\xd9\x66\xb3\xf8\x6a\xd8\x78\x7b\x7b\xfe\xcf\x6d\xf6\x90\xaf\x5e\xde\x6f\x73\xb0\xff\xbd\x88\xa6\x79\xe5\xec\xfe\x79\xaf\x7e\xcb\x01\x04\x30\x57\x2c\x02\x28\x76\xa8\x83\x59\x63\xbf\xa1\x29\xae\x2b\x8a\xf5\x11\x82\x5d\xdb\xa4\xb5\x9b\x3f\x2a\xa8\x71\x73\xc2\x7d\x68\xf6\x1f\x5a\x29\x06\x45\x2b\x15\xd4\x33\x1b\x42\xba\x20\xda\xd7\x7b\x5f\x93\x11\x79\x3e\x30\xdc\x20\x90\xad\x80\x98\xe1\x56\x66\xb6\x06\x9b\x83\xa9\xe7\x46\x79\x32\x94\x51\x43\xdf\x4a\xab\xb1\x09\xc1\x94\xfa\x5e\x89\x02\xab\x6a\x56\x75\x4b\x84\xb2\x19\xb3\x32\x6b\x12\x1d\x8b\x53\x99\xc6\x3e\x7f\x5f\x08\x33\xa3\x9a\xb5\x02\x3d\x58\xaf\xbc\x0f\x3c\xf1\x3d\x84\x7f\xfd\x58\x4e\xc3\x33\x46\x8a\x9c\x22\x24\x05\x76\x34\x1e\x43\xbb\x6a\xbb\xd7\xda\xd4\x46\x74\xf2\x58\xde\xe1\xca\xfb\xf9\x38\x54\x8a\x25\x41\x93\xc0\x12\xc5\x05\x4f\x59\xc9\x5c\x43\xe4\x30\x11\xd6\x47\x50\xc8\xcf\xf5\x95\x98\x00\x0b\x99\x42\x38\xd0\xdf\xb0\xf0\x6a\x67\x52\x25\x97\x4c\x3b\x0b\xa9\x84\xdc\xbd\xa2\xd2\x64\x42\x33\x2a\x8c\xad\xbd\xe4\x31\xd7\x12\x07\xc3\x3b\xe1\x29\x58\x4d\xee\x13\x34\x71\xe8\x20\xbe\xcf\x85\xd2\x66\x34\x0c\xfc\xd7\x2f\xb8\x9f\x29\x39\x24\xd7\xf5\x00\xcb\x9a\x2e\x0c\x65\xff\x8d\x46\x9f\x00\xda\x39\xff\xbf\xc3\xfa\xb0\x2b\x6c\x4c\xd8\x78\x06\x42\xb6\x31\x13\x3b\x71\x75\x81\x4b\x58\xdd\x19\xe2\xc7\x98\x09\xb1\xd5\x1e\x56\xc3\xb6\x38\xd4\xc1\xcb\x8a\x14\x8a\xa0\x9a\x03\xfb\x2b\xe2\x27\x98\x25\xe8\x46\x07\x51\x79\xfb\xe8\xc7\x7a\x95\x96\xf5\xb9\xf3\x21\x96\x74\xca\xee\x46\xde\xf2\x36\x53\x2b\x42\x36\x30\x98\x32\x9a\xb9\xd4\x49\xe8\x93\xe3\x41\x42\xc5\xee\x6e\xad\x8d\x02\x87\xa3\xc4\xa9\xf7\x4b\xa3\x4d\x47\xfb\x15\xd9\x73\xb5\x0e\x44\xb3\x2c\xc3\x35\x58\x6f\xdb\x46\xfc\x86\x6d\xe1\x39\x8c\x10\x6b\xce\x2b\x6f\x8c\x7b\xc9\x63\x12\x1f\x18\x67\x0b\x0f\xef\x33\x24\x93\x4a\x1b\x35\xdb\x88\xcc\x3b\x29\xda\x68\x4c\xcc\x59\x56\x90\x92\xa5\x55\x62\x8b\xfe\x40\x46\xef\x87\x5a\x01\xb6\x65\x74\x8b\x7e\x27\x22\xe8\x0e\xf6\x09\x11\xb1\x11\xc1\xa7\xb0\xa4\xc1\xf4\xe1\x53\xc2\xae\x58\xb9\x20\x85\x54\x0a\x56\x17\x2c\x1a\xcc\x7c\x07\x27\x8b\x47\x22\x84\x1d\x0c\xde\xca\x6d\x1a\x3b\x76\xd7\xd8\x01\xad\x4a\x46\x12\xe6\xf3\x18\x91\x5f\x3f\x7b\x61\x8c\xc8\xdb\x14\x80\x53\xf8\x5f\x6d\x15\xba\xff\x1e\x4f\x57\xe8\x39\xf5\xbb\x44\x9c\x73\x1f\xc3\xf1\x2b\xb0\xef\xbe\x1e\x04\xf6\xe3\xd7\xc6\xd4\xdd\x33\xef\xfa\xd5\xc0\xbc\x75\x60\x19\x7e\x15\x58\x86\xfe\x4e\xfb\x46\x4c\x45\xb6\xe1\xb1\xb0\x65\x0e\xd0\x23\xcc\x6a\x87\x36\x65\xde\xbc\x91\xd2\x56\x2f\xe0\xb9\x13\xd1\xc8\x76\xb1\x66\xba\xab\xd1\x44\xe5\x9a\x7c\x61\x54\xd3\x2f\x82\xeb\x6f\xb4\xe9\xda\x9b\x6a\x5d\x5b\xcf\x67\x5c\x69\xe8\x3f\x6f\x34\xff\xfb\xf7\x46\x6e\x1f\x4b\xef\x1a\x49\x5f\xfe\x0a\x24\x48\x4e\x8b\x7b\x8c\x83\x60\xec\x9d\x1a\x95\xbd\xb6\x51\x58\x3b\x94\x8d\x32\xa2\x23\x21\xb7\xd1\xf0\xc9\x22\x2c\x9e\x99\xb0\x4c\x22\xb4\xbd\xcd\x13\xbc\x47\x5d\x9e\xef\x0d\xa4\xb4\x2c\xe9\x8c\x3d\xb3\x8f\x7d\x2c\x3d\xc1\x7e\x42\xf4\xfb\x28\xa4\x84\xd8\x05\x16\x17\xdf\xd5\x2f\xb9\x64\x03\x90\x02\x34\x81\xd4\x7f\x20\x64\x04\x3e\x15\x14\x15\x3c\x92\xbc\x95\x16\x48\x39\x5d\xa2\xa4\xf4\x5a\x1d\x65\x54\x69\x9e\x7c\x9f\xc9\xe4\xf2\x5c\xcb\xb2\x07\xd5\x62\xd5\xa8\xd1\x9c\x0a\xb2\xff\xf3\x39\x39\xe4\xea\xb2\x6e\xb1\x84\x30\xe6\x71\xb6\x3d\xf5\x30\x7e\xb6\xf0\x92\xe4\x34\x99\xa3\x46\x6a\xfd\x1e\xae\x95\x43\x7f\x6b\xe5\x0f\xf4\x5a\x31\x7c\xfd\x89\x79\x7d\xf3\x33\x6b\x2f\x82\xd7\x06\xba\x84\x9f\x73\x7c\xb8\x86\x2c\x97\xa9\x6a\xdb\x7b\x8e\xac\x68\x08\xe2\x90\x65\xb1\x80\x30\x63\xb6\x29\x2c\xc0\x19\xc6\x4d\x3e\x80\x87\x16\xb2\x22\xd7\x14\xc3\x55\x20\x61\xc7\xe4\x82\x17\x2f\xc9\x51\x00\x97\xbf\x6a\x28\xa3\x7d\x78\xe8\x32\x9b\x20\x08\x3c\xb7\xdc\x1a\xff\x08\x55\x2b\xf5\x92\xec\xb0\x0f\xfa\x4f\x3b\x43\xb2\xf3\x61\xaa\xcc\x7f\x84\x9e\x42\x7b\x0d\xdb\xb6\xcb\xe8\x78\x62\xca\xca\xda\x22\xc4\x1b\x96\x51\x03\xfa\x67\x59\x72\xf1\xf6\xf0\xed\x4b\xd0\xe5\x53\x69\x8c\x39\xdb\xd8\xd6\x61\x60\x58\xd9\x18\x90\x01\x8a\x39\x13\x99\x17\xa5\xcc\x79\x50\xa9\x02\x4b\xae\xcd\x0a\x20\x7d\x84\x4a\xc1\x5e\x05\x66\xe8\x85\x9f\xfc\x70\x8e\xa5\x82\x13\xe2\x2e\xcc\x74\x3c\x25\x12\x83\x53\x71\xad\x1c\x57\xfe\x22\xc3\x3e\x76\x14\x6c\xd7\x5a\x33\x8c\xd1\xcc\xed\x4f\xcf\x52\x76\xf5\x4c\xa5\xf4\xc5\x10\x1e\x83\xdc\xb0\x68\xbc\x13\x55\x64\xe7\xc5\xce\x98\x9c\xf3\x9c\x67\xb4\xcc\x6c\x1f\x39\x3b\x44\x7d\x9d\x31\x14\xdc\x80\x60\xfe\x3e\xdf\x21\x7b\x58\xac\x06\xea\x46\xc6\x1c\x74\x89\x87\xea\x82\x58\xfe\xa0\x95\x76\x49\x7a\x70\x0e\x91\xce\x0e\x22\x62\x5b\xca\xbe\x15\x59\xeb\x14\x9f\x98\x39\xdc\x68\x2e\xd3\xbb\xac\x6c\x35\xed\x54\x96\xd6\x08\xf4\x97\xb8\x8a\x78\x2e\xac\xda\xf2\xc6\x4c\xfd\xfd\xdb\x38\x3e\xd4\xf6\x43\x7a\x40\x69\x21\x7e\x17\xe9\x87\xbe\x6e\x34\x08\x7f\x09\xfe\x5b\xc5\xc8\xf1\xa1\xef\xd7\xcd\x4a\xc5\x95\x36\x22\x2a\x8d\x54\x03\x8e\xfa\xc2\xde\x7e\x4e\xff\x23\x05\x39\xfa\xfe\xdc\xbe\xd6\x60\x03\x89\xdd\x52\xd2\xd1\xff\x54\x25\x33\x1a\x51\x67\xf5\xcb\x8f\xd4\x54\xb9\xcc\x79\x72\x48\x35\x45\xcd\x0b\x25\x95\xac\x51\x24\x40\xa9\x9a\x40\x76\xaf\x83\x08\x69\xa9\x3c\x93\xf5\x6b\x3f\x86\x83\x4e\xda\xc3\x4e\x9a\xdb\xdf\x9d\x1d\xaf\x41\x77\x4a\x60\xbb\x9d\xbd\x91\x69\x4f\x0a\x54\x30\xa0\xdb\xf2\x00\xd5\xeb\x00\xcf\x93\xdc\x3c\x89\x9c\x48\xc1\x86\xe4\x8c\xd1\x94\x18\xe9\x66\xff\xf9\x73\xc9\xf5\x7d\x81\x12\xea\xa3\xf3\xd6\xef\x26\xb1\x17\x42\xb8\xc1\x1c\x11\x4e\x02\x70\x1c\x40\x72\x02\xa1\x63\x75\x80\x49\x26\x27\xc4\x0a\x8b\x75\x7e\xfd\xbb\xb3\xe3\xde\x3e\xfe\xdd\xd9\xb1\xfb\x76\xf3\x4f\x39\xdd\xcc\xcf\xee\xd1\x78\xa8\x6d\x87\x57\x0d\x65\xbf\x56\xe7\x6a\x4c\xf9\xa6\x41\x70\x77\x6b\x60\xdc\x97\x1d\xb0\x2e\x9a\x5f\x72\xd1\x3a\x59\x3c\x96\x36\x80\x27\xef\xb1\x13\x82\xd8\x18\x40\xb6\xa4\x2f\x49\x5e\x65\x1a\xca\xe3\x81\xd7\x0c\xf3\x41\x86\x82\xe3\x3a\x62\xa1\xa2\x08\x39\x64\x18\x8e\x48\x5f\xba\x84\x45\x7f\xc7\xea\x1b\xde\x50\x41\x67\xe6\x72\xd8\x01\x49\x8e\x7f\x06\x4c\xbe\x87\x4e\x77\xe1\x7f\xa2\x57\x94\x67\x74\xc2\x33\xae\x41\x9f\x1b\x8c\x9d\x36\xaf\x10\x2b\xc3\xbc\xf2\xda\xa4\x5f\xaf\xaa\xad\x57\x5b\xc3\x42\x62\xc0\xc1\x21\x7b\xe6\xb7\x67\xd7\x46\xd4\x0f\xc6\x20\xf7\xe1\x42\x80\x2d\x6d\x28\xbf\x67\x9f\x52\x7e\xd7\xa2\xa7\xc2\x7c\xbf\x6a\xd9\xec\x62\x59\x77\x32\x23\xad\xd4\x9d\xe0\x07\x8b\x4e\xf5\xc4\xd5\x27\x6c\x38\xda\x41\x81\x82\xb5\xd3\xf2\xfe\xae\x2a\xd4\xc3\x2c\x9c\xf4\xe9\x2d\x1c\x82\x6d\x81\xec\x4c\xf7\x42\xae\x7a\x38\xa7\x6b\x78\x14\x42\xfc\xa9\x51\x67\x85\x2b\xeb\xdc\xca\x72\x87\x4e\x08\xf7\x9b\xf5\xd4\xa6\x0a\x13\x8f\xce\xe2\xd7\x73\x70\x3f\x74\x71\xa3\x39\xb2\xe0\x26\x05\xa7\x49\xeb\x75\xd6\xf1\x33\x13\x56\xcc\xa7\xdd\xb3\x29\xcd\x30\xaf\xce\xe3\xa8\xcd\x01\x2b\xe6\xe4\xd5\xf9\x0a\x31\x89\x99\xac\xe6\xbb\x15\xc6\x72\x76\x15\xc9\xf8\x94\x69\xde\x8a\x08\x6b\x16\x94\xb9\x14\x5c\xcb\x52\xad\xa3\x96\xd4\x3e\xba\x1f\xc5\xcd\x8d\x66\xf8\xf3\xcc\x11\x85\xbc\x09\xce\x52\x92\xc8\x2c\x63\x89\xcb\x2f\x85\x29\xf6\xb7\xad\x70\xc4\xd8\x0c\x04\x35\xbe\xfc\x06\x5c\x31\xd6\xe9\xf2\x0c\xd9\xee\xd9\xd9\xd1\xfe\xe1\x9b\xa3\x71\x9e\xfe\x61\x2e\xaf\x47\x5a\x8e\x2a\xc5\x46\x5c\x77\xd3\xb7\xd6\x58\x78\xda\x83\xa7\x5b\xcf\xfb\x72\x72\xeb\xb9\x99\xb2\x1a\xfd\xf0\x9d\xaa\xf1\x49\x5d\xdc\xb9\x94\x52\x2f\x23\x94\x4e\xab\x2c\xc3\xb9\xd5\x25\x63\xc3\xd0\xbf\x7d\x4f\xfc\xd6\xfa\xd8\x2c\x5d\xb8\x76\xf3\x46\x24\x7a\x58\xcd\x78\x53\x16\x48\x77\x5d\xa1\xad\xa6\x4d\x96\xe6\xa1\x1e\x2f\x9e\x89\xf3\xe8\x3c\x06\x44\xf4\xdc\xcc\xcb\x25\x5b\x10\xa8\x31\x9c\xca\x12\xf0\xbe\x63\xfe\x64\x3a\x01\xe2\x3d\x83\xe6\xda\x56\xe1\xd8\x10\xc2\x77\x51\x45\xe0\x43\xce\xd8\xb4\x4f\xb2\x9f\xb1\xe9\x2a\xaa\xdb\xd3\x00\x8a\xe6\xd3\xe3\x8c\xbe\x52\xe9\x39\xa6\xbc\x22\x18\x23\xd2\x76\xe5\x34\xd8\x22\xd1\x0d\xa1\x7b\xa7\xf2\xbe\x3e\x4a\xd0\xbb\xb4\x12\x22\x4b\x93\x17\xba\x2d\xed\x24\xe9\x7b\x87\x41\xe4\x95\xb1\x62\xd9\xf5\xb3\x6b\x59\x5e\x72\x31\x1b\x5d\x73\x3d\x1f\x21\xa5\xd4\x33\x80\x86\x7d\xf6\x07\xf8\x8f\x8d\x22\xef\xa7\xa9\xcd\x7f\xab\x14\x9b\x56\x19\x66\xa6\xa9\x31\xa1\x05\xff\x89\x95\x0a\xb2\x2c\x2f\xb9\x48\x87\xa4\xe2\xe9\x77\x6d\x67\x8c\xf4\xb1\x5a\xda\xb7\x76\x6d\xd2\xba\xb2\xdd\x5d\x65\xb8\x8d\x96\x4e\x26\x95\x34\x95\x0a\x1b\x04\x18\x52\x45\x4b\x80\xa6\x39\x17\x9b\xb2\x02\xda\x5a\x07\x5c\xa4\xed\x28\xd9\x08\x40\xc0\x38\xb1\x79\x60\xcf\xd9\x30\xb6\xcf\xf9\xa1\xce\x7b\x82\x1d\x40\x6d\xf6\x4f\x9c\xfb\x73\x27\xc1\x92\x2f\xd4\x6f\xd9\x08\x9f\x32\x2a\xd2\x9a\xae\xdb\x44\x9e\xfb\x1c\x9f\x2f\x91\xa7\x5f\x87\xfc\x67\x48\xcf\x79\x50\x8e\x23\x1b\xac\x33\x3f\xac\x1f\x6c\x8d\xa4\xee\xae\x19\x3f\x8c\x86\x56\xef\x3e\xd0\xbc\x46\x39\x44\x15\x50\xc0\x50\x2a\x39\x7f\x1a\xf6\x43\xf6\xdd\x12\x5c\x85\x71\x22\x85\xb0\x40\xba\x6f\x0b\x26\xce\x35\x4d\x2e\x3b\x46\x75\xb7\x5a\xd5\xef\x4c\xab\x7a\xa0\x44\x20\xc7\xa2\x58\x4f\x67\xd3\xdf\xea\x64\x6f\x5c\xe4\x8f\x50\x00\x63\x57\x98\x37\xb4\xe8\xee\x5d\x75\x23\x35\x34\x28\x7f\xda\x3a\x54\xa1\x38\xa8\x90\x45\x95\x21\x4c\x2c\x57\x96\x8e\x9f\x5f\xe3\xe9\xba\xbe\xed\x16\xd3\x5f\x0e\x4c\x30\x60\x2c\x51\x73\x73\x66\xc2\x75\x2d\x2b\x15\xd3\x08\x3f\x62\xb1\xf4\xa4\x20\x89\x2d\x31\x06\x7d\xc4\xe8\x1e\x76\xb8\x40\x57\x11\x44\x26\xda\x15\x83\x7a\xa4\x92\xe7\xcf\x9f\x3f\x47\xf4\x85\xff\xfa\xaf\xff\x22\xb2\x84\xa6\x55\x09\xcf\x97\x2f\x84\xab\xfe\xfc\xe2\xc5\x98\xfc\x63\xff\xcd\x6b\xa8\x68\x28\xb4\xc2\x56\x26\x38\xb2\xb9\x20\xba\x59\x0d\xc9\xff\x3e\x7f\x7b\x52\x57\x05\xc7\xbf\x82\x69\xee\x3f\x2f\x06\x90\x7e\xfe\x97\x3f\xfd\x69\x4c\x0e\x79\x09\x15\x5d\x9c\xf9\xe6\xa4\xde\xd5\x42\x4b\x86\x68\x11\x50\xb7\xef\x34\x2e\xee\xfb\x00\x59\x08\x28\x6c\xdf\x8c\x85\xae\x86\x21\x33\x9e\x68\x2c\x1e\x43\xb1\xe6\x7a\x9f\x22\xf6\xb4\x45\x73\xb7\xda\x1f\xbc\xdc\x90\x64\xfc\x92\x91\xa9\x82\xb6\xe8\x35\x1e\x90\xed\xd8\x67\x0b\x65\x70\xb0\x7a\xae\x14\xd3\x8f\x3c\x6d\xb5\x93\xab\x39\xe2\x6d\x18\xa9\xa1\xb0\xda\xf2\xd6\x4b\xb6\x18\x21\x9f\x15\x94\xfb\x62\x18\xc8\x00\x8c\x9a\x45\x79\x5f\x4f\x4a\x0e\xbc\x54\x71\x75\xee\x45\x29\xff\x8d\x2c\x00\x25\xc6\x81\x78\x86\x12\x60\x98\x49\x5b\x00\x1c\x44\xb7\x5c\x99\xb4\xed\x4e\xea\x4e\x5b\xc8\xf3\xe5\xbe\x11\x19\x57\xe6\x11\x00\x30\x71\xcb\x93\xeb\xa6\x77\x86\x4b\x15\xf2\x4b\x25\x96\xee\xb6\xc5\xfc\x56\x5c\xda\x6e\x51\x16\xba\xaf\x1e\x03\x71\x8c\x2c\xf6\x82\xbd\xd6\x51\xc9\x13\x22\xca\xb7\x56\x4c\x57\x96\x34\x90\x45\x6f\x9e\x0d\x9d\x8c\xe0\x0b\x73\x5a\x5e\x1a\xc3\xd5\x4a\x97\x31\x39\x35\x2f\xe9\xe1\x1b\x10\x15\xef\x0a\x03\x9b\x39\x5d\xc0\x63\xad\xe2\x06\x0f\xd9\x1d\x8f\x77\x71\xf9\xc9\x92\x28\x4d\x4b\xbb\x96\xcc\xf9\xa7\x01\xc7\xf9\x86\x16\x0a\xe1\xe1\x8c\xa6\x0a\xd0\x89\x12\x4a\xd2\xf5\xbc\xee\x8f\x8c\xb4\xde\x42\x68\x92\x11\x10\xa6\xf5\x00\x1b\x0e\x9f\x69\x67\xdf\xae\xf2\x8d\xc0\x76\xcc\x3b\x28\x1c\x78\x34\x63\xaa\x69\x23\xb2\x71\x27\x7d\xc3\xb6\x0f\xc8\xd8\xa3\x52\x30\x56\xb7\x0b\xb3\x82\x33\x54\xc0\xe2\x1e\xe7\x8f\x55\x8f\xc0\xa3\x0f\x6d\x02\x8f\xee\x3a\x05\x1e\x5d\x82\xc8\x78\x44\x3c\xec\x22\xc9\x48\x4c\xbb\x81\xe1\x1e\x35\xad\xa7\x00\x9a\xba\x14\xc1\xb2\xc6\x0e\x68\xae\x93\x9f\x20\x74\xa2\x64\x56\x69\xbc\xb5\xfe\x31\xdc\xfd\x60\x50\x07\x2e\x09\x5b\x9e\xbf\x2c\xd8\x0b\x41\x0b\xc0\xed\xa3\xcb\xb6\x88\x47\x67\xb1\xd1\xc5\x09\xf1\x3b\x72\x40\x74\xa6\xb3\x37\xd8\xfa\xa0\xb5\x1b\xcc\x57\xdc\x5d\xcf\x99\x4d\x81\x08\xf4\x3e\x23\x4d\x8d\x8c\x00\xa5\xd2\xa9\x70\x88\x87\x93\xae\xc5\xcd\x98\x28\xde\xdd\x97\xa0\x38\xd9\xf3\x7d\xd5\x7d\xda\xdd\xb1\xd0\xac\x9c\xd2\x84\x0d\x42\x1f\x03\x2b\xe6\x2c\x67\xa5\x21\x94\xbd\xce\xd5\x68\xcf\xa9\x48\x33\x0b\x5c\xc0\x4a\x58\xc1\xec\x83\x66\xa5\x21\xea\xc1\xf9\x31\x49\x4b\x7e\xc5\x4a\x45\xf6\xbe\x67\xc6\xd6\x40\x18\xaa\xc1\x23\x4c\x83\xc5\x0f\x59\x87\x07\x04\x1e\xdc\x4f\xe9\x07\x0c\xb5\xaa\x25\x74\x3d\x55\x0e\xf2\xca\x4c\xab\x0a\x7d\x47\x63\xb3\x20\x60\x0b\x05\xe9\x0b\xad\x0f\x31\xb6\xe9\x3a\xfd\x42\x87\x86\x44\xe3\xc0\x54\xd9\xce\xbf\x00\x87\x63\x05\xbb\x85\x49\x59\x5b\x71\x43\xff\x05\x25\x75\xb0\xea\xb6\xda\x8f\xa9\xb5\x2b\xe5\x15\x4f\x9d\x3a\x04\xa9\x11\x35\xe8\x5f\x41\x55\x00\x5e\x40\x95\x92\xb6\x9f\x79\x30\x35\x68\xa5\x82\xd2\x14\xf7\xcc\x70\xe1\xe6\x30\x4c\x26\x01\x79\xbe\x55\xc3\x2e\xd2\xcb\x86\x28\x53\x76\x5a\x4d\x32\xae\xe6\xe7\xbd\x86\x44\x56\x0d\x8c\x49\x89\x4b\x99\x2a\x37\x46\x46\x14\x13\x8a\xdb\xfe\xaa\xa8\x6e\x71\xa3\x6d\x4b\x98\x06\x77\x77\xb8\x28\x24\x54\xc3\x43\xd7\x56\xf7\xd3\x49\xfd\x1e\x16\xac\x04\xdb\x05\xa6\xec\x9d\x28\xa2\xf3\x09\xcd\x32\x65\xf5\x5b\x0f\x86\xed\xf6\x1e\xd4\x50\x1d\x80\x09\x72\x05\x37\x0c\xe3\xde\x1e\x52\x70\x50\x78\x79\xe4\xf6\x95\x1f\xa6\x02\x88\x4b\x29\xdc\x45\xd0\xf5\xd0\xdd\xe0\x29\x84\x95\x38\xc8\x74\x6b\xc4\xcc\xde\x86\x7f\x1e\x5f\xf8\xe7\x61\x6a\x2a\xea\x5e\x54\x14\x4e\x8e\xa0\x42\xcb\x75\xd4\xa7\x1e\xd9\xa0\xb6\x24\xc7\x9f\x4a\xd3\x5c\x5b\x08\x18\xdf\x6f\x5f\x5b\xfc\xf3\x7e\xbc\xbb\xcd\x41\x41\x15\x33\xa6\x38\x48\xa8\x91\xa5\x5f\x12\x2c\x29\x6b\x23\xfb\x75\xbe\x2c\xd7\xea\x3d\x1d\xb6\x73\x3c\xb9\xab\x48\x2a\x93\xca\x18\x5f\x35\xd9\xeb\x84\x8b\x6e\x6d\x6d\x9e\x16\xce\x7e\x2a\xaf\xc5\x35\x2d\xd3\xfd\xd3\x56\xb5\xb9\xb1\x72\x56\x8f\x15\xaa\xde\xee\x34\x31\xe7\xe9\x44\x56\xda\x63\x1b\x6e\xa3\x7d\x2b\x87\x08\xa5\xf9\x2a\x77\x9b\x96\x46\xc8\xde\x31\x9a\x77\x5f\x87\xdd\x36\x40\xb8\x0d\x10\x46\xc7\x26\x05\x08\x8f\x31\x40\x18\xb6\x84\x8b\xc4\x8b\xf5\xd0\x1a\x8a\x3f\x89\x18\xd3\x61\x2d\x52\x51\x13\x6f\xd6\xf3\x36\x94\x7f\x5c\xbc\x35\xd7\x05\x06\x83\x93\xb9\xa0\x97\x3d\x85\x78\xd4\x06\xc4\x93\x80\x96\x1d\xac\x42\x3c\x62\x81\x5f\xd7\xab\x21\x4a\x2d\x06\xa6\x83\x08\x77\x21\xd3\x97\x08\x1a\x0b\x40\xef\xd8\x9c\x6c\x68\x61\xbf\x87\xd6\x77\x21\x52\xf8\x87\x2a\x68\xc2\x40\xbe\x79\xf5\xa7\x97\x20\x41\x47\x06\x20\x3d\x31\x01\x01\x46\x00\xea\x9c\x76\xe1\x06\xd2\x1b\x47\x98\xa3\xb6\x78\xba\x8e\xd4\x44\x14\xc5\x51\x1d\x23\xa8\x64\xce\x72\x0a\xff\x7c\xe5\x48\x60\x64\xa3\x31\x1e\x34\x43\x08\x38\x56\xe6\x8a\xc8\xe9\x30\xca\x74\xdd\xb9\x7a\xb1\xd3\x2d\xd8\x40\xfa\x8b\x53\x12\xb7\x8e\x4e\x3b\x07\x7b\x48\x93\x60\xa7\x51\x6c\xc7\xac\x21\xd0\x79\xcc\xb2\xf2\x70\xf6\x3e\x83\x02\xf6\x0f\xa4\xf0\xc6\x10\xa7\xef\x20\x6e\xdb\xe0\xed\xd0\x47\x0d\x1e\x81\xf2\xb7\x0d\xde\x3e\xc5\xe0\x6d\xb0\x31\x3a\x41\xb7\x22\x90\x1b\x86\x04\x5c\x34\x77\xc2\x9c\x51\x63\x6d\x18\x17\xca\x75\x71\x5c\x59\xc6\xa9\x4b\xbb\xe3\xf1\xee\xae\x8b\xee\x5a\xbe\xaf\xf4\x74\xf4\x0d\x61\x22\x91\x29\x32\x8b\x19\xbf\x54\x1a\xd4\xbd\xda\xdd\x16\xbe\x4b\xee\x9e\x15\xa6\x3f\xc1\xd8\x7d\x4c\x75\x67\xd9\xe2\x20\x09\x5f\x3d\x80\x12\x53\xab\x2e\x1e\xf8\xd0\x92\xc8\xe3\x59\x5b\x1d\xc6\xfd\xae\x48\xc6\x73\x6e\x1b\xa5\x9a\x85\xce\x94\x56\x64\x0f\x4f\x8e\x93\xa2\x1a\xda\x0b\xc6\x39\xcb\x65\xb9\x18\xfa\x8b\xcc\x8f\xd1\x5d\xf6\x8a\x01\xb6\x31\xa9\xca\x92\x09\x9d\x2d\x9e\xb2\x06\xe4\x88\xb8\x21\x0a\x90\x9f\xe3\x2e\x88\x23\xf5\x11\xb3\x56\x1d\xf1\x05\xb7\x79\xd0\x5f\xc0\xa3\xd1\xaa\x61\x1d\x17\x37\x67\x99\xb8\x22\x57\xb4\xbc\x27\x72\xfc\xaa\xa3\x47\x9d\x27\xe5\x57\x5c\x75\xed\x62\x4c\x9a\xe4\x39\xf7\x4e\x68\xb3\xd8\x64\xa5\x8b\x4a\x5b\x89\xee\x56\xa0\x43\x19\xf7\x2b\xaf\xa1\x1c\xbe\x68\xd3\x5d\x29\x3e\x0a\xaa\x35\x2b\xc5\x4b\xf2\x3f\x7b\xef\xbf\xfc\x38\x1a\x7c\xb7\xb7\xf7\xcb\xf3\xd1\x5f\x7f\xfd\x72\xef\xfd\x18\xfe\xf1\xc5\xe0\xbb\xc1\x47\xf7\xc7\x97\x83\xc1\xde\xde\x2f\x3f\xbe\xf9\xe1\xe2\xf4\xe8\x57\x3e\xf8\xf8\x8b\xa8\xf2\x4b\xfc\xeb\xe3\xde\x2f\xec\xe8\xd7\x3b\x0e\x32\x18\x7c\xf7\xc7\xce\xaf\x4e\xc5\xe2\x6d\x47\x51\x88\xc7\xa8\xc7\x2d\x39\x1e\xb1\x17\xf6\x6b\xb4\x95\xe0\x42\x8f\x64\x39\xc2\xa1\x5f\x02\x58\x70\xc7\x07\x38\xf6\xea\x7b\xfd\xd7\x6a\x40\x0d\xb7\xef\x94\xfa\x35\x2f\x70\x08\x7d\x1e\xf2\x1e\xca\x8c\xdd\x48\x71\x99\x8c\x66\x79\x21\x4b\x5a\x2e\x48\x6a\xbd\x99\x8b\x15\x08\x44\x01\x04\x51\x67\x48\x61\x78\x8f\x94\x97\x6b\xa8\x34\xee\x8c\x28\xc4\x52\x5e\xe5\x3d\xe1\x09\xc1\x58\xe1\x64\x5c\x03\xf2\xbe\x45\xed\x77\x29\x45\xf6\x32\x1b\xd0\x98\xd0\xe4\x12\x2d\x28\x3f\x5b\xa8\x37\x06\xa5\xf5\x3b\x3b\x36\x25\x22\x67\x54\x78\xc7\xbe\xeb\x38\x66\xa6\xd2\x5d\x8c\x63\x47\x4e\x78\x8c\xb4\xdb\x04\xc2\xba\x23\x95\x2c\xc9\x1b\x50\x80\xd6\x3a\xfb\xa4\x17\xac\x10\xfe\x1f\xf6\xda\x68\x7d\x3d\x55\xa2\xba\xe1\x5c\x02\x91\x96\x60\x6f\x5a\x5c\xaf\x29\x34\xd9\xaa\x33\xc4\x22\xcd\x02\x26\xf2\xc8\x2d\x4b\x17\xbf\x35\xd3\x69\x46\x45\xdd\x14\x1c\xd3\x99\xc2\xbc\x15\x9e\x40\x1f\x28\xb0\x4d\x61\x3a\xfc\x14\x5e\x04\xcd\xa1\x2b\x65\x9e\x24\x45\x7c\x4d\xfd\x20\x6c\x93\x35\x41\x9e\x70\x1d\x5d\x63\x8b\xda\xfc\x72\xee\xbf\xac\xf6\x67\x40\xc9\xb2\x33\x3f\x55\x05\x46\x8a\x7d\x8a\x55\xb5\xe5\x14\x32\x2b\x82\x7e\x3d\xae\x25\xcd\x12\xa3\x0a\x9e\xc5\x9c\xea\x3a\x4f\xf8\x0f\xaf\x84\x4d\x28\x5c\x62\xbb\xd5\x5c\x57\x29\x56\x8e\x66\x15\x4f\xfb\xe3\xb7\x47\xa7\x76\x74\x54\x36\xfa\x52\x31\x7a\x51\x2c\x7a\x57\x27\x7c\xca\x66\xf7\x0e\xc9\x75\xf6\x67\xb4\x9f\x86\xcd\x31\xe2\x4c\x50\xea\xfb\xa1\x39\x61\xe0\xd2\x0d\x2e\xbc\x2b\xc9\xee\xb3\xc9\x22\xb1\xd0\x4e\x3c\x6a\xdd\x83\xc3\xe2\x9a\x80\xa2\xaa\x91\x6f\x95\x5a\x3b\x24\xc8\x84\x4d\x31\xe3\x09\xef\x01\x4f\x81\x2d\x05\x4b\x59\xc6\x34\x0b\x7a\x1c\x17\xd8\x95\xb5\x64\xb9\xbc\x32\xcb\xec\xbd\x20\xef\x94\x8d\x97\xf3\xe9\x4b\x42\x07\x51\xc1\xb1\x42\x03\x5b\x30\x96\x62\x7d\x58\xd0\x54\xb0\xac\x84\x1a\x92\xc9\xc0\xe5\xb3\x2a\xec\x1e\x5a\x82\x53\xcd\x76\xf7\x02\x3f\x56\xc9\x0c\x01\x00\xa4\xaa\x94\x39\x51\x82\x16\x6a\x2e\x35\xb8\x4c\x68\x41\x13\xae\x17\x44\x97\x34\xb9\x34\x97\x40\x1c\x15\x1e\x37\x24\xc9\xc0\xa6\xb7\x87\xe4\x8b\x4b\xd6\xf4\xbc\x94\xd5\x6c\x0e\x35\x54\x78\x55\x92\x51\xe5\xbe\x7e\xe5\xfd\xd6\x86\x57\x24\x5d\x08\x9a\xf3\xc4\xf7\x0e\x29\xe5\x15\x57\x5c\xda\x48\x97\x1b\xf7\xd4\x77\x61\xc0\xe8\xd9\x41\x46\x79\x4e\xf6\x14\x63\xe4\xc8\xb1\x04\xfe\x72\x8e\x9a\x24\x7a\x12\xcb\x38\xa9\xce\x02\x3e\x5a\xe0\x01\x73\xa6\x16\xbd\x3e\x55\x01\x95\x01\xf3\xe6\x2b\x1f\x3a\xf0\xd3\xb5\xfa\x9d\x64\x09\x09\x6f\xae\x05\x10\x13\xa9\x0c\x32\x62\xf6\x4f\x8f\x55\x68\xdf\xda\x36\x8a\x38\x12\xfc\x90\x49\x31\x0b\x81\xef\x6a\xce\x34\x42\x5e\x40\x3f\xcc\x2b\x9e\x56\x34\x43\xf1\x6e\x5f\xe6\xe0\xfc\x18\x6f\xe7\xb3\xb9\x1e\x5d\x33\xf0\x7e\xe2\x2e\x58\xaf\x19\xf7\x50\xbe\x94\x69\xcb\x15\x6c\x07\xda\x7a\xd9\xd0\x93\x0c\x3d\x27\xe9\x02\x80\x77\x6d\x72\x67\x94\x8c\xe3\x60\xea\x71\x88\x55\x14\x87\xd7\xdb\xf7\x0d\x12\x8d\x4a\x04\xee\x61\x43\x62\xe0\xd4\xe5\x77\x83\x6e\x8f\x75\xcf\x0d\x7f\x5a\xd7\x9d\x1f\x41\x21\x6e\xdf\x39\x78\x6d\x8a\xec\x55\xcd\x26\x17\x2c\x2f\x32\xaa\xfb\x49\x2d\xd9\xf9\x39\x70\x7f\x07\xc1\x63\xb3\x1c\xa9\x48\x47\x34\x33\x1c\x79\xfa\xd3\x81\xad\x6c\xc3\x05\x16\xa5\xaf\x5d\xd4\x3d\x4a\x51\x39\x40\x2d\x69\xe5\xd2\x02\x2c\xb5\x09\x4b\x41\x18\xd9\x27\x83\x8f\xe2\x5a\x60\xeb\x5f\xf3\xc7\xe9\x4f\x07\x43\xc2\xc7\x6c\xec\xfe\xf2\x97\x3a\x69\xa8\xe5\x0c\x0b\x1c\x7c\x05\x0d\xf0\x33\x76\xe1\x0e\x9c\xbf\xe1\xbd\xff\xfa\xd6\xbc\xa4\xf9\xf5\x6f\xa3\x6f\x83\x5e\x46\x7f\xfb\x97\x11\xae\xa5\xb9\x20\x3e\x1b\xe6\x97\x83\xdc\x33\x7f\xfd\xeb\x54\xa6\xe7\x05\x4b\xc6\xf8\x59\xea\x5f\x98\x25\x40\x98\xd0\x46\xd7\x3e\x95\x90\x59\xc6\x53\xe4\x72\x78\x76\xc9\xfe\xed\x02\x04\xb6\x5d\xaa\x15\x24\x09\xd5\x4c\xc0\x06\xe0\x0a\x8d\x85\xd4\x78\x3b\x36\x5a\x85\xf7\xdf\x9b\x86\xad\x4f\xb5\x94\xb0\xcc\x51\x94\xec\x0b\xc2\x3e\x70\x05\xb8\x33\xf8\xad\x40\x0e\x6a\x93\xd7\xdd\x9e\x66\x86\x35\x14\xf6\x30\x43\xd8\x3d\x3c\xcb\xc8\x17\x42\xea\x2f\xfc\xf4\xbb\xc4\x44\xd8\xb8\x24\xa1\x57\x92\xa7\xa4\x82\xbe\x59\x66\x05\x0a\xf0\x6c\xd7\xad\x0b\x27\x0b\x92\x73\xa5\xe9\x25\x1b\x93\x73\xb3\x67\x85\x19\x06\x48\x3d\x41\xa0\x0b\x0d\x4b\x49\x25\x34\xcf\xe0\xd7\x7a\x1c\xf3\xca\xe1\x5e\x76\x3c\x25\xaa\x4a\xa0\x39\x6f\xc9\x46\x6e\x77\xb4\x57\x2d\xc9\x98\xfa\x5b\x86\x7e\xb2\xe7\x14\xed\xa7\x22\x85\x5b\xb1\xd5\xaf\xb0\xec\xb5\x94\x57\x6d\xde\x53\x8a\xa4\xde\x11\x81\x98\xd0\x35\xdb\x6c\x82\x99\x4b\x00\x42\x53\xce\x06\x0c\x04\x4b\x98\x52\xb4\x5c\x60\x37\x54\xee\x9b\x36\xda\x94\x57\xd8\xa9\x73\x2a\x2a\x18\xa0\x64\xd8\x5b\xb7\x4a\x80\x3a\x94\x4c\x4a\x79\xc9\x84\x2f\x21\xf0\x0d\xd2\x7d\x42\x75\x9d\x35\x0a\xf1\x7b\x49\x92\x39\x15\x33\x56\x57\x91\xe7\x34\x05\xda\xff\xe8\x35\x2d\xf7\x3d\x86\x02\x74\x6a\x14\x16\xae\x81\x14\x13\xb3\x3f\xf9\xb0\xc7\x7b\xe1\x71\x70\x87\x75\x5c\xc2\x7c\x12\xcf\x5a\xc9\x44\xd2\x8f\x23\xbc\xbb\x0b\x7c\x04\x0a\xc5\x1a\x93\xb7\x73\xa6\x69\x4a\x35\xed\x2d\x81\xfb\x0d\xf5\x5d\x3f\x6d\x52\x07\xb0\x43\x90\xec\x61\xf7\x58\xa7\x4a\xca\x82\x87\xb8\x02\x20\x0d\xe6\x6e\xf6\x01\x97\x4a\x1b\xbe\xb6\x41\x47\xcc\xcb\x06\x5d\x8d\x66\x99\xbc\xb6\x48\x75\x6e\x34\x14\x59\x2c\x25\x69\x05\x6a\x5f\x2d\xd2\xba\x04\xc5\x7b\x89\x99\x98\x89\xee\x8d\xca\x17\x75\xec\x3f\x89\x73\xb3\x57\x2a\x68\xb8\xd7\x31\xa1\x39\xb6\xc6\x77\x40\x10\x96\xf8\x95\xc0\xa5\xda\x98\x06\x98\xa7\x19\xd3\xaa\xce\xaa\xc4\xdd\xc4\x88\x48\xbb\x97\x5b\x27\x02\x6c\x35\x76\x6a\xac\x1d\xbe\x5a\x53\xc4\x89\x53\xd2\xee\x16\x66\xff\x5a\xfb\xcc\xf4\x17\x3c\xc2\xf6\xb7\x6f\x64\xda\x3d\x0a\xd5\xe8\xe3\x5a\x0f\x5c\x57\x9b\x60\xe5\x91\x02\x27\x0f\x5e\x00\x31\x79\x15\xc1\x64\xe0\x16\x30\xa7\x57\xed\xdd\xa9\xb5\x66\x3a\xf2\xcd\xda\xe0\x71\x23\x78\xdc\xe8\x45\x57\xc7\x75\xf7\xac\x45\x77\x74\xcc\x5e\x8c\x5f\xa8\x87\x48\x85\x11\xad\xe7\xbd\x04\x12\x1a\x28\x4a\x7e\x5c\xbb\xff\xda\xcc\x0c\x9f\x0d\x63\xeb\x69\x19\x37\x52\xf3\x25\xf9\x22\xd2\xb8\xac\x66\xeb\xad\x61\xac\x62\xda\x73\xe6\xf1\xd8\x4e\xbc\x83\xf3\x8a\x2f\x1f\x34\x06\x03\x55\x6f\xb5\xd5\xe8\xaa\xa5\xbc\xfa\x6d\x54\x65\xe8\xc3\xef\x6b\x54\x0d\x33\x97\x32\xcb\x5c\xef\x76\xb4\x90\x1b\xb9\x4d\xd0\x37\x08\xa3\x25\x43\xef\x86\xf0\xfa\xbe\x60\xd7\x5e\xb1\xa3\x0a\xe1\x4a\x5d\xac\x1e\x5c\x25\x2e\xe1\x6c\xd5\x78\xbe\xa2\x6b\x5f\x2c\xf0\xd5\x0f\x03\xd2\xa2\x7b\x81\xcc\xcc\x83\x8c\x05\x20\xe8\x24\xc3\x8c\x1c\xaf\xf8\xc0\xbb\xd0\xec\x9a\x2e\x14\xac\xb2\xda\x62\xf3\xcf\xb7\x58\xef\xf5\xc0\x67\x6c\xda\xa1\x9f\x7c\x78\xf4\x16\xcd\xef\x2f\x9e\x0f\x60\x2b\x5c\xb4\x4f\xd2\xad\x87\x69\xd1\x82\xbb\x79\xf4\x97\x16\x00\x99\x91\x90\x16\xd5\x47\x7c\x35\x5a\xce\xfb\xa7\xc7\x30\xb0\xb3\xdc\x66\xf0\x87\xdb\xd1\x7d\xa0\x70\xc2\xcc\x7a\xab\x21\xa2\x80\x77\xc3\x7b\x57\xe4\x8d\xd5\x4c\xff\x23\xf4\x43\xb2\xf1\x17\x57\x0f\x6c\x36\x84\xfd\xd3\x63\x7c\xe2\x18\x5a\xe2\x52\xb1\xb0\xba\x96\x9e\xf3\x32\x1d\x15\xb4\xd4\x0b\x74\x5e\x0c\xa3\xa7\xf9\xa2\xc8\x1e\xc8\xd1\x6b\x68\xb8\x4b\x0b\xb5\xf0\x88\xe6\x08\xc8\xe7\x02\x2f\x36\x72\x76\xe3\xcc\x6c\x1a\x45\xba\x96\x68\xba\x23\xa2\x48\xd8\x42\xc7\xf9\x2e\x1e\x05\x45\xd2\x50\x10\x3f\xd4\xbe\x6c\x64\xbc\x8a\xd3\x59\x70\x9b\x05\x1d\xda\xfa\x9b\x64\x58\x37\xe6\x75\x36\x30\xfe\xcd\x48\x43\xc2\xa7\x66\x83\x93\x62\x64\xab\xd5\xbd\x73\xdc\xea\x7d\x2e\xef\x13\x0d\x79\xb3\x74\xd1\xfd\x19\x3e\x2b\x1c\xc0\xaf\x75\xb2\x27\xa4\xc0\xf5\x8f\xd7\x0e\x30\xed\xf5\x06\xff\x2e\x5c\x32\x26\x3f\xcf\x99\x08\x37\xbf\xd0\x21\x3e\xf4\x9b\x30\x17\xa9\x99\x7c\xd8\x19\xc1\x1f\xa0\xaa\x24\x61\xcc\x7b\x90\xc2\x76\xf1\xb5\x7c\xb2\xaf\x9c\x53\x9d\xcc\x99\x22\x4a\x02\xec\xa8\xd2\x34\xcb\x6a\xcf\x8d\x25\x97\x04\x3d\xc2\x79\xd1\x03\xf5\x22\x2a\xf2\xb6\x4e\xac\x22\xa3\xd6\x53\x32\xad\x44\x82\x89\x55\x5c\x2f\xdc\x1b\x1c\x36\x55\x29\x30\x57\x15\x3a\x74\xf8\x14\x7d\xb7\x81\xd9\xe9\x89\x09\x02\x76\x81\x22\x35\xde\xf9\x2d\xb6\x9e\x91\xa6\x13\x9a\x5c\x5e\xd3\x32\x55\x50\xbf\x4e\x35\xc7\x16\x87\xc3\x68\xd8\xbd\xe0\x1d\xcc\xd3\x23\x4d\x61\xe0\x8d\x5b\xc5\x7c\x2b\xbb\xfa\x31\x84\x56\x5a\xe6\x54\xf3\x04\xdc\x36\x7c\x1a\x78\xe2\x73\xdf\x02\xc2\x47\x52\x51\xb2\xc3\x5e\x61\x3f\x03\x2c\xb8\x12\xcb\x2c\xf4\xb5\x24\x3c\x37\x1a\x18\x85\xd6\xcf\x53\x5f\xad\xee\x62\x06\xb7\xbd\xa9\x51\x33\x7f\x86\x40\x4d\x70\x15\x3a\x84\x8c\xa9\xae\x60\x78\x1f\x15\xf0\xee\x70\x5b\x96\x3d\x6c\x28\x48\xf6\x1e\xc3\xd3\xe6\x5d\x03\x56\x1d\x9a\xe9\xb9\x66\x46\xef\x52\xb7\x32\xac\x1a\xaf\x7a\x23\x3e\x13\x58\xb8\xcb\x95\x73\x21\xd8\x4c\xec\xbd\xb4\x94\x45\x61\x9d\x81\xf9\xa0\xf9\x46\x10\x7b\x2b\xaf\x98\x82\xb8\xb3\xcb\xed\x36\x64\x98\x31\xc1\x4a\xaa\xc1\x93\x6f\xe1\x08\x61\xe5\x36\x1f\x11\x2d\x98\x31\x82\xb2\x0c\xc8\x3b\xdb\xe0\xdf\x33\xae\xcf\x14\xbf\x93\x62\x8a\x9e\x45\xab\x9b\x6e\x35\xca\x5b\x87\xd9\x6a\x94\x5b\x8d\xb2\xc5\xb1\xd5\x28\x9b\xc7\x56\xa3\x0c\x0f\x9f\x8c\xdc\xaf\x36\x59\x57\x17\x04\x89\x1f\x61\x2a\x55\x7d\xc1\x4d\x2e\xbf\xe3\x29\x39\x63\x89\xbc\x62\x25\x6e\x22\x47\x1f\x0a\x2a\x8c\xae\xf4\x8a\xf2\xcc\x6c\x21\x6e\x2b\xa9\xdd\x1b\xd0\x47\x27\x76\xb1\x07\x1e\x25\x3f\x1f\x76\xb1\xe6\xf6\xa5\x2c\xd2\x85\xb9\xde\x06\xf2\x8b\x92\x5d\x71\x59\x29\x97\xf0\x55\x69\x14\x16\x4a\x5b\x7d\x66\xce\x67\xbe\xdd\x9d\x4f\xc7\x28\x59\x22\xcb\xb4\x86\xac\x52\x9a\xea\x4a\xc5\x35\xa4\x09\xfa\xb4\xfb\x73\x67\x7a\x3a\x6e\xd0\xee\xd9\xe7\x3e\x83\x19\x73\xbd\xaf\xd7\xdd\xd7\x98\x89\x87\x27\x27\x96\x0d\x5d\x72\x60\x9d\x98\x68\x54\xdf\x4a\xb3\x80\x5d\x2d\x63\xdd\x7b\x0e\x23\x3c\x9a\x67\xd8\x3c\x7c\xe4\x87\x1d\xd5\xb9\x80\xad\xfb\x23\x86\x47\x8f\xb3\x49\x7a\x07\x4e\x09\x8f\x47\x97\x3a\x18\x1f\xbd\x55\x2d\x90\x07\xa9\x5c\x20\xfd\x57\x2f\x90\x87\xaf\x60\x20\xbe\xa2\xac\xff\x75\x7f\xe6\x2a\xdc\x1a\x2b\xdf\x6e\x4b\xb7\xad\xfc\x08\x4a\xcd\x8f\xc3\x15\x91\x39\xd7\x9a\xb9\x04\x12\xbf\x92\xc1\xe1\x1f\x56\xf8\x58\x99\x03\xbe\x04\xcc\x12\x61\x1f\x7c\x0f\xa9\x40\x57\x05\x8d\xf3\x9a\x2b\x30\x90\xa8\x30\x76\x2d\x22\xda\x82\xec\x18\xd9\x74\x5f\x67\xab\x6f\xe5\x50\xf7\x71\xb7\x72\x28\x3c\xb6\x72\x88\x40\x37\xae\x0c\x8a\x47\x7a\x55\x8c\xdd\xa0\x16\x4a\x87\x4e\x58\x46\x7e\xab\x58\xb9\x20\x46\xd1\xad\xd3\x4c\xa1\xdd\x96\xe2\xa9\x4d\xd4\xb4\x8e\xc9\xae\xd6\xe5\x86\xea\x78\xe0\x38\x3d\xfa\x60\xec\x04\x40\x40\xe8\x5d\xea\x37\x1f\x10\x03\x19\xe1\x2c\xf8\x99\x09\xad\x03\xcc\x11\x89\xec\x05\x63\x2a\xec\x9f\x1c\xf6\x69\xea\xf7\x91\x3e\x40\xfa\x4b\x21\x20\x4b\x2e\x99\x5b\x48\x84\xa4\xf4\xbf\xc0\xc6\xe6\xd3\x3c\xbc\xa3\x91\x5c\xb2\xc5\xd0\x66\x53\xd9\x5e\x8b\xee\x62\x4c\x4c\x8c\x1b\xbe\x74\x03\x0a\x8c\x8f\x9e\x77\xa0\x3e\x7d\x83\x78\x74\x6d\xf0\x11\x8f\xe5\x88\xdb\xcf\xa6\xd8\xf3\x26\xdb\x43\x23\x90\xf0\xb8\xa9\x29\x08\x72\x2b\xf4\x10\x70\xd5\x52\x9e\x41\xa1\x42\x0c\x24\x6c\x3f\xec\x45\xfa\x76\x4f\xe1\xe1\xa6\xf1\x81\x88\xe5\x97\x60\x54\x96\x73\xc9\x16\xbb\xca\x62\x69\x48\xa1\xe6\xbc\x70\x5d\x22\x41\x4e\xda\x55\x49\x7e\x82\xfc\x37\x37\x04\x4a\xc4\x63\x31\x24\x27\x52\x9b\xff\x1c\x41\x42\x2f\xc6\x58\x24\x53\x27\x52\xc3\x99\x8d\x26\x37\x7e\xda\x03\x11\xdb\x86\x68\x38\x84\x58\x30\x75\x1d\x6a\x57\x5d\x9a\x27\x10\xd5\xe6\xf2\xf8\x89\xe1\x8a\x1c\x0b\x22\x4b\x47\x55\xed\x1a\x5f\x29\x3b\x84\xf3\x5e\x07\xd1\xb0\x15\x63\xd8\xc9\x90\x65\x34\x17\xb7\x0c\xe7\x03\x6b\xdc\xfd\x02\xde\x6d\x88\x44\xfa\xdc\x54\x68\xbe\x44\x35\x9b\xf1\x84\xe4\xac\x9c\x01\xee\x4a\x32\xef\x7b\x8a\xfb\xda\x17\xf1\xe8\x71\x77\xc4\xa3\x57\x3e\x04\x15\xe5\x35\x64\x1d\x3f\x8c\xfa\x83\x63\xe3\x76\x9d\xd3\xc2\xb0\xe0\xff\x31\xbb\x32\x70\xc1\xff\x85\xe6\x6e\x6a\x4c\xf6\x89\xe2\x62\x96\xb1\xe8\x37\xeb\xcf\x0c\x87\x31\x23\x18\xfb\xf5\xb7\x8a\x5f\xd1\x8c\x61\x95\x00\x15\xbe\xf5\x8a\x9c\x2e\x29\x5d\x43\xdb\xe1\xcd\xc8\x65\x1f\x83\xdf\xb9\x64\x8b\x9d\xe1\x12\xdb\xee\x1c\x8b\x9d\x1a\xc2\x29\x62\x54\xaf\x5c\x40\x78\x76\x07\x7e\xdb\xf9\x3c\x7a\xda\x23\x30\x63\x7b\xe3\x49\xeb\x72\x3e\xc8\xa8\x52\x7d\xa0\xc9\x34\x0a\xc2\x1b\xa3\xaf\x6a\x2c\x71\x1e\x5c\x53\x97\x84\xdb\x0a\x94\xde\xfd\xe8\x50\x01\xd9\x57\x3e\x70\x0f\xf4\xbf\xb2\xfd\xac\xbb\xc2\xd0\xad\x84\x02\x07\x10\x36\x57\x21\x1b\x21\x2a\xd4\x69\x3a\x37\x50\xfc\x27\x88\x88\xc8\x29\x79\x55\x37\x8c\xe0\x0a\x5c\x54\xdc\xd5\xcc\x0a\xa9\x09\x17\x49\x56\xd9\x60\x08\xdc\x0a\x0e\xae\x7e\x0c\xd8\xde\xc8\xdb\x3b\x63\xd7\xc3\x3a\x8e\x76\x29\x45\x4b\x85\x50\xcd\xec\x0f\xc8\xb7\xf1\xd9\x14\x48\xed\x75\x52\x6b\xda\xaa\xe4\x23\x6e\x74\x92\xc4\xfa\xe5\x2b\x3e\x29\x19\x39\x98\x53\x21\x58\x16\xa0\xc8\x58\x67\x28\xd5\x9a\x26\x73\x8c\xd9\x51\x62\xd6\x71\xc6\xf4\xae\xc2\x06\xfd\x39\x4d\xe6\x5c\x78\x5c\x05\xe1\xd1\x94\xea\xba\xb2\x35\xb4\x06\xea\x6a\x20\xf5\xd8\x55\x66\xd7\xb6\x95\xb1\x7c\x17\xf6\x73\x89\xbb\xcd\xd4\x00\xe5\xcd\x6b\x6a\xa4\x7e\xbb\xe6\x81\xf2\xb8\x2f\x43\xeb\x13\xb8\xf6\xf6\x7e\x35\xb9\x77\x68\x73\x31\x65\x65\x89\x33\x34\x61\xf6\x86\x46\x8f\xd9\xb1\x6d\x62\x31\x97\xd7\x24\x95\xe4\x1a\xba\xad\x5e\x19\x05\x02\x52\x91\x94\x53\x3d\x82\x37\x85\xc4\xc0\x44\xe6\x45\x29\x73\xae\x5c\xf9\xa3\x65\x8f\xb5\x01\xa6\x64\x55\x6b\xcc\xd9\x78\x16\xb3\x4a\xc4\xcd\x1e\x5f\x1d\x10\x4d\xcb\x19\xd3\xe6\x19\x44\x54\xf9\x84\x75\xc4\x85\x59\x37\x2a\x79\xaf\x5d\x40\x76\x7d\x1b\x90\x88\x6a\x9f\xe8\xef\x41\xce\xdc\x5d\x90\x40\x08\x69\x8a\x53\x59\xda\x64\x4b\xff\xa3\x85\xa1\x37\x5c\xf8\x93\xdd\x38\x2b\xa1\x55\x47\x54\xf8\x2e\xfd\x41\x90\x15\x7e\xfe\xf9\xa4\x1f\x58\xf7\xdd\x7a\xbc\x9b\xb8\xee\x5a\x96\x59\x7a\xcd\x53\x54\xce\x14\xd9\x33\x17\x0f\xba\x51\x60\x8d\x28\xef\x9d\x57\xfa\xf5\x35\x4f\x7b\x22\x3e\x0c\x15\x13\xdd\xe5\x51\x1b\xa2\x13\xa0\x3a\x4f\x99\xd0\x46\x58\x96\x8a\xec\xc1\x1d\x03\x72\xc4\xb1\x12\x1f\xee\x07\x10\xd5\x7c\xc2\x45\x8d\xf2\x50\x4f\xaa\xd9\x2e\x8d\xdc\x70\xe6\xbd\x62\x1a\x6b\xa8\xa1\x0c\x59\xea\x39\x51\x3c\xaf\x32\x4d\x05\x93\x95\xca\x16\x1d\x59\xfb\xb1\x4e\xec\x34\x63\x1f\x70\x85\x77\x57\x7a\xfc\x50\xb1\xf2\x03\x89\xb6\x35\x70\xca\x92\xf6\x53\xa7\x82\xa7\xcf\xbc\x26\xe4\x81\x00\xd8\x07\x96\xd8\x1a\xb1\x22\xab\x66\xbc\x55\x51\xf0\xb6\x0f\x62\xab\xbb\xef\xd6\x07\xb1\x6e\xf7\x56\x29\x56\x23\x97\x75\xeb\x43\xbe\x81\x6d\x0b\xd7\xab\x5f\x5e\xac\x6e\x59\x98\xb2\x82\x89\x14\xa0\xd3\x5f\xd5\xeb\x0f\x5f\x7e\x6d\xb4\xb7\x90\xe5\xfd\xec\x15\x0e\xff\x3c\xda\xa5\x83\xc4\xfb\xb9\xcc\x52\x45\xd8\x07\x5d\x52\xb3\x1d\xe4\x46\xf0\xfb\x7b\xa6\x84\x8a\xae\xa2\xfd\xa9\x34\xde\x22\x9f\x49\x03\x4d\x9f\xa8\x06\xaa\x7a\xed\xc8\xb9\xab\xc2\x3e\x9c\x35\xf5\xa2\xd3\x3d\x37\xe7\xc4\x0d\xd4\x4a\x07\x15\xd7\xa1\xad\x68\xa2\x69\x9f\x12\xd7\xbf\x74\x6b\xa6\xa9\x56\xb4\xd6\x6b\xbc\xd5\x1a\x17\xeb\xb6\xb3\xe6\xe3\xea\xac\x39\x05\xb8\xa7\xee\xe0\xc7\x76\x9c\x86\xcf\xce\x9e\xb4\x6a\xeb\x5d\x7c\x74\x76\x45\x05\x7b\x32\x74\xca\xb1\x03\x59\xd8\x04\xa2\xcc\x6c\xd4\xc5\x11\x95\x10\xed\xa4\xf9\xba\xfb\x0e\x52\x4d\x15\xd3\x5d\x3c\xc9\xb1\x82\x59\x8f\x67\x44\x4e\xc8\xf9\xf6\x27\xec\xde\x09\x85\x9e\x0e\x02\x89\x8c\xfe\x66\x75\x51\x11\x5d\x69\xb4\x50\x47\x77\x07\x8e\xcc\x7c\x66\x19\x8e\x91\x9a\xd9\x4e\xa8\xee\xd8\x90\xbe\xc3\x6e\x6c\xdf\xf6\xdd\xbb\xe3\xc3\x3e\x49\x68\xc6\x73\xda\x2a\xfc\x3b\x26\xa3\xe5\x52\x00\xd0\xe5\xbf\x55\xa1\xa1\x0d\xd0\x8d\x9e\x70\xf6\xfa\x75\x50\x67\x96\xb0\x3a\x4c\x70\xc8\xd5\x65\x77\x80\xf3\xa5\x21\xe3\xe5\xfe\xc3\xc1\x11\xb1\x67\xef\xe4\x9d\xbf\x8f\x7b\xbe\x2b\x2a\xf6\x2c\x61\x75\xe0\x2e\xe5\xea\x72\x0d\xe0\xe8\x5d\x6d\xe0\x22\x3d\x69\x57\xc7\xb9\x99\x91\x86\xa6\x85\xe7\x60\x54\x03\x7c\xdf\x85\xac\xc8\xb5\x85\x11\xb4\x16\xe2\x05\x2f\x5e\x92\x23\xa1\xaa\x92\xd5\x19\x5a\xcd\xa1\x8c\xbe\x75\x67\x7b\x11\x90\x1a\xd5\xcb\xde\xa2\x12\x7d\x73\xea\x53\x09\x73\x14\xb4\xd4\x60\xc8\xf5\xc3\x48\x7e\x38\x27\xa7\x83\x13\xe2\x2e\x9c\x74\x3c\x75\xc5\x17\x43\x8b\x29\xe6\x81\xd3\xdd\x45\x86\x77\x02\x90\xd1\x90\x5b\x5e\x79\x60\x5f\xf2\x2c\x65\x57\xcf\x54\x4a\x5f\x0c\xe1\x31\xae\x64\x30\x7e\x27\xaa\xc8\xce\x8b\x9d\x31\x39\xe7\x39\xcf\x68\x99\x2d\xa2\x06\x67\xf5\x75\x66\xdb\x75\x03\x42\x36\xcb\xf3\x1d\xb2\x27\x4b\x18\x39\xa1\x82\x64\xcc\x61\x2e\xd8\x55\xbd\x40\xbb\x63\xb0\x19\x22\x92\x6c\x4c\xa4\x08\xa5\x65\x4f\xbc\x96\x3a\x9d\xca\xee\xf7\x11\x68\xed\x61\xbd\xe1\x71\x61\x76\xc1\x31\x79\x67\xb7\x2f\xab\x17\x20\x33\xc0\x62\x76\x57\x6c\xd6\x64\x6d\x9e\x3f\xa4\x95\x67\x63\x39\x74\xb7\x69\x84\x6e\xeb\x3d\x99\x71\x7d\xc6\x0a\xd9\x83\x0e\x87\x03\x35\xe2\x0b\x5c\x9b\x13\x52\x71\x68\x4f\x43\x35\xa1\x28\x92\x92\x2a\xa3\xc6\xa8\xc3\xe8\xc2\x98\x1c\x1e\x9d\x9e\x1d\x1d\xec\x5f\x1c\x1d\xbe\x24\x3f\xd8\x91\x78\x68\x07\x8c\xc9\x45\x88\x3b\x1d\x54\xb4\x59\x70\x5f\xff\xac\xa1\x15\xb1\x54\xd4\x8d\x33\x00\x87\x93\x0a\x72\x2c\xb8\xae\x5b\x86\x61\x5d\x40\x26\x85\xcd\xf4\x37\x77\xdb\xe8\xc6\x8c\x63\x3e\xaa\xb0\x83\x99\x9f\xe3\xd1\x60\x85\x62\x83\x1d\xff\x2a\xad\x1c\x24\x6b\x56\xfe\xea\xe9\x59\x87\xa1\xea\x7a\xe1\xf4\x63\x63\xf9\x3e\x48\x0e\x06\x02\xa3\xc5\xf5\x79\xdc\x6c\x7d\xdb\x47\x07\xac\x2b\xcb\xa8\x2b\xe3\x78\xbc\x3b\x26\x66\x1b\xdf\x1d\xef\x3a\x95\x2f\x5b\x6a\x1d\xea\x07\x0d\xf1\xcb\x63\x86\x1f\x13\xf2\xd6\x95\x4d\x02\xf8\xd4\xea\x2e\xa4\x88\xbf\x18\xf4\x9c\x6c\x2c\x1b\x57\xba\x5f\x4d\xc2\x87\x5a\xc0\xf3\x19\xbf\x62\x02\x3f\x6c\x7d\x92\xda\xbd\x6a\x2f\xd3\x18\x7e\xb9\xb5\x94\xcf\x5e\xaf\xef\xdb\x50\xe2\xf4\xf4\x65\x56\x7c\xd9\xef\x4a\x64\x9e\x23\x42\xf7\xdc\x83\xc9\xd4\x78\x30\x5e\x3a\xae\xc5\xca\x47\x5c\xf2\x69\xab\x85\xdd\xd8\x19\xdc\x50\x0d\xab\xde\x9f\xb6\xe5\xcd\xa2\x36\xa7\xee\xdf\xc7\xcc\x02\xe3\x2b\x07\xb2\x6a\xb7\xd9\x67\xfe\xe1\xcf\xce\x8e\xf6\x0f\xdf\x1c\x8d\xf3\xf4\x11\x0a\x69\x26\xd2\x42\x72\xa1\x55\x5b\x0b\xbf\x5d\x3f\xf4\xae\xe2\xdd\xbf\x76\x3f\x3a\x9c\x1f\xce\xad\x1f\x77\x22\xe8\x72\x90\x32\x4d\x79\xa6\x02\xee\xd2\xb2\x90\x99\x9c\xad\x6e\x80\x76\x0f\xb6\xf9\x03\x22\xe4\x8e\xe8\xc8\xf0\xe3\xfa\x8c\xdd\xf6\x7d\x94\x9b\x76\x2e\xf6\x4d\x36\x84\xac\xa9\xe5\xed\x46\x68\x77\xfc\x04\x08\xf6\x19\xcd\x88\x25\x2a\xa2\x3b\x07\xc4\x9b\x6b\x42\x51\x77\x75\x08\xba\xab\xdf\xd5\xbe\x58\x0f\xf1\xdb\x9a\x16\x46\x92\xb7\x6d\xe3\x1f\x53\xdd\x8d\x14\x6f\x20\x45\xc9\x46\x1e\x36\x1b\xda\x7b\xcb\x32\x50\xcb\xc2\xfd\xc4\x79\x82\x9d\xdf\x18\xaf\xca\x16\x4d\x8f\x70\xad\xc9\x7b\x47\x3c\x62\x11\x66\xd9\xa2\x6e\x8d\x62\xbd\x61\x74\x86\x70\xd8\xa5\x0d\xc8\x15\x25\xbf\xe2\x19\x9b\x41\xdb\x23\x2e\x66\x01\x8c\x53\x08\xfc\x64\xdb\x20\xc5\xc1\xa9\x37\xe6\xaf\xa0\xf5\x1e\x70\xd6\xc9\xdb\x0b\xe8\xa0\x05\x29\x15\x9d\x0d\x4e\xf3\x40\x58\xf3\xa3\xd1\x08\x5c\x7f\x7b\xff\x36\x96\x4f\x9a\x0d\xc8\xcf\xcc\x3e\x47\x42\x8b\xaf\x12\xda\xdc\xcf\xa5\xef\xb7\x04\xef\x5a\x53\x16\x18\x1a\xd3\xf8\xec\x55\xcf\xcc\x95\x46\xa3\xc6\xad\x3c\xba\x9e\x33\x80\xec\xae\xf3\x0c\x1e\xa3\x95\xb4\xa6\x0d\xb4\x67\x69\xef\x82\x4d\xab\xd6\x88\x4f\x1f\x70\xfb\x02\x25\x6a\x91\x67\x5c\x5c\xd6\x18\xf1\x53\x69\xf8\x18\xcb\x99\xb9\xb8\x74\xab\xa6\x64\x34\xbb\x79\xc7\x68\xc3\xa3\x6b\xdb\x2d\x74\x6f\xf1\x08\x88\x17\x18\x69\xf1\x77\x27\xbc\x6c\x02\x58\x28\xea\x77\x76\x1e\x35\xc5\xb8\x4a\x14\xef\x2e\xde\x61\x98\x48\xb6\x0b\x72\x7c\x7e\x70\x7e\xfc\x59\xa3\x7e\x37\x6d\xae\xf0\x76\x8f\xda\x7a\xe0\xbf\xb5\xcb\xaa\x1a\x91\xac\x6a\x7b\x27\xba\x5e\x4e\x65\xa9\x69\xb6\x06\xc1\x99\xcc\x69\xb1\x5f\xe9\xf9\x21\x57\x80\xd6\xd8\x8f\xfa\xb7\x34\x6a\x50\xaf\x88\x7d\xe8\x5c\xc3\x0d\xee\xd8\xd7\x5e\x77\xf0\xf7\xfd\x53\x42\x2b\xc3\x8f\xda\xb6\x18\x5a\x5b\xb2\x9c\xfb\x8a\x73\xac\x81\xee\x95\x32\x76\xcc\x4f\xd0\xc5\x5d\xb5\x49\x54\xf9\x7c\x55\x6f\xdb\x78\x34\xec\x5c\x28\xf5\x9f\x48\x0c\x9a\x0b\xae\x39\xd5\xb2\xec\x2d\x36\x18\x8d\xe8\x1d\x86\x95\xd2\x32\xb7\xab\xe8\xd8\x5d\x01\x09\x59\xa0\xbf\x2d\xdd\x54\x7b\x13\xc1\xfa\x04\x9a\x1f\x0b\x63\x2b\xd2\x84\x35\xca\x6c\x86\xd0\xfa\x07\xc7\xe6\xfe\x9a\x6f\xad\x13\x1d\x50\xec\xb3\xbf\xbd\x8c\x9a\x63\x2e\x75\x30\x76\x5e\xcc\xba\x3d\xee\xda\xbc\xd2\xfc\xb7\x7e\x44\x1b\xff\x4d\x34\xe2\x09\x48\xa2\xff\xae\x68\x86\xa4\x3d\x59\xa7\xf3\x3d\x9e\xd2\x7e\xbe\x38\xe6\x12\xfb\xf1\x35\x4b\x9c\x78\x6f\x5b\xa5\x10\xa3\x1f\x29\xa2\x4b\x2a\x94\xe1\x93\xd8\x9f\xb1\x6b\x13\x20\x76\xc9\x9e\x4e\x8a\xc1\xda\x28\xd5\x57\x39\x6c\x56\x89\x50\x59\xc5\x6f\xbf\x40\xd6\x78\xed\xcb\x61\xbb\x7d\xe6\xda\x93\x1c\x60\xb5\xf7\xe3\xb7\xb5\x63\x79\x3e\x0a\xe9\x85\x0a\x22\x79\xcd\x95\x76\x0d\x84\xe1\x04\x57\xb6\xd7\x1a\xd8\x02\xa7\x44\x96\x84\x17\xff\xa4\x69\x5a\xbe\x44\x3d\xc2\xda\xaa\xf0\x6f\xe5\xe1\xf0\xa9\xf0\xd9\x36\x7b\x7a\x51\xd8\x26\x1e\x17\x07\xa7\x04\x1b\x85\x7f\xf3\x97\xe7\x60\x17\x7c\xfd\xd5\x5f\x9e\x77\x64\xc4\xc7\x5a\x55\x48\xfa\xf6\x89\xf6\x9e\x59\xf1\x44\xaa\x48\xa2\x6a\x11\x43\x0b\xd0\x76\xcf\xb1\x38\xc3\xec\x93\x56\x68\xe2\x42\x30\x5c\xe9\x77\xef\x3e\x75\xe2\x6d\xd5\xc5\xef\xa8\xea\x82\xf8\x6a\x7c\x14\xac\xbd\x30\x72\x38\x20\xc0\xea\x2c\x0b\x70\x94\xdd\xa7\x8f\x45\x76\xb7\xa4\x6e\x5b\x4e\x8e\x39\x38\x4c\xf1\x73\xad\xf3\xeb\xf2\xd4\xc3\x93\xf3\x7f\xbe\xde\xff\xfe\xe8\x35\x7c\xab\xcd\x0a\x34\xec\x69\x2d\xa1\x36\x39\xeb\x77\x67\xf7\xf6\xce\xad\xb6\x24\xed\x23\xc1\x40\x34\x52\x0b\x04\x39\x79\x75\x7e\xdf\xac\x82\xae\xe6\xac\x98\x76\xa0\xde\x63\x8b\x6b\x40\xa7\x75\x56\xae\xa7\x72\xbe\xe7\xa0\x48\x00\x7b\x1f\xf9\x51\x0c\x0f\xe1\x37\x76\x76\x75\xb4\xe4\x0d\xb2\x71\xba\xde\xed\xf1\x6f\x43\x31\xa4\x62\xef\x91\xef\xcf\x4a\xed\x6e\x3a\x64\xd9\x17\xac\xc3\x2e\x8e\xe5\xd4\x47\x23\xc2\x70\xef\x28\xcd\xae\x6a\xf6\x53\xa6\x7c\x37\xe6\x27\xc0\xad\xc5\xaa\xd6\x83\xdd\x77\x87\x95\xc3\xda\x1e\xdc\xae\xf5\x52\x90\x55\x10\xd5\x75\xdf\xd4\xc0\xd3\x65\x64\x52\xeb\x08\x53\x05\x4d\x7a\x6d\x08\x5f\x9f\xc2\x33\x00\xbd\xf7\x18\x37\x18\x78\xf1\x35\x95\x97\xf9\x67\xf7\xb3\x1c\xfd\x70\x4d\xa4\x95\x7b\x71\x89\x6b\x5f\x5e\x48\x87\xa4\x13\x42\xb2\x6c\x24\x0b\x91\x8d\xdb\x87\xfc\x36\xf4\x73\x4b\x77\xc3\x3a\x5d\x0d\xc5\x5c\x6a\x29\x7a\xae\xa1\x5d\x35\x68\x2c\xd8\x4e\xe1\x8a\x03\xac\x74\xcf\x58\x19\xc8\x5b\xac\x20\xf2\x61\x75\x63\x79\xb8\xad\x5b\x0a\x17\x60\x8f\xc3\xeb\x8f\x4f\x12\x15\xe9\xf1\xe1\x1a\x84\xd0\x53\x03\x3b\xba\x6f\x98\x70\x6d\x89\xb2\x69\x4f\x95\xfb\x66\x20\x47\xf3\xe3\x43\x6b\x2e\xb8\xb2\x7c\x65\x97\x15\xb9\x79\x5d\xad\x45\x95\x92\xa5\xbe\x96\x65\x5f\xf0\x71\xf1\x70\x8d\x2c\x4c\xfb\xdb\x12\x18\xc7\xd3\x94\x22\xf8\x95\x8f\x5e\x92\x9c\x83\x24\x69\xb4\x41\xbd\x49\xa2\x3c\x84\x40\x79\x3c\x82\xe4\x61\x14\x97\x87\x45\xe2\x5a\x9b\xf9\xeb\x96\x47\x2f\xc4\x72\x83\x59\x37\xa8\x61\x94\x5a\xee\x52\x70\x37\x07\x92\x67\x2d\x72\xb6\x94\x46\x0e\xb5\x13\x27\xb1\x88\x75\x23\x61\x70\x10\xdb\x36\x66\x99\x99\x59\x29\xc2\x86\x8f\x16\xac\x6b\x48\xb0\x67\x62\x4e\x0b\xdb\x34\x3f\x95\xd7\xe2\x9a\x96\x29\xd9\x3f\x3d\xfe\xfc\x72\xb5\x73\x25\x28\xae\x87\x2e\xbd\x05\xe2\x5a\xd0\x7a\x3c\xc8\xc0\x87\x24\x21\xf3\xc7\x84\x6b\x85\xa9\xfc\x90\x8c\xaf\x43\x6f\x94\xd9\xa7\x7c\x26\x8b\x91\x74\x46\xaa\xd9\x91\x02\xb5\x4a\x10\x99\x68\x9a\xb9\x46\xcc\x4c\x5f\x33\x26\xc8\xf3\xe7\xcf\x31\x40\xf1\xfc\xbf\xfe\xeb\xbf\x08\x74\xdd\x4c\x59\xc2\xf3\xe5\x0b\xe1\xaa\x3f\xbf\x78\x31\x26\xff\xd8\x7f\xf3\x9a\xd0\x04\x6c\x39\x44\xbe\xc5\x91\x61\x3e\xc3\x9b\xd5\x90\xfc\xef\xf3\xb7\x27\x6e\xfb\x52\x8d\x5f\x81\x5d\xfc\xe7\x8d\xc9\x61\x90\x7b\x1f\x06\x0f\xa8\x9e\x03\x35\x84\xd4\x84\x4e\xa7\xc8\x70\x20\xb9\xb9\x72\xc2\xc4\x61\xcf\xf1\xd9\xdc\x75\xa2\x37\xac\x96\x41\x51\x00\x37\xaf\x08\x01\x1b\x87\xe3\x88\x35\x0e\x30\x96\xdf\x44\xe0\x55\x86\x24\xe3\x97\x8c\x4c\x15\xf4\xa3\xaf\x1b\xa7\x94\x4c\x19\x03\x2c\xa1\xc2\x8c\x8e\x83\xd5\x33\xa3\x58\x47\x6c\xcc\x75\x67\x4e\x74\xec\x5c\x1e\x87\x90\xed\x9a\x77\x2d\xc4\x6c\x6f\x40\x57\xa3\x85\x22\xc3\xcc\xc2\x63\xcd\x64\x88\xbe\xf6\xd4\x7f\x0f\x32\x95\x45\x3f\xac\x25\x23\xcd\xa4\x98\x85\x3c\x58\x6b\x1f\x2e\x99\x72\x51\xb0\xb6\xc4\xe8\xa9\xa1\x4e\x3f\xed\xe9\x50\xb8\xbf\xa1\x45\xb7\x4e\x20\x71\x8e\xae\x1b\x33\xc2\xa1\xa4\x13\x59\x69\x97\xb3\x67\x7f\x07\xf8\x36\x2d\x1d\xe9\x3b\xbd\x42\x6f\x5d\x8a\xfa\xeb\xfb\xd7\x53\xd3\xad\x38\x67\x0e\x76\xed\x58\x65\x1d\x12\x46\x93\x39\xb9\x64\x8b\x11\xee\x00\x05\x05\xf4\x08\xa0\xf6\xa1\xa1\x71\xd4\x86\xdf\x7b\x9e\x53\x63\x4d\xda\xa9\x70\x09\x96\x81\x7e\xe0\xd0\x27\x9c\xc1\xa5\xac\x5e\x6e\x5b\x59\x89\xc0\x43\xe9\x7a\x57\x26\x52\x68\xdb\x17\xd3\xf7\xae\x82\x84\xd1\x06\x20\x81\x91\x30\x2c\x35\xb7\xa9\xdb\x9e\x5c\x67\x95\x9a\x1d\xc5\xea\x1f\x95\x58\xba\x1b\xf0\xdc\x21\xa7\x57\x31\x8b\x8c\x44\x5d\x4f\xc4\x20\x33\x75\xce\x13\xa8\x38\x32\x97\xdb\x6b\x1d\x95\x3c\x21\x22\xc0\x04\xc5\x74\x65\x49\x03\x79\xc2\xe6\xd9\x4c\x29\xc2\xe1\x0b\x73\x5a\x5e\x32\x07\x34\x4c\xb3\x31\x39\x35\x2f\xe9\xd1\xe6\xb1\x95\xe0\x15\x16\x88\x18\x19\x13\x22\x41\x98\x87\xec\x8e\xc7\xbb\xb8\x55\xae\xc0\x85\xe8\xcc\x35\x7d\x76\x91\xeb\xad\x7b\x5c\xc4\xca\x6f\x68\xa1\xb0\x9b\x9e\x31\x2d\xa0\x63\xa5\x04\xdc\x16\x3d\x77\xca\x04\xed\x08\x21\x1e\x1e\x3d\xb7\x31\xeb\xb7\x13\x6a\x7f\x7d\x50\x3b\xc4\xda\xe3\xa3\xef\xfe\xa7\x3d\x76\x3f\xbd\xa9\xf7\xa9\xe5\x21\x2b\x49\xfa\xea\xc8\xd8\x7b\xcb\xcd\xbc\x87\xc6\x66\xee\x88\x43\x47\xa0\xdf\x46\x58\xd2\x77\xb2\x45\x2c\x94\x7a\xc6\x1e\x95\xf1\x71\x3c\x05\x91\xba\x1a\xeb\x26\xb4\xcb\xdc\x0e\x63\x28\xb0\x7e\xab\xa3\x6b\x97\x3d\x77\x3c\x44\x9b\xfa\xee\x66\x49\xf3\xe8\x92\x44\xd3\x3c\x62\x47\x46\x00\x2b\xe1\xb7\xda\xb0\xfa\x18\xa6\x4a\x4b\xe8\xd6\x59\x0b\x87\x31\x79\x63\xb7\x62\x64\x72\x3a\x51\x32\xab\xb4\x47\xa2\x58\xb1\x4f\xc3\xa0\xae\xb7\x27\x82\x36\xb9\xcb\x82\x5d\x1b\xf4\x15\xdc\xca\xfa\xd9\xc0\xf1\xe8\x51\xf8\x74\x4d\x90\xc5\xe3\x77\x96\x26\x8b\x47\x8f\xb3\xe0\xd4\xc5\x9e\x67\xc2\x0d\xeb\xd1\x3b\x5d\x45\x64\xa4\xdd\x42\x8e\xac\x56\xa8\x3a\x3b\x45\x15\x6b\x28\xdb\x22\x60\xd7\x47\x77\xaf\xae\xfd\x2e\xeb\x60\xdc\x3f\x3d\xee\xd1\x2a\x0d\x46\xbd\xc1\x2e\x0d\xaf\xd8\x5a\xa6\x77\x39\x22\x02\x1f\xa3\x65\x6a\x54\x7a\xe7\x40\x3a\xac\x29\x6a\x43\x7a\x46\x28\xff\x0e\x4c\x9b\xa5\x0f\x7f\x65\x36\xa3\xb0\x98\x2b\xee\xd0\x81\xce\xe0\x7a\xdb\x0a\xba\x7a\xb8\x1c\x1e\x10\x71\x4f\xdf\x0c\xda\x50\xe3\x05\xa8\xdf\xa1\x62\xa7\x79\xc4\xbb\xe8\x99\x23\x22\x39\x67\x99\xd9\xf4\x48\xc3\x65\x53\xc8\xf4\x25\xf6\xfc\xa6\x42\x48\x0d\x7c\xa3\x86\x24\x83\x7e\xe4\x43\x74\xc5\x18\x0d\x34\xc8\xfe\x2a\x83\xa0\x69\xcf\x3a\x67\x6f\xcc\x43\x7a\x67\x20\x02\x4c\x04\xb4\x3b\xed\x87\x93\xc8\x03\x70\x93\x39\x6a\x55\xa5\xcf\xb6\xfc\x11\x5f\xd9\xf1\x1d\x13\xa9\x64\xce\x72\x8a\xfd\x48\x1c\x81\x8c\xbc\xbe\x2e\xb9\xd6\x0c\x51\xc7\x59\x99\x2b\x22\xa7\xc3\x28\x6e\xbc\x73\xf5\x62\xa7\x2f\x7d\x96\x3c\x84\x41\x4d\xdc\x0a\x6d\x0b\x03\x76\xd3\x11\xc7\x0d\x22\xe3\xc2\xac\x4e\xb0\xa6\x33\x68\x90\x24\x1a\x0e\x4b\xa3\x44\x5c\x21\xfd\x37\x9a\x74\x0f\xe7\x8b\x68\xeb\x83\x18\x7a\xc5\x74\xeb\x83\xd8\xfa\x20\xfa\x18\xf1\xc1\x7c\x10\xc1\xc6\xed\x84\xe9\x0a\x7f\x44\x58\x88\xe7\x9c\x12\x35\x94\x45\x00\x13\x6d\x58\xde\xb9\x23\x64\x19\xc7\x0a\x76\xc7\xe3\xdd\x5d\xe7\xa4\xb0\xeb\xa3\xd2\xd3\xd1\x37\x84\x89\x44\xa6\xc8\x54\x66\xfc\x52\x69\x50\x6a\x6b\xab\x3c\x7c\x97\xdc\x3d\x2b\x8c\x37\xc0\xd8\xfd\xb2\x44\x8f\x12\xca\xa5\xa4\xbc\x7a\x50\x15\xac\x56\xbc\x3c\x0c\x98\x25\xa0\x47\x4b\xb4\x1a\x58\x9d\x22\x93\xf1\x9c\x5b\x7c\x42\x23\x2e\x98\xd2\x8a\xec\xe1\xc9\x71\x52\x54\x43\x7b\xc1\x38\x67\xb9\x2c\x17\x43\x7f\x91\xf9\x31\xba\xcb\x5e\x31\x00\xad\x2d\xa9\xca\x92\x09\x9d\x2d\x7e\xbf\xfa\x9b\x23\xf1\x06\xab\x6f\x9e\x2b\xba\xd4\x7d\xac\x3a\x62\xb6\xac\x9b\x08\x80\xf7\xce\x53\x1b\xf6\x21\x5b\x81\x31\xac\x9d\x3f\xe6\x2c\x13\x57\xe4\x8a\x96\xad\x2b\x30\x56\x1d\x0f\xa2\xb1\xa5\xfc\x8a\x2b\xd9\xba\x86\x6d\xe5\x90\x21\xf1\xce\xed\xa6\x8c\x3e\x62\x59\xe9\xa2\xd2\x76\x77\x71\x6b\xdb\x41\xf6\xf9\x35\xdd\x50\x7c\x5f\xec\xf4\xf8\x72\x05\xd5\x9a\x95\xe2\x25\xf9\x9f\xbd\xf7\x5f\x7e\x1c\x0d\xbe\xdb\xdb\xfb\xe5\xf9\xe8\xaf\xbf\x7e\xb9\xf7\x7e\x0c\xff\xf8\x62\xf0\xdd\xe0\xa3\xfb\xe3\xcb\xc1\x60\x6f\xef\x97\x1f\xdf\xfc\x70\x71\x7a\xf4\x2b\x1f\x7c\xfc\x45\x54\xf9\x25\xfe\xf5\x71\xef\x17\x76\xf4\xeb\x1d\x07\x19\x0c\xbe\xfb\x63\x8f\x1f\x41\xc5\xe2\x6d\x6f\x22\x18\x8f\xd1\x83\xa8\x11\xf1\xd8\x3d\xb3\x2e\x21\x1f\x46\xb5\x47\x7b\xc4\x85\x1e\xc9\x72\x84\x0f\x79\x49\x74\x59\xf5\x25\xba\xea\xed\xef\xe1\x64\x4c\xad\xc4\xd4\x08\x98\xce\xb0\xd9\x40\x21\x82\x89\xa9\x3d\x7a\x86\x6d\x1f\xdb\xd5\x4e\x61\xfb\xe3\xd6\x1f\x7c\x97\xe3\x01\x33\x95\x2c\x9e\xcd\xef\x3c\x4d\xe9\xdc\x76\x53\xde\xe6\x28\x2d\x1d\xdb\x1c\xa5\xe5\x63\x9b\xa3\x74\xcf\x63\x9b\xa3\xe4\x8e\x6d\x8e\xd2\xd6\x3f\xd8\xfd\xf8\x9d\xfb\x07\xb7\x39\x4a\xf7\x3d\xb6\x39\x4a\xad\x8f\x47\x94\xa3\x84\x4a\xfe\xaa\x4c\x25\xab\xe6\xd7\x69\x4a\x1b\x9b\xa5\xa4\x0c\x3f\x24\x6c\x3f\x49\x64\x25\xf4\x85\xbc\x64\x1d\x03\xb9\x0d\x9b\x74\x69\x74\x80\x44\xbc\xc1\x46\x5d\xbe\x78\x23\x0d\xd6\xbe\xf4\xd1\x1e\xf4\xc7\xfe\x34\x47\x5a\xa5\xdc\xd8\xa8\x3d\x2f\x16\x37\x6c\x08\x8b\x2d\x52\x96\xd6\x3f\x58\x91\xa6\xcd\x7c\x8f\xc9\x3e\x29\x59\xc2\x0b\x6e\x36\x00\xc0\x0a\x82\xf3\xb8\x7c\x7c\x17\x67\xae\x15\xcb\xa6\xb6\x93\xad\xa8\xcb\x9c\xcb\xc0\xfe\xb4\x3b\xca\xca\xc7\xa0\x0e\x21\x5d\xaf\x51\xa2\xe6\xb2\xca\x52\x52\xb2\x7f\x3b\xe5\xc3\xbe\xcd\x45\x38\x42\xe8\x52\x85\x4f\xa9\x1f\x6b\x07\xa7\x05\xb7\xa0\x62\x9b\x24\x06\xd9\x87\x82\x97\xb0\xd8\xce\x59\x22\x45\xda\xb7\x87\x64\x69\xfc\x5a\x57\x80\xb8\x10\x4b\x49\x5a\xe1\x05\x50\x8e\x49\x33\x9e\x72\xbd\xf0\xf9\x1c\xb8\xec\x8d\xda\x8a\xbd\x83\x2d\x23\xa8\x7a\x22\x08\x2d\x8a\x52\xd2\x64\xce\x54\xf0\x34\x54\x42\x2d\x50\x86\xaf\xf2\xcc\xaa\x19\x17\xa8\x87\xc2\x3d\x46\x59\xc9\x16\xa4\x94\xda\xa5\xa6\xdd\xf0\xc0\x8b\x60\x30\xb8\x1d\x35\x0e\x5d\x2e\x20\x7f\x4d\x86\x43\xe0\x5b\xf1\x69\xf8\x87\x22\x32\x4b\x1d\x34\xeb\x37\xcf\x8d\xe2\x9f\x58\x2e\x36\x9b\x00\x80\x66\x6a\x49\x32\xa3\x3c\x99\x8d\xe1\xe6\x9b\xbf\xfa\x13\x99\xcb\xaa\x54\xe3\x10\xec\xef\x05\x9c\x43\x0f\x87\x33\x1c\x34\xc9\x18\x55\x9a\xbc\x78\x4e\x72\x2e\x2a\xb3\xe3\xf7\xc4\x78\x7d\xe9\xba\x81\x96\xfb\x97\x3f\x75\x1c\xad\x1f\xfd\xf6\x46\xcd\xb6\xc0\x8e\x79\x56\xbd\xb5\x6b\x1c\x01\x3d\xb0\x6b\x66\x43\xd9\xb5\x5b\x52\x38\x8b\x42\xcb\x35\xaf\xfc\xdf\x2a\x39\x59\xe8\xee\x10\x36\x76\x9c\x18\xbb\xe6\xbf\xed\xc9\xbb\x40\xc5\xd6\x48\xb1\x2d\x5e\x65\xed\x3d\xbe\x67\x5c\xe9\x56\x1d\xbe\x6b\xcc\x9b\x16\x37\x77\xdd\xcc\x67\xc6\x3e\xee\xa5\x92\x1e\x46\x72\x16\x9d\xf3\x48\x27\x09\x53\x20\x8a\x1c\x28\x1c\x38\x77\xf1\xda\x96\x0f\xdd\x50\xb4\x99\x55\x20\x32\x8e\xf9\x7b\xe8\x55\xda\x89\x58\x5d\x54\x7e\xc7\xd8\x3d\x51\x0b\x07\x8b\x65\x84\xe2\x62\x86\xad\x45\xf3\x2a\xd3\xbc\xc8\x6a\xca\x9d\xb9\x1b\xec\x06\x1c\x46\x0b\x68\xe0\x9e\xa6\x08\x7a\x85\xe8\xe7\x10\x59\xd9\xf3\x63\x31\xa1\xb1\x43\x66\x69\xf6\xf1\x82\x96\xd4\x93\x3f\x91\x79\x4e\xd5\xc0\x06\x1e\x28\x64\xc1\xd8\x36\x40\xe6\x2e\x9a\xd5\x6f\x1c\x64\x1d\xac\x8b\x71\x35\x13\x54\xb4\x0e\xff\xc5\x80\xf3\x30\x14\x91\xd7\x3e\xd1\x1e\x9b\xdc\x37\x38\xd6\x2a\xc4\xdf\xd3\xe4\x92\x89\x94\xbc\x53\x8e\x70\xe9\x42\xd0\xdc\xe2\xc7\x17\xa5\xc4\x2e\xea\x2c\x6d\xdc\xaf\x86\xd6\xed\x88\xd0\x27\x0e\xc0\x0a\xf5\xad\x75\x51\xb1\x52\x3d\x81\x07\x9b\x81\x3e\x25\xef\x14\xba\x74\x4b\x7e\x95\x30\xa7\x3b\x9a\xfb\xd6\xf5\xf1\x57\xad\xd1\xea\xc8\x6a\xe8\x28\xdb\xc6\x14\x57\x21\x6c\xe9\x3e\x72\x09\x30\xf1\x34\x33\x22\x6e\xe1\x31\x7f\x1a\x0c\x36\x59\x80\xdf\x6b\x2d\xc8\x63\xe5\xa4\x3b\xa6\xd4\x6e\x39\x49\x63\x61\x76\x46\x53\xa9\xc8\xf7\x99\x4c\x2e\xc9\x21\x03\xa3\xe1\x21\x9b\xef\x97\x93\xf4\x71\x37\xce\xcc\xe9\xac\x5d\xc6\xc8\x88\xe4\x52\x70\x2d\xcb\x36\xf2\x78\x83\x80\x02\xb7\xad\x0c\xef\x82\x98\x6e\xd6\xd9\x53\x69\x64\x68\x58\xbe\x1f\xd6\x81\xa1\xbc\xeb\x04\x24\x0f\x9e\x02\xa1\xda\x5a\x8e\xfc\x61\x2e\xaf\x47\x5a\x8e\x2a\xc5\x46\xbc\x75\x22\x54\x67\x42\x5d\xb2\x05\x64\x95\xf5\x42\x2a\x3b\x58\x64\xb9\x6b\x09\x7e\x76\x38\x6f\xf4\xbb\xb3\xef\x0f\xdf\x29\x56\x8e\x43\x6b\xe5\x19\xd3\xc9\xb3\x84\x15\xf3\x67\x76\x84\x47\x4f\x56\x27\x36\xfb\xa1\xab\x1b\x0d\x15\x81\x44\x66\x99\x05\x18\x93\x53\x72\xc0\x8a\xb9\x7f\xdc\x66\xd0\xed\x31\xf7\x94\x2b\xa4\xec\xa7\xdd\xd4\xae\x19\x29\x16\x1b\x70\x06\xa5\x46\xc0\xfc\xe5\xe4\x7e\x8d\xbc\x37\x91\xdd\x3f\x63\x77\x96\x36\xad\xf8\x36\x82\xbc\x9b\xd3\xd2\x6f\x37\xea\xe9\x17\xd6\x0f\xc5\x0d\xfb\x5c\x76\x6a\x24\xb6\x8f\xa7\x68\x8c\xa6\x2c\x25\xf2\x8a\x95\x25\x4f\x99\x22\x5e\x6e\x87\x3e\x28\x9e\x6d\x06\xe5\xb7\xbd\x03\x1f\x57\xc2\xc1\xe6\xb8\x1f\x76\xc1\xff\x10\x09\x71\x38\xb3\x24\xc4\x69\x9a\x73\xb1\x19\xdc\xde\x92\x6e\x2a\xa1\x19\x3b\x7e\xdb\xd9\x5a\xb7\xe3\xc4\x06\xfb\xb9\x3d\x19\xf4\x14\xf8\x04\xce\xfe\x8f\x9e\x77\x89\x90\x69\xbb\x00\xda\x9a\xcd\xee\x19\xd5\xec\xba\xa5\x22\x34\xaa\x45\x7e\xdb\xfb\xc1\x3c\x7b\xdc\x66\xfb\x46\x74\x0a\x09\x56\x39\x42\xfe\xaf\x4b\xc9\xb2\xfc\xd4\x4f\x20\x09\xc7\x0a\x9b\xb2\x35\x5b\xb1\xb9\x35\xbb\x7f\x7a\x4c\x7e\xc0\xcb\xd7\xd7\x05\xa5\x94\x1a\x4d\x9e\x43\x99\x53\xde\x4f\x03\xf4\xe6\xa0\xcd\x7e\x58\x21\x11\x4e\xfd\xb5\xc4\x5e\x6c\x94\xa2\x1a\x6e\xb8\x2a\x59\x4a\xac\x3f\xe5\x89\xb5\x78\x58\x52\xa7\x9f\x46\x8b\x87\x87\xea\x92\x1d\xb8\xe6\x5d\xfd\x4e\xad\x45\x3b\x76\x02\x25\xc2\xe7\x3a\x11\xc5\x84\xe2\x90\xde\x10\x64\xe0\x81\xaa\x0d\x69\xe9\xbe\x58\x07\xd5\xee\x21\x79\x2d\x67\x5c\x38\x29\x26\x6d\x56\xcd\x94\xf2\xac\x1b\x39\xb7\x7a\xf2\xef\x4c\x4f\x56\x2a\x3b\x12\x74\x92\xb5\x4f\x99\x8c\x17\x81\x1f\x8e\xbc\xca\xe8\x8c\x30\xf8\xe3\x59\xca\x95\xf9\x2f\x39\x3f\x7f\x0d\xc1\xe0\x4a\x38\xfb\x12\xc2\x9c\x76\x6f\xf1\xa5\xd1\x28\x64\xd6\x27\x17\x50\x88\xf7\xd6\xc1\x23\x18\x8f\x70\x91\x9a\x4f\x67\x2a\x4a\x4a\xb6\x57\x60\xaf\x14\x5f\x77\x87\xa9\x8f\x13\x46\x2e\xe6\x3c\xb9\x3c\x0d\xe2\xbf\xb2\x34\xe7\x44\x70\x2a\x52\x52\x9a\xbf\xad\x6b\x37\xb2\x9f\x75\xda\x97\x43\x2d\x18\xcf\xed\xd4\x4e\x9c\x9e\x5b\x0a\xc2\x6f\x54\x29\x99\xf0\x3a\xff\x00\x3c\xd1\xf5\xf6\x9d\xc2\xf6\xbd\x3e\xaa\x80\xc2\xd9\x0f\x41\x50\xcf\x5d\xa1\xb5\x38\x8e\xb2\x57\x50\x15\x6a\x29\x5c\x38\xba\xad\x8d\x08\xc8\xe3\xbd\xb5\x34\xad\x87\x5b\x6e\x69\xea\xcc\xcc\x46\x88\xdc\x15\xbc\x5a\x06\x72\x26\x83\xed\xa1\xbd\xcc\x42\xbe\xb5\xa9\x6d\x66\xb2\x16\xd2\xb5\x2f\x4d\x5f\xe5\xfe\x6b\xe4\x07\xe1\x39\x1b\x34\x07\xd9\x53\xc8\xa2\xca\x30\xb3\xb6\x7b\x67\x57\x17\x63\xc4\xe7\xac\x21\x88\xbe\x69\x9d\x9d\x76\xc3\xf2\xbc\xfb\xd7\x2b\x3e\x8d\xfe\x4e\x81\x69\xf1\xfc\x2f\x7f\xfa\xd3\x63\xef\xf8\xd4\xcd\x71\xb7\xee\x96\x4f\x9d\x42\x6f\x2b\xb0\x19\x8e\xb7\xd8\x0c\x5b\x6c\x86\xf8\x58\x7b\x7c\xf8\xf3\xa3\x2f\xf4\x52\xdd\xd6\x47\x65\x5b\x57\x7c\x85\x8e\x55\x71\xfd\x54\xc4\x75\x46\x50\xf8\x1c\xb8\x09\x3d\xd5\x88\x75\xc7\x48\xd8\x22\x23\xfc\xbe\x90\x11\xfa\xab\x11\xeb\x0b\x05\xa1\x7b\x6d\xd8\xef\x07\xf1\xa0\xb3\xd8\xe8\x5a\x57\xdf\xb9\x9a\xbe\xaf\xa6\x1f\x7d\x79\xf7\x7b\xf3\x30\xec\xd6\xe3\xad\xf4\xb7\x38\x88\x37\x87\xa6\xbf\xbb\xab\x02\xb0\x7c\x2d\x8d\x74\x59\xa3\xe9\x4c\x3a\x7b\x1e\xf0\x55\x64\xab\xbd\x7b\x95\x17\xef\xed\x79\x23\x41\xc0\x9f\xde\xfc\xbc\x80\x6d\x80\xbc\x5b\x9a\xfa\xd3\x0a\x8f\x3e\xd1\x0e\xf8\x0f\x15\x1e\x55\x11\x6a\xae\xf3\x3a\x82\x80\x04\x15\x4e\x4e\xc2\xce\x34\xb5\x58\xd8\x3f\x3d\x26\x49\xc9\x00\xda\x81\x66\x6a\x4c\x56\x68\x78\x2e\x80\x64\x35\x42\xa7\xd9\x51\xad\x59\x5e\xe8\xae\x9c\xb7\x8d\x8e\xfe\xce\xa2\xa3\x0f\x1e\xa5\x98\x57\x39\x15\x23\x23\x2d\x20\x3e\x1a\xe5\x9d\x34\xf6\xc3\x31\xb1\x72\x01\xd5\x0a\xf0\x85\x42\x49\x73\x25\xf8\x6f\x15\xab\xdd\x15\x5e\xeb\xd8\x80\xe0\x0e\xbc\x47\xcf\xb4\x43\x8d\xaa\x21\x45\x12\xb9\x54\xc4\x65\x09\xe2\xe9\xe8\x04\x46\xa0\x96\x45\xae\x37\x3d\x67\xa8\xbd\x9d\x02\x48\x42\x7d\x55\x6c\x1f\xa2\x81\x48\xb3\x4c\x5e\xe3\xb3\x43\x7d\xc4\xcc\x9f\x79\x17\x8b\x4b\x32\x61\x24\xe7\x65\x29\x4b\x1b\x46\x0a\x5f\x07\xd3\x87\x8c\x9d\xc9\x4a\x34\xd8\x4a\x9b\xf4\x71\xce\xb4\x9d\x6a\x60\x15\x2d\x09\x15\x58\xc0\x69\xfe\xed\x32\xae\xe1\xd9\x4e\xde\x4d\xd8\x9c\x5e\x71\x59\x95\x78\xb7\x96\x64\xc7\xfe\x04\x7b\xef\x42\x56\xde\x77\x5e\x41\x85\x96\xff\x3a\xb5\x82\x4e\x27\xf5\x8f\x60\xe0\xa6\xd2\xb9\x23\x47\xec\x03\x57\x7a\xf9\x5b\x1c\x89\x5c\xcb\x89\x75\x70\xde\x95\x2a\xcc\x06\xfb\x53\xeb\xda\xdb\x98\xdf\xc2\xd1\x62\x4d\xf5\xea\x1c\x7e\xfa\x94\x9e\x6a\x11\x6b\xb0\x64\xde\x95\xc3\x3d\xbe\x1c\x56\xfc\xca\x96\xbd\xae\x36\x52\x51\xde\x2a\xc9\xb7\x1e\x3e\xcb\x22\xe3\xc9\xe2\xf8\xb0\xdf\xcc\x0d\x1c\xd3\x6d\x7f\xca\x67\x6d\x98\xf3\xe4\x7b\xaa\x58\x4a\xde\x50\x41\x67\xe8\x75\xd9\x3b\x3f\xfd\xfe\xcd\xc0\x70\x11\x78\x75\x8e\x0f\x57\xa6\x76\x9c\x87\x83\x9f\xac\xab\xce\x9d\x34\x49\xd7\x9b\xda\xb0\x34\x6a\x4b\xf2\xad\x0d\x02\x80\x78\x9d\xa0\x4b\xfb\xb4\x15\xea\xc0\x69\x13\x24\x0a\xd3\x37\x1c\xfa\x9b\x6a\x8a\xea\xab\x3c\xbd\x7c\x48\x02\x04\x7e\xf3\xdb\xbe\xf2\x6e\x31\xb0\x3b\xc4\xb9\xe2\x6e\x24\xba\xa4\x9a\xcd\x16\x87\xac\xc8\xe4\xc2\x30\xc0\x69\xe0\xc6\xc7\x4b\x27\xa8\x36\x94\x13\x9a\x90\xb2\xca\x18\xf6\x16\x6a\xc2\xae\x09\xc6\xd2\x5a\xd2\x71\xa1\x34\x05\xd0\x35\x1c\xff\xd6\x37\xba\xf3\x66\x75\xd7\x6d\x69\x84\xef\xf9\xc9\xab\x62\x88\x4a\xb3\x4a\x6e\xbd\xe5\xee\x1b\x13\x3c\xfe\xd3\x3c\x7b\x9f\xb8\xe6\x9d\x23\x98\x71\x77\x40\x58\xe5\x67\x55\x66\x36\x9f\x2c\x6d\xb4\x78\x05\x3d\xcd\xce\x31\xa2\x5d\x80\x4c\x30\x6f\x3f\x24\x93\xca\x28\x71\x4c\x45\x3e\xee\x65\xa8\xcf\xeb\x39\x86\xb4\xcd\x4d\x84\x16\x45\xc6\x31\x85\x59\x96\x36\x2e\x1d\x38\x34\x97\x2f\xbb\x8b\x68\xb9\xa7\x2e\x73\x3f\xdd\x65\x44\xae\x58\x39\xb9\x0b\x4e\xc5\x7d\xd5\x12\x5a\x70\x88\xe3\xdc\x59\x8b\x89\x26\x6e\xff\xf4\x18\xef\x5e\xe5\x38\x76\x3f\xe2\x0c\xda\xb9\x71\xe1\x0d\xdb\x33\x08\x2d\x17\x8f\xb4\xb4\x7f\x7a\x8c\xd0\x5e\x16\x6c\xa9\x76\x7f\x18\x3b\x81\x62\x92\x63\x8d\xf0\x48\x67\x66\x44\x4d\xa4\xf0\x0f\x65\xa2\xca\x19\x02\x34\xd5\xcd\xc6\x8c\xf1\x28\x16\xf5\xe8\xb5\xf7\xc4\xd8\x3a\x77\x57\x48\xee\x1f\xe1\xbf\x67\x44\xff\xde\x7b\x91\x90\xe2\xcc\x7e\xe6\xbb\xb3\xd7\xed\x26\xf1\x24\x1e\xc3\x02\xf2\x30\xc0\x1e\x2c\x68\xa9\x39\xcd\x48\x55\x66\x2e\x24\x88\xf9\xfd\x36\x8d\x6e\x4e\xaf\x02\xd0\xa2\x31\x21\x5f\xe0\xcc\x59\xc2\xe2\xfa\xc4\xe6\xbb\xd6\x8d\x5b\x65\xd9\x90\x4c\x39\xb4\x5b\xd7\xac\x20\x61\x48\xea\x9c\x8b\xc4\x98\x72\x62\xe4\xbb\xe9\xc0\x1b\x39\x03\xcf\x2f\x52\x88\x78\x82\xbe\xcb\xb2\x14\x80\x2c\xe1\x11\x66\xc1\x26\xe0\x6e\x30\x16\xe8\x41\x56\x29\xcd\xca\x33\x69\x36\x83\x20\xe5\x06\x40\x3d\x68\xf8\xf3\xf7\x5c\xa4\x90\x63\x75\x06\x1b\x47\x42\x05\x61\x1c\x1c\x39\x66\x48\x88\x9d\x1b\xde\xa9\x19\x6a\x4f\x55\xc9\xdc\x7c\xd2\x4e\x21\x53\xb5\x63\xc4\xc8\x0e\xba\xfb\xd4\xce\xc0\xfc\xd5\xfc\x06\xcc\xa0\x09\xee\x7b\x46\x0b\xbe\x33\x18\x12\x20\x10\x04\xef\xa4\x9e\x3f\x5e\x3e\x74\xdf\x0a\xf6\x75\x2b\x2e\x3c\x0b\x47\x00\x1e\x14\x75\x98\xee\x7a\xce\x35\xf3\xad\xd1\xd1\x4b\xe4\x51\x6a\x9a\xc2\x9a\x90\x7d\x41\x58\x5e\x68\xf0\x3c\x93\x9c\x51\x17\xce\x66\x57\xac\x5c\x18\xfb\x1e\x50\x3c\x1e\xfd\xe2\xf7\xfc\xd8\x89\xe0\x8d\xbe\xf3\x35\x93\xc3\x0a\x5b\x22\xee\xee\x17\xbb\x91\xcf\x20\xcb\x02\x69\xfe\x68\x49\x09\xdb\x6b\x2b\x32\xfe\x64\xee\x8c\x49\x88\xa7\x50\x5a\x7a\xf9\xf1\xfa\xb5\x0d\x8a\x20\xad\x7e\xe4\x22\x55\xbe\x13\xa2\xcd\xd9\xb6\xf4\x5e\x49\x64\x78\xc3\xc7\x48\xe0\x65\xf5\xf5\xae\x2a\xe7\x2d\xc3\x3b\x8d\xfd\xa6\xa1\x6e\x1d\xc0\xaa\xfd\x6f\x64\xba\x7a\xe9\x44\xf3\x7b\x1c\x5c\xec\x13\x05\x6a\x9f\x89\x1d\xcb\xaa\xaa\x8b\x62\xa5\x3e\x7f\xfb\x74\xdc\x42\xfa\x9b\xde\xa4\x76\x16\x80\x9c\x0c\x7e\x01\x4f\x10\x62\x94\x93\x69\x46\x67\x35\x1b\x81\xd4\x43\x25\xe9\xe0\xfc\x27\xf7\x09\x8a\xf0\xd5\xea\xea\x27\xf5\xd9\x4f\x69\xb0\xa3\x9a\x4a\x37\x5e\x61\x1e\xb2\xf2\xc7\x4f\xab\xb1\x7e\xf0\x9b\xb9\xe9\x2e\x81\x42\x7d\xab\x13\xee\x26\xfa\x3b\x7f\x1b\x0d\x38\xc1\x81\xad\x39\xa3\x12\x72\x9f\x40\x0f\x39\xff\x29\x62\x93\x4f\xbc\xef\x0d\x4c\x7b\xc9\x16\xd7\xb2\x5c\x8d\xa3\xde\x9a\xbf\x6e\x7d\x62\x46\x27\x2c\xfb\xf4\x02\x79\x43\x0b\xf3\xd9\x75\xa2\x29\x5a\xde\x36\x4e\x89\xba\x3f\xe6\x84\xb9\x3c\x3c\x59\xce\xa8\xe0\xff\xc1\xec\xdc\xc4\xac\x63\x59\x9a\x3f\xf7\x30\xd6\x81\x76\x7b\xc6\x12\x3d\xb0\xfc\xb7\x52\xee\x7d\x82\x41\x69\x9a\x72\xd4\x1e\x4e\x3f\xc1\x4b\xb7\x13\x81\x8b\xcb\x87\xa0\xf9\x2d\x0b\xeb\xd3\xbc\x7f\x7b\xb0\xf4\x0e\xb2\xb9\x2a\x6f\xc9\xa3\xba\xf5\xfe\x9c\x72\xdb\x55\x77\xe3\xa8\xc2\x72\xca\xdb\x7e\x16\x1e\x1d\xe8\x9a\x53\x5d\x95\x5c\xaf\xdc\x90\x6e\xbf\x91\x8b\x1f\xab\x09\xb3\xf1\xe1\x7b\xdf\x2e\x20\x4d\x70\xff\xf4\xb8\xdf\xe9\x88\x56\x38\x58\xf1\xf6\x05\x8d\xde\x42\x2a\x41\xf3\x09\x9f\x55\xb2\x52\xd9\x22\x74\x4a\x52\x08\x6f\x1b\xa3\x1e\xbd\x32\xff\x1f\x7b\x57\xf3\xdb\xb8\x8d\xc5\xef\xfd\x2b\x08\x5f\x32\x13\xc4\x1e\x2c\xda\xd9\xc3\xdc\x82\x24\xc5\x06\x9b\x8f\x81\x9d\xb6\x97\x1e\xca\x48\xb4\x2d\x44\x22\xbd\xa4\x64\xc7\x2d\xfa\xbf\x2f\xf8\xf8\x48\x89\xb6\x44\x51\xb1\x93\xa6\xc5\xf8\x92\x19\x89\x7c\xe2\xe7\xe3\xfb\xfa\x3d\xf2\x93\x92\x50\x2e\xf8\xb6\xc0\xa2\x3c\xc9\xab\x94\x79\x14\xc1\x0b\xb8\x16\x59\x4a\x68\x55\x8a\x82\x96\x59\x42\x12\xc1\x64\x02\x1e\xc3\x26\xa5\x4a\x31\x42\x3b\xea\x26\x95\x2a\x45\x41\x0a\x2a\xd5\x92\xe6\x79\xd7\x1c\x1f\xe1\x54\x0b\xa5\x1e\x1f\x43\xff\x3b\x5f\xae\x4d\xab\x5f\xb8\xbe\x7b\x32\xad\x47\xac\x6f\xdd\xb8\x83\x08\xac\xbb\x57\x69\x04\x0d\xc4\xf8\xb7\x66\x2f\xea\x99\x98\xbe\xd1\x09\xed\xdc\xde\x7e\x05\xb8\x61\xb0\x2e\x04\xe9\xb2\xf4\xba\xa0\x8b\x08\x41\xf2\x46\x6b\x07\x94\x6f\x6d\x35\x93\x68\x53\x9d\x11\x21\x31\x6a\xc4\xdd\x8b\x8e\xaf\x5c\xb2\x56\x49\xee\xc1\x1d\x27\x24\x86\x6f\xe3\x2a\x85\xa0\x7e\x26\xe7\x42\x16\x5a\xae\xcb\x24\x99\x57\x1c\x8c\x64\x0a\xa3\xbd\x41\x25\x41\x5b\x0d\xcd\x95\x70\x3b\x10\xfc\x7b\xdc\x36\x82\x50\x45\x36\x2c\xcf\x27\xe4\x3c\xcf\x31\x03\x68\x23\xd7\x43\x8d\xd7\xae\x63\x0a\x1e\xb7\x24\xcd\x16\x4c\x95\xe4\xc3\xec\x3f\xe7\x1f\xe1\xd4\x06\x3b\xc6\x96\x94\xd4\xc2\xd5\x7c\xfb\x0c\x9c\xff\x69\x05\x72\x42\x42\x4b\x9a\x8b\x85\x71\xab\x83\x9d\x96\xa7\x64\x95\xd3\x2d\xa4\xf7\x5f\x51\x09\x11\xa7\x89\xb1\xd1\x10\x59\x71\x48\x6c\xfc\xa6\x27\x4e\x3f\x2b\x08\xe5\x1e\x1e\xc3\x9a\x7c\xe1\x56\xef\xc9\xf0\xfa\xba\x47\x99\x64\xab\x9c\x76\x58\x15\xbc\x15\xfd\xe0\x81\x91\xb5\x98\x0b\x2a\xac\xe0\xcc\xd1\x98\x90\x99\x59\x3b\x05\x2d\x13\xe3\xd3\xfc\xad\x60\x25\x4d\x69\x49\x27\x5a\x17\xfc\xcd\x47\xc6\x89\x3c\xd5\x84\xba\x27\xba\xa3\xcd\x46\x5e\x6c\xbf\x10\xdf\xdf\x85\x5a\xa8\x75\xc5\x41\x3e\xb7\xfb\x31\x68\xc6\x38\x90\x3f\x41\xf7\xaf\x9e\xb5\x2a\x16\xf4\xa1\x79\x6d\xdd\xad\xe4\x5b\x19\x72\xbf\x27\xb8\x5a\x0b\x06\x69\x22\x1f\xf0\x26\x24\xfb\x04\x4c\xa8\xe7\x77\x97\xdd\xe6\xae\x7e\x93\x41\x8f\x89\xc0\x77\x0c\x04\x9a\x67\x0d\xcc\xf8\xc6\xf7\x0e\x58\x38\x0c\x00\x08\x0d\xb8\x84\xda\x6c\x30\xb6\xb0\x99\x30\x1f\xfa\x68\xea\x75\xdb\x47\xa2\xdc\x33\x31\x4e\x99\x3e\xa4\xd9\xd8\x35\xb6\xb3\x50\x9c\x8f\xa6\x17\x0d\xd6\x85\xf6\x32\x23\x0f\xe0\x10\x6b\x22\x75\x83\x1d\xeb\xd3\x8a\xb4\xef\xd8\xae\x0e\x68\xa8\x9b\x4a\x2f\xf0\xe8\x89\x6d\x4f\x14\xa2\x5e\x04\x57\xcb\x6c\x65\xe0\x8a\xe8\x86\xc0\xd9\x25\x3f\xd3\x3c\x4b\x1d\x09\xb3\xaa\xaf\xf9\x19\xb9\x13\xa5\xfe\x73\xf5\x9c\xa9\xd2\xa8\x9f\x97\x82\xa9\x3b\x51\xc2\x93\xa3\x74\xd5\x34\x61\x40\x47\x51\x01\x36\x96\x6c\xd8\x57\x0d\x35\xd9\x76\xe8\x1a\xd9\x9e\x1d\x94\x4c\x91\x6b\xae\x25\x02\xec\x91\x83\xf1\x2a\x24\x61\x31\x28\x5c\xf0\x31\xd8\xb8\x5b\x69\xe0\x40\x08\xe9\x8d\x43\x80\x1c\x92\x32\x01\x80\xf0\x26\x53\x96\x89\xbb\x33\x9b\x5a\xb3\x5b\x96\x90\x82\xc9\x05\x78\x6d\x92\x1e\xaf\x45\xac\x29\x32\xca\x00\xd9\x3b\x57\xc0\x32\x6f\x3a\x0d\x17\x7b\x93\xd4\x28\x6f\xd8\x52\x61\xac\x19\x7f\x68\xee\x03\x23\xf5\x27\x60\xb9\xd5\x84\x9c\xdb\x6b\x66\x9a\xef\xd0\x7b\xd5\x24\xa3\x29\x64\x8a\x68\x56\xb2\xa6\x39\x33\x59\xf6\x29\x77\x78\x2b\x31\xdf\x63\xec\x67\x88\xe9\xd6\x7b\xd6\x89\x4c\xa3\x27\xb6\x1d\x9d\xed\x4d\xed\xe8\x9a\x8f\x6a\xd0\x9d\x37\x99\x8e\x89\x82\xb4\x35\x82\x77\xa3\x97\x9f\x05\x41\x66\x19\x6f\x5e\xe9\x9d\x37\xf5\x94\xb5\xbb\x9f\x5b\x85\x8d\x0f\xea\xa3\x1e\x42\x70\xf9\x4a\x52\x08\x09\xe6\x4c\xfd\xb4\x99\xde\x43\x8b\xaa\x4f\xd9\x6a\x55\x67\x43\xa9\x56\x0b\x49\x53\x46\x16\x92\xae\x96\x43\xc5\x12\x23\xdb\xb4\x91\xff\xdb\x08\xba\x1d\x83\x1f\xd0\xe8\x82\xf5\x36\xec\x71\x29\xc4\x13\x40\xe1\x60\x21\xbc\xa2\xfd\xe1\x17\xf3\xad\xcb\xfa\x99\x55\x25\x15\x49\x59\x49\xb3\x1c\x62\x39\xee\x6f\x6e\x31\xda\xc3\x9e\xe3\xb6\x95\xed\x81\x13\x47\x50\x00\x68\x8a\x51\x48\x53\xb6\xce\xd8\x06\xad\x12\x5d\x71\x1a\x63\xb2\x60\x1c\x82\x13\x02\x41\x3c\x63\xa2\xb2\x94\x5d\x01\xf0\xb6\x9b\xd0\x01\x86\xf3\x8e\x36\xf7\x6d\xde\x30\x07\xef\xe5\xde\x11\xa7\xac\x53\x7f\xbf\x0a\x19\x48\x04\x14\x87\x03\x8e\xc3\xf8\x62\x24\xf9\x17\xf2\xc3\x0f\xdf\x77\x16\x2a\xe8\x73\x56\x54\xc5\x17\xf2\xef\xcf\x9f\xbf\xff\xdc\x5d\x2c\xe3\xa6\xd8\xbf\xba\xfb\x87\xbb\xed\x62\x7a\xf9\x0e\xc6\x3b\x75\xd1\x74\x61\xa7\x5c\x04\xa9\x39\xcd\xf2\x4a\x62\x1c\x67\xa4\x8a\xf0\x63\xb3\x0e\x38\x54\x6a\xe0\x03\xb5\x14\x6d\xb0\x17\x06\x81\xcd\x33\xce\x14\x5c\xe0\x52\x71\xc9\x12\xb1\xe0\xd9\xef\x2c\xb5\xf7\xb7\x40\x60\x07\x64\x7a\xb7\x4b\x9c\x30\x9e\x9a\x7b\x34\xf5\x99\xb7\xa4\x3c\xcd\x43\x0e\xff\x88\x9e\x36\x77\xf0\x41\x43\x06\x27\xcf\xa0\x01\xbb\xad\x6b\xec\x0c\x17\xdc\x06\x8a\xee\x27\x73\xa2\x99\x61\x3b\xa8\xa7\x86\x31\xce\x02\x8a\x75\x4b\x1b\xf7\xf4\x3e\xa3\xb2\xc2\xb3\xff\x55\x4c\x6e\x01\xe4\x51\x0b\xf6\x8d\x40\xb0\x87\x3a\x87\x80\xed\x06\x4a\x54\x26\x89\xcb\x8e\x2e\x5c\x0b\x31\x75\xb8\xc7\xce\xb7\xa1\x0e\x33\xee\x73\xeb\x48\x22\xe7\x84\x57\x79\xde\x55\x94\x8b\x90\xcb\xa9\x39\x76\x3d\xaa\x64\x9c\x8e\x17\x6b\x16\x68\x19\xe9\x37\x35\x0e\x34\x3b\x7e\x24\x51\xfe\x7d\x9b\x0b\x9a\x1d\x8e\x8a\xe9\x8c\x8f\xe7\x8c\x4b\x55\x13\x61\x46\x30\xbf\x21\x01\x9f\x91\x09\x66\x5e\xd3\xb0\x60\x7e\x83\xe2\x73\xe2\x8c\x0c\x2d\x4d\x7f\x77\xa6\x86\x17\x74\x3e\xc6\xec\xd0\xd2\xf5\x6f\xc6\x87\xbd\x01\x8f\x8d\x86\x1a\x10\x09\x15\x39\x93\x11\x46\x09\xf3\xfb\x66\x9a\x18\x74\x12\x45\x30\xe6\x61\x66\x8a\xe8\x59\x95\x2c\xe3\x6b\x61\x12\x3d\x0f\x92\xe1\xa6\x7b\x15\x77\x44\xb9\x0d\x70\x56\x94\xe5\x9c\xf0\xdb\x14\x69\xb5\x42\x4b\x2a\xd5\x6f\xec\x0e\xf7\x20\x8c\xfd\x38\x8a\x0e\xe2\xf7\xbc\xca\xd9\x2f\x59\xb9\xbc\xb7\x89\xdd\x71\x55\x97\xd5\x2a\x87\xce\x36\x5e\xe8\x25\x34\xad\x25\xc3\x6b\x73\x95\x18\x4b\x44\x51\x30\x9e\x9a\x20\xa2\x82\x3e\x31\x52\x5f\x57\xa9\x65\x3c\x10\x83\x81\x1c\x7b\x5e\x51\x5e\xcb\x89\x6b\xcd\xcb\x43\x2b\x2a\x72\x3d\xc5\x9e\xb5\xd1\xa0\x8a\x30\x98\xa2\x81\x86\xf0\x40\x13\xe4\x91\xe5\x02\x60\xd8\x26\x52\xd4\xc4\x32\x63\x51\x60\xc9\xf8\x14\x4f\x3d\x4c\xfa\xc8\xf8\xa2\xce\x25\xa5\x72\xb8\x58\x16\x39\xb0\xe0\x6c\x42\xa6\x28\xc2\xc4\x49\x45\x31\xec\x34\x92\x95\x46\x1f\x88\x75\x1e\x85\xc1\x23\x6b\xeb\x35\xc7\x76\x6d\x9f\xc5\x8c\xae\x2d\xfc\x4f\x1e\x5f\x77\xe9\xc2\xb0\xe1\xf5\xb7\x74\x7d\x2a\xb8\xb1\xdd\x61\x5e\x89\xb9\xb6\x18\x4c\x75\x63\x72\x31\xbd\x3a\x7f\xb8\x3a\x23\x3f\x7d\xbd\x84\xbf\x97\x57\x37\x57\xfa\xef\xc5\xfd\xdd\xdd\xd5\xc5\x83\x96\x23\x4e\x4d\xfa\x78\xad\xc6\xe9\xd1\xd5\xe7\x91\xf0\xb9\x05\xe5\x5b\x32\xaf\x4a\xcd\x0e\xea\x8f\x79\xad\xa0\xc6\x06\x40\xd3\x54\xab\x8c\x7f\xbb\x39\x6c\x1f\xf0\x5d\xb3\x49\xf3\xde\x0c\x93\x71\x1f\xc1\x52\xfd\x62\x52\xf4\x22\x89\x46\x1d\x78\x4d\x1e\xbd\x10\x6e\xf0\x2b\x27\x3f\x0a\x49\xf0\xa2\x31\xb8\x79\x32\x55\x27\x08\xea\xd0\xff\x9e\x98\x47\x9f\x72\xb1\x38\x71\x58\x0f\x46\x72\xb1\x20\xaa\x7a\x74\x18\x1c\x38\x4d\xa1\xf4\xa9\x2d\xe6\x41\x17\xce\x1c\x10\xa7\x51\xcb\x11\xf7\xea\x34\x0b\x34\xe9\x7e\x82\xdb\xc1\xbc\x92\xfa\xc1\x2e\xc1\xd3\x4f\xed\x2d\xb0\x82\x53\x26\x77\x6a\xfc\xca\xf5\x72\xdd\x64\x79\x9a\x50\x99\xee\xad\x59\x38\xdc\xcc\x94\xc3\xe8\x99\x94\xb9\xe6\x26\xe7\x9a\x38\x26\xba\x10\x6b\x26\x73\xba\x32\x11\xe2\x90\xb3\x18\x42\x8f\xe0\x23\x97\x6c\xc5\x00\x07\x65\x6f\x1a\x67\x3c\xc9\x05\xe4\xd4\x30\x27\xe3\x99\xdf\x75\x13\x8a\x64\x13\x0f\x22\x98\xa6\xde\x21\xa3\x77\xcb\xe6\x20\xcc\x78\xd0\xea\x35\x81\xc9\x9d\x89\x59\x1c\x6e\xc3\x28\x8d\x4e\xf2\x65\x64\x84\x28\xb3\xd1\x19\x19\xb9\xdc\x23\x29\x4a\xc9\xa3\xd3\x51\x5d\xa0\x89\x53\x02\x21\x19\x5d\x42\x63\xf8\x4e\x13\xcd\x08\x13\x6c\x1d\x57\xee\xd3\x75\xfe\x18\x7d\xb4\xa1\x11\x0b\xda\xe0\x13\x9a\x78\x0d\xd9\xfb\x6a\x0d\xb1\xeb\xfd\xa2\x6e\x7e\xa3\x7a\x09\x70\x74\x03\xd5\xc3\xc1\x91\x4c\xcf\x86\x0d\x48\x9b\x79\x8b\xc7\x39\xde\x9a\x09\x6e\x32\x49\x56\x54\x6a\x55\xc4\x96\xf4\xaf\x28\x3b\xed\xbd\xa0\x2c\x62\x11\x34\xfc\x2b\x91\x52\xfb\xcc\xd5\xb8\xc8\xa9\x52\x2d\x96\x57\x60\x04\x9a\x30\x61\x86\x32\xa1\xd6\xf9\x04\xf9\xa7\x97\x74\x1d\x48\x50\x10\xd1\xe8\x92\xca\x05\x2b\xc3\x9e\x11\xca\xb7\xf7\xc1\x94\x66\xe3\xe8\x24\xaa\xe3\xb8\xdd\xf4\x3c\xae\x13\x68\x8d\x33\x5e\x8e\x85\x1c\x9b\x2a\x5f\x48\x29\xab\x2e\x1f\x57\x99\x15\x4c\x54\xe5\x8c\x25\x82\xb7\x23\x1a\xb0\xdc\xd1\x5c\x3d\x03\x60\x1e\xe8\x6d\x3c\xb7\x62\x44\x33\x09\xa1\x55\xcc\x6a\x19\xc3\x7a\x18\xfd\x34\x2a\xf7\x37\xb7\x87\x4c\x36\x01\x18\x73\x78\x26\x7f\x46\xb6\xcf\x17\xae\xa5\xd8\xf2\x60\xb5\xdb\xaa\x1c\x5e\xe9\xc2\x79\xae\xc2\xa5\x71\x30\xc2\xa9\x30\x3a\xfb\xaf\x4a\x5a\x56\x7b\xab\xc1\x9b\x1b\x64\x96\x33\x03\x29\x43\x99\x7e\x06\xf5\x9a\x46\xbe\x7d\xfc\xbf\xc9\x29\x02\xe5\x6c\xb0\xe2\x84\x60\x45\xbd\x3f\x4b\x49\x33\xa3\x40\xd2\xa4\xac\x00\x9b\x4c\x4b\x0c\x6c\xc4\x04\x38\xdf\xb5\x75\xa3\x55\x65\x0c\xa9\x89\x09\x93\xa5\xba\xa1\xaa\xfc\x69\x95\xd2\x0e\xf4\xd2\x4e\xc0\xa2\x2a\x61\xc3\x18\xc1\x7a\xc3\x59\xaa\x39\x3c\x0e\x81\xa1\x47\x36\x9a\xf5\x56\x86\xe2\x50\x4f\x7e\xbd\x81\x74\xf5\xb1\xfe\x54\x7b\xab\xa7\x42\x8f\xc9\x79\x2b\x03\xf2\x43\x35\xfa\x5a\xab\x8f\x13\x09\xd4\x08\x67\xcf\x6d\x1a\xf7\xe1\x2d\xce\x19\xe5\xed\xe1\xf2\x3b\x2b\x0a\xca\x0d\x5f\x43\xf8\x01\xb2\x59\x66\x5a\x64\x35\x28\x2f\x45\xac\x08\x95\xb2\x9c\x75\x80\xbd\x0e\x0c\x25\xc5\x2f\x5c\xe2\x07\xa2\xc2\x9c\xbe\xfa\x75\x9c\x41\x1f\x85\x70\x04\x4f\xd4\xc2\x32\x4a\x0f\x4e\x6b\xda\xed\x15\x88\x2f\x8f\xb9\x48\x9e\x4c\x42\x30\xc0\xf3\x67\xbf\x33\x69\xe3\xce\xeb\xcb\xc0\xf0\x86\xaa\x85\xbd\x7d\xd3\x8e\x9b\xbd\x8e\x08\xa8\x68\xda\x7a\x00\x1d\x7d\x21\x6b\xcb\x62\xc5\x11\x3d\xf7\x36\xa1\xab\x56\x51\x81\x78\x7d\xcf\x73\xb0\xaf\xb3\x98\xdc\x21\x90\xaf\x10\x55\x46\x5a\x20\xba\xe5\xd3\x7f\xbb\x91\x20\x47\x0d\x47\x0d\xe1\x51\x4c\x09\x18\x3e\x9e\x04\x53\xcd\x04\x91\x2b\xb1\x96\xaf\x1e\x84\x0a\x89\x17\xd2\x5d\x93\x63\xa8\x1d\x35\xb8\xf0\xe8\xde\xbe\x4e\x18\x40\xfd\x1b\xe2\xc3\x8b\x4d\x94\x3a\xc8\xcb\xc4\x87\x24\xb4\xf4\x93\x87\x38\xb5\x03\x41\x9e\xc6\x13\x3f\x17\xb2\x53\x81\x39\x5e\xe3\xc3\x78\xa6\x5e\x42\x5a\xfa\xec\x8e\x5d\xdb\x07\xef\x68\xee\xe5\xaa\x9c\x11\x4a\x96\x99\x2a\x85\x44\xd7\x1a\x5c\x26\x26\x29\x5c\x76\xda\x1e\x03\x76\x9c\x68\xb8\x0b\xd7\x04\x42\x57\x2b\x46\xdd\x3d\x43\x78\x36\xc1\x45\x41\x92\x25\x42\xa6\xad\x0d\xb3\xda\x7d\xab\x2c\xd5\xfa\xf9\x23\x60\x33\x73\xaa\xca\x07\xd7\x06\x2d\x20\x44\x72\x63\x5f\xfc\xc1\x2e\xd6\xbd\xb1\xe9\x5c\x04\xaf\x5f\x0a\x42\xb9\xb1\x6a\x1c\x26\x83\xf7\x0b\x19\x75\xdf\x8c\x34\xf7\xa2\x7e\x6d\x9c\xe4\xd6\xe8\xe2\xdb\xb4\xbc\x60\x4a\x05\x81\x46\x3b\x41\x1a\x90\xd3\x97\xb8\x9c\xbe\x58\xdd\x1e\xf6\x46\x40\x30\xe1\x98\x36\xeb\xd6\xb6\x7b\xa9\x11\x10\x13\x8c\x41\xc1\x6d\xab\x83\xa6\x6c\xb5\xa4\x2a\xb6\x33\x6e\x17\xb9\x10\xdf\xe8\xed\x10\xd9\x1a\xc9\xa8\x0a\x41\x25\x77\xc6\xf6\x51\x66\x6c\x4e\x2e\x68\xc1\xf2\x0b\xaa\x8e\x39\xb8\xc0\x01\x26\x84\x4d\x16\x13\x72\x32\x6d\x78\x5b\xef\x44\x79\x1b\xba\x73\xa1\x27\x3b\x40\xcc\x8e\x7e\xd5\xbd\x7c\xb0\x92\xd0\xbf\x73\x0f\xdc\xb3\x07\xb7\x30\xb0\x43\xdf\xc5\xde\x0c\xe3\x7d\xbb\xf6\xa3\xbf\x13\x2b\x09\x16\xbf\xe4\xa5\x3b\xb2\x07\xcc\xd8\xb5\x0b\xdf\xf3\xfe\xeb\xe9\x92\x23\x31\x6b\x35\x99\xec\xf5\xee\xc1\xd3\x5c\xc1\xec\xdf\x0c\xb0\x33\xb7\xfd\x67\x4a\xab\x60\xc7\x14\x5b\xfe\x5a\xb0\x3d\x4e\x60\xe7\xfb\x80\x5c\x3e\x0e\x9f\xc2\x87\x02\xf9\x53\x70\xb4\xe8\x15\xf0\x96\x01\x18\x97\xf6\xab\x68\xeb\x70\x99\x76\xe1\x7f\x73\xbc\xd1\x0c\xcb\x78\xeb\xe3\x03\xdc\x1d\xc7\xd6\xe6\xc2\x46\x00\x7c\x30\xc2\x99\xd2\x9b\xe2\x63\xe0\xf3\x91\x0a\x55\x9c\x32\xd5\xaf\xe8\xf6\x2a\xb1\xa4\x7f\x6a\x6d\xa1\xd0\x04\x9b\x5f\xac\xce\x16\xa1\x13\x0f\x50\xd6\xfa\x35\x9e\x01\xc4\x7a\xc5\xbf\x81\xf4\xda\x0d\xb8\xbb\xbf\x9d\xcc\xbe\xba\xca\x14\x98\xb4\x71\x0c\x27\x9a\x03\x27\x90\xef\xd9\xf0\x6e\x64\x4f\xbe\xfd\x76\xba\xcb\x03\x21\xdc\xd0\x5f\xe1\xc7\xea\x56\x55\x65\xc7\x1b\xf3\xde\x0c\x1a\xd1\xf4\xde\x41\x3a\x90\xde\x05\xf4\xba\x89\x0a\xcc\xaf\x6f\xd5\xfd\xf5\xeb\x2d\x26\x21\x53\x70\x8d\xbd\x52\x66\x16\xc5\xe4\x9a\xa5\x9e\xa7\x0e\xf3\xae\xfb\xcf\x1a\x7e\xdb\x9a\x3e\x0e\x3b\xf9\xe3\xcf\xef\xfe\x1f\x00\x00\xff\xff\x1b\xfd\x79\x5c\xe0\xce\x07\x00") +var _operatorsCoreosCom_clusterserviceversionsYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xfd\x7b\x73\xe3\x36\x96\x30\x8c\xff\x3f\x9f\x02\xe5\xc9\x3e\xb6\x67\x24\xb9\x7b\x6e\xbf\x99\xfe\xcd\xbb\x29\xaf\xed\x24\x7e\xd3\xed\x56\xd9\x4e\xe6\x99\x4a\xb2\x59\x88\x3c\x92\xb0\x26\x01\x2e\x00\xca\xd6\x3c\x79\xbe\xfb\x5b\x38\x00\x48\x50\x17\x5b\x12\xd9\x6d\xd9\x01\xa6\x2a\xd3\x16\x49\x10\x3c\x38\x38\xf7\x0b\x2d\xd8\xf7\x20\x15\x13\xfc\x1d\xa1\x05\x83\x07\x0d\xdc\xfc\xa5\x06\x77\x7f\x55\x03\x26\x4e\x66\x6f\x7f\x73\xc7\x78\xfa\x8e\x9c\x95\x4a\x8b\xfc\x1a\x94\x28\x65\x02\xe7\x30\x66\x9c\x69\x26\xf8\x6f\x72\xd0\x34\xa5\x9a\xbe\xfb\x0d\x21\x94\x73\xa1\xa9\xf9\x59\x99\x3f\x09\x49\x04\xd7\x52\x64\x19\xc8\xfe\x04\xf8\xe0\xae\x1c\xc1\xa8\x64\x59\x0a\x12\x27\xf7\xaf\x9e\xbd\x19\xfc\x6d\xf0\xe6\x37\x84\x24\x12\xf0\xf1\x5b\x96\x83\xd2\x34\x2f\xde\x11\x5e\x66\xd9\x6f\x08\xe1\x34\x87\x77\x24\xc9\x4a\xa5\x41\x2a\x90\x33\x96\x80\x7b\x5e\x0d\x44\x01\x92\x6a\x21\xd5\x20\x11\x12\x84\xf9\xbf\xfc\x37\xaa\x80\xc4\xac\x62\x22\x45\x59\xbc\x23\x2b\xef\xb1\xf3\xfa\xc5\x52\x0d\x13\x21\x99\xff\x9b\x90\x3e\x11\x59\x8e\xff\x76\x40\xb0\xaf\xbf\xb1\xaf\x77\x90\xc3\xeb\x19\x53\xfa\xdb\xf5\xf7\xbc\x67\x4a\xe3\x7d\x45\x56\x4a\x9a\xad\xfb\x10\xbc\x45\x4d\x85\xd4\x57\xf5\xb2\xcc\x32\x12\x35\x0b\xff\xed\x6e\x64\x7c\x52\x66\x54\xae\x99\xed\x37\x84\xa8\x44\x14\xf0\x8e\xe0\x64\x05\x4d\x20\xfd\x0d\x21\xfe\x5d\x76\xf2\x3e\xa1\x69\x8a\x1b\x49\xb3\xa1\x64\x5c\x83\x3c\x13\x59\x99\xf3\xea\xe5\xe6\x9e\x14\x54\x22\x59\xa1\x71\xb3\x6e\xa7\x80\x50\x23\x62\x4c\xf4\x14\xc8\xd9\xcd\xf7\xd5\xad\x84\xfc\xb7\x12\x7c\x48\xf5\xf4\x1d\x19\x98\x0d\x18\xa4\x4c\x15\x19\x9d\x9b\x25\x04\x77\xd9\xdd\x3c\xb7\xd7\x82\xdf\xf5\xdc\xac\x57\x69\xc9\xf8\xe4\xb1\xf7\xbb\x8f\xd8\x6c\x09\xb3\x60\x9f\xc2\xd7\x7f\xbf\xf4\xfb\xa6\xaf\xf7\x9f\x4f\xcd\x9b\x89\x9e\x52\x4d\xf4\x94\x29\x22\x38\x10\x09\x45\x46\x13\x50\x8f\x2c\x68\xc5\x2d\x76\x45\xd7\xcb\x17\xd6\x2c\x29\x9c\x52\x53\x5d\xaa\x41\x31\xa5\x6a\x19\xc4\xc3\x85\x5f\x57\x4c\x67\x6f\x9c\xbd\xa5\x59\x31\xa5\x6f\xdd\x8f\x2a\x99\x42\x4e\x6b\x1c\x10\x05\xf0\xd3\xe1\xe5\xf7\x7f\xbc\x59\xb8\x40\x9a\xd0\x59\x89\xfd\x84\x29\x03\x2a\xa4\x20\xc4\x93\x10\xdc\xbb\x79\x01\xe4\xbf\x56\x3e\x73\x53\x40\xf2\x5f\x83\xa5\x95\x8b\xd1\x7f\x43\xa2\x83\x9f\x25\xfc\x4f\xc9\x24\xa4\xe1\x8a\x0c\x80\x3c\x59\x5a\xf8\xd9\xc0\x3f\xf8\xa9\x90\x86\x2c\xe8\xe0\xc8\xdb\x11\xd0\xc5\xc6\xef\x0b\x5f\x7b\x68\x40\xe2\xbe\x31\x35\x24\x11\x14\xe2\xa3\xc3\x38\x48\x1d\x1c\x2d\x9e\x32\x65\x90\x43\x82\x02\x6e\x89\x24\xa2\x10\x77\xdf\x34\x20\x06\x00\x20\x95\x21\x00\x65\x96\x1a\xda\x39\x03\xa9\x89\x84\x44\x4c\x38\xfb\x57\x35\x9b\x22\x5a\xe0\x6b\x32\xaa\x41\x69\x82\xa7\x96\xd3\x8c\xcc\x68\x56\x42\x8f\x50\x9e\x92\x9c\xce\x89\x04\x33\x2f\x29\x79\x30\x03\xde\xa2\x06\xe4\x83\x90\x40\x18\x1f\x8b\x77\x64\xaa\x75\xa1\xde\x9d\x9c\x4c\x98\xf6\x54\x3f\x11\x79\x5e\x72\xa6\xe7\x27\x48\xc0\xd9\xa8\x34\x84\xf3\x24\x85\x19\x64\x27\x8a\x4d\xfa\x54\x26\x53\xa6\x21\xd1\xa5\x84\x13\x5a\xb0\x3e\x2e\x96\x23\xe5\x1f\xe4\xe9\x6f\xa5\xdb\x64\x75\xb8\x00\xbe\x95\xe8\x4c\x3c\x81\x7d\x14\xd6\x86\xbc\x5a\x4c\xb2\x8f\xdb\x6f\xa9\x41\x6a\x7e\x32\x50\xb9\xbe\xb8\xb9\x25\x7e\x01\xee\x5c\x22\x84\xeb\x5b\x55\x0d\x6c\x03\x28\xc6\xc7\x20\xed\x9d\x63\x29\x72\x9c\x05\x78\x5a\x08\xc6\x35\xfe\x91\x64\x0c\xb8\x26\xaa\x1c\xe5\x4c\x2b\xc4\x39\x50\xda\xec\xc3\x80\x9c\x21\xd3\x23\x23\x20\x65\x91\x52\x0d\xe9\x80\x5c\x72\x72\x46\x73\xc8\xce\xa8\x82\x4f\x0e\x6a\x03\x51\xd5\x37\xe0\xdb\x1c\xd8\x21\xcf\x5e\x7e\x60\xe9\x8c\x11\xe2\x79\xe9\xda\xdd\x59\x7b\x86\x49\x0a\x49\x46\xa5\x15\x0a\x88\x86\x2c\x23\x1f\xdf\x7f\x20\x53\x71\x6f\xb0\x98\x71\xa5\x69\x96\xe1\x29\x70\xfc\xd9\x92\xd3\x84\x72\x92\x53\x4e\x27\x40\x68\x51\x28\x32\x16\x92\x50\x32\x61\x33\xe0\xfe\x74\x0d\x36\x5d\xfc\x3a\x22\x41\x2c\x71\x5f\xc9\xa0\xfc\x55\xb7\xc0\x85\x2b\xeb\xc8\x86\x19\x4b\x32\xd0\x23\x50\x3b\xad\xef\x45\xcc\xe6\xa4\xe4\x4a\xcb\x12\x37\x3b\x25\x77\x30\x77\x48\x9e\xd3\x82\x28\x2d\xcc\x8f\xf7\x4c\x4f\x09\x0d\x11\x9c\x6a\xc4\xe2\x11\x10\x05\x9a\x8c\xe6\xc4\x88\x71\x48\x10\xb4\x10\x19\x52\x0b\x7c\x16\x09\x83\x04\x2d\x19\xcc\x80\x50\x39\x62\x5a\x52\x39\xaf\xb0\x61\x11\xa0\x4f\x00\x15\x3f\x36\x10\x1e\xd6\x83\x84\x3c\x86\x8b\xc4\x92\x5b\x27\xbb\xa4\x95\x60\xb9\x01\xf4\x86\x97\x0e\xdf\x6a\x71\x54\x39\x7c\x03\x45\x0c\x5e\x39\xf9\xa0\x92\x6b\xf1\x4d\x0e\xb1\x52\x22\x64\x85\x19\x06\x6c\x21\x12\x8e\xc0\x90\x13\x49\xb9\xb9\xb0\x12\xb9\x77\x80\xd6\x63\x68\x63\x86\xb8\xe7\xab\x70\x34\x9c\x9b\x4a\xd9\x10\x98\xc2\xc1\x34\xe4\x6b\x66\x7e\x14\x76\xd5\xcf\x66\x81\x33\x96\x82\x01\xa2\xa6\xcc\xa2\x8e\x39\xad\x74\x24\x4a\x6d\x61\xe7\x6e\x49\xc9\x8c\x51\x42\x27\x13\x09\x13\x44\xe0\xb5\xaf\x7d\x02\x26\x76\xac\x3f\xa0\xf5\xe8\x5b\x49\xfe\xd1\x3b\x0c\x19\x7c\xf4\x06\xbe\xea\x98\x87\x37\x2c\x0b\x8b\xcd\xf1\xd4\x1e\xda\x41\x13\x03\x13\x0f\x5a\x21\x1f\xbd\x79\x93\xbd\xb5\xe3\x89\x1d\xb6\xa3\xb9\xcf\x0b\x0b\x71\x57\x47\xe6\x7c\xd4\xa4\xd9\x90\x03\xbc\xb1\x26\xbe\x23\x20\x05\xc8\xb1\x90\xb9\x39\x28\x9c\x50\x92\x58\xf9\xad\x22\x3c\x48\x1a\x79\xf2\x18\x38\xc9\xa6\xfb\x6f\xc7\x26\x58\x60\x47\x9f\x14\x54\x4f\x9f\xb8\x6d\xb3\xad\xb2\x23\x04\xda\x93\x37\x3f\x41\xcd\x96\xe6\xae\x39\x4c\xe7\x73\x1b\x30\x74\x3e\x29\xf2\x9c\x4d\x66\x6d\xa0\xda\x35\xbd\xff\x00\x4a\x19\x96\x8d\x52\x9a\xa4\xf7\x04\x78\x22\x0c\xb1\xf8\x7f\x6f\x3e\x5e\xd9\x69\x07\xe4\x52\x13\x96\x17\x19\xe4\x46\x10\x23\x1f\xa8\x54\x53\x9a\x81\x44\xee\xf4\x1d\xcf\x1b\x7f\x3b\x4c\x2c\x15\xa4\x86\x16\xa5\x90\xd1\xb9\x9d\x2c\x85\x44\xa4\x86\x46\x0b\x49\x0a\x23\xe0\xe6\x45\xa9\x81\x50\x7b\x15\xdf\xcb\xf8\x64\x15\x91\x6e\x05\x1a\x62\x24\x91\x9c\xea\x77\x64\x34\xd7\x4f\xa1\x3e\x21\x0f\xfd\x74\x53\x1a\x10\x2e\xe6\x69\x4a\x60\xc7\x46\xf4\x20\x9c\xf8\xc9\xaf\x34\x42\x28\x65\x1c\xe4\x50\x48\xbd\x09\xd1\x32\xca\xc7\x04\xe4\xa3\x77\x7a\x90\x31\xae\xff\xf8\x87\x47\xee\x4c\xa1\xc8\xc4\xdc\xe0\xc5\xd3\x67\x65\xc3\xef\xd9\xf8\x5c\x6f\x3a\xdf\xa6\x67\x79\xc3\xf9\xac\x71\xaa\x8b\x99\x56\x29\x50\x3b\x4d\xc4\xbb\xfa\xb6\x4a\x09\x7c\x36\xe6\x37\xbc\xf4\xd6\x86\x6b\x18\x83\x04\x9e\x78\xda\x54\xfd\xa9\x05\xa1\xe4\xdb\x72\x04\x92\x83\x06\x15\xc8\xd5\xf3\x02\xbc\x69\x07\xec\x03\x12\x24\x29\x35\xcb\xd8\xbf\x40\x3d\x45\x59\x3e\x11\xdb\x7b\x42\xc0\xf1\xb7\x3d\x21\xe6\xf8\xdb\x9e\x12\x76\xec\xd8\x86\x8f\x3e\x8d\x85\x76\x34\xf6\x09\x35\x7b\x27\xaa\x57\x3b\x93\x36\xb7\xa2\x73\x4a\xfe\x34\x9a\xaf\x58\xe9\x10\xcd\xb7\x0d\xf3\xe7\xba\x05\x93\xa3\x75\x26\xf3\x81\xd1\x8b\x07\x68\x94\xfd\xe1\xa7\x81\x9d\xf2\x78\x40\x2e\xf2\x42\xcf\xbd\x6d\x83\x3d\x31\x39\x53\x84\x0b\xbd\x2c\x95\x75\x0e\xa6\xd9\x6a\x33\xd8\x93\x90\x3a\x1d\x5e\x7a\x03\xeb\x67\xdc\x5a\x55\x40\xb2\x07\x52\xf7\x4d\x63\x19\x0d\x99\x7b\xcc\x20\x4b\x09\x33\x02\xb5\x59\x2c\x19\x65\x22\xb9\x73\xb6\xe4\xeb\x73\xa2\x84\xa5\x39\x46\xeb\x32\xc2\x4f\x22\xb8\x2a\x73\x20\xec\x29\x22\x12\xc5\xec\x28\x66\x47\x31\xfb\xa5\x88\xd9\xd6\x67\xb3\x0f\x94\x6a\x61\x21\x6b\x69\x15\xde\x17\xa9\xd5\x63\x23\x52\x2b\x1c\x91\x5a\x3d\x31\x5e\x1c\xb5\xda\x48\x06\x7c\x72\xae\xa7\x0e\x72\x34\x70\x47\x03\x77\x34\x70\xbb\x11\x79\x99\x1b\x91\x97\x45\x5e\x16\x0d\xdc\x8f\x4d\x19\x0d\xdc\x5b\x4e\x14\x0d\xdc\xd1\xc0\xdd\x18\xd1\xc0\x1d\x0d\xdc\xd1\xc0\x1d\x0d\xdc\x6b\x46\x14\xb3\x77\x9c\x34\x8a\xd9\x8f\x8c\xd7\x2d\x66\x47\x03\x77\xa4\x56\x91\x5a\x45\x6a\xf5\x32\xa8\x55\x7b\x03\x77\x92\x01\xe5\xab\x15\xdd\x85\x3c\x09\xbc\x0f\x45\x23\x36\x66\x2e\x5f\xc8\x3d\x4d\x46\x30\xa5\x33\x26\x4a\x49\xee\xa7\xc0\x7d\x6a\x1b\x99\x80\x56\x06\x0b\x40\xc3\x2a\xdd\xe8\x09\x5a\xf3\x38\x7d\xe9\x13\xe0\x74\x94\xad\x9c\xf8\x29\x52\xe2\x9e\x7c\xdc\xa0\x3f\x12\xc2\x7c\xdd\x32\xc4\x50\xae\xf7\x72\xf2\x36\x71\xff\x07\xeb\xf4\x8e\xd5\xc1\xff\x67\xd7\xe7\x5d\x85\xfc\x93\x1f\x39\xb9\xac\x66\x25\xe8\x2d\xc0\x84\x22\xc3\x43\xcc\xaf\x1f\xef\x39\xa4\x98\x0c\xda\x23\x4c\x9b\x1b\xcc\xa1\x67\x09\xd3\xd9\xbc\x7a\xf1\xe0\x60\xfb\x4d\xdc\xa3\xd4\x81\xb3\xeb\xf3\xcd\x5d\x2a\x7e\x03\x3e\x87\xf7\x24\xfa\x46\xa2\x6f\xa4\x1a\x51\x0c\xda\x71\xd2\x28\x06\x3d\x32\x5e\xb7\x18\xb4\xef\xbe\x84\xe8\x01\x20\xd1\x03\xe0\x6f\x8b\x1e\x80\xe8\x01\xe8\x06\x4c\xd1\x03\x10\x3d\x00\x8f\xdf\x14\x85\xc9\x1d\x27\x8d\xc2\xe4\x23\xe3\x75\x0b\x93\xd1\x03\x10\xa9\x55\xa4\x56\x91\x5a\xbd\x0c\x6a\xf5\x12\x43\xdc\xa3\x21\x36\x1a\x62\xa3\x21\x36\x72\xa3\xc8\x8d\x9e\x18\x2f\x8e\x1b\x45\x43\xec\xb6\x13\x45\x43\x6c\x34\xc4\xae\x1b\xd1\x10\x1b\x0d\xb1\xd1\x10\x1b\x0d\xb1\x8f\x8f\x28\x4c\xe2\x88\xc2\xe4\x13\xe3\xc5\x09\x93\xd1\x10\x1b\xa9\x55\xa4\x56\x91\x5a\xbd\x0c\x6a\xd5\xde\x10\xfb\xc4\x49\x6a\xa0\x4c\x68\x3f\x75\x92\xa3\x8f\x07\xc6\xca\xfe\x84\xf1\x24\x2b\x53\xc0\x2b\x63\xa0\xba\x94\xa0\x7a\x24\x63\x39\xf3\x75\xdb\x85\x34\xd8\xd1\x4f\xa8\x02\xb5\x34\xc7\x8a\xf7\x3f\xbe\xf6\xc7\x4f\xea\xa3\x7d\x58\xaa\x40\x66\xc6\xfd\x3c\x0e\x57\xb6\x5e\x06\x4b\x36\x80\x9d\x79\xbf\xb9\x11\x6b\xf3\xdb\x36\x0b\x4f\x7e\xf6\x3a\xbc\x7a\x04\x8f\x9e\x24\xdf\x4f\x11\xed\x3e\x19\x51\x05\x7f\xf9\xd3\x52\x37\x90\xf0\x96\x1c\x52\x46\xcd\xab\x56\xde\xf1\x34\x21\xaf\x5f\xb1\x1e\x73\x37\x38\x01\xd5\x32\x76\x9c\xc5\xb5\x2b\x78\x72\xef\x0c\x82\xa5\x97\xf6\xe6\x1b\x2d\xa9\x86\xc9\x3c\x68\x8f\x81\xf8\x54\xf3\x5f\xbe\xa6\xad\x4b\xa5\x59\xdd\x4f\x41\xda\x33\xe2\x1b\x3a\x28\x3f\x29\x53\x55\xae\x43\xba\x43\xc9\xfc\xa7\x92\x17\xfc\x7b\x56\x5c\x7e\x6a\xd3\x56\xf5\xb4\x58\x09\x2c\x0f\xa0\x73\xeb\x57\x39\xaf\x8a\x38\x2c\x42\xac\xa0\xd2\xf0\x09\xef\x7f\x41\xd1\x25\xb8\x7b\x01\xde\xeb\x58\xc3\x06\xf2\xca\xd3\x72\x4a\x3f\xa8\x35\xb1\xce\xe7\xb3\x89\x78\xe2\x3a\x4b\x0d\x41\xe6\x4c\xa9\x75\xe9\x19\xcd\xa5\x3f\xc5\x3c\x36\x60\x1a\x6b\xe0\xef\xbf\x28\x58\x4e\x25\x44\x5a\xb5\x7f\x44\x13\x22\xcb\xcc\x88\x94\x3c\x25\xae\xa9\x04\xa1\x49\x22\x4a\xae\x09\x07\x48\x6d\xe2\xc7\x2a\x5c\xdd\x80\xe5\x6c\x20\x45\x6e\x2a\x43\xf6\xed\x3a\x9f\xbc\xcb\x7d\xc3\xa9\xfd\x84\x95\x6d\x4a\xc2\xb1\xb9\xcc\x89\xaf\x7f\x9a\x77\x6f\x23\x10\x6c\x2c\x0e\x34\x0d\x5d\x22\x63\xc9\xfc\xba\xcc\x80\x4c\x45\x96\x2a\x6c\x96\x63\xf8\x56\xe5\x0a\x0b\x15\x85\x02\xef\xc6\xd5\xf7\xc8\xa8\xd4\x24\x15\x60\x0d\x54\xae\xb4\x4b\xe3\x71\xeb\xfc\xbc\x9f\xda\x86\x49\xe6\x21\x42\x8b\x22\xc3\xc4\x2b\x61\x78\xf7\xfd\x94\x25\x53\xdb\x05\xae\xa0\x09\xac\xba\x6d\x73\x19\x6e\x23\x25\x83\x6c\xa5\x68\x10\x6f\x3c\x1d\x3d\x85\x2a\x64\x4b\x8d\x83\xd8\xc6\x2b\x5f\x4b\x51\x16\x1b\xde\xbe\x6c\x77\xb3\x4f\x1b\x2a\xaf\x17\xc4\x11\x7f\xd1\x39\x33\xed\xde\x28\x67\x9c\x73\xc6\xfa\x01\x21\x97\x63\x92\x97\x99\x66\x45\x86\x8f\xd8\x7a\x31\x8a\x50\x09\x35\xdf\xe8\x11\xca\xe7\xde\x37\xea\x9a\x2f\x41\x4a\xe8\xc4\xcc\xa8\xb1\xeb\x9a\x6f\xf4\xc2\xcb\xdc\xc8\x20\x81\xd9\x4f\xa1\x52\xc9\xe7\xf5\xec\xe4\x9e\x65\x99\x91\xea\x69\x96\x89\x7b\x48\x07\xe4\xe0\x60\x91\x94\x27\x42\x06\xeb\x41\x62\x72\xf0\xbb\xc6\x5d\x86\x72\xd4\x0b\xde\x04\x47\xc8\xd6\xe2\x35\xd9\x4e\xc4\x26\xdb\x2b\x13\x84\x70\xc1\xbd\xd9\xf8\xbb\xeb\xf7\xbb\x21\xc2\x55\x73\x0e\xd7\xa5\x0b\xb4\xd9\x96\x82\x4a\xcd\x68\x46\x4a\x99\x29\x8b\x0b\xd4\x08\xcc\xd2\xb7\x39\x9b\x52\xf4\x7b\x27\xa0\x6c\x3f\x2d\xf2\x3b\xbb\xfb\x6e\x73\xec\x19\x17\x3c\x9b\x13\x6a\xb7\x66\x5c\x66\x59\x8f\x8c\x19\xa7\x86\x74\x43\xe1\x73\xef\x8c\x26\x4a\x6e\x18\x4f\xc0\x7c\x53\xbf\x12\x4e\x70\x45\x66\x46\x43\x23\xaa\x83\x9e\xf6\x5c\xc3\x2f\x6b\x77\x50\xee\x15\xe6\xd0\x27\x74\x94\x01\x4a\xb5\x4e\xec\xb9\x16\x19\x7a\x6b\x2a\x93\x32\x76\x09\xa3\xe1\xe5\xff\x60\x1c\xd5\x3d\x72\x8d\xcc\xc7\xa8\x8d\xc0\xf4\xd4\x68\x91\x45\x91\xcd\x0d\xb1\x31\xc8\x52\x23\xe5\x91\x2a\x93\xa9\xf9\xa4\x83\x42\xa4\xea\xc0\x90\xa2\x03\x05\x89\x04\xad\x0e\x8e\xcd\x5f\x8b\xdf\x80\xdf\x17\x3e\x77\x42\x0b\x76\x70\xdc\x23\x08\x20\x6c\x41\x26\xf4\xf4\xe5\xe2\xa1\xff\xd6\x46\xe7\xcb\xa7\x46\x53\xff\x0f\x67\x70\xfd\xb4\x44\x61\xdb\x53\x19\x3a\xaf\x01\x33\x33\x0d\x52\x22\x1a\x04\x1e\xb7\x05\x82\x4f\xc8\x29\x27\x60\x7d\x24\xa0\x49\x0e\x94\xbb\xbb\x61\x06\x72\xae\xa7\xe8\x36\x51\x15\x01\x79\xf1\x40\x6f\x07\x70\x77\xe0\x3d\x70\x6b\x24\xb7\x3d\x0f\x17\x81\x7b\xf8\xbb\xc3\x45\x42\x5a\x73\x84\x17\x0b\x4a\x64\xd1\x3b\x81\xf1\x7b\xf3\x64\x13\x84\xf6\x27\x4b\x2d\x2b\xfa\xf1\xfe\xbd\xed\x6f\xe8\x60\xf5\x2d\xe3\xa9\xaa\xea\xd9\xa5\x96\x0c\x3a\x78\xaf\x04\x32\xae\xf0\x25\x02\x78\x59\x04\xde\x54\x6c\x7d\x62\xfa\x40\x47\xda\x07\xb5\x06\xfb\x25\x36\x24\x25\x43\xa7\x7a\xd6\x79\x67\x44\x90\x8c\x8e\x20\x53\xce\xe0\x02\xc1\xf2\xc9\xe9\xfb\x0f\x55\xdf\x50\x09\xf4\x09\xcb\xe0\x27\x50\x66\x36\x88\x02\x58\xea\xbe\xba\x3c\x36\x97\x5f\x11\x14\xdb\x99\xd5\xc9\x0d\x68\x7b\xcc\x72\x5a\x98\x53\x66\xe7\x58\x69\x15\x7e\x8f\x90\x7e\xfa\xb0\x6c\x25\xf7\x6f\xde\x2d\x71\xd5\x4b\x36\x3a\x2a\x9b\x45\x1a\x6c\x73\xf6\x1e\xb1\x92\xd4\x63\xc1\xa8\xda\x40\x68\xa7\x1b\x38\x69\x3e\xa1\xa1\xb1\x35\x05\x65\x4b\x31\xd8\xc2\x17\xd2\xff\x5e\x4f\xd1\xf1\x16\x6c\xa3\x78\x19\xdd\x3b\x83\x44\x8b\xc7\x8b\x7f\xfa\x9b\x35\xe4\x45\xf6\xd4\xc9\x23\x5b\x2b\x69\x39\xe3\xd7\x40\xd3\xf9\x0d\x24\x82\xa7\x1b\x12\xd8\xc6\x7e\x7c\x60\x9c\xe5\x65\x4e\x78\x99\x8f\x00\x41\xac\xec\x5c\x48\x48\xac\x02\x4c\x09\x87\xfb\x6c\xee\x88\x47\x4a\x0a\x91\x7a\x7a\x32\x32\x0a\x1b\x4d\xe7\xd8\x79\x14\xcb\x64\xf3\xb9\x99\x84\xe9\x9a\xfb\x48\x92\x48\xaa\x8c\x58\xd4\xc3\x49\x99\x36\x1c\x6b\x04\xe8\xa5\x63\x29\x98\x3d\xa6\x33\xca\x32\x23\x5a\x0f\xc8\x39\x8c\x69\x99\x61\x03\x5d\xf2\x86\x1c\x99\x97\x79\x9d\x6c\xd5\x03\x46\xdc\x55\xc2\x68\xf3\xca\x55\xd5\xc0\x05\x1d\x6f\xe1\x77\xd8\xa4\x8a\xab\x1f\x9b\x56\x73\xf5\xa3\xa0\xa5\xda\x54\x95\x6f\x6c\xcc\x25\x4f\xcd\x79\x08\x25\xd1\x80\xa4\x33\xe5\x66\xde\x8c\x65\x3f\x5e\x6d\x65\xc5\xaa\xa5\x98\x48\x50\xea\x1c\x68\x9a\x31\x0e\xbb\xe3\xd7\xed\x14\x48\x4e\x1f\x10\xc7\x34\xcb\xc1\x48\x22\x21\x86\xd1\xf0\xab\xb4\x20\x39\xbd\x83\xea\xf5\x64\x04\x63\x6c\x90\x8c\x1f\x1c\xec\xbe\xc5\x9f\x31\x65\x99\xd1\xd0\x6f\x9b\xb0\xc1\x5e\xc9\x22\xcb\x40\x5a\xc4\x31\x7f\x33\x5e\x62\x88\x5d\x21\x05\x2a\x93\xf6\xd1\x90\xc7\x23\x0f\xa5\xe6\x66\x4b\x87\x7d\x2f\xdd\xe1\x02\x28\x2e\x1e\x12\x6b\x28\x94\x40\x15\xde\x66\x71\x53\x95\x72\x6c\x54\x47\xaf\x71\x06\x0b\x72\x4d\xd8\xc9\x95\xd0\x2e\x92\xaf\xfa\x40\x7c\xda\xb5\x88\x06\xa5\x59\x8e\x07\x2c\x2d\xa5\x6f\x58\x8d\x30\xa3\xab\xb7\xbe\x71\x54\xfe\xf2\xe6\xcd\x86\xf2\xdb\xa7\x47\x7a\x09\xa8\x29\xef\x82\x2f\x57\x15\x1d\xf2\xe4\xdf\xa8\xc0\x66\x8f\x99\x13\x83\xb1\xf3\x36\x48\xf4\xb8\x32\xa5\x19\x9f\x94\x4c\x4d\xc9\x08\xf4\x3d\x00\x27\xf0\x60\x6b\xea\x90\x7f\x81\x14\xb8\xa9\x06\xbc\xb5\x9b\xa1\x01\xb4\xb7\xfb\x03\xb1\x19\x53\x4c\xf0\x6f\x98\xd2\x42\xce\xdf\xb3\x9c\x3d\x51\x80\xda\x8f\x65\xb7\x5f\x05\x41\x91\xa5\xe4\xda\x6e\xc5\x0d\xd8\x0f\x96\x80\x56\x50\x2d\xac\x7a\x4a\xcc\x39\x19\xd1\xe4\xee\x93\x01\xf8\xcd\xbe\x40\xd8\xb3\xeb\x1d\xa0\x8a\xf2\x5e\x35\x01\x92\x2d\x8b\x94\x17\x0f\x16\x3e\x0d\x28\xdf\x4f\x85\x02\xbc\xc1\x1a\x2a\xf1\x31\xef\x58\x60\xaa\x22\x18\xe8\x96\xe5\xa0\x08\x1d\x8f\x9b\x77\xd4\x87\x1d\x25\xcf\xbc\x54\x9a\xe4\x54\x27\x53\x6b\xca\x12\x69\x25\x4e\x1c\x2a\x27\xf6\x6f\x03\xe5\x8d\x0d\xd1\xdb\x9b\x8c\x89\x5d\xe7\xc5\x83\xd1\x2d\x9f\xf4\x08\x35\x47\x03\xe4\x8b\xd3\x34\x35\xe0\xac\xb9\x21\x4e\x6e\xcb\x6d\xf3\xfe\x5b\x34\x22\xd7\xbf\xe0\x2e\x9c\x5e\x9d\x6f\x6e\x8a\xd9\x45\xc1\xdd\x5a\xc5\x5d\x34\x97\x3f\xf2\x51\xde\x64\xea\xae\x34\x6d\xe6\xa8\xa1\xa8\x1e\xa1\xe4\x0e\xe6\x3d\xcb\xc5\x16\x1b\xe6\x4b\xc8\x9c\x24\x01\xd8\x37\xde\xdc\x64\x9f\xdb\x1c\x24\x3b\x60\x8f\x1d\xdb\xb9\x33\xfc\xe8\x9b\x85\x6e\xf9\x84\xff\xe8\x2d\x1e\xdb\x1e\xc1\xed\xb8\x83\xf9\x76\x0f\x2c\x6c\xb7\xd9\x05\xa7\xfb\xd8\x7d\x37\x3f\x54\x82\x5e\xb5\xd5\xdb\xf9\x99\xc2\xb1\xb5\x89\xca\x0f\x0f\xc4\x56\x9f\x57\xa1\x5f\x68\x65\x32\xdf\x78\xa8\x2c\x32\x9a\x33\x3d\x65\x85\xcd\x7a\x70\xce\x00\x87\x91\xe4\x7b\x9a\xb1\xb4\x9a\xc2\x9e\xdf\x4b\xde\x33\xe2\x93\xf9\x3f\x24\xba\x56\x5c\x3b\x17\xa0\xae\x84\xc6\x5f\x3e\x1b\x80\xec\x32\x5b\x81\xc7\x4e\xe1\xac\xd0\x48\x65\x50\xf1\xb2\x11\xf7\x1e\x0c\x97\x8b\x91\x3b\x8a\x5c\x72\x22\xa4\x87\x83\xb9\xe8\x26\xb2\x53\x20\x9f\x18\x59\x07\x07\xda\xa7\x57\xce\xe1\xc0\x27\x64\x03\x7a\x8f\x4c\xe7\xa6\x42\xf9\xc0\x5e\x41\x1d\xab\xc8\x50\xda\x75\xa2\x2a\xf5\x8e\x72\x96\x90\x1c\xe4\x04\x3d\x2e\xc9\xc6\x1e\x87\xe6\xa6\x6c\x47\x77\xed\xd8\x9a\xfa\x86\x2f\xdc\x0a\x0b\x90\x35\x59\x13\x50\x1b\xe6\x66\x67\x68\x98\x9c\xfe\x8f\xa1\xe0\xb8\x07\xff\x97\x14\x94\x49\x35\x20\xa7\x44\x31\x3e\xc9\xa0\x71\xcd\x69\x18\xe1\x34\x66\x06\xa6\x88\x21\xb5\x33\x9a\x39\x5d\x8a\x72\x02\xd6\x66\x65\x66\x5f\x64\xa9\x3d\x27\xa9\x18\xca\x53\x39\xba\x0e\xee\x60\x7e\xd0\x5b\x42\x9a\x83\x4b\x7e\x60\x79\xcb\x12\x9a\x54\x8c\x08\x7d\x64\x07\x78\xed\xa0\x4b\x2e\xbc\x25\xc3\xd9\xd5\x8e\xd6\x7c\xe9\xc6\x18\xe1\xe3\x43\x76\x14\xd6\x1b\x5a\xa2\x8b\x8a\xd2\x82\x94\x0a\xac\xb4\x8e\xa7\x8c\x80\x97\x33\x51\xaa\x44\xc5\x94\xc3\x3d\x4a\x8f\x7b\x23\xf8\x19\x4d\x82\xf1\xc9\x77\x45\x4a\xf5\x46\xe1\xb9\x76\x34\x20\x72\x78\x6d\x27\x21\x25\xce\x62\x70\x6b\xcc\x26\xa4\xa0\x92\xe6\x6a\x40\x86\xae\x9e\x2a\x62\x1a\x1b\x87\xb6\x44\x07\xbb\xdb\x79\x01\xe4\xff\x21\xd7\xe1\x5a\x06\xa4\xdf\xef\x93\xdb\x8f\xe7\x1f\xdf\x11\xfb\x8b\x95\xb2\xb5\x20\x63\x81\x4a\x90\x28\xa5\x79\xd5\x0c\x38\x2a\xfe\x46\xbe\x17\x1c\x3e\x8e\xcd\x09\xa1\x1a\x66\x20\xc9\xbd\xd9\xaa\x84\xa5\x50\x59\xaf\x06\x87\x9f\x16\x8f\x77\x93\x4c\x72\xfa\x70\x53\xca\xc9\x16\x1b\x40\x96\x36\x21\x34\xd9\xd4\xca\x24\xa2\x5e\x98\x7b\xae\x92\x29\xa4\x65\x06\x29\xa1\x23\x31\x83\x86\xc9\xb6\xf9\x18\xb2\xf4\x12\xfc\x83\x86\xe7\x8d\x94\xc8\x4a\x5d\x29\xab\x47\xf0\xf0\x8e\xfc\x19\x5d\xdb\x94\x14\x20\x13\xe0\x9a\x4e\x60\xd1\x0c\x60\xef\x7b\xfb\xe6\xdf\x8e\x1d\x3f\x32\x33\x3a\xeb\xc9\x1b\x83\x11\x1f\xe8\xc3\x77\xbc\x36\x0d\x32\x45\xde\x0c\xc8\xe9\xc2\xcb\xf0\xb9\x2c\x29\x33\xb4\xb5\xa0\xbb\x3e\x78\xe5\x68\x4e\xa4\x28\xd1\x61\x4f\xca\xa2\xa9\xcd\xfe\xe1\xcf\xff\x66\x94\x3e\x9a\x17\x19\xbc\xf3\x65\x98\xad\xda\x6c\x64\x18\x2d\xc8\x1f\xdf\xfc\x9b\xa5\x9e\xe6\x7c\xd6\x5a\x61\x0d\x33\x6a\x00\x56\x16\x84\xe5\x36\x9c\x13\xb2\x79\x5d\xcf\x59\x36\xd1\x5f\x69\x2a\xb5\xea\x11\xf4\xea\x57\xc2\xa1\x16\x9a\x66\x0b\x5a\x3e\x6a\xe1\x70\x6f\x81\x94\x0a\x84\x09\xa0\xa1\x8a\xbc\xfd\xe3\x9b\x7f\x5b\x36\xa7\x7c\xe4\x09\xe0\x93\xf8\x04\x86\x59\x8c\x8c\x72\x7f\xc7\xb2\x0c\xd2\xde\x93\xcb\x1f\x97\x52\x4f\x41\xf6\x08\x70\xe5\x8d\x55\x66\x7d\x0b\x6b\xc3\xd9\x65\xc9\x39\xca\x08\xd6\x3a\x8c\x16\xad\xc0\xc2\xe5\x3e\xd6\x30\x42\x4d\x72\xa1\xf4\xea\x25\x6f\x7e\xdc\xcc\xa0\x7c\xfe\x71\xbc\xad\x38\xd0\xdf\xc1\x0c\xb1\xfc\xf4\x0e\x22\xe5\x43\xff\xae\x4a\xfc\xed\x33\xae\xfb\x42\xf6\xed\x34\xef\x88\x96\xe5\xd3\x5e\x83\x7a\xe4\x8d\x13\xf0\x19\xc8\x40\x19\x9c\xb7\xa5\x5d\xfd\x24\x27\x7f\xf7\xf3\x9c\x8a\x7b\xbe\x9e\x72\x20\xe1\x74\x34\x63\xc7\x53\xdf\xb4\xb8\x2d\x1c\x1b\xf3\x76\x73\xf7\xff\x6f\x19\xbb\xb7\x20\x07\xee\xec\x56\xa7\xdd\xc8\x55\xe8\xf1\xe8\x6d\xf0\xf6\xea\xd8\x5a\xce\x67\x6d\x4e\xe6\x06\xfb\x9a\x15\x94\x6b\xe9\x84\xaf\xa0\x40\x76\x1d\xb5\x43\x46\x63\x44\x81\x39\xe7\x6a\xed\x41\xcf\x80\x2a\xbd\x0a\x14\xf1\xa0\x3f\x3d\x1e\x4f\x02\x58\x1c\x4d\xa1\xd3\x48\x48\x08\xf2\xda\xc6\x78\x66\x11\xe5\xe0\x1a\xac\x87\xcf\x06\x9c\x35\x84\xa8\x83\xea\x48\x98\xfd\x6b\xca\x57\x9f\x2a\x6c\xc6\x1b\x39\x77\x11\xad\xdd\xa3\x41\x70\xb0\x33\x9d\x3a\xe2\x55\x79\x14\xad\x4b\xd3\xea\x2b\x36\xca\xcf\x1d\x0c\xff\xf6\x81\x2a\x20\x19\x48\xc0\xd3\x67\xa3\x91\xad\x02\x84\x7a\xd1\x69\x76\x4f\xe7\xea\x60\x6f\xa4\xf0\x1c\x34\x7d\x3c\xd1\x64\x71\x34\x89\xfe\x8d\xa6\x3c\xa5\x32\x75\xab\x3c\x3c\x54\xd5\x94\x03\xf2\x01\x7d\x71\x7c\x2c\xde\x91\xa9\xd6\x85\x7a\x77\x72\x32\x61\x7a\x70\xf7\x57\x35\x60\xe2\x24\x11\x79\x5e\x72\xa6\xe7\x27\xe8\x80\x63\xa3\x52\x0b\xa9\x4e\x52\x98\x41\x76\xa2\xd8\xa4\x4f\x65\x32\x65\x1a\x12\x5d\x4a\x38\xa1\x05\xeb\xd7\x32\xb7\x1a\xe4\xe9\x6f\xfd\x8b\x3e\xb1\x60\xdd\x38\x83\x68\x9d\x92\x33\xe8\x97\xfc\x8e\x8b\x7b\xde\x47\x4d\x58\x6d\x75\x1a\x37\x8b\x82\xf0\x63\x01\xde\xdb\x04\x3e\x14\x22\xfd\xe4\x9b\x60\x3e\xa6\x4f\x79\xda\xb7\x4e\xcb\x4f\xbc\x17\xbb\xd8\x86\xfb\x75\x60\xc1\x26\x51\xef\x76\xec\xa6\x4d\xd1\x44\xb3\x19\xec\xe4\x04\xf7\xa3\xb1\xdd\x1f\x7d\xc0\x69\x5a\x4a\xbb\xe3\x81\x37\xdc\xfb\x76\x72\x3a\x47\x59\x09\xdf\x4d\x84\x15\x05\xb8\x48\xc1\x59\x4e\x67\x68\x1a\xb8\x31\xe4\xe8\xd6\x88\xd2\xce\x47\x8e\x76\xe3\xb9\xd2\x90\x5b\xe2\x66\x9f\xcf\xe6\x44\xcb\xb9\x75\xac\xcb\x3b\xa3\xbc\x3a\xcf\xb7\xd1\x18\xee\xf0\x3e\xa5\x44\xc2\x50\x74\xaa\xe1\xea\xe5\x36\x6f\x03\xa4\xa4\x10\x8a\xe1\xbb\x1d\xcf\xdc\xce\xb2\xb7\x3b\xbb\x0d\xdc\x7c\x7f\xf9\xd3\x36\x5b\x37\xc6\x2a\x27\x5b\x5a\xe9\x9b\x11\x18\xe3\x30\xcb\xc0\x6d\xcf\xa1\xf2\x8a\xaf\x11\x6b\x12\xc1\x95\x96\x94\xad\xcf\xa3\x5a\x3d\x76\x74\xa5\xec\xee\xaf\x20\x88\x41\xa7\x3b\x01\x85\xac\x4e\x8c\x1d\x61\x66\x4d\x0a\x15\xa8\x43\xc0\xd8\x34\x2b\x1f\x8b\x68\x08\xd7\x8e\xa6\xd9\x1d\x60\x44\x5a\xc1\xc9\x3e\x6d\xab\x2c\xa5\xe7\x28\xbd\xde\x54\xdf\x75\x39\xe1\xa2\xfa\xf9\xe2\x01\x92\x72\xd3\x9c\xfc\xe5\xb1\x64\x0b\xf4\x06\x15\x17\xb6\x62\x17\x61\x8e\xae\xbf\xe0\xe4\x17\x81\x60\x77\x82\x8c\xa2\x9a\xa9\xb1\xcd\x59\xab\x36\x02\x02\xc7\x69\x85\xc2\x95\x7b\x19\x59\x9c\x4d\x9d\x60\x1a\xc9\x4d\x32\x15\x42\x99\x53\x8e\xfb\x89\xf3\xce\x98\xb0\x3e\x43\x4c\xa0\x91\x24\x37\x34\xc6\x27\xd2\xd4\xd3\x5b\xc1\xa9\x7e\x8c\x29\xab\xc2\x57\x10\xf4\x5e\x2e\x33\x0d\x1a\x2e\xcd\x1f\x13\x94\xba\x94\x26\xaa\xcc\xcd\xa4\xf7\xc0\x26\x53\xad\x7a\x84\x0d\x60\x80\x58\x03\x34\x99\x06\xd3\xe6\x00\xba\xd1\xb7\x29\x44\xb5\xd0\xca\x7c\x54\x65\x45\xb8\x54\xa0\x5e\xc5\x63\x16\xf7\x72\x25\xb8\x7a\x04\x74\x32\x38\xee\x91\x3a\x65\xdf\xac\x71\x34\x27\x4c\x83\xa1\xd9\xa8\xcb\x48\x51\x4e\xec\x97\x80\x8f\x09\xc5\x75\x55\x29\x23\xe8\x85\x4d\x51\xe7\x3c\xb0\x1f\x77\x60\xf6\x0d\x57\x5e\xe6\xbe\xa8\x12\x7e\x1f\x9a\xe5\xa1\x4a\x2c\x92\xa0\x0a\x61\xb5\xd5\x45\x83\xfd\xff\xbf\x7a\xe8\x48\x1d\xd7\xc0\x9c\xb2\xc9\xd4\xc3\x92\x3a\x46\xd0\xdc\x83\xed\xcf\x1e\x69\xe5\x8b\xb1\x63\x47\x8f\x8c\x1d\x4d\xdf\xb8\xcf\xb7\xa8\xb1\x2a\xd8\x7f\x0d\x32\xaf\xa0\x88\x28\x82\x24\xc3\xd9\xc9\x7d\x8b\x2d\x87\x63\xe4\x0d\x39\x42\x24\x63\xfa\x50\x21\xc2\xf7\x45\x71\x3c\x20\xa7\x84\x97\xd5\x99\x7b\xec\x05\x5c\x54\xf3\xbb\x89\xcc\x4b\x95\xa8\xe7\xda\xf1\x8b\x5b\x91\x3b\x3b\x76\xf3\xb4\x87\xa3\xef\x20\x00\x4f\x17\x0d\x7d\x6c\x12\x0b\xeb\x1d\x27\x68\x47\xba\xfd\x1c\xfe\x2b\x76\x9f\x63\x29\x40\x03\x8f\x6b\x1d\x85\x01\x32\xef\x85\xd2\x53\x75\x20\x9b\xa7\xd8\xc2\x62\x57\xac\x20\xdd\x60\x06\xe9\x08\xae\xa4\x55\x84\xcf\xea\xb1\x18\x06\xe3\xb3\xb0\x1a\xd0\x6e\x10\xf9\xd1\x1c\xaf\x6e\x19\xfc\xb4\x7e\xb4\xa5\x74\xf5\x68\x45\xf3\xea\xf1\x28\xe2\xed\x5f\x60\xd0\xea\xd1\x11\xda\xda\xd1\x9e\xb4\xd5\x63\xfb\xd0\xa2\x75\xf3\xec\x10\x70\xb4\x7a\x74\x75\x36\xed\xd8\x21\x38\x69\xf5\x58\x12\x51\x3f\x4d\xac\xd2\xea\xb1\xb3\x91\x75\xf5\xd8\x35\xae\x69\xf5\x58\x48\x75\xfc\x44\x41\x4e\xbd\x66\x84\x13\xf9\x5a\xdb\x73\xfc\xbe\x15\x3f\xa9\x47\xc7\x20\xde\x2d\x32\x6a\xf5\x58\x14\x00\x5f\x48\x94\xd4\x8a\xa9\xbe\xd6\x66\x9a\xf7\x6b\x1f\xb6\x39\xee\x3e\xce\xc7\x29\x14\x3d\x97\x7a\xe3\xed\xd4\x18\x91\x5d\x48\xc0\xd2\x06\x18\x36\xe6\xed\x30\x9f\x27\x30\x6b\xf5\xe8\x8e\x71\xda\xd1\x11\xfb\xb4\xa3\x33\xe4\x46\x81\xe7\x2b\x6b\x17\x7e\x46\x59\xc7\x5a\xa6\xa3\xac\x13\x65\x9d\x2d\x46\x94\x75\x36\x1d\x51\xd6\x59\x37\xa2\xac\xb3\x62\x44\x59\x27\xca\x3a\xad\xc6\xfe\xc9\x3a\xd6\x52\xd5\x99\xc1\xec\x1f\xd6\xe0\xba\x68\x21\x43\x69\xca\x87\x04\x35\x4d\x65\x86\xf7\xdf\x38\x12\x7b\x8b\xe6\x35\x17\xe9\x2e\x29\x9f\x00\x79\xdb\x7f\xfb\x66\xc3\x74\xc2\xd5\xa3\x4d\xd0\x4f\x38\xb6\x4d\x3d\x5c\x1c\xeb\x3c\x12\x9f\xcc\xbb\xe4\x4e\x6a\xe5\xf0\x68\x48\x98\x6b\x1c\x44\x55\x55\xac\x1c\x34\xa1\xba\x61\x10\x67\x39\x54\x0e\xd1\x46\x0a\x73\x1d\x13\x2c\xb8\xf3\x77\x98\x4d\x1d\xec\xb6\x82\x04\xa8\x8d\x83\x1f\x41\xb5\x0a\x91\x83\x4d\x50\xf5\x87\xde\x2c\x01\x3c\xac\xc8\x11\x0c\x26\x03\x92\xda\x64\x6f\xca\x5d\xcc\xd9\x71\x2f\x74\x8f\xe7\x86\xb8\x4a\xfc\x3f\xb3\x6c\xe7\x1f\x87\x19\x70\x5d\xd2\x2c\x9b\x13\x98\xb1\x44\x57\xdf\x87\x01\x85\x4c\x5b\x67\x67\x1b\x57\x4a\x0b\xf1\xb0\xad\x48\xd8\x5f\x3a\x5b\xdb\xf9\xab\xfd\x68\x2f\xbb\x2d\xad\x63\x77\x7a\xb3\x20\x97\x58\x08\x0d\xd6\xaa\x55\xda\xbc\xcd\xfa\x2b\xf1\x9f\x88\xe0\x1f\xaf\x77\x75\x8f\x91\x8e\x78\x42\x6b\x3e\xb0\xa8\x40\x95\x59\x66\xd0\xdb\x7a\xcc\x96\x41\xb0\xc2\x93\xb5\x22\x5b\xc7\xba\x59\xf3\x20\x6b\x07\xef\xb9\x15\x85\xc8\xc4\x64\x1e\xee\xa0\xeb\x03\x53\x97\xc7\xa1\x44\x95\x23\x27\x02\x9a\x43\x74\xb5\xb0\xe5\xd1\x17\xb2\x76\x44\x5f\xc8\xd2\x88\xf6\x81\xc5\x11\xed\x03\x5b\x8c\x68\x1f\x58\x31\xa2\x7d\x60\x79\x44\xfb\x40\xb4\x0f\xb4\x19\xaf\xdf\x3e\x40\xa2\x2f\x64\xdd\x88\xb2\x4e\x3d\xa2\xac\xb3\xf9\x88\xb2\xce\xf2\x88\xb2\x4e\x94\x75\xa2\xac\x13\x65\x9d\x5d\x47\x0b\xe4\x2e\x44\xda\x79\x8a\x4c\x21\xd2\x47\x32\x64\xac\xbd\x3a\x11\xfd\x4c\x24\x55\x65\x12\xf3\x88\xf3\x7c\x28\x9a\x5b\x13\x7a\x8f\xfc\x4b\x70\xb0\xe9\x09\xb6\xe4\x6d\x0e\x44\x60\x13\x89\x42\xa4\x47\xea\x78\x87\xc0\xf3\x98\x61\x13\x33\x6c\x7e\x05\x19\x36\x53\xaa\x5c\xe1\x24\x24\xad\xeb\x13\x6e\x82\xe3\x7f\x0b\x32\xff\xd5\xe6\xdb\x18\x84\x73\x08\x83\x7d\xea\x6a\xa4\xb0\xb0\x4b\x9d\x6f\x17\xd2\x61\x13\x62\x4e\x2f\xb3\x2d\x7a\xd2\x14\x52\x52\x80\xec\x5b\x24\x13\x64\xcc\x5c\xfd\xb0\x05\xfc\x75\x10\x7e\xe1\x79\x33\x4d\x48\xbc\xe8\xe4\x99\xe6\xa7\x74\xe6\x9b\x0a\x5d\x74\x0d\xae\xf8\xe2\x52\x69\xba\xd1\x4a\xfb\x44\x3b\x77\xda\xb7\xad\xf4\xd2\xae\x94\x48\x54\xf2\x6e\xb6\x2a\x93\xbc\x7e\xac\x2c\x6e\xfb\x3f\x25\xc8\x39\x11\x33\x90\xb5\x62\x54\x75\xf7\xe9\x55\x4d\x6a\x12\xea\x0a\x28\x77\x63\xe0\xe9\xc4\x14\xd1\xa5\xa6\xde\xb5\xd7\x90\xec\x59\xf5\xe4\xf5\xa3\x5b\xc5\xa1\x43\xb5\xe1\xa5\xd5\x62\x5e\x3f\x3a\x35\xbf\x91\x8e\x4d\x70\xa4\x43\x33\x1c\xe9\xd6\x14\x47\x3a\x37\xc7\x91\x2e\x4d\x72\xe4\xb3\x57\x90\x5e\x3f\x3a\x36\x1f\x91\xce\xad\x74\xe4\x05\xd6\xa3\x5e\x3f\x3e\x01\xb8\xbb\xb4\xd8\x91\x58\xdd\xba\xf5\xe8\xda\xa0\x46\xba\x36\xaa\x91\xae\xf1\x70\xa7\x2a\xda\xeb\x47\xac\xaf\xfd\x09\xe4\xb4\xce\x84\x88\xb6\x35\xb9\x9f\x5a\x68\x07\x38\x59\xf5\xfe\xfd\x5c\x0a\x90\xe5\xd2\x75\xc3\x59\xf3\xee\xa0\xd7\x17\x86\x6a\x86\x8d\x51\x7d\xdc\x2a\x62\x34\xfe\x9e\x7a\x83\x57\xc9\x83\xe2\x71\xc1\x64\x4b\xad\x67\x6a\xd3\x59\xd5\x7c\xc6\x28\x05\x75\xd3\xaa\xe0\x61\xbc\x77\x60\xc3\x49\x6b\x69\x82\xa7\x8b\x01\xa6\xf5\x13\xa8\x5f\xd8\x76\xb8\x07\xde\x8e\x7d\xa8\xea\x3b\x0e\x06\x61\xe7\x5c\x37\xe3\xd1\xff\xf9\xbf\xc7\x8d\xea\x2d\xf5\x84\x51\xfb\xdb\x78\x44\xed\xaf\xd5\x88\xda\xdf\xda\x11\xb5\xbf\x16\x23\x6a\x7f\x9b\x8d\xa8\xfd\xad\x1f\x51\xfb\x8b\xda\xdf\x0e\x23\x6a\x7f\x51\xfb\xdb\x75\xfc\x8a\xb5\xbf\x6e\xa3\x9a\x43\x5d\xcc\x05\x89\xa0\xfc\xa8\xa9\x66\x49\x1d\xf1\xec\xef\xb2\xff\xea\x56\x07\x0c\xf5\xbb\xd5\x1a\x60\xa8\x25\x2e\x69\xc1\x83\x27\xd4\xbd\x4a\x21\x5c\x7a\xf2\x71\x4d\xf0\xb5\x45\x6e\x77\x86\x89\x81\x4b\xb8\x53\x54\xbc\xf5\x81\x65\x75\xe3\xf6\x2a\xea\x2c\x25\x47\xde\x17\x8f\x8d\x58\xb8\xd0\xcd\x8b\x5c\xb3\x7e\x7d\x47\xe5\x9d\xc7\xa0\x9a\x46\x3e\x7f\xc3\x85\x5c\xc5\xb0\x55\xf1\x51\x35\xf6\x18\xf2\x08\xb2\xb1\x06\x6c\x7c\x3b\x66\xdc\x46\x3a\xfa\xa6\x41\x82\xfb\xa0\x29\x4b\x4f\x6d\xeb\x05\x87\xe7\x56\xf4\xc5\xf5\xa0\xfc\x5b\xc3\x2e\x88\xf2\xa1\x78\xc8\x28\x77\xc9\xb0\x82\xfb\xae\xf6\xb6\x53\x7d\x2d\x2f\x57\xbd\x58\xaa\xb7\x0f\xc8\x05\x62\x7d\x38\x31\x53\x08\x1f\xd7\x26\xa2\x1b\x44\xde\xaf\xc2\x0d\xf7\x5b\x17\x6e\x58\x88\x18\x89\x75\x1b\x62\xdd\x86\x56\x75\x1b\xf0\xa2\x3d\xdc\x9d\x17\x70\x20\xff\x70\xed\x95\x24\x20\xa8\xf2\x32\xd3\xac\xa8\x23\xb0\x95\x7d\x55\x66\x35\x89\xb1\x8b\x04\x6d\xe2\xbb\x79\x1b\x4d\xa6\x8b\x78\x8f\xf3\x61\xc4\xb6\x42\x72\xe2\xa2\x2d\xb1\x19\x12\x56\x1c\xf0\x6a\x87\x0d\x29\x65\x2f\x3f\x52\xf0\x1c\x09\xb6\xaa\xb5\x66\xdb\xab\xcb\xd0\xf9\xcc\xa0\x84\xa1\xd8\x8f\x30\x88\xb0\xa1\x05\x46\xad\xb2\x19\xf0\x9a\x4b\x1c\xa9\xe3\x63\x2f\x0d\x75\xca\xbd\x3e\x09\xf7\xf9\x7b\xc0\x25\xfe\x7d\x13\xfe\x83\x1f\x54\x71\xa0\x1a\x7c\x35\xff\x79\xd9\x21\x91\xed\xa3\xdb\xba\xb0\xc8\x75\x16\xd5\xf6\xec\x11\x6d\xbf\xa6\xda\x17\x7b\xe9\xc3\xd8\x3b\xad\xe3\x75\xf8\x2d\x62\xc2\xe8\xe6\xe3\x25\x24\x8c\x3e\x93\x6f\xe2\xe5\xe4\x8d\xbe\x58\x7f\xc4\x4b\xc9\x1b\x8d\x3e\x88\xad\xc6\x6b\x4d\xe7\x6c\x8e\x0e\x7d\x0e\xd1\xdf\xd0\xb1\x4c\xd5\x09\xf3\xff\x34\x7e\x86\x4e\xf0\xaf\xd3\xe8\xb2\x18\x59\xf6\x9c\x91\x65\x51\x0b\x8b\x5a\x58\x73\x44\x2d\x6c\x69\x44\x2d\x6c\x8b\x11\xb5\xb0\xf5\x23\x6a\x61\xcb\x23\x6a\x61\x51\x0b\xdb\x60\x44\x2d\x2c\x6a\x61\x9b\x8e\x5f\x99\x16\xd6\x5d\xbd\xf5\x18\xe1\xf5\x09\x22\xbc\xba\xa1\x84\x1d\xd0\xbf\x4e\xb0\xae\xa3\x88\xae\x18\xcd\xb5\xdf\xd1\x5c\x2d\xcb\xce\x71\xcd\x3e\x4d\xe9\xb9\x70\xb7\xd7\xd5\x9f\xa3\x33\xc1\x52\x52\x94\xda\x55\xdf\x8a\x35\xe8\xf6\xb9\x06\x5d\x63\x47\x63\x21\xba\x8d\x0a\xd1\xad\x83\x59\xac\x46\xb7\x66\xec\x4f\x8c\x59\xac\x46\xb7\xed\x88\xd5\xe8\x56\x8f\x58\x8d\xee\x91\x11\xab\xd1\xc5\x6a\x74\xb1\x1e\x41\x8b\x11\xeb\x11\xac\x18\xb1\x1e\xc1\xee\x23\xd6\x23\xd8\x68\xc4\x7a\x04\xb1\x1e\x41\x73\x44\x2f\x54\xbb\x11\xeb\x11\xb4\x1c\xd1\x33\x15\xeb\x11\xb4\x9a\x30\x56\xa3\x7b\x55\x31\x83\x24\x6a\x7f\x51\xfb\xdb\x78\x44\xed\x6f\xed\x88\xda\x5f\x8b\x11\xb5\xbf\xcd\x46\xd4\xfe\xd6\x8f\xa8\xfd\x45\xed\x6f\x87\x11\xb5\xbf\xa8\xfd\xed\x3a\x7e\xc5\xda\x5f\xac\x46\xb7\xf7\xb1\x8a\x64\x1f\x33\x92\x62\x35\xba\x18\xbf\xb8\xd3\x76\xc7\x6a\x74\x4f\x8f\x5f\x7d\x35\xba\x46\x2c\xdd\xf3\x95\xa4\xdb\x7e\x19\xb1\x2e\x5d\xac\x4b\x17\xeb\xd2\xc5\xba\x74\xb1\x2e\x5d\xac\x4b\xb7\xf9\xd8\x7f\x6f\xc6\xde\xe9\x1f\xaf\xc3\x83\x11\x2b\x22\x6c\x3e\x62\x45\x84\xb5\x23\x56\x44\x88\x15\x11\xa2\x37\x62\x97\x11\x2b\x22\x6c\x39\xa2\xe7\x21\x56\x44\xd8\x6a\xc4\xba\x74\xaf\x26\xc6\x2c\x6a\x61\x51\x0b\x6b\x8e\xa8\x85\x2d\x8d\xa8\x85\x6d\x31\xa2\x16\xb6\x7e\x44\x2d\x6c\x79\x44\x2d\x2c\x6a\x61\x1b\x8c\xa8\x85\x45\x2d\x6c\xd3\xf1\x2b\xd3\xc2\x62\x5d\xba\xbd\x8e\xf5\x8a\x75\xe9\x56\x8c\x18\xd7\xb5\xdf\x71\x5d\x3b\xe2\x0a\x2d\xb5\xc8\x45\xc9\xf5\x0d\xc8\x19\x4b\xe0\x34\x49\xcc\x5f\xb7\xe2\x0e\xb6\x8c\x25\x6a\xaa\xa1\x8f\x4c\x4b\x18\x4f\x59\x82\x8a\xe4\xfd\x14\xb0\xac\x9c\x91\x6f\xf1\x3e\x42\xed\x8d\x44\xe3\x9d\x35\x7a\xe1\x3a\x0d\x51\xc3\x00\x1b\x9c\x7a\x5b\x78\x59\x08\x8d\x84\xc8\x80\xf2\x2d\x9e\x74\xdc\x10\xe4\x96\xa7\xb9\x01\x90\xf7\x8e\x14\xd7\x93\x91\x11\x64\x82\x4f\x5c\x3c\x8f\x3b\x01\x03\x72\x56\xdf\x90\x50\x8e\x87\xa7\x94\x12\xb8\xce\xe6\x08\x07\x2c\x70\x85\x5a\x43\x2e\x66\x90\x22\xc9\xc6\x30\x22\x2b\x47\x52\x4d\x32\xa0\xe6\x5d\x1c\xea\x97\x99\xc3\x43\xc9\x10\xe7\xb7\x93\x8e\xc0\x85\x36\xed\x04\xc4\xed\x69\xe3\x4e\xd4\x70\xc1\xb2\xe1\xc4\x26\xe4\x4b\x09\xea\x47\xc1\x17\xe2\xd1\x9c\x8b\x92\xdc\x53\x2b\x29\xc9\x92\xe3\x61\xc6\x4f\x37\xa0\xdd\xf2\xe5\x2d\x64\x92\xdd\xcd\x0f\x7d\xa4\x6a\x5b\x3e\xd6\xc6\x1c\x40\xe5\x64\x27\x26\xd5\xd8\x9a\xc3\x53\x39\x29\xad\x48\xe8\x50\x19\xb8\x96\x73\x8c\xb7\xb3\x32\x45\x80\x89\x39\x9d\xc0\xe1\xa1\x22\x67\x1f\xce\x0d\xf9\x2b\x95\xa1\xd6\xae\xca\x9e\x23\x87\x85\x14\x33\x96\x1a\xe4\xfe\x9e\x4a\x46\x47\x99\x91\x3b\xc7\x20\x81\x1b\xb1\xe0\x8b\xa3\xef\x4f\xaf\x7f\xbe\x3a\xfd\x70\x71\x8c\x12\x28\x3c\x14\x94\x9b\x53\x51\xaa\x3a\x50\xd4\xbd\xce\xbc\x08\xf8\x8c\x49\xc1\xcd\xfa\x50\x57\xa3\x64\xe6\x67\x4d\xaa\xc3\x20\x41\x89\x6c\x06\xa9\x95\x93\xab\xb7\x79\xae\xc3\x78\x51\x6a\xaf\x3b\x62\xf8\xa2\x39\x40\x3c\x99\x52\x3e\x31\xeb\x3c\x17\xa5\x99\xef\x8b\x2f\x70\x45\x12\xd2\x32\xb1\x92\x13\xf5\x58\xfb\x45\xcf\x73\x0a\x43\xeb\x95\x2d\x89\xa8\x12\x5a\xf8\x35\x87\x9f\xa5\xe6\x5c\xd3\x87\x77\x36\x7e\xef\xe0\x8b\xe0\xd2\x81\x2f\x27\x29\xcc\x2b\x2c\xbf\xb1\xab\xca\xb0\x92\x61\x46\x0e\xc2\xbb\x07\xe4\xc2\xbc\x03\xd2\x10\x80\x36\xfc\x12\x66\x20\x51\xf3\x74\xe0\xeb\x11\x09\x13\x2a\xd3\x0c\x14\x06\x1e\x7a\xda\x6c\xb5\x03\x07\x30\xa8\xf4\x5a\x2e\xf4\x2a\x62\x42\x3e\x08\x0c\x42\x1c\x8b\x77\x64\xaa\x75\xa1\xde\x9d\x9c\xdc\x95\x23\x90\x1c\x34\xa8\x01\x13\x27\xa9\x48\xd4\x89\xa6\xea\x4e\x9d\x30\x6e\x0e\x57\x3f\xa5\x9a\xf6\x83\x53\x7d\x62\x39\x77\x3f\x11\x79\x4e\x79\xda\xa7\x0e\xbb\xfa\xd5\xb6\x9e\xfc\xd6\xf1\xd4\x3e\xad\xee\x62\xbc\x4f\xfb\x6a\x0a\x59\x76\xb8\x03\x3e\xb7\x93\xf9\x5a\xc8\x7a\xad\x64\x3c\xf7\xed\xed\x0f\xf0\x45\x75\x5e\x2d\x0c\x06\xe4\x4a\x68\x17\x1f\xeb\x42\xb1\x91\x8e\x22\x7c\xd7\x1e\xe9\x8b\xab\xdb\xeb\x7f\x0e\x3f\x5e\x5e\xdd\xc6\x93\x1d\x4f\x76\x3c\xd9\x2d\x4e\x36\xf0\x59\xeb\x53\xed\x65\xce\xe0\x98\x54\xfb\x8d\x9c\x5a\x81\xf6\xc7\xa0\xda\x80\xd6\x12\xa2\x1d\xcf\x06\xf5\x06\x04\x2e\xf8\xec\x7b\xda\xb4\xb0\xf3\x95\xe0\x20\xee\x06\x2b\x28\x57\x32\x78\x9b\xf8\xf8\x16\xd6\xac\xb6\xee\xab\x9d\xa4\x48\x3b\xda\xbb\x96\xcc\xab\x77\x37\x34\x34\xb6\xef\x8a\xe6\x75\x85\xea\x15\xbb\x36\x20\x1f\xbc\xda\x43\xce\x7e\xbe\x3c\xbf\xb8\xba\xbd\xfc\xea\xf2\xe2\x7a\x77\x3d\xba\x03\x8b\x0b\xda\x14\x3a\x02\xc0\xe1\x8e\x5c\xb2\x90\x30\x63\xa2\x54\xd9\xbc\xb2\x82\xac\x26\x02\x8b\xa7\xdf\xf9\x7d\xe7\x95\x3e\xbe\xf2\xb1\xc8\x6c\xbb\x65\xb6\xe7\x30\xa6\x65\x66\xb5\xa7\x83\x83\xc1\x2e\x5c\xce\x8e\xae\xd0\xf7\x2b\x29\x5a\x54\x60\x6e\xa0\xf0\x8d\xad\xdd\x3e\x16\x72\xed\x31\x3e\x74\xd1\x07\x0d\xd6\xe3\x84\x47\x6b\xa1\x73\xd2\xa3\x75\x92\xb5\x84\x4e\x4b\x2f\x43\x37\xbe\xf7\x44\xf0\x31\x9b\x7c\xa0\xc5\xb7\x30\xbf\x86\x71\x3b\x33\x71\x13\xde\x68\x7d\x74\xae\x64\xb4\x55\x1a\x76\x66\x5f\xd6\xce\x4d\xd3\x99\x93\xa6\xab\xe8\x8c\xf6\x91\x19\xdd\x05\x52\x74\x12\x44\xb1\x54\x0f\xdf\xda\xa1\x9d\x45\xb9\xab\x18\x9b\x4e\x3c\xf7\xed\xb8\xbc\x1f\x4d\x66\x17\xb2\x7b\x47\x67\xf5\xa6\x6a\x47\x22\x78\x02\x85\x56\x27\x62\x66\x38\x17\xdc\x9f\xdc\x0b\x79\x67\xf4\x08\xa3\xbb\xf6\x2d\xd6\xaa\x13\xf4\x19\x9c\xfc\xd6\xba\xc1\x6e\x3f\x9e\x7f\x7c\x47\x4e\xd3\xd4\x35\x37\x29\x15\x8c\xcb\xcc\xb5\x13\x18\x10\x5a\xb0\xef\x41\x2a\x26\x78\x8f\xdc\x31\x9e\xf6\x48\xc9\xd2\x2f\x77\x27\xce\x7e\x74\xb8\x0b\xa2\xb0\xae\xce\x8e\x77\xe2\x06\x7d\x2c\xf3\x06\xef\xaa\x88\x88\xe1\x5a\x4c\x2b\xc4\x4d\x6f\x75\x76\x42\x46\x47\xa0\xd9\xde\x44\xbf\x38\x70\x0b\xbb\xa5\xab\x87\x35\x61\xb5\x2e\x4e\x87\xa8\x85\x48\xdf\x11\x55\x16\x85\x90\x5a\x91\x1c\x34\x35\x4a\xef\xc0\x60\x58\xaf\xf9\x27\xfa\xaa\x7a\xe4\xbf\xaa\x1f\xd1\xe1\xa4\x7e\x38\x3c\xfc\xfb\xb7\x17\xff\xfc\xf7\xc3\xc3\x9f\xfe\x2b\xbc\x8a\xac\xd0\x46\x01\x35\x6f\x51\x05\x24\x03\x2e\x52\xb8\xc2\x77\xe0\x9f\xaa\xe1\x66\x71\x17\x34\xd5\xa5\x1a\x4c\x85\xd2\x97\xc3\xea\xcf\x42\xa4\x8b\x7f\xa9\x16\x12\x07\xd9\x4f\xc6\x80\x5b\x34\xa4\x7a\xba\x27\xec\xa1\xa6\x25\x1d\x1f\x55\x37\x6b\xd8\x44\x27\xa7\xf8\xcf\xaf\x3c\x08\x8c\xf4\x74\x2f\x99\xd6\xe8\x7a\x73\xa9\xe0\x62\xdc\x33\xa7\xb6\x16\x3b\x67\x6f\x5b\xd7\x47\xe9\x94\xb4\x55\x3b\xd8\x31\xc0\x10\x22\x0e\x5a\xf6\x20\x57\x0c\x76\xd9\xc5\x7c\x3a\xbc\x24\x33\x0b\xe1\xbd\x01\x8e\x4f\xef\xfd\xea\x93\xd2\xb8\xaa\xe9\x92\x03\x55\xa5\x21\xbe\xb3\x41\x41\x55\x92\x31\xc9\x58\xce\x5c\xac\xa1\x6b\xd0\xa4\xc8\x91\xfd\x71\x90\x14\x65\xcf\xdd\x30\xc8\x21\x17\x72\x5e\xfd\x09\xc5\x14\x72\xa3\x69\xf5\x95\x16\x92\x4e\xa0\x57\x3d\x6e\x1f\xab\xfe\xb2\x0f\x36\x5e\xb0\xfc\xb4\x55\x85\x6b\x57\xa9\xa3\xc8\x90\xbe\x3e\xda\xe6\x41\xbf\x27\xa4\xad\xc2\x8c\xab\x4f\x20\x12\x56\x96\x38\x2b\x70\x56\x50\x44\x7d\x72\x26\xb2\x32\x07\xd5\xab\xc4\x20\x6b\x0d\xe0\x33\xa3\x59\xaa\xbd\x12\xd4\x52\x36\x63\xaa\x8b\x30\xe2\x15\x72\x1a\x73\x11\xf9\xa2\xd4\x45\xa9\x5d\xbd\x99\xa0\xb1\x9b\x50\x68\xb7\xa8\x8a\x02\x34\xc8\xfe\xdb\x83\xf6\xd1\xe8\x54\x6b\x90\xfc\x1d\xf9\xcf\xa3\x1f\x7f\xff\x4b\xff\xf8\xcb\xa3\xa3\x1f\xde\xf4\xff\xf6\xd3\xef\x8f\x7e\x1c\xe0\x3f\x7e\x77\xfc\xe5\xf1\x2f\xfe\x8f\xdf\x1f\x1f\x1f\x1d\xfd\xf0\xed\x87\xaf\x6f\x87\x17\x3f\xb1\xe3\x5f\x7e\xe0\x65\x7e\x67\xff\xfa\xe5\xe8\x07\xb8\xf8\x69\xc3\x49\x8e\x8f\xbf\xfc\xa2\xf5\xd2\x29\x9f\x7f\x6c\x49\x40\xed\xe8\x77\x56\x2e\x68\x71\xc6\x8e\xe2\xac\x1f\xfa\xb5\xd2\xd4\x67\x5c\xf7\x85\xec\xdb\xa9\xdf\x11\x2d\xcb\x76\xc4\xa4\x66\x4a\x5d\x9f\x7f\xdf\xbd\xeb\x5d\xcd\x90\x2a\x76\xbd\x37\x07\x5c\x41\x22\x41\x7f\x0e\x4b\x8e\x7d\x93\x97\x53\x16\x62\x1e\x5f\x1b\x9f\xfb\x35\x18\x77\xaa\x90\x41\xdc\xd7\x5a\x12\x1d\x4b\x91\x0f\x48\xe0\xde\x98\x61\xc2\x87\xbb\xef\x0e\x5a\x58\x41\xfd\x88\xc6\xa0\x68\x0c\x5a\x33\x9e\x34\x06\xdd\x58\x3c\xdc\x5b\x4b\x10\xf0\xd9\xae\x2e\x8c\x95\x1e\x74\xaf\xeb\x68\x41\x0a\x51\x94\x19\xd5\x6b\x3c\x63\x2b\xdc\xe9\xee\xa8\xd7\xf1\xc8\x75\x30\x8d\x65\x68\xf9\x6a\x1f\x26\x39\xcd\x32\xc2\xb8\x3d\xf8\x38\x81\x77\x98\x49\xb0\xaa\x0d\xa1\xd6\x9f\x3d\x33\x4b\xb8\x77\x65\xe5\xc2\xb8\x1c\x45\x94\xa6\x52\x63\xec\x31\x96\x9d\xb3\xac\xc4\x79\x9f\x18\xaf\x8b\xcf\x55\xc2\x61\x95\x0b\xb2\xb2\x33\x66\x46\x95\xf6\xcb\xc6\xd5\x68\x7a\x87\xde\xc6\x04\x52\xe0\x09\x60\x62\x5a\x09\xf5\xb7\x8e\x8c\xde\x46\x2e\xf8\xcc\xce\x41\x49\x5a\xda\x60\x10\x4b\xfe\x56\xcf\xf1\xba\x02\x10\x0c\x22\xde\xf8\x06\xc6\x55\x1c\x02\x52\xfd\x4a\xc3\xae\xf2\xfb\x2a\x2b\xab\x7a\x9e\xc8\x83\xf6\x3c\xb3\xf2\x6c\xb5\x12\x86\x96\x98\x65\x6d\x7e\x6e\x32\xc9\xd7\xe0\x0c\x6c\xcf\x3e\x7f\x75\xac\xb3\x23\xb6\xd9\x0d\xcb\xdc\xc2\x77\xd2\x25\x9b\xec\xc2\x59\x52\x48\x18\xb3\x87\x8e\xce\xe9\x29\xaf\x2d\x31\x2c\x05\xae\xd9\x98\xd9\x9e\xf7\x85\x84\x02\x78\x5a\x15\x2e\xc5\xe4\x70\xde\x84\xcd\x5e\x06\xf3\x58\x81\xbb\x5b\x52\x76\xb3\x4a\xd8\x8f\x74\x8c\x44\x3a\xb6\xf3\xf8\x4c\x74\xcc\x61\xee\xfe\x10\x31\x8c\x3c\x6f\x1f\xfd\x7e\xd6\x0c\x65\x47\x44\xde\x1a\xd1\xea\xcc\xae\x13\x9c\x45\xd9\x2c\xc9\x2a\x0d\xbb\x22\x8d\x5a\xd8\xe0\x35\x32\x65\x13\x03\xd9\x0c\x66\x90\x39\xb9\x89\xe4\x94\xd3\x89\xcd\xef\xd6\xc2\x9b\x6a\x8d\xa2\x65\xf0\x58\xb2\x74\x29\xee\x1e\xe5\x78\x83\xdb\x99\xa0\x29\x5e\x94\x22\xcb\x40\x2a\x92\xb1\x3b\x20\xe7\x50\x64\x62\xee\xd2\xb5\x79\x4a\x6e\x34\xd5\x06\xab\x6f\x40\xef\xe6\xf6\x6d\x85\xb1\xb8\xe2\x61\x99\x65\x43\x91\xb1\x64\x27\xa3\x4a\x73\xe7\x2e\x71\xbf\x8a\x32\xcb\x48\x81\x53\x0e\xc8\x47\x8e\x44\xe3\x34\xbb\xa7\x73\xd5\x23\x57\x30\x03\xd9\x23\x97\xe3\x2b\xa1\x87\x56\xfa\x6e\x06\xdc\xd9\x1b\x09\x1b\x93\x77\x58\xdd\x46\x13\x4d\x27\xa8\x3b\x79\x37\x60\xcf\xc0\x3f\x9c\xc0\xd2\x87\x7b\xa6\x56\x2a\x2b\xad\x11\xe7\xb7\x38\x93\xa1\x55\xf6\xef\xcf\xbe\x4d\x19\x1b\x43\x32\x4f\xb2\xf6\x47\xeb\x34\xc1\x00\x86\x3a\xe3\x3c\xc0\x6f\x57\x4d\xdd\xe5\x78\xa2\x16\xc8\x38\xb1\x65\xce\x6d\xfd\xf6\x1a\xd5\xab\x15\x59\x6d\x57\x75\xaa\x24\xee\xcc\x3c\xdb\xb2\xcd\x42\x28\x7d\x63\x34\xf4\x4e\x8a\xa1\x1f\x0e\xfd\x74\x04\x4b\x3e\x67\x19\xa4\x84\xe5\x39\xa4\x46\x8b\xcf\xe6\x84\x8e\x35\xe6\xda\x36\x2c\x04\x89\x04\x8b\xb5\xae\x8a\xc9\x94\xf2\x34\x03\x49\xc6\x94\x65\xce\x1e\xd0\xb8\x5f\x83\xcc\x19\x47\xb3\x80\xf5\xc8\xa2\x89\xc1\xfc\x95\x24\x42\xfa\xf2\xf4\x4c\x2b\x7f\xa9\x3e\x98\xc8\x47\x02\x04\x58\x74\x2d\x93\x51\x26\x92\x3b\x45\x4a\xae\x59\x66\x17\x23\xc4\x1d\x49\x44\x5e\x64\x78\x74\x5a\x9c\xac\xea\x9f\xfd\x0a\x95\xfa\x66\x76\x75\xf2\xdb\xfa\x12\xfe\xb0\x2b\x43\xef\x40\x10\xeb\x42\x0c\x83\x07\x48\x3a\xcb\xf3\xbf\x78\x80\x24\x28\x2c\x81\xfd\x18\xf0\x44\x63\x9e\x27\xbd\x83\x57\x54\xc9\xae\x45\x2e\x5d\x38\x1a\xf0\x3b\xb3\x73\xfa\x42\x58\xee\x15\x24\x63\x1c\xe9\x9b\xcb\xaf\x23\x8c\x2b\xc3\xd9\x1b\x87\xc1\x1e\x3d\x27\xb4\x92\x94\x49\xac\x82\x30\xaf\x02\xa9\xfd\x5c\x58\x60\x40\x08\x4d\x8e\x0e\x4f\x0e\x8f\x97\xec\x8f\x87\x46\x02\xc9\xc0\xd2\x5a\x9f\xb8\x57\x2d\x4a\xb1\xbc\xc8\xe6\xb8\x8e\xc3\xb4\x47\x98\xf6\x91\xd6\xb2\xe4\x7e\x55\x2e\xe9\xaf\x47\x94\x20\x5a\x52\x5f\x5d\xc5\xfe\x6a\x6e\xd2\xb2\x74\x54\xfe\xe8\xf0\x97\xc3\x1e\x01\x9d\x1c\x93\x7b\xc1\x0f\x35\x2e\x7f\x40\x6e\x85\x11\xa5\xeb\x89\xe6\xa2\x24\x1c\x6c\x60\x3f\x3c\x14\x19\x4b\x98\xce\xe6\x48\xb1\x88\x28\xb5\xcd\x21\xa6\xda\x27\x1b\x5e\x3c\x30\xed\xe2\xd5\x0c\xc9\x78\x83\xd0\xb4\x54\x8b\x50\x23\xe6\xcc\xe0\x64\x0a\x34\xd3\x53\x1b\x24\xc2\x05\xef\xff\x0b\xa4\xc0\x1c\x44\xee\xae\xbc\xba\xaa\x7f\x9d\x68\x0e\x86\x88\x7e\x0d\xdd\x35\xf1\xf9\xe6\xf6\x76\xf8\x35\xe8\x05\x92\x61\xde\xe2\x43\x77\xd0\x1a\x00\x72\x2c\x64\xbe\x07\xb4\xa3\x1b\x67\x65\x9f\x14\x42\xee\x03\x09\x9b\x0a\xd5\x6a\x2f\xc9\xd2\x7e\x0a\xa5\x51\x1b\x72\xd2\x18\x87\xc4\xec\x60\x33\x86\xc4\xf7\xb9\xb9\x1c\x0e\xc8\x3f\x45\x69\xbe\x66\x44\x47\xd9\xbc\xaa\xc4\xa0\x40\x93\x03\x33\xd5\x81\x21\x4f\x06\x1b\xbe\x01\x9a\x1a\x15\xc5\x50\x0f\xa0\xfb\xd1\xcf\x8a\xb8\xf3\xe0\xd6\xd6\x2d\x1f\x28\x95\x16\x39\x99\xba\xcf\x6e\xa6\x5e\xba\x93\x31\xc0\xd3\xe3\xf3\x9a\x24\x14\x96\xc2\xb9\x67\x5e\x1d\xfd\x5a\xa2\x1b\x16\xee\xee\xf7\x11\x96\xb1\x4a\x42\xb0\xb9\x86\x4e\x36\x31\x88\x5b\x60\x19\x54\x83\xdd\x5c\x25\xe1\xd8\xe3\xda\xa3\x3b\x27\x72\x2e\x4e\x84\x4e\xbd\xf6\xb1\x5e\x9d\x56\x1e\xed\x26\x6e\x80\xac\x32\xb2\x3a\x9c\xb1\xd6\x17\x6b\xcf\x41\x73\x8c\xf7\xa1\x26\x94\x0b\xce\x12\x9a\xb1\x7f\x41\x4a\xca\x42\x70\x17\x3f\x87\x72\x4e\x42\x15\xf4\xd1\xa9\xcb\xb5\xab\x99\x56\x67\x2b\x9a\xe3\xa8\x85\x40\xe1\x03\xdd\x78\x86\x3e\xda\xf7\xed\x6f\x81\xcd\xcf\x01\xe6\x6e\x50\x8c\x74\x09\x81\xa2\x83\x00\xf2\xe5\xf0\x71\x2d\x8c\xb6\x8b\x09\x9e\x96\x84\x23\x31\x52\x20\x67\xed\x51\xa0\xbb\x4f\x17\xbb\xdb\x15\xfc\x58\x91\x8d\x2d\x09\x2f\xf3\x11\xc8\x3a\xff\x45\xea\x65\x80\x04\xf1\x0f\x57\xf6\x76\x6f\x34\x6e\x36\x69\x34\x4f\xfe\xe5\xcf\x7f\xfe\xe3\x9f\x07\x76\xfa\x2a\x16\x82\x93\xcb\xd3\xab\xd3\x9f\x6f\xbe\x3f\xc3\x14\xdc\xb6\x50\xed\x28\xd0\xb3\xeb\x30\xcf\x4e\x83\x3c\x3f\x69\x88\x27\x26\x96\xb4\xa6\x22\x4d\x0f\x03\x4e\x69\x30\xc0\x68\x87\x46\xaf\x75\x12\x66\x50\x12\xcd\x48\xb4\x4d\x73\xad\x39\x6a\x7b\x71\xc6\x74\x52\xdc\x88\xe4\xae\x43\xed\xe9\x1c\x0a\x09\x89\xb5\xc6\xdd\x9e\x0d\xed\xec\x46\x8b\xbd\xfa\x78\x5b\x27\x34\x60\xd4\x0f\x79\xef\xad\x58\xdf\x38\x7b\x9d\xd1\x7c\xef\xa0\xd0\x95\x81\x60\x44\x93\xbb\x7b\x2a\x53\xb4\x9f\x51\xcd\x46\x2c\x63\xb6\xc4\xb0\x6f\x3d\xc9\x85\x0d\x2b\xb4\xa5\xd4\xc4\x78\xb1\x80\x67\x6d\x74\x45\xc3\x98\x65\x81\x63\xca\x32\xb4\xd3\x96\x5c\xb3\x1c\x5c\xdc\x51\x52\x54\x86\xc3\xd0\x72\x1e\x55\x3c\x3f\xf6\x56\xc5\x3b\xfc\xe8\x7d\x87\x5b\x6b\x7b\x6d\xa3\x1f\xf7\x98\xd5\x39\x16\x67\xd3\x4e\x22\xab\xfb\x55\xb0\xba\x42\xc2\x8d\x16\x45\x47\xbe\x18\x3b\xd9\x1a\x4f\xcc\x08\xc6\xc2\x10\xe1\xb5\xae\x15\xdf\x89\x98\x63\x0a\xa2\xb7\x9d\x89\x86\xfb\xc4\xc6\x7d\xaa\x32\x99\x7a\x33\x28\x07\xa5\x4e\xd0\xe9\x52\x16\x56\x37\x46\x72\x5d\x4a\xe8\x99\xaf\x83\x1c\x57\xd7\xab\x73\x29\xcc\xeb\x81\xdb\x1f\x41\x27\xd6\x3e\x1c\x10\x72\x2c\x3f\xea\x96\xbf\xe8\xac\x49\x24\x55\x53\xc0\x22\x26\xf0\xc0\x7c\xcf\x95\xa1\x48\x0f\x0f\xeb\x4f\x31\x8c\x65\x22\x69\x02\xa4\x00\xc9\x84\x61\x46\x25\xd7\xa9\xb8\xe7\x64\x04\x13\xc6\x95\x07\x85\x99\xdb\xc3\x0c\xbd\x3e\x4c\x55\xe5\xe7\x06\xe4\xba\x51\x52\xc5\x25\x3b\x25\xa2\x3e\x9a\x6e\xcd\x8b\xfe\x2a\xe4\x58\x41\x63\xe6\x0a\xc2\x3e\x08\x57\x6f\xb0\xe4\xa3\x92\xe3\x9b\x53\xc8\xe8\xdc\xc6\xb4\x8e\x19\x47\xcd\x51\xaa\xe3\x0e\xfc\x5a\x06\x84\xf5\xb5\xb5\xeb\xc0\x86\x00\x34\x99\xb6\x73\x31\x47\x47\xd8\x86\x23\x3a\xc2\xda\x4c\x12\x1d\x61\xd1\x11\xf6\xc4\x88\x8e\xb0\xe8\x08\x5b\x18\x7b\xab\x25\x45\x47\xd8\xce\x23\x3a\xc2\x1e\x1f\xd1\x11\xb6\xc1\x88\x8e\xb0\x0d\x47\x74\x84\xad\x1f\xd1\x11\xd6\x6e\x31\xd1\x11\x16\x1d\x61\x6e\xfc\xfa\xac\x83\x7e\x44\x47\xd8\xd2\x24\xd1\x11\x16\x1d\x61\x1b\x8f\xbd\x55\xf1\xa2\x23\xcc\x8e\xe8\x08\x6b\x8e\x5f\x17\xab\xf3\x6e\xa4\xa1\x51\x28\xdb\xe7\xe7\x0d\xd1\x75\xc1\x12\xe7\x8d\x0a\x1b\xe0\x55\xaf\x0a\x7a\xde\x05\x25\x4e\x7c\x5a\x91\xf3\x3b\xd5\xde\xac\x95\xb9\x5f\xdb\x3a\x44\x7c\xc2\xa4\x3a\x29\x84\xfd\x4f\xed\x0e\x09\xfc\x20\x56\xad\xde\x3d\xff\xee\xd9\x32\xcb\xda\x38\x3f\x3e\x8f\xe3\x63\x4f\xbc\x44\x1d\x38\x3b\xa2\xa3\xe3\xd5\x39\x3a\x5e\x4f\x07\x60\xe7\xff\xbf\x9d\x4a\x50\x53\x91\xed\x8c\xe8\x0d\x24\xff\xc0\x38\xcb\xcb\xdc\xe0\x9c\x32\xf8\xcc\x66\x55\xa0\x81\xaa\xd0\xd5\x52\x6c\x6b\xab\x34\x37\xb2\x14\xb0\x70\x2b\x65\x99\xd9\x46\xcc\x45\x9d\xd2\x99\xc1\x75\x55\x26\x09\x00\xb6\x85\x0b\x35\x9c\x3f\x0e\xaa\x37\x55\x6d\x40\xde\xb6\xa3\x37\xed\x98\xb8\x2d\xad\x8a\xb3\xfc\xf1\x0f\x3b\xcd\x31\x91\x45\x37\x74\xf9\xeb\xeb\xe1\x59\xd8\xf2\x9b\x7b\xb2\xcc\xf8\x4c\x64\x08\x55\x6a\x6f\x32\xc2\xda\x33\x12\xe9\xf6\x6a\x47\x2b\x95\xa3\x0b\x1e\xd1\x56\xaa\x6e\xda\xcd\x8c\xec\xdc\xb4\x1c\x4d\x70\x2f\x6d\x05\xff\x8d\x65\xe7\xd6\xd4\xad\xbd\x3c\xdb\xfe\x38\x10\x2c\xb1\x83\x1f\xde\x19\x80\x0f\x5c\xcb\x69\xcf\x82\x43\xc5\xc5\x77\xb5\xd2\x82\x14\x19\xad\xfb\x52\xe1\x0e\x7c\x83\x7c\xe3\x6c\x0a\xc9\xdd\xb5\xf3\xd1\x1e\x29\x80\x4a\x9e\x9c\x30\x3d\x2d\x47\x83\x44\xe4\x27\xe6\x18\xdb\xff\x8c\x32\x31\x3a\xc9\xa9\xd2\x20\x8d\x88\xe9\xd8\x52\x3f\x31\xb3\x30\x3e\x19\xe4\xe9\xf1\x80\xfc\xc8\x6d\x76\x7d\xdd\x07\x33\xa8\x2d\x61\xde\xef\xeb\x7c\x8c\xc0\x50\x44\x21\xc3\xf6\xe5\xa3\x39\x2e\x6f\xd0\xa6\x50\x73\x6b\x36\xd2\xd2\x3f\xfe\xf9\x7d\xe3\x91\x72\x91\x0e\x8c\x24\x2f\xcd\x07\xde\x59\x2c\x48\x07\xbe\xef\x3d\xf2\x7b\xef\x8d\x38\xbb\x2f\xbe\xee\x3d\xac\x76\xdd\x81\x7f\xbb\x0b\xdf\x76\x77\x7e\xed\x4f\x50\x14\xfa\x25\xfb\xb3\x3b\x34\xfa\x75\xe4\xc7\xfe\x1c\x3e\xec\x4e\xbe\xba\xad\xef\xfa\xf3\xf9\xad\xbb\xf9\xdc\x2e\xd5\x8d\x97\xea\xab\xee\xc0\x78\xdf\xa5\xe1\xbe\x33\xa3\xfd\x27\xf3\x4d\xb7\xf7\x4b\xef\x81\x4f\xba\x35\x90\x19\x67\x9a\xd1\xec\x1c\x32\x3a\xbf\x81\x44\xf0\x74\x67\x3e\xb6\x50\x8b\xb4\x3a\x3f\xca\x4e\xeb\x2c\x58\xcd\x44\x8f\x29\x75\x25\xd7\x8d\xde\x66\x13\x5b\xbc\x97\xc3\x89\x2d\xe8\x6f\xb6\xab\xdc\x4b\xbf\x05\xd9\x1b\x53\x99\xcd\x7a\xe9\x72\x13\xbf\x11\xf7\x44\x8c\x35\x70\x72\xc4\xb8\xdf\xc7\xe3\x40\xd9\xac\xed\x96\x15\x5a\x9b\xab\x6f\xdf\xf8\x9b\x5f\x9f\x41\x12\x4d\xaf\x4a\x7d\x7a\xfb\xb0\x7b\xd1\xd3\x06\x62\x77\xe3\xb8\xcc\x9a\x46\x62\x6b\x38\x6e\xd2\x9b\xb7\x75\xd1\xe8\xb7\x38\x6f\x75\xda\x28\x4f\x89\xcb\x84\x7b\x7d\x9b\xd6\x3a\xe2\xa6\x29\xfa\x55\x11\x36\x4f\xd9\x93\x6f\xcf\x86\xd1\x9c\xbc\x5f\x46\x99\x67\x8a\x5a\xd9\x43\x41\xf7\x85\x46\xaa\x44\x41\x77\x8b\x11\xe4\xc6\x7e\x2d\x69\x02\xc3\xce\x65\x04\x7f\x9c\x48\x5a\x4a\xea\x08\x60\x25\xf2\xf9\xc3\xc3\x01\x52\x7b\x9a\xaa\x7c\x62\xcc\xd4\x1d\x97\x59\x36\xb7\x36\x87\x46\xf6\xb5\xf5\xc2\x2f\x26\xf3\xa2\xe1\x7f\xc5\x5b\x6a\xc1\xb2\x90\xc2\xf1\x4c\x59\x72\x6e\x68\x70\xdd\xf9\x0d\x05\x49\x2c\x46\x4d\x1b\x29\xc3\x8a\x4d\xcc\xf2\x0d\xff\xc3\x6c\xe2\x3a\x34\xb1\x31\xa1\x79\x7a\x2c\x64\xc2\x46\xd9\x9c\x4c\x69\x56\xb5\xf9\xa1\xe4\x8e\x65\x99\x9b\x66\x40\x6e\x40\x5b\xc7\x85\xe5\x9d\x99\xe0\x13\x5c\x1c\xe5\xbe\xbd\x24\x24\xe6\xd9\x24\x03\xca\xcb\xc2\xbe\xcf\x70\xe2\xb9\x28\xa5\x7f\xdf\xa0\x72\x7f\x54\x1c\x98\xb3\xac\x17\x34\xb1\x7b\x74\x63\x6b\x13\x8d\x32\x02\xc0\x47\x5f\x7c\xbb\x17\xce\xe9\xeb\xa3\xab\xa0\x85\x51\x21\xc5\x8c\xa5\xd6\x87\xe2\xc1\x86\xed\xb2\x6d\x9b\xa2\xea\x3c\x73\xc1\xfb\x1c\x26\x14\x05\x15\x77\x8a\xec\x9e\xd9\x79\x6c\x6c\x01\x4f\xb1\x71\x91\x91\xf0\x45\xd1\x48\xe7\x9f\x31\xdb\x72\x39\x80\x1c\x39\xe2\x82\x08\x8c\x54\x2d\x39\xd3\xb6\x8d\xff\xb4\xd4\x24\x15\xf7\xfc\xd8\xd9\xac\x98\x22\x94\x8c\x40\xd3\x20\xd6\xd4\x31\x38\x45\x80\xd3\x51\x66\xf6\x1c\x43\xb1\x6e\x57\x02\x88\x8c\x81\xea\x52\x02\x99\x50\x0d\x2b\xe5\x1c\xfb\xbd\x8f\x83\x97\x29\x67\x60\x1d\x93\x92\x2b\x68\xc9\xde\x3b\x13\x8e\xfe\xf2\xa7\xdd\x68\x04\xcb\x41\x94\xfa\xb3\x68\x7f\xf7\x53\x96\x4c\x43\x61\x96\xe5\xa0\x88\x28\x17\xd4\xe2\xb7\xee\xb1\xd5\x3b\x14\x55\xc0\x55\x63\x57\xf3\xf1\x0a\xeb\xd7\x62\x39\x86\xba\xbf\x37\x46\x90\x9f\x5f\xdd\xfc\xfc\xfe\xf4\x3f\x2e\xde\x0f\xc8\x05\x4d\xa6\x61\x4d\x0e\x4e\x28\x12\x0d\x24\x14\x53\x3a\x03\x42\x49\xc9\xd9\xff\x94\xce\xad\x7c\x54\x3d\x7b\xdc\x69\x45\xfa\x1d\xb9\xaf\xa1\x36\x3b\x61\xfc\xca\xa6\x77\x38\x9b\x8b\xd8\x12\x0a\xb0\x4d\xcd\x92\xf8\x54\xf9\xb2\xe7\x56\x45\x40\x81\x0b\x03\xeb\xcf\x3f\x5e\xdc\x60\xc0\x7e\x21\x6d\xa5\x12\x8c\xf0\xc2\xeb\x38\xd3\x08\xcc\x13\xae\x3f\xf1\x80\x9c\xf2\xb9\xbd\x68\xcf\x14\x53\x24\x63\x4a\x03\x72\x3d\x27\xb6\x79\x2f\xf9\xc1\x9b\x01\xfe\xef\x80\xd0\x34\x95\x46\xae\xab\x02\xd7\x92\xa5\x48\x52\x2b\xf9\xb1\x51\x16\x7c\x00\x07\x6d\xe3\xd4\x3e\x88\xd4\xad\x1c\x39\x09\x7a\xc8\x2c\x1b\x54\x5a\x52\x0d\x13\x96\x90\x1c\xe4\x04\x48\x41\x75\x32\x25\x39\x9d\x93\x44\x48\x59\x16\xb6\x9b\x41\x4a\x35\x1d\x90\xaf\x84\x24\xb9\x3f\xc4\x06\xe7\x0d\x1f\xbe\x59\x1d\x39\x50\x9f\xec\xf0\x9f\x4c\xa9\x12\xd4\xc9\xdb\x37\x7f\xfd\xc3\x9f\xff\xfc\xaa\x1a\xe0\x55\xa1\xbd\x18\xf7\x12\x34\xc0\xa3\x7e\x17\xec\xae\xdb\x86\x88\x8c\x4f\xb2\x10\xbf\x76\x63\x00\x6d\xb5\xcc\xb6\x3a\x66\xbf\xfe\x82\xe1\xae\xaa\x66\x27\x8d\xf8\xea\x35\x74\xd4\xbe\xaa\xe6\x83\x5e\xb1\x72\xb4\x41\x84\x1d\x89\x2f\x87\xfe\x60\x3a\x39\x27\x5f\x68\x63\x5b\xd4\x31\x50\x3d\xf2\x86\xfc\x9d\x3c\x90\xbf\xa3\xa2\xf5\x97\xb6\xcd\xbe\xda\xaa\x40\x5d\x84\x34\x19\xfd\xfe\x72\xd8\x11\xc4\xff\x61\x88\xa6\x99\xd1\x40\x55\x0b\x32\x62\x4e\xb0\x87\x07\x0d\xd2\x08\x9a\x6e\x27\x9e\xb5\x4d\x9a\x59\xe0\x67\x44\x33\xeb\x78\xb8\x1c\x37\xc3\xa8\xb6\x43\x34\xf3\xf8\x37\x42\xe9\x2b\x47\x85\x9a\x0d\x7f\xea\xd9\x72\x24\xfc\x0d\x32\x66\xf8\x86\xd2\xf5\x01\x53\x24\x15\x18\xd5\x65\x43\x9c\xa7\xac\x45\xb0\xc6\xfe\xa0\x71\x3b\xff\x7d\x63\x3f\x1f\xdb\xa9\x05\x53\x0a\xea\x40\x4e\xc4\x0a\x6a\x74\x15\x22\x75\xd2\x99\x59\x56\x1a\xf0\x8c\x47\xc4\x33\x67\xb5\xa9\xec\xcd\x88\x4b\xe6\x3c\x25\x94\xdb\x24\x93\x31\x48\x69\xa3\xd2\x47\x73\x1f\x1c\xd8\x7a\xf3\x5a\x9d\xa4\x42\x0a\x2d\x12\xd1\xa2\x93\x5b\xd3\xdb\xed\xa6\x43\x20\x14\x16\x77\x1d\xe4\xbf\x3b\x1f\xf6\xc8\xed\xd9\x10\xbb\x5b\xdd\x9c\xdd\x0e\x9b\x3a\xcb\xc1\xed\xd9\xf0\xe0\x59\x41\x41\xbc\xc0\x87\x26\xea\x1d\x26\x69\x98\xa0\x8c\x34\xd9\xcf\x69\xd1\xbf\x83\xf9\x8e\x3c\xb5\x0b\xbe\xde\xaf\x76\xb8\x93\x0f\xb2\x60\xce\x69\xb1\xf5\x6c\x12\x68\xca\x3e\x53\xa6\x97\x0f\xbb\xad\xde\xb9\x3a\xe5\x2b\x17\x33\x48\xad\x94\xee\x9f\x00\x9e\x16\x82\x19\x79\x31\xe6\x81\x6d\xff\x74\xcc\x03\xdb\x78\xc4\x3c\xb0\x98\x07\xb6\x3c\xf6\x26\x70\x36\xe6\x81\xbd\x2e\x0f\x7e\xcc\x03\xdb\x7e\x3c\xbb\xe3\x3e\xe6\x81\xad\x1e\x31\x0f\x2c\xe6\x81\x6d\x36\x62\x1e\xd8\xf6\x63\xef\x42\x8e\x62\x1e\xd8\x56\x23\xe6\x81\x2d\x8f\x98\x07\xb6\x66\xc4\x3c\xb0\x35\x23\xe6\x81\x2d\x8f\x98\x07\xb6\xdd\x88\x79\x60\x31\x0f\xec\x55\x87\xc7\x92\x98\x07\xe6\x46\xcc\x03\x7b\x15\x41\x80\x24\xe6\x81\x6d\x34\x62\x1e\x58\xcc\x03\xdb\x65\xc4\x3c\xb0\xd7\x62\x94\x89\x79\x60\x31\x0f\xec\xd7\x23\xe8\xc6\x3c\xb0\x98\x07\x16\xf3\xc0\x62\x1e\xd8\xa3\xab\x88\x79\x60\xaf\x41\x05\x94\xa0\xd8\xbf\x60\x28\x32\x96\xcc\x5b\x47\x29\x5e\xbb\xc6\xc7\xca\x4d\x4b\x0a\x9c\x37\x08\xad\x6a\x91\x79\xb2\x67\x09\x37\xd7\x01\xe0\xc2\xc4\x9b\xaa\xf9\xf3\x27\x00\xc1\x5e\x24\xdf\xf8\x0f\xbc\xda\xdd\x93\xd2\xf7\x0d\x08\x2c\xf8\x76\xb3\x5b\xb4\x56\x11\xc2\x0f\xe9\x28\x1e\xfc\x30\xcc\x88\xac\x30\x41\x8b\x8a\x82\xb1\xb5\x08\x42\x8b\x22\x63\xa0\x06\xe4\xa6\x6a\xc0\x83\xd4\x4b\xbd\x23\x49\x51\xf6\x48\x0e\xb9\x90\xf3\x16\xda\x44\x07\x02\x67\x63\xd7\x3a\x02\xd9\xb5\x9d\xd3\x83\xc1\x28\x11\x45\x91\xcd\xad\x30\x55\xa7\x92\x56\x50\x63\x9e\xb8\xa4\x28\xee\x2c\x44\x79\x30\xdd\x50\xc3\xae\x84\xbe\x76\x08\xff\x6c\xb1\xf6\xeb\xa2\xca\xa9\x16\x39\x4b\x76\x21\xd8\x96\xc6\xb6\x8f\x29\x3f\x13\x79\x51\x6a\x68\x90\x6d\x0b\x2c\x2b\xc9\x31\x15\xaa\x70\xed\xa3\xc1\x13\xc1\xc7\x6c\xe2\x44\xf1\x13\xdb\xd1\xbd\x5f\x7d\x4f\x3f\xe8\xa2\xfe\x02\x43\xc1\x93\x8c\xb2\xdd\xfd\xf6\xcd\xd0\xaa\x33\x9c\x0b\x33\x74\xeb\xe0\x2a\x8c\xd1\xad\xa0\xd5\xab\x02\x97\x98\x3d\x26\x03\x7f\xc9\x3e\xdc\xb3\x91\xbe\x46\xff\x40\xa1\x73\xc5\x86\xfe\xc8\x6b\xf1\x98\x13\x9a\x15\xd3\xc7\x05\x64\xb3\x90\xf3\x39\xa7\x39\x4b\x3c\xc6\x9c\x66\x99\x48\xac\x42\xd4\x14\x91\xfd\xdc\x76\x3e\xf3\x92\x3c\x2f\x35\x1d\x65\x30\x20\x97\x36\x43\x48\xf0\x6c\x6e\xb0\x49\x81\xf6\x8e\x0f\xb7\xfd\x3b\xc7\x60\xb5\x0f\xc0\x68\x19\x7c\xb1\x52\x1a\xc2\x0d\xb1\xd9\x50\xc0\xcd\x29\x13\x1c\x08\x70\x2d\xe7\x66\xef\x86\x22\xbd\x31\xdb\xd7\xb8\xbb\x75\x92\x54\xcb\x98\x8b\x2e\xe2\x2d\x5a\xc6\x5a\x74\x13\x21\xd1\x3e\x3a\x62\xd9\xcd\x1b\xe4\x2d\x86\x81\x8f\x8d\x5d\x2d\x44\x3a\x58\x71\x2a\xbd\x68\x30\x14\xa9\x61\x70\x12\xc2\x56\x78\x4e\x3f\xc4\x03\x92\xd3\x3b\x54\xb1\xa9\xae\x39\x1f\x9d\x51\x96\x99\x23\xb4\x22\x1f\xbf\x5d\xe0\x44\x07\xa2\x41\xd7\xc9\x60\xa4\x2d\x06\x75\x99\xcc\x45\xb0\x73\x57\xce\x76\xab\xfe\x40\x96\x18\xef\x7b\x9c\x2b\x08\xc7\x32\x38\x91\xd3\x07\xd4\x59\x69\x2e\x4a\xae\x6d\x86\x97\xe5\xcf\x15\xd1\xb7\x41\x6b\x7b\xc7\x79\x49\x37\x64\x87\xa6\x3e\x05\x66\xd8\x45\x34\x39\xd5\x1a\x24\x7f\x47\xfe\xf3\xe8\xc7\xdf\xff\xd2\x3f\xfe\xf2\xe8\xe8\x87\x37\xfd\xbf\xfd\xf4\xfb\xa3\x1f\x07\xf8\x8f\xdf\x1d\x7f\x79\xfc\x8b\xff\xe3\xf7\xc7\xc7\x47\x47\x3f\x7c\xfb\xe1\xeb\xdb\xe1\xc5\x4f\xec\xf8\x97\x1f\x78\x99\xdf\xd9\xbf\x7e\x39\xfa\x01\x2e\x7e\xda\x70\x92\xe3\xe3\x2f\xbf\xd8\x79\xc9\xad\x6d\xd4\xdd\x59\xa8\x3b\xb2\x4f\x7f\x12\xeb\xb4\x8b\xe3\xec\xe8\x2c\xba\x18\xf4\xa5\xd3\xe8\x2c\x48\x8f\x9d\x46\xcf\x25\x51\x11\xa9\xe6\x61\x8a\x88\x9c\x69\xa3\xc0\x19\xb1\x86\x86\x99\x67\x0b\xea\x89\xa3\x03\x98\x7b\x49\x31\x45\x2c\xc8\xda\x0a\xb4\x1a\xe1\x4d\xb1\xa8\x1e\x71\xc2\xf2\x22\x83\x1c\xb8\xc6\xf3\xdc\xf7\x92\x20\xea\x8b\x83\x7a\x25\x89\x95\xd8\xe1\x21\x01\x48\xdd\xcb\x22\xe9\x78\x7a\x44\xd2\xf1\x1a\x49\x87\x82\xa4\x94\x4c\xcf\xcf\x04\xd7\xf0\xb0\x93\x47\xb4\x49\x39\x6e\x9a\x13\x3a\x85\xcc\xc5\xb4\xba\x6b\x44\x14\x36\x83\x73\xa1\x44\xd6\x54\x94\x59\x8a\x69\xd9\x25\x47\x87\x90\xad\xb7\x01\xda\x7a\x6b\x50\x20\x44\x69\x71\xf1\x25\xde\xff\x62\xdd\x42\xff\x53\xb2\x19\xcd\x80\xeb\xe0\x89\x21\x7a\x1c\xc2\x87\x36\x3d\xf3\x9a\xaa\xbb\xfa\xc0\x43\xbf\x10\x69\x7d\xbe\x4f\xfc\x27\xe1\x4f\xf0\xa0\x5f\xa2\x92\x8e\xf2\xd3\x50\xb2\x19\xcb\x60\x02\x17\x2a\xa1\x19\xd2\xb5\x6e\x58\xc9\xe9\x9a\xd9\x71\xe3\xa5\xc8\x94\x91\xf9\x0d\x29\x27\xd4\xbb\xec\x50\x13\x9e\x50\xc6\x6d\x85\xab\xc2\x3f\xac\xac\xef\xcf\x70\x87\x82\x4a\xb3\xc1\x95\x8f\x0f\xf5\xea\x91\x10\x99\xcb\x5d\xce\xe6\xf5\xfc\x2e\x8b\x9f\x8b\x9f\x39\xdc\xff\x6c\x66\x53\x64\x9c\xd1\x49\xe5\xda\x33\xca\xf6\xa2\x77\xbe\x9e\x7a\xed\x07\x60\x62\x70\x09\x84\x66\xf7\x74\xae\x6a\x47\x67\x50\xcb\x4d\xbd\x23\x6f\x8f\x11\x9d\xa9\x22\xd5\x1c\x29\xf9\xc3\x31\x86\xeb\x9d\x9d\x0e\x7f\xbe\xf9\xe7\xcd\xcf\xa7\xe7\x1f\x2e\xaf\xc8\x95\xd0\x60\x79\x5e\xa0\xff\x24\x95\x81\xc9\xac\xb2\xb2\xff\x0d\x84\x1a\xa0\x8e\x85\xd1\xe7\x3c\x15\xf7\x6a\x67\x2b\xa8\x45\x3f\x03\x3c\xa0\x7c\x37\x33\x0f\x2d\x28\x76\x38\x6f\xc1\x61\x96\x22\xc2\xc3\x49\x91\xc5\xa7\xe9\x49\x2a\x45\x61\x81\xe0\x9d\xd2\x81\x81\xa4\xe1\xf6\x0a\x33\xdb\x70\x7f\xc7\xcd\x09\x27\x92\x72\x5d\x7b\x67\xeb\x3d\x73\xad\xd5\x07\xad\xb7\xe3\xf9\x18\x7f\x17\x56\x02\x9a\x76\x57\x97\xe0\x34\x4d\x21\x6d\x80\xff\xd5\xe5\x13\x9d\xf9\x8f\x0b\xdc\x5e\x64\xf8\xf1\xe6\xf2\x7f\x2f\xe0\xf1\xbc\x68\x97\xd8\xd0\x4d\x8d\x1b\x29\x8a\xce\x76\xf7\xda\xd5\x50\x89\xfb\xbb\x17\xfb\x5b\x71\xcb\x6e\xc2\x69\xaf\x4b\xde\x2c\x4e\x5a\xcf\x4f\x72\x91\xc2\x80\x0c\xab\xb8\x9e\xe6\xd5\xa0\x54\x19\x95\x40\xcc\x2d\x5c\x33\x9a\x65\xf3\x50\x44\xd3\xc2\xd6\x13\x69\x54\x59\x0b\x09\xf9\x98\x66\xea\xb9\xa9\x71\x1b\xde\x68\xe4\x88\x0f\x46\x5d\xee\x64\x3b\xaa\xd9\x48\x0a\x5c\x68\x27\x58\x9b\x55\x62\xe5\x3a\x29\x12\x62\x75\xf3\x20\x79\xa2\xc1\xdf\x94\x8d\x2d\xf2\xac\x91\x29\x0f\xec\x61\x35\xb3\x75\xcb\x96\x0a\x16\x05\x74\xc7\x1a\x6b\x6d\xdd\xcc\x2e\x81\xa6\xe8\xb5\x28\xa8\x9e\xda\xd8\xe7\x9c\xaa\x3b\x48\xed\x0f\x4e\x34\xab\x1c\x27\x68\xe8\xf5\xaf\xba\x35\xeb\xf6\x3e\x12\x14\xc9\x6c\x44\x36\x7a\x57\x20\x7d\xe6\x5d\x6f\x71\x08\x0d\x50\x3e\xf2\x6c\x7e\x2d\x84\xfe\xaa\x2a\x88\xd3\x09\x06\xfc\xc3\x49\xcb\x4d\xc7\x15\x8a\x93\x14\xdf\xdb\xc7\xdd\xc0\x43\x15\xd6\xe2\x39\xaf\x77\xfc\xa5\x1f\x29\x59\xf2\x53\xf5\xb5\x14\xe5\xce\x4c\x6c\x49\xd8\xfc\xfa\xf2\x1c\x49\x51\xe9\x42\x0b\xb9\x96\x73\x2c\x02\xb6\x5c\xc9\xb9\x52\x0c\xbe\x73\xc1\x91\xe1\x99\xa8\xe3\xd8\xc8\x07\x3a\x27\x34\x53\xc2\xc3\xd2\xb9\xb5\x16\xb5\x50\xa7\xe2\x9a\xcb\x23\xa1\xa7\x4b\xba\xad\x39\x50\xcb\xcf\xf5\x82\x48\xc3\x3a\x1e\x80\xf1\xa5\xc7\x35\xfa\x4c\x0a\x09\x09\xa4\xc0\x93\xe7\xde\xf6\xe7\x0e\xd0\x43\xd4\xb9\x12\xdc\x1c\xcc\x4e\x90\xe7\xb2\x8a\xcc\x74\x20\x0d\x51\x05\x9d\x62\x4e\xfb\xa3\x18\xe9\x89\xc7\xb2\x54\x20\x6d\x58\xaa\x2c\xc1\xee\xe4\xb7\xe5\x08\x32\x03\x79\xa3\x92\x62\x1d\x51\xaa\xad\x39\x83\xe5\x74\x02\x84\xea\x0a\xd3\xb4\x20\xc0\x55\x29\xdd\x26\x32\x4d\x52\x01\x75\x1d\x2d\xaa\xc8\x77\x97\xe7\xe4\x0d\x39\x32\xef\x3a\x46\xfc\x19\x53\x96\x61\x10\x28\x06\x95\x2c\xe8\xa8\x63\x3f\x05\x2e\x09\x91\x97\x08\x69\x89\x44\x8f\x70\x41\x54\x99\x4c\xfd\x9a\x8c\xde\xeb\xd5\x66\x97\xb8\x84\x9e\x97\xfd\xc4\xf5\xe7\xa5\x50\xdf\x29\x90\x9d\x11\xa8\xef\x76\x20\x50\xa1\x18\x65\x70\xae\x09\x3d\x8b\x58\x39\x68\x9a\x52\x4d\x1d\xe1\xf2\x37\xec\xed\x96\xfe\xba\xc9\x97\x82\xf7\x8c\x97\x0f\x36\x51\xa0\x3b\x53\xcb\xcd\x05\x4e\x4b\x12\x0f\x75\xdc\x75\x1b\x7c\x97\x7a\x6b\x4a\x10\x24\x73\xd9\xc0\x95\xde\x1a\x31\x11\xe9\x04\xb5\xc1\x30\x60\x84\x13\xca\x53\x91\x2f\xbd\xcc\x08\x91\xd0\xe8\x81\x30\x20\x11\xfb\x9a\x63\x4f\x8c\x42\x19\xcc\xa0\x45\x95\xe0\xc5\x9e\x0f\x66\x36\x03\x1c\x8f\x11\x38\x3d\xc9\xe8\x08\x32\x17\xa8\x65\xc3\x3f\x97\x31\xf0\xb9\xb3\xc7\xa4\xc8\xba\x4b\x77\xbf\x16\x19\xd8\x74\x0c\x0f\x08\x33\xfd\x8b\x80\x03\x4e\xd2\x15\x1c\x50\x1b\x6c\xc0\x01\xf5\xda\x97\x00\x87\xb2\x05\xab\x27\x8b\x70\x30\x72\x43\x13\x0e\xc8\xbc\xf7\x1d\x0e\x0a\x92\x44\xe4\xc5\x50\x0a\xa3\x76\x76\xc6\x9b\xdc\xb4\xb5\xcf\xd0\x1a\x36\x56\x84\x6e\x22\x2f\x68\xde\x4c\x65\x90\x88\x45\xb5\x65\x12\x3e\x1b\xeb\x7f\x05\x3c\x0b\x49\xcf\x22\x23\xf3\xb3\x34\xdc\x8b\xe6\x49\x77\xe1\x25\xb3\x83\x2e\x72\x99\x5b\x18\x3b\x3b\xe1\x46\x22\xa1\x19\x76\x81\x68\x87\x72\x64\x11\xed\x16\x27\x0e\xd2\xef\xd0\x47\x89\xbf\x05\x91\xc6\x14\x0d\x2d\xde\x84\xc9\x45\x0a\x81\x2f\xdb\x46\x2f\xde\xda\x34\x2d\xbc\xcf\x67\xfe\x19\xb9\xc2\xbb\x95\xd3\xc6\xd3\x5a\xb8\x5a\xc6\x1f\xaa\xde\x12\x66\x81\xc0\x53\xc6\x27\x68\x57\xeb\x11\x09\x99\xcd\x19\x74\x44\xe0\xce\x6a\x90\x87\x78\x24\xfc\xa4\xfe\x3c\xf8\x57\xfb\xc0\x64\x37\x73\x18\x6d\xcc\xc6\x96\xdc\x32\x45\x0e\xde\x7b\x00\xb4\x28\xc6\xbf\x8f\x1c\xe6\xc0\x7e\x61\xb5\x9b\xd6\xd2\x79\xc7\x78\xea\xd2\xeb\x1a\xc0\xaa\xba\x39\x59\x39\x18\x13\x37\x59\x1a\xd2\x96\x77\xe4\x47\x4e\x2a\x60\x91\xfe\xce\xe8\x71\x6d\x45\x66\x6f\xa3\xeb\x3f\x6e\x78\xad\x5e\xb2\x38\xcd\x77\x1c\xf7\xde\xbc\xb7\x6f\x34\xf7\xe5\xfb\xfc\xb7\x3c\x6b\x41\x4f\x47\xfd\xba\xd6\x62\xfe\x61\xa7\xf5\x22\x7d\x62\xd0\x5a\x33\x3e\x51\xa1\x26\x43\xb3\xac\x61\x0c\x5f\xa5\xca\xf8\x1d\xae\x7a\x77\x2d\xab\x10\x0b\x69\xc1\x2f\x45\x0d\xc9\x8c\x38\xf1\xc2\x95\x90\x49\xae\xe8\x99\x34\x90\xd0\x8c\x66\x37\xc5\xee\xcd\x06\xc8\x52\x61\xeb\x0f\x37\xa7\xcd\xa9\x91\x59\xbb\x98\x74\xc0\xeb\x84\xa6\x39\x53\x0a\x0d\x61\x30\x9a\x0a\x71\x47\x8e\x1e\xed\xb9\xd6\x57\x6c\xa2\x4e\x1c\xce\xf7\xcd\xea\x8f\x09\xe3\x59\x15\x15\x85\x7a\x30\xd7\x55\x18\x3c\xbe\x24\xa9\x56\x81\x7b\xe8\x3a\xd0\xb8\x60\x85\xe5\x65\xda\x9e\x33\x06\x0b\x9e\x9d\x60\x2f\x6f\x4f\xbb\x54\xc2\x27\xb7\xe8\xca\xe1\xf6\x62\xbd\xe5\x95\x70\xb4\xd2\xe3\xb3\x03\xc9\x09\x17\x09\xa8\xee\xca\xbc\x7e\x53\xcf\x49\x52\xb0\x59\xf7\x80\xd1\x4f\x74\x6d\x90\x1d\xda\xa5\x0f\xb1\x78\x8b\x7b\xf4\x30\x94\xa8\x9b\xd9\x4a\x98\x0c\xd5\xb7\x4a\xba\xa1\x68\x48\x02\xbd\x08\x31\x15\x5c\xb8\x1c\x39\xc3\x44\x05\x47\x94\x46\x12\x65\xbd\x79\xb8\x27\x8e\x44\x07\x4b\x3d\xab\xbd\xc4\xa1\x23\x10\x8b\x3f\xe8\xaa\x49\xa2\x5d\xc3\x3d\xd3\x53\xec\xd8\x30\x5d\xf0\x1a\xe2\x4a\x24\x28\x74\xc0\x70\x02\x52\x0a\xe9\x02\xb2\xbc\xdd\xda\xa5\x6a\x0d\x45\x8a\x11\x5d\x06\x49\xa8\xf9\xeb\x50\x85\x8e\xea\xba\xa9\x53\x55\x83\x13\xc6\x63\x48\x50\xd0\x0a\x01\x6c\xa9\xf6\x51\xdd\xc2\xc2\x25\x21\x18\x04\x73\x4d\xa1\x72\xf6\x60\xde\x12\x3e\x15\xba\xc4\x5d\xeb\x88\xd5\x97\x8f\x07\x84\x5c\xf2\x2a\x82\xb7\x67\x76\x31\xbc\xd3\x87\x9e\x69\xf3\x89\x61\x47\x31\xfc\x80\xd0\x70\x66\xa4\x43\x59\x76\x80\xf1\x6d\xcc\xe1\x24\x34\x89\x77\x4a\x0e\xd0\x34\xee\x26\x35\x5b\xef\x65\x80\x36\xa6\x72\x73\xcb\xa7\x32\x97\xbf\x0c\x07\x08\x69\x4b\xe7\x5c\xf5\xb3\x8e\xda\x3c\xdd\x04\xb3\x05\xd2\x7b\xe5\x70\x1b\x8a\xd4\x56\x3f\xac\xaa\xb7\x65\x73\x5f\x8d\xb1\xca\x89\x0e\x64\x3c\x2e\x6c\xf2\x40\x58\x16\xd1\x35\xc7\x49\x89\x11\xb5\x33\x6f\x5b\xc8\x8b\x0c\xb0\xea\x4a\x30\x73\x5d\x50\x26\xe8\x0b\xd5\xab\x33\xd8\xaa\xd6\x52\xae\x18\x63\x8f\xfc\x37\x1e\xca\x2a\x10\xd5\xd7\x89\x1b\x56\x8f\x5b\x0d\x91\x29\xdf\x24\x0e\x93\x53\xb5\xf0\xa6\x0b\x92\xb2\x31\xe6\x49\x6a\xf7\xca\x82\x4a\x9a\x1b\x12\xaf\x88\x03\xc1\x08\x26\xcc\x06\x44\x56\x84\xed\xd0\x88\x7b\xae\x36\x47\xcf\x12\x43\xa6\x49\xce\x26\x53\x8b\x28\x84\x62\x45\x1d\xe2\x9d\x8a\x99\xa0\x29\x36\x97\x25\x42\x92\x7b\x2a\x73\xc3\x37\x68\x32\x45\x0f\x25\xe5\x24\x2d\x25\xf6\x4b\xd1\x40\xd3\x79\x5f\x69\xaa\x8d\xa4\x0c\xd2\x29\x94\x7e\xfd\xb1\x39\xd6\xa3\x23\x36\xc7\xda\x70\xc4\xe6\x58\xb1\x39\xd6\xf2\xd8\x9b\xe8\xd0\xd8\x1c\xeb\x75\x95\x35\x8d\xcd\xb1\xb6\x1f\xcf\x5e\xcd\x34\x36\xc7\x5a\x3d\x62\x73\xac\xd8\x1c\x6b\xb3\x11\x9b\x63\x6d\x3f\xf6\xae\x0e\x73\x6c\x8e\xb5\xd5\x88\xcd\xb1\x96\x47\x6c\x8e\xb5\x66\xc4\xe6\x58\x6b\x46\x6c\x8e\xb5\x3c\x62\x73\xac\xed\x46\x6c\x8e\x15\x9b\x63\xbd\xea\x9e\x01\x24\x36\xc7\x72\x23\x36\xc7\x7a\x15\x95\xd1\x49\x6c\x8e\xb5\xd1\x88\xcd\xb1\x62\x73\xac\x5d\x46\x6c\x8e\xf5\x5a\x8c\x32\xb1\x39\x56\x6c\x8e\xf5\xeb\x11\x74\x63\x73\xac\xd8\x1c\x2b\x36\xc7\x8a\xcd\xb1\x1e\x5d\x45\x6c\x8e\xf5\x1a\x54\x40\xa5\x53\xb6\x53\x6d\xd0\x4d\xca\x18\xb9\xf0\xf4\xa0\x6a\xc0\xa8\x1c\x8f\x41\x22\xe5\xc2\x37\x2f\x85\x55\xd5\x15\x1b\x17\x5d\xb9\xa0\x7b\x58\x11\xc9\x65\xf2\xac\x79\xdc\x95\x29\xc0\x1a\x9e\x75\x0c\xf9\xc5\xc7\xaf\x56\xd4\x4c\xda\x39\xde\x70\xd7\xe8\x69\x5c\xf3\x47\xbe\x9b\x17\x7e\x0d\xc0\x57\x65\x96\x39\xb8\x27\x99\x50\x2e\xf6\x1d\x81\x95\x4c\x29\xe7\xe0\xf5\x3d\xa6\xd1\x8e\x32\x02\xe0\x44\x14\xe0\x7c\xe0\x94\x28\xc6\x27\x19\x10\xaa\x35\x4d\xa6\x03\xf3\x26\xee\x81\x5d\xc7\xa9\xbb\x5f\x94\x96\x40\x73\x1f\xb1\x9f\x53\x66\xa7\x22\x34\x91\x42\x29\x92\x97\x99\x66\x45\x35\x19\x51\x80\xa9\x36\x96\x51\x55\xc0\xc0\x78\xb9\x3a\xb8\xbd\x57\xbf\xcd\x2d\x4b\x84\x45\xeb\x50\xdb\xec\x61\x21\xf1\xbc\xd0\xf3\x2a\xc2\x17\xc8\x98\x49\xa5\x49\x92\x31\xe4\xd6\xf8\x46\x9b\x55\x8d\xf3\xf5\x3c\xaf\xe6\x6e\xa5\xca\x2d\x95\xa7\x28\xb6\x16\x5a\xd9\x78\xd9\x7a\x42\x37\x55\xca\x94\x13\xf3\x55\x8f\x50\x5f\x51\xcd\x02\xda\xaf\x14\x41\xed\x39\x8b\x9d\xdd\xfd\x14\x4c\x17\x54\x92\xad\x03\x8a\x6b\x44\xc7\xe4\x07\x8f\x9c\xbd\x46\x9e\x47\x2d\x50\xb8\x7e\x19\x0b\xc7\x00\x37\x80\xc3\xcc\xe0\x00\x24\x60\xf8\x2b\x5d\x83\xf5\x9f\x1d\xe9\x03\xa6\xf8\x01\x94\xa2\x13\x18\xee\xe8\x68\x58\xa7\x91\xa1\xaf\xa1\xde\x18\x44\x85\xac\xd1\x93\x2c\x8c\xdb\x6c\x8a\x41\x24\xb7\x6b\xaa\x84\x9f\x7b\xc9\xb4\x06\xdc\x54\xac\xbd\x87\x1e\xd1\xc5\xd4\xfc\xc3\x85\xe8\xcf\x0f\x7e\x92\xfa\x61\x43\xd4\x79\x6a\x63\x31\x47\x40\x46\x92\xc1\x98\x8c\x19\x06\x78\x62\xc8\x65\xcf\x96\x62\xa2\xd6\x0a\xa0\x94\xd1\x77\x05\xf7\xb2\xac\x5f\xd7\x80\xfc\xc3\x2d\x4c\xcb\x92\x27\x34\xa8\x72\x8b\xb9\xa7\x6c\x4c\x26\x18\xb2\xe9\xa4\xc5\x3f\xbd\xf9\xdb\x5f\xc8\x68\x6e\x58\x1a\x4a\x56\x5a\x68\x9a\x55\x1f\x99\x01\x9f\x18\x58\xd9\xe3\xd9\xcc\x9e\xac\x20\x80\x6d\x40\xec\xc2\xdf\xfe\xe1\x6e\xd4\xe4\xb1\x27\x29\xcc\x4e\x02\xf8\xf5\x33\x31\x59\xd5\x38\x6b\xf7\x60\xee\x1d\x55\xa2\x15\x68\xd6\x4d\xc7\x47\x5f\x13\x8c\x4c\xc5\xbd\x95\xf5\x57\x60\x4f\x9d\x88\x55\x88\xa2\xcc\xac\xd1\xf9\xab\x2a\xef\xb8\x54\xb0\x9c\x1d\xb8\xf2\x5c\xa0\x99\xd4\x4d\xb1\x58\x51\xdd\x46\xea\xfa\x57\x0a\x97\x75\xe2\x0c\x79\x55\x69\x30\x54\x84\xbe\xa2\x59\x36\xa2\xc9\xdd\xad\x78\x2f\x26\xea\x23\xbf\x90\x52\xc8\xe6\x5a\x32\x6a\xa8\xe5\xb4\xe4\x77\xb6\xf5\x43\x55\x3c\x41\x4c\x9c\x2b\xd7\xa7\x38\xac\xfa\x60\x9b\x49\xef\x89\xb0\x57\x83\xea\x59\xe0\x81\xd5\xba\x8e\x4b\xe2\xb2\x18\x19\xce\xaf\x42\x64\xfb\xc3\x9b\x3f\xfd\xd5\xa2\x2e\x11\x92\xfc\xf5\x0d\x46\x73\xab\x9e\x3d\xc4\x48\xdb\x0c\xa3\xc8\x69\x96\x19\xb5\x21\x44\x4a\x03\xe8\x55\x48\xf8\xd9\x71\x50\xb7\x47\xb7\x8d\x45\xa9\xdb\xdb\x7f\xa2\x1c\xc5\xb4\x82\x6c\xdc\xb3\xf9\x4a\x95\x5a\x73\x88\x8c\xe1\xd0\x51\x1f\x4c\x1a\xdb\x03\x01\x68\x26\xb2\x32\x87\x73\x98\xb1\x2e\xba\xfb\x35\x66\xf3\xaa\x7e\xc6\x14\xa6\x86\x8d\x32\x91\xdc\x91\xd4\x5d\x0c\xe2\x5b\x16\x6b\x84\xbf\xdc\x46\xad\xe1\xf7\x37\x62\x7b\x72\x5a\x14\x55\xf6\x90\xa4\xf7\x0d\x60\xe0\x99\xc4\x42\x06\x2f\xbf\x51\xab\xfd\x22\x43\x37\x77\x9e\x62\xe7\x80\xa0\xf6\x36\xea\x7a\xf5\x1d\xb5\xe3\xab\x27\xf4\xa7\xa1\xc0\x7f\xdb\x7c\x93\xa5\x7c\xc9\x2a\xe5\xae\x42\x0c\x2b\x00\x18\xf4\x41\x92\xfc\x6c\x0d\x45\x49\xeb\xc0\xa6\x06\x5c\xf8\x23\x3d\xed\x28\x29\x40\x2a\xa6\x0c\x5f\xfe\x1e\x0f\x94\x6d\x66\x58\x9b\x00\x9f\x07\x08\xf6\x70\x63\x61\xe5\xf6\x94\x72\x28\x52\x37\x21\x92\x42\x5b\x54\x7a\x85\x58\xdb\x94\x6a\x3b\x64\xa8\xcf\x4d\x2a\xbf\xaf\xa1\xd9\xa4\x94\xe6\x97\x8a\x54\xda\xbb\x5e\x13\x81\xc4\xef\x7b\xa9\xf4\xb1\x5a\x7c\x47\x64\x00\x09\xa3\xdb\xdc\x26\x25\x6c\x28\x8f\xf6\xa0\x04\x22\xbd\xd3\x03\x07\xc4\x7a\xc1\xcd\x99\x70\x8f\x92\xc3\x77\x87\xcf\x4a\x24\x2d\x88\xa4\x28\xe8\xa4\x55\x97\x9f\x05\x48\x2d\x4e\x1b\x96\xa0\x30\x6a\x10\x5e\xaf\x0a\xb2\xe1\x5d\x90\xd6\x15\x76\xb0\x7e\x92\xf5\x8e\x7a\x00\x3b\x05\xc1\x66\x6a\xdf\xd3\x39\xa1\x52\x94\x3c\x75\xf6\xa5\xca\xc0\xf7\x61\xe1\xc5\x57\x82\x43\xdd\x35\xb4\x59\xc1\x02\x2d\xfa\x8c\x93\xb7\x83\xb7\x6f\x5e\x0b\xa7\xc2\x2f\x5c\xe0\x54\x57\x15\xa7\xb2\xf4\xe9\x59\xbf\xd5\xd7\xc2\xef\xe8\x7b\x3f\x38\x13\x4b\x5d\xea\x9e\xf9\x42\xda\xf8\xd3\xbd\x64\x1a\x82\xe6\x80\x47\xa8\xb8\x18\xfd\x30\xa8\xd7\x70\xbc\xaa\xc7\x44\x4b\x20\xb5\x2b\x90\xa1\xca\xd1\x27\xa4\x5b\x8e\x40\xe1\x71\x5b\x65\xe1\x52\x8f\x90\xb0\x10\x50\x07\x07\xe4\xc8\xde\x79\x68\x53\x9d\x8f\x9f\x15\xb5\x1c\xd0\x2e\x1e\x8a\x16\xd5\x37\x17\xb2\xea\x0b\x8a\x36\xb8\xa2\x43\x08\xfe\x07\x4c\xe9\x0c\x30\xc5\x9b\x65\x54\x66\xe8\x73\xbc\xb1\x6b\x27\xa3\x52\x13\xe0\x33\x26\x05\xcf\x81\x6b\x82\x31\xf0\xa3\x0c\xc2\xde\xd8\x5f\x1c\x7d\x7f\x7a\x8d\x01\x0d\xc7\xae\x58\x85\x5b\x65\xa9\x7c\x61\x9b\x70\x25\xc1\x74\x4f\x6e\x9f\x5f\x87\x81\x21\xd2\x5c\xbf\x2e\xf3\x9e\xbc\xd4\xa5\x6d\xd8\xf2\x90\x64\xa5\x62\xb3\xe7\xa2\x24\x2e\xf7\xfe\x9c\xed\xb4\xcf\x0b\x75\x00\x6a\x40\x2d\xa5\xf4\xa3\x69\x7d\x45\x1a\xe0\x92\xc3\xe4\x50\x55\xa9\x81\xa1\x0f\xdc\x99\x9e\x5c\x95\x0d\x1b\x3e\xe7\x6b\x31\x2e\x89\x10\x58\x51\xe6\x79\x8d\x50\x29\x57\x67\xb8\xc2\xed\xc0\xda\x0c\x48\x6e\x64\x0b\x9e\x5f\xdd\x84\xe5\x49\xac\xba\x24\xd2\x01\x19\xd6\x3f\xd6\x35\x6c\xb0\xb2\x5a\xa5\x44\x82\x9c\xd4\xe5\xc6\x27\xc0\x41\xa2\x90\x60\xa6\x6c\x34\x5c\x25\x23\xaa\xac\x93\xe7\xfc\xea\xc6\xda\x6c\xb7\x83\xd9\xce\x62\xf6\xee\x12\x2a\xa6\xb4\x60\x1a\xc3\x0e\xc2\x6d\xb3\x9b\x5a\x65\xb0\x32\x80\x41\xa5\xd4\x4e\x4c\x2e\x87\x84\xa6\xa9\x44\xb7\xcf\x42\xf2\x8d\xd1\xcf\xbd\x6f\x01\xeb\xc5\x50\x05\xe1\x9a\x02\x70\x23\x89\xab\x01\x4b\xce\xcb\x22\x63\xd6\x8d\x10\x3e\x50\xd7\xb9\xc1\xf6\x5f\xdb\x23\x6d\x1b\x35\x6f\x67\x25\xaf\x05\x15\x12\xbb\x96\xab\x7c\x64\xf7\x24\x28\x91\xcd\xea\x52\xc3\x0b\xbb\xe6\x4e\x04\x9a\xc4\xab\x5d\xf3\xd5\x29\x37\xda\x31\xe0\x5a\x32\x58\xde\x2d\x72\x6d\xde\x5c\xe2\x69\xaa\x26\x64\x33\x40\xff\xb8\x2b\xcc\xe9\x0a\xbc\xd5\xc5\x8f\xad\x6f\xd8\xd6\x9f\x06\x2a\x3d\x45\xc3\x55\xed\x78\x12\xc9\x73\x21\xc2\xa2\xb1\xe3\xfc\xea\xc6\x52\x42\xfb\xf1\x55\xdf\xda\x55\xbb\x54\x53\xb5\x9d\x31\xf0\xd9\xea\x0f\xb5\xd1\x3c\x16\xda\xfe\xb9\x3e\xdf\xad\x02\x59\x5a\x88\x7f\xad\x92\xed\x5a\xbc\x5d\x01\x95\xc9\x74\x17\xf8\x3f\x42\x08\xec\xa4\x24\x15\x36\x12\x60\x2c\x24\xaa\xc4\x7d\x24\xef\x99\x10\x77\x65\xb1\x09\x45\x77\xd3\xd8\x56\x6c\x1b\x11\x88\xc6\x13\xbf\x2a\x9a\x9e\x72\xb5\x8b\xbf\xb7\x29\xfb\x80\xb6\x12\x0f\x4e\x54\x27\x50\x88\x45\xbd\xe9\x2c\x2b\x95\x06\xf9\x15\x93\x4a\x1f\xf8\x4a\xd2\x88\xc1\xd6\x26\x72\x18\xde\xf0\x0f\xa6\xa7\xae\xa8\xe3\x61\xaf\x79\xc9\xfc\xed\x26\x3e\x34\x3a\xed\xe1\x95\xe0\x70\x38\x58\x14\xbb\x2a\x52\x5e\x91\xb5\xb5\x3c\xc5\x2d\x5d\x41\x66\xe3\x45\xf1\x42\x80\x2b\xb7\xae\xa0\xa5\x79\x83\xa7\x7f\x0a\x34\xa1\x58\x3c\x0e\xef\x9e\xd6\x05\x28\x6d\x45\x29\x5b\x41\x53\x38\x41\x6f\x1e\x82\x28\x28\x32\xa5\xc5\xfa\xcf\xde\x45\x9e\xdb\x1a\x03\x6c\x61\x52\x57\x95\xe4\x3d\xe3\x77\x5b\xa2\x5f\x33\xba\xe4\x62\x69\xb6\x46\xa5\x71\xeb\xa3\x65\xdc\x06\xdf\x19\x16\x43\x47\xa2\xd4\xbe\xf2\x89\x0a\x14\x47\xc6\xff\xdb\xee\x05\xda\xdb\x0b\x5b\xcb\x6f\x95\x8e\xa8\x7a\xd6\xe8\xe3\x95\x40\x35\xe7\x9a\x62\xd5\xd1\x73\x91\xdc\x81\x24\x99\x59\xc6\x80\xd4\x81\x2f\x8d\x3a\x97\xb2\x84\x2d\xa3\x2e\x76\xb5\x74\x40\x31\x85\x1c\x24\xcd\xea\x72\xaf\x2d\x40\xfd\xde\x11\xce\x6a\xd6\x30\x26\xc5\x96\x4b\x73\x05\x1a\xcd\x39\xbc\x58\x75\x57\x4e\xe7\xbe\x06\x2e\xe3\x18\x6e\xf0\xc0\x14\x9a\xf5\x0b\x91\x86\x89\x67\xa5\x02\xd9\xaf\xd2\x02\x5d\xee\x8d\xaa\x02\x71\x52\x18\x95\x93\x09\xe3\x13\x47\x9d\x91\xa6\x07\x85\xb8\x2b\x4d\x07\x23\xbd\x13\x09\xb6\x14\x2d\x4a\x0f\x36\xbe\x8c\x85\xf7\xe7\x22\xb5\xb7\x8f\xe6\x56\x1b\xf4\x3b\x5b\x07\x48\x5f\x72\x22\xa4\x2b\xc0\x40\xd3\x14\xd7\xbe\xfc\x85\x78\xb5\xf9\x55\xbd\x2a\x8e\xc3\x46\x76\x57\x4f\x05\x60\x51\xe5\xc8\x08\x3b\xa5\xdc\xb6\x76\xe8\xae\x84\x7f\x27\xa2\xdf\xac\x2a\x74\xca\xeb\x2d\x3e\x0b\x03\xe6\x28\xd1\x90\x17\x42\x52\x39\x5f\x74\x61\x1a\x22\x65\x50\xc0\x00\x70\x01\x52\x43\x91\x22\x1d\x5f\xb1\xf1\x33\xdb\xe3\x77\xc5\xde\xaf\xc4\x31\xa4\x82\x5c\x10\x0f\x51\x43\xaf\x55\x32\x85\xb4\xc4\xe8\xf1\x49\x49\xb1\x07\xb9\x39\xc5\xce\xd8\x3d\x77\x61\x79\x16\x19\xaa\x80\xbf\x2a\x4d\x60\x8e\x41\x32\x58\x9f\xd3\xfc\x82\x75\x3e\x6d\x68\xa0\x6d\xc1\x8c\xed\x58\xab\x28\xc1\xdb\xba\x2b\x04\x7e\x2c\xcc\x58\xa2\xfd\x43\xe3\x75\x88\x93\xd0\xaa\xf3\xeb\x50\xb8\xba\x80\x09\x18\x62\xa4\x55\xfd\x29\x2e\xaa\x04\x2b\x7f\xfe\xc8\x0d\x93\x58\x8f\x8b\x35\xe2\x3d\x81\x72\x28\x57\x37\xb7\xe2\x91\xe3\x5b\x41\x69\xc5\xb7\x6f\x5b\x92\xa9\x85\x50\xbe\xbb\xc7\x6d\x27\x4f\x59\x1b\xf9\x9f\xca\x49\x7b\x5d\xe9\xf0\x54\x4e\xca\xdc\x56\xf7\x16\x0b\x05\x96\x2d\xce\xa1\x5d\xcb\xb0\xac\xb3\x0f\xe7\x61\x0a\x43\x18\x9b\xed\x13\x40\x8c\x28\xd4\xd2\xde\xb9\x68\xf0\xbc\x34\xca\x59\x65\x45\xad\x69\xab\xd3\xe2\x9c\x45\xaf\x7a\x9b\xd7\x62\x19\x2f\x0c\x37\x46\x19\x22\x28\x3d\x92\x4c\x29\x9f\xa0\x19\x5c\x94\x66\xbe\x2f\xbe\xc0\x15\x49\x48\xcb\xc4\x75\x94\xf0\xf1\xcf\x5f\x78\xeb\x9f\x2b\x14\x84\x8d\xed\x54\x42\x0b\xbf\xe6\xf0\xb3\x2c\xab\x7e\x47\xd8\x00\x06\xe4\xe0\x8b\xe0\xd2\x81\x7d\x7b\x21\x85\x79\x85\x0b\x9d\xc6\x55\x65\x4c\xe3\x41\x38\x08\xef\x1e\x90\x0b\xf3\x0e\xf4\x88\x54\x00\x0c\xa2\x7b\x47\x35\xf8\x7a\x44\xc2\x84\xca\x34\xc3\x8c\xbb\x71\x25\x94\xd8\xbc\x1c\x07\x30\x3c\x7d\x18\x4f\xc7\x85\x5e\x65\x9d\xdc\x30\x2d\x42\x53\x75\xa7\x4e\xac\x28\xd3\x4f\xa9\xa6\x7d\xec\xc2\x61\x89\xc6\x89\x55\xaf\xfb\xae\xfe\x69\x9f\x3a\x9c\xea\x57\xdb\x7a\xf2\x5b\x97\x59\xd5\xa7\xd5\x5d\x8c\xf7\x69\x1f\x2b\x91\xee\x1e\x2b\xfa\x0c\x61\x05\xad\x34\xdd\x16\x65\x70\x17\xc5\xd3\xaa\x0c\x3a\xc2\x00\x9b\x88\xd4\x65\xaf\xab\x08\x06\x57\xe9\xb5\x71\x90\x2f\xae\x6e\xaf\xff\x39\xfc\x78\x79\x75\x1b\xcf\x73\x3c\xcf\xf1\x3c\xb7\x38\xcf\xc0\x67\xad\xcf\x72\xa5\xff\xac\x52\x09\x17\x4a\xd8\x05\x19\xd5\xaf\x28\x38\xeb\x82\xcf\xbe\xa7\x46\xe0\x2b\x24\x28\x94\x45\x8c\xdc\xb8\xca\x8b\xea\x6e\xb0\x7d\xb8\xce\x5e\x7c\x74\xd6\x33\xc6\x56\x75\x18\xb3\x72\x15\x14\x02\x58\xb5\x6b\x61\xe3\xbb\xb3\x9f\x2f\xcf\x2f\xae\x6e\x2f\xbf\xba\xbc\xb8\x7e\xd6\x60\x83\x96\xc5\xdd\x9a\xdc\x78\x47\x2e\x59\x48\x98\x31\x51\xaa\x6c\x5e\x55\xa1\x5d\x4d\x04\x96\xe3\xd5\xb8\x51\xcf\xe6\x55\xa1\xdd\x95\x8f\x45\x66\xdb\x2d\xb3\x6d\xc6\x5e\xb4\xa8\xeb\xd1\x15\xfa\x7e\x25\x45\xde\x11\x0a\xdf\x58\x95\xdd\x9b\xbc\x57\xe1\xd3\xa1\x2b\x01\xd0\x60\x3d\x4e\x78\xac\xeb\x0d\x18\x29\x34\x2f\x74\x8b\xb6\x00\x9d\x14\x0d\xed\xa6\xbe\xa6\x8d\x53\xf8\x40\x8b\x6f\x61\x7e\x0d\x2d\xcb\x87\x2c\xb8\x1a\x32\x48\x0c\xa3\x23\x77\x30\xb7\x1e\xc8\x33\xff\xb2\x76\x45\x30\xf7\xb0\xe6\xea\x1d\xb4\xa9\x87\xdb\x65\xb1\xd4\x3b\x68\x11\xb8\xe8\xc7\x52\x41\x4f\xb3\x85\x28\xa7\x99\x3d\xdd\xab\x12\xa6\x9f\xa0\x38\xec\x61\xc8\xee\x1d\x9d\xd5\x5b\x57\x57\x10\x33\xc3\xb9\xe0\xfe\xc4\x05\x6d\xf5\x8d\xc6\xda\xb7\x58\xab\x4e\x30\x32\xe5\xe4\xb7\xb6\x70\xec\xed\xc7\xf3\x8f\xef\xc8\x69\x9a\xba\xe0\xe1\x52\xc1\xb8\xcc\x6c\x18\xb0\x1a\x10\x5a\xb0\xef\x41\x2a\xec\xab\x76\xc7\x78\xda\x23\x25\x4b\xbf\x6c\x53\x74\xc9\x8e\x0e\x77\x41\x78\x87\x4d\xb7\x3b\x71\xe3\xfc\x71\x21\xef\xaa\x88\x08\xb1\x99\x81\x88\x9b\xbe\xfe\x8a\x13\x32\x3a\x02\x4d\xdb\x16\x72\xc4\x6e\x61\xb7\x74\xf5\xb0\x26\xac\x36\x4e\xbc\x2a\x50\x95\xbe\x23\xaa\xc4\x42\x31\xaa\xea\xfb\x86\x9d\x54\x7b\xcd\x3f\x55\x41\x13\xe8\x91\xff\xaa\x7e\xc4\x4e\xed\xea\x87\xc3\xc3\xbf\x7f\x7b\xf1\xcf\x7f\x3f\x3c\xfc\xe9\xbf\xc2\xab\xc8\x0a\x51\x6b\x5e\xb8\x05\xfd\x3b\x5c\xa4\x70\x85\xef\xc0\x3f\x9d\xb8\x76\x9a\x24\xa2\xe4\xda\x5d\xc0\xac\xde\xc1\x54\x28\x7d\x39\xac\xfe\x2c\x44\xba\xf8\x97\x6a\x55\x49\x6c\x2f\x19\x03\x6e\x51\x8b\xec\x14\x3b\xba\x63\x0f\x35\x2d\xe9\xf8\xa8\xba\x59\xab\xfe\x18\xc9\x14\x72\x5b\xcb\xe8\x2b\x0f\x02\xec\x4d\xeb\xcb\x07\x70\xcc\xb9\x36\x92\x69\xb3\xac\xdc\xc1\xec\x6d\xab\x26\xde\x76\x74\x48\xda\xaa\x1d\xec\x18\x60\x08\x11\x07\x2d\x7b\x90\x2b\x06\xeb\xb5\x94\xda\x1b\x7b\x3a\xbc\x24\x33\x0b\xe1\xbd\x01\x8e\xf7\x82\x7d\xf5\x49\x69\x5c\xe8\x6b\x6b\x68\x88\xef\x6c\x2b\x57\x7f\xdd\xe5\xd9\xab\xaa\xf4\x15\x18\xc5\xe6\xc8\xfe\x38\x48\x8a\xb2\xe7\x6e\x18\xe4\x90\x0b\x39\xaf\xfe\xac\x7c\x7c\x7d\xa5\x85\xa4\x13\xcc\xcb\xb0\x8f\xdb\xc7\xaa\xbf\xec\x83\x8d\x17\x2c\x3f\x6d\x55\xe1\xa4\x94\x46\x68\xc8\xe6\x9e\x22\xef\x58\x2f\xa2\x1e\x7b\x48\xdb\x3c\xe8\xf7\x84\xb4\x55\x98\xd1\xb6\x61\xab\x1d\x4d\x84\xac\x1d\xf5\x28\x70\x56\x50\x44\x7d\xd2\xe5\x9d\xf6\x2a\x31\xc8\x5a\x03\xf8\xcc\x68\x96\x3b\x57\xce\xaa\x47\x87\xd4\x2c\x65\x33\xa6\x44\x8b\xec\x93\x6a\xa2\xf5\x21\xf5\xae\xf4\x85\x0d\x1c\xaa\xcc\x66\x0f\x05\x16\x0b\xaa\xce\xeb\x02\xd9\x7f\xdb\xa6\x2b\x91\x1d\x05\xd5\x1a\x24\x7f\x47\xfe\xf3\xe8\xc7\xdf\xff\xd2\x3f\xfe\xf2\xe8\xe8\x87\x37\xfd\xbf\xfd\xf4\xfb\xa3\x1f\x07\xf8\x8f\xdf\x1d\x7f\x79\xfc\x8b\xff\xe3\xf7\xc7\xc7\x47\x47\x3f\x7c\xfb\xe1\xeb\xdb\xe1\xc5\x4f\xec\xf8\x97\x1f\x78\x99\xdf\xd9\xbf\x7e\x39\xfa\x01\x2e\x7e\xda\x70\x92\xe3\xe3\x2f\xbf\x68\xbd\xf4\x0e\x6a\x77\xda\xd1\x65\x05\xcf\xe6\x8c\x9d\xa0\xdf\x27\x2c\x5b\x6f\x87\x47\xaf\xae\xcf\xbf\x8f\x1e\x7e\x57\x33\xa4\x8a\x5d\xef\xcd\x01\x57\x90\x48\xd0\x9f\xc3\x92\x63\xdf\x14\x54\x10\x38\x54\xa4\x52\x2d\x5e\x1b\x9f\xfb\x35\x18\x77\xaa\xb6\x76\xb8\xaf\xb5\x24\x3a\x96\x22\xf7\x59\xe1\xe8\xde\xc0\xfe\xf4\xfe\xbe\x3b\x68\xd5\x1c\xd5\x8e\x68\x0c\x8a\xc6\xa0\x35\xe3\x49\x63\xd0\x8d\xc5\xc3\xbd\xb5\x04\x01\x9f\xed\xea\xc2\x58\xe9\x41\xf7\xba\x4e\x58\x42\x6d\x33\x87\xda\xc0\x1f\xf5\xba\x1f\x64\x1d\x42\x63\x19\x5a\xbe\xda\x87\x49\x4e\xb1\x57\xb3\x3d\xf8\x38\x41\x9d\x76\x61\x55\x1b\x57\xe1\x0f\x66\x66\x09\x55\x89\xe8\x46\x31\x48\x0c\x74\xc4\xd0\xd3\x7f\xd8\x48\xd0\x3b\x1b\x1c\x6a\x94\x34\xc6\xeb\x32\x9a\x95\x70\x58\xd7\x5e\xa6\x4a\x89\xc4\x06\xb5\x56\x49\x00\x58\xd9\xcd\x2d\x1b\x57\x83\x0d\xe2\x0b\x09\x09\xa4\xc0\x13\x70\x75\x99\x1b\xbd\x2f\x29\x27\x17\x7c\xe6\x6b\x53\xa7\x3e\xa5\x04\x57\xb2\x7a\x8e\xd7\x15\x80\x60\x10\xd1\x39\xc1\x82\x38\x04\xa4\xfa\x75\x34\x2b\x86\x62\x88\x71\x6d\x65\xdd\xad\x3d\x5e\x6b\x2e\xde\x9e\x67\x56\x9e\xad\x56\xc2\xd0\x12\xb3\xac\xcd\xcf\x4d\x26\xf9\x1a\x9c\x81\xed\xd9\xe7\xaf\x8e\x75\x76\xc4\x36\xbb\x61\x99\x5b\xf8\x4e\xba\x64\x93\x5d\x38\x4b\x0a\x09\x63\xf6\xd0\xd1\x39\x3d\xe5\xb5\x25\x86\xa5\xc0\x35\x1b\x33\x9b\x62\x52\x48\x28\x80\xdb\x2c\x01\x9a\x4c\x91\xf6\x3b\x4e\x59\x3b\xa7\xf7\x31\x98\xc7\x0a\xdc\xdd\x92\xb2\x9b\x55\xc2\x7e\xa4\x63\x24\xd2\xb1\x9d\xc7\x67\xa2\x63\x0e\x73\xf7\x87\x88\x61\xe4\x79\xfb\x98\xf7\xb3\x66\xad\x15\xd7\x95\x76\x4b\x44\xab\xd3\x8e\x4e\x70\x96\x9d\x0c\xd0\xad\xf0\x01\x5f\x3b\x2c\xb3\xac\xa3\xfa\xd4\x87\x97\x08\x8d\xa2\xcc\x32\x97\x96\x3b\x20\x1f\x39\x1e\xc9\x53\xec\x83\xd0\x23\x57\x30\x03\xd9\x23\x97\xe3\x2b\xa1\x87\x56\xb6\x6d\x86\xb3\xd9\x1b\x09\x1b\x93\x77\x46\x6b\x52\x9a\x68\x5b\x8b\x3e\xa8\x9c\x23\x64\x63\x82\xba\x28\x57\x8b\x30\xf4\xf5\xdb\xf2\x5b\x9f\x30\xd9\x7f\xa6\x6d\xaa\x9a\x7d\x74\xa0\x9e\xba\x99\x7c\x80\x1c\x06\x45\x3a\xef\xc8\xaa\xac\xd7\x17\x58\x88\xa2\x10\x4a\xdf\x18\x2d\xb6\x9b\x46\x30\x43\x3f\x1d\xf6\x56\xa0\x59\x06\x69\xa3\x13\x90\xed\x60\x41\x9b\x5a\x34\xe6\xe3\x56\x0d\x15\x80\x4c\x29\x4f\x33\x90\x58\x14\x5d\x2d\x56\x7e\x62\x75\x17\x80\xaa\x6f\x83\x4f\xd0\xa4\x49\x22\x64\xea\x3a\xb0\xba\x44\x49\x5c\x4c\x75\xbc\x90\xd6\xe6\x94\xd3\x09\xa0\x65\x61\xa9\xb4\x2e\x16\x5c\x56\x41\xf3\x87\xa9\x10\x77\x24\x11\x79\x91\xe1\x01\x68\x71\x3e\xea\xde\x33\x15\x8a\xf6\xcd\xec\xea\x24\x68\x4b\x83\x3f\xb4\xeb\x4a\xd3\x4a\x58\xe9\x42\x54\x81\x07\x48\x3a\xeb\x5b\x77\xf1\x00\x49\xd0\x78\xd1\x6c\x89\xeb\xbc\xa8\x05\xda\x36\xda\xf7\xd3\x6d\x6d\x96\xef\xca\x14\xde\x22\xcb\x2c\x1c\x0b\x85\xd6\x70\x4e\x5f\x57\xda\xbd\x02\x4b\xf4\xdb\xac\x62\xcc\x3c\xf3\xa5\xa6\x1b\x87\xc1\x1e\xbd\xa5\xea\x6c\x55\xb0\xb1\x9f\x0b\x73\x9f\x85\xd0\xe4\xe8\xf0\xe4\xf0\x78\xc9\x46\xb7\x50\x9c\xf8\x36\x78\x92\x61\x35\xbe\x02\x4b\xdb\x41\x72\x98\xf6\x08\xd3\x9e\xd8\xda\xa2\x00\xb8\x2a\x97\x0e\x87\x1d\xea\xb5\xa4\x29\x73\x5a\x10\xfe\x6a\x6e\xd2\xb2\x74\x15\x01\x8e\x0e\x7f\x39\xec\x11\xd0\xc9\x31\xb9\x17\xfc\x50\xe3\xf2\xb1\x7c\x46\xa9\x82\x89\xe6\xa2\xc4\x2e\x75\x16\x04\x55\x2d\x0c\x43\xb1\x88\x28\x6d\x4b\x9b\x29\xd5\x3e\x0d\xef\xe2\x81\x69\xdf\xc6\x41\x8c\xc9\x1b\xdb\x51\x07\xa8\xb3\x12\x66\x6c\x06\x27\x53\xa0\x99\x9e\xda\x40\x0a\x2e\x78\xdf\x36\x45\x33\xa4\xc4\x5d\x69\xeb\x53\x68\x67\x72\x0b\x47\x0b\xf3\xdb\xf2\x82\x5a\x4a\xd7\x86\x88\x7e\xbd\x7b\xa7\x56\xb2\xd4\xc4\xf8\xf6\x76\xf8\x75\xa3\x57\x2b\x52\x71\xad\x0b\x1f\xde\x12\xd4\x95\xd8\x03\xda\xd1\x8d\x43\xaf\x55\xd3\x56\xd2\x21\x09\x6b\xdb\xbc\x95\x2c\x37\xa5\xde\xae\x6b\x2b\xf9\xa7\x28\xb1\xdb\x1c\x1d\x65\x73\x72\x4f\xb9\xf6\xa9\x78\x07\x66\xaa\x03\x43\x9e\x0c\x36\x7c\x03\x34\x05\xa9\x90\x7a\x00\xdd\xb9\x7e\x96\x1f\x9d\x39\x9a\x82\xb5\x75\xcb\x07\x4a\xa5\x45\x4e\xa6\xee\xb3\x9b\xe9\x89\xee\x64\x0c\xf0\xf4\xf8\xdc\x1f\x09\x85\xa5\x70\xee\x99\x57\x47\xbf\x96\xe8\x86\x85\x7b\xa3\xce\x7c\x12\x82\x2d\xec\x46\xc2\xb8\x05\x96\xed\x23\xd8\x11\x2d\xed\x20\x40\x80\x74\x18\x24\x40\xda\x25\x3b\x2e\x4e\x84\x8e\xaf\xf6\xf1\x50\x9d\xc5\x1d\x90\xce\x7c\xeb\x64\x95\x21\xd2\xe1\x8c\x8d\x82\xb5\x36\x8f\x46\xe9\xb8\x84\x72\xc1\x59\x42\x33\xf6\x2f\x48\x6d\x57\x5c\x1b\x63\x86\x72\x4e\x42\x15\xf4\xd1\xf1\xc9\x2d\xfd\x0b\xda\xbc\x72\x73\x1c\xb5\x10\x28\x7c\xa0\xab\xcb\xd0\x47\xfb\xbe\xf6\x91\x0b\xa4\x5b\xbf\x39\x69\x9f\xb4\x19\x8e\xc7\xc1\xdc\x0d\x8a\x91\x2e\x21\x50\x74\x10\x64\xbd\x1c\x62\xbd\xd4\xb3\x1b\x89\x91\xad\x0a\xbb\x37\xbc\xac\x6d\x03\x73\xb2\x3a\x63\x59\x12\x5e\xf5\x9b\x7d\x19\x4d\xcc\x49\x77\xc1\x90\x5d\x87\x42\x76\x1a\x08\xf9\x49\xc3\x20\x31\xf9\xa2\x35\x15\x69\x5a\xe1\x71\x4a\x83\x01\x46\x3b\x34\x7a\xad\x93\x30\x9d\x0d\xc9\xf7\xc4\x68\x1a\x5d\xcd\x51\xdb\x8b\x33\xa6\x93\xe2\x46\x24\x77\x1d\x6a\x4f\xe7\x50\x48\x48\xac\x35\xee\xf6\x6c\x68\x67\x37\x5a\xec\xd5\xc7\xdb\x3a\xe8\x1f\x23\x63\x6a\xf3\xe8\x37\xce\x5e\x67\x34\xdf\x3b\x28\x74\x65\x20\x18\xd1\xe4\xee\x9e\xca\x14\xed\x67\x54\xb3\x11\xcb\x98\x9e\xa3\x09\x40\x02\x66\x14\x70\x61\x43\xef\x6c\x29\x46\xe1\x1b\xaa\x56\xdd\xbe\x2b\x4b\x19\xda\xe1\x1c\x0b\x1c\x53\x66\xb4\xfe\xaa\x6b\xae\x8d\xcd\x49\x8a\xca\x70\x18\xda\xbf\xa3\x8a\xe7\xc7\xde\xaa\x78\x41\x47\xd8\x6d\xb5\xbd\xb6\x11\x82\x7b\xcc\xea\x1c\x8b\x93\x55\xc3\xb3\xc8\xea\x3a\x9a\x6f\x7f\x59\x5d\x21\xe1\x46\x8b\xa2\x23\x5f\x8c\x9d\x6c\x8d\x27\x66\x04\x63\x61\x88\xf0\x5a\xd7\x4a\x5a\x82\x2b\xca\x79\x3a\xbc\xac\x6c\x67\xa2\xe1\x3e\xb1\xb1\x91\xbe\x12\x67\xc6\x66\xc0\x41\xa9\x13\x74\xba\x94\x85\x6b\xfa\xef\x7a\xdb\xf6\xcc\xd7\x41\x8e\xab\xeb\xd5\xf9\x06\xae\xb3\x2e\xfe\x08\x3a\xb1\xf6\xe1\x80\x90\x63\xd3\x2e\xb7\xfc\x45\x67\x4d\x22\xa9\x9a\xda\xae\xb3\xf0\xc0\xb4\xeb\x9c\x3c\xb4\x95\x7a\xc3\xe6\xb7\x13\x49\x13\x20\x05\x48\x26\x0c\x33\x2a\xb9\x4e\xc5\x3d\x27\x23\x98\x30\xae\x3c\x28\xb0\xd6\xa6\x83\x19\x7a\x7d\x98\xaa\x0a\xb3\x0d\xc8\x75\xa3\xec\x88\x4b\x08\x4a\x44\x7d\x34\xdd\x9a\x17\xfd\x55\xc8\xb1\x10\x4e\xb6\x87\x4b\x05\xe1\xb0\xad\xcd\x53\x4b\x3e\x2a\x39\xbe\x39\x85\x8c\xce\x6d\xdc\x27\x76\xa4\x66\xff\x02\xa9\x8e\x3b\xf0\x6b\xd9\xc6\x4c\xfe\xda\xda\x75\x60\x91\x53\x9a\x4c\xdb\x39\x8a\xa3\x23\x6c\xc3\x11\x1d\x61\x6d\x26\x89\x8e\xb0\xe8\x08\x7b\x62\x44\x47\x58\x74\x84\x2d\x8c\xbd\xd5\x92\xa2\x23\x6c\xe7\x11\x1d\x61\x8f\x8f\xe8\x08\xdb\x60\x44\x47\xd8\x86\x23\x3a\xc2\xd6\x8f\xe8\x08\x6b\xb7\x98\xe8\x08\x8b\x8e\x30\x37\x7e\x7d\xd6\x41\x3f\xa2\x23\x6c\x69\x92\xe8\x08\x8b\x8e\xb0\x8d\xc7\xde\xaa\x78\xd1\x11\x66\x47\x74\x84\x35\xc7\xaf\x8b\xd5\x79\x37\xd2\xd0\x28\x94\xed\x9b\x0a\xa3\x5a\xea\x68\xec\xab\x4c\xe1\x6a\xe3\x65\xf8\x3c\x1e\x86\x3d\x71\xc7\x74\xe0\x55\x88\x1e\x85\x57\xe7\x51\xe8\xc6\x1a\xd7\x81\x25\xae\x35\x4d\x76\x8e\xf6\xdb\xa9\x04\x35\x15\xd9\xce\x88\xde\x40\xf2\x0f\x8c\xb3\xbc\xcc\x0d\xce\x29\x83\xcf\x6c\x56\x79\xf4\x55\xdd\x69\x19\x1d\xfd\xd6\x28\x68\x6e\x64\x29\x60\x15\x51\xca\x32\xb3\x8d\x98\xf4\x39\xa5\x33\x83\xeb\xaa\x4c\x12\x00\xec\x51\x16\xaa\x12\x7f\x1c\x54\x6f\xaa\x7a\x52\xbc\x6d\x47\x6f\xda\x71\x4b\x5b\xe7\x13\x67\xf9\xe3\x1f\x76\x9a\x63\x22\x8b\x6e\xe8\xf2\xd7\xd7\xc3\xb3\x80\x2e\x53\xee\xc9\x32\xe3\x33\x91\xcd\x6c\x27\x5b\xbc\xc9\x48\x45\xcf\x48\xa4\xdb\xcb\xf7\xad\x64\xfb\x2e\x78\x44\x5b\xf1\xb5\x29\x7b\x18\x21\xb5\x69\xa2\x99\xe0\x5e\xda\x72\xf2\x1b\x0b\xa9\xad\xa9\x5b\x7b\xc1\xb1\xfd\x71\x20\x58\xef\x05\x3f\xbc\x33\x00\x1f\xb8\x3e\xdf\x9e\x05\x87\x1a\x82\x6f\xb1\xa4\x05\x29\x32\x5a\x37\x49\xc2\x1d\xf8\x06\xf9\xc6\xd9\x14\x92\xbb\x6b\xe7\x0c\x3d\x52\x00\x55\x24\xcb\x84\xe9\x69\x39\x1a\x24\x22\x3f\x31\xc7\xd8\xfe\x67\x94\x89\xd1\x49\x4e\x95\x06\x79\x92\x8a\xc4\xb1\xa5\x7e\x62\x66\x61\x7c\x32\xc8\xd3\x63\x6c\xc3\x7b\xd9\x6c\xca\x18\x94\x62\x30\xef\x77\x0a\x1c\x19\x81\xa1\x88\x02\x95\xf4\xa0\x9e\x9b\x59\xde\xd6\x8d\x73\xc3\xd1\x9a\x8d\xb4\x74\x44\x7f\x7e\x27\x74\xa4\x5c\xa4\x03\x6b\xc4\x4b\x73\x36\x77\x16\x74\xd1\x81\x93\x79\x8f\x1c\xcc\x7b\x23\xce\xee\x8b\x53\x79\x0f\x4b\x2f\x77\xe0\x48\xee\xc2\x89\xdc\x9d\x03\xf9\x13\x54\x28\x7e\xc9\x8e\xe3\x0e\xad\x6b\x1d\x39\x8c\x3f\x87\xb3\xb8\x93\xaf\x6e\xeb\x24\xfe\x7c\x0e\xe2\x6e\x3e\xb7\x4b\x75\xe3\xa5\x3a\x85\x3b\xb0\x92\x77\x69\x21\xef\xcc\x3a\xfe\xc9\x9c\xc0\xed\x1d\xc0\x7b\xe0\xfc\x6d\x0d\x64\xc6\x99\x66\x34\x3b\x87\x8c\xce\x6f\x20\x11\x3c\xdd\x99\x8f\x2d\x14\xc6\xac\xce\x8f\xb2\xd3\x3a\x0b\x56\x33\xa3\x62\x4a\x5d\xfd\x6f\xa3\xb7\xd9\x0c\x12\xef\xb9\x70\x62\x0b\x3a\x1d\xec\x2a\x77\x29\xad\x77\x2f\xe4\x5d\x26\x68\xaa\x4e\x0a\x61\xff\x53\xe7\x4b\x04\x89\x12\xf6\x5d\xed\x32\x25\x9e\xdb\x54\x66\xd3\x4b\xba\xdc\xc4\x6f\xc4\x3d\x11\x63\x0d\x9c\x1c\x31\xee\xf7\xf1\x38\x50\x36\x6b\xbb\x65\x85\xd6\xe6\xea\xdb\x37\xfe\xe6\xd7\x67\x90\x44\xd3\xab\x52\x9f\xde\x3e\xec\x5e\xf4\xb4\x81\xd8\xdd\x38\x2e\xb3\xa6\x91\xd8\x1a\x8e\x9b\xf4\xe6\x6d\x5d\xc1\xf8\x2d\xce\x5b\x9d\x36\xca\x53\xe2\x52\xce\x5e\xdf\xa6\xb5\x0e\x6d\x69\x8a\x7e\x55\x28\xcb\x53\xf6\xe4\xdb\xb3\x61\x34\x27\xef\x97\x51\xe6\x99\xc2\x43\xf6\x50\xd0\x7d\xa1\x21\x21\x51\xd0\xdd\x62\x04\x49\xa8\x5f\x4b\x9a\xc0\xb0\x73\x19\xc1\x1f\x27\x92\x96\x92\x3a\x02\x58\x89\x7c\xfe\xf0\x70\x80\xd4\x9e\xa6\x2a\x71\x17\x53\x62\xc7\x65\x96\xcd\xad\xcd\xa1\x91\xe6\x6c\xbd\xf0\x8b\x59\xb3\x68\xf8\x5f\xf1\x96\x5a\xb0\x2c\xa4\x70\x3c\x53\x96\x9c\x1b\x1a\x5c\xb7\x21\x43\x41\x12\x6b\x37\xd3\x46\x6e\xae\x62\x13\xb3\x7c\xc3\xff\x30\x6d\xb7\x8e\x01\x6c\x4c\x68\x9e\x1e\x0b\x99\xb0\x51\x36\x27\x53\x9a\x55\x3d\x67\x28\xb9\x63\x59\xe6\xa6\x19\x90\x1b\xd0\xd6\x71\x61\x79\x67\x26\xf8\x04\x17\x47\xb9\xef\x75\x08\x89\x79\x36\xc9\x80\xf2\xb2\xb0\xef\x33\x9c\x78\x2e\x4a\xe9\xdf\x37\xa8\xdc\x1f\x15\x07\xe6\x2c\xeb\x05\x1d\xd5\x1e\xdd\xd8\xda\x44\xa3\x8c\x00\xf0\xd1\xd7\xaa\xee\x85\x73\x8a\x19\x48\xc9\x52\xe7\x4d\xb0\xbf\x15\x52\xcc\x58\x6a\x7d\x28\x1e\x6c\xd8\xbb\xd9\xf6\xcc\xa9\xce\x33\x17\xbc\xcf\x61\x42\x51\x50\x71\xa7\xc8\xee\x99\x9d\xc7\xc6\x16\xf0\x14\xbb\xe8\x18\x09\x5f\x14\x8d\xbc\xf9\x19\xb3\xfd\x7f\x03\xc8\x91\x23\x2e\x88\xc0\x90\xd0\x92\x33\x6d\x7b\xca\x4f\x4b\x4d\x52\x71\xcf\x8f\x9d\xcd\x8a\x29\x42\xc9\x08\x34\x0d\x82\x3a\x1d\x83\x53\x04\x38\x1d\x65\x66\xcf\x31\x5a\xe9\x76\x25\x80\xc8\x18\xa8\x2e\x25\x90\x09\xd5\xb0\x52\xce\xb1\xdf\xfb\x38\x78\x99\x72\x06\xd6\x31\x29\xb9\x82\x96\xec\xbd\x33\xe1\xe8\x2f\x7f\xda\x8d\x46\xb0\x1c\x44\xa9\x3f\x8b\xf6\x77\x3f\x65\xc9\x34\x14\x66\x59\x0e\x8a\x88\x72\x41\x2d\x7e\xeb\x1e\x5b\xbd\x43\x51\x05\x5c\x35\x76\x35\x1f\xaf\xb0\x7e\xb9\xb6\xac\xcb\x91\x7d\x41\xdb\x69\x0c\xda\x3e\xbf\xba\xf9\xf9\xfd\xe9\x7f\x5c\xbc\x77\xe7\x93\x87\x4c\xbf\xe4\xec\x7f\x4a\x20\x34\x17\x46\x16\xce\xc2\x00\xc1\x1e\x6a\xf4\xc1\x0f\x78\x92\xbb\x0d\x25\xdc\x91\x21\x63\x8f\xfc\xf6\x01\x93\xd8\x69\xff\xd3\xc7\x4b\x3e\x77\xef\xb0\xaa\x2b\x05\x46\x69\x04\xbd\xc3\x28\xe1\xa0\xcd\xc9\xb3\x12\xa5\xed\x25\xc7\xf8\x24\x0b\x85\xc9\xdd\xc8\x55\x5b\x9d\xa8\xad\x46\xd4\xaf\xbf\x60\xb8\xab\x62\xd4\x49\x0f\xb3\x7a\x0d\x1d\x75\xfe\xa9\xa9\xb6\x57\x03\x6c\x6b\x66\xaf\x06\x58\xd1\xe3\x72\x48\x68\x9a\x4a\x14\x53\xf0\xd4\xe7\x0b\x1d\x40\x8b\x3a\x62\xa7\x47\xde\x90\xbf\x93\x07\xf2\x77\x54\x0b\xfe\xd2\xb6\x4f\x52\x5b\x81\xbd\x8b\x00\x1c\xa3\x8d\x5e\x0e\x3b\x82\xf8\x3f\xa6\x54\xe3\x8c\x06\xaa\x5a\x90\x11\x73\x62\x28\x3c\x68\x90\x46\x2c\x72\x3b\xf1\xac\x1d\xa6\xcc\x02\x3f\x23\x9a\x59\x33\xf9\xe5\xb8\x19\xf4\xb3\x1d\xa2\x99\xc7\x8d\x7e\x7f\xe5\xa8\x50\xb3\x9b\x4b\x3d\x5b\x4e\x75\x32\x6d\x92\x31\x23\x60\xa8\x06\x73\x4a\x05\x92\x71\x1b\x90\x3b\x65\x2d\x42\x0b\xf6\x07\x8d\xdb\x79\x9b\x1b\xfb\xf9\xd8\x4e\x2d\x28\xfe\xc8\xe7\x9d\x60\x10\x94\x6e\x2a\x44\x3a\x20\x17\x34\x99\xe2\xb2\xd2\x80\x67\x18\x0d\x04\x27\x9b\xd2\x99\xd9\x78\xf7\xac\xf5\x63\xa3\xb4\x52\x59\x47\x11\x97\xcc\x79\x4a\x28\xb7\x2d\x48\xc7\x20\xa5\x8d\xa1\x1e\xcd\x7d\x28\x5b\xeb\xcd\x6b\x75\x92\x0a\x29\xb4\x48\x44\x8b\x26\x58\x8b\x79\x19\x38\x1d\x02\xa1\xb0\xb8\xeb\x20\xff\xdd\xf9\xb0\x47\x6e\xcf\x86\xd8\xba\xe8\xe6\xec\x76\xd8\x94\xb0\x0f\x6e\xcf\x86\x07\xcf\x0a\x0a\xe2\xcd\x6c\x68\x50\xdd\x61\x92\x86\xc1\x24\x63\x4a\xf7\x73\x5a\xf4\xef\x60\xbe\x23\x4f\xed\x82\xaf\xf7\xab\x1d\xee\xe4\x83\x2c\x98\x73\x5a\x6c\x3d\x9b\x04\x9a\xb2\x98\x00\xb4\xf9\x88\x09\x40\x1b\x8e\x98\x00\x14\x13\x80\x96\xc7\xde\x44\x4c\xc6\x04\xa0\xd7\xe5\xba\x8d\x09\x40\xdb\x8f\x67\xf7\xd8\xc6\x04\xa0\xd5\x23\x26\x00\xc5\x04\xa0\xcd\x46\x4c\x00\xda\x7e\xec\x5d\xac\x49\x4c\x00\xda\x6a\xc4\x04\xa0\xe5\x11\x13\x80\xd6\x8c\x98\x00\xb4\x66\xc4\x04\xa0\xe5\x11\x13\x80\xb6\x1b\x31\x01\x28\x26\x00\xbd\xea\xb8\x48\x12\x13\x80\xdc\x88\x09\x40\xaf\x22\xfa\x8b\xc4\x04\xa0\x8d\x46\x4c\x00\x8a\x09\x40\xbb\x8c\x98\x00\xf4\x5a\x8c\x32\x31\x01\x28\x26\x00\xfd\x7a\x04\xdd\x98\x00\x14\x13\x80\x62\x02\x50\x4c\x00\x7a\x74\x15\x31\x01\xe8\x35\xa8\x80\x12\x14\xfb\x17\x0c\x45\xc6\x92\x79\xeb\x80\xbf\x6b\xd7\x5a\x56\xb9\x69\x49\x81\xf3\x06\xa1\x55\x2d\x92\x38\xf6\x2c\x77\xe5\x3a\x00\x5c\x98\xc3\x52\xb5\xd7\xfd\x04\x20\xd8\x8b\x3c\x16\xff\x81\x57\xbb\x7b\x52\x70\x12\xa3\x35\x5a\xf0\xed\x66\xb7\x68\xad\x22\x84\x1f\xd2\x51\x68\xf5\x61\x98\x0a\x57\x61\x82\x16\x15\x05\x63\x6b\x11\x84\x16\x45\xc6\x40\x0d\xc8\x4d\xd5\xe2\x04\xa9\x97\x7a\x47\x92\xa2\xec\x91\x1c\x72\x21\xe7\x2d\xb4\x89\x0e\x04\xce\xc6\xae\x75\x04\xb2\x6b\x3b\xa7\x07\x83\x51\x22\x8a\x22\x9b\x5b\x61\xaa\xce\x1c\xac\xa0\xc6\x3c\x71\x49\x51\xdc\x59\x88\xf2\x60\xba\xa1\x86\x5d\x09\x7d\xed\x10\xfe\xd9\xc2\xd6\xd7\x05\x68\x53\x2d\x72\x96\xec\x42\xb0\x2d\x8d\xed\x90\x5a\x6f\x1c\xa1\x4d\x2e\x56\xfc\x8a\xa6\x6b\x55\x98\x49\x64\x3d\x65\x26\x81\xa6\x73\x9c\x12\x9b\xf9\x04\x5a\xf1\x0b\x0c\xf4\x4e\x32\xca\x76\xf7\xca\x37\x03\xa7\xce\x70\x2e\x62\x50\xa1\x0e\x9d\xc2\x08\xdc\x0a\x7c\xbd\x2a\x2c\x89\xd9\x43\x30\xf0\x97\xec\xc3\x3d\x1b\xc7\x6b\x40\x8e\x22\x25\x0a\xde\x4c\x85\x1a\xf7\x8f\xbc\x16\x7e\x39\xa1\x59\x31\x7d\x5c\xfc\x35\x0b\x39\x9f\x73\x9a\xb3\xc4\x23\xc6\xa9\xdd\x3b\xa3\xee\x34\x05\x60\x3f\xb7\x9d\xcf\xbc\x24\xcf\x4b\x4d\x47\x19\x0c\xc8\xa5\x4d\xa5\x11\x1c\x3b\xdd\x63\xfc\x85\x73\x6b\x78\x24\xda\x35\xc2\xaa\x7d\x78\x45\xcb\xd0\x8a\x95\xa7\x07\x37\xc4\xa6\x0d\x01\x37\x98\x2f\x38\x10\xe0\x5a\xce\xcd\xde\x0d\x45\x7a\x63\xb6\xaf\x71\x77\xeb\x6c\xa2\x96\x11\x15\x5d\x44\x53\xb4\x8c\xa4\xe8\x26\xfe\xa1\x7d\xec\xc3\xb2\x13\x37\x48\xf0\x0b\xc3\x1a\x1b\xbb\x6a\x68\xd8\x8a\x53\xe9\x19\xff\x50\xa4\x86\x7d\x49\x08\x5b\x89\x39\xed\x0f\x0f\x48\x4e\xef\x50\x81\xa6\xba\xe6\x6b\x74\x46\x59\x66\x8e\x50\x9d\x1e\xd0\x52\x56\xf4\xa3\x03\xc6\xdf\x75\xd6\x14\x69\x8b\x41\x5d\x66\x3d\x11\xec\x7c\x94\xb3\xdd\x32\xf8\xc9\x92\x0c\xf8\x1e\xe7\x0a\x82\xad\x0c\x4e\xe4\xf4\x01\x35\x52\x9a\x8b\x92\x6b\x83\x29\x89\xc8\x8b\x52\x37\x79\x26\xb2\xdf\xad\x55\xd5\x44\xf0\x31\x9b\x38\x13\xd7\x49\x4e\x39\x9d\x40\xbf\x9a\xb6\x5f\x93\xde\x93\x76\x7a\x6a\x2b\xb2\x43\x53\x9f\xe0\x32\xec\x22\x56\x9c\x6a\x0d\x92\xbf\x23\xff\x79\xf4\xe3\xef\x7f\xe9\x1f\x7f\x79\x74\xf4\xc3\x9b\xfe\xdf\x7e\xfa\xfd\xd1\x8f\x03\xfc\xc7\xef\x8e\xbf\x3c\xfe\xc5\xff\xf1\xfb\xe3\xe3\xa3\xa3\x1f\xbe\xfd\xf0\xf5\xed\xf0\xe2\x27\x76\xfc\xcb\x0f\xbc\xcc\xef\xec\x5f\xbf\x1c\xfd\x00\x17\x3f\x6d\x38\xc9\xf1\xf1\x97\x5f\xec\xbc\xe4\xd6\x16\xe8\xee\xec\xcf\x1d\x59\x9f\x3f\x89\xed\xd9\x45\x69\x76\x74\x16\x5d\x84\xf9\xd2\x69\x74\xf6\xa1\xc7\x4e\xa3\xe7\x92\xa8\x66\x54\xf3\x30\x45\x44\xce\xb4\x76\x52\x32\x0d\xf3\xca\x16\x94\x0f\x47\x07\xd8\xd8\x52\x7a\xa6\xc2\x9c\xac\x40\x67\x11\xde\xd0\x8a\xca\x0f\x27\x2c\x2f\x32\xc8\x81\x6b\x3c\xcf\x7d\x2f\x09\xa2\x36\x38\xa8\x57\x92\x50\x6e\x64\x76\x78\x48\x00\x52\xf7\xb2\x48\x3a\x9e\x1e\x91\x74\xbc\x46\xd2\xa1\x20\x29\x25\xd3\xf3\x33\xc1\x35\x3c\xec\xe4\xef\x5c\xe7\xf0\xbd\x69\x4e\xed\x54\x33\x17\xbb\xea\xae\x11\x51\xd8\x4c\xcd\xb5\x35\x90\xa6\xa2\xcc\x52\xac\x30\x50\x72\x74\x01\xd9\x62\x15\xa0\xad\x7f\x06\x85\x44\x94\x20\x17\x5f\xe7\x3d\x2e\x76\xea\xff\x29\xd9\x8c\x66\xc0\x75\xf0\xc4\x10\x7d\x0c\xe1\x43\x3b\x99\x89\x9e\x59\xc5\x46\xe9\x67\x28\xd9\x8c\x65\x30\x81\x0b\x95\xd0\x0c\xa9\x52\x37\x8c\xe0\x74\xcd\xec\xb8\x45\x52\x64\xca\x48\xec\x86\x10\x13\xea\xdd\x69\xa8\xc7\x4e\x28\xe3\x24\x37\x44\xb5\xf0\x0f\x2b\xeb\x97\x33\xb4\xbd\xa0\xd2\x6c\x45\xe5\x7f\x43\xad\x78\x24\x44\xe6\xf2\x8a\xb3\x79\x3d\x3f\xb3\xca\x01\x17\x3f\x73\xb8\xff\xd9\xcc\xa6\xc8\x38\xa3\x93\xca\xed\x66\x54\xe5\x45\xcf\x79\x3d\xf5\xda\x0f\xc0\xa4\xdd\x12\x08\xcd\xee\xe9\x5c\xd5\x4e\xc8\x7a\x0e\xa6\xde\x91\xb7\xc7\x88\x78\x54\x91\x6a\x8e\x94\xfc\xe1\x18\x43\xe9\xce\x4e\x87\x3f\xdf\xfc\xf3\xe6\xe7\xd3\xf3\x0f\x97\x57\xe4\x4a\x68\xb0\x1c\x2b\xd0\x5e\x1c\xb3\x71\xab\xac\x6c\x73\x03\xa1\x06\xa8\x21\x61\x64\x38\x4f\xc5\xbd\xda\xd9\x42\x69\xd1\xcf\x00\x0f\x28\xdf\xcd\x48\x43\x0b\x8a\xfd\x9d\x5b\xf0\x87\xa5\x68\xed\x70\x52\x64\xd0\x69\x7a\x92\x4a\x51\x58\x20\x78\x87\x71\x68\x23\x3b\x5f\x88\x03\xf1\x59\x67\xb8\xbf\xe3\xe6\x84\x13\x49\xb9\xae\x3d\xa7\xf5\x9e\xb9\xc6\xd2\x83\xd6\xdb\xf1\x7c\x6c\xbb\x0b\x1d\x9f\xa6\xdd\xd5\x0c\x38\x4d\x53\x48\x1b\xe0\x7f\x75\xb9\x3e\x67\xfe\xe3\x02\x97\x14\x19\x7e\xbc\xb9\xfc\xdf\x0b\x78\x3c\x2f\xda\x25\x1d\x74\x53\xca\x45\x8a\xa2\xb3\xdd\xbd\x86\x5c\xcc\xe2\xfe\xee\xcb\xfe\x56\xdc\xb2\x9b\x50\xd7\xeb\x92\x87\x0c\x8d\x07\xf3\x93\x5c\xa4\x30\x20\xc3\x2a\xe6\xa6\x79\x35\x2c\x17\x29\x81\x98\x5b\xb8\x66\x34\xcb\xe6\xa1\x30\xa5\x85\xad\xf5\xd1\x28\x26\x16\x12\xf2\x31\xcd\xd4\x73\x53\xe3\x36\xbc\xd1\xc8\x11\x1f\x8c\xb2\xdb\xc9\x76\x54\xb3\x91\x14\xb8\xd0\x4e\x18\x36\xab\xc4\x02\x6d\x52\x24\xc4\x6a\xd6\x41\x62\x43\x83\xbf\x29\x1b\xf7\xe3\x59\x23\x53\x1e\xd8\xc3\x6a\x66\xeb\x32\x2d\x15\xa8\xd5\xac\xb1\xd6\xb5\xcd\xec\x12\x68\x8a\x3e\x87\x82\xea\xa9\x8d\x4b\xce\xa9\xba\x83\xd4\xfe\xe0\x44\xb3\xca\xed\x81\x66\x5a\xff\xaa\x5b\xb3\x6e\xef\xe1\x40\x91\xcc\x46\x4b\xa3\x6f\x04\xd2\x67\xde\xf5\x16\x87\xd0\x00\xe5\x23\xcf\xe6\xd7\x42\xe8\xaf\xaa\x62\x35\x9d\x60\xc0\x3f\x9c\xb4\xdc\x74\x3b\xa1\x38\x49\xf1\xbd\x7d\xdc\x0d\x3c\x54\x61\x9d\x9c\xf3\x7a\xc7\x5f\xfa\x91\x92\x25\x3f\x55\x5f\x4b\x51\xee\xcc\xc4\x96\x84\xcd\xaf\x2f\xcf\x91\x14\x95\x2e\xec\x8f\x6b\x39\x2f\x04\xb3\x26\xaa\x35\x8a\xc1\x77\x2e\x70\x31\x3c\x13\x75\x8c\x19\xf9\x40\xe7\x84\x66\x4a\x78\x58\x3a\xa7\xd4\x82\xbe\x48\x9c\x32\x6a\x2e\x8f\x84\x9e\x2e\x69\xa1\xe6\x40\x2d\x3f\xd7\x0b\xa2\x00\x6b\x5f\x3d\xe3\x4b\x8f\x6b\xf4\x78\x14\x12\x12\x48\x81\x27\xcf\xbd\xed\xcf\x1d\x3c\x87\xa8\x73\x25\xb8\x39\x98\x9d\x20\xcf\x65\x15\x35\xe9\x40\x1a\xa2\x0a\xba\xb4\x9c\xf6\x47\x31\x0a\x13\x8f\x65\xa9\x40\xda\x90\x51\x59\x82\xdd\xc9\x6f\xcb\x11\x64\x06\xf2\x46\x25\xc5\x72\x99\x54\x5b\xc3\x03\xcb\xe9\x04\x08\xd5\x15\xa6\x69\x41\x80\xab\x52\xba\x4d\x64\x9a\xa4\x02\xea\x1a\x57\x54\x91\xef\x2e\xcf\xc9\x1b\x72\x64\xde\x75\x8c\xf8\x33\xa6\x2c\xc3\x00\x4d\x0c\xf8\x58\xd0\x51\xc7\x7e\x0a\x5c\x12\x22\x2f\x11\xd2\x12\x89\x1e\xe1\x82\xa8\x32\x99\xfa\x35\x19\xbd\xd7\xab\xcd\x2e\xa9\x08\xfd\x26\xfb\x89\xeb\xcf\x4b\xa1\xbe\x53\x20\x3b\x23\x50\xdf\xed\x40\xa0\x42\x31\xca\xe0\x5c\x13\x7a\x16\xb1\x72\xd0\x34\xa5\x9a\x3a\xc2\xe5\x6f\xd8\xdb\x2d\xfd\x75\x93\x2f\x05\xef\x19\x2f\x1f\xac\x89\xb4\x3b\x53\xcb\xcd\x05\x4e\x8b\x38\x84\x50\xc7\x5d\xb7\x81\x71\x55\xfc\x50\x10\xe2\x72\xd9\xc0\x95\xde\x1a\x31\x11\xe9\x84\x0f\x43\x32\xc2\x09\xe5\xa9\xc8\x97\x5e\x86\x31\x4f\x34\x99\x86\x2f\x88\xd8\xd7\x1c\x7b\x62\x14\xca\x60\x06\x2d\x8a\xe1\x2e\x60\xde\x7b\x33\x9b\x01\x8e\xc7\x08\x9c\x9e\x64\x74\x04\x99\x0b\xb3\xb2\xa1\x99\xcb\x18\xf8\xdc\x99\x5d\x52\x64\xdd\xa5\xa2\x5f\x8b\x0c\x6c\xaa\x84\x07\x84\x99\xfe\x45\xc0\x01\x27\xe9\x0a\x0e\xa8\x0d\x36\xe0\x80\x7a\xed\x4b\x80\x43\xd9\x82\xd5\x93\x45\x38\x18\xb9\xa1\x09\x07\x64\xde\xfb\x0e\x07\x05\x49\x22\xf2\x62\x28\x85\x51\x3b\x3b\xe3\x4d\x6e\xda\xda\xcf\x67\x0d\x1b\x2b\x02\x2f\x91\x17\x34\x6f\xa6\x32\x48\x92\xa2\xda\x32\x09\x9f\x29\xf5\xbf\x02\x9e\x85\xa4\x67\x91\x91\xf9\x59\x1a\x8e\x40\xf3\xa4\xbb\xf0\x92\xd9\x41\x17\x79\xc6\x2d\x8c\x9d\x9d\x70\x23\x91\xd0\x0c\x9b\x1d\xb4\x43\x39\xb2\x88\x76\x8b\x13\x07\xa9\x71\xe8\xa3\xc4\xdf\x82\x38\x61\x8a\x86\x16\x6f\xc2\xe4\x22\x85\xc0\xeb\x6c\x63\x0f\x6f\x6d\x0a\x15\xde\xe7\xb3\xf2\x8c\x5c\xe1\xa2\x40\x20\x6d\x3c\xad\x85\xab\x33\xfc\xa1\x6a\xa1\x60\x16\x08\x3c\x65\x7c\x82\x76\xb5\x1e\x91\x90\xd9\x7c\x3e\x47\x04\xee\xac\x06\x79\x88\x47\xc2\x4f\xea\xcf\x83\x7f\xb5\x0f\x2b\x76\x33\x87\xb1\xc2\x6c\x6c\xc9\x2d\x53\xe4\xe0\xbd\x07\x40\x8b\x9a\xf3\xfb\xc8\x61\x0e\xec\x17\x56\xbb\x69\x2d\x9d\x77\x8c\xa7\x2e\xf5\xad\x01\x2c\xaf\xe7\x3a\x39\x18\x93\x2a\x59\x1a\xd2\x96\x77\xe4\x47\x4e\x2a\x60\x91\xfe\xce\xe8\x71\x6d\x45\x66\x6f\xa3\xeb\x3f\x6e\x78\xad\x5e\xb2\x38\xcd\x77\x1c\xf7\xde\xbc\xb7\x6f\x34\xf7\xe5\xfb\xfc\xb7\x3c\x6b\xb1\x4d\x47\xfd\xba\xd6\x62\xfe\x61\xa7\xf5\x22\x7d\x62\xd0\x5a\x33\x3e\x51\xa1\x26\xd3\xec\x6c\xb5\x5a\x95\xf1\x3b\x3c\x96\x22\xf7\x71\xc5\x8b\xaa\x41\x33\x65\xf7\xa5\xa8\x21\x99\x11\x27\x5e\xb8\x12\x32\xc9\x15\x3d\x93\x06\x12\x9a\xd1\xec\xa6\xd8\xbd\x11\x00\x59\x2a\x3a\xfd\xe1\xe6\xb4\x39\x35\x32\x6b\x17\x51\x0e\x78\x9d\xd0\x34\x67\x4a\xa1\x21\x0c\x46\x53\x21\xee\xc8\xd1\x8a\x0a\xba\x41\x94\x95\x62\x13\x75\xe2\x70\xbe\x6f\x56\x7f\x4c\x18\xcf\xaa\x48\x26\xd4\x83\xb9\xae\x82\xd8\xf1\x25\x49\xb5\x0a\xdc\x43\xd7\x68\xc5\x05\x2b\x2c\x2f\xd3\xb6\x56\x31\x58\xf0\xec\x04\x7b\x79\x7b\xda\xa5\xf9\x3d\xb9\x45\x57\x0e\xb7\x17\x6b\x21\xaf\x84\xa3\x95\x1e\x9f\x1d\x48\x4e\xb8\x48\x40\x75\x57\x82\xf5\x9b\x7a\x4e\x92\x82\xcd\x88\x07\x8c\x7e\xa2\x6b\xc3\xe1\xd0\x2e\x7d\x88\x85\x55\xdc\xa3\x87\xa1\x44\xdd\xcc\x35\xc2\x54\xa6\xbe\x55\xd2\x0d\x45\x43\x12\xe8\x45\x88\xa9\xe0\x42\x5a\x14\x35\x4c\x54\x70\x44\x69\x24\x51\xd6\x9b\x87\x7b\xe2\x48\x74\xb0\xd4\xb3\xda\x4b\x1c\x3a\x02\xb1\x30\x83\xad\xc5\x56\xaf\xe1\x9e\xe9\x29\x76\x53\x98\x2e\x78\x0d\x71\x25\x12\x14\x3a\x60\x38\x01\x29\x85\x74\x01\x59\xde\x6e\xed\x12\xad\x86\x22\xc5\x88\x2e\x83\x24\xd4\xfc\x75\xa8\x42\x47\x75\xdd\xbb\xa8\xaa\x8f\x09\xe3\x31\x24\x28\x68\x85\x00\xb6\x54\xfb\xa8\x6e\x2f\xe1\x33\xf8\xb4\xf0\xbd\x8f\x72\xf6\x60\xde\x12\x3e\xb5\xd0\x41\x91\x0b\xde\x5f\x7d\xf9\x78\x40\xc8\x25\xaf\xe2\x6f\x7b\x66\x17\xc3\x3b\x7d\xe8\x99\x36\x9f\x18\x36\xce\xc2\x0f\x08\x0d\x67\x46\x3a\x94\x65\x07\x18\xdf\xc6\x1c\x4e\x42\x93\x78\xa7\xe4\x00\x4d\xe3\x6e\x52\xb3\xf5\x5e\x06\x68\x63\x2a\x37\xb7\x7c\x2a\x73\xf9\xcb\x70\x80\x90\xb6\x74\xce\x55\x26\x8b\xdd\x8c\x36\x1b\xb1\x9b\xd1\x86\x23\x76\x33\x8a\xdd\x8c\x96\xc7\xde\x84\x0c\xc6\x6e\x46\xaf\xab\x0e\x65\xec\x66\xb4\xfd\x78\xf6\xf2\x93\xb1\x9b\xd1\xea\x11\xbb\x19\xc5\x6e\x46\x9b\x8d\xd8\xcd\x68\xfb\xb1\x77\x85\x73\x63\x37\xa3\xad\x46\xec\x66\xb4\x3c\x62\x37\xa3\x35\x23\x76\x33\x5a\x33\x62\x37\xa3\xe5\x11\xbb\x19\x6d\x37\x62\x37\xa3\xd8\xcd\xe8\x55\x17\x79\x27\xb1\x9b\x91\x1b\xb1\x9b\xd1\xab\x28\x65\x4d\x62\x37\xa3\x8d\x46\xec\x66\x14\xbb\x19\xed\x32\x62\x37\xa3\xd7\x62\x94\x89\xdd\x8c\x62\x37\xa3\x5f\x8f\xa0\x1b\xbb\x19\xc5\x6e\x46\xb1\x9b\x51\xec\x66\xf4\xe8\x2a\x62\x37\xa3\xd7\xa0\x02\x2a\x9d\xb2\x9d\x0a\x46\x6e\x52\xdb\xc6\xc5\x2c\x07\xa9\xe4\xa3\x72\x3c\x06\x89\x94\x0b\xdf\xbc\x14\x56\x55\x97\xf1\x5b\x74\xe5\x82\xee\x61\x99\x1c\x97\xde\xb1\xe6\x71\x97\xbb\x8e\x85\x1d\xeb\xc0\xe2\x8b\x8f\x5f\xad\x28\xa4\xb3\x73\xbc\xe1\xae\x21\xb5\xb8\xe6\x8f\x7c\x37\x2f\xfc\x1a\x80\xaf\x4a\x37\x72\x70\x4f\x32\xa1\x5c\x40\x34\x02\x2b\x99\x52\xce\xc1\xeb\x7b\x4c\xa3\x1d\x65\x04\xc0\x89\x28\xc0\xf9\xc0\x29\x51\x8c\x4f\x32\x20\x54\x6b\x9a\x4c\x07\xe6\x4d\xdc\x03\xbb\x0e\x5e\x76\xbf\x28\x2d\x81\xe6\x3e\x8c\x3b\xa7\xcc\x4e\x45\x68\x22\x85\x52\x24\x2f\x33\xcd\x8a\x6a\x32\xa2\x00\xf3\x2f\x2c\xa3\xaa\x80\x81\xf1\x72\x75\xc4\x73\xaf\x7e\x9b\x5b\x96\x08\x2b\x99\xa1\xb6\xd9\xc3\xda\xd0\x79\xa1\xe7\xc4\x7c\x72\xe6\x0a\xc2\x4a\xa5\x49\x92\x31\xe4\xd6\xf8\x46\x9b\x6a\x8b\xf3\xf5\x3c\xaf\xe6\x6e\xa5\xca\x2d\x95\xa7\x28\xb6\x16\x5a\x11\x0c\x10\xae\x27\x74\x53\xa5\x4c\x39\x31\x5f\xf5\x08\xf5\x65\xb6\x2c\xa0\xfd\x4a\x11\xd4\x9e\xb3\xd8\xd9\xdd\x4f\xc1\x74\x41\x79\x51\xdf\x18\xc8\xe5\x20\xd9\x58\xf9\x8c\x4e\x2a\xe4\xec\x35\x82\xff\x6b\x81\xc2\xb5\x40\x58\x38\x06\xb8\x01\x1c\x66\x06\x07\x20\x01\xc3\x5f\xe9\x1a\xac\xff\xec\x48\xaf\xa9\x9c\x80\xae\xd2\x05\x76\x8d\x22\x6f\x06\x9f\x84\x85\x80\x43\x45\xa4\x06\x19\x42\xc7\x35\x13\x09\x32\xae\x56\x55\x1a\xb6\x2b\x74\x05\xd6\x56\xdd\xe0\x05\x23\x1b\xbc\x59\x77\xa0\x29\x68\x02\x8a\x1c\x5d\x0e\xcf\x7a\x64\x78\x79\xee\x22\x34\xc5\x78\x55\x86\xb3\xa3\x61\x16\x03\xd7\xd5\x3c\xae\x6a\xb7\x05\xd3\x07\x59\xa1\xee\xdd\xc3\x4a\xbe\xc2\xb6\x32\xab\x28\x00\x8a\x5c\x55\x59\x74\xa2\x6c\x87\x2c\x67\x13\x62\x55\xca\x86\x43\x3e\xa8\x13\x15\x7d\x45\x22\xff\x44\xb5\x10\x07\x25\x97\x8f\xe1\x3d\xea\x48\x60\x91\x5f\x2f\x25\x7d\x60\x90\xa8\x8b\xae\xd9\x29\xaa\xa6\x95\x86\x14\x88\x62\x1f\x40\x29\x3a\x81\xe1\x8e\xee\xad\x75\x76\x00\xf4\x70\xd5\xe4\x00\x09\x50\xd6\x68\x5d\x16\x46\x0b\x37\x85\x6f\x92\xdb\x35\x55\x98\x75\x2f\x99\xd6\x80\xa4\x04\xcb\x00\xe2\x66\x2f\x56\x09\x38\x5c\x88\x39\xfe\xe0\x27\xa9\x1f\x36\xa2\x04\x4f\x6d\x04\xf0\x08\xc8\x48\x32\x18\x93\x31\xc3\xb0\x62\x0c\xf4\xed\xd9\xaa\x50\xd4\xda\x9e\x94\x02\x69\xbb\x15\x59\x0d\xca\xaf\x6b\x40\xfe\xe1\x16\xa6\x65\xc9\x6d\x37\x2a\x27\xdc\x63\x1a\x2c\x1b\x93\x09\x06\x0a\x3b\x1d\xe5\x4f\x6f\xfe\xf6\x17\x32\x9a\x1b\x41\x0a\x11\x52\x0b\x4d\xb3\xea\x23\x33\xe0\x13\x03\x2b\xcb\x14\x9a\x89\x9c\x15\x04\xb0\x9f\x88\x5d\xf8\xdb\x3f\xdc\x8d\x9a\x92\xdd\x49\x0a\xb3\x93\x00\x7e\xfd\x4c\x4c\x06\xe4\xac\xca\x9b\x2c\x8b\x14\xed\xfc\xbb\x17\xf1\xee\x0e\xcd\xba\x69\x0c\xe9\xcb\x93\x91\xa9\xb8\xb7\x1a\xe6\x0a\xec\xa9\x73\xc2\x0a\x51\x94\x99\x75\x75\x7c\x55\xa5\x40\x97\x0a\x96\x13\x15\x57\x9e\x0b\x34\xce\xbb\x29\x16\xe8\xa8\x8b\x0f\xf7\xaf\x14\x2e\x01\xc6\x99\x8f\xab\x2a\x65\x48\x4c\xbe\xa2\x59\x36\xa2\xc9\xdd\xad\x78\x2f\x26\xea\x23\xbf\x90\x52\xc8\xe6\x5a\x32\x6a\x78\xf4\xb4\xe4\x77\xb6\x87\x44\x55\xc7\x41\x4c\x5c\x00\x81\x2f\xfb\xbd\xea\x83\x6d\x52\xbf\x67\xfd\x5e\xf9\xae\x67\x81\x07\x56\x6b\xd8\x2e\x9f\xcc\x62\x64\x38\xbf\x0a\x91\xed\x0f\x6f\xfe\xf4\x57\x8b\xba\x44\x48\xf2\xd7\x37\x98\x43\xa0\x7a\xf6\x10\x23\x47\x35\xe2\x49\x4e\xb3\xcc\x10\xf2\x10\x29\x0d\xa0\x57\x21\xe1\x67\xc7\x41\xdd\x1e\xdd\x36\x16\xe0\x6f\x6f\xff\x89\x5c\x84\x69\x05\xd9\xb8\x67\x53\xa7\x2a\x65\xfa\x10\xc5\x91\x43\x47\x7d\x30\x7f\x6d\x0f\xc4\xee\x99\xc8\xca\x1c\xce\x61\xc6\xba\x68\x02\xd8\x98\xcd\x1b\x98\x32\xa6\x90\x0f\x8e\x32\x91\xdc\x91\xd4\x5d\x0c\xa2\xaa\x16\xcb\x95\xbf\xdc\x7e\xae\xe1\xf7\x37\x22\xca\x72\x5a\x14\x46\x06\xc0\x0c\x4d\x49\xef\x1b\xc0\xc0\x33\x89\x35\x15\x5e\x7e\x3f\x57\xfb\x45\x86\x6e\xee\x3c\xc5\xce\x61\x68\xed\x3d\x23\xf5\xea\x3b\xea\xeb\x57\x4f\xe8\x4f\x43\x81\xff\xb6\x59\x4e\x4b\x82\x79\x55\x6e\xb3\x42\x0c\x2b\x00\x18\xf4\x41\x92\xfc\x6c\x7d\x47\x49\xeb\x70\xba\x06\x5c\xf8\x23\xcd\xf1\x28\x29\x40\x2a\xa6\x0c\x5f\xfe\x1e\x0f\x94\xed\x8a\x58\x1b\x9e\x9f\x07\x08\xf6\x70\x63\x8d\xe7\xf6\x94\xd2\xe8\x29\x76\x42\x24\x85\xb6\xbe\xf5\x0a\xb1\xb6\x29\xd5\xde\x94\x23\xc4\x1f\xbc\x7d\x9b\x4e\xab\x1d\x72\xe2\xe7\xa6\xb1\xdf\xd7\xdb\xd0\x24\xb1\xe6\x97\x8a\xc6\xda\xbb\x5e\x13\x65\xc5\xef\x7b\xa9\x84\xb5\x5a\x7c\x47\xf4\x03\x29\xaa\xdb\xdc\x26\x09\x6d\x68\x9d\xf6\x84\x05\xba\x80\x53\x20\x07\xc4\x06\x6d\x98\x33\xe1\x1e\x25\x87\xef\x0e\x9f\x95\xba\x5a\x10\x49\x51\xd0\x49\xab\x4e\x45\x0b\x90\x5a\x9c\x36\x2c\xa3\x61\xf4\xa7\x80\x94\x14\xee\x2e\x43\x49\x7c\x95\x20\xac\x01\x65\x9d\xf9\x1e\xc0\x4e\xb3\xc0\x46\x73\xe4\x9e\xce\x09\x95\xa2\xe4\xa9\x33\x87\x56\xf6\xe8\x0f\x0b\x2f\xbe\x12\x1c\xea\xbe\xa5\xcd\x2a\x1c\xe8\x80\x62\x9c\xbc\x1d\xbc\x7d\xf3\x5a\x58\x1c\x7e\xe1\x02\x8b\xbb\xaa\x58\x9c\xa5\x4f\xcf\xfa\xad\xbe\x9e\x7f\x47\xdf\xfb\xc1\xd9\x66\xea\x72\xfd\xcc\x17\x03\xc7\x9f\xee\x25\xd3\x10\xb4\x27\x3c\x42\x8d\xc7\x28\x96\x41\xcd\x89\xe3\x55\x7d\x32\x5a\x02\xa9\x5d\x91\x0f\x55\x8e\x3e\x21\xdd\x72\x04\x0a\x8f\xdb\x2a\xd3\x98\x7a\x84\x84\x85\x80\x3a\x38\x20\x47\xf6\xce\x43\x9b\x99\x7f\xfc\xac\xa8\xe5\x80\x76\xf1\x50\xb4\xa8\x20\xba\x50\x04\xa2\xa0\x68\xbc\x2b\x3a\x84\xe0\x7f\xc0\x94\xce\x00\x2b\x12\xb0\x8c\xca\x0c\x5d\xe4\x37\x76\xed\x64\x54\x6a\x02\x7c\xc6\xa4\xe0\x68\x27\xc6\x94\x8d\x51\x06\x61\x77\xee\x2f\x8e\xbe\x3f\xbd\xc6\xf8\x9b\x63\xdb\x0f\xc6\xaf\xb2\x54\xbe\x38\x4f\xb8\x92\x60\xba\x27\xb7\xcf\xaf\xc3\xc0\x10\x69\xae\x5f\x97\x79\x4f\x5e\xea\xd2\x36\x9d\x79\x48\xb2\x52\xb1\xd9\x73\x51\x12\x57\x2a\xe2\x9c\xed\xb4\xcf\x0b\x65\x2b\x6a\x40\x2d\x55\xa0\xa8\xdd\x04\x4f\x14\xe8\x3e\xfc\xff\xd8\xfb\x1b\xee\x36\x6e\x6b\x5f\x18\xff\x2a\x58\x6a\xd7\x5f\x52\x4b\x52\x76\x72\xda\xd3\xe3\x9b\x7f\xb3\x54\x49\x4e\x74\x63\xcb\x3a\x96\x9c\x3c\x7d\xe2\x9c\x16\x9a\x01\x49\x54\x33\xc0\x64\x80\x91\xcc\xde\xdc\xef\xfe\x2c\xec\xbd\x81\x01\x86\x94\x63\x71\xc6\xa6\xe4\x70\xba\x56\x63\x91\x43\x0c\x06\x2f\x1b\xfb\xf5\xf7\x33\xa1\x92\x35\x4e\xd9\x20\x9f\x15\x2b\xe5\x6c\x6e\x29\xdb\xb3\x13\x39\x88\x42\x50\x25\xb8\x79\x37\xe9\xbd\x72\xc7\xee\x61\x21\xb9\xb9\xaf\xca\xb5\x54\x2e\x49\xad\x10\x73\xbf\xf6\xb9\x45\xde\x29\xe3\x1e\x84\x9e\xca\xd3\x73\x8a\xa0\xf9\x71\x93\xea\x5f\x98\x58\x13\xcc\x12\x4c\x94\xc1\x9f\xa0\xbb\x71\xca\x22\xb8\x20\x9f\x50\x02\xc2\x1f\x30\xaa\xc0\x22\x51\x5a\x8d\xe7\x11\x9c\x53\xa5\xf3\x7b\x96\x12\xae\x6b\x78\xac\x65\x72\xac\x1e\x41\x36\xd7\x45\xee\xc9\xb7\xd1\x97\x73\x25\xec\xad\x10\x8a\x9d\x9e\xc3\xf8\xb9\x57\xc4\x72\xae\xd5\xa3\x88\x61\x85\xc0\xfa\xbe\x6a\x3c\xef\xbb\xc0\x7a\x58\x25\x7d\x54\xfa\xf0\xa6\xbd\xf7\xfc\xb7\x61\xcc\x7c\x46\x36\xbf\xd2\x37\x02\x86\x34\xcf\x6b\x61\x7a\x00\x1f\x6d\xc0\x4e\xed\x25\x4a\xe5\x5a\xc4\x3f\x69\x60\x24\x0c\x9b\x77\x2d\x81\xfa\x0e\x5b\x15\x16\xde\x27\x96\x60\xa7\xe7\x47\x3d\xa4\xd7\xee\x1b\x8a\x8b\xb8\xa6\x76\x77\x0d\x93\x55\xd6\xc6\x5c\x27\xac\x0d\x37\x46\x85\x12\xa8\x31\xde\x2f\xd6\xb5\xae\x9a\x18\x09\xb5\x9e\x42\x9a\x29\x6c\xc6\x89\x15\x2a\xc5\x26\x77\x0e\x04\x1d\x2a\x9d\x03\x33\x53\x3b\x1a\xc6\xff\x22\x1e\x10\x9f\x2c\x81\x42\x9e\x52\x47\x46\x21\x09\xb9\x23\x98\xc0\xf5\xee\xd3\x0f\x23\x29\xbe\x34\x98\x9f\x6c\x2c\xcf\x4f\x8f\x87\x5c\x2e\x95\xcc\x1f\xdc\x72\x79\x63\xee\x5d\xd2\xff\xfe\x97\x04\x4c\xbf\x5f\x7b\x4b\x0c\x36\x11\x4c\x1f\xfd\x0d\x69\xea\xda\x32\xe2\x7d\x0c\x99\xb0\xab\x12\x3a\x40\x8a\xa4\x4f\x1a\xb9\xbf\xa7\x4d\x01\x8b\xb4\x4d\xee\x0d\x99\xc9\x3c\xe4\x85\x82\x36\xc0\x6f\xb8\x2c\x10\x31\x53\xdf\xdd\xa4\x0f\xbf\x17\x9a\xe7\x58\xee\x71\x2d\x6a\x25\x0a\x56\xea\xbc\x29\xd0\x9b\x17\xf8\x85\x5f\xbe\x3a\x7e\xf3\xe2\xc4\x27\x61\x89\x76\x3a\x47\x8c\x33\x25\x6e\xa1\x75\x05\x0a\x49\x46\xc0\x5d\xa1\xec\xc7\xed\x27\x8f\xc5\x89\x66\x28\x3a\x26\xfc\x0b\x95\xd2\xca\x19\x02\x6c\xb6\x6a\xe1\x55\x2d\xf8\xb5\x6e\x2c\xbb\x69\x0a\x25\xea\x96\x1f\x53\xdc\x08\x85\x3e\x58\xf7\x03\xf7\xd8\x18\xab\x51\xd6\x09\x44\x26\x01\xa7\x79\xd8\x4f\x9e\x91\x26\x4f\x25\x46\xf0\x65\x44\x0e\x9d\x50\x48\xbe\x1f\xba\xd4\x6b\x5e\x11\x6a\x29\x96\x13\x2f\x43\x96\x7a\x74\x49\x4c\xa3\xb9\xf0\x19\x30\x94\xf8\xf2\xe9\xb6\xc3\xfd\xdd\x2d\x69\x85\x68\x0a\xdf\x42\x0d\xfa\xb3\xef\x5c\xe7\x77\x58\x0d\xad\xde\x05\xf7\xc7\x94\xd9\x56\x33\xce\xd0\xdd\x3e\xf6\xf0\x37\x90\x29\xbb\x8e\x18\xbc\xf7\xa1\x09\x96\xc7\x79\x53\x14\x17\x22\xab\xc5\x7d\xc3\x0c\xa9\xa4\x38\xed\xb4\x75\x97\x05\x10\x99\xb3\x80\x09\x42\x37\xab\x16\x7f\x20\xca\x73\x6a\x6b\x71\xab\xa6\x80\xd4\x70\xae\x16\x7e\xc0\xa1\xf7\x26\x8a\xe9\x4a\xe3\xb3\xcc\x50\xfa\x24\xb3\x60\x44\x78\x58\x20\x5f\xe3\xc6\x60\xe6\x81\x54\xb9\xbc\x91\x79\xc3\x0b\x78\x10\x18\x65\x94\xb0\xc5\x09\xc7\x1c\xf7\x72\xe9\xd1\x8f\xef\x9b\xc3\xdc\xee\xc9\x03\xec\xf7\xef\xb0\x7b\x0b\xa9\x66\x63\xf8\xc4\x3d\x98\x7a\x38\xd6\x6a\xcc\xc7\x6e\xd9\x3c\x12\xbb\x05\xf0\xfb\x5f\x81\x61\xf0\xda\xcf\xaf\x17\x43\x86\x09\xa5\x9b\xd9\x1c\x06\xab\x2e\xb9\x87\xd2\x2c\x84\x05\x94\x44\xca\x67\xc0\x24\x36\xfa\x6d\x4e\x56\x46\x8c\x1a\x99\xae\x8d\x47\x62\xbb\xac\xeb\xe0\xed\x24\xe3\x47\x62\x86\xc6\xc8\xde\x7b\x05\xea\x1b\x51\xdf\x48\x71\x7b\x40\x9a\xdf\xd8\x9d\x09\x63\x1c\x11\x73\x00\x03\x7b\xf0\x3b\xb4\x8e\x2e\x5f\x1d\xbf\x02\xca\x71\xf2\xba\xfb\xa3\xca\x1d\x05\x66\xc2\x78\x25\xbf\x17\xb5\x01\x50\xe5\x6b\xa9\xf2\x11\x6b\x64\xfe\xf5\x27\x4c\xf8\x92\x4a\xb6\x59\xac\xbd\xa4\xd6\x0b\x92\x4a\x54\x45\x2f\xff\x8d\xcb\x33\x3a\x41\xaf\x44\xa1\xd5\x2c\xc2\x00\x80\xd3\xfc\x54\x49\xbb\xc4\xce\x8c\x48\xa7\xe0\xe1\xd1\x75\x0e\xb9\xc2\x52\xd7\x49\x38\xc3\xb5\x07\xf8\x8f\x51\xc6\xb1\x13\x69\x32\x69\x0f\xd2\xb8\x4c\xab\x23\x61\x22\x90\x2f\x17\xf6\xf0\xd8\x1e\x57\x12\xcf\xe2\x39\x57\x39\xfc\x99\x65\xba\xce\xa9\xbf\xd2\x86\xf4\x66\x4c\x86\xc3\x0c\x2c\x38\x86\x9c\x44\xe3\xaa\xfb\x64\x50\xd3\xea\x32\x49\x85\xf5\x5a\x7b\xa3\xe4\xcf\x8d\x60\xbc\xd4\x4e\x10\x77\x49\x20\x3a\x23\x52\xf2\x05\x9c\x85\xd0\xd5\x17\xbe\x5c\x83\x6a\x6c\xcd\x88\xbd\x16\x4e\xe9\x6a\x61\x02\x46\xec\x45\x8a\x1b\x30\x72\x7d\xb9\xc0\x82\x66\xfa\x08\x7b\x5f\x0b\xa3\x9b\x3a\x13\xaf\x31\xc6\x59\xfa\x7c\xba\xe5\x97\x71\xb3\x62\xf9\xb5\x50\xe8\x53\x72\x43\x03\x61\xdc\xa6\x86\x39\xc8\xe6\x22\x6f\xe0\x54\xb9\x5a\xb0\xa9\x44\x66\x18\x38\xda\xe5\x6c\x2e\x8c\xf5\xb6\xd1\x01\xe4\xa8\xb5\x24\x7b\xbe\x03\xb0\x7c\xa3\x64\xf6\xd6\x0b\x5b\x72\xc0\x2d\x87\x2d\xcb\xad\xaf\xd7\x42\x6d\xd0\x34\xa5\xdf\xcb\xdd\x91\x36\x13\xf6\xc2\x3d\x0a\xd7\x53\xc4\xb8\x21\x3b\x83\x0b\x31\x66\x72\x23\xb3\x29\x37\x73\xe0\xa3\xe9\x4e\x01\x91\x59\x64\x4d\xed\x04\x06\x62\xcc\xf3\x3c\x77\xd2\xb5\x66\x35\x52\xce\xaf\xf2\x3b\xf6\xac\xcf\x71\x9d\x1d\x47\xe7\xdd\x63\x39\xc4\x0e\x43\xbd\x85\x1b\xf8\xac\x23\x09\x70\x26\xdd\x81\xe5\x71\xdd\x9c\xc2\x1d\x02\xfe\x4e\x2a\x7c\xba\x23\x69\xfd\xf0\xfe\x5a\x61\xf9\x3e\x27\x20\xaf\x67\xfd\x1d\x77\xbb\x87\xf5\xac\xc1\x8d\x4e\x52\xb8\x45\xa4\x9f\x74\xf2\xee\x41\x99\x72\xb6\xea\xd1\xcb\xe3\xb8\xd0\x2f\xae\x60\xf2\x65\x92\x13\xf6\x7d\xdf\x30\x4b\x37\xce\xe2\x04\x7a\x1b\xbc\x69\xf9\x64\x9c\xd0\x28\x6e\xbc\x49\x10\x9e\xe6\x35\x5f\xa9\xaa\xc6\xd2\x49\x18\x01\x74\x65\x73\xae\x66\xe0\x26\xd1\x8d\x6b\xef\xf7\xbf\x87\x1e\xd5\x22\x6f\x32\x22\xe3\xf1\xab\xf6\xf7\x3e\xe8\x40\x70\x7a\x20\xae\x4c\xc6\x2b\xdf\xe7\xf8\xb5\xcc\x42\x59\xfe\xee\x19\x93\x13\x31\x61\x3b\xbf\x8f\xbe\xda\xc1\xa7\x57\xb5\x76\x8f\xa0\x02\x23\xe8\x55\x21\x2d\x24\xfa\xec\xc4\x77\x4f\xd8\x89\x7b\x06\x04\x62\xc3\x00\x46\x35\x30\x57\xed\xf0\x8d\x58\x2d\x66\xbc\xce\x0b\x72\x18\xde\x46\x85\x53\x61\xc0\xc4\x3b\x69\xac\x21\x6f\x41\x0f\xe1\x64\xb9\xb9\x76\xa2\xc8\x6d\xae\x71\xce\x2d\x1f\x47\xbb\xfa\x00\x4d\xad\x31\xa1\x84\x8f\x39\xad\xae\x56\x6a\x1d\xfc\x8e\xea\x8f\xc7\x3c\xdc\x25\x9d\x52\x0e\x78\xdd\xeb\xab\x3a\x8f\xcd\x4b\xdc\x03\x2c\x3e\xdd\xc0\x27\x2d\x83\x04\x8c\x01\xf0\x2f\xb5\x2a\x53\x90\xa3\x84\x87\x7e\xc7\x96\x3e\x39\xbb\x7c\xfd\xf7\xf3\x57\xa7\x67\x97\xdb\x9d\xbd\xdd\xd9\xdb\x9d\xdd\x63\x67\x0b\x75\xd3\x7b\x57\x7b\xeb\x69\x55\xde\x42\x17\xf2\x35\x2a\xc1\xfb\x8c\xb2\x43\x4f\xd4\xcd\xf7\xdc\x29\xd3\xe4\xd7\xa6\xa0\xeb\x8a\x34\x0e\xba\x01\x55\xf7\xa3\x47\x9f\x1e\xba\xc1\xe4\xce\x01\x93\xe6\x62\xc7\xca\xaa\x59\x8b\xd9\x43\x8f\xfe\x71\x7a\x7c\x72\x76\x79\xfa\xfc\xf4\xe4\xf5\x46\xb3\x9d\x7a\x82\xa1\xa6\xe7\xf2\x9a\xa7\x64\x55\x8b\x1b\xa9\x1b\x53\x2c\x02\x6a\xfb\x6a\x21\xb0\x9c\x30\xab\x72\xf0\x78\x78\x60\xfa\x95\x3f\xdb\x1e\xb6\xc3\x1e\xb6\x69\xf2\x57\x0f\x1c\xac\xa1\x96\xef\xf3\x5a\x97\x03\x2d\xe1\x0b\xf4\xc5\xf8\x60\xdb\xaa\xf5\xb4\x4b\x90\x39\xc9\xd1\x43\xca\x63\x8b\xcf\xe3\xf4\xd1\xb2\xb2\x3d\x68\x74\x06\x01\xd9\x1e\x06\x8f\x1a\x13\xce\x5e\xf2\xea\x3b\xb1\x78\x2d\x7a\xc2\x6d\xa5\xe3\x2d\x0a\x91\xb9\x83\x8e\x5d\x8b\x05\x66\x17\x1f\xf9\x87\xf5\x03\x8d\x7e\x80\x18\xe5\xd7\xa2\x0f\x7e\xfc\x90\xe0\xe2\xd7\xa2\x47\xe6\xb4\xbf\x96\x00\xb0\xdd\x14\x82\x9e\xe6\xe6\xf4\x41\x41\x7e\x7f\x04\x30\xf5\xcf\x37\x8e\x92\x5e\x03\xce\x82\x0f\xdf\x0e\x3c\x13\x18\x49\x5f\x24\x67\x57\x10\x22\x0c\x6b\x9a\x61\x6d\xfa\xd0\x03\x29\x19\x03\x0d\x4d\x5f\x1e\x4e\x86\x53\x38\xac\x5c\xdd\x6d\x05\x2b\xe6\x5c\x04\x40\xc7\xfc\x99\xc7\x00\x31\x81\x3c\x13\xe8\xa8\x47\xe9\x9f\x94\xd6\xf2\xcf\xf0\x61\xc1\xaf\x44\x61\x7e\xdc\xdd\xfd\xea\xbb\x93\xbf\xff\x75\x77\xf7\xa7\x7f\xc6\xdf\xc2\x51\x88\xe1\xed\xf4\x16\x00\x34\x51\x3a\x17\x67\xf0\x0c\xf8\x93\xd4\xb5\x43\x0c\xa1\xd0\x17\x80\x47\x30\xc1\xd4\xbb\xf0\x67\xa5\xf3\xee\x5f\xa6\x17\xf2\xe6\x83\x3c\x18\x60\x8a\x7a\x94\xc7\xe1\x35\xdc\xf1\xd0\xca\x92\x81\xb7\x2a\xb5\x1a\xf8\xa4\xb2\xb9\x28\x11\xfb\xef\xb9\x1f\x02\x20\xf8\xf6\xc0\x27\x0a\xd0\x22\x9c\x66\x9a\xc2\xb0\xee\xdc\x3c\xdd\x79\x50\x07\x4c\x98\xc1\x81\x07\x0c\x46\x84\x46\x0b\x37\x72\x38\x60\x43\x9a\x4b\x20\xa0\x3d\x3c\x3f\x65\x37\x38\xc2\x0f\x66\x70\x7c\x78\xf3\xf9\x47\x95\x71\x21\x88\xda\xad\x4a\x7f\x86\x69\x65\xfe\x7b\x42\x08\x31\x01\x2a\x52\x38\xc3\x66\x0f\x3f\x9c\x64\x55\x33\xa2\x1b\x26\xa5\x28\x75\xbd\x08\x7f\x86\xca\xe4\xb1\xb1\xba\xe6\x33\x28\x0c\xc3\x9f\xe3\xcf\xc2\x5f\xf8\xc3\xe4\x01\xcb\xbf\x46\x53\xb8\x8d\xa5\x92\x44\x5e\x13\xe9\xa6\xbd\x1e\xa0\x6c\xf3\x43\xff\x40\x44\x5b\xd6\x17\xaf\x2c\xbd\xd2\x05\x19\x3c\x71\xa8\x70\x86\x51\x04\x7b\x92\x2a\xe6\x47\x6d\x16\x1b\x78\x03\xd4\x8d\xb3\x2c\xd7\x46\x9a\x6c\xaf\x01\xa5\x59\x2e\x6f\xa4\xd1\x3d\xca\xdf\x42\x43\x77\x67\x3c\x12\x68\x0f\x66\x71\x05\xb7\xd9\xbb\x0a\xc0\xf5\xc2\x7e\xed\x88\xfd\xa7\x7d\x58\xfc\xf0\xaa\xb8\xb5\xa2\x56\xcf\xd8\xff\xec\xbd\xfd\xe3\x2f\xe3\xfd\xaf\xf7\xf6\x7e\x7c\x32\xfe\xaf\x9f\xfe\xb8\xf7\x76\x02\xff\xf8\xc3\xfe\xd7\xfb\xbf\xf8\x3f\xfe\xb8\xbf\xbf\xb7\xf7\xe3\x77\x2f\xbf\xb9\x3c\x3f\xf9\x49\xee\xff\xf2\xa3\x6a\xca\x6b\xfc\xeb\x97\xbd\x1f\xc5\xc9\x4f\x1f\xd8\xc8\xfe\xfe\xd7\xbf\xef\xdd\xf5\x01\xb0\xae\xf1\x1a\x12\xf1\x3a\x6d\x71\x90\xe5\xf7\x11\x69\x5e\xf0\xf2\xcb\x6b\xe8\xfd\xff\xda\x4b\xcd\x28\xab\xc7\x1f\xd7\x0f\x66\x83\x63\x5a\xe8\xa7\xf0\xe4\xe0\x93\xd2\x82\xb1\x60\x5a\x7c\x6e\xe7\xdc\x6f\xc1\xb9\x13\x68\x60\x61\x5e\x5b\x4d\x74\x5a\xeb\xd2\xc3\x52\x40\x78\x03\x0b\x28\xe9\xbe\x6b\xd1\x8b\x4c\x1c\xaf\xad\x33\x68\xeb\x0c\xba\xe3\xfa\x55\x67\x10\x16\x11\x3c\x5c\x4f\x90\x50\x37\xeb\x86\x30\x56\x46\xd0\xbd\xad\x13\x83\x3f\x7e\x58\x40\x6d\xe2\xb7\x7a\xcb\x9f\xdc\x26\xd3\xe0\x81\x56\xae\x8e\x61\xb2\xc3\xa2\x60\x52\xe1\xc6\x87\x06\x42\x2d\x96\x40\xd3\xc6\x17\x11\xdf\xb8\x2e\x84\xaa\xab\x04\x3c\x19\x72\x8b\xa5\x9a\x51\x61\x14\x1e\x25\x14\x7d\x92\xaa\x85\x9d\x0e\xca\x61\xcb\x55\xc0\x8d\xd1\x19\x90\x82\x61\xa5\x55\xc0\xa4\xa4\x6e\x43\x6f\x2c\xbf\x86\x68\x63\x26\x72\xa1\x32\x41\x3c\x06\x09\x57\x34\x57\xec\x44\xdd\x78\x2e\x87\xbc\xc1\x64\x10\x14\x7f\xab\xdb\xf8\xbc\x12\x10\xdc\x42\xa4\x20\x58\x94\x87\x00\x52\x3f\x58\xd8\x1c\x52\x31\xf4\xb4\xf5\xb2\xae\x47\x27\xdb\xfb\x14\xef\x7f\x66\x86\xc8\x56\x2f\x65\x68\xe9\xb0\x6c\xdd\xcf\xe9\x21\xf9\x39\x04\x03\xfb\x1f\x9f\xbf\xb9\xa3\x73\xa0\x63\x73\x98\x23\xf3\x1e\xb1\x93\x21\x8f\xc9\x21\x82\x25\x55\x2d\xa6\xf2\xdd\x40\xfb\xf4\x30\xaa\x27\x94\xb9\x50\x56\x4e\x25\x32\x66\x57\xb5\xa8\x84\x02\x57\x2b\x94\x68\x38\xd9\x4f\x27\x65\x1b\x9c\x7e\x88\xc9\x3c\xa8\x70\x0f\x2b\xca\x2e\x56\x29\xfb\x5b\x39\xc6\xb6\x72\x6c\xed\xeb\x13\xc9\x31\x5a\xb9\x0f\x47\x88\x41\xe6\x79\xff\xec\xf7\xa3\x34\x95\x9d\x58\xdc\xfb\x96\x10\x77\x0a\xf4\x83\x68\xb4\x1a\x93\xd7\xb0\x8e\xad\x66\x58\xb3\x8f\x7a\x13\x2b\xb9\xe2\x33\xa4\xa2\xb0\x3a\x80\x57\xe9\x3a\xd0\x89\x75\xf3\xee\x41\x8f\xf7\x25\x5e\xf0\x65\xad\x8b\x42\xd4\x86\x15\xf2\x5a\xb0\x63\x51\x15\x7a\x51\x52\xee\x6b\xce\x2e\x2c\xb7\x6e\x55\x5f\x08\xbb\x5e\xd8\xb7\x1f\xaa\x8d\xaf\x42\x1f\x08\xfb\x1f\xcb\xda\xa1\x28\x9c\x55\x54\x41\xf9\x4a\x81\xd0\x38\x04\x66\xa3\x11\x3b\x13\x37\xa2\x1e\xb1\xd3\xe9\x99\xb6\xe7\xa8\x7d\xa7\x09\x77\x78\x23\x93\x53\xf6\xcc\xd9\x75\xc6\x32\x8b\xec\x32\x51\x81\xba\xae\x93\x06\x5a\xdc\xc2\x21\xea\xf3\x96\x6b\xcf\xa1\xa5\x50\x79\xbe\x56\x24\xa3\xd7\x34\x05\xfa\xae\xde\x13\x74\x88\xf5\xa4\x2d\x94\x75\xb4\xbe\x11\x57\xc1\x23\xf1\x81\x15\x28\x15\xab\x85\xa9\xb4\x32\x22\x85\x19\x0d\x3d\x42\x6b\x77\x58\x0c\xe3\xb5\x0f\xcf\xbe\xc7\x66\xa5\x8d\x85\x12\xda\x61\x48\xe1\xce\x7d\x73\x50\x91\xcc\x8b\x42\xe4\x09\x2b\x20\xb2\x59\xf1\xd4\x43\x40\x68\x28\x81\xdf\x06\x0b\x95\x93\x1a\xe7\xe4\xfe\xc0\x30\xe9\x39\x9c\x3c\xbd\xf8\x5d\x95\xcd\xed\xc6\x84\x73\x24\x5a\x00\x4b\x80\xe7\x00\x83\x6f\x22\x22\xa8\xb9\xd6\xd7\x2c\xd3\x65\x55\xc0\xd6\xe9\xb1\xb3\x5a\x1e\xba\xb0\x94\xc6\xae\x75\x73\x10\x51\xd4\xc1\x07\xfd\x18\xea\x7a\x29\x62\x43\xa8\x61\xe2\x9d\xc8\x06\xe3\xb0\x3d\x79\x27\xb2\x88\x84\x19\x20\xd9\x32\x8f\x10\xe1\x76\x6c\x7f\x6e\xfd\xde\x21\x87\xa1\xdc\xfc\x3d\x6a\xe9\xe2\xab\x83\x62\x09\x6d\x7a\xb4\x7f\x7a\x04\x10\xa7\x80\x2d\x84\xf5\x75\x31\x8c\x46\x58\x8c\xb8\xf5\x96\xa0\x2f\x43\x22\xb5\x6f\x0b\x28\xd2\xb4\xb6\x6c\x6f\xf7\x60\x77\x7f\xc9\xff\xd8\x81\x8c\xbf\x8c\x7e\x29\x01\xea\xb4\x02\xdc\x50\x91\xed\xe6\x23\x26\xad\xcf\xb4\x46\xb8\x27\xe8\x15\x15\xfd\x8d\x98\xd1\xcc\xd6\x3c\x97\xa4\xc6\xc0\xa7\xee\x26\x5b\x37\x24\xe5\xf7\x76\x7f\xd9\x25\x6a\xaf\x5b\xad\x76\x2d\x74\x7f\xc2\x2e\x11\x27\x26\x34\xb4\xd0\x0d\xe0\x42\xe1\x10\x54\x85\xcc\xa4\x2d\x16\x20\xb1\x98\x6e\x10\x93\xca\x9d\x17\x54\x6c\x78\xf2\x4e\x5a\x4f\xae\xa3\xa7\xec\x09\xb2\xeb\x21\x86\x13\x37\xc0\xb0\x7e\x30\x17\xbc\xb0\x73\x4c\x12\x51\x5a\x8d\x91\x20\xd5\x89\x12\xfa\xa6\x6f\xbc\xa4\x9f\x3b\x31\xbe\x7a\xb8\x16\x97\x3b\xd4\xd3\x72\x70\x42\xf4\x9b\xf5\x59\xdb\xd9\x12\x7a\xdd\xe5\xe5\xf9\x37\x09\x6f\x3b\x48\x71\x6b\x2b\x9f\xba\x03\xde\x00\x51\x4f\x75\x5d\x3e\x00\xd9\x31\x4c\xb0\xb2\x17\x81\x3b\x1b\x50\x84\xf5\x25\x72\x67\xab\xd1\x08\x3f\x9c\xc1\x9d\xfd\x5d\x37\x00\x06\xc2\xaf\x8a\x45\x40\x62\x30\xc2\xb2\x1d\xd7\xd4\x8e\x13\x4f\x6e\x35\x7c\x2b\x78\x8e\x40\x19\xc6\x0a\xbe\x96\xea\x16\x5f\x83\x05\xd1\xa2\xbe\x0d\x7b\x0e\x34\xc6\xea\x92\xcd\xe9\xb5\xd3\xd2\x4b\xda\x19\x13\xd8\x3d\xbe\xae\xa9\x16\x15\x4a\x38\xfa\xcd\x67\x27\xbf\x96\xe4\x06\x8e\x7b\x42\xe2\x91\xc5\xc3\x16\x73\x44\x49\x85\x83\x85\xb8\x33\x03\xc9\xd2\x01\x92\x1f\xd8\x80\x09\x10\xac\x5f\x21\x67\xb7\x21\x08\xea\xf5\xcf\xf5\x1a\x2c\xa7\x82\x0d\x96\x37\xc0\x56\x39\x59\x69\xcd\xa0\xf7\x05\xfd\x39\xe0\x8e\xf1\x31\xd4\x8c\x2b\xad\x64\xc6\x0b\xf9\x6f\x91\x23\x43\x3e\xe6\xcf\x81\x9e\x93\x71\x23\xc6\x10\xd4\x55\x44\xec\x19\x55\x2b\xba\xed\x68\xb5\x06\xe5\x23\x20\x9f\xe1\xf3\xfa\x67\x65\xb0\x61\x73\x02\x58\xff\x82\xd4\xf8\x7a\xff\x30\x0f\xb3\xc4\xd8\x90\x23\x50\x0d\x90\x40\xbe\x9c\x3e\x8e\x60\x55\x50\xe0\x89\x22\x1c\x84\x11\xc2\x6b\x3e\x98\xb3\xcc\xe9\x24\x83\xbe\x3a\xba\xe3\x6b\xa6\x02\xf7\xbc\xc7\x12\x5e\x1e\x90\x28\xff\x81\xa8\xea\xbd\xd3\xd8\x1f\x7a\x5c\xcd\x04\x7b\xea\x7e\xf9\xe7\x3f\xfd\xe9\xcb\x3f\x4d\xb0\xf9\x90\x0b\xa1\xd8\xe9\xe1\xd9\xe1\x3f\x2e\xbe\x3f\x82\x12\xdc\xbe\xa3\x3a\x50\xa2\xe7\xd0\x69\x9e\x83\x26\x79\x7e\xd4\x14\x4f\x28\x2c\xe9\x2d\x45\xd2\x08\x03\x34\x19\xa3\x88\x92\x86\x19\xa1\xf9\x21\xd2\x6d\xec\xae\x75\x5b\xed\x41\xec\x31\x9b\x55\x17\x3a\xbb\x1e\xd0\x7a\x3a\x16\x55\x2d\x32\xf4\xc6\x5d\x1e\x9d\x63\xeb\xce\x8a\x3d\x7b\x75\xd9\x16\x34\x40\xd6\x4f\x0b\xd9\xf7\x2d\xf9\xeb\x9c\xe5\x7b\x2d\x2a\x1b\x1c\x04\x57\x3c\xbb\xbe\xe5\x75\x0e\xfe\x33\x6e\x25\x00\x14\x23\xc2\x60\x2d\x88\x2c\x0e\xd3\x0a\x11\x4a\xcd\x93\x71\xa3\x2c\x47\x37\x85\x77\xba\x82\x63\x0c\x8f\xc0\x29\x97\x05\xf8\x69\x89\x07\x1b\xf3\x8e\xb2\x2a\x38\x0e\x63\xcf\xf9\xd6\xc4\xf3\xd7\x83\x35\xf1\x22\x9e\xee\xfb\x5a\x7b\x7d\xb3\x1f\x1f\xf0\x51\x47\x47\x5c\x9d\x50\xe6\x6f\x8f\xba\x01\xda\x7b\xb8\x47\x5d\x55\x8b\x0b\xab\xd7\xe2\xdd\x60\xcb\xb1\x18\x6c\xec\x8e\x48\xcc\x95\x98\x6a\x27\x84\xef\x0c\xad\xe4\x0d\x6c\x42\xae\xa0\x04\xd1\xfb\xce\x74\x12\x3e\xc1\xbc\xcf\x80\x92\x4f\xf0\xac\x07\x26\xc6\x64\xf5\x8c\xe3\x23\xf7\x76\xa2\x84\xde\x8d\xda\x5a\x0a\xe2\x3b\x87\x0f\x85\xcd\xd0\x3f\x1c\x09\x72\xc0\x27\xa5\xee\x77\x83\x35\x59\xcd\xcd\x1c\xb9\xc0\xc5\x3b\x69\x09\xfd\xf5\x5c\xe7\x5d\x06\xff\x59\xcd\x33\xc1\x2a\x51\x4b\xed\x0e\xa3\x46\xd9\x5c\xdf\x2a\x76\x25\x66\x52\x19\x3f\x14\x00\xd1\x4e\x63\x06\x51\x1f\x69\x02\xfc\xdc\x84\xbd\x4e\x20\x55\xa8\xd8\x29\xd3\xed\xd6\xa4\x3e\x77\xe3\x55\x70\x62\xc1\x38\x21\xac\x7e\x18\xe1\x98\x33\xec\xd7\xba\xbc\xd7\x28\x78\x72\x2e\x0a\xbe\xc0\x9c\xd6\xa9\x54\x60\x39\xd6\x66\x7f\x80\xb8\x16\xb2\xde\xf9\xef\xee\xec\x87\x34\xac\x16\x3c\x9b\xf7\x0b\x31\x6f\x03\x61\x1f\x78\x6d\x03\x61\x7d\x1a\xd9\x06\xc2\xb6\x81\xb0\x5f\xb9\xb6\x81\xb0\x6d\x20\xac\x73\x3d\x58\x2b\x69\x1b\x08\x5b\xfb\xda\x06\xc2\xde\x7f\x6d\x03\x61\x1f\x70\x6d\x03\x61\x1f\x78\x6d\x03\x61\x77\x5f\xdb\x40\x58\xbf\xce\x6c\x03\x61\xdb\x40\x18\x5d\xbf\x3d\xef\xa0\xbf\xb6\x81\xb0\xa5\x46\xb6\x81\xb0\x6d\x20\xec\x83\xaf\x07\x6b\xe2\x6d\x03\x61\x78\x6d\x03\x61\xe9\xf5\xdb\x3a\xea\x7c\x18\xe9\xdc\x19\x94\xfd\xeb\xf3\xce\x21\x74\x21\x33\x8a\x46\xe9\x69\x52\xd3\x85\x8f\x9a\xb4\x7c\x1b\x11\xc4\x89\x2f\x2b\xa2\xb8\x53\x1b\xcd\x5a\x59\xfb\xd5\x93\x13\xaf\xd2\x79\x1b\x0e\x89\xe2\x20\x68\x56\xaf\x5f\x7f\xb7\xb1\xca\xb2\x3e\xc1\x8f\x4f\x13\xf8\x78\x20\x51\xa2\x01\x82\x1d\xdb\x40\xc7\x67\x17\xe8\x18\xc6\x49\x38\x80\x83\xb0\xf7\x51\x41\xf1\xff\xcb\x79\x2d\xcc\x5c\x17\x6b\x2f\xf4\x64\x91\xbf\x94\x4a\x96\x4d\x09\xac\xb7\x6e\x3d\xcb\x9b\x90\x68\x60\x5a\x5a\x7d\x90\xd8\xe8\xab\x8c\xe8\x71\x3d\x2d\x2e\xd4\xa2\x12\xcd\xbd\x69\xb2\x4c\x08\xa0\x85\x8b\x2d\x9c\x2f\x27\xe1\x49\x81\x06\xe4\x69\x3f\x79\xd3\xef\x10\x47\x68\x55\x68\xe5\xcb\x2f\xd6\x6a\x63\x56\x57\xc3\xc8\xe5\x6f\x5e\x9f\x1f\x45\x72\x99\x2b\x2f\x96\xa5\xba\xd1\x05\x8c\x2a\xc7\x9b\x9c\xb2\xb6\x41\x21\xdd\xdf\xec\xe8\x65\x72\x0c\x71\x46\xf4\xd5\xaa\x53\xbf\x99\xd3\x9d\x53\xcf\xd1\x0c\xe6\x12\x11\xfc\x3f\x58\x77\xee\x2d\xdd\xfa\xeb\xb3\xfd\xb7\x03\x03\x88\x1d\x78\xf1\xc1\x06\x78\xe7\x82\xa8\xab\xe8\x08\x8e\x0d\x17\xcf\x6a\x65\x35\xab\x0a\xde\xf2\x52\xc1\x0c\x7c\x0b\xe7\xc6\xd1\x5c\x64\xd7\xaf\x29\x46\xbb\x67\x84\x08\xfa\xe4\x4c\xda\x79\x73\x35\xc9\x74\x79\xe0\xb6\x31\xfe\xdf\x55\xa1\xaf\x0e\x4a\x6e\xac\xa8\x9d\x8a\x49\xc7\xd2\x38\x73\xad\x48\x35\x9b\x94\xf9\xfe\x84\xbd\x55\x58\x5d\xdf\xf2\x60\x46\xd8\x12\xee\xf9\x1e\xe7\xe3\x4a\x38\x89\xa8\xc1\x77\x10\x41\xe8\xb9\xee\x4d\xfa\x00\x35\xf7\x3e\x46\x7a\xc6\xc7\x3f\x7d\x6c\x7c\x2b\xb9\xd8\x00\x4e\x92\xc7\x16\x03\x1f\x2c\x17\x64\x80\xd8\xf7\x03\x8a\x7b\x3f\x18\x75\xf6\xa1\xc4\xba\x1f\x20\xda\xf5\x00\xf1\xed\x21\x62\xdb\xc3\xc5\xb5\x3f\x02\x28\xf4\x63\x8e\x67\x0f\xe8\xf4\x1b\x28\x8e\xfd\x29\x62\xd8\x83\xbc\x75\xdf\xd8\xf5\xa7\x8b\x5b\x0f\xf3\xba\x43\x9a\x1b\x8f\x35\x56\x3d\x80\xf3\x7e\x48\xc7\xfd\x60\x4e\xfb\x8f\x16\x9b\xee\x1f\x97\x7e\x00\x31\xe9\xde\x83\x2c\x95\xb4\x92\x17\xc7\xa2\xe0\x8b\x0b\x91\x69\x95\xaf\x7d\x8e\x75\xb0\x48\xc3\xfe\x31\xd8\x2c\x79\xb0\xd2\x42\x8f\x39\x27\xc8\x75\x67\xb7\x61\x61\x8b\x8f\x72\x90\xda\x02\xf1\x66\xec\xe5\x83\x8c\x5b\xb0\x07\xe3\x2a\xc3\xaa\x97\x21\x27\xf1\x5b\x7d\xcb\xf4\xd4\x0a\xc5\xf6\xa4\xf2\xf3\xb8\x1f\x19\x9b\xad\xdf\x32\x2c\x6b\xf7\xed\xd3\x27\xfe\xe6\xcf\xcf\x21\x09\xae\x57\x63\x3e\xbe\x7f\x98\x1e\xf4\xeb\x0e\x62\xba\x71\xda\x14\xa9\x93\x18\x1d\xc7\xa9\xbc\x79\xda\x82\x46\x3f\x85\x76\xc3\x6e\xe3\x2a\x67\x54\x09\xf7\xf9\x4d\x5a\xef\x8c\x9b\x54\xf5\x0b\x19\x36\xbf\xe6\x4f\xbe\x3c\x3a\xdf\xba\x93\x1f\x96\x53\x66\x43\x59\x2b\x0f\x50\xd1\x7d\xa4\x99\x2a\x5b\x45\xf7\x1e\x57\x54\x1b\xfb\x4d\xcd\x33\x71\x3e\xb8\x8e\xe0\xb7\x13\xcb\x9b\x9a\x93\x00\x0c\x2a\x9f\xdf\x3c\x4a\x88\x1c\x77\x53\xa8\x27\x86\x4a\xdd\x69\x53\x14\x0b\xf4\x39\x24\xd5\xd7\x18\x85\xef\x16\xf3\x82\xe3\x7f\xc5\x53\x5a\xc5\xb2\xaa\x35\x9d\x99\x75\xa3\x94\x93\xc1\x2d\xf3\x1b\x28\x92\x00\x46\xcd\x93\x92\x61\x23\x67\xae\xfb\xee\xfc\x83\x6a\xe2\x36\x35\x31\x69\xd0\xfd\x7a\xaa\xeb\x4c\x5e\x15\x0b\x36\xe7\x45\xa0\xf9\xe1\xec\x5a\x16\x05\x35\x33\x61\x17\xc2\x62\xe0\x02\xcf\xce\x42\xab\x19\x74\x8e\x2b\x4f\x2f\x29\x32\xf7\xdb\xac\x10\x5c\x35\x15\x3e\xcf\x9d\xc4\x0b\xdd\xd4\xfe\x79\x93\x10\xfe\x08\x27\xb0\x92\xc5\x28\x22\xb1\x7b\xef\xc4\xb6\x2e\x1a\xe3\x14\x80\x57\x1e\x7c\x7b\x14\xb7\xe9\xf1\xd1\x4d\x44\x61\x54\xd5\xfa\x46\xe6\x18\x43\xf1\xc3\x06\x74\xd9\x48\x53\x14\xf6\xb3\xd2\x6a\xac\xc4\x8c\x83\xa2\x42\xbb\x08\xe7\x0c\xdb\xc1\xdc\x02\x95\x03\x71\x91\xd3\xf0\x75\x95\x94\xf3\xdf\x48\xa4\x5c\x8e\x46\x8e\xed\x29\xcd\x34\x64\xaa\x36\x4a\x5a\xa4\xf1\x9f\x37\x96\xe5\xfa\x56\xed\x93\xcf\x4a\x1a\xc6\xd9\x95\xb0\x3c\xca\x35\xa5\x03\xce\x30\xa1\xf8\x55\xe1\xe6\x1c\x52\xb1\x2e\x57\x0e\x10\x9b\x0a\x6e\x9b\x5a\xb0\x19\xb7\x62\xa5\x9e\x83\xef\xfb\xfe\xe1\x95\x86\x1c\xac\x53\xd6\x28\x23\x7a\x1e\xef\x83\x29\x47\x7f\xfe\x8f\xf5\x64\x84\x2c\x85\x6e\xec\x27\xb1\xfe\x6e\xe7\x32\x9b\xc7\xca\xac\x2c\x85\x61\xba\xe9\x98\xc5\x4f\xe9\x67\xab\x67\x68\x6b\x02\xae\xba\xd6\x75\x1f\xaf\xf0\x7e\x75\xe1\x18\x5a\x7e\x6f\xc8\x20\x3f\x3e\xbb\xf8\xc7\x8b\xc3\xbf\x9d\xbc\x98\xb0\x13\x9e\xcd\x63\x4c\x0e\xc5\x38\x08\x0d\x10\x14\x73\x7e\x23\x18\x67\x8d\x92\x3f\x37\x14\x56\xde\x0b\xbf\xdd\x1f\x14\x91\x7e\xcd\xd3\xd7\x49\x9b\xb5\x56\xfc\x4a\xd2\x3b\x68\x8d\x32\xb6\xb4\x11\x40\x53\xb3\xa4\x3e\x85\x58\xf6\x02\x4d\x04\x50\xb8\x20\xb1\xfe\xf8\xd5\xc9\x05\x24\xec\x57\x35\x22\x95\x40\x86\x17\x7c\x0f\x2d\x5d\x09\xf7\x0b\xe2\x27\x9e\xb0\x43\xb5\xc0\x2f\x71\x4f\x49\xc3\x0a\x69\xac\x80\x53\x8f\xd4\x36\x1f\x25\xdf\x79\x32\x81\xff\xed\x30\x9e\xe7\xb5\xd3\xeb\x42\xe2\x5a\xb6\x94\x49\x8a\x9a\x9f\xbc\x2a\xa2\x17\x50\xc2\x62\x9e\xda\x4b\x9d\x53\xcf\xe1\x24\x81\x08\x19\x1e\x83\xc6\xd6\xdc\x8a\x99\xcc\x58\x29\xea\x99\x60\x15\xb7\xd9\x9c\x95\x7c\xc1\x32\x5d\xd7\x4d\x85\x6c\x06\x39\xb7\x7c\xc2\x9e\xeb\x9a\x95\x7e\x13\xbb\x35\xef\xce\xe1\x8b\xd5\x99\x03\xed\xce\x8e\xff\x29\x8d\x69\x84\x39\x78\xfa\xe4\x2f\x5f\xfc\xe9\x4f\x9f\x15\x01\x5e\x48\xed\x85\xbc\x97\x88\x00\x8f\xfb\x59\xc0\x59\x47\x42\x44\xa9\x66\x45\xbc\xbe\xd6\x3b\x00\xfa\x5a\x99\x7d\x6d\xcc\x71\xfb\x06\xe7\xeb\x9a\x9a\x83\x10\xf1\xb5\x7d\x18\x88\xbe\xaa\x3d\x07\xbd\x61\x45\xb2\x41\xc7\x8c\xc4\xa7\xe7\x7e\x63\x92\x9e\x53\x76\x68\x6c\xab\x36\x07\x6a\xc4\x9e\xb0\xaf\xd8\x3b\xf6\x15\x18\x5a\x7f\xee\x4b\xf6\xd5\xd7\x04\x1a\x22\xa5\xc9\xd9\xf7\xa7\xe7\x03\x8d\xf8\x0f\x4e\x68\xba\x16\xdd\xa8\x5a\xcd\xae\x24\x29\xf6\xe2\x9d\x15\xb5\x53\x34\x69\x26\x36\x4a\x93\xe6\x3a\xf8\x09\x97\x19\x06\x1e\x4e\xa7\x69\x1a\xd5\xfd\x16\x9a\xfb\xf9\xb7\xda\xd8\x33\x92\x42\x29\xe1\x4f\xdb\x5a\x09\x82\x3f\x11\x63\xee\xdc\x30\xb6\xdd\x60\x86\xe5\x1a\xb2\xba\x30\xc5\x79\x2e\x7b\x24\x6b\x3c\x9c\x65\xdc\x2f\x7e\x9f\xcc\xe7\xfb\x66\xaa\xe3\x4a\x01\x1b\x88\x54\xac\x08\xa3\xab\xd2\x39\x69\x67\xae\x5b\x79\x74\x66\xbc\x47\x3d\x23\xaf\x4d\xf0\x37\xc3\x5a\x72\xfb\x29\xe3\x0a\x8b\x4c\xa6\xa2\xae\x31\x2b\xfd\x6a\xe1\x93\x03\x7b\x4f\x5e\xaf\x9d\x54\xd5\xda\xea\x4c\xf7\x60\x72\x4b\xa3\xdd\xd4\x1c\x0c\x42\x85\x6b\x97\x46\xfe\xcd\xf1\xf9\x88\x5d\x1e\x9d\x03\xbb\xd5\xc5\xd1\xe5\x79\x6a\xb3\xec\x5c\x1e\x9d\xef\x6c\x74\x28\x98\x57\xf8\xc0\x45\xbd\x46\x23\x89\x0b\xca\x69\x93\xe3\x92\x57\xe3\x6b\xb1\x58\xf3\x4c\x1d\xe2\x5c\x1f\x87\x19\x1e\xe4\x85\x70\x98\x4b\x5e\xdd\xbb\xb5\x5a\xf0\x5c\x7e\xa2\x4a\x2f\x9f\x76\x1b\x9e\xb9\xba\xe4\xab\xd4\x37\x22\x47\x2d\xdd\xff\x42\xa8\xbc\xd2\xd2\xe9\x8b\xdb\x3a\xb0\xfb\xff\x7a\x5b\x07\xf6\xc1\xd7\xb6\x0e\x6c\x5b\x07\xb6\x7c\x3d\x98\xc4\xd9\x6d\x1d\xd8\xe7\x15\xc1\xdf\xd6\x81\xdd\xff\xda\x78\xe0\x7e\x5b\x07\xb6\xfa\xda\xd6\x81\x6d\xeb\xc0\x3e\xec\xda\xd6\x81\xdd\xff\x7a\x70\x29\x47\xdb\x3a\xb0\x7b\x5d\xdb\x3a\xb0\xe5\x6b\x5b\x07\x76\xc7\xb5\xad\x03\xbb\xe3\xda\xd6\x81\x2d\x5f\xdb\x3a\xb0\xfb\x5d\xdb\x3a\xb0\x6d\x1d\xd8\x67\x9d\x1e\xcb\xb6\x75\x60\x74\x6d\xeb\xc0\x3e\x8b\x24\x40\xb6\xad\x03\xfb\xa0\x6b\x5b\x07\xb6\xad\x03\x5b\xe7\xda\xd6\x81\x7d\x2e\x4e\x99\x6d\x1d\xd8\xb6\x0e\xec\xb7\xa3\xe8\x6e\xeb\xc0\xb6\x75\x60\xdb\x3a\xb0\x6d\x1d\xd8\x7b\x7b\xb1\xad\x03\xfb\x1c\x4c\xc0\x5a\x18\xf9\x6f\x71\xae\x0b\x99\x2d\x7a\x67\x29\xbe\x26\xe2\x63\x43\xcd\xb2\x0a\xda\x8d\x52\xab\x7a\x54\x9e\x3c\xb0\x82\x9b\xd7\xd1\xc0\xc5\x85\x37\x81\xfc\xf9\x23\x0c\xc1\x83\x28\xbe\xf1\x2f\x78\xb6\x7e\x24\x65\xec\x09\x08\x70\xf8\xd6\xf3\x5b\xf4\x36\x11\xe2\x17\x19\x28\x1f\x7c\x37\xae\x88\x0c\x2b\xc1\xea\x20\xc1\xe4\x9d\x0b\x84\x57\x55\x21\x85\x99\xb0\x8b\x40\xc0\x03\xd2\xcb\x3c\x63\x59\xd5\x8c\x58\x29\x4a\x5d\x2f\x7a\x58\x13\x03\x28\x9c\xc9\xac\x0d\x34\x64\xaf\xb1\x4d\x3f\x0c\xce\x88\xa8\xaa\x62\x81\xca\x54\x5b\x4a\x1a\x46\x4d\x7a\xe1\x92\x83\xba\xd3\xc9\xf2\x90\x36\x31\xc3\xce\xb4\x7d\x4d\x0b\x7e\x63\xb9\xf6\x77\x65\x95\x73\xab\x4b\x99\xad\x23\xb0\x51\xc6\xf6\xcf\x29\x3f\xd2\x65\xd5\x58\x91\x88\x6d\x1c\x2c\xd4\xe4\xa4\x89\x4d\xb8\xfe\xd9\xe0\x99\x56\x53\x39\x23\x55\xfc\x00\x19\xdd\xc7\xe1\x7d\xc6\x11\x8b\xfa\x23\x4c\x05\xcf\x0a\x2e\xd7\x8f\xdb\xa7\xa9\x55\x47\xd0\x16\x54\xe8\xb6\xc9\x55\x90\xa3\x1b\x46\x6b\x14\x12\x97\x24\x6e\x93\x89\xff\x0a\x7f\x3c\xc2\x4c\x5f\x67\x7f\x80\xd2\xb9\x62\x42\xdf\xaa\x56\x3d\x56\x8c\x17\xd5\xfc\xfd\x0a\xb2\xeb\xc8\xf1\x42\xf1\x52\x66\x7e\xc5\x1c\x16\x85\xce\xd0\x20\x4a\x55\x64\xdf\x36\xb6\xe7\x1e\x52\x96\x8d\xe5\x57\x85\x98\xb0\x53\xac\x10\xd2\xaa\x58\xb8\xd5\x64\x84\xf5\x81\x0f\x9a\xfe\xb5\x73\xb0\xfa\x27\x60\xf4\x4c\xbe\x58\xa9\x0d\xc1\x84\x60\x35\x94\x50\x6e\x97\x69\x25\x98\x50\xb6\x5e\xb8\xb9\x3b\xd7\xf9\x85\x9b\xbe\xe4\xee\xde\x45\x52\x3d\x73\x2e\x86\xc8\xb7\xe8\x99\x6b\x31\x4c\x86\x44\xff\xec\x88\xe5\x30\x6f\x54\xb7\x18\x27\x3e\x26\xb3\x5a\xe9\x7c\xb2\x62\x57\x7a\xd5\xe0\x5c\xe7\xee\x80\xab\x45\x4c\x85\x47\xf6\x21\x6c\x90\x92\x5f\x83\x89\xcd\x6d\x7b\xf2\xf1\x1b\x2e\x0b\xb7\x85\x56\xd4\xe3\xf7\x4b\x9c\x18\x40\x35\x18\xba\x18\x8c\xf5\x5d\x41\x43\x16\x73\x31\x60\xee\x2a\xe5\x7a\xe8\x0f\x6c\xe9\xe0\x7d\x01\x6d\x45\xe9\x58\x6e\x4d\x94\xfc\x1d\xd8\xac\xbc\xd4\x8d\xb2\x58\xe1\x85\xe7\x73\x10\xfa\x98\xb4\xf6\xe0\x4e\x5e\x36\x8c\xd8\xe1\xb9\x2f\x81\x39\x1f\x22\x9b\x9c\x5b\x2b\x6a\xf5\x8c\xfd\xcf\xde\xdb\x3f\xfe\x32\xde\xff\x7a\x6f\xef\xc7\x27\xe3\xff\xfa\xe9\x8f\x7b\x6f\x27\xf0\x8f\x3f\xec\x7f\xbd\xff\x8b\xff\xe3\x8f\xfb\xfb\x7b\x7b\x3f\x7e\xf7\xf2\x9b\xcb\xf3\x93\x9f\xe4\xfe\x2f\x3f\xaa\xa6\xbc\xc6\xbf\x7e\xd9\xfb\x51\x9c\xfc\xf4\x81\x8d\xec\xef\x7f\xfd\xfb\xb5\xbb\xdc\xdb\x47\x3d\x9c\x87\x7a\x20\xff\xf4\x47\xf1\x4e\x53\x1e\xe7\x40\x7b\x91\x72\xd0\x97\x76\x23\x79\x90\xde\xb7\x1b\xfd\x29\x09\x86\x48\x68\x47\x1a\xa6\x4b\x69\x9d\x01\xe7\xd4\x1a\x1e\x57\x9e\x75\xcc\x13\x92\x03\x50\x7b\xc9\xa1\x44\x2c\xaa\xda\x8a\xac\x1a\xed\x5d\xb1\x60\x1e\x29\x26\xcb\xaa\x10\xa5\x50\x16\xf6\xf3\xd8\x6b\x82\x60\x2f\x4e\xda\x9e\x64\xa8\xb1\x8b\x77\x99\x10\x39\x3d\x6c\x2b\x3a\x7e\xfd\xda\x8a\x8e\xcf\x51\x74\x18\x91\x35\xb5\xb4\x8b\x23\xad\xac\x78\xb7\x56\x44\x34\x95\x1c\x17\x69\x83\x64\x90\x51\x4e\x2b\x7d\xc7\x74\x85\x15\x9c\x1d\x88\xac\xb9\x6e\x8a\x1c\xca\xb2\x1b\x05\x01\x21\xc4\xdb\x10\x16\xa3\x35\xa0\x10\x82\xb6\xd8\x7d\x88\x8f\xbf\x60\x58\xe8\xe7\x46\xde\xf0\x42\x28\x1b\xfd\xe2\x1c\x22\x0e\xf1\x8f\x3e\x74\xcf\x5b\x6e\xae\xdb\x0d\x2f\xc6\x95\xce\xdb\xfd\x7d\xe0\x5f\x09\x3e\x12\xef\xec\x63\x34\xd2\x41\x7f\x3a\xaf\xe5\x8d\x2c\xc4\x4c\x9c\x98\x8c\x17\x20\xd7\x86\x39\x4a\x0e\xef\x68\x1d\x26\xbe\xd6\x85\x71\x3a\xbf\x13\xe5\x8c\xfb\x90\x1d\x58\xc2\x33\x2e\x15\x22\x5c\x55\xfe\xc7\x06\x63\x7f\xee\x74\xa8\x78\xed\x26\x38\xc4\xf8\xc0\xae\xbe\xd2\xba\xa0\xda\xe5\x62\xd1\xb6\x4f\x55\xfc\x4a\xff\x43\x89\xdb\x7f\xb8\xd6\x0c\x9b\x16\x7c\x16\x42\x7b\xce\xd8\xee\x46\xe7\xdb\xa6\xef\x7c\x01\x28\x0c\x6e\x04\xe3\xc5\x2d\x5f\x98\x36\xd0\x19\x61\xb9\x99\x67\xec\xe9\x3e\x2c\x67\x6e\x58\x68\x23\x67\x5f\xec\x43\xba\xde\xd1\xe1\xf9\x3f\x2e\xfe\x7e\xf1\x8f\xc3\xe3\x97\xa7\x67\xec\x4c\x5b\x81\x67\x5e\x64\xff\x64\xc1\xc1\xe4\x7a\x19\xfc\x7f\x13\x6d\x26\x60\x63\x41\xf6\xb9\xca\xf5\xad\x59\xdb\x0b\x8a\xcb\xcf\x0d\x9e\xe0\x6a\x3d\x37\x0f\xaf\x38\x30\x9c\xf7\x38\x61\x96\x32\xc2\xe3\x46\xe1\x88\xcf\xf3\x83\xbc\xd6\x15\x0e\x82\x0f\x4a\x47\x0e\x92\x24\xec\x15\x57\xb6\xc1\xfc\x4e\xd3\x06\x67\x35\x57\xb6\x8d\xce\xb6\x73\x46\xd4\xea\x93\xde\xd3\xb1\xb9\x83\x7f\x08\x2f\x01\xcf\x87\xc3\x25\x38\xcc\x73\x91\x27\xc3\xff\xd9\xd5\x13\x1d\xf9\x97\x8b\xc2\x5e\xec\xfc\xd5\xc5\xe9\xff\xd3\x59\xc7\x8b\xaa\x5f\x61\xc3\x30\x18\x37\xb5\xae\x06\x9b\xdd\xd7\x84\xa1\xb2\x9d\xdf\x07\x31\xbf\xe1\xb4\x1c\x26\x9d\xf6\x75\xa3\x52\x70\xd2\xb6\x7d\x56\xea\x5c\x4c\xd8\x79\xc8\xeb\x49\xbf\x8d\xa0\xca\x78\x2d\x98\xbb\x45\x59\xc9\x8b\x62\x11\xab\x68\x56\x23\x9e\x48\x82\xb2\x16\x0b\xf2\x29\x2f\xcc\xa6\xa5\x71\x9f\xb3\xd1\xe9\x11\x2f\x9d\xb9\x3c\xc8\x74\x84\xd6\x58\x2e\x94\xb6\xa4\x58\xbb\x5e\x02\x72\x5d\xad\x33\x86\xb6\x79\x54\x3c\x91\x9c\x6f\x06\x73\x8b\xfc\xd1\x28\x8d\x1f\xec\xf3\xd0\x32\x86\x65\x1b\x23\xba\x0a\x3a\x1d\x8d\xad\xb5\xee\x5a\xaf\x05\xcf\x21\x6a\x51\x71\x3b\xc7\xdc\xe7\x92\x9b\x6b\x91\xe3\x07\xa4\x9a\x85\xc0\x09\x38\x7a\xfd\xa3\x2e\x5d\xbf\x7d\x8c\x04\x54\x32\xcc\xc8\x86\xe8\x8a\xc8\x37\x3c\xeb\x3d\x36\xa1\x1b\x94\x57\xaa\x58\xbc\xd6\xda\x3e\x0f\x80\x38\x83\xac\x80\x1f\x48\x5b\x4e\x03\x57\xa0\x4e\x72\x78\xee\x18\x66\x03\x36\x55\x8c\xc5\x73\xdc\xce\xf8\x63\xdf\x52\x75\xa3\x0e\xcd\x37\xb5\x6e\xd6\x3e\xc4\x96\x94\xcd\x6f\x4e\x8f\x41\x14\x35\x94\x5a\xa8\x6c\xbd\x00\x10\xb0\x65\x24\xe7\x60\x18\xbc\xa1\xe4\xc8\x78\x4f\xb4\x79\x6c\xec\x25\x5f\x30\x5e\x18\xed\xc7\x92\xc2\x5a\x5d\x2b\x94\x4c\x5c\xf7\xf5\x95\xb6\xf3\x25\xdb\xd6\x6d\xa8\xe5\xdf\x8d\xa2\x4c\xc3\x36\x1f\x40\xaa\xa5\x9f\x5b\x88\x99\x54\xb5\xc8\x44\x2e\x54\xb6\xe9\x69\xdf\x74\x82\x1e\x2c\x9d\x33\xad\xdc\xc6\x1c\x64\xf1\x9c\x86\xcc\x4c\x1a\xd2\x78\xa9\x40\x50\x8c\xac\x3f\x0e\x99\x9e\xb0\x2d\x1b\x23\x6a\x4c\x4b\xad\x1b\x81\x33\xf9\x5d\x73\x25\x0a\x37\xf2\xce\x24\x05\x1c\x51\x6e\xd1\x9d\x21\x4b\x3e\x13\x8c\xdb\xb0\xd2\xac\x66\x42\x99\xa6\xa6\x49\x94\x96\xe5\x5a\xb4\x38\x5a\xdc\xb0\x37\xa7\xc7\xec\x09\xdb\x73\xcf\xda\x87\xf5\x33\xe5\xb2\x80\x24\x50\x48\x2a\xe9\xd8\xa8\x53\xdf\x04\x74\x09\x16\x2f\xd3\x35\x0a\x89\x11\x53\x9a\x99\x26\x9b\xfb\x3e\x39\xbb\xd7\x9b\xcd\x54\xb8\x04\x91\x97\x87\xb9\xd6\x37\x2b\xa1\xde\x18\x51\x0f\x26\xa0\xde\xac\x21\xa0\x62\x35\xca\xad\xb9\x74\xf4\x70\x61\x95\xc2\xf2\x9c\x5b\x4e\x82\xcb\xdf\xf0\x60\xa7\xf4\xb7\x2d\xbe\x8c\x78\x21\x55\xf3\x0e\x0b\x05\x86\x73\xb5\x5c\x9c\x40\xb3\x2c\xf3\xa3\x0e\xb3\x8e\xc9\x77\xb9\xf7\xa6\x44\x49\x32\xa7\xc9\x5a\x19\xdd\xa1\x26\x82\x9c\xe0\x98\x0c\x23\x9c\x72\xc2\x55\xae\xcb\xa5\x87\x39\x25\x52\x24\x1c\x08\x13\xb6\x5d\x7d\xe9\xf5\x40\x9c\x42\x85\xb8\x11\x3d\x50\x82\xbb\x9c\x0f\xae\x35\x37\x38\x7e\x45\x40\xf3\xac\xe0\x57\xa2\xa0\x44\x2d\x4c\xff\x5c\x5e\x81\x9b\xae\x1e\xab\x75\x31\x5c\xb9\xfb\x6b\x5d\x08\x2c\xc7\xf0\x03\xe1\x9a\x7f\x14\xe3\x00\x8d\x0c\x35\x0e\x60\x0d\x26\xe3\x00\x76\xed\x63\x18\x87\xa6\xc7\x51\xcf\xba\xe3\xe0\xf4\x86\x74\x1c\xe0\xf0\x7e\xe8\xe3\x60\x44\x96\xe9\xb2\x3a\xaf\xb5\x33\x3b\x07\x3b\x9b\xa8\xd9\x36\x66\x88\x8e\x8d\x15\xa9\x9b\x70\x16\xa4\x37\xf3\x3a\x2a\xc4\xe2\x16\x0f\x09\x5f\x8d\xf5\xff\x8b\xce\x2c\x10\x3d\xdd\x83\xcc\xb7\x92\x84\x17\xdd\x2f\xe9\x8b\xc7\x7c\x1c\x0c\x51\xcb\xdc\xc3\xd9\x39\xc8\x69\xa4\x33\x5e\x00\x0b\x44\xbf\x25\xc7\xba\xcb\xae\xdb\x70\x54\x7e\x07\x31\x4a\xf8\x2c\xca\x34\xe6\xe0\x68\xf1\x2e\x4c\xa5\x73\x11\xc5\xb2\x31\x7b\xf1\x12\xcb\xb4\xe0\x3e\x5f\xf9\xe7\xf4\x0a\x1f\x56\xce\x93\x5f\x5b\x4d\x58\xc6\x2f\x03\xb7\x84\xeb\xa0\x50\xb9\x54\x33\xf0\xab\x8d\x58\x2d\x0a\xac\x19\x24\x21\x70\x8d\x16\xe4\x2e\x6c\x09\xdf\xa8\xdf\x0f\xfe\xd1\x3e\x31\x99\x5a\x8e\xb3\x8d\xe5\x14\xc5\xad\x34\x6c\xe7\x85\x1f\x80\x1e\x60\xfc\x0f\xf1\x84\xd9\xc1\x37\x0c\xb3\x89\x9e\xce\x6b\xa9\x72\x2a\xaf\x4b\x06\x2b\xb0\x39\xa1\x1e\x0c\x85\x9b\x32\x8f\x65\xcb\x33\xf6\x56\xb1\x30\x58\x6c\xbc\xf6\xf2\x78\x8d\x2a\xb3\xf7\xd1\x8d\xdf\xef\x78\x0d\x0f\xe9\x36\xf3\x46\xc1\xdc\xbb\xe7\x8e\x9d\xe5\xbe\x7c\x9f\x7f\x97\x8d\x02\x7a\x92\xf4\x1b\xda\x8a\xf9\x01\x9b\xf5\x2a\x7d\xe6\x96\xb5\x95\x6a\x66\x62\x4b\x86\x17\x45\xe2\x0c\x5f\x65\xca\xf8\x19\x0e\xdc\x5d\xcb\x26\x44\xa7\x2c\xf8\xb1\x98\x21\x85\x53\x27\x1e\xb9\x11\x32\x2b\x0d\x3f\xaa\xdd\x48\x58\xc9\x8b\x8b\x6a\x7d\xb2\x01\xb6\x04\x6c\xfd\xf2\xe2\x30\x6d\x1a\x0e\x6b\xca\x49\x17\xf0\x3d\xe3\x79\x29\x8d\x01\x47\x98\xb8\x9a\x6b\x7d\xcd\xf6\xde\xcb\xb9\x36\x36\x72\x66\x0e\x68\xcd\x8f\x5d\xef\xf7\x99\x54\x45\xc8\x8a\x02\x3b\x58\xd9\x90\x06\x0f\x0f\xc9\x42\x2f\x60\x0e\x89\x81\x86\x92\x15\x96\xbb\x89\x9c\x33\x6e\x15\x6c\x5c\x60\x2f\x4f\x4f\xbf\x52\xc2\x5f\x9d\xa2\x33\x5a\xdb\x5d\xbc\xe5\x95\xe3\x88\xda\xe3\xc6\x07\x89\x94\x8b\x4c\x98\xe1\x60\x5e\xbf\x6d\xdb\x64\xb9\xc0\xaa\x7b\x01\xd9\x4f\xfc\xce\x24\x3b\xf0\x4b\xef\x02\x78\x0b\xfd\x74\x37\xd6\xa8\xd3\x6a\x25\x28\x86\x1a\xa3\x91\xee\x24\x1a\x88\x40\xaf\x42\xcc\xb5\xd2\x54\x23\xe7\x0e\x51\xad\x60\x49\x83\x88\xc2\x68\x1e\xcc\x09\x89\xe8\xa8\xab\x47\x6d\x94\x38\x0e\x04\x02\xf8\x83\x0d\x24\x89\xd8\x87\x5b\x69\xe7\xc0\xd8\x30\xef\x44\x0d\xa1\x27\xb5\x30\x10\x80\x51\x4c\xd4\xb5\xae\x29\x21\xcb\xfb\xad\xa9\x54\xeb\x5c\xe7\x90\xd1\xe5\x16\x09\x77\x7f\xed\x9a\x38\x50\xdd\x92\x3a\x05\x0c\x4e\x31\x9d\x8a\x0c\x14\xad\x78\x80\x51\x6a\xef\xb5\x14\x16\x54\x84\xe0\x16\x18\x91\x42\x95\xf2\x9d\x7b\x4a\xfc\xab\x38\x24\x4e\xd4\x11\xab\xbf\xde\x9f\x30\x76\xaa\x42\x06\xef\xc8\xcd\x62\x7c\xa7\x4f\x3d\xb3\xee\x15\x63\x46\x31\x78\x81\xd8\x71\xe6\xb4\xc3\xba\x19\x60\xc5\xf7\x71\x87\xb3\xd8\x25\x3e\xa8\x38\x00\xd7\x38\x35\xea\xa6\xde\xeb\x00\x7d\x5c\xe5\xee\x96\x8f\xe5\x2e\x7f\x1c\x01\x10\xd6\x57\xce\x11\xfa\xd9\x40\x34\x4f\x17\x51\x6b\x91\xf6\x1e\x02\x6e\xe7\x3a\x47\xf4\xc3\x80\xde\x56\x2c\x3c\x1a\x63\xa8\x89\x8e\x74\x3c\xa5\xb1\x78\x20\x86\x45\x24\x72\x9c\x9c\x39\x55\xbb\xf0\xbe\x85\xb2\x2a\x04\xa0\xae\x44\x2d\xb7\x80\x32\x11\x2f\xd4\xa8\xad\x60\x0b\xd4\x52\x04\xc6\x38\x62\xff\x82\x4d\x19\x12\x51\x3d\x4e\xdc\x79\xf8\x39\x5a\x88\xd2\x78\x92\x38\x28\x4e\xb5\xda\xbb\x2e\x58\x2e\xa7\x50\x27\x69\xe9\x91\x15\xaf\x79\xe9\x44\xbc\x61\x34\x04\x57\x62\x26\x31\x21\x32\x08\xb6\x5d\xa7\xee\x11\x36\xc7\x08\x85\xa1\xb4\xac\x94\xb3\x39\x2e\x14\xc6\x01\x51\x87\xf9\xa0\x62\xa1\x79\x0e\xe4\xb2\x4c\xd7\xec\x96\xd7\xa5\x3b\x37\x78\x36\x87\x08\x25\x57\x2c\x6f\x6a\xe0\x4b\xb1\x82\xe7\x8b\xb1\xb1\xdc\x3a\x4d\x59\xd4\x64\x50\xfa\xfe\x6f\xc9\xb1\xde\x7b\x6d\xc9\xb1\x3e\xf0\xda\x92\x63\x6d\xc9\xb1\x96\xaf\x07\x93\x1d\xba\x25\xc7\xfa\xbc\x60\x4d\xb7\xe4\x58\xf7\xbf\x36\x8e\x66\xba\x25\xc7\x5a\x7d\x6d\xc9\xb1\xb6\xe4\x58\x1f\x76\x6d\xc9\xb1\xee\x7f\x3d\x38\x1c\xe6\x2d\x39\xd6\xbd\xae\x2d\x39\xd6\xf2\xb5\x25\xc7\xba\xe3\xda\x92\x63\xdd\x71\x6d\xc9\xb1\x96\xaf\x2d\x39\xd6\xfd\xae\x2d\x39\xd6\x96\x1c\xeb\xb3\xe6\x0c\x60\x5b\x72\x2c\xba\xb6\xe4\x58\x9f\x05\x32\x3a\xdb\x92\x63\x7d\xd0\xb5\x25\xc7\xda\x92\x63\xad\x73\x6d\xc9\xb1\x3e\x17\xa7\xcc\x96\x1c\x6b\x4b\x8e\xf5\xdb\x51\x74\xb7\xe4\x58\x5b\x72\xac\x2d\x39\xd6\x96\x1c\xeb\xbd\xbd\xd8\x92\x63\x7d\x0e\x26\xa0\xb1\xb9\x5c\x0b\x1b\xf4\x43\x60\x8c\x28\x3d\x3d\x42\x0d\xb8\x6a\xa6\x53\x51\x83\xe4\x82\x27\x2f\xa5\x55\xb5\x88\x8d\xdd\x50\xae\xb0\x23\x40\x44\xa2\x4a\x9e\x3b\x7e\x4e\x30\x05\x80\xe1\xd9\xe6\x90\x9f\xbc\x7a\xbe\x02\x33\x69\xed\x7c\xc3\x75\xb3\xa7\xa1\xcf\xaf\xd4\x7a\x51\xf8\x3b\x06\x7c\x55\x65\x19\x8d\x7b\x56\x68\x43\xb9\xef\x30\x58\xd9\x9c\x2b\x25\xbc\xbd\x27\x2d\xf8\x51\xae\x84\x50\x4c\x57\x82\x62\xe0\x9c\x19\xa9\x66\x85\x60\xdc\x5a\x9e\xcd\x27\xee\x49\xca\x0f\x76\x9b\xa7\x4e\x9f\x18\x5b\x0b\x5e\xfa\x8c\xfd\x92\x4b\x6c\x8a\xf1\xac\xd6\xc6\xb0\xb2\x29\xac\xac\x42\x63\xcc\x08\x28\xb5\xc1\x83\x2a\x0c\x06\xe4\xcb\xb5\xc9\xed\xa3\xf6\x69\xd4\x2d\x1d\x83\xd6\x81\xb5\x39\x02\x20\xf1\xb2\xb2\x8b\x90\xe1\x2b\xd8\x54\xd6\xc6\xb2\xac\x90\x70\x5a\xc3\x13\xb1\xaa\x1a\xda\x1b\xf9\xb3\x5a\x51\x4f\x0d\x75\x55\xe5\xa0\xb6\x56\xd6\x60\xbe\x6c\xdb\x20\x35\x95\x4b\x43\x6a\xbe\x19\x31\xee\x11\xd5\x70\xa0\x7d\x4f\x61\xa8\xfd\xc9\x82\xad\xd3\x47\x51\x73\x11\x92\x6c\x9b\x50\xdc\x2e\x74\x28\x7e\xf0\x8b\x73\x94\xd4\x79\xb4\x0a\x05\xf1\x65\x74\xb6\x01\x4c\x80\x12\x37\x6e\x0d\x88\x4c\xb8\xf3\x95\xdf\xb1\xea\x3f\xf9\xa2\x8f\x0e\xc5\x97\xc2\x18\x3e\x13\xe7\x6b\x06\x1a\xee\xb2\xc8\x20\xd6\xd0\x4e\x0c\x2c\x85\x22\xe1\x24\x8b\xf3\x36\x53\x35\x88\x95\xd8\xa7\xa0\xfc\xdc\xd6\xd2\x5a\x01\x93\x0a\xd8\x7b\x10\x11\xed\x96\xe6\xef\x76\xb2\x3f\x5f\xfa\x46\xda\x1f\x3b\xa1\xae\x72\xcc\xc5\xbc\x12\xec\xaa\x96\x62\xca\xa6\x12\x12\x3c\x21\xe5\x72\x84\x50\x4c\x1c\xbd\x00\xc6\x38\x7b\x57\x2b\xaf\xcb\xfa\x7e\x4d\xd8\x0f\xd4\x31\x5b\x37\x2a\xe3\x11\xca\x2d\xd4\x9e\xca\x29\x9b\x41\xca\x26\x69\x8b\xff\xf1\xe4\xbf\xfe\xcc\xae\x16\xee\x48\x03\xcd\xca\x6a\xcb\x8b\xf0\x92\x85\x50\x33\x37\x56\xb8\x3d\xd3\xea\xc9\x30\x02\x40\x03\x82\x1d\x7f\xfa\xc5\xf5\x55\x7a\xc6\x1e\xe4\xe2\xe6\x20\x1a\xbf\x71\xa1\x67\xab\x88\xb3\xd6\x4f\xe6\x5e\xd3\x24\x5a\xb1\xcc\x86\x61\x7c\xf4\x98\x60\x6c\xae\x6f\x51\xd7\x5f\xb1\x7a\xda\x42\xac\x4a\x57\x4d\x81\x4e\xe7\xe7\xa1\xee\xb8\x31\x62\xb9\x3a\x70\xe5\xbe\x00\x37\x29\x35\xd1\x45\x54\xc7\x4c\x5d\xff\x48\x4d\x55\x27\xe4\xc8\x0b\xd0\x60\x60\x08\x3d\xe7\x45\x71\xc5\xb3\xeb\x4b\xfd\x42\xcf\xcc\x2b\x75\x52\xd7\xba\x4e\xfb\x52\x70\x27\x2d\xe7\x8d\xba\x46\xea\x87\x00\x9e\xa0\x67\x14\xca\xf5\x25\x0e\xab\x5e\x18\x2b\xe9\xbd\x10\xf6\x66\x50\xdb\x8a\x78\x27\x5b\x5b\x87\x8a\xb8\x70\x45\xc6\xed\x9b\x78\xb1\x7d\xf1\xe4\x3f\xfe\x82\x4b\x97\xe9\x9a\xfd\xe5\x09\x64\x73\x9b\x11\x6e\x62\x90\x6d\xee\xa0\x28\x79\x51\x38\xb3\x21\x5e\x94\x6e\xa0\x57\x2d\xc2\x4f\xbe\x06\x6d\xff\xe5\xf6\xc1\xaa\xd4\xe5\xe5\xdf\x41\x8f\x92\xd6\x88\x62\x3a\xc2\x7a\xa5\x60\xd6\xec\xc2\xc1\xb0\x4b\xd2\x07\x8a\xc6\x1e\x80\x02\x74\xa3\x8b\xa6\x14\xc7\xe2\x46\x0e\xc1\xee\x97\xb4\xe6\x4d\xfd\x42\x1a\x28\x0d\xbb\x2a\x74\x76\xcd\x72\xfa\x32\xca\x6f\xe9\x62\x84\x3f\x5e\xa2\xd6\xf8\xfd\x93\xdc\x9e\x92\x57\x55\xa8\x1e\xaa\xf9\x6d\x32\x18\xb0\x27\x01\xc8\xe0\xf1\x13\xb5\xe2\x1b\x39\xb9\xb9\x76\x13\x6b\x27\x04\xf5\xf7\x51\xb7\xbd\x1f\x88\x8e\xaf\x6d\xd0\xef\x86\x0a\xfe\x8d\xf5\x26\x4b\xf5\x92\xa1\xe4\x2e\x2c\x0c\x54\x00\xdc\xf2\x01\x91\xbc\x31\x42\x51\xd6\x3b\xb1\x29\x19\x17\xf5\x1e\x4e\x3b\xce\x2a\x51\x1b\x69\xdc\xb9\xfc\x3d\x6c\x28\x24\x33\x6c\x5d\x80\x9b\x19\x04\xdc\xdc\x00\xac\xdc\x5f\x52\x9e\xeb\x9c\x1a\x04\x51\x88\xa0\xd2\x2b\xd4\xda\x54\xab\x1d\xf0\x40\xdd\xb4\xa8\xfc\xbe\x1d\xcd\x54\x52\xba\x4f\x82\xa8\xc4\xbb\x3e\x27\x01\x09\xef\xf7\x58\xe5\x63\xe8\xfc\x40\x62\x00\x04\x23\x4d\x6e\x2a\x09\x13\xe3\x11\x37\x4a\xa4\xd2\x93\x1d\x38\x61\x18\x05\x77\x7b\x82\x7e\xca\x76\x9f\xed\x6e\x54\x48\xe2\x10\xd5\xba\xe2\xb3\x5e\x2c\x3f\x9d\x91\xea\x36\x1b\x43\x50\x38\x33\x08\xbe\x0f\x80\x6c\x70\x97\xc8\x5b\x84\x1d\xc0\x4f\xc2\xe8\xa8\x1f\x60\x32\x10\xb0\x52\xfb\x96\x2f\x18\xaf\x75\xa3\x72\xf2\x2f\x05\x07\xdf\xcb\xce\x83\xcf\xb4\x12\x2d\x6b\x68\x8a\x60\x01\x1e\x7d\xa9\xd8\xd3\xc9\xd3\x27\x9f\xcb\x49\x05\x6f\xd8\x39\xa9\xce\xc2\x49\x85\xf2\x69\xa3\xef\xea\xb1\xf0\x07\x7a\xdf\x97\xe4\x62\x69\xa1\xee\xa5\x07\xd2\x86\x8f\x6e\x6b\x69\x45\x44\x0e\xb8\x07\x86\x8b\xb3\x0f\x23\xbc\x86\xfd\x55\x1c\x13\x3d\x07\xa9\x1f\x40\x86\x69\xae\x3e\xa2\xdc\x22\x01\x05\xdb\x6d\x95\x87\xcb\xbc\x47\x84\xc5\x03\xb5\xb3\xc3\xf6\xf0\xce\x5d\x2c\x75\xde\xdf\xe8\xd2\xa2\x41\x3b\x79\x57\xf5\x40\xdf\xec\x54\xd5\x57\x1c\x7c\x70\xd5\x80\x23\xf8\x37\x31\xe7\x37\x02\x4a\xbc\x65\xc1\xeb\x02\x62\x8e\x17\xd8\x77\x76\xd5\x58\x26\xd4\x8d\xac\xb5\x2a\x85\xb2\x0c\x72\xe0\xaf\x0a\x11\x73\x63\xff\x7e\xef\xfb\xc3\xd7\x90\xd0\xb0\x4f\x60\x15\xd4\xcb\xc6\x78\x60\x9b\xb8\x27\x51\x73\xbf\x3a\x7d\xbe\x1f\x6e\x0c\x41\xe6\xfa\x7e\xb9\xe7\x94\x8d\x6d\x90\xb0\xe5\x5d\x56\x34\x46\xde\x6c\x4a\x92\x50\xed\xfd\xb1\x5c\x6b\x9e\x3b\x38\x00\xed\x40\x2d\x95\xf4\x83\x6b\x7d\x45\x19\xe0\x52\xc0\x64\xd7\x84\xd2\xc0\x38\x06\x4e\xae\x27\x42\xd9\xc0\xf4\x39\x8f\xc5\xb8\xa4\x42\x00\xa2\xcc\x66\x9d\x50\x4a\xe7\xe2\xfe\x78\x3c\x69\x7a\x0f\x35\x81\x31\xf3\xa8\x4e\xd0\x64\x73\x91\x37\x05\xb1\x79\x03\x6c\xaa\x33\x1f\x78\x8b\xcf\xa7\x80\x3f\xe8\x74\x1a\xc0\x0e\xd4\x18\x9c\x83\x38\xe6\xfe\xf7\xb5\x87\x46\xf0\x1f\x98\x4e\x8b\x60\x94\xba\xb6\x46\x8c\x1b\xd3\x94\xb8\x25\x90\x1a\x61\x2a\xad\x69\xc9\xc2\x49\x3b\x76\x1b\xe3\x9e\x65\x5b\x3d\xc6\xf7\x42\x14\xb0\xb8\x7a\x8c\xf1\xee\x59\xd4\x0e\x0e\xb4\xf1\x7f\xd1\x82\xa3\x84\x09\x88\xb6\x85\x3c\x4e\x0d\x5e\xd2\xa9\x04\x7a\x25\x4e\xe3\x7d\xb1\xe2\x97\xa8\x3a\xe0\x1d\x00\x1c\xc3\xaf\x44\x61\xba\x0d\x5d\xb5\x93\x42\x78\xa5\x34\xf0\x3d\xf9\x73\xb9\x31\x72\xa6\x80\x59\xd3\xb5\x76\x4f\x0e\xcd\xb5\x6d\xa6\x21\xf8\x71\xd7\x96\x6a\x49\x16\x56\xc9\x2b\x22\x62\xe7\x56\x97\x32\xbb\x47\x4b\xfa\x9e\x5d\xee\x54\x64\x27\x95\xbe\xaf\x2e\x96\x3c\x3e\x26\xf2\x6a\x4c\xd8\x85\x2e\x29\xc5\x49\x45\xfc\x5e\x9e\x66\xd5\x9d\x18\xb5\x70\x63\x01\x89\x47\xb2\x8d\xc6\x03\x1f\x8e\xaf\xb5\x86\xe7\x04\x95\x9c\xc2\xb8\x00\x4c\x49\x34\xaf\xba\x28\xf4\x2d\x24\x16\x63\xbb\x7e\x6d\x43\x0a\xcc\x33\x36\xee\x70\xd6\x4e\x52\x38\xd1\xf7\x3f\x87\xee\x1d\xfd\xfa\x53\x30\x3f\x07\x80\xfa\x4e\x8f\xe3\x3f\x4f\xcf\x8f\xe2\x3f\xdf\x18\x37\x4a\xf4\x41\xb7\x6b\x29\x5f\xc3\xdd\x77\xc5\xc8\xd9\x77\xdd\x35\x45\xca\xa3\x5f\xf9\xfa\x68\xce\x95\x0f\x64\xdd\xf9\xbc\x85\xc9\x6c\xd1\x76\x67\xce\x6b\x41\xc8\x72\x4e\x92\x9b\x8a\x67\x77\xf6\x22\xc0\xb8\xbd\xf7\x86\xf7\xf6\xd4\x34\x95\x67\xea\x2e\xe0\xc6\xd0\x93\x76\xd9\xfd\xf8\x87\x9f\x3e\x70\x30\x7f\xed\x37\xab\x86\xf6\xfd\xbf\x49\x08\xfd\x3e\xe8\x17\xab\xe9\xbe\x3e\xec\xb7\x11\x63\xde\x07\xdd\x7f\x17\x5b\xef\x87\x3e\xcd\xb3\xbc\x7d\xd8\x8b\x75\x67\xfb\x03\x6e\x87\x29\xbd\x1f\x26\xc2\xda\x22\x7c\x5d\x77\xd7\x1a\x4e\xaa\xf5\x9d\x53\xeb\x19\xfb\x1d\x05\xe0\x0e\x90\x53\x02\x60\x53\x33\x96\xc0\x4a\x35\x75\x2d\x14\xf0\xe5\x37\x90\xe9\xe8\x79\xf0\x51\x48\x83\xb0\x25\x08\x4f\xc4\xa1\x67\x87\xe1\x2c\xa4\x0c\xb8\x92\x03\xac\x67\x04\x63\x3d\x6d\x20\xa1\x11\x44\x3f\xc2\xd4\x69\xe5\xfa\xf1\x6c\x15\x0e\x87\xae\x84\x8a\x58\xf0\x49\x6b\x1e\xbb\x35\x94\x20\x73\xa0\x22\x30\x29\xf3\xdf\x55\x05\xb7\x53\x5d\x97\x63\xaf\x1e\x8e\x13\x25\x81\x1d\x41\x6a\x8d\xf1\xf6\x15\xe6\xb7\x22\xdc\xa6\xca\x0b\x11\x9d\xe6\xe1\x55\x55\x8e\xe0\x54\xac\x51\xb5\xc8\xf4\x4c\x41\xe5\x31\x7d\x0b\xe7\x5a\x70\x0e\x71\xe3\x4e\x52\xa6\x9a\xa2\xb8\x7f\x1e\xc2\x9a\x4a\x80\xbe\x11\xf5\x5c\xf0\x7b\x2e\xde\x4e\x4a\x0b\xb5\xd1\xb2\x92\x1a\x42\x2e\x20\x95\xd7\x3f\xc4\xa9\xc6\x3a\x83\xda\x36\x0c\xb1\xfb\xc4\x65\x0e\x07\xba\xd3\xf4\x38\x9b\xc9\x1b\xa1\x3c\x18\xf9\x51\xc1\x03\xb3\xb6\xc7\x5f\x25\x40\xf4\xc6\xea\x90\xb4\xc0\xb8\x8d\x20\x91\x21\xc7\x89\xe2\xa5\x71\x3b\xd1\x2d\xc4\xcb\x5d\x78\x0e\xb4\x0f\xb9\x13\xf2\x06\x90\x14\x72\xd4\xbe\x52\xe9\x7d\xab\x09\xe6\x26\xcb\x20\xbb\xc5\x9b\x22\x94\xd5\xf2\xeb\x8f\xa0\x94\x34\x27\x83\x56\x35\x43\xea\x72\x00\x87\x6d\x07\xb6\x70\xe2\x7f\x81\x4a\xce\xe9\x34\x7d\x92\x4c\xe0\xf8\xa1\xf6\x09\xd4\xef\xd6\x1e\x3c\xd7\xb9\xd3\xc2\x46\x2c\x4c\x65\x4c\x4b\x4e\xf1\x16\xdc\x93\xd1\x66\x44\x25\xad\xae\x85\xa9\x34\xb2\x02\xc4\x8f\x1d\x45\xfe\x2f\x69\x93\x64\x3b\xe4\x77\x0b\x5b\x03\x71\xdb\xfe\x2d\x6a\xbd\x52\x87\x9f\x49\x3b\xb9\xfe\x0b\x28\xf0\x42\xcd\xb9\xca\xd0\x76\x3a\xb8\x16\x95\x39\x30\x72\x86\xfa\xfa\x9f\xff\xf2\x17\x50\xde\xfd\x90\x1c\xbc\x3e\x39\x3c\x7e\x79\x32\x29\xf3\x47\xa4\xc9\x57\xdc\x5a\x51\xab\x67\xec\x7f\xf6\xde\xfe\xf1\x97\xf1\xfe\xd7\x7b\x7b\x3f\x3e\x19\xff\xd7\x4f\x7f\xdc\x7b\x3b\x81\x7f\xfc\x61\xff\xeb\xfd\x5f\xfc\x1f\x7f\xdc\xdf\xdf\xdb\xfb\xf1\xbb\x97\xdf\x5c\x9e\x9f\xfc\x24\xf7\x7f\xf9\x51\x35\xe5\x35\xfe\xf5\xcb\xde\x8f\xe2\xe4\xa7\x0f\x6c\x64\x7f\xff\xeb\xdf\xdf\xb3\xa3\x6b\xd6\xa5\xf4\xad\x45\xe9\x55\x7f\x32\x60\xcd\x49\x55\x0b\x51\x82\xf8\x5b\x27\x5b\x2b\xf5\x92\x76\x9a\xf2\x07\x2c\xfd\xe5\x64\xa2\x7f\x9a\x9a\x39\x31\x69\x50\x74\x16\xfa\x16\x32\x2c\xa5\x76\xca\xcf\x84\xbd\x82\x73\x90\x9d\x89\x1b\x51\x8f\x7c\xab\x2f\xdc\x4d\xe7\xe1\x9e\xd8\x0d\xb7\xea\x8e\x35\x73\xfc\xd7\x9c\x13\xdf\xf7\x1e\x83\x87\x8c\x26\xd4\x79\x90\x4f\x13\xf6\x3d\xaf\xa5\x6e\x0c\xe9\x22\x31\x10\x38\xa6\x90\x85\x93\x04\xbc\x12\x14\xe0\x09\x8d\x84\xca\x30\x1f\xe3\x09\x63\x73\x18\xe4\xf5\xd1\xea\x23\x41\x5a\x37\x53\x37\xfe\x51\xb5\x4f\x75\x5d\xc2\x10\xc7\xc3\x60\xa5\xfc\xf7\x27\x9a\x89\x3b\x0a\xcd\xf8\x7e\x80\x6c\x3d\x23\x64\x13\xc1\xe6\x72\xe6\x13\xaa\xe1\xfd\xd1\x7c\x8d\x3e\x0d\x2b\x64\x8d\x29\x5d\x67\x9b\xae\x9b\xd7\x5f\x75\xdf\xaf\xc7\xb2\x48\x91\x96\x63\xb0\x66\x5f\x51\xd4\xee\x9b\x1d\x5c\x27\x70\x88\x8c\xb3\x5a\x5a\x99\xf1\x62\x07\x0e\x27\xff\x55\x56\x34\x4e\x4f\x8c\xbf\xad\x05\xb3\xb7\x1a\x9f\xc2\x0b\x76\x2d\x16\xb7\xba\xce\xfd\xf9\xec\x9f\xd8\xce\x85\xb1\xfe\x91\x52\xd0\x06\x46\x37\x43\x5d\x8a\x9a\x5d\x09\xef\x41\xef\xdc\xbc\x98\xb0\x43\xb5\xa0\xf0\xa3\x8a\x8b\x0c\x23\xfc\x37\xd0\x11\x50\x8b\x4a\x16\x09\x1d\x62\xfe\x69\xdc\x12\x20\xce\x6a\xef\xb2\x53\xc0\xc2\x2e\xf0\xa7\xbf\x77\x2f\xeb\x9a\xaa\x9c\x60\x77\xd4\x58\xa3\xa5\xfd\xd7\x9f\x44\x5a\x38\xfd\x46\x2a\x61\xcc\x37\x6e\x2a\xfb\xa8\xab\xe9\xea\xe0\xa0\x96\x50\xdb\x50\x29\xd5\xa6\x14\x0b\xb7\xa5\x30\x46\xec\xc4\xb0\xce\xdb\x3b\x27\xec\x10\x3e\x80\x9c\x78\xa7\x79\x41\x15\x9d\x6b\x4c\x5a\xd3\xa5\x9d\xc7\x3b\x0e\xcf\x8e\x7d\xee\x32\x6a\x0a\x26\x05\x52\x47\x95\x39\xed\x09\x68\x7a\x94\x41\x2b\x7e\x6e\x38\x30\xe8\xee\x5c\xd6\x8d\xd8\x59\x4f\x55\x42\x88\xfe\x83\x3f\xfd\xe5\x09\x68\x4b\xe1\x79\x63\x78\xde\x3a\xaa\xd2\xfd\x73\x64\xd6\xca\x8e\xe9\x26\x06\xbd\x8e\xd7\x83\x1f\x70\x6f\x77\x50\xd0\x0a\x6a\x7b\x61\x9a\xc2\x98\xaf\xe5\x5a\x5d\x2b\x17\x66\xfd\x2c\x98\x71\xdb\xdd\xcb\xfb\xb3\x9b\xf5\x49\x60\x49\x9e\x3b\x44\x94\xab\x6d\x0d\x67\xc5\xe0\x94\x84\xe7\x44\x9e\x5d\x24\xc1\xa0\x8f\x21\x1d\x16\x04\x17\x44\x05\x40\x3c\x2e\xaa\x1e\xa9\xbf\x6b\xc8\x1b\x34\x5e\x21\xad\xae\x97\x7f\xfb\x75\xd2\x12\x49\x6e\x7f\x54\x74\xbe\x0c\x35\xe4\x94\x30\xed\x6b\x73\x00\x7c\x2a\xa0\xc6\x78\x98\x7f\xe0\x43\x09\x94\x1f\x50\x99\x83\x5a\x81\xef\xbc\x89\x92\x23\x73\xc1\xf8\x0d\x97\x05\xf2\xa0\x38\x93\x4e\x9b\xc4\xc9\x8e\x1d\xca\xb4\x32\x4d\x09\xcf\x28\xdd\xe9\x82\x67\xc6\x5b\xd5\xd6\xa4\x2a\x24\x61\x79\x6f\x55\xaa\xeb\xe1\xf1\x42\xf1\x52\x66\xfe\x0d\x0f\x0b\x4f\xfc\xd6\xa9\x4b\xf5\x6d\x07\x37\xb9\x2c\xcb\xc6\xba\x6e\xde\x13\xd5\x74\xc3\xf2\x28\x9a\xc8\x38\x6e\x2e\xde\xf1\xcc\x16\x0b\x70\x54\xa5\x37\xd9\x79\xad\x9b\xd9\x9c\x71\x06\x7f\x5f\xc0\x57\x13\x76\x6a\x9d\x2d\x09\x64\xed\x04\xd7\x20\x2d\x9e\xdf\x8d\x92\x3f\x37\xa2\x58\x30\x09\x7c\x42\x21\x66\x92\x36\x1b\xa1\xc7\x03\xd3\x4c\xc4\x6e\x83\x5a\x80\x10\xb9\x87\x3c\x20\xd3\xfe\x8e\xce\xa3\xdd\x0e\xda\x83\x3b\xf0\xf9\xfd\x93\x78\x36\x24\x3f\xd7\xc8\xfe\xeb\x23\x36\xd7\xcd\xa4\x5a\xc6\x62\x5b\x3d\xc3\x32\x0a\x1f\x67\xdd\x39\x06\x53\xa5\x4d\xc0\x02\xa2\xc6\xe3\xb3\x8b\x7f\xbc\x38\xfc\xdb\xc9\x8b\x4f\x5e\x4b\x82\xbd\xec\x3d\x18\xb8\x17\xa2\x9c\x57\xe2\x3f\x8b\x4c\xb6\x64\xcd\xae\xff\x9e\x1b\x23\xe1\x48\x0e\x98\x3e\x7c\x44\x29\x8f\x73\xb7\xd5\xae\xc3\x9e\x77\x36\x3b\x19\x09\x74\x0e\x03\xa8\xa5\x0a\xf1\x37\xde\xa6\x39\xf4\x2b\xfb\xef\x91\x61\x95\x8c\xd3\xa5\x28\x2b\x67\x1f\x0f\x36\x5e\xe9\xe9\x1c\x37\xff\x2b\x03\xe7\x6f\xfd\xf0\x01\xc4\x83\x4e\x30\xeb\x7f\x19\x27\xed\x40\xde\x29\x3a\x7b\x39\x53\xe2\x36\x7d\x98\x4f\xe9\xf1\xbf\xb8\xd2\x8d\x22\x4e\x7c\xdf\xf8\x0f\x88\xe2\x41\x39\x29\x80\x10\x5e\x08\xeb\xad\xbb\x74\xce\xa9\xda\x1c\x89\xa2\xe8\x3e\x54\x1c\xe2\xb0\xce\x8a\xdf\x5c\x09\xf6\x15\x40\x9c\xf0\x52\xfc\x75\xfc\x55\x10\x4a\xf0\xf7\x88\x36\x69\xe7\xe3\xd6\xa1\x95\x9e\x91\x13\x74\x62\x40\x8e\x3f\xf1\xa3\x69\x95\x38\xc0\xbd\x59\x2a\x43\x3e\x80\x53\x89\x14\xa8\x45\x9e\x4c\xd2\x59\xb2\xf0\x73\x8a\x1e\xa4\x9d\xde\x13\x93\xd9\x84\x59\xad\x01\x9a\x04\xb1\xd6\x0f\x15\x13\xef\xa4\x01\x8b\xb9\xfb\x8a\xb1\xa1\x4c\xe9\x3b\xf8\x08\x7d\xab\x52\xa0\x10\x2c\x5d\xa6\x94\x29\x43\x16\x62\x94\xa6\xc2\x6f\xb4\xf4\xa9\x71\x5c\x41\xf0\x07\x23\x15\x61\x70\xae\x16\xac\x94\x06\x48\x72\x00\x4f\x31\x6f\x0a\xbc\x39\x47\x24\x12\x84\x27\x43\x57\x83\x9b\x5b\x28\x86\x4a\x2a\xb3\xdb\x46\x3b\x0a\x80\x3b\x2e\x4a\x7d\x23\xf2\xf7\x29\x57\xc4\x8d\x02\xe5\xf5\xb3\xae\xa6\x18\x4a\x2c\x12\xef\x7e\xf2\x94\xa8\x20\xad\xd6\x05\xab\x0a\xae\x04\xd5\xe8\x07\x8f\xc4\xb2\x9c\x5e\x17\xa7\x7e\x98\x1c\x17\x67\x56\x40\xa2\xcb\xb5\x58\xdc\x5b\x6c\xaf\xa1\x56\x2c\x3f\x1c\xdf\xa3\xe4\xd5\xfd\x4c\x11\xb7\x18\x7a\xbb\x9a\x77\x5f\x63\x43\xac\x6a\x7d\xcb\x4b\xc5\xd4\x21\xd9\x14\xa4\x0a\x79\x95\x0f\x01\x99\x62\xc4\x5e\xa9\xe7\x58\xaa\x3b\x42\x47\xf3\x84\x9d\x2a\x66\x74\x49\x25\xc2\xef\xac\x19\x21\x19\x23\x67\xa6\xb9\x32\x82\xd8\xee\x9c\xa1\x41\x11\x4f\x0a\xe9\x56\xa2\x2e\xa5\x8d\x53\x7b\xdd\x92\xc3\xc7\x0c\x8a\x79\x72\xf0\x3b\x1a\xbd\x31\xbe\xf4\x3a\x1e\x8e\xfb\xdb\x8e\x51\x18\xac\xa7\x2b\x73\xf7\x75\xa7\xad\xc4\x8e\x4e\xc2\x7c\xe9\x41\x04\x29\x71\xe8\x0b\x62\xb3\x5a\x37\x95\x3f\x43\x52\xbe\xe6\x96\xa4\xd0\x1f\x24\xe8\x1f\x4c\x9b\x0e\x42\x0b\xac\x71\xd1\x1e\x8c\xb9\xd3\x47\x8d\x19\xad\x94\x8b\x75\xa3\x3c\xb7\xb1\x00\x1f\x62\x94\x58\xb9\x53\x88\x19\xcf\x16\x3b\xe9\x73\x56\xa5\xb1\xa2\xc9\x29\x4b\xe4\x85\xc2\xe7\xb5\x05\xda\x50\xc7\x0d\x26\x35\x3a\x0e\xd0\x4e\x32\xd4\x45\xef\xbf\xf4\x08\x23\x18\xa6\xaf\x7b\x84\x19\xff\xf4\x97\x3f\x8d\x7d\x22\x01\x74\xe5\x93\x2c\xa8\x90\x86\x3a\xa8\x63\x3c\x99\x33\xa7\x09\x48\x53\xc1\xfc\xc2\x49\xd7\xfa\x26\xc3\xd3\xdf\xe7\x3b\x5e\xdd\x88\x9f\x80\xb6\x89\x4f\x38\x5c\x52\xcd\xfa\x3a\x8b\x77\x2e\xd2\xa6\x68\x35\xea\x8a\xff\xdc\xb4\x45\xdb\x24\xdb\x50\x61\x88\x86\x98\x06\x05\xaa\x98\xdb\x3e\xb5\xd2\xd5\x4d\xc7\x72\xfb\x6e\x80\xa3\x9d\x12\x06\xd7\x58\xbe\xf0\xbb\x3b\xed\x16\x68\x0b\x56\x84\x72\xa5\x36\x6b\x39\x6c\x47\x6e\x9d\xda\xd9\xcd\x89\x16\x41\x31\xed\xbe\x67\xe6\xde\x32\x62\xe6\xe7\x16\xfd\xa8\x70\xb2\x53\x8e\x05\x62\xd3\x00\xcd\x24\x68\x1b\x24\xfa\x9d\x0a\x70\xcb\xeb\xdc\xa4\x6e\x23\x82\x32\x23\xd7\x0f\x45\xcd\xbc\x16\x71\xae\xf3\xb6\x07\xc1\xb5\x9b\x3a\x8a\x1e\x91\x33\x28\x1d\x4d\x78\xfd\x36\xf3\x05\x24\xf7\x39\xaa\x89\xb3\x86\xd7\x39\x84\x0c\xda\x85\xb0\xf5\xb1\xac\xba\x86\xf3\xb1\x78\xb6\xa7\x76\x43\xa2\x1f\xf2\x04\xb0\x9e\xd2\x4f\x23\x32\x66\x4e\xce\x19\x34\x0e\xd6\xe6\x39\xff\x2d\x2b\xb2\x9d\x54\xcd\x3e\x6a\x51\x97\x75\x78\xae\x8b\x1c\x14\x18\xe2\x06\xf7\x8f\x72\x82\xaf\x96\x57\x8d\xa5\x5c\xbc\x4c\x97\x65\x0a\xcc\x85\xe1\x79\x33\x61\x2d\x32\x53\x9c\x27\x01\x92\x78\xc2\xd8\x85\x10\x30\x77\x71\x3f\x40\x83\xf6\x47\x1c\x1d\x02\x7a\xca\x84\x5b\x48\xb8\x40\x3e\x51\xee\xd1\xfa\x1b\x8b\x32\xb6\x7b\xa6\x86\xee\x1c\x86\x50\x78\x9c\x58\x8d\x8a\x27\x9e\x8b\xbc\xaa\x0a\x89\x75\xfc\x1d\x9b\x03\x6a\xd6\xdb\xd4\x7e\x2a\x61\x73\x63\x41\xe1\x0d\xd8\xae\xdf\x35\x57\xa2\xc0\x64\x34\xb4\x58\x31\x01\xee\xd6\x35\x31\x97\x15\xee\x6a\x6e\xc3\xcf\xc1\xb7\xd1\x35\xdb\x9f\xb9\x13\xe9\x29\xba\x3a\xf4\x2d\xa4\x1e\x7e\x73\x7a\x1c\x74\x17\x77\xd7\xf3\x0b\xcc\x1b\xff\x02\xef\x32\xc2\xce\x64\xce\xae\xb0\x3a\xc8\x9d\x84\x7b\x4a\xdc\x22\xde\x00\x39\x6c\x42\xf0\xf6\xc6\xd7\xe1\x63\x6b\xe1\xe1\xd4\xe4\x3e\xfb\x12\xdb\x04\xe3\x07\x53\x3f\xae\x24\xd5\x23\xbf\x7a\xbd\xeb\x73\x22\x6f\xc7\xf5\xed\x78\x3c\x1e\x53\x11\x01\x68\xcf\xa3\x64\x0c\xc2\xa9\x5e\xea\x5c\x4e\x17\x9d\x91\x00\x0f\x42\x78\x04\xac\x48\xae\x16\xd4\xbb\x09\x3b\xd3\x56\x78\x0c\x8d\xe0\x18\x68\x39\x93\xdd\x2b\x42\x2c\x1b\x52\xad\xb5\x99\x78\x4f\x8b\x4f\xd3\xbd\xbf\x05\xdf\x2f\xe7\xab\x0f\xe6\xe7\x8a\x7a\x84\xbe\x49\xd0\xab\x4a\x1c\x7c\x48\x2f\x10\xf4\xe9\x29\x2e\x52\x80\x68\xb8\x63\x62\xfc\x39\x44\xab\x86\x42\x7b\x98\x0a\x22\xde\x55\x1a\x49\xad\xc0\xcd\x7f\xae\xf3\xe5\x1c\x58\x54\xb6\xaa\x0a\x2b\x39\x93\x5d\x43\x86\x1e\xa6\x5d\xfb\x41\x60\x57\xdc\x35\x19\xba\xb3\xd7\x59\x27\xfb\x10\x79\x82\xa6\xe1\xbc\x53\x9a\x89\xe9\xd4\x59\x94\x5a\x31\x51\xcd\x45\x29\x6a\x5e\xa4\x0f\x22\x28\xb8\x67\x4e\xdc\xd6\x6e\x95\x62\x9e\x69\xc9\x2b\x94\xb6\x20\x3c\x73\x59\x03\xa4\xae\x4c\xf2\xbf\x77\x5e\xa9\xd7\x5a\xdb\x97\xd2\x80\x4d\x49\x19\x37\xe8\x01\xd8\x59\x65\x68\xf8\xef\xda\xba\xfa\xbe\x2b\xf9\x93\x25\x59\x33\xf4\x09\x1c\x0e\x22\x6b\x9d\x04\x71\x42\x2b\x18\xee\x4e\x99\xb6\xf5\xa2\xd2\x52\xd9\x65\xb4\x9c\x00\xb2\xfc\x86\x90\xa2\xc1\x10\xf6\x87\x56\x48\xf8\x63\x2f\xf9\x22\xb8\x84\x29\x8f\xb9\x73\xc6\xa2\x6b\x80\xbe\x03\x0c\xb7\xee\x21\xec\xa6\xf0\x1c\x90\x83\xe3\x8f\x47\x51\xf6\x70\x92\xf0\xd2\xfd\xb9\xe5\xd7\xc2\xb0\xaa\x16\x99\xc8\x21\xfc\x88\x3e\x55\x6e\x13\x48\xf6\x9e\x93\xfe\x88\xa4\x17\x2c\x99\x33\x0d\xfb\xa4\xe7\xa2\x39\x8d\x72\xe0\x08\x3d\xa9\x5d\x22\xa0\xe3\xba\xb5\xc4\x21\xe8\xac\xd5\x18\x08\xc4\x1b\xe3\xb3\xe3\x6b\x9f\x57\x98\x1c\x40\xe4\xb5\xc7\x63\x13\xea\x88\x9d\x95\xe8\x57\x98\x53\x9d\x94\x69\x6a\x11\xca\x60\x73\x2d\x5a\x32\x71\x6e\xd8\x9b\xd3\x63\xf6\x84\xed\x41\x09\x78\x80\x01\x0c\x89\x0c\xdd\x3a\xe5\xa9\x6f\x22\x75\x29\x11\xea\xa8\xd2\x28\x8b\xba\x91\x04\x74\x35\x42\x9a\x5d\xfe\x20\xd7\xf8\xba\xeb\x71\x3d\xa0\x87\x50\x4a\x35\x80\x0c\x7a\xb3\x86\x0c\x8a\x15\x6b\xb7\xbc\xd2\xb1\xc2\x35\x54\x0a\xcb\x01\xd1\x16\x65\x93\xbf\xe1\x41\xce\xde\x6f\x5d\x42\xa5\xd5\x90\x03\x2c\xaa\x8b\x13\x68\xd0\x87\x13\x48\x8d\x47\xdb\x21\x5f\xb6\x1d\xbc\x2c\xf8\x15\xa0\x04\x1f\xf0\x0c\x20\x94\x35\x57\xb9\x2e\x97\x9e\xe6\x66\x13\x8c\xb7\x68\x36\xb7\xcb\xee\xae\xab\x57\xfe\x44\xbf\xec\x09\xb0\xf1\x07\xc0\x57\x7b\x01\xbe\x02\x69\xc2\x4a\x40\xe7\x01\x20\x0f\x2c\x99\xad\xbd\xe1\x37\x7b\x27\x43\xd4\xba\x58\x33\xeb\x21\xcd\x11\xd1\x05\x21\x65\xf8\xd7\x76\x0d\x3f\xd8\xb7\xb6\x6b\xe6\xa2\x76\xc5\xcb\xa2\xea\xbc\x35\xb8\x73\x1e\xea\x5b\x37\x6b\x9d\xd2\xac\xfb\xd6\x50\x37\x9d\xbc\x35\x9c\xbb\x0f\xf1\xad\xd3\x32\xf9\x01\x0e\x13\x6a\x90\x69\x2a\xd6\x27\xba\xca\x2e\x92\x6e\x5b\x86\x0b\x4e\xa8\xc7\x25\x47\xfb\x60\x2d\x62\x35\xdd\xa7\x16\xdd\x3a\xe3\x05\x20\x5a\xac\x3b\xcf\xac\x3b\xd7\xdd\x26\xa3\x8a\x1f\xee\x7a\x0b\x9f\x45\x75\xab\x1c\x61\xc0\x75\x1b\x28\xef\x04\xc5\xc9\x4d\x47\xbf\xf4\x69\x95\xee\xfc\x6d\xcb\x68\xe3\x5f\x5b\x0d\x28\x4e\x2d\xdd\x20\x87\x0e\x0a\x4c\x9b\xa9\xb8\x9d\x8f\x18\xa4\xea\xc8\x9b\x90\x5a\x73\x8d\xa6\xd4\x6e\x52\x9b\xeb\x57\xac\x7f\xb4\xcf\x98\xa6\x96\xe3\x80\x9c\x9c\xa2\xfc\x92\x86\xed\xbc\xf0\x03\xb0\xf3\x98\x05\xf4\x0e\xbe\x4f\x98\x3b\xf4\x62\x5d\x4b\x95\x13\xb5\x4e\x32\x34\xa1\x0e\x1c\x75\x43\xef\x61\xf2\x7b\x9d\xd7\x02\x9c\xbd\x61\x68\xd8\x78\xed\xc5\x40\x29\x0a\x3e\x51\x65\x7c\x87\x92\xe9\x7d\x2a\xfe\x21\xdd\x66\xde\x28\x98\x69\x05\x20\x1b\x4a\xaf\xb8\xcf\xbf\xcb\x7a\x49\x52\x7d\x44\xef\x12\x1a\x4a\x4f\xf1\x7b\x18\x62\xe3\x33\x04\x57\x89\x54\x78\x1b\x48\x4f\xc8\x2e\x04\x1b\x52\xaa\x8e\xea\x3d\x82\xd9\xa1\xa2\xea\xa5\xd3\x09\x6b\xf8\x4a\x5e\x2f\xd8\x37\xa7\xc7\x04\xda\x43\x8e\xce\xbd\x38\x06\xbf\x8f\x51\x6a\x8c\x44\x94\xa2\xbc\x42\xef\xa7\x59\x2e\x64\x4f\x20\xd1\x42\x3e\x5f\x23\xf3\xf7\x18\xb4\x5d\xf3\x43\xe9\x18\x03\xc2\xbf\x7b\x0d\xc8\x10\x64\xc0\xa8\xc5\x6a\xad\xfd\xa3\xf4\x10\x79\xe0\xac\xdb\x2b\xe8\xcc\x95\x37\x62\xc4\xc4\x8d\x50\x94\x55\xb9\x80\x3b\xdc\xd9\x26\x55\x56\x34\xb9\x7f\x1c\x70\x1c\x18\xbb\xb1\xe3\x70\x3d\xe4\xe5\xb5\x71\x97\xfb\x32\x5a\xf5\x32\xa2\x11\x09\xa9\xe7\x8e\xbb\x20\x3c\xa5\xb9\x2e\x72\xc6\xc3\xf6\x0b\xa9\xc8\xb9\x7f\xce\x52\xba\x2a\xe4\xe0\x52\x4a\x55\xa3\x5a\xb0\x16\x7f\xff\x5e\x57\x61\xf2\x12\x6f\x9f\x20\x06\xbd\xdf\xae\xe0\x8d\xca\xe6\xbf\x95\x25\xb3\x62\xf4\x43\x20\x88\xb3\x6b\x51\x2b\x51\xb0\x8a\xd7\xbc\x14\x40\x73\xe3\x1d\x08\x9f\xbe\x52\xa1\x1f\x1e\x77\x0f\x2c\xed\x31\x3a\x37\x36\x50\x5c\xd1\x07\xdb\x78\x65\xc6\x08\xf7\x5d\x42\xae\xc6\xb5\xa6\x91\x0d\x51\x0e\x01\x23\x3a\xc8\xab\x21\xcb\xe5\xc3\x78\xb7\x14\x3e\x6f\x00\xdb\xef\x07\x6c\xb0\xc5\xf9\xf4\x79\x1e\xf7\x75\x26\x7a\x85\x72\x19\x5d\x7f\xd7\x2c\x39\xea\x52\x2a\xd2\x4f\x1c\x49\x58\x5b\xee\x02\x14\xd7\xa3\xf2\xff\xcd\x4a\xc3\x8f\x6a\x01\x35\x72\xbc\xb8\xa8\x44\x36\x80\xfd\xf1\xcd\xcb\x8b\xc3\xb4\x51\x38\x94\xb0\xf0\x6c\x2e\xe0\xfb\x08\xb5\xe3\x56\x5c\xcd\xb5\xbe\x66\x7b\x2b\x90\xc7\xa2\x64\x29\x23\x67\xe6\x80\x96\xf7\xd8\xf5\x7b\x9f\x49\x05\x14\x51\xe1\x50\x0d\xd4\x5a\xfe\x21\x59\xe8\x05\xcc\x15\x65\x5a\xd3\x31\xbc\xdc\xcd\xb3\x5e\x09\x69\xbd\x65\xd2\xf2\x64\xac\x5f\x9d\xf5\x2b\x13\x72\x17\x02\xdd\xca\x51\x43\x77\xcf\x46\x86\x84\x9c\x11\x4e\x03\x1f\x60\x1c\xbe\x6d\x5b\x8b\x19\x0d\xe4\x34\x21\x5b\x6c\xcd\xc8\x10\xca\xdd\x05\xd2\x77\xfa\xe9\x6e\x6c\x76\xa4\x35\x41\x50\xcf\x4d\x89\x73\x88\xc8\xe7\xf3\x4b\xae\x04\x9b\x6b\xa5\x6b\x42\x1a\x69\xb1\x74\x40\xcc\x60\x12\x2f\xcc\x00\xc9\xdb\xa8\xab\x51\xd9\xb1\x4f\xe3\x9d\x16\x7c\x06\xa4\xd1\x1d\x40\x1c\x10\xae\xba\xc1\x98\x6f\x7c\xb3\x2f\x07\xf3\x84\xa8\xc0\xc7\x66\x50\x8a\xf9\x50\x2f\x25\x54\x43\x8e\xcc\xa1\xeb\xf7\x14\xd3\x6b\x77\x13\x18\x8e\x36\x8f\x33\x54\xe9\x05\x83\x28\x19\x60\x94\xbc\x7b\x32\x94\x7e\x45\x15\xf6\x94\x07\x5a\xca\x77\xee\x29\xf1\xaf\x62\xc0\x0f\x28\xab\x52\xe3\xd5\x5f\xef\x4f\x18\x3b\x6d\xed\xda\x91\x9b\xc5\xf8\xce\x88\xac\x54\xc1\x17\x67\x88\xd8\x81\x2f\x10\xc7\xa1\x88\x77\xb4\xcf\xfa\x5e\x9f\x2d\x20\x04\x92\x07\xda\xea\x10\x50\xa6\xe6\xdc\x44\xfb\xe3\xbb\x4f\x80\x19\x6c\xe3\x01\x82\xcc\xcb\x67\xf4\x27\x3f\xda\x3f\xa5\x0c\x33\xa2\xbe\x91\x99\x38\xcc\x32\xdd\xa8\x5e\x39\xba\xc7\xc2\xbd\x02\xb7\x22\xbf\x48\xda\xc4\x78\x44\x0e\xdf\x62\x4a\x3c\x2f\x24\x47\xa4\xef\xf4\x4e\x2c\x11\x6d\xdb\x81\x78\x46\xa7\x87\xb4\x64\x8c\x15\x7c\xbd\x7c\xdb\x9e\x23\xd4\xb7\xc0\x6b\xf9\x8d\x57\x9d\x70\x9d\x11\xa4\x50\xc6\x52\xf1\xd6\x87\x55\xce\x59\x6e\xae\x5b\xfc\x73\x01\x48\x40\x61\x33\x45\x9f\xd3\x8b\x8e\x39\x3e\x75\x2d\x4c\xf4\x35\x46\xd7\x3a\xb9\xe7\x5e\xfe\xd0\x3c\xff\xef\xe3\xb3\x7e\xf5\x4e\x81\xfa\x19\x21\x66\xe6\xd4\x74\x50\xd5\x63\x64\xcc\x18\x21\xcc\x3d\x79\xc4\x6a\x4e\xac\x96\x1c\x85\x50\x21\x38\xfa\x54\xd8\x5e\x54\x5f\xb6\x0f\x75\x90\x6d\x2e\x01\x8a\xfa\x11\xce\x4b\x29\xb8\x32\x11\x0a\x9c\x80\xa6\xbd\x53\x2f\xf4\x07\x0f\x42\x9a\x6d\xf2\x1e\xec\x79\x97\x74\x7a\x87\xb1\x75\x93\x59\xd6\x58\xe3\x3e\xc7\x87\x7b\x81\xf9\x01\x8f\xaf\xc5\x4c\x1a\x5b\x13\x60\x9e\x6b\xb0\xed\x04\x79\x85\xc2\x2d\xd7\x62\xc1\xbe\xfd\xee\xe4\xef\xff\x78\xf1\xea\xe8\xf0\xc5\x3f\x5e\x1e\x1e\x7d\x7b\x7a\x76\xf2\xf6\xed\xc5\xdf\x2f\x2e\x4f\x5e\xbe\x7d\x7b\x84\x20\xbf\x84\x88\x77\x21\xec\xdb\xb7\xb4\x52\xcd\xdb\xb7\x97\x59\x25\xab\xb7\x6f\xcf\xbd\x0f\x04\x49\x4f\xff\xfb\xf8\x0c\xe4\x27\x02\x33\x85\xa4\x30\x38\x5b\x71\xd0\xa1\xdf\x73\x6e\xda\x14\xd4\xa4\x4a\x74\x0d\xa2\x9c\x75\x8f\xbb\x95\xa8\xe4\xbd\x36\xfb\x1c\x9c\xc1\x9e\xad\xdc\x7b\x69\x5b\xc0\x80\x2b\x61\x6f\x05\x21\x89\xad\xc4\xc1\xe7\xdd\x72\x7f\x4a\x4b\x5f\xc1\x88\xec\x91\x7e\x6e\xa4\xb8\x45\xd8\x57\x39\x53\xbc\x88\x68\xb9\x01\x59\x10\xd1\xe5\x96\xd1\xf6\x41\x49\xaa\x74\x1e\x28\xc8\x3b\x5e\xfb\x25\x8f\x7d\x52\xfc\x89\x7c\x0a\x22\x67\xe7\xa7\xc7\xec\xe9\x04\x95\x9c\xd3\x63\xa4\x77\x59\x09\xf6\xee\x2d\x55\x77\xa0\xe2\xe9\xbb\xa2\x26\xa3\x5d\x00\xeb\x08\xa3\x35\x56\x40\x73\x95\xeb\x92\xcb\x7b\x52\x94\xfd\x4a\xd5\xe5\xb4\x29\x8a\x05\xfb\xb9\xe1\x05\xea\x00\xe7\x3a\x5f\x96\x4c\x3b\x5f\xf9\x8f\xfe\x3a\xf9\x2a\xf4\xe3\xaf\x93\x80\xc0\x00\xc3\xf6\xd7\x89\xb9\xc9\x26\x5f\x11\x46\x21\xa3\x9b\x56\x66\x50\x2f\xd5\xe8\x92\x3e\x8b\xbf\x81\x67\x73\xd0\x77\x3f\x49\x91\x66\x44\xcf\xfc\x4d\xcd\x33\x71\x2e\x6a\x09\x2a\x93\x56\x79\x9f\x92\x4d\xbf\x64\x58\xee\x51\xbb\xa5\x62\x06\x9b\x0d\x43\xa0\x84\xc8\x51\x49\xa4\x5e\x08\x36\x73\x9d\x80\x89\x41\x2d\x10\xa0\x31\xb2\x5a\x70\x4c\xc4\x27\x9c\x0c\x0f\xc5\x3c\x21\xf7\x99\x0f\x0e\x3b\x8d\x5f\x89\x19\x86\x78\x29\x8e\x80\x61\x64\x94\xb2\x08\x9f\x18\x62\x9b\xc6\xea\x8a\xc9\xb2\x14\xb9\x53\x80\x8a\x05\xbb\x91\x1c\x25\x3f\x54\x7a\xe2\x3e\xdd\x53\x9a\x69\xf0\xc6\x37\x4a\x92\x73\x6e\xde\x58\x96\xeb\x5b\xb5\xdf\x12\xf0\xe3\x03\x9c\xb5\x22\x8b\x51\x52\xf6\x0c\xaf\xc4\x2a\x18\xd8\x14\x6d\xc4\xeb\x4b\xd0\xc3\xe4\x36\xd2\x3d\x56\x0d\x1e\x82\x3b\x20\xa8\xa8\x97\x20\x1e\xc1\xbb\x05\x0d\xc0\x90\x93\x50\x96\xf1\x84\x82\x9b\x5e\xca\xcb\x12\xcc\xcb\x43\x29\x16\x37\xe8\x7e\x3d\xd5\x75\x26\xaf\x8a\x05\x9b\xf3\xa2\xa5\xe3\x8e\xc7\x06\xac\xc8\xf8\xf5\x0b\xad\x66\xf1\x41\x8d\xd0\xec\x50\x9f\x2e\xb8\x6a\x2a\x7c\x9e\x3b\xdf\x16\xba\xb9\xc3\x60\xf8\xf2\x89\x7f\xd5\x0d\x80\xa5\xde\x2b\x6c\x64\x75\x21\x70\x7e\xfa\xec\x94\x95\xd5\xe0\xbb\x26\x6e\x7d\x9d\x81\xd8\x44\xcd\xed\xa5\x47\x5e\x71\x2b\xe2\x32\xf4\x1f\x2c\x0d\x6b\x39\x94\xa3\xbb\xdd\x8e\xdf\x40\x2d\xe0\x82\xb9\x53\x8b\x90\xd5\x62\x5c\x03\x5b\xcb\xaa\x10\xec\xab\x6b\xb1\x18\x21\xa6\x2e\x2a\x21\x7f\x8d\x98\xce\x02\x2a\x21\x72\x1f\xe8\x9a\x7d\xe5\xff\xf5\xd7\x4f\x58\xbf\xdb\xc7\x8b\x8a\x2f\xd5\x3b\xf2\x75\x82\x35\x42\x29\xc8\x2e\x8e\x2c\x95\x0f\x59\x8d\xc3\x35\x61\x27\x80\xd6\x80\x1a\x29\xb1\x3d\x15\x45\x72\xb3\x21\xcd\x26\x05\x68\x05\xff\x4b\x54\x3b\x74\xa6\xa9\xc0\x5a\x00\xd2\xf5\x54\xd4\xed\x27\x20\x60\xce\xf4\xc9\x3b\x91\x35\xf6\x53\x02\x46\xe2\x75\x2d\xfa\x73\xe9\x7f\x27\x02\x0a\x38\x8e\x8d\xd3\xc2\x43\xdd\x46\xbb\x3b\xa3\xd4\xbd\xf7\x8f\xed\xb5\x58\x98\xc0\x73\x70\x8d\xad\x13\xc2\x40\x58\xbf\xfe\x20\x3b\x79\x27\x8d\x35\xff\xcb\x13\xf9\x97\x57\x5e\x7e\x63\xd3\x7e\x32\xa1\xf5\x88\xe3\xc2\xfd\x09\x8f\xf9\xd4\x03\xee\x5f\xa0\xf7\xa8\xbf\xf2\x23\x11\xb1\x58\x70\xf7\x4e\xbb\x86\x92\xb7\xb4\x82\x32\xbe\x98\x0e\xa1\x4d\x3b\xc2\x1f\xe3\xfa\xc4\x31\x84\x71\x39\x71\x4a\x5e\x7a\xcc\xd0\x47\x74\x93\x04\x60\x5f\x79\xc3\x0b\xa1\x88\x1d\xaa\xc8\x33\x5e\x63\x88\x9e\x30\xbd\x0d\x11\xcc\x11\x98\xad\x3b\xe3\x48\x92\xb5\xb3\x6c\x28\x94\xc7\x6b\x2b\xb3\xa6\xe0\x35\x73\xfb\x71\xa6\xeb\x7b\x42\x7f\xe3\xd5\x6b\x4e\xda\x25\xba\x96\x3a\x87\x57\x2a\xdf\xbb\x2d\x76\xb9\x46\x48\x7b\x71\x26\x93\x44\xf4\xd2\x78\xa3\xec\xa5\x04\x75\x7a\xea\x65\x53\x10\x14\x31\x5b\x85\x4d\x01\xb3\x66\xe0\xff\xde\x8f\x0e\x8f\xb0\x33\x27\xec\x6f\x01\xe3\x64\xc4\x5a\x9f\x31\x54\xec\xd2\x33\x69\xdb\xd0\x74\xb5\x9b\x7a\xaa\x6b\x71\x23\x6a\xb6\x97\x6b\x84\xfc\xb8\x91\x99\xdd\x9f\xb0\xff\xd7\x69\x8a\xe0\x44\xf6\xea\x24\x6d\xb3\x50\xa5\xdc\x72\x66\x3c\x61\x7b\xf0\xb3\x58\x95\xdc\xf7\x81\x22\x22\xe3\x79\x64\xd9\x30\x3d\x22\xdc\x2b\xa2\xdb\x89\x18\x45\x4d\xb1\xb3\x34\xc2\xc9\xaf\x83\x84\x0c\x32\x51\x1a\xda\xa5\x89\xe7\x36\xc4\x59\xbc\x08\x0d\x0b\xe7\x5f\xe0\xa3\x67\xb5\x98\xc1\xfe\xc3\xdd\xf3\x09\x77\x9f\xd5\x95\x2e\xf4\x6c\x71\x51\xd5\x82\xe7\x47\x5a\x19\x5b\x83\x68\xe8\x43\xb1\x70\x57\x9b\x11\x38\xe7\x5c\xdf\x32\x4e\x09\x6c\x7a\x8a\x24\x15\xba\x99\xcd\x11\x6e\x06\x7e\xc8\x78\x56\x6b\x00\x9c\xc5\xe6\xc8\xe8\x34\x01\xfb\xce\xbb\x0f\x02\x3a\x0d\xb4\x02\x0e\x8f\x5b\xbe\xa0\xcd\xc4\xaf\x64\x2e\x4c\x94\xc1\xed\x3b\x83\xa1\x9f\x3b\xdf\x1f\xa4\xf2\xe1\xd9\xf1\x7d\x79\x4d\x37\xa8\xd0\xde\xf1\x2a\x41\x33\xc2\x51\x6f\xc7\x37\x68\xa4\x30\x6e\xbc\xd4\xa4\xa9\x22\x9d\x92\x1f\x99\x47\x82\x2d\x53\xf2\x77\x17\xd7\xe2\x76\x8d\x5f\xfa\x17\xfd\x4e\xdc\x3f\x15\x6c\x0c\xf6\xe8\x1b\x65\xb8\x95\x66\x0a\x04\xc8\x9f\x50\x1f\x87\x92\x8c\xf5\x78\x5a\xf1\x4a\x2b\x9b\xe2\xd6\x7c\xc9\x7c\xc0\xcf\x4d\x16\x0b\xe5\xff\xb5\x76\x10\xa5\x7f\x42\x89\x48\xa0\x78\x75\x3b\x28\x23\xda\x73\xab\xdb\x38\x34\x46\x2a\x9a\xf2\x4a\xd4\x61\xef\xa3\x33\x40\xd6\x1d\xfc\xc8\xce\xde\x7f\x84\x98\xbd\x30\x3c\x27\xef\x9c\xe6\x61\xd6\x4b\x54\xc2\x2b\x99\xaa\x6e\xa3\x18\x1e\xf3\x09\x9c\x9d\x69\x48\xd8\x83\x09\xeb\xbd\xfd\x64\x5d\x39\xd7\x5e\x7d\x52\x29\xf1\x5a\x3b\xa1\x12\xaf\x6e\x1a\xf9\x9d\xaf\xdf\xa1\x20\x8e\xcb\x21\xc9\x29\x64\x46\xa8\xc0\xa3\x03\x1b\x60\xdb\xe8\x60\x87\x9b\x11\x3c\xd5\x04\xa3\xc8\xdd\x84\xbf\xeb\x4b\x30\xbe\xf6\xfa\xc4\xab\x5f\xbe\x26\x5e\x63\xf7\x4a\xbd\x7e\xef\x07\x6b\xed\x46\xfa\x6e\x36\xbc\xd6\x34\xa8\xdb\x2b\x59\x50\xd7\xad\x69\x8d\x2b\x2b\x31\xad\x5b\x61\xd7\x1a\xd6\xbd\x9e\xdd\x3b\xdb\x13\xaf\x3e\x36\x6e\x7b\x25\x03\xa1\xef\x61\xed\x72\x46\x48\xae\xb4\x3b\x56\xda\xbc\xa7\x6a\xc4\xce\xb4\x75\xff\x89\xcc\xdf\x63\x2d\xcc\x99\xb6\xf0\xc9\x83\x18\x4a\x7c\x85\x01\x07\xd2\x33\x79\x22\x31\x86\x93\x9b\x14\xa2\x75\x27\x9e\x1f\xb0\x15\x86\xc5\xa9\x62\xba\xf6\x23\x16\xac\x0b\x43\x4d\xc4\x61\x05\x42\x20\xbb\xd3\x38\x71\xed\xc4\xe3\xfc\x9e\xe6\xa8\x29\xc8\xfe\xc2\x6f\x00\x2b\xba\x2a\xa0\x40\x20\x6f\x6a\xa4\x91\x72\xba\xa6\x15\x33\x99\xb1\x52\xd4\x33\xc1\x00\xd0\x73\x88\xe9\xeb\x73\xae\xe0\xd5\xf3\x74\x89\x3b\xd3\x63\x2d\xc1\x91\x0d\x2a\xd6\x80\x2a\x00\xb6\x87\xc7\x5a\xc9\xc1\x92\xfa\x3f\xc1\x07\xfd\x7f\x59\xc5\x65\x0d\xb4\x53\x14\x3b\x8e\xbf\xa3\xe8\x4b\xdc\x8c\x6b\x61\xc9\xb7\xc4\x15\x13\x58\xe7\xe5\x5a\xef\x2a\x1e\x23\x76\x0b\x50\xcd\x4e\x26\x06\xf7\xc7\xce\xb5\x58\xec\x8c\x96\x96\xde\xce\xa9\xda\x69\x03\xc3\xc9\x62\x0b\x87\x30\x64\x10\xee\xc0\x77\x3b\x1f\x4f\x57\xe9\x75\xd8\x0e\x41\xda\xd9\xed\xd0\x9a\xeb\xaa\x9d\xbc\xef\xd6\xc0\x74\x64\x4b\xd5\x94\x2f\x93\xf6\xbc\xb6\x64\x49\x49\x6f\x8f\x3f\x83\x49\xff\x45\x84\xb8\x6f\x80\x58\xd6\xc3\x88\x55\x48\x12\x36\x6b\x53\x66\x78\x91\x21\xef\x2e\xce\x2a\x34\xe2\x66\xd3\xdb\x18\x85\xd6\xd7\x4d\xe5\x57\x05\x24\x19\x00\x46\x90\xca\x74\x49\x56\x07\x3e\x1f\x1c\x2b\xb4\xe4\xc6\x14\xc8\xc3\xe5\x1b\x16\x07\xb1\x5d\x26\xe6\x4c\xda\xe1\xe0\x77\x08\xb0\xfe\xf7\x79\x85\x90\xf3\x12\xf7\x8e\xb0\xff\x78\x19\xdc\xe5\x53\x5d\x5f\xc9\x3c\x07\x53\x1a\x1f\x14\x92\xff\x3a\x03\xed\xf6\x44\x62\x7d\x4d\xba\x77\xac\x48\xc9\xef\x9a\x6b\x6a\xd7\x62\x02\x04\xfc\x00\x14\x94\x5c\xbb\x0f\xc3\xa3\xef\x18\xd0\xf0\x86\xe4\xb6\x74\x02\x43\x35\x45\x11\xe0\xb7\xd1\xb0\x40\xaf\x24\x6c\x50\x72\xe7\xcf\xdc\x96\xb5\xe9\x40\xaf\x04\xf0\x5d\x66\x7d\x72\x5d\x49\x5f\xf1\x54\x9d\xeb\x3c\x75\x61\x24\x58\xbe\x54\x0d\xe5\x41\x80\xf7\x22\x34\xe0\x90\x52\xb5\x4e\x11\x6c\xbf\x53\xa6\xc7\xd9\xd2\xf3\x44\xb9\x0b\x5e\x95\x5b\x5d\xca\x6c\x0d\x51\x02\xee\x93\xde\x32\x64\xf7\x25\x36\x14\xb9\xfa\x30\xbd\x60\x56\x0b\xac\x7a\x87\xed\x05\xdb\x8d\x80\xfd\x1b\x25\x6e\x84\x5b\x56\xb9\x34\x04\xbc\xea\xb3\x95\xfe\xb9\xe4\x5d\xf9\xff\x1f\xeb\x33\x6d\xbd\x03\xf0\x9f\xde\x83\x8e\x47\xd9\x3b\x59\x36\x65\x4b\x14\xc0\x72\x39\xf5\xb4\x54\x3e\x49\x2a\x75\x3d\xa4\x1e\x30\xda\x22\x96\xd7\x33\x48\x96\x26\xd7\x83\x3f\xb1\x66\x85\xbe\xe2\x05\x2b\xa5\x72\x8f\xa1\x3c\x88\xe4\xb3\xd0\x13\xfa\xf3\x3d\x0f\x82\x63\x55\xce\xe4\x55\x21\xc8\xb7\xd1\x61\xcc\x8c\x7e\xdc\xb9\x11\xb6\x56\x01\x54\x5c\x73\xae\xd8\x4b\xa9\x8e\xbd\x63\xf4\xb9\xdb\xb2\xef\x78\x59\x15\x02\x6b\xa1\xd9\x97\xe3\x7f\x6b\x25\x18\xe5\xfa\x8c\x98\x9f\x1e\x4a\x01\xb3\x9a\x3d\x1d\x79\x02\x91\x88\x65\x14\xe4\x58\x2a\x41\xbd\x53\xd6\xb0\x2f\x0e\xbe\x38\x78\xfa\xcc\xa9\xa3\x18\xf1\xe3\x86\xb0\xde\x96\x47\xe3\xe9\x84\xfd\xc2\x5c\x0f\x9e\xd2\x7f\xbf\xa0\xff\x7e\xc9\x7e\x61\xbf\x30\x76\xce\xce\x59\xfc\x5f\xf7\x1f\xf6\x0b\x1b\xbb\x41\x88\xba\xfa\x74\x94\x0a\xae\x04\x6a\x9c\xd6\x02\x1c\x23\xd8\x34\x88\x8a\x4c\x97\x02\xba\xfa\xc5\xff\x8a\x21\x9a\xa5\x65\x5a\xd1\x9d\x4f\xf7\xa0\x4b\xfb\xec\x16\xfc\xf3\x25\xbf\x46\xdf\xd4\x61\x66\x1b\x5e\xb8\x87\xef\x7d\x39\x7e\xba\xcf\xb4\x4a\x6f\xbf\x91\x1a\xd8\x78\xa8\x87\x7b\x4f\xf7\x27\x4b\x5d\xfe\x62\x45\x97\x93\xde\x42\x2f\xb8\x5a\x40\xd3\x77\xaf\x77\xbf\xd4\x0f\xd5\xe2\x96\x2f\xc2\x82\xf7\xe7\xe6\x4c\xde\x04\xee\xde\x08\xed\x09\x12\x17\x60\xfd\x4a\x0f\xe0\x87\x8d\x2e\x98\xb4\x13\x76\x6a\x77\x77\x0d\x84\x1d\xd0\x6d\xe0\x49\x86\x8f\x63\x60\x62\x18\x78\x58\x1b\x4f\x3a\x85\x0d\x6b\xc0\x60\x0e\x1a\x21\xba\x17\x4b\x30\x5e\x65\xd8\x25\x03\xa8\x49\xa1\xad\x04\x36\x64\x79\xd7\x77\x37\x6e\xc8\xc1\x7c\xef\xee\xee\x70\x58\x7a\x31\x74\x4d\x2a\x59\xbb\xf3\xdb\x77\x1a\x41\x3a\xa0\x3f\x3d\x19\x1d\x9f\x10\xf5\x33\xec\xed\x4e\xba\x2f\xdf\xee\x40\x1c\x30\xa8\xe2\x04\x15\x40\xea\x0d\xc1\xcc\xfa\x65\x1c\x41\x21\x1e\xaa\xbc\xcd\xbe\x5a\xb3\xff\x40\x48\x0b\xe6\xe7\x0c\x42\x92\xf5\xf2\x9b\x44\x19\x5a\x49\x42\xaf\xdb\x85\x11\xe2\x3d\x3b\xc4\x05\x6c\x20\x8e\xfa\x21\xfd\xba\x73\xec\x22\xee\x03\x50\x98\x42\x3c\xa9\x44\xe6\x4c\x77\x3b\x6d\x6c\x74\x7b\x7b\x26\xcc\x30\xad\xa7\xd3\x15\x29\x75\x6d\xac\x09\x51\x7e\xdd\x22\x81\x12\xac\x78\xfd\x44\x1c\xbd\x4f\x57\x40\xde\xd2\x76\x31\xe9\x70\x3d\xa1\x85\xd4\x3e\x53\x5b\x7c\xee\x0f\x5d\xf9\x11\xec\xf8\xe4\xdc\x04\x2d\x6d\x9d\xc3\xe2\x8b\x51\xa7\xf7\xf4\xf9\x9f\xd6\x39\x43\xbe\x78\x76\xbf\xc3\x81\xfe\x7b\x99\x4c\xf3\xca\xd9\xfd\xd3\x5e\xdb\xcb\x7d\xc8\x85\x58\xb1\x09\xa0\x6e\xaa\x8d\x8b\x4f\xc2\x81\x66\xa4\x6d\x38\x96\x5a\x29\x71\x4b\xf9\xaf\x77\xbf\x54\xa4\x9b\x7b\xe1\x3e\x72\xe7\x0f\x6f\x80\x2c\xb5\xac\x1a\x80\x46\x70\x03\xe9\x35\xed\x2f\xf7\xbe\x64\x63\xf6\x64\xdf\xad\x06\x85\xcb\x0a\x06\x33\x3e\xca\xdc\xd1\x40\xe9\xdc\x76\xee\x94\x27\x37\x32\x66\x84\x04\x9b\x45\xd1\x3d\x84\xee\xa3\x78\x87\xb1\xd9\xac\xd2\xbd\xa9\xb3\x40\xe9\x5c\x1c\x4e\x81\xff\x67\xb1\x2e\xc2\x77\xf7\x4c\x38\x5b\x6a\x33\x3a\x1b\xe6\xfa\x96\xdd\x52\x96\x36\x2c\x39\x2a\x36\x8c\x3b\x72\xe0\xfe\x08\x6b\x0a\xe4\x59\x10\xc9\xa4\x42\x04\x51\x4a\xdb\xc8\xc0\xb4\xbf\x8a\xe1\x8b\xc6\xec\x5b\xad\x74\xfd\x0c\xb5\x23\xd7\xa4\x69\x45\xf1\xdd\x8f\x43\x51\x13\x83\xb9\x24\x07\x82\x71\xea\xcd\x29\x58\x87\xcf\x7e\xad\x95\x60\x43\x42\xc2\x78\x1e\xe4\xd8\xfb\x1a\x47\xd4\xfa\x3b\x32\x93\x03\x42\xfa\x92\x6b\xca\x7d\x0b\xaf\x4b\xec\x64\x93\xce\xfa\xa7\xf2\x54\xbf\xa0\x7d\x8a\x73\x87\x47\xc6\xcd\xdc\xa9\xeb\x9e\x91\x5a\xe1\xd4\xbd\x6f\x5b\x40\x41\xea\xfa\x6b\x7e\x4d\x7b\xcf\x8d\xe4\x25\xe4\x25\x0c\xb9\x60\xe3\x16\xdf\xbb\x5c\x11\xb2\x0c\xf3\x22\x7a\x2f\x4d\x5c\x15\xa1\x7e\x17\x5a\x1d\x31\x5e\x68\x70\xb6\x38\x39\xeb\x3e\x12\x39\xdd\x38\xd5\xde\x27\xb3\xe4\xbf\x98\x43\xc9\x72\x9b\x99\x33\x4a\xd6\x5a\x77\xd1\xfa\x17\xf8\x80\x65\xda\x6b\x49\xe2\x33\x3f\xff\x35\x19\xe5\x4d\x0c\x90\xac\x17\xda\xf2\x46\xf4\xb5\x80\xf3\x0f\x66\x0e\x1d\x55\x13\x18\x17\x32\x67\xa8\x10\x05\x7d\x92\x2d\xe3\xb4\x8f\xca\x22\x19\x72\xc6\x8b\x58\x9b\x72\x1a\x99\xcc\x45\x8d\x07\xec\x95\x48\xca\x96\x42\xbe\x0b\xfb\xa1\xbd\x13\xcb\x95\x20\xaf\x1b\x1b\xfa\x2b\x96\xc9\xef\x5c\x35\xd9\xb5\xb0\xde\x9f\x5d\x43\xa5\x45\xd5\x58\x76\xc5\x0b\xae\x32\xb7\x78\xbb\xf9\x0d\x56\x63\x63\xf8\x4b\x78\x0a\x62\xff\x84\x72\x1a\x6c\x3a\xca\xc6\x94\xca\x58\xd7\x1a\xa6\x69\xb6\x1d\x3c\x2c\x8c\x1e\xb9\x2d\xea\x1b\x58\x76\x26\x40\x53\xf4\x6f\x74\xd1\xd3\x61\x20\x84\xa5\x7a\xbd\xc8\xaf\x4e\xe3\xdc\x39\xc0\xb0\x2c\x3d\x15\x13\x13\x06\xfc\xa8\xa7\xd3\xee\x94\xed\xa4\x45\xa3\xbe\x0e\x69\x67\x84\x6f\xed\x66\x8e\x8a\x78\xc9\xdb\x41\xe4\x2b\xd1\x5b\xa9\x1c\x6a\xdb\xbb\x0d\x87\x3b\xd2\x27\x38\x75\xc8\xb7\x0e\x6a\xeb\xfb\x5b\x3f\xb5\xab\x2c\xde\x4f\xbd\x67\x96\xec\xfb\xfe\x0e\xb7\x65\x95\x3f\x95\xe4\x90\x79\xc3\x0b\x5f\x11\x43\xec\xb8\x84\x8c\xaf\x76\x77\x5b\xcf\x00\x6c\x05\x94\x2c\xad\xed\xe2\xa4\x68\x62\x3b\xb0\x3d\xaf\xfa\x31\x2b\x8a\x02\x37\x6b\x6b\x42\x39\x55\x38\x66\x8c\x93\xd0\x42\xea\xc5\x58\xf9\xc3\x15\x34\x73\xe8\x28\x5b\x04\x4c\xcb\x11\xbb\x6a\x2c\x9b\xc9\x1b\x77\x00\x7c\x90\xd3\x03\x1d\x3b\x73\x51\x54\xac\x16\x79\x93\x11\x96\x03\x9c\x4e\x87\xb1\x85\x06\x99\xeb\x41\x3a\xec\x24\x03\xba\x83\xb4\xa7\x2a\x3d\x7c\xe4\x14\x36\x08\x28\x5a\x72\xca\xc4\x8d\xa8\x17\xac\xd2\xc6\xc0\x36\x04\xb1\x85\x05\x8d\x10\x3b\x0b\xf0\xdb\x60\x4d\x40\xaf\xbc\x02\xbf\x43\x1a\xfc\x0e\x58\xb8\x3a\x11\x45\x9f\xc6\xa1\xf7\xe5\xc1\xd3\x83\xa7\xef\x37\xc6\xce\xe1\x7f\xad\x87\xce\xff\xf7\x74\xba\xc2\xe6\x6c\xfb\x92\xac\x9c\xfb\x38\xf1\xbe\x00\x5f\xdb\x97\xfb\x91\x2f\xef\xcb\x83\x2f\x0e\x9e\xee\xb9\xbe\x7e\xb1\xef\x7a\x1d\x79\xe9\xbe\x88\xbc\x74\xe1\x97\xd4\x23\x61\x12\x3f\xdd\xa9\xa2\xea\xd5\x5b\x5d\xe7\x94\xa5\xeb\x2b\x21\x5d\x8f\x10\xf9\xd0\x9d\x0d\xa5\x97\xe5\xb8\xec\x52\x2f\xc1\xae\x45\x77\xa1\xb4\xec\x0f\xa5\xae\xc5\x1f\xa2\xfb\xef\xf4\xaf\xad\xef\x36\xdb\x30\xf9\xdb\xfa\x29\x92\x7d\x13\x24\x87\x61\x91\x43\x06\xa2\x3e\x39\xcd\xbb\x2f\x3c\x71\x27\x36\x45\xc9\x63\xe8\xd4\x2d\x29\xc9\xf1\x6a\x11\xd7\x44\x5f\x09\xa7\xd2\xa2\x0f\xac\x05\x4e\xbc\x27\x51\xb1\xb1\xba\xe6\x33\x71\x40\x8f\x5d\xa7\x82\x79\x13\xb9\xc8\xdf\x23\xe5\x53\x92\x29\x84\x90\x54\x44\x06\xe5\xcb\xd2\x7d\x0e\x29\x48\x01\x9e\x41\x45\x27\x0c\x64\x02\x7a\x1a\xd5\x8a\x3e\x92\x74\xe4\x4f\x4c\x75\xc9\x6f\xcd\x49\xc1\x8d\x95\xd9\xdf\x0a\x9d\x5d\x5f\x58\x67\xf5\xf4\x56\x2d\x56\xb5\x9a\xcc\xa9\x62\x87\x3f\x5c\xb0\x63\x69\xae\x5b\xbe\x67\xcf\x81\x1f\x17\x51\xf2\x80\x5d\x4d\x78\x1a\xac\xe4\xd9\x1c\x55\x57\xf2\x41\x7b\xfe\xb2\xe1\xf6\xca\xef\xf8\xad\x11\xd8\x7d\xe0\xd3\x75\x5f\x8b\xf5\x45\xf0\xc6\xb0\x34\xf1\x75\x4e\x8f\x37\x90\xbc\x3c\x35\x97\x6b\x03\x75\x2f\xb3\xe0\x79\x3a\x05\xc4\x85\x28\x04\x56\x1b\x21\x26\x79\xca\x6c\x07\x6b\x68\xa1\x1b\x76\xcb\xd1\xae\x06\x09\x3b\x61\x97\xb2\x7a\xc6\x4e\x22\x8e\xa8\x55\x4d\x39\xed\x23\x20\xd2\x92\x41\x0d\x6b\x0e\x93\x91\x9c\x40\xa6\x3a\x27\x76\x82\xaa\x95\x79\xc6\x76\xc4\x3b\xfb\x1f\x3b\x23\xb6\xf3\x6e\x6a\xdc\x7f\x94\x9d\x02\xa7\x1c\x71\x88\x3b\x1d\x4f\x4d\x45\xdd\x9a\x8e\xf8\x83\x65\x30\xa8\xe1\x97\x2c\xbb\x7c\x75\xfc\xea\x19\xe8\xf2\xb9\x76\x56\x5f\x55\x8b\x1b\xa7\x53\x12\xb4\x19\xc9\xc6\x68\x18\x20\x7d\x26\xd3\x65\x55\xeb\x52\x46\x05\xc8\xb0\xe5\xd6\xd9\x01\x6c\x88\x0c\x38\x30\x6c\x61\x31\x0c\xb2\x9e\x42\x73\x7e\x49\x45\x1f\xa8\x0f\x59\x4c\xa7\x53\xa6\x31\x51\x20\x85\x40\x90\x26\xdc\xe4\x96\x0f\xb5\xa2\x00\x57\xaa\x5d\x30\x4e\x33\xa7\xaf\x0e\x72\x71\x73\x60\x72\xfe\x74\x04\x8f\xc1\xd5\xb0\xe8\xf4\x89\x1b\xb6\xf3\x74\x67\xc2\x2e\x64\x29\x0b\x5e\x17\x44\xd5\x4d\x4d\xb4\xf7\x39\x43\xc1\x37\x08\xe6\xef\x93\x1d\xb6\x87\x18\x04\xa0\x6e\x14\xc2\x23\xd2\x05\x04\x56\x48\xd2\xd9\x5f\x4b\xbb\x64\x03\x38\xe3\x59\x6f\x87\x3c\x03\x29\xc9\xf3\x57\xaa\x58\x3b\x73\x3b\x5d\x1c\xbe\x35\x5f\xc0\x57\x37\xe4\xcf\x9c\xea\x9a\x8c\xc0\x70\x8b\x07\x3a\x92\x8a\xd4\x96\x97\x6e\xea\xcd\x83\x39\x7e\xd8\x00\xe0\x7b\x2c\x9c\x22\xc3\x8c\xaf\x6f\x0d\x52\x11\x90\xe3\xfa\xf4\xd8\x0b\xf1\x4a\xd4\x46\x1a\xeb\x44\x54\x9e\xa8\x06\x12\xf5\x85\xbd\xc3\x92\xff\x5b\x2b\x76\xf2\xb7\x0b\xea\xd6\xfe\x03\x1c\xec\x35\x25\x1d\xff\x77\x53\x0b\xa7\x11\xf5\x56\xbf\x42\x4b\x5d\x95\xcb\x7d\xce\x8e\xb9\xe5\xa8\x79\xa1\xa4\xd2\x2d\x38\x18\x72\xec\x43\xd1\x96\x47\x7e\x5b\x53\x79\x66\x9b\xd7\x7e\xdc\x0a\x3a\x5b\x1f\x4d\xdc\xfd\xfc\xcd\xeb\xd3\x0d\xe8\x4e\x19\x1c\xb7\xb3\x97\x3a\x1f\x48\x81\x8a\x1a\xf4\x47\x1e\x80\xb5\x1e\xe1\xe7\xac\x74\x4f\x62\x67\x5a\x89\x11\x7b\x2d\x78\xce\x9c\x74\xa3\x7f\xfe\x50\x4b\x7b\x5f\xfc\xab\xf6\xea\x7d\xf4\xfb\x49\x1c\x64\x20\x7c\x63\x7e\x10\x62\x86\x7e\x00\xe8\x04\xa1\x43\x3a\xc0\x55\xa1\xaf\x18\x09\x8b\x4d\xbe\xfd\x9b\xd7\xa7\x83\xbd\xfc\x9b\xd7\xa7\xfe\xdd\xdd\x3f\xf5\xf4\x61\xbe\xf6\x80\xc6\x43\x6b\x3b\x3c\xef\x28\xfb\xad\x3a\xd7\x12\x29\x75\x0d\x82\x0f\xb7\x06\x26\x43\xd9\x01\x9b\x1a\xf3\x6b\xa9\xd6\xae\x01\x4c\xa5\x0d\x90\x28\x05\x48\xac\x28\x88\x06\x48\x7c\xf9\x33\x56\x36\x85\x05\xd4\x23\x58\x6b\x6e\xf1\x41\xb6\x98\x5f\x75\x8c\x10\x40\x19\x3b\x16\x18\x8e\xc8\x9f\xf9\x3a\x94\xf0\x8b\xd5\x3f\x78\xc9\x15\x9f\xb9\xdb\xe1\x04\x64\x25\xfe\x19\x2d\xf2\x3d\x74\xba\xab\xf0\x15\xbf\xe1\xb2\xe0\x57\xb2\x90\x16\xf4\xb9\xfd\x89\xd7\xe6\xb1\x54\x01\xba\xbc\x31\xe9\x37\xa8\x6a\x1b\xd4\xd6\x18\x1f\x06\xe0\x0d\xd9\x9e\xfb\xee\xe0\xd6\x89\xfa\xfd\x09\xc8\x7d\xb8\x11\xd0\xe8\x3b\xca\xef\xeb\x5f\x53\x7e\x37\xa2\xa7\xc2\x7c\x3f\x5f\x93\xe1\x6d\x59\x77\x72\x2d\xad\xd4\x9d\xe0\x0b\x02\x1d\xfd\xcc\xd5\x27\x64\xd9\xef\xa1\x40\xc1\xde\x59\xf3\xf7\x7d\x55\xa8\x8f\xb3\x71\xf2\xcf\x6f\xe3\x30\xe4\xc2\xa4\x99\x1e\x64\xb8\xda\xe6\xbc\xae\x11\xc0\xa5\xf1\xab\x4e\xf9\x3c\xee\xac\x0b\x92\xe5\x1e\x74\x1a\x7e\xef\xf6\xd3\x3a\xe0\x1a\x78\xf5\x16\xbf\x61\x05\x0f\x33\x2e\xbe\x35\x3f\x2c\x78\x48\xc1\xc7\x6c\xed\x7d\xd6\xf3\x35\x33\x51\xcd\xa7\xfd\x33\xdb\x5d\x33\xcf\x2f\xd2\xa8\xcd\x91\xa8\xe6\xec\xf9\xc5\x0a\x31\x89\x55\x05\xee\xbd\x0d\xc6\x72\x76\x0d\x2b\xe4\x54\x58\xb9\xd6\x20\x6c\x58\x50\x96\x5a\x49\xab\x6b\xb3\x01\x31\xe7\x1f\x3d\x8c\xe2\xe6\x5b\x73\xeb\xf3\xb5\x1f\x14\xf6\x32\xfa\x94\xb3\x4c\x17\x85\xc8\x7c\xae\x3f\x4c\x71\xf8\xd9\x0a\x47\x0c\x65\x20\x98\xc9\xf5\x5f\xc0\x15\x43\x4e\x97\x03\x5c\x76\x07\xaf\x4f\x0e\x8f\x5f\x9e\x4c\xca\xfc\x77\x73\x7d\x3b\xb6\x7a\xdc\x18\x31\x96\xb6\x9f\xbe\xb5\x41\x3c\x91\x01\x3c\xdd\x76\x3e\x94\x93\xdb\xce\xdd\x94\xb5\xa0\xd6\x6f\x4c\x0b\x3b\xef\xe3\xce\xb5\xd6\x76\x19\x78\x7e\xda\x14\x05\xce\xad\xad\x85\x18\xc5\xfe\xed\x7b\xc2\xf2\xb7\xd7\xc3\xd2\x85\x5b\x37\x6f\x32\x44\x1f\x57\x33\x7e\x28\x1b\xa4\xbf\xae\xb0\xae\xa6\xcd\x96\xe6\xa1\x6d\x2f\x9d\x89\x8b\xe4\x73\x0c\x88\xd8\xb9\x9b\x97\x6b\xb1\x60\x00\x1d\x31\xd5\x35\xd0\xb8\xa4\xeb\x53\xd8\x0c\x06\xef\xa0\x31\xa2\x9e\x90\xc2\xf1\x40\x06\xbe\x8f\x2a\x02\x2f\xf2\x5a\x4c\x87\x1c\xf6\xd7\x62\xba\x6a\xd4\xe9\x63\xc0\xba\x0d\xe9\x71\x4e\x5f\x69\xec\x1c\x73\x63\x11\x63\x1b\xc7\x76\xe5\x34\x10\xf6\xc7\x03\x19\xf7\x5e\xa8\x0d\x43\x20\x0b\xf5\x61\x88\x64\x4b\x93\x17\xbb\x2d\x69\x92\xec\xbd\xc3\x20\xfa\xc6\x59\xb1\xe2\xf6\xe0\x56\xd7\xd7\x52\xcd\xc6\xb7\xd2\xce\xc7\x38\x52\xe6\x00\x10\xff\x0f\x7e\x07\xff\xa1\x28\xf2\x61\x9e\x53\xfe\x5b\x63\xc4\xb4\x29\x30\x33\xcd\x4c\x18\xaf\xe4\xf7\xa2\x36\x90\x65\x79\x2d\x55\x3e\x62\x8d\xcc\xbf\x5e\x77\xc6\xd8\x10\xbb\xc5\xed\xfd\x61\x36\x0a\x70\x3a\x49\x43\xcc\x8c\x74\x8c\xd6\x5e\x26\xd5\x3c\xd7\x06\x79\x9f\xdc\x50\x25\x5b\x80\xe7\xa5\x54\x0f\x65\x07\xac\x6b\x1d\x48\x95\xaf\x37\x92\x9d\x00\x04\xb4\x93\x9a\x07\xf4\x19\x85\xb1\x43\xce\x0f\xf7\xde\x13\xa4\xbd\xa7\xec\x9f\x34\xf7\xe7\x83\x04\x4b\xb9\x30\x3f\x17\x63\x7c\xca\xb8\xca\xdb\x71\xdd\x26\xf2\xdc\xe7\xfa\x74\x89\x3c\xc3\x3a\xe4\x3f\x41\x7a\xce\x47\x5d\x71\xec\x01\xeb\xcc\x1f\xd7\x0f\xb6\xc1\xa1\xee\xaf\x19\x7f\x1c\x0d\xad\x3d\x7d\x80\x93\xd0\x78\xa0\x3c\x50\xc0\x50\x2a\x79\x7f\x1a\xe4\xc8\xb7\x24\x58\x1e\xed\x21\xd3\x4a\x11\x3f\xc2\xab\x4a\xa8\x0b\xcb\xb3\xeb\x9e\x51\xdd\xad\x56\xf5\x1b\xd3\xaa\x3e\x52\x22\x90\x5f\xa2\x58\x78\x47\xe9\x6f\x6d\xb2\x37\x6e\xf2\x47\x28\x80\x91\xec\xef\x25\xaf\xfa\x7b\x57\x7d\x4b\x1d\x0d\x2a\x7c\x4c\x0e\x55\x28\x0e\xaa\x74\x05\x60\x63\x54\x82\x0a\xe3\xf8\xe9\x35\x9e\xbe\xfb\x9b\x8e\x98\xe1\x72\x60\xa2\x06\x53\x89\x5a\xba\x4f\xae\xa4\x6d\x65\xa5\x11\x16\xa1\xa0\x08\x22\x59\x2b\x96\x11\xdc\x03\xe8\x23\x11\x88\x41\xa4\xab\x28\xa6\x33\xeb\xab\x46\x03\x6a\xd4\x93\x27\x4f\x9e\x20\x12\xce\x7f\xfe\xe7\x7f\x32\x5d\x03\x17\x69\x26\xcb\xe5\x1b\xe1\xae\x3f\x3d\x7d\x3a\x61\x7f\x3f\x7c\xf9\x02\x2a\x1a\x2a\x6b\x10\xf5\x0d\x5b\x76\x37\x24\x3f\x36\x23\xf6\xbf\x2f\x5e\x9d\xb5\x18\x0d\xe9\xb7\x60\x9a\x87\xd7\x4b\x79\x41\x9e\xfc\xf9\x3f\xfe\x63\xc2\x8e\x65\x0d\x15\x5d\x52\x04\xce\xf9\xe0\x6a\xe1\xb5\x40\xe4\x1e\xc0\x50\xf1\x1a\x97\x0c\xf4\x8e\x54\x9f\x5c\xca\xd9\xdc\x52\x45\xac\x5b\x90\x85\xcc\x2c\x16\x8f\xa1\x58\xf3\x94\xf6\x48\x29\x42\x24\x3d\xa4\xfd\x41\xe7\x46\xac\x90\xd7\x82\x4d\xcd\x37\xb5\x6e\xaa\x16\xe6\x91\x88\x98\xa9\x50\x06\x1b\x6b\xe7\xca\x08\xfb\xc8\xd3\x56\x7b\xb9\x9a\x93\xb5\x0d\x2d\x75\x14\x56\x2a\x6f\x6d\xa1\x0e\x2b\x2e\x43\x31\x0c\x64\x00\x26\x1c\xa0\xc1\xd7\x93\xb3\xa3\x20\x55\x3c\xe6\x48\x55\xeb\x7f\xe1\x12\x80\x5a\xe4\x48\x3c\x43\xad\x30\xcc\x24\x55\x0a\x47\xd1\x2d\x5f\x4f\x4d\xa4\xf3\xfe\x63\x62\xb2\x59\xa6\x03\x2b\xa4\x71\x8f\x00\xb0\x9f\xf7\x3c\xb9\xe5\x32\x76\xab\xd4\xe0\x7a\x69\xd4\xd2\xaf\x09\x58\x85\xc4\x25\x91\x80\x12\xbe\x62\xdb\x06\xc2\x03\x10\x0e\x0e\xdd\xeb\x47\x29\x0c\x44\x92\x6f\x6d\x84\x6d\x68\x68\x20\x8b\xde\x3d\x1b\x08\x2a\xe1\x0d\x4b\x5e\x5f\x3b\xc3\x95\xa4\xcb\x84\x9d\xbb\x4e\x06\x28\x1d\x04\x3b\xbe\xc1\xc0\x66\xc9\x17\xf0\x58\x52\xdc\xe0\x21\xbb\x93\xc9\x2e\x6e\x3f\x5d\x33\x63\x79\x4d\x7b\xc9\x7d\xfe\x79\xa0\xac\xbf\xe4\x95\x41\xd4\x5f\xa7\xa9\x02\x22\xb6\x86\xda\x75\x3b\xf7\x22\x88\xd3\x58\x6f\x91\xd1\xd9\x18\x06\x66\xed\x06\x1e\x38\x2a\x3a\xcd\x3e\xed\xf2\x07\x01\xd9\x5d\xf6\x50\x38\xf0\xea\xc6\x54\xf3\x4e\x64\xe3\x83\xf4\x0d\x62\x85\x2a\xc4\xa3\x52\x30\x56\xb3\xc0\x92\xe0\x8c\x15\xb0\x98\x1e\xf4\xf1\xea\x11\x78\x0d\xa1\x4d\xe0\xd5\x5f\xa7\xc0\xab\x4f\x10\x19\xaf\x64\x0d\xfb\x48\x32\x0e\x26\x1d\x60\x78\x46\x4d\xdb\x29\x00\xae\xbe\x2a\xda\xd6\x48\x6c\xeb\x09\x9a\x15\xe3\x57\x46\x17\x8d\xc5\x9f\xb6\x5f\xc6\xa7\x1f\x34\xea\x31\xc3\xe1\xc8\x0b\xb7\x45\x67\x21\x68\x01\x78\x7c\xf4\x39\x16\xf1\xea\x2d\x36\xfa\x38\x21\x7e\x43\x0e\x88\xde\xe3\x1c\x0c\xb6\x21\xc6\xda\x37\x16\x2a\xee\x6e\xe7\x82\x52\x20\x22\xbd\xcf\x49\x53\x27\x23\x40\xa9\xf4\x2a\x1c\x02\xe7\xe4\x1b\x71\x33\x66\x46\xf6\xf7\x25\x18\xc9\xf6\x8e\x42\x79\xbc\x4f\xbb\x3b\x55\x56\xd4\x53\x9e\x89\xfd\xd8\xc7\x20\xaa\xb9\x28\x45\xed\x06\x8a\xee\xf3\x35\xda\x73\xae\x72\x82\x9d\xca\x44\x0d\x3b\x58\xbc\xb3\xa2\x76\x83\x7a\x74\x71\xca\xf2\x5a\xde\x88\xda\xb0\xbd\xbf\x01\x9c\x20\xc2\x4d\xed\x3f\xc2\x34\x58\x7c\x91\x4d\x78\x40\xe0\xc1\xc3\x94\x7e\x40\x53\x5e\x86\xab\x48\xce\xb4\x53\xe5\xb1\xb1\xdc\xb4\x9a\xd8\x77\x34\x71\x1b\x02\x8e\x50\x90\xbe\xc0\x68\x8d\xb1\x4d\x0f\x66\x0f\xc4\x5b\x99\xc5\x86\xb9\x61\xb5\x98\x39\x6b\xac\x8e\x40\xfb\x10\x26\x65\x63\xc5\x0d\xc3\x17\x94\xb4\xc1\xaa\xf7\xd5\x7e\x4c\xc9\xae\xd4\x37\x32\xf7\xea\x10\x02\xe3\x07\x68\xb8\x8a\x9b\x08\xbc\x80\x1b\xa3\x33\x09\xae\xa6\x68\x6a\xd0\x4a\x05\xa5\x29\xa5\x42\xf3\xe1\xe6\x38\x4c\xa6\x81\x50\x68\x2d\x1e\x56\x36\xc8\x81\xa8\x73\x71\xde\x5c\x15\xd2\xcc\x2f\x06\x0d\x89\xac\x6a\x18\x93\x12\x97\x32\x55\xee\x8c\x8c\x18\xa1\x8c\x24\xda\x7c\x54\xb7\xa4\x06\x96\x05\x37\x0d\xfe\xd7\xf1\xa6\xd0\x50\x0d\x0f\x64\xfc\xfe\xab\xb3\xb6\x1f\x04\x56\x82\x2c\xd0\xb9\x78\xa3\xaa\xe4\xf3\x8c\x17\x85\x21\xfd\x36\x70\x9c\xf8\xb3\x07\x35\x54\x0f\x60\x82\xab\x42\xba\x05\xe3\x7b\x0f\x29\x38\x28\xbc\x02\x21\xcf\xca\x17\x33\x11\xdc\xb0\x56\xfe\x26\x20\xb3\xf6\x3f\x08\x23\x84\x95\x38\xb8\xe8\x36\x48\x85\xb2\x0d\xff\x3c\xbe\xf0\xcf\xc7\xa9\xa9\x68\x29\x46\x39\x7c\x38\x86\x0a\x2d\x0c\x6d\x34\x44\x9b\xeb\x0f\x1a\x7f\x20\xfd\x4a\x9a\xe6\xc6\x42\xc0\xd8\xbf\x43\x4b\x5c\x14\xc3\x78\x77\xbb\x8d\x82\x2a\xe6\x4c\x71\x90\x50\x63\x1a\xbf\x2c\xda\x52\x64\x23\x87\x7d\xbe\x2c\xd7\xda\x33\x1d\x8e\x73\xfc\x70\xd7\xb0\x5c\x67\x8d\x33\xbe\xda\x61\x6f\x13\x2e\xfa\xb1\x15\x7e\x5e\xf4\x49\xb9\xbe\x55\xb7\xbc\xce\x0f\xcf\xd7\xaa\xcd\x4d\x95\xb3\xb6\xad\x58\xf5\xf6\x1f\x33\xf7\x39\xbf\x02\xc0\x5b\xc2\x36\xdc\x46\xfb\x56\x36\x11\x4b\xf3\x55\xee\x36\xab\x9d\x90\xfd\xc0\x68\xde\x7d\x1d\x76\xdb\x00\xe1\x36\x40\x98\x5c\x0f\x29\x40\x78\x8a\x01\xc2\x98\xe9\x37\x11\x2f\xe4\xa1\x75\x23\xfe\x59\xc4\x98\x8e\x5b\x91\x8a\x9a\x78\xb7\x9e\xb7\xa3\xfc\xe3\xe6\x6d\x57\x5d\x64\x30\x78\x99\x0b\x7a\xd9\xe7\x10\x8f\x7a\x00\xf1\x24\x18\xcb\x1e\x56\x21\x5e\xa9\xc0\x6f\xeb\xd5\x10\xa5\x16\x03\xd3\x51\x84\xbb\xd2\x39\x71\x1b\x00\xe9\x06\x12\x08\x8c\x02\x33\xa0\xf2\xe5\xa6\xa0\x9d\x57\x3c\x13\x20\xdf\x82\xfa\x33\x48\x90\xa0\xe7\x02\x60\x03\x2d\x02\x06\x0b\x01\x46\xe7\xbc\xcf\x6a\x60\x83\xad\x08\x77\xb5\x16\x4f\xdf\x96\xba\x88\xa2\xd8\xaa\x5f\x08\x26\x9b\x8b\x92\xc3\x3f\x9f\xfb\x21\x70\xb2\xd1\x19\x0f\x56\x20\x04\x9c\xa8\x4b\xc3\xf4\x74\x94\x64\xba\xee\xdc\x3c\xdd\xe9\x17\x6c\x60\xc3\xc5\x29\x99\xdf\x47\xe7\xbd\x83\x3d\xac\x3b\x60\xe7\x49\x6c\xc7\xed\xa1\x96\x03\xd3\xe3\xde\x87\x0c\x0a\x38\x3f\x70\x84\x1f\xcc\xe0\x0c\x1d\xc4\x5d\x37\x78\x3b\x0a\x51\x83\x47\xa0\xfc\x6d\x83\xb7\x9f\x63\xf0\x36\x3a\x18\xbd\xa0\x5b\x11\xc8\x8d\x43\x02\x3e\x9a\x7b\x25\xbc\x51\x43\x36\x8c\x0f\xe5\xfa\x38\xae\xae\xd3\xd4\xa5\xdd\xc9\x64\x77\xd7\x47\x77\x69\xdd\x37\x76\x3a\xfe\x0b\x13\x2a\xd3\xb9\x27\xf0\x9d\xca\xda\x58\x50\xf7\x5a\x77\x5b\xdc\x97\xd2\x3f\x2b\x4e\x7f\x82\xb6\x87\x98\xea\xde\xb2\xc5\x43\x12\x3e\xff\x08\x4a\x4c\xab\xba\x04\xe0\x43\x1a\xa2\x80\x67\x4d\x3a\x8c\xff\xde\xb0\x42\x96\x92\xf8\xef\xdd\x46\x17\xc6\x1a\xb6\x87\x1f\x4e\xb2\xaa\x19\xd1\x0d\x93\x52\x94\xba\x5e\x8c\xc2\x4d\xee\xcb\xe4\x57\x74\xc7\x3e\xf2\x9d\x34\x75\x2d\x94\x2d\x16\x9f\xb3\x06\xe4\x07\xf1\x81\x28\x40\x61\x8e\xfb\x20\x8e\xb4\x57\xba\xb4\xda\x88\x2f\xb8\xcd\x23\x7e\x81\x80\x46\x6b\x46\x6d\x5c\xdc\x7d\x2a\xd4\x0d\xbb\xe1\xf5\x3d\x91\xe3\x57\x5d\x03\xea\x3c\xb9\xbc\x91\x46\xaf\x1d\x16\x8d\x1a\x8a\x87\xe7\x22\x38\xa1\xdd\x66\xd3\x8d\xad\x1a\x4b\x12\xdd\xef\x40\x8f\x32\x1e\x76\x5e\x47\x39\x7c\xba\x0e\x8b\x52\x7a\x55\xdc\x5a\x51\xab\x67\xec\x7f\xf6\xde\xfe\xf1\x97\xf1\xfe\xd7\x7b\x7b\x3f\x3e\x19\xff\xd7\x4f\x7f\xdc\x7b\x3b\x81\x7f\xfc\x61\xff\xeb\xfd\x5f\xfc\x1f\x7f\xdc\xdf\xdf\xdb\xfb\xf1\xbb\x97\xdf\x5c\x9e\x9f\xfc\x24\xf7\x7f\xf9\x51\x35\xe5\x35\xfe\xf5\xcb\xde\x8f\xe2\xe4\xa7\x0f\x6c\x64\x7f\xff\xeb\xdf\xf7\xee\x3a\x57\x8b\x57\x3d\x45\x21\x5e\xe3\x01\x8f\xe4\xb4\xc5\x41\x96\x5f\x87\x56\x42\x2a\x3b\xd6\xf5\x18\x9b\x7e\x06\x60\xc1\x3d\x1f\xe0\x97\xd7\xd0\xfb\xbf\x55\x03\x5a\xb8\x7d\xaf\xd4\x6f\x78\x83\x43\xe8\xf3\x58\x0e\x50\x66\xec\x5b\x4a\xcb\x64\xac\x28\x2b\x5d\xf3\x7a\xc1\x72\xf2\x66\x2e\x56\x20\x10\x45\x10\x44\xbd\x21\x85\xa1\x1f\xb9\xac\x37\x50\x69\xdc\x1b\x51\x48\xe4\xb2\x29\x07\xc2\x13\x82\xb6\xe2\xc9\xb8\x05\xe4\x7d\x42\xed\xf7\x29\x45\x74\x1b\x05\x34\xae\x78\x76\x8d\x16\x54\x98\x2d\xd4\x1b\xa3\xd2\xfa\x9d\x1d\x4a\x89\x28\x05\x57\xc1\xb1\x0f\xb9\x2d\x3a\x17\x6e\x2a\xfd\xcd\xd8\x76\xe2\x84\xc7\x48\x3b\x25\x10\xb6\x8c\x54\xba\x66\x2f\x41\x01\xda\xe8\xec\xb3\x41\xb0\x42\xe4\xbf\xc5\x0b\xa7\xf5\x0d\x54\x89\xea\x9b\xf3\x09\x44\x56\x83\xbd\x49\xb8\x5e\x53\x20\xd9\x6a\x33\xc4\x12\xcd\x02\x26\xf2\xc4\x6f\x4b\x1f\xbf\x75\xd3\xe9\x5a\x45\xdd\x14\x1c\xd3\x85\xc1\xbc\x15\x99\x01\x0f\x14\xd8\xa6\x30\x1d\x61\x0a\x2f\x23\xa2\xfe\xc6\xb8\x27\x69\x95\xde\xd3\x3e\x08\x69\xb2\xae\x70\x4d\x78\x76\xed\xd4\xa2\x76\xdf\x5c\x84\x37\x6b\xfd\x19\x50\xb2\xec\xcd\x4f\xd3\x80\x91\x42\x4f\x21\x55\x5b\x4f\x21\xb3\x22\xe2\xeb\xf1\x94\x34\x4b\x0b\x55\xc9\x22\x5d\xa9\x9e\x79\x22\xbc\x78\xa3\x28\xa1\x70\xe3\xcb\xee\xd1\x69\x1f\x3d\x75\x8e\xa1\x34\x8d\x41\xf4\x8b\xc1\xb5\x8a\x90\xb9\xd9\x9f\xef\xb5\x4d\x02\x4d\x8e\xd5\x98\x23\x23\x4d\x08\xe5\x81\x16\xcd\xcb\x04\x9f\x75\x70\x19\x3c\x4a\x74\xdc\x66\x8b\x8c\x10\x9e\x64\xc2\xe0\x83\xcd\xe2\xd6\x80\xda\xaa\x71\x60\xaf\x6e\xfd\x12\xec\x4a\x4c\x31\xf1\x09\x7f\x03\x0e\x03\xaa\x08\xcb\x45\x21\xac\x88\x68\xe7\x2b\x24\xca\xae\x45\xa9\x6f\x88\xa6\xf5\x8d\xa1\xb0\xb9\x9c\x3e\x63\x7c\x3f\xa9\x3b\x36\xc4\x83\x2c\x44\x8e\x65\x62\x11\xb7\x60\xdd\x28\x33\x62\x57\xfb\x3e\xad\x95\x58\x30\x6b\xf0\xad\x11\xc9\x17\xb8\xb3\x6a\xe1\x06\x00\xb0\xaa\x6a\x5d\x32\xa3\x78\x65\xe6\xda\x82\xe7\x84\x57\x3c\x93\x76\xc1\x6c\xcd\xb3\x6b\x77\x0b\x84\x53\xe1\x71\x23\x96\xed\x53\x96\x7b\x3c\x7c\x69\xe5\x9a\x9d\xd7\xba\x99\xcd\xa1\x94\x0a\xef\xca\x0a\x6e\xfc\xdb\xaf\xfc\x3d\x99\xf2\x86\xe5\x0b\xc5\x4b\x99\x05\x0a\x91\x5a\xdf\x48\x23\x35\x05\xbc\x7c\xbb\xe7\x81\x8c\x01\x83\x68\x47\x05\x97\x25\xdb\x33\x42\xb0\x13\xbf\x24\xf0\x9b\x0b\x54\x28\xd1\xa1\x58\xa7\xb9\x75\x84\xfb\x48\xf8\x03\xee\x93\x56\x02\x87\x8c\x05\xd4\x09\x5c\xcf\x57\x3e\x74\x3f\x4c\xd7\xea\x3e\xe9\x1a\xf2\xde\x3c\x13\x90\x50\xb9\x8e\x12\x63\x0e\xcf\x4f\x4d\x6c\xe6\x12\x9b\x22\xb6\x04\x5f\x14\x5a\xcd\x62\xfc\xbb\x76\x65\x3a\x59\xaf\x80\x16\xf3\x46\xe6\x0d\x2f\x50\xca\x53\x67\x8e\x2e\x4e\xf1\xe7\x72\x36\xb7\xe3\x5b\x01\x4e\x50\x3c\x0c\xdb\x3d\xe3\x1f\x2a\x97\x12\x6e\xa5\x81\x53\xc1\x92\xb3\x0d\x1d\xca\x40\x3d\xc9\x17\x80\xbf\x4b\x39\x9e\x49\x4e\x8e\x47\xab\xc7\x26\x56\x8d\x38\x74\xef\x30\xf0\x24\x3a\xcd\x08\xbc\xc4\x6e\x88\x61\xa5\x2e\xf7\x0d\x48\x1f\x5b\xea\x8d\xf0\xb1\x6d\x09\x20\x41\x2f\x5e\x9f\x28\x78\x63\xfa\xec\x4d\xbb\x4c\x2e\x45\x59\x15\xdc\x0e\x93\x61\xb2\xf3\x43\xe4\x05\x8f\x62\xc8\x6e\x3b\x72\x95\x8f\x79\xe1\x56\xe4\xf9\xf7\x47\x54\xe0\x86\x1b\x2c\xc9\x62\xbb\x6c\xa9\x4a\x3d\x4b\xb5\x53\x96\x56\x6e\x2d\x80\x54\xbb\x12\x39\x08\x23\x7a\x32\xb8\x2a\x6e\x15\x52\x05\xbb\x3f\xce\xbf\x3f\x1a\x31\x39\x11\x13\xff\x57\xb8\xd5\x4b\x43\xab\x67\x58\xe7\x10\x0a\x69\x60\x3d\x43\x57\x62\x1f\x70\xfc\xdb\x7f\x7e\xe5\x3a\xe9\xbe\xfd\xeb\xf8\xab\x88\xd2\xe8\xaf\xff\x74\xc2\xb5\x76\x37\xa4\x9f\xc6\x69\xe6\x20\xf7\xdc\x5f\xff\x3c\xd7\xf9\x45\x25\xb2\x09\xbe\x96\xf9\x27\x26\x0b\x30\xa1\xac\x53\xb9\xcf\x35\x24\x98\xc9\x1c\x57\x39\x3c\xbb\x16\xff\xf2\x71\x02\x62\x4d\x25\x41\x92\x71\x2b\x14\x1c\x00\xbe\xde\x58\x69\x8b\x3f\x47\xbe\x55\xe8\xff\xde\x34\x66\x40\xb5\x5a\xc3\x36\x47\x51\x72\xa8\x98\x78\x27\x0d\xc0\xcf\xe0\xbb\xc2\x70\x70\xca\x61\xf7\x67\x9a\x6b\xd6\x8d\x70\x40\x1b\x02\x0a\x56\xd7\xb7\x3f\x28\x6d\xff\x10\xa6\xdf\xe7\x27\x22\x9f\x39\xe3\x37\x5a\xe6\xac\x01\xfa\x2c\xb7\x03\x15\x38\xb8\x5b\x06\xc3\xab\x05\x2b\xa5\xb1\xfc\x5a\x4c\xd8\x85\x3b\xb3\xe2\x44\x03\x1c\x3d\xc5\x80\x8c\x46\xe4\xac\x51\x56\x16\xf0\x6d\xdb\x8e\xeb\x72\x7c\x96\x9d\x4e\x99\x69\x32\xe0\xe8\xad\xc5\xd8\x9f\x8e\x74\xd7\x92\x8c\x69\xdf\x65\x14\x26\x7b\xce\xd1\x8c\xaa\x72\xf8\x29\x32\xfe\x2a\x5a\x5e\x4b\xe9\xd5\xae\x9f\x5a\x65\xed\x89\x08\x83\x09\x2c\xdb\xee\x10\x2c\x7c\x1e\x10\x5a\x74\x14\x37\x50\x22\x13\xc6\xf0\x7a\x81\xa4\xa8\x32\x70\x37\x52\xe6\x2b\x9c\xd4\x25\x57\x0d\x34\x50\x0b\xa4\xd8\x6d\x32\x18\x1d\xce\xae\x6a\x7d\x2d\x54\xa8\x24\x70\xb3\x98\xe6\x55\xb7\xc9\xa3\xc8\x3e\xcd\xb2\x39\x57\x33\xd1\x16\x93\x97\x3c\x87\xb1\xff\x2e\x68\x5a\xfe\x7d\xdc\x08\xf0\xa9\x53\x58\xa4\x85\xa1\xb8\x72\xe7\x53\x88\x7e\xbc\x55\x01\x0e\x77\xd4\x86\x27\xdc\x2b\xc9\x62\x2d\x99\xc8\x86\xf1\x87\xf7\xf7\x84\x8f\x41\xa1\xd8\x60\x0e\x77\x29\x2c\xcf\xb9\xe5\x83\xe5\x71\xbf\xe4\x81\xfc\x93\x72\x3b\x60\x39\x44\x39\x1f\x74\xc6\x7a\x55\x52\x57\x32\x86\x17\x00\x69\x30\xf7\xb3\x0f\xf0\x54\xd6\xad\x6b\x8a\x3d\x62\x7a\x36\xe8\x6a\xbc\x28\xf4\x2d\x01\xd6\xf9\xd6\x50\x64\x89\x9c\xe5\x0d\xa8\x7d\xad\x48\xeb\x13\x1b\x1f\x24\x74\xe2\x26\x7a\xb0\x51\xbe\x6c\x53\x00\xb2\x34\x45\x7b\xa5\x82\x86\x67\x9d\x50\x56\x22\x95\xbe\xc7\x83\xa0\xc1\x6f\x14\x6e\xd5\xce\x34\xc0\x3c\xcd\x84\x35\x6d\x72\x25\x9e\x26\x4e\x44\xd2\x59\x4e\xbe\x04\x38\x6a\x68\x6a\xc8\x1c\x5f\xad\x29\xe2\xc4\x19\x4d\xa7\x85\x3b\xbf\x36\x3e\x33\xc3\xc5\x90\x90\x05\xf7\xa5\xce\xfb\x07\xa3\x3a\x74\xae\x6d\xc3\x6d\xd1\x09\x16\x20\x19\xf0\xf5\xe0\x0d\x10\x9a\x37\x09\x5a\x06\x1e\x01\x73\x7e\xb3\xbe\x57\xb5\xd5\x4c\xc7\x81\xb3\x0d\x1e\x37\x86\xc7\x8d\x9f\xf6\xf5\x5f\xf7\x4f\x5e\xf4\x57\xcf\x24\xc6\xb4\x43\x03\x04\x2c\x9c\x68\xbd\x18\x24\x9e\xd0\x01\x53\x0a\xed\xd2\xf9\x4b\x09\x1a\x21\x29\x86\xca\x6a\x85\x74\x52\xf3\x19\xfb\x43\xa2\x71\x91\x66\x1b\xac\x61\x2c\x66\xda\xf3\xe6\xf1\x84\x26\xde\xa3\x7a\xa5\xb7\xef\x77\x1a\x03\x55\x6f\xb5\xd5\xe8\x8b\xa6\x82\xfa\xed\x54\x65\xa0\xe3\x0f\xa5\xaa\x6e\x31\xd7\xba\x28\x3c\x85\x3b\x5a\xc8\x9d\x14\x27\xa0\x0f\xc2\xa0\xc9\x28\xb8\x21\x82\xbe\xaf\xc4\x6d\x50\xec\xb8\x41\xd4\x52\x1f\xb2\x07\x57\x89\xcf\x3b\x5b\xd5\xde\x04\x38\xf0\xe1\xfb\x43\xb5\xc0\xce\x1f\x47\x83\x8b\x0e\x06\x36\x73\x8f\x72\x36\x80\xe2\x57\x85\xd3\x42\xa2\x09\x08\xcf\xe9\x1c\x69\x56\x47\x77\xbd\x16\x53\xf2\x0c\xc4\x1f\x7d\xd8\x6f\xf1\x3c\x4c\x7e\x38\x69\xb3\x24\x49\x4d\x8e\x90\x32\x69\xd4\x93\x5b\xd2\xac\xa2\x4e\x6b\x09\x60\xcf\xaa\x1e\xf4\x4c\x3d\x18\x30\xf9\x60\xb8\xf4\x03\xc0\x86\x91\x6a\xfd\x9c\xe2\xb6\x99\x35\x18\xc3\xbb\xd7\x70\x59\x0c\x90\xc8\x09\x59\x5c\x43\x84\x83\x13\xb1\x73\x78\x7e\x0a\x0d\x7b\x0b\x73\x06\x7f\x78\xcd\x23\xc4\x35\xaf\x84\x93\x0b\x2d\xa2\x15\xac\xc8\xf8\xb7\x2b\xd2\xdc\xda\xcd\xf9\x1d\xd0\x37\x51\xb8\xc8\x97\x2f\xbb\x83\xeb\xf0\xfc\x14\x9f\x38\x01\x06\x5f\xae\x16\xa4\x13\xda\xb9\xac\xf3\x71\xc5\x6b\xbb\x40\x27\xcb\x28\x79\x5a\xa8\xe1\x1c\x60\x38\x06\x8d\x64\xf7\x61\x7c\x8b\xaf\x64\x8e\x60\xf8\x7c\x9c\x88\x02\x7d\x77\xce\xcc\x43\x1b\x91\xbe\x15\xa5\xfe\x4a\x46\x24\x66\xfc\xf1\x3e\x96\x47\x31\x22\x89\x8c\xfe\x58\xfa\x83\x13\xff\x26\xcd\xbe\x41\x75\x00\x74\x7d\xf2\x8b\xe9\xb8\xcc\x2d\xe8\x96\xe0\xa4\x70\x2d\x8d\x98\x9c\xba\x83\x58\xab\x31\x15\xd7\x07\x27\x3e\xe9\xa7\x3e\x4d\x15\x1d\x0e\xb0\x75\xa3\xa7\xc4\x3f\x0d\xbb\x9c\xed\x29\xad\x70\xe7\xe3\xbd\xfb\x98\x9f\x7b\x87\x07\x1a\x6e\x09\xa7\x79\xec\x97\x88\x24\x8d\x57\x13\xa4\xca\xdd\xb4\xc3\xb1\x07\x1e\x0b\xd3\x64\x99\x10\xc1\xc7\x15\xf3\xda\xb7\x92\x89\xba\x5c\x72\x9b\xcd\x85\x61\x46\x03\x3e\xaa\xb1\xbc\x28\x5a\xdf\x12\x0d\x94\x06\x4d\xc7\xfb\xf9\x23\x05\x28\xa9\x46\x27\x37\x5b\x55\x70\xf2\xe5\x4c\x1b\x95\x61\x06\x98\xb4\x8b\x98\x19\x35\x51\xf6\xc0\xa0\x36\xe8\x72\x92\x53\xf4\x2e\x47\x86\x71\x18\x4c\x10\xad\x0b\x14\xa6\x73\xcf\x3d\x0e\xb6\x1a\x81\x00\x3a\x39\x7a\xc5\xb3\xeb\x5b\x5e\xe7\x06\x0a\xed\xb9\x95\xc8\xc5\x38\x42\xad\x23\x56\x22\xd4\xee\x6e\x1c\xa8\x95\xaa\xab\xdf\xc4\x1d\xd9\x8b\x7a\xbd\xa4\xf7\xec\x07\x7d\xc7\x88\xc0\xd2\xd7\x76\x8c\xf1\xc6\xea\x92\x5b\x99\x81\x2b\x4a\x4e\xa3\xe8\x42\x19\xd8\x2d\x42\x90\x18\x4f\x01\x38\x57\xe8\xc5\x69\x1d\xac\xd6\x80\x56\x74\x3c\xea\xab\x7f\xcd\xd5\xfd\x8a\x8e\x26\x7a\xd0\x25\xc6\xab\x21\x0a\x56\x0b\xc1\x64\xe9\x14\x58\x0e\x04\xda\xd3\x50\xf3\xef\x43\x2e\xef\x1b\x14\xa7\xa5\xff\x00\x71\xae\xe8\x2e\xf4\xa7\x15\x85\xbe\x35\xcc\xde\xea\x60\xf4\xb7\xd1\x04\x2a\x6e\x1f\x75\x54\x3a\xfa\x8d\xdb\x6a\x6e\x58\xa2\x7d\x34\x72\x6b\xe7\x56\x14\x85\xfb\xef\xfb\x76\x93\x99\xac\xea\x91\x9c\x29\x2c\x7f\x96\xc6\x7b\x60\x28\x9f\x7d\x2f\xaf\x75\x55\x91\x2f\xb5\xdc\xef\xf6\x08\x42\x97\xf5\x8d\x30\x10\xbd\xf7\x19\xf2\x6e\x18\x66\x42\x89\x9a\x5b\x08\x84\x10\xa8\x23\x08\x94\xee\x23\x92\x69\x5c\xd9\xb9\x78\xb8\x30\x10\xf4\xfe\xe1\xa1\x6f\xc1\x63\xe1\x46\xca\x2f\x18\x33\x41\xe0\x9c\x7d\xf6\xc6\xe0\x0b\x85\x3d\x1b\xb2\xf9\x3f\xc8\x66\x40\xb7\x2f\x99\x0d\x13\xb6\x77\x58\x54\xf3\xa8\xd5\x58\x4b\x0f\xd5\x52\x69\x4f\x93\xe7\x1d\xd5\xda\x98\x33\xff\x93\xfb\x3c\x7a\xab\xc1\xbf\xaf\x99\xad\x06\xbf\xd5\xe0\xd7\xb8\xb6\x1a\x7c\xf7\xda\x6a\xf0\xdd\x2b\x08\xf8\x8f\x32\x2c\x41\xbd\x49\xcf\x92\xf7\x0d\x10\x3b\xd3\x96\x42\xac\xa0\xe2\xf1\x3b\x3d\x45\x1c\x0e\x92\x5b\xbe\x98\x28\x61\x09\x51\xc7\x3b\x05\x5f\xfb\xf6\xbe\xa9\x9d\xb2\x43\xba\x71\xb4\x59\xfd\xce\xf7\x58\x3e\xd1\x53\xac\xc6\xf3\xb7\x8d\xf8\xc2\xe7\xbb\x86\xe2\x9d\xee\x7b\xa8\xaf\x8b\x1b\xc8\xc4\x84\x5d\x08\x4f\x61\x92\x3c\x7c\x19\x35\x25\x17\x96\xcb\xc2\xb4\x07\xee\xe5\x1d\x07\xf8\xfa\x07\xea\x43\x5a\x67\xa1\x26\x62\x58\x2b\xb1\x2d\x72\x8a\x12\xcf\xe2\x8c\xce\xf6\x86\xbb\x42\x0e\xa7\x53\xf6\x5a\x64\xfa\x46\xd4\x38\xb6\x27\xef\x2a\xae\x9c\x25\xf4\x9c\xcb\xc2\x8d\xac\x1f\xe1\xd6\xb9\x0a\x74\x5e\x69\x88\x2f\xf2\x68\x87\x65\x4d\xd3\x58\x52\xa7\x08\x70\xc7\xdd\x4f\x89\x44\x55\x2d\x6e\xa4\x6e\x8c\xcf\x3b\x6d\x2c\x1e\x4a\xc6\x92\xed\x31\x97\xb3\xc0\xba\x19\xd2\xc1\x6a\x91\xe9\x3a\x6f\x97\xaf\xb1\xdc\x36\x26\x2d\x65\xcf\x30\xa6\x36\x5c\x38\x25\x8c\xe3\x03\xd2\xd2\x86\xd4\x67\x60\xc0\x06\x68\xa7\x9b\x03\x04\xd6\x8a\x01\x4c\x8d\x48\x02\xc6\xd2\x0f\xab\x84\xa4\xc2\x09\x75\x8b\x68\xe2\xbf\xc2\x1f\x8f\xda\xb5\xd3\x26\x67\x48\xd3\x66\x17\xb7\x99\x0e\x12\xec\x13\xee\x04\x4a\x64\x88\x07\x71\x02\xcb\xd7\xab\xf5\xc7\x68\xf9\xbf\xa6\x67\x1d\x16\xce\x1a\x41\xf1\x14\x89\x94\x15\x59\x14\xb2\x2c\x1b\xeb\xf6\xc1\x84\x9d\x62\xdd\x2d\xd8\x34\x64\x2a\x4f\xdb\x9a\x4f\x51\x9b\xb5\x73\x1f\xe2\x6b\xb8\xe0\x1b\x1b\x2e\x00\xc7\xba\x53\xfd\x3a\x9e\xb4\x18\x4d\x4f\x2b\x81\x39\x4c\x6e\x7e\x7d\x8e\x53\x72\xf7\xda\x90\x59\xe9\x35\xe0\xd6\xc2\x6b\x38\x33\x08\xaf\x41\xac\x18\xbc\x86\xdc\xfb\x78\x0d\xa5\x17\xe2\xb5\xac\x1d\x82\x64\x07\xcf\x5c\xa2\x25\x26\xab\xa3\xd2\xf9\x64\x85\x04\x08\x39\x77\x3a\xa7\x84\xba\xd4\x7f\x88\x65\xf6\xa7\xae\xf9\x6b\x9f\xbc\x1a\x4e\x21\x7e\xc3\x65\x01\x15\x13\x52\x19\x99\x0b\x64\x05\x22\xc9\x31\xd8\xfb\x0e\xaa\x90\x76\x92\xdd\x9d\xf0\x1c\x97\xbc\x1a\x5f\x8b\xc5\x40\xd3\x3d\xd8\x4a\x5c\xee\x28\x8e\x44\xc9\xab\xde\xad\x63\x31\xc9\xe0\x67\xd2\xee\x0b\x2c\x52\xc1\x0f\xaf\x48\x35\xf2\x75\x33\x6d\xcd\x4e\xa6\xcb\xaa\xb1\x22\x52\xa1\x48\xd9\xb9\xb7\x5e\x91\x40\x35\x1e\x94\x5c\xf1\x99\x18\x87\x66\xc7\xed\x71\xb1\x36\x75\x78\x7c\x0d\x2c\x06\x87\xc5\x14\x8c\xaf\x47\x57\x4e\x93\x5e\x83\x15\xf4\xb2\x8f\x52\xd4\xcb\x86\x2f\xec\x65\x1f\xbf\xb8\x97\x05\xb0\x85\xe1\xf7\xfd\x6b\x0f\xfe\xd0\xd9\xf9\x64\x2a\xbd\x6f\xe7\x27\x28\xc3\xa1\x1d\x69\x98\x2e\xa5\xb5\xc2\x27\x55\x87\x9d\x0c\x49\x30\x71\xf1\x3b\xc9\x1c\x88\x5e\x61\xe6\xb4\x78\x17\xe8\x55\x23\x83\x1e\xbc\x6d\xb7\xd2\xa0\x09\xae\x98\x2c\x2b\x24\x7b\x00\xd9\x31\xf6\x9a\x32\x45\x87\x42\x4f\x32\xc8\xde\x64\xe2\x1d\xc4\xc8\xf0\x61\x5b\x31\xb5\x15\x53\x5b\x31\xf5\x31\xc4\x14\x62\x02\xf4\x87\xd8\x48\xc4\x93\x6f\x94\x40\x28\xf9\x95\x28\xd8\xcf\x8d\xa8\x17\x4c\xdf\x88\xa8\x32\x0b\x88\x6a\x9d\x22\x8b\xb5\x4d\x14\x29\xef\xab\xc9\x3e\x50\xb7\x04\xd8\x0b\x27\xef\xaa\x5a\x20\x76\xd8\xe0\x87\x42\xf7\x01\x29\x04\x28\xce\x42\x98\x99\xd8\xa1\x85\x69\xd5\x89\x8b\x8b\xd7\x82\x1d\x9e\x1d\x0f\xe9\x79\x7c\xe8\x46\xff\xe1\x7b\x86\x08\x87\x32\x7c\x03\xe7\x5e\xc8\x8c\x0e\xc1\x65\x76\x2d\x16\x23\x2a\x40\x20\x96\x72\x7f\x33\xd6\xf2\xa4\x54\x89\xfd\x20\xb6\xd3\xeb\x11\xf8\x0b\xfa\x51\xe3\xa5\x6d\xf9\xc1\x7d\xa0\xfe\x87\xde\x14\x7a\xf1\x75\x17\x9d\x1e\xae\x56\x60\xdf\xf2\x38\x03\x61\x81\x02\xb6\x02\x48\xd8\x07\xeb\x16\x60\xc0\xf2\x84\xd3\xf8\x91\x06\x2b\x6c\xc1\xa4\x92\xfd\x5a\x2c\x76\x0d\xa1\xd0\x69\x65\xe6\xb2\xf2\xfc\xea\x20\x27\x69\x57\xb2\xef\xa1\x64\xc4\x37\x81\x12\xf1\x54\x8d\xd8\x99\xb6\xee\x3f\x27\x50\x03\x07\xfb\xf8\x58\x0b\x73\xa6\x2d\x7c\xf2\xa0\x87\x1b\x5f\xed\x23\x0d\x36\xa5\xe5\x90\xdb\x1a\xaa\x3d\x01\xf5\xc5\x57\x46\xc1\xa0\x52\xb2\x78\x98\x18\x69\xd8\xa9\x62\xba\xf6\xa3\x6a\x3d\x65\xac\xa1\x26\x7c\x60\x3f\x4a\xb6\x5a\xd1\x06\x4d\x86\xae\x93\xb9\x78\x4f\x73\x21\x9d\x4a\xfa\x6f\x20\x96\x08\xa9\x71\xa1\x9c\x0b\x68\x4b\xb9\x15\x33\x99\xb1\x52\xd4\x33\x40\x2c\xcc\xe6\x43\x4f\xf1\x50\xe7\x22\x5e\x03\x9e\x8e\x78\x0d\xba\x0e\x41\x45\x79\x01\x85\x7a\x1f\x47\xfd\xc1\xb6\xf1\xb8\x2e\x79\xe5\x96\xe0\xff\x71\xa7\x32\xac\x82\xff\x0b\xb4\xc8\x66\xc2\x0e\x99\x91\x6a\x56\x88\xe4\x3b\x0a\xc1\xc5\xcd\xb8\x16\x9c\x79\xfb\x73\x23\x6f\x78\x21\xb0\xb0\x96\xab\x40\x5a\xa8\xa7\x4b\x4a\xd7\x88\xb8\x91\x9d\x5c\x0e\x4e\xdd\x9d\x6b\xb1\xd8\x19\x2d\x2d\xdb\x9d\x53\xb5\xd3\x82\x9f\x26\x0b\x35\x28\x17\x10\x8f\xd9\x81\xef\x76\x3e\x8d\x9e\xf6\x08\xcc\xd8\xc1\xd6\x24\x45\x49\x8f\x0a\x8e\x71\xf9\x61\x23\xda\xdd\xd6\x57\x51\xb2\x5d\x44\xf7\xb4\xd9\x0c\x54\xb4\x3d\x78\xe8\x17\x40\x43\x86\x2a\xa1\x1b\x60\xfc\xb1\x5f\x7d\x88\x40\xfc\xb5\x82\x44\x07\xe0\x8b\x3d\xa8\x4c\x82\x45\xd6\x66\x8c\xdf\x31\xe2\xdf\x43\x10\x5f\x4f\xd9\xf3\x96\x6a\x0d\xc2\xa5\x4e\xad\x22\x98\x19\xa5\x2d\x93\x2a\x2b\x1a\x8a\xdf\xc3\x4f\x31\xe8\xfb\xb0\x86\x77\xf0\x85\xdd\x36\xeb\x57\xb4\xcf\x71\x5f\xc2\x0e\xe8\x66\xfc\x42\x02\x78\xc8\x71\xc5\xd1\xde\xe4\x68\x4d\xd7\xaa\x92\x4e\x29\x02\xb3\x54\xbf\x7c\x2e\xaf\x6a\xc1\x8e\xe6\x5c\x29\x51\x44\xf8\x8b\xe4\x2b\xe5\xd6\xf2\x6c\x8e\x69\x26\x9c\xb9\x7d\x5c\x08\xbb\x6b\xd8\x5c\x43\x4c\x31\x9b\x4b\x15\x10\xc9\x54\xc0\x21\x6d\xa1\x18\x36\x40\xaa\xd9\xd7\x40\x1a\x90\x8f\x71\x97\x08\x19\x69\xdd\xc5\x4c\x88\x29\x4f\x63\x4b\xed\xd3\xbd\xa7\xe5\xb8\xa2\x3d\x0f\x23\x8f\xe7\x32\x90\x06\xc2\xbd\xef\x67\x7a\x2c\x83\xbf\x5b\xaa\xa9\xa8\x6b\x9c\xa1\x2b\x41\x3f\x60\x72\xca\x1a\x15\x25\x8f\x23\xfd\xdb\x5c\xdf\xb2\x5c\xb3\x5b\x01\xd9\x42\x4e\x81\x80\xf4\x73\xe3\x55\x8f\xa8\xa7\x50\xa9\x92\xe9\xb2\xaa\x75\x29\x43\xfa\x36\x2d\x8f\x8d\x41\x0d\x16\xcd\xda\x6c\x0d\xe9\x2c\x16\x8d\x4a\x69\xd2\x9f\x1f\x31\xcb\xeb\x99\xb0\xee\x19\x4c\x35\xe5\x95\xe8\x89\xa8\xb8\x69\x3e\x9f\x41\xf9\xf3\x76\x03\x81\x5e\x32\x6a\xbf\xc2\x8c\xc7\x5e\xfb\x5f\x41\xa2\x01\x54\xc1\x4c\x75\x9d\xf9\xb4\x46\xcf\xc9\x87\x04\x4e\x6e\x15\x7e\x4f\x07\x67\xa3\xac\xe9\xc9\xa7\xd4\x87\x59\x0f\x97\xc2\x0f\x3f\x9c\x0d\x43\x88\xb4\xdb\xb6\x77\xd7\xaa\xbb\xd5\x75\x91\xdf\xca\xdc\x27\x75\xed\xb9\x9b\xf7\xfb\x8d\xc0\x06\xf9\x91\x7a\xef\xf4\xdb\x5b\x99\x0f\x34\xf8\xd0\x54\x3a\xe8\xbe\xa4\xcf\x0d\x3a\x83\x51\x97\xb9\x50\xd6\x09\xcb\xda\xb0\x3d\xf8\xc5\x3e\x3b\x91\x08\x5e\x05\xbf\x87\x54\xb4\xf2\x4a\xaa\x16\x18\xad\x9d\x54\x77\x5c\x3a\xb9\xe1\xcd\x7b\x23\x2c\xc2\x0e\x41\x95\xb9\xb6\x73\x66\x64\xd9\x14\x96\x2b\xa1\x1b\x53\x2c\x7a\x2e\xed\xc7\x3a\xb1\xd3\x42\xbc\xc3\x1d\xde\x5f\xe9\x09\x4d\xa5\xca\x0f\x14\x57\xb5\x58\x83\x4b\xda\x4f\x5b\x9b\x98\x1f\x04\x4d\x28\x60\x67\x89\x77\x22\x23\x58\x85\xaa\x68\x66\x72\x2d\x1c\x9d\x2d\x83\xf8\x5a\xbf\xfe\x30\x06\xf1\x96\x28\xb9\x31\xa2\xc5\xfc\x25\x90\xbb\x4d\xe9\x25\xc3\x13\x7e\x6f\x56\xbf\xbc\x5c\x4d\xf6\x9d\x8b\x4a\xa8\x1c\x48\x87\x9e\xb7\xfb\x0f\x3b\xbf\xb1\xb1\x27\xb2\x9f\x61\xce\x0a\xcf\x1c\x94\x9c\xd2\x51\x82\xe4\x5c\x17\xb9\x61\xe2\x9d\xad\xb9\x3b\x0e\x4a\x27\xf8\xc3\x6f\xa6\x8c\xab\xbe\xa2\xfd\x73\xa1\xac\x65\x9f\x48\x03\xcd\x3f\x53\x0d\xd4\x0c\xca\x65\xbf\x6b\x62\x06\xfb\x76\xf4\x92\x8f\x07\xa6\xb5\xc7\x03\x94\xa4\x83\x49\x21\x11\x56\xd0\xcf\xb7\x25\x55\xcb\xd8\x3e\x6b\xd2\xd0\x9b\x15\xa4\xd4\x9d\x5e\x6d\x70\xb3\x6e\x39\xe9\x1f\x17\x27\xfd\x14\x10\x52\xfb\xd3\x86\x50\x3b\x1d\x9f\x1d\x7d\x48\x6a\xeb\x87\xf8\xe8\x68\x47\x45\x67\xb2\x9b\x37\xdf\x10\x21\x8d\x31\xe3\x66\xa3\x2d\x8b\x6c\x94\x5a\x4f\x9a\x6f\x9a\xb1\x9b\x5b\x6e\x84\xed\xe3\x49\x4e\x15\xcc\xb6\x3d\x27\x72\xe2\x95\x4f\x5f\x21\xef\x3d\x20\x8f\x78\xd4\x50\x36\xfe\x2b\xe9\xa2\x2a\xb9\xd3\x69\xa1\x7e\xdc\x3d\xad\x88\x08\x99\x65\xd8\x46\xee\x66\x3b\xe3\x76\xed\x8a\xdd\xde\xa7\x31\xf5\xf6\xcd\x9b\xd3\xe3\x21\x87\xd0\xb5\xe7\xb5\x55\xf8\x77\x3a\x8c\x93\x50\x4c\xd6\x28\xf9\x73\x13\x1b\xda\x80\x76\x1e\x06\x8e\xee\xdf\xc4\xe8\xcc\x32\xd1\x86\x09\x8e\xa5\xb9\xee\x4f\x0d\xb4\xd4\x64\xba\xdd\xbf\x39\x3a\x61\xf4\xe9\x07\x79\xe7\xef\xe3\x9e\xef\x4b\xec\x31\xcb\x44\x1b\xb8\xcb\xa5\xb9\xde\x00\xad\x50\x5f\x1b\xb8\xca\xcf\xd6\x2b\xc9\x79\x98\x91\x86\xae\x85\xe7\x99\x07\x22\x4a\x8c\x85\x6e\xd8\x2d\x21\x6f\x93\x85\x78\x29\xab\x67\xec\x44\x99\xa6\x16\x6d\x86\x56\xb7\x29\xa7\x6f\x7d\xb0\xbd\x08\xe0\xe6\xe6\xd9\x60\x51\x89\xa1\x57\xea\xe7\x12\xe6\xa8\x78\x6d\xc1\x90\x1b\x66\x21\x85\xe6\xbc\x9c\x8e\x3e\x50\x1f\xb2\x92\x4e\xa7\xbe\x36\x63\x44\x30\xbc\x81\x72\xc8\xdf\xe4\xd6\x4e\x84\xcb\x1f\xaf\x96\xe7\x81\x0b\x83\x1d\xe4\xe2\xe6\xc0\xe4\xfc\xe9\x08\x1e\xe3\xab\xdc\xd3\x3e\x71\xc3\x76\x9e\xee\x4c\xd8\x85\x2c\x65\xc1\xeb\x62\x91\x50\x03\xb7\xf7\xb9\x63\xd7\x37\x08\xd9\x2c\x4f\x76\xd8\x9e\xae\xa1\xe5\x8c\x2b\x56\x08\x0f\x02\x46\xbb\x7a\x81\x76\xc7\xfe\xc3\x10\x91\xec\xc1\x44\x8a\x50\x5a\x0e\xb4\xd6\x72\xaf\x53\xd1\x79\x9f\xf0\x3c\x1c\xb7\x07\x9e\x54\xee\x14\x9c\xb0\x37\x74\x7c\x91\x5e\x80\x8b\x01\x36\xb3\xbf\xe3\x61\x4d\xd6\xc3\xf3\x87\xac\xe5\xd9\x58\x0e\xdd\x3d\xb4\x81\x5e\xd7\x7b\x32\x93\xf6\xb5\xa8\xf4\x00\x3a\x1c\x36\xd4\x89\x2f\x48\xeb\x3e\xd0\x46\x02\xb1\x23\xb7\x8c\xa3\x48\xca\x9a\x82\x3b\xa3\x0e\xa3\x0b\x13\x76\x7c\x72\xfe\xfa\xe4\xe8\xf0\xf2\xe4\xf8\x19\xfb\x86\x5a\x92\xb1\x1d\x30\x61\x97\x31\x55\x4b\x54\xf0\x46\x7c\x18\xe1\x59\x23\x12\xb1\x5c\xb5\x94\x73\x00\x5d\xcf\x15\x3b\x55\xd2\xb6\x64\xbb\x58\x17\x50\x68\x45\x99\xfe\xee\xd7\x14\xdd\x98\x49\x4b\x60\xc8\xd8\x98\xfb\x3a\x6d\x8d\xaa\xc2\x9d\xb2\xd9\x16\x75\x3f\x42\xe5\xaf\x9d\x9e\x4d\x18\xaa\x9e\x45\x72\x18\x1b\x2b\x30\x88\x7a\x84\x2c\x8c\x16\xb7\x9f\xe3\x61\x1b\x08\xd3\x3d\x17\x85\xae\x13\x3e\xf3\xc9\x64\x77\xc2\xdc\x31\xbe\x3b\xd9\xf5\x2a\x5f\xb1\x44\xba\x1f\x1a\x8d\x29\x7f\xd2\x05\x3f\x61\xec\x95\xaf\xaa\x04\x1c\xd4\xd5\xfc\xfd\x08\x59\x1e\xb1\xb5\x77\xb6\x8d\x47\x9b\x69\xae\xe2\x87\x12\x47\xd0\x4c\xde\x10\x9a\xe5\xc6\x62\x0a\x6d\x57\x07\x99\xc6\xf8\xcd\xc9\x52\x7e\xfd\x62\x73\xef\x86\x12\x67\xa0\x37\x23\xf1\x45\xef\x95\xe9\xb2\x44\x52\x9b\x79\xc0\xd9\x6b\xa1\xf2\x82\x74\xdc\x88\x95\x8f\x54\x3e\xd3\xb5\x36\x76\xe7\x64\xf0\x4d\x75\xac\xfa\xf0\x31\x55\x3f\xab\xd6\x9c\xba\x3f\x03\x30\x71\x49\x19\x0f\x41\x46\xc7\xec\x41\x78\xf8\xc1\xeb\x93\xc3\xe3\x97\x27\x93\x32\x7f\x84\x42\x5a\xa8\xbc\xd2\x52\x59\xb3\xae\x85\xcf\xed\x7c\x03\xe2\x3d\x74\x7b\x18\x1d\x2e\x34\xe7\xf7\x8f\xff\x20\x22\x06\x23\x70\xb7\x68\x75\x59\x5d\xe9\x42\xcf\x56\x53\x07\xdf\x63\xd9\xfc\x0e\x49\x25\xc6\x7c\xec\xd6\xe3\xe6\x8c\x5d\x3b\x1f\xca\xce\xb5\x73\x3f\x90\xed\x68\x05\xbb\xd1\xce\x3f\x8f\x01\xfb\x84\x66\xc4\xd2\x28\xa2\x3b\x07\xc4\x9b\xe7\x6d\x6b\x89\xd0\x2a\x51\x97\x12\xab\x50\x3e\xd4\xbe\xd8\xcc\xe0\xaf\x6b\x5a\x38\x49\x7e\xbe\xe6\x72\x4d\x47\xdd\xb7\x94\x1e\x20\x55\x2d\xc6\x81\x69\x66\x2a\x0b\x01\xa8\xea\x41\x43\x8a\xcf\x13\xef\x09\xf6\x7e\x63\xbc\xab\x58\x74\x3d\xc2\x11\xb0\x9b\x77\xc4\x23\xfe\x74\x51\x2c\x5a\x36\x41\xf2\x86\xf1\x19\x32\xc8\xd4\x14\x90\xab\x6a\x79\x23\x0b\x31\x03\xa6\x50\xa9\x66\x11\xf2\x60\x8c\x55\x48\x30\x95\x69\x70\xea\xa5\xfb\x2b\x22\xad\x86\x95\x75\xf6\xea\x12\x48\x67\x21\xa5\xa2\xb7\xc1\xe9\x1e\x08\x7b\x7e\x3c\x1e\x83\xeb\x6f\xef\x5f\xce\xf2\xc9\x8b\x7d\xf6\x83\xa0\xe7\x68\x60\xc5\xad\x65\x66\xd9\xed\x5c\x07\x8a\x52\xe8\x6b\x3b\xb2\xb0\xa0\x31\x8d\x8f\xee\x3a\x70\x77\x3a\x8d\x1a\x8f\xf2\xe4\x7e\x29\x80\xf7\xab\xcd\x33\x78\x8c\x56\xd2\x86\x0e\xd0\x81\xa5\xbd\x0f\x36\xad\xda\x23\x21\x7d\xc0\x9f\x0b\x9c\x99\x45\x59\x48\x75\xdd\xd2\x2a\x4d\x35\x21\xb3\x0a\xe6\xbe\xf0\xbb\xa6\x16\xbc\xb8\xfb\xc4\x58\x67\x8d\x6e\xec\xb4\xb0\x83\xc5\x23\x20\x5e\xe0\xa4\xc5\xb7\x5e\x78\x51\x02\x58\x2c\xea\x77\x76\x1e\xf5\x88\x49\x93\x19\xd9\x5f\xbc\x43\x33\x89\x6c\x57\xec\xf4\xe2\xe8\xe2\xf4\x93\x46\xfd\xee\x3a\x5c\xa1\x77\x8f\xda\x7a\x90\x3f\xaf\x97\x55\x35\x66\x45\xb3\xee\x2f\xd1\xf5\x72\xae\x6b\xcb\x8b\x0d\x08\xce\x6c\xce\xab\xc3\xc6\xce\x8f\xa5\x01\x80\xe1\x61\xd4\xbf\xa5\x56\xa3\x7a\x45\xa4\x6e\xf6\x1c\x75\xd2\x2f\x5f\xba\xef\xe8\xdb\xc3\x73\xc6\x1b\xb7\x1e\x2d\xb1\x72\x6e\x2c\x59\xce\xbf\xc5\x05\xd6\x40\x0f\x3a\x32\xd4\xe6\xaf\x8c\x8b\xbf\xeb\x21\x8d\xca\xa7\xab\x7a\xdb\xc6\xa3\xe1\xe4\x42\xa9\xff\x99\xc4\xa0\xa5\x92\x56\x72\xab\xeb\xc1\x62\x83\x49\x8b\xc1\x61\xd8\x18\xab\x4b\xda\x45\xa7\xfe\x0e\x48\xc8\x02\xfd\x6d\xe9\x47\xad\x37\x11\xac\x4f\x18\xf3\x53\xe5\x6c\x45\x9e\x89\x4e\x99\xcd\x08\xd8\x32\xb1\x6d\x19\xee\xf9\x8a\x9c\xe8\xc0\x5c\x54\xfc\xf5\x59\xc2\x27\xdf\x52\x53\x7a\x12\x60\xf2\x62\x66\x5a\x29\x91\xf5\xe1\x56\xee\x3f\x25\x3f\x0f\x23\xda\xe4\xcf\xaa\x13\x4f\xc0\x21\xfa\xef\x86\x17\x38\xb4\x67\x9b\x74\xbe\xa7\x53\x3a\xcc\x1b\xa7\xab\x84\x5e\xbe\x5d\x12\x67\xc1\xdb\xd6\x18\xe4\x65\xc2\x11\xb1\x35\x57\xc6\xad\x93\xd4\x9f\xb1\x4b\x09\x10\xbb\x6c\xcf\x66\xd5\xfe\xc6\x46\x6a\xa8\x72\xd8\xa2\x51\xb1\xb2\x8a\xef\x7e\x89\x4b\xe3\x45\x28\x87\xed\xf7\x9a\x1b\x4f\x72\x80\xdd\x3e\x8c\xdf\x96\xda\x0a\xeb\x28\x1e\x2f\x54\x10\xd9\x0b\x69\x2c\xd6\xd1\xe0\xcd\x00\xe3\x82\xf5\x84\xce\x16\x38\x67\xba\x66\xb2\xfa\x07\xcf\xf3\xfa\x19\xea\x11\x64\xab\xc2\xbf\x4d\x60\x0a\xe2\x2a\x64\xdb\xec\xd9\x45\x45\x1c\x71\x97\x47\xe7\x70\xa7\x61\x7f\xf9\xf3\x13\xb0\x0b\xbe\xfc\xe2\xcf\x4f\x7a\x2e\xc4\xc7\x5a\x55\xc8\x86\xf6\x89\x0e\x9e\x59\xf1\x99\x54\x91\x24\xd5\x22\x40\x27\xe3\xb4\xdd\x0b\x2c\xce\x70\xe7\x24\x09\x4d\xdc\x08\x6e\x55\x86\xd3\x7b\x48\x9d\x78\x5b\x75\xf1\x1b\xaa\xba\x60\xa1\x1a\x1f\x05\xeb\x20\x0b\x39\x6e\x10\x60\x75\x96\x05\x38\xca\xee\xf3\xc7\x22\xbb\xd7\x1c\xdd\x75\x57\x72\xba\x82\xe3\x14\x3f\x2a\xc4\x8d\xca\x53\x8f\xcf\x2e\xfe\xf1\xe2\xf0\x6f\x27\x2f\xe0\x5d\x29\x2b\xd0\x2d\x4f\xb2\x84\xd6\xc9\x59\xff\xf0\xe5\xbe\xbe\x73\x6b\xdd\x21\x1d\x22\xc1\x40\x75\x52\x0b\x14\x3b\x7b\x7e\x71\xdf\xac\x82\xbe\xe6\xac\x9a\xf6\x18\xbd\xc7\x16\xd7\x70\x3f\x05\xbe\xd6\x4d\x54\xce\x0f\x1c\x14\x89\x50\xf1\x13\x3f\x8a\x5b\x43\xf8\x8e\xbd\x5d\x1d\x6b\xae\x0d\xf6\xe0\x74\xbd\xf7\xc7\xbf\xdd\x88\xe1\x28\x0e\x1e\xf9\xfe\xa4\xa3\xdd\x4f\x87\xac\x87\x82\x75\xd8\xc5\xb6\xbc\xfa\xe8\x44\x18\x9e\x1d\xb5\x3b\x55\xdd\x79\x2a\x4c\x20\x28\xfa\x0c\x56\x6b\xb5\x8a\x6e\xba\xff\xe9\xb0\xb2\x59\xfc\xe7\x85\x67\x0b\x8c\xb2\x0a\x92\xba\xee\xbb\x18\xe5\x7d\x46\x26\x2f\x23\x62\xcd\x21\x91\x1f\xdb\x8f\xf0\x13\x24\xc9\x7b\x84\x07\x0c\x74\x7c\x43\xe5\x65\xe1\xd9\xc3\x6c\xc7\xd0\x5c\x17\x69\xe5\x5e\xab\x84\x71\xe3\x15\x39\xca\x35\x8f\x21\x59\x1e\xe4\x12\x62\x0f\xee\x1c\x0a\xc7\xd0\x0f\x6b\xba\x1b\x36\xe9\x6a\xa8\xe6\xda\x6a\x35\x70\x0d\xed\xaa\x46\x53\xc1\x76\x0e\x77\x1c\x61\xa5\x7b\x21\xea\x48\xde\x62\x05\x51\x08\xab\x3b\xcb\xc3\x1f\xdd\x5a\xf9\x00\x7b\x1a\x5e\x7f\x7c\x92\xa8\xca\x4f\x8f\x37\x20\x84\x3e\x37\xb0\xa3\xfb\x86\x09\x37\x96\x28\x9b\x0f\x54\xb9\xef\x1a\xf2\x63\x7e\x7a\x4c\xe6\x82\x2f\xcb\x37\xb4\xad\xd8\xdd\xfb\x6a\x23\xaa\x94\xae\xed\xad\xae\x87\x82\x8f\x4b\x9b\xeb\x64\x61\xd2\x77\x4b\x60\x1c\x9f\xa7\x14\xc1\xb7\x7c\xf4\x92\xe4\x02\x24\x49\x87\xb9\xfb\x2e\x89\xf2\x31\x04\xca\xe3\x11\x24\x1f\x47\x71\xf9\xb8\x48\x5c\x1b\x33\x7f\xfd\xf6\x18\x64\xb0\x7c\x63\xe4\x06\x75\x0b\xa5\x95\xbb\x1c\xdc\xcd\x91\xe4\xd9\x88\x9c\xad\xb5\x93\x43\xeb\x89\x93\x54\xc4\xfa\x96\x30\x38\x88\xac\x8e\x45\xe1\x66\x56\xab\x98\x0f\x92\xc0\xba\x46\x0c\x39\x13\x4b\x5e\x19\x24\xa5\xc8\xf5\xad\xba\xe5\x75\xce\x0e\xcf\x4f\x3f\xbd\x5c\xed\x5d\x09\x8a\xfb\xa1\x0f\xb7\x40\x5a\x0b\xda\xb6\x07\x19\xf8\x90\x24\xe4\xfe\xb8\x92\x16\x69\x9b\x31\x19\xdf\xc6\xde\x28\x77\x4e\x85\x4c\x16\x27\xe9\x9c\x54\xa3\x96\x22\xb5\x4a\x31\x9d\x59\x5e\x20\x05\x08\xbb\x12\xf6\x56\x08\xc5\x9e\x3c\x79\x82\x01\x8a\x27\xff\xf9\x9f\xff\xc9\x80\x94\x33\x17\x99\x2c\x97\x6f\x84\xbb\xfe\xf4\xf4\xe9\x84\xfd\xfd\xf0\xe5\x0b\xc6\x33\xb0\xe5\x10\xf9\x16\x5b\x86\xf9\x8c\x7f\x6c\x46\xec\x7f\x5f\xbc\x3a\x6b\x09\xe5\xd3\x6f\x61\xb9\x84\xd7\x9b\xb0\xe3\x28\xf7\x3e\x0e\x1e\x70\x3b\x87\xd1\x50\xda\x32\x3e\x9d\xe2\x82\xf3\xac\xf6\x24\x4c\x3c\xf6\x9c\x9c\xcd\xe1\x75\xa5\x82\xa5\x56\x40\x51\x80\x74\x5d\x84\x80\x8d\xc7\x71\xc4\x1a\x07\x68\x2b\x1c\x22\xd0\x95\x11\x2b\xe4\xb5\x60\x53\xf3\x4d\xad\x9b\xaa\x25\x4e\xa9\x85\x71\x06\x58\xc6\x95\x6b\x1d\x1b\x6b\x67\xc6\x88\x9e\xd8\x98\x9b\xce\x9c\xa0\x7d\x3a\x4c\x08\x99\xf6\xbc\xa7\x10\x23\x6e\x40\x5f\xa3\x85\x22\xc3\xcd\xc2\x63\xcd\x64\x48\xde\xf6\x3c\xbc\x0f\x2e\x2a\x42\x3f\x6c\x25\x23\x2f\xb4\x9a\xc5\x6b\xb0\xd5\x3e\x7c\x32\xe5\xa2\x12\xeb\x0e\xc6\x40\x84\x3a\xc3\xd0\xd3\xa1\x70\x7f\xc9\xab\x7e\x4c\x20\x69\x8e\xae\x6f\x33\xc1\xa1\xe4\x57\xba\xb1\x3e\x67\x8f\xbe\x07\xf8\x36\xab\xfd\xd0\xf7\xea\xc2\x60\x2c\x45\xc3\xf1\xfe\x0d\x44\xba\x95\xe6\xcc\xc1\xa9\x9d\xaa\xac\x23\x26\x78\x36\x67\xd7\x62\x31\xc6\x13\xa0\xe2\x80\x1e\x01\xa3\x7d\xec\xc6\x18\x61\x72\xd3\x74\x86\x4c\xe4\xce\x9a\xa4\xa9\xf0\x09\x96\x91\x7e\xe0\xd1\x27\xbc\xc1\x65\x48\x2f\x27\x2a\x2b\x15\x79\x28\x3d\x77\x65\xa6\x95\x25\x5e\xcc\xc0\x5d\x05\x09\xa3\x1d\x40\x02\x27\x61\x44\xee\x7e\x66\xde\xf7\xe4\x36\xab\xd4\x9d\x28\xff\x1f\x7b\x5f\xf7\xdc\x38\x6e\x24\xfe\x9e\xbf\x02\xe5\xdf\xaf\xca\xf6\xc4\xd2\xec\x5e\x36\xa9\xdc\xbe\xa4\x3c\xf6\x6c\xce\xb5\xf3\xe1\xb3\x66\x27\x0f\xbb\xb9\x0a\x44\xc2\x12\xcf\x24\xc0\x00\xa0\x3c\xda\x6c\xfe\xf7\x2b\x74\x03\x20\x28\xf1\x4b\x22\x3d\x96\x67\xcc\x97\x19\x53\x00\x08\x34\x1a\x8d\xfe\x6e\xcb\x7f\x14\x7c\xab\x37\xe4\x73\x07\x9f\x5e\xc5\x6c\x66\x24\xea\x6a\x22\x06\x9e\xa9\xcb\x24\x82\x88\x23\xd3\xdc\xb6\x75\x50\xf2\x80\xa8\x24\x4c\x50\x4c\x17\x16\x34\xe0\x27\x6c\xbe\xcd\x94\x22\x09\xac\x30\xa3\xf2\x8e\xb9\x44\xc3\x34\x9d\x92\x6b\x33\x49\x9f\x6d\x1e\x4b\x09\xae\x30\x40\xc4\xd0\x98\x30\x13\x84\xf9\xc8\xf1\x74\x7a\x8c\x57\x65\x4d\x5e\x88\xc1\x58\x33\x66\x15\xb9\xd1\xaa\xc7\x55\x50\xf9\x2d\xcd\x15\x56\xd3\x33\xa2\x05\x54\xac\x14\x90\xb7\x45\x2f\x1d\x33\x41\x07\xa6\x10\x0f\x9f\x91\xcb\x98\x8d\x5b\x09\x75\xbc\x3a\xa8\x03\x6c\xed\xd5\x67\xec\xfa\xa7\x23\x56\x3f\x6d\xaa\x7d\x6a\x71\xc8\x52\x92\xb1\x2a\x32\x8e\x5e\x72\x33\x1b\xa1\xb0\x99\x7b\xaa\xa6\x23\xe0\x6f\x2b\xb9\xa4\x7b\xc9\x22\x36\x95\x7a\xca\x9e\x94\xf0\x71\x75\x0b\x24\xb5\x3e\xd7\x4d\x28\x97\xb9\x1b\xc6\x40\xe0\xf1\xa5\x8e\xa1\x55\xf6\xdc\xf3\x10\x65\xea\x87\x8b\x25\x9b\xcf\x10\x27\x9a\xcd\xa7\xaa\xc8\x08\xd2\x4a\xf8\xab\x36\x8c\x3e\x86\xad\xd2\x02\xaa\x75\x96\xc4\x61\x4a\xde\xda\xab\x18\x91\x9c\xce\x95\x48\x0b\xed\x33\x51\xd4\xdc\xd3\x30\xa8\xab\xed\x89\x49\x9b\x5c\xb3\xe0\xd6\x06\x7e\x05\xaf\xb2\x71\x2e\x70\x7c\x46\x24\x3e\x43\x1d\x64\xf1\xf9\xca\xdc\x64\xf1\x19\x71\x17\x1c\xbb\x38\xf2\x4e\xb8\x61\x7d\xf6\x4e\x17\x11\x59\xe1\x6e\xc1\x47\x56\x2b\x64\x9d\x1d\xa3\x8a\x31\x94\xfb\x66\xc0\x2e\x9f\xe1\x5a\x5d\xbb\x2e\xab\x60\x3c\xbf\xbe\x1a\x51\x2a\x0d\x46\x6d\x90\x4b\xc3\x16\xcf\x92\x69\x9f\xa7\x02\xe0\x2b\x94\x4c\x0d\x4b\xef\x14\x48\x97\x25\x44\xad\x49\xcf\x10\xe5\xaf\x40\xb4\xd9\x5a\xf8\x0f\xe6\x32\x0a\x83\xb9\xaa\x15\x3a\x50\x19\x5c\x5e\x5b\x41\x55\x0f\xe7\xc3\x03\x24\xee\xcb\x17\x83\x0e\x54\x78\x01\xe8\x0f\x88\xd8\xd9\x7c\xaa\xb7\xe8\x8d\x03\x22\x99\xb1\xd4\x5c\x7a\x64\x43\x65\x93\x8b\xf8\x7b\xac\xf9\x4d\x39\x17\x1a\xf0\x46\x9d\x91\x14\xea\x91\x9f\xa1\x2a\xc6\x70\xa0\x81\xf7\x97\x0c\x8c\xa6\x23\xf3\x9c\xa3\x21\x0f\x19\x1d\x81\x08\x20\x11\xc0\xee\x7a\x1c\x4c\x22\x0f\x80\x4d\xe6\x29\x59\x95\x31\xcb\xf2\x57\xf0\xca\x8e\xef\x90\x48\x45\x4b\x96\x51\xac\x47\xe2\x00\x64\xe8\xf5\xbd\x4c\xb4\x66\x98\x75\x9c\xc9\x4c\x11\x71\x7b\x56\xb1\x1b\x1f\xad\xbe\x3d\x1a\x8b\x9f\x25\x0f\x21\x50\x13\x77\x42\xf7\x4d\x03\xd6\xf4\x54\xed\x06\x15\xe1\xc2\x9c\x4e\x90\xa6\x53\x28\x90\xc4\x37\x14\x96\x86\x89\x58\x21\xfc\x0f\x1a\x74\x0f\xa7\x8b\xd8\x57\x07\x71\xe6\x19\xd3\x67\x1d\xc4\xb3\x0e\x62\x8c\x11\x1f\x4c\x07\x11\x5c\xdc\x8e\x98\xd6\xe8\x23\xc2\x40\x3c\xa7\x94\x28\x53\x59\x04\x69\xa2\x0d\xca\x3b\x75\x84\x90\x55\x5b\xc1\xf1\x74\x7a\x7c\xec\x94\x14\xf6\x7c\x14\xfa\x76\xf2\x67\xc2\x78\x24\x62\x44\x2a\x33\xbe\x54\x1a\x98\xda\x52\x2a\x0f\xe7\x92\xb9\x6f\x85\xf6\x06\x18\x7b\x5c\x94\x18\x91\x42\x39\x97\x94\x1f\x1e\x94\x05\x2b\x19\x2f\x9f\x06\xcc\x02\xd0\x67\x4b\xb4\x1c\x58\xe9\x22\x93\x26\x59\x62\xf3\x13\x1a\x72\xc1\x94\x56\xe4\x04\x5f\x4e\xa3\xbc\x38\xb3\x0d\xa6\x19\xcb\x84\x5c\x9f\xf9\x46\xe6\xc7\x4a\x2f\xdb\xe2\x14\xb8\xb6\xa8\x90\x92\x71\x9d\xae\xbf\x5e\xfe\xcd\x81\xf8\x80\xd9\x37\x8f\x15\x43\xe2\x3e\xea\x9e\x2a\x5a\x96\x45\x04\x40\x7b\xe7\xa1\x0d\xf7\x90\x8d\xc0\x38\x2b\x95\x3f\xe6\x2d\xe3\x2b\xb2\xa2\x72\xef\x08\x8c\xba\xe7\x41\x38\xb6\x38\x59\x25\x4a\xec\x1d\xc3\x56\x3b\x64\x08\xbc\x99\xbd\x94\x51\x47\x2c\x0a\x9d\x17\xda\xde\x2e\xee\x6c\xbb\x94\x7d\xfe\x4c\x6f\x30\xbe\xdf\x1e\x8d\x38\xb9\x9c\x6a\xcd\x24\xff\x9e\xfc\xcf\xc9\x2f\xbf\xff\x6d\x72\xfa\x97\x93\x93\x9f\xbf\x99\xfc\xe7\xdf\x7f\x7f\xf2\xcb\x14\xfe\xf3\xe2\xf4\x2f\xa7\xbf\xb9\x3f\x7e\x7f\x7a\x7a\x72\xf2\xf3\x8f\x6f\xff\xfa\xe1\xfa\xf5\xdf\x93\xd3\xdf\x7e\xe6\x45\x76\x87\x7f\xfd\x76\xf2\x33\x7b\xfd\xf7\x9e\x83\x9c\x9e\xfe\xe5\xff\x8f\xb8\x08\xca\xd7\xef\x47\x23\xc1\xf8\x4c\x1e\x84\x8d\xa8\x8e\x3d\x32\xea\x12\xf2\x69\x52\x6a\xb4\x27\x09\xd7\x13\x21\x27\xf8\x91\xef\x89\x96\xc5\x58\xa4\xab\xbc\xfe\x1e\x8e\xc6\x94\x4c\x4c\x99\x01\xd3\x09\x36\x07\x48\x44\xd0\x31\x75\x44\xcd\xb0\xad\x63\x5b\xaf\x14\xb6\x3f\x3e\xeb\x83\xfb\x3c\x0f\xe8\xa9\x64\xf3\xd9\x7c\xe5\x6e\x4a\x33\x5b\x4d\xf9\xd9\x47\x69\xeb\x79\xf6\x51\xda\x7e\x9e\x7d\x94\x76\x7c\x9e\x7d\x94\xdc\xf3\xec\xa3\xf4\xac\x1f\x1c\xfe\x7c\xe5\xfa\xc1\x67\x1f\xa5\x5d\x9f\x67\x1f\xa5\xbd\x9f\x27\xe4\xa3\x84\x4c\x7e\x9d\xa7\x92\x65\xf3\x4b\x37\xa5\x83\xf5\x52\x52\x06\x1f\x22\x76\x1e\x45\xa2\xe0\xfa\x83\xb8\x63\x03\x0d\xb9\x1b\x32\xe9\xd6\xe8\x90\x12\xb1\x41\x46\xdd\x6e\x7c\x90\x02\xeb\x58\xfc\xe8\x08\xfc\xe3\x78\x9c\x23\x2d\xe2\xc4\xc8\xa8\x23\x1f\x16\x37\x6c\x98\x16\x9b\xc7\x2c\x2e\x7f\xb0\x24\x4d\x9b\xfd\x9e\x92\x73\x22\x59\x94\xe4\x89\xb9\x00\x20\x57\x10\xbc\xc7\xe3\xe3\xab\x38\x27\x5a\xb1\xf4\xd6\x56\xb2\xe5\x65\x98\xb3\x0c\xe4\x4f\x7b\xa3\xd4\x7e\x06\x79\x08\xe1\x6a\x8d\x12\xb5\x14\x45\x1a\x13\xc9\xfe\xd7\x31\x1f\x76\x36\x1f\xc2\x11\x42\x95\x2a\x2c\xa5\xfc\xac\x1d\x9c\xe6\x89\x4d\x2a\x76\x48\x64\x90\x7d\xca\x13\x09\x87\x6d\xc6\x22\xc1\xe3\xb1\x35\x24\x5b\xe3\x97\xbc\x02\xd8\x85\x58\x4c\xe2\x02\x1b\x40\x38\x26\x4d\x93\x38\xd1\x6b\xef\xcf\x81\xc7\xde\xb0\xad\x58\x3b\xd8\x22\x82\x2a\x37\x82\xd0\x3c\x97\x82\x46\x4b\xa6\x82\xaf\x21\x13\x6a\x13\x65\xf8\x28\xcf\xb4\x58\x24\x1c\xf9\x50\xe8\x63\x98\x95\x74\x4d\xa4\xd0\xce\x35\xad\xe1\x83\x1f\x82\xc1\xa0\x3b\x72\x1c\x5a\xae\xc1\x7f\x4d\x84\x43\xe0\xac\x92\xdb\xf0\x0f\x45\x44\x1a\xbb\xd4\xac\x7f\xfe\xc6\x30\xfe\x91\xc5\x62\x73\x09\x40\xd2\x4c\x2d\x48\x6a\x98\x27\x73\x31\x34\x77\xfe\x8f\xef\xc8\x52\x14\x52\x4d\xc3\x64\x7f\xdf\xc2\x3b\xd4\x70\x38\xc1\x41\x93\x94\x51\xa5\xc9\xb7\xdf\x90\x2c\xe1\x85\xb9\xf1\x47\x42\xbc\xb1\x78\xdd\x80\xcb\xfd\xd3\x77\x03\x47\x1b\x87\xbf\x6d\xe4\x6c\x73\xac\x98\x67\xd9\x5b\x7b\xc6\x31\xa1\x07\x56\xcd\xdc\x60\x76\xed\x95\x14\xee\x22\xd7\xe2\x91\x4f\xfe\x3f\x0b\x31\x5f\xeb\xe1\x29\x6c\xec\x38\xd5\xdc\x35\xff\x6d\x5f\xf6\x49\x15\x5b\x66\x8a\xdd\x63\x2a\x8f\x5e\xe3\x7b\x91\x28\xbd\x57\x85\xef\x32\xe7\xcd\x1e\x9d\x87\x5e\xe6\x0b\x23\x1f\x8f\x12\x49\x0f\x23\x39\x89\xce\x69\xa4\xa3\x88\x29\x20\x45\x2e\x29\x1c\x28\x77\xb1\xed\x9e\x1f\x3d\xd0\x6c\x33\x75\x49\x64\x1c\xf2\x8f\x50\xab\x74\x10\xb0\x86\xb0\xfc\x0e\xb1\x47\x82\x16\x0e\x56\xa5\x11\x2a\xe1\x0b\x2c\x2d\x9a\x15\xa9\x4e\xf2\xb4\x84\xdc\x8d\xeb\x60\x2f\xe0\xd0\x5a\x40\x03\xf5\x34\xc5\xa4\x57\x98\xfd\x1c\x2c\x2b\x27\x7e\x2c\xc6\x35\x56\xc8\x94\xe6\x1e\xcf\xa9\xa4\x1e\xfc\x91\xc8\x32\xaa\x4e\xad\xe1\x81\x82\x17\x8c\x2d\x03\x64\x7a\xd1\xb4\x9c\x71\xe0\x75\xf0\x58\x88\xab\x19\xa7\x7c\x6f\xf3\x5f\x35\xe1\x3c\x0c\x45\xc4\xbd\x77\xb4\xc7\x22\xf7\x1b\x18\x6b\x19\xe2\x57\x34\xba\x63\x3c\x26\x3f\x29\x07\xb8\x78\xcd\x69\x66\xf3\xc7\xe7\x52\x60\x15\x75\x16\x6f\xf4\x57\x67\x56\xed\x88\xa9\x4f\x5c\x02\x2b\xe4\xb7\x1e\x0b\x8a\x85\x1a\x29\x79\xb0\x19\xa8\x8b\xde\x29\x54\xe9\xca\x64\x15\x31\xc7\x3b\x9a\x7e\x8f\xb5\xf8\xd5\xde\xd9\xea\x48\x7d\xea\x28\x5b\xc6\x14\x4f\x21\x5c\xe9\xde\x72\x09\x69\xe2\x69\x6a\x48\xdc\xda\xe7\xfc\xd9\x40\xb0\xf9\x1a\xf4\x5e\x8f\x92\x79\x4c\xce\x87\xe7\x94\x3a\x96\xf3\xb8\x4a\xcc\x6e\x68\x2c\x14\x79\x95\x8a\xe8\x8e\x5c\x32\x10\x1a\x1e\xb2\xf8\xbe\x9c\xc7\x4f\xbb\x70\x66\x46\x17\xfb\x79\x8c\x4c\x48\x26\x78\xa2\x85\xdc\x87\x1e\x1f\x50\xa2\xc0\xe7\x52\x86\x7d\x32\xa6\x9b\x73\xf6\xa5\x14\x32\x34\x28\x3f\x0e\xea\xc0\x50\x5e\x75\x02\x94\x07\x5f\x01\x51\xdd\x9b\x8e\xfc\xbf\xa5\xb8\x9f\x68\x31\x29\x14\x9b\x24\x7b\x3b\x42\x0d\x06\xd4\x1d\x5b\x83\x57\xd9\x28\xa0\xb2\x83\x55\x24\x77\x2d\x40\xcf\x0e\xef\x0d\x7f\x77\xf3\xea\xf2\x27\xc5\xe4\x34\x94\x56\x5e\x32\x1d\xbd\x8c\x58\xbe\x7c\x69\x47\x78\xf2\x60\x75\x64\x73\x1c\xb8\xba\xd1\x90\x11\x88\x44\x9a\xda\x04\x63\xe2\x96\x5c\xb0\x7c\xe9\x3f\x77\x18\x70\x7b\xca\x35\xe5\x72\x21\xc6\x29\x37\x75\x6c\x46\xaa\x92\x0d\x78\x83\x54\x23\x40\x7e\x39\xdf\xad\x90\xf7\x21\xa2\xfb\x67\xac\xce\xb2\x4f\x29\xbe\x83\x00\xef\xe1\x94\xf4\x3b\xae\xd4\xf4\x0b\xe3\x87\xaa\x05\xfb\x9c\x77\x6a\x85\x6c\x5f\xdd\xa2\x30\x1a\xb3\x98\x88\x15\x93\x32\x89\x99\x22\x9e\x6e\x87\x3a\xa8\x24\x3d\x0c\xc8\x3f\xd7\x0e\x7c\x5a\x0e\x07\x87\xa3\x7e\x38\x06\xfd\x43\x85\x88\xc3\x9b\x2d\x22\x4e\xe3\x2c\xe1\x87\x81\xed\x7b\xc2\x4d\x45\x34\x65\x57\xef\x07\x4b\xeb\x76\x9c\xaa\xc0\x3e\xb3\x2f\x83\x9a\x02\x1d\x79\xf6\x7f\xf4\xb8\x4b\xb8\x88\xf7\x33\xa0\x3d\xb2\xd8\xbd\xa0\x9a\xdd\xef\xc9\x08\x4d\x4a\x92\xbf\x6f\x7f\x10\xcf\x9e\xb6\xd8\x7e\x10\x95\x42\x82\x53\x8e\x29\xff\x1f\x8b\xc9\xb2\xf8\x34\x8e\x21\x09\xc7\x0a\x8b\xb2\x6d\x96\x62\x73\x67\xf6\xfc\xfa\x8a\xfc\x15\x9b\x3f\x5e\x15\x14\x29\x34\x8a\x3c\x97\x22\xa3\xc9\x38\x05\xd0\x37\x07\xdd\xac\x87\x15\x02\xe1\xda\xb7\x25\xb6\xb1\x61\x8a\xca\x74\xc3\x85\x64\x31\xb1\xfa\x94\x2f\xac\xc4\xc3\x16\x3b\xfd\x65\x94\x78\x78\xa8\x2a\xd9\x81\x6a\xde\xc5\xef\x94\x5c\xb4\x43\x27\x60\x22\xbc\xaf\x13\x51\x8c\xab\x04\xdc\x1b\x02\x0f\x3c\x60\xb5\xc1\x2d\xdd\x07\xeb\x20\xdb\x7d\x46\xde\x88\x45\xc2\x1d\x15\x13\xd6\xab\xe6\x96\x26\xe9\x30\x70\x3e\xf3\xc9\x5f\x19\x9f\xac\x54\xfa\x9a\xd3\x79\xba\xbf\xcb\x64\xf5\x10\xf8\xe1\xc8\x0f\x29\x5d\x10\x06\x7f\xbc\x8c\x13\x65\xfe\x25\xb3\xd9\x1b\x30\x06\x17\xdc\xc9\x97\x60\xe6\xb4\x77\x8b\x0f\x8d\x46\x22\xf3\x78\x74\x01\x89\xf8\x68\x15\x3c\x82\xf1\x48\xc2\x63\xb3\x74\xa6\x2a\x4e\xc9\xb6\x05\xd6\x4a\xf1\x71\x77\xe8\xfa\x38\x67\xe4\xc3\x32\x89\xee\xae\x03\xfb\xaf\x90\xe6\x1d\x0f\x5e\x55\x98\x94\xcd\xdf\x1e\xeb\x36\xb2\xcb\xba\x1e\x4b\xa1\x16\x8c\xe7\x6e\x6a\x47\x4e\x67\x16\x82\xf0\x1b\x55\x4a\x44\x49\xe9\x7f\x00\x9a\xe8\xf2\xfa\x8e\xe1\xfa\x7e\x3c\xa8\x00\xc3\x39\x0e\x40\x90\xcf\xad\xe1\x5a\x1c\x46\xd9\x16\x54\x85\x5c\x4a\xc2\x1d\xdc\x1e\x0d\x08\x88\xe3\xa3\x95\x34\x2d\x87\xdb\x2e\x69\xea\xc4\xcc\x0d\x13\xb9\x0b\x78\xb5\x08\xe4\x44\x06\x5b\x43\x7b\x1b\x85\x7c\x69\x53\x5b\xcc\xe4\x51\x40\xb7\x7f\x68\x7a\x9d\xfa\x6f\xc3\x3f\x08\xdf\x59\xa3\x39\xd0\x9e\x5c\xe4\x45\x8a\x9e\xb5\xc3\x2b\xbb\x3a\x1b\x23\x7e\xe7\x11\x8c\xe8\x87\x56\xd9\xe9\x38\x0c\xcf\xdb\x3d\x5e\xf1\xcb\xa8\xef\x14\x88\x16\xdf\xfc\xe9\xbb\xef\x9e\x7a\xc5\xa7\x61\x8a\xbb\xc7\x2e\xf9\x34\xc8\xf4\x56\x93\x9b\xe1\xea\x39\x37\xc3\x73\x6e\x86\xea\xf3\xe8\xf6\xe1\xcf\x9f\x7d\x61\x94\xe8\xb6\x31\x22\xdb\x86\xe6\x57\x18\x18\x15\x37\x4e\x44\xdc\xe0\x0c\x0a\x9f\x23\x6f\xc2\x48\x31\x62\xc3\x73\x24\x3c\x67\x46\xf8\xba\x32\x23\x8c\x17\x23\x36\x56\x16\x84\xe1\xb1\x61\x5f\x4f\xc6\x83\xc1\x64\x63\x68\x5c\xfd\xe0\x68\xfa\xb1\x8a\x7e\x8c\xa5\xdd\x1f\x4d\xc3\x70\x5c\x8e\x57\xab\x6f\x71\x29\xde\x5c\x36\xfd\xe3\x63\x15\x24\xcb\xd7\xc2\x50\x97\x47\x14\x9d\xc9\x60\xcd\x03\x4e\x45\xec\x75\x77\xd7\x69\xf1\xde\xcf\x36\x1c\x04\xfc\xeb\xc3\xf7\x0b\x78\x36\x90\x0f\x73\x53\xff\xb2\xcc\xa3\x5f\x68\x05\xfc\x87\x32\x8f\xaa\x4a\xd6\x5c\xa7\x75\x04\x02\x09\x2c\x9c\x98\x87\x95\x69\x4a\xb2\x70\x7e\x7d\x45\x22\xc9\x20\xb5\x03\x4d\xd5\x94\xd4\x70\x78\xce\x80\x64\x39\x42\xc7\xd9\x51\xad\x59\x96\xeb\xa1\x98\xf7\x6c\x1d\xfd\xca\xac\xa3\x0f\x6e\xa5\x58\x16\x19\xe5\x13\x43\x2d\xc0\x3e\x5a\xf1\x3b\xd9\xb8\x0f\xa7\xc4\xd2\x05\x64\x2b\x40\x17\x0a\x21\xcd\x05\x4f\xfe\x59\xb0\x52\x5d\xe1\xb9\x8e\x03\x30\xee\xc0\x3c\x46\x86\x1d\x72\x54\x1b\x54\x24\x12\x5b\x41\x5c\x16\x20\x1e\x8e\x8e\x60\x04\x6c\x59\x45\xf5\xa6\x97\x0c\xb9\xb7\x6b\x48\x92\x50\xb6\xaa\xca\x87\x28\x20\xd2\x34\x15\xf7\xf8\xed\x90\x1f\x31\xfb\x67\xe6\x62\xf3\x92\xcc\x19\xc9\x12\x29\x85\xb4\x66\xa4\x70\x3a\xe8\x3e\x64\xe4\x4c\x26\x51\x60\x93\xd6\xe9\x63\xc6\xb4\xdd\x6a\x40\x15\x2d\x08\xe5\x18\xc0\x69\xfe\xef\x3c\xae\xe1\xdb\x8e\xde\xcd\xd9\x92\xae\x12\x51\x48\xec\xad\x05\x39\xb2\x3f\xc1\xdd\xbb\x16\x85\xd7\x9d\x17\x10\xa1\xe5\x57\xa7\x6a\xe0\xf4\xae\xfc\x11\x04\xdc\x58\x38\x75\xe4\x84\x7d\x4a\x94\xde\x5e\x8b\x03\x91\x2b\x39\xf1\x18\x98\xb7\x52\xb9\xb9\x60\x3f\xee\x1d\x7b\x5b\xc5\xb7\x70\xb4\x2a\xa7\xba\x9a\xc1\x4f\x5d\x7c\xaa\xcd\x58\x83\x21\xf3\x2e\x1c\xee\xe9\xf9\xb0\xe2\x2a\xf7\xac\x75\x75\x90\x8c\xf2\x33\x93\xdc\xfa\x78\x2f\x8b\x34\x89\xd6\x57\x97\xe3\x7a\x6e\xe0\x98\xee\xfa\x53\xde\x6b\xc3\xbc\x27\xaf\xa8\x62\x31\x79\x4b\x39\x5d\xa0\xd6\xe5\x64\x76\xfd\xea\xed\xa9\xc1\x22\xd0\xea\x5c\x5d\xd6\xba\x76\xcc\xc2\xc1\xdf\x3d\x56\x9c\x3b\xd9\x04\xdd\x68\x6c\xc3\xd6\xa8\x7b\x82\xef\xd1\x52\x00\x10\xcf\x13\x0c\x29\x9f\x56\xc3\x0e\x5c\x6f\x26\x89\x42\xf7\x0d\x97\xfd\x4d\x6d\x92\xea\x55\x16\xdf\x3d\x24\x00\x02\xbd\x79\xdb\x2a\xfb\xd9\xc0\x7a\xd8\xb9\xaa\xd5\x48\xb4\xa4\x9a\x2d\xd6\x97\x2c\x4f\xc5\xda\x20\xc0\x75\xa0\xc6\xc7\xa6\x73\x64\x1b\xe4\x9c\x46\x44\x16\x29\xc3\xda\x42\x9b\x69\xd7\x38\x63\x71\x49\xe9\x12\xae\x34\x85\xa4\x6b\x38\x7e\xeb\x8c\x7a\x5f\x56\x7d\xaf\xa5\x09\xce\xb3\xb3\x55\x35\x45\xa5\x39\x25\xad\x5d\xfa\x5f\x4c\xf0\xf9\x6e\x9c\xdd\xc5\xae\xd9\xdb\x82\x59\xad\x0e\x08\xa7\xfc\xa6\x48\xcd\xe5\x93\xc6\x1b\x25\x5e\x81\x4f\xb3\x7b\x8c\xd9\x2e\x80\x26\x98\xd9\x9f\x91\x79\x61\x98\x38\xa6\x2a\x3a\xee\xed\x54\x9f\xf7\x4b\x34\x69\x9b\x4e\x84\xe6\x79\x9a\xa0\x0b\xb3\x90\xd6\x2e\x1d\x28\x34\xb7\x9b\xf5\x21\x2d\x3b\xf2\x32\xbb\xf1\x2e\x13\xb2\x62\x72\xde\x27\x4f\xc5\xae\x6c\x09\xcd\x13\xb0\xe3\xf4\xe6\x62\x2a\x1b\x77\x7e\x7d\x85\xbd\xeb\x14\xc7\xee\x47\xdc\x41\xbb\x37\xce\xbc\x61\x6b\x06\xa1\xe4\xe2\x33\x2d\x9d\x5f\x5f\x61\x6a\x2f\x9b\x6c\xa9\x54\x7f\x18\x39\x81\xa2\x93\x63\x99\xe1\x91\x2e\xcc\x88\x9a\x08\xee\x3f\xca\x78\x91\x31\x4c\xd0\x54\x16\x1b\x33\xc2\x23\x5f\x97\xa3\x97\xda\x13\x23\xeb\x18\xd1\xe7\xe8\x28\x64\x84\x31\xf4\x41\x06\xf3\x01\x62\x72\xf4\xa2\xd2\xca\x50\x8e\x72\xc2\x7d\xaf\x9f\xdd\xbd\x04\x76\xf4\x0a\xd8\xf9\x3e\xe3\x82\xdf\x58\x50\xfd\x74\xf3\x66\x3f\x44\x78\x57\x1d\xc3\x26\xf5\x61\x90\xbf\x30\xa7\x52\x27\x34\x25\x85\x4c\x9d\x59\x11\x63\x04\xac\x2b\xde\x92\xae\x82\xc4\x47\x53\x42\x5e\xe0\xee\xdb\xcd\xc1\x33\x8e\x05\x7c\xad\x2a\xb8\x48\xd3\x33\x72\x9b\x40\xc9\x76\xcd\x72\x12\x9a\xb5\x66\x09\x8f\x8c\x38\xc8\x27\xbe\x22\x0f\xcc\xc8\x09\x89\xfe\xa0\x83\xd5\x14\x78\x66\x96\xc6\x90\x0c\x13\x3e\x61\x0e\x7d\x04\x2a\x0b\x23\xc5\x5e\xa4\x85\xd2\x4c\xde\x08\x73\xa1\x04\x6e\x3b\x90\x18\x84\x86\x3f\xbf\x4a\x78\x0c\x7e\x5a\x37\x70\xf9\x44\x94\x13\x96\x80\x32\xc8\x0c\x09\xf6\x77\x83\x2c\x25\x52\x9e\xa8\x22\x5a\x9a\x25\x1d\xe5\x22\x56\x47\x86\x14\x1d\xa1\xca\x50\x1d\x9d\x9a\xbf\x36\xd7\x80\x5e\x38\x41\xbf\x97\x34\x4f\x8e\x4e\xcf\x08\x00\x08\x0c\x80\x42\x2f\x9f\x2e\x1e\xba\xb5\x82\x8c\xbe\x17\x16\xde\x84\x23\x00\x0e\xf2\xd2\xd4\x77\xbf\x4c\x34\xf3\xe5\xd5\x51\xd3\xe4\x33\xdd\x6c\x12\x7c\x42\xce\x39\x61\x59\xae\x41\x7b\x4d\x32\x46\x9d\x49\x9c\xad\x98\x5c\xeb\xa5\xcd\x04\xe2\x08\xc8\x93\x07\xfa\x30\x80\x6f\xd4\xae\x2f\x91\x1c\x4e\xd8\x16\x70\x8f\x5f\x1c\x6f\x12\xd2\xf2\x46\x78\xb2\xa0\x84\x2b\x7a\x2f\x30\x7e\x34\x3d\xab\x20\xc4\x57\x48\x2d\x3d\xfd\x78\xf3\xc6\x1a\x56\x10\x56\x3f\x26\x3c\x56\xbe\x9a\xa2\xf5\xfb\xb6\xf0\xae\x05\x32\xcc\xf0\x29\x02\x78\x9b\x05\xee\xcb\xb6\xb6\x0c\xef\xb8\xfe\xa6\xa1\x5a\x07\xb0\xa2\xc3\x5b\x11\xd7\x1f\x9d\xca\xfe\x5e\x05\x8d\xbd\xb3\x41\xa9\x77\xb1\x63\x59\x76\x77\x9d\xd7\xca\x04\xed\xdb\xd1\x02\xfa\xa6\x99\x94\x0a\x07\xa0\x93\xc1\x2f\xa0\x4d\xc2\x3c\xe7\xe4\x36\xa5\x8b\x12\x8d\x80\xea\x21\xa3\x75\x31\xfb\xe8\x96\xa0\x48\x52\xcf\xf2\x76\xf2\xc4\x5d\x5c\xf0\xa4\x84\x52\x63\x0b\xf3\x91\xda\x1f\xbb\x59\x61\x3f\x78\x33\x36\xf5\x31\x36\xea\x56\x45\x5e\x13\xfc\x9d\xce\x8e\x06\x98\xe0\x12\xb6\x39\xc1\x14\xfc\xa7\x80\x0f\x99\x7d\xac\xa0\x49\xc7\x7c\x1b\x90\xf6\x8e\xad\xef\x85\xac\xcf\xc5\x5e\xe5\xeb\x3d\x1d\x72\x5d\x9c\x04\xe6\x8c\x97\xa8\x1f\x14\xb5\x49\xe7\xf7\x46\xd5\xd6\xc9\xa7\x74\xce\xd2\xee\xa9\xbf\xa5\xb9\x99\x77\xe9\xf7\x8a\x8a\x00\x6b\x36\x45\x51\x04\x5d\xd4\x9c\x5b\xa0\x90\x0b\xca\x93\x5f\xd1\x59\x38\x32\x24\x41\x48\xf3\xe7\x09\x9a\x5e\x50\x8d\x90\xb2\x48\x9f\x5a\x54\xae\x25\xa1\x1d\xb8\x4e\xe3\x38\x41\x46\xe4\xba\x03\x2d\xdb\x81\x90\xf0\xbb\x5d\xb6\x0f\xda\xa3\x37\x19\x2e\xf6\x81\xf7\xae\xe5\xac\x77\x1f\xc7\x76\x1b\x70\x8f\xeb\xa2\x90\x2d\xee\x61\xad\xfd\x33\x9a\xd8\x62\xc1\xbb\x40\xd7\x62\x0e\xb5\x1c\xa6\x21\x90\x66\x7d\x7e\xb4\xcf\x70\x58\x06\x01\x9c\x65\x34\xd9\x17\x62\xf8\x0c\xd8\xb2\x8c\xea\x42\x26\xba\xf6\xfa\x6d\xef\x98\xf0\x1f\x8b\x39\xb3\x16\xf5\x9d\xbb\x73\x70\xac\x3c\xbf\xbe\xaa\x05\xcb\x38\xd7\x2c\xe8\x3d\xec\x04\x0d\x97\x46\x0a\x4e\xb3\x79\xb2\x28\x44\xa1\xd2\x75\xa8\xc6\xa5\xe0\x10\x30\x25\xe4\x0a\xf5\x58\xfc\x58\x13\xca\x05\x5f\x67\xb6\x29\x8f\xd2\x22\x66\x95\x11\xc1\x6e\xba\x12\x49\x4c\x68\xa1\x45\x46\x75\x12\x91\x48\x30\x19\x81\x8d\x35\x1c\xa9\x50\x8c\xd0\x86\xbe\x51\xa1\xb4\xc8\x48\x46\xa5\x5a\xd2\x34\x6d\xda\xe3\x11\xee\xf0\xb6\x64\xed\x13\x58\x7f\xe3\x8f\x2b\x9c\xf5\x9e\xf8\xdd\x91\x9b\xbe\x07\x7e\x9b\xc9\x0d\x1a\x60\xd5\x8c\xa5\x3d\xc6\xb0\x59\x11\x6a\xf3\x3d\x55\x10\xee\xc3\x92\x91\xbc\x98\xa7\x89\x02\xc9\x14\x28\xd1\x9a\xcc\xd9\x32\xb1\xde\xd9\xdd\x24\xa8\x71\x8b\xbb\xe0\xdc\x46\x03\x3a\x21\xd4\x42\xb2\x5b\xfb\xda\x2b\xed\x2a\xa3\x8b\x1e\x0c\xf8\x1b\x43\xb0\x29\x5f\xfb\x9b\x10\x92\x9c\xaa\x33\x22\xa4\xf5\xd8\xf1\x35\xe9\xed\x4f\x3e\x51\xae\x24\xef\x2d\xe8\xac\xeb\xbc\xc5\x77\x08\xa8\x60\xf2\x56\xc8\xcc\x00\x38\x91\xe4\xb6\xe0\xa0\xa0\x54\xd6\xd3\x1e\x6e\x09\xab\xe3\xa2\xa9\x12\xfe\x2c\xc3\x5e\x70\x37\x09\x42\x15\xb9\x67\x69\x3a\x25\xe7\x69\x6a\xb3\xaf\x06\x79\x36\xca\x58\xf9\xd2\x9f\x63\xbe\x26\x71\xb2\x60\x4a\x93\x93\xd9\x7f\x9d\x9f\x02\x8b\x02\xfa\x9f\x35\xd1\xd4\x85\x0a\x56\xf5\x5a\xc0\xec\xc4\x05\x30\x45\x11\xd5\x34\x15\x0b\x74\x69\x00\x1d\x39\x8f\x49\x9e\xd2\x35\x94\x56\xc8\xa9\x04\x6f\xdf\x08\x75\x5b\x44\x16\x1c\x92\x4a\x7f\xd6\xbb\xab\x9b\xa8\xb4\xe5\x7d\x9e\x00\x4e\xee\x49\x34\x3a\xb2\xeb\x3e\xec\xa5\x28\x59\x9e\xd2\x06\x6d\xcc\xd6\x81\x2f\x03\xc1\x8d\x78\x00\xa2\xbf\xe0\xcc\x8f\x31\x25\x33\xc4\x9d\x8c\xea\x08\xed\xc9\xff\xc8\x98\xa6\x31\xd5\x74\x6a\x64\xe8\x7f\x54\xa3\x12\x45\x1a\x9b\x81\x9a\x37\xba\x61\xce\xc8\x1c\x8b\x6e\x22\xf5\xc6\x70\xf0\xbe\x39\xc8\x35\xee\x3c\xb6\xaa\x7f\x06\xd2\x27\x58\xfe\xeb\x4f\x46\x84\x6d\xb5\x5f\x56\xe6\xba\xd9\xa9\xaa\x9d\x49\xab\x2b\xb1\xd8\x9a\x31\x48\xd1\xf9\xc1\x56\xa1\x72\x6f\x40\xf5\x7c\xfe\xee\xb2\x59\x4d\xd8\xad\x6a\xe9\x50\xad\x6c\xf2\xa7\x8d\xd3\x73\x8a\x79\xfb\x4b\xd5\x32\xe3\x42\x91\x20\x78\x13\x03\x7b\x28\xf7\x37\x87\x4b\xce\x9f\x82\xc6\x20\x0c\x3b\xc5\x7e\xcd\x7a\xa5\x5e\xa6\xb1\x3e\x06\xb1\xae\x28\xbf\x89\x9f\x6c\x63\xa3\x7e\xf6\xb1\xce\x48\xbc\xa6\x48\x3b\x84\x3c\x04\xe6\x38\xd5\xb2\x07\x76\x5f\x7b\x62\x4f\xbd\x98\x5b\xea\x0e\x13\xf5\x5b\x59\x71\xfa\xba\x63\xeb\x63\x2b\x23\x1a\x4c\x5f\x26\x39\x86\x8a\x5a\xf3\x8d\xdd\x5d\xf2\x91\xa6\x49\xec\x87\x40\xac\xbe\xe2\x67\xe4\x9d\xd0\xe6\x9f\xd7\x9f\x12\xa5\x51\xd6\xbe\x14\x4c\xbd\x13\x1a\xde\x8c\xb2\x54\x9c\xc2\x0e\x0b\xb5\xd2\x3e\x5a\x00\xe0\x5c\x05\x3a\x01\xb7\xa0\xab\xdb\x0a\x67\x64\x5a\x5f\x71\xc3\x11\xd8\x15\xf9\x10\x6a\x65\x87\x70\xf1\x3f\x5c\xf0\x09\xd8\x06\x6a\xc7\xb0\x80\x10\xb2\x02\x87\x96\xe1\xec\x50\xe8\x7c\x09\xbf\x24\xca\x11\x71\x7f\x67\x53\xa7\xae\x4c\x22\x92\x31\xb9\x00\x6b\x57\xd4\x61\xed\xe9\xab\xc2\xed\xa5\xb8\xed\xdc\x2b\x20\x99\x6f\x1a\xb5\x34\x5b\x9b\x14\xb4\x47\xb2\x94\xa1\xea\xe6\x5f\x86\xfa\x00\xa4\xfe\x0d\x71\xf4\x6a\x4a\xce\x5d\x89\x9f\xf0\x37\x6b\xf5\x0b\x87\x31\x23\x24\x8a\x18\x52\xb2\xa2\x29\xc3\x0a\x07\x94\xfb\x58\x37\x71\xbb\x45\xd8\xcf\x6c\x3c\xbd\x39\xb3\x9e\x65\x3a\xba\x63\xeb\xa3\xb3\xad\xad\x3d\xba\xe2\x47\x65\xc0\x63\x65\x33\x3d\x11\x05\x6e\xeb\x08\x7e\x3b\xda\xff\x2e\x68\x25\x96\xfd\x75\x49\x9d\xfb\xa6\xee\x92\x7a\xd3\x7f\x2d\xb3\x71\xa2\x4e\x41\xed\xc1\xb1\xd6\x92\x90\xa0\x06\x36\x6f\xc3\xd4\x2a\x86\x55\xbd\x4b\xf2\xbc\xcc\x44\x53\xe4\x0b\x49\x63\x46\x16\x92\xe6\xcb\x5d\xd9\x12\xe4\x6d\xea\x86\x7f\x32\x8c\x6e\x03\xf0\x5b\x64\xc3\xd6\x7e\xf7\x6c\xbe\x14\xe2\x0e\xc2\x10\x01\x11\x1e\x50\x93\xf1\x37\xfc\xd6\x65\xf9\xce\x09\xa5\x8a\xc4\x4c\xd3\x24\x05\x3f\x9a\xf7\x6f\xde\x5a\x4f\x1b\x77\x8f\xbb\x59\xd6\x3b\xad\x8c\x20\x00\xd0\xd8\x7a\x80\xdd\xb0\x55\xc2\xee\xad\x7e\xa3\xc9\x47\x66\x42\x16\x8c\x83\x63\x48\x8b\x03\xd5\x84\xa8\x24\x66\xaf\x21\xe8\xb9\x79\xa0\x01\x06\x87\x86\x39\x77\x1d\xde\x76\x0a\xde\x49\xbd\x7b\xdc\xb2\x5e\xfc\xbd\x16\xb2\x25\x09\x53\xbf\x18\xec\x7e\xf1\xd5\xd6\x8b\xff\x7b\xf2\xdd\x77\x7f\x68\x6c\x94\xd1\x4f\x49\x56\x64\xdf\x93\x3f\xfd\xf1\x8f\x7f\xf8\x63\x73\xb3\x84\x63\xb3\x6f\x9b\xd7\x67\x4f\xdb\xc5\xcd\xe5\x01\xc0\x3b\xf6\x9e\x8c\xed\xc6\xcc\x1e\x43\xdd\xd2\x24\x2d\xa4\xf5\xa1\xed\x29\x22\xfc\x10\xf6\x01\x43\x54\x19\x74\x42\xdd\x88\xce\xd1\xce\x3a\xe0\xdd\x26\x9c\x29\x28\x9e\x53\x70\xc9\x22\xb1\xe0\xc9\xaf\x2c\x76\xb5\x73\xc0\x21\x06\xb2\xec\x3b\x14\x27\x8c\xc7\x58\xc3\xd4\xdc\x79\x4b\xca\xe3\xb4\xcd\x51\xa2\xc7\x4a\xc3\x13\x3c\x08\x64\x70\xf3\xec\x04\xb0\xb7\x65\x8f\x0d\x70\x41\x25\x56\x6b\xb6\xc3\x1b\x0d\xc1\x36\x68\xa5\x48\x18\x67\x2d\x82\x75\xcd\x1c\xb7\xe4\x3e\x14\x59\xe1\xdd\x3f\x0b\x26\xd7\x10\x60\x53\x32\xf6\x81\x13\xde\x87\x32\x7f\x83\x5b\x86\xe5\xa8\x30\x81\xce\x86\x2c\x5c\x32\x31\xa5\x9b\xcc\xc6\xb7\xa1\x0f\x43\xb7\x03\x67\x35\x23\xe7\x84\x17\x69\xda\xd4\x94\x8b\x36\xfb\x5a\x08\xbb\x0e\x51\xb2\x9f\x8c\xd7\x57\x2d\x50\x03\xe9\xcf\xaa\x1c\x08\x17\x3e\x12\x2b\x7f\xd8\xea\x82\x70\xc1\xbd\xfc\x69\xfb\xfb\xd2\xf6\x4b\x13\xd4\x43\x8d\x80\xcf\x2e\xce\xb6\x3d\x93\xfb\x3c\xa4\x62\x01\x9f\x9d\xfc\x9a\xfa\x29\x19\x6a\xa6\x7e\x70\xaa\x86\x3d\x16\xdf\x47\xed\x50\xb3\xf4\x67\xe5\xc3\x16\xc0\xfb\x7a\x91\xed\xe0\x41\xd6\x73\x27\x7b\x28\x25\xf0\x79\x56\x4d\xec\x74\x13\xf5\x20\xcc\xbb\xa9\x29\x7a\xef\xaa\x64\x09\x5f\x09\x4c\xb2\xbd\x13\x0f\x77\xb3\xd5\x71\x83\x95\xbb\x07\xca\x6a\x79\x39\xcf\xfc\x86\x2c\xad\x11\x68\x49\xa1\xba\x95\xdd\xed\x2b\x68\x8f\xbb\x19\x45\x06\xa9\xae\xbc\x48\xd9\xdf\x12\xbd\x7c\xef\x92\xea\x5b\xac\xd6\x45\x9e\xc2\x62\x83\x1f\x0c\x0a\xdd\x94\x9c\xe1\x15\x96\x71\x63\x91\xc8\x32\xc6\x63\x74\x22\xca\xe8\x1d\x23\x65\xa9\x50\xc3\xe3\x01\x1b\x0c\xc3\xb1\x4f\x39\xe5\x25\x9f\xb8\x32\xb4\xbc\x0d\xa3\x7a\xe2\x53\xdf\xbb\xb6\x77\x40\x4b\x7b\x20\x4b\x10\x89\x52\x09\x58\x21\x73\x96\x0a\x08\x81\x47\x0f\x5b\xf4\x01\x77\x31\x20\x86\x24\xdb\xb7\xf6\xd6\xb3\x09\x37\x19\x5f\x94\x79\xbc\x54\x0a\x45\x7d\x2d\x05\x16\x9c\x4d\xc9\x8d\x65\x61\xfa\x71\x45\x7d\xc8\x69\x4f\x52\xba\xc3\x85\xf8\x69\x52\x66\xcb\x98\x18\x66\x77\x62\x67\xa3\x45\x96\x44\x5d\x9b\xd2\xad\xeb\xc0\x67\x73\x5b\x5c\xbf\x70\x63\x56\xee\x5d\x9f\xad\x71\x8d\x9f\x37\xa7\xe1\xf1\xa5\x36\x76\xdb\x9b\x2a\x31\x29\xef\x23\xbf\x31\x1b\x64\x33\xc2\x62\xd5\xa0\x24\x9c\x90\x8b\x9b\xd7\xe7\x1f\x5e\x9f\x91\x9f\xae\x2f\xe1\xdf\xcb\xd7\x6f\x5e\x9b\x7f\x2f\xde\xbf\x7b\xf7\xfa\xe2\x83\xe1\x60\x5e\x60\xd1\x00\x23\x40\x9a\xad\x31\x37\xa1\xa8\xd2\x29\xca\xd7\xe4\xb6\xd0\x86\x10\x95\x1f\xab\xcc\x82\xa2\xf6\x81\xc6\xb1\x11\x56\x9f\x1c\x02\xd4\x03\x7c\x53\x61\x13\x56\x4b\xc1\x3a\x0b\x36\x44\xae\x9b\x41\xfb\x3c\x18\xd6\x3b\xc8\xa4\xb2\xde\xa3\x3d\xa3\x4b\x7e\xe1\xe4\x07\x21\x89\xad\x4d\x07\xc5\x4a\x63\x75\x6c\x63\x78\xcc\xff\xa7\xf8\xea\x65\x2a\x16\xc7\x3e\xb4\x87\x91\x54\x2c\x88\x2a\xe6\x3e\xe4\x0a\x98\x00\x68\xfd\xc2\x35\xab\x44\xaa\x9c\xf9\xb8\xab\xa0\x97\x1f\xbc\xd2\x27\x6c\x10\x8e\xfb\x12\x0a\xca\x55\x5a\x9a\x17\x9b\x03\xbe\x78\x59\x3f\x03\xc7\xef\x25\x72\xa3\xc7\x2f\xdc\xe0\xfa\x7d\x92\xc6\x11\x95\xf1\x16\xc2\xc3\x9d\x8c\xf8\x02\xd0\xc3\x2c\xcb\x58\xfc\xbb\x1c\xdc\xe6\x46\x11\x2b\x26\x53\x9a\x63\x40\x00\xa4\xb9\x06\x8f\x29\xf8\xc8\x25\xcb\x19\x84\xbd\xb9\xe2\xf4\x8c\x47\xa9\x80\x34\x2c\x78\xa1\x9f\x55\x97\x8e\x1e\x54\x2e\x57\xa5\x0b\xbe\xf4\xc7\xeb\xe8\xcb\x24\xb0\xe0\x47\xbe\x13\xea\xa3\xe7\x79\x63\x22\x20\x1f\xe3\x83\x82\xb2\xe7\xf6\x19\x39\xb2\x11\x89\x47\x67\xe4\xc8\xe7\xba\x89\xad\x64\x70\xf4\xe2\xa8\x6c\x10\xc6\xb4\x81\x60\x60\xcd\x60\x13\xf8\x4e\x18\x3d\x0b\xd8\xe1\x8c\x75\xfe\xd3\x65\xbe\x22\x73\x23\x5b\xc5\x1d\xcc\xa1\x3a\xd0\xb4\x32\x91\xad\xaf\x96\xe1\x98\x9d\x5f\x34\xd3\x0f\xba\x6b\x48\x7f\x80\x61\x9d\x16\x38\x92\x99\xad\x74\x4e\x78\xb3\x0a\xe6\x79\x63\x63\x98\x50\x29\x91\x24\xa7\xd2\x88\x5f\xae\x65\xb5\x24\xde\x8b\xce\x82\x78\x3d\x30\x28\xb0\x29\xf5\x94\x54\x66\xbe\xc7\x45\x4a\x95\xaa\xd1\x36\x03\x15\x31\x03\x13\x86\x23\x13\xea\x0c\x6e\x90\xef\x7c\x49\x57\x2d\x09\x31\x7a\x4c\x5a\x53\xb9\x60\xba\xdd\x1a\x44\xf9\xfa\x7d\x6b\x0a\xbd\x49\xef\xa4\xbd\x93\x7e\x47\xb1\x72\x08\x13\xae\x27\x42\x4e\xb0\xcb\xf7\x44\xcb\xa2\xc9\xae\xa7\x93\x8c\x89\x42\xcf\x58\x24\x78\x7d\xf4\x8b\x6d\x37\x9a\x79\x6b\x87\x90\x20\x6b\x61\x3d\x77\x0c\x4c\x98\xf4\xd2\x09\xa3\x25\x77\xe3\xac\xaa\xd5\xb4\x3d\xef\xdf\xbc\x1d\xb2\xd9\x04\xc2\xe6\xdb\x77\xf2\xa3\xbd\x33\xf8\xc2\xcf\xd4\xce\xbc\xb5\xdb\xdb\x42\xef\xde\xe9\xc2\x5b\xeb\xda\x5b\x5b\x60\xb4\xa7\x5e\x69\x5c\xbf\xd2\x54\x17\x5b\xd8\x50\xd9\x1b\x4b\x2c\x67\x18\x7e\x68\x45\x91\x19\xf4\x0b\x15\x9b\xdb\xf9\x26\x30\x87\x0d\xb4\x73\x0e\x9a\x53\x62\x3b\x9a\xf3\xa9\x25\x4d\x50\x68\xa6\x91\x2e\x20\x8e\x9d\x6a\xeb\xcc\x69\x13\x2e\xfd\xae\x6e\x19\xb5\x62\x72\x9b\x68\x1c\x31\xa9\xd5\x1b\xaa\xf4\x4f\x79\x4c\x1b\x22\xdd\x36\x9c\x34\x95\x86\x03\x83\x2c\xfd\x3d\x67\xb1\xa1\xf0\x16\x04\x38\x1e\xb9\x37\xa4\xb7\xc0\x11\x1b\x5d\x0f\x1a\x51\xce\x1d\x20\xd3\x7d\x62\x3e\x55\x3f\xeb\x1b\x61\x60\x72\x5e\x4b\x80\xaa\xee\x29\x5d\xb3\x35\xd7\x89\x84\xd1\x08\x67\x9f\xea\xb4\x0c\xc3\x67\x9c\x32\xca\xeb\x83\x0d\x36\x30\x0a\xda\xed\x8e\x43\xf6\x03\xe4\x7e\x99\x18\x7e\x17\x23\x02\x15\x71\xfc\x57\xcc\x52\xd6\x10\x18\x38\xd0\x7d\xd6\x7e\xe1\xd2\x7e\xa0\x97\x6b\xd7\x75\xb5\x8f\x37\x62\x58\x0e\xde\x86\x9e\x94\x9c\xb6\xe5\x1e\xbc\xbc\xb6\xb9\x2a\x60\x5f\xe6\xa9\x88\xee\x30\x01\x1d\xe4\x7e\x48\x7e\x65\xd2\xf9\xda\x97\xc5\xe7\x6c\x45\xb4\x85\xab\xf6\xea\xe0\xe6\xca\x5f\xc1\x28\x66\x6c\x03\x40\x3f\xbe\x90\xa5\x36\xb5\xe0\x36\xd2\xf2\xf3\xb8\xeb\x3a\x29\x07\x62\x14\x2a\xd6\x92\x6d\x81\x07\x73\xd5\x40\x7e\x4c\x2b\xac\xd2\xcc\xc6\x06\xbd\xfc\xb1\x39\x8e\x66\x54\x17\xdc\xb6\x68\x1e\x6c\x01\xe0\xe3\x51\x6b\x6a\xa3\xd6\xb8\x9f\xbe\xda\xbe\x8e\xf8\x1e\xd2\x9f\xc3\xf7\x53\xee\x33\xda\xa8\x0e\x95\xa3\x5b\x38\x1b\x43\x1f\xca\x67\x17\xbb\x65\xdf\xc4\xbc\x3b\x59\xd6\xf8\x2e\x09\x54\xab\x89\x66\xbc\xd8\x61\xa3\x78\xd1\xfb\xe0\x56\xc8\x46\x01\x66\xbc\xc9\xb7\x47\x83\x75\x0e\x64\xb8\xcf\x66\x7f\xbd\xed\x80\x25\x43\xbd\x7c\x97\x33\x42\xc9\x32\x51\x5a\x48\x6b\x4e\x84\xe2\x75\x92\x42\x71\xdd\x7a\xbf\xb7\x71\x3c\x00\x2f\xfc\x14\x08\xcd\x73\x46\x7d\x5d\x2b\x7b\x37\x41\x61\x2a\xc9\x22\x21\xe3\xda\x89\x39\xd5\x40\x2d\x2f\x55\xfb\xf9\x11\x22\x5b\x53\xaa\xf4\x07\x3f\x07\xc3\x20\xf4\xa4\xc6\x55\xf6\xc7\x2e\xb1\x5c\x8d\x4b\xfd\x23\x78\xf9\xa3\x20\x94\xa3\x4a\x64\x18\x0f\xde\xcd\x64\x94\x6b\x43\x6e\x6e\xaf\x75\xdd\x7b\xce\x2d\x58\xe2\xe7\x99\x79\xc6\x94\x6a\x0d\xae\xda\x70\x4c\x81\x1c\xd2\xc4\xe7\x90\xb6\xdd\xdd\x65\x8f\x0c\x02\xba\xa0\xba\x2c\x6f\xeb\x66\x54\x23\xc0\x26\xa0\x42\xc1\x1f\xab\x41\x5b\x96\x2f\xa9\xea\xbb\x18\x7f\x8a\xbc\x5b\x73\xef\xe3\xd0\x73\x36\x92\x51\xd5\x16\x68\xba\x01\xdb\xb9\x4c\xd8\x2d\xb9\xa0\x19\x4b\x2f\xa8\x1a\x13\xb8\x40\x01\xa6\x84\x4d\x17\x53\x72\x7c\x13\x58\x98\xdf\x09\xfd\xb6\xad\xc6\x47\x47\xfa\x87\x3e\x27\xfa\x41\xcf\xf2\x60\x21\xa1\xfb\xe4\x0e\x3c\xb3\x83\x67\xd8\x72\x42\x0f\xe2\x6c\xb6\x47\x4b\x37\x9d\xc7\xea\x49\x2c\x24\x68\xfc\xa2\x7d\x4f\x64\x47\x00\x67\xd3\x29\x3c\xe4\xf3\xd7\xb1\x24\x3f\xc4\xac\x56\x65\xb2\xb5\xba\x0f\x15\xc9\x15\x6c\x06\xa1\x53\x21\xa4\x87\x37\x33\xbd\x98\x7d\x1c\x93\x6d\x79\xdc\x54\x05\x76\x03\x1b\x7f\x6f\xe1\xcb\x27\xed\xb7\xf0\xd0\x34\x08\x31\x58\x69\x0c\x06\x7c\x4e\xa7\x93\x4b\xf7\x55\xab\xeb\xf0\x99\x9d\xe1\xaf\x5b\x5b\x41\xcf\xb6\xa9\xe0\xc7\x09\xd4\x2a\x64\x2b\x2c\x10\x0a\x41\x2e\x8c\x70\xa6\xcc\xa1\x38\x6d\xf9\x7c\x4f\x81\xaa\x9f\x30\xd5\x2d\xe8\x76\x0a\xb1\xa4\x7b\x6b\x5d\xa3\xb6\x0d\xc6\xa7\xaf\xcc\xd6\x43\x26\xde\x41\x58\xeb\x96\x78\x76\x18\xac\x93\xfd\xdb\x71\xbc\x7a\x05\xee\xe6\xb3\x91\x49\xda\x74\xb9\x01\x22\x8d\x56\xe5\xc8\x50\xe0\x08\xf2\x8b\x23\xed\xb6\xe4\xa9\xaa\xbf\xbd\xd9\xa4\x81\xe0\x62\x59\xc5\xf0\xb1\x96\x55\x14\xc9\x78\x30\xef\xcc\x3f\xd2\x7b\xbc\x03\x48\xa6\xd2\x89\x40\x0f\x9b\x9c\x01\x9f\x2e\xac\x7b\x7c\x7c\xeb\x93\x29\xab\x15\xc7\x1e\x28\xaf\x8d\x62\x72\xc5\xe2\x8a\xa5\xce\xe6\xf9\xaf\xbe\x0b\xec\xb6\xe5\xf8\x16\xec\xe4\x5f\xff\xfe\xdd\xff\x05\x00\x00\xff\xff\x96\x44\x81\xaa\x39\x2a\x08\x00") func operatorsCoreosCom_clusterserviceversionsYamlBytes() ([]byte, error) { return bindataRead( @@ -125,7 +125,7 @@ func operatorsCoreosCom_clusterserviceversionsYaml() (*asset, error) { return a, nil } -var _operatorsCoreosCom_installplansYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5b\x4b\x93\xdb\x36\x12\xbe\xcf\xaf\xe8\x9a\x1c\x9c\x54\x59\x9a\x24\x7b\x49\xe9\xe6\x9d\x6c\xb6\x66\x37\x0f\x97\x67\xe2\x4b\x36\x87\x16\xd9\x12\x91\x01\x01\x04\x0f\xc9\xda\x54\xfe\xfb\x56\x03\x7c\x4a\x24\x45\x8d\x27\x8e\x6b\x2b\xbc\xd8\x43\x36\x80\x7e\xf7\xd7\x00\x84\x46\xbc\x25\xeb\x84\x56\x2b\x40\x23\xe8\x9d\x27\xc5\x7f\xb9\xe5\xe3\x57\x6e\x29\xf4\xcd\xee\x8b\xab\x47\xa1\xf2\x15\xdc\x06\xe7\x75\xf9\x86\x9c\x0e\x36\xa3\xaf\x69\x23\x94\xf0\x42\xab\xab\x92\x3c\xe6\xe8\x71\x75\x05\x80\x4a\x69\x8f\xfc\xda\xf1\x9f\x00\x99\x56\xde\x6a\x29\xc9\x2e\xb6\xa4\x96\x8f\x61\x4d\xeb\x20\x64\x4e\x36\x4e\x5e\x2f\xbd\xfb\x7c\xf9\xd5\xf2\xf3\x2b\x80\xcc\x52\x1c\xfe\x20\x4a\x72\x1e\x4b\xb3\x02\x15\xa4\xbc\x02\x50\x58\xd2\x0a\x84\x72\x1e\xa5\x34\x12\x95\x5b\x6a\x43\x16\xbd\xb6\x6e\x99\x69\x4b\x9a\xff\x29\xaf\x9c\xa1\x8c\xd7\xde\x5a\x1d\xcc\x0a\x06\x69\xd2\x6c\x35\x8b\xe8\x69\xab\xad\xa8\xff\x06\x58\x80\x96\x65\xfc\x7f\x12\xfd\x2e\x2d\xfa\x5a\xa2\x8a\x6f\xa5\x70\xfe\xdf\xc7\x5f\xbe\x15\xce\xc7\xaf\x46\x06\x8b\xb2\xcf\x6a\xfc\xe0\x0a\x6d\xfd\xf7\xed\xc2\xbc\x90\x30\xe9\x93\x50\xdb\x20\xd1\xf6\x46\x5d\x01\xb8\x4c\x1b\x5a\x41\x1c\x64\x30\xa3\xfc\x0a\xa0\x52\x5a\x35\xc9\x02\x30\xcf\xa3\x21\x50\xbe\xb6\x42\x79\xb2\xb7\x5a\x86\x52\x35\x8b\x30\x4d\x4e\x2e\xb3\xc2\xf8\xa8\xec\x87\x82\x60\x23\xac\xf3\x70\x7b\xff\x16\x84\x02\x5f\x50\x94\x09\xf4\x06\x32\x19\x9c\x27\x7b\x4f\x76\x27\x32\xaa\x7c\x23\xae\xdf\x4c\x07\xf0\x8b\xd3\xea\x35\xfa\x62\x05\x4b\x56\xf7\x72\x7c\xd0\x4f\x9f\xff\xdc\x19\x97\x6c\x78\x7b\xff\xb6\xf3\xce\x1f\x58\x42\xe7\xad\x50\xdb\x29\x8e\xd1\x18\xab\x77\x28\xa1\xd4\x39\x4d\xf0\x52\xd3\x9d\x2c\xfb\xea\xf4\xc3\xc8\xda\xc3\x53\x46\xe5\x0f\x4d\xd9\xfb\x90\xa6\x5c\x6b\x2d\xa9\xf2\x96\x9a\x78\xf7\x05\x4a\x53\xe0\x17\xd5\x4b\x97\x15\x54\x62\x6b\x24\x6d\x48\xbd\x7a\x7d\xf7\xf6\x6f\xf7\x47\x1f\xa0\xaf\x8b\x8e\xcb\x41\xce\x51\x48\x2e\x1a\xb0\x72\x9c\x18\x3d\x6c\x48\x04\x47\xd1\xa2\x6d\x04\x9c\xb0\xa9\xd7\xbf\x50\xe6\x3b\xaf\x2d\xfd\x1a\x84\xa5\xbc\xbb\x3a\x6b\xa4\x8e\xf1\xa3\xd7\xac\x9d\xce\x2b\x63\x79\x2d\xdf\x89\xa4\xf4\x74\x92\x4c\xef\xfd\x91\x64\x2f\x58\xfc\x44\xd7\x93\xac\x72\x78\xca\x2b\x9d\xb1\x50\xbe\x10\x0e\x2c\x19\x4b\x8e\x94\x6f\x85\x56\x95\x4c\x4b\x60\x67\x24\xeb\x38\xea\x82\xcc\x39\x11\xed\xc8\x7a\xb0\x94\xe9\xad\x12\xff\x6d\x66\x73\xe0\x75\x8a\x00\xf4\xe4\x3c\xc4\x10\x52\x28\x61\x87\x32\xd0\x4b\x40\x95\x43\x89\x07\xb0\xc4\xf3\x42\x50\x9d\x19\x22\x89\x5b\xc2\x77\xda\xb2\x01\x36\x7a\x05\x85\xf7\xc6\xad\x6e\x6e\xb6\xc2\xd7\x29\x34\xd3\x65\x19\x94\xf0\x87\x9b\x98\x0d\xc5\x3a\xb0\x35\x6e\x72\xda\x91\xbc\x71\x62\xbb\x40\x9b\x15\xc2\x53\xe6\x83\xa5\x1b\x34\x62\x11\x99\x55\x31\x8d\x2e\xcb\xfc\x13\x5b\x25\x5d\xf7\xe2\x48\x7d\x83\xfe\x0b\x75\xde\x9a\xd4\x35\xe7\x2f\x10\x8e\xdd\x24\x0e\x4f\xb2\xb4\x2a\xe5\x57\xac\x95\x37\xff\xb8\x7f\x80\x9a\x81\xa4\xf6\xa4\xe1\x96\xd4\xb5\xca\x66\x45\x09\xb5\x21\x9b\x28\x37\x56\x97\x71\x16\x52\xb9\xd1\x42\xf9\xf8\x47\x26\x05\x29\x0f\x2e\xac\x4b\xe1\x5d\xf4\x39\x72\x9e\xed\xb0\x84\xdb\x58\x41\x60\x4d\x10\x4c\x8e\x9e\xf2\x25\xdc\x29\xb8\xc5\x92\xe4\x2d\x3a\xfa\xc3\x55\xcd\x1a\x75\x0b\x56\xdf\x7c\x65\x77\x0b\xe0\xe9\x80\x93\x18\x03\xa8\x4b\xd4\xa8\x75\x3a\x31\x7e\x6f\x28\x6b\xa2\xa1\x89\xe9\x57\xc6\x48\x91\x25\xb7\x6f\xbc\x83\x1d\x79\xdd\x24\x82\x5e\x56\x9a\x64\x67\x2c\xec\x21\x95\x97\xd3\xb4\xd9\xff\x74\xb2\x10\x7f\x9a\x55\x46\x60\x22\x67\x40\xcc\x1b\x69\xe9\xd3\x2f\x47\xfa\xaa\x53\x3b\x3b\x34\x7b\x58\x70\x64\xdb\x82\x61\xb4\x14\xd9\x01\x36\xda\x72\x7e\xe8\xe8\x76\x09\x77\x1e\xca\xe0\xa2\xbf\x69\x45\xac\xd9\xeb\x57\xc1\xeb\x12\xbd\xc8\xae\x41\x5b\xb8\xfe\x0e\x55\x40\x79\xbd\x1c\x60\x61\xd4\x21\x5a\xde\x87\x54\x3a\x5c\x23\xda\x67\x5c\x75\xe3\x73\xa1\xb5\x78\x18\xf8\x2a\x3c\x95\x83\xc3\xce\x70\xbf\x25\xc5\x45\x63\x20\x63\xb7\x43\x39\x51\x6e\xc9\x9e\x7c\x4f\xde\x38\x3e\x6e\x64\xc9\x34\xac\x41\x3a\x17\x8d\x77\x1e\x7d\x38\x91\xb3\xe7\x22\xd7\xdd\x98\x8a\xe4\x9d\x04\x56\x15\xd0\x8d\xb6\x65\x8a\x29\x5c\xeb\x90\x92\x55\x9a\x9a\x3d\xc3\x79\x32\xae\x09\x15\x0e\xb6\x4c\x97\x46\x92\xef\xd7\xde\x25\xfc\x47\x41\xb5\x02\xa7\x43\x6f\x51\xc8\x38\x15\x66\x3e\xa0\x8c\x33\x52\x55\xa1\x0f\xce\x53\xb9\xbc\x7e\x9e\x48\xcd\xd0\xa3\xd4\xdb\xfb\x94\x0d\x06\x08\x4c\x81\x8e\x2e\x89\x3f\xef\x49\x05\xce\xc2\x95\x33\xbe\xca\x32\x1d\x94\x7f\x43\x9b\xf3\x21\x39\x3e\x16\x2c\x6d\xc8\x92\xca\xaa\xfa\xee\x12\x01\x60\xa2\x00\x5f\xa0\xe7\x48\x0e\x2e\xa9\x39\xd7\x09\x07\xe7\x0d\x94\xa9\x15\x3e\x1e\x95\x83\xca\x3b\x27\x2f\x4c\x62\x95\x61\x31\x5f\xdf\xd5\xf8\x24\xc1\x12\xaa\xa5\xf3\x43\xcc\xc1\xb9\x28\xe0\x67\x23\x48\xe6\x11\x7f\xce\xe1\xe0\xc5\x5d\xa5\xd0\x58\xc5\xbd\x06\x04\x23\x28\xa3\x1e\x1c\x8a\x0a\x23\xcc\xab\x97\x5c\xf0\x2c\x55\xdf\x5e\xa6\x5a\x5d\xc1\x80\x16\x2e\x79\x14\x0a\x90\x71\x81\xc8\xe1\x5f\xf7\x3f\x7c\x7f\xf3\x4f\x9d\x78\x63\x4b\x91\x73\xc9\x93\x4b\x52\xfe\x25\xb8\x90\x15\x80\x8e\x59\x63\xf7\x64\xff\xa7\x65\x89\x4a\x6c\xc8\xf9\x65\x35\x1b\x59\xf7\xd3\x97\x3f\x2f\xe1\x1b\x6d\x81\xde\x21\x07\xcf\x4b\x10\x49\x6b\x0d\xa8\xa8\x5c\x23\xa6\x72\x16\xa6\x19\x0b\x7b\xe1\x8b\xc8\x92\xd1\x79\xc5\xf4\x3e\x32\xeb\xf1\x91\xf3\x77\x62\x36\x70\x2f\xf3\x48\x2b\xb8\x4e\xad\x49\xb3\xf4\x6f\x0c\xc3\x7f\xbf\x86\x4f\xf7\x05\x59\x82\x6b\xfe\xf3\x3a\x2d\xd8\x60\x40\x7e\x57\xdb\xb1\x5d\x38\x3a\xa4\xb7\x62\xbb\xa5\x18\xf9\x0c\x68\x18\x34\x7c\xc6\x15\x42\x6c\x40\xe9\x0e\x71\x9c\x82\xf5\x69\x28\x13\x1b\x41\xf9\x09\x23\x3f\x7d\xf9\xf3\x35\x7c\xda\x97\x0b\x84\xca\xe9\x1d\x7c\x99\xda\x31\xe1\x58\xc6\xcf\x96\xf0\x10\x2d\x73\x50\x1e\xdf\xf1\x9c\x59\xa1\x1d\x29\xd0\x4a\x1e\x98\xe3\x02\x77\x04\x4e\x97\x04\x7b\x92\x72\x91\x50\x42\x0e\x7b\x3c\xb0\x0c\xb5\x2a\xd9\xaa\x08\x06\xad\x3f\x42\xc8\x0f\x3f\x7c\xfd\xc3\x2a\xad\xc6\x66\xdb\x2a\x5e\x82\xd1\xd7\x46\x30\xfe\x65\xe0\x9b\x50\x5c\xb4\x39\x33\x12\x92\x91\x38\xf5\x15\xa8\xb6\x54\x37\x8f\x9b\xc0\x78\x6a\x79\x8c\x98\x66\x7b\xfc\x10\x5c\x1d\x76\xf6\x08\x5b\x8f\x03\xed\x4f\x04\x85\xb3\x45\x8c\x3d\xe0\x2c\x11\xbf\xef\xf8\xe0\xa4\x88\x8f\x61\x4d\x56\x91\xa7\x28\x65\xae\x33\xc7\x02\x66\x64\xbc\xbb\xd1\x3b\x4e\xaa\xb4\xbf\xd9\x6b\xfb\x28\xd4\x76\xc1\x4e\xb6\x48\x96\x77\x37\x71\xf7\xe3\xe6\x93\xf8\xcf\x7b\x49\x34\x5a\xaa\x87\xc5\x8a\xe4\x1f\x42\x36\x5e\xc7\xdd\x3c\x59\xb4\x1a\x52\x5f\x52\x09\x5e\xdc\xa7\x80\xcf\x8e\x47\x73\xb8\xec\x0b\x91\x15\x75\xd3\xda\xc9\x70\x25\xe6\x29\x05\xa2\x3a\xfc\xe1\x6e\xcc\x0a\x0c\x96\xd7\x3e\x2c\xaa\x7d\xb9\x05\xaa\x9c\xff\xef\x84\xf3\xfc\xfe\xc9\x1a\x0b\x62\x66\x00\xff\x78\xf7\xf5\x87\x71\xee\x20\x9e\x18\xad\xeb\xa0\x72\x49\xdf\x6a\xfd\x18\xcc\x20\x48\xe8\x09\xf4\xf7\x2e\x75\xdd\x7f\x54\x5d\x9a\x50\x0b\x63\xf5\xd6\x72\xad\xec\x74\xb9\x60\x82\x4c\xe9\x35\x28\x83\xd9\x23\x6e\xa9\x5a\x34\x96\x11\xee\x8d\xab\x72\x54\xb5\x02\xe3\x30\xe7\x09\xb8\x7f\x94\xfb\xb4\x1b\x50\xf1\x39\xc2\x66\x5d\x17\x99\xc7\x88\x60\x2b\xbe\xcf\xf3\x7b\x16\x98\x4d\x61\xdb\xf4\x1c\x21\xdc\x37\xb4\x19\x25\x14\x39\xfb\xfd\x46\x0c\xb4\x27\x35\x89\x41\x5f\x8c\x7e\xb4\x64\x24\x0e\x81\x68\x98\x01\x21\xe1\x84\xcf\x31\xba\x23\x6b\xdc\x1e\x0d\xab\x2d\x52\x27\x8c\x4a\xcb\x3d\xb2\xf8\xa6\xb2\x02\x8b\x04\x7b\x74\x31\x03\xc9\x1d\xe5\x71\x03\x66\x0c\x87\xce\xb0\xc8\x3c\x69\x61\x16\x6c\x1e\x90\xf7\x09\xe0\xb9\xcb\xf8\x44\x3a\x4a\xcf\x59\x20\x3d\xc0\xd3\x5f\x70\xfa\x2f\x38\xfd\x91\xc3\xe9\x8b\x62\x60\x0a\x5a\x0f\xb9\xff\xc7\x0a\xb0\x2f\x12\x7a\x0a\x6c\x0f\x09\xfd\x91\x40\xee\x8b\x65\x9c\x84\xdf\x63\x82\x7e\x24\x20\xfc\x22\x61\x67\x02\xf2\x21\x91\xff\x9f\x61\xf9\x45\x3a\x9c\x80\xe8\x43\x7a\xfb\x28\x80\xfa\x6c\x01\x33\xad\xd2\x29\xf8\x04\x4a\xe9\x63\xad\x66\xc0\xf1\x3e\x30\x33\x8d\xb2\xb7\x4f\xdb\x85\xc9\xe7\xe0\xd4\x18\x24\x4f\xcf\x04\x30\xef\x4e\x72\x06\x93\x9d\xc7\xca\xe9\x59\x54\xdb\xd7\x67\x88\x78\xcd\x09\x92\x79\x08\x10\x40\xa2\xf3\x0f\x16\x95\x13\xf5\x0d\x8e\x69\xfa\x23\x8b\x7c\x8b\xdc\x76\x88\xb2\xe9\x32\x92\x7d\xc0\x37\x53\x56\x80\x36\x1e\xd5\x54\xfb\xf2\x8c\x69\x94\xf6\xc5\x58\xd3\xd1\x3e\x33\xa3\x84\x9f\x74\x0e\xb0\x82\x1c\x3d\x2d\x98\xa3\xb3\x62\xff\x18\x0f\x2b\x9f\x4d\x64\xc6\xf0\xc6\xea\x35\xe5\x7f\x9a\x54\x25\x39\x87\xdb\xcb\xc4\x79\x05\x45\x28\x51\x81\x25\xcc\x71\x2d\xa9\x9e\x84\xd1\x58\x3c\xad\x54\x5b\xc8\xc9\xa3\x90\xae\x73\xc2\xd2\xda\xf7\xd9\x84\xb5\x84\xee\x5c\x95\x80\xd3\x2b\x26\x69\x58\x3c\x28\xec\xd9\xe3\x85\x8b\x46\xfe\x23\x38\x1d\x3e\xb9\x9a\xe4\xf4\xbe\x39\x91\xea\x31\xf9\xb2\x3e\xc1\x7c\xb0\x81\x5e\xc2\x37\x28\x1d\xbd\x84\x1f\xd5\xa3\xd2\xfb\xe7\xe3\x37\x12\x5e\xa4\xd7\x83\x89\x5c\x35\x7c\x3e\x03\x2b\x6d\x77\x3f\x33\xd9\xdf\x35\x03\xea\x1d\x9a\xaa\x43\x5f\x04\x25\x7e\x0d\xfd\x46\xa5\x39\x64\xfa\xf4\xb8\x85\xb9\xbd\x7f\x1b\x9d\x23\xb5\xdb\x2e\x35\x32\x75\x6b\x77\x7b\xff\xd6\x7d\x76\xa6\x36\x4c\x4a\x65\x26\x1b\xd5\x9e\x3c\xdc\xd3\x1e\xb5\x5a\x52\x67\x9d\xab\x3f\xed\xb6\x8c\x09\x52\x2e\xe1\xce\xbf\x70\xcc\x83\xc8\x50\xca\x03\x77\x2d\xa2\xe4\xc0\x6c\x50\xcf\xb9\xaa\x36\xcd\xf9\x8c\x02\x71\x12\x6c\xb4\xd9\x50\xe6\xc5\x8e\x3a\xc3\x6b\x45\xa7\x0d\x27\xca\x2b\x39\xde\x8b\xb9\x7a\x2b\x67\x26\x6b\x6f\x2a\xf2\xda\x51\xba\xf6\x6f\xb5\x5a\x4d\x9a\x7a\xcd\xe8\x34\x8a\x60\xa3\x83\xca\x01\x7d\x34\xcf\x13\x79\xee\x9f\xe1\x7e\xb8\x03\xff\x69\xfc\xf4\x3c\x9b\x8d\x9d\x13\xf8\x06\x7d\x4d\x81\xaf\x36\xc9\xd1\x3b\xca\x42\xe7\x8e\x57\xf7\x0e\xc7\xd3\xf6\x1a\xcf\xbb\xec\x25\x68\x66\x56\xfa\x9c\x5b\x7f\xe7\xe2\x89\x67\x5d\xf4\x6c\xb9\x9f\x15\x69\xd3\x55\x77\x18\x7f\xbf\x49\x45\x37\x6e\x75\x66\x58\x92\xcc\xd0\x51\x7e\x5c\x8b\x13\x18\x9f\x53\x80\x67\x30\x7a\xae\xe8\xce\x98\x62\xba\x0e\x9e\x75\xfb\x58\x15\x13\xd5\xba\xbe\x05\xd1\xb4\x1b\x3d\xff\xe6\x7c\x82\x90\x91\x8d\x45\x26\x5d\xa2\x43\xd6\xd5\xbe\xd0\x4f\xce\x8c\x13\xd6\xee\xb1\xfe\x5d\x8d\xdf\x78\xc1\x88\xed\x16\x27\xd8\xae\xaa\x7f\x2d\xb6\xa3\xbc\x77\x95\x26\x16\xc9\x12\x0f\xf1\x6a\x5a\x69\xb4\xf5\x98\x0e\x38\x82\xca\xc9\x3a\x8f\x2a\xe7\xb1\xfb\xe2\x10\xd5\x60\x58\xe6\x02\x1d\x08\xef\x20\xf5\xc5\xbe\x32\xd8\xc5\x77\xb0\xe2\x7d\x97\xb3\x42\x76\x94\xfd\x9a\x07\x34\x10\xa1\xb7\x78\xaa\xab\x3d\xc3\x4c\x5a\x61\x9a\x31\x89\x13\x17\xab\xde\x37\xcf\xde\x7b\x32\xc7\x79\xb5\x23\x84\x8a\x70\x7c\x27\xf2\x74\x19\x89\x0c\x08\xf5\x3c\x49\xf5\xfc\x01\x4e\x3a\x98\x18\x0f\xab\x45\xb3\x4b\x33\x4a\x30\xd1\xd1\x9e\x4f\xea\xda\xa4\x9b\xf2\xe7\x62\x7f\xec\x6e\x5e\x7a\x1a\x29\xde\x33\x5d\x8e\xdf\x94\x4b\xcf\x89\x55\xeb\x5f\x5f\x4c\x58\xb7\x73\x57\x37\xde\x06\xf5\xb6\x42\x52\x87\x59\x36\x86\xb9\x5b\x10\x73\x36\x20\x16\xe9\x47\x18\x93\x14\x8f\x42\x9d\xde\x1f\xed\x12\x30\x00\x9b\x24\x68\x2f\x0e\xce\x24\x8b\x1b\x93\x93\xb4\xd5\xa1\xd4\x7b\x9e\x89\xa5\x5f\xa0\x7c\x98\x4d\xfc\x99\x13\xd5\x47\x48\xcf\x32\xd9\xf9\x5d\xf6\x99\x13\xb5\xa6\x79\xe6\xe9\x66\xec\x8f\xcf\x9c\x73\x37\x67\xe3\xf9\x19\xa0\xc7\x49\xc8\x57\xdd\xfe\x44\x4d\x32\x68\xbd\xc8\x82\x44\xdb\xc6\x7e\x4c\xf2\x27\xbf\x5b\xba\x98\x67\xe7\xd1\xfa\x31\x14\x7a\xbc\x29\x91\x28\x6b\x4e\xe3\xae\xd6\xbe\x20\xd5\x1c\xfe\xa5\x9f\x81\xc1\x9a\xb6\x5c\x3c\x8d\x91\x87\xfa\x37\x06\xed\x0d\x76\x29\x9c\x8f\xf8\xa1\xc5\x02\x73\xaf\x42\x8c\xaa\x7d\x0c\x02\x3b\xb2\x3b\xca\x57\xe0\x6d\x68\x5e\x79\x6d\x19\x17\xf5\xde\x85\x75\xc3\x5f\xab\x86\xca\x8e\xf0\xdb\xef\x57\xff\x0b\x00\x00\xff\xff\xae\xb2\xfa\x2c\x43\x37\x00\x00") +var _operatorsCoreosCom_installplansYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5b\x4b\x93\x1b\xb7\x11\xbe\xef\xaf\xe8\x5a\x1f\x64\x57\x89\x5c\xdb\xb9\x24\xbc\x29\xeb\x38\xb5\x89\x1f\x2a\xed\x5a\x17\xc7\x87\xe6\x4c\x93\x03\x2f\x06\x80\xf1\x20\xc5\xb8\xfc\xdf\x53\x0d\xcc\x93\x9c\x19\x0e\x57\x6b\x59\x95\xf2\x5c\xa4\x9d\x69\x00\xfd\xee\xaf\x01\x10\x8d\x78\x4b\xd6\x09\xad\x56\x80\x46\xd0\x3b\x4f\x8a\xff\x72\xcb\xc7\xbf\xba\xa5\xd0\x37\xbb\x2f\xae\x1e\x85\xca\x57\x70\x1b\x9c\xd7\xe5\x1b\x72\x3a\xd8\x8c\xbe\xa2\x8d\x50\xc2\x0b\xad\xae\x4a\xf2\x98\xa3\xc7\xd5\x15\x00\x2a\xa5\x3d\xf2\x6b\xc7\x7f\x02\x64\x5a\x79\xab\xa5\x24\xbb\xd8\x92\x5a\x3e\x86\x35\xad\x83\x90\x39\xd9\x38\x79\xbd\xf4\xee\xf3\xe5\xdf\x96\x9f\x5f\x01\x64\x96\xe2\xf0\x07\x51\x92\xf3\x58\x9a\x15\xa8\x20\xe5\x15\x80\xc2\x92\x56\x20\x94\xf3\x28\xa5\x91\xa8\xdc\x52\x1b\xb2\xe8\xb5\x75\xcb\x4c\x5b\xd2\xfc\x4f\x79\xe5\x0c\x65\xbc\xf6\xd6\xea\x60\x56\x30\x48\x93\x66\xab\x59\x44\x4f\x5b\x6d\x45\xfd\x37\xc0\x02\xb4\x2c\xe3\xff\x93\xe8\x77\x69\xd1\xd7\x12\x55\x7c\x2b\x85\xf3\xff\x3e\xfe\xf2\x8d\x70\x3e\x7e\x35\x32\x58\x94\x7d\x56\xe3\x07\x57\x68\xeb\xbf\x6b\x17\xe6\x85\x84\x49\x9f\x84\xda\x06\x89\xb6\x37\xea\x0a\xc0\x65\xda\xd0\x0a\xe2\x20\x83\x19\xe5\x57\x00\x95\xd2\xaa\x49\x16\x80\x79\x1e\x0d\x81\xf2\xb5\x15\xca\x93\xbd\xd5\x32\x94\xaa\x59\x84\x69\x72\x72\x99\x15\xc6\x47\x65\x3f\x14\x04\x1b\x61\x9d\x87\xdb\xfb\xb7\x20\x14\xf8\x82\xa2\x4c\xa0\x37\x90\xc9\xe0\x3c\xd9\x7b\xb2\x3b\x91\x51\xe5\x1b\x71\xfd\x66\x3a\x80\x9f\x9d\x56\xaf\xd1\x17\x2b\x58\xb2\xba\x97\xe3\x83\x7e\xfc\xfc\xa7\xce\xb8\x64\xc3\xdb\xfb\xb7\x9d\x77\xfe\xc0\x12\x3a\x6f\x85\xda\x4e\x71\x8c\xc6\x58\xbd\x43\x09\xa5\xce\x69\x82\x97\x9a\xee\x64\xd9\x57\xa7\x1f\x46\xd6\x1e\x9e\x32\x2a\x7f\x68\xca\xde\x87\x34\xe5\x5a\x6b\x49\x95\xb7\xd4\xc4\xbb\x2f\x50\x9a\x02\xbf\xa8\x5e\xba\xac\xa0\x12\x5b\x23\x69\x43\xea\xd5\xeb\xbb\xb7\x7f\xb9\x3f\xfa\x00\x7d\x5d\x74\x5c\x0e\x72\x8e\x42\x72\xd1\x80\x95\xe3\xc4\xe8\x61\x43\x22\x38\x8a\x16\x6d\x23\xe0\x84\x4d\xbd\xfe\x99\x32\xdf\x79\x6d\xe9\x97\x20\x2c\xe5\xdd\xd5\x59\x23\x75\x8c\x1f\xbd\x66\xed\x74\x5e\x19\xcb\x6b\xf9\x4e\x24\xa5\xa7\x93\x64\x7a\xef\x8f\x24\x7b\xc1\xe2\x27\xba\x9e\x64\x95\xc3\x53\x5e\xe9\x8c\x85\xf2\x85\x70\x60\xc9\x58\x72\xa4\x7c\x2b\xb4\xaa\x64\x5a\x02\x3b\x23\x59\xc7\x51\x17\x64\xce\x89\x68\x47\xd6\x83\xa5\x4c\x6f\x95\xf8\x6f\x33\x9b\x03\xaf\x53\x04\xa0\x27\xe7\x21\x86\x90\x42\x09\x3b\x94\x81\x5e\x02\xaa\x1c\x4a\x3c\x80\x25\x9e\x17\x82\xea\xcc\x10\x49\xdc\x12\xbe\xd5\x96\x0d\xb0\xd1\x2b\x28\xbc\x37\x6e\x75\x73\xb3\x15\xbe\x4e\xa1\x99\x2e\xcb\xa0\x84\x3f\xdc\xc4\x6c\x28\xd6\x81\xad\x71\x93\xd3\x8e\xe4\x8d\x13\xdb\x05\xda\xac\x10\x9e\x32\x1f\x2c\xdd\xa0\x11\x8b\xc8\xac\x8a\x69\x74\x59\xe6\x9f\xd8\x2a\xe9\xba\x17\x47\xea\x1b\xf4\x5f\xa8\xf3\xd6\xa4\xae\x39\x7f\x81\x70\xec\x26\x71\x78\x92\xa5\x55\x29\xbf\x62\xad\xbc\xf9\xc7\xfd\x03\xd4\x0c\x24\xb5\x27\x0d\xb7\xa4\xae\x55\x36\x2b\x4a\xa8\x0d\xd9\x44\xb9\xb1\xba\x8c\xb3\x90\xca\x8d\x16\xca\xc7\x3f\x32\x29\x48\x79\x70\x61\x5d\x0a\xef\xa2\xcf\x91\xf3\x6c\x87\x25\xdc\xc6\x0a\x02\x6b\x82\x60\x72\xf4\x94\x2f\xe1\x4e\xc1\x2d\x96\x24\x6f\xd1\xd1\xef\xae\x6a\xd6\xa8\x5b\xb0\xfa\xe6\x2b\xbb\x5b\x00\x4f\x07\x9c\xc4\x18\x40\x5d\xa2\x46\xad\xd3\x89\xf1\x7b\x43\x59\x13\x0d\x4d\x4c\xbf\x32\x46\x8a\x2c\xb9\x7d\xe3\x1d\xec\xc8\xeb\x26\x11\xf4\xb2\xd2\x24\x3b\x63\x61\x0f\xa9\xbc\x9c\xa6\xcd\xfe\xa7\x93\x85\xf8\xd3\xac\x32\x02\x13\x39\x03\x62\xde\x48\x4b\x9f\x7e\x39\xd2\x57\x9d\xda\xd9\xa1\xd9\xc3\x82\x23\xdb\x16\x0c\xa3\xa5\xc8\x0e\xb0\xd1\x96\xf3\x43\x47\xb7\x4b\xb8\xf3\x50\x06\x17\xfd\x4d\x2b\x62\xcd\x5e\xbf\x0a\x5e\x97\xe8\x45\x76\x0d\xda\xc2\xf5\xb7\xa8\x02\xca\xeb\xe5\x00\x0b\xa3\x0e\xd1\xf2\x3e\xa4\xd2\xe1\x1a\xd1\x3e\xe3\xaa\x1b\x9f\x0b\xad\xc5\xc3\xc0\x57\xe1\xa9\x1c\x1c\x76\x86\xfb\x2d\x29\x2e\x1a\x03\x19\xbb\x1d\xca\x89\x72\x4b\xf6\xe4\x7b\xf2\xc6\xf1\x71\x23\x4b\xa6\x61\x0d\xd2\xb9\x68\xbc\xf3\xe8\xc3\x89\x9c\x3d\x17\xb9\xee\xc6\x54\x24\xef\x24\xb0\xaa\x80\x6e\xb4\x2d\x53\x4c\xe1\x5a\x87\x94\xac\xd2\xd4\xec\x19\xce\x93\x71\x4d\xa8\x70\xb0\x65\xba\x34\x92\x7c\xbf\xf6\x2e\xe1\x3f\x0a\xaa\x15\x38\x1d\x7a\x8b\x42\xc6\xa9\x30\xf3\x01\x65\x9c\x91\xaa\x0a\x7d\x70\x9e\xca\xe5\xf5\xf3\x44\x6a\x86\x1e\xa5\xde\xde\xa7\x6c\x30\x40\x60\x0a\x74\x74\x49\xfc\x79\x4f\x2a\x70\x16\xae\x9c\xf1\x55\x96\xe9\xa0\xfc\x1b\xda\x9c\x0f\xc9\xf1\xb1\x60\x69\x43\x96\x54\x56\xd5\x77\x97\x08\x00\x13\x05\xf8\x02\x3d\x47\x72\x70\x49\xcd\xb9\x4e\x38\x38\x6f\xa0\x4c\xad\xf0\xf1\xa8\x1c\x54\xde\x39\x79\x61\x12\xab\x0c\x8b\xf9\xfa\xae\xc6\x27\x09\x96\x50\x2d\x9d\x1f\x62\x0e\xce\x45\x01\x3f\x1b\x41\x32\x8f\xf8\x73\x0e\x07\x2f\xee\x2a\x85\xc6\x2a\xee\x35\x20\x18\x41\x19\xf5\xe0\x50\x54\x18\x61\x5e\xbd\xe4\x82\x67\xa9\xfa\xf6\x32\xd5\xea\x0a\x06\xb4\x70\xc9\xa3\x50\x80\x8c\x0b\x44\x0e\xff\xba\xff\xfe\xbb\x9b\x7f\xea\xc4\x1b\x5b\x8a\x9c\x4b\x9e\x5c\x92\xf2\x2f\xc1\x85\xac\x00\x74\xcc\x1a\xbb\x27\xfb\x3f\x2d\x4b\x54\x62\x43\xce\x2f\xab\xd9\xc8\xba\x1f\xbf\xfc\x69\x09\x5f\x6b\x0b\xf4\x0e\x39\x78\x5e\x82\x48\x5a\x6b\x40\x45\xe5\x1a\x31\x95\xb3\x30\xcd\x58\xd8\x0b\x5f\x44\x96\x8c\xce\x2b\xa6\xf7\x91\x59\x8f\x8f\x9c\xbf\x13\xb3\x81\x7b\x99\x47\x5a\xc1\x75\x6a\x4d\x9a\xa5\x7f\x65\x18\xfe\xdb\x35\x7c\xba\x2f\xc8\x12\x5c\xf3\x9f\xd7\x69\xc1\x06\x03\xf2\xbb\xda\x8e\xed\xc2\xd1\x21\xbd\x15\xdb\x2d\xc5\xc8\x67\x40\xc3\xa0\xe1\x33\xae\x10\x62\x03\x4a\x77\x88\xe3\x14\xac\x4f\x43\x99\xd8\x08\xca\x4f\x18\xf9\xf1\xcb\x9f\xae\xe1\xd3\xbe\x5c\x20\x54\x4e\xef\xe0\xcb\xd4\x8e\x09\xc7\x32\x7e\xb6\x84\x87\x68\x99\x83\xf2\xf8\x8e\xe7\xcc\x0a\xed\x48\x81\x56\xf2\xc0\x1c\x17\xb8\x23\x70\xba\x24\xd8\x93\x94\x8b\x84\x12\x72\xd8\xe3\x81\x65\xa8\x55\xc9\x56\x45\x30\x68\xfd\x11\x42\x7e\xf8\xfe\xab\xef\x57\x69\x35\x36\xdb\x56\xf1\x12\x8c\xbe\x36\x82\xf1\x2f\x03\xdf\x84\xe2\xa2\xcd\x99\x91\x90\x8c\xc4\xa9\xaf\x40\xb5\xa5\xba\x79\xdc\x04\xc6\x53\xcb\x63\xc4\x34\xdb\xe3\x87\xe0\xea\xb0\xb3\x47\xd8\x7a\x1c\x68\x7f\x20\x28\x9c\x2d\x62\xec\x01\x67\x89\xf8\x5d\xc7\x07\x27\x45\x7c\x0c\x6b\xb2\x8a\x3c\x45\x29\x73\x9d\x39\x16\x30\x23\xe3\xdd\x8d\xde\x71\x52\xa5\xfd\xcd\x5e\xdb\x47\xa1\xb6\x0b\x76\xb2\x45\xb2\xbc\xbb\x89\xbb\x1f\x37\x9f\xc4\x7f\xde\x4b\xa2\xd1\x52\x3d\x2c\x56\x24\xff\x10\xb2\xf1\x3a\xee\xe6\xc9\xa2\xd5\x90\xfa\x92\x4a\xf0\xe2\x3e\x05\x7c\x76\x3c\x9a\xc3\x65\x5f\x88\xac\xa8\x9b\xd6\x4e\x86\x2b\x31\x4f\x29\x10\xd5\xe1\x77\x77\x63\x56\x60\xb0\xbc\xf6\x61\x51\xed\xcb\x2d\x50\xe5\xfc\x7f\x27\x9c\xe7\xf7\x4f\xd6\x58\x10\x33\x03\xf8\x87\xbb\xaf\x3e\x8c\x73\x07\xf1\xc4\x68\x5d\x07\x95\x4b\xfa\x46\xeb\xc7\x60\x06\x41\x42\x4f\xa0\xbf\x77\xa9\xeb\xfe\xa3\xea\xd2\x84\x5a\x18\xab\xb7\x96\x6b\x65\xa7\xcb\x05\x13\x64\x4a\xaf\x41\x19\xcc\x1e\x71\x4b\xd5\xa2\xb1\x8c\x70\x6f\x5c\x95\xa3\xaa\x15\x18\x87\x39\x4f\xc0\xfd\xa3\xdc\xa7\xdd\x80\x8a\xcf\x11\x36\xeb\xba\xc8\x3c\x46\x04\x5b\xf1\x7d\x9e\xdf\xb3\xc0\x6c\x0a\xdb\xa6\xe7\x08\xe1\xbe\xa1\xcd\x28\xa1\xc8\xd9\xef\x37\x62\xa0\x3d\xa9\x49\x0c\xfa\x62\xf4\xa3\x25\x23\x71\x08\x44\xc3\x0c\x08\x09\x27\x7c\x8e\xd1\x1d\x59\xe3\xf6\x68\x58\x6d\x91\x3a\x61\x54\x5a\xee\x91\xc5\x37\x95\x15\x58\x24\xd8\xa3\x8b\x19\x48\xee\x28\x8f\x1b\x30\x63\x38\x74\x86\x45\xe6\x49\x0b\xb3\x60\xf3\x80\xbc\x4f\x00\xcf\x5d\xc6\x27\xd2\x51\x7a\xce\x02\xe9\x01\x9e\xfe\x84\xd3\x7f\xc2\xe9\x8f\x1c\x4e\x5f\x14\x03\x53\xd0\x7a\xc8\xfd\x3f\x56\x80\x7d\x91\xd0\x53\x60\x7b\x48\xe8\x8f\x04\x72\x5f\x2c\xe3\x24\xfc\x1e\x13\xf4\x23\x01\xe1\x17\x09\x3b\x13\x90\x0f\x89\xfc\xff\x0c\xcb\x2f\xd2\xe1\x04\x44\x1f\xd2\xdb\x47\x01\xd4\x67\x0b\x98\x69\x95\x4e\xc1\x27\x50\x4a\x1f\x6b\x35\x03\x8e\xf7\x81\x99\x69\x94\xbd\x7d\xda\x2e\x4c\x3e\x07\xa7\xc6\x20\x79\x7a\x26\x80\x79\x77\x92\x33\x98\xec\x3c\x56\x4e\xcf\xa2\xda\xbe\x3e\x43\xc4\x6b\x4e\x90\xcc\x43\x80\x00\x12\x9d\x7f\xb0\xa8\x9c\xa8\x6f\x70\x4c\xd3\x1f\x59\xe4\x1b\xe4\xb6\x43\x94\x4d\x97\x91\xec\x03\xbe\x99\xb2\x02\xb4\xf1\xa8\xa6\xda\x97\x67\x4c\xa3\xb4\x2f\xc6\x9a\x8e\xf6\x99\x19\x25\xfc\xa4\x73\x80\x15\xe4\xe8\x69\xc1\x1c\x9d\x15\xfb\x87\x78\x58\xf9\x6c\x22\x33\x86\x37\x56\xaf\x29\xff\xc3\xa4\x2a\xc9\x39\xdc\x5e\x26\xce\x2b\x28\x42\x89\x0a\x2c\x61\x8e\x6b\x49\xf5\x24\x8c\xc6\xe2\x69\xa5\xda\x42\x4e\x1e\x85\x74\x9d\x13\x96\xd6\xbe\xcf\x26\xac\x25\x74\xe7\xaa\x04\x9c\x5e\x31\x49\xc3\xe2\x41\x61\xcf\x1e\x2f\x5c\x34\xf2\xef\xc1\xe9\xf0\xc9\xd5\x24\xa7\xf7\xcd\x89\x54\x8f\xc9\x97\xf5\x09\xe6\x83\x0d\xf4\x12\xbe\x46\xe9\xe8\x25\xfc\xa0\x1e\x95\xde\x3f\x1f\xbf\x91\xf0\x22\xbd\x1e\x4c\xe4\xaa\xe1\xf3\x19\x58\x69\xbb\xfb\x99\xc9\xfe\xae\x19\x50\xef\xd0\x54\x1d\xfa\x22\x28\xf1\x4b\xe8\x37\x2a\xcd\x21\xd3\xa7\xc7\x2d\xcc\xed\xfd\xdb\xe8\x1c\xa9\xdd\x76\xa9\x91\xa9\x5b\xbb\xdb\xfb\xb7\xee\xb3\x33\xb5\x61\x52\x2a\x33\xd9\xa8\xf6\xe4\xe1\x9e\xf6\xa8\xd5\x92\x3a\xeb\x5c\xfd\x69\xb7\x65\x4c\x90\x72\x09\x77\xfe\x85\x63\x1e\x44\x86\x52\x1e\xb8\x6b\x11\x25\x07\x66\x83\x7a\xce\x55\xb5\x69\xce\x67\x14\x88\x93\x60\xa3\xcd\x86\x32\x2f\x76\xd4\x19\x5e\x2b\x3a\x6d\x38\x51\x5e\xc9\xf1\x5e\xcc\xd5\x5b\x39\x33\x59\x7b\x53\x91\xd7\x8e\xd2\xb5\x7f\xab\xd5\x6a\xd2\xd4\x6b\x46\xa7\x51\x04\x1b\x1d\x54\x0e\xe8\xa3\x79\x9e\xc8\x73\xff\x0c\xf7\xc3\x1d\xf8\x4f\xe3\xa7\xe7\xd9\x6c\xec\x9c\xc0\x37\xe8\x6b\x0a\x7c\xb5\x49\x8e\xde\x51\x16\x3a\x77\xbc\xba\x77\x38\x9e\xb6\xd7\x78\xde\x65\x2f\x41\x33\xb3\xd2\xe7\xdc\xfa\x3b\x17\x4f\x3c\xeb\xa2\x67\xcb\xfd\xac\x48\x9b\xae\xba\xc3\xf8\xfb\x4d\x2a\xba\x71\xab\x33\xc3\x92\x64\x86\x8e\xf2\xe3\x5a\x9c\xc0\xf8\x9c\x02\x3c\x83\xd1\x73\x45\x77\xc6\x14\xd3\x75\xf0\xac\xdb\xc7\xaa\x98\xa8\xd6\xf5\x2d\x88\xa6\xdd\xe8\xf9\x37\xe7\x13\x84\x8c\x6c\x2c\x32\xe9\x12\x1d\xb2\xae\xf6\x85\x7e\x72\x66\x9c\xb0\x76\x8f\xf5\x6f\x6b\xfc\xc6\x0b\x46\x6c\xb7\x38\xc1\x76\x55\xfd\x6b\xb1\x1d\xe5\xbd\xab\x34\xb1\x48\x96\x78\x88\x57\xd3\x4a\xa3\xad\xc7\x74\xc0\x11\x54\x4e\xd6\x79\x54\x39\x8f\xdd\x17\x87\xa8\x06\xc3\x32\x17\xe8\x40\x78\x07\xa9\x2f\xf6\x95\xc1\x2e\xbe\x83\x15\xef\xbb\x9c\x15\xb2\xa3\xec\xd7\x3c\xa0\x81\x08\xbd\xc5\x53\x5d\xed\x19\x66\xd2\x0a\xd3\x8c\x49\x9c\xb8\x58\xf5\xbe\x79\xf6\xde\x93\x39\xce\xab\x1d\x21\x54\x84\xe3\x3b\x91\xa7\xcb\x48\x64\x40\xa8\xe7\x49\xaa\xe7\x0f\x70\xd2\xc1\xc4\x78\x58\x2d\x9a\x5d\x9a\x51\x82\x89\x8e\xf6\x7c\x52\xd7\x26\xdd\x94\x3f\x17\xfb\x63\x77\xf3\xd2\xd3\x48\xf1\x9e\xe9\x72\xfc\xa6\x5c\x7a\x4e\xac\x5a\xff\xfa\x62\xc2\xba\x9d\xbb\xba\xf1\x36\xa8\xb7\x15\x92\x3a\xcc\xb2\x31\xcc\xdd\x82\x98\xb3\x01\xb1\x48\x3f\xc2\x98\xa4\x78\x14\xea\xf4\xfe\x68\x97\x80\x01\xd8\x24\x41\x7b\x71\x70\x26\x59\xdc\x98\x9c\xa4\xad\x0e\xa5\xde\xf3\x4c\x2c\xfd\x02\xe5\xc3\x6c\xe2\xcf\x9c\xa8\x3e\x42\x7a\x96\xc9\xce\xef\xb2\xcf\x9c\xa8\x35\xcd\x33\x4f\x37\x63\x7f\x7c\xe6\x9c\xbb\x39\x1b\xcf\xcf\x00\x3d\x4e\x42\xbe\xea\xf6\x27\x6a\x92\x41\xeb\x45\x16\x24\xda\x36\xf6\x63\x92\x3f\xf9\xdd\xd2\xc5\x3c\x3b\x8f\xd6\x8f\xa1\xd0\xe3\x4d\x89\x44\x59\x73\x1a\x77\xb5\xf6\x05\xa9\xe6\xf0\x2f\xfd\x0c\x0c\xd6\xb4\xe5\xe2\x69\x8c\x3c\xd4\xbf\x31\x68\x6f\xb0\x4b\xe1\x7c\xc4\x0f\x2d\x16\x98\x7b\x15\x62\x54\xed\x63\x10\xd8\x91\xdd\x51\xbe\x02\x6f\x43\xf3\xca\x6b\xcb\xb8\xa8\xf7\x2e\xac\x1b\xfe\x5a\x35\x54\x76\x84\x5f\x7f\xbb\xfa\x5f\x00\x00\x00\xff\xff\xa9\xc5\x05\x0b\x43\x37\x00\x00") func operatorsCoreosCom_installplansYamlBytes() ([]byte, error) { return bindataRead( @@ -145,7 +145,7 @@ func operatorsCoreosCom_installplansYaml() (*asset, error) { return a, nil } -var _operatorsCoreosCom_olmconfigsYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb4\x58\x6f\x6f\xdb\x46\xd2\x7f\xef\x4f\x31\xd0\xf3\x00\xb1\x73\x12\x15\x27\x87\x5c\x4a\x20\x08\x02\xe5\x5c\x04\x89\xaf\x41\xec\xcb\x01\x67\xf9\xae\x43\x72\x44\x6d\x43\xee\xb2\xbb\xb3\xb6\xd5\xa2\xdf\xfd\x30\xbb\x24\x45\xc9\xa2\x63\xa0\xad\xde\x58\x9a\x9d\x9d\x9d\xbf\xbf\x99\x31\x36\xea\x0b\x59\xa7\x8c\x4e\x01\x1b\x45\x77\x4c\x5a\x7e\xb9\xe4\xeb\x2b\x97\x28\x33\xbf\x39\x3d\xfa\xaa\x74\x91\xc2\xc2\x3b\x36\xf5\x67\x72\xc6\xdb\x9c\xde\xd1\x4a\x69\xc5\xca\xe8\xa3\x9a\x18\x0b\x64\x4c\x8f\x00\x50\x6b\xc3\x28\x64\x27\x3f\x01\x72\xa3\xd9\x9a\xaa\x22\x3b\x2b\x49\x27\x5f\x7d\x46\x99\x57\x55\x41\x36\x08\xef\x9e\xbe\x79\x96\xbc\x4a\x9e\x1d\x01\xe4\x96\xc2\xf5\x4b\x55\x93\x63\xac\x9b\x14\xb4\xaf\xaa\x23\x00\x8d\x35\xa5\x60\xaa\x3a\x37\x7a\xa5\x4a\x97\x98\x86\x2c\xb2\xb1\x2e\xc9\x8d\x25\x23\x7f\xea\x23\xd7\x50\x2e\x2f\x97\xd6\xf8\x26\x85\x83\x3c\x51\x56\xa7\x20\x32\x95\xc6\xaa\xee\x37\xc0\x4c\x1e\x09\xdf\xa3\xe1\x3f\x7c\x3c\x5f\x84\x27\x03\xad\x52\x8e\x3f\xec\xd2\x3f\x2a\xc7\xe1\xac\xa9\xbc\xc5\x6a\xa8\x64\x20\x3b\xa5\x4b\x5f\xa1\x1d\x1c\x1c\x01\xb8\xdc\x34\x94\xc2\xa2\xf2\x8e\xc9\x1e\x01\xb4\xce\x68\xf5\x98\xb5\x06\xdf\x9c\xb6\x6a\xb9\x7c\x4d\x35\x76\x4a\x82\x98\xa6\xdf\x7e\x7a\xff\xe5\xc5\xc5\xde\x01\x40\x41\x2e\xb7\xaa\xe1\xe0\xda\x5e\x4d\x50\x0e\x10\x6c\x1b\x40\xf9\xd2\x18\xed\x54\x56\x11\xac\x8c\x85\xa8\x98\xb7\x4a\x97\x72\x27\x19\xc8\xe3\x8d\x68\x6a\xb2\x9f\x28\xe7\x01\xd9\xd2\xcf\x5e\x59\x2a\x86\x4f\x8b\xe2\x5d\x42\x0c\xc8\x8d\x95\x48\xf0\xc0\xcb\xf1\x33\x48\xbf\x1d\xfa\x9e\x0d\x4f\xc4\xd0\xc8\x07\x85\x64\x1e\x39\xe0\x35\x75\x2e\xa3\xa2\xf5\x0e\x98\x15\xf0\x5a\x39\xb0\xd4\x58\x72\xa4\x63\x2e\x0a\x19\x75\x6b\x40\x02\x17\x64\xe5\x22\xb8\xb5\xf1\x55\x21\x86\xdf\x90\x65\xb0\x94\x9b\x52\xab\x5f\x7a\x69\x0e\xd8\x84\x67\x2a\x64\x72\x0c\x4a\x33\x59\x8d\x15\xdc\x60\xe5\x69\x0a\xa8\x0b\xa8\x71\x03\x96\x44\x2e\x78\x3d\x90\x10\x58\x5c\x02\xe7\xc6\x12\x28\xbd\x32\x29\xac\x99\x1b\x97\xce\xe7\xa5\xe2\xae\xb8\x72\x53\xd7\x5e\x2b\xde\xcc\x43\x9d\xa8\xcc\x4b\xae\xce\x0b\xba\xa1\x6a\xee\x54\x39\x43\x9b\xaf\x15\x53\xce\xde\xd2\x1c\x1b\x35\x0b\xca\xea\x50\x60\x49\x5d\xfc\x5f\x17\x4d\xf7\x64\xcf\x7d\x31\x64\x8e\x25\x9c\x3b\x47\x21\xa7\x1f\xf4\xb5\x64\x77\xcc\x95\x78\x3d\xda\xb2\x75\xa9\x90\xc4\x2b\x9f\xff\x7e\x71\xb9\x4d\xa7\xe0\xf6\xe8\xe1\x2d\xab\xdb\x3a\x5b\x1c\xa5\xf4\x8a\x6c\xe4\x5c\x59\x53\x07\x29\xa4\x8b\xc6\x28\xcd\xe1\x47\x5e\x29\xd2\x0c\xce\x67\xb5\x62\x17\x12\x8c\x1c\x4b\x1c\x12\x58\x04\x6c\x81\x8c\xc0\x37\x05\x32\x15\x09\xbc\xd7\xb0\xc0\x9a\xaa\x05\x3a\xfa\xd3\x5d\x2d\x1e\x75\x33\x71\xdf\xe3\x9d\x3d\x84\xc6\xfb\x17\xee\x15\x14\x40\x07\x5f\xa3\xd1\xe9\xab\xf9\xa2\xa1\x5c\xa2\x24\x6e\x93\x5b\xa1\x86\x51\x0f\xca\xbd\x0b\x4d\xf2\xd8\xc7\xc7\xcb\x54\x3e\x2b\x42\x71\xcd\x81\x93\x3d\x15\xcf\x5a\xc6\x80\xfd\xa8\x74\xd4\x51\x70\x53\xea\xb0\x83\x19\x14\xdc\xf9\xe1\xe3\x79\x2f\x77\x5f\xcd\x6f\xa8\xfa\x2d\x75\x83\x5a\xca\xc9\x33\x0b\xd3\x28\x2a\x16\x17\x5f\x46\xd8\xf6\xf4\x7f\xb7\x7f\x4b\xdc\xec\x1d\x15\x02\x07\xad\x48\xd1\xfc\x89\x83\x49\x64\x82\xc5\xc5\x97\x49\x67\x48\x08\x44\xdf\x77\x40\x69\xc7\x58\x55\x54\x00\x76\x39\x1e\x00\x3f\xe2\xff\x14\x6e\xd7\x64\x09\x70\x97\x5c\xf4\x02\xe4\x6d\xa3\xa5\xbc\x90\x61\x8d\x0e\x32\x22\x3d\x10\xaa\x74\x08\x7a\xcb\xfd\xbd\x74\xbd\xc8\xcb\x68\x4b\x62\x07\x58\x55\xb1\xdd\x35\x98\x0b\x20\xfd\x6b\x4d\x1a\x2c\x91\x16\x33\x8a\x69\x08\xc1\xad\xaa\x2a\x81\x3f\xe9\xbd\x14\x94\x1c\x18\xe6\x26\xc1\x22\xc2\x7c\x3d\xa6\xe4\xa1\xd0\x6d\xc3\x97\x19\x53\x11\xea\xdd\x3c\x67\x64\x7f\x2f\x1c\x23\x99\x1e\x78\xfb\x5c\x8f\xbf\xfe\xec\x6c\xcf\x8d\x2e\xd4\x60\x8e\x39\x24\x14\xad\xc5\xcd\x81\x53\xc5\x54\x8f\x65\xe4\xd0\xc2\xc9\xa2\x7b\x64\x5b\x2a\x05\x31\xaa\x2a\xda\x27\x71\x47\xa9\x6d\x8e\x7d\x8d\x20\xf7\xd6\x06\x80\x64\x09\x54\xd7\xec\xde\x7e\x7a\x0f\xdd\x5c\x96\xc0\x6c\x36\x83\x4b\x21\x3b\xb6\x3e\x67\xf1\x9b\x34\x2e\x5d\x50\x11\xa4\x16\xca\x86\x6e\xe5\x44\xb8\xf8\x30\x98\xd1\x65\xe7\x4a\x51\x55\x40\x83\xbc\x86\x24\xba\x3a\xd9\xba\x22\x01\x38\x93\x54\xb8\xc3\xba\xa9\x68\x1a\xdc\x00\x67\xc6\xb4\x11\x8a\x0f\xfe\x0a\xf3\x39\x7c\xee\x3b\x40\x90\x6a\x32\x47\xf6\x26\xce\x85\xa1\x19\xc3\xca\x98\x27\x6e\xd7\x9e\x44\x2e\x7e\xd0\xe6\x56\x1f\x7a\x3a\xbc\x85\x96\x52\x58\x4e\xde\xde\xa0\xaa\x24\x7f\x97\x93\x29\x2c\x27\x9f\xac\x29\x2d\x39\x19\xb3\x84\x20\x6d\x79\x39\x79\x47\xa5\xc5\x82\x8a\xe5\x44\xc4\xfe\xa5\x41\xce\xd7\xe7\x64\x4b\xfa\x40\x9b\xd7\x41\x58\x4f\xbe\x60\x2b\x43\xe0\xe6\x75\x2d\xe7\x81\x2e\x68\x75\xb9\x69\xe8\x75\x8d\x4d\x4f\x38\xc7\xa6\xbf\xdc\x87\xce\xc1\xd5\xb5\xc0\xfc\xcd\x69\xb2\x0d\xe7\x8f\x3f\x39\xa3\xd3\xe5\x64\xab\xff\xd4\xd4\x92\x16\x0d\x6f\x96\x13\xd8\x79\x35\x5d\x4e\xc2\xbb\x1d\xbd\x53\x32\x5d\x4e\xe4\x25\x21\x5b\xc3\x26\xf3\xab\x74\x39\xc9\x36\x4c\x6e\x7a\x3a\xb5\xd4\x4c\xa5\xaa\x5f\x6f\x5f\x58\x4e\x7e\x84\xa5\x16\x65\x0d\xaf\xc9\xc6\x48\x3a\xf8\x6d\x72\x30\x11\xbf\x81\xac\x63\xc3\xdd\xf6\x33\x83\x0a\x1d\x5f\x5a\xd4\x4e\x75\x03\xfb\x28\x6b\x4d\xce\x61\x39\x7e\x6e\x09\x9d\xd1\xa3\xc7\x31\x1b\x46\x8f\xc5\x96\x83\x87\xdf\xea\x0f\x70\xc0\x86\x31\xce\xbd\xda\xbd\x7f\xb1\x03\x28\x39\x01\x16\x42\xa8\xd8\x3e\x27\xb8\xe7\x96\x42\x94\xf1\x47\xea\xbb\x85\x33\x36\x80\x3a\xc4\x2d\x69\x8b\x37\xce\xa6\x19\x49\x83\xd0\x41\x94\xd7\x05\xd9\x6a\x23\xe3\xd7\x56\x6a\xbe\x46\x5d\xca\x2c\x04\xef\x57\x11\xf8\x95\x03\x99\x93\xbe\x4a\x21\x4d\xe5\xa2\x06\xef\xba\x99\x2d\xe8\xd5\x4b\x14\xe0\x88\x05\xdf\x8a\x09\x63\x5f\x9e\x53\xc3\x52\x5d\x63\xb0\xfe\xc0\xc0\x33\xfc\xac\x8c\xad\x91\x53\x90\x61\x6d\xc6\xe3\xe9\xd1\x26\xc7\x23\x1d\xdf\x72\xc7\x01\x75\xed\x6b\x94\x6e\x86\x45\x68\xca\xfd\x99\x2e\x54\x8e\x61\x50\xed\xf0\x14\x33\xe3\x23\xc2\x6d\xe3\xd0\xba\x5a\x26\xd3\x8c\x04\x09\x43\x7d\xb6\x66\xfd\x4e\xe3\x6b\xbc\xfb\x48\xba\xe4\x75\x0a\x2f\x9e\xff\xed\xe5\xab\x11\xc6\x08\x8c\x54\x7c\x4f\x5a\x5a\xe9\x81\x3d\x68\xc4\x0d\xf7\x2f\x0e\xa6\xee\x60\x67\xd2\x0d\x9f\x49\xb9\xe5\x89\xa3\xc1\x4e\x5e\xde\xa2\x03\x47\x0c\x19\xca\x88\xe3\x1b\xf1\x8b\xa0\x7c\x98\x31\x74\x4e\x53\x50\xab\xc3\xc2\x54\x0f\xe0\xd5\x06\x4e\x9f\x4f\x21\x6b\x5d\x7c\x1f\xbe\xaf\xee\xae\x93\x03\x2a\x2b\x07\xdf\x4d\xf7\xf4\x91\x81\xc7\x87\x8e\x27\x89\x03\xb7\x8a\xd7\x61\x57\x95\xa6\xd5\xee\x63\x07\xda\x20\xf5\xfa\x7e\x2b\x70\xd2\x0c\xcb\xb0\x70\x1f\xfe\x74\x69\xab\x34\xbf\xfc\xeb\x78\x7c\x95\x56\xb5\xaf\x53\x78\x36\xc2\x12\x21\xed\x91\xd1\x8c\xcc\xdb\x29\x00\x05\xba\x4a\x8b\x75\x8d\xac\x72\x50\x85\xec\x21\x2b\x45\x76\x98\xda\x62\x74\x7b\x51\xfa\xfa\x8e\x17\x9f\xb8\x16\x87\x06\xc9\xfe\xc9\x9a\xc2\xe7\xb2\x8b\x99\x55\x58\x19\xd4\x4a\xe5\x43\x80\x92\x05\x27\x54\x43\x5c\xb1\x81\xee\xc4\xe9\xfd\x32\x1b\xf7\x5d\x42\xad\x74\xe9\xda\x27\x65\x93\x13\x00\x89\x5d\xf7\x76\x4d\xa1\xf5\x84\xd5\xbc\xbd\x63\x83\x56\x4e\x15\x64\x65\x06\x86\xd2\xa3\x45\xcd\x44\x85\xc0\x8f\x94\x60\xcb\x3b\x80\x3c\xdc\xae\x75\x5d\x35\xc6\x52\x8d\x60\x25\x2a\xb6\xab\x60\xa8\xd8\x3f\xae\x54\x4f\x9f\x3d\x7f\x30\xe4\x3d\xdf\x28\x53\x83\xcc\x64\x75\x0a\xff\xb9\x7a\x3b\xfb\x37\xce\x7e\xb9\x3e\x6e\xbf\x3c\x9b\x7d\xf7\xdf\x69\x7a\xfd\x74\xf0\xf3\xfa\xe4\xcd\xff\x8f\x48\x3a\x3c\x20\x8f\xa4\x4f\xdb\x44\xba\x21\xb1\x8b\xe8\x34\x74\x18\xb3\x82\x4b\xeb\x69\x0a\x67\x58\x39\x9a\xc2\x3f\x75\x68\x0d\xbf\xd3\x69\xa4\x7d\x3d\xae\x9d\x74\xe5\x89\xbc\x7a\x78\xf8\xe8\x59\x82\x4a\x0f\xf3\xb4\xea\x3e\xb4\x61\x3c\xce\x49\x61\x6c\x8b\x0b\x68\x87\x34\x83\x7f\x1f\x40\x40\x3c\x19\x4b\x93\x76\xbc\x4d\x72\x53\xcf\x07\xff\x5e\x90\xb9\xfa\x1c\xf5\x06\xb6\xb0\x16\x87\xd2\xfd\x4c\x77\x2c\xd8\x84\xb9\x35\xce\xf5\x6b\x89\x83\x4a\x7d\x25\xe8\x27\xd7\x08\x96\x19\xe5\x18\x06\x71\x9b\x29\xb6\x68\x37\x83\xbd\x03\x72\xd4\xe1\xbf\x1d\x8e\x56\xbe\x82\x63\x47\x04\x89\x36\x05\xdd\x47\xd7\x93\x88\xa1\x98\xa9\x4a\xf1\x26\xac\xa9\x24\x7b\x76\xa5\xda\xf9\xbf\x6e\x8c\x65\xd4\x1c\xcb\xcd\x52\x49\x77\xa0\x18\x6a\x99\x37\x29\xac\x56\xc7\x85\x76\xa7\xa7\xcf\x5f\x5c\xf8\xac\x30\x35\x2a\x7d\x56\xf3\xfc\xe4\xcd\xf1\xcf\x1e\x2b\x41\x9e\xe2\x1f\x58\xd3\x59\xcd\x27\x7f\x5c\x5b\x3c\x7d\xf9\x88\x2a\x3a\xbe\x8a\xb5\x72\x7d\x7c\x35\x6b\xbf\x3d\xed\x48\x27\x6f\x8e\x97\xc9\x83\xe7\x27\x4f\xc5\x86\x41\x05\x5e\x5f\xcd\xb6\xe5\x97\x5c\x3f\x3d\x79\x33\x38\x3b\xe9\x8a\x31\xf6\xa9\x14\xd8\xfa\x6e\x68\x71\x6c\xac\x0c\x29\x3b\x34\x9f\xf5\xe1\xdd\x26\x61\x5b\xb9\xf0\xeb\x6f\x47\xff\x0b\x00\x00\xff\xff\x65\x57\xc7\x70\x5d\x17\x00\x00") +var _operatorsCoreosCom_olmconfigsYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb4\x58\x6f\x6f\xdb\x46\xd2\x7f\xef\x4f\x31\xd0\xf3\x00\xb1\x73\x12\x15\x27\x87\x5c\x43\x20\x08\x02\xe5\x5c\x04\x89\xaf\x41\xec\xcb\x01\x67\xf9\xae\x43\x72\x44\x6d\x43\xee\xb2\xbb\xb3\xb6\xd5\xa2\xdf\xfd\x30\xbb\x24\x45\xc9\xa2\x63\xa0\xad\xde\x58\x9a\x9d\x9d\x9d\xbf\xbf\x99\x31\x36\xea\x0b\x59\xa7\x8c\x4e\x01\x1b\x45\x77\x4c\x5a\x7e\xb9\xe4\xeb\x77\x2e\x51\x66\x7e\x73\x7a\xf4\x55\xe9\x22\x85\x85\x77\x6c\xea\xcf\xe4\x8c\xb7\x39\xbd\xa3\x95\xd2\x8a\x95\xd1\x47\x35\x31\x16\xc8\x98\x1e\x01\xa0\xd6\x86\x51\xc8\x4e\x7e\x02\xe4\x46\xb3\x35\x55\x45\x76\x56\x92\x4e\xbe\xfa\x8c\x32\xaf\xaa\x82\x6c\x10\xde\x3d\x7d\xf3\x2c\x79\x95\x3c\x3b\x02\xc8\x2d\x85\xeb\x97\xaa\x26\xc7\x58\x37\x29\x68\x5f\x55\x47\x00\x1a\x6b\x4a\xc1\x54\x75\x6e\xf4\x4a\x95\x2e\x31\x0d\x59\x64\x63\x5d\x92\x1b\x4b\x46\xfe\xd4\x47\xae\xa1\x5c\x5e\x2e\xad\xf1\x4d\x0a\x07\x79\xa2\xac\x4e\x41\x64\x2a\x8d\x55\xdd\x6f\x80\x99\x3c\x12\xbe\x47\xc3\x7f\xf8\x78\xbe\x08\x4f\x06\x5a\xa5\x1c\x7f\xd8\xa5\x7f\x54\x8e\xc3\x59\x53\x79\x8b\xd5\x50\xc9\x40\x76\x4a\x97\xbe\x42\x3b\x38\x38\x02\x70\xb9\x69\x28\x85\x45\xe5\x1d\x93\x3d\x02\x68\x9d\xd1\xea\x31\x6b\x0d\xbe\x39\x6d\xd5\x72\xf9\x9a\x6a\xec\x94\x04\x31\x4d\xbf\xfd\xf4\xfe\xcb\x8b\x8b\xbd\x03\x80\x82\x5c\x6e\x55\xc3\xc1\xb5\xbd\x9a\xa0\x1c\x20\xd8\x36\x80\xf2\xa5\x31\xda\xa9\xac\x22\x58\x19\x0b\x51\x31\x6f\x95\x2e\xe5\x4e\x32\x90\xc7\x1b\xd1\xd4\x64\x3f\x51\xce\x03\xb2\xa5\x9f\xbd\xb2\x54\x0c\x9f\x16\xc5\xbb\x84\x18\x90\x1b\x2b\x91\xe0\x81\x97\xe3\x67\x90\x7e\x3b\xf4\x3d\x1b\x9e\x88\xa1\x91\x0f\x0a\xc9\x3c\x72\xc0\x6b\xea\x5c\x46\x45\xeb\x1d\x30\x2b\xe0\xb5\x72\x60\xa9\xb1\xe4\x48\xc7\x5c\x14\x32\xea\xd6\x80\x04\x2e\xc8\xca\x45\x70\x6b\xe3\xab\x42\x0c\xbf\x21\xcb\x60\x29\x37\xa5\x56\xbf\xf4\xd2\x1c\xb0\x09\xcf\x54\xc8\xe4\x18\x94\x66\xb2\x1a\x2b\xb8\xc1\xca\xd3\x14\x50\x17\x50\xe3\x06\x2c\x89\x5c\xf0\x7a\x20\x21\xb0\xb8\x04\xce\x8d\x25\x50\x7a\x65\x52\x58\x33\x37\x2e\x9d\xcf\x4b\xc5\x5d\x71\xe5\xa6\xae\xbd\x56\xbc\x99\x87\x3a\x51\x99\x97\x5c\x9d\x17\x74\x43\xd5\xdc\xa9\x72\x86\x36\x5f\x2b\xa6\x9c\xbd\xa5\x39\x36\x6a\x16\x94\xd5\xa1\xc0\x92\xba\xf8\xbf\x2e\x9a\xee\xc9\x9e\xfb\x62\xc8\x1c\x4b\x38\x77\x8e\x42\x4e\x3f\xe8\x6b\xc9\xee\x98\x2b\xf1\x7a\xb4\x65\xeb\x52\x21\x89\x57\x3e\xff\xfd\xe2\x72\x9b\x4e\xc1\xed\xd1\xc3\x5b\x56\xb7\x75\xb6\x38\x4a\xe9\x15\xd9\xc8\xb9\xb2\xa6\x0e\x52\x48\x17\x8d\x51\x9a\xc3\x8f\xbc\x52\xa4\x19\x9c\xcf\x6a\xc5\x2e\x24\x18\x39\x96\x38\x24\xb0\x08\xd8\x02\x19\x81\x6f\x0a\x64\x2a\x12\x78\xaf\x61\x81\x35\x55\x0b\x74\xf4\xa7\xbb\x5a\x3c\xea\x66\xe2\xbe\xc7\x3b\x7b\x08\x8d\xf7\x2f\xdc\x2b\x28\x80\x0e\xbe\x46\xa3\xd3\x57\xf3\x45\x43\xb9\x44\x49\xdc\x26\xb7\x42\x0d\xa3\x1e\x94\x7b\x17\x9a\xe4\xb1\x8f\x8f\x97\xa9\x7c\x56\x84\xe2\x9a\x03\x27\x7b\x2a\x9e\xb5\x8c\x01\xfb\x51\xe9\xa8\xa3\xe0\xa6\xd4\x61\x07\x33\x28\xb8\xf3\xc3\xc7\xf3\x5e\xee\xbe\x9a\xdf\x50\xf5\x5b\xea\x06\xb5\x94\x93\x67\x16\xa6\x51\x54\x2c\x2e\xbe\x8c\xb0\xed\xe9\xff\x6e\xff\x96\xb8\xd9\x3b\x2a\x04\x0e\x5a\x91\xa2\xf9\x13\x07\x93\xc8\x04\x8b\x8b\x2f\x93\xce\x90\x10\x88\xbe\xef\x80\xd2\x8e\xb1\xaa\xa8\x00\xec\x72\x3c\x00\x7e\xc4\xff\x29\xdc\xae\xc9\x12\xe0\x2e\xb9\xe8\x05\xc8\xdb\x46\x4b\x79\x21\xc3\x1a\x1d\x64\x44\x7a\x20\x54\xe9\x10\xf4\x96\xfb\x7b\xe9\x7a\x91\x97\xd1\x96\xc4\x0e\xb0\xaa\x62\xbb\x6b\x30\x17\x40\xfa\xd7\x9a\x34\x58\x22\x2d\x66\x14\xd3\x10\x82\x5b\x55\x55\x02\x7f\xd2\x7b\x29\x28\x39\x30\xcc\x4d\x82\x45\x84\xf9\x7a\x4c\xc9\x43\xa1\xdb\x86\x2f\x33\xa6\x22\xd4\xbb\x79\xce\xc8\xfe\x5e\x38\x46\x32\x3d\xf0\xf6\xb9\x1e\x7f\xfd\xd9\xd9\x9e\x1b\x5d\xa8\xc1\x1c\x73\x48\x28\x5a\x8b\x9b\x03\xa7\x8a\xa9\x1e\xcb\xc8\xa1\x85\x93\x45\xf7\xc8\xb6\x54\x0a\x62\x54\x55\xb4\x4f\xe2\x8e\x52\xdb\x1c\xfb\x1a\x41\xee\xad\x0d\x00\xc9\x12\xa8\xae\xd9\xbd\xfd\xf4\x1e\xba\xb9\x2c\x81\xd9\x6c\x06\x97\x42\x76\x6c\x7d\xce\xe2\x37\x69\x5c\xba\xa0\x22\x48\x2d\x94\x0d\xdd\xca\x89\x70\xf1\x61\x30\xa3\xcb\xce\x95\xa2\xaa\x80\x06\x79\x0d\x49\x74\x75\xb2\x75\x45\x02\x70\x26\xa9\x70\x87\x75\x53\xd1\x14\x96\x3a\x78\x02\xce\x8c\x69\x83\x14\xdf\xfc\x15\xe6\x73\xf8\xdc\x37\x81\x20\xd8\x64\x8e\xec\x4d\x1c\x0d\x43\x3f\x86\x95\x31\x4f\xdc\xae\x49\x89\x5c\xfc\xa0\xcd\xad\x3e\xf4\x7a\x78\x0b\x2d\xa5\xb0\x9c\xbc\xbd\x41\x55\x49\x0a\x2f\x27\x53\x58\x4e\x3e\x59\x53\x5a\x72\x32\x69\x09\x41\x3a\xf3\x72\xf2\x8e\x4a\x8b\x05\x15\xcb\x89\x88\xfd\x4b\x83\x9c\xaf\xcf\xc9\x96\xf4\x81\x36\xaf\x83\xb0\x9e\x7c\xc1\x56\xe6\xc0\xcd\xeb\x5a\xce\x03\x5d\x00\xeb\x72\xd3\xd0\xeb\x1a\x9b\x9e\x70\x8e\x4d\x7f\xb9\x8f\x9e\x83\xab\x6b\x41\xfa\x9b\xd3\x64\x1b\xd1\x1f\x7f\x72\x46\xa7\xcb\xc9\x56\xff\xa9\xa9\x25\x33\x1a\xde\x2c\x27\xb0\xf3\x6a\xba\x9c\x84\x77\x3b\x7a\xa7\x64\xba\x9c\xc8\x4b\x42\xb6\x86\x4d\xe6\x57\xe9\x72\x92\x6d\x98\xdc\xf4\x74\x6a\xa9\x99\x4a\x61\xbf\xde\xbe\xb0\x9c\xfc\x28\x31\x99\xcf\xc1\xf0\x9a\x6c\x0c\xa6\x83\xdf\x26\x07\x73\xf1\x1b\xe0\x3a\x36\xdf\x6d\x3f\x33\xa8\xd0\xf1\xa5\x45\xed\x54\x37\xb3\x8f\xb2\xd6\xe4\x1c\x96\xe3\xe7\x96\xd0\x19\x3d\x7a\x1c\xb3\x61\xf4\x58\x6c\x39\x78\xf8\xad\x16\x01\x07\x6c\x18\xe3\xdc\x2b\xdf\xfb\x17\x3b\x8c\x92\x13\x60\x21\x84\xa2\xed\x73\x82\x7b\x6e\xa9\x45\x99\x80\xa4\xc4\x5b\x44\x63\x03\xa8\x43\xdc\x92\xb6\x7e\xe3\x78\x9a\x91\xf4\x08\x1d\x44\x79\x5d\x90\xad\x36\x32\x81\x6d\xa5\xe6\x6b\xd4\xa5\x8c\x43\xf0\x7e\x15\xb1\x5f\x39\x90\x51\xe9\xab\x14\xd2\x54\x2e\x6a\xf0\xae\x1b\xdb\x82\x5e\xbd\x44\xc1\x8e\x58\xf3\xad\x98\x30\xf9\xe5\x39\x35\x2c\xd5\x35\x86\xec\x0f\xcc\x3c\xc3\xcf\xca\xd8\x1a\x39\x05\x99\xd7\x66\x3c\x9e\x1e\x6d\x72\x3c\xd2\xf1\x2d\x77\x9c\x51\xd7\xbe\x46\x69\x68\x58\x84\xbe\xdc\x9f\xe9\x42\xe5\x18\x66\xd5\x0e\x52\x31\x33\x3e\x82\xdc\x36\x0e\xad\xab\x65\x38\xcd\x48\xc0\x30\xd4\x67\x6b\xd6\xef\x34\xbe\xc6\xbb\x8f\xa4\x4b\x5e\xa7\xf0\xe2\xf9\xdf\x5e\x7e\x37\xc2\x18\x81\x91\x8a\xef\x49\x4b\x37\x3d\xb0\x0a\x8d\xb8\xe1\xfe\xc5\xc1\xe0\x1d\xec\x4c\xba\xf9\x33\x29\xb7\x3c\x71\x3a\xd8\xc9\xcb\x5b\x74\xe0\x88\x21\x43\x99\x72\x7c\x23\x7e\x11\xa0\x0f\x63\x86\xce\x69\x0a\x6a\x75\x58\x98\xea\x01\xbc\xda\xc0\xe9\xf3\x29\x64\xad\x8b\xef\xc3\xf7\xd5\xdd\x75\x72\x40\x65\xe5\xe0\xd5\x74\x4f\x1f\x99\x79\x7c\x68\x7a\x92\x38\x70\xab\x78\x1d\xd6\x55\xe9\x5b\xed\x4a\x76\xa0\x13\x52\xaf\xef\xb7\x02\x27\xfd\xb0\x0c\x3b\xf7\xe1\x4f\x97\xb6\x4a\xf3\xcb\xbf\x8e\xc7\x57\x69\x55\xfb\x3a\x85\x67\x23\x2c\x11\xd2\x1e\x19\xcd\xc8\xbc\x1d\x04\x50\xa0\xab\xb4\x58\xd7\xc8\x2a\x07\x55\xc8\x2a\xb2\x52\x64\x87\xa9\x2d\x46\xb7\x17\xa5\xb5\xef\x78\xf1\x89\x6b\x71\x68\x90\xec\x9f\xac\x29\x7c\x2e\xeb\x98\x59\x85\xad\x41\xad\x54\x3e\x04\x28\xd9\x71\x42\x35\xc4\x2d\x1b\xe8\x4e\x9c\xde\xef\xb3\x71\xe5\x25\xd4\x4a\x97\xae\x7d\x52\x96\x39\x01\x90\xd8\x75\x6f\xd7\x14\x5a\x4f\xd8\xce\xdb\x3b\x36\x68\xe5\x54\x41\x56\xc6\x60\x28\x3d\x5a\xd4\x4c\x54\x08\xfc\x48\x09\xb6\xbc\x03\xc8\xc3\xed\x66\xd7\x55\x63\x2c\xd5\x08\x56\xa2\x62\xbb\x0d\x86\x8a\xfd\xe3\x4a\xf5\xf4\xd9\xf3\x07\x43\xde\xf3\x8d\x32\x35\xc8\x4c\x56\xa7\xf0\x9f\xab\xb7\xb3\x7f\xe3\xec\x97\xeb\xe3\xf6\xcb\xb3\xd9\xab\xff\x4e\xd3\xeb\xa7\x83\x9f\xd7\x27\x6f\xfe\x7f\x44\xd2\xe1\x19\x79\x24\x7d\xda\x26\xd2\xcd\x89\x5d\x44\xa7\xa1\xc3\x98\x15\x5c\x5a\x4f\x53\x38\xc3\xca\xd1\x14\xfe\xa9\x43\x6b\xf8\x9d\x4e\x23\xed\xeb\x71\xed\xa4\x2b\x4f\xe4\xd5\xc3\xc3\x47\xcf\x12\x54\x7a\x98\xa7\x55\xf7\xa1\x25\xe3\x71\x4e\x0a\x63\x5b\xdc\x41\x3b\xa4\x19\xfc\x07\x01\x02\xe2\xc9\x58\x9a\xb4\x13\x6e\x92\x9b\x7a\x3e\xf8\x0f\x83\x8c\xd6\xe7\xa8\x37\xb0\x85\xb5\x38\x94\xee\x67\xba\x63\xc1\x26\xcc\xad\x71\xae\xdf\x4c\x1c\x54\xea\x2b\x41\x3f\xb9\x46\xb0\xcc\x28\xc7\x30\x8b\xdb\x4c\xb1\x45\xbb\x19\xac\x1e\x90\xa3\x0e\xff\xf0\x70\xb4\xf2\x15\x1c\x3b\x22\x48\xb4\x29\xe8\x3e\xba\x9e\x44\x0c\xc5\x4c\x55\x8a\x37\x61\x53\x25\x59\xb5\x2b\xd5\xae\x00\x75\x63\x2c\xa3\xe6\x58\x6e\x96\x4a\xba\x03\xc5\x50\xcb\xbc\x49\x61\xbb\x3a\x2e\xb4\x3b\x3d\x7d\xfe\xe2\xc2\x67\x85\xa9\x51\xe9\xb3\x9a\xe7\x27\x6f\x8e\x7f\xf6\x58\x09\xf2\x14\xff\xc0\x9a\xce\x6a\x3e\xf9\xe3\xda\xe2\xe9\xcb\x47\x54\xd1\xf1\x55\xac\x95\xeb\xe3\xab\x59\xfb\xed\x69\x47\x3a\x79\x73\xbc\x4c\x1e\x3c\x3f\x79\x2a\x36\x0c\x2a\xf0\xfa\x6a\xb6\x2d\xbf\xe4\xfa\xe9\xc9\x9b\xc1\xd9\x49\x57\x8c\xb1\x4f\xa5\xc0\xd6\x77\x43\x8b\x63\x63\x65\x48\xd9\xa1\xf9\xac\x0f\xef\x36\x09\xdb\xca\x85\x5f\x7f\x3b\xfa\x5f\x00\x00\x00\xff\xff\x1e\x16\x84\x1b\x60\x17\x00\x00") func operatorsCoreosCom_olmconfigsYamlBytes() ([]byte, error) { return bindataRead( @@ -165,7 +165,7 @@ func operatorsCoreosCom_olmconfigsYaml() (*asset, error) { return a, nil } -var _operatorsCoreosCom_operatorconditionsYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5b\xdd\x6f\x1b\xb9\x11\x7f\xf7\x5f\x31\x50\x0b\xc4\x4e\xa5\x55\x9c\x2b\xae\x39\x01\x41\x10\xe4\x9a\x22\x48\x7c\x09\x62\xf7\x1e\x6a\xb9\xcd\xec\x72\x24\xf1\xb2\x4b\xee\x91\x5c\xd9\xba\xc3\xfd\xef\xc5\x90\xfb\x25\x69\xa5\xf8\x90\x34\x68\x0b\xf2\xc5\x12\x3f\x86\xc3\xf9\xfe\xd1\x14\x96\xf2\x47\x32\x56\x6a\x35\x03\x2c\x25\xdd\x39\x52\xfc\xcd\x26\x1f\x9f\xd8\x44\xea\xe9\xfa\xfc\xe4\xa3\x54\x62\x06\x2f\x2a\xeb\x74\xf1\x9e\xac\xae\x4c\x46\xdf\xd3\x42\x2a\xe9\xa4\x56\x27\x05\x39\x14\xe8\x70\x76\x02\x80\x4a\x69\x87\xdc\x6d\xf9\x2b\x40\xa6\x95\x33\x3a\xcf\xc9\x4c\x96\xa4\x92\x8f\x55\x4a\x69\x25\x73\x41\xc6\x13\x6f\xb6\x5e\x3f\x4a\x9e\x24\x8f\x4e\x00\x32\x43\x7e\xf9\x95\x2c\xc8\x3a\x2c\xca\x19\xa8\x2a\xcf\x4f\x00\x14\x16\x34\x03\x5d\x92\x41\xa7\x4d\xa6\x95\xf0\xdb\xdb\xa4\xe9\xb2\x49\xa6\x0d\x69\xfe\x53\x9c\xd8\x92\x32\xe6\x60\x69\x74\x55\x76\xcb\xb6\xe6\x04\x9a\x0d\xa3\xe8\x68\xa9\x8d\x6c\xbe\x03\x4c\x40\xe7\x85\xff\x1c\x04\xf0\xb6\xa6\xf1\xa2\xd9\xda\x8f\xe5\xd2\xba\xd7\xc3\xe3\x6f\xa4\x75\x7e\x4e\x99\x57\x06\xf3\x21\xe6\xfd\xb0\x5d\x69\xe3\x7e\xe8\x58\xe1\xad\xb3\xad\x4d\xac\x54\xcb\x2a\x47\x33\x40\xe2\x04\xc0\x66\xba\xa4\x19\x78\x0a\x25\x66\x24\x4e\x00\x6a\xc9\xd6\x14\x27\xb5\xf4\xd6\xe7\xf5\x06\x36\x5b\x51\x81\xcd\x76\xc0\x64\xd5\xf3\x77\xaf\x7e\xfc\xe6\x72\x67\x00\x40\x90\xcd\x8c\x2c\x9d\xd7\xd3\xde\x19\x41\x5a\xc0\xda\x36\xa0\x31\x0e\xd0\x0b\x70\x9b\x92\xe0\xc3\xde\xfc\x0f\x70\xbb\x92\xd9\x8a\x97\x55\x96\x04\x38\xcd\x47\x5d\xd3\x06\xa4\x5a\x68\x53\x78\xe5\x73\xef\xdb\x37\x17\x80\xa9\xae\x1c\xb8\x15\x81\x75\xe8\x3c\x59\x54\xad\x08\x92\x1e\x93\xbc\xdb\x0c\x74\xfa\x13\x65\xae\xd7\x6d\xe8\xe7\x4a\x1a\x12\xfd\xf3\xb0\x34\x1a\x93\xed\x75\x97\x86\xe9\xba\x9e\xfe\x43\xeb\x39\xc8\x56\xff\x8e\x60\x1e\xb0\xf4\xc2\x3c\x10\xec\x1b\x64\x3d\xe3\xb5\x1e\x48\xd4\x22\xf7\xa2\x59\x49\x0b\x86\x4a\x43\x96\x54\xf0\x96\xe6\x68\xfe\x00\x09\x5c\x92\xe1\x85\x6c\x19\x55\x2e\x82\x84\x8c\x03\x43\x99\x5e\x2a\xf9\x4b\x4b\xcd\xb2\xa4\x78\x9b\x1c\x1d\x59\x07\x52\x39\x32\x0a\x73\x58\x63\x5e\xd1\x18\x50\x09\x28\x70\x03\x86\x98\x2e\x54\xaa\x47\xc1\x4f\xb1\x09\x5c\x68\x43\x5e\xf8\x33\x58\x39\x57\xda\xd9\x74\xba\x94\xae\x71\xff\x4c\x17\x45\xa5\xa4\xdb\x4c\xbd\x27\xcb\xb4\x62\x2f\x9a\x0a\x5a\x53\x3e\xb5\x72\x39\x41\x93\xad\xa4\xa3\xcc\x55\x86\xa6\x58\xca\x89\x67\x56\x05\xd7\x2c\xc4\x1f\x4c\x6d\x13\xf6\xc1\x8e\xf8\x82\xca\xac\x33\x52\x2d\xb7\x86\xbc\xb7\x1d\x95\x35\xfb\x5b\x30\xbc\xb0\x3c\x9c\xa5\x13\x29\x77\xb1\x54\xde\xff\xf5\xf2\x0a\x1a\x06\x82\xd8\x83\x84\xbb\xa9\xb6\x13\x36\x0b\x4a\xaa\x05\x99\x30\x73\x61\x74\xe1\xa9\x90\x12\xa5\x96\x2a\x18\x62\x96\x4b\x52\x0e\x6c\x95\x16\xd2\x59\x6f\x60\x64\x1d\xeb\x21\x81\x17\x3e\xfa\x41\x4a\x50\x95\x02\x1d\x89\x04\x5e\x29\x78\x81\x05\xe5\x2f\xd0\xd2\x7f\x5c\xd4\x2c\x51\x3b\x61\xf1\xdd\x5f\xd8\xfd\xe0\xbd\xbf\x60\xcf\xa1\x00\x9a\xc0\x7a\x50\x3b\x7b\x2e\x7f\x59\x52\x06\x98\xe7\xfa\x96\x35\x96\xe5\x95\x75\x64\x00\x45\x21\xd5\x01\xf7\x3f\xee\xf7\x75\x74\x18\x43\xa9\x1d\x9f\x1e\xf3\x7c\x03\x7a\x4d\xc6\x48\xc1\x9a\x0f\x6b\x0c\x95\xda\x38\x12\x90\x6e\x3c\xa5\xa1\xa8\x71\xf4\xa0\x87\x43\x42\x38\x72\x99\xeb\x4d\xc1\x16\xb4\x3f\xd8\x50\x45\x63\x70\x33\x30\x2a\x1d\x15\x83\xcb\x8e\x28\x8a\x5b\x7d\xc8\x21\x7e\x3e\x63\xcb\x2d\xed\x8d\xba\xc8\xce\x56\x88\x52\x59\x10\xe4\x50\xe6\x16\x16\xda\x80\x56\x04\xc8\x36\xe0\x42\x24\x23\xc8\x2a\x63\xbc\x4b\x34\xaa\xf2\xde\xf3\xfc\xdd\xab\x36\x1d\x24\x30\x99\x4c\xe0\x8a\xbb\xad\x33\x55\xe6\xd8\x77\x39\x54\x29\x41\xc2\x53\x15\xd2\xf8\xf8\x64\x99\x38\xeb\xda\x1f\x03\x30\x18\xc1\x42\x52\x2e\xa0\x44\xb7\x82\x84\x77\xa9\x38\x7d\xb7\xe9\x1f\xe0\xa5\x36\x40\x77\x58\x94\x39\x8d\x43\xde\x79\xa9\xf5\xa5\x9f\x58\x6f\xf8\x2b\x4c\xa7\xf0\xbe\xf5\xf9\x60\x10\xa9\x25\xb3\x0e\xb5\x8a\xb7\x30\x58\x68\xfd\xc0\x6e\x9f\x27\xe1\x85\xaf\x95\xbe\x55\x43\x5b\xfb\xbd\xd0\xd0\x0c\xe6\xa3\xe7\x6b\x94\x39\xa6\x39\xcd\x47\x63\x98\x8f\xde\x19\xbd\x34\x64\x39\x71\x73\x07\x07\xe2\xf9\xe8\x7b\x5a\x1a\x14\x24\xe6\x23\x26\xfb\xa7\x12\x5d\xb6\xba\x20\xb3\xa4\xd7\xb4\x79\xea\x89\xb5\xdd\x97\xce\x70\x41\xb2\x79\x5a\xf0\xb8\xef\xe7\x4a\xe3\x6a\x53\xd2\xd3\x02\xcb\xb6\xe3\x02\xcb\x76\x71\xab\x3a\x0b\xd7\x37\xec\xd8\xeb\xf3\xa4\x53\xe7\x87\x9f\xac\x56\xb3\xf9\xa8\xe3\x7f\xac\x0b\x36\x8b\xd2\x6d\xe6\x23\xd8\xda\x75\x36\x1f\xf9\x7d\x9b\xfe\x86\xc9\xd9\x7c\xc4\x3b\x71\xb7\xd1\x4e\xa7\xd5\x62\x36\x1f\xa5\x1b\x47\x76\x7c\x3e\x36\x54\x8e\xb9\xcc\x78\xda\xed\x30\x1f\x7d\x80\xb9\x62\x66\xb5\x5b\x91\x09\x9a\xb4\xf0\xdb\xe8\x88\xed\x0f\xba\x62\x68\xc3\xe9\xbc\x6b\x9c\xd8\xad\xc5\x25\x1d\x1c\x37\x84\xb6\xae\xa9\x86\x86\x83\x8a\x0f\x0e\x33\x83\x83\x83\xc7\x22\x45\x68\x39\x5a\x77\x65\x50\x59\xd9\x54\xb7\x87\x66\xee\x38\xe4\xfe\x42\xf6\x9e\x90\xf3\xad\x03\xc7\x1d\xde\x0d\x5b\x45\xbb\x76\x36\x7b\x17\x67\x31\x76\xda\x70\x34\x8e\x9d\xa8\xbc\x32\x92\xda\x23\x43\x89\x91\x12\xdc\xae\x48\x79\x52\x95\x12\x64\xf2\x0d\xc7\xd2\x8e\x6a\xb6\x42\xb5\xe4\x94\x06\xaf\xd8\xc5\xd1\x3b\x31\xa7\xbb\x8f\xec\x1d\x63\x5e\xa8\xa0\xb2\x4d\xea\xf5\x7c\xb5\x14\x39\x1a\x04\x2f\xae\xc9\xf8\xec\x9d\x65\x54\x3a\x76\x99\xdd\x98\xdc\xb5\xa3\xe1\xb0\x69\x21\x71\xcc\x80\x73\xee\x84\x37\x3e\x30\xb3\x36\x8e\x7b\x0a\xbe\x9e\x1d\xea\x8c\x55\x55\xa0\x62\xeb\x11\xcc\x6f\x37\xa6\x84\xcc\xd0\xd7\x1b\x4d\x90\xec\x72\x57\xa7\x87\x5a\xd4\x5c\x60\xa4\xc4\xe1\xcd\x3b\x5d\x7d\xac\xcf\x3c\x7c\x81\x77\x6f\x48\x2d\xdd\x6a\x06\xdf\x3c\xfe\xcb\xb7\x4f\x0e\x4c\x0c\xd1\x8e\xc4\xdf\x48\x71\x1e\x1c\x28\x67\x0f\x88\x61\x7f\x61\xaf\x78\xf2\xe7\x4c\x9a\x1a\x22\x59\x76\x73\xbc\x85\x6c\xdb\xe5\x2d\x5a\xb0\xe4\x20\x45\x2e\xfc\xab\x92\xe5\xc2\xa1\x5b\x2a\xeb\x50\x65\x34\x06\xb9\x18\x26\x26\xdb\xa8\x9c\x6f\xe0\xfc\xf1\x18\xd2\x5a\xc4\xfb\x31\xf9\xfa\xee\x26\x19\x60\x59\x5a\xf8\x6e\xbc\xc3\x0f\x57\x83\x95\x4f\x63\x6c\x38\x70\x2b\xdd\x8a\x8b\x45\x9f\xdb\xea\xb2\x7a\x20\xb7\x51\xcb\xef\xa7\x14\xc7\x19\x6e\x49\xe6\x93\x66\x2b\x95\xfb\xf6\xcf\x87\xf5\x2b\x95\x2c\xaa\x62\x06\x8f\x0e\x4c\x09\x21\xed\x9e\xda\x0c\x93\xbb\xd4\x8e\x1c\xba\x96\x06\x0b\xae\xbc\x32\x90\x82\x0b\xaa\x85\x24\xd3\x37\x6d\x3e\x74\xbd\x90\x93\xf5\x96\x14\x1f\xd8\x3a\x0e\xf5\x8c\xfd\x9d\xd1\xa2\xca\xb8\xa4\xd6\x0b\x5f\x2f\xca\x85\xcc\xfa\x01\x8a\xeb\x54\xef\x0d\x01\x29\x01\xdd\xb1\xd0\x5b\x4c\x12\x60\x0b\xa1\x92\x6a\x69\xeb\x2d\xb9\x20\xe7\x00\x12\x52\xe9\xed\x8a\x7c\x3e\xf1\x08\xab\x5e\x63\x3c\x57\x56\x0a\x32\x24\x00\x61\x59\xa1\x41\xe5\x88\x04\x87\x1f\x76\xc1\x7a\x6e\x2f\xe4\x61\x57\x9d\x37\xde\x18\x5c\x35\x04\x2b\x66\xb1\xae\xe8\xbd\xc7\x7e\x39\x57\x3d\x7f\xf4\xf8\xa8\xca\xdb\x79\x07\x27\x95\xe8\x18\xeb\xcd\xe0\x9f\xd7\xcf\x27\xff\xc0\xc9\x2f\x37\xa7\xf5\x87\x47\x93\xef\xfe\x35\x9e\xdd\x3c\xec\x7d\xbd\x39\x7b\xf6\xc7\x03\x94\x82\x07\xdd\xd3\x7c\xea\x24\xd2\x54\x7e\x8d\x46\xc7\x3e\xc3\xe8\x05\x5c\x19\x46\x9d\x2f\x31\xb7\x34\x86\xbf\x2b\x9f\x1a\x3e\x53\x68\xa4\xaa\xe2\x30\x77\x9c\x95\x47\xbc\xeb\x70\x45\xd1\x4e\xf1\x2c\x1d\x9f\x53\xb3\x7b\x60\x8e\xe7\xf5\x7e\x42\xf2\xb5\x98\x5e\xf4\x23\x4d\x0f\x05\x82\x8f\x78\x5c\x6b\x26\x75\xcd\x9a\x64\xba\x98\xf6\x50\x22\x17\xcb\x17\xa8\x36\xd0\x85\xb5\x50\x69\xee\x5a\xba\x65\xf8\x03\x98\x19\x6d\x6d\x0b\x73\x2d\xe4\xf2\x23\x41\x5b\x8e\x86\x60\x99\x52\x86\xbe\xba\x36\xa9\x74\x06\xcd\xa6\xe3\xce\x42\x86\xca\x83\x56\x4b\x8b\x2a\x87\x53\x4b\x04\x89\xd2\x82\xf6\xa3\xeb\x59\x88\xa1\x98\xca\x5c\xba\x0d\x47\x49\x41\x99\x56\x8b\x5c\xd6\x45\x7d\xc1\xa0\x0b\x95\x0b\xee\x66\x68\x49\x77\x20\x1d\x14\x5c\x44\x92\xe5\x29\xa7\x42\xd9\xf3\xf3\xc7\xdf\x5c\x56\xa9\xd0\x05\x4a\xf5\xb2\x70\xd3\xb3\x67\xa7\x3f\x57\x98\x73\xe4\x11\x3f\x60\x41\x2f\x0b\x77\xf6\xe5\xd2\xe2\xf9\xb7\xf7\xf0\xa2\xd3\xeb\xe0\x2b\x37\xa7\xd7\x93\xfa\xd3\xc3\xa6\xeb\xec\xd9\xe9\x3c\x39\x3a\x7e\xf6\x90\xcf\xd0\xf3\xc0\x9b\xeb\x49\xe7\x7e\xc9\xcd\xc3\xb3\x67\xbd\xb1\xb3\x7d\x67\xe4\x8c\x25\x33\x7a\x9e\x65\xba\xfa\x6a\x98\x72\xd8\xf7\x3f\x81\xe6\x43\x08\x68\xf0\xfc\x36\x2c\x1f\xc0\xf2\xd2\xd9\x3a\x7d\x06\xd8\x1e\x2c\xa3\x0e\x24\x1c\x60\x9d\x41\x99\x07\xb3\xca\x5c\x85\x79\x0f\xf3\x83\xdd\x58\x47\xc5\x17\x82\xec\x9d\x19\x47\xf8\x1c\xe1\x73\x84\xcf\x7b\x6d\x32\x00\x36\x23\xd2\x8e\x48\xbb\x6b\x11\x69\x47\xa4\x1d\x91\xf6\xbd\xb4\x19\x91\x76\x44\xda\xdb\x2d\x22\xed\x7a\x4e\x44\xda\x11\x69\x7f\x6d\xa4\x1d\xf2\xd4\x0c\x9c\xa9\x9a\xa2\xc5\x3a\x6d\xb8\x48\x81\x05\x9b\x6c\xd3\x59\xa5\xad\x7e\x3b\x2b\xac\x5d\x17\x7e\xfd\x6d\xfb\x39\xcd\xe3\xf8\x9c\x26\x3e\xa7\x89\xcf\x69\xe2\x73\x9a\xa6\x7d\xed\xe7\x34\xdb\xd7\x6f\xe1\xcd\xcb\xd6\x75\x9b\xb7\xd9\xd2\xe8\xb5\x14\x64\x77\x1e\xdf\xf8\x3a\x7c\x27\xcb\x14\xa8\xaa\xfe\x83\x1a\xfa\x3a\xcf\x69\xe2\xdd\x5c\xbc\x9b\x8b\x77\x73\xf1\x6e\xae\xd7\xe2\xdd\x5c\xdb\xe2\xdd\x5c\xbc\x9b\x8b\x77\x73\xf1\x6e\x2e\xde\xcd\xed\xb6\x78\x37\x17\x5a\xbc\x9b\x8b\x77\x73\x03\xed\x7f\xe3\x6e\xae\x6f\x41\xf1\x57\x15\x11\x7a\x46\xe8\xf9\x5f\x06\x3d\x23\x9e\x8c\x78\x32\xe2\xc9\x81\x16\xf1\x64\xc4\x93\x11\x4f\x46\x3c\xb9\xd7\x22\x9e\xac\xe7\x44\x3c\x19\xf1\x64\xfc\x55\xc5\xef\xfc\x55\xc5\xdb\x37\x17\xbd\x97\x1c\xe1\x85\x47\xcf\xb2\x56\xb8\x26\x48\x89\x54\x5b\x46\xc4\xff\xc2\x46\x28\x1c\xa1\x70\xfc\x2f\x2c\x44\xd4\x1c\x51\x73\x44\xcd\x11\x35\xef\x2a\x2e\xa2\xe6\x88\x9a\xb7\x55\x19\x51\xf3\xef\x17\x5a\x44\xcd\x11\x35\x0f\xa8\xe2\xff\x03\x35\x1f\xfb\x85\x44\xbf\xef\x53\x3f\x90\xf8\x77\x00\x00\x00\xff\xff\x79\xf0\xdc\xa4\x52\x56\x00\x00") +var _operatorsCoreosCom_operatorconditionsYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5b\x5f\x6f\x1b\xb9\x11\x7f\xf7\xa7\x18\xa8\x05\x62\xa7\xd2\x2a\x4e\x8a\xf4\x22\x20\x08\x82\x5c\x53\x04\x89\x2f\x41\xec\xde\x43\x2d\xb7\x99\x5d\x8e\x24\x9e\x77\xc9\x3d\x92\x2b\x5b\x77\xb8\xef\x5e\x0c\xb9\xff\x64\xad\x14\x1f\x92\x06\x6d\x41\xbe\x58\x22\x87\x43\x72\xfe\xff\x68\x0a\x4b\xf9\x23\x19\x2b\xb5\x9a\x01\x96\x92\x6e\x1d\x29\xfe\x66\x93\xeb\xef\x6c\x22\xf5\x74\x7d\x7a\x74\x2d\x95\x98\xc1\xab\xca\x3a\x5d\x7c\x24\xab\x2b\x93\xd1\xf7\xb4\x90\x4a\x3a\xa9\xd5\x51\x41\x0e\x05\x3a\x9c\x1d\x01\xa0\x52\xda\x21\x77\x5b\xfe\x0a\x90\x69\xe5\x8c\xce\x73\x32\x93\x25\xa9\xe4\xba\x4a\x29\xad\x64\x2e\xc8\x78\xe6\xcd\xd2\xeb\x47\xc9\xb3\xe4\xd1\x11\x40\x66\xc8\x4f\xbf\x90\x05\x59\x87\x45\x39\x03\x55\xe5\xf9\x11\x80\xc2\x82\x66\xa0\x4b\x32\xe8\xb4\xc9\xb4\x12\x7e\x79\x9b\x34\x5d\x36\xc9\xb4\x21\xcd\x7f\x8a\x23\x5b\x52\xc6\x3b\x58\x1a\x5d\x95\xdd\xb4\x2d\x9a\xc0\xb3\xd9\x28\x3a\x5a\x6a\x23\x9b\xef\x00\x13\xd0\x79\xe1\x3f\x07\x01\xbc\xaf\x79\xbc\x6a\x96\xf6\x63\xb9\xb4\xee\xed\xf0\xf8\x3b\x69\x9d\xa7\x29\xf3\xca\x60\x3e\xb4\x79\x3f\x6c\x57\xda\xb8\x1f\xba\xad\xf0\xd2\xd9\xd6\x22\x56\xaa\x65\x95\xa3\x19\x60\x71\x04\x60\x33\x5d\xd2\x0c\x3c\x87\x12\x33\x12\x47\x00\xb5\x64\x6b\x8e\x93\x5a\x7a\xeb\xd3\x7a\x01\x9b\xad\xa8\xc0\x66\x39\x60\xb6\xea\xe5\x87\x37\x3f\x3e\x39\xbf\x33\x00\x20\xc8\x66\x46\x96\xce\xeb\x69\xe7\x8c\x20\x2d\x60\x6d\x1b\xd0\x18\x07\xe8\x05\xb8\x4d\x49\xf0\x69\x87\xfe\x13\xdc\xac\x64\xb6\xe2\x69\x95\x25\x01\x4e\xf3\x51\xd7\xb4\x01\xa9\x16\xda\x14\x5e\xf9\xdc\xfb\xfe\xdd\x19\x60\xaa\x2b\x07\x6e\x45\x60\x1d\x3a\xcf\x16\x55\x2b\x82\xa4\xb7\x49\x5e\x6d\x06\x3a\xfd\x89\x32\xd7\xeb\x36\xf4\x73\x25\x0d\x89\xfe\x79\x58\x1a\x8d\xc9\xf6\xba\x4b\xc3\x7c\x5d\x4f\xff\xa1\xf5\x1c\x64\xab\xff\x8e\x60\x1e\xb0\xf4\x02\x1d\x08\xf6\x0d\xb2\x7e\xe3\xb5\x1e\x48\xd4\x22\xf7\xa2\x59\x49\x0b\x86\x4a\x43\x96\x54\xf0\x96\xe6\x68\xfe\x00\x09\x9c\x93\xe1\x89\x6c\x19\x55\x2e\x82\x84\x8c\x03\x43\x99\x5e\x2a\xf9\x4b\xcb\xcd\xb2\xa4\x78\x99\x1c\x1d\x59\x07\x52\x39\x32\x0a\x73\x58\x63\x5e\xd1\x18\x50\x09\x28\x70\x03\x86\x98\x2f\x54\xaa\xc7\xc1\x93\xd8\x04\xce\xb4\x21\x2f\xfc\x19\xac\x9c\x2b\xed\x6c\x3a\x5d\x4a\xd7\xb8\x7f\xa6\x8b\xa2\x52\xd2\x6d\xa6\xde\x93\x65\x5a\xb1\x17\x4d\x05\xad\x29\x9f\x5a\xb9\x9c\xa0\xc9\x56\xd2\x51\xe6\x2a\x43\x53\x2c\xe5\xc4\x6f\x56\x05\xd7\x2c\xc4\x1f\x4c\x6d\x13\xf6\xc1\x1d\xf1\x05\x95\x59\x67\xa4\x5a\x6e\x0d\x79\x6f\x3b\x28\x6b\xf6\xb7\x60\x78\x61\x7a\x38\x4b\x27\x52\xee\x62\xa9\x7c\xfc\xeb\xf9\x05\x34\x1b\x08\x62\x0f\x12\xee\x48\x6d\x27\x6c\x16\x94\x54\x0b\x32\x81\x72\x61\x74\xe1\xb9\x90\x12\xa5\x96\x2a\x18\x62\x96\x4b\x52\x0e\x6c\x95\x16\xd2\x59\x6f\x60\x64\x1d\xeb\x21\x81\x57\x3e\xfa\x41\x4a\x50\x95\x02\x1d\x89\x04\xde\x28\x78\x85\x05\xe5\xaf\xd0\xd2\x7f\x5c\xd4\x2c\x51\x3b\x61\xf1\xdd\x5f\xd8\xfd\xe0\xbd\x3b\x61\xc7\xa1\x00\x9a\xc0\xba\x57\x3b\x3b\x2e\x7f\x5e\x52\x06\x98\xe7\xfa\x86\x35\x96\xe5\x95\x75\x64\x00\x45\x21\xd5\x1e\xf7\x3f\xec\xf7\x75\x74\x18\x43\xa9\x1d\x9f\x1e\xf3\x7c\x03\x7a\x4d\xc6\x48\xc1\x9a\x0f\x73\x0c\x95\xda\x38\x12\x90\x6e\x3c\xa7\xa1\xa8\x71\xf0\xa0\xfb\x43\x42\x38\x72\x99\xeb\x4d\xc1\x16\xb4\x3b\xd8\x70\x45\x63\x70\x33\x30\x2a\x1d\x15\x83\xd3\x0e\x28\x8a\x5b\x7d\xc8\xa1\xfd\x7c\xc1\x92\x5b\xda\x1b\x75\x91\x9d\xad\x10\xa5\xb2\x20\xc8\xa1\xcc\x2d\x2c\xb4\x01\xad\x08\x90\x6d\xc0\x85\x48\x46\x90\x55\xc6\x78\x97\x68\x54\xe5\xbd\xe7\xe5\x87\x37\x6d\x3a\x48\x60\x32\x99\xc0\x05\x77\x5b\x67\xaa\xcc\xb1\xef\x72\xa8\x52\x82\x84\xe7\x2a\xa4\xf1\xf1\xc9\x32\x73\xd6\xb5\x3f\x06\x60\x30\x82\x85\xa4\x5c\x40\x89\x6e\x05\x09\xaf\x52\x71\xfa\x6e\xd3\x3f\xc0\x6b\x6d\x80\x6e\xb1\x28\x73\x1a\xc3\x5c\x85\xd4\xf3\x5a\xeb\x73\x4f\x5b\xaf\xf9\x2b\x4c\xa7\xf0\xb1\x75\xfb\x60\x13\xa9\x25\xb3\x0e\xe5\x8a\x37\x32\x58\x68\xfd\xc0\x6e\x1f\x29\xe1\x89\x6f\x95\xbe\x51\x43\xab\xfb\xb5\xd0\xd0\x0c\xe6\xa3\x97\x6b\x94\x39\xa6\x39\xcd\x47\x63\x98\x8f\x3e\x18\xbd\x34\x64\x39\x77\x73\x07\xc7\xe2\xf9\xe8\x7b\x5a\x1a\x14\x24\xe6\x23\x66\xfb\xa7\x12\x5d\xb6\x3a\x23\xb3\xa4\xb7\xb4\x79\xee\x99\xb5\xdd\xe7\xce\x70\x4d\xb2\x79\x5e\xf0\xb8\xef\xe7\x62\xe3\x62\x53\xd2\xf3\x02\xcb\xb6\xe3\x0c\xcb\x76\x72\xab\x3d\x0b\x97\x57\xec\xdb\xeb\xd3\xa4\xd3\xe8\xa7\x9f\xac\x56\xb3\xf9\xa8\xdb\xff\x58\x17\x6c\x19\xa5\xdb\xcc\x47\xb0\xb5\xea\x6c\x3e\xf2\xeb\x36\xfd\xcd\x26\x67\xf3\x11\xaf\xc4\xdd\x46\x3b\x9d\x56\x8b\xd9\x7c\x94\x6e\x1c\xd9\xf1\xe9\xd8\x50\x39\xe6\x4a\xe3\x79\xb7\xc2\x7c\xf4\x89\x75\x32\x9d\x82\x76\x2b\x32\x41\x99\x16\x7e\x1b\x1d\x30\xff\x41\x6f\x0c\x6d\x38\xa3\x77\x8d\x73\xbb\xb5\xb8\xa4\xbd\xe3\x86\xd0\xd6\x65\xd5\xd0\x70\x50\xf1\xde\x61\xde\xe0\xe0\xe0\xa1\x60\x11\x5a\x8e\xd6\x5d\x18\x54\x56\x36\x05\xee\x3e\xca\x3b\x3e\xb9\x3b\x91\x1d\x28\xa4\x7d\xeb\xc0\x71\x87\xf7\xc4\x56\xd1\xae\xa5\x66\x07\xe3\x44\xc6\x7e\x1b\x8e\xc6\xe1\x13\x95\x57\x46\x52\x3b\x65\xa8\x32\x52\x82\x9b\x15\x29\xcf\xaa\x52\x82\x4c\xbe\xe1\x70\xda\x71\xcd\x56\xa8\x96\x9c\xd5\xe0\x0d\x7b\x39\x7a\x3f\xe6\x8c\x77\xcd\xde\x31\xe6\x89\x0a\x2a\xdb\x64\x5f\xbf\xaf\x96\x23\x07\x84\xe0\xc8\x35\x1b\x9f\xc0\xb3\x8c\x4a\xc7\x2e\x73\x37\x2c\x77\xed\x60\x44\x6c\x5a\xc8\x1d\x33\xe0\xb4\x3b\xe1\x85\xf7\x50\xd6\xc6\x71\x4f\xc1\xd7\xd4\xa1\xd4\x58\x55\x05\x2a\xb6\x1e\xc1\xfb\xed\xc6\x94\x90\x19\xfa\x92\xa3\x89\x93\x5d\xfa\xea\xf4\x50\x8b\x9a\x6b\x8c\x94\x38\xc2\x79\xa7\xab\x8f\xf5\x85\x87\x2f\xf0\xf6\x1d\xa9\xa5\x5b\xcd\xe0\xc9\xe3\xbf\x3c\xfd\x6e\x0f\x61\x88\x76\x24\xfe\x46\x8a\x53\xe1\x40\x45\xbb\x47\x0c\xbb\x13\x7b\xf5\x93\x3f\x67\xd2\x94\x11\xc9\xb2\xa3\xf1\x16\xb2\x6d\x97\x37\x68\xc1\x92\x83\x14\xb9\xf6\xaf\x4a\x96\x0b\x47\x6f\xa9\xac\x43\x95\xd1\x18\xe4\x62\x98\x99\x6c\xa3\x72\xbe\x81\xd3\xc7\x63\x48\x6b\x11\xef\xc6\xe4\xcb\xdb\xab\x64\x60\xcb\xd2\xc2\xb3\xf1\x9d\xfd\x70\x41\x58\xf9\x4c\xc6\x86\x03\x37\xd2\xad\xb8\x5e\xf4\xe9\xad\xae\xac\x07\xd2\x1b\xb5\xfb\xfd\x9c\xe2\x38\xc9\x2d\xc9\x7c\xd6\x6c\xa5\x72\x4f\xff\xbc\x5f\xbf\x52\xc9\xa2\x2a\x66\xf0\x68\x0f\x49\x08\x69\xf7\xd4\x66\x20\xee\xb2\x3b\x72\xe8\x5a\x1a\x2c\xb8\xf8\xca\x40\x0a\xae\xa9\x16\x92\x4c\xdf\xb4\xf9\xd0\xf5\x44\xce\xd7\x5b\x52\x7c\x60\xeb\x38\xd4\x33\xf6\x0f\x46\x8b\x2a\xe3\xaa\x5a\x2f\x7c\xc9\x28\x17\x32\xeb\x07\x28\x2e\x55\xbd\x37\x04\xb0\x04\x74\xcb\x42\x6f\x61\x49\x40\x2e\x84\x4a\xaa\xa5\xad\x97\xe4\x9a\x9c\x03\x48\x48\xa5\x37\x2b\xf2\xf9\xc4\x83\xac\x7a\x8e\xf1\xbb\xb2\x52\x90\x21\x01\x08\xcb\x0a\x0d\x2a\x47\x24\x38\xfc\xb0\x0b\xd6\xb4\xbd\x90\x87\x5d\x81\xde\x78\x63\x70\xd5\x10\xac\x78\x8b\x75\x51\xef\x3d\xf6\xeb\xb9\xea\xe9\xa3\xc7\x07\x55\xde\xd2\xed\x25\x2a\xd1\x31\xdc\x9b\xc1\x3f\x2f\x5f\x4e\xfe\x81\x93\x5f\xae\x8e\xeb\x0f\x8f\x26\xcf\xfe\x35\x9e\x5d\x3d\xec\x7d\xbd\x3a\x79\xf1\xc7\x3d\x9c\x82\x07\xdd\xd3\x7c\xea\x24\xd2\x14\x7f\x8d\x46\xc7\x3e\xc3\xe8\x05\x5c\x18\x06\x9e\xaf\x31\xb7\x34\x86\xbf\x2b\x9f\x1a\xbe\x50\x68\xa4\xaa\x62\xff\xee\x38\x2b\x8f\x78\xd5\xe1\x8a\xa2\x25\xf1\x5b\x3a\x4c\x53\x6f\x77\x0f\x8d\xdf\xeb\xfd\x84\xe4\x6b\x31\xbd\xe8\x47\x9a\x1e\x10\x04\x1f\xf1\xb8\xd6\x4c\xea\xb2\x35\xc9\x74\x31\xed\x01\x45\xae\x97\xcf\x50\x6d\xa0\x0b\x6b\xa1\xd2\xbc\x6b\xe9\x96\x11\x10\x60\x66\xb4\xb5\x2d\xd2\xb5\x90\xcb\x6b\x82\xb6\x1c\x0d\xc1\x32\xa5\x0c\x7d\x81\x6d\x52\xe9\x0c\x9a\x4d\xb7\x3b\x0b\x19\x2a\x8f\x5b\x2d\x2d\xaa\x1c\x8e\x2d\x11\x24\x4a\x0b\xda\x8d\xae\x27\x21\x86\x62\x2a\x73\xe9\x36\x1c\x25\x05\x65\x5a\x2d\x72\x59\xd7\xf5\x05\xe3\x2e\x54\x2e\xb8\x9b\xa1\x25\xdd\x82\x74\x50\x70\x11\x49\x96\x49\x8e\x85\xb2\xa7\xa7\x8f\x9f\x9c\x57\xa9\xd0\x05\x4a\xf5\xba\x70\xd3\x93\x17\xc7\x3f\x57\x98\x73\xe4\x11\x3f\x60\x41\xaf\x0b\x77\xf2\xf5\xd2\xe2\xe9\xd3\x7b\x78\xd1\xf1\x65\xf0\x95\xab\xe3\xcb\x49\xfd\xe9\x61\xd3\x75\xf2\xe2\x78\x9e\x1c\x1c\x3f\x79\xc8\x67\xe8\x79\xe0\xd5\xe5\xa4\x73\xbf\xe4\xea\xe1\xc9\x8b\xde\xd8\xc9\xae\x33\x72\xc6\x92\x19\xbd\xcc\x32\x5d\x7d\x33\x58\x39\xec\xfb\x9f\x01\xf4\x21\x04\x34\x90\x7e\x1b\x99\x0f\xc0\x79\xe9\x6c\x9d\x3e\x03\x72\x0f\x96\x51\x07\x12\x0e\xb0\xce\xa0\xcc\x83\x59\x65\xae\xc2\xbc\x07\xfb\xc1\x6e\xac\xa3\xe2\x2b\xa1\xf6\xce\x8c\x23\x82\x8e\x08\x3a\x22\xe8\xa1\x36\x19\xc0\x9b\x11\x6c\x47\xb0\xdd\xb5\x08\xb6\x23\xd8\x8e\x60\xfb\x5e\xda\x8c\x60\x3b\x82\xed\xed\x16\xc1\x76\x4d\x13\xc1\x76\x04\xdb\xdf\x1a\x6c\x87\x3c\x35\x03\x67\xaa\xa6\x68\xb1\x4e\x1b\x2e\x52\x60\xc1\x26\xdb\x74\x56\x69\xab\xdf\xce\x0a\x6b\xd7\x85\x5f\x7f\xdb\x7e\x54\xf3\x38\x3e\xaa\x89\x8f\x6a\xe2\xa3\x9a\xf8\xa8\xa6\x69\xdf\xfa\x51\xcd\xf6\x0d\x5c\x78\xf9\xb2\x75\xe3\xe6\x6d\xb6\x34\x7a\x2d\x05\xd9\x3b\x4f\x70\x7c\x1d\x7e\x27\xcb\x14\xa8\xaa\xfe\xb3\x1a\xfa\x36\x8f\x6a\xe2\xf5\x5c\xbc\x9e\x8b\xd7\x73\xf1\x7a\x6e\xbb\xc5\xeb\xb9\xb6\xc5\xeb\xb9\x78\x3d\x17\xaf\xe7\xe2\xf5\x5c\xbc\x9e\xbb\xdb\xe2\xf5\x5c\x68\xf1\x7a\x2e\x5e\xcf\x0d\xb4\xff\x8d\xeb\xb9\xbe\x05\xc5\x9f\x57\x44\xf4\x19\xd1\xe7\x7f\x1f\xfa\x8c\x90\x32\x42\xca\x08\x29\x07\x5a\x84\x94\x11\x52\x46\x48\x19\x21\xe5\x4e\x8b\x90\xb2\xa6\x89\x90\x32\x42\xca\xf8\xf3\x8a\xdf\xf9\xf3\x8a\xf7\xef\xce\x7a\xef\x39\xc2\x3b\x8f\x9e\x65\xad\x70\x4d\x90\x12\xa9\xb6\x8c\x88\xff\x8b\x8d\x68\x38\xa2\xe1\xf8\xbf\xd8\xba\x45\xe0\x1c\x81\x73\x04\xce\x11\x38\x6f\x29\x2e\x02\xe7\x08\x9c\xb7\x55\x19\x81\xf3\xef\x17\x5a\x04\xce\x11\x38\x0f\xa8\xe2\xff\x03\x38\x1f\xfa\xa9\x44\xbf\xef\x73\xbf\x94\xf8\x77\x00\x00\x00\xff\xff\x0a\x10\x91\x5e\x61\x56\x00\x00") func operatorsCoreosCom_operatorconditionsYamlBytes() ([]byte, error) { return bindataRead( @@ -185,7 +185,7 @@ func operatorsCoreosCom_operatorconditionsYaml() (*asset, error) { return a, nil } -var _operatorsCoreosCom_operatorgroupsYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5a\x79\x6f\x23\x37\x96\xff\xbf\x3f\xc5\x83\x66\x81\xb6\xb3\x3a\xda\x9d\x45\x36\x23\x20\x08\x8c\xee\x74\xe0\x4d\xb7\xdb\x68\xbb\xb3\xc0\x5a\xde\x1d\xaa\xea\x55\x89\x63\x16\x59\x43\xb2\x24\x6b\x82\x7c\xf7\xc5\x7b\x64\x1d\xba\xe5\x1c\xb3\x93\x85\xea\x1f\x5b\x3c\xdf\xc1\xf7\x7b\x07\x29\x4a\xf9\x23\x5a\x27\x8d\x1e\x83\x28\x25\x3e\x79\xd4\xf4\xcb\x0d\x1f\xbf\x76\x43\x69\x46\xf3\x8b\x17\x8f\x52\xa7\x63\x78\x53\x39\x6f\x8a\x4f\xe8\x4c\x65\x13\x7c\x8b\x99\xd4\xd2\x4b\xa3\x5f\x14\xe8\x45\x2a\xbc\x18\xbf\x00\x10\x5a\x1b\x2f\xa8\xd9\xd1\x4f\x80\xc4\x68\x6f\x8d\x52\x68\x07\x39\xea\xe1\x63\x35\xc5\x69\x25\x55\x8a\x96\x17\xaf\xb7\x9e\xbf\x1a\x7e\x3d\x7c\xf5\x02\x20\xb1\xc8\xd3\xef\x64\x81\xce\x8b\xa2\x1c\x83\xae\x94\x7a\x01\xa0\x45\x81\x63\x30\x25\x5a\xe1\x8d\xcd\xad\xa9\x4a\x37\xac\x7f\xba\x61\x62\x2c\x1a\xfa\x53\xbc\x70\x25\x26\xb4\x3b\x8f\x69\xa7\xac\x8c\x09\xeb\xd5\x44\x0a\x8f\xb9\xb1\xb2\xfe\x0d\x30\x00\xa3\x0a\xfe\x3f\x30\xff\x31\xae\xf1\x3d\x2d\xc9\xed\x4a\x3a\xff\xc3\x66\xdf\x7b\xe9\x3c\xf7\x97\xaa\xb2\x42\xad\x13\xcc\x5d\x6e\x66\xac\xbf\x6e\xb7\xe7\xed\xf2\xd0\x25\x75\x5e\x29\x61\xd7\xe6\xbd\x00\x70\x89\x29\x71\x0c\x3c\xad\x14\x09\xa6\x2f\x00\xa2\xf8\xe2\x32\x83\x28\xa2\xf9\x45\x5c\xd5\x25\x33\x2c\x44\xbd\x07\xd0\x92\xfa\xf2\xe6\xea\xc7\x2f\x6f\xd7\x3a\x00\x52\x74\x89\x95\xa5\x67\x65\xac\x30\x04\xd2\x81\x9f\x21\x54\x5a\x7a\x30\x19\x14\x95\xf2\xd2\xa3\x16\x3a\x59\x42\x66\x2c\x7c\x7c\xff\x01\x0a\xa1\x45\x8e\x69\x47\xd4\x70\xe5\x49\xf7\xce\x5b\x21\x75\x58\x41\x6a\xe7\x85\x52\xac\x5e\x5a\xa9\x19\x0c\x52\x83\xf4\x2e\x68\x84\x78\x03\x6f\x40\x00\xa9\x51\x66\x12\x53\x70\xc8\x5b\x7b\x61\x73\xf4\xed\x30\x37\xec\x70\xe0\x97\x24\x1e\x33\xfd\x2b\x26\xbe\xd3\x6c\xf1\x6f\x95\xb4\x98\x76\x99\x25\x51\xd5\x87\xb6\xd3\x5c\x5a\xa2\xc8\x77\x4e\x41\xf8\x3a\x26\xb2\xd2\xbe\x26\xb5\x97\x24\xda\x30\x0e\x52\xb2\x0e\x0c\x6c\x47\x25\x11\x1b\x2c\x76\xe6\x64\x26\x1d\x58\x2c\x2d\x3a\xd4\xbe\x91\x88\xd0\x91\x81\x21\xdc\xa2\xa5\x89\x74\x56\x2a\x95\x92\x28\xe7\x68\x3d\x58\x4c\x4c\xae\xe5\xdf\x9b\xd5\x1c\xc9\x8a\xb6\x51\xc2\xa3\xf3\x20\xb5\x47\xab\x85\x82\xb9\x50\x15\xf6\x41\xe8\x14\x0a\xb1\x04\x8b\xb4\x2e\x54\xba\xb3\x02\x0f\x71\x43\xf8\x60\x2c\x69\x27\x33\x63\x98\x79\x5f\xba\xf1\x68\x94\x4b\x5f\x03\x40\x62\x8a\x82\x94\xbf\x1c\xb1\x2d\xcb\x69\x45\x3a\x1b\xa5\x38\x47\x35\x72\x32\x1f\x08\x9b\xcc\xa4\xc7\xc4\x57\x16\x47\xa2\x94\x03\x26\x56\x33\x08\x0c\x8b\xf4\x4f\x36\x42\x86\x7b\xb9\x26\xbe\xa0\x32\xe7\xad\xd4\xf9\x4a\x17\xdb\xdc\x5e\x59\x93\xe5\xd1\xc9\x14\x71\x7a\xe0\xa5\x15\x29\x35\x91\x54\x3e\x7d\x77\x7b\x07\x35\x01\x41\xec\x41\xc2\xed\x50\xd7\x0a\x9b\x04\x25\x75\x86\x36\x8c\xcc\xac\x29\x78\x15\xd4\x69\x69\xa4\xf6\xfc\x23\x51\x12\xb5\x07\x57\x4d\x0b\x3a\xb4\x74\xc0\xd0\x79\xd2\xc3\x10\xde\x30\xfe\xc1\x14\xa1\x2a\x53\xe1\x31\x1d\xc2\x95\x86\x37\xa2\x40\xf5\x46\x38\xfc\xdd\x45\x4d\x12\x75\x03\x12\xdf\xf1\xc2\xee\xc2\xf7\xe6\x84\x0d\x83\x02\xa8\xe1\x75\xa7\x76\x56\xf0\xe3\xb6\xc4\xa4\xc6\x10\x9a\xc9\x98\x21\xf4\x1a\xc8\xd4\x2a\x1a\x1e\x4b\x04\x6d\x99\x89\x4a\xf9\x75\x4a\x00\xaa\x32\xb7\x22\xc5\x5b\x6f\x09\xd6\x97\x63\x78\x1b\x46\xae\x0d\xdc\x65\xee\xcc\x22\x2a\x4c\xbc\xb1\x9b\x3d\x6b\xac\xde\xc6\x81\x71\x46\x60\x73\x85\xb5\x97\x6e\x3f\x6e\x1d\xc1\xe9\x21\x6a\xe9\x2b\x84\x4f\x66\xdf\x3d\xd1\x99\xee\xb8\x84\x03\xd4\xaf\x4f\x0a\x16\x45\x9e\x8d\xd0\x48\x89\x29\xaa\x46\x14\x35\x92\x16\xc1\x64\xee\x66\xb8\xd2\x02\xc2\x22\x5c\x5e\xbf\xc5\x74\x1b\x73\x2d\x83\xc2\x5a\xb1\xdc\x31\x42\x7a\x2c\x76\x12\xbe\x46\xfa\xe5\x1e\xf2\x22\x30\xd4\x3d\x7e\x26\xd8\x17\x79\xf6\x44\x01\xf4\xfa\x20\xe0\x11\x97\x01\x1f\x09\x76\xa3\xca\xc2\x60\x8b\x8c\xa6\xac\xcc\x47\x5c\xf2\xa0\x08\x96\x3b\xa9\x3b\xa0\xbf\xf0\x6d\xf7\x46\xab\xdf\x80\xb6\xdc\xdb\x5f\x13\xbb\x73\xd0\xa1\xc3\x12\xbe\x47\x5c\xee\xeb\x5e\x13\x38\xc9\x21\x9a\x71\x90\x3c\x35\xb0\xb4\xd8\xb2\x6b\x61\x8b\xb2\x54\x12\x19\x0d\xf7\xae\xbd\x13\x8e\x56\xbf\x9a\xd5\x67\x10\xda\xa8\xb2\x45\xf8\xa0\xec\x97\x2e\x28\x96\x4e\xfa\x4c\x96\x31\xc8\x08\xa1\x45\xed\x0a\x7f\x14\x4a\x76\xc2\x18\x3e\xd5\x57\xba\x0f\xd7\xc6\xd3\x9f\xef\x9e\x24\x41\x3d\x9d\x87\xb7\x06\xdd\xb5\xf1\xdc\xf2\x9b\xb0\x1a\x48\x78\x06\xa3\x61\x02\x1f\x76\x1d\xec\x8a\x38\xe9\xfa\x43\x0a\xc3\x32\xd6\x4f\x23\x14\xe9\xc8\x23\x19\x5b\x73\xc4\x11\x4a\x58\x28\x2c\x51\x54\x8e\x1d\x98\x36\x7a\x80\x45\xe9\x97\x5b\xd7\x88\x82\x30\x76\x45\x0e\x7b\x96\x8b\x4b\xdd\x91\x5f\x0d\x3d\x21\x02\x52\x14\xca\x42\x5a\x31\xd1\xec\xcd\x09\xb4\x65\x02\x05\xda\x1c\xa1\x24\x84\x3a\x46\xbc\xfb\x70\x25\x7c\x07\xd0\xe5\x48\x5d\x31\x64\xbe\x27\x03\x78\x06\xc4\x86\xf1\x01\x96\x0a\x51\x92\x9a\x7e\x22\xf4\x61\x49\xfd\x0c\xa5\x90\x14\x31\x5f\x72\xf4\xaf\x70\xa5\x4f\x6a\x96\x69\x77\x19\x5a\x41\x3a\x20\x28\x99\x0b\x45\x78\x47\x27\x59\x03\xaa\x80\x7e\x14\xa4\xaf\x01\x7b\x1f\x16\x33\xe3\x02\x98\x65\x12\x15\xc7\x4e\xbd\x47\x5c\xf6\xfa\x1b\xaa\xed\x5d\xe9\x5e\xc0\xc5\x0d\x65\x36\x20\x6a\xb4\x5a\x42\x8f\xfb\x7a\xbf\xdc\x17\xec\x05\x4b\x91\xa6\x9c\x5e\x0a\x75\x73\x04\x9a\xed\xd5\x9b\x43\x3b\x97\x09\x5e\x26\x89\xa9\x34\x27\x5e\x47\xf8\xf5\xf5\x29\x35\xf8\x89\xb4\x90\x7a\x25\x37\xe1\x91\x20\xc2\x50\x58\xcc\x64\x32\x83\x85\x54\x8a\xc3\x40\x87\x29\xa9\x27\xc5\x52\x99\x65\x23\xe7\x33\x77\x1e\x34\x4b\xf1\x68\x2d\x7b\xce\xf4\x76\x87\x06\xbb\x98\xa3\xf4\x21\xb9\xb1\x66\x2e\x53\x4c\x2f\x6f\xae\xb6\x4a\x69\x95\x39\x9e\x02\x1e\x95\x72\x9c\xbe\x51\xcc\xea\x4d\x8c\x59\xb7\x86\x30\x65\x67\xfd\x4e\x92\xbf\x93\xd8\xa9\x31\x0a\xc5\x66\x7f\x08\x85\x9a\x24\xf6\x30\xad\x77\x6b\x13\x22\xdc\xe1\x53\xa9\x64\x22\x7d\x8d\xdf\x6d\x6c\xc5\xf9\x10\x4f\x62\xe0\x92\x1c\x0d\x38\xf4\xfd\x36\x56\x93\x0e\x64\xae\x8d\xdd\x7e\x3e\xf7\xe3\xc9\x1e\x14\x39\x80\x1d\x4f\x83\xc7\x6a\x8a\x56\xa3\x47\x37\xa0\x18\x6b\x10\x27\xe0\xa6\x09\xac\x87\xb0\x87\xa4\xd4\xfb\xbc\x3a\x61\x25\x01\x8d\x8b\xd5\xd8\x1a\xb2\xf6\x95\xe4\x9b\x46\x35\x12\x64\x7b\xb6\xc8\x46\x9c\x54\xd6\xa2\xf6\x6a\x09\x7e\x61\xc0\x55\x65\x69\xac\xc7\x74\x7d\x49\x32\x4d\x98\xe8\x3a\xd0\x1e\xf3\xa1\x62\x13\x60\xa0\x10\x4a\x99\x05\x24\xaa\x72\x1e\x6d\xb4\xac\x98\x29\xb3\xba\x0a\x33\xc7\x3a\x8d\x0d\x2e\x81\x9c\x41\x39\x13\x0e\xdb\x1c\xcc\x55\x49\x82\x98\x62\x1a\x3a\xa2\x2b\xc1\x2c\xc3\xc4\xcb\x39\xaa\x25\x14\x28\xb8\xd2\x20\x7c\xbb\x3f\x9d\xec\xb0\x7d\xcb\xf0\xda\x8e\x1a\x9f\x7c\x9d\xa4\x83\xe4\x24\x7c\xb5\x52\x61\x1b\x76\x67\xc2\x41\x26\xa4\xa2\xbc\x6e\xa2\xe1\x0e\x93\xd9\x8d\xc5\xb9\xc4\xc5\x67\xed\x44\x86\xef\x84\x54\xef\x8c\x5d\x08\x9b\x76\x64\xf0\x7b\xb0\x4f\x54\x35\x7d\x81\xa4\x5a\x2e\x97\x0d\x70\xaa\x65\xbf\xa5\x22\x47\x4d\x02\x20\x7e\x17\x35\x83\x37\x8a\x24\xb6\x98\xa1\x26\xd7\x5b\x4d\x9b\x13\x05\x16\x33\xb4\xa8\xc9\x9e\x44\xbd\x7e\x67\x52\xe3\x1e\x12\xe1\x85\x32\x39\x4b\x66\x8a\xa8\xeb\xbc\x17\x16\xd2\xcf\x40\xf0\x66\xb5\xf4\x32\x0e\xaf\x11\x90\x42\x05\x62\x31\xda\x6e\xa7\x68\x34\xd1\xf0\x9f\x97\x9f\xae\xaf\xae\xbf\x1f\xb3\x57\xd9\x27\xe1\xcd\x73\x2d\x1d\x54\x3c\xaa\x53\xf5\x70\x95\xf2\x74\xc4\x2b\x8d\x4f\x25\x26\x44\xda\x14\x67\x62\x2e\xc9\x06\x6c\xac\x87\xcc\xd1\x8a\xa9\x42\xa0\x34\x18\x94\x71\xb4\x8e\x42\xe7\x60\x69\x2a\x98\x89\x39\x42\x8a\x58\x42\xa5\x53\xb4\xce\x0b\x9d\x12\xf5\x26\x8b\x91\xef\x2a\x13\x30\x45\xea\xad\x2b\x62\x1b\xd6\xd5\x7b\x2e\xc0\xb7\x99\xee\x8e\x44\x96\x3e\xd4\x55\xb1\x1d\x95\x06\x7b\x66\x51\xef\x3e\x11\xaf\xa6\xfd\x5e\xf8\x6a\x03\xfa\xf6\x24\xfe\x3c\xbe\x49\xfd\xc3\xaf\x6d\xc9\xff\xa7\xe7\xe7\xfe\xbb\xf3\xa8\x01\x28\xe1\xfc\xe7\x70\x0a\x9f\x91\xf1\x27\x46\x07\xb3\x39\xec\x92\xde\x34\x43\xd7\x63\xef\x6d\x9e\xb3\x5d\xf8\x37\x75\x36\xab\xf0\xdf\x90\xd4\x86\x68\x29\x7a\x21\x55\x90\xb8\xd1\x08\x82\x42\x16\x5f\x53\x19\x81\x9d\xd5\x82\x4d\x45\xf2\xf2\xe6\x0a\x1a\x6d\xc0\x60\x30\x08\x20\xeb\xbc\xad\x12\xf6\xa3\x52\x7b\xd4\x04\x42\xb4\x6a\x2a\x2d\x97\x14\x1d\x2d\xde\xca\x21\x66\x84\x21\xcc\x2c\x85\x9f\xc1\x30\x28\x7f\xd8\x11\x05\xc0\x3b\x63\x01\x9f\x44\x51\x2a\xec\xb3\x18\xe0\x9d\x31\xf1\xcc\x84\x0d\x7f\x82\xd1\x08\x3e\xb5\x49\x1c\x07\xaa\x53\x8a\xb7\x42\x0e\xc7\x15\x53\xc8\x8c\x21\x29\x77\xf9\x19\xd2\xc4\x1f\xb4\x59\xe8\x6d\x5b\xf3\x5e\xc2\xe2\x18\x26\xbd\xcb\xb9\x90\x8a\x4c\x7f\xd2\xeb\xc3\xa4\x77\x63\x4d\xce\x21\xb3\xce\x27\x31\x06\x9e\xf4\xde\x22\xc3\x4c\x3a\xe9\xd1\xb2\xff\xca\x19\xc9\x07\x4a\x4e\x7e\xc0\xe5\x37\xbc\x58\xd3\x5c\xbb\xdf\x6f\x42\xf2\x42\xed\xe4\xe8\xef\x96\x25\x7e\x43\x51\x7b\xdd\xf0\x41\x94\xcd\xe4\xce\x69\xba\x7f\x28\xd0\x8b\xf9\xc5\xb0\x55\xe7\x5f\xfe\xea\x8c\x1e\x4f\x7a\x2d\xfd\x7d\x53\xd0\xb1\x28\xfd\x72\xd2\x83\x95\x5d\xc7\x93\x1e\xef\x5b\xb7\xd7\x44\x8e\x27\x3d\xda\x89\x9a\xad\xf1\x66\x5a\x65\xe3\x49\x6f\xba\xf4\xe8\xfa\x17\x7d\x8b\x65\x9f\xc0\xe9\x9b\x76\x87\x49\xef\x2f\x04\xc4\xa3\x11\x18\x3f\x43\x1b\x34\xe9\xe0\xe7\x6d\xc8\x75\x44\x28\x7f\xa8\xe6\x11\x2c\xf6\xce\x0a\xed\x64\x7d\xf3\xb3\x73\x68\x81\xce\x89\x7c\x77\xbf\x45\xe1\xb6\x86\xa5\xa1\x3b\x9c\x86\x9d\xdd\xc4\xcb\xd6\xce\xc3\x05\x95\x4d\x1e\x8e\x2c\x64\x6d\x4e\x6c\xcb\x2c\xce\x83\xa7\x06\xb6\xd8\xe6\x4c\xf8\x66\x34\x19\x22\x05\x01\x64\xdf\x11\x60\x39\x15\x64\xbd\xc5\x08\x29\x5e\x20\x4c\x31\xf8\xf9\x70\x95\x93\xa2\x55\x4b\x72\x53\xed\xaa\xc9\x4c\xe8\x9c\x02\x9b\x90\xee\x0b\xb6\x77\x0a\x9f\x1e\xc9\x90\x38\x4d\xd4\x50\xb9\xba\xb0\xce\x74\x35\x2b\x12\x70\x04\x83\x8f\xcb\x30\x32\x26\x09\x96\x9e\xac\xeb\x50\xd5\xec\x40\x6d\x24\x33\xb6\x10\x7e\x4c\xee\x19\x07\x7e\xf7\xf1\x88\x87\xe3\x48\xc1\xc7\xd1\x21\x2b\x9f\x55\x85\xa0\xa8\x47\xa4\x1c\x08\x34\x7d\x3a\x95\x89\xe0\x60\xa5\xc6\x53\x31\x35\x55\x40\xb8\x56\x0f\x51\xd4\x14\x71\x4c\x91\xd3\x13\xb2\xcf\xc8\xd6\xaf\x64\xbe\x10\x4f\xef\x51\xe7\x7e\x36\x86\x2f\x5f\xff\xfb\x57\x5f\xef\x18\x18\x80\x11\xd3\xef\x43\x98\xb7\xe5\xb2\x6a\x87\x18\x36\x27\x76\x0b\x67\xc4\xe7\xb0\xbe\x21\x18\xe6\xed\x98\xa6\xf2\xd7\x9e\xa0\x85\xe0\x44\x0b\xa6\xc2\x71\x8a\x40\x72\x21\x94\xe7\xb8\x51\x27\xd8\xa7\xe8\x7a\xeb\x62\xd2\x75\x32\x8d\x8b\xd7\x7d\x98\x46\x11\x6f\xc2\xf7\xfd\xd3\xc3\x70\x0b\xc9\xd2\xc1\x9f\xfb\x6b\xf4\x50\x6e\x5d\xb1\xc7\xe3\xb4\x96\x23\x52\x8b\xc1\x0d\xc6\x70\x7b\x8b\x1b\xc4\x86\xde\x43\x8a\x23\x67\x98\xe3\xee\x2a\x6c\x7d\x6c\xa5\xf6\x5f\xfd\xdb\x6e\xfd\x4a\x2d\x8b\xaa\x18\xc3\xab\x1d\x43\x02\xa4\x1d\xa9\xcd\x30\xb8\x8d\x02\x04\x41\x57\x6e\x45\x51\x70\xca\x2f\x53\xd4\x5e\x66\x12\x6d\xf7\x68\x87\xc4\x83\x27\xd6\x31\x7a\x23\xc5\x97\x2e\xe2\x50\xe7\xb0\xdf\x58\x93\x56\x09\x5a\xf6\xc0\xb1\x12\x92\x74\x01\x6a\x59\x62\xb0\x86\x90\x86\x42\x13\x7a\xd7\xd5\x24\x0a\xcf\x51\x68\xa9\x73\x17\xb7\x94\x2e\x00\x48\xf0\xba\x8b\x19\xb2\xeb\x59\xa9\x40\x31\x55\x4e\xa6\x68\x31\x05\x01\x79\x25\xac\xd0\x1e\x31\x25\xf8\x09\x55\xa8\x70\x0b\xd8\x42\x9e\x68\xef\xde\x6a\x6b\x0c\xa6\x1a\xc0\x8a\x48\x8c\xf7\x75\xa1\x3e\xf9\x9b\x99\xea\xc5\xab\xd7\x7b\x55\xde\x8c\xdb\x5d\xc3\x17\xde\xa3\xd5\x63\xf8\xef\xfb\xcb\xc1\x7f\x89\xc1\xdf\x1f\xce\xe2\x3f\xaf\x06\x7f\xfe\x9f\xfe\xf8\xe1\x8b\xce\xcf\x87\xf3\x6f\xff\x65\xc7\x4a\xdb\xc3\xf6\x1d\xc7\x27\x3a\x91\x3a\x48\xac\x35\xda\x67\x0f\x63\x32\xb8\xb3\x15\xf6\xe1\x9d\x50\x0e\xfb\xf0\x59\xb3\x6b\xf8\x95\x42\xdb\x9d\xb9\x84\x6f\x00\x3d\xda\x75\x7b\xf0\xd1\x0c\x61\x92\xf6\x8f\x89\xe4\xee\xab\x48\x1e\x27\x24\x0e\xdb\x4c\xd6\x45\x9a\xce\x1d\x2f\x30\xe2\x51\x58\x3a\x8c\xe1\xed\x30\x31\xc5\xa8\x73\x07\x4c\x71\xf5\x07\xa1\x97\xd0\xc2\x5a\x08\x4a\xd7\x4f\xba\xf3\x84\x4d\x22\xb1\x94\x91\x36\xb7\xe8\xa0\xe4\x23\x42\x13\xb9\x06\xb0\x9c\x62\x22\x38\x10\xb7\x53\xe9\xad\xb0\xcb\x4e\xde\x01\x89\xd0\xb1\x16\x99\x55\x0a\xce\x1c\x22\x0c\xb5\x49\x71\x13\x5d\xcf\x03\x86\x8a\xa9\x54\xd2\x2f\x43\xe1\x32\x31\x3a\x53\x32\xc6\xff\x45\x69\xac\x17\xda\xd7\x45\xdf\x1c\x9f\x40\xfa\x50\x6f\x0e\xc5\xb9\xb3\x54\xbb\x8b\x8b\xd7\x5f\xde\x56\xd3\xd4\x14\x42\xea\x77\x85\x1f\x9d\x7f\x7b\xf6\xb7\x4a\x28\xae\x98\x5e\x8b\x02\xdf\x15\xfe\xfc\xb7\x73\x8b\x17\x5f\x1d\x61\x45\x67\xf7\xc1\x56\x1e\xce\xee\x07\xf1\xbf\x2f\xea\xa6\xf3\x6f\xcf\x26\xc3\xbd\xfd\xe7\x5f\x10\x0f\x1d\x0b\x7c\xb8\x1f\xb4\xe6\x37\x7c\xf8\xe2\xfc\xdb\x4e\xdf\xf9\xa6\x31\x76\xb2\xd2\x83\x09\xe6\xfb\x76\x6c\x88\x4e\x7c\xfd\x18\xaa\xb6\xcc\xd5\xd0\x70\x3d\xe5\x8c\x56\x4c\xfe\x38\x2e\xf3\xec\xaa\xf2\x31\x41\x97\x3e\xbe\x8a\xbb\x5a\xbf\xed\x94\x4d\x36\xae\xc6\x1b\x0f\xb4\xc2\xd4\x3f\x6b\x9d\x76\xf5\x66\xe1\x13\x66\xcf\xbc\x58\xf8\x84\x59\xb7\xd4\x16\x04\xb3\x7a\x9f\x10\x9f\xab\x34\x17\x0e\xbf\xc3\xdb\x81\xdd\x0f\x9c\xb6\xb2\x40\xc1\x7e\x5d\x2f\x8d\xe7\x31\xf2\xb0\xf3\x22\xf4\xa0\x49\xb3\x3f\xbe\x11\x7e\x76\x14\x05\x2f\xaf\xa2\xd8\xf8\xd6\x90\xef\x71\x4b\x89\x09\xae\xbc\xa1\xe2\x38\x0e\x45\x1a\x1b\x29\xf0\xb1\x18\xfb\xfa\x21\xe2\x88\x77\xa5\xed\x1b\x2b\x0a\x9a\x40\x10\x10\xcb\x14\xfe\xe3\xf6\xe3\xf5\xe8\x7b\x13\x63\x05\xca\x66\x5c\xb0\x2d\xbe\xe5\xea\x83\xab\x92\x19\x08\x47\xa4\x51\x7e\x7b\xcb\xa5\x87\x42\x68\x99\xa1\xf3\xc3\xb8\x1a\x5a\x77\xff\xfa\x61\xb8\x5a\xee\x90\xf1\x42\xb5\x7e\x89\x14\x0f\x00\xdb\x06\x31\xd3\xcc\xe5\xa0\x95\x49\x2a\x4d\x1a\x89\x5e\x30\xb1\x5e\x3c\x22\x98\x48\x6c\x85\xec\x14\xc6\xd0\xa3\x63\xd2\xd9\xfa\x27\x32\xac\x9f\x7b\x70\xb6\xe0\x92\x7e\x8f\x7e\xf6\xc2\x86\xcd\xc3\x31\x6a\xeb\x78\xfc\xb8\x71\x88\xef\xad\xcc\x73\x0e\xb7\xb8\x6e\x3b\x47\xed\xcf\xd9\xbf\x65\xa0\x4d\x67\xb0\x8e\xf7\x63\xed\xad\xd8\x3a\x21\xf7\xaf\x1f\x7a\x70\xb6\xca\x17\x85\xa0\xf8\x04\xaf\x9b\x9b\xb0\xd2\xa4\xe7\x75\xd6\xba\xd4\x5e\x3c\x71\x62\x30\x33\x0e\x75\xb8\x48\xf0\x26\x54\x63\x9d\xa1\xe4\x13\x95\x1a\x84\x00\x33\x85\x45\x28\xc0\xd5\xa2\x0c\x97\xc9\xa5\xb0\x7e\xed\x59\xdd\xdd\xc7\xb7\x1f\xc7\x61\x37\x52\x5b\xae\xeb\x2c\x37\x93\x5a\xa8\x58\xd6\x6e\xe2\x43\x22\xa4\x0a\x4a\xf2\x26\xa6\xb6\x75\x45\x37\xab\x7c\x65\x71\xb8\xfe\xcc\xea\xe8\x13\xbf\xed\x8d\xdb\xf6\xc3\xce\x6f\xdd\xd6\x0d\xed\xff\xf0\x25\xd9\xd1\x2c\xea\x1d\x37\xad\x9b\x2c\x5e\x77\xce\xe0\x5e\x16\x5b\x68\x26\x2e\x53\x93\x38\x62\x30\xc1\xd2\xbb\x91\x99\x13\x74\xe2\x62\xb4\x30\xf6\x51\xea\x7c\x40\x87\x6c\x10\x34\xef\x46\xec\x62\x46\x7f\xe2\x3f\xbf\x8a\x23\xf6\x53\xc7\xb3\x15\x1e\xb4\xfe\x03\x78\x63\xf7\x39\xfa\xc5\xac\xd5\xf1\xe5\x73\x3c\xc1\xcb\xdb\x3a\xf9\x5b\x9b\x4d\xe6\x12\x2e\xc2\xe3\x4b\xd7\x0e\xc2\x15\x22\x0d\x10\x28\xf4\xf2\x77\x3f\xc6\x24\x40\xce\xf1\x93\xe5\x20\x3e\x45\x1f\x08\x9d\x0e\x9a\xf8\x3a\x59\xfe\x62\x89\x55\xf2\x48\x03\xfe\x7c\xf5\xf6\x1f\x73\xb8\x2b\xf9\x2c\x6b\x0d\x55\x94\x31\x78\x5b\xd5\xd1\x9d\xf3\xc6\x8a\x1c\x57\xdb\xaa\x69\x93\x7c\xb4\x0c\xc7\xbc\x12\x7e\xfa\x99\x9b\xda\xc7\xe7\x42\x95\x33\xf1\xba\x9e\x7b\x7a\x82\x7e\x7a\x82\x7e\x7a\x82\x7e\x7a\x82\xbe\x57\xd8\x7f\xd4\x27\xe8\xa7\x27\xe4\xa7\x27\xe4\xa7\x27\xe4\xbb\xbb\x4f\x4f\xc8\x4f\x4f\xc8\x4f\x4f\xc8\xd7\xbf\xd3\x13\xf2\xd3\x13\xf2\xd3\x13\xf2\xd3\x13\xf2\x2d\xdf\x4e\x35\xfd\xff\x7e\x7c\x79\xba\x1c\xfb\x63\x5c\x8e\x9d\xae\xbb\x4e\xd7\x5d\xa7\xeb\xae\xd3\x75\xd7\x2f\x38\xf1\xa7\xeb\xae\xd3\x75\xd7\xe9\xba\xeb\x74\xdd\xf5\x4f\x7a\xdd\x95\x09\xe5\x8e\xbe\xef\xfa\xdf\x00\x00\x00\xff\xff\x25\xf1\x04\x48\x34\x4b\x00\x00") +var _operatorsCoreosCom_operatorgroupsYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5a\x79\x6f\x23\x37\x96\xff\xbf\x3f\xc5\x83\x66\x81\xb6\xb3\x3a\xda\x9d\x45\x76\x22\x20\x08\x8c\xee\x74\xe0\x4d\xb7\xdb\x68\xbb\xb3\xc0\x5a\xde\x1d\xaa\xea\x55\x89\x63\x16\x59\x43\xb2\x24\x6b\x82\x7c\xf7\xc5\x7b\x64\x1d\xba\xe5\x1c\xb3\x93\x85\xea\x1f\x5b\x3c\xdf\xc1\xf7\x7b\x07\x29\x4a\xf9\x23\x5a\x27\x8d\x1e\x83\x28\x25\x3e\x79\xd4\xf4\xcb\x0d\x1f\xff\xec\x86\xd2\x8c\xe6\x17\x2f\x1e\xa5\x4e\xc7\xf0\xa6\x72\xde\x14\x9f\xd0\x99\xca\x26\xf8\x16\x33\xa9\xa5\x97\x46\xbf\x28\xd0\x8b\x54\x78\x31\x7e\x01\x20\xb4\x36\x5e\x50\xb3\xa3\x9f\x00\x89\xd1\xde\x1a\xa5\xd0\x0e\x72\xd4\xc3\xc7\x6a\x8a\xd3\x4a\xaa\x14\x2d\x2f\x5e\x6f\x3d\x7f\x35\xfc\x7a\xf8\xea\x05\x40\x62\x91\xa7\xdf\xc9\x02\x9d\x17\x45\x39\x06\x5d\x29\xf5\x02\x40\x8b\x02\xc7\x60\x4a\xb4\xc2\x1b\x9b\x5b\x53\x95\x6e\x58\xff\x74\xc3\xc4\x58\x34\xf4\xa7\x78\xe1\x4a\x4c\x68\x77\x1e\xd3\x4e\x59\x19\x13\xd6\xab\x89\x14\x1e\x73\x63\x65\xfd\x1b\x60\x00\x46\x15\xfc\x7f\x60\xfe\x63\x5c\xe3\x7b\x5a\x92\xdb\x95\x74\xfe\x87\xcd\xbe\xf7\xd2\x79\xee\x2f\x55\x65\x85\x5a\x27\x98\xbb\xdc\xcc\x58\x7f\xdd\x6e\xcf\xdb\xe5\xa1\x4b\xea\xbc\x52\xc2\xae\xcd\x7b\x01\xe0\x12\x53\xe2\x18\x78\x5a\x29\x12\x4c\x5f\x00\x44\xf1\xc5\x65\x06\x51\x44\xf3\x8b\xb8\xaa\x4b\x66\x58\x88\x7a\x0f\xa0\x25\xf5\xe5\xcd\xd5\x8f\x5f\xde\xae\x75\x00\xa4\xe8\x12\x2b\x4b\xcf\xca\x58\x61\x08\xa4\x03\x3f\x43\xa8\xb4\xf4\x60\x32\x28\x2a\xe5\xa5\x47\x2d\x74\xb2\x84\xcc\x58\xf8\xf8\xfe\x03\x14\x42\x8b\x1c\xd3\x8e\xa8\xe1\xca\x93\xee\x9d\xb7\x42\xea\xb0\x82\xd4\xce\x0b\xa5\x58\xbd\xb4\x52\x33\x18\xa4\x06\xe9\x5d\xd0\x08\xf1\x06\xde\x80\x00\x52\xa3\xcc\x24\xa6\xe0\x90\xb7\xf6\xc2\xe6\xe8\xdb\x61\x6e\xd8\xe1\xc0\x2f\x49\x3c\x66\xfa\x57\x4c\x7c\xa7\xd9\xe2\xdf\x2a\x69\x31\xed\x32\x4b\xa2\xaa\x0f\x6d\xa7\xb9\xb4\x44\x91\xef\x9c\x82\xf0\x75\x4c\x64\xa5\x7d\x4d\x6a\x2f\x49\xb4\x61\x1c\xa4\x64\x1d\x18\xd8\x8e\x4a\x22\x36\x58\xec\xcc\xc9\x4c\x3a\xb0\x58\x5a\x74\xa8\x7d\x23\x11\xa1\x23\x03\x43\xb8\x45\x4b\x13\xe9\xac\x54\x2a\x25\x51\xce\xd1\x7a\xb0\x98\x98\x5c\xcb\xbf\x37\xab\x39\x92\x15\x6d\xa3\x84\x47\xe7\x41\x6a\x8f\x56\x0b\x05\x73\xa1\x2a\xec\x83\xd0\x29\x14\x62\x09\x16\x69\x5d\xa8\x74\x67\x05\x1e\xe2\x86\xf0\xc1\x58\xd2\x4e\x66\xc6\x30\xf3\xbe\x74\xe3\xd1\x28\x97\xbe\x06\x80\xc4\x14\x05\x29\x7f\x39\x62\x5b\x96\xd3\x8a\x74\x36\x4a\x71\x8e\x6a\xe4\x64\x3e\x10\x36\x99\x49\x8f\x89\xaf\x2c\x8e\x44\x29\x07\x4c\xac\x66\x10\x18\x16\xe9\x9f\x6c\x84\x0c\xf7\x72\x4d\x7c\x41\x65\xce\x5b\xa9\xf3\x95\x2e\xb6\xb9\xbd\xb2\x26\xcb\xa3\x93\x29\xe2\xf4\xc0\x4b\x2b\x52\x6a\x22\xa9\x7c\xfa\xee\xf6\x0e\x6a\x02\x82\xd8\x83\x84\xdb\xa1\xae\x15\x36\x09\x4a\xea\x0c\x6d\x18\x99\x59\x53\xf0\x2a\xa8\xd3\xd2\x48\xed\xf9\x47\xa2\x24\x6a\x0f\xae\x9a\x16\x74\x68\xe9\x80\xa1\xf3\xa4\x87\x21\xbc\x61\xfc\x83\x29\x42\x55\xa6\xc2\x63\x3a\x84\x2b\x0d\x6f\x44\x81\xea\x8d\x70\xf8\xbb\x8b\x9a\x24\xea\x06\x24\xbe\xe3\x85\xdd\x85\xef\xcd\x09\x1b\x06\x05\x50\xc3\xeb\x4e\xed\xac\xe0\xc7\x6d\x89\x49\x8d\x21\x34\x93\x31\x43\xe8\x35\x90\xa9\x55\x34\x3c\x96\x08\xda\x32\x13\x95\xf2\xeb\x94\x00\x54\x65\x6e\x45\x8a\xb7\xde\x12\xac\x2f\xc7\xf0\x36\x8c\x5c\x1b\xb8\xcb\xdc\x99\x45\x54\x98\x78\x63\x37\x7b\xd6\x58\xbd\x8d\x03\xe3\x8c\xc0\xe6\x0a\x6b\x2f\xdd\x7e\xdc\x3a\x82\xd3\x43\xd4\xd2\x57\x08\x9f\xcc\xbe\x7b\xa2\x33\xdd\x71\x09\x07\xa8\x5f\x9f\x14\x2c\x8a\x3c\x1b\xa1\x91\x12\x53\x54\x8d\x28\x6a\x24\x2d\x82\xc9\xdc\xcd\x70\xa5\x05\x84\x45\xb8\xbc\x7e\x8b\xe9\x36\xe6\x5a\x06\x85\xb5\x62\xb9\x63\x84\xf4\x58\xec\x24\x7c\x8d\xf4\xcb\x3d\xe4\x45\x60\xa8\x7b\xfc\x4c\xb0\x2f\xf2\xec\x89\x02\xe8\xf5\x41\xc0\x23\x2e\x03\x3e\x12\xec\x46\x95\x85\xc1\x16\x19\x4d\x59\x99\x8f\xb8\xe4\x41\x11\x2c\x77\x52\x77\x40\x7f\xe1\xdb\xee\x8d\x56\xbf\x01\x6d\xb9\xb7\xbf\x26\x76\xe7\xa0\x43\x87\x25\x7c\x8f\xb8\xdc\xd7\xbd\x26\x70\x92\x43\x34\xe3\x20\x79\x6a\x60\x69\xb1\x65\xd7\xc2\x16\x65\xa9\x24\x32\x1a\xee\x5d\x7b\x27\x1c\xad\x7e\x35\xab\xcf\x20\xb4\x51\x65\x8b\xf0\x41\xd9\x2f\x5d\x50\x2c\x9d\xf4\x99\x2c\x63\x90\x11\x42\x8b\xda\x15\xfe\x28\x94\xec\x84\x31\x7c\xaa\xaf\x74\x1f\xae\x8d\xa7\x3f\xdf\x3d\x49\x82\x7a\x3a\x0f\x6f\x0d\xba\x6b\xe3\xb9\xe5\x37\x61\x35\x90\xf0\x0c\x46\xc3\x04\x3e\xec\x3a\xd8\x15\x71\xd2\xf5\x87\x14\x86\x65\xac\x9f\x46\x28\xd2\x91\x47\x32\xb6\xe6\x88\x23\x94\xb0\x50\x58\xa2\xa8\x1c\x3b\x30\x6d\xf4\x00\x8b\xd2\x2f\xb7\xae\x11\x05\x61\xec\x8a\x1c\xf6\x2c\x17\x97\xba\x23\xbf\x1a\x7a\x42\x04\xa4\x28\x94\x85\xb4\x62\xa2\xd9\x9b\x13\x68\xcb\x04\x0a\xb4\x39\x42\x49\x08\x75\x8c\x78\xf7\xe1\x4a\xf8\x0e\xa0\xcb\x91\xba\x62\xc8\x7c\x4f\x06\xf0\x0c\x88\x0d\xe3\x03\x2c\x15\xa2\x24\x35\xfd\x44\xe8\xc3\x92\xfa\x19\x4a\x21\x29\x62\xbe\xe4\xe8\x5f\xe1\x4a\x9f\xd4\x2c\xd3\xee\x32\xb4\x82\x74\x40\x50\x32\x17\x8a\xf0\x8e\x4e\xb2\x06\x54\x01\xfd\x28\x48\x5f\x03\xf6\x3e\x2c\x66\xc6\x05\x30\xcb\x24\x2a\x8e\x9d\x7a\x8f\xb8\xec\xf5\x37\x54\xdb\xbb\xd2\xbd\x80\x8b\x1b\xca\x6c\x40\xd4\x68\xb5\x84\x1e\xf7\xf5\x7e\xb9\x2f\xd8\x0b\x96\x22\x4d\x39\xbd\x14\xea\xe6\x08\x34\xdb\xab\x37\x87\x76\x2e\x13\xbc\x4c\x12\x53\x69\x4e\xbc\x8e\xf0\xeb\xeb\x53\x6a\xf0\x13\x69\x21\xf5\x4a\x6e\xc2\x23\x41\x84\xa1\xb0\x98\xc9\x64\x06\x0b\xa9\x14\x87\x81\x0e\x53\x52\x4f\x8a\xa5\x32\xcb\x46\xce\x67\xee\x3c\x68\x96\xe2\xd1\x5a\xf6\x9c\xe9\xed\x0e\x0d\x76\x31\x47\xe9\x43\x72\x63\xcd\x5c\xa6\x98\x5e\xde\x5c\x6d\x95\xd2\x2a\x73\x3c\x05\x3c\x2a\xe5\x38\x7d\xa3\x98\xd5\x9b\x18\xb3\x6e\x0d\x61\xca\xce\xfa\x9d\x24\x7f\x27\xb1\x53\x63\x14\x8a\xcd\xfe\x10\x0a\x35\x49\xec\x61\x5a\xef\xd6\x26\x44\xb8\xc3\xa7\x52\xc9\x44\xfa\x1a\xbf\xdb\xd8\x8a\xf3\x21\x9e\xc4\xc0\x25\x39\x1a\x70\xe8\xfb\x6d\xac\x26\x1d\xc8\x5c\x1b\xbb\xfd\x7c\xee\xc7\x93\x3d\x28\x72\x00\x3b\x9e\x06\x8f\xd5\x14\xad\x46\x8f\x6e\x40\x31\xd6\x20\x4e\xc0\x4d\x13\x58\x0f\x61\x0f\x49\xa9\xf7\x79\x75\xc2\x4a\x02\x1a\x17\xab\xb1\x35\x64\xed\x2b\xc9\x37\x8d\x6a\x24\xc8\xf6\x6c\x91\x8d\x38\xa9\xac\x45\xed\xd5\x12\xfc\xc2\x80\xab\xca\xd2\x58\x8f\xe9\xfa\x92\x64\x9a\x30\xd1\x75\xa0\x3d\xe6\x43\xc5\x26\xc0\x40\x21\x94\x32\x0b\x48\x54\xe5\x3c\xda\x68\x59\x31\x53\x66\x75\x15\x66\x8e\x75\x1a\x1b\x5c\x02\x39\x83\x72\x26\x1c\xb6\x39\x98\xab\x92\x04\x31\xc5\x34\x74\x44\x57\x82\x59\x86\x89\x97\x73\x54\x4b\x28\x50\x70\xa5\x41\xf8\x76\x7f\x3a\xd9\x61\xfb\x96\xe1\xb5\x1d\x35\x3e\xf9\x3a\x49\x07\xc9\x49\xf8\x6a\xa5\xc2\x36\xec\xce\x84\x83\x4c\x48\x45\x79\xdd\x44\xc3\x1d\x26\xb3\x1b\x8b\x73\x89\x8b\xcf\xda\x89\x0c\xdf\x09\xa9\xde\x19\xbb\x10\x36\xed\xc8\xe0\xf7\x60\x9f\xa8\x6a\xfa\x02\x49\xb5\x5c\x2e\x1b\xe0\x54\xcb\x7e\x4b\x45\x8e\x9a\x04\x40\xfc\x2e\x6a\x06\x6f\x14\x49\x6c\x31\x43\x4d\xae\xb7\x9a\x36\x27\x0a\x2c\x66\x68\x51\x93\x3d\x89\x7a\xfd\xce\xa4\xc6\x3d\x24\xc2\x0b\x65\x72\x96\xcc\x14\x51\xd7\x79\x2f\x2c\xa4\x9f\x81\xe0\xcd\x6a\xe9\x65\x1c\x5e\x23\x20\x85\x0a\xc4\x62\xb4\xdd\x4e\xd1\x68\xa2\xe1\x3f\x2f\x3f\x5d\x5f\x5d\x7f\x3f\x66\xaf\xb2\x4f\xc2\x9b\xe7\x5a\x3a\xa8\x78\x54\xa7\xea\xe1\x2a\xe5\xe9\x88\x57\x1a\x9f\x4a\x4c\x88\xb4\x29\xce\xc4\x5c\x92\x0d\xd8\x58\x0f\x99\xa3\x15\x53\x85\x40\x69\x30\x28\xe3\x68\x1d\x85\xce\xc1\xd2\x54\x30\x13\x73\x84\x14\xb1\x84\x4a\xa7\x68\x9d\x17\x3a\x25\xea\x4d\x16\x23\xdf\x55\x26\x60\x8a\xd4\x5b\x57\xc4\x36\xac\xab\xf7\x5c\x80\x6f\x33\xdd\x1d\x89\x2c\x7d\xa8\xab\x62\x3b\x2a\x0d\xf6\xcc\xa2\xde\x7d\x22\x5e\x4d\xfb\xbd\xf0\xd5\x06\xf4\xed\x49\xfc\x79\x7c\x93\xfa\x87\x5f\xdb\x92\xff\x4f\xcf\xcf\xfd\x77\xe7\x51\x03\x50\xc2\xf9\xcf\xe1\x14\x3e\x23\xe3\x4f\x8c\x0e\x66\x73\xd8\x25\xbd\x69\x86\xae\xc7\xde\xdb\x3c\x67\xbb\xf0\x6f\xea\x6c\x56\xe1\xbf\x21\xa9\x0d\xd1\x52\xf4\x42\xaa\x20\x71\xa3\x11\x04\x85\x2c\xbe\xa6\x32\x02\x3b\xab\x05\x9b\x8a\xe4\xe5\xcd\x15\x34\xda\x80\xc1\x60\x10\x40\xd6\x79\x5b\x25\xec\x47\xa5\xf6\xa8\x09\x84\x68\xd5\x54\x5a\x2e\x29\x3a\x5a\xbc\x95\x43\xcc\x08\x43\x98\x59\x0a\x3f\x83\x61\x50\xfe\xb0\x23\x0a\x80\x77\xc6\x02\x3e\x89\xa2\x54\xd8\x27\xbb\x27\x49\xc0\x3b\x63\xe2\xb1\x09\x7b\xfe\x04\xa3\x11\x7c\x6a\xf3\x38\x8e\x55\xa7\x14\x72\x85\x34\x8e\x8b\xa6\x90\x19\x43\x82\xee\xb2\x34\xa4\x89\x3f\x68\xb3\xd0\xdb\x76\xe7\xbd\x84\xc5\x31\x4c\x7a\x97\x73\x21\x15\x59\xff\xa4\xd7\x87\x49\xef\xc6\x9a\x9c\xa3\x66\x9d\x4f\x62\x18\x3c\xe9\xbd\x45\x46\x9a\x74\xd2\xa3\x65\xff\x95\x93\x92\x0f\x94\x9f\xfc\x80\xcb\x6f\x78\xb1\xa6\xb9\xf6\xc0\xdf\x84\xfc\x85\xda\xc9\xd7\xdf\x2d\x4b\xfc\x86\x02\xf7\xba\xe1\x83\x28\x9b\xc9\x9d\x03\x75\xff\x50\xa0\x17\xf3\x8b\x61\xab\xd1\xbf\xfc\xd5\x19\x3d\x9e\xf4\x5a\xfa\xfb\xa6\xa0\x93\x51\xfa\xe5\xa4\x07\x2b\xbb\x8e\x27\x3d\xde\xb7\x6e\xaf\x89\x1c\x4f\x7a\xb4\x13\x35\x5b\xe3\xcd\xb4\xca\xc6\x93\xde\x74\xe9\xd1\xf5\x2f\xfa\x16\xcb\x3e\xe1\xd3\x37\xed\x0e\x93\xde\x5f\x48\x27\xa3\x11\x18\x3f\x43\x1b\x94\xe9\xe0\xe7\x6d\xe0\x75\x44\x34\x7f\xa8\xec\x11\x8c\xf6\xce\x0a\xed\x64\x7d\xf9\xb3\x73\x68\x81\xce\x89\x7c\x77\xbf\x45\xe1\xb6\x46\xa6\xa1\x3b\x9c\x86\x9d\xdd\xc4\xcb\xd6\xce\xc3\x35\x95\x4d\x1e\x8e\xac\x65\x6d\x4e\x6c\x2b\x2d\xce\x83\xa7\x06\x36\xda\xe6\x4c\xf8\x66\x34\xd9\x22\xc5\x01\x64\xe2\x11\x63\x39\x1b\x64\xbd\xc5\x20\x29\xde\x21\x4c\x31\xb8\xfa\x70\x9b\x93\xa2\x55\x4b\xf2\x54\xed\xaa\xc9\x4c\xe8\x9c\x62\x9b\x90\xf1\x0b\x36\x79\x8a\xa0\x1e\xc9\x90\x38\x53\xd4\x50\xb9\xba\xb6\xce\x74\x35\x2b\x12\x76\x04\x9b\x8f\xcb\x30\x38\x26\x09\x96\x9e\xac\xeb\x50\xe1\xec\x40\x79\x24\x33\xb6\x10\x7e\x4c\x1e\x1a\x07\x7e\xf7\xf1\x88\x87\xe3\x48\xc1\xc7\xd1\x21\x31\x9f\x55\x85\xa0\xc0\x47\xa4\x1c\x0b\x34\x7d\x3a\x95\x89\xe0\x78\xa5\x86\x54\x31\x35\x55\x00\xb9\x56\x0f\x51\xd4\x14\x74\x4c\x91\x33\x14\xb2\xcf\xc8\xd6\xaf\x64\xbe\x10\x4f\xef\x51\xe7\x7e\x36\x86\x2f\x5f\xff\xfb\x57\x7f\xde\x31\x30\x00\x23\xa6\xdf\x87\x48\x6f\xcb\x7d\xd5\x0e\x31\x6c\x4e\xec\xd6\xce\x88\xcf\x61\x7d\x49\x30\xcc\xdb\x31\x4d\xf1\xaf\x3d\x41\x0b\xc1\xb9\x16\x4c\x85\xe3\x2c\x81\xe4\x42\x40\xcf\xa1\xa3\x4e\xb0\x4f\x01\xf6\xd6\xc5\xa4\xeb\x24\x1b\x17\xaf\xfb\x30\x8d\x22\xde\x84\xef\xfb\xa7\x87\xe1\x16\x92\xa5\x83\xaf\xfb\x6b\xf4\x50\x7a\x5d\xb1\xd3\xe3\xcc\x96\x83\x52\x8b\xc1\x13\xc6\x88\x7b\x8b\x27\xc4\x86\xde\x43\x8a\x23\x7f\x98\xe3\xee\x42\x6c\x7d\x6c\xa5\xf6\x5f\xfd\xdb\x6e\xfd\x4a\x2d\x8b\xaa\x18\xc3\xab\x1d\x43\x02\xa4\x1d\xa9\xcd\x30\xb8\x0d\x04\x04\x41\x57\x6e\x45\x51\x70\xd6\x2f\x53\xd4\x5e\x66\x12\x6d\xf7\x68\x87\xdc\x83\x27\xd6\x61\x7a\x23\xc5\x97\x2e\xe2\x50\xe7\xb0\xdf\x58\x93\x56\x09\x5a\xf6\xc0\xb1\x18\x92\x74\x01\x6a\x59\x62\xb0\x86\x90\x89\x42\x13\x7d\xd7\x05\x25\x8a\xd0\x51\x68\xa9\x73\x17\xb7\x94\x2e\x00\x48\xf0\xba\x8b\x19\xb2\xeb\x59\x29\x42\x31\x55\x4e\xa6\x68\x31\x05\x01\x79\x25\xac\xd0\x1e\x31\x25\xf8\x09\x85\xa8\x70\x11\xd8\x42\x9e\x68\xaf\xdf\x6a\x6b\x0c\xa6\x1a\xc0\x8a\x48\x8c\x57\x76\xa1\x44\xf9\x9b\x99\xea\xc5\xab\xd7\x7b\x55\xde\x8c\xdb\x5d\xc6\x17\xde\xa3\xd5\x63\xf8\xef\xfb\xcb\xc1\x7f\x89\xc1\xdf\x1f\xce\xe2\x3f\xaf\x06\x5f\xff\x4f\x7f\xfc\xf0\x45\xe7\xe7\xc3\xf9\xb7\xff\xb2\x63\xa5\xed\x91\xfb\x8e\xe3\x13\x9d\x48\x1d\x27\xd6\x1a\xed\xb3\x87\x31\x19\xdc\xd9\x0a\xfb\xf0\x4e\x28\x87\x7d\xf8\xac\xd9\x35\xfc\x4a\xa1\xed\x4e\x5e\xc2\x37\x80\x1e\xed\xba\x3d\xf8\x68\x86\x30\x49\xfb\xc7\x44\x72\xf7\x15\x25\x8f\x13\x12\x87\x6d\x26\xeb\x22\x4d\xe7\x9a\x17\x18\xf1\x28\x2c\x1d\xc6\x08\x77\x98\x98\x62\xd4\xb9\x06\xa6\xd0\xfa\x83\xd0\x4b\x68\x61\x2d\x04\xa5\xeb\x27\xdd\x79\xc2\x26\x91\x58\x4a\x4a\x9b\x8b\x74\x50\xf2\x11\xa1\x89\x5c\x03\x58\x4e\x31\x11\x1c\x8b\xdb\xa9\xf4\x56\xd8\x65\x27\xf5\x80\x44\xe8\x58\x8e\xcc\x2a\x05\x67\x0e\x11\x86\xda\xa4\xb8\x89\xae\xe7\x01\x43\xc5\x54\x2a\xe9\x97\xa1\x76\x99\x18\x9d\x29\x19\x53\x80\xa2\x34\xd6\x0b\xed\xeb\xba\x6f\x8e\x4f\x20\x7d\x28\x39\x87\xfa\xdc\x59\xaa\xdd\xc5\xc5\xeb\x2f\x6f\xab\x69\x6a\x0a\x21\xf5\xbb\xc2\x8f\xce\xbf\x3d\xfb\x5b\x25\x14\x17\x4d\xaf\x45\x81\xef\x0a\x7f\xfe\xdb\xb9\xc5\x8b\xaf\x8e\xb0\xa2\xb3\xfb\x60\x2b\x0f\x67\xf7\x83\xf8\xdf\x17\x75\xd3\xf9\xb7\x67\x93\xe1\xde\xfe\xf3\x2f\x88\x87\x8e\x05\x3e\xdc\x0f\x5a\xf3\x1b\x3e\x7c\x71\xfe\x6d\xa7\xef\x7c\xd3\x18\x3b\x89\xe9\xc1\x1c\xf3\x7d\x3b\x36\x44\x27\xbe\x7e\x0f\x55\x5b\xe6\x6a\x68\xb8\x9e\x75\x46\x2b\x26\x7f\x1c\x97\x79\x76\x61\xf9\x98\xa0\x4b\x1f\x5f\xc8\x5d\x2d\xe1\x76\x2a\x27\x1b\xb7\xe3\x8d\x07\x5a\x61\xea\x9f\xb5\x54\xbb\x7a\xb9\xf0\x09\xb3\x67\xde\x2d\x7c\xc2\xac\x5b\x6d\x0b\x82\x59\xbd\x52\x88\x2f\x56\x9a\x3b\x87\xdf\xe1\xf9\xc0\xee\x37\x4e\x5b\x59\xa0\x60\xbf\x2e\x99\xc6\xf3\x18\x79\xd8\x79\x17\x7a\xd0\xa4\xd9\x1f\xdf\x08\x3f\x3b\x8a\x82\x97\x57\x51\x6c\x7c\x71\xc8\x57\xb9\xa5\xc4\x04\x57\x9e\x51\x71\x1c\x87\x22\x8d\x8d\x14\xf8\x58\x8c\x7d\xfd\x10\x71\xc4\xeb\xd2\xf6\x99\x15\x05\x4d\x20\x08\x88\x65\x0a\xff\x71\xfb\xf1\x7a\xf4\xbd\x89\xb1\x02\x65\x33\x2e\xd8\x16\x5f\x74\xf5\xc1\x55\xc9\x0c\x84\x23\xd2\x28\xbf\xbd\xe5\xd2\x43\x21\xb4\xcc\xd0\xf9\x61\x5c\x0d\xad\xbb\x7f\xfd\x30\x5c\xad\x78\xc8\x78\xa7\x5a\x3f\x46\x8a\x07\x80\x6d\x83\x98\x69\xe6\x72\xd0\xca\x24\x95\x26\x8d\x44\x2f\x98\x58\x2f\x1e\x11\x4c\x24\xb6\x42\x76\x0a\x63\xe8\xd1\x31\xe9\x6c\xfd\x13\x19\xd6\xcf\x3d\x38\x5b\x70\x55\xbf\x47\x3f\x7b\x61\xc3\xe6\xed\x18\xb5\x75\x3c\x7e\xdc\x38\xc4\xf7\x56\xe6\x39\x87\x5b\x5c\xba\x9d\xa3\xf6\xe7\xec\xdf\x32\xd0\xa6\x33\x58\xc7\x2b\xb2\xf6\x62\x6c\x9d\x90\xfb\xd7\x0f\x3d\x38\x5b\xe5\x8b\x42\x50\x7c\x82\xd7\xcd\x65\x58\x69\xd2\xf3\x3a\x6b\x5d\x6a\x2f\x9e\x38\x31\x98\x19\x87\x3a\xdc\x25\x78\x13\x0a\xb2\xce\x50\xf2\x89\x4a\x0d\x42\x80\x99\xc2\x22\xd4\xe0\x6a\x51\x86\xfb\xe4\x52\x58\xbf\xf6\xb2\xee\xee\xe3\xdb\x8f\xe3\xb0\x1b\xa9\x2d\xd7\x75\x96\x9b\x49\x2d\x54\xac\x6c\x37\xf1\x21\x11\x52\x05\x25\x79\x13\x53\xdb\xba\xa8\x9b\x55\xbe\xb2\x38\x5c\x7f\x69\x75\xf4\x89\xdf\xf6\xcc\x6d\xfb\x61\xe7\xe7\x6e\xeb\x86\xf6\x7f\xf8\x98\xec\x68\x16\xf5\x8e\xcb\xd6\x4d\x16\xaf\x3b\x67\x70\x2f\x8b\x2d\x34\x13\x97\xa9\x49\x1c\x31\x98\x60\xe9\xdd\xc8\xcc\x09\x3a\x71\x31\x5a\x18\xfb\x28\x75\x3e\xa0\x43\x36\x08\x9a\x77\x23\x76\x31\xa3\x3f\xf1\x9f\x5f\xc5\x11\xfb\xa9\xe3\xd9\x0a\x6f\x5a\xff\x01\xbc\xb1\xfb\x1c\xfd\x62\xd6\xea\xf8\xf2\x39\x9e\xe0\xe5\x6d\x9d\xfc\xad\xcd\x26\x73\x09\x77\xe1\xf1\xb1\x6b\x07\xe1\x0a\x91\x06\x08\x14\x7a\xf9\xbb\x1f\x63\x12\x20\xe7\xf8\xc9\x72\x10\x5f\xa3\x0f\x84\x4e\x07\x4d\x7c\x9d\x2c\x7f\xb1\xc4\x2a\x79\xa4\x01\x7f\xbe\x7a\xfb\x8f\x39\xdc\x95\x7c\x96\xb5\x86\x2a\xca\x18\xbc\xad\xea\xe8\xce\x79\x63\x45\x8e\xab\x6d\xd5\xb4\x49\x3e\x5a\x86\x63\x5e\x09\x3f\xfd\xcc\x4d\xed\xfb\x73\xa1\xca\x99\x78\x5d\xcf\x3d\xbd\x42\x3f\xbd\x42\x3f\xbd\x42\x3f\xbd\x42\xdf\x2b\xec\x3f\xea\x2b\xf4\xd3\x2b\xf2\xd3\x2b\xf2\xd3\x2b\xf2\xdd\xdd\xa7\x57\xe4\xa7\x57\xe4\xa7\x57\xe4\xeb\xdf\xe9\x15\xf9\xe9\x15\xf9\xe9\x15\xf9\xe9\x15\xf9\x96\x6f\xa7\x9a\xfe\x7f\xbf\xbf\x3c\x5d\x8e\xfd\x31\x2e\xc7\x4e\xd7\x5d\xa7\xeb\xae\xd3\x75\xd7\xe9\xba\xeb\x17\x9c\xf8\xd3\x75\xd7\xe9\xba\xeb\x74\xdd\x75\xba\xee\xfa\x27\xbd\xee\xca\x84\x72\x47\xdf\x77\xfd\x6f\x00\x00\x00\xff\xff\x43\xb0\x74\xb5\x37\x4b\x00\x00") func operatorsCoreosCom_operatorgroupsYamlBytes() ([]byte, error) { return bindataRead( @@ -205,7 +205,7 @@ func operatorsCoreosCom_operatorgroupsYaml() (*asset, error) { return a, nil } -var _operatorsCoreosCom_operatorsYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\x59\xcd\x72\xe3\x36\x12\xbe\xfb\x29\xba\x94\x83\x93\x2a\xfd\x24\xb3\x97\x94\x6e\x2e\x7b\xb2\xe5\xdd\xac\x67\x6a\xec\x99\x4b\x2a\x87\x16\xd9\x12\xb1\x02\x01\x06\x0d\x4a\xd6\x4e\xcd\xbb\x6f\x35\x00\x4a\xa4\x24\x4b\xd4\xac\x27\x1b\x5c\x24\x82\x40\xa3\x7f\xbf\xee\x06\xb1\x52\x9f\xc8\xb1\xb2\x66\x0a\x58\x29\x7a\xf6\x64\xe4\x89\xc7\xcb\x9f\x79\xac\xec\x64\xf5\xd3\xd5\x52\x99\x7c\x0a\xb7\x35\x7b\x5b\x7e\x20\xb6\xb5\xcb\xe8\x8e\xe6\xca\x28\xaf\xac\xb9\x2a\xc9\x63\x8e\x1e\xa7\x57\x00\x68\x8c\xf5\x28\xd3\x2c\x8f\x00\x99\x35\xde\x59\xad\xc9\x8d\x16\x64\xc6\xcb\x7a\x46\xb3\x5a\xe9\x9c\x5c\x20\xde\x1c\xbd\xfa\x71\xfc\xf3\xf8\xc7\x2b\x80\xcc\x51\xd8\xfe\xa4\x4a\x62\x8f\x65\x35\x05\x53\x6b\x7d\x05\x60\xb0\xa4\x29\xd8\x8a\x1c\x7a\xeb\x78\xbc\xfb\x97\x59\x47\x56\x7e\xca\x2b\xae\x28\x93\x83\x17\xce\xd6\x55\x7b\x75\x6b\x4d\x24\xd5\xf0\x87\x9e\x16\xd6\xa9\xe6\x19\x60\x04\x56\x97\xe1\x7f\x94\xfb\x5d\xa2\x11\xa6\xb4\x62\xff\xcf\xce\xf4\xaf\x8a\x7d\x78\x55\xe9\xda\xa1\x6e\x9d\x19\x66\x59\x99\x45\xad\xd1\xed\xe6\xaf\x00\x38\xb3\x15\x4d\xe1\x56\xd7\xec\x49\x26\x92\x1e\x12\x0f\xa3\x24\xeb\xea\xa7\xc4\x12\x67\x05\x95\xd8\x30\x08\x42\xca\xdc\xbc\xbf\xff\xf4\xb7\xc7\xbd\x17\x00\x39\x71\xe6\x54\xe5\x83\x56\x1b\x1e\xc1\x51\xe5\x88\xc9\x78\x06\x84\x2c\x1e\xbb\x65\x68\xdc\xda\xee\x37\xc2\x98\x9d\xfd\x9b\x32\xdf\x9a\xae\x9c\x2c\xf6\x2d\x2d\xc5\xd1\xf2\x9e\xce\xfc\x1e\x1f\xd7\xc2\x6c\x5c\x07\xb9\x38\x0e\x31\xf8\x82\x1a\xb1\x29\x4f\x12\x82\x9d\x83\x2f\x14\xef\xf8\x0d\xbe\x20\xd3\x68\x12\x57\x63\x78\x24\x27\x1b\x81\x0b\x5b\xeb\x5c\x3c\x6c\x45\xce\x83\xa3\xcc\x2e\x8c\xfa\xcf\x96\x1a\x83\xb7\xe1\x18\x8d\x9e\xd8\x83\x32\x9e\x9c\x41\x0d\x2b\xd4\x35\x0d\x01\x4d\x0e\x25\x6e\xc0\x91\xd0\x85\xda\xb4\x28\x84\x25\x3c\x86\x7f\x59\x47\xa0\xcc\xdc\x4e\xa1\xf0\xbe\xe2\xe9\x64\xb2\x50\xbe\x89\x8d\xcc\x96\x65\x6d\x94\xdf\x4c\x82\x9b\xab\x59\x2d\x76\x9f\xe4\xb4\x22\x3d\x61\xb5\x18\xa1\xcb\x0a\xe5\x29\xf3\xb5\xa3\x09\x56\x6a\x14\x98\x35\x21\x3e\xc6\x65\xfe\x9d\x4b\xd1\xc4\xd7\x7b\xea\x8b\x76\x60\xef\x94\x59\x74\x5e\x05\x9f\x3c\xa9\x6b\x71\x4f\x50\x62\xe8\xb8\x3d\xca\xb2\x53\xa9\x4c\x89\x56\x3e\xbc\x7d\x7c\x82\x86\x81\xa8\xf6\xa8\xe1\x96\xb7\xec\x94\x2d\x8a\x52\x66\x4e\x2e\xae\x9c\x3b\x5b\x06\x2a\x64\xf2\xca\x2a\xe3\xc3\x43\xa6\x15\x19\x0f\x5c\xcf\x4a\xe5\xc5\x8a\x7f\xd4\xc4\x5e\xec\x30\x86\xdb\x00\x0d\x30\x23\xa8\xab\x1c\x3d\xe5\x63\xb8\x37\x70\x8b\x25\xe9\x5b\x64\xfa\xe6\xaa\x16\x8d\xf2\x48\xd4\xd7\x5f\xd9\x6d\x64\x3b\xdc\x70\x10\x25\x00\x0d\xfc\xbc\x68\x9d\x26\x22\x1f\x2b\xca\x3a\xa1\x90\x13\x2b\x27\xae\xeb\xd1\x93\x38\x7c\x07\x76\xfa\x1c\xed\xd1\xd7\xdc\xef\xf0\xb0\xb4\x73\xbc\x9d\xb1\x18\xba\x75\x3e\x9a\x1d\x7c\x48\xa4\x88\x41\x33\x5b\x56\xd6\x88\x63\xf4\xe5\xea\x65\xe8\x80\x90\x1c\x1a\x7a\x87\xef\xf6\x78\xbf\xdd\x2e\x4d\xf3\x33\xe2\xad\xf7\x8a\x0c\xe8\x23\x39\xa6\x28\xd0\x11\x70\xeb\xc1\xad\x0c\x71\x5b\xb1\xc5\x31\x9e\x04\x9c\x35\xce\x48\x3f\x92\xa6\xec\xd0\x3c\xe7\x24\x96\xd1\xd9\x7f\x7c\xc9\x9e\xf0\xbf\xb6\x77\xc4\xd8\x0e\x44\xe0\x8f\x9a\xdc\x06\xec\x8a\x9c\x84\x3b\x79\x31\xdc\x4e\x29\x35\x53\x2e\x18\xc8\x61\x67\x47\x2d\xd7\x27\x8c\xd9\x53\x4d\x7d\x44\x95\x51\xa2\xcf\x8a\xb7\xcf\x02\x29\xad\x1c\xd7\x43\xea\xfd\x8d\x49\x70\xc5\x41\xcc\xa8\x00\x6e\x94\x92\x8c\x56\x46\xd4\x7a\x2a\xa8\x33\x03\xe8\x08\x6e\x1e\xee\x28\x3f\xe6\x0f\x5d\x81\xd1\x39\xdc\x9c\x58\xa5\x3c\x95\x27\x85\xd8\x13\xe3\xe6\x04\xab\x09\xa7\x9b\x37\xc9\x8b\x8d\x47\x65\x38\xe5\xa0\x21\x20\x2c\x69\x13\xd3\x95\x64\xc1\x26\x28\xc3\x62\x47\x21\xb9\x05\xdb\x2e\x69\x13\x16\xa5\xdc\x75\x92\xc3\x1e\xb6\x8d\xe3\x74\x30\xec\xc6\x48\x8e\x3f\xbb\xc6\x1e\x07\xb5\xee\xe8\xe3\x54\x71\x2c\x69\x73\x6e\xc9\x9e\x31\x44\x47\x8a\x53\x55\x20\x56\x91\x89\xa0\x49\x99\xda\x1a\x02\xab\x4a\x2b\x0a\x89\xeb\x2c\xfd\x17\xb3\xc7\xe1\x68\xc4\xbf\x90\x69\x7b\xb4\x8c\x5b\xd2\xe6\x9a\xa3\x03\x48\x74\x14\xaa\x92\x58\xdf\xc2\x40\x53\xc1\x7c\x42\xad\xf2\x5d\x51\x1a\x22\xe1\xde\x0c\xe1\xc1\x7a\xf9\x79\xfb\xac\x24\x43\x8b\xdf\xdc\x59\xe2\x07\xeb\xc3\xcc\xab\x8a\x1d\x59\xb9\x50\xe8\xb8\x29\x04\x88\x89\x31\x29\x52\xb5\x4b\x1a\x1e\xc3\xfd\xbc\x83\x6a\xb2\xfa\xde\x80\x75\x8d\x74\xa1\xc8\x8c\x84\x22\x89\xb2\xe6\x50\x83\x18\x6b\x46\x54\x56\x7e\x73\x94\x46\x52\x8a\x75\x1d\x9d\x9c\x20\x97\x48\x3d\x49\x69\x14\xdf\xc4\x22\x56\x63\x46\x39\xe4\x75\x60\x3a\x14\x64\xd2\x6e\xa8\x0c\x4a\x72\x0b\x82\x4a\x10\xae\xaf\xaa\xcf\xe1\x52\x1c\x3d\xd0\xa9\x4d\xf4\x8c\xfd\x02\x04\x87\xec\x73\x21\x6c\xc7\x3d\x11\xde\x4a\xac\xc4\x74\x9f\x05\xc5\x82\xf6\xbe\x40\x85\xca\xf1\x18\x6e\x42\x7b\xa4\xa9\xf3\x4e\x99\xa0\xe7\x36\x19\xa1\xa0\x18\x04\x8a\x56\xa8\x05\x37\xc5\xd3\x0d\x90\x8e\x28\x6a\xe7\x07\xc9\x62\x08\xeb\x42\x6a\x01\x89\xef\xb9\x22\x1d\x4a\xe2\xc1\x92\x36\x83\xe1\x81\xb9\x07\xf7\x66\x10\xf1\xf5\xc0\xc0\x5b\x30\xb6\x46\x6f\x60\x10\xde\x0d\xfe\xb7\xfc\x72\x16\x74\x31\xcf\x43\x63\x8d\xfa\x7d\x4f\x24\x3c\x6b\x4b\x47\xf3\x17\x49\x74\x8c\xf7\x81\xe6\x51\x98\x56\x39\x31\x27\x47\x26\x14\x59\xf6\xc5\x1a\x62\x57\x75\x0c\x13\x8a\x52\x0e\x6b\xe5\x8b\x6e\xed\xf2\x92\x76\xce\x7b\xf8\x19\xbf\xee\x0a\xa1\xb2\xe2\x43\xc3\x76\xf4\xc1\xad\x14\x11\x23\x1b\x6e\x87\x40\xc6\xa9\xac\x68\x98\x95\x22\x37\x16\xd2\x62\xf9\x68\x86\x13\x99\xb4\x97\x41\xfb\xa5\xb3\x97\x3b\xe9\x13\x82\xde\xbc\xbf\x6f\x7a\xe8\xd8\x3a\x53\x23\xe8\x19\x00\xef\x09\xde\x3b\x1d\x5c\xc0\xd4\xed\x76\x53\x3b\x5f\xb5\xfa\xf0\x6d\x8b\x11\x5a\xc6\xc6\x83\xfa\x30\x7c\x1e\x02\x7b\xc1\xdf\x71\x76\x77\xdc\xb6\x99\xc5\x15\x2a\x8d\x33\xdd\xb4\x48\x31\xd9\xa6\x06\x69\xcb\xfc\x75\x74\x1b\x3a\x87\xe5\xbd\xcb\xae\xfe\x85\x97\x94\x55\xd1\x65\x7b\x2c\x94\xf3\xcf\x2c\xeb\x5f\x7d\x49\x27\xc3\xfe\xc9\xa1\x61\xd5\x5c\xd9\xf5\xc9\x3c\x7b\xad\x0d\x7b\xf0\xaa\xa4\xe4\x0d\x8d\x31\xfc\x96\x2c\xe5\xf1\xb6\xc1\x1a\x6a\x62\x33\xa0\xbf\xf5\x05\xbd\x08\x28\xed\x71\x41\xa5\x22\x63\x6e\x5d\x89\x7e\x0a\x39\x7a\x1a\x09\x67\xbd\xd4\xf0\x31\x5c\x6a\xbc\xaa\x0a\xd6\xc8\x62\x8d\x19\xe5\x7f\x05\x21\x4b\x62\xc6\xc5\xe5\xd2\xdd\x40\x51\x97\x28\xd1\x85\x79\x88\xa3\x44\x08\x94\xc9\x55\x86\xe1\x3a\x2a\x27\x8f\x4a\x33\xe0\xcc\xd6\x31\xfa\x76\xe6\x7f\x75\x0b\x3b\x42\x3e\x87\xb2\x47\xe4\x88\x29\x5f\xb6\x8a\xf2\xba\xa6\xba\xe6\xe0\x03\xdf\x92\xeb\xe3\xd7\x3b\x67\xb9\x4e\x57\x3d\x5b\xb0\x4d\x0c\x0f\x43\x34\xd9\x39\x3c\xb9\x9a\x86\xf0\x0b\x6a\xa6\x21\x7c\x34\x4b\x63\xd7\xaf\xcf\x7b\x58\x7c\xb1\xbe\x37\x55\xe0\x70\xcb\xf3\x2b\xb2\x15\x0a\xc2\xf7\xe8\x8b\x0b\xd2\xda\xf5\x7d\xaa\x85\x42\x2d\x1f\xaa\x88\x4a\x51\x46\x9d\xcb\x69\x50\x86\x3d\x61\x9e\x26\xc9\x78\xe5\x28\xbd\x1b\xc6\x9b\xd3\xd4\xc1\xec\x2e\xaf\xa5\xbe\x04\x94\xb2\x53\xe5\xf0\x8f\xc7\x77\x0f\x93\xbf\xdb\x54\xb2\x62\x96\x11\xa7\xd4\x22\x75\xe6\x10\xb8\xce\x0a\x40\x6e\xae\x0b\x1f\x43\xd2\x29\xd1\xa8\x39\xb1\x1f\x27\x6a\xe4\xf8\xb7\x37\xbf\x8f\xe1\x17\xeb\x80\x9e\xb1\xac\x34\x0d\x41\xa5\x36\xa7\xb9\xe2\x6d\x95\x47\x41\x98\xed\xde\x50\x09\x05\x96\x2a\x9b\x27\xa6\xd7\x81\x59\x8f\x4b\x02\x9b\x98\xad\x09\xb4\x5a\xd2\x14\x06\x5c\x51\xd6\x3a\xfa\xb3\xc1\x92\xbe\x0c\xe0\xfb\x75\x41\x8e\x60\x20\x8f\x83\x78\xe0\xb6\x84\x94\xb9\x96\x53\xa6\x83\x63\x1f\xee\xd4\x62\x41\x8e\x62\x31\x4e\x2b\x32\xfe\x07\xe9\xc4\xd4\x1c\x8c\x6d\x2d\x0e\x24\x44\x9f\x15\x65\x6a\xae\x28\x3f\x60\xe4\xb7\x37\xbf\x0f\xe0\xfb\xae\x5c\x82\x3a\xf4\x0c\x6f\x62\x97\xa1\x58\x64\xfc\x21\x35\x6e\xbc\x31\x1e\x9f\x85\x66\x26\xad\x83\x89\x35\xbf\xb7\x50\xe0\x8a\x80\x6d\x49\xb0\x26\xad\x47\xf1\xde\x34\x87\x75\x6c\x49\x1b\x55\xc6\x16\xaf\x42\xe7\xf7\xbe\x57\x3c\xbd\xbb\x7b\x37\x8d\xa7\x89\xd9\x16\x46\x8e\x30\xd6\xc3\x5c\x19\xd4\xa9\xef\x50\xbc\x6b\x53\xb8\x8e\x46\xf2\x16\xb2\x02\x4d\xc0\xca\xa0\x8d\x79\xed\x6b\x47\xe3\xfd\xfb\xeb\xaf\x8a\x81\x63\x1f\x12\x4e\xb9\x7f\xf8\xac\xb0\x5f\x64\xfe\x1f\x2f\xed\xbf\x4a\xe8\xf0\x5d\xed\x02\xa1\x1f\x5a\x7e\x7a\x52\xe8\x65\x3d\x23\x67\xc8\x53\x90\x3b\xb7\x19\x8b\xc8\x19\x55\x9e\x27\x76\x45\x6e\xa5\x68\x3d\x59\x5b\xb7\x54\x66\x31\x12\x47\x1c\x45\xef\xe0\x49\xf8\x16\x39\xf9\x2e\xfc\xbc\x9a\x8c\x5c\x61\x76\xb1\xa0\x61\xd3\x9f\x21\xad\x9c\xc3\x93\x57\x11\xb6\x69\xe4\x2e\xef\x9d\xae\x1f\x23\x70\x64\xfb\x34\x24\xec\xd6\x85\xca\x8a\xe6\x53\x64\x0b\x29\x4b\xcc\x23\x94\xa2\xd9\x7c\x73\xe7\x17\x95\xd6\x4e\xce\xde\x8c\xd2\x67\xf4\x11\x9a\x5c\xfe\xb3\x62\x2f\xf3\xaf\xa2\xc3\x5a\x5d\x04\x04\x1f\xef\xef\xfe\x9c\x90\xa8\xd5\x57\x44\x7d\xfc\x8c\x35\x05\xef\xea\xa6\xa6\x65\x6f\x9d\x54\xae\x9d\xb9\x7a\xb6\xbd\xb1\xd8\x09\x9f\x8a\x2c\xf8\xfc\xe5\xea\xbf\x01\x00\x00\xff\xff\x7e\x2b\xf8\xdd\x18\x21\x00\x00") +var _operatorsCoreosCom_operatorsYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\x59\x5f\x73\xe3\xb6\x11\x7f\xf7\xa7\xd8\x51\x1e\x9c\xcc\xe8\x4f\x72\x7d\x69\xf5\xe6\xb1\x2f\x1d\xb7\xa9\xef\xe6\xec\xbb\x97\x4c\x1e\x56\xe4\x4a\x44\x05\x02\x0c\x16\x94\xac\xde\xdc\x77\xef\x2c\x00\x4a\xa4\x24\x4b\xd4\xd5\x97\x06\x2f\x12\x41\x60\xb1\x7f\x7f\xbb\x0b\x62\xa5\x3e\x91\x63\x65\xcd\x14\xb0\x52\xf4\xec\xc9\xc8\x13\x8f\x97\x7f\xe5\xb1\xb2\x93\xd5\x4f\x57\x4b\x65\xf2\x29\xdc\xd6\xec\x6d\xf9\x81\xd8\xd6\x2e\xa3\x3b\x9a\x2b\xa3\xbc\xb2\xe6\xaa\x24\x8f\x39\x7a\x9c\x5e\x01\xa0\x31\xd6\xa3\x4c\xb3\x3c\x02\x64\xd6\x78\x67\xb5\x26\x37\x5a\x90\x19\x2f\xeb\x19\xcd\x6a\xa5\x73\x72\x81\x78\x73\xf4\xea\xc7\xf1\xdf\xc6\x3f\x5e\x01\x64\x8e\xc2\xf6\x27\x55\x12\x7b\x2c\xab\x29\x98\x5a\xeb\x2b\x00\x83\x25\x4d\xc1\x56\xe4\xd0\x5b\xc7\xe3\xdd\xbf\xcc\x3a\xb2\xf2\x53\x5e\x71\x45\x99\x1c\xbc\x70\xb6\xae\xda\xab\x5b\x6b\x22\xa9\x86\x3f\xf4\xb4\xb0\x4e\x35\xcf\x00\x23\xb0\xba\x0c\xff\xa3\xdc\xef\x12\x8d\x30\xa5\x15\xfb\x7f\x76\xa6\x7f\x51\xec\xc3\xab\x4a\xd7\x0e\x75\xeb\xcc\x30\xcb\xca\x2c\x6a\x8d\x6e\x37\x7f\x05\xc0\x99\xad\x68\x0a\xb7\xba\x66\x4f\x32\x91\xf4\x90\x78\x18\x25\x59\x57\x3f\x25\x96\x38\x2b\xa8\xc4\x86\x41\x10\x52\xe6\xe6\xfd\xfd\xa7\xbf\x3c\xee\xbd\x00\xc8\x89\x33\xa7\x2a\x1f\xb4\xda\xf0\x08\x8e\x2a\x47\x4c\xc6\x33\x20\x64\xf1\xd8\x2d\x43\xe3\xd6\x76\xbf\x11\xc6\xec\xec\xdf\x94\xf9\xd6\x74\xe5\x64\xb1\x6f\x69\x29\x8e\x96\xf7\x74\xe6\xf7\xf8\xb8\x16\x66\xe3\x3a\xc8\xc5\x71\x88\xc1\x17\xd4\x88\x4d\x79\x92\x10\xec\x1c\x7c\xa1\x78\xc7\x6f\xf0\x05\x99\x46\x93\xb8\x1a\xc3\x23\x39\xd9\x08\x5c\xd8\x5a\xe7\xe2\x61\x2b\x72\x1e\x1c\x65\x76\x61\xd4\x7f\xb6\xd4\x18\xbc\x0d\xc7\x68\xf4\xc4\x1e\x94\xf1\xe4\x0c\x6a\x58\xa1\xae\x69\x08\x68\x72\x28\x71\x03\x8e\x84\x2e\xd4\xa6\x45\x21\x2c\xe1\x31\xfc\xcb\x3a\x02\x65\xe6\x76\x0a\x85\xf7\x15\x4f\x27\x93\x85\xf2\x4d\x6c\x64\xb6\x2c\x6b\xa3\xfc\x66\x12\xdc\x5c\xcd\x6a\xb1\xfb\x24\xa7\x15\xe9\x09\xab\xc5\x08\x5d\x56\x28\x4f\x99\xaf\x1d\x4d\xb0\x52\xa3\xc0\xac\x09\xf1\x31\x2e\xf3\xef\x5c\x8a\x26\xbe\xde\x53\x5f\xb4\x03\x7b\xa7\xcc\xa2\xf3\x2a\xf8\xe4\x49\x5d\x8b\x7b\x82\x12\x43\xc7\xed\x51\x96\x9d\x4a\x65\x4a\xb4\xf2\xe1\xed\xe3\x13\x34\x0c\x44\xb5\x47\x0d\xb7\xbc\x65\xa7\x6c\x51\x94\x32\x73\x72\x71\xe5\xdc\xd9\x32\x50\x21\x93\x57\x56\x19\x1f\x1e\x32\xad\xc8\x78\xe0\x7a\x56\x2a\x2f\x56\xfc\xbd\x26\xf6\x62\x87\x31\xdc\x06\x68\x80\x19\x41\x5d\xe5\xe8\x29\x1f\xc3\xbd\x81\x5b\x2c\x49\xdf\x22\xd3\x37\x57\xb5\x68\x94\x47\xa2\xbe\xfe\xca\x6e\x23\xdb\xe1\x86\x83\x28\x01\x68\xe0\xe7\x45\xeb\x34\x11\xf9\x58\x51\xd6\x09\x85\x9c\x58\x39\x71\x5d\x8f\x9e\xc4\xe1\x3b\xb0\xd3\xe7\x68\x8f\xbe\xe6\x7e\x87\x87\xa5\x9d\xe3\xed\x8c\xc5\xd0\xad\xf3\xd1\xec\xe0\x43\x22\x45\x0c\x9a\xd9\xb2\xb2\x46\x1c\xa3\x2f\x57\x2f\x43\x07\x84\xe4\xd0\xd0\x3b\x7c\xb7\xc7\xfb\xed\x76\x69\x9a\x9f\x11\x6f\xbd\x57\x64\x40\x1f\xc9\x31\x45\x81\x8e\x80\x5b\x0f\x6e\x65\x88\xdb\x8a\x2d\x8e\xf1\x24\xe0\xac\x71\x46\xfa\x91\x34\x65\x87\xe6\x39\x27\xb1\x8c\xce\xfe\xe3\x4b\xf6\x84\xff\xa5\xbd\x23\xc6\x76\x20\x02\xbf\xd7\xe4\x36\x60\x57\xe4\x24\xdc\xc9\x8b\xe1\x76\x4a\xa9\x99\x72\xc1\x40\x0e\x3b\x3b\x6a\xb9\x3e\x61\xcc\x9e\x6a\xea\x23\xaa\x8c\x12\x7d\x56\xbc\x7d\x16\x48\x69\xe5\xb8\x1e\x52\xef\x6f\x4c\x82\x2b\x0e\x62\x46\x05\x70\xa3\x94\x64\xb4\x32\xa2\xd6\x53\x41\x9d\x19\x40\x47\x70\xf3\x70\x47\xf9\x31\x7f\xe8\x0a\x8c\xce\xe1\xe6\xc4\x2a\xe5\xa9\x3c\x29\xc4\x9e\x18\x37\x27\x58\x4d\x38\xdd\xbc\x49\x5e\x6c\x3c\x2a\xc3\x29\x07\x0d\x01\x61\x49\x9b\x98\xae\x24\x0b\x36\x41\x19\x16\x3b\x0a\xc9\x2d\xd8\x76\x49\x9b\xb0\x28\xe5\xae\x93\x1c\xf6\xb0\x6d\x1c\xa7\x83\x61\x37\x46\x72\xfc\xd9\x35\xf6\x38\xa8\x75\x47\x1f\xa7\x8a\x63\x49\x9b\x73\x4b\xf6\x8c\x21\x3a\x52\x9c\xaa\x02\xb1\x8a\x4c\x04\x4d\xca\xd4\xd6\x10\x58\x55\x5a\x51\x48\x5c\x67\xe9\xbf\x98\x3d\x0e\x47\x23\xfe\x85\x4c\xdb\xa3\x65\xdc\x92\x36\xd7\x1c\x1d\x40\xa2\xa3\x50\x95\xc4\xfa\x16\x06\x9a\x0a\xe6\x13\x6a\x95\xef\x8a\xd2\x10\x09\xf7\x66\x08\x0f\xd6\xcb\xcf\xdb\x67\x25\x19\x5a\xfc\xe6\xce\x12\x3f\x58\x1f\x66\x5e\x55\xec\xc8\xca\x85\x42\xc7\x4d\x21\x40\x4c\x8c\x49\x91\xaa\x5d\xd2\xf0\x18\xee\xe7\x1d\x54\x93\xd5\xf7\x06\xac\x6b\xa4\x0b\x45\x66\x24\x14\x49\x94\x35\x87\x1a\xc4\x58\x33\xa2\xb2\xf2\x9b\xa3\x34\x92\x52\xac\xeb\xe8\xe4\x04\xb9\x44\xea\x49\x4a\xa3\xf8\x26\x16\xb1\x1a\x33\xca\x21\xaf\x03\xd3\xa1\x20\x93\x76\x43\x65\x50\x92\x5b\x10\x54\x82\x70\x7d\x55\x7d\x0e\x97\xe2\xe8\x81\x4e\x6d\xa2\x67\xec\x17\x20\x38\x64\x9f\x0b\x61\x3b\xee\x89\xf0\x56\x62\x25\xa6\xfb\x2c\x28\x16\xb4\xf7\x05\x2a\x54\x8e\xc7\x70\x13\xda\x23\x4d\x9d\x77\xca\x04\x3d\xb7\xc9\x08\x05\xc5\x20\x50\xb4\x42\x2d\xb8\x29\x9e\x6e\x80\x74\x44\x51\x3b\x3f\x48\x16\x43\x58\x17\x52\x0b\x48\x7c\xcf\x15\xe9\x50\x12\x0f\x96\xb4\x19\x0c\x0f\xcc\x3d\xb8\x37\x83\x88\xaf\x07\x06\xde\x82\xb1\x35\x7a\x03\x83\xf0\x6e\xf0\xbf\xe5\x97\xb3\xa0\x8b\x79\x1e\x1a\x6b\xd4\xef\x7b\x22\xe1\x59\x5b\x3a\x9a\xbf\x48\xa2\x63\xbc\x0f\x34\x8f\xc2\xb4\xca\x89\x39\x39\x32\xa1\xc8\xb2\x2f\xd6\x10\xbb\xaa\x63\x98\x50\x94\x72\x58\x2b\x5f\x74\x6b\x97\x97\xb4\x73\xde\xc3\xcf\xf8\x75\x57\x08\x95\x15\x1f\x1a\xb6\xa3\x0f\x6e\xa5\x88\x18\xd9\x70\x3b\x04\x32\x4e\x65\x45\xc3\xac\x14\xb9\xb1\x90\x16\xcb\x47\x33\x9c\xc8\xa4\xbd\x0c\xda\x2f\x9d\xbd\xdc\x49\x9f\x10\xf4\xe6\xfd\x7d\xd3\x43\xc7\xd6\x99\x1a\x41\xcf\x00\x78\x4f\xf0\xde\xe9\xe0\x02\xa6\x6e\xb7\x9b\xda\xf9\xaa\xd5\x87\x6f\x5b\x8c\xd0\x32\x36\x1e\xd4\x87\xe1\xf3\x10\xd8\x0b\xfe\x8e\xb3\xbb\xe3\xb6\xcd\x2c\xae\x50\x69\x9c\xe9\xa6\x45\x8a\xc9\x36\x35\x48\x5b\xe6\xaf\xa3\xdb\xd0\x39\x2c\xef\x5d\x76\xf5\x2f\xbc\xa4\xac\x8a\x2e\xdb\x63\xa1\x9c\x7f\x66\x59\xff\xea\x4b\x3a\x19\xf6\x4f\x0e\x0d\xab\xe6\xca\xae\x4f\xe6\xd9\x6b\x6d\xd8\x83\x57\x25\x25\x6f\x68\x8c\xe1\xb7\x64\x29\x8f\xb7\x0d\xd6\x50\x13\x9b\x01\xfd\xad\x2f\xe8\x45\x40\x69\x8f\x0b\x2a\x15\x19\x73\xeb\x4a\xf4\x53\xc8\xd1\xd3\x48\x38\xeb\xa5\x86\x8f\xe1\x52\xe3\x55\x55\xb0\x46\x16\x6b\xcc\x28\xff\x33\x08\x59\x12\x33\x2e\x2e\x97\xee\x06\x8a\xba\x44\x89\x2e\xcc\x43\x1c\x25\x42\xa0\x4c\xae\x32\x0c\xd7\x51\x39\x79\x54\x9a\x01\x67\xb6\x8e\xd1\xb7\x33\xff\xab\x5b\xd8\x11\xf2\x39\x94\x3d\x22\x47\x4c\xf9\xb2\x55\x94\xd7\x35\xd5\x35\x07\x1f\xf8\x96\x5c\x1f\xbf\xde\x39\xcb\x75\xba\xea\xd9\x82\x6d\x62\x78\x18\xa2\xc9\xce\xe1\xc9\xd5\x34\x84\x9f\x51\x33\x0d\xe1\xa3\x59\x1a\xbb\x7e\x7d\xde\xc3\xe2\x8b\xf5\xbd\xa9\x02\x87\x5b\x9e\x5f\x91\xad\x50\x10\xbe\x47\x5f\x5c\x90\xd6\xae\xef\x53\x2d\x14\x6a\xf9\x50\x45\x54\x8a\x32\xea\x5c\x4e\x83\x32\xec\x09\xf3\x34\x49\xc6\x2b\x47\xe9\xdd\x30\xde\x9c\xa6\x0e\x66\x77\x79\x2d\xf5\x25\xa0\x94\x9d\x2a\x87\x7f\x3c\xbe\x7b\x98\xfc\xdd\xa6\x92\x15\xb3\x8c\x38\xa5\x16\xa9\x33\x87\xc0\x75\x56\x00\x72\x73\x5d\xf8\x18\x92\x4e\x89\x46\xcd\x89\xfd\x38\x51\x23\xc7\xbf\xbe\xf9\x6d\x0c\x3f\x5b\x07\xf4\x8c\x65\xa5\x69\x08\x2a\xb5\x39\xcd\x15\x6f\xab\x3c\x0a\xc2\x6c\xf7\x86\x4a\x28\xb0\x54\xd9\x3c\x31\xbd\x0e\xcc\x7a\x5c\x12\xd8\xc4\x6c\x4d\xa0\xd5\x92\xa6\x30\xe0\x8a\xb2\xd6\xd1\x9f\x0d\x96\xf4\x65\x00\xdf\xaf\x0b\x72\x04\x03\x79\x1c\xc4\x03\xb7\x25\xa4\xcc\xb5\x9c\x32\x1d\x1c\xfb\x70\xa7\x16\x0b\x72\x14\x8b\x71\x5a\x91\xf1\x3f\x48\x27\xa6\xe6\x60\x6c\x6b\x71\x20\x21\xfa\xac\x28\x53\x73\x45\xf9\x01\x23\xbf\xbe\xf9\x6d\x00\xdf\x77\xe5\x12\xd4\xa1\x67\x78\x13\xbb\x0c\xc5\x22\xe3\x0f\xa9\x71\xe3\x8d\xf1\xf8\x2c\x34\x33\x69\x1d\x4c\xac\xf9\xbd\x85\x02\x57\x04\x6c\x4b\x82\x35\x69\x3d\x8a\xf7\xa6\x39\xac\x63\x4b\xda\xa8\x32\xb6\x78\x15\x3a\xbf\xf7\xbd\xe2\xe9\xdd\xdd\xbb\x69\x3c\x4d\xcc\xb6\x30\x72\x84\xb1\x1e\xe6\xca\xa0\x4e\x7d\x87\xe2\x5d\x9b\xc2\x75\x34\x92\xb7\x90\x15\x68\x02\x56\x06\x6d\xcc\x6b\x5f\x3b\x1a\xef\xdf\x5f\x7f\x55\x0c\x1c\xfb\x90\x70\xca\xfd\xc3\x67\x85\xfd\x22\xf3\xff\x78\x69\xff\x55\x42\x87\xef\x6a\x17\x08\xfd\xd0\xf2\xd3\x93\x42\x2f\xeb\x19\x39\x43\x9e\x82\xdc\xb9\xcd\x58\x44\xce\xa8\xf2\x3c\xb1\x2b\x72\x2b\x45\xeb\xc9\xda\xba\xa5\x32\x8b\x91\x38\xe2\x28\x7a\x07\x4f\xc2\xb7\xc8\xc9\x77\xe1\xe7\xd5\x64\xe4\x0a\xb3\x8b\x05\x0d\x9b\xfe\x08\x69\xe5\x1c\x9e\xbc\x8a\xb0\x4d\x23\x77\x79\xef\x74\xfd\x18\x81\x23\xdb\xa7\x21\x61\xb7\x2e\x54\x56\x34\x9f\x22\x5b\x48\x59\x62\x1e\xa1\x14\xcd\xe6\x9b\x3b\xbf\xa8\xb4\x76\x72\xf6\x66\x94\x3e\xa3\x8f\xd0\xe4\xf2\x9f\x15\x7b\x99\x7f\x15\x1d\xd6\xea\x22\x20\xf8\x78\x7f\xf7\xc7\x84\x44\xad\xbe\x22\xea\xe3\x67\xac\x29\x78\x57\x37\x35\x2d\x7b\xeb\xa4\x72\xed\xcc\xd5\xb3\xed\x8d\xc5\x4e\xf8\x54\x64\xc1\xe7\x2f\x57\xff\x0d\x00\x00\xff\xff\x08\x9c\x4f\xa3\x18\x21\x00\x00") func operatorsCoreosCom_operatorsYamlBytes() ([]byte, error) { return bindataRead( @@ -225,7 +225,7 @@ func operatorsCoreosCom_operatorsYaml() (*asset, error) { return a, nil } -var _operatorsCoreosCom_subscriptionsYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xbd\x7b\x73\xe3\xb8\x95\x38\xfa\xff\x7c\x0a\x94\x93\x2a\xdb\x59\x49\xee\xce\xe6\x97\xe4\xf6\xa6\xb2\xe5\xb1\xdd\x13\xff\xa6\xbb\xc7\xdb\x76\xcf\xd4\xde\x6c\xee\x06\x22\x21\x09\x31\x09\x70\x00\x50\x6e\xe5\xf1\xdd\x6f\xe1\x1c\x00\x04\xa9\x17\x29\xc9\x8f\x9e\x21\xff\x98\x69\x53\x00\x08\x1c\x1c\x9c\x17\xce\x83\x16\xfc\x7b\xa6\x34\x97\xe2\x0d\xa1\x05\x67\x9f\x0d\x13\xf6\x2f\x3d\xba\xff\xbd\x1e\x71\x79\x36\x7f\xfd\xd5\x3d\x17\xe9\x1b\x72\x51\x6a\x23\xf3\x8f\x4c\xcb\x52\x25\xec\x92\x4d\xb8\xe0\x86\x4b\xf1\x55\xce\x0c\x4d\xa9\xa1\x6f\xbe\x22\x84\x0a\x21\x0d\xb5\xaf\xb5\xfd\x93\x90\x44\x0a\xa3\x64\x96\x31\x35\x9c\x32\x31\xba\x2f\xc7\x6c\x5c\xf2\x2c\x65\x0a\x06\xf7\x9f\x9e\xbf\x1a\xfd\x7e\xf4\xea\x2b\x42\x12\xc5\xa0\xfb\x1d\xcf\x99\x36\x34\x2f\xde\x10\x51\x66\xd9\x57\x84\x08\x9a\xb3\x37\x44\x97\x63\x9d\x28\x5e\xc0\x27\x46\xb2\x60\x8a\x1a\xa9\xf4\x28\x91\x8a\x49\xfb\xbf\xfc\x2b\x5d\xb0\xc4\x7e\x7c\xaa\x64\x59\xbc\x21\x2b\xdb\xe0\x70\x7e\x8e\xd4\xb0\xa9\x54\xdc\xff\x4d\xc8\x90\xc8\x2c\x87\x7f\xe3\xda\x6f\xa3\xaf\xc2\xeb\x8c\x6b\xf3\xed\xd2\x4f\xef\xb8\x36\xf0\x73\x91\x95\x8a\x66\x8d\xd9\xc2\x2f\x7a\x26\x95\xf9\x50\x7d\xdb\x7e\x4b\x97\xe3\xf8\xdf\xae\x21\x17\xd3\x32\xa3\xaa\x3e\xc8\x57\x84\xe8\x44\x16\xec\x0d\x81\x31\x0a\x9a\xb0\xf4\x2b\x42\x1c\x1c\xdd\x98\x43\x42\xd3\x14\xf6\x86\x66\x37\x8a\x0b\xc3\xd4\x85\xcc\xca\x5c\x84\x6f\xda\x36\x29\x0b\xa3\xbe\x21\x77\x33\x46\x0a\x9a\xdc\xd3\x29\xf3\xdf\x1b\xb3\x94\x18\x19\x3a\x10\xf2\x37\x2d\xc5\x0d\x35\xb3\x37\x64\x64\x41\x3c\xb2\x10\x8c\x7e\xc6\xfd\xb9\xc1\x41\xa2\xf7\x66\x61\xa7\xab\x8d\xe2\x62\xba\xe9\xf3\x09\x35\x34\x93\x53\x82\xf8\x45\x26\x52\x11\x33\x63\xc4\x7e\x8a\x4f\x38\x4b\xfd\xfc\x36\xcc\x08\xbb\x2e\xcd\xe9\xb6\xf9\xba\xf5\x94\x66\x54\x08\x96\x11\x39\x21\x65\x91\x52\xc3\x34\x31\xb2\x82\xcf\x66\xf0\xb8\xce\x4b\xb3\xb9\x58\x7a\xbf\x62\x3a\xd8\x74\xfe\x9a\x66\xc5\x8c\xbe\x76\x2f\x75\x32\x63\x39\xad\xf6\x50\x16\x4c\x9c\xdf\x5c\x7f\xff\xef\xb7\x8d\x1f\x48\x7d\x29\x31\x8a\x92\x7b\xc6\x0a\x5d\x1d\x0a\x52\x16\x76\x4d\x76\x71\x64\xbc\x20\x46\xd1\xe4\x9e\x8b\x29\x2c\x7d\x8a\xeb\xbd\xc0\x8d\xd1\xa3\xa5\x29\xcb\xf1\xdf\x58\x62\xa2\xd7\x8a\xfd\x58\x72\xc5\xd2\x78\x2a\x16\xb2\x9e\x44\x34\x5e\x5b\x38\x45\xaf\x0a\x65\xa7\x65\xa2\x73\x88\x4f\x44\xa3\x6a\xef\x1b\xcb\x3c\xb6\xb0\xc0\x76\x24\xb5\xe4\xc9\x4e\x7f\xc6\xfc\xe1\x60\xa9\x03\xa0\xdd\x4e\x33\xe3\x9a\x28\x56\x28\xa6\x99\x40\x82\x65\x5f\x53\xe1\xd6\x34\x22\xb7\x4c\xd9\x8e\xf6\xc0\x96\x59\x6a\xe9\xd8\x9c\x29\x43\x14\x4b\xe4\x54\xf0\xbf\x87\xd1\x00\x44\xf6\x33\x99\xc5\x0f\x43\xe0\xb8\x09\x9a\x91\x39\xcd\x4a\x36\x20\x54\xa4\x24\xa7\x0b\xa2\x98\x1d\x97\x94\x22\x1a\x01\x9a\xe8\x11\x79\x2f\x15\x23\x5c\x4c\xe4\x1b\x32\x33\xa6\xd0\x6f\xce\xce\xa6\xdc\x78\x0a\x9c\xc8\x3c\x2f\x05\x37\x8b\x33\x20\xa6\x7c\x5c\xda\x8d\x3b\x4b\xd9\x9c\x65\x67\x9a\x4f\x87\x54\x25\x33\x6e\x58\x62\x4a\xc5\xce\x68\xc1\x87\x30\x59\x81\x24\x32\x4f\x7f\xa1\x1c\xcd\xd6\xc7\x0d\xf0\xad\x3c\x07\xc4\x53\xbd\x8d\xb0\xb6\xc4\x8f\x70\x4d\xa8\xeb\x8e\x6b\xa9\x40\x6a\x5f\x59\xa8\x7c\xbc\xba\xbd\x23\x7e\x02\x08\x76\x84\x70\xd5\x54\x57\xc0\xb6\x80\xe2\x62\xc2\x14\xb6\x9c\x28\x99\xc3\x28\x4c\xa4\x85\xe4\xc2\xc0\x1f\x49\xc6\x99\x30\xf6\x18\xe6\xdc\x68\xc0\x39\xa6\x8d\xdd\x87\x11\xb9\x00\x06\x44\xc6\xcc\x1d\xd8\x74\x44\xae\x05\xb9\xa0\x39\xcb\x2e\xa8\x66\x8f\x0e\x6a\x0b\x51\x3d\xb4\xe0\x6b\x0f\xec\x98\x7f\x2e\x77\x58\x3a\x63\x84\x78\x06\xb7\x76\x77\xe2\x03\x7f\x5b\xb0\x24\x1c\x07\x2a\xc8\x79\x51\x64\x3c\x41\x8c\x37\x33\x6a\x48\x42\x85\x85\x17\x17\xda\xd0\x2c\x03\x76\xd2\x6a\x16\xeb\x4e\x3b\x81\xa3\xdd\x60\x0e\xfe\xf5\x12\x85\xae\xff\x10\x98\x5a\xa3\xc5\x3a\xca\x60\x1f\x47\x67\x97\x7f\xd8\x00\x72\x82\x92\xc9\x84\x4f\x57\x75\x5b\x0b\xcb\x0b\xe8\x02\x32\x0d\xe5\x42\xbb\x21\x4a\x85\xd0\xac\x38\x95\xe5\x5d\xb4\xc6\xb7\x47\x6b\x67\xb7\x12\xb2\xdb\xd6\x6c\x1f\x3a\x01\x09\x6c\xb1\xfa\xd7\xc6\x2a\xae\x27\xd5\xf4\x06\x44\xce\x99\x52\x3c\x75\xf4\xb1\x90\xe9\xb1\x06\x6a\x96\x96\x19\xd0\x7e\x29\xb4\x51\x94\xc3\xd1\x14\x3c\xb3\x2b\x19\x52\x83\xe7\x81\x69\xf2\xc0\xb3\x8c\xfc\x4a\x48\xf3\xab\x30\x12\x0c\x24\x15\x9f\xf2\x40\xfa\x34\xe1\xc2\x8f\x0f\x1c\xd1\xb1\x74\xa9\x59\x63\xc0\x11\xf9\xa4\x19\x61\x79\x61\x16\x9e\x38\x9c\xfc\xe3\x5f\xa7\x96\xb0\x32\x45\x75\x34\x70\xad\x9f\x27\x9f\x6b\xd6\xbf\x05\xbc\x6d\x40\x6c\x1f\x21\x53\x76\xbe\x05\xd4\x4b\xe0\xbe\x64\x28\x21\x68\xe8\x1e\xb6\x2a\x06\xb2\x2a\x33\xa6\x83\x94\x63\x61\xb4\x61\xf0\x16\x6b\x69\xbb\x1e\x6c\xc7\x26\x4c\x29\x96\x5e\x96\xf6\x68\xdc\x86\x59\x5d\x4f\x85\x0c\xaf\xaf\x3e\xb3\xa4\x34\x2b\xb8\xee\xc6\xa5\x5b\xb9\xc9\x2d\x93\x29\x44\x15\xfc\x1c\x88\x4e\xee\x07\xbb\x5e\x60\x9c\x16\x3c\x1a\xe9\x90\xa6\x86\xeb\xc9\x02\xc0\x11\x00\xc6\x3e\x5b\x26\x01\xb2\x6d\x74\xbe\xac\xa0\x02\xfc\x81\xb3\x2c\x1d\x90\x71\x69\x08\x37\xc0\x3c\x92\x99\xb4\xf8\x45\x11\xee\x30\xee\x9c\x4b\x60\xcd\x44\x0a\x8b\x49\x24\xb7\x1c\x00\x44\x00\x16\x0f\x3f\x82\x99\x57\xdd\xb8\x26\xb9\xd4\xa6\x82\x95\x7d\x03\x58\x2e\x18\x79\xe0\x66\x06\x7f\x4c\xad\xba\x62\xd9\xbe\x2e\x73\x3b\xe8\x03\xe3\xd3\x99\xd1\x03\xc2\x47\x6c\x04\xbb\xcb\x68\x32\x8b\x86\xcd\x19\x33\x9a\xd0\x2c\xf3\x53\x88\x51\x02\xe9\x69\x6e\x79\x22\x39\x09\x4c\xd3\x31\xb8\x41\xa0\xb7\xcd\x5d\x5b\x09\xae\x01\x61\x26\x19\x9d\x0e\x48\x22\xf3\xc2\x9e\x16\x0a\x73\x1c\x2f\x08\x37\x56\xf6\x43\x06\xad\x64\x39\xc5\x95\xb0\xcc\x7d\xd8\x4b\x47\x00\x5c\x10\x5f\xac\x36\x21\xa6\xe4\x08\x17\x77\xe4\x05\x1e\x3b\x1c\xc7\x45\xc0\xfa\x72\x6a\x92\x99\xa3\x29\x89\x54\x8a\xe9\x42\x0a\xe8\x09\xbf\x5c\x55\x73\xfb\x8f\xd0\xe9\x44\x9f\x56\xc0\x9c\xf1\xe9\xcc\xc3\x92\x2a\xa4\x29\xf5\x3d\xd8\x74\x46\xaa\x73\x42\x95\xa2\x8b\x2d\x2d\xb9\x61\xf9\x96\x53\xb2\x84\xda\xe7\xc2\x11\xa9\x0a\x27\xa2\xdd\x33\x4c\xe5\x01\x06\xb0\xc1\x70\x5c\x35\xae\x8f\xe7\x96\xed\x72\xe3\x30\x84\xbc\x22\x27\x80\x22\xdc\x1c\x6b\x40\xd7\xa1\x2c\x4e\x47\xe4\x1c\xb4\xdd\x16\x1f\x10\x32\x8c\xef\x06\xb2\x1f\xd5\xb2\x1a\x6b\xeb\xda\x5a\x12\x15\x7c\xd6\xf3\xfa\xe5\x67\xe8\xe6\xcf\xc4\x0a\x56\xbf\xaa\x39\xc2\x64\x6b\xd3\xb6\xe4\xcd\xb7\xf6\x73\x68\xd3\xba\xb9\xd5\x88\xd2\x9a\x65\x2c\x31\x96\x46\x33\x95\x0f\x08\xd5\x5a\x26\xdc\x8a\x95\x15\xd2\xd6\x31\x1d\x57\xb2\x1d\xf6\xa4\x2b\xfc\x49\xe7\xf5\xdb\xa7\x79\xf0\xda\xf6\x5b\x82\x46\xc6\xb5\xb1\x94\xa1\x0e\x95\x1a\xc1\x1a\x2f\xe0\xd7\x63\x4d\x32\x3a\x66\xd9\x5a\xbe\xbc\xfc\xb4\x3f\xb5\xd5\xd3\xf2\xfc\xae\x5d\xd0\xda\x85\x38\xa5\x26\x6c\x3c\x88\xc8\x5e\xe0\x43\x89\x63\x40\x28\xb9\x67\x0b\xd4\xed\xac\xca\xe8\x94\x69\x6c\xac\x18\xb2\x1b\x8b\x1c\xf7\x6c\x01\x8d\x36\x4b\x2a\xeb\x61\xd2\x01\x39\xf0\xe9\x72\x4c\xab\x67\x68\x27\xda\xb1\x87\x5f\x74\x87\x6e\xdd\xf1\x17\x9f\x7b\xb6\x51\xf2\x5a\xf5\x2c\x89\x24\x80\x93\xb0\x1f\xb0\x49\xc0\xbf\xfc\x1e\x53\xab\x12\x81\xad\xa3\xcb\x0e\x91\x6d\x0a\xc6\xa6\xc7\x43\x6f\xaf\x75\x7d\x0c\x1a\x34\x22\xe4\xb1\x46\xe4\xb3\x27\x7d\xc6\xc1\xae\x63\x31\x19\x0e\xae\x37\x35\x7c\x4f\x33\x9e\x46\xe6\x1f\xcb\x67\xaf\xc5\x80\x7c\x90\xc6\xfe\xef\xea\x33\xd7\x56\x7c\xb9\x94\x4c\x7f\x90\x06\xfe\x1c\x91\x6f\x0c\xe2\xfa\xbb\x96\x94\xed\x00\x00\xc2\xf9\xee\x05\x9e\x73\x81\x34\xc5\x2e\x3f\x36\x52\xe8\x91\x55\x87\x40\x94\xf3\x07\x97\x6b\x72\x2d\xac\x70\xe8\xc0\x00\x66\x23\x54\x62\x70\x88\xbc\xd4\x60\x55\x10\x52\x0c\x41\x06\x58\x39\x06\x42\xcf\x8e\x13\xc3\x6f\xc3\x70\xeb\x87\xfa\xc6\xd8\x61\xde\xad\xed\x3c\xa3\x73\x10\xe9\xb8\x98\x66\x41\x78\x1b\x90\x87\x19\x4f\x66\x28\x75\x83\x4e\x6f\x98\x2a\x14\xb3\x0c\x8b\x82\xf6\x6f\xdf\x4c\x99\xb2\xc2\x2e\xf7\xe3\xa1\x25\x2c\xa3\x09\x4b\x49\x0a\xa2\x25\x5a\x75\xa8\x61\x53\x9e\x90\x9c\xa9\x29\x23\x85\xe5\x24\xbb\xed\x7e\x37\xc2\x8e\x4f\x67\xf2\x1e\x7f\xb0\x13\xba\x01\x8b\x7c\x6b\x65\xdd\x27\xe2\x8e\x20\x57\xf7\xdc\xb1\xe7\x8e\x8d\xa7\xe7\x8e\xe1\xe9\xb9\xe3\x96\xa7\xe7\x8e\x3d\x77\x7c\x74\xee\x88\xba\xec\x0e\xca\xf3\x0f\x68\xe2\x68\x6a\xcb\xc0\x69\xfd\xbd\x50\x5d\x6d\xb6\xfc\xe6\xd6\x11\x9c\x3b\x50\xb5\x9d\xed\x58\x51\x31\x65\xe4\xf5\xf0\xf5\xab\x57\x5d\x94\x6a\xb7\x91\xad\x7a\x4c\xa4\xca\xa9\x81\x3e\xff\xfe\xeb\x8d\x3d\xd6\xd9\xdf\x0e\x60\x35\x75\x38\x1e\x0c\x79\x35\xd9\x61\x8d\xe1\x13\xa8\x93\x90\x86\xe4\xcc\x10\x6a\x6a\xa6\x22\x9e\xb3\x81\x37\x2c\x23\xc2\xbb\x6b\x31\x6f\x81\x4d\x89\x14\xce\x8e\x67\x81\x3f\xda\x6d\x06\x09\xa3\x9a\x59\x4a\x3a\x66\x61\x16\x32\xb7\x5f\xe5\xc2\xf8\xe3\x62\xa7\xc0\x3c\x54\xc8\x09\x1b\x4d\x47\x24\x2d\xa1\x1b\x15\xee\x9e\xee\x14\x67\xab\x17\xda\xb0\x1c\x2c\xb9\x52\xc1\xff\xec\xb4\x8d\x5a\xc0\x5d\xc0\x9c\x09\x53\xd2\x2c\x5b\x10\x36\xe7\x89\x09\xeb\x83\x6b\x42\x6e\xd0\xd8\xde\xce\x44\xd8\x4a\x74\x68\x2f\x2e\x0c\x97\x30\x58\x6f\xe9\xd3\x85\xdb\x2f\x8d\xdd\xe6\x4c\x36\x78\x21\xae\x64\xb4\x56\x58\x35\x76\x5c\xb4\x81\xc3\x3f\x01\xb9\xbe\xfb\xb8\xdd\xe4\x4a\x3a\x53\xb2\x0e\xd4\xab\x29\x96\x96\x59\x66\x11\x03\xad\xb0\xcb\x0b\x58\x61\x1d\xc5\x25\xd5\x90\x19\x0d\xef\x68\x62\x3e\xff\x70\x69\xa1\x62\xdb\xdc\xc9\x42\x66\x72\xba\x88\x21\x0d\x2b\x03\xdb\xad\xeb\x8b\xb7\x7a\x28\x34\x58\xf4\xfb\xd0\xd8\x9a\xde\xf2\xd7\x5b\xfe\x7a\xdd\x66\xe9\xe9\x75\x9b\xf0\xf4\xba\xcd\x96\xa7\xd7\x6d\x7a\xdd\xa6\xb7\xfc\x91\x9e\x3b\x6e\x80\x49\xcf\x1d\x49\xcf\x1d\xd7\xae\xab\xe7\x8e\x1b\xc1\xd3\x73\xc7\x9e\x3b\xae\x7a\x0a\x99\xee\xe1\xe8\x58\xc8\x74\x83\x9f\x23\x5a\x7d\x12\x39\xcc\x64\x42\x8d\x73\x04\xb7\x5d\x9c\x9d\x4f\xd3\x1c\x0d\x51\x03\xf2\x77\x29\x18\x3a\xaf\xd9\xbd\x01\x73\x92\x34\x33\xa6\x6c\xf3\x13\x7d\xba\xd1\xb1\xa9\xf7\x93\xec\xfd\x24\x5f\xbc\x9f\xe4\x8c\x6a\xdc\x57\x24\x4a\xeb\xdd\x26\xa3\x03\x79\xc7\x54\xfe\x85\x7a\x4d\x5a\x74\x71\xdb\x0d\x21\x36\xd5\x96\xe2\xca\x53\x77\x5f\xc0\xd2\x9b\xfa\x7a\x9d\xbc\x0c\x8b\xa2\x69\xca\x52\x52\x30\x35\x44\x14\x91\x64\xc2\x45\xba\x62\xad\x1e\x3e\xcf\xea\xfd\x58\x5f\xc7\x33\xba\x40\xd6\x27\xb2\x83\xcd\x35\x36\x1c\xd7\x28\xfc\x8b\x70\x88\xec\x2a\xd5\x0f\x89\x71\x46\xde\x6f\x5b\xca\xf5\xdd\x45\x73\x10\xa8\xbd\x49\x78\x77\xbd\x12\xc4\xf2\x1f\x4b\xa6\x16\x10\x63\x51\x09\xac\x21\x98\xcb\xdd\x91\x71\x4d\x12\xaa\x91\x53\x74\x55\x2d\x3b\xaa\x51\xbb\xe9\x29\xbb\x5b\xa2\x49\x13\x2e\xcd\xa1\x50\x27\xf5\x3a\x38\xc2\x6c\xa5\x12\xbe\xe2\x16\xa0\xb2\xfe\x77\x9a\xcf\xae\xa2\xdb\x4e\x82\xdb\x4a\xa4\x78\xc1\xca\x39\xd9\x5d\x41\x27\x3b\x2b\xe9\x64\x27\x45\x9d\xec\xaa\xac\x93\x3d\x14\x76\xb2\x9b\xd2\x4e\x9a\xa8\x60\x77\xc8\x49\x59\x8f\xa3\xbf\x93\x7d\x54\x54\xb2\x87\x1e\x4f\x9a\x4b\x0d\x68\xaa\x1e\x4b\xa9\x07\x5c\xaf\xe9\xf5\x4f\x0d\xac\xdd\x74\x7a\xd2\x04\x95\x8f\xba\x03\x85\xf6\x0b\xd1\xf0\x9f\x44\xdd\x26\x7b\xa9\xdc\x64\x77\xb5\x9b\xec\x8e\x19\xc0\xea\xde\xc1\x75\xea\xbe\x0c\x13\x47\x41\x16\x91\xd3\xc2\x22\xc5\x3f\x2c\x27\x80\x7d\xf9\x17\x29\x28\x57\xda\xca\x77\xce\x66\x12\xff\xe6\xb4\xf3\x78\x18\x3b\x02\xd7\xc4\x92\xea\x39\xcd\x2c\xef\x41\x3f\x0e\xa7\x17\xd9\xd1\x9b\x6c\x7a\x40\x1e\x20\xea\xd3\x52\x29\xd4\x96\xb8\x26\x47\xf7\x6c\x71\x34\x58\x42\xa4\xa3\x6b\x71\x84\x3c\x6a\x09\x75\x02\x43\x93\x22\x5b\x90\x23\xf8\xed\xe8\xd0\x9c\x7d\x07\xc6\x15\x27\xdb\xd8\x95\x2f\xec\x80\x25\xc2\xc7\x4a\x1f\x5e\xd8\x44\x2e\x82\x17\x1b\xfe\x2b\xba\x62\x30\xe0\x6a\x11\x31\x97\xe0\x35\x02\x38\x06\xef\x53\xaf\xfc\x96\xc2\xa5\x56\x00\xdd\xb5\x1a\x0c\x99\xd4\xb2\x4b\x93\xdb\x78\x29\x98\x06\xc1\x8e\x05\x13\x51\xd4\x19\xda\x8e\xd0\x1d\xa4\xe2\x76\x22\x6d\x3a\x88\x54\x3d\x40\x46\xcc\x19\x15\x9a\x1c\x79\xdb\xd3\xb1\xae\x5a\x1c\x8d\xaa\xe8\xbe\x30\x22\x04\x21\xc7\x11\x7d\xd5\x80\xbd\xa4\xdd\x4b\xda\xbd\xa4\xdd\xa1\x57\x2f\x69\xaf\x7f\x7a\x49\xbb\xc3\xd3\x4b\xda\xbd\xa4\xbd\xe9\xc3\xbd\xa4\xdd\x4b\xda\xdb\x3f\xbe\x9b\xa4\xbd\xab\x9f\x50\x2c\xf7\xba\xcb\x39\xcc\x9c\x45\x0d\x4f\x2a\x1f\x22\xdf\x0a\xff\x75\x58\x79\x3b\x96\xa5\x57\x4b\xdb\xb1\x44\xbe\xa4\x5b\x8c\xb6\x88\xd6\x41\xf8\x5e\xea\xb9\x59\xea\x7e\x59\xbe\x50\x3b\xe0\x46\x74\xa1\xb0\x23\x72\xdc\xf9\xab\x70\x97\x69\x6e\xcc\xaa\x7b\xf2\x94\x9c\xf8\x1b\x97\x53\x0b\x7c\x21\x4d\xfd\x47\x61\xf8\xb0\x6a\x11\xee\x60\xe0\x7a\xb1\x16\x6f\x53\xbb\x96\x08\xb7\xee\xe1\xa6\xb8\xda\x4f\x4b\x42\x98\xaa\xcd\x81\x6b\x97\x40\x0c\xbc\x25\x54\x29\x84\x1d\x55\x0a\x7f\x7d\x8c\x34\x07\x13\xc0\x39\xcc\x43\x61\x09\xe6\x03\x12\x53\x05\xa5\xe8\xbe\x93\x1a\xcc\xb9\xe7\x5c\xf9\xa5\x70\x37\xa2\xf6\x8d\xbf\xf5\xf5\x48\x09\x2b\xe2\xe1\xeb\x23\x72\x05\x78\x18\x0f\xcc\x35\xc0\x87\x66\x99\x7c\xe8\x42\x92\x9e\x2a\x2c\xea\xa1\x73\x58\x54\xe3\xfe\xae\x8f\x8a\xfa\x99\x44\x45\xc1\x8f\x78\x84\x0e\x1e\x1e\x45\x7e\x98\x31\xc0\x22\xc5\x00\x54\x79\x99\x19\x5e\x54\xbe\x52\x1a\x3f\x95\xa1\x94\x39\x71\x9e\x27\x75\xbc\xb4\x5f\xa3\xc9\xac\x89\x9f\x30\x1e\xf8\x56\x69\x38\xb4\xce\xbb\x83\x66\x99\x8b\x29\xf2\x22\x29\xba\xb0\xf0\xe7\xf6\x4c\xb8\xf4\x59\x11\xbd\x36\x03\x44\xe6\xc4\xd2\xc2\x6c\xe1\x32\xd5\x6d\x20\xa2\xa8\x14\xcd\x99\x67\xbd\x53\x3e\x67\xa2\xa2\xa4\x27\xfa\xf4\xd4\xf3\xf0\x83\x52\xf8\x47\xa1\xd0\x7f\x88\x28\xe9\x1f\xdb\xd0\x68\x58\x50\xa0\xd2\x15\xf8\x2a\x1a\xfd\x9c\x2e\x18\x5d\xee\xf9\xbb\xd9\x18\x76\xb8\xdf\x7f\xc2\xbb\xfd\x2f\x27\xb2\xec\x99\x2d\x8c\xcf\xe1\x5b\xff\xe2\xad\x8a\xbd\x73\x7d\xf5\xec\xeb\x5c\xff\xe8\x96\xc3\xe7\xf5\xb1\xff\x02\xac\x85\xcf\xe9\x63\xdf\x5b\x08\x37\x6e\xca\x4b\x73\x7d\xaf\x3f\x3b\x59\x04\x7b\x6b\xe0\xce\x5c\xb8\x23\xc3\xd9\xd7\x0a\xd8\x11\x23\x76\xbc\x67\xef\xef\xd8\x9f\xe6\x8e\xbd\x97\x78\x5b\x3e\xbd\xc4\xbb\x16\x28\xbd\xc4\x4b\x7a\x89\x77\xdb\xf2\x7a\x89\x77\x23\x78\x7a\x89\x77\xe3\xa6\xf4\x12\x6f\x2f\xf1\x92\x2f\x4d\xe2\xdd\x25\x4b\x57\x7f\xd7\xbd\xd7\x5d\x77\x57\x6a\xd1\x89\x46\x74\xc4\x83\xce\x77\xdb\xfd\xbd\xf6\x4b\xb9\xd7\x6e\x1d\xf0\x2f\x0c\xdf\x37\xe8\x3f\xde\xab\x75\x91\xff\x74\x2e\x79\x4a\x8a\xd2\xb8\x78\xea\x3e\xfa\xff\x10\xd1\xff\x35\xc8\xf7\x29\x00\x5a\xa5\x00\x58\x07\xb3\x3e\x0f\x40\x9f\x07\xe0\xc0\x97\xd0\x7d\x1e\x80\x3e\x0f\x40\x9f\x07\xc0\x3f\x7d\x74\x12\xe9\xa3\x93\x5a\x3d\x7d\x74\xd2\xfa\xa7\x8f\x4e\x7a\xb1\xd6\x57\xd2\x47\x27\xbd\x6c\x4b\x2c\xe9\xa3\x93\x7a\xeb\x6c\xcb\x8d\xfa\x02\xa3\x93\xfa\x3c\x00\x2f\xd5\x47\x81\xf4\x92\x76\x2f\x69\xf7\x92\x76\x2f\x69\x6f\x7e\x7a\x49\xbb\xc3\xd3\x4b\xda\xbd\xa4\xbd\xe9\xc3\xbd\xa4\xdd\x4b\xda\xdb\x3f\xde\xe7\x01\xf8\x82\x7c\x23\x48\x9f\x07\xa0\xf7\x97\xe8\xf3\x00\xfc\x7c\xf3\x00\xd4\xee\xee\x9f\x2f\x19\x40\xf7\x69\xf4\x19\x01\xfa\x8c\x00\x7d\x46\x80\x3e\x23\x80\x7f\xfa\x8c\x00\xf8\xbc\x24\x5b\x63\x1f\x1f\xb5\x16\x28\x7d\x7c\x14\xe9\xe3\xa3\xb6\x2d\xef\x0b\xb0\x1b\xf6\xf1\x51\x2f\xd0\x56\xd8\xc7\x47\xf5\x76\xc1\xe6\xe6\x7c\x21\xf1\x51\x7d\x46\x80\x97\x78\xdb\xde\x4b\xbc\x2d\x9f\x5e\xe2\x5d\x0b\x94\x5e\xe2\x25\xbd\xc4\xbb\x6d\x79\xbd\xc4\xbb\x11\x3c\xbd\xc4\xbb\x71\x53\x7a\x89\xb7\x97\x78\xc9\x97\x26\xf1\xf6\x19\x01\xfa\x8c\x00\x7d\x46\x80\x2f\xf1\x86\x7b\xeb\x4e\x33\x31\x5f\xb7\xa7\xb5\x5d\xbc\x12\xf3\xba\x9e\xc2\xc4\x9c\x2b\x29\x80\x02\xcf\xa9\xe2\x74\x9c\xc1\x49\x05\x89\xc7\xc1\xdf\xd1\x4f\xa6\x46\xe4\x82\x0a\x77\xd1\x8a\x37\x99\x6b\xe7\xbf\x1d\xf1\xb7\xa0\x7a\x73\xda\xdf\xd3\xba\xa8\x26\x56\x4e\x9d\xb8\x06\x76\xea\x94\x5c\x84\x89\xaf\xfd\x4c\x2b\x02\xde\x46\x3f\x18\x02\x72\xae\x6d\xd0\x4e\x8a\xb7\x43\x6c\x3e\x9b\x35\xb0\x7c\xa0\x79\x15\xe2\xbf\x02\x1a\x23\xf2\xde\x49\x48\x94\x5c\xfc\xef\xf5\xe5\xd5\x87\xbb\xeb\xb7\xd7\x57\x1f\x37\x23\x5d\x4b\xb2\x02\x07\xa9\xc3\x64\x8f\xbf\xf7\x7b\x04\x61\xde\x4c\x58\x0a\xfc\xcb\x93\xef\xcf\x3f\xfe\xef\x87\xf3\xf7\x57\xa7\xc0\x7e\xd9\xe7\x82\x8a\x94\xa5\xa4\xd4\x9e\x24\x14\x8a\xcd\xb9\x2c\x75\xb6\x08\xc7\x7b\x35\xd2\x36\xb1\xd5\x29\x9a\x0b\xa2\x99\x9a\xf3\x64\x35\x88\x50\x8a\xa5\x15\x02\x25\x01\xc3\x15\xd3\x32\x9b\xb3\x14\x65\x8d\x30\x69\xff\x1d\x2e\x8a\xd2\x78\x89\x18\x5c\x10\xec\xa9\x10\xc9\x8c\x8a\x29\x4b\x47\xe4\x52\x96\x76\xbc\x5f\xfe\x12\x16\xa6\x58\x5a\x26\xc8\xeb\xa8\x17\x98\x7e\x39\xf0\x94\xc4\xd2\x02\x8d\x69\x14\x74\x42\x0b\xbf\xf4\x18\x3a\x7a\x21\x0c\xfd\xfc\x06\xef\xe0\x8f\x7e\x19\xfd\x74\xe4\x53\x50\x48\xfb\x09\xa4\x47\x38\xab\x0c\xb2\x1f\x64\xe4\x28\x6e\x3d\x22\x57\xf6\x1b\x2c\x8d\xf7\x01\x5d\x28\xd8\x9c\x29\x90\xa7\xdd\x2e\x0c\x88\x62\x53\xaa\xd2\x8c\x69\x70\x1e\x78\x98\x31\x48\xe7\x81\x12\x96\x03\x18\x0b\xd2\xba\x90\x66\x44\x2e\xd9\x84\x96\x99\x01\x1a\x72\x74\x34\x3a\x3e\x18\xaa\xbd\x55\x72\x4b\xf0\x7b\x0d\xdd\x6e\x31\xa9\xc4\x44\xaa\xb5\xc7\xe3\xd8\x99\x26\x6a\x64\x4d\x5b\x4e\xe2\x34\x3d\x4f\xab\x51\xbf\x68\xb1\x92\x16\x82\x60\x7b\x75\x3e\x91\x62\xc2\xa7\xef\x69\xf1\x2d\x5b\x7c\x64\x93\x8e\xde\x10\xc8\x44\x9d\x4e\x0b\x0c\xcc\x92\x43\x1c\x70\x3b\xd3\x79\xc4\xbb\xfc\x36\x46\x93\x6e\x36\x8f\xd6\x96\x8e\xa5\x94\x16\xc8\xf4\x1d\xfb\x3e\x60\x72\x9e\xea\xd9\x4e\xd1\x57\x4e\xee\x38\x26\xed\xee\x9c\x9a\x11\x79\x2f\xc1\x25\x67\x22\xdf\x90\x99\x31\x85\x7e\x73\x76\x76\x5f\x8e\x99\x12\xcc\x30\x3d\xe2\xf2\x2c\x95\x89\x3e\x4b\xa4\x48\x58\x61\xf4\x99\x9c\x5b\xca\xc7\x1e\xce\x1e\xa4\xba\xe7\x62\x3a\xb4\x92\xce\x10\x77\x55\x9f\x81\x30\x75\xf6\x0b\x94\xd8\xef\xbe\xbb\xfc\xee\x0d\x39\x4f\x53\x97\xb1\xa7\xd4\x6c\x52\x66\x2e\x7b\xc7\x88\xd0\x82\x7f\xcf\x94\x55\xca\x06\xe4\x9e\x8b\x74\x40\x4a\x9e\xfe\xe7\xe6\xc3\xbd\x23\xc4\x64\x81\xba\xd1\x0e\x50\xbb\x05\x41\x71\x51\xa3\x53\x01\xe9\x2d\x85\xe2\x46\xc3\x9e\x7b\xc3\x81\x63\x28\x1d\x96\x31\x96\x32\x63\x54\x6c\xe9\x01\x60\xeb\x7e\x66\x8f\xab\x43\x8b\x5a\x8e\x43\x80\x42\xa6\x6f\x88\x2e\x8b\x42\x2a\xa3\x49\xce\x0c\x4d\xa9\xa1\x23\xbb\x73\x83\xfa\x9f\x20\x1c\x0f\xc8\x5f\xc3\x4b\x90\x70\xf5\x9f\x8f\x8f\xff\xf0\xed\xd5\x7f\xff\xf1\xf8\xf8\x2f\x7f\x8d\x7f\x05\xb2\x87\xa6\xae\x7a\x13\x2b\x72\x8f\xac\xb8\xfb\x01\xbe\x01\x7f\x3a\x36\x7a\x9e\x24\xb2\x14\xc6\xfd\x60\xa8\x29\xf5\x68\x26\xb5\xb9\xbe\x09\x7f\x16\x32\x6d\xfe\xa5\xb7\x70\x02\xf2\xb8\x44\x07\xc0\x79\x43\xcd\xec\xc0\xa4\xa7\x3a\x17\x3b\xa0\xab\xeb\x19\x67\x48\xca\x29\xfc\xf3\xad\x9f\xae\xe5\x40\x0f\x8a\x1b\xc3\x04\xc8\x1d\xe0\x77\x27\x27\x03\x8b\xb9\x15\x9b\x9d\xbf\xee\xa4\x8e\xb6\x3e\x8a\x01\x6a\x3b\x2c\x0e\x66\xef\x56\x86\xc8\x1c\x08\xed\xb2\x5e\x77\x7e\x73\x4d\xe6\x08\x8d\x83\x2f\xc4\x7b\x61\xbd\xdd\xfb\x4c\x86\x4c\x55\x6e\x59\x41\xd2\x7c\x83\x96\xa5\xe0\xef\x45\x32\x9e\x73\x67\x00\x76\x59\xad\x34\x39\xc1\x97\xa3\xa4\x28\x07\xae\xc1\x28\x67\xb9\x54\x8b\xf0\x27\x2b\x66\x2c\xb7\x12\xdb\x50\x1b\xa9\xe8\x94\x0d\x42\x77\xec\x16\xfe\xc2\x8e\xb5\x0f\x2c\xf7\x46\x91\x3a\x29\x95\x65\x1e\xd9\xc2\x53\x10\x96\x3e\xef\x59\xf4\x60\x3a\xf0\x51\x0c\xbb\xf1\x61\x47\x96\x1b\xb4\x45\x64\xda\x61\x55\x20\x43\xce\x65\x56\xe6\x4c\x0f\x02\x7b\x42\x69\x5d\xcc\xad\x34\xa9\x1f\x85\x11\xa6\x7c\xce\xf5\x4e\xf7\xd3\xb7\xc1\x52\x07\x26\xb2\xd2\x58\x4d\x05\x9d\xc1\xa3\x8c\x70\x52\x83\x0e\x10\x7c\x14\x6b\x24\xe5\xf5\x51\xbb\xdb\x57\x6a\x0c\x53\xe2\x0d\xf9\xff\x4e\xfe\xe7\xdf\xfe\x39\x3c\xfd\xcf\x93\x93\x3f\xbf\x1a\xfe\x3f\x7f\xf9\xb7\x93\xff\x19\xc1\x3f\x7e\x75\xfa\x9f\xa7\xff\xf4\x7f\xfc\xdb\xe9\xe9\xc9\xc9\x9f\xbf\x7d\xff\xcd\xdd\xcd\xd5\x5f\xf8\xe9\x3f\xff\x2c\xca\xfc\x1e\xff\xfa\xe7\xc9\x9f\xd9\xd5\x5f\x5a\x0e\x72\x7a\xfa\x9f\xbf\x6c\x35\x3d\x2a\x16\xdf\xb5\x38\xf0\xf8\x0c\x77\xf0\xb0\xaf\x7a\x75\x30\xd0\x7f\x1e\x56\x42\xdb\x90\x0b\x33\x94\x6a\x88\xdd\xdf\x10\xa3\xca\xed\x07\xa3\x22\x6a\xbb\xe0\xb9\x4f\x07\xf6\xa6\x22\x68\x81\x34\x1f\x1c\x91\x35\x4b\x14\x33\x87\xd2\x60\x70\x34\xcf\x3f\x1a\x26\xd9\x5e\xa9\xa9\x94\x9a\x60\x97\x04\x78\x55\x9c\x77\xa2\x64\x3e\x22\x91\x59\x68\x0e\x37\x99\xae\xdd\x3d\xdb\xa2\xe5\xfa\xa7\x57\x82\xbe\x2c\x25\xe8\x16\xf7\xf7\xd1\x35\x20\x26\xe6\x9b\xcc\x34\x4d\x9b\xee\x5b\x08\x65\x89\xcd\xd1\x5e\x80\x32\x92\x14\xb2\x28\x33\x6a\xd6\x98\xed\x56\xd8\xa6\x1d\xee\x57\xb7\x00\x76\xa3\xc1\x0e\xec\xa8\x5c\xbe\xda\x18\x4a\xce\xb3\x8c\x70\x81\x27\x01\x06\xf0\xd6\x3c\xc5\x50\x5e\x22\x14\x0d\xce\x73\x3b\x85\x07\x17\x70\x13\x19\x1a\xb9\xb6\xba\x8e\x32\x60\xf1\x87\x80\x1c\xa4\x59\xce\x34\xc6\x45\x15\x96\x13\xb8\x6d\xb8\xa5\x5c\x99\x7f\x31\xa3\xda\xf8\x69\xc3\x6c\x0c\xbd\x07\x53\x68\xc2\x52\x26\x12\x06\x2e\x08\x25\xab\xd6\x3a\xb6\xc2\x20\x98\xf7\x61\x0c\x4a\xd2\xb2\xc8\x78\x62\xe1\x67\x67\xb2\x7a\x8c\xeb\x3c\x2f\x0d\x18\x8a\x9f\xca\x8a\x6f\x77\xfc\xd6\xa7\x7b\x0d\xc6\x7c\x20\x55\x41\xb4\x0e\xde\x16\x41\x75\xd7\xfb\x99\xef\xdb\x11\xde\x60\x6e\xdb\xca\xa9\x96\x28\x6e\x65\x63\xa8\x53\xda\xa7\xb6\x18\xb6\xa3\xb3\x3f\x49\x1a\xdb\x81\xbe\xb6\xa7\xad\x1d\x8c\x4b\x5d\xe9\x69\x5b\x6b\x52\xa1\xd8\x84\x7f\xee\x80\x8f\xe7\xa2\x52\x51\x78\xca\x84\xb1\x8a\x00\x64\xa6\x2e\x14\x2b\x98\x48\x43\xb8\x1f\x38\x78\x89\xfa\x3a\x1e\xf5\xc6\x08\xa5\x8c\xee\xc7\xeb\x76\x95\x14\xd3\x9f\xad\x9f\xf8\xd9\x72\xbb\x7e\xf8\x83\x25\x64\xba\xd5\xf9\xbb\xb1\x8f\x51\x8f\x86\xa7\xab\x4b\xff\xed\x26\x69\xb5\xb7\x70\xe5\x54\xc8\x14\x73\x5c\x9b\xca\x09\x61\x44\x6e\x57\xf4\x04\x5f\x03\xd7\xe2\xf8\x58\xa3\x5b\x82\x6e\x0e\xd4\x88\x6e\x46\xcf\x04\x1c\xb4\x23\x4a\x21\xab\x2b\x15\x58\x7e\xcf\xa8\xd6\x7c\x2a\x86\x85\x4c\x21\x2f\xf7\xd9\x3a\x84\x68\x71\xa8\xba\x79\x36\x6d\xc5\xab\x60\x9c\x68\xb7\x4d\x1f\x83\xfd\x2d\x92\x2d\x7c\x46\x78\x15\xfd\xe8\xec\x3a\xde\x8f\x3e\x92\x21\x2b\x89\x68\x3f\x98\xe6\x54\xd0\x29\x1b\xba\x8f\x0f\xc3\xc7\x87\xe1\x5b\xfb\x80\xb9\x0d\xd5\x42\x93\x62\xeb\xb2\x10\xc7\xef\xd0\x64\x99\x86\xf2\x10\xe8\xbf\xf7\x99\xe7\x65\x4e\x68\x2e\x4b\x74\xd1\x5b\x06\xa7\x77\x64\x39\x08\xc0\x56\x00\x4a\xaf\x85\x54\x4b\x68\x91\x9d\x5c\xee\x5e\xa8\x65\xab\x95\x45\xab\x9b\x25\xab\x83\x05\x6b\x67\xcb\x95\x37\x52\xb7\xc7\xc7\x8f\xde\x6e\xde\xc0\x48\x2e\xb6\x62\xa4\x0a\xf9\xee\xaf\x27\x24\x8c\xc3\x35\x91\x39\x37\xc6\x19\x74\x69\x75\xec\x07\x84\x9b\x9a\xf5\xd3\x9d\x05\xa8\xf7\x80\x25\x32\xd8\x67\xab\x4d\x71\xb0\xa2\xfb\x5b\x8b\x01\x72\xd9\x07\x8e\xd9\x21\xa8\x20\x3c\x2f\xd0\x99\x15\x70\x7a\xe8\x75\x33\xe7\x64\xd0\x9f\x8f\xfe\x7c\xac\xea\xa4\xbb\xc8\x22\xb1\x18\x52\x79\x30\x06\x71\xc4\x62\xb6\x2f\x3c\x03\x1e\x9a\x88\x43\xf6\x2c\x80\x13\x3d\x17\x53\xf2\x91\x81\x65\xe0\x96\x19\xed\x7c\x22\xa1\x07\x55\x6c\x39\xc4\xcc\x5b\x42\x82\xab\x2d\x9d\x4c\xea\x2d\x52\x56\x64\x72\x91\x83\x64\x7b\x6d\x62\x79\x26\x88\x2e\x2c\x2f\x32\x6a\x58\x10\x6c\x36\x5b\x1b\xf6\xe6\x7c\x5d\xe2\xbb\x9e\x37\xa2\xab\x9d\x77\x70\x0b\x9f\xe0\x97\x1f\xa7\xd5\x5a\x23\x6b\x6b\x77\x6f\x63\x73\x6f\x19\x6f\xd5\x5e\x09\x6c\x65\x94\x7f\xec\x28\xaa\x4e\xea\x58\xdb\x48\xa9\x97\x1f\x1b\xd5\x61\xd9\x6d\xe3\x9f\xfa\x88\xa7\x4d\xa0\x6e\x17\xb5\xd0\x3a\x62\xa1\xd5\xfe\xb5\x8c\x5c\xea\x63\x95\x3a\xf0\x97\x47\x10\xfe\xb6\xee\xa5\x91\x19\x43\xc9\xb5\x9d\xee\x7e\x57\xb5\x0f\xf5\xcf\xf0\x7a\x37\x1a\xe9\x69\x6e\x29\xee\xbc\xd8\x62\xcf\x56\x35\x2f\x40\x2d\x63\x28\x14\x3b\x33\xd2\xcf\xcb\x6e\x9c\x58\x10\xbb\x67\xc6\x55\xbe\x8b\x4a\xc1\x19\x05\x97\x3e\x7f\x08\xd8\x36\x60\x20\x3f\xfd\x31\xf2\x6f\x0f\xf1\x2f\x01\x43\xfe\xe0\xff\xf5\xc7\x3d\xe3\x16\xda\x31\x36\x9c\x52\x07\x01\xe3\x0a\x3a\x10\x2e\x52\xb8\x60\x72\x4b\x05\x08\xe0\x58\x16\x3e\xb0\x2c\x1f\xff\x82\x81\x54\xce\xcc\x05\x37\x51\x55\x63\xed\xae\xcc\x22\xbd\xca\x99\x14\xaa\x93\xc1\xc8\x07\xe9\x92\x12\xb2\x01\xb9\x01\x5b\x6a\xf5\x06\x4e\xd2\x07\x89\xe9\x09\xd7\xde\x65\xc5\x70\xdb\xca\x45\xb6\x32\xfa\x1a\x40\xbe\xad\x98\x3c\xae\xac\xc6\xe4\x2b\x0c\xae\x45\xc2\x6d\x82\xcc\x3d\x5b\x54\xcc\xc6\x89\x10\x40\xf2\x07\x15\x96\x78\x56\x80\xbc\xe3\x3f\xbc\x29\x2b\x1f\x73\x81\x1f\xc3\xa1\xfd\x56\xc0\xe8\x1e\xa0\x56\xb2\xcb\x32\xfc\xcc\x21\xc0\xd5\x4e\xce\xa8\xc1\xec\xbb\x0e\x32\x46\xa0\x92\xab\xa5\x8b\x48\xa4\xb8\xfa\xb1\xa4\x59\x3d\x08\xc1\xbd\x72\x8d\x96\xa8\xfa\x03\xcf\xd2\x84\x2a\xe7\xe5\x05\x67\x94\x68\x89\xbb\x87\x59\xf1\x12\x2a\xc2\x69\xaf\xf6\x08\xeb\x20\x92\x82\x2a\xc3\x93\x32\xa3\x8a\xd8\xb3\x30\x95\xaa\x55\xa0\xc0\x56\x88\x56\x48\x73\xcb\x12\x29\xd2\x2e\x0a\xc0\x5d\xb3\x6f\xf3\xae\xb5\x60\x8a\xbb\x74\x7f\x3c\x67\x4d\x24\x3d\xa9\xdb\xb4\xe5\xc4\x9f\xea\x70\xc4\x6a\x96\x8f\x2a\x26\x93\x6b\xc2\x31\x5f\xe8\x69\x44\x1e\xc3\xa9\x18\x91\xaf\x17\xde\xcc\x02\x26\x17\x17\x5d\xa1\x99\xf1\x81\x30\x1e\x65\x1d\xb0\xab\x03\x35\x91\x0a\x82\x53\x4e\x52\x89\x11\x19\x73\x9e\x98\xd3\x11\xf9\x7f\x99\x92\x18\xc1\xc9\xa6\x98\xbd\xd1\xa1\x78\x50\x5c\xa1\x70\x29\xdc\xe0\xbf\x22\x27\x98\x49\x93\xe7\x39\x4b\x39\x35\x2c\x5b\x9c\xa2\x1e\xeb\x73\x71\xb6\xd9\xba\x36\x46\x83\x28\xf1\xea\x6f\x7f\xb3\xa1\x65\xd7\x18\xaa\xef\x7d\x54\x4a\x05\x19\xf4\x21\x68\x6c\x61\xe0\x41\x72\x83\xb8\x19\xfb\x20\x54\x41\x9d\x9e\xcc\x84\x0d\xfe\x9b\xc5\x03\x4a\x14\x9b\x02\x96\x23\xe6\xee\x89\xe3\xe8\x4d\xf9\x5e\x96\x62\xbd\x49\xb0\xb6\xf0\x77\x4e\x09\xff\x3e\xea\xb8\x36\x4a\xf1\x49\xc4\x84\x68\x26\x91\x89\x92\x12\xb0\x4b\x02\x3b\xb7\xe4\x01\x5b\x55\x9e\x28\x5b\x27\x79\xd0\x88\x44\x98\xcb\x16\xaf\xf7\x83\xc4\x2d\x86\x0f\x75\xc0\x65\x70\x10\x77\x80\x69\xc4\xed\x19\x47\x0e\x00\x3f\x11\x82\x15\x82\xc2\xb7\x58\xea\xbd\xd8\x30\xd6\x18\xba\x92\xe3\x37\xc7\x07\x21\xbe\xb8\x1c\x25\x0b\x3a\xa5\xdb\xf3\x1d\xd7\x95\x91\x46\x57\x92\x32\xc3\x54\x0e\x89\x69\x67\xf2\x01\x7f\x47\xb6\x55\xb8\x56\xcc\xe5\xf4\xb5\xab\x9d\x49\x0d\x5c\xa9\x1e\xc4\x08\xe7\x17\x2e\x46\x1f\xe8\x82\x50\x25\x4b\x91\x3a\xa9\x29\x10\xd0\xf7\x8d\x0f\x7f\x90\x02\x28\x45\xa9\x2d\xac\xee\x6a\x54\x7a\xcc\x0c\xb5\xc7\xe6\xf5\xe8\xf5\x96\xdc\xd3\x2d\x01\xd6\x31\x6e\x15\x66\xd3\xb0\x14\xfa\xbb\x72\x7f\x66\x0e\x32\x2f\xc5\x68\xfa\x9d\xc8\xba\xc8\x72\xef\x11\xbd\xa0\xeb\x10\x94\x30\x3e\x01\xdb\xed\x00\x5f\x3d\x28\x6e\x58\x44\x1e\x4f\x26\x34\xd3\x50\x70\xbb\x14\x41\x84\x3d\xad\x8b\x20\xd0\xa4\xcd\x82\xb6\xfb\x83\xe8\x72\xbc\xe7\x39\x73\x07\x0a\x50\xae\x3a\x66\x01\xe1\x8e\xf5\x86\x23\x57\x0f\xee\x24\x27\xd8\xd2\x4a\x6c\x52\x9a\x8d\xe5\xdd\xdb\x3b\x89\xe0\x02\xad\x66\xdd\x45\x25\xf1\x71\xc3\xc5\x01\x57\xfb\x35\x9b\xd1\x39\xd3\x44\xf3\x9c\x67\x54\x65\x10\x2b\x78\x8b\xf3\x83\x62\xec\x2b\x23\xd0\xbb\x45\x37\xc7\x33\x89\x86\xdb\x0a\x6a\x3f\x0f\x0b\x27\xa0\x11\x7e\x5e\x98\x04\xdc\x67\x0e\xff\x9c\x64\xa5\xe6\xf3\x7d\x4f\x93\x8b\x7e\xd8\x81\x55\x37\xb9\x74\x21\xd3\xdb\x82\x25\x4f\xc9\xa3\xeb\x1a\x86\x25\x55\xa9\xdf\x74\xe0\xc9\xa8\xec\x53\x2c\xac\x3f\x66\x84\x26\x09\xd3\xda\xfb\x54\x2e\x62\x3f\xcf\xb0\x86\x2f\x25\xa1\x00\x7d\xd0\x57\x19\xd5\x86\x27\x5f\x67\x32\xb9\xbf\x35\x52\x75\x8a\xd9\x5f\xd5\xbf\x91\x86\xe1\xfc\x87\x5b\x72\xc9\xf5\x7d\x14\x4d\xe0\x2e\x4d\x63\x73\x09\x25\xf7\xe5\x98\x65\xcc\x1c\x1f\x6b\xe4\x72\x39\x4d\x66\x5c\x30\xcf\xe0\x44\x08\x49\x71\x0a\x9f\x85\x72\xd7\x3b\x53\x17\xf8\x74\xe6\xf0\xf5\x17\xf4\x41\x33\x9c\xfe\xd8\x4e\xdf\xfe\xcc\xda\x44\xa4\x1f\xf4\x9e\x02\x27\x73\x7d\x79\xa0\x3b\x88\x89\xbe\xb3\x73\xec\x66\xdc\x3e\xc6\x5e\x5e\x75\x98\xf0\x8c\xb9\xea\x03\x76\xc1\xde\x47\xcd\x9d\x0a\xd8\xbf\x85\x2c\xc9\x03\x45\x1d\x19\x28\xe2\x88\xdc\xf1\xe2\x0d\xb9\x12\xba\x54\xac\xb2\x6e\x34\x87\xe2\xba\x8a\x33\xf3\xca\x15\xec\x37\x2a\x20\x96\xee\x39\x5d\x8b\x5c\x7d\xa6\x79\x91\x31\xfd\x86\x1c\xb1\xcf\xe6\x37\x47\x03\x72\xf4\x79\xa2\xed\xff\x84\x99\xe8\xa3\x11\xb9\xce\xc3\xad\x3b\x17\x13\xa6\x14\xf3\x8e\x50\xd8\xc1\xb2\xe6\x88\xeb\x3e\x0a\xba\x38\xa7\x3a\x2b\xbb\xa5\x92\x3c\x60\x3e\x0a\x4b\xf0\x99\x52\x52\x05\x3f\xf4\x08\x0c\xc0\x6b\x12\x99\x17\x4a\xe6\x3c\x32\xf3\x01\xba\x1f\xd4\xdb\x0e\x8c\x0f\x6d\x0a\x72\x34\xb1\x21\x74\xf4\x08\x11\xbd\x10\x6d\x50\xe1\x7a\xe2\x9d\x29\x50\x8b\x74\x6a\x3d\x0c\xe7\x1a\xd9\xcd\x77\xa3\x58\x42\x16\x6f\xf7\xdb\x10\x50\x47\xce\x52\x36\x3f\xd3\x29\x7d\x3d\x80\xcf\x68\xe7\x08\x58\x9f\x13\xd5\xe4\xe8\xf5\xd1\x88\xdc\x7a\x46\x3c\x88\xe7\x58\xb5\x9b\x48\x15\x06\x04\x3b\xfb\xab\x23\x72\x22\x15\x8c\x9c\x50\x41\x32\x46\xe7\xce\xb6\x8c\xc7\x6d\x81\xea\xee\x69\xeb\x80\xc8\xb6\xb1\x61\xed\x2b\xaf\xb4\x15\x52\x97\x37\xd1\xf7\xf3\x26\x00\x55\xba\x58\x81\x89\x54\x2e\x0f\x48\x68\xa2\x99\x81\xa3\xc7\x45\x4d\x85\x7e\x06\x02\x4b\x3a\x86\xd2\x7b\xea\xd9\x15\x3a\xbe\x1f\xe8\x40\x82\xff\x58\x32\x72\x7d\x19\x02\xea\x99\xd2\x5c\x1b\x7b\x8c\xd3\x1a\xeb\xe2\xc8\xcf\x4e\xce\x73\xfa\x77\x29\xc8\xd5\xd7\xb7\x6e\x02\xa7\xcf\x0a\xaa\xad\xd4\x80\xfe\xbd\x54\xcc\x72\xe1\x0e\xcc\x3d\xf4\x69\x32\x74\xfb\x9e\x5c\x52\x43\x91\xaf\x3b\x4f\x2b\x51\x91\x72\xcb\xb2\xc7\x5c\xa4\xee\xa7\x88\x61\x3f\x35\x6f\xb5\xbb\xf7\x61\x93\x98\x14\x37\xfc\xf4\xf1\xfa\x40\x3c\x38\x01\x62\x3e\x7d\x2f\xd3\xce\x8c\x38\xea\xea\x89\xef\x9f\x2c\x4c\x2f\xf0\x3d\xc9\xed\x98\xc4\x6a\xef\x03\xf2\x91\xd1\x94\xd8\xf3\xeb\xfe\xf9\x83\xd5\x3d\x5b\xd3\xaa\x56\x2c\xc4\x03\xb0\xe3\x32\x7c\x37\xbf\x84\xd8\xd3\x3d\xb5\x98\x03\xc7\xca\xf1\x92\x71\x26\xc7\xc4\x1d\x87\x43\xcf\xfd\xd3\xc7\xeb\x1d\xa6\xfe\xe9\xe3\xb5\x9f\xb9\xfd\xa7\x9c\x3c\xdd\xa4\x77\x12\xdf\x2a\xe9\xed\x6d\x43\xdc\xaa\x58\x72\x15\xb8\xd1\x14\xc9\xda\xcb\x63\xa3\x43\x49\x62\x87\x84\xd8\x3d\x17\x2d\xa2\x70\xeb\xa7\xcc\xf6\xb1\x0a\x05\xfa\xaa\x45\xf7\x88\xb7\x33\x0a\xa1\xcf\x21\x20\x0f\xf6\xd9\x6e\xbc\xb6\x5c\xc1\xef\xb8\x55\x02\x81\xb6\x91\x4b\x86\xb7\x9c\xe9\x1b\xef\x3b\x10\x7a\xac\xee\xf0\x1e\x3c\x35\x53\x47\x5f\x09\x3a\x6e\xa6\x11\x82\x9d\xa0\x55\x49\x84\x9f\xe8\x9c\xf2\x8c\x8e\x79\xc6\x21\x95\xba\xd5\xee\x63\x6f\x54\x0d\x53\x3e\xe8\xa9\xdf\x51\xe4\x08\xe2\xc4\x92\x71\x8b\x9c\xd8\xdf\xce\xc0\x38\x76\x3a\x02\x6a\x05\x0d\x21\x47\x63\x43\x28\xf9\xb8\x4d\x28\x39\x98\xfc\x00\x3b\x60\x4f\x4c\x57\xae\x68\xfb\xac\xe4\x8a\xf0\xc3\xad\xcb\x27\xf7\x92\x19\x23\xc6\x5a\xb5\x62\x8d\x80\x5f\x5b\x5b\xb6\x67\x8e\xfb\x22\x57\xfa\x65\x20\x17\x09\x11\x6d\x3b\xf0\xcf\xaa\xa3\xe7\x43\xa0\x24\x81\xc7\x99\x8b\x76\xab\xb9\x66\x22\xf6\xdd\x3a\x5a\xe3\x52\x30\x21\xd7\xb5\x38\xd7\xa6\x2e\x5a\x97\xa4\x0d\x1e\x23\xba\xae\xca\xf7\xf3\x8b\x42\x12\x08\xaf\x49\x0b\x5c\x6c\x3d\xc9\x84\x15\xb3\x49\x97\x2b\x71\xdb\xe1\xed\x6d\xdd\x12\x78\xc1\x8a\x19\x79\x7b\xbb\xe2\x18\x03\xec\x61\xd6\x1a\xed\x83\xc7\x9a\x64\x7c\xc2\x0c\xdf\xb2\x84\x47\x38\xc8\xb9\x14\xdc\x48\xb5\x3e\x04\x9a\x74\x3a\x9c\x7e\xb8\xae\x0c\xd5\xf7\xb3\x3b\x5b\x25\x10\x79\x1f\xbd\xa5\x24\x91\x59\xc6\x12\xe3\x52\x5a\x01\x78\x43\xb7\x15\xca\x13\x73\xf6\x80\xd1\xfd\xef\x41\x7d\x72\x8a\xd2\x19\x6e\xee\xd9\xc7\xab\xf3\xcb\xf7\x57\xa3\x3c\xfd\xc5\x4c\x3e\x0c\x8d\x1c\x96\x9a\x0d\x79\x8b\x0c\x25\xcf\xe7\xbd\x88\x4f\xd1\x2a\x61\x56\xd3\x20\x83\xb9\xbe\xbe\xf3\xf1\x93\xe4\x93\x46\xaf\x05\xb0\x1d\xf9\x3b\x29\x29\xcd\x80\x28\xea\x62\x24\xa9\x33\x3d\x95\x59\x86\xd0\x36\x8a\xb1\x41\x6c\x8b\xd9\x18\x1a\xd2\x79\x61\x7b\x1b\x2a\x6a\x0b\x7c\x5c\x19\xe2\xe9\x11\xae\x0b\xc7\xd8\x2e\x93\x2c\x43\xb1\xea\x59\x87\xe3\x6d\xed\x3d\x1a\xce\xcc\xcc\x42\xf5\x9e\x2d\x08\x38\x02\x4f\xa4\xb2\xf8\xa4\xea\xb8\xc1\x4c\x02\x4b\x3f\x2b\x35\x53\x23\xc7\x76\x9e\x1c\x6c\x1d\xb2\x08\xed\x90\xbc\x2d\x74\x5c\x05\x33\xf7\xba\xca\xec\xeb\xe4\x35\x5a\x9a\x19\x13\xc6\x8a\xfd\x96\x96\x39\xc8\xac\x04\xa2\xf3\xc3\x7e\x72\xa8\xb5\x4c\x62\xd4\x2d\xe5\x50\x9f\xa6\xa7\x0b\x4e\xda\x53\xd3\x15\x1d\x6d\x1f\x08\x44\x8c\xc9\x7c\x88\xe5\x52\x34\x95\xe0\xb0\x81\x19\xe8\x6a\x88\x46\xd3\x9c\x8b\x17\x78\x3a\x13\x2e\xd2\x6d\x70\x68\x18\xc0\xa0\x47\x5d\x14\x73\xef\x9c\x41\x3f\xdc\x1b\x52\xaf\x49\x61\xc0\xbb\xbb\x41\xac\xdf\x1f\xb6\x3a\x7c\xf9\x42\xff\x98\x0d\xf1\x2b\xc3\x22\xad\xa0\xd2\x5f\x06\x2e\xdf\xe0\x1d\xd6\xa4\xf4\x04\x57\x7c\x07\xda\x6d\xf2\xc4\xd2\xd0\xe3\xea\xb9\x4f\x02\xa8\x2e\x32\xcf\xbe\xdc\xbb\xa2\x99\x50\x78\x5f\xfb\xe0\x33\xcc\x6c\x06\x67\xd4\xeb\xcb\x50\x90\x9f\x2a\x9a\x33\xc3\x14\xba\xc0\x39\xa7\x3a\xe1\xa2\x13\xbe\x2b\x98\xb8\x35\x34\xb9\x3f\x74\x2a\xd4\x9e\xe3\x3e\x1e\xc7\xdd\xfb\x2a\xd0\x23\x82\xcb\x8b\xb4\x88\x6f\x91\xb9\x70\x5c\xe8\x85\x90\x98\x90\x8e\xac\x8b\x95\x23\xa4\xa3\xaa\x73\xd7\x2a\x3d\x19\x1a\x36\xc0\xd3\x2d\xe4\xd7\x03\x0f\x7e\x84\xc2\x61\xb8\x61\xfb\x33\xe0\x48\xe0\x2e\xf7\x68\x51\xd7\x3a\x75\xc8\xed\x9b\x31\x37\xd5\xb9\xd7\xcc\x90\x82\xa9\x9c\xbb\xb0\x6e\x29\x48\xe2\xc2\x02\x80\xaf\x59\x1e\xe6\x86\x8b\x78\x9e\x20\x32\x31\xd4\xc5\xcc\x90\x31\x33\x0f\x8c\x09\xf2\xea\xd5\xab\x57\x20\x97\xbc\xfa\xdd\xef\x7e\x47\x20\x8f\x44\xca\x12\x9e\x2f\x37\x84\x56\xff\xe7\xf5\xeb\x11\xf9\xef\xf3\xf7\xef\xc0\xab\xac\x30\x9a\x8c\xa5\x99\xb9\x91\x6d\x83\x5a\x67\x3d\x20\xff\xf7\xf6\xbb\x0f\x5e\x9c\xd0\x8d\x5f\x41\x05\x09\xcb\xab\xbb\x08\xbe\xfa\xed\x6f\x7e\x33\x22\x97\x5c\x41\x3c\x31\x87\x08\x88\xe0\x04\x59\x78\xc7\x40\x28\x3c\xd4\x8c\xe0\x77\x1c\xc4\x39\x09\xe7\x7c\x3a\x03\x00\xd8\x03\x21\xc5\x24\xe3\x89\xc1\x9c\x82\x78\xf4\x11\xd0\xae\x2e\x12\x75\xe1\x5e\x4e\x8a\x80\xc9\x0d\x48\xc6\xef\x19\x99\xe8\x6f\x94\x2c\x8b\x2a\xcc\x51\x31\x6d\x65\xd9\x84\x0a\x88\x2a\x81\xc1\xaa\xbd\xd2\xcc\x3c\xab\x13\x46\x4b\x43\x50\x0d\x07\xa1\x4f\x43\x40\x19\x84\xdc\x6a\x43\xc4\x87\x82\xf2\xe0\x38\x08\x77\xea\xb5\xcc\xfe\x41\xf7\x4c\xa3\x5c\x72\x3e\x76\xa5\x50\xf2\x6f\xb8\x55\x5c\xf8\x28\x28\x27\x21\x6b\x27\x93\xb9\xa0\x53\x11\xd9\x5c\x7d\x54\xbe\xe5\x85\x2e\xe2\x3f\x8a\x9f\xba\x9e\xc4\x81\x76\x10\x96\x8e\xe5\xd5\x6a\x89\x2f\x57\x7c\xb9\x4a\xd6\x6e\xb1\x49\xe3\xbe\x96\x62\xa9\xb7\xab\xa3\xe2\xc8\x8f\xab\xae\xe3\x42\xd8\xaa\x31\xd0\x15\xd7\x05\x00\x45\x35\x9b\x6a\xc9\xe8\x6a\x5e\x3e\x9a\x99\xd2\x81\x06\x3c\xaf\xec\xb7\x99\xd6\x2e\x8e\x28\xa7\xea\xde\x2a\x09\x8e\x0a\x8c\xc0\xeb\x59\x87\x18\x26\x0c\x28\x9b\xa3\xb1\x3c\xa7\x8b\x5a\xd4\x80\xfd\xc8\xf1\x68\x74\x8c\xc7\x44\x2a\xcc\xe5\x89\x38\x6f\xdf\x3f\x53\xbc\x74\xdd\x2b\x9d\x16\x58\x76\x0f\xec\x39\xae\x6c\x09\xad\x79\x3b\x53\x07\xa9\x36\x19\x7c\x3b\x96\x2d\xec\x56\x1f\xb7\x7d\x5d\xdc\x21\x2c\xa0\x45\xd3\xae\x35\x70\x3b\xd4\xbe\x5d\x97\xad\xc1\xc1\xd8\x9d\x84\xb6\x15\x21\x3b\xe7\x02\xcf\x5b\xb1\xbe\x15\x53\x3d\xce\x1d\xe7\xfb\xae\x1b\xe7\x73\xf1\x7a\xb5\xe2\x60\x2f\x9f\xd5\x5d\x4f\x30\xd2\xa5\x4e\xba\x1c\x69\x88\x45\x81\x50\x88\xab\x0a\x7b\x79\xd1\x1c\x2d\x46\x9b\x6e\x89\xe7\xbb\x70\x37\x7c\xda\x5d\x4c\xe0\x53\xc3\x35\x7f\x3b\x81\x8b\x76\xa4\xb4\xa8\x15\xf8\xc8\xd0\x6e\x00\x32\xa6\x3f\x3c\x23\xf2\xde\x91\x5a\x44\x32\x3a\xd6\x32\x2b\x0d\x76\xad\x7e\x8c\xe9\x30\x0c\xea\xb3\x2c\x00\xf1\x0d\xcd\x22\xaa\x6c\xaa\x12\x67\xed\x08\x34\x3e\x1d\x0e\x67\x9f\xed\xf3\x11\xb3\x7d\x86\xfc\xb4\xba\x65\xbd\x26\xfd\x68\xe9\x75\x13\xcd\xbb\xe8\x57\x9a\x93\x93\xaa\x4c\x88\xbf\x8e\xbf\x16\x86\xa9\x09\x4d\xd8\x69\xac\x77\x85\x72\x2c\xc1\x45\xc8\xc7\x45\xcc\xa8\x48\x33\x14\xc0\x13\xa6\x00\xf7\xd9\x67\xc3\x94\x05\xc9\xc5\xed\x35\x49\x15\x9f\x33\xa5\xc9\xc9\xd7\xcc\xca\x8b\x8c\x9a\x52\xb1\x56\xd1\x55\x87\xf5\xad\x84\x69\x1c\x4a\xd3\x83\xc1\xba\xba\xea\x41\x27\x4f\x79\x44\x74\xbe\x2a\x30\x21\x54\x11\xa4\x3a\xd6\x65\x47\x16\x95\x80\x40\x03\xcd\x58\xc8\x52\x39\x2b\xba\xcf\xab\x9a\x48\x65\xd5\x25\x1c\x98\x6a\xa2\xd8\xd4\x4a\xb3\xca\x17\x1b\x66\x24\xc9\x4a\xfb\xe2\xa0\xee\x6c\xfb\x38\x00\x56\xa6\xd9\x4d\xbe\x7a\x13\x27\x55\xcb\x39\x4f\x3d\xab\xc4\xda\xc7\xa1\xaa\x61\x41\x75\x14\x6a\x13\x65\xa0\x8f\x00\x8b\x32\x3a\x30\xd4\x10\xc4\x5a\x73\xf6\x8f\x8d\xc2\x12\x72\x5b\xb4\x28\x1f\xd1\x85\x08\xcb\x94\xdd\x94\xe3\x8c\xeb\xd9\xed\x8e\x26\xc4\x55\x43\xa0\xb3\xc2\xd2\xad\xdf\x5a\x4b\xa2\x66\x42\x73\x60\x79\x96\x8c\x5b\xa6\xcb\xad\x1c\x25\x01\x88\xbe\x77\x8c\x90\x12\xa2\x3f\x32\xe6\x32\x18\xd8\x9f\x3e\x54\xf3\x70\x41\x69\x98\xb3\x24\x65\x9f\x44\x51\x7b\x9f\xd0\x2c\xd3\xcd\x80\x5d\x4f\x31\x51\xf6\xf0\x81\x6a\xb8\xa7\xdc\x6e\x77\xa8\x8c\xd2\xc8\x7e\xb9\x76\x61\x9a\xe4\x12\xc3\x78\x04\x91\xc2\x37\x82\xd4\x2b\xbe\x43\x14\xc8\x08\xe1\xca\x80\x32\x07\x2e\x1d\xd9\x9b\x4b\x1f\xcf\x5c\xba\xaf\x1f\x5e\x5c\xef\xbd\x8a\x86\xae\xa5\x25\x0d\xa4\xd4\x93\xdc\x2d\x4e\x1d\x07\xbd\x56\xc0\x6f\x9e\x1b\xa3\xf8\xb8\x34\xdd\xf3\xbd\x35\xba\x03\x9b\xb6\x8a\x08\x9c\xe2\xa1\x5b\x7d\x12\xa1\xa8\xd3\x10\xc2\x59\x58\x3e\xfb\x15\xcf\x01\x76\x83\x2f\x8f\x35\x49\x65\x52\x86\xbc\xb0\x00\xb4\xea\x02\xad\x4d\xf6\x44\xd2\xf5\x5c\x75\x4f\xe9\x15\x7f\x64\x2b\x7a\xa5\xf2\x41\x3c\x50\x95\x9e\xdf\x6c\xf1\xbe\xaf\xb3\xf3\xaa\x57\x2c\x28\xf9\xd7\x50\x05\x90\x8e\x65\x69\xaa\xd4\xa1\x3f\x1d\x7b\xf5\x2a\x35\xdd\x48\x4b\x1a\x5a\xda\xa3\xbb\x2a\xfa\xbd\x89\xbb\x37\x71\xd7\x9e\x5d\x4c\xdc\xd7\x68\xe2\x8e\xf3\xe0\xd6\x8e\xab\x4f\xaf\xc0\xb3\xb6\xbe\xbd\x8f\x69\x25\xbd\xac\x08\x0c\x4a\x53\x4d\x3f\xfe\x86\x00\x87\x47\xa4\xda\xdb\x48\xe8\xf3\x14\x08\x78\xf6\xf3\x5b\x54\x1f\xc9\x4e\xda\xbe\x4e\x31\x3e\xeb\x0a\x09\x6e\xaa\x5b\x0c\x52\x43\x54\x68\x78\xe0\xb2\x40\x0f\x9c\xde\x25\xd2\xaa\x84\x1f\x26\xa1\xee\x50\xa6\x14\x9f\x8e\xc0\x27\x9d\x37\x80\x74\x2c\x22\x8c\x4f\xd7\xdd\x20\x3b\x14\x14\xc6\xe7\x99\xcb\x0a\xe3\xd3\xd9\xf6\x4d\xba\x97\x18\x5e\xb1\xdc\xc7\x2d\x34\xbc\xe3\xd2\x76\x37\xeb\xef\x6a\xce\x1f\x54\xe5\xed\x5e\x3e\x5b\xef\xcd\xf9\x4b\xcf\x13\x9a\xf3\x23\xc2\xed\x89\xc1\x0a\xd3\x7e\x6c\x6e\xf3\xf6\xfd\x31\xf3\x62\xe5\xa8\xca\xbe\x66\x51\xce\x5b\xf6\xa5\xaa\x5f\xab\x1e\x8f\x46\xc7\xc7\xde\xde\xef\xf0\xb3\x34\x93\xe1\xef\x09\x13\x89\x4c\x71\x53\xed\xf8\x4a\x1b\x60\xfa\x95\x9a\x1e\xcf\x25\xf7\xdf\x8a\xaf\x66\x61\xec\x6e\x5b\xd2\xe1\x04\x77\x2f\x1b\xbe\x0a\xd2\x4f\x51\x3c\x3c\x2e\x11\x5e\xaf\x08\x8e\x2d\xf6\x29\x03\x1e\x03\xef\xd1\xf9\x6b\xeb\xc2\xe0\xf8\xec\xc2\x5e\x77\x28\x12\x8e\xcf\x13\x97\x0a\xc7\x67\x27\x8e\xda\xa9\x6c\xf8\x8a\xc5\x3d\x5d\xf1\x70\x7c\x5e\x68\x21\x99\xfa\xd3\xa9\x90\x38\x3e\xbb\x95\x13\xaf\xf7\xed\xb8\xf5\x07\x29\x2d\x8e\x4f\xb7\x02\xe3\xf8\x1c\xba\xcc\x38\x3e\x2d\x21\x01\xc6\xf0\x4b\xde\x29\x14\xc1\xf7\xa9\xbb\x4b\x1a\x96\x17\x52\x51\xb5\x20\xa9\xb3\x35\x2c\x56\x44\x84\x46\x21\xa1\x7b\xa7\x86\x81\x79\xa4\x5c\x1d\x28\x1a\xa1\x43\x34\x28\x4b\x79\xb9\xb6\x5c\xf3\x3a\xb0\x61\xaf\x18\x68\x0f\x90\x0d\xcc\x65\x12\xf3\xd7\x9d\xae\x99\x4f\xac\x48\x93\x7b\x57\x31\xc8\x43\x15\x79\x7f\x14\xe4\x72\x74\xd4\xc8\x03\x0d\xe6\x31\xb8\xfb\x73\x95\x11\x7d\x63\x1c\xbb\x66\xca\xc2\xdb\x10\xe7\x16\x70\xe2\x1a\x9e\x5a\x89\xe4\x3d\xb0\xc1\x27\xda\x25\xd2\x31\xb2\x8d\xff\x9d\x41\xb9\xb1\xce\xbe\xf1\xbe\x63\x48\x07\x2d\x41\x32\x0f\x75\xd1\x32\x99\x44\x77\xcf\x35\x0e\x05\xdb\x70\xe5\x91\xdf\xdb\xee\xed\x66\xd8\x51\x51\xbe\x00\xa3\x4f\xa6\xf1\x5e\x8f\x27\x90\xda\x12\xa4\x78\x00\x66\xd8\x80\xbb\xa8\x4a\x60\xa9\xed\x97\x20\xf3\x7c\xd4\xa6\xfa\xd0\x83\xcf\xb0\x69\xa2\x42\x6e\x75\xdd\xc3\xfe\x72\x1b\x56\x56\xe9\x6d\x10\x02\xe1\x05\x75\x5d\x82\x98\xe8\xbe\xe2\xc4\x25\x39\x81\xbb\xab\xaa\x2c\x5a\x48\xee\xb8\x84\x66\x82\x67\x75\x3c\xf3\xb9\xec\xc2\xc2\x4b\xe1\x1c\x0d\x96\x90\x66\x35\xce\x94\x9a\xa9\xe1\xb4\xe4\xe9\x2e\xd8\xf2\x82\x19\x60\x6b\xb6\xd7\x9d\xd9\x75\x64\x71\x7b\x30\xb6\xe0\x88\xd1\x81\x35\x1c\x55\xde\x1b\x35\xde\x10\xa7\xc5\xab\x7b\x72\x50\xef\x2c\x10\x8e\x9c\xbf\x12\xba\x0b\xaa\xad\xe3\x19\xc9\x22\x71\xc1\xba\xbc\x96\xee\x12\x87\x45\xcc\x03\xc7\xd6\xa1\xfd\x8f\x57\x81\xbd\x3d\x7f\xcc\x26\xb2\xaa\x90\x82\x1a\x91\x73\xc7\x4d\x59\xc6\xa0\x8c\xbc\x2f\x51\x6f\x1b\xc0\x95\x70\x2e\xe7\x16\x99\xff\x47\x90\x4f\x3e\x67\x3f\x9f\xbc\x21\xf4\xb4\x16\x02\xe1\xaa\xce\x08\xc6\x52\xf4\xd1\xcd\xaa\xef\xa8\x52\xe8\x01\x19\x9f\x7a\x7f\x14\x38\x71\xc2\x8a\x85\x99\x97\x78\x51\xaf\x56\xcc\x02\x00\xc2\x8e\x95\xcc\x89\x16\xb4\xd0\x33\x69\x40\x35\xa4\x05\x4d\xb8\x59\x10\xa3\x68\x72\x0f\x25\x8a\x14\x73\x9f\x1b\x90\xe4\xd4\x39\x76\xc5\xe0\xab\xbb\x0d\x9b\x99\x92\xe5\x74\x06\x9e\xb0\xd8\x2a\xc9\xa8\xf6\xab\x5f\xd9\xdf\x69\x3b\x9a\xa4\x0b\x41\x73\x9e\x84\xac\x81\x4a\xce\xb9\xe6\xd2\x59\x7b\xfd\xb8\x37\x21\x33\x1c\x5a\x90\x2f\x32\xca\x73\x72\xa2\x19\x23\x57\x1e\x25\xf0\x17\x57\xc6\x1e\x2d\x1b\xaa\xee\x1c\x20\x43\x4a\x73\xe1\x12\x22\x54\x04\x2e\x5c\x5e\x21\xc3\xb4\x33\x5f\xf9\xd1\xd3\xb0\x5d\xab\xe7\x24\x15\x5c\xdc\xfb\xd4\x9d\x4c\xa4\x32\xba\xb5\x3c\xbf\xb9\xd6\xb1\x36\x82\xb8\xe5\xf2\xde\xc1\x0f\x99\x14\xd3\x38\x8d\x40\x85\x99\x96\x94\x0a\x28\xef\x32\xe7\x69\x49\x33\x24\xa2\x6e\x32\x17\xb7\xd7\xd8\x9d\x4f\x67\x66\xf8\xc0\xc0\x1a\x83\xbc\xa6\x3a\x33\xfe\xa3\x7c\xc9\x5b\x87\x6b\x20\xba\xc6\x59\x13\xd0\xb2\x65\xa7\xf6\x40\x17\x90\xb6\xc6\xb9\x98\xd4\x2e\x4c\x7d\x62\x31\x1c\x62\x15\xc4\x61\x7a\xe7\xa1\x5c\x87\x15\x1b\xc0\x5c\x65\x41\x0c\x98\xba\x3c\x37\x0b\xf8\x28\x0f\x60\x78\xed\x2a\xb3\x51\xbb\x41\x56\xb8\xdb\xac\xcb\x3c\x82\x50\x36\xaf\x36\xf9\xce\x95\x4e\xec\x28\x1c\x1c\xfd\x10\x99\xcd\xa2\x8b\x0e\x7b\x6c\xa8\x48\x87\x34\xb3\x98\x73\xf3\xfd\x85\xf3\x70\xc6\x83\x50\xbb\xc8\xf7\x55\x90\xb8\x08\x69\xb3\xad\xcc\xb0\xf2\x08\x40\x1c\xfc\x98\xa5\x40\x34\xe2\x82\x91\x0f\x56\x43\x76\x9b\x77\xf3\xfd\xc5\x80\xf0\x11\x1b\xf9\xbf\x42\x53\x4f\xb5\x8c\x9c\xa2\x1b\x60\xf0\xf1\x04\xbc\x83\xa9\xc4\xc6\xa8\xb8\xef\x5f\xff\x60\x27\x69\x7f\xfd\xe3\xf0\x0f\x51\xb6\xd1\x3f\xfe\xd5\x12\x41\x65\x1b\xd4\xdf\xc6\xbe\x64\x21\xeb\xfe\x5f\x6f\x5c\x56\x6a\x97\xb3\xfa\xaf\xae\x18\x17\x13\xc6\xca\x8d\x37\x12\x6e\xe9\x79\x8a\xd8\x08\xdf\x56\xec\x6f\xde\xb0\x08\x60\x0a\x46\x9d\x84\x1a\x26\x80\x50\xfb\xa0\x0c\x21\x0d\x76\x77\x75\x67\xed\xfc\x4f\xc0\x24\x80\x41\x65\x03\x62\xa4\x84\xe3\x88\x47\xfe\x5c\x10\xe6\x6b\x75\xe2\x5a\x01\x1c\xd4\x39\xaa\x79\xde\x63\x87\xb5\x10\x0e\x21\xb8\x76\x1e\x30\xb7\x5f\x09\x69\x7e\x15\xb6\xbf\x51\x45\x9c\xce\x25\xf7\x09\xc8\xed\x49\x11\x58\xd1\x31\xa4\xc4\x1e\x2f\x48\xce\xb5\xa1\xf7\x6c\x44\x6e\x2d\x6f\x89\x6f\xc3\x10\x7a\x82\x40\x06\x4b\x96\x92\x52\x18\x9e\xc1\xaf\xd5\x38\x76\xca\x31\xcf\xb9\x9e\x10\x5d\x42\x79\xf3\x42\xb1\xa1\xe7\x62\xae\xd5\x12\x2d\xa8\xd6\x32\x08\x9b\x3d\xa3\xa8\x0b\x14\x29\x74\x05\x78\x50\xe1\xd0\x6b\xc9\x8f\xcb\xce\x53\x8a\xa4\xe2\x5c\x00\x4c\x3d\x22\x1f\x80\x59\x65\xfe\x4a\x18\xd5\x12\x67\xc0\x14\x2c\x61\x5a\x53\xb5\x18\x40\x62\x77\x1e\x92\x81\x3b\xd7\x1d\xe0\xa8\x39\x15\x98\x56\x5d\xb1\x44\x0a\x6d\x54\x99\x18\xac\xb3\x37\x56\xf2\x9e\x89\xe0\x2e\x68\x77\xb1\xee\xc0\x55\xf9\xcf\xc0\x7d\x97\x24\xc9\x8c\x8a\x69\x54\xa7\x26\xa7\x29\xc0\xfe\xdb\x20\xe5\xf8\xf5\x58\x08\xd0\x89\x15\x2c\xb8\x01\x50\x8c\x2d\x1f\x09\x66\xd8\xff\x11\x21\x1f\xcf\xa0\xb2\x93\xda\x25\xf1\x6c\x0b\xed\xea\x44\xbf\x48\x47\xa3\xde\x10\xd8\xf6\x81\x1d\xc0\x72\x66\x68\x4a\x0d\xdd\xc1\x09\xec\x7d\x55\x5c\xcf\xd7\xd7\xc7\x02\xa7\xe1\x62\xd2\xf1\x21\x2f\x6e\xc9\x82\xc7\xf1\x4f\x70\x12\x67\x1e\xf2\x10\x71\x6d\x2c\x4e\xb9\x8b\x02\xf4\xed\x02\x79\xc6\x57\x2f\xb3\xc3\xfb\xd1\x90\x5c\x54\xa5\x19\x2b\x72\xd2\xee\x1a\xaa\xa3\x05\xd6\x82\x7e\x07\x18\xdd\x55\x77\x65\x49\xdd\xbf\x6b\xa5\x08\x82\x5c\x82\x09\xc3\x15\x8b\xc3\xcd\x1c\xe8\x4a\x81\x48\xde\x00\x22\x40\x79\xca\x8c\xae\x3c\x54\x90\x0e\x5b\xe2\xe2\xf8\x9d\x53\x46\x81\x48\x3b\xc0\x3a\x7d\x6e\xb5\x2c\x84\x60\xd7\xd2\xd1\x59\x4b\xf9\x1f\x05\xae\xbb\x18\x9d\xb1\x9c\xc0\x7b\x99\x76\xb1\x53\x37\xb2\xf0\x57\x43\x54\xfe\x9b\xe8\x89\xab\x41\xa9\xc7\x06\x70\x5b\xa5\x6b\x41\x73\x48\xe4\x66\x74\xbe\xbb\x91\xaa\x92\x91\x86\x21\x95\x31\x7c\x6e\x08\x9f\x1b\xbe\x6e\x6f\xcc\xeb\xe2\x01\xe2\x9f\xd6\x9e\x20\xf5\x8f\x74\xb2\x9c\x5a\x92\x72\xdb\xd1\xdc\xd9\x88\x46\x0e\x23\x38\x9a\xef\x6e\x11\xc3\xcd\xad\x8b\x74\x60\xdc\x52\x8b\x37\xe4\x57\x35\x2e\xef\xa4\xa9\xa0\x29\xa1\xa7\xee\x89\x57\x9d\x46\x6e\x2b\x7c\xf0\x79\xbd\xf9\x69\x63\x30\x10\x2f\x56\x6b\x14\xde\x23\x38\x88\x7c\x56\x3c\x53\x60\x3c\xf3\xf1\x07\x16\xbd\x94\xcc\x32\xa6\x60\x09\x4e\x7b\x6a\xdc\xa2\x43\x2e\x53\xb4\xe9\x0e\x82\x8a\x1a\x64\x4c\xc1\x1e\x82\x30\x41\x35\xa6\x6e\xf1\x37\x5e\xcc\x15\xce\x5b\x3b\x5e\xf0\x5a\x3e\x17\x0b\x9c\xfa\x65\x04\x5a\x54\x3d\xc9\xd4\x7e\xc8\x4a\x9d\x82\x8e\x33\xbc\x3d\x0e\xcc\x16\xe6\x42\xb3\x07\xba\xd0\x80\xf7\x95\x34\x1f\xbe\xef\xb2\xaa\x55\x03\x7f\x64\x13\xec\xdd\xfa\x46\x6c\xa7\x3b\xb1\x5d\x6e\xc5\x20\x9c\x92\x8b\x36\x2e\x48\x55\x87\x8d\x85\x43\x9a\xcf\x2e\xd7\x68\xe0\xa7\x02\xd7\xe7\xdd\xee\x44\xea\x75\xca\x6f\xae\x61\x08\x2f\x93\x4f\xe1\x0f\xcf\x71\xc2\xa5\xc1\x98\x59\xac\xae\x02\xa5\x01\x43\xe2\xbe\x2b\x3c\x09\x2a\xd4\xfa\x16\xb2\xb1\x3a\x2b\x71\xa8\x34\xa6\x18\x78\x82\xc0\x17\x47\x50\x8e\x80\x8a\x85\xe3\xe4\x66\xc6\x55\x3a\x2c\xa8\x32\x0b\x54\x1f\x07\xb5\xaf\x05\xf7\xfa\x4e\x0b\xdf\xf1\x3a\xa7\x5d\xea\xe3\xb5\x10\x86\xc5\x7b\xf3\xb0\xb3\xce\xaf\x85\xeb\x53\xac\xa7\xbd\x03\xff\xca\xf5\xc4\xa9\x45\xbd\x46\xf8\x6c\xeb\x49\x63\xf2\xb1\x3f\xdf\xb0\x34\x48\xd7\xaf\x5e\x91\x0d\xc4\xa5\xab\x64\xec\x05\x1d\xb8\x3c\x28\x44\x76\xa4\x81\xd5\x43\x69\x55\x6b\x3c\x32\xec\x39\x49\xc1\xfb\xd0\xb8\x4a\x47\x62\xe1\x4c\x37\xf1\xb7\xe2\x01\xc2\x29\x21\x27\x42\x0a\x3c\x39\xd8\xf6\x14\x5d\x88\xd6\xd8\xa6\xa0\x89\x2b\x51\x57\xaf\x10\x1a\x9d\x54\xcf\x24\xb8\x48\xed\xd6\x01\xe5\x06\x1d\x49\x97\x49\xc2\x58\xd0\xaa\xe3\x12\x35\xd5\xc9\x76\x53\xf6\xa5\x2e\xb5\x84\x24\x2e\xda\xd0\x2c\xab\xb4\x59\x07\x2e\x09\x7c\xce\x5b\x00\x23\xf6\x57\x0b\xb4\x71\x8a\x3d\x14\x51\x47\xb7\x97\x52\x24\x78\x85\xcf\xcd\xc2\xcf\xe0\xb2\xc9\xea\x41\x8d\xd0\xa8\xe4\xf2\x09\xda\x9d\x22\x75\x20\x00\x13\x48\x93\x2b\xe1\x5e\xe7\x4c\x2e\x37\x83\xa5\x43\x63\x9a\xdc\x3f\x50\x95\x42\x29\xdf\x82\x1a\x8e\x69\xc1\x07\xb5\x61\x4f\xa2\x39\x40\x21\xfd\x18\x8b\x4e\x83\xd2\xa1\x59\x48\x41\x5d\x7d\x86\xd0\xd2\xc8\x9c\x1a\x9e\x80\x2a\xcb\x27\x91\x15\x31\x0f\x29\x0d\x1b\x65\x07\x81\xca\x86\x02\xf6\x77\x78\x1b\xa3\x18\x31\x0f\x92\xf0\xdc\x4a\x08\x14\x4a\x69\x4c\x42\xc4\x90\xb7\x77\x6e\x9a\xa9\x15\x83\x7e\x00\x23\x73\xd4\x0a\x95\x64\xab\x42\x69\x18\x3e\x58\x34\x83\x29\xcf\x85\xdc\x0c\x1a\x0c\xdc\xf5\xb1\x38\x6d\xe7\x1a\xa1\xea\xc0\x6e\xcf\x03\xb3\x72\x81\xde\x88\xb0\x7a\xb4\x6a\x46\x58\xd3\x56\x93\x94\xeb\x46\x61\xea\x93\x54\xc9\xa2\x70\x06\x92\xfc\xb4\x39\x23\xb8\x37\x50\x73\xa6\xa3\xda\xcb\x68\xaa\x9e\x32\x11\x8a\x87\xbb\x74\x16\x70\x72\x9b\x9f\xa8\x1d\x98\x11\x06\x84\x9e\x92\x4f\xae\xa8\x50\x40\xdc\xe0\x75\xd7\x4a\x70\x42\x6b\x8b\x93\x9d\x7a\x89\xa7\xed\xd3\x4b\x3c\xbd\xc4\xf3\xf3\x96\x78\x82\xbb\xd7\xae\xd2\x4e\xe5\xe3\xd8\x28\x48\xee\x9d\x01\xaa\x06\xeb\x8c\x18\xd7\x13\xf2\x91\x25\x72\xce\x14\x12\x39\x28\xfc\x69\x79\xf9\x5b\xca\x33\x4b\xe2\x3c\xa9\xab\xd4\x43\xc8\xa8\x5a\x37\xcd\x45\x1a\x79\x80\xa6\x43\xf3\xdc\x4d\xca\x45\xfa\xd9\xf6\xee\x92\xac\x50\x6c\xce\x65\xa9\xbd\xcb\x42\x69\xf0\x98\x69\xe3\xf8\xed\x8c\x4f\x43\x62\xee\x70\xd5\xa9\x58\x22\x55\x5a\x85\x94\x6b\x43\x4d\xa9\xeb\x71\x12\x09\x5a\xd3\x0e\x67\xa0\x09\x70\x7c\x64\xea\xbe\x1b\x25\x45\x8f\x8d\x3d\x4e\xc5\xf1\x3b\xf4\xf9\xa8\xea\x6e\x9b\xc8\x0d\xa5\x72\x81\xb1\x22\x54\x69\x58\x84\x56\x0e\x01\x3a\xc3\xba\x16\xf5\x7a\x86\x85\x5b\x86\x61\xd8\x61\xe5\x75\xd2\x22\xe3\x7a\xfc\xec\x04\x75\xb2\x47\x80\x67\xfc\xbc\x60\xc7\x93\xc6\x62\xbb\x7b\x5f\x92\x3d\x3d\x30\xc9\x3e\x5e\x98\xe4\x90\x9e\x98\x24\xf8\x73\xef\x73\x62\x3e\x7a\x4f\xf2\xc6\x99\x71\x84\x77\xd3\x99\xa9\x25\x14\x08\xe3\x70\xed\x2b\x40\xba\x6b\xcd\x70\x06\xc0\x24\x18\xfb\x03\xbb\xd3\x0a\xda\x1c\xde\x5d\xb2\xcf\x21\xeb\x6f\x24\xc7\x54\x45\xb5\x8d\x04\x0f\x84\xbc\xc0\x4c\x40\x70\xea\x86\xce\x25\xcb\x6b\x4b\xfd\x09\xee\x4f\x70\xdb\xfe\xcf\x79\x82\xd1\xe3\xb9\x8b\x43\x7e\xa3\x52\x10\x76\x77\x41\xb8\x74\xcc\x32\xf2\x63\xc9\xd4\x82\x58\x21\xa8\x72\xef\x81\xf4\xc6\x9a\xa7\xce\x41\xc6\x19\x55\xda\xcb\xec\x4f\xc8\xff\xc1\x64\x73\xf5\xd9\x4a\x80\x10\xc7\xb6\x07\x5d\x6b\x0e\x55\x0f\x55\x46\x68\x05\x08\xc6\x12\x1e\xde\x30\xd6\x64\x3e\x2b\xee\x9d\x7f\xb8\xdc\x4d\xd1\xe9\x76\xa9\x45\x76\xb9\xd8\x5a\x5a\xfc\xf9\x86\x05\x22\x20\xc2\x2f\xf5\x6a\x52\xc1\x14\x41\xee\xd9\x62\xe0\xee\xc1\x5d\xf6\x76\xdf\x18\xdd\x39\xea\x29\x45\xdb\xa6\xaa\x58\x05\xa0\x1d\x28\xe4\x6e\xd6\x03\x7c\xda\x27\xa1\xac\xf7\xf2\x40\xe8\x4a\x88\x77\x26\xe1\x9d\x92\x55\xc6\xcf\xba\xc4\x95\x88\x13\x90\x81\xcf\xfb\x35\x07\x34\x00\x5f\x6e\xa0\x16\x5d\x37\x91\xec\xae\x02\xe3\xe3\x01\xbb\xf7\x52\x03\x9a\xd6\x1c\x73\xef\xd9\xe2\x58\xbb\xa8\x41\x29\xf4\x8c\x17\x3e\x3f\x3c\x50\x02\x87\xb9\xe4\x7b\xf0\x0f\xf0\x43\xe0\x99\xbf\x16\x03\xf2\x41\x1a\xfb\xbf\x2b\x70\x15\x42\x4b\xa5\x64\xfa\x83\x34\xf0\xe6\xc9\x81\x85\xd3\xdd\x1b\x54\xce\x4c\xc9\xc1\xcc\x88\x2e\x6d\x10\x9f\xe1\x5d\x50\x00\x24\xee\xbe\x35\x80\x95\x6b\x72\x2d\x88\x54\x1e\x26\xc6\x27\x0f\xd6\x6e\x08\x6f\x5b\x8a\x2c\xc2\x2b\xc6\x70\xa0\x94\xaa\x06\xc9\x0d\xc3\x05\xe3\x32\xf7\xbf\x80\xed\x09\xac\xf1\xc1\x6f\x06\x52\xe0\x52\xc3\xa6\x3c\x21\x39\x53\x53\x88\x0f\x4d\x66\xbb\x6f\x50\x77\xba\x8d\xcf\x4e\xd4\x3b\xfe\x70\x67\xcc\x00\x56\xf7\x0e\x3c\x97\xf6\x65\x98\x38\x0a\xb2\x88\x9c\x16\x16\x29\xfe\x61\x39\x01\xec\xcb\xbf\x20\x65\xb5\x1e\x91\x73\x5f\xf0\x34\xfe\xcd\x59\x31\xe2\x61\xec\x08\x56\xa6\xff\xb1\xe4\x73\x9a\x31\xf4\xe7\xa3\x22\xa4\xf1\x94\x93\x25\x36\x3d\x70\x79\xab\x2d\x95\x0a\x37\x43\x47\xf7\x6c\x71\x34\x58\x42\xa4\xa3\x6b\x71\x54\x05\x69\xd7\x50\x27\x30\x34\xb8\x34\x38\x82\xdf\x8e\x0e\xcd\xd9\x9f\x49\xb4\xdf\x01\x4b\x9c\x41\xe8\x22\xa3\x5a\x77\x8b\x6f\x6d\x84\x16\x35\xc6\x59\x95\x80\xf1\x36\x6a\x53\x05\x17\x39\xef\xcd\x83\xdb\xb3\xc0\xcb\xbf\xbb\xa7\x51\x27\xe8\xcd\x5d\xf5\x94\xf6\x89\x1b\x56\x26\x14\x83\xb4\x05\x3e\x86\xa3\x16\x17\x57\x5d\xc6\xae\x81\xd7\xf7\x60\x57\x94\x93\xb8\xc8\x33\xd7\xa0\x06\x73\x1f\xd5\x21\xa4\x21\x5c\x24\x59\xe9\x4c\x8a\xd0\x15\x94\xe8\xae\xa2\xfe\x0e\xc0\xd9\x03\xa9\xaa\x01\x3c\x36\xf9\x6b\xdf\x25\x07\xde\xe6\x0d\x1d\xdc\x89\x86\x1b\x2f\x84\xd5\xa1\xd7\x3a\xd9\xe2\x2e\x59\x4f\xc6\x99\xd4\x65\x8f\xb7\x7c\xac\x18\xb9\x98\x51\x21\x58\x16\x45\xbb\x3a\x63\x47\x28\x67\x05\x02\x89\x2b\x62\x75\x5c\xaf\x62\xe5\xe9\x9b\x08\xb1\xd5\x07\xaf\x1d\xfc\x53\x2a\x2a\x75\xb0\x3a\xe5\x2e\x55\xe3\x4c\x3e\x90\x54\x92\x07\xa8\x5b\x30\xb7\x4c\x0b\x2e\x65\xb5\x67\x77\xd1\x4c\xc1\x45\x22\x91\x79\xa1\x64\xce\xb5\x77\x8e\x77\xdb\x78\xd0\xd0\xd0\xac\x6c\x91\x03\xa8\xbe\x07\x59\x29\xea\x29\xe1\xdf\x5e\x10\x43\xd5\x94\x19\x3b\x1a\x11\x65\x3e\x66\xad\xe3\x57\x1f\x23\x07\xd9\x97\x54\x42\xf4\xb0\x45\xb0\x70\x1b\x7e\xf8\xe1\x43\xe7\xd2\xbb\x55\xcf\x75\x7b\xfb\x20\x55\x96\x3e\xf0\x14\x59\xb4\x26\x27\xb6\xf1\xe9\xcb\xaf\x94\xfb\xf0\xc0\xd3\xce\xe0\x80\x4e\x75\x30\x78\x3f\x28\x0b\x06\x02\x70\x70\x15\x9e\x38\xa4\xd1\x86\x1e\xa7\xe4\x8a\x63\x74\x11\xf4\x87\x44\x35\xf9\x98\x8b\x2a\xc2\xac\x02\xb3\x25\xc6\xf6\xbc\x78\xd5\x44\x33\x83\x71\x21\x10\x5a\x21\xcd\x8c\x68\x9e\x97\x99\xa1\x82\xc9\x52\x67\x8b\xd6\xa8\xf2\x3c\xa0\x9e\x64\xec\x33\x62\x76\x17\x26\x17\x3a\xd5\x99\x1d\xb8\xae\x54\x61\x94\x4b\xdc\xae\x72\xae\x4a\xcf\x02\xe7\x0b\xe1\x46\xec\x33\x4b\x9c\x57\x70\x91\x95\x53\xbe\x25\xfc\xe1\x67\x96\xd5\xbc\x4a\x20\x5d\x6a\x56\x45\xea\xb7\xad\xeb\xf2\x44\x49\xc8\x9f\x97\xc3\xdf\xad\x4e\x40\x9e\xb2\x82\x89\x14\x52\xa2\xbd\xad\x30\x17\x27\x7f\x50\xc8\xb9\xf4\x62\x5d\xa9\x96\xcf\x4a\x56\xa3\xe0\x91\x0b\xd7\x4c\x66\xa9\x26\xec\xb3\x51\xd4\x12\xa6\xdc\x92\xa0\xd0\x67\x42\xa8\x68\x4f\x64\x5e\x46\x8a\x60\x72\x70\x6e\xff\xb8\xf5\x32\x5f\x62\xc9\xcb\x6a\xed\x7a\x63\xc1\xea\xfd\x52\xd7\x23\x21\x76\x67\x45\xd7\x3d\x84\x57\xa4\x98\x77\x5f\xa9\x7b\x26\xee\x97\x6a\x5e\xaf\x48\xaa\xdd\x98\x55\x5f\xa6\xf3\x8b\xc8\x3b\x3f\x81\xc0\xe0\x2e\x49\x98\x5c\x8f\x86\x46\xed\x5e\x36\x0b\x42\x6f\xd0\xa0\x1d\xde\x46\x7c\x00\x32\x9e\xba\x81\x5c\x58\x13\xd1\x16\x96\x95\xeb\x5c\x29\xc4\x36\x2a\xf6\x18\x59\xc4\xa9\xa1\x9a\x99\x76\xd6\x94\xba\xe8\x50\xf5\xb4\x07\x30\xc6\x2f\xf7\x13\x66\xb1\x07\x87\x74\x1f\x2c\x4b\x86\x7f\x74\x52\x86\xa8\xb5\xb4\xf2\x85\x87\x8f\x4f\xd2\xc4\xc2\x2d\x32\x8e\x91\xda\x5d\x49\xa8\x69\x5d\x72\xa7\x15\x5f\x70\x33\xf8\xf4\xa9\x73\x2d\xd7\xa8\xa7\x97\x43\xe0\xdf\x75\x20\x38\x5c\x80\x44\x3e\xfc\xc7\x32\x56\x07\x20\xb9\x45\x58\xb6\x6b\x7f\xa8\xb5\x4d\x13\x56\x19\xaf\x2e\xb9\xbe\xef\x92\x8c\x6c\xa9\x73\xfd\x48\x7c\x73\x71\x45\xdc\xdb\x56\xf6\xa5\x2e\x06\xa6\x7d\x33\x63\x4d\x13\x56\x19\x6d\x53\xae\xef\x9f\xbc\xac\x7a\x91\x7e\xd8\xe6\x01\xfe\x74\xf6\xaf\xa6\xd4\xeb\x53\xb4\x44\xb9\x83\x16\xb2\x24\x0f\x2e\xf5\x81\x93\x9a\xef\x78\xf1\x86\x5c\x09\x5d\x2a\x56\xdd\xdc\x36\x87\xb2\x5c\xf7\x25\x95\x5e\xdf\x0b\x4b\x5e\xb2\xf1\xad\xa0\xca\x80\x78\xdc\x15\x0d\x42\x47\x4f\x9f\xa2\x17\xa2\x0d\x1e\x5c\x4f\xbc\x63\xdd\xc0\xc5\x78\x87\xc4\x65\xbe\x91\xdd\xf9\x28\xad\x49\xbc\xd7\x6f\x43\xca\x1f\x72\x96\xb2\xf9\x99\x4e\xe9\xeb\x01\x7c\xc6\x3b\x3c\xd7\xe7\x44\x35\x39\x7a\x7d\x34\x22\xb7\x3c\xe7\x19\x55\xd9\xa2\x96\x8a\xb9\x6a\x67\x99\x85\x1f\x10\x6e\xe5\x5e\x1d\x91\x13\xa9\x60\xe4\x84\x0a\x92\x31\x1f\xd1\xe4\xce\xd9\x02\x65\xc7\xd3\xa7\x26\x2e\xe4\x51\xed\x97\x48\x67\x3a\xe3\x44\xea\x39\xb6\xe3\x47\xb5\x74\x36\x97\x15\x49\xe7\xc2\xd2\xf9\x11\xf9\xb4\xaa\x50\x39\x1c\x19\xdf\xe2\xb9\x80\xfa\x34\x7a\xdf\x4e\x1a\xdc\xb2\x39\xf8\xf9\xc0\xb4\x5d\x4b\x9c\x72\xf3\x91\x15\xb2\x93\x84\x80\x5d\x1a\xf6\x38\x6e\xec\x0b\xa9\x39\x24\x2a\xa5\x06\xca\x02\x2b\xc3\x93\x32\xa3\x56\xac\x46\x6b\xdc\x88\x5c\x5e\xdd\x7c\xbc\xba\x38\xbf\xbb\xba\x7c\x43\xbe\x71\x23\xf1\x58\xc2\x1b\x91\xbb\x38\x1b\x54\xe4\xd1\xeb\x52\xee\x84\x6f\x0d\x1c\x19\xa2\xa2\x4a\xee\x08\x39\x3e\xa8\x20\xd7\x82\x9b\x2a\x3d\x32\xfa\x9d\x65\x52\x30\x5f\x3d\xb4\x90\xce\x1a\x38\xe5\xe8\x0d\x22\xdc\x60\xf6\xe7\xfa\x68\x70\x3a\x30\xd5\x6a\x98\xca\x16\x45\xf0\x11\x44\x8b\x0a\xb8\x87\x12\xff\x7d\xfe\xd3\xae\xb2\x6f\xc8\x46\xeb\x03\x9c\xd0\xfa\x5f\xbd\x47\x66\x10\x12\xb3\xfb\x74\x37\x2b\x4a\x5a\x13\xcb\x66\x8e\x47\xc7\x5e\xa0\xc8\x96\x92\xf0\x87\x41\xe3\x8c\x5e\x75\x64\x1b\x11\xf2\x9d\x77\xd9\x86\xd0\xe3\xd5\xf9\xfc\x31\x3b\x44\x94\x15\xbe\x81\xb2\x3e\x30\xa6\x1c\xc7\x1f\x75\x29\xc0\xa6\x7c\xce\x04\x2e\xec\xb0\x14\xca\x7f\xbe\x73\x75\xb4\x6a\xde\x4e\xff\xf8\xf8\xee\xb0\x33\xc3\xf3\xd7\x79\x5e\xee\xd8\xba\x59\x25\x32\xcf\x31\x5f\xd4\x2c\x04\x18\x56\x31\x82\x81\x2a\x1c\x4c\xf3\xc1\xcc\x57\x93\x2d\xc8\xdf\xa0\x67\xbe\x53\x43\xd3\x09\xaf\x5d\x50\x82\xa8\xc4\xdc\xee\x79\x98\x5d\x92\x35\xed\x93\xa7\x38\xd2\x7e\x16\x3e\x7e\xf6\xf1\xea\xfc\xf2\xfd\xd5\x28\x4f\x9f\x9c\xb4\x30\x91\x16\x92\x0b\xa3\xb7\xeb\x37\xdb\xaa\xce\xb4\x27\x3f\xe1\xa3\x5d\xb9\x73\xe8\xe8\x71\xcc\xbf\x88\xf2\xd2\xa5\xcc\x50\x9e\xe9\x68\x0f\x8d\x2c\x64\x26\xa7\xab\xd3\x2f\x77\xd8\x9c\x5f\x60\x7e\x99\x21\x1d\xda\x5d\x3f\xac\xa8\xdf\xa6\x8e\x46\x53\xca\xaf\x2a\x62\x57\x6b\x0d\x52\x33\x94\xbb\x78\xa1\xcb\x7d\x14\xe1\x6c\x09\x06\xa8\x48\xc2\x01\xf6\x29\xfb\xaa\x1c\x78\x51\x0d\x9b\xb6\x52\xdb\x63\x83\x6e\xbb\xc0\x66\xe9\xcf\xf6\x42\x45\x75\x98\xf9\x3e\x75\x02\x57\x28\x36\x0c\xe9\x9a\xa0\xb4\x8a\x54\x11\xc3\x8d\xe9\x9d\xb7\xde\x78\x5b\x0f\xb6\xca\x16\x4d\x2b\x4e\x25\x1f\x05\xd3\x17\xe6\x18\xc8\xb2\x45\x95\x06\xd2\x69\xd1\x74\x8a\x69\x98\x94\x33\x13\x17\x8a\xcf\x79\xc6\xa6\x90\x8a\x95\x8b\x69\x14\xfe\x1a\x07\xcc\xba\xd4\xac\x75\xa3\xeb\x7b\xfb\x57\x94\x74\x1b\xf0\xe2\xc3\x77\x77\x90\xd5\x17\x2e\xb8\xf6\x16\xc2\xed\x07\xe1\xbc\x0d\x87\x43\x30\x19\x9c\xfc\xcd\xca\x93\x69\x76\x4a\x7e\x60\xee\x3b\x12\xd2\x0e\x2b\x28\x05\x34\x93\x21\x07\x2c\xcc\xb5\x82\x2c\xa0\x23\x5e\xef\xbb\x56\x67\xb6\xa5\x95\x95\x90\xd5\xd4\xda\x43\xe5\x53\x4c\xdd\x88\x77\x4c\x4f\x2f\x7b\x1e\x90\xec\xef\x4c\xe5\xbc\x69\x75\x15\x7e\x86\x8b\x1f\x4f\x0f\x29\xd1\x8b\x3c\xe3\xe2\xbe\xca\x0b\x36\x91\x16\x87\x30\x34\x81\x8b\x7b\x8f\xb1\x8a\xd1\x6c\x3d\xa5\xdc\x05\x3f\x0e\x4a\x25\xcd\x0e\x16\x40\xb0\xd0\xd9\x73\xf6\x27\x7f\xec\xdd\x35\x74\x4c\xe2\x8e\x8e\x5e\xdc\x7a\xb9\xee\x56\x06\xff\x18\x3a\xd4\x68\x9a\x20\xd7\xb7\x17\xb7\xd7\x4f\x6a\xa1\x5e\xc7\x12\x60\x76\xcf\x28\xd5\xf1\x1f\xb7\xdd\x0e\x0f\x49\x56\x6e\x6f\x83\xea\xdd\x8d\x54\x86\x66\x07\x22\x02\xc9\x8c\x16\xe7\xa5\x99\x5d\x72\x0d\x39\x14\xba\x0a\x01\x4b\xfd\x23\x4f\x67\xcc\xdd\xec\x13\x06\x72\x8f\x0e\xae\xdd\xc5\x9f\xce\x6f\x08\x2d\xed\xfe\x1a\x97\x5c\xf4\xa0\x17\xee\x7e\x66\xb7\x18\x61\xb0\xe3\xba\x5c\xef\x2d\xab\xf2\xad\x1e\x7b\x4d\x8f\xe1\x87\xdb\xdf\x45\x00\x0d\x45\x0a\xf6\x82\xef\x1f\xb8\xe0\x86\x53\x23\x5b\x16\x2a\xab\xa1\x40\xad\x6f\x30\x08\x94\xda\xc8\xdc\x61\xf0\xb5\x6f\x01\x57\xc8\xc0\xc5\x97\x3a\x55\xd6\x02\x90\xde\x01\x62\xd7\xc2\xca\xda\x34\x61\x0d\x07\xc8\x01\x24\xfd\xc4\xb1\x79\x68\xf3\x07\x67\xa0\x82\xfc\x60\xd9\x1f\xdf\xd4\x52\xb1\x2f\xd5\xb5\xf0\x56\x8a\xaa\x68\xc2\x41\x2d\x3e\xfc\xc7\xae\x44\x81\xff\x28\x1a\x96\x36\x5c\xe0\x7f\x95\x34\x43\xc0\x7c\x38\xb4\x59\xaa\x0e\xe4\xae\xf3\xad\xef\x90\x9b\x7a\xb5\x1d\x1f\x82\x96\x5e\x6a\xcc\x3c\x86\xeb\x31\x8a\x0a\x6d\xf7\xa8\xae\x8b\x1d\xbb\x8b\xa7\x63\x72\x62\x92\xa2\x75\xed\xfe\x47\x72\x6d\xcf\x4a\x51\x2b\xe4\x0c\x33\xbf\xc3\x6d\x79\x17\x5c\xdb\xdb\x4e\xf2\x51\xae\x86\x00\xcb\xbb\x5a\x55\x5c\xaf\xb0\x5b\xf1\xba\x90\xf5\x93\x77\x5c\x1b\x5f\x90\x01\x5e\x70\xed\xf2\x08\x83\xdc\x75\x63\x15\x39\x5e\xfc\x2f\x4d\x53\xf5\x06\xb9\x94\xaf\xbe\xac\x40\xfa\xf2\x49\xbe\xa8\x08\x77\x89\x27\x66\x51\xb8\x04\x80\x77\x17\x37\x04\x0b\xa4\xfc\xfe\xb7\x58\xf9\xf5\xdf\x7f\xfd\xdb\x57\xad\xb7\xfb\xf9\x9c\xc7\x77\xb4\x63\x1c\xfc\x8e\xe9\x45\xf8\x0d\xd6\xfc\x03\xed\x4a\x40\x36\xb9\x45\x77\x3c\x4b\x59\xdd\x51\x47\xc4\xb2\xbb\x1c\xe8\xfd\x6e\x12\x4c\xef\x67\xf7\xac\x7e\x76\x24\x44\x94\x20\x91\xe8\x88\x2e\x71\x57\x08\x31\x5c\x26\x3b\x48\x71\x6e\x5e\x1e\xc5\xd9\x0a\x9b\xed\x58\x54\xc7\x9e\xf8\x32\xde\x97\xbf\xa9\x5c\xd8\x2f\x3f\xdc\xfe\xef\xbb\xf3\xaf\xaf\xde\xc1\x4c\xdd\xfd\xbd\x45\x0d\x2e\x76\xf6\x9f\x6a\x8f\x6a\x6d\x94\xd7\xed\x00\xe9\x76\x2d\x23\x1a\x17\x32\x82\x7c\x78\x7b\xdb\xf5\x2e\x66\x5f\x01\x5d\x4c\x5a\xad\xfd\x69\xad\x6d\x50\xd5\x84\xa9\xc3\xc5\x8f\xec\x6c\x94\x8b\x12\x69\xd5\xf4\x2f\xbb\x53\x38\xc3\xbd\x55\xa4\xad\x3b\x40\x5e\xc0\xbd\x83\x5d\x2f\xc2\xe0\xe0\x37\x0e\x8f\x04\xab\xb6\x72\x80\xea\x1e\x58\x74\x8c\xbd\xbc\x08\x60\x0f\x29\xd2\x36\x65\x69\xb6\xa5\xd6\x4c\x87\xea\x0b\x2f\x14\x53\x8a\x55\xe9\x99\xbb\x50\xaf\x95\x03\xd4\xca\x95\xd5\xee\x62\x6a\xb1\x14\xeb\xd2\x99\x7b\x0f\x05\xea\x94\x57\x5d\xd0\xe4\xa0\x05\x55\xaa\x57\xf8\x06\x82\xdc\x9f\x9e\x00\xc2\x67\x0f\xe8\x48\x1b\xc6\xeb\x8a\xc8\xa1\x63\x33\x4a\xae\xd3\x0e\xf9\x42\x1f\x85\xf4\x11\x88\x71\x38\xdd\x33\x6f\x1f\x79\x5a\x6d\xe7\x87\x1d\x15\x9d\x43\x2b\x39\xc5\x4c\x1a\x29\x76\xf6\x92\x5f\xd5\xbd\x7e\xa0\x6f\xa0\xc5\x45\x55\xc6\x26\xaa\xf1\x08\x1e\x94\xe1\x32\xc2\xca\x73\x9e\x5d\x48\xe1\xaf\x25\xea\x97\x12\x4f\x2e\x82\xa4\xd7\x97\x07\x3a\x7c\x5f\x6e\x88\x67\x57\x63\xf0\x41\x9d\x41\xd2\xce\x31\x29\xb6\x8b\x87\xd8\xf5\xa5\x13\xcd\x7c\xc0\x89\x76\x08\x49\xd6\x63\xe4\xc1\x58\xa7\x54\xe6\x41\xaa\xee\xa1\xde\xf5\x8e\x0d\x5f\x05\xf7\xdb\x52\x28\xd6\x4b\x3c\x3d\x38\xc7\x67\x3e\x41\xb7\x70\x82\x1a\x09\xce\xd7\x9d\xa4\xc7\x38\x48\xcf\x7b\x80\xf6\x65\x54\x8f\x1b\xe5\x7b\x50\x21\xdd\xa3\x5b\xc7\xa5\xfa\x6e\xce\x98\x60\x37\xa9\xa2\x16\x14\x4c\x2e\xd1\x89\x3b\x18\x75\x50\x12\x4b\x50\x76\x21\x0c\xbe\x0f\x1a\x70\x31\xd1\x73\x96\x59\xa8\x4a\x11\xa7\x88\x76\x61\xbc\x03\x82\x59\x96\x73\x5a\xf8\x9a\xdc\xf2\x41\x3c\x50\x95\x92\xf3\x9b\xeb\xc3\x50\x83\x0e\x7e\xd6\x88\x49\xed\x32\x7a\xd5\x3d\xad\xab\x9e\x58\xe6\x66\xc6\xa0\xb6\x22\x19\x73\xa3\xab\x9a\x7e\xcc\xc4\x7a\xa5\xa5\x82\xe1\x2e\xcb\x9e\x65\x7b\x6e\xdd\x48\x11\xc3\x14\x44\x26\x86\x66\xbe\x88\x80\x2b\x93\xf3\xea\xd5\x2b\x34\x85\xbd\xfa\xdd\xef\x7e\x87\x95\x95\x52\x96\xf0\x7c\xb9\x21\xb4\xfa\x3f\xaf\x5f\x8f\xc8\x7f\x9f\xbf\x7f\x07\x95\x1f\x0b\xa3\x31\x2b\x09\x8e\x8c\x95\xe0\xa3\xce\x7a\x40\xfe\xef\xed\x77\x1f\xaa\x32\x31\xf5\x5f\x5d\x41\x6d\xb7\xbc\x11\xb9\x8c\xfc\x9f\x62\x43\x17\x35\x33\x57\xd0\xc8\x10\x3a\x99\x20\x62\x8c\x7d\x39\x5d\x3c\x70\x3e\x7a\x1c\xaa\x82\x63\xfd\x11\x8b\x12\x19\x38\x66\x59\x95\x1c\x4d\x83\x3e\xb3\x01\xfa\x99\xc1\x58\x81\x4c\xc2\x54\x06\x58\x4b\x7e\xa2\xa1\x0a\x49\x95\xfe\x4f\x31\x6d\x85\x52\x57\x5d\x11\x07\xab\x76\x46\xb3\xd6\xb9\x1e\x1e\xe3\x06\xa8\x75\x75\x8c\xba\xe9\xde\x9d\x21\x9f\xbe\xd5\xe5\x2e\xae\xca\xd4\xff\x0d\x6f\x43\xb7\x39\x09\x3f\xd2\x8d\x4c\x6d\xae\x37\x61\x36\xb8\x75\x2e\x4b\x40\x45\x27\x68\x26\xa1\x92\x57\xd8\xe9\x8a\x8b\x45\x45\xef\xb7\x2f\xa5\x73\xf2\xc5\xae\x09\x78\x91\x50\xbd\xa7\xad\xcb\xf9\xd4\xfd\x45\x7c\xef\x5a\x5e\x05\x3a\x96\xa5\xf1\x77\xd8\xee\x77\x08\xc0\xc6\x2a\xeb\x1d\xd2\x48\xee\x90\x79\x72\x97\x0c\xc4\x9d\x93\x98\xd6\xef\x9b\x81\x27\xd4\x45\x89\x01\x61\x34\x99\x91\x7b\xb6\x18\x22\xdd\x2a\x28\x44\xf3\x00\x54\x2e\x2d\x2c\x6a\x85\x4f\xaa\xda\x35\x56\x3e\x76\x20\xf3\x8e\x01\x11\xf7\xf1\xd1\x40\x5e\x08\xd5\x4e\x5e\x72\x69\x44\x45\x64\x29\xf0\xb9\xaa\xa3\x7a\xc4\x21\x6f\x28\x16\x23\xaf\x07\xa9\xd8\xf3\xc6\x52\xdb\x4d\x6f\xfa\x72\xe5\x0d\x61\xe9\xa0\xe3\x6e\xa5\x58\xea\xed\x8a\x6f\x3b\xe1\x0f\x3e\x48\x7d\x76\xe6\xc8\xa3\x02\xca\xf9\xb9\x4a\x4e\xae\xad\x87\x52\x00\x44\x2d\x88\x46\x33\x53\x3a\xd0\x60\xbd\xb0\x52\x64\x4c\x6b\xc2\x61\x85\x39\x55\xf7\xcc\x27\x8c\xa1\xd9\x88\xdc\xd8\x49\x86\xfc\x55\x98\x16\x79\x8e\x2e\x76\xf6\xcc\xc6\xd1\x41\xf6\x23\xc7\xa3\xd1\x31\x12\xf8\x15\xb1\x42\x1d\xf0\x63\xb7\x9c\xba\x3b\xe4\xd2\x6d\x94\xf6\x2e\x34\x66\x06\xb6\x22\x1f\x64\xbe\x96\x10\x05\x67\x66\x9e\x81\xd1\xd6\x49\x94\x96\x97\xb3\x43\x02\xd8\x5d\xf3\x96\xef\x92\xb5\xbc\xd5\xbd\x45\xfd\xd9\x3d\x5b\xf9\x4e\xb9\xca\xd7\x65\x2a\x77\x3b\xe5\x4e\x5b\xf7\x1c\xce\x7b\xa4\xd8\xce\x3b\xa5\x79\xf5\x4f\xdd\x48\x09\x72\x47\x2d\x4b\x4f\x2b\x19\xd1\x25\x7d\xca\xd8\x17\x25\x14\x5e\x4f\x56\x55\x9d\xf3\xc1\x82\x91\xbc\xec\x69\xa8\x85\xc0\xf3\x4b\x83\xdd\x6a\xb9\x90\xce\xe2\x61\xf3\xe9\x22\x2e\x36\x9f\x76\x97\x81\xcd\xa7\xae\xb0\x45\x61\x49\x81\xe8\xc7\x5e\xfc\x00\x52\x23\x21\x67\x77\x75\x04\x47\xe4\xbd\x63\x0a\x88\x8c\x74\xac\x65\x56\x9a\x10\xc9\xb4\x82\x63\xc0\xa0\x3e\xc3\x37\x86\x94\xfa\x66\x11\xff\x00\xce\x89\x64\xb9\x2b\x2b\xc1\x67\xa7\x23\xde\xb5\xe6\xde\x4f\xd6\x99\x64\x0f\x18\x7a\x51\x62\x67\x38\xfa\x01\x42\xde\x09\xef\x4b\x5d\x93\x71\xc0\x93\xc4\x68\x14\xa0\xbc\xb8\xe2\x0a\x3d\x75\x5e\x62\x3b\xab\x8d\x9b\xab\x33\x4c\x9c\xdf\x5c\xef\xa4\x01\x44\xfd\xd7\xe8\x00\x71\x8b\x9f\xb0\x16\x70\x8d\x5a\x40\x5c\x76\xe7\xb2\x5a\xb9\x33\x29\x5b\xb2\xf3\xe2\xc5\xc8\xa5\x69\xbf\xb5\xc4\x32\x76\x3a\xad\xe7\xd0\x43\x63\x4f\x45\x56\xa3\xbc\x7b\xfe\xd6\x11\x0e\xf1\x4b\x17\x39\x9f\x50\x7c\x04\x78\x74\x2a\x97\xee\x9f\xe5\x6a\x76\xb0\x58\x72\x0b\xa5\x6d\x50\x1f\x8c\x14\xcb\x42\xa6\x6f\x5c\x29\x69\x21\x24\x16\x90\xd3\x03\xac\x8d\xa3\x07\xa8\x30\x5a\x29\x22\xba\x2b\x56\x91\xc9\x7d\x67\xb9\x61\xa7\x2a\x47\xfb\xd4\x39\xb2\x1b\x08\x2b\xbf\xe9\xba\x8b\x64\xcf\xb2\x45\x24\x62\x4d\xbb\x15\x42\xa9\xed\xa9\x1b\x29\xd4\x79\x4f\x66\x2c\xa7\x98\xc3\xcf\x2f\xcf\x52\x99\x07\xc5\x8d\x61\x98\x4b\x89\xa9\x5c\x13\x39\x19\xd4\xee\x0c\x8e\xe6\xaf\x8f\x76\x29\x07\xb3\x67\xc5\x1e\x52\xed\xc2\x01\x80\x71\x53\x13\xd9\x2c\x5e\x83\x2e\x91\x41\xe2\x4d\xd1\x30\x48\x58\x06\x33\x47\xe8\x3d\xf9\xc2\x0f\xa1\x47\xed\xaa\x3f\x0d\x82\xc0\xd0\xeb\x4f\xbd\xfe\x74\x10\xfd\x29\x62\x2c\x9e\xe0\xac\xd0\xa5\x62\x87\x61\xaf\x50\x55\x81\x4c\x51\x02\x1e\x8b\x9a\x5e\x95\x92\xaa\x6e\x71\xb3\xfa\xd0\xb1\x57\xb0\x1c\x1e\x97\x66\x32\xfc\x3d\x61\x22\x91\x29\x6e\xbe\x1d\x5f\x69\x03\xa2\x4d\xa5\x93\xc4\x73\xc9\xfd\xb7\x62\xab\x1d\x8c\xbd\xeb\xd6\xed\x44\x07\xfc\x55\xe0\xdb\x03\x31\xf8\x8a\xad\x87\x60\x62\x5f\x2b\xdb\xe7\x1a\x70\xfc\xbd\xba\x84\xc4\xb2\xd2\x80\xdc\xbe\x62\x2e\x39\xc1\x97\xa3\xa4\x28\x07\xae\xc1\x28\x67\xb9\x54\x8b\x41\x68\x64\x7f\xac\xf5\x72\x2d\x4e\x41\x26\x48\x4a\x65\x35\xc0\x6c\xf1\xa5\x4a\x07\x1e\x40\x4f\x2c\x1c\x84\x7d\xea\x56\x34\x28\x7e\xea\x28\x51\x25\x15\x03\xfd\xbe\x2a\xa2\x34\x09\x29\x0f\xf5\xa0\x52\x3b\xed\x5b\x26\xe6\x64\x4e\x55\x87\x2a\xe8\xf1\xb3\xa7\x3c\x90\xf2\x39\xd7\xbb\xd5\x3b\x6c\x2c\xfd\xd6\x31\x0d\xb4\xeb\xc8\xd2\x14\xa5\x71\x94\xd2\x9f\x0a\x1f\x32\x1f\x4e\x43\x43\x28\x7a\x7d\xb4\xd3\x34\xbe\x98\xfa\xc2\xf8\xec\x58\x65\x18\x9f\x7d\x6b\x0d\xd7\x47\xd9\x19\x6d\x0e\x5a\x39\xdc\x3f\x1e\x2d\x0e\x71\x0e\x2b\x16\x59\xe5\x79\xf0\xc2\xe9\x13\x1d\x34\x74\x37\xd9\xc9\x6e\xe3\x32\xd4\xaf\x36\xd9\xb8\x1f\x7f\xc2\xd6\x9a\xc3\xde\xd9\xba\xf8\xc2\x9f\xf9\x85\xed\xad\xab\x67\xd0\xdf\xd6\xb6\x42\xc1\xfe\xb6\xb6\xbf\xad\xed\x6f\x6b\x7b\x6b\x43\x6f\x6d\xe8\x6f\x6b\x49\x7f\x5b\x7b\x10\x18\x1e\xee\xb6\x16\x45\xbd\x55\x77\xb6\x4e\xd8\xab\x2e\x6c\x9f\xf4\xbe\xd6\x15\xee\x39\x4f\x12\x59\x0a\x73\x27\xef\x59\xeb\x4b\x87\x86\xfc\xbf\x34\x0e\x24\x40\x58\xa3\x0f\x2c\x37\x7e\x32\xe5\xa0\xbb\x54\xd2\x49\xb6\xd8\x45\xaa\xa0\x65\xca\xad\xe4\xbf\x33\x9a\xf9\x01\xe2\xe4\x44\x22\x65\x69\xf5\x83\x3b\xca\xc6\xc2\x7a\x44\xce\x89\x62\x09\x2f\xb8\x2b\x23\x4f\xf1\x3d\x22\x5e\xa8\x8d\xc0\x8d\x66\xd9\xc4\xe5\xa8\x17\x71\xad\x9f\x4a\x7e\x77\x74\x70\xe5\x67\x90\x43\x49\x9f\xc9\xdc\xd7\x42\x52\xec\x6f\x9e\xb5\xb9\xd9\xdc\xc5\x23\xc4\xe6\x15\x58\x4a\xad\xc4\x10\x7c\xac\xe0\x2e\xc0\xfa\xb1\x8f\x3f\xfb\x5c\x70\x05\xc8\x7b\xcb\x12\x29\xda\xd4\x54\x5d\xb3\x41\x4b\x23\x55\xfc\x09\x6c\xa3\x2c\x25\x69\xa9\x42\xcd\xd4\x39\xcd\x78\xca\xcd\x22\xdc\xda\xb9\xf2\x5a\x14\x4f\x4c\xd8\x46\x5d\x81\x91\xd0\xa2\x50\x92\x26\x33\xa6\xa3\xaf\xa1\x80\xe2\x82\xc8\x82\xef\x3b\x96\x80\x03\x19\x05\xfa\x58\x06\x99\x2d\x88\x92\xc6\x5f\xbc\xaf\xf9\xe0\x5d\x34\x18\x74\x47\x2e\x67\xd4\x02\x6e\xe7\x65\x3c\x04\xce\x8a\x4f\xe2\x3f\x34\x91\x59\xea\x53\x98\xfc\xfe\x95\x15\x0a\x13\x87\x83\x96\xf8\x41\x82\x0b\x23\x49\x66\x19\xb6\x25\x88\xeb\x3b\xff\xfa\x37\x64\x26\x4b\xa5\x47\x71\xd2\x81\xd7\xf0\x0e\xf5\x3b\x2f\x54\x1a\x92\x31\xaa\x0d\x79\xfd\x8a\xe4\x5c\x94\x96\x4f\x75\x46\x9b\xee\x72\x50\x24\x01\xfd\xf6\x37\xad\xfb\x75\x95\x7d\xd6\x4a\x3d\x05\xe6\x46\x76\xa2\x8f\x3b\x49\x18\x18\x87\x99\xc5\x1b\x82\x90\x23\xba\x31\xb4\x85\x91\x8f\x70\xbe\x7e\x2c\xe5\x78\x61\xba\x04\x51\xba\x1e\xf5\xe8\xc9\xff\x72\x2f\xdb\x24\x4f\xa9\x72\xa7\x6c\xfc\xe8\xa3\x54\xb8\x98\x72\x6d\xb6\xd4\xb7\xa8\xe2\x2b\x37\x36\x6b\xcf\x56\xa6\x56\x3b\xe8\x18\x2b\x03\x7d\xbc\x44\xec\x6d\x4b\x49\xc2\xb0\x98\xe5\x65\x55\x29\x49\x48\x6c\xbb\x75\xf8\x67\x4e\x38\xe6\x11\xe4\x00\x59\xd3\x5b\x2e\xb5\x9d\xd0\xe5\x51\xa2\xf3\x5a\xb1\x5b\xfd\x14\x68\x2e\xa6\x98\xe4\x3c\x2f\x33\xc3\x8b\xac\x5a\xf7\x47\xdf\xc1\x11\xf2\xd8\xe6\x46\x23\x33\x11\xc5\xc0\x62\xcc\x36\x05\xf6\xc9\x93\x30\x16\x13\x06\x73\x75\x2b\xcb\x0f\x0a\xaa\x68\x00\x1e\x54\xd2\xd5\xa7\xce\x7c\x47\xe1\x46\xd1\xa5\xc3\xb4\xbd\x68\x56\xcd\x38\xba\x45\x3a\x24\xd2\x18\x26\xa8\x68\x61\xaa\xae\xa7\xe7\x82\x4e\x44\x3e\x04\x67\x32\x2c\x83\xd2\xc0\x16\x27\xd4\x7c\x4d\x93\x7b\x26\x52\x2c\x1a\x05\xcb\x4e\x17\x82\xe6\x2e\xdb\x56\x54\x8f\xbb\xd1\x5f\x0f\x9c\x61\x02\xc3\xf7\x7c\x98\x31\x72\xdd\x43\xc2\xa0\xd4\x9d\x53\xd9\xd8\x2e\xdb\xce\xb9\x46\x93\x8d\xe2\xf3\x84\x79\xfe\x6f\xfb\x1d\x72\xea\xf3\x16\xb1\xf4\x4b\x93\xf7\xdb\x13\xe1\x2f\x90\xfb\x60\x39\x87\xa4\x5a\x34\xb3\x47\x7b\x11\x62\x46\x1b\x9b\x3b\x5e\x1c\xb6\xea\x8d\x1a\x77\x89\xfc\x3d\x56\xe3\xb4\x7e\x88\x3f\xd2\x54\x6a\xf2\x75\x26\x93\x7b\x72\xc9\x40\xe8\x7a\xcc\xf2\x2c\x6a\x9c\x3e\x67\x0a\xef\x9c\x4e\xb7\xdd\xb3\x0d\x49\x2e\x05\x37\x52\x6d\xa6\x17\x4f\x57\x76\xb2\x4f\xf7\xbc\x36\x43\x95\xc5\xe6\x97\x9c\xec\xd9\xa2\x5b\xd7\x8d\x87\x4e\x41\x3d\x83\xd3\x89\xaf\x5c\x15\xb0\x1d\xcf\xda\x2f\x66\xf2\x61\x68\xe4\xb0\xd4\x6c\xc8\x5b\x5c\xe8\x76\x58\xe6\x3d\x5b\xc0\x2d\x76\xc7\x85\xba\x6e\x35\x9d\xc1\x48\xb0\x40\xc1\x7b\xcb\xb9\x3f\x7e\x7d\xf9\x49\x33\x35\x8a\x65\xc0\x33\x66\x92\xb3\x84\x15\xb3\x33\x37\xc2\x8b\x04\x8a\x27\x22\x5d\xa1\xe2\xfb\x21\x9b\x49\x64\x96\xb9\xc0\x6c\x39\x21\x17\xac\x98\x85\x81\x9f\x7a\xd5\xcf\x97\x11\xb8\x90\xb2\x6b\x22\xd4\x63\xdb\xa7\x7e\x88\xe0\x0d\x9e\xa1\x08\x99\xd4\xb8\x5b\x11\x8a\xa7\x42\x9f\x17\x5d\x6a\xf3\x11\x81\xf3\xb8\xe9\x94\x8f\x6b\xf9\x94\x63\x7f\xcf\x7a\xb2\x64\xef\x31\x52\x23\x41\xd7\x13\x14\xba\x53\x96\x12\x39\x67\x4a\xf1\x94\x69\x12\x68\x50\xac\xa5\xf2\xec\xa9\xe1\xd6\xe7\x6d\x7e\xf6\xbc\xcd\x3b\xa8\x43\xc7\xa0\x0f\xd5\xc8\x14\xbc\x59\x22\x53\x34\xcd\xb9\x78\x71\x84\x4a\x27\x34\x63\xd7\xdf\x75\xd0\x3f\x5c\x8f\xba\x0a\x72\xeb\x5e\x46\xf9\xd3\xb6\x64\x25\xfb\x36\xe0\x0d\x11\x32\xdd\x66\x52\x7d\x04\x45\x62\x4a\x0d\x7b\xd8\xca\x0e\x87\x15\xa1\xda\xde\x12\x84\xd3\xe7\x54\x39\x5e\x44\x8e\xc0\x08\xe7\x31\xe9\xd9\x21\x99\xaa\xdb\xb5\xae\xc6\x49\xec\x15\xa7\xdf\x6d\x26\xdd\xf5\x18\x7c\x7e\x73\x4d\xbe\xc1\xe6\x87\xcd\x5e\xa8\xa4\x41\x31\xf0\x52\xe6\x94\x77\x2d\xb2\xd1\xec\xde\xcc\xbe\x1a\x2f\xe1\x26\xb4\x25\xae\x71\x54\xc0\x65\xc2\xa7\xa5\xd5\xe9\x9c\x1e\xf6\xa2\x12\xcc\x2d\x89\x2e\x2f\x37\xc1\xdc\xfe\xd5\x20\x22\x93\x93\xf7\x8b\xac\x24\x16\xbf\x95\xc0\x4a\xc2\x1d\x28\xd1\x4c\x68\x0e\x17\x32\xd1\xad\xb8\xab\xf4\x87\xa5\x25\xd1\x09\x12\x45\x9c\x01\x79\x27\xa7\x5c\xf8\xd3\x2b\xdd\x7d\xdd\x84\xf2\xac\x2d\x30\x7a\x99\xe4\xd9\x65\x12\xad\xb3\x2b\x41\xc7\x59\x1b\x77\x83\x3a\xaa\x85\x8e\xe4\x6d\x46\xa7\x84\xc1\x1f\x67\x29\xd7\xf6\xff\xe4\xf6\xf6\x1d\x18\xe1\x4b\xe1\x25\x66\x30\x50\x3b\xda\x17\x82\x14\xf0\x20\x1e\xf6\xec\x20\xe9\xd9\x21\xfb\x5f\xd4\x93\x70\x91\xda\x89\x47\xa5\xe0\xd0\x49\x0a\x5a\x60\x3e\xc4\xe0\xf3\x8b\x6e\x03\x63\x46\xee\x66\x3c\xb9\xbf\x89\xec\xee\x52\xd9\x77\x22\x7a\x55\x63\x60\xcd\xdf\x0e\x49\x2d\xdd\x54\x6f\xba\xab\xc6\x51\x4f\xcf\x07\x3c\xc1\xb8\x75\xeb\x87\xdf\xa8\xd6\x32\xe1\xd5\x9d\x0b\xd8\x68\x2a\xe6\x90\x02\x73\x38\xec\x9a\x40\x3c\xe8\xba\x1c\x94\x3f\x56\x70\x34\xbf\x9b\xbe\x3a\xae\x8e\x39\x18\x17\x7e\xd5\x07\x5d\x02\xe2\xcc\x0e\xa9\xd1\xab\x8e\xcb\xa9\xd1\xbd\x30\xdc\xb8\x58\xf0\x6e\xea\x6e\xf3\xbc\x20\xe6\x6b\x73\x2e\x6d\x5f\x48\x91\xee\x52\x13\x1e\x6c\xe1\x6d\xc2\x36\x56\xa9\xe1\x8d\xdb\x44\x7c\xe7\xae\x1a\xe0\xcc\x15\xb2\x28\x33\xf4\xe7\xd8\x3f\xbf\xbb\xb7\x19\xe3\x77\x0e\x74\xf5\xf0\x14\x59\x4b\x8f\x63\xc7\xde\xee\x9e\xce\x3f\x8d\xdc\xa5\x91\x70\xf7\xea\xb7\xbf\xf9\xcd\x97\x9e\xcd\xb4\xad\x0a\xfe\x18\xe9\x4c\x5b\x9a\x68\x57\xc4\x17\x5d\xf7\xf1\x45\x3f\xdf\xf8\xa2\xc7\xcf\x42\x7b\xe0\x08\xa2\x8e\xbe\xb9\xdd\xfc\x72\xdb\xc7\x08\xb5\xf6\xde\xed\xea\xb9\xdb\x21\x0a\xe8\xb0\xb1\x3f\x9d\x7d\x59\xbb\xc4\xf9\xf4\xd1\x3d\x3f\xd5\xe8\x9e\x5d\x7c\x59\xbb\x47\xf2\x74\xf1\x61\xfd\x29\x46\xed\x74\x38\x9c\xed\xa3\x4b\xf6\x8e\x29\xe9\x9e\x04\xb0\xbb\x3d\x6d\x97\x82\x54\x55\xcf\x95\x1a\xa4\x0f\x2a\xf7\xb9\xc7\x8e\x8f\x75\x94\x5a\xcc\x48\x7b\x02\x9f\x44\x21\x21\x1d\xb4\x31\x1c\x5e\x76\xa9\x0d\xe9\xfa\x7c\x77\xdb\xb8\x98\x09\xaf\x9f\xe7\x3e\xe6\xe7\x70\xe1\xd1\xd7\x74\xf9\x42\x4c\xee\xba\x96\xad\xc5\x5b\x2b\x80\x04\x00\x23\x97\xe3\x38\x4b\x64\x75\x74\xce\x6f\xae\xad\x0e\x0e\x61\x44\x34\xd3\x23\xb2\x82\xcf\x7b\x73\xa9\x93\x0b\x3c\x7f\xa7\xc6\xb0\xbc\x30\xed\x77\xbd\xb7\xb8\x3f\xbb\xc5\xfd\x80\x16\xc0\x59\x99\x53\x31\xb4\x27\x0a\x6c\xee\xb5\xdb\xba\x06\x65\x1e\x11\x77\x76\x90\x3d\x81\x05\x04\x82\x0b\xea\x85\x8d\x69\x54\xe6\xf2\x71\xcc\x9e\x30\xf6\xce\x2b\x47\xbe\xda\x38\x69\x89\x5c\x72\x78\x75\xcb\x09\x50\xf0\x87\x2a\x62\xce\x35\x35\xdc\xcc\x18\xf2\xf0\x1b\x08\xc8\xa9\x5a\xd5\x25\x69\x14\xa5\x69\x96\xc9\x07\xfc\x76\xcc\xd7\x2c\xf4\xed\x5c\x5c\xa4\xd9\x98\x91\x9c\x5b\x1d\xdd\x19\x58\xe3\xe9\xe0\x95\xa9\x95\xc8\x99\x42\x81\x57\xb9\xcb\xb6\x5b\x66\xdc\x46\xc1\x46\x5b\xfd\x56\xa0\x43\xb8\xfd\xb7\xf7\x2a\x82\x6f\x7b\x9a\x30\x66\x33\x3a\xe7\xb2\x54\xd8\xdb\x48\x72\xe4\x7e\x02\xde\xb0\x90\x65\xb0\x77\x61\x31\xcc\xb0\x3a\xbd\x02\x4e\x1f\xaa\x1f\x41\x15\x48\xa5\x37\x4d\x0c\xd9\x67\xae\xcd\xf2\x5a\x3c\x88\x7c\x1a\xbc\x43\xe1\xcd\x5c\x17\x96\x2d\x74\xae\x6a\x57\xeb\x57\x97\x57\xe6\xb7\xf0\xd3\x17\x54\xd3\x6e\x6b\x76\xd7\x27\x13\x81\x7e\x86\xe2\x4f\xb8\x09\xcb\x78\xb2\xe8\x5c\xee\xad\xd1\xdb\x13\x6d\x1d\xee\xd0\xec\x7b\xf2\x35\xd5\x2c\x25\xef\xa9\xa0\x53\xd4\xf7\x4e\x6e\x6f\xbe\x7e\x7f\x6a\xf7\x15\xf4\xc9\xeb\xcb\x95\x17\x6d\xb7\xf1\xe0\x1f\x0e\x19\x2f\xb2\xb4\xf0\x1d\x58\xd5\x52\xff\x1d\x17\x7f\xd0\x40\x18\x12\xf8\x50\xbb\x64\xbd\x2b\x58\xd0\x4d\x33\x84\xb5\x59\xf3\xb3\x41\x60\xe6\x79\xba\x67\x95\x4f\x2e\xb4\xa1\x59\x76\x93\x51\x71\x5e\x14\x4a\xce\x57\x6b\xe3\xb5\xb9\xfa\x86\x7e\xa6\xe8\xe6\xe1\x5f\x16\x08\x7a\xb8\xc2\x16\xe4\xba\x1a\x7f\x44\xae\x4d\xd0\xc2\xa5\x00\x96\x7a\x74\x5e\x1a\x99\x53\xc3\x93\x23\xab\xac\x1f\xbd\xa7\xa2\xa4\xd9\x4a\xa7\xab\x8d\xcb\x58\x27\x22\x6e\xec\xb4\x3e\x75\x5d\x8b\x6e\x1b\x65\x8d\xcd\xfd\x0d\x55\x96\x3a\x5d\xdc\x7e\xdf\xa9\xaf\x36\xd4\x94\x4b\x54\x78\x03\x67\x58\xcf\x0b\x86\x24\xa3\xda\x7c\x2a\x52\x7b\xe8\x1b\xbf\x6e\x22\xf8\x09\x35\x34\x93\xd3\x3f\x31\x9a\xad\xc6\xf0\x1a\x9e\x5c\xc4\xad\xbd\x01\xca\x5d\xf8\x97\xe3\xd0\xf0\x58\x13\x2b\x60\xfb\x18\x78\xc5\x32\x36\xa7\xc2\xf8\xee\x58\x5c\x5d\x1f\xbb\xf5\x03\x16\xf1\xca\xf8\x9a\x32\xc3\x54\xce\x45\x7d\xcc\x5b\x68\x7b\x21\x45\xca\xd1\xec\x08\x06\x35\xec\x51\x1f\x77\x3d\xaa\xad\xbb\x69\xd8\x70\xb7\x50\xcf\xae\x19\xcd\xa7\x0e\x0a\x6c\x36\x76\xf2\xe5\x0c\x5f\xc2\x4d\x7b\x6d\x6e\x4b\x90\x22\xf7\xc2\x0a\x86\x90\x47\x64\x35\xd9\xda\x2a\x27\x6c\x93\x0f\x86\x7e\x8f\x71\x0a\xeb\x1d\x47\x87\x6e\xde\xeb\xee\x20\x36\xa1\x18\x3e\xdb\x25\x8b\xe6\x54\xd6\xd3\xd4\x55\x78\x17\xba\x61\x24\x4b\xa3\x20\x7f\xad\xd1\x7a\x1e\xd0\x4a\xf0\x6a\x27\x23\xb5\xcd\x6a\x5f\xa7\xb5\x55\x0e\xf6\x25\x55\xb6\x85\xc4\xb8\x95\x69\xb5\x4c\x2e\x5f\x57\xac\xaf\x9d\xff\x9f\x72\xaa\x08\x25\x05\x67\x98\xfc\x84\x0a\x07\x2c\xe0\x2c\x8c\xa6\xee\xa5\xe5\x60\x56\x25\x84\xdf\x06\xee\x32\x1c\x8d\xcb\xce\xd7\xc2\x1b\xa8\x29\x26\xff\x80\x8b\x8b\xb3\x6f\xa4\x33\xf2\xba\x20\x5d\x4b\x03\x80\x93\x0f\x88\x2e\x93\x19\xa1\xda\x4e\xcd\x22\xb4\x3d\xf1\x6c\x94\x53\xc1\x27\x4c\x9b\x51\xc8\x12\xac\xff\xfc\xeb\xbf\x8c\xc8\x5b\xa9\x88\x73\x54\x1f\xf8\xac\x1a\x6e\x9e\x15\x5e\x70\x8d\x8b\x09\x7d\x2b\xad\xb5\x90\xa9\x9b\xf4\x03\x4c\xd6\xd0\x7b\xcb\xc3\x70\xb2\x25\x83\xab\x8b\x37\xe4\xc8\x8a\x89\xd1\xa7\xff\x61\xd9\xd2\xbf\x8e\xc8\xc9\x03\x30\xed\x23\xfb\xe7\x11\x7e\x30\xb8\x4d\xc6\x4a\x75\xf5\x61\x0c\x96\x54\x7c\x3a\x65\x0a\xd5\x47\x02\x41\x85\xa7\x2e\x2b\x88\x90\x51\x63\x7f\x29\x5d\xa9\x9b\xcd\x89\xfc\xf9\xd7\x7f\x39\x22\x27\xf5\x75\x11\x2e\x52\xf6\x99\xfc\x1a\xad\xcb\x5c\xdb\x35\x9e\xba\xcb\x1c\xbd\x10\x86\x7e\xb6\x63\x26\x33\xa9\x99\x40\x55\xde\x48\x32\xa3\x73\x46\xb4\xb4\x1a\x30\xcb\xb2\xa1\xb3\xa5\x93\x07\x0a\x99\x5a\x3c\x28\x21\xb0\x9e\x14\x54\x99\x1a\x4a\x8c\x9c\x85\x04\xbe\x66\xb7\x6d\x2a\xfc\xcd\xf4\x84\x0b\x77\x7f\xe5\x6e\xce\xec\x9e\x43\x60\x28\x6e\x92\x91\x24\x99\x51\x31\x0d\xb1\xe9\x93\xd2\x94\x8a\x6d\xb9\xfa\x69\x79\x06\xee\xb9\xe8\x14\xc2\xfc\x2d\x17\x4d\xa7\x82\xd5\x76\xa5\x29\x37\x3e\x2a\xc2\xf9\x2a\x9a\xc5\x99\xdd\x05\xc5\xc7\xa5\x91\x4a\x9f\xa5\x6c\xce\xb2\x33\xcd\xa7\x43\xaa\x92\x19\x37\x2c\xb1\xcb\x3a\xa3\x05\x1f\x26\x52\xd8\x1d\x87\xac\x0c\x79\xfa\x0b\x28\x6f\x3a\xb4\x53\xdd\x92\x75\xba\xe5\xa2\xb7\x1b\xd5\x9e\xd5\x98\x76\xb0\x35\xb6\xb0\x07\x2d\x2f\x14\x6d\x33\x4f\xb0\x5a\x30\x84\x9c\x1d\x64\xb1\x3e\x69\x72\x77\x1e\x73\xec\xf2\x80\x27\xcd\x31\xec\xb1\x43\x07\x12\x38\x95\x35\x4a\x99\xd3\x14\x49\x29\x15\x8b\x47\x47\x7e\x0b\x52\x48\x97\x9f\x2c\x86\x30\x84\xcc\x86\x54\xa4\xf6\xdf\x18\xb0\x93\x2c\x0e\x02\xc3\x92\x77\x22\x04\x9f\xae\x2f\x9f\xe6\x48\x94\xfc\x00\xa7\xde\xc9\x6b\x2d\x85\x28\x14\x55\xd1\x51\x43\x95\xcc\x33\xcd\xba\x80\xca\xb5\x1f\xf5\x3f\xdc\xfd\x4b\xc8\x76\xb6\x4d\xa4\xda\x7c\x6b\x12\xc9\x8e\x2d\xe7\xfb\xae\xea\x11\xdb\xe4\xc0\xf1\x8a\x6a\xe3\x52\x6b\xf9\x1c\x04\xb5\x65\x78\x05\x05\x18\xcc\xfa\x8b\xe1\x56\x38\xe4\xfd\x05\xec\x44\x86\x2b\x73\x2e\x25\x41\x29\xd9\xae\x40\x55\xfa\x4b\xad\x0e\x1a\x2e\xca\x30\x6d\x08\x9d\x53\x9e\x81\x75\x5e\x8e\x35\x53\x73\x2c\x48\xe5\x52\x0d\xd2\xa6\x9e\xe5\x6a\x4e\xa0\x18\xf5\x44\x9a\x8f\x5f\xc3\xf2\xae\x6c\x5a\x00\x68\x43\x8d\xd9\xaf\x9d\xf5\x41\xf4\x1e\x54\x2f\xd7\xfe\x6c\xbf\xb0\xa3\x1a\x63\xf1\xef\x4f\x8c\x2a\x33\x66\xd4\xdc\xf1\x4d\x7c\x77\x09\xa5\x6b\xfd\x42\x29\xf7\x80\xd0\x0f\x8c\x4c\xa5\xb1\x22\x56\x09\xb8\x8f\x32\x29\x26\xf5\x09\x88\xf6\xd8\x18\x5d\xad\xf2\x4e\x51\x08\xf1\x91\xa2\xe3\x32\xeb\x1d\x97\xd7\xe9\xa4\x63\x87\x49\x06\x5b\x63\x22\x0d\x29\x98\xdb\x3b\xbc\xcd\x00\x0a\xf4\x34\x4b\xce\x99\xd6\x1b\x13\x6c\xd4\xbd\x0b\xb1\x35\x1e\xe5\xc6\xd5\x5a\xee\x7f\xc3\xb0\x10\x2b\x40\xa7\xcc\x50\x9e\xf9\xa3\x8c\xa0\x08\x50\xda\x46\x5d\x37\x2e\x50\x31\xaa\x37\x09\x08\xb5\x59\x7f\x84\xc6\x38\x69\x29\xd8\xf0\x41\xaa\x94\x5c\xd0\x9c\x65\x17\x54\x33\x37\x56\x1c\xa2\x87\x7b\x74\xac\x0f\x3a\xe5\xd5\xb6\xaf\x35\x53\x46\xe3\x4f\x65\x12\x86\xbf\x2a\x15\x0b\x27\x38\xf0\x26\xc8\x3b\x55\xb2\x01\x79\x6b\xb9\xd7\x80\x7c\x12\xf7\x42\x3e\xec\x37\x57\xb3\xf1\x16\xa4\x36\xd3\xd8\xfd\xc3\xa7\xd5\xa9\x19\x7c\xc2\x74\x77\x9c\x91\x23\xf8\x6b\x4c\x8d\x75\x66\x13\x9a\xfa\x19\xd9\x7f\x2e\x99\xa0\xac\xa2\xa8\xe4\x54\x31\x8d\x99\x6b\x56\x26\x49\x6c\x6b\x72\xfe\x86\x09\x17\xdc\xb7\x75\x7a\xd7\xab\x7a\xf9\x99\x7a\xbe\x36\xad\x7e\x71\xfb\xed\x3e\x56\x64\x2b\x45\x8d\xcd\x1e\x81\xd1\x44\xd7\x18\x9f\xd6\xcd\x70\xb5\xd1\x29\xe2\x7a\x51\x5b\x14\x4a\x36\x59\x47\xfd\xea\x2e\x6e\xbf\x5f\x0f\xec\xb5\xbc\x6f\x1b\x7f\xda\x6e\x96\xda\xd7\x20\xb5\xf5\xcc\x6c\x35\x42\xf5\xe6\xa7\xde\xfc\xf4\x25\x99\x9f\xb6\x62\xfc\x26\x93\xd3\x97\x61\x6c\xda\xba\xc4\x4d\x06\xa6\x17\x69\x5a\x6a\xb5\xa2\x8d\xe6\xa4\x17\x6b\x48\xda\xba\xb4\x96\xc6\xa3\x9f\x8f\xd9\x68\x2b\xc4\x36\x98\x8a\x5e\xa0\x91\xa8\x8d\x40\xc6\xd2\x36\x62\xe2\x75\xd4\x38\x16\x14\xab\x72\x96\x61\x38\xef\x94\x13\x8b\x33\xbb\x4a\x8b\x56\x80\xdb\x3a\xb7\x63\x37\xb9\xf6\xb2\x97\x13\x18\x5d\xb1\xc7\xa5\xc9\x92\xcb\xab\x9b\x8f\x57\x17\xe7\x77\x57\x97\x4d\xf9\x6e\x15\xa4\xb7\x48\x62\x9b\x6d\x10\xc3\x48\x12\x5b\xd3\xc0\x12\xe4\x35\x3f\x59\x1c\x58\xf3\x53\x59\xf2\x55\xbd\xf6\x97\x0b\xf7\xe2\x72\x7b\xf1\x8f\xed\xa7\xb3\xed\xf1\xfc\x84\x8e\x53\xd4\xf9\x9c\x59\xb9\x67\x26\xb3\x54\x7b\xbf\xd5\xeb\xcb\x10\x49\xc5\x45\x92\x95\xa9\x15\x2e\x3e\x7d\xba\xbe\xd4\x23\x42\xbe\x66\x09\x2d\x35\x58\x61\x52\x29\x8e\x0d\xf9\xee\xc3\xbb\xff\x06\x7f\x6c\x68\x31\x08\x79\x4d\x20\x2b\x2f\xa7\x98\x58\xd8\x60\xba\x36\xf2\x35\x43\x41\x05\xbe\x9c\xd0\xc2\x52\x31\x8d\x95\x2b\x0c\xc8\x22\x33\x96\x15\x96\x62\xde\x33\x52\x65\x50\xb5\x03\x57\x15\xe6\xbd\xfb\xe4\x94\x19\x8c\xba\xda\xe4\x21\xb9\x11\x6a\x5b\x2c\xae\x7b\xd8\x5a\x6b\xea\xa3\xd3\xc6\x1f\xa8\x76\x16\xab\x95\xb3\xdd\xb2\xbf\xdb\xed\x33\xeb\x4d\x1c\x6b\x8c\x1b\x48\x9e\xe1\xaf\xa5\x39\xdb\xc9\x56\x76\x0c\x74\x22\xe1\xa6\xb5\x35\x75\xbd\x1b\xd0\xea\x3a\x00\x4b\xb6\x0c\xd6\x04\x72\xed\xc3\xc1\x23\x3b\x9a\x72\xbb\xb9\x40\x11\x91\xb4\x56\xfb\xd3\xf9\xcf\xd5\xdf\x95\xe3\x50\xfd\xb5\x9a\xaf\xb3\xc8\x90\x7f\xfc\xeb\xab\xff\x3f\x00\x00\xff\xff\x01\xa8\x18\xd1\x2e\x5c\x02\x00") +var _operatorsCoreosCom_subscriptionsYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xbd\x7b\x73\xe3\xb8\x95\x28\xfe\x7f\x3e\x05\xca\x49\x95\xed\xac\x24\x77\x67\x73\x93\xdc\xde\x54\xb6\x3c\xb6\x7b\xe2\x3b\xdd\x3d\xbe\xed\x9e\x99\xda\x5f\x92\xdf\x06\x22\x21\x09\x31\x09\x70\x00\x50\x6e\x25\x9b\xef\x7e\x0b\xe7\xe0\x45\xea\x45\xca\xf2\xa3\x27\xe2\x1f\x33\x6d\x0a\x00\x81\x83\x83\xf3\xc2\x79\xd0\x8a\x7f\xcf\x94\xe6\x52\xbc\x21\xb4\xe2\xec\xb3\x61\xc2\xfe\xa5\x47\x77\xbf\xd3\x23\x2e\xcf\xe6\xaf\x7f\x76\xc7\x45\xfe\x86\x5c\xd4\xda\xc8\xf2\x23\xd3\xb2\x56\x19\xbb\x64\x13\x2e\xb8\xe1\x52\xfc\xac\x64\x86\xe6\xd4\xd0\x37\x3f\x23\x84\x0a\x21\x0d\xb5\xaf\xb5\xfd\x93\x90\x4c\x0a\xa3\x64\x51\x30\x35\x9c\x32\x31\xba\xab\xc7\x6c\x5c\xf3\x22\x67\x0a\x06\xf7\x9f\x9e\xbf\x1a\xfd\xef\xd1\xab\x9f\x11\x92\x29\x06\xdd\x3f\xf1\x92\x69\x43\xcb\xea\x0d\x11\x75\x51\xfc\x8c\x10\x41\x4b\xf6\x86\xe8\x7a\xac\x33\xc5\x2b\xf8\xc4\x48\x56\x4c\x51\x23\x95\x1e\x65\x52\x31\x69\xff\x57\xfe\x4c\x57\x2c\xb3\x1f\x9f\x2a\x59\x57\x6f\xc8\xca\x36\x38\x9c\x9f\x23\x35\x6c\x2a\x15\xf7\x7f\x13\x32\x24\xb2\x28\xe1\xdf\xb8\xf6\xdb\xe4\xab\xf0\xba\xe0\xda\x7c\xb3\xf4\xd3\x3b\xae\x0d\xfc\x5c\x15\xb5\xa2\x45\x6b\xb6\xf0\x8b\x9e\x49\x65\x3e\xc4\x6f\xdb\x6f\xe9\x7a\x9c\xfe\xdb\x35\xe4\x62\x5a\x17\x54\x35\x07\xf9\x19\x21\x3a\x93\x15\x7b\x43\x60\x8c\x8a\x66\x2c\xff\x19\x21\x0e\x8e\x6e\xcc\x21\xa1\x79\x0e\x7b\x43\x8b\x1b\xc5\x85\x61\xea\x42\x16\x75\x29\xc2\x37\x6d\x9b\x9c\x85\x51\xdf\x90\x4f\x33\x46\x2a\x9a\xdd\xd1\x29\xf3\xdf\x1b\xb3\x9c\x18\x19\x3a\x10\xf2\x37\x2d\xc5\x0d\x35\xb3\x37\x64\x64\x41\x3c\xb2\x10\x4c\x7e\xc6\xfd\xb9\xc1\x41\x92\xf7\x66\x61\xa7\xab\x8d\xe2\x62\xba\xe9\xf3\x19\x35\xb4\x90\x53\x82\xf8\x45\x26\x52\x11\x33\x63\xc4\x7e\x8a\x4f\x38\xcb\xfd\xfc\x36\xcc\x08\xbb\x2e\xcd\xe9\xb6\xfd\xba\xf3\x94\x66\x54\x08\x56\x10\x39\x21\x75\x95\x53\xc3\x34\x31\x32\xc2\x67\x33\x78\x5c\xe7\xa5\xd9\x5c\x2c\xbd\x5f\x31\x1d\x6c\x3a\x7f\x4d\x8b\x6a\x46\x5f\xbb\x97\x3a\x9b\xb1\x92\xc6\x3d\x94\x15\x13\xe7\x37\xd7\xdf\xff\xfb\x6d\xeb\x07\xd2\x5c\x4a\x8a\xa2\xe4\x8e\xb1\x4a\xc7\x43\x41\xea\xca\xae\xc9\x2e\x8e\x8c\x17\xc4\x28\x9a\xdd\x71\x31\x85\xa5\x4f\x71\xbd\x17\xb8\x31\x7a\xb4\x34\x65\x39\xfe\x1b\xcb\x4c\xf2\x5a\xb1\x1f\x6b\xae\x58\x9e\x4e\xc5\x42\xd6\x93\x88\xd6\x6b\x0b\xa7\xe4\x55\xa5\xec\xb4\x4c\x72\x0e\xf1\x49\x68\x54\xe3\x7d\x6b\x99\xc7\x16\x16\xd8\x8e\xe4\x96\x3c\xd9\xe9\xcf\x98\x3f\x1c\x2c\x77\x00\xb4\xdb\x69\x66\x5c\x13\xc5\x2a\xc5\x34\x13\x48\xb0\xec\x6b\x2a\xdc\x9a\x46\xe4\x96\x29\xdb\xd1\x1e\xd8\xba\xc8\x2d\x1d\x9b\x33\x65\x88\x62\x99\x9c\x0a\xfe\xf7\x30\x1a\x80\xc8\x7e\xa6\xb0\xf8\x61\x08\x1c\x37\x41\x0b\x32\xa7\x45\xcd\x06\x84\x8a\x9c\x94\x74\x41\x14\xb3\xe3\x92\x5a\x24\x23\x40\x13\x3d\x22\xef\xa5\x62\x84\x8b\x89\x7c\x43\x66\xc6\x54\xfa\xcd\xd9\xd9\x94\x1b\x4f\x81\x33\x59\x96\xb5\xe0\x66\x71\x06\xc4\x94\x8f\x6b\xbb\x71\x67\x39\x9b\xb3\xe2\x4c\xf3\xe9\x90\xaa\x6c\xc6\x0d\xcb\x4c\xad\xd8\x19\xad\xf8\x10\x26\x2b\x90\x44\x96\xf9\xcf\x95\xa3\xd9\xfa\xb8\x05\xbe\x95\xe7\x80\x78\xaa\xb7\x11\xd6\x96\xf8\x11\xae\x09\x75\xdd\x71\x2d\x11\xa4\xf6\x95\x85\xca\xc7\xab\xdb\x4f\xc4\x4f\x00\xc1\x8e\x10\x8e\x4d\x75\x04\xb6\x05\x14\x17\x13\xa6\xb0\xe5\x44\xc9\x12\x46\x61\x22\xaf\x24\x17\x06\xfe\xc8\x0a\xce\x84\xb1\xc7\xb0\xe4\x46\x03\xce\x31\x6d\xec\x3e\x8c\xc8\x05\x30\x20\x32\x66\xee\xc0\xe6\x23\x72\x2d\xc8\x05\x2d\x59\x71\x41\x35\x7b\x74\x50\x5b\x88\xea\xa1\x05\x5f\x77\x60\xa7\xfc\x73\xb9\xc3\xd2\x19\x23\xc4\x33\xb8\xb5\xbb\x93\x1e\xf8\xdb\x8a\x65\xe1\x38\x50\x41\xce\xab\xaa\xe0\x19\x62\xbc\x99\x51\x43\x32\x2a\x2c\xbc\xb8\xd0\x86\x16\x05\xb0\x93\x4e\xb3\x58\x77\xda\x09\x1c\xed\x16\x73\xf0\xaf\x97\x28\x74\xf3\x87\xc0\xd4\x5a\x2d\xd6\x51\x06\xfb\x38\x3a\xbb\xfc\xc3\x06\x90\x13\x94\x4c\x26\x7c\xba\xaa\xdb\x5a\x58\x5e\x40\x17\x90\x69\x28\x17\xda\x0d\x51\x2b\x84\x66\xe4\x54\x96\x77\xd1\x06\xdf\x1e\xad\x9d\xdd\x4a\xc8\x6e\x5b\xb3\x7d\xe8\x04\x24\xb0\xc5\xea\x5f\x5b\xab\xb8\x9e\xc4\xe9\x0d\x88\x9c\x33\xa5\x78\xee\xe8\x63\x25\xf3\x63\x0d\xd4\x2c\xaf\x0b\xa0\xfd\x52\x68\xa3\x28\x87\xa3\x29\x78\x61\x57\x32\xa4\x06\xcf\x03\xd3\xe4\x9e\x17\x05\xf9\xa5\x90\xe6\x97\x61\x24\x18\x48\x2a\x3e\xe5\x81\xf4\x69\xc2\x85\x1f\x1f\x38\xa2\x63\xe9\x52\xb3\xd6\x80\x23\xf2\x9d\x66\x84\x95\x95\x59\x78\xe2\x70\xf2\x8f\x7f\x9e\x5a\xc2\xca\x14\xd5\xc9\xc0\x8d\x7e\x9e\x7c\xae\x59\xff\x16\xf0\x76\x01\xb1\x7d\x84\xcc\xd9\xf9\x16\x50\x2f\x81\xfb\x92\xa1\x84\xa0\xa1\x7b\xd8\xaa\x14\xc8\xaa\x2e\x98\x0e\x52\x8e\x85\xd1\x86\xc1\x3b\xac\xa5\xeb\x7a\xb0\x1d\x9b\x30\xa5\x58\x7e\x59\xdb\xa3\x71\x1b\x66\x75\x3d\x15\x32\xbc\xbe\xfa\xcc\xb2\xda\xac\xe0\xba\x1b\x97\x6e\xe5\x26\xb7\x4c\xa6\x10\x55\xf0\x73\x20\x3a\xb9\x1f\xec\x7a\x81\x71\x5a\xf0\x68\xa4\x43\x9a\x1a\xae\x27\x0b\x00\x47\x00\x18\xfb\x6c\x99\x04\xc8\xb6\xc9\xf9\xb2\x82\x0a\xf0\x07\xce\x8a\x7c\x40\xc6\xb5\x21\xdc\x00\xf3\xc8\x66\xd2\xe2\x17\x45\xb8\xc3\xb8\x73\x2e\x81\x35\x13\x29\x2c\x26\x91\xd2\x72\x00\x10\x01\x58\x3a\xfc\x08\x66\x1e\xbb\x71\x4d\x4a\xa9\x4d\x84\x95\x7d\x03\x58\x2e\x18\xb9\xe7\x66\x06\x7f\x4c\xad\xba\x62\xd9\xbe\xae\x4b\x3b\xe8\x3d\xe3\xd3\x99\xd1\x03\xc2\x47\x6c\x04\xbb\xcb\x68\x36\x4b\x86\x2d\x19\x33\x9a\xd0\xa2\xf0\x53\x48\x51\x02\xe9\x69\x69\x79\x22\x39\x09\x4c\xd3\x31\xb8\x41\xa0\xb7\xed\x5d\x5b\x09\xae\x01\x61\x26\x1b\x9d\x0e\x48\x26\xcb\xca\x9e\x16\x0a\x73\x1c\x2f\x08\x37\x56\xf6\x43\x06\xad\x64\x3d\xc5\x95\xb0\xc2\x7d\xd8\x4b\x47\x00\x5c\x10\x5f\xac\x36\x21\xa6\xe4\x08\x17\x77\xe4\x05\x1e\x3b\x1c\xc7\x45\xc0\xfa\x4a\x6a\xb2\x99\xa3\x29\x99\x54\x8a\xe9\x4a\x0a\xe8\x09\xbf\x5c\xc5\xb9\xfd\x47\xe8\x74\xa2\x4f\x23\x30\x67\x7c\x3a\xf3\xb0\xa4\x0a\x69\x4a\x73\x0f\x36\x9d\x91\x78\x4e\xa8\x52\x74\xb1\xa5\x25\x37\xac\xdc\x72\x4a\x96\x50\xfb\x5c\x38\x22\x15\x71\x22\xd9\x3d\xc3\x54\x19\x60\x00\x1b\x0c\xc7\x55\xe3\xfa\x78\x69\xd9\x2e\x37\x0e\x43\xc8\x2b\x72\x02\x28\xc2\xcd\xb1\x06\x74\x1d\xca\xea\x74\x44\xce\x41\xdb\xed\xf0\x01\x21\xc3\xf8\x6e\x20\xfb\x51\x2d\xe3\x58\x5b\xd7\xd6\x91\xa8\xe0\xb3\x9e\xd7\x2f\x3f\x43\x37\x7f\x26\x56\xb0\xfa\x55\xcd\x11\x26\x5b\x9b\x76\x25\x6f\xbe\xb5\x9f\x43\x97\xd6\xed\xad\x46\x94\xd6\xac\x60\x99\xb1\x34\x9a\xa9\x72\x40\xa8\xd6\x32\xe3\x56\xac\x8c\x48\xdb\xc4\x74\x5c\xc9\x76\xd8\x93\xbe\xf0\x27\xbd\xd7\x6f\x9f\xf6\xc1\xeb\xda\x6f\x09\x1a\x05\xd7\xc6\x52\x86\x26\x54\x1a\x04\x6b\xbc\x80\x5f\x8f\x35\x29\xe8\x98\x15\x6b\xf9\xf2\xf2\xd3\xfd\xd4\xc6\xa7\xe3\xf9\x5d\xbb\xa0\xb5\x0b\x71\x4a\x4d\xd8\x78\x10\x91\xbd\xc0\x87\x12\xc7\x80\x50\x72\xc7\x16\xa8\xdb\x59\x95\xd1\x29\xd3\xd8\x58\x31\x64\x37\x16\x39\xee\xd8\x02\x1a\x6d\x96\x54\xd6\xc3\xa4\x07\x72\xe0\xd3\xe7\x98\xc6\x67\x68\x27\xda\xb3\x87\x5f\x74\x8f\x6e\xfd\xf1\x17\x9f\x3b\xb6\x51\xf2\x5a\xf5\x2c\x89\x24\x80\x93\xb0\x1f\xb0\x49\xc0\xbf\xfc\x1e\x53\xab\x12\x81\xad\xa3\xcf\x0e\x91\x6d\x0a\xc6\xa6\xc7\x43\xef\x41\xeb\xfa\x18\x34\x68\x44\xc8\x63\x8d\xc8\x67\x4f\xfa\x8c\x83\x5d\xc7\x62\x32\x1c\x5c\x6f\x6a\xf8\x9e\x16\x3c\x4f\xcc\x3f\x96\xcf\x5e\x8b\x01\xf9\x20\x8d\xfd\xdf\xd5\x67\xae\xad\xf8\x72\x29\x99\xfe\x20\x0d\xfc\x39\x22\x5f\x1b\xc4\xf5\x77\x1d\x29\xdb\x1e\x00\x84\xf3\x7d\x10\x78\xce\x05\xd2\x14\xbb\xfc\xd4\x48\xa1\x47\x56\x1d\x02\x51\xce\x1f\x5c\xae\xc9\xb5\xb0\xc2\xa1\x03\x03\x98\x8d\x50\x89\xc1\x21\xca\x5a\x83\x55\x41\x48\x31\x04\x19\x60\xe5\x18\x08\x3d\x3b\x4e\x0a\xbf\x0d\xc3\xad\x1f\xea\x6b\x63\x87\x79\xb7\xb6\xf3\x8c\xce\x41\xa4\xe3\x62\x5a\x04\xe1\x6d\x40\xee\x67\x3c\x9b\xa1\xd4\x0d\x3a\xbd\x61\xaa\x52\xcc\x32\x2c\x0a\xda\xbf\x7d\x33\x65\xca\x0a\xbb\xdc\x8f\x87\x96\xb0\x82\x66\x2c\x27\x39\x88\x96\x68\xd5\xa1\x86\x4d\x79\x46\x4a\xa6\xa6\x8c\x54\x96\x93\xec\xb6\xfb\xfd\x08\x3b\x3e\xbd\xc9\x7b\xfa\xc1\x5e\xe8\x06\x2c\xf2\xad\x95\x75\x9f\x88\x3b\x82\x5c\x7d\xe0\x8e\x07\xee\xd8\x7a\x0e\xdc\x31\x3c\x07\xee\xb8\xe5\x39\x70\xc7\x03\x77\x7c\x74\xee\x88\xba\xec\x0e\xca\xf3\x0f\x68\xe2\x68\x6b\xcb\xc0\x69\xfd\xbd\x50\x53\x6d\xb6\xfc\xe6\xd6\x11\x9c\x4f\xa0\x6a\x3b\xdb\xb1\xa2\x62\xca\xc8\xeb\xe1\xeb\x57\xaf\xfa\x28\xd5\x6e\x23\x3b\xf5\x98\x48\x55\x52\x03\x7d\xfe\xfd\x57\x1b\x7b\xac\xb3\xbf\xed\xc1\x6a\xea\x70\x3c\x18\xf2\x1a\xb2\xc3\x1a\xc3\x27\x50\x27\x21\x0d\x29\x99\x21\xd4\x34\x4c\x45\xbc\x64\x03\x6f\x58\x46\x84\x77\xd7\x62\xde\x02\x9b\x13\x29\x9c\x1d\xcf\x02\x7f\xb4\xdb\x0c\x32\x46\x35\xb3\x94\x74\xcc\xc2\x2c\x64\x69\xbf\xca\x85\xf1\xc7\xc5\x4e\x81\x79\xa8\x90\x13\x36\x9a\x8e\x48\x5e\x43\x37\x2a\xdc\x3d\xdd\x29\xce\x56\x2f\xb4\x61\x25\x58\x72\xa5\x82\xff\xd9\x69\x1b\xb5\x80\xbb\x80\x39\x13\xa6\xa6\x45\xb1\x20\x6c\xce\x33\x13\xd6\x07\xd7\x84\xdc\xa0\xb1\xbd\x9b\x89\xb0\x93\xe8\xd0\x5d\x5c\x18\x2e\x61\xb0\xde\xd2\xa7\x0f\xb7\x5f\x1a\xbb\xcb\x99\x6c\xf1\x42\x5c\xc9\x68\xad\xb0\x6a\xec\xb8\x68\x03\x87\x7f\x02\x72\x7d\xfb\x71\xbb\xc9\x95\xf4\xa6\x64\x3d\xa8\x57\x5b\x2c\xad\x8b\xc2\x22\x06\x5a\x61\x97\x17\xb0\xc2\x3a\x8a\x4b\x6a\x20\x33\x1a\xde\xd1\xc4\x7c\xfe\xe1\xd2\x42\xc5\xb6\xf9\x24\x2b\x59\xc8\xe9\x22\x85\x34\xac\x0c\x6c\xb7\xae\x2f\xde\xea\xa1\xd0\x60\xd1\xef\x43\x6b\x6b\x0e\x96\xbf\x83\xe5\xef\xa0\xdb\x2c\x3d\x07\xdd\x26\x3c\x07\xdd\x66\xcb\x73\xd0\x6d\x0e\xba\xcd\xc1\xf2\x47\x0e\xdc\x71\x03\x4c\x0e\xdc\x91\x1c\xb8\xe3\xda\x75\x1d\xb8\xe3\x46\xf0\x1c\xb8\xe3\x81\x3b\xae\x7a\x2a\x99\x3f\xc0\xd1\xb1\x92\xf9\x06\x3f\x47\xb4\xfa\x64\x72\x58\xc8\x8c\x1a\xe7\x08\x6e\xbb\x38\x3b\x9f\xa6\x25\x1a\xa2\x06\xe4\xef\x52\x30\x74\x5e\xb3\x7b\x03\xe6\x24\x69\x66\x4c\xd9\xe6\x27\xfa\x74\xa3\x63\xd3\xc1\x4f\xf2\xe0\x27\xf9\xe2\xfd\x24\x67\x54\xe3\xbe\x22\x51\x5a\xef\x36\x99\x1c\xc8\x4f\x4c\x95\x5f\xa8\xd7\xa4\x45\x17\xb7\xdd\x10\x62\x13\xb7\x14\x57\x9e\xbb\xfb\x02\x96\xdf\x34\xd7\xeb\xe4\x65\x58\x14\xcd\x73\x96\x93\x8a\xa9\x21\xa2\x88\x24\x13\x2e\xf2\x15\x6b\xf5\xf0\x79\x56\xef\xc7\xe6\x3a\x9e\xd1\x05\xb2\x39\x91\x1d\x6c\xae\xa9\xe1\xb8\x41\xe1\x5f\x84\x43\x64\x5f\xa9\x7e\x48\x8c\x33\xf2\x7e\xd3\x51\xae\xef\x2f\x9a\x83\x40\xed\x4d\xc2\xbb\xeb\x95\x20\x96\xff\x58\x33\xb5\x80\x18\x8b\x28\xb0\x86\x60\x2e\x77\x47\xc6\x35\xc9\xa8\x46\x4e\xd1\x57\xb5\xec\xa9\x46\xed\xa6\xa7\xec\x6e\x89\x26\x6d\xb8\xb4\x87\x42\x9d\xd4\xeb\xe0\x08\xb3\x95\x4a\xf8\x8a\x5b\x80\x68\xfd\xef\x35\x9f\x5d\x45\xb7\x9d\x04\xb7\x95\x48\xf1\x82\x95\x73\xb2\xbb\x82\x4e\x76\x56\xd2\xc9\x4e\x8a\x3a\xd9\x55\x59\x27\x0f\x50\xd8\xc9\x6e\x4a\x3b\x69\xa3\x82\xdd\x21\x27\x65\x3d\x8e\xfe\x4e\x1e\xa2\xa2\x92\x07\xe8\xf1\xa4\xbd\xd4\x80\xa6\xea\xb1\x94\x7a\xc0\xf5\x86\x5e\xff\xd4\xc0\xda\x4d\xa7\x27\x6d\x50\xf9\xa8\x3b\x50\x68\xbf\x10\x0d\xff\x49\xd4\x6d\xf2\x20\x95\x9b\xec\xae\x76\x93\xdd\x31\x03\x58\xdd\x3b\xb8\x4e\x7d\x28\xc3\xc4\x51\x90\x45\x94\xb4\xb2\x48\xf1\x0f\xcb\x09\x60\x5f\xfe\x49\x2a\xca\x95\xb6\xf2\x9d\xb3\x99\xa4\xbf\x39\xed\x3c\x1d\xc6\x8e\xc0\x35\xb1\xa4\x7a\x4e\x0b\xcb\x7b\xd0\x8f\xc3\xe9\x45\x76\xf4\x36\x9b\x1e\x90\x7b\x88\xfa\xb4\x54\x0a\xb5\x25\xae\xc9\xd1\x1d\x5b\x1c\x0d\x96\x10\xe9\xe8\x5a\x1c\x21\x8f\x5a\x42\x9d\xc0\xd0\xa4\x28\x16\xe4\x08\x7e\x3b\xda\x37\x67\xdf\x81\x71\xa5\xc9\x36\x76\xe5\x0b\x3b\x60\x89\xf0\xb1\xd2\xfb\x17\x36\x91\x8b\xe0\xc5\x86\xff\x8a\x8e\x0c\x06\x5c\x2d\x12\xe6\x12\xbc\x46\x00\xc7\xe0\x7d\xee\x95\xdf\x5a\xb8\xd4\x0a\xa0\xbb\xc6\xc1\x90\x49\x2d\xbb\x34\xb9\x8d\x97\x82\x69\x10\xec\x58\x30\x11\x25\x9d\xa1\xed\x08\xdd\x41\x22\xb7\x13\x79\xdb\x41\x24\xf6\x00\x19\xb1\x64\x54\x68\x72\xe4\x6d\x4f\xc7\x3a\xb6\x38\x1a\xc5\xe8\xbe\x30\x22\x04\x21\xa7\x11\x7d\x71\xc0\x83\xa4\x7d\x90\xb4\x0f\x92\x76\x8f\x5e\x07\x49\x7b\xfd\x73\x90\xb4\x7b\x3c\x07\x49\xfb\x20\x69\x6f\xfa\xf0\x41\xd2\x3e\x48\xda\xdb\x3f\xbe\x9b\xa4\xbd\xab\x9f\x50\x2a\xf7\xba\xcb\x39\xcc\x9c\x45\x0d\xcf\xa2\x0f\x91\x6f\x85\xff\xda\xaf\xbc\x9d\xca\xd2\xab\xa5\xed\x54\x22\x5f\xd2\x2d\x46\x5b\x44\xeb\x20\x7c\x2f\xf5\xdc\x2c\x75\xbf\x2c\x5f\xa8\x1d\x70\x23\xb9\x50\xd8\x11\x39\x3e\xf9\xab\x70\x97\x69\x6e\xcc\xe2\x3d\x79\x4e\x4e\xfc\x8d\xcb\xa9\x05\xbe\x90\xa6\xf9\xa3\x30\x7c\x18\x5b\x84\x3b\x18\xb8\x5e\x6c\xc4\xdb\x34\xae\x25\xc2\xad\x7b\xb8\x29\x8e\xfb\x69\x49\x08\x53\x8d\x39\x70\xed\x12\x88\x81\xb7\x84\xaa\x85\xb0\xa3\x4a\xe1\xaf\x8f\x91\xe6\x60\x02\x38\x87\x79\x28\x2c\xc1\x7c\x40\x62\x8a\x50\x4a\xee\x3b\xa9\xc1\x9c\x7b\xce\x95\x5f\x0a\x77\x23\x6a\xdf\xf8\x5b\x5f\x8f\x94\xb0\x22\x1e\xbe\x3e\x22\x57\x80\x87\xe9\xc0\x5c\x03\x7c\x68\x51\xc8\xfb\x3e\x24\xe9\xa9\xc2\xa2\xee\x7b\x87\x45\xb5\xee\xef\x0e\x51\x51\xff\x22\x51\x51\xf0\x23\x1e\xa1\xbd\x87\x47\x91\x1f\x66\x0c\xb0\x48\x31\x00\x55\x59\x17\x86\x57\xd1\x57\x4a\xe3\xa7\x0a\x94\x32\x27\xce\xf3\xa4\x89\x97\xf6\x6b\x34\x9b\xb5\xf1\x13\xc6\x03\xdf\x2a\x0d\x87\xd6\x79\x77\xd0\xa2\x70\x31\x45\x5e\x24\x45\x17\x16\xfe\xdc\x9e\x09\x97\x3e\x2b\xa2\xd7\x66\x80\xc8\x9c\x58\x5a\x58\x2c\x5c\xa6\xba\x0d\x44\x14\x95\xa2\x39\xf3\xac\x77\xca\xe7\x4c\x44\x4a\x7a\xa2\x4f\x4f\x3d\x0f\xdf\x2b\x85\x7f\x14\x0a\xfd\xfb\x84\x92\xfe\xa1\x0b\x8d\x86\x05\x05\x2a\x1d\xc1\x17\x69\xf4\x73\xba\x60\xf4\xb9\xe7\xef\x67\x63\xd8\xe1\x7e\xff\x09\xef\xf6\xbf\x9c\xc8\xb2\x67\xb6\x30\x3e\x87\x6f\xfd\x8b\xb7\x2a\x1e\x9c\xeb\xe3\xf3\x50\xe7\xfa\x47\xb7\x1c\x3e\xaf\x8f\xfd\x17\x60\x2d\x7c\x4e\x1f\xfb\x83\x85\x70\xe3\xa6\xbc\x34\xd7\xf7\xe6\xb3\x93\x45\xf0\x60\x0d\xdc\x99\x0b\xf7\x64\x38\x0f\xb5\x02\xf6\xc4\x88\x1d\xef\xd9\x0f\x77\xec\x4f\x73\xc7\x7e\x90\x78\x3b\x3e\x07\x89\x77\x2d\x50\x0e\x12\x2f\x39\x48\xbc\xdb\x96\x77\x90\x78\x37\x82\xe7\x20\xf1\x6e\xdc\x94\x83\xc4\x7b\x90\x78\xc9\x97\x26\xf1\xee\x92\xa5\xeb\x70\xd7\xfd\xa0\xbb\xee\xbe\xd4\xa2\x17\x8d\xe8\x89\x07\xbd\xef\xb6\x0f\xf7\xda\x2f\xe5\x5e\xbb\x73\xc0\xbf\x30\xfc\xa1\x41\xff\xe9\x5e\xad\x8b\xfc\xa7\x73\xc9\x73\x52\xd5\xc6\xc5\x53\x1f\xa2\xff\xf7\x11\xfd\xdf\x80\xfc\x21\x05\x40\xa7\x14\x00\xeb\x60\x76\xc8\x03\x70\xc8\x03\xb0\xe7\x4b\xe8\x43\x1e\x80\x43\x1e\x80\x43\x1e\x00\xff\x1c\xa2\x93\xc8\x21\x3a\xa9\xd3\x73\x88\x4e\x5a\xff\x1c\xa2\x93\x5e\xac\xf5\x95\x1c\xa2\x93\x5e\xb6\x25\x96\x1c\xa2\x93\x0e\xd6\xd9\x8e\x1b\xf5\x05\x46\x27\x1d\xf2\x00\xbc\x54\x1f\x05\x72\x90\xb4\x0f\x92\xf6\x41\xd2\x3e\x48\xda\x9b\x9f\x83\xa4\xdd\xe3\x39\x48\xda\x07\x49\x7b\xd3\x87\x0f\x92\xf6\x41\xd2\xde\xfe\xf1\x43\x1e\x80\x2f\xc8\x37\x82\x1c\xf2\x00\x1c\xfc\x25\x0e\x79\x00\xfe\x75\xf3\x00\x34\xee\xee\x9f\x2f\x19\x40\xff\x69\x1c\x32\x02\x1c\x32\x02\x1c\x32\x02\x1c\x32\x02\xf8\xe7\x90\x11\x00\x9f\x97\x64\x6b\x3c\xc4\x47\xad\x05\xca\x21\x3e\x8a\x1c\xe2\xa3\xb6\x2d\xef\x0b\xb0\x1b\x1e\xe2\xa3\x5e\xa0\xad\xf0\x10\x1f\x75\xb0\x0b\xb6\x37\xe7\x0b\x89\x8f\x3a\x64\x04\x78\x89\xb7\xed\x07\x89\xb7\xe3\x73\x90\x78\xd7\x02\xe5\x20\xf1\x92\x83\xc4\xbb\x6d\x79\x07\x89\x77\x23\x78\x0e\x12\xef\xc6\x4d\x39\x48\xbc\x07\x89\x97\x7c\x69\x12\xef\x21\x23\xc0\x21\x23\xc0\x21\x23\xc0\x97\x78\xc3\xbd\x75\xa7\x99\x98\xaf\xdb\xd3\xc6\x2e\x5e\x89\x79\x53\x4f\x61\x62\xce\x95\x14\x40\x81\xe7\x54\x71\x3a\x2e\xe0\xa4\x82\xc4\xe3\xe0\xef\xe8\x27\x53\x23\x72\x41\x85\xbb\x68\xc5\x9b\xcc\xb5\xf3\xdf\x8e\xf8\x5b\x50\xbd\x3d\xed\xef\x69\x53\x54\x13\x2b\xa7\x4e\x5c\x03\x3b\x75\x4a\x2e\xc2\xc4\xd7\x7e\xa6\x13\x01\xef\xa2\x1f\x0c\x01\x39\xd7\x36\xe8\x26\xc5\xdb\x21\x36\x9f\xcd\x06\x58\x3e\xd0\x32\x86\xf8\xaf\x80\xc6\x88\xbc\x77\x12\x12\x25\x17\xff\x7d\x7d\x79\xf5\xe1\xd3\xf5\xdb\xeb\xab\x8f\x9b\x91\xae\x23\x59\x81\x83\xd4\x63\xb2\xc7\xdf\xfb\x3d\x82\x30\x6f\x26\x2c\x05\xfe\xc5\xc9\xf7\xe7\x1f\xff\xfb\xc3\xf9\xfb\xab\x53\x60\xbf\xec\x73\x45\x45\xce\x72\x52\x6b\x4f\x12\x2a\xc5\xe6\x5c\xd6\xba\x58\x84\xe3\xbd\x1a\x69\xdb\xd8\xea\x14\xcd\x05\xd1\x4c\xcd\x79\xb6\x1a\x44\x28\xc5\xd2\x88\x40\x59\xc0\x70\xc5\xb4\x2c\xe6\x2c\x47\x59\x23\x4c\xda\x7f\x87\x8b\xaa\x36\x5e\x22\x06\x17\x04\x7b\x2a\x44\x36\xa3\x62\xca\xf2\x11\xb9\x94\xb5\x1d\xef\x17\xbf\x80\x85\x29\x96\xd7\x19\xf2\x3a\xea\x05\xa6\x5f\x0c\x3c\x25\xb1\xb4\x40\x63\x1a\x05\x9d\xd1\xca\x2f\x3d\x85\x8e\x5e\x08\x43\x3f\xbf\xc1\x3b\xf8\xa3\x5f\x24\x3f\x1d\xf9\x14\x14\xd2\x7e\x02\xe9\x11\xce\xaa\x80\xec\x07\x05\x39\x4a\x5b\x8f\xc8\x95\xfd\x06\xcb\xd3\x7d\x40\x17\x0a\x36\x67\x0a\xe4\x69\xb7\x0b\x03\xa2\xd8\x94\xaa\xbc\x60\x1a\x9c\x07\xee\x67\x0c\xd2\x79\xa0\x84\xe5\x00\xc6\x82\xb4\x2e\xa4\x19\x91\x4b\x36\xa1\x75\x61\x80\x86\x1c\x1d\x8d\x8e\xf7\x86\x6a\x6f\x95\xdc\x12\xfc\xde\x40\xb7\x5b\x4c\x2a\x31\x91\x6a\xed\xf1\x38\x76\xa6\x89\x06\x59\xd3\x96\x93\x38\x4d\xcf\xd3\x6a\xd4\x2f\x3a\xac\xa4\x83\x20\xd8\x5d\x9d\xcf\xa4\x98\xf0\xe9\x7b\x5a\x7d\xc3\x16\x1f\xd9\xa4\xa7\x37\x04\x32\x51\xa7\xd3\x02\x03\xb3\xe4\x10\x07\xdc\xce\x74\x1e\xf1\x2e\xbf\x8b\xd1\xa4\x9f\xcd\xa3\xb3\xa5\x63\x29\xa5\x05\x32\x7d\xc7\xbe\xf7\x98\x9c\x27\x3e\xdb\x29\xfa\xca\xc9\x1d\xa7\xa4\xdd\x9d\x53\x33\x22\xef\x25\xb8\xe4\x4c\xe4\x1b\x32\x33\xa6\xd2\x6f\xce\xce\xee\xea\x31\x53\x82\x19\xa6\x47\x5c\x9e\xe5\x32\xd3\x67\x99\x14\x19\xab\x8c\x3e\x93\x73\x4b\xf9\xd8\xfd\xd9\xbd\x54\x77\x5c\x4c\x87\x56\xd2\x19\xe2\xae\xea\x33\x10\xa6\xce\x7e\x8e\x12\xfb\xa7\x6f\x2f\xbf\x7d\x43\xce\xf3\xdc\x65\xec\xa9\x35\x9b\xd4\x85\xcb\xde\x31\x22\xb4\xe2\xdf\x33\x65\x95\xb2\x01\xb9\xe3\x22\x1f\x90\x9a\xe7\xff\xb9\xf9\x70\xef\x08\x31\x59\xa1\x6e\xb4\x03\xd4\x6e\x41\x50\x5c\x34\xe8\x54\x40\x7a\x4b\xa1\xb8\xd1\xb0\xe7\xde\x70\xe0\x18\x4a\x8f\x65\x8c\xa5\x2c\x18\x15\x5b\x7a\x00\xd8\xfa\x9f\xd9\xe3\x78\x68\x51\xcb\x71\x08\x50\xc9\xfc\x0d\xd1\x75\x55\x49\x65\x34\x29\x99\xa1\x39\x35\x74\x64\x77\x6e\xd0\xfc\x13\x84\xe3\x01\xf9\x6b\x78\x09\x12\xae\xfe\xd3\xf1\xf1\xef\xbf\xb9\xfa\xaf\x3f\x1c\x1f\xff\xe5\xaf\xe9\xaf\x40\xf6\xd0\xd4\xd5\x6c\x62\x45\xee\x91\x15\x77\x3f\xc0\x37\xe0\x4f\xc7\x46\xcf\xb3\x4c\xd6\xc2\xb8\x1f\x0c\x35\xb5\x1e\xcd\xa4\x36\xd7\x37\xe1\xcf\x4a\xe6\xed\xbf\xf4\x16\x4e\x40\x1e\x97\xe8\x00\x38\x6f\xa8\x99\xed\x99\xf4\xc4\x73\xb1\x03\xba\xba\x9e\x69\x86\xa4\x92\xc2\x3f\xdf\xfa\xe9\x5a\x0e\x74\xaf\xb8\x31\x4c\x80\xdc\x01\x7e\x77\x72\x32\xb0\x98\x1b\xd9\xec\xfc\x75\x2f\x75\xb4\xf3\x51\x0c\x50\xdb\x61\x71\x30\x7b\xb7\x32\x44\xe6\x40\x68\x97\xf5\xba\xf3\x9b\x6b\x32\x47\x68\xec\x7d\x21\xde\x0b\xeb\xed\x83\xcf\x64\xc8\x54\xe5\x96\x15\x24\xcd\x37\x68\x59\x0a\xfe\x5e\xa4\xe0\x25\x77\x06\x60\x97\xd5\x4a\x93\x13\x7c\x39\xca\xaa\x7a\xe0\x1a\x8c\x4a\x56\x4a\xb5\x08\x7f\xb2\x6a\xc6\x4a\x2b\xb1\x0d\xb5\x91\x8a\x4e\xd9\x20\x74\xc7\x6e\xe1\x2f\xec\xd8\xf8\xc0\x72\x6f\x14\xa9\xb3\x5a\x59\xe6\x51\x2c\x3c\x05\x61\xf9\xf3\x9e\x45\x0f\xa6\x3d\x1f\xc5\xb0\x1b\x1f\x76\x64\xb9\x41\x5b\x44\xa6\x1d\x56\x05\x32\xe4\x5c\x16\x75\xc9\xf4\x20\xb0\x27\x94\xd6\xc5\xdc\x4a\x93\xfa\x51\x18\x61\xce\xe7\x5c\xef\x74\x3f\x7d\x1b\x2c\x75\x60\x22\xab\x8d\xd5\x54\xd0\x19\x3c\xc9\x08\x27\x35\xe8\x00\xc1\x47\xb1\x41\x52\x5e\x1f\x75\xbb\x7d\xa5\xc6\x30\x25\xde\x90\xff\xff\xe4\xcf\xff\xf6\x3f\xc3\xd3\xff\x3c\x39\xf9\xd3\xab\xe1\xff\xfe\xcb\xbf\x9d\xfc\x79\x04\xff\xf8\xe5\xe9\x7f\x9e\xfe\x8f\xff\xe3\xdf\x4e\x4f\x4f\x4e\xfe\xf4\xcd\xfb\xaf\x3f\xdd\x5c\xfd\x85\x9f\xfe\xcf\x9f\x44\x5d\xde\xe1\x5f\xff\x73\xf2\x27\x76\xf5\x97\x8e\x83\x9c\x9e\xfe\xe7\x2f\x3a\x4d\x8f\x8a\xc5\xb7\x1d\x0e\x3c\x3e\xc3\x1d\x3c\xec\x63\xaf\x1e\x06\xfa\xcf\xc3\x28\xb4\x0d\xb9\x30\x43\xa9\x86\xd8\xfd\x0d\x31\xaa\xde\x7e\x30\x22\x51\xdb\x05\xcf\x7d\x3a\xb0\x37\x91\xa0\x05\xd2\xbc\x77\x44\xd6\x2c\x53\xcc\xec\x4b\x83\xc1\xd1\x3c\xff\x68\x99\x64\x0f\x4a\x4d\x54\x6a\x82\x5d\x12\xe0\x15\x39\xef\x44\xc9\x72\x44\x12\xb3\xd0\x1c\x6e\x32\x5d\xbb\x3b\xb6\x45\xcb\xf5\xcf\x41\x09\xfa\xb2\x94\xa0\x5b\xdc\xdf\x47\xd7\x80\x98\x98\x6f\x32\xd3\xb4\x6d\xba\x6f\x21\x94\x25\x35\x47\x7b\x01\xca\x48\x52\xc9\xaa\x2e\xa8\x59\x63\xb6\x5b\x61\x9b\x76\xb8\x1f\x6f\x01\xec\x46\x83\x1d\xd8\x51\xb9\x72\xb5\x31\x94\x9c\x17\x05\xe1\x02\x4f\x02\x0c\xe0\xad\x79\x8a\xa1\xbc\x44\x28\x1a\x9c\xe7\x76\x0a\xf7\x2e\xe0\x26\x31\x34\x72\x6d\x75\x1d\x65\xc0\xe2\x0f\x01\x39\x48\xb3\x9c\x69\x8c\x8b\x18\x96\x13\xb8\x6d\xb8\xa5\x5c\x99\x7f\xb1\xa0\xda\xf8\x69\xc3\x6c\x0c\xbd\x03\x53\x68\xc6\x72\x26\x32\x06\x2e\x08\x35\x8b\x6b\x1d\x5b\x61\x10\xcc\xfb\x30\x06\x25\x79\x5d\x15\x3c\xb3\xf0\xb3\x33\x59\x3d\xc6\x75\x59\xd6\x06\x0c\xc5\x4f\x65\xc5\xb7\x3b\x7e\xeb\xd3\xbd\x06\x63\x3e\x90\xaa\x20\x5a\x07\x6f\x8b\xa0\xba\xeb\x87\x99\xef\xbb\x11\xde\x60\x6e\xdb\xca\xa9\x96\x28\x6e\xb4\x31\x34\x29\xed\x53\x5b\x0c\xbb\xd1\xd9\x9f\x24\x8d\xed\x41\x5f\xbb\xd3\xd6\x1e\xc6\xa5\xbe\xf4\xb4\xab\x35\xa9\x52\x6c\xc2\x3f\xf7\xc0\xc7\x73\x11\x55\x14\x9e\x33\x61\xac\x22\x00\x99\xa9\x2b\xc5\x2a\x26\xf2\x10\xee\x07\x0e\x5e\xa2\xb9\x8e\x47\xbd\x31\x42\x29\xa3\xff\xf1\xba\x5d\x25\xc5\x1c\xce\xd6\x4f\xfc\x6c\xb9\x5d\xdf\xff\xc1\x12\x32\xdf\xea\xfc\xdd\xda\xc7\xa4\x47\xcb\xd3\xd5\xa5\xff\x76\x93\xb4\xda\x5b\xb8\x72\xaa\x64\x8e\x39\xae\x4d\x74\x42\x18\x91\xdb\x15\x3d\xc1\xd7\xc0\xb5\x38\x3e\xd6\xe8\x96\xa0\xdb\x03\xb5\xa2\x9b\xd1\x33\x01\x07\xed\x89\x52\xc8\xea\x6a\x05\x96\xdf\x33\xaa\x35\x9f\x8a\x61\x25\x73\xc8\xcb\x7d\xb6\x0e\x21\x3a\x1c\xaa\x7e\x9e\x4d\x5b\xf1\x2a\x18\x27\xba\x6d\xd3\xc7\x60\x7f\x4b\x64\x0b\x9f\x11\x5e\x25\x3f\x3a\xbb\x8e\xf7\xa3\x4f\x64\xc8\x28\x11\x3d\x0c\xa6\x25\x15\x74\xca\x86\xee\xe3\xc3\xf0\xf1\x61\xf8\xd6\x43\xc0\xdc\x85\x6a\x65\x05\xe5\x9b\x5d\x89\x1a\xc0\x3b\xba\x80\xf6\x2e\x50\x3c\x78\x60\xb5\xc2\x58\xbd\xb4\xc9\x05\x5e\x09\xf8\x9f\xb0\xf3\x00\x51\x92\x2a\x77\x8d\xba\x02\xbe\x7f\x16\xe8\x48\xe4\xfc\x4a\x8b\x6a\x46\x13\x87\x2e\xb7\x33\x9a\x30\x41\xc7\x85\xbf\x05\xbf\x5c\x08\x5a\xf2\xcc\xef\xee\x79\x01\x0e\x3f\x5c\x0a\x32\x61\xd4\xd4\x8a\x91\x29\x35\x2c\x8e\x1d\x3c\x05\x79\xdc\xcc\x6b\x43\x32\x2a\xd0\x4c\x3b\xc6\x48\x0d\x7b\xba\xc2\xcc\xf4\x68\x93\xbd\xab\x9b\x17\x57\x07\xdf\xad\x56\x5a\xf6\x04\x78\xe9\x65\xbc\x14\x56\xe9\x31\x0a\xd8\xf3\x8d\xcc\x2d\x75\x1c\x35\x5a\x6f\x71\x8a\xef\xcc\xfe\xba\x1a\x39\xb6\x38\xb7\x90\xc7\xe6\xa4\xc0\x48\x13\x52\xe9\xf1\xd3\xa2\x67\x03\x5a\x95\xcc\x47\x2b\x30\xd3\x33\xe1\x1b\x99\x3b\xbf\x31\xd3\xc0\x14\x8b\xae\x80\x24\x25\xbd\xf3\x3e\x5f\xc1\x38\x46\xe7\x94\x17\xe0\xea\xc0\x85\xe6\xb9\x15\x8d\xb2\xed\x8e\x45\xfe\xe9\xc8\x3c\x1b\x36\x41\x7b\x08\x87\x25\xad\x86\x56\x1b\xdd\x0c\xaa\xad\x3b\xb3\x3c\x30\xce\xa8\xa4\xd5\xda\x5e\x78\x1d\xd1\x99\x76\x1c\xbf\xc3\xeb\x8e\x3c\x94\x96\x41\xdf\xdf\xcf\xbc\xac\x4b\x42\x4b\x59\xa3\x7b\xef\x32\x29\xf6\x4e\x70\x7b\x21\xb6\x2b\x88\xac\x5e\x4b\x65\x49\xf7\x63\xd2\xdf\x5d\xf7\x85\x5a\xc5\x3b\x59\xc3\xfb\x59\xc1\x7b\x58\xbf\x77\xb6\x7a\xfb\x0b\xae\xee\xf8\xf8\xd1\xdf\xb9\xb5\x30\x92\x8b\xad\x18\xa9\x42\xad\x8c\xeb\x09\x09\xe3\x70\x4d\x64\xc9\x8d\x71\x97\x41\x09\x01\x18\x10\x6e\x1a\x37\x27\xee\x2c\x40\xad\x18\x2c\xaf\xc3\x3e\x57\x05\xcf\x38\xdc\xc0\xf9\x1b\xcf\x01\x4a\xe8\xf7\x1c\x33\xcb\x50\x41\x78\x59\xa1\x23\x3c\xe0\xf4\xd0\x73\x5a\xe7\xa0\x14\x66\xe2\xdc\xd3\xd8\xe7\x8c\xb1\xdc\x7d\xec\x70\x7c\x0e\xc7\x67\xf5\xf1\xd1\x7d\xd4\x9c\x54\xc3\x89\xce\xd1\x41\xd3\xb1\x88\xef\x6b\x5a\x81\xf3\x37\xe2\x90\x3d\x2a\x10\x9f\x63\xc5\xb5\x8f\x0c\x8c\x8e\xb7\xcc\x68\xe7\x6e\x0d\x3d\xac\x44\xb8\x14\xbd\xea\x8d\xac\xc1\x8b\x9f\x4e\x26\xcd\x16\x39\xab\x0a\xb9\x28\x41\x69\xbe\x36\x6d\xfe\x0f\x5a\x11\x2b\xab\x82\x1a\x16\x74\xa6\xcd\x86\xcc\x07\x0b\xd5\x7d\x42\x47\x9f\x37\x58\xf4\x71\x44\xd6\x17\x19\x02\xfa\x08\xd2\xee\xf6\xeb\xbc\x8e\xa1\x9c\xdd\xa5\xe2\x4e\xf7\x7d\x8f\x1d\xa0\xd9\xcb\xd2\xd3\x35\x08\xf3\xe5\x87\x5d\xf6\x58\x76\xd7\xd0\xca\x43\x30\xe5\x26\x50\x77\x0b\x88\xea\x1c\x0c\xd5\x69\xff\x3a\x06\x45\x1e\xc2\x20\x7b\xf0\x97\x47\x10\xfe\xb6\xee\xa5\x91\x05\x43\xc9\xb5\x9b\x59\xf0\x53\x6c\x1f\x4a\x2b\xa2\xe7\x48\x32\xd2\xd3\x5c\x80\x7e\xf2\x62\x8b\x3d\x5b\x71\x5e\x80\x5a\xc6\x50\xa8\xa3\x68\xa4\x9f\x97\xdd\x38\xb1\x20\x76\xcf\x8c\x2b\xaa\x99\x54\x99\x34\x0a\xee\x93\x7f\x1f\xb0\x6d\xc0\x40\x7e\xfa\x43\x12\x3a\x13\x42\xeb\x02\x86\xfc\xde\xff\xeb\x0f\x0f\x0c\x89\xea\xc6\xd8\x70\x4a\x3d\x04\x8c\x2b\xe8\x40\xb8\xc8\xe1\xee\xda\x2d\x15\x20\x80\x63\x59\xf8\xc0\xb2\x7c\x68\x1d\xc6\x68\x3a\x0b\x3a\x5c\x72\xc7\xc6\xda\xdd\xc6\x27\x6a\x97\xb3\x38\xc4\x93\xc1\xc8\x07\xe9\xf2\x9d\xb2\x01\xb9\x01\x33\x5c\x7c\x03\x27\xe9\x83\xc4\xcc\xa7\x6b\xaf\xc9\x53\xb8\x6d\xe5\x22\x5b\x19\x7d\x03\x20\xdf\x44\x26\x8f\x2b\x6b\x30\xf9\x88\xc1\x8d\x20\xdb\x4d\x90\xb9\x63\x8b\xc8\x6c\x9c\x08\x01\x24\x7f\x10\xb1\xc4\xb3\x02\xe4\x1d\xff\xe1\xad\xb8\xe5\x98\x0b\xfc\x18\x0e\xed\xb7\x02\x46\xf7\x00\xb5\x92\x5d\x51\xe0\x67\xf6\x01\xae\x6e\x72\x46\x03\x66\xdf\xf6\x90\x31\x02\x95\x5c\x2d\x5d\x24\x22\xc5\xd5\x8f\x35\x2d\x9a\xf1\x4d\xee\x95\x6b\xb4\x44\xd5\xef\x79\x91\x67\x54\x39\x07\x52\x38\xa3\x44\x4b\x67\x24\x07\x42\x90\x51\x11\x4e\x7b\xdc\x23\x2c\xb1\x4a\x2a\xaa\x0c\xcf\xea\x82\x2a\x62\xcf\xc2\x54\xaa\x4e\x31\x48\x5b\x21\x1a\x91\xe6\x96\x65\x52\xe4\x7d\x14\x80\x4f\xed\xbe\x6d\x37\x8e\x8a\x29\xee\x32\x89\xf2\x92\xb5\x91\xf4\xa4\x79\x5d\x26\x27\xfe\x54\x87\x23\xd6\x30\x8c\x34\xad\xf9\x98\x8a\xf8\x34\x21\x8f\xe1\x54\x8c\xc8\x57\x0b\x6f\x85\x01\x8b\x8c\x0b\xdc\xd2\xcc\xf8\x18\x3b\x8f\xb2\x0e\xd8\xf1\x40\x4d\xa4\x82\xb8\xb7\x93\x5c\x62\xb0\xd7\x9c\x67\xe6\x74\x44\xfe\x3f\xa6\x24\x06\x87\xb3\x29\x26\x86\x75\x28\x1e\x14\x57\xa8\x89\x0c\xce\x41\xaf\xc8\x09\x26\xe9\xe5\x65\xc9\x72\x4e\x0d\x2b\x16\xa7\xa8\xc7\xfa\x34\xbf\x5d\xb6\xae\x8b\xd1\x20\xc9\xe9\xfc\x9b\x5f\x6f\x68\xd9\x37\x3c\xf3\x7b\x1f\xf0\x16\x21\x83\xee\x49\xad\x2d\x0c\x3c\x48\x6e\x10\x37\x53\xf7\xa6\x18\x2f\xee\xc9\x4c\xd8\xe0\xbf\x59\x3c\xa0\x44\xb1\x29\x60\x39\x62\xee\x03\x71\x1c\x1d\xb5\xdf\xcb\x5a\xac\xb7\x18\x36\x16\xfe\xce\x29\xe1\xdf\x27\x1d\xd7\x06\x40\x3f\x89\x98\x90\xcc\x24\xb1\x60\x52\x02\x66\x4b\x60\xe7\x96\x3c\x60\xab\xe8\xe4\xd6\xe1\x4e\x62\x8f\xc1\xce\x30\x97\x2d\x01\x35\x7b\x09\x89\x0e\x1f\xea\x81\xcb\x10\x7b\xe2\x00\xd3\x0a\x09\x36\x8e\x1c\x00\x7e\x22\x04\x23\x82\xc2\xb7\x58\xee\x1d\x64\x31\x8d\x01\x74\x25\xc7\x6f\x8e\xf7\x42\x7c\x71\x39\x4a\x56\x74\x4a\xb7\xa7\x52\x6f\x2a\x23\xad\xae\x24\x67\x86\xa9\x12\x72\x5e\xcf\xe4\x3d\xfe\x8e\x6c\xab\x72\xad\x98\x4b\x17\x6e\x57\x3b\x93\x1a\xb8\x52\x33\x3e\x1a\xce\x2f\xf8\x5c\xdc\xd3\x05\xa1\x4a\xd6\x22\x77\x52\x53\x20\xa0\xef\x5b\x1f\xfe\x20\x05\x8b\xb7\x66\xcd\x3b\xd7\x31\x33\xd4\x1e\x9b\xd7\xa3\xd7\x5b\xd2\xda\x77\x04\x58\xcf\x90\x78\x98\x4d\xcb\x52\xe8\xdd\x70\xfc\x99\xd9\xcb\xbc\x14\xa3\xf9\xb7\xa2\xe8\x23\xcb\xbd\x47\xf4\x82\xae\x43\x50\xc2\xf8\x04\x6c\xb7\x03\x7c\x75\xaf\xb8\x61\x09\x79\x3c\x99\xd0\x42\x43\x2d\xff\x5a\x04\x11\xf6\xb4\x29\x82\x40\x93\x2e\x0b\xda\xee\x6a\xa6\xeb\xf1\x03\xcf\x99\x3b\x50\x80\x72\xf1\x98\x05\x84\x3b\xd6\x1b\x8e\x5c\x33\x6e\x9c\x9c\x60\x4b\x2b\xb1\x49\x69\x4e\xf7\xe3\x7f\x86\x0b\xb4\x9a\x75\x1f\x95\xc4\xa7\x24\xa8\xf6\xb8\xda\xaf\xd8\x8c\xce\x99\x26\x9a\x97\xbc\xa0\xaa\x80\x30\xe4\x5b\x9c\x1f\x19\xd7\x66\x75\x72\x8b\x7e\x89\x13\xd2\x99\x24\xc3\x6d\x05\xb5\x9f\x87\x85\x13\xd0\x08\x3f\x2f\xac\x2f\xe0\x8b\x12\x7c\xce\x8a\x5a\xf3\xf9\x43\x4f\x93\x0b\xac\xda\x81\x55\xb7\xb9\x74\xe5\x3c\x25\x9e\x90\x47\x37\x35\x0c\x4b\xaa\x72\xbf\xe9\xc0\x93\x51\xd9\x07\xcd\x1d\xfc\x4e\x68\x96\x31\xad\xbd\xbb\xf6\x22\x75\x21\x0f\x6b\xf8\x52\x72\x95\xd0\x7b\x7d\x55\x50\x6d\x78\xf6\x55\x21\xb3\xbb\x5b\x23\x55\xaf\x74\x20\xab\xfa\xb7\x32\xbc\x9c\xff\x70\x4b\x2e\xb9\xbe\x4b\x02\x95\xdc\x9d\x6a\x6a\x2e\xa1\xe4\xae\x1e\xb3\x82\x99\xe3\x63\x8d\x5c\xae\xa4\xd9\x8c\x0b\xe6\x19\x9c\x08\xd1\x6e\x4e\xe1\xb3\x50\xee\x7b\x67\xea\x62\x2a\xcf\x1c\xbe\xfe\x9c\xde\x6b\x86\xd3\x1f\xdb\xe9\xdb\x9f\x59\x97\x64\x17\x7b\xbd\xa7\xc0\xc9\x5c\x5f\xee\xe9\x0e\x62\xa2\x3f\xd9\x39\xf6\x33\x6e\x1f\x63\x2f\xaf\x3a\x4c\x78\xc1\x5c\x61\x13\xbb\x60\xef\x79\xe3\x4e\x05\xec\xdf\x42\xd6\xe4\x9e\xa2\x8e\x0c\x14\x71\x44\x3e\xf1\xea\x0d\xb9\x12\xba\x56\x2c\x5a\x37\xda\x43\x71\x1d\x43\x58\xbd\x72\x05\xfb\x8d\x0a\x88\xa5\x7b\x4e\xd7\x22\x57\x9f\x69\x59\x15\x4c\xbf\x21\x47\xec\xb3\xf9\xf5\xd1\x80\x1c\x7d\x9e\x68\xfb\x3f\x61\x26\xfa\x68\x44\xae\xcb\x70\x29\xcf\xc5\x84\x29\xc5\xbc\x8f\x25\x76\xb0\xac\x39\xe1\xba\x8f\x82\x2e\xce\x5f\xd7\xca\x6e\xb9\x24\xf7\x98\xea\xc6\x12\x7c\xa6\x94\x54\x21\xc4\x25\x01\x03\xf0\x9a\x4c\x96\x95\x92\x25\x4f\xcc\x7c\x80\xee\x7b\x75\xe4\x05\xe3\x43\x97\x5a\x3f\x6d\x6c\x08\x1d\x3d\x42\x24\x2f\x44\x17\x54\xb8\x9e\x78\x5f\x0b\xd4\x22\x9d\x5a\x0f\xc3\xb9\x46\x76\xf3\xdd\x28\x96\x90\xa5\xdb\xfd\x36\xc4\xea\x92\xb3\x9c\xcd\xcf\x74\x4e\x5f\x0f\xe0\x33\xda\xf9\x18\x37\xe7\x44\x35\x39\x7a\x7d\x34\x22\xb7\x9e\x11\x0f\xd2\x39\xc6\x76\x13\xa9\xc2\x80\x60\x67\x7f\x75\x44\x4e\xa4\x82\x91\x33\x2a\x48\xc1\xe8\xdc\xd9\x96\xf1\xb8\x2d\x50\xdd\x3d\xed\x1c\x6b\xdd\x35\xec\xb4\x7b\x51\xa7\xae\x42\xea\xf2\x26\xfa\x7e\xde\x04\xa0\x6a\x17\x86\x34\x91\xca\xa5\x18\x0a\x4d\x34\x33\x70\xf4\xb8\x68\xa8\xd0\xcf\x40\x60\x49\xcf\x2c\x1d\x9e\x7a\xf6\x85\x8e\xef\x07\x3a\x90\xe0\x3f\xd6\x8c\x5c\x5f\x86\x5c\x1d\x4c\x69\xae\x8d\x3d\xc6\x79\x83\x75\x71\xe4\x67\x27\xe7\x25\xfd\xbb\x14\xe4\xea\xab\x5b\x37\x81\xd3\x67\x05\xd5\x56\x6a\x40\xff\x5e\x2b\x66\xb9\x70\x0f\xe6\x1e\xfa\xb4\x19\xba\x7d\x4f\x2e\xa9\xa1\xc8\xd7\x9d\x23\x96\x88\xa4\xdc\xb2\xec\x31\x17\xb9\xfb\x29\x61\xd8\x4f\xcd\x5b\xed\xee\x7d\xd8\xe6\xf5\xea\x1b\x7e\xf7\xf1\x7a\x4f\x3c\x38\x03\x62\x3e\x7d\x2f\xf3\xde\x8c\x38\xe9\xea\x89\xef\x1f\x2d\x4c\x2f\xf0\x3d\x29\xed\x98\xc4\x6a\xef\x03\xf2\x91\xd1\x9c\xd8\xf3\xeb\xfe\xf9\x83\xd5\x3d\x3b\xd3\xaa\x4e\x2c\xc4\x03\xb0\xe7\x32\x7c\x37\xbf\x84\x34\x88\x26\xb7\x98\x03\xc7\xca\xf1\x92\x71\x21\xc7\xc4\x1d\x87\x7d\xcf\xfd\xbb\x8f\xd7\x3b\x4c\xfd\xbb\x8f\xd7\x7e\xe6\xf6\x9f\x72\xf2\x74\x93\xde\x49\x7c\x8b\xd2\xdb\xdb\x96\xb8\x15\x59\x72\x8c\x09\x6b\x8b\x64\xdd\xe5\xb1\xd1\xbe\x24\xb1\x7d\x42\xec\x8e\x8b\x0e\x01\xfe\xcd\x53\x66\xfb\x58\x85\x02\x7d\xd5\x92\x7b\xc4\xdb\x19\x85\xac\x0a\x21\xd6\x17\xf6\xd9\x6e\xbc\xb6\x5c\xc1\xef\xb8\x55\x02\x81\xb6\x91\x4b\x86\xb7\x9c\xf9\x1b\xef\x3b\x10\x7a\xac\xee\xf0\x1e\x3c\x35\x73\x47\x5f\x09\x3a\x6e\xe6\x09\x82\x9d\xa0\x55\x49\x84\x9f\x9c\xef\x3a\x2f\x38\x54\x69\xb0\xda\x7d\xea\xac\xaa\x61\xca\x7b\x3d\xf5\x3b\x8a\x1c\x41\x9c\x58\x32\x6e\x91\x13\xfb\xdb\x19\x18\xc7\x4e\x47\x40\xad\xa0\x21\xb8\xf1\xb7\x84\x92\x8f\xdb\x84\x92\xbd\xc9\x0f\xb0\x03\xf6\xc4\xf4\xe5\x8a\xb6\xcf\x4a\xae\x08\x3f\xdc\xba\x54\x95\x2f\x99\x31\x62\x18\x67\x27\xd6\x08\xf8\xb5\xb5\x65\x77\xe6\xf8\x50\xe4\xca\xbf\x0c\xe4\x22\x21\x58\x76\x07\xfe\x19\x3b\x7a\x3e\x14\x42\x65\x7c\x3a\x90\x86\x6b\x26\x62\xdf\xad\xa3\x35\x2e\xbb\x1b\x72\x5d\x8b\x73\x5d\x4a\x2e\xf6\xc9\x07\xe3\x31\xa2\xef\xaa\x7c\x3f\xbf\x28\x24\x81\xf0\x9a\x74\xc0\xc5\xce\x93\xcc\x58\x35\x9b\xf4\xb9\x12\xb7\x1d\xde\xde\x36\x2d\x81\x17\xac\x9a\x91\xb7\xb7\x2b\x8e\x31\xc0\x1e\x66\xad\xd1\x3e\x78\xac\x49\xc1\x27\xcc\xf0\x2d\x4b\x78\x84\x83\x5c\x4a\xc1\x8d\x54\xeb\xb3\x2b\x90\x5e\x87\xd3\x0f\xd7\x97\xa1\xfa\x7e\x76\x67\x63\x6e\xa2\xf7\xc9\x5b\x4a\x32\x59\x14\x2c\x33\x2e\x5b\x1e\x80\x37\x74\x5b\xa1\x3c\x31\x67\x0f\x18\xdd\xfd\x0e\xd4\x27\xa7\x28\x9d\xe1\xe6\x9e\x7d\xbc\x3a\xbf\x7c\x7f\x35\x2a\xf3\x9f\xcf\xe4\xfd\xd0\xc8\x61\xad\xd9\x90\x77\x48\x7e\xf4\x7c\xde\x8b\xf8\x54\x9d\x72\xf1\xb5\x0d\x32\x98\x46\xf0\x5b\x1f\x9a\x4d\xbe\xd3\xe8\xb5\x00\xb6\x23\x7f\x27\x25\xa5\x19\x10\x45\x5d\xf8\x35\x75\xa6\xa7\xba\x28\x10\xda\x46\x31\x36\x48\x6d\x31\x1b\x43\x43\x7a\x2f\xec\xc1\x86\x8a\xc6\x02\x1f\x57\x86\x78\x7a\x84\xeb\xc3\x31\xb6\xcb\x24\xcb\x50\x8c\x3d\x9b\x70\xbc\x6d\xbc\x47\xc3\x99\x99\x59\xa8\xde\xb1\x05\x01\x47\xe0\x89\x54\x16\x9f\x54\x13\x37\x98\xc9\x60\xe9\x67\xb5\x66\x6a\xe4\xd8\xce\x93\x83\xad\x47\x82\xb2\x1d\xf2\x42\x86\x8e\xab\x60\xe6\x5e\xc7\xa4\xe1\x4e\x5e\xa3\xb5\x99\x31\x61\xb8\x0b\x60\x76\x90\x59\x09\x44\xe7\x87\xfd\xe4\x50\xeb\x98\x1f\xad\x5f\x36\xb3\x43\x06\xb0\x3e\x38\x69\x4f\x4d\x5f\x74\xb4\x7d\x20\x4e\x31\x25\xf3\x21\x96\x4b\xd1\x5c\x82\xc3\x06\x26\xb7\x6c\x20\x1a\xcd\x4b\x2e\x5e\xe0\xe9\xcc\xb8\xc8\xb7\xc1\xa1\x65\x00\x83\x1e\x4d\x51\xcc\xbd\x73\x06\xfd\x70\x6f\x48\xbd\x26\x85\xb9\x34\xdc\x0d\x62\xf3\xfe\xb0\xd3\xe1\x2b\x17\xfa\xc7\x62\x88\x5f\x19\x56\x79\x84\xca\xe1\x32\x70\xf9\x06\x6f\xbf\x26\xa5\x27\xb8\xe2\xdb\xd3\x6e\x93\x27\x96\x86\x1e\x57\xcf\x7d\x12\x40\xf5\x91\x79\x1e\xca\xbd\x23\xcd\xac\x24\x77\xee\x9f\x21\xd9\x28\x9e\x51\xaf\x2f\x5b\x78\x54\x54\xd1\x92\x19\xa6\xd0\x05\xce\x39\xd5\x09\x17\x9d\xf0\x6d\xc5\xc4\xad\xa1\xd9\xdd\xbe\xb3\x2c\x1f\x38\xee\xe3\x71\xdc\x07\x5f\x05\x7a\x44\x70\x29\xd7\x16\xe9\x2d\x32\x17\x8e\x0b\xbd\x10\x12\x13\x32\x1d\xf6\xb1\x72\x84\x4c\x77\x4d\xee\x1a\x33\x1f\xa2\x61\x03\x3c\xdd\x42\xea\x4e\xf0\xe0\x47\x28\xec\x87\x1b\x76\x3f\x03\x8e\x04\xee\x72\x8f\x96\x74\x6d\x52\x87\xd2\xbe\x19\x73\x13\xcf\xbd\x66\x86\x54\x4c\x95\xdc\x85\x75\x4b\x41\x32\x17\x16\x00\x7c\xcd\xf2\x30\x37\x5c\xc2\xf3\x04\x91\x99\xa1\x2e\x66\x86\x8c\x99\xb9\x67\x4c\x90\x57\xaf\x5e\xbd\x02\xb9\xe4\xd5\x6f\x7f\xfb\x5b\x02\x69\x26\x72\x96\xf1\x72\xb9\x21\xb4\xfa\x5f\xaf\x5f\x8f\xc8\x7f\x9d\xbf\x7f\x07\x5e\x65\x95\xd1\x64\x2c\xcd\xcc\x8d\x6c\x1b\x34\x3a\xeb\x01\xf9\x3f\xb7\xdf\x7e\x88\x29\x96\x9a\xbf\x82\x0a\x12\x96\xd7\x74\x11\x7c\xf5\x9b\x5f\xff\x7a\x44\x2e\xb9\x82\x78\x62\x0e\x11\x10\xc1\x09\xb2\xf2\x8e\x81\x50\xd3\xac\x1d\xc1\xef\x38\x88\x73\x12\x2e\xf9\x74\x06\x00\xb0\x07\x42\x8a\x49\xc1\x33\x83\xe9\x4a\xf1\xe8\x23\xa0\x5d\xfa\x1d\xea\xc2\xbd\x9c\x14\x01\x93\x1b\x90\x82\xdf\x31\x32\xd1\x5f\x2b\x59\x57\x31\xcc\x51\x31\x6d\x65\xd9\x8c\x0a\x88\x2a\x81\xc1\xe2\x5e\x69\x66\x9e\xd5\x09\xa3\xa3\x21\xa8\x81\x83\xd0\xa7\x25\xa0\x0c\x42\xda\xc6\x21\xe2\x43\x45\x79\x70\x1c\x84\x3b\xf5\x46\xd1\x90\xa0\x7b\xe6\x49\x9a\x4a\x1f\xbb\x52\x29\xf9\x37\xdc\x2a\x2e\x7c\x14\x94\x93\x90\xb5\x93\xc9\x5c\xd0\xa9\x48\x6c\xae\x3e\x2a\xdf\xf2\x42\x17\xf1\x9f\xc4\x4f\x5d\x4f\xd2\x40\x3b\x08\x4b\xc7\xca\x8d\x8d\x9c\xba\x2b\xbe\x1c\xeb\x40\x58\x6c\xd2\xb8\xaf\xb5\x58\xea\xed\x4a\x34\x39\xf2\xe3\x0a\x77\xb9\x10\xb6\x38\x06\xba\xe2\xba\x00\xa0\xa4\x1c\x5c\x23\xcf\x65\xc3\xcb\x47\x33\x53\x3b\xd0\x80\xe7\x95\xfd\x36\xd3\xda\xc5\x11\x95\x54\xdd\x59\x25\xc1\x51\x81\x11\x78\x3d\xeb\x10\xc3\x84\x01\x65\x73\x34\x96\x97\x74\xd1\x88\x1a\xb0\x1f\x39\x1e\x8d\x8e\xf1\x98\x48\x85\x69\x82\x11\xe7\xed\xfb\x67\x8a\x97\x6e\x7a\xa5\xd3\x0a\x2b\x7a\x82\x3d\xc7\x55\x44\xa2\x0d\x6f\x67\xea\x20\xd5\x25\x39\x78\xcf\x8a\xa8\xfd\x4a\x6f\x77\x2f\xb9\x3d\x84\x05\x74\x68\xda\xb7\xbc\x76\x8f\xb2\xda\xeb\xb2\x35\x38\x18\xbb\x93\xd0\xb5\xd8\x6c\xef\x32\x03\x65\x27\xd6\xb7\x62\xaa\xc7\xa5\xe3\x7c\xdf\xf6\xe3\x7c\x2e\x5e\xaf\x51\x77\xf0\xe5\xb3\xba\xeb\x09\x46\xba\x34\x49\x97\x23\x0d\xa9\x28\x10\x6a\xfc\xc5\xb0\x97\x17\xcd\xd1\x52\xb4\xe9\x57\xd3\xa2\x0f\x77\xc3\xa7\xdb\xc5\x04\x3e\x0d\x5c\xf3\xb7\x13\xb8\x68\x47\x4a\xab\x46\xed\xa0\x02\xed\x06\x20\x63\xfa\xc3\x33\x22\xef\x1d\xa9\x45\x24\xa3\x63\x2d\x8b\xda\x60\xd7\xf8\x63\x4a\x87\x61\x50\x9f\x65\x01\x88\x6f\x68\x96\x50\x65\x13\xab\x27\x76\x23\xd0\xf8\xf4\x38\x9c\x87\x44\xc2\x8f\x98\x48\x38\xa4\xbe\xd6\x1d\x4b\xc1\xe9\x47\xcb\xdc\x9d\x69\xde\x47\xbf\xd2\x9c\x9c\xc4\x0a\x44\xfe\x3a\xfe\x5a\x18\xa6\x26\x34\x63\xa7\xa9\xde\x15\x2a\x3d\x05\x17\x21\x1f\x17\x31\xa3\x22\x2f\x50\x00\xcf\x98\x02\xdc\x67\x9f\x0d\x53\x16\x24\x17\xb7\xd7\x24\x57\x7c\xce\x94\x26\x27\x5f\x31\x2b\x2f\x62\xfe\xd4\x4e\xd1\x55\xfb\xf5\xad\x84\x69\xec\x4b\xd3\x83\xc1\xfa\xba\xea\x41\x27\x4f\x79\x44\x72\xbe\x22\x98\x10\xaa\x08\x52\x9d\xea\xb2\x23\x8b\x4a\x40\xa0\x81\x66\x2c\x64\xad\x9c\x15\xdd\xa7\x6c\xce\xa4\xb2\xea\x12\x0e\x4c\x35\x51\x6c\x6a\xa5\x59\xe5\xeb\x98\x33\x92\x15\xb5\x7d\xb1\x57\x77\xb6\x87\x38\x00\x46\xd3\xec\x26\x5f\xbd\x89\x93\xaa\xe5\x9c\xe7\x9e\x55\x62\x59\xf5\x50\x30\xb5\xa2\x3a\x09\xb5\x49\x8a\x5b\x24\x80\x45\x19\x1d\x18\x6a\x08\x62\x6d\x38\xfb\xa7\x46\x61\x09\xb9\x2d\x3a\x54\xa6\xe9\x43\x84\x65\xce\x6e\xea\x71\xc1\xf5\xec\x76\x47\x13\xe2\xaa\x21\xd0\x59\x61\xe9\xd6\x6f\xad\x25\x51\x33\xa1\x39\xb0\x3c\x4b\xc6\x2d\xd3\xe5\x56\x8e\x92\x00\x44\xdf\x3b\x45\x48\x09\xd1\x1f\x05\x73\x19\x0c\xec\x4f\x1f\xe2\x3c\x5c\x50\x1a\xe6\x2c\xc9\xd9\x77\xa2\x6a\xbc\xcf\x68\x51\xe8\x76\xc0\xae\xa7\x98\x28\x7b\xf8\x40\x35\xdc\x53\x6e\xb7\x3b\x14\x5d\x6a\x25\xc7\x5c\xbb\x30\x4d\x4a\x89\x61\x3c\x02\x92\xf3\x62\x23\x48\xbd\xe2\x3b\x24\x81\x8c\x10\xae\x0c\x28\xb3\xe7\xaa\xb4\x07\x73\xe9\xe3\x99\x4b\x1f\xea\x87\xa7\x43\x81\x3a\x9a\x44\x43\x37\xd2\x92\x06\x52\xea\x49\xee\x16\xa7\x8e\xbd\x5e\x2b\xe0\x37\xcf\x8d\x51\x7c\x5c\x9b\xfe\xf9\xde\x5a\xdd\x81\x4d\x5b\x45\x04\x4e\xf1\xd0\xad\x3e\x4b\x50\x34\x66\x4e\x6f\x92\xcf\x78\xf6\x23\xcf\x01\x76\x83\x2f\x8f\x35\xc9\x65\x56\x87\xb4\xb1\x00\xb4\x78\x81\xd6\x25\x7b\x22\xe9\x7b\xae\xfa\xa7\xf4\x4a\x3f\xb2\x15\xbd\x72\x79\x2f\xee\xa9\xca\xcf\x6f\xb6\x78\xdf\x37\xd9\x79\xec\x95\x0a\x4a\xfe\x35\x14\x18\xa5\x63\x59\x9b\x98\x3a\xf4\xa7\x63\xaf\x5e\xa5\xa6\x1b\x69\x49\x43\x47\x7b\x74\x5f\x45\xff\x60\xe2\x3e\x98\xb8\x1b\xcf\x2e\x26\xee\x6b\x34\x71\xa7\x79\x70\x1b\xc7\xd5\xa7\x57\xe0\x45\x57\xdf\xde\xc7\xb4\x92\x5e\x46\x02\x83\xd2\x54\xdb\x8f\xbf\x25\xc0\xe1\x11\x89\x7b\x9b\x08\x7d\x9e\x02\x01\xcf\x7e\x7e\x8b\xea\x23\xd9\x49\xbb\x97\x40\xc7\x67\x5d\x8d\xd2\x4d\x25\xd1\x41\x6a\x48\x6a\x98\x0f\x5c\x16\xe8\x81\xd3\xbb\x44\x1e\xab\x83\x62\x12\xea\x1e\x15\x90\xf1\xe9\x09\x7c\xd2\x7b\x03\x48\xcf\xfa\xe4\xf8\xf4\xdd\x0d\xb2\x43\xad\x72\x7c\x9e\xb9\x62\x39\x3e\xbd\x6d\xdf\xa4\x7f\xf5\xf2\x15\xcb\x7d\xdc\x1a\xe6\x3b\x2e\x6d\x77\xb3\xfe\xae\xe6\xfc\x41\xac\x9c\xf9\xf2\xd9\xfa\xc1\x9c\xbf\xf4\x3c\xa1\x39\x3f\x21\xdc\x9e\x18\xac\x30\xed\xa7\xe6\x36\x6f\xdf\x1f\x33\x2f\x56\x8e\x62\xf6\x35\x8b\x72\xde\xb2\x1f\xcb\x35\xe1\xb5\xea\xf1\x68\x74\x7c\xec\xed\xfd\x0e\x3f\x6b\x33\x19\xfe\x8e\x30\x91\xc9\x1c\x37\xd5\x8e\xaf\xb4\x01\xa6\x1f\xd5\xf4\x74\x2e\xa5\xff\x56\x7a\x35\x0b\x63\xf7\xdb\x92\x1e\x27\xd8\xa7\x04\x78\xfb\x20\x16\x19\x19\x63\x48\x31\xe0\x16\x18\xb2\x0a\x39\x0e\x19\xab\x9b\x60\x61\x9f\x50\x6b\x0b\x2a\x8a\x9c\xe0\xcb\x51\x56\xd5\x03\xd7\x60\x54\xb2\x52\xaa\xc5\x20\x34\xb2\x3f\x36\x7a\xb9\x16\x98\x7b\x2a\xab\x95\x62\x02\xea\x9b\xbc\x54\xfe\xea\x41\xf0\x88\xec\x35\x40\xbd\x5b\x74\x5b\x7c\x9a\xdb\x1a\xef\x00\xc0\x24\x15\xab\xd5\x4d\x42\x66\x13\x3d\x88\xf7\x1c\xf6\x2d\x13\x73\x32\xa7\x4a\x77\x85\x39\xd9\x95\xa3\xe6\x7c\xce\x75\x97\x94\xff\x6b\x16\x77\x1b\xcc\x3e\x90\x76\xb0\x36\x55\x6d\x1c\x75\xf2\xb8\xeb\x33\x35\x35\x8b\xce\x45\xc1\xe1\xf5\xa6\x3a\x6d\xed\xe7\x85\x16\x92\x69\x3e\x9d\xca\xca\x34\x9f\x7e\x45\x66\x56\xf7\xed\xb9\xf5\x0f\xa8\xdf\xd4\x7e\xfc\xd6\xee\x7e\x46\x22\x93\x89\x89\xc1\xbc\x60\xf6\x08\x87\x00\x8c\xe1\x97\xbc\x57\x28\x82\xef\xd3\x74\x97\x34\xac\xac\xa4\xa2\x6a\x41\x72\x67\x6b\x58\xac\x88\x08\x4d\x42\x42\x1f\x9c\x1a\x06\xe6\x91\x73\xb5\xa7\x68\x84\x1e\xd1\xa0\x2c\xe7\xf5\xda\x4a\xf0\xeb\xc0\x86\xbd\x52\xa0\xdd\x43\x36\x30\x97\x49\xcc\x5f\x77\xba\x66\x3e\xb1\x22\xcd\xee\x5c\xc5\x20\x0f\x55\xe4\xfd\x49\x90\xcb\xd1\x51\x2b\x0f\x34\x98\xc7\xe0\xee\xcf\x15\x5d\xf5\x8d\x71\xec\x86\x29\x0b\x6f\x43\x9c\x5b\xc0\x89\x6b\x78\x6a\x25\x92\xf7\xc0\x06\x9f\x68\x97\x48\xcf\xc8\x36\xfe\x77\x06\x05\xc2\x7a\xfb\xc6\xfb\x8e\x21\x1d\xb4\x04\xc9\x3c\x94\x4d\x2b\x64\x96\xdc\x3d\x37\x38\x14\x6c\xc3\x95\x47\x7e\x6f\xbb\xb7\x9b\x61\x47\x45\xf9\x02\x8c\x3e\x85\xc6\x7b\x3d\x9e\x41\x6a\x4b\x90\xe2\x01\x98\x61\x03\x3e\x25\x45\x04\x6b\x6d\xbf\x04\x99\xe7\x93\x36\xf1\x43\xf7\x3e\xc3\xa6\x49\xea\xbc\x35\x75\x0f\xfb\xcb\x6d\x58\x59\xd4\xdb\x20\x04\xc2\x0b\xea\xba\x06\x31\xd1\x7d\xc5\x89\x4b\x72\x02\x77\x57\xb1\x2c\x5a\x48\xee\xb8\x84\x66\x82\x17\x4d\x3c\xf3\xb9\xec\xc2\xc2\x6b\xe1\x1c\x0d\x9e\x10\x69\x5e\x30\x1f\xec\xcc\xfd\xfa\xf3\xbc\x9e\x9c\xee\x01\xfc\x2d\xf8\x63\xf4\xe0\x10\x47\xd1\x89\xa3\xc1\x22\xd2\xec\x78\x4d\x87\x0e\xea\x7d\x06\xc2\xc9\xf3\x37\x43\x9f\x82\x86\xeb\x58\x47\xb6\xc8\x5c\xcc\x2e\x6f\x64\xbd\xc4\x61\x11\x01\xc1\xbf\x75\x68\xff\xe3\x35\x61\x6f\xd6\x1f\xb3\x89\x8c\x85\x52\x50\x31\x72\x5e\xb9\x39\x2b\x98\x01\x27\x5b\x16\x12\x96\xe2\xcd\x70\x29\xe7\x16\xa7\xff\x2c\xc8\x77\x3e\x75\x3f\x9f\xbc\x21\xf4\xb4\x11\x09\xe1\x8a\xcf\x08\xc6\x72\x74\xd5\x2d\xe2\x77\x54\x2d\xf4\x80\x8c\x4f\xbd\x5b\x0a\x1c\x3c\x61\xa5\xc3\xc2\x0b\xbe\xa8\x5e\x2b\x66\x01\x00\xd1\xc7\x4a\x96\x44\x0b\x5a\xe9\x99\x34\xa0\x21\xd2\x8a\x66\xdc\x2c\x88\x51\x34\xbb\x83\x4a\x45\x8a\xb9\xcf\x0d\x48\x76\xea\xfc\xbb\x52\xf0\x35\xbd\x87\xcd\x4c\xc9\x7a\x3a\x03\x87\x58\x6c\x95\x15\x54\xfb\xd5\xaf\xec\xef\x94\x1e\x4d\x72\x2c\x54\x1c\x92\x07\x2a\x39\xe7\x9a\x4b\x67\xf4\xf5\xe3\xde\x84\x04\x71\x68\x48\xc6\xf2\xbf\x27\x9a\x31\x72\xe5\x51\x02\x7f\xb9\x45\xd1\x06\x0d\x1c\xaa\xe9\x23\x20\x43\x66\x73\xe1\xf2\x22\x44\x3a\x17\xee\xb0\x90\x6f\xda\x99\xaf\xfc\xe8\x69\xd8\xae\xd5\x73\x92\x0a\xee\xef\x7d\x06\x4f\x26\x72\x99\x5c\x5e\x9e\xdf\x5c\xeb\x54\x29\x41\xdc\x72\xe9\xef\xe0\x87\x42\x8a\x69\x9a\x4d\x20\x62\xa6\xa5\xa8\x02\xaa\xbc\xcc\x79\x5e\xd3\x02\x69\xa9\x9b\xcc\xc5\xed\x35\x76\xe7\xd3\x99\x19\xde\x33\x30\xca\x20\xcb\x89\x67\xc6\x7f\x94\x2f\x39\xed\x70\x0d\xb4\xd7\x38\xa3\x02\x1a\xb8\xec\xd4\xee\xe9\x02\xb2\xd7\x38\x4f\x93\xc6\xbd\xa9\xcf\x2f\x86\x43\xac\x82\x38\x4c\xef\x3c\x54\xed\xb0\xd2\x03\x58\xad\x2c\x88\x01\x53\x97\xe7\x66\x01\x9f\xa4\x03\x0c\xaf\x5d\x81\x36\x6a\x37\xc8\xca\x78\x9b\x55\x9a\x47\x90\xcd\xe6\x71\x93\x3f\xb9\x0a\x8a\x3d\x65\x84\xa3\x1f\x12\xeb\x59\x72\xdf\x61\x8f\x0d\x15\xf9\x90\x16\x16\x73\x6e\xbe\xbf\x70\x8e\xce\x78\x10\x1a\xf7\xf9\xbe\x18\x12\x17\x21\x7b\xb6\x15\x1d\x56\x1e\x01\x08\x87\x1f\xb3\x1c\x88\x46\x5a\x37\xf2\xde\x2a\xca\xbe\xb8\xf3\xf7\x17\x03\xc2\x47\x6c\xe4\xff\x0a\x4d\x3d\xd5\x32\x72\x8a\xde\x80\xc1\xd5\x13\xf0\x0e\xa6\x92\xda\xa4\xd2\xbe\x7f\xfd\xbd\x9d\xa4\xfd\xf5\x0f\xc3\xdf\x27\x49\x47\xff\xf0\x57\x57\x49\xfa\xaf\xad\xb7\xa9\x4b\x59\x48\xbe\xff\x57\x5f\xc6\xdb\xa5\xae\xfe\xab\xab\xc9\x05\x85\xab\x47\x50\x97\x7a\x4e\x0b\x9e\x23\x36\xc2\xb7\x15\xfb\x9b\xb7\x2f\x02\x98\x82\x6d\x27\xa3\x86\x09\x20\xd4\x3e\x36\x43\x48\x83\xdd\x5d\x75\x5a\x3b\xff\x13\xb0\x0c\x60\x6c\xd9\x80\x18\x29\xe1\x38\xe2\x91\x3f\x17\x84\xf9\x92\x9d\xb8\x56\x00\x07\x75\xfe\x6a\x9e\xf7\xd8\x61\x2d\x84\x43\x24\xae\x9d\x07\xcc\xed\x97\x42\x9a\x5f\x86\xed\xf7\x9e\x1a\xc0\x60\x24\xa1\x73\xc9\x7d\x1e\x72\x7b\x52\x04\x16\x76\x0c\x99\xb1\xc7\x0b\x52\x72\x6d\xe8\x1d\x1b\x91\x5b\xcb\x5b\xd2\x4b\x31\x84\x9e\x20\x90\xc8\x92\xe5\xa4\x16\x86\x17\xf0\x6b\x1c\xc7\x4e\x39\xe5\x39\xd7\x13\xa2\xeb\xcc\xd2\xd6\x4a\xb1\xa1\xe7\x62\xae\xd5\x12\x2d\x88\x6b\x19\x84\xcd\x9e\x51\x54\x09\xaa\x1c\xba\x02\x3c\xa8\x70\xe8\xb5\xe4\xce\x65\xe7\x29\x45\x16\x39\x17\x00\x53\x8f\xc8\x07\x60\x56\x85\xbf\x19\x46\xed\xc4\xd9\x31\x05\xcb\x98\xd6\x54\x2d\x06\x90\xdf\x9d\x87\x9c\xe0\xce\x83\x07\x38\x6a\x49\x05\x66\x57\x57\x2c\x93\x42\x1b\x55\x67\x06\xcb\xed\x8d\x95\xbc\x63\x22\x78\x0d\x2e\x17\xbb\x8f\x6e\x34\x70\xed\x25\x49\x36\xa3\x62\x9a\x94\xab\x29\x69\x0e\xb0\xff\x26\x48\x39\x7e\x3d\x16\x02\x74\x62\x05\x0b\x6e\x00\x14\x63\xcb\x47\x82\x35\xf6\xcf\x22\xa4\xe5\x19\x44\x73\xa9\x5d\x12\x2f\xb6\xd0\xae\x5e\xf4\x8b\xf4\xb4\xed\x0d\x81\x6d\xef\xd9\x0f\xac\x64\x86\xe6\xd4\xd0\x1d\x7c\xc1\xde\xc7\x1a\x7b\xee\x1e\xd2\xd5\x39\x0d\xf7\x93\x8e\x0f\x79\x71\x4b\x56\x3c\x0d\x83\x82\x93\x38\xf3\x90\x87\xc0\x6b\x63\x71\xca\xdd\x17\xa0\x8b\x17\xc8\x33\xbe\x88\x99\x1d\xde\x8f\x86\xe4\x22\x56\x68\x8c\xe4\xa4\xdb\x6d\x54\x4f\x43\xac\x05\xfd\x0e\x30\xfa\x14\xaf\xcc\xb2\xa6\x9b\xd7\x4a\x11\x04\xb9\x04\x13\x86\x2b\x96\x46\x9d\x39\xd0\xd5\x02\x91\xbc\x05\x44\x80\xf2\x94\x19\x1d\x1d\x55\x90\x0e\x5b\xe2\xe2\xf8\x9d\xd3\x49\x81\x48\x3b\xc0\x3a\xb5\x6e\xb5\x2c\x84\x60\xd7\xd2\xd1\x59\x4b\xf9\x1f\x05\xae\xbb\xd8\x9e\xb1\xaa\xc0\x7b\x99\xf7\x31\x57\xb7\x92\xf1\xc7\x21\xa2\x1b\x27\x3a\xe4\x6a\xd0\xed\xb1\x01\x5c\x5a\xe9\x46\xec\x1c\x12\xb9\x19\x9d\xef\x6e\xab\x8a\x32\xd2\x30\x64\x34\x86\xcf\x0d\xe1\x73\xc3\xd7\xdd\x6d\x7a\x7d\x1c\x41\xfc\xd3\xd9\x21\xa4\xf9\x91\x5e\x06\x54\x4b\x52\x6e\x7b\x5a\x3d\x5b\x41\xc9\x61\x04\x47\xf3\xdd\x65\x62\xb8\xc0\x75\x01\x0f\x8c\x5b\x6a\xf1\x86\xfc\xb2\xc1\xe5\x9d\x34\x15\x34\x25\x74\xd8\x3d\xf1\xaa\xd3\xc8\x6d\x85\x8f\x41\x6f\x36\x3f\x6d\x0d\x06\xe2\xc5\x6a\x8d\xc2\x3b\x06\x07\x91\xcf\x8a\x67\x0a\x6c\x68\x3e\x0c\xc1\xa2\x97\x92\x45\xc1\x14\x2c\xc1\x69\x4f\xad\xcb\x74\x48\x69\x8a\xa6\xdd\x41\x50\x51\x83\x8c\x29\xd8\x7d\x10\x26\xa8\xc6\x0c\x2e\xfe\xe2\x8b\xb9\xfa\x79\x6b\xc7\x73\xd5\x8d\xec\xef\xe7\x62\x81\x93\xbf\x4c\x80\x8b\xca\x27\x99\xda\x4f\x59\xb9\x53\xd0\x71\x61\x39\x5f\xb2\x01\xe1\x3b\x2d\x52\x6e\x64\xd2\xea\x23\x9b\x38\xad\x31\x7d\xd5\xad\x2f\xf2\x81\x46\xc7\x51\xf4\x64\xf1\xc5\xed\x62\xe6\x12\x07\xf5\x46\x93\xe6\x0d\x78\x6b\xb4\x46\x40\xed\xaa\x19\x74\xbe\xc0\xdb\xe9\x0a\x6f\x97\x4b\x3c\x88\xfe\xe4\xa2\x8b\xc7\x54\xec\xb0\xb1\xce\x49\xfb\xd9\xe5\xd6\x0f\xdc\x6a\xe0\xb6\xbf\xdf\x15\x4e\xb3\xac\xfa\xcd\x35\x0c\xe1\x75\x87\x29\xfc\xe1\x39\x63\xb8\xe3\x18\x33\x7b\xfa\x62\x5c\x37\xec\x7b\xda\x77\x85\xe3\x43\x3c\x02\xdf\x40\xf2\x58\x67\xd4\x0e\x85\xd1\x14\x03\xc7\x15\xf8\xe2\x08\xaa\x27\x50\xb1\x70\x12\x87\x99\x71\x95\x0f\x2b\xaa\xcc\x02\xd5\xdc\x41\xe3\x6b\x21\x1a\xa0\xd7\xc2\x77\xbc\x7d\xea\x96\xa9\x79\x2d\x84\x61\xf1\xde\x9a\xed\x2e\x13\xd6\xc2\xf5\x29\xd6\xd3\x3d\xde\x60\xe5\x7a\xd2\x4c\xa8\x5e\x73\x7d\xb6\xf5\x34\x28\xcb\xc3\xf9\x9b\x25\x4f\xba\x79\x53\x8c\xec\x2a\xad\xb4\x25\x53\xa7\xed\x20\x8d\x80\xe2\x66\x47\x1a\x58\x7d\x99\xc6\xd2\xe8\x89\x01\xd2\x49\x34\xde\xe5\xc7\x15\x66\xb2\x48\x9f\x7c\x25\xed\x1a\xce\x07\x39\x11\x52\xe0\x99\xc1\xb6\xa7\xe8\xeb\xb4\xc6\x7a\x06\x4d\x02\xb7\x49\x75\xb5\xe4\x8c\x7a\x36\xc6\x45\x6e\x37\x0d\xc8\x32\x68\x71\xba\xce\x32\xc6\x82\xde\x9f\xd6\xd2\x89\x67\xda\x4d\xd9\xd7\xe4\xd4\x12\xb2\xcd\x68\x43\x8b\x22\xea\xdb\x0e\x50\x12\x38\xb1\xb7\x51\x26\x0c\xba\x11\x11\xe4\x4c\x0f\x50\xed\x1d\xfd\x73\x6a\x91\xa1\xaf\x01\x37\x8b\x34\x0f\x7f\x43\x18\x01\x45\x47\xa3\x1a\xce\x27\x68\x19\x4b\x14\x96\x00\x4c\x20\x4a\xae\xd6\xfc\xcc\x57\x4c\x01\x29\xdc\x25\x91\xb0\x14\x68\x4c\xb3\xbb\x7b\xaa\x72\xa8\x39\x5c\x51\xc3\x31\x7f\xf9\x00\xb9\x62\xca\xe4\xc4\xf1\x71\x7a\x95\xc3\x45\x9b\xff\xa6\x13\x39\x49\x66\xbd\xc4\x97\x4f\x03\x3f\xd6\x2c\x64\xd7\x8e\x13\x23\xb4\x36\xb2\xa4\x86\x67\xa0\x9e\xf3\x49\x62\x19\x2d\x43\xb6\xc6\x56\x45\x45\xa0\xc8\xa1\x36\xff\x0f\xed\xc9\x6f\x9c\x78\x32\x57\xbf\xcc\xd5\xf3\x4a\x88\x7a\xa8\xdc\x0f\x37\x5a\x60\xc1\x57\x8c\x11\x5e\x5a\x01\x8b\x42\x41\x92\x49\x88\xbb\xf2\xe6\xe2\x4d\x40\xb1\x52\xe4\x0f\x60\xa3\x4f\x5a\xa1\x8d\xc1\x6a\xa0\x9a\x98\x7b\x19\xd4\xb9\x68\x09\x75\x81\x4b\x83\x96\xc8\xe1\xfa\xd8\xa3\x66\xc1\x92\x9c\xa3\x81\xc5\x9d\x7b\x56\x14\xf6\xff\x9b\x4e\x93\x1e\xad\x9a\x11\x56\x06\xd6\x24\xe7\xba\x55\xde\xfb\x24\x57\xb2\xaa\x9c\x7d\xa9\x3c\x6d\xcf\x08\xae\x5d\xd4\x9c\xe9\xa4\x82\x35\xca\x6c\x53\x26\x42\x09\x76\x97\x14\x04\x08\x4a\xfb\x13\x8d\x6d\x5c\x39\xb9\x14\x5c\x68\xc4\xde\x0c\x1e\xf7\x2b\xe8\xa2\x16\x52\x1e\x61\xf4\x08\x83\x76\x4f\xc9\x77\xae\xf0\x53\x38\xb3\xc1\x33\xb2\x93\x4c\x8b\xa6\x30\x27\xd6\x8e\xc8\xc9\x79\x51\xcd\x92\x51\x53\x29\x32\x78\x5c\x37\x67\xda\xf8\xde\x85\x92\x5a\x7f\xf0\x5d\xfa\x7c\xfa\x20\x61\x76\x7c\x0e\x12\xe6\x41\xc2\xfc\xd7\x96\x30\xfd\x7a\x80\xc6\x3c\x70\x51\x81\xfd\x36\x69\xdd\xa6\xe5\x91\x0f\xd2\xb8\x6b\x11\x10\x41\xe8\x5a\x4d\x9b\x02\xa1\xbb\xa7\x8b\x91\x60\xc6\x45\xf3\x7a\xa3\xca\x47\x3f\xde\xd7\xca\x32\x63\x27\xbb\x25\x68\xee\xcf\x8c\x8f\x23\x4e\xbe\x62\x24\xf2\x87\x78\x4b\x03\xef\x8f\xb5\xbb\xa3\xb0\xbf\x83\x2f\x7d\x3a\x40\xc6\x46\xe4\x96\xf9\xa4\x9e\x8d\x8f\x2f\x47\x8d\xe6\xcc\x50\x5e\xe8\xc8\x10\x3e\xad\x61\x30\xbb\x13\xfc\xc7\xc6\x92\xe0\x33\xba\xab\x0e\x12\x1d\xa5\x13\x97\x8c\xd4\xa3\x28\x36\x58\x67\x02\xbd\x9e\x90\x8f\x2c\x93\x73\xa6\x10\x32\x50\x3d\xd8\xca\xd9\x6f\x29\x2f\x2c\x5c\x3c\x7c\xa2\x69\x09\xd2\x32\x37\x0d\xfb\x89\x3d\x2f\x20\xa5\xdb\x84\xd2\x4d\xca\x85\x0b\xdb\xf6\xee\x8a\xbd\x52\x6c\xce\x65\xad\xbd\xdf\x53\x6d\x90\x18\x6b\xe3\x24\xdb\x19\x9f\x86\xec\xfe\xc1\x51\x42\xb1\x4c\xaa\x3c\x22\x9f\x36\xd4\xd4\xba\x19\x6c\x95\xa1\x2d\x7e\x7f\xe6\xdd\x00\xc7\x47\x96\x01\x76\xe3\xb7\xb0\xdc\x5e\x3d\xda\xb7\xe3\x20\xb3\x6a\x88\x6b\x4c\xe8\x4c\x4a\x63\xd0\xaf\x99\x0b\x04\xbc\xdd\xec\x91\xff\x09\x3b\x0f\xe2\x1e\xc7\x6b\x4b\xae\x93\x32\xff\xe1\x0e\x90\x83\x94\x4a\xed\xb1\x4d\xd4\xb1\x70\x68\x01\xcd\xbc\x70\x77\x89\xfa\xdf\x47\xf7\xad\xf3\xc2\xca\xa4\x48\x04\x92\x83\xbb\xe2\x7e\x91\x97\x65\x6d\x2c\xbe\x8e\xc8\x35\x46\xb2\x80\x64\xeb\x14\xa6\x49\x8c\xce\x60\x4a\x77\xb8\x15\x4c\x9f\x5d\x8c\xf6\x64\x17\xc3\xfd\xd2\x46\x7d\x4c\x41\x9e\x66\xa5\xb0\xda\x1d\xdc\xcd\xdb\xdd\xf1\x77\xf7\x8d\xd6\x1d\xc2\xea\x57\xad\xb2\x27\x02\xe3\xb3\x8b\x28\x8b\x4f\x4f\xf9\x14\x9f\xdd\x4e\x0d\x3e\xfd\xa5\x0e\x7c\x96\x65\x8f\x56\x11\x7f\x2f\x83\x34\x76\xa6\x92\xf9\x68\xc5\xd9\x09\x7e\x1c\x32\x77\x4e\x1a\x4d\xfb\x0b\x86\x7c\x5d\xdb\xe1\xef\xbc\xe3\x52\xa0\xb3\xae\x64\x5a\x01\x96\x14\x9e\x33\xcc\x72\xeb\xce\xdc\x0e\x2b\xdb\x51\xdc\x69\x39\x24\x5a\x52\x32\x2c\x69\x35\xbc\x63\x8b\xde\xdb\xb2\x03\x16\x2c\x7f\x1c\xd7\x51\xd2\xaa\xc7\x38\xe8\x40\xfb\x00\x4a\x7a\xfc\x0e\x5d\x70\xf1\xe5\xd8\x31\x5e\xef\x15\x1c\x3d\x92\x33\x59\x56\xb5\x61\x09\x83\x76\xac\xb4\x37\xd7\x6a\x24\x21\x39\xc3\x3a\x7a\xc3\x30\xec\x30\x12\xb9\x0e\x05\x70\xd2\x67\xe7\xe3\xbf\x6b\xbe\x8d\xf4\x79\xc1\x0e\xc0\xad\xc5\xf6\x0f\x86\x21\x0f\x0c\x88\x21\x0f\x09\x8a\x21\xfb\x0c\x8c\x21\x21\xbc\xee\x21\x27\xe6\xa3\x0f\xec\x6b\x9d\x19\x27\xc2\x6e\x3a\x33\x8d\xfc\x4e\x61\x1c\xae\x7d\x41\x6e\xe7\x5e\x16\xce\x00\x5c\xcd\xa6\xe1\x59\xee\xb4\x82\xcd\x1a\x7d\xc8\xd8\xe7\x50\x84\x21\x51\x93\x40\xfb\xbf\xe7\x1a\x15\x1b\x41\x78\x59\x61\x62\x46\x38\x75\x43\x2f\x19\x39\x9b\x70\x98\x49\x06\xbe\x34\x84\x7d\x06\xcb\x38\x7e\xec\x70\xc0\xc9\xe1\x80\x77\xee\xff\x9c\x07\x1c\xe3\xd3\xfa\x84\x4f\xb6\xea\x3a\x62\x77\x97\x32\x85\x8e\x59\x41\x7e\xac\x99\x5a\x10\xab\x6d\x46\x2f\x6c\x28\x46\x61\x05\x17\xf4\x63\x76\x37\x4b\xdd\x25\x97\x27\x54\xb4\x40\xba\xbb\xfa\x6c\x55\x6d\xc8\x3a\xf0\x00\xb2\xd7\x1e\xaa\x99\x58\x06\xa1\x15\x20\x98\xaa\xd2\xe8\x08\xd6\x50\xae\xad\xce\x75\xfe\xe1\x72\x37\x8b\xc5\x73\xa8\x31\xe7\x1b\x16\x88\x80\x08\xbf\x34\x6b\x7f\x86\x2b\x0f\x72\xc7\x16\x03\xe7\xae\xe8\x6a\xed\xf8\xc6\xe8\x75\xdb\x4c\x00\xdf\x35\xb1\xd8\x2a\x00\x3d\xb9\x06\xd4\x35\x65\x78\xb3\x97\x07\xc2\x13\xea\x4e\x3d\x52\x8b\xa7\xcf\xba\x34\xe3\x88\x13\x90\x2f\xd9\x47\xa1\x05\x34\x80\xc8\x3b\xa0\x16\x4f\xaa\xd2\x10\xc8\xec\x8b\x80\x7d\xf0\x52\x03\x9a\x36\xe2\xa7\xee\xd8\xe2\x58\xbb\x1c\x0f\x52\xe8\x19\xaf\x7c\x35\x1f\xa0\x04\x0e\x73\xc9\xf7\xe0\xc6\xe9\x87\xc0\x33\x7f\x2d\x06\xe4\x83\x34\xf6\x7f\x57\xe0\xd1\x0d\xb8\x7e\x29\x99\xfe\x20\x0d\xbc\x79\x72\x60\xe1\x74\x1f\x0c\x2a\x77\x1d\xea\x0c\x45\x10\x79\x00\xd1\xb4\xde\x53\x18\x40\xe2\x9c\xc8\x02\x58\xb9\x26\xd7\x82\x48\xe5\x61\x62\x7c\xa9\x07\xed\x86\xf0\x57\x3d\xc9\x25\xf7\x8a\x31\x1c\x28\xa5\x6a\x40\x72\xc3\x70\xe1\x1a\x9b\xfb\x5f\xc0\x46\x0e\x2e\x09\xc1\xbd\x19\x0a\x16\x50\xc3\xa6\x3c\x23\x25\x53\x53\xc8\xe6\x91\xcd\x76\xdf\xa0\xfe\x74\x1b\x9f\x9d\xa8\x77\xfa\xe1\xde\x98\x01\xac\xee\x1d\x38\x98\x3f\x94\x61\xe2\x28\xc8\x22\x4a\x5a\x59\xa4\xf8\x87\xe5\x04\xb0\x2f\xff\x84\x02\x23\x7a\x44\xce\x7d\x79\xfa\xf4\x37\x67\x2e\x4e\x87\xb1\x23\x58\x91\xff\xc7\x9a\xcf\x69\xc1\x30\xec\x82\x8a\x90\x74\x5d\x4e\x96\xd8\xf4\xc0\x55\x19\xb1\x54\x2a\x98\x67\x8e\xee\xd8\xe2\x68\xb0\x84\x48\x47\xd7\xe2\x28\xa6\xd4\x69\xa0\x4e\x60\x68\x60\x93\x3c\x82\xdf\x8e\xf6\xcd\xd9\x9f\x49\xb4\xdf\x01\x4b\x9c\xe5\xfd\xa2\xa0\x78\x53\xb3\xeb\x7d\x48\x7b\x9c\x55\xe9\xb2\x6f\x93\x36\xf1\x26\xcb\x05\xd9\xec\xfd\xe2\x00\x82\x31\xfb\x3b\x84\xf7\x82\xde\xdc\xd5\xba\xeb\x9e\x66\x6b\x65\xfa\x57\x48\x32\xe5\x43\x6d\x1b\x59\x0c\xa2\x2f\xda\x1a\x78\x7d\x0f\x17\x38\x72\x42\xde\xc6\x34\xd8\x60\x82\xb7\x4c\xdb\x05\xdf\x5a\x45\x98\x8b\xac\xa8\xdd\xdd\x0d\x74\xc5\x8b\x84\xc7\x07\xce\x03\x90\x2a\x0e\xe0\xb1\xc9\xfb\xbe\x2d\xc5\x59\xb5\x3d\x81\xc0\x31\x2c\xf8\xbe\x20\xac\xf6\xbd\xd6\xc9\x96\xa8\x96\x66\xea\xf4\xac\x29\x7b\xbc\xe5\x63\xc5\xc8\xc5\x8c\x0a\xc1\x8a\x24\x37\x89\xb3\x85\x84\xe2\xa3\x20\x90\xb8\x92\xa3\xc7\xcd\x9a\xa3\x9e\xbe\x89\x90\x09\x27\x06\x9d\xed\x29\x4d\xff\x4f\xa9\x04\xe8\xfa\x4c\xf5\x7d\x8b\x7f\x62\x62\xed\x99\xbc\x27\xb9\x24\xf7\x50\x65\x6a\x6e\x99\x16\x38\x7f\x69\xcf\xee\x92\x99\x82\x9f\x68\x26\xcb\x4a\xc9\x92\x07\xe7\x29\xb7\x8d\x7b\x4d\xe4\x51\xd4\x1d\x32\x36\x36\xf7\xa0\xa8\x45\xb3\x80\xcf\xdb\x0b\x62\xa8\x9a\x32\x63\x47\x23\xa2\x2e\xc7\xac\x73\xb6\x91\xc7\xc8\x18\xfb\x25\x15\x7c\xdf\x6f\xc9\x52\xdc\x86\x1f\x7e\xf8\xd0\x37\x61\xee\x71\xec\xb9\x6e\x6f\xef\xa5\x2a\xf2\x7b\x9e\xfb\x0b\xe7\x13\xdb\xf8\xb4\xeb\xfc\xf7\x9c\x3f\xb7\x07\x86\xdf\xdf\xf3\xbc\x37\x38\xa0\x53\x13\x0c\xde\x0d\xdc\x82\x81\x00\x1c\x5c\x3d\x4e\x0e\x45\x4f\xa0\xc7\x29\xb9\xe2\x18\x04\x0e\xfd\xe1\xe2\xba\x1c\x73\x11\x13\x01\x44\x30\x5b\x62\x6c\xcf\x8b\x57\x4d\x34\x33\x18\xbe\x0b\x91\x33\xd2\xcc\x88\xe6\x65\x5d\x18\x2a\x98\xac\x75\xb1\xe8\x8c\x2a\xcf\x03\xea\x49\xc1\x3e\x23\x66\xf7\x61\x72\xa1\x53\x93\xd9\x81\x8b\x6c\xcc\x76\xb1\xc4\xed\xa2\x87\x79\x7e\x16\x38\x5f\x88\x0a\x67\x9f\x59\xe6\x82\xb7\xaa\xa2\x9e\xf2\x2d\x51\xaa\xff\x62\x35\x68\x62\xb9\x8f\x5a\xb3\x98\x57\xa9\x6b\x15\xbe\x27\x2a\x19\xf3\xbc\x1c\xfe\xd3\xea\x72\x31\x39\xab\x98\xc8\x21\x81\xed\xdb\x88\xb9\x38\xf9\xbd\x42\xce\x25\x83\xed\x4b\xb5\x7c\x0e\xd9\x06\x05\x4f\xdc\x13\x66\xb2\xc8\x35\x61\x9f\x8d\xa2\x96\x30\x95\x96\x04\x85\x3e\x13\x42\x45\x77\x22\xf3\x32\x0a\x3a\x90\xbd\x73\xfb\xc7\xad\x6e\xfe\x12\x0b\x94\xc7\xb5\x37\x5e\xef\xb9\xd0\x10\x12\x62\x77\x56\x74\x33\x40\x6a\x45\x41\xa0\xe8\xc0\xba\x1c\x89\xba\x63\x61\x20\xbd\xa2\x04\x4a\x6b\x56\x87\xa2\xea\x5f\x44\x95\xa0\x09\xe4\x6f\xe9\x93\x32\xd3\xf5\x68\x69\xd4\xee\xa5\x2f\x4e\xdc\x41\x83\x76\x78\x9b\xf0\x01\x0b\x75\x3f\x90\x8b\x3e\x27\xda\xc2\x32\xba\x7a\xd7\x42\x6c\xa3\x62\x8f\x51\xf3\x85\x1a\xaa\x99\xe9\x66\x4d\x69\x8a\x0e\xb1\xa7\x3d\x80\x29\x7e\xb9\x9f\xb0\xe6\x10\x44\xe5\xf9\x9c\x26\x64\xf8\x07\x27\x65\x88\x46\x4b\x2b\x5f\x78\xf8\xf8\x94\x9a\x2c\xdc\x22\xe3\x18\xb9\xdd\x95\x8c\x9a\xce\x05\x12\x3b\xf1\x05\x37\x83\xef\xbe\xeb\x5d\x79\x3f\xe9\xe9\xe5\x10\xf8\x77\x13\x08\xa3\xe0\x20\x5b\x0b\xfe\x63\x9d\xaa\x03\x90\x83\x2c\x2c\xdb\xb5\xdf\xd7\xda\xa6\x19\x8b\xc6\xab\x4b\xae\xef\xfa\xa4\x8e\x5d\xea\xdc\x3c\x12\x5f\x5f\x5c\x11\xf7\xb6\x93\x7d\xa9\x8f\x81\xe9\xa1\x29\x29\xa7\x19\x8b\x46\xdb\x9c\xeb\xbb\x3d\xa5\x9d\xed\x2e\xd5\x57\xf9\x87\x6d\xae\x8e\x4f\x67\xff\x6a\x4b\xbd\x3e\x93\x5e\x92\xe2\x71\x21\x6b\x72\xef\x32\x54\x39\xa9\xf9\x13\xaf\xde\x90\x2b\xa1\x6b\xc5\xe2\xcd\x6d\x7b\x28\xcb\x75\x3b\xcb\xd0\x90\x04\x4c\xbf\xd9\x9b\xad\x6c\xdf\x58\xf2\x92\x8d\x6f\x15\x55\x06\xc4\xe3\xbe\x68\x10\x3a\x7a\xfa\x94\xbc\x10\x5d\xf0\xe0\x7a\xe2\xfd\xee\x06\x2e\x15\x4f\x48\x33\xeb\x1b\xd9\x9d\x4f\xb2\xcf\xa5\x7b\xfd\x36\x64\x66\x24\x67\x39\x9b\x9f\xe9\x9c\xbe\x1e\xc0\x67\x7c\x64\x49\x73\x4e\x54\x93\xa3\xd7\x47\x23\x72\xcb\x4b\x5e\x50\x55\x2c\x1a\x85\x33\x62\x3b\xcb\x2c\xfc\x80\x70\x2b\xf7\xea\x88\x9c\x48\x05\x23\x67\x54\x90\x82\xf9\xb0\x6e\x77\xce\x16\x28\x3b\x9e\x3e\x35\x71\x21\x8f\x6a\xbf\x44\x3a\xd3\x1b\x27\x72\xcf\xb1\x1d\x3f\x6a\x64\x1d\xbc\x8c\x24\x9d\x0b\x4b\xe7\x47\xe4\x3b\x47\xa0\x1d\xdf\xc2\x4d\x83\x23\xe3\x5b\x3c\x17\x50\x9f\x46\xef\xdb\x49\x83\x5b\x36\x07\x3f\x1f\x98\xb6\x6b\x89\x53\x6e\x3e\xb2\x4a\xf6\x92\x10\xb0\x4b\xcb\x1e\xc7\x8d\x7d\x21\x35\x87\xb4\xf2\xd4\x10\x8a\xc7\x36\xab\x0b\x6a\xc5\x6a\xb4\xc6\x8d\xc8\xe5\xd5\xcd\xc7\xab\x8b\xf3\x4f\x57\x97\x6f\xc8\xd7\x6e\x24\x9e\x4a\x78\x23\xf2\x29\x4d\xda\x99\x38\xfc\xba\xcc\x88\xe1\x5b\x03\x47\x86\xa8\x88\xa9\xb8\x21\x15\x1b\x15\xe4\x5a\x70\x13\x8b\x59\xa0\xdf\x59\x21\x05\xf3\xb5\xde\x2b\xe9\xac\x81\x53\x6e\x5c\x8a\x22\x1c\xcc\xfe\xdc\x1c\xcd\xc5\x72\x58\x51\x26\x86\x62\x3c\xb9\x68\x11\x81\xbb\x2f\xf1\xdf\x67\xab\xef\x2b\xfb\x86\xda\x01\x3e\xde\x18\xad\xff\xf1\x3d\x32\x83\x50\x46\xc7\x67\x25\x94\xaa\x51\xe5\x06\x6a\xe0\x5b\x36\x73\x3c\x3a\xf6\x02\x45\xb1\x54\x32\x29\x0c\x9a\x26\x5e\x6d\x22\xdb\x88\x90\x6f\xbd\x47\x37\x64\x5e\x59\x5d\x7d\x09\x93\x78\x25\x35\x7c\x5a\x28\xeb\x23\x10\xeb\x71\xfa\x51\x97\xa9\x75\xca\xe7\x2e\x7f\xc6\x5e\xad\x78\xf1\xf3\xbd\x6b\xd9\xc6\x79\x3b\xfd\xe3\xe3\xbb\xfd\xce\x0c\xcf\x5f\xef\x79\xb9\x63\xeb\x66\x95\xc9\xb2\xc4\xb4\x9e\xb3\x10\xef\x1f\x43\xf6\x03\x55\xd8\x9b\xe6\x83\x09\x4a\x27\x5b\x90\xbf\x45\xcf\x7c\xa7\x96\xa6\x13\x5e\xbb\x98\x05\x11\xc5\xdc\xfe\x55\x33\x5c\x2e\x5c\xed\xc3\xb1\x1d\x69\x3f\x0b\x1f\x3f\xfb\x78\x75\x7e\xf9\xfe\x6a\x54\xe6\x4f\x4e\x5a\x98\xc8\x2b\xc9\x85\xd1\xdb\xf5\x9b\x6d\x35\x02\xbb\x93\x9f\xf0\xd1\xbe\xdc\x39\x74\xf4\x38\xe6\x5f\x24\xe9\x83\x5d\x38\x79\xb2\x87\x46\x56\xb2\x90\xd3\xd5\xc5\x32\x7a\x6c\xce\xcf\x31\x0d\xe0\x90\x0e\xed\xae\xef\x57\xd4\xef\x52\xf5\xac\x2d\xe5\x63\x95\x33\x0b\x86\xb8\xd6\x20\x35\x43\x71\xb2\x17\xba\xdc\x47\x11\xce\x96\x60\x80\x8a\x24\x1c\x60\x9f\x59\x39\xa6\x2a\x4e\x2a\x0e\x76\x95\xda\x1e\x1b\x74\xdb\x05\x36\x4b\x7f\xb6\x97\x95\x6c\xc2\xcc\xf7\x69\x12\xb8\x4a\xb1\x61\xc8\xaa\x09\x85\xf0\xa4\x4a\x18\x6e\x4a\xef\xbc\xf5\xc6\xdb\x7a\xb0\x55\xb1\x68\x5b\x71\x92\xf0\x70\x6f\xfa\xc2\x5c\x46\x45\xb1\x88\xd9\xba\x9d\x16\x4d\xa7\x98\x2d\x53\x39\x33\x71\xa5\xf8\x9c\x17\x6c\x0a\x19\xf3\xb9\x98\x26\x79\x06\xd2\xcc\x04\x2e\xa5\x44\xd3\xe8\xfa\xde\xfe\x95\x94\x48\x01\xbc\xf8\xf0\xed\x27\x28\xbe\x00\x17\x5c\x0f\x16\xc2\xed\x07\xe1\xbc\x0d\x87\x43\x30\x19\x9c\xfc\xcd\xca\x93\x79\x71\x4a\x7e\x60\xee\x3b\x12\xaa\x43\x28\x28\xdc\x38\x93\x21\x55\x3f\xcc\x35\x42\x16\xd0\x11\xaf\xf7\x5d\xab\x33\xdb\xd2\xca\x4a\xc8\x6a\x1a\xed\xa1\x4e\x3d\x66\xd8\xc6\x3b\xa6\xa7\x97\x3d\xf7\x48\xf6\x77\xa6\x72\xde\xb4\xba\x0a\x3f\xc3\xc5\x8f\xa7\x87\x94\xe8\x45\x59\x70\x71\x17\xd3\xb7\x4e\xa4\xcb\x60\xc2\x88\xfd\xc1\x63\xac\x62\xb4\x58\x4f\x29\x77\xc1\x8f\xbd\x52\x49\xb3\x83\x05\x10\x2c\x74\xf6\x9c\xfd\xd1\x1f\x7b\x77\x0d\x9d\x92\xb8\xa3\xa3\x17\xb7\x5e\xae\x33\xcd\xfb\x90\x35\xe8\xd0\xa0\x69\x82\x5c\xdf\x5e\xdc\x5e\x3f\xa9\x85\x7a\x1d\x4b\x80\xd9\x3d\xa3\x54\xc7\x7f\xdc\x76\x3b\x3c\x24\x45\xbd\xbd\x0d\xaa\x77\x37\x52\x19\x5a\xec\x89\x08\x64\x33\x5a\x9d\xd7\x66\x76\xc9\x35\x24\xab\xe9\x2b\x04\x2c\xf5\x4f\x3c\x9d\xb1\xc4\x86\xcf\xeb\xcc\x3d\x3a\xb8\x76\x17\x7f\x3c\xbf\x21\xb4\xb6\xfb\x6b\x5c\x0e\xf8\xbd\x5e\xb8\xfb\x99\xdd\x62\x84\xc1\x8e\xeb\x72\xbd\xb7\xac\xca\xb7\x7a\xec\x35\x3d\x86\x1f\xee\xe1\x2e\x02\x68\x28\x52\xb0\x17\x7c\xff\xc0\x05\x37\x9c\x1a\xd9\xb1\xac\x6c\x03\x05\x1a\x7d\x83\x41\xa0\xd6\x46\x96\x0e\x83\xaf\x7d\x0b\xb8\x42\x06\x2e\xbe\xd4\x29\x5a\x0b\x40\x7a\x07\x88\x5d\x0b\x2b\x6b\xd3\x8c\xb5\x1c\x20\x07\x90\x9b\x1d\xc7\xe6\xa1\xcd\xef\x9d\x81\x0a\xf2\x90\x16\x7f\x78\xd3\xa8\x98\xb3\x54\x7e\xcc\x5b\x29\x62\x6d\xab\xbd\x5a\x7c\xf8\x8f\x7d\x89\x02\xff\x51\xb4\x2c\x6d\xb8\xc0\xff\x5b\xd3\x02\x01\xf3\x61\xdf\x66\xa9\x26\x90\xfb\xce\xb7\xb9\x43\x6e\xea\x71\x3b\x3e\x04\x2d\xbd\xd6\x98\xe1\x14\xd7\x63\x14\x15\xda\xee\x51\x53\x17\x3b\x76\x17\x4f\xc7\xe4\xc4\x64\xd5\xe9\x5e\xd7\xd9\xdf\xb5\xbd\xa8\x45\x2a\x70\xe0\xcc\x3f\xe1\xb6\xbc\x0b\xae\xed\x5d\x27\xf9\x28\x57\x43\x80\xe5\x7d\xad\x2a\xae\x57\xd8\xad\x74\x5d\xc8\xfa\xc9\x3b\xae\x8d\xaf\x9b\x05\x2f\xb8\x76\xe5\x1e\x40\xee\xba\xb1\x8a\x1c\xaf\xfe\x9b\xe6\xb9\x7a\x83\x5c\xca\xc9\xe4\xf0\x6f\x1d\x72\x6e\x52\x11\xee\x12\x4f\xcc\xa2\x72\x39\x8d\x3f\x5d\xdc\x10\xac\x63\xf7\xbb\xdf\x60\x9d\xfe\x7f\xff\xd5\x6f\x5e\x75\xde\xee\xe7\x73\x1e\xdf\xd1\x8e\xb1\xf7\x3b\xa6\x17\xe1\x37\xd8\xf0\x0f\x84\x74\x8d\x56\x36\xb9\x45\x77\x3c\x4b\x59\xdd\x51\x47\xc4\xb2\xbb\x1c\xe8\xfd\x6e\x12\xcc\xc1\xcf\xee\x59\xfd\xec\x48\x88\x28\x41\x22\xd1\x13\x5d\xd2\xae\x10\x62\xb8\x4c\x76\x90\xe2\xdc\xbc\x3c\x8a\xb3\x15\x36\xdb\xb1\xa8\x89\x3d\xe9\x65\xbc\xaf\x52\x18\x5d\xd8\x2f\x3f\xdc\xfe\xf7\xbb\xf3\xaf\xae\xde\xc1\x4c\xdd\xfd\xbd\x45\x0d\x2e\x76\xf6\x9f\xea\x8e\x6a\x5d\x94\xd7\xed\x00\xe9\x77\x2d\x23\x5a\x17\x32\x82\x7c\x78\x7b\xdb\xf7\x2e\xe6\xa1\x02\xba\x98\x74\x5a\xfb\xd3\x5a\xdb\xa0\xf8\x1c\x53\xfb\x8b\x1f\xd9\xd9\x28\x97\xe4\xd9\x6a\xe8\x5f\x76\xa7\x70\x86\x0f\x56\x91\xb6\xee\x00\x79\x01\xf7\x0e\x76\xbd\x08\x83\xbd\xdf\x38\x3c\x12\xac\xba\xca\x01\xaa\x7f\x60\xd1\x31\xf6\xf2\x22\x80\x3d\xa4\x48\xdb\x94\xa5\xd9\x96\x5a\x33\x1d\x92\x64\xbe\x50\x4c\xa9\x56\x95\x81\xe8\x43\xbd\x56\x0e\xd0\xa8\x2a\xdb\xb8\x8b\x69\xc4\x52\xac\xab\xe9\xe2\x3d\x14\x68\x99\xa4\x0e\xdf\x67\x7e\x83\xf8\x0a\xdf\x60\x2a\xe2\x27\x27\x80\xf0\xd9\x3d\x3a\xd2\x86\xf1\xfa\x22\x72\xe8\xd8\x8e\x92\xeb\xb5\x43\x84\x6a\xcf\xa2\x9d\xcf\x51\x1a\x4e\xf7\xcc\xdb\x47\x9e\x56\xdb\xf9\x61\x47\x45\x67\xdf\x4a\x4e\x35\x93\x46\x8a\x9d\xbd\xe4\x57\x75\x6f\x1e\xe8\x1b\x68\x71\x11\xab\x0d\x26\xa5\xb8\xc1\x83\x32\x5c\x46\x40\x0d\x1d\xc7\x2e\xa4\xf0\xd7\x12\xcd\x4b\x89\x27\x17\x41\xf2\xeb\xcb\x3d\x1d\xbe\x2f\x37\xc4\xb3\xaf\x31\x78\xaf\xce\x20\x79\xef\x98\x14\xdb\xc5\x43\xec\xfa\xd2\x89\x66\x3e\xe0\x44\x3b\x84\x24\xeb\x31\x72\x6f\xac\x53\x2a\x73\x2f\x55\xff\x50\xef\x66\xc7\x96\xaf\x82\xfb\x6d\x29\x14\xeb\x25\x9e\x1e\x9c\xe3\x33\x9f\xa0\x5b\x38\x41\xad\x4a\x12\xeb\x4e\xd2\x63\x1c\xa4\xe7\x3d\x40\x0f\x65\x54\x8f\x1b\xe5\xbb\x57\x21\xdd\xa3\x5b\xcf\xa5\xfa\x6e\xce\x98\x60\x37\x29\x52\x0b\x0a\x26\x97\xe4\xc4\xed\x8d\x3a\x28\x89\x95\xc2\xfb\x10\x06\xdf\x07\x0d\xb8\x98\x07\xba\x28\x2c\x54\xa5\x48\x33\x48\xbb\x30\xde\x01\xc1\x2c\xcb\x25\xad\x5c\x41\xb5\x5c\xde\x8b\x7b\xaa\x72\x72\x7e\x73\xbd\x1f\x6a\xd0\xc3\xcf\x1a\x31\xa9\x5b\x46\xaf\xa6\xa7\x75\xec\xe9\x0a\xea\x31\x28\x81\x4d\xc6\xdc\xe8\x58\x7a\x99\x99\x54\xaf\xb4\x54\x30\xdc\x65\xd9\xb3\x6c\xcf\xad\x1b\x29\x61\x98\x82\xc8\xcc\xd0\xc2\x57\x6b\x71\xe5\xf8\x5e\xbd\x7a\x85\xa6\xb0\x57\xbf\xfd\xed\x6f\xb1\xbc\x64\xce\x32\x5e\x2e\x37\x84\x56\xff\xeb\xf5\xeb\x11\xf9\xaf\xf3\xf7\xef\x5c\xf9\x1f\x8d\x59\x49\x70\x64\x80\x7b\xda\x59\x0f\xc8\xff\xb9\xfd\xf6\x43\x2c\x0d\xd2\xfc\x15\xb6\x35\x2c\x6f\x44\x2e\x13\xff\xa7\xd4\xd0\x45\xcd\xcc\x55\x75\x34\x84\x4e\x26\x88\x18\xbe\x3e\x89\x3b\x70\x3e\x7a\x9c\x4f\x67\xbe\x1c\x98\x45\x89\x02\x1c\xb3\xac\x4a\x8e\xa6\x41\x9f\xd9\x00\xfd\xcc\x60\xac\x40\x26\x61\x2a\x03\x52\xf0\x3b\x46\x26\x1a\x8a\x82\xc5\xf4\x7f\x8a\x69\x2b\x94\xba\x22\xd8\x38\x58\xdc\x19\xcd\x3a\xe7\x7a\x78\x8c\x1b\xa0\xce\x65\x88\x9a\xa6\x7b\x77\x86\x7c\xfa\x56\x97\xbb\xd8\xfb\x92\xe2\x11\xb4\xd0\x7a\x9e\x1b\x99\xc6\x5c\x6f\xc2\x6c\x70\xeb\x5c\x96\x80\x48\x27\x68\x21\xa1\x9c\x69\xd8\xe9\xc8\xc5\xbc\xcb\xc1\xa2\x62\xdb\x97\xd2\x3b\xf9\x62\xdf\x04\xbc\x48\xa8\xde\xd3\xce\xd5\xf5\x9a\xfe\x22\xbe\x77\x23\xaf\x02\x1d\xcb\xda\xf8\x3b\x6c\xf7\x3b\x04\x60\x1b\xe9\x41\xd4\xf1\x63\x3b\x64\x9e\xdc\x25\x03\x71\xef\x24\xa6\xcd\xfb\x66\xe0\x09\x4d\x51\x62\x40\x18\xcd\x66\xe4\x8e\x2d\x86\x48\xb7\x2a\x0a\xd1\x3c\x58\x84\xc8\xc2\xa2\x51\x61\x2a\xa9\xb5\x76\x11\x40\xe6\x1d\x03\x12\xee\xe3\xa3\x81\xbc\x10\xaa\x9d\xbc\xe4\xd2\x88\x8a\xc4\x52\xe0\x73\x55\xbb\x82\xeb\xfe\xb5\xab\x29\x70\xbd\x14\xa4\x62\xcf\x1b\xcb\x6d\x37\xbd\xe9\xcb\xd1\x1b\xc2\xd2\x41\xc7\xdd\x6a\xb1\xd4\xdb\xd5\x56\x77\xc2\x1f\x7c\x90\xfa\xec\xcc\x89\x47\x05\x54\x33\x76\x85\x15\x5d\x5b\x0f\xa5\x00\x88\x46\x10\x8d\x66\xa6\x76\xa0\xc1\xba\xa4\xb5\x28\x98\xd6\x84\xc3\x0a\x4b\xaa\xee\x98\x4f\x18\x43\x8b\x11\xb9\xb1\x93\x0c\xf9\xab\x30\x2d\xf2\xdc\x95\x8d\xa5\x8b\x46\x74\x90\xfd\xc8\xf1\x68\x74\x8c\x04\x7e\x45\xac\x50\x0f\xfc\xd8\x2d\xa7\xee\x0e\xb9\x74\x1b\x88\xf8\x9e\x56\x1a\x33\x03\x5b\x91\x0f\x32\x5f\x4b\x88\x82\x33\x33\xcf\xc0\x68\xe7\x24\x4a\xcb\xcb\xd9\x21\x01\xec\xae\x79\xcb\x77\xc9\x5a\xde\xe9\xde\xa2\xf9\xec\x9e\xad\x7c\xa7\x5c\xe5\xeb\x32\x95\xbb\x9d\x72\xa7\xad\x7f\x0e\xe7\x07\xa4\xd8\x2e\x7b\xa5\x79\xf5\x4f\xd3\x48\x09\x72\x47\x23\x4b\x4f\x27\x19\xd1\x25\x7d\x2a\xd8\x17\x25\x14\x5e\x4f\x56\x15\x81\xf5\xc1\x82\x89\xbc\xec\x69\x28\x16\xdb\x7a\x6e\x69\xb0\x5f\x2d\x17\xd2\x5b\x3c\x6c\x3f\x7d\xc4\xc5\xf6\xd3\xed\x32\xb0\xfd\x34\x15\xb6\x24\x2c\x29\x10\xfd\xd4\x8b\x1f\x40\x6a\x24\xe4\xec\x8e\x47\x70\x44\xde\x3b\xa6\x80\xc8\x48\xc7\x5a\x16\xb5\x09\x91\x4c\x2b\x38\x06\x0c\xea\x33\x7c\x63\x48\xa9\x6f\x96\xf0\x0f\xe0\x9c\x48\x96\xfb\xb2\x12\x7c\x76\x3a\xe2\x7d\x8b\xd1\xfd\x64\x9d\x49\x1e\x00\x43\x2f\x4a\xec\x0c\x47\x3f\x40\xc8\x3b\xe1\x7d\xa9\x1b\x32\x0e\x78\x92\x18\x8d\x02\x94\x17\x57\x5c\x1d\xa8\xde\x4b\xec\x66\xb5\x71\x73\x75\x86\x89\xf3\x9b\xeb\x9d\x34\x80\xa4\xff\x1a\x1d\x20\x6d\xf1\x13\xd6\x02\xae\x51\x0b\x48\xcb\xee\x5c\xc6\x95\x3b\x93\xb2\x25\x3b\x2f\x5e\x8c\x5c\x9a\xf6\x5b\x4b\x2c\x53\xa7\xd3\x66\x0e\x3d\x34\xf6\x44\xb2\x9a\xe4\xdd\xf3\xb7\x8e\x70\x88\x5f\xba\xc8\xf9\x84\xe2\x23\xc0\xa3\x93\x77\x63\xfb\x59\x2e\x76\x07\x8b\x25\xb7\x50\xda\x06\xf5\xc1\x44\xb1\xac\x64\xfe\x06\xab\x42\x40\xed\x38\x2c\x0a\x33\xc0\xda\x38\x7a\x80\x0a\xa3\x95\x22\x92\xbb\x62\x95\x98\xdc\x77\x96\x1b\x76\xaa\x72\xf4\x90\x3a\x47\x76\x03\x61\xe5\x37\x7d\x77\x91\x3c\xb0\x6c\x11\x49\x58\xd3\x6e\x85\x50\x1a\x7b\xea\x46\xf2\x1b\xa8\xb3\x19\x2b\x29\xe6\xf0\xf3\xcb\xb3\x54\xe6\x5e\x71\x63\x18\xe6\x52\x62\x0a\x6a\xbe\x0e\x1a\x77\x06\x47\xf3\xd7\x47\xbb\x94\x83\x79\x60\xc5\x1e\x12\x77\x61\x0f\xc0\xb8\x69\x88\x6c\x16\xaf\x41\x97\x28\x20\xf1\xa6\x68\x19\x24\x2c\x83\x99\x23\xf4\x9e\x7c\xe1\xfb\xd0\xa3\x76\xd5\x9f\x06\x41\x60\x38\xe8\x4f\x07\xfd\x69\x2f\xfa\x53\xc2\x58\x3c\xc1\x59\xa1\x4b\xa5\x0e\xc3\x5e\xa1\x8a\x81\x4c\x49\x02\x1e\x8b\x9a\x5e\x95\x8a\x95\xd2\xd1\xe2\x66\xf5\xa1\x63\xaf\x60\x39\x3c\xae\xcd\x64\xf8\x3b\xc2\x44\x26\x73\xdc\x7c\x3b\xbe\xd2\x06\x44\x9b\xa8\x93\xa4\x73\x29\xfd\xb7\x52\xab\x1d\x8c\xbd\xeb\xd6\xed\x44\x07\xfc\x55\xe0\xdb\x3d\x31\xf8\xc8\xd6\x43\x30\xb1\x5b\x7e\xc8\x35\xe0\xf8\x7b\xbc\x84\xc4\xaa\xd3\xa1\x08\x3e\x94\x8e\x3d\xc1\x97\xa3\xac\xaa\x07\xae\xc1\xa8\x64\xa5\x54\x8b\x41\x68\x64\x7f\x6c\xf4\x72\x2d\x4e\x41\x26\xc8\x6a\x65\x35\xc0\x62\xf1\xa5\x4a\x07\x1e\x40\x4f\x2c\x1c\x84\x7d\xea\x57\x34\x28\x7d\x9a\x28\x11\x93\x8a\x81\x7e\x1f\x8b\x28\x4d\x42\xca\x43\x3d\x88\x6a\xa7\x7d\xcb\xc4\x9c\xcc\xa9\xea\xe0\x89\xb7\xea\x79\xa0\x3c\x90\xf3\x39\xd7\xbb\xd5\x3b\x6c\x2d\xfd\xd6\x31\x0d\xb4\xeb\xc8\xda\x54\xb5\x71\x94\xd2\x9f\x0a\x1f\x32\x1f\x4e\x43\x4b\x28\x7a\x7d\xb4\xd3\x34\xbe\x98\xfa\xc2\xf8\xec\x58\x65\x18\x9f\x87\xd6\x1a\x6e\x8e\xb2\x33\xda\xec\xb5\xb0\xb8\x7f\x3c\x5a\xec\xe3\x1c\x46\x16\x19\xf3\x3c\x78\xe1\xf4\x89\x0e\x1a\xba\x9b\xec\x64\xb7\x71\x19\xea\x57\x9b\x6c\xdc\x8f\x3f\x61\x6b\xcd\x7e\xef\x6c\x5d\x7c\xe1\xbf\xf8\x85\xed\xad\xab\x67\x70\xb8\xad\xed\x84\x82\x87\xdb\xda\xc3\x6d\xed\xe1\xb6\xf6\x60\x6d\x38\x58\x1b\x0e\xb7\xb5\xe4\x70\x5b\xbb\x17\x18\xee\xef\xb6\x16\x45\xbd\x55\x77\xb6\x4e\xd8\x8b\x17\xb6\x4f\x7a\x5f\xeb\x0a\xf7\x9c\x67\x99\xac\x85\xf9\x24\xef\x58\xe7\x4b\x87\x96\xfc\xbf\x34\x0e\x24\x40\x58\xa3\x0f\x2c\x37\x7e\x32\xe5\xa0\xbf\x54\xd2\x4b\xb6\xd8\x45\xaa\xa0\x75\xce\xad\xe4\xbf\x33\x9a\xf9\x01\xd2\xe4\x44\x22\x67\x79\xfc\xc1\x1d\x65\x63\x61\x3d\x22\xe7\x44\xb1\x8c\x57\xdc\x95\x91\xa7\xf8\x1e\x11\x2f\xd4\x46\xe0\x46\xb3\x62\xe2\x72\xd4\x8b\xb4\xd6\x4f\x94\xdf\x1d\x1d\x5c\xf9\x19\xe4\x50\xd2\x67\x32\xf7\xb5\x90\x14\xfb\x9b\x67\x6d\x6e\x36\x9f\xd2\x11\x52\xf3\x0a\x2c\xa5\x51\x62\x08\x3e\x56\x71\x17\x60\xfd\xd8\xc7\x9f\x7d\xae\xb8\x02\xe4\xbd\x65\x99\x14\x5d\x6a\xaa\xae\xd9\xa0\xa5\x91\x22\x7f\x02\xdb\x28\xcb\x49\x5e\xab\x50\x33\x75\x4e\x0b\x9e\x73\xb3\x08\xb7\x76\xae\xbc\x16\xc5\x13\x13\xb6\x51\x47\x30\x12\x5a\x55\x4a\xd2\x6c\xc6\x74\xf2\x35\x14\x50\x5c\x10\x59\xf0\x7d\xc7\x12\x70\x20\xa3\x40\x1f\xcb\x20\x8b\x05\x51\xd2\xf8\x8b\xf7\x35\x1f\xfc\x94\x0c\x06\xdd\x91\xcb\x19\xb5\x80\xdb\x79\x99\x0e\x81\xb3\xe2\x93\xf4\x0f\x4d\x64\x91\xfb\x14\x26\xbf\x7b\x65\x85\xc2\xcc\xe1\xa0\x25\x7e\x90\xe0\xc2\x48\x52\x58\x86\x6d\x09\xe2\xfa\xce\xbf\xfa\x35\x99\xc9\x5a\xe9\x51\x9a\x74\xe0\x35\xbc\x43\xfd\xce\x0b\x95\x86\x14\x8c\x6a\x43\x5e\xbf\x22\x25\x17\xb5\xe5\x53\xbd\xd1\xa6\xbf\x1c\x94\x48\x40\xbf\xf9\x75\xe7\x7e\x7d\x65\x9f\xb5\x52\x4f\x85\xb9\x91\x9d\xe8\xe3\x4e\x12\x06\xc6\x61\x66\xf1\x96\x20\xe4\x88\x6e\x0a\x6d\x61\xe4\x23\x9c\xaf\x1f\x6b\x39\x5e\x98\x3e\x41\x94\xae\x47\x33\x7a\xf2\xff\xba\x97\x5d\x92\xa7\xc4\xdc\x29\x1b\x3f\xfa\x28\x15\x2e\xa6\x5c\x9b\x2d\xf5\x2d\x62\x7c\xe5\xc6\x66\xdd\xd9\xca\xd4\x6a\x07\x3d\x63\x65\xa0\x8f\x97\x88\xbd\x6d\x29\xcb\x18\x16\xb3\xbc\x8c\x95\x92\x84\xc4\xb6\x5b\x87\x7f\xe6\x84\x63\x1e\x41\xf6\x90\x35\xbd\xe3\x52\xbb\x09\x5d\x1e\x25\x7a\xaf\x15\xbb\x35\x4f\x81\xe6\x62\x8a\x49\xce\xcb\xba\x30\xbc\x2a\xe2\xba\x3f\xfa\x0e\x8e\x90\xa7\x36\x37\x9a\x98\x89\x28\x06\x16\x63\xb6\x29\xb0\x4f\x9e\x84\xb1\x98\x30\x98\xab\x5b\x59\x7e\x50\x51\x45\x03\xf0\xa0\x92\xae\x3e\x75\xe6\x3b\x0a\x37\x8a\x2e\x1d\xa6\xed\x45\x8b\x38\xe3\xe4\x16\x69\x9f\x48\x63\x98\xa0\xa2\x83\xa9\xba\x99\x9e\x0b\x3a\x11\x79\x1f\x9c\xc9\xb0\x0c\x4a\x0b\x5b\x9c\x50\xf3\x15\xcd\xee\x98\xc8\xb1\x68\x14\x2c\x3b\x5f\x08\x5a\xba\x6c\x5b\x49\x3d\xee\x56\x7f\x3d\x70\x86\x09\x0c\xdf\xf3\x61\xc6\xc8\x75\xf7\x09\x83\x5a\xf7\x4e\x65\x63\xbb\x6c\x3b\xe7\x1a\x4d\x36\x8a\xcf\x33\xe6\xf9\xbf\xed\xb7\xcf\xa9\xcf\x3b\xc4\xd2\x2f\x4d\xde\x6f\x4f\x82\xbf\x40\xee\x83\xe5\x1c\x92\x6a\xd1\xc2\x1e\xed\x45\x88\x19\x6d\x6d\xee\x78\xb1\xdf\xaa\x37\x6a\xdc\x27\xf2\xf7\x58\x8d\xf3\xe6\x21\xfe\x48\x73\xa9\xc9\x57\x85\xcc\xee\xc8\x25\x03\xa1\xeb\x31\xcb\xb3\xa8\x71\xfe\x9c\x29\xbc\x4b\x3a\xdd\x76\xcf\x36\x24\xa5\x14\xdc\x48\xb5\x99\x5e\x3c\x5d\xd9\xc9\x43\xba\xe7\xb5\x19\xaa\x2c\x36\xbf\xe4\x64\xcf\x16\xdd\xfa\x6e\x3c\x74\x0a\xea\x19\x9c\x4e\x7c\xe5\xaa\x80\xed\x78\xd6\x7e\x3e\x93\xf7\x43\x23\x87\xb5\x66\x43\xde\xe1\x42\xb7\xc7\x32\xef\xd8\x02\x6e\xb1\x7b\x2e\xd4\x75\x6b\xe8\x0c\x46\x82\x05\x0a\xde\x5b\xce\xfd\xf1\xab\xcb\xef\x34\x53\xa3\x54\x06\x3c\x63\x26\x3b\xcb\x58\x35\x3b\x73\x23\xbc\x48\xa0\x78\x22\xd2\x17\x2a\xbe\x1f\xb2\x99\x4c\x16\x85\x0b\xcc\x96\x13\x72\xc1\xaa\x59\x18\xf8\xa9\x57\xfd\x7c\x19\x81\x2b\x29\xfb\x26\x42\x3d\xb6\x7d\x9a\x87\x08\xde\xe0\x19\x4a\x90\x49\x8d\xfb\x15\xa1\x78\x2a\xf4\x79\xd1\xa5\x36\x1f\x11\x38\x8f\x9b\x4e\xf9\xb8\x91\x4f\x39\xf5\xf7\x6c\x26\x4b\xf6\x1e\x23\x0d\x12\x74\x3d\x41\xa1\x3b\x67\x39\x91\x73\xa6\x14\xcf\x99\x26\x81\x06\xa5\x5a\x2a\x2f\x9e\x1a\x6e\x87\xbc\xcd\xcf\x9e\xb7\x79\x07\x75\xe8\x18\xf4\xa1\x06\x99\x82\x37\x4b\x64\x8a\xe6\x25\x17\x2f\x8e\x50\xe9\x8c\x16\xec\xfa\xdb\x1e\xfa\x87\xeb\xd1\x54\x41\x6e\xdd\xcb\x24\x7f\xda\x96\xac\x64\xdf\x04\xbc\x21\x42\xe6\xdb\x4c\xaa\x8f\xa0\x48\x4c\xa9\x61\xf7\x5b\xd9\xe1\x30\x12\xaa\xed\x2d\x41\x38\x7d\x4e\x95\xe3\x45\xe4\x08\x4c\x70\x1e\x93\x9e\xed\x93\xa9\xba\x5d\xeb\x6b\x9c\xc4\x5e\x69\xfa\xdd\x76\xd2\x5d\x8f\xc1\xe7\x37\xd7\xe4\x6b\x6c\xbe\xdf\xec\x85\x4a\x1a\x14\x03\x2f\x65\x49\x79\xdf\x22\x1b\xed\xee\xed\xec\xab\xe9\x12\x6e\x42\x5b\xe2\x1a\x27\x05\x5c\x26\x7c\x5a\x5b\x9d\xce\xe9\x61\x2f\x2a\xc1\xdc\x92\xe8\xf2\x72\x13\xcc\x3d\xbc\x1a\x44\x62\x72\xf2\x7e\x91\x51\x62\xf1\x5b\x09\xac\x24\xdc\x81\x12\xcd\x84\xe6\x70\x21\x93\xdc\x8a\xbb\x4a\x7f\x58\x5a\x12\x9d\x20\x51\xc4\x19\x90\x77\x72\xca\x85\x3f\xbd\xd2\xdd\xd7\x4d\x28\x2f\xba\x02\xe3\x20\x93\x3c\xbb\x4c\xa2\x75\x71\x25\xe8\xb8\xe8\xe2\x6e\xd0\x44\xb5\xd0\x91\xbc\x2d\xe8\x94\x30\xf8\xe3\x2c\xe7\xda\xfe\x9f\xdc\xde\xbe\x03\x23\x7c\x2d\xbc\xc4\x0c\x06\x6a\x47\xfb\x42\x90\x02\x1e\xc4\xfd\x9e\x1d\x24\x3d\x3b\x64\xff\x4b\x7a\x12\x2e\x72\x3b\xf1\xa4\x14\x1c\x3a\x49\x41\x0b\xcc\x87\x18\x7c\x7e\xd1\x6d\x60\xcc\xc8\xa7\x19\xcf\xee\x6e\x12\xbb\xbb\x54\xf6\x9d\x48\x5e\x35\x18\x58\xfb\xb7\x7d\x52\x4b\x37\xd5\x9b\xfe\xaa\x71\xd2\xd3\xf3\x01\x4f\x30\x6e\xdd\xfa\xe1\x37\xaa\xb5\xcc\x78\xbc\x73\x01\x1b\x4d\x64\x0e\x39\x30\x87\xfd\xae\x09\xc4\x83\xbe\xcb\x41\xf9\x63\x05\x47\xf3\xbb\xe9\xab\xe3\xea\x94\x83\x71\xe1\x57\xbd\xd7\x25\x20\xce\xec\x90\x1a\x3d\x76\x5c\x4e\x8d\xee\x85\xe1\xd6\xc5\x82\x77\x53\x77\x9b\xe7\x05\x31\x5f\x9b\x73\x69\xfb\x42\x8a\x74\x97\x9a\x70\x6f\x0b\xef\x12\xb6\xb1\x4a\x0d\x6f\xdd\x26\xe2\x3b\x77\xd5\x00\x67\xae\x92\x55\x5d\xa0\x3f\xc7\xc3\xf3\xbb\x7b\x9b\x31\x7e\x67\x4f\x57\x0f\x4f\x91\xb5\xf4\x38\x75\xec\xed\xef\xe9\xfc\xd3\xc8\x5d\x9a\x08\x77\xaf\x7e\xf3\xeb\x5f\x7f\xe9\xd9\x4c\xbb\xaa\xe0\x8f\x91\xce\xb4\xa3\x89\x76\x45\x7c\xd1\xf5\x21\xbe\xe8\x5f\x37\xbe\xe8\xf1\xb3\xd0\xee\x39\x82\xa8\xa7\x6f\x6e\x3f\xbf\xdc\xee\x31\x42\x9d\xbd\x77\xfb\x7a\xee\xf6\x88\x02\xda\x6f\xec\x4f\x6f\x5f\xd6\x3e\x71\x3e\x87\xe8\x9e\x9f\x6a\x74\xcf\x2e\xbe\xac\xfd\x23\x79\xfa\xf8\xb0\xfe\x14\xa3\x76\x7a\x1c\xce\xee\xd1\x25\x0f\x8e\x29\xe9\x9f\x04\xb0\xbf\x3d\x6d\x97\x82\x54\xb1\xe7\x4a\x0d\xd2\x07\x95\xfb\xdc\x63\xc7\xc7\x3a\x49\x2d\x66\xa4\x3d\x81\x4f\xa2\x90\x90\x1e\xda\x18\x0e\x2f\xfb\xd4\x86\x74\x7d\xbe\xbd\x6d\x5d\xcc\x84\xd7\xcf\x73\x1f\xf3\xaf\x70\xe1\x71\xa8\xe9\xf2\x85\x98\xdc\x75\x23\x5b\x8b\xb7\x56\x00\x09\x00\x46\x2e\xc7\x69\x96\xc8\x78\x74\xce\x6f\xae\xad\x0e\x0e\x61\x44\xb4\xd0\x23\xb2\x82\xcf\x7b\x73\xa9\x93\x0b\x3c\x7f\xa7\xc6\xb0\xb2\x32\xdd\x77\xfd\x60\x71\x7f\x76\x8b\xfb\x1e\x2d\x80\xb3\xba\xa4\x62\x68\x4f\x14\xd8\xdc\x1b\xb7\x75\x2d\xca\x3c\x22\xee\xec\x20\x7b\x02\x0b\x08\x04\x17\x34\x0b\x1b\xd3\xa4\xcc\xe5\xe3\x98\x3d\x61\xec\x9d\x57\x8e\x7c\xb5\x75\xd2\x32\xb9\xe4\xf0\xea\x96\x13\xa0\xe0\x0f\x55\xc2\x9c\x1b\x6a\xb8\x99\x31\xe4\xe1\x37\x10\x90\x13\x5b\x35\x25\x69\x14\xa5\x69\x51\xc8\x7b\xfc\x76\xca\xd7\x2c\xf4\xed\x5c\x5c\xa4\xd9\x98\x91\x92\x5b\x1d\xdd\x19\x58\xd3\xe9\xe0\x95\xa9\x95\xc8\x99\x42\x81\x57\xb9\xcb\xb6\x5b\x66\xdc\x46\xc1\x46\x5b\xfd\x56\xa0\x43\xb8\xfd\xb7\xf7\x2a\x82\x6f\x7b\x9a\x30\x66\x33\x3a\xe7\xb2\x56\xd8\xdb\x48\x72\xe4\x7e\x02\xde\xb0\x90\x75\xb0\x77\x61\x31\xcc\xb0\x3a\xbd\x02\x4e\x1f\xe2\x8f\xa0\x0a\xe4\xd2\x9b\x26\x86\xec\x33\xd7\x66\x79\x2d\x1e\x44\x3e\x0d\xde\xbe\xf0\x66\xae\x2b\xcb\x16\x7a\x57\xb5\x6b\xf4\x6b\xca\x2b\xf3\x5b\xf8\xe9\x0b\xaa\x69\xb7\x35\xbb\xeb\x93\x89\x40\xff\x82\xe2\x4f\xb8\x09\x2b\x78\xb6\xe8\x5d\xee\xad\xd5\xdb\x13\x6d\x1d\xee\xd0\xec\x7b\xf2\x15\xd5\x2c\x27\xef\xa9\xa0\x53\xd4\xf7\x4e\x6e\x6f\xbe\x7a\x7f\x6a\xf7\x15\xf4\xc9\xeb\xcb\x95\x17\x6d\xb7\xe9\xe0\x1f\xf6\x19\x2f\xb2\xb4\xf0\x1d\x58\xd5\x52\xff\x1d\x17\xbf\xd7\x40\x18\x12\xf8\x50\xb7\x64\xbd\x2b\x58\xd0\x4d\x3b\x84\xb5\x5d\xf3\xb3\x45\x60\xe6\x65\xfe\xc0\x2a\x9f\x5c\x68\x43\x8b\xe2\xa6\xa0\xe2\xbc\xaa\x94\x9c\xaf\xd6\xc6\x1b\x73\xf5\x0d\xfd\x4c\xd1\xcd\xc3\xbf\xac\x10\xf4\x70\x85\x2d\xc8\x75\x1c\x7f\x44\xae\x4d\xd0\xc2\xa5\x00\x96\x7a\x74\x5e\x1b\x59\x52\xc3\xb3\x23\xab\xac\x1f\xbd\xa7\xa2\xa6\xc5\x4a\xa7\xab\x8d\xcb\x58\x27\x22\x6e\xec\xb4\x3e\x75\x5d\x87\x6e\x1b\x65\x8d\xcd\xfd\x0d\x55\x96\x3a\x5d\xdc\x7e\xdf\xab\xaf\x36\xd4\xd4\x4b\x54\x78\x03\x67\x58\xcf\x0b\x86\xa4\xa0\xda\x7c\x57\xe5\xf6\xd0\xb7\x7e\xdd\x44\xf0\x33\x6a\x68\x21\xa7\x7f\x64\xb4\x58\x8d\xe1\x0d\x3c\xb9\x48\x5b\x7b\x03\x94\xbb\xf0\xaf\xc7\xa1\xe1\xb1\x26\x56\xc0\xf6\x31\xf0\x8a\x15\x6c\x4e\x85\xf1\xdd\xb1\xb8\xba\x3e\x76\xeb\x07\x2c\xe2\xd1\xf8\x9a\x33\xc3\x54\xc9\x45\x73\xcc\x5b\x68\x7b\x21\x45\xce\xd1\xec\x08\x06\x35\xec\xd1\x1c\x77\x3d\xaa\xad\xbb\x69\xd8\x70\xb7\xd0\xcc\xae\x99\xcc\xa7\x09\x0a\x6c\x36\x76\xf2\xe5\x0c\x5f\xc2\x4d\x7b\x63\x6e\x4b\x90\x22\x77\xc2\x0a\x86\x90\x47\x64\x35\xd9\xda\x2a\x27\x6c\x93\x0f\x86\x7e\x8f\x71\x0a\xeb\x1d\x47\x87\x6e\xde\xeb\xee\x20\x36\xa1\x18\x3e\xdb\x25\x8b\xf6\x54\xd6\xd3\xd4\x55\x78\x17\xba\x61\x24\x4b\xab\x20\x7f\xa3\xd1\x7a\x1e\xd0\x49\xf0\xea\x26\x23\x75\xcd\x6a\xdf\xa4\xb5\x31\x07\xfb\x92\x2a\xdb\x41\x62\xdc\xca\xb4\x3a\x26\x97\x6f\x2a\xd6\xd7\xce\xff\x4f\x39\x55\x84\x92\x8a\x33\x4c\x7e\x42\x85\x03\x16\x70\x16\x46\x73\xf7\xd2\x72\x30\xab\x12\xc2\x6f\x03\x77\x19\x8e\xc6\x65\xe7\x6b\xe1\x0d\xd4\x14\x93\x7f\xc0\xc5\xc5\xd9\xd7\xd2\x19\x79\x5d\x90\xae\xa5\x01\xc0\xc9\x07\x44\xd7\xd9\x8c\x50\x6d\xa7\x66\x11\xda\x9e\x78\x36\x2a\xa9\xe0\x13\xa6\xcd\x28\x64\x09\xd6\x7f\xfa\xd5\x5f\x46\xe4\xad\x54\xc4\x39\xaa\x0f\x7c\x56\x0d\x37\xcf\x88\x17\x5c\xe3\x62\x42\xdf\xa8\xb5\x56\x32\x77\x93\xbe\x87\xc9\x1a\x7a\x67\x79\x18\x4e\xb6\x66\x70\x75\xf1\x86\x1c\x59\x31\x31\xf9\xf4\x3f\x2c\x5b\xfa\xe7\x11\x39\xb9\x07\xa6\x7d\x64\xff\x3c\xc2\x0f\x06\xb7\xc9\x54\xa9\x8e\x1f\xc6\x60\x49\xc5\xa7\x53\xa6\x50\x7d\x24\x10\x54\x78\xea\xb2\x82\x08\x99\x34\xf6\x97\xd2\x51\xdd\x6c\x4f\xe4\x4f\xbf\xfa\xcb\x11\x39\x69\xae\x8b\x70\x91\xb3\xcf\xe4\x57\x68\x5d\xe6\xda\xae\xf1\xd4\x5d\xe6\xe8\x85\x30\xf4\xb3\x1d\x33\x9b\x49\xcd\x04\xaa\xf2\x46\x92\x19\x9d\x33\xa2\xa5\xd5\x80\x59\x51\x0c\x9d\x2d\x9d\xdc\x53\xc8\xd4\xe2\x41\x09\x81\xf5\xa4\xa2\xca\x34\x50\x62\xe4\x2c\x24\xf0\x35\xbb\x6d\x53\xe1\x6f\xa6\x27\x5c\xb8\xfb\x2b\x77\x73\x66\xf7\x1c\x02\x43\x71\x93\x8c\x24\xd9\x8c\x8a\x69\x88\x4d\x9f\xd4\xa6\x56\x6c\xcb\xd5\x4f\xc7\x33\x70\xc7\x45\xaf\x10\xe6\x6f\xb8\x68\x3b\x15\xac\xb6\x2b\x4d\xb9\xf1\x51\x11\xce\x57\xd1\x2c\xce\xec\x2e\x28\x3e\xae\x8d\x54\xfa\x2c\x67\x73\x56\x9c\x69\x3e\x1d\x52\x95\xcd\xb8\x61\x99\x5d\xd6\x19\xad\xf8\x30\x93\xc2\xee\x38\x64\x65\x28\xf3\x9f\x43\x79\xd3\xa1\x9d\xea\x96\xac\xd3\x1d\x17\xbd\xdd\xa8\xf6\xac\xc6\xb4\xbd\xad\xb1\x83\x3d\x68\x79\xa1\x68\x9b\x79\x82\xd5\x82\x21\xe4\x6c\x2f\x8b\xf5\x49\x93\xfb\xf3\x98\x63\x97\x07\x3c\x6b\x8f\x61\x8f\x1d\x3a\x90\xc0\xa9\x6c\x50\xca\x92\xe6\x48\x4a\xa9\x58\x3c\x3a\xf2\x5b\x90\x42\xba\xfc\x6c\x31\x84\x21\x64\x31\xa4\x22\xb7\xff\xc6\x80\x9d\x6c\xb1\x17\x18\xd6\xbc\x17\x21\xf8\xee\xfa\xf2\x69\x8e\x44\xcd\xf7\x70\xea\x9d\xbc\xd6\x51\x88\x42\x51\x15\x1d\x35\x54\xcd\x3c\xd3\x6c\x0a\xa8\x5c\xfb\x51\xff\xc3\xdd\xbf\x84\x6c\x67\xdb\x44\xaa\xcd\xb7\x26\x89\xec\xd8\x71\xbe\xef\x62\x8f\xd4\x26\x07\x8e\x57\x54\x1b\x97\x5a\xcb\xe7\x20\x68\x2c\xc3\x2b\x28\xc0\x60\xd6\x5f\x0c\x77\xc2\x21\xef\x2f\x60\x27\x32\x5c\x99\x73\x29\x0b\x4a\xc9\x76\x05\x2a\xea\x2f\x8d\x3a\x68\xb8\x28\xc3\xb4\x21\x74\x4e\x79\x01\xd6\x79\x39\xd6\x4c\xcd\xb1\x20\x95\x4b\x35\x48\xdb\x7a\x96\xab\x39\x81\x62\xd4\x13\x69\x3e\x7e\x0d\xcb\xbb\xb2\x69\x01\xa0\x0d\xb5\x66\xbf\x76\xd6\x7b\xd1\x7b\x50\xbd\x5c\xfb\xb3\xfd\xc2\x8e\x6a\x8c\xc5\xbf\x3f\x32\xaa\xcc\x98\x51\xf3\x89\x6f\xe2\xbb\x4b\x28\xdd\xe8\x17\x4a\xb9\x07\x84\xbe\x67\x64\x2a\x8d\x15\xb1\x6a\xc0\x7d\x94\x49\x31\xa9\x4f\x40\xb4\xc7\xc6\xe8\xb8\xca\x4f\x8a\x42\x88\x8f\x14\x3d\x97\xd9\xec\xb8\xbc\x4e\x27\x1d\x3b\x4c\x32\xd8\x1a\x13\x69\x48\xc1\xdc\xde\xe1\x6d\x06\x50\xa0\xa7\x59\x72\xc9\xb4\xde\x98\x60\xa3\xe9\x5d\x88\xad\xf1\x28\xb7\xae\xd6\x4a\xff\x1b\x86\x85\x58\x01\x3a\x67\x86\xf2\xc2\x1f\x65\x04\x45\x80\xd2\x36\xea\xba\x71\x81\x8a\x51\xbd\x49\x40\x68\xcc\xfa\x23\x34\xc6\x49\x4b\xc1\x86\xf7\x52\xe5\xe4\x82\x96\xac\xb8\xa0\x9a\xb9\xb1\xd2\x10\x3d\xdc\xa3\x63\xbd\xd7\x29\xaf\xb6\x7d\xad\x99\x32\x1a\x7f\xa2\x49\x18\xfe\x8a\x2a\x16\x4e\x70\xe0\x4d\x90\x9f\x54\xcd\x06\xe4\xad\xe5\x5e\x03\xf2\x9d\xb8\x13\xf2\xfe\x61\x73\x35\x1b\x6f\x41\x1a\x33\x4d\xdd\x3f\x7c\x5a\x9d\x86\xc1\x27\x4c\x77\xc7\x19\x39\x82\xbf\xc6\xd4\xd8\x64\x36\xa1\xa9\x9f\x91\xfd\xe7\x92\x09\xca\x2a\x8a\x4a\x4e\x15\xd3\x98\xb9\x66\x65\x92\xc4\xae\x26\xe7\xaf\x99\x70\xc1\x7d\x5b\xa7\x77\xbd\xaa\x97\x9f\xa9\xe7\x6b\xd3\xf8\x8b\xdb\x6f\xf7\xb1\xaa\x58\x29\x6a\x6c\xf6\x08\x4c\x26\xba\xc6\xf8\xb4\x6e\x86\xab\x8d\x4e\x09\xd7\x4b\xda\xa2\x50\xb2\xc9\x3a\xea\x57\x77\x71\xfb\xfd\x7a\x60\xaf\xe5\x7d\xdb\xf8\xd3\x76\xb3\xd4\x43\x0d\x52\x5b\xcf\xcc\x56\x23\xd4\xc1\xfc\x74\x30\x3f\x7d\x49\xe6\xa7\xad\x18\xbf\xc9\xe4\xf4\x65\x18\x9b\xb6\x2e\x71\x93\x81\xe9\x45\x9a\x96\x3a\xad\x68\xa3\x39\xe9\xc5\x1a\x92\xb6\x2e\xad\xa3\xf1\xe8\x5f\xc7\x6c\xb4\x15\x62\x1b\x4c\x45\x2f\xd0\x48\xd4\x45\x20\x63\x79\x17\x31\xf1\x3a\x69\x9c\x0a\x8a\xb1\x9c\x65\x18\xce\x3b\xe5\xa4\xe2\xcc\xae\xd2\xa2\x15\xe0\xb6\xce\xed\xd8\x4d\xae\xbb\xec\xe5\x04\x46\x57\xec\x71\x69\xb2\xe4\xf2\xea\xe6\xe3\xd5\xc5\xf9\xa7\xab\xcb\xb6\x7c\xb7\x0a\xd2\x5b\x24\xb1\xcd\x36\x88\x61\x22\x89\xad\x69\x60\x09\xf2\x9a\x9f\x2c\x0e\xac\xf9\xa9\xae\xf9\xaa\x5e\x0f\x97\x0b\x1f\xc4\xe5\x1e\xc4\x3f\xb6\x9f\xce\xae\xc7\xf3\x3b\x74\x9c\xa2\xce\xe7\xcc\xca\x3d\x33\x59\xe4\xda\xfb\xad\x5e\x5f\x86\x48\x2a\x2e\xb2\xa2\xce\xad\x70\xf1\xdd\x77\xd7\x97\x7a\x44\xc8\x57\x2c\xa3\xb5\x06\x2b\x4c\x2e\xc5\xb1\x21\xdf\x7e\x78\xf7\x5f\xe0\x8f\x0d\x2d\x06\x21\xaf\x09\x64\xe5\xe5\x14\x13\x0b\x1b\x4c\xd7\x46\xbe\x62\x28\xa8\xc0\x97\x33\x5a\x59\x2a\xa6\xb1\x72\x85\x01\x59\x64\xc6\x8a\xca\x52\xcc\x3b\x46\x62\x06\x55\x3b\x70\xac\x30\xef\xdd\x27\xa7\xcc\x60\xd4\xd5\x26\x0f\xc9\x8d\x50\xdb\x62\x71\x7d\x80\xad\xb5\xa1\x3e\x3a\x6d\xfc\x9e\x6a\x67\xb1\x5a\x39\xdb\x2d\xfb\xbb\xdd\x3e\xb3\xde\xc4\xb1\xc6\xb8\x81\xe4\x19\xfe\x5a\x9a\xb3\x9d\x6c\xb4\x63\xa0\x13\x09\x37\x9d\xad\xa9\xeb\xdd\x80\x56\xd7\x01\x58\xb2\x65\xb0\x36\x90\x1b\x1f\x0e\x1e\xd9\xc9\x94\xbb\xcd\x05\x8a\x88\xe4\x8d\xda\x9f\xce\x7f\xae\xf9\xae\x1e\x87\xea\xaf\x71\xbe\xce\x22\x43\xfe\xf1\xcf\x9f\xfd\xbf\x00\x00\x00\xff\xff\xab\xf2\x0f\xc7\x37\x6a\x02\x00") func operatorsCoreosCom_subscriptionsYamlBytes() ([]byte, error) { return bindataRead( @@ -311,11 +311,13 @@ var _bindata = map[string]func() (*asset, error){ // directory embedded in the file by go-bindata. // For example if you run go-bindata on data/... and data contains the // following hierarchy: -// data/ -// foo.txt -// img/ -// a.png -// b.png +// +// data/ +// foo.txt +// img/ +// a.png +// b.png +// // then AssetDir("data") would return []string{"foo.txt", "img"} // AssetDir("data/img") would return []string{"a.png", "b.png"} // AssetDir("foo.txt") and AssetDir("notexist") would return an error diff --git a/staging/api/go.mod b/staging/api/go.mod index afa9ff25f9..4120ad8147 100644 --- a/staging/api/go.mod +++ b/staging/api/go.mod @@ -1,95 +1,95 @@ module github.com/operator-framework/api -go 1.18 +go 1.19 require ( - github.com/blang/semver v3.5.1+incompatible github.com/blang/semver/v4 v4.0.0 github.com/ghodss/yaml v1.0.0 github.com/go-bindata/go-bindata/v3 v3.1.3 - github.com/google/cel-go v0.10.1 - github.com/google/go-cmp v0.5.6 // indirect - github.com/sirupsen/logrus v1.8.1 - github.com/spf13/cobra v1.4.0 - github.com/stretchr/testify v1.7.0 - google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368 - k8s.io/api v0.24.0 - k8s.io/apiextensions-apiserver v0.24.0 - k8s.io/apimachinery v0.24.0 - k8s.io/client-go v0.24.0 - sigs.k8s.io/controller-runtime v0.12.1 + github.com/google/cel-go v0.15.3 + github.com/sirupsen/logrus v1.9.2 + github.com/spf13/cobra v1.7.0 + github.com/stretchr/testify v1.8.3 + google.golang.org/genproto v0.0.0-20230525154841-bd750badd5c6 + k8s.io/api v0.27.2 + k8s.io/apiextensions-apiserver v0.27.2 + k8s.io/apimachinery v0.27.2 + k8s.io/client-go v0.27.2 + sigs.k8s.io/controller-runtime v0.15.0 ) require ( - github.com/PuerkitoBio/purell v1.1.1 // indirect - github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect - github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210826220005-b48c857c3a0e // indirect + github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df // indirect github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cenkalti/backoff/v4 v4.1.3 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/felixge/httpsnoop v1.0.1 // indirect - github.com/go-logr/logr v1.2.0 // indirect - github.com/go-openapi/jsonpointer v0.19.5 // indirect - github.com/go-openapi/jsonreference v0.19.5 // indirect - github.com/go-openapi/swag v0.19.14 // indirect + github.com/emicklei/go-restful/v3 v3.9.0 // indirect + github.com/felixge/httpsnoop v1.0.3 // indirect + github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-openapi/jsonpointer v0.19.6 // indirect + github.com/go-openapi/jsonreference v0.20.1 // indirect + github.com/go-openapi/swag v0.22.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/google/gnostic v0.5.7-v3refs // indirect + github.com/google/go-cmp v0.5.9 // indirect github.com/google/gofuzz v1.1.0 // indirect - github.com/google/uuid v1.1.2 // indirect - github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect github.com/imdario/mergo v0.3.12 // indirect - github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/kisielk/errcheck v1.5.0 // indirect - github.com/mailru/easyjson v0.7.6 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mitchellh/mapstructure v1.4.1 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.12.1 // indirect - github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.32.1 // indirect - github.com/prometheus/procfs v0.7.3 // indirect + github.com/prometheus/client_golang v1.15.1 // indirect + github.com/prometheus/client_model v0.4.0 // indirect + github.com/prometheus/common v0.42.0 // indirect + github.com/prometheus/procfs v0.9.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stoewer/go-strcase v1.2.0 // indirect - go.opentelemetry.io/contrib v0.20.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0 // indirect - go.opentelemetry.io/otel v0.20.0 // indirect - go.opentelemetry.io/otel/exporters/otlp v0.20.0 // indirect - go.opentelemetry.io/otel/metric v0.20.0 // indirect - go.opentelemetry.io/otel/sdk v0.20.0 // indirect - go.opentelemetry.io/otel/sdk/export/metric v0.20.0 // indirect - go.opentelemetry.io/otel/sdk/metric v0.20.0 // indirect - go.opentelemetry.io/otel/trace v0.20.0 // indirect - go.opentelemetry.io/proto/otlp v0.7.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.35.1 // indirect + go.opentelemetry.io/otel v1.10.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.10.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.10.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.10.0 // indirect + go.opentelemetry.io/otel/metric v0.31.0 // indirect + go.opentelemetry.io/otel/sdk v1.10.0 // indirect + go.opentelemetry.io/otel/trace v1.10.0 // indirect + go.opentelemetry.io/proto/otlp v0.19.0 // indirect + golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect - golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect - golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect - golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect - golang.org/x/sys v0.0.0-20220209214540-3681064d5158 // indirect - golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect - golang.org/x/text v0.3.7 // indirect - golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect - golang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717 // indirect - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + golang.org/x/mod v0.10.0 // indirect + golang.org/x/net v0.10.0 // indirect + golang.org/x/oauth2 v0.5.0 // indirect + golang.org/x/sys v0.8.0 // indirect + golang.org/x/term v0.8.0 // indirect + golang.org/x/text v0.9.0 // indirect + golang.org/x/time v0.3.0 // indirect + golang.org/x/tools v0.9.1 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/grpc v1.40.0 // indirect - google.golang.org/protobuf v1.27.1 // indirect + google.golang.org/grpc v1.54.0 // indirect + google.golang.org/protobuf v1.30.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect - k8s.io/apiserver v0.24.0 // indirect - k8s.io/component-base v0.24.0 // indirect - k8s.io/klog/v2 v2.60.1 // indirect - k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42 // indirect - k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 // indirect - sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.30 // indirect - sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/apiserver v0.27.2 // indirect + k8s.io/component-base v0.27.2 // indirect + k8s.io/klog/v2 v2.90.1 // indirect + k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // indirect + k8s.io/utils v0.0.0-20230209194617-a36077c30491 // indirect + sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect sigs.k8s.io/yaml v1.3.0 // indirect ) diff --git a/staging/api/go.sum b/staging/api/go.sum index c5357c9828..a15d6312c8 100644 --- a/staging/api/go.sum +++ b/staging/api/go.sum @@ -13,11 +13,6 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -26,7 +21,6 @@ cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4g cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -37,109 +31,53 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= -github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= -github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= -github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210826220005-b48c857c3a0e h1:GCzyKMDDjSGnlpl3clrdAK7I1AaVoaiKDOYkUzChZzg= -github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210826220005-b48c857c3a0e/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df h1:7RFfzj4SSt6nnvCPbCqijJi1nWCd+TqAT3bYCStRC18= +github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= -github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= -github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= +github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= +github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= -github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= -github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= -github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= -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 h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk= -github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= +github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= -github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -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/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= -github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= -github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= +github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= +github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-bindata/go-bindata/v3 v3.1.3 h1:F0nVttLC3ws0ojc7p60veTurcOm//D4QBODNM7EGrCI= @@ -147,36 +85,24 @@ github.com/go-bindata/go-bindata/v3 v3.1.3/go.mod h1:1/zrpXsLD8YDIbhZRqXzm1Ghc7N github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v1.2.0 h1:QK40JKJyMdUDz+h+xvCsru/bJhvG0UxvePV0ufL/AcE= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM= -github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng= -github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonreference v0.20.1 h1:FBLnyygC4/IZZr893oiomc9XaghoveYTrLC1F86HID8= +github.com/go-openapi/jsonreference v0.20.1/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= +github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -189,7 +115,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -205,15 +130,13 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= -github.com/google/cel-go v0.10.1 h1:MQBGSZGnDwh7T/un+mzGKOMz3x+4E/GDPprWjDL+1Jg= -github.com/google/cel-go v0.10.1/go.mod h1:U7ayypeSkw23szu4GaQTPJGx66c20mx8JklMSxrmI1w= -github.com/google/cel-spec v0.6.0/go.mod h1:Nwjgxy5CbjlPrtCWjeDjUyKMl8w41YBYGjsyDdqk0xA= +github.com/google/cel-go v0.15.3 h1:W1wIeGuEs81+lBVU+cQRg1hkRT58Q6bNxvM5yn008S8= +github.com/google/cel-go v0.15.3/go.mod h1:YzWEoI07MC/a/wj9in8GeVatqfypkldgBlwXh9bCwqY= github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -223,18 +146,15 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -242,287 +162,126 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 h1:BZHcxBETFHIdVyhyEfOvn/RdU/QGdLI4y34qQGjGWO0= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0 h1:e8esj/e4R+SAOwFwN+n3zr0nYeCyeweozKfO23MvHzY= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 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/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= -github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q= +github.com/onsi/gomega v1.27.7 h1:fVih9JD6ogIiHUN6ePK7HJidyEDpWGVB5mzM7cWNXoU= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_golang v1.15.1 h1:8tXpTmJbyH5lydzFPoxSIJ0J46jdh3tylbvM1xCv0LI= +github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= +github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= +github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= +github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= +github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= +github.com/sirupsen/logrus v1.9.2 h1:oxx1eChJGI6Uks2ZC4W1zpLlVgqB8ner4EuQwV4Ik1Y= +github.com/sirupsen/logrus v1.9.2/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= -github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= -github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= -go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= -go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= -go.etcd.io/etcd/client/v3 v3.5.1/go.mod h1:OnjH4M8OnAotwaB2l9bVgZzRFKru7/ZMoS46OtKyd3Q= -go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= -go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= -go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opentelemetry.io/contrib v0.20.0 h1:ubFQUn0VCZ0gPwIoJfBJVpeBlyRMxu8Mm/huKWYd9p0= -go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0 h1:Q3C9yzW6I9jqEc8sawxzxZmY48fs9u220KXq6d5s3XU= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= -go.opentelemetry.io/otel v0.20.0 h1:eaP0Fqu7SXHwvjiqDq83zImeehOHX8doTvU9AwXON8g= -go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= -go.opentelemetry.io/otel/exporters/otlp v0.20.0 h1:PTNgq9MRmQqqJY0REVbZFvwkYOA85vbdQU/nVfxDyqg= -go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= -go.opentelemetry.io/otel/metric v0.20.0 h1:4kzhXFP+btKm4jwxpjIqjs41A7MakRFUS86bqLHTIw8= -go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= -go.opentelemetry.io/otel/oteltest v0.20.0 h1:HiITxCawalo5vQzdHfKeZurV8x7ljcqAgiWzF6Vaeaw= -go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= -go.opentelemetry.io/otel/sdk v0.20.0 h1:JsxtGXd06J8jrnya7fdI/U/MR6yXA5DtbZy+qoHQlr8= -go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= -go.opentelemetry.io/otel/sdk/export/metric v0.20.0 h1:c5VRjxCXdQlx1HjzwGdQHzZaVI82b5EbBgOu2ljD92g= -go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= -go.opentelemetry.io/otel/sdk/metric v0.20.0 h1:7ao1wpzHRVKf0OQ7GIxiQJA6X7DLX9o14gmVon7mMK8= -go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= -go.opentelemetry.io/otel/trace v0.20.0 h1:1DL6EXUdcg95gukhuRRvLDO/4X5THh/5dIV52lqtnbw= -go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= -go.opentelemetry.io/proto/otlp v0.7.0 h1:rwOQPCuKAKmwGKq2aVNnYIibI6wnV7EvzgfTCzcdGg8= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.35.1 h1:sxoY9kG1s1WpSYNyzm24rlwH4lnRYFXUVVBmKMBfRgw= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.35.1/go.mod h1:9NiG9I2aHTKkcxqCILhjtyNA1QEiCjdBACv4IvrFQ+c= +go.opentelemetry.io/otel v1.10.0 h1:Y7DTJMR6zs1xkS/upamJYk0SxxN4C9AqRd77jmZnyY4= +go.opentelemetry.io/otel v1.10.0/go.mod h1:NbvWjCthWHKBEUMpf0/v8ZRZlni86PpGFEMA9pnQSnQ= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.10.0 h1:TaB+1rQhddO1sF71MpZOZAuSPW1klK2M8XxfrBMfK7Y= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.10.0/go.mod h1:78XhIg8Ht9vR4tbLNUhXsiOnE2HOuSeKAiAcoVQEpOY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.10.0 h1:pDDYmo0QadUPal5fwXoY1pmMpFcdyhXOmL5drCrI3vU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.10.0/go.mod h1:Krqnjl22jUJ0HgMzw5eveuCvFDXY4nSYb4F8t5gdrag= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.10.0 h1:KtiUEhQmj/Pa874bVYKGNVdq8NPKiacPbaRRtgXi+t4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.10.0/go.mod h1:OfUCyyIiDvNXHWpcWgbF+MWvqPZiNa3YDEnivcnYsV0= +go.opentelemetry.io/otel/metric v0.31.0 h1:6SiklT+gfWAwWUR0meEMxQBtihpiEs4c+vL9spDTqUs= +go.opentelemetry.io/otel/metric v0.31.0/go.mod h1:ohmwj9KTSIeBnDBm/ZwH2PSZxZzoOaG2xZeekTRzL5A= +go.opentelemetry.io/otel/sdk v1.10.0 h1:jZ6K7sVn04kk/3DNUdJ4mqRlGDiXAVuIG+MMENpTNdY= +go.opentelemetry.io/otel/sdk v1.10.0/go.mod h1:vO06iKzD5baltJz1zarxMCNHFpUlUiOy4s65ECtn6kE= +go.opentelemetry.io/otel/trace v1.10.0 h1:npQMbR8o7mum8uF95yFbOEJffhs1sbCOfDh8zAJiH5E= +go.opentelemetry.io/otel/trace v1.10.0/go.mod h1:Sij3YYczqAdz+EhmGhE6TpTxUO5/F/AzrK+kxfGqySM= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw= +go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= +go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -533,6 +292,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= +golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -545,7 +306,6 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= @@ -556,18 +316,10 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= +golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= +golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -575,11 +327,9 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -590,40 +340,22 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.5.0 h1:HuArIo48skDwlrvM3sEdHXElYslAMsf3KwRkkW4MC4s= +golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -633,32 +365,19 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= 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= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -670,56 +389,31 @@ golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= -golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -727,19 +421,15 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -759,7 +449,6 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -767,21 +456,12 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717 h1:hI3jKY4Hpf63ns040onEbB3dAkR/H/P83hw1TG8dD3Y= -golang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= +golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= +golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= @@ -799,11 +479,6 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -833,7 +508,6 @@ google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= @@ -843,22 +517,10 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201102152239-715cce707fb0/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368 h1:Et6SkiuvnBn+SgrSYXs/BrUpGB4mbdwt4R3vaPIlicA= -google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20230525154841-bd750badd5c6 h1:62QuyPXKEkZpjZesyj5K5jABl6MnSnWl+vNuT5oz90E= +google.golang.org/genproto v0.0.0-20230525154841-bd750badd5c6/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -871,17 +533,12 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag= +google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -894,40 +551,27 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= -gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 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= @@ -935,42 +579,34 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.24.0 h1:J0hann2hfxWr1hinZIDefw7Q96wmCBx6SSB8IY0MdDg= -k8s.io/api v0.24.0/go.mod h1:5Jl90IUrJHUJYEMANRURMiVvJ0g7Ax7r3R1bqO8zx8I= -k8s.io/apiextensions-apiserver v0.24.0 h1:JfgFqbA8gKJ/uDT++feAqk9jBIwNnL9YGdQvaI9DLtY= -k8s.io/apiextensions-apiserver v0.24.0/go.mod h1:iuVe4aEpe6827lvO6yWQVxiPSpPoSKVjkq+MIdg84cM= -k8s.io/apimachinery v0.24.0 h1:ydFCyC/DjCvFCHK5OPMKBlxayQytB8pxy8YQInd5UyQ= -k8s.io/apimachinery v0.24.0/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= -k8s.io/apiserver v0.24.0 h1:GR7kGsjOMfilRvlG3Stxv/3uz/ryvJ/aZXc5pqdsNV0= -k8s.io/apiserver v0.24.0/go.mod h1:WFx2yiOMawnogNToVvUYT9nn1jaIkMKj41ZYCVycsBA= -k8s.io/client-go v0.24.0 h1:lbE4aB1gTHvYFSwm6eD3OF14NhFDKCejlnsGYlSJe5U= -k8s.io/client-go v0.24.0/go.mod h1:VFPQET+cAFpYxh6Bq6f4xyMY80G6jKKktU6G0m00VDw= -k8s.io/code-generator v0.24.0/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w= -k8s.io/component-base v0.24.0 h1:h5jieHZQoHrY/lHG+HyrSbJeyfuitheBvqvKwKHVC0g= -k8s.io/component-base v0.24.0/go.mod h1:Dgazgon0i7KYUsS8krG8muGiMVtUZxG037l1MKyXgrA= -k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.60.1 h1:VW25q3bZx9uE3vvdL6M8ezOX79vA2Aq1nEWLqNQclHc= -k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42 h1:Gii5eqf+GmIEwGNKQYQClCayuJCe2/4fZUvF7VG99sU= -k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk= -k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 h1:HNSDgDCrr/6Ly3WEGKZftiE7IY19Vz2GdbOCyI4qqhc= -k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/api v0.27.2 h1:+H17AJpUMvl+clT+BPnKf0E3ksMAzoBBg7CntpSuADo= +k8s.io/api v0.27.2/go.mod h1:ENmbocXfBT2ADujUXcBhHV55RIT31IIEvkntP6vZKS4= +k8s.io/apiextensions-apiserver v0.27.2 h1:iwhyoeS4xj9Y7v8YExhUwbVuBhMr3Q4bd/laClBV6Bo= +k8s.io/apiextensions-apiserver v0.27.2/go.mod h1:Oz9UdvGguL3ULgRdY9QMUzL2RZImotgxvGjdWRq6ZXQ= +k8s.io/apimachinery v0.27.2 h1:vBjGaKKieaIreI+oQwELalVG4d8f3YAMNpWLzDXkxeg= +k8s.io/apimachinery v0.27.2/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E= +k8s.io/apiserver v0.27.2 h1:p+tjwrcQEZDrEorCZV2/qE8osGTINPuS5ZNqWAvKm5E= +k8s.io/apiserver v0.27.2/go.mod h1:EsOf39d75rMivgvvwjJ3OW/u9n1/BmUMK5otEOJrb1Y= +k8s.io/client-go v0.27.2 h1:vDLSeuYvCHKeoQRhCXjxXO45nHVv2Ip4Fe0MfioMrhE= +k8s.io/client-go v0.27.2/go.mod h1:tY0gVmUsHrAmjzHX9zs7eCjxcBsf8IiNe7KQ52biTcQ= +k8s.io/component-base v0.27.2 h1:neju+7s/r5O4x4/txeUONNTS9r1HsPbyoPBAtHsDCpo= +k8s.io/component-base v0.27.2/go.mod h1:5UPk7EjfgrfgRIuDBFtsEFAe4DAvP3U+M8RTzoSJkpo= +k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw= +k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f h1:2kWPakN3i/k81b0gvD5C5FJ2kxm1WrQFanWchyKuqGg= +k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f/go.mod h1:byini6yhqGC14c3ebc/QwanvYwhuMWF6yz2F8uwW8eg= +k8s.io/utils v0.0.0-20230209194617-a36077c30491 h1:r0BAOLElQnnFhE/ApUsg3iHdVYYPBjNSSOMowRZxxsY= +k8s.io/utils v0.0.0-20230209194617-a36077c30491/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.30 h1:dUk62HQ3ZFhD48Qr8MIXCiKA8wInBQCtuE4QGfFW7yA= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.30/go.mod h1:fEO7lRTdivWO2qYVCVG7dEADOMo/MLDCVr8So2g88Uw= -sigs.k8s.io/controller-runtime v0.12.1 h1:4BJY01xe9zKQti8oRjj/NeHKRXthf1YkYJAgLONFFoI= -sigs.k8s.io/controller-runtime v0.12.1/go.mod h1:BKhxlA4l7FPK4AQcsuL4X6vZeWnKDXez/vp1Y8dxTU0= -sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 h1:kDi4JBNAsJWfz1aEXhO8Jg87JJaPNLh5tIzYHgStQ9Y= -sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY= -sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.2.1 h1:bKCqE9GvQ5tiVHn5rfn1r+yao3aLQEaLzkkmAkf+A6Y= -sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2 h1:trsWhjU5jZrx6UvFu4WzQDrN7Pga4a7Qg+zcfcj64PA= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2/go.mod h1:+qG7ISXqCDVVcyO8hLn12AKVYYUjM7ftlqsqmrhMZE0= +sigs.k8s.io/controller-runtime v0.15.0 h1:ML+5Adt3qZnMSYxZ7gAverBLNPSMQEibtzAgp0UPojU= +sigs.k8s.io/controller-runtime v0.15.0/go.mod h1:7ngYvp1MLT+9GeZ+6lH3LOlcHkp/+tzA/fmHa4iq9kk= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/staging/api/pkg/manifests/bundleloader.go b/staging/api/pkg/manifests/bundleloader.go index 5d5bf2dc1a..94f14a22ac 100644 --- a/staging/api/pkg/manifests/bundleloader.go +++ b/staging/api/pkg/manifests/bundleloader.go @@ -51,6 +51,10 @@ func (b *bundleLoader) LoadBundle() error { // Add values from the annotations when the values are not loaded func (b *bundleLoader) addChannelsFromAnnotationsFile() { + if b.bundle == nil { + // None of this is relevant if the bundle was not found + return + } // Note that they will not get load for Bundle Format directories // and PackageManifest should not have the annotationsFile. However, // the following check to ensure that channels and default channels diff --git a/staging/api/pkg/operators/v1alpha1/catalogsource_types.go b/staging/api/pkg/operators/v1alpha1/catalogsource_types.go index 020fecc0ec..c4c7662d37 100644 --- a/staging/api/pkg/operators/v1alpha1/catalogsource_types.go +++ b/staging/api/pkg/operators/v1alpha1/catalogsource_types.go @@ -89,6 +89,11 @@ type CatalogSourceSpec struct { // +optional Secrets []string `json:"secrets,omitempty"` + // RunAsRoot allows admins to indicate that they wish to run the CatalogSource pod in a privileged + // pod as root. This should only be enabled when running older catalog images which could not be run as non-root. + // +optional + RunAsRoot bool `json:"runAsRoot,omitempty"` + // Metadata DisplayName string `json:"displayName,omitempty"` Description string `json:"description,omitempty"` @@ -114,6 +119,10 @@ type GrpcPodConfig struct { // +optional Tolerations []corev1.Toleration `json:"tolerations,omitempty"` + // Affinity is the catalog source's pod's affinity. + // +optional + Affinity *corev1.Affinity `json:"affinity,omitempty"` + // If specified, indicates the pod's priority. // If not specified, the pod priority will be default or zero if there is no // default. diff --git a/staging/api/pkg/operators/v1alpha1/clusterserviceversion_types.go b/staging/api/pkg/operators/v1alpha1/clusterserviceversion_types.go index eb4d1635ea..3e6d324803 100644 --- a/staging/api/pkg/operators/v1alpha1/clusterserviceversion_types.go +++ b/staging/api/pkg/operators/v1alpha1/clusterserviceversion_types.go @@ -145,11 +145,14 @@ type APIServiceDescription struct { ActionDescriptor []ActionDescriptor `json:"actionDescriptors,omitempty"` } -// APIResourceReference is a Kubernetes resource type used by a custom resource +// APIResourceReference is a reference to a Kubernetes resource type that the referrer utilizes. // +k8s:openapi-gen=true type APIResourceReference struct { - Name string `json:"name"` - Kind string `json:"kind"` + // Plural name of the referenced resource type (CustomResourceDefinition.Spec.Names[].Plural). Empty string if the referenced resource type is not a custom resource. + Name string `json:"name"` + // Kind of the referenced resource type. + Kind string `json:"kind"` + // API Version of the referenced resource type. Version string `json:"version"` } @@ -279,13 +282,34 @@ type ClusterServiceVersionSpec struct { WebhookDefinitions []WebhookDescription `json:"webhookdefinitions,omitempty"` NativeAPIs []metav1.GroupVersionKind `json:"nativeAPIs,omitempty"` MinKubeVersion string `json:"minKubeVersion,omitempty"` - DisplayName string `json:"displayName"` - Description string `json:"description,omitempty"` - Keywords []string `json:"keywords,omitempty"` - Maintainers []Maintainer `json:"maintainers,omitempty"` - Provider AppLink `json:"provider,omitempty"` - Links []AppLink `json:"links,omitempty"` - Icon []Icon `json:"icon,omitempty"` + + // The name of the operator in display format. + DisplayName string `json:"displayName"` + + // Description of the operator. Can include the features, limitations or use-cases of the + // operator. + // +optional + Description string `json:"description,omitempty"` + + // A list of keywords describing the operator. + // +optional + Keywords []string `json:"keywords,omitempty"` + + // A list of organizational entities maintaining the operator. + // +optional + Maintainers []Maintainer `json:"maintainers,omitempty"` + + // The publishing entity behind the operator. + // +optional + Provider AppLink `json:"provider,omitempty"` + + // A list of links related to the operator. + // +optional + Links []AppLink `json:"links,omitempty"` + + // The icon for this operator. + // +optional + Icon []Icon `json:"icon,omitempty"` // InstallModes specify supported installation types // +optional diff --git a/staging/api/pkg/operators/v1alpha1/installplan_types.go b/staging/api/pkg/operators/v1alpha1/installplan_types.go index 5210436d98..09deba525b 100644 --- a/staging/api/pkg/operators/v1alpha1/installplan_types.go +++ b/staging/api/pkg/operators/v1alpha1/installplan_types.go @@ -239,6 +239,9 @@ const ( // BundleLookupPending describes BundleLookups that are not complete. BundleLookupPending BundleLookupConditionType = "BundleLookupPending" + // BundleLookupFailed describes conditions types for when BundleLookups fail + BundleLookupFailed BundleLookupConditionType = "BundleLookupFailed" + crdKind = "CustomResourceDefinition" ) diff --git a/staging/api/pkg/operators/v1alpha1/subscription_types.go b/staging/api/pkg/operators/v1alpha1/subscription_types.go index 900cc46577..2452f9a1cf 100644 --- a/staging/api/pkg/operators/v1alpha1/subscription_types.go +++ b/staging/api/pkg/operators/v1alpha1/subscription_types.go @@ -111,6 +111,12 @@ const ( // SubscriptionResolutionFailed indicates that the dependency resolution in the namespace in which the subscription is created has failed SubscriptionResolutionFailed SubscriptionConditionType = "ResolutionFailed" + + // SubscriptionBundleUnpacking indicates that the unpack job is currently running + SubscriptionBundleUnpacking SubscriptionConditionType = "BundleUnpacking" + + // SubscriptionBundleUnpackFailed indicates that the unpack job failed + SubscriptionBundleUnpackFailed SubscriptionConditionType = "BundleUnpackFailed" ) const ( diff --git a/staging/api/pkg/operators/v1alpha1/zz_generated.deepcopy.go b/staging/api/pkg/operators/v1alpha1/zz_generated.deepcopy.go index e26ddea616..cf01001f5c 100644 --- a/staging/api/pkg/operators/v1alpha1/zz_generated.deepcopy.go +++ b/staging/api/pkg/operators/v1alpha1/zz_generated.deepcopy.go @@ -723,6 +723,11 @@ func (in *GrpcPodConfig) DeepCopyInto(out *GrpcPodConfig) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.Affinity != nil { + in, out := &in.Affinity, &out.Affinity + *out = new(v1.Affinity) + (*in).DeepCopyInto(*out) + } if in.PriorityClassName != nil { in, out := &in.PriorityClassName, &out.PriorityClassName *out = new(string) diff --git a/staging/api/pkg/validation/internal/annotations.go b/staging/api/pkg/validation/internal/annotations.go index 2ab63aa9fb..715b04171f 100644 --- a/staging/api/pkg/validation/internal/annotations.go +++ b/staging/api/pkg/validation/internal/annotations.go @@ -30,13 +30,13 @@ which are known to be case sensitive. It also checks to see if the olm.propertie annotation is defined in order to add a warning if present. This function can be used anywhere annotations need to be checked for case sensitivity. -Arguments +# Arguments • annotations: annotations map usually obtained from ObjectMeta.GetAnnotations() • value: is the field or file that caused an error or warning -Returns +# Returns • errs: Any errors that may have been detected with the annotation keys provided */ diff --git a/staging/api/pkg/validation/internal/community.go b/staging/api/pkg/validation/internal/community.go index dfc7c4aabe..debaae2bab 100644 --- a/staging/api/pkg/validation/internal/community.go +++ b/staging/api/pkg/validation/internal/community.go @@ -7,7 +7,7 @@ import ( "os" "strings" - "github.com/blang/semver" + "github.com/blang/semver/v4" "github.com/operator-framework/api/pkg/manifests" "github.com/operator-framework/api/pkg/validation/errors" diff --git a/staging/api/pkg/validation/internal/operatorhub.go b/staging/api/pkg/validation/internal/operatorhub.go index ac9fd0cf53..f5da37a274 100644 --- a/staging/api/pkg/validation/internal/operatorhub.go +++ b/staging/api/pkg/validation/internal/operatorhub.go @@ -71,15 +71,15 @@ import ( // containing a list of categories will enable those categories to be used when comparing CSV categories for // OperatorHub validation. The json file should be in the following format: // -// ```json -// { -// "categories":[ -// "Cloud Pak", -// "Registry", -// "MyCoolThing", -// ] -// } -// ``` +// ```json +// { +// "categories":[ +// "Cloud Pak", +// "Registry", +// "MyCoolThing", +// ] +// } +// ``` // // - The `csv.Spec.Provider.Name` was provided // diff --git a/staging/api/pkg/validation/internal/removed_apis.go b/staging/api/pkg/validation/internal/removed_apis.go index 44dee85d06..13feafb5d2 100644 --- a/staging/api/pkg/validation/internal/removed_apis.go +++ b/staging/api/pkg/validation/internal/removed_apis.go @@ -2,12 +2,17 @@ package internal import ( "fmt" - "github.com/blang/semver" + "sort" + "strings" + + "github.com/blang/semver/v4" "github.com/operator-framework/api/pkg/manifests" + "github.com/operator-framework/api/pkg/operators/v1alpha1" "github.com/operator-framework/api/pkg/validation/errors" interfaces "github.com/operator-framework/api/pkg/validation/interfaces" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "sort" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" ) // k8sVersionKey defines the key which can be used by its consumers @@ -147,11 +152,12 @@ func checkRemovedAPIsForVersion( errs []error, warns []error) ([]error, []error) { found := map[string][]string{} + warnsFound := map[string][]string{} switch k8sVersionToCheck.String() { case "1.22.0": found = getRemovedAPIsOn1_22From(bundle) case "1.25.0": - found = getRemovedAPIsOn1_25From(bundle) + found, warnsFound = getRemovedAPIsOn1_25From(bundle) case "1.26.0": found = getRemovedAPIsOn1_26From(bundle) default: @@ -172,6 +178,16 @@ func checkRemovedAPIsForVersion( warns = append(warns, msg) } } + + if len(warnsFound) > 0 { + deprecatedAPIsMessage := generateMessageWithDeprecatedAPIs(warnsFound) + msg := fmt.Errorf(DeprecateMessage, + k8sVersionToCheck.Major, k8sVersionToCheck.Minor, + k8sVersionToCheck.Major, k8sVersionToCheck.Minor, + deprecatedAPIsMessage) + warns = append(warns, msg) + } + return errs, warns } @@ -287,40 +303,115 @@ func getRemovedAPIsOn1_22From(bundle *manifests.Bundle) map[string][]string { // add manifests on the bundle using these APIs. On top of that some Kinds such as the CronJob // are not currently a valid/supported by OLM and never would to be added to bundle. // See: https://github.com/operator-framework/operator-registry/blob/v1.19.5/pkg/lib/bundle/supported_resources.go#L3-L23 -func getRemovedAPIsOn1_25From(bundle *manifests.Bundle) map[string][]string { +func getRemovedAPIsOn1_25From(bundle *manifests.Bundle) (map[string][]string, map[string][]string) { deprecatedAPIs := make(map[string][]string) + warnDeprecatedAPIs := make(map[string][]string) + + deprecatedGvk := map[schema.GroupVersionKind]struct{}{ + {Group: "batch", Version: "v1beta1", Kind: "CronJob"}: {}, + {Group: "discovery.k8s.io", Version: "v1beta1", Kind: "EndpointSlice"}: {}, + {Group: "events.k8s.io", Version: "v1beta1", Kind: "Event"}: {}, + {Group: "autoscaling", Version: "v2beta1", Kind: "HorizontalPodAutoscaler"}: {}, + {Group: "policy", Version: "v1beta1", Kind: "PodDisruptionBudget"}: {}, + {Group: "policy", Version: "v1beta1", Kind: "PodSecurityPolicy"}: {}, + {Group: "node.k8s.io", Version: "v1beta1", Kind: "RuntimeClass"}: {}, + } + + addIfDeprecated := func(u *unstructured.Unstructured) { + if _, ok := deprecatedGvk[u.GetObjectKind().GroupVersionKind()]; ok { + deprecatedAPIs[u.GetKind()] = append(deprecatedAPIs[u.GetKind()], u.GetName()) + } + } + + deprecatedGroupResource := map[schema.GroupResource]struct{}{ + {Group: "batch", Resource: "cronjobs"}: {}, + {Group: "discovery.k8s.io", Resource: "endpointslices"}: {}, + {Group: "events.k8s.io", Resource: "events"}: {}, + {Group: "autoscaling", Resource: "horizontalpodautoscalers"}: {}, + {Group: "policy", Resource: "poddisruptionbudgets"}: {}, + {Group: "policy", Resource: "podsecuritypolicies"}: {}, + {Group: "node.k8s.io", Resource: "runtimeclasses"}: {}, + } + + warnIfDeprecated := func(gr schema.GroupResource, msg string) { + if _, ok := deprecatedGroupResource[gr]; ok { + warnDeprecatedAPIs[gr.Resource] = append(warnDeprecatedAPIs[gr.Resource], msg) + } + } + for _, obj := range bundle.Objects { switch u := obj.GetObjectKind().(type) { case *unstructured.Unstructured: switch u.GetAPIVersion() { - case "batch/v1beta1": - if u.GetKind() == "CronJob" { - deprecatedAPIs[u.GetKind()] = append(deprecatedAPIs[u.GetKind()], obj.GetName()) - } - case "discovery.k8s.io/v1beta1": - if u.GetKind() == "EndpointSlice" { - deprecatedAPIs[u.GetKind()] = append(deprecatedAPIs[u.GetKind()], obj.GetName()) - } - case "events.k8s.io/v1beta1": - if u.GetKind() == "Event" { - deprecatedAPIs[u.GetKind()] = append(deprecatedAPIs[u.GetKind()], obj.GetName()) - } - case "autoscaling/v2beta1": - if u.GetKind() == "HorizontalPodAutoscaler" { - deprecatedAPIs[u.GetKind()] = append(deprecatedAPIs[u.GetKind()], obj.GetName()) - } - case "policy/v1beta1": - if u.GetKind() == "PodDisruptionBudget" || u.GetKind() == "PodSecurityPolicy" { - deprecatedAPIs[u.GetKind()] = append(deprecatedAPIs[u.GetKind()], obj.GetName()) - } - case "node.k8s.io/v1beta1": - if u.GetKind() == "RuntimeClass" { - deprecatedAPIs[u.GetKind()] = append(deprecatedAPIs[u.GetKind()], obj.GetName()) + case "operators.coreos.com/v1alpha1": + // Check a couple CSV fields for references to deprecated APIs + if u.GetKind() == "ClusterServiceVersion" { + resInCsvCrds := make(map[string]struct{}) + csv := &v1alpha1.ClusterServiceVersion{} + err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.Object, csv) + if err != nil { + fmt.Println("failed to convert unstructured.Unstructed to v1alpha1.ClusterServiceVersion:", err) + } + + // Loop through all the CRDDescriptions to see + // if there is any with an API Version & Kind that is deprecated + crdCheck := func(crdsField string, crdDescriptions []v1alpha1.CRDDescription) { + for i, desc := range crdDescriptions { + for j, res := range desc.Resources { + resFromKind := fmt.Sprintf("%ss", strings.ToLower(res.Kind)) + resInCsvCrds[resFromKind] = struct{}{} + unstruct := &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": res.Version, + "kind": res.Kind, + "metadata": map[string]interface{}{ + "name": fmt.Sprintf("ClusterServiceVersion.Spec.CustomResourceDefinitions.%s[%d].Resource[%d]", crdsField, i, j), + }, + }, + } + addIfDeprecated(unstruct) + } + } + } + + // Check the Owned Resources + crdCheck("Owned", csv.Spec.CustomResourceDefinitions.Owned) + + // Check the Required Resources + crdCheck("Required", csv.Spec.CustomResourceDefinitions.Required) + + // Loop through all the StrategyDeploymentPermissions to see + // if the rbacv1.PolicyRule that is defined specifies a resource that + // *may* have a deprecated API then add it to the warnings. + // Only present a warning if the resource was NOT found as a resource + // in the ClusterServiceVersion.Spec.CustomResourceDefinitions fields + permCheck := func(permField string, perms []v1alpha1.StrategyDeploymentPermissions) { + for i, perm := range perms { + for j, rule := range perm.Rules { + for _, apiGroup := range rule.APIGroups { + for _, res := range rule.Resources { + if _, ok := resInCsvCrds[res]; ok { + continue + } + warnIfDeprecated(schema.GroupResource{Group: apiGroup, Resource: res}, fmt.Sprintf("ClusterServiceVersion.Spec.InstallStrategy.StrategySpec.%s[%d].Rules[%d]", permField, i, j)) + } + } + } + } + } + + // Check the ClusterPermissions + permCheck("ClusterPermissions", csv.Spec.InstallStrategy.StrategySpec.ClusterPermissions) + + // Check the Permissions + permCheck("Permissions", csv.Spec.InstallStrategy.StrategySpec.Permissions) } + default: + addIfDeprecated(u) } } } - return deprecatedAPIs + return deprecatedAPIs, warnDeprecatedAPIs } // getRemovedAPIsOn1_26From return the list of resources which were deprecated diff --git a/staging/api/pkg/validation/internal/removed_apis_test.go b/staging/api/pkg/validation/internal/removed_apis_test.go index 60cc3a2ff8..ac238fabb7 100644 --- a/staging/api/pkg/validation/internal/removed_apis_test.go +++ b/staging/api/pkg/validation/internal/removed_apis_test.go @@ -72,27 +72,47 @@ func Test_GetRemovedAPIsOn1_25From(t *testing.T) { mock["HorizontalPodAutoscaler"] = []string{"memcached-operator-hpa"} mock["PodDisruptionBudget"] = []string{"memcached-operator-policy-manager"} + warnMock := make(map[string][]string) + warnMock["cronjobs"] = []string{"ClusterServiceVersion.Spec.InstallStrategy.StrategySpec.ClusterPermissions[0].Rules[7]"} + warnMock["endpointslices"] = []string{"ClusterServiceVersion.Spec.InstallStrategy.StrategySpec.Permissions[0].Rules[3]"} + warnMock["events"] = []string{"ClusterServiceVersion.Spec.InstallStrategy.StrategySpec.Permissions[0].Rules[2]"} + warnMock["horizontalpodautoscalers"] = []string{"ClusterServiceVersion.Spec.InstallStrategy.StrategySpec.Permissions[0].Rules[4]"} + warnMock["poddisruptionbudgets"] = []string{"ClusterServiceVersion.Spec.InstallStrategy.StrategySpec.Permissions[0].Rules[5]"} + warnMock["podsecuritypolicies"] = []string{"ClusterServiceVersion.Spec.InstallStrategy.StrategySpec.Permissions[0].Rules[5]"} + warnMock["runtimeclasses"] = []string{"ClusterServiceVersion.Spec.InstallStrategy.StrategySpec.Permissions[0].Rules[6]"} + type args struct { bundleDir string } tests := []struct { - name string - args args - want map[string][]string + name string + args args + errWant map[string][]string + warnWant map[string][]string }{ { name: "should return an empty map when no deprecated apis are found", args: args{ bundleDir: "./testdata/valid_bundle_v1", }, - want: map[string][]string{}, + errWant: map[string][]string{}, + warnWant: map[string][]string{}, }, { name: "should fail return the removed APIs in 1.25", args: args{ bundleDir: "./testdata/removed_api_1_25", }, - want: mock, + errWant: mock, + warnWant: map[string][]string{}, + }, + { + name: "should return warnings with all deprecated APIs in 1.25", + args: args{ + bundleDir: "./testdata/deprecated_api_1_25", + }, + errWant: mock, + warnWant: warnMock, }, } for _, tt := range tests { @@ -102,8 +122,14 @@ func Test_GetRemovedAPIsOn1_25From(t *testing.T) { bundle, err := manifests.GetBundleFromDir(tt.args.bundleDir) require.NoError(t, err) - if got := getRemovedAPIsOn1_25From(bundle); !reflect.DeepEqual(got, tt.want) { - t.Errorf("getRemovedAPIsOn1_25From() = %v, want %v", got, tt.want) + errGot, warnGot := getRemovedAPIsOn1_25From(bundle) + + if !reflect.DeepEqual(errGot, tt.errWant) { + t.Errorf("getRemovedAPIsOn1_25From() = %v, want %v", errGot, tt.errWant) + } + + if !reflect.DeepEqual(warnGot, tt.warnWant) { + t.Errorf("getRemovedAPIsOn1_25From() = %v, want %v", warnGot, tt.warnWant) } }) } @@ -252,8 +278,8 @@ func TestValidateDeprecatedAPIS(t *testing.T) { wantWarning: true, warnStrings: []string{"this bundle is using APIs which were deprecated and removed in v1.22. " + "More info: https://kubernetes.io/docs/reference/using-api/deprecation-guide/#v1-22. " + - "Migrate the API(s) for CRD: ([\"etcdbackups.etcd.database.coreos.com\"" + - " \"etcdclusters.etcd.database.coreos.com\" \"etcdrestores.etcd.database.coreos.com\"])"}, + "Migrate the API(s) for CRD: ([\"etcdbackups.etcd.database.coreos.com\" " + + "\"etcdclusters.etcd.database.coreos.com\" \"etcdrestores.etcd.database.coreos.com\"])"}, }, { name: "should return an error when the csv.spec.minKubeVersion informed is invalid", diff --git a/staging/api/pkg/validation/internal/testdata/deprecated_api_1_25/cache.example.com_memcacheds.yaml b/staging/api/pkg/validation/internal/testdata/deprecated_api_1_25/cache.example.com_memcacheds.yaml new file mode 100644 index 0000000000..a8ea3eb8d3 --- /dev/null +++ b/staging/api/pkg/validation/internal/testdata/deprecated_api_1_25/cache.example.com_memcacheds.yaml @@ -0,0 +1,66 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.1 + creationTimestamp: null + name: memcacheds.cache.example.com +spec: + group: cache.example.com + names: + kind: Memcached + listKind: MemcachedList + plural: memcacheds + singular: memcached + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: Memcached is the Schema for the memcacheds API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: MemcachedSpec defines the desired state of Memcached + properties: + foo: + description: Foo is an example field of Memcached. Edit memcached_types.go + to remove/update + type: string + size: + description: Size defines the number of Memcached instances + format: int32 + type: integer + type: object + status: + description: MemcachedStatus defines the observed state of Memcached + properties: + nodes: + description: Nodes store the name of the pods which are running Memcached + instances + items: + type: string + type: array + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/staging/api/pkg/validation/internal/testdata/deprecated_api_1_25/horizontal-pod.yaml b/staging/api/pkg/validation/internal/testdata/deprecated_api_1_25/horizontal-pod.yaml new file mode 100644 index 0000000000..69f77b5f49 --- /dev/null +++ b/staging/api/pkg/validation/internal/testdata/deprecated_api_1_25/horizontal-pod.yaml @@ -0,0 +1,18 @@ +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: memcached-operator-hpa +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: memcached-operator-controller-manager + minReplicas: 1 + maxReplicas: 10 + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 50 \ No newline at end of file diff --git a/staging/api/pkg/validation/internal/testdata/deprecated_api_1_25/memcached-operator.clusterserviceversion.yaml b/staging/api/pkg/validation/internal/testdata/deprecated_api_1_25/memcached-operator.clusterserviceversion.yaml new file mode 100644 index 0000000000..a28ca3a117 --- /dev/null +++ b/staging/api/pkg/validation/internal/testdata/deprecated_api_1_25/memcached-operator.clusterserviceversion.yaml @@ -0,0 +1,287 @@ +apiVersion: operators.coreos.com/v1alpha1 +kind: ClusterServiceVersion +metadata: + annotations: + alm-examples: |- + [ + { + "apiVersion": "cache.example.com/v1alpha1", + "kind": "Memcached", + "metadata": { + "name": "memcached-sample" + }, + "spec": { + "size": 1 + } + } + ] + capabilities: Basic Install + name: memcached-operator.v0.0.1 + namespace: placeholder +spec: + apiservicedefinitions: {} + customresourcedefinitions: + owned: + - description: Memcached is the Schema for the memcacheds API + displayName: Memcached + kind: Memcached + name: memcacheds.cache.example.com + version: v1alpha1 + description: Memcached Operator description. TODO. + displayName: Memcached Operator + icon: + - base64data: "" + mediatype: "" + install: + spec: + clusterPermissions: + - rules: + - apiGroups: + - apps + resources: + - deployments + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - cache.example.com + resources: + - memcacheds + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - cache.example.com + resources: + - memcacheds/finalizers + verbs: + - update + - apiGroups: + - cache.example.com + resources: + - memcacheds/status + verbs: + - get + - patch + - update + - apiGroups: + - "" + resources: + - pods + verbs: + - get + - list + - watch + - apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create + - apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create + - apiGroups: + - batch + resources: + - cronjobs + verbs: + - get + serviceAccountName: memcached-operator-controller-manager + deployments: + - name: memcached-operator-controller-manager + spec: + replicas: 1 + selector: + matchLabels: + control-plane: controller-manager + strategy: {} + template: + metadata: + labels: + control-plane: controller-manager + spec: + containers: + - args: + - --secure-listen-address=0.0.0.0:8443 + - --upstream=http://127.0.0.1:8080/ + - --logtostderr=true + - --v=10 + image: gcr.io/kubebuilder/kube-rbac-proxy:v0.8.0 + name: kube-rbac-proxy + ports: + - containerPort: 8443 + name: https + resources: {} + - args: + - --health-probe-bind-address=:8081 + - --metrics-bind-address=127.0.0.1:8080 + - --leader-elect + command: + - /manager + image: quay.io/example/memcached-operator:v0.0.1 + livenessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 + name: manager + ports: + - containerPort: 9443 + name: webhook-server + protocol: TCP + readinessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 + securityContext: + allowPrivilegeEscalation: false + securityContext: + runAsNonRoot: true + serviceAccountName: memcached-operator-controller-manager + terminationGracePeriodSeconds: 10 + permissions: + - rules: + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - apiGroups: + - events.k8s.io + resources: + - events + verbs: + - create + - patch + - apiGroups: + - discovery.k8s.io + resources: + - endpointslices + verbs: + - create + - patch + - apiGroups: + - autoscaling + resources: + - horizontalpodautoscalers + verbs: + - create + - patch + - apiGroups: + - policy + resources: + - poddisruptionbudgets + - podsecuritypolicies + verbs: + - create + - patch + - apiGroups: + - node.k8s.io + resources: + - runtimeclasses + verbs: + - create + - patch + serviceAccountName: memcached-operator-controller-manager + strategy: deployment + installModes: + - supported: false + type: OwnNamespace + - supported: false + type: SingleNamespace + - supported: false + type: MultiNamespace + - supported: true + type: AllNamespaces + keywords: + - memcached-operator + links: + - name: Memcached Operator + url: https://memcached-operator.domain + maintainers: + - email: your@email.com + name: Maintainer Name + maturity: alpha + provider: + name: Provider Name + url: https://your.domain + version: 0.0.1 + webhookdefinitions: + - admissionReviewVersions: + - v1 + - v1beta1 + containerPort: 443 + deploymentName: memcached-operator-controller-manager + failurePolicy: Fail + generateName: vmemcached.kb.io + rules: + - apiGroups: + - cache.example.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - memcacheds + sideEffects: None + targetPort: 9443 + type: ValidatingAdmissionWebhook + webhookPath: /validate-cache-example-com-v1alpha1-memcached + - admissionReviewVersions: + - v1 + - v1beta1 + containerPort: 443 + deploymentName: memcached-operator-controller-manager + failurePolicy: Fail + generateName: mmemcached.kb.io + rules: + - apiGroups: + - cache.example.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - memcacheds + sideEffects: None + targetPort: 9443 + type: MutatingAdmissionWebhook + webhookPath: /mutate-cache-example-com-v1alpha1-memcached diff --git a/staging/api/pkg/validation/internal/testdata/deprecated_api_1_25/policy.yaml b/staging/api/pkg/validation/internal/testdata/deprecated_api_1_25/policy.yaml new file mode 100644 index 0000000000..15714a60c3 --- /dev/null +++ b/staging/api/pkg/validation/internal/testdata/deprecated_api_1_25/policy.yaml @@ -0,0 +1,9 @@ +apiVersion: policy/v1beta1 +kind: PodDisruptionBudget +metadata: + name: memcached-operator-policy-manager +spec: + minAvailable: 2 + selector: + matchLabels: + app: memcached-operator \ No newline at end of file diff --git a/staging/api/pkg/validation/internal/testdata/valid_bundle/etcdoperator.v0.9.4.clusterserviceversion.yaml b/staging/api/pkg/validation/internal/testdata/valid_bundle/etcdoperator.v0.9.4.clusterserviceversion.yaml index f5ff405ebf..29d1f682ac 100644 --- a/staging/api/pkg/validation/internal/testdata/valid_bundle/etcdoperator.v0.9.4.clusterserviceversion.yaml +++ b/staging/api/pkg/validation/internal/testdata/valid_bundle/etcdoperator.v0.9.4.clusterserviceversion.yaml @@ -192,6 +192,22 @@ spec: name: etcd-operator-alm-owned name: etcd-operator-alm-owned spec: + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: kubernetes.io/arch + operator: In + values: + - amd64 + - arm64 + - ppc64le + - s390x + - key: kubernetes.io/os + operator: In + values: + - linux containers: - command: - etcd-operator @@ -205,8 +221,8 @@ spec: valueFrom: fieldRef: fieldPath: metadata.name - image: quay.io/coreos/etcd-operator@sha256:66a37fd61a06a43969854ee6d3e21087a98b93838e284a6086b13917f96b0d9b - name: etcd-operator + image: quay.io/coreos/etcd-operator2@sha256:66a37fd61a06a43969854ee6d3e21087a98b93838e284a6086b13917f96b0d9b + name: manager resources: limits: cpu: 500m diff --git a/staging/api/pkg/validation/internal/testdata/valid_bundle_v1/memcached-operator.clusterserviceversion.yaml b/staging/api/pkg/validation/internal/testdata/valid_bundle_v1/memcached-operator.clusterserviceversion.yaml index bddc807691..66794210ec 100644 --- a/staging/api/pkg/validation/internal/testdata/valid_bundle_v1/memcached-operator.clusterserviceversion.yaml +++ b/staging/api/pkg/validation/internal/testdata/valid_bundle_v1/memcached-operator.clusterserviceversion.yaml @@ -176,13 +176,6 @@ spec: - update - patch - delete - - apiGroups: - - "" - resources: - - events - verbs: - - create - - patch serviceAccountName: memcached-operator-controller-manager strategy: deployment installModes: diff --git a/staging/operator-lifecycle-manager/.github/workflows/build.yml b/staging/operator-lifecycle-manager/.github/workflows/build.yml index 738064565b..b48d9e8939 100644 --- a/staging/operator-lifecycle-manager/.github/workflows/build.yml +++ b/staging/operator-lifecycle-manager/.github/workflows/build.yml @@ -7,9 +7,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out the repo - uses: actions/checkout@v1 + uses: actions/checkout@v3 - name: Build the container image - uses: docker/build-push-action@v2 + uses: docker/build-push-action@v4 with: context: . file: Dockerfile diff --git a/staging/operator-lifecycle-manager/.github/workflows/e2e-tests.yml b/staging/operator-lifecycle-manager/.github/workflows/e2e-tests.yml index 55eea714ca..4d2c44370e 100644 --- a/staging/operator-lifecycle-manager/.github/workflows/e2e-tests.yml +++ b/staging/operator-lifecycle-manager/.github/workflows/e2e-tests.yml @@ -15,15 +15,15 @@ jobs: parallel-id: [0, 1, 2, 3] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 - - uses: actions/setup-go@v3 + - uses: actions/checkout@v3 + - uses: actions/setup-go@v4 with: go-version-file: "go.mod" - run: mkdir -p artifacts - run: make e2e-local E2E_TEST_CHUNK=${{ matrix.parallel-id }} E2E_TEST_NUM_CHUNKS=${{ strategy.job-total }} E2E_NODES=2 ARTIFACT_DIR=./artifacts/ SKIP='\[FLAKE\]' - name: Archive Test Artifacts # test results, failed or not, are always uploaded. if: ${{ always() }} - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: e2e-test-output-${{ (github.event.pull_request.head.sha || github.sha) }}-${{ github.run_id }}-${{ matrix.parallel-id }} path: ${{ github.workspace }}/bin/artifacts/* diff --git a/staging/operator-lifecycle-manager/.github/workflows/flaky-e2e.yml b/staging/operator-lifecycle-manager/.github/workflows/flaky-e2e.yml index 2260a65346..1686f67c9c 100644 --- a/staging/operator-lifecycle-manager/.github/workflows/flaky-e2e.yml +++ b/staging/operator-lifecycle-manager/.github/workflows/flaky-e2e.yml @@ -11,15 +11,15 @@ jobs: flaky-e2e-tests: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 - - uses: actions/setup-go@v3 + - uses: actions/checkout@v3 + - uses: actions/setup-go@v4 with: go-version-file: "go.mod" - run: mkdir -p artifacts - run: make e2e-local E2E_NODES=1 TEST='\[FLAKE\]' ARTIFACT_DIR=./artifacts/ - name: Archive Test Artifacts # test results, failed or not, are always uploaded. if: ${{ always() }} - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: e2e-test-output-${{(github.event.pull_request.head.sha||github.sha)}}-${{ github.run_id }} path: ${{ github.workspace }}/bin/artifacts/* diff --git a/staging/operator-lifecycle-manager/.github/workflows/goreleaser.yaml b/staging/operator-lifecycle-manager/.github/workflows/goreleaser.yaml index c66e177213..8e39d47f80 100644 --- a/staging/operator-lifecycle-manager/.github/workflows/goreleaser.yaml +++ b/staging/operator-lifecycle-manager/.github/workflows/goreleaser.yaml @@ -10,11 +10,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v1 + uses: actions/checkout@v3 with: fetch-depth: 0 - name: Set up Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v4 with: go-version-file: "go.mod" @@ -25,7 +25,10 @@ jobs: if [[ $GITHUB_REF == refs/tags/* ]]; then echo IMAGE_TAG="${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV fi - + + # TODO dtfranz + # This action uses node12 and the source repo is archived; + # we should remove it or find a suitable replacement before it becomes a blocker. - name: Create a draft release uses: actions/create-release@v1 id: release @@ -37,8 +40,12 @@ jobs: tag_name: ${{ github.ref }} release_name: ${{ github.ref }} + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + if: startsWith(github.ref, 'refs/tags') + - name: Docker Login - uses: docker/login-action@v1 + uses: docker/login-action@v2 if: startsWith(github.ref, 'refs/tags') with: registry: quay.io @@ -46,7 +53,7 @@ jobs: password: ${{ secrets.QUAY_PASSWORD }} - name: Run GoReleaser - uses: goreleaser/goreleaser-action@v2 + uses: goreleaser/goreleaser-action@v4 if: startsWith(github.ref, 'refs/tags') with: version: 0.177.0 diff --git a/staging/operator-lifecycle-manager/.github/workflows/quickstart.yml b/staging/operator-lifecycle-manager/.github/workflows/quickstart.yml index 9df3656a97..5a3334e9bf 100644 --- a/staging/operator-lifecycle-manager/.github/workflows/quickstart.yml +++ b/staging/operator-lifecycle-manager/.github/workflows/quickstart.yml @@ -8,7 +8,7 @@ jobs: install-quickstart: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v3 - run: | curl -sLo kind "$(curl -sL https://api.github.com/repos/kubernetes-sigs/kind/releases/latest | jq -r '[.assets[] | select(.name == "kind-linux-amd64")] | first | .browser_download_url')" chmod +x kind diff --git a/staging/operator-lifecycle-manager/.github/workflows/run-kind-local.yml b/staging/operator-lifecycle-manager/.github/workflows/run-kind-local.yml index 1b8455aa0f..d95962db58 100644 --- a/staging/operator-lifecycle-manager/.github/workflows/run-kind-local.yml +++ b/staging/operator-lifecycle-manager/.github/workflows/run-kind-local.yml @@ -8,8 +8,8 @@ jobs: e2e-kind: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 - - uses: actions/setup-go@v3 + - uses: actions/checkout@v3 + - uses: actions/setup-go@v4 with: go-version-file: "go.mod" - name: Install kind diff --git a/staging/operator-lifecycle-manager/.github/workflows/run-minikube-local.yml b/staging/operator-lifecycle-manager/.github/workflows/run-minikube-local.yml index 8da949402d..04aa0a4533 100644 --- a/staging/operator-lifecycle-manager/.github/workflows/run-minikube-local.yml +++ b/staging/operator-lifecycle-manager/.github/workflows/run-minikube-local.yml @@ -8,8 +8,8 @@ jobs: e2e-minikube: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 - - uses: actions/setup-go@v3 + - uses: actions/checkout@v3 + - uses: actions/setup-go@v4 with: go-version-file: "go.mod" - name: Install minikube diff --git a/staging/operator-lifecycle-manager/.github/workflows/sanity.yaml b/staging/operator-lifecycle-manager/.github/workflows/sanity.yaml index 695c48f889..2c0a365c49 100644 --- a/staging/operator-lifecycle-manager/.github/workflows/sanity.yaml +++ b/staging/operator-lifecycle-manager/.github/workflows/sanity.yaml @@ -9,8 +9,8 @@ jobs: vendor: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 - - uses: actions/setup-go@v3 + - uses: actions/checkout@v3 + - uses: actions/setup-go@v4 with: go-version-file: "go.mod" - name: Run sanity checks @@ -18,8 +18,11 @@ jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 + - uses: actions/setup-go@v4 + with: + go-version-file: "go.mod" - name: Run linting checks - uses: "golangci/golangci-lint-action@v2" + uses: "golangci/golangci-lint-action@v3" with: - version: "v1.46.0" + version: "v1.50.1" diff --git a/staging/operator-lifecycle-manager/.github/workflows/unit.yml b/staging/operator-lifecycle-manager/.github/workflows/unit.yml index d60d56ae1a..90ac078a90 100644 --- a/staging/operator-lifecycle-manager/.github/workflows/unit.yml +++ b/staging/operator-lifecycle-manager/.github/workflows/unit.yml @@ -11,8 +11,8 @@ jobs: unit: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 - - uses: actions/setup-go@v3 + - uses: actions/checkout@v3 + - uses: actions/setup-go@v4 with: go-version-file: "go.mod" - name: Envtest setup diff --git a/staging/operator-lifecycle-manager/.github/workflows/verify.yml b/staging/operator-lifecycle-manager/.github/workflows/verify.yml index a4ffba7bf0..734ba2f4c7 100644 --- a/staging/operator-lifecycle-manager/.github/workflows/verify.yml +++ b/staging/operator-lifecycle-manager/.github/workflows/verify.yml @@ -9,8 +9,8 @@ jobs: verify: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 - - uses: actions/setup-go@v3 + - uses: actions/checkout@v3 + - uses: actions/setup-go@v4 with: go-version-file: "go.mod" @@ -18,6 +18,4 @@ jobs: # codegen script still relies on $GOPATH being set and will return an error otherwise. # The setup-go action does not set this value for us: https://github.com/actions/setup-go/issues/14. - name: Run the verify target - run: | - export GOPATH=$(go env GOPATH) - make verify + run: GOPATH=$(go env GOPATH) make verify diff --git a/staging/operator-lifecycle-manager/Dockerfile b/staging/operator-lifecycle-manager/Dockerfile index 075a5dbd4e..72df7fa0fe 100644 --- a/staging/operator-lifecycle-manager/Dockerfile +++ b/staging/operator-lifecycle-manager/Dockerfile @@ -1,4 +1,4 @@ -FROM quay.io/fedora/fedora:34-x86_64 as builder +FROM quay.io/fedora/fedora:37-x86_64 as builder LABEL stage=builder WORKDIR /build diff --git a/staging/operator-lifecycle-manager/Dockerfile.goreleaser b/staging/operator-lifecycle-manager/Dockerfile.goreleaser index a117f6623e..5308799547 100644 --- a/staging/operator-lifecycle-manager/Dockerfile.goreleaser +++ b/staging/operator-lifecycle-manager/Dockerfile.goreleaser @@ -1,4 +1,4 @@ -FROM --platform=$BUILDPLATFORM gcr.io/distroless/static:debug +FROM gcr.io/distroless/static:debug LABEL stage=olm WORKDIR / # bundle unpack Jobs require cp at /bin/cp diff --git a/staging/operator-lifecycle-manager/Makefile b/staging/operator-lifecycle-manager/Makefile index f892f12e95..ae104d6de2 100644 --- a/staging/operator-lifecycle-manager/Makefile +++ b/staging/operator-lifecycle-manager/Makefile @@ -29,7 +29,11 @@ GO := GO111MODULE=on GOFLAGS="$(MOD_FLAGS)" go GINKGO := $(GO) run github.com/onsi/ginkgo/v2/ginkgo BINDATA := $(GO) run github.com/go-bindata/go-bindata/v3/go-bindata GIT_COMMIT := $(shell git rev-parse HEAD) - +ifeq ($(shell arch), arm64) +ARCH := arm64 +else +ARCH := 386 +endif # Phony prerequisite for targets that rely on the go build cache to determine staleness. .PHONY: build test clean vendor \ coverage coverage-html e2e \ @@ -82,15 +86,15 @@ build-coverage: build_cmd=test -c -covermode=count -coverpkg ./pkg/controller/.. build-coverage: clean $(CMDS) build-linux: build_cmd=build -build-linux: arch_flags=GOOS=linux GOARCH=386 +build-linux: arch_flags=GOOS=linux GOARCH=$(ARCH) build-linux: clean $(CMDS) build-wait: clean bin/wait bin/wait: FORCE - GOOS=linux GOARCH=386 go build $(MOD_FLAGS) -o $@ $(PKG)/test/e2e/wait + GOOS=linux GOARCH=$(ARCH) go build $(MOD_FLAGS) -o $@ $(PKG)/test/e2e/wait -build-util-linux: arch_flags=GOOS=linux GOARCH=386 +build-util-linux: arch_flags=GOOS=linux GOARCH=$(ARCH) build-util-linux: build-util build-util: bin/cpb diff --git a/staging/operator-lifecycle-manager/OWNERS b/staging/operator-lifecycle-manager/OWNERS index b50656f1c4..1b8bbde740 100644 --- a/staging/operator-lifecycle-manager/OWNERS +++ b/staging/operator-lifecycle-manager/OWNERS @@ -7,8 +7,8 @@ approvers: - benluddy - awgreene - dinhxuanvu - - timflannagan - perdasilva + - grokspawn # review == this code is good /lgtm reviewers: - ecordell @@ -22,7 +22,9 @@ reviewers: - awgreene - ankitathomas - joelanford - - timflannagan - perdasilva -# Bugzilla component -component: "OLM" + - akihikokuroda + - oceanc80 + - grokspawn + - dtfranz + - asmacdo diff --git a/staging/operator-lifecycle-manager/cmd/catalog/main.go b/staging/operator-lifecycle-manager/cmd/catalog/main.go index 20134d71d2..d282dfebb3 100644 --- a/staging/operator-lifecycle-manager/cmd/catalog/main.go +++ b/staging/operator-lifecycle-manager/cmd/catalog/main.go @@ -27,7 +27,7 @@ const ( defaultWakeupInterval = 15 * time.Minute defaultCatalogNamespace = "olm" defaultConfigMapServerImage = "quay.io/operator-framework/configmap-operator-registry:latest" - defaultOPMImage = "quay.io/operator-framework/upstream-opm-builder:latest" + defaultOPMImage = "quay.io/operator-framework/opm:latest" defaultUtilImage = "quay.io/operator-framework/olm:latest" defaultOperatorName = "" defaultWorkLoadUserID = int64(1001) diff --git a/staging/operator-lifecycle-manager/deploy/chart/crds/0000_50_olm_00-catalogsources.crd.yaml b/staging/operator-lifecycle-manager/deploy/chart/crds/0000_50_olm_00-catalogsources.crd.yaml index 169e1e8149..321b99467b 100644 --- a/staging/operator-lifecycle-manager/deploy/chart/crds/0000_50_olm_00-catalogsources.crd.yaml +++ b/staging/operator-lifecycle-manager/deploy/chart/crds/0000_50_olm_00-catalogsources.crd.yaml @@ -71,6 +71,467 @@ spec: description: GrpcPodConfig exposes different overrides for the pod spec of the CatalogSource Pod. Only used when SourceType = SourceTypeGrpc and Image is set. type: object properties: + affinity: + description: Affinity is the catalog source's pod's affinity. + type: object + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the pod. + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node matches the corresponding matchExpressions; the node(s) with the highest sum are the most preferred. + type: array + items: + description: An empty preferred scheduling term matches all objects with implicit weight 0 (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). + type: object + required: + - preference + - weight + properties: + preference: + description: A node selector term, associated with the corresponding weight. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + weight: + description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to an update), the system may or may not try to eventually evict the pod from its node. + type: object + required: + - nodeSelectorTerms + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The terms are ORed. + type: array + items: + description: A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + weight: + description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. + type: array + items: + description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes that satisfy the anti-affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + weight: + description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the anti-affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. + type: array + items: + description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string nodeSelector: description: NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node's labels for the pod to be scheduled on that node. type: object diff --git a/staging/operator-lifecycle-manager/deploy/chart/crds/0000_50_olm_00-clusterserviceversions.crd.yaml b/staging/operator-lifecycle-manager/deploy/chart/crds/0000_50_olm_00-clusterserviceversions.crd.yaml index 7eb672aa5f..77422915c5 100644 --- a/staging/operator-lifecycle-manager/deploy/chart/crds/0000_50_olm_00-clusterserviceversions.crd.yaml +++ b/staging/operator-lifecycle-manager/deploy/chart/crds/0000_50_olm_00-clusterserviceversions.crd.yaml @@ -119,7 +119,7 @@ spec: resources: type: array items: - description: APIResourceReference is a Kubernetes resource type used by a custom resource + description: APIResourceReference is a reference to a Kubernetes resource type that the referrer utilizes. type: object required: - kind @@ -127,10 +127,13 @@ spec: - version properties: kind: + description: Kind of the referenced resource type. type: string name: + description: Plural name of the referenced resource type (CustomResourceDefinition.Spec.Names[].Plural). Empty string if the referenced resource type is not a custom resource. type: string version: + description: API Version of the referenced resource type. type: string specDescriptors: type: array @@ -229,7 +232,7 @@ spec: resources: type: array items: - description: APIResourceReference is a Kubernetes resource type used by a custom resource + description: APIResourceReference is a reference to a Kubernetes resource type that the referrer utilizes. type: object required: - kind @@ -237,10 +240,13 @@ spec: - version properties: kind: + description: Kind of the referenced resource type. type: string name: + description: Plural name of the referenced resource type (CustomResourceDefinition.Spec.Names[].Plural). Empty string if the referenced resource type is not a custom resource. type: string version: + description: API Version of the referenced resource type. type: string specDescriptors: type: array @@ -343,7 +349,7 @@ spec: resources: type: array items: - description: APIResourceReference is a Kubernetes resource type used by a custom resource + description: APIResourceReference is a reference to a Kubernetes resource type that the referrer utilizes. type: object required: - kind @@ -351,10 +357,13 @@ spec: - version properties: kind: + description: Kind of the referenced resource type. type: string name: + description: Plural name of the referenced resource type (CustomResourceDefinition.Spec.Names[].Plural). Empty string if the referenced resource type is not a custom resource. type: string version: + description: API Version of the referenced resource type. type: string specDescriptors: type: array @@ -445,7 +454,7 @@ spec: resources: type: array items: - description: APIResourceReference is a Kubernetes resource type used by a custom resource + description: APIResourceReference is a reference to a Kubernetes resource type that the referrer utilizes. type: object required: - kind @@ -453,10 +462,13 @@ spec: - version properties: kind: + description: Kind of the referenced resource type. type: string name: + description: Plural name of the referenced resource type (CustomResourceDefinition.Spec.Names[].Plural). Empty string if the referenced resource type is not a custom resource. type: string version: + description: API Version of the referenced resource type. type: string specDescriptors: type: array @@ -505,10 +517,13 @@ spec: version: type: string description: + description: Description of the operator. Can include the features, limitations or use-cases of the operator. type: string displayName: + description: The name of the operator in display format. type: string icon: + description: The icon for this operator. type: array items: type: object @@ -1664,6 +1679,21 @@ spec: description: 'Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable." + type: array + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + type: object + required: + - name + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object @@ -2476,6 +2506,21 @@ spec: description: Resources are not allowed for ephemeral containers. Ephemeral containers use spare resources already allocated to the pod. type: object properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable." + type: array + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + type: object + required: + - name + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object @@ -3299,6 +3344,21 @@ spec: description: 'Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable." + type: array + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + type: object + required: + - name + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object @@ -3617,6 +3677,31 @@ spec: conditionType: description: ConditionType refers to a condition in the pod's condition list with matching type. type: string + resourceClaims: + description: "ResourceClaims defines which ResourceClaims must be allocated and reserved before the Pod is allowed to start. The resources will be made available to those containers which consume them by name. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable." + type: array + items: + description: PodResourceClaim references exactly one ResourceClaim through a ClaimSource. It adds a name to it that uniquely identifies the ResourceClaim inside the Pod. Containers that need access to the ResourceClaim reference it with this name. + type: object + required: + - name + properties: + name: + description: Name uniquely identifies this resource claim inside the pod. This must be a DNS_LABEL. + type: string + source: + description: Source describes where to find the ResourceClaim. + type: object + properties: + resourceClaimName: + description: ResourceClaimName is the name of a ResourceClaim object in the same namespace as this pod. + type: string + resourceClaimTemplateName: + description: "ResourceClaimTemplateName is the name of a ResourceClaimTemplate object in the same namespace as this pod. \n The template will be used to create a new ResourceClaim, which will be bound to this pod. When this pod is deleted, the ResourceClaim will also be deleted. The name of the ResourceClaim will be -, where is the PodResourceClaim.Name. Pod validation will reject the pod if the concatenated name is not valid for a ResourceClaim (e.g. too long). \n An existing ResourceClaim with that name that is not owned by the pod will not be used for the pod to avoid using an unrelated resource by mistake. Scheduling and pod startup are then blocked until the unrelated ResourceClaim is removed. \n This field is immutable and no changes will be made to the corresponding ResourceClaim by the control plane after creating the ResourceClaim." + type: string + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map restartPolicy: description: 'Restart policy for all containers within the pod. One of Always, OnFailure, Never. Default to Always. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy' type: string @@ -3626,6 +3711,21 @@ spec: schedulerName: description: If specified, the pod will be dispatched by specified scheduler. If not specified, the pod will be dispatched by default scheduler. type: string + schedulingGates: + description: "SchedulingGates is an opaque list of values that if specified will block scheduling the pod. More info: https://git.k8s.io/enhancements/keps/sig-scheduling/3521-pod-scheduling-readiness. \n This is an alpha-level feature enabled by PodSchedulingReadiness feature gate." + type: array + items: + description: PodSchedulingGate is associated to a Pod to guard its scheduling. + type: object + required: + - name + properties: + name: + description: Name of the scheduling gate. Each scheduling gate must have a unique name field. + type: string + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map securityContext: description: 'SecurityContext holds pod-level security attributes and common container settings. Optional: Defaults to empty. See type description for default values of each field.' type: object @@ -3677,7 +3777,7 @@ spec: description: "type indicates which kind of seccomp profile will be applied. Valid options are: \n Localhost - a profile defined in a file on the node should be used. RuntimeDefault - the container runtime default profile should be used. Unconfined - no profile should be applied." type: string supplementalGroups: - description: A list of groups applied to the first process run in each container, in addition to the container's primary GID. If unspecified, no groups will be added to any container. Note that this field cannot be set when spec.os.name is windows. + description: A list of groups applied to the first process run in each container, in addition to the container's primary GID, the fsGroup (if specified), and group memberships defined in the container image for the uid of the container process. If unspecified, no additional groups are added to any container. Note that group memberships defined in the container image for the uid of the container process are still effective, even if they are not included in this list. Note that this field cannot be set when spec.os.name is windows. type: array items: type: integer @@ -3812,10 +3912,10 @@ spec: type: integer format: int32 nodeAffinityPolicy: - description: "NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector when calculating pod topology spread skew. Options are: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. \n If this value is nil, the behavior is equivalent to the Honor policy. This is a alpha-level feature enabled by the NodeInclusionPolicyInPodTopologySpread feature flag." + description: "NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector when calculating pod topology spread skew. Options are: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. \n If this value is nil, the behavior is equivalent to the Honor policy. This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag." type: string nodeTaintsPolicy: - description: "NodeTaintsPolicy indicates how we will treat node taints when calculating pod topology spread skew. Options are: - Honor: nodes without taints, along with tainted nodes for which the incoming pod has a toleration, are included. - Ignore: node taints are ignored. All nodes are included. \n If this value is nil, the behavior is equivalent to the Ignore policy. This is a alpha-level feature enabled by the NodeInclusionPolicyInPodTopologySpread feature flag." + description: "NodeTaintsPolicy indicates how we will treat node taints when calculating pod topology spread skew. Options are: - Honor: nodes without taints, along with tainted nodes for which the incoming pod has a toleration, are included. - Ignore: node taints are ignored. All nodes are included. \n If this value is nil, the behavior is equivalent to the Ignore policy. This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag." type: string topologyKey: description: TopologyKey is the key of node labels. Nodes that have a label with this key and identical values are considered to be in the same topology. We consider each as a "bucket", and try to put balanced number of pods into each bucket. We define a domain as a particular instance of a topology. Also, we define an eligible domain as a domain whose nodes meet the requirements of nodeAffinityPolicy and nodeTaintsPolicy. e.g. If TopologyKey is "kubernetes.io/hostname", each Node is a domain of that topology. And, if TopologyKey is "topology.kubernetes.io/zone", each zone is a domain of that topology. It's a required field. @@ -4101,7 +4201,7 @@ spec: items: type: string dataSource: - description: 'dataSource field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. If the AnyVolumeDataSource feature gate is enabled, this field will always have the same contents as the DataSourceRef field.' + description: 'dataSource field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef, and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. If the namespace is specified, then dataSourceRef will not be copied to dataSource.' type: object required: - kind @@ -4117,7 +4217,7 @@ spec: description: Name is the name of resource being referenced type: string dataSourceRef: - description: 'dataSourceRef specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any local object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the DataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, both fields (DataSource and DataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. There are two important differences between DataSource and DataSourceRef: * While DataSource only allows two specific types of objects, DataSourceRef allows any non-core object, as well as PersistentVolumeClaim objects. * While DataSource ignores disallowed values (dropping them), DataSourceRef preserves all values, and generates an error if a disallowed value is specified. (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled.' + description: 'dataSourceRef specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the dataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, when namespace isn''t specified in dataSourceRef, both fields (dataSource and dataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. When namespace is specified in dataSourceRef, dataSource isn''t set to the same value and must be empty. There are three important differences between dataSource and dataSourceRef: * While dataSource only allows two specific types of objects, dataSourceRef allows any non-core object, as well as PersistentVolumeClaim objects. * While dataSource ignores disallowed values (dropping them), dataSourceRef preserves all values, and generates an error if a disallowed value is specified. * While dataSource only allows local objects, dataSourceRef allows objects in any namespaces. (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled. (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled.' type: object required: - kind @@ -4132,10 +4232,28 @@ spec: name: description: Name is the name of resource being referenced type: string + namespace: + description: Namespace is the namespace of resource being referenced Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled. + type: string resources: description: 'resources represents the minimum resources the volume should have. If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' type: object properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable." + type: array + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + type: object + required: + - name + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object @@ -4805,6 +4923,7 @@ spec: description: InstallModeType is a supported type of install mode for CSV installation type: string keywords: + description: A list of keywords describing the operator. type: array items: type: string @@ -4814,6 +4933,7 @@ spec: additionalProperties: type: string links: + description: A list of links related to the operator. type: array items: type: object @@ -4823,6 +4943,7 @@ spec: url: type: string maintainers: + description: A list of organizational entities maintaining the operator. type: array items: type: object @@ -4852,6 +4973,7 @@ spec: version: type: string provider: + description: The publishing entity behind the operator. type: object properties: name: @@ -4990,22 +5112,26 @@ spec: type: array items: type: string + x-kubernetes-list-type: atomic apiVersions: description: APIVersions is the API versions the resources belong to. '*' is all versions. If '*' is present, the length of the slice must be one. Required. type: array items: type: string + x-kubernetes-list-type: atomic operations: description: Operations is the operations the admission hook cares about - CREATE, UPDATE, DELETE, CONNECT or * for all of those operations and any future admission operations that are added. If '*' is present, the length of the slice must be one. Required. type: array items: description: OperationType specifies an operation for a request. type: string + x-kubernetes-list-type: atomic resources: description: "Resources is a list of resources this rule applies to. \n For example: 'pods' means pods. 'pods/log' means the log subresource of pods. '*' means all resources, but not subresources. 'pods/*' means all subresources of pods. '*/scale' means all scale subresources. '*/*' means all resources and their subresources. \n If wildcard is present, the validation rule will ensure resources do not overlap with each other. \n Depending on the enclosing object, subresources might not be allowed. Required." type: array items: type: string + x-kubernetes-list-type: atomic scope: description: scope specifies the scope of this rule. Valid values are "Cluster", "Namespaced", and "*" "Cluster" means that only cluster-scoped resources will match this rule. Namespace API objects are cluster-scoped. "Namespaced" means that only namespaced resources will match this rule. "*" means that there are no scope restrictions. Subresources match the scope of their parent resource. Default is "*". type: string diff --git a/staging/operator-lifecycle-manager/deploy/chart/crds/0000_50_olm_00-subscriptions.crd.yaml b/staging/operator-lifecycle-manager/deploy/chart/crds/0000_50_olm_00-subscriptions.crd.yaml index 0ebb188ac0..02411590d9 100644 --- a/staging/operator-lifecycle-manager/deploy/chart/crds/0000_50_olm_00-subscriptions.crd.yaml +++ b/staging/operator-lifecycle-manager/deploy/chart/crds/0000_50_olm_00-subscriptions.crd.yaml @@ -643,6 +643,21 @@ spec: description: 'Resources represents compute resources required by this container. Immutable. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' type: object properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable." + type: array + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + type: object + required: + - name + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object @@ -1016,7 +1031,7 @@ spec: items: type: string dataSource: - description: 'dataSource field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. If the AnyVolumeDataSource feature gate is enabled, this field will always have the same contents as the DataSourceRef field.' + description: 'dataSource field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef, and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. If the namespace is specified, then dataSourceRef will not be copied to dataSource.' type: object required: - kind @@ -1032,7 +1047,7 @@ spec: description: Name is the name of resource being referenced type: string dataSourceRef: - description: 'dataSourceRef specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any local object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the DataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, both fields (DataSource and DataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. There are two important differences between DataSource and DataSourceRef: * While DataSource only allows two specific types of objects, DataSourceRef allows any non-core object, as well as PersistentVolumeClaim objects. * While DataSource ignores disallowed values (dropping them), DataSourceRef preserves all values, and generates an error if a disallowed value is specified. (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled.' + description: 'dataSourceRef specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the dataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, when namespace isn''t specified in dataSourceRef, both fields (dataSource and dataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. When namespace is specified in dataSourceRef, dataSource isn''t set to the same value and must be empty. There are three important differences between dataSource and dataSourceRef: * While dataSource only allows two specific types of objects, dataSourceRef allows any non-core object, as well as PersistentVolumeClaim objects. * While dataSource ignores disallowed values (dropping them), dataSourceRef preserves all values, and generates an error if a disallowed value is specified. * While dataSource only allows local objects, dataSourceRef allows objects in any namespaces. (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled. (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled.' type: object required: - kind @@ -1047,10 +1062,28 @@ spec: name: description: Name is the name of resource being referenced type: string + namespace: + description: Namespace is the namespace of resource being referenced Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled. + type: string resources: description: 'resources represents the minimum resources the volume should have. If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' type: object properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable." + type: array + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + type: object + required: + - name + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object diff --git a/staging/operator-lifecycle-manager/deploy/chart/templates/0000_50_olm_17-upstream-operators.catalogsource.yaml b/staging/operator-lifecycle-manager/deploy/chart/templates/0000_50_olm_17-upstream-operators.catalogsource.yaml index 534a21c2c8..3a072034f0 100644 --- a/staging/operator-lifecycle-manager/deploy/chart/templates/0000_50_olm_17-upstream-operators.catalogsource.yaml +++ b/staging/operator-lifecycle-manager/deploy/chart/templates/0000_50_olm_17-upstream-operators.catalogsource.yaml @@ -9,6 +9,8 @@ spec: image: quay.io/operatorhubio/catalog:latest displayName: Community Operators publisher: OperatorHub.io + grpcPodConfig: + securityContextConfig: restricted updateStrategy: registryPoll: interval: 60m diff --git a/staging/operator-lifecycle-manager/deploy/chart/templates/0000_90_olm_00-service-monitor.yaml b/staging/operator-lifecycle-manager/deploy/chart/templates/0000_90_olm_00-service-monitor.yaml index 5497a8c1aa..6585bd609e 100644 --- a/staging/operator-lifecycle-manager/deploy/chart/templates/0000_90_olm_00-service-monitor.yaml +++ b/staging/operator-lifecycle-manager/deploy/chart/templates/0000_90_olm_00-service-monitor.yaml @@ -36,7 +36,6 @@ metadata: labels: app: catalog-operator spec: - jobLabel: k8s-app endpoints: - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token interval: 30s diff --git a/staging/operator-lifecycle-manager/deploy/chart/templates/0000_90_olm_01-prometheus-rule.yaml b/staging/operator-lifecycle-manager/deploy/chart/templates/0000_90_olm_01-prometheus-rule.yaml index 42905bed82..c9039ae552 100644 --- a/staging/operator-lifecycle-manager/deploy/chart/templates/0000_90_olm_01-prometheus-rule.yaml +++ b/staging/operator-lifecycle-manager/deploy/chart/templates/0000_90_olm_01-prometheus-rule.yaml @@ -29,7 +29,7 @@ spec: namespace: "{{ "{{ $labels.namespace }}" }}" annotations: summary: CSV abnormal for over 30 minutes - description: Fires whenever a CSV is in the Replacing, Pending, Deleting, or Unkown phase for more than 30 minutes. + description: Fires whenever a CSV is in the Replacing, Pending, Deleting, or Unknown phase for more than 30 minutes. message: Failed to install Operator {{ printf "{{ $labels.name }}" }} version {{ printf "{{ $labels.version }}" }}. Phase-{{ printf "{{ $labels.phase }}" }} Reason-{{ printf "{{ $labels.reason }}" }} - name: olm.installplan.rules rules: diff --git a/staging/operator-lifecycle-manager/deploy/chart/templates/_packageserver.deployment-spec.yaml b/staging/operator-lifecycle-manager/deploy/chart/templates/_packageserver.deployment-spec.yaml index 75cdc5b508..43e9d33b0a 100644 --- a/staging/operator-lifecycle-manager/deploy/chart/templates/_packageserver.deployment-spec.yaml +++ b/staging/operator-lifecycle-manager/deploy/chart/templates/_packageserver.deployment-spec.yaml @@ -54,6 +54,7 @@ spec: imagePullPolicy: {{ .Values.package.image.pullPolicy }} ports: - containerPort: {{ .Values.package.service.internalPort }} + protocol: TCP livenessProbe: httpGet: scheme: HTTPS diff --git a/staging/operator-lifecycle-manager/doc/design/building-your-csv.md b/staging/operator-lifecycle-manager/doc/design/building-your-csv.md index 3a23b56a6f..4349c75bd5 100644 --- a/staging/operator-lifecycle-manager/doc/design/building-your-csv.md +++ b/staging/operator-lifecycle-manager/doc/design/building-your-csv.md @@ -247,7 +247,7 @@ The metadata section contains general metadata around the name, version and othe **Version**: The semanic version of the Operator. This value should be incremented each time a new Operator image is published. -**Icon**: a base64 encoded image of the Operator logo or the logo of the publisher. The `base64data` parameter contains the data and the `mediatype` specifies the type of image, eg. `image/png` or `image/svg`. +**Icon**: a base64 encoded image of the Operator logo or the logo of the publisher. The `base64data` parameter contains the data and the `mediatype` specifies the type of image, eg. `image/png` or `image/svg+xml`. **Links**: A list of relevant links for the Operator. Common links include documentation, how-to guides, blog posts, and the company homepage. diff --git a/staging/operator-lifecycle-manager/doc/install/install.md b/staging/operator-lifecycle-manager/doc/install/install.md index b842906146..4be3e31aba 100644 --- a/staging/operator-lifecycle-manager/doc/install/install.md +++ b/staging/operator-lifecycle-manager/doc/install/install.md @@ -25,7 +25,7 @@ This command starts minikube, builds the OLM containers locally with the minikub $ make run-local ``` -You can verify that the OLM components have been successfully deployed by running `kubectl -n local get deployments` +You can verify that the OLM components have been successfully deployed by running `kubectl -n olm get deployments` **NOTE** It is recommended for development purposes and will use the source locally diff --git a/staging/operator-lifecycle-manager/go.mod b/staging/operator-lifecycle-manager/go.mod index 0776678982..4537e757dd 100644 --- a/staging/operator-lifecycle-manager/go.mod +++ b/staging/operator-lifecycle-manager/go.mod @@ -7,122 +7,105 @@ require ( github.com/coreos/go-semver v0.3.0 github.com/davecgh/go-spew v1.1.1 github.com/distribution/distribution v2.7.1+incompatible - github.com/fsnotify/fsnotify v1.5.4 + github.com/fsnotify/fsnotify v1.6.0 github.com/ghodss/yaml v1.0.0 github.com/go-air/gini v1.0.4 github.com/go-bindata/go-bindata/v3 v3.1.3 github.com/go-logr/logr v1.2.3 github.com/golang/mock v1.6.0 - github.com/google/go-cmp v0.5.8 + github.com/google/go-cmp v0.5.9 github.com/googleapis/gnostic v0.5.5 github.com/itchyny/gojq v0.11.0 github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2 github.com/mikefarah/yq/v3 v3.0.0-20201202084205-8846255d1c37 github.com/mitchellh/hashstructure v1.0.0 github.com/mitchellh/mapstructure v1.4.1 - github.com/onsi/ginkgo/v2 v2.1.6 - github.com/onsi/gomega v1.20.1 + github.com/onsi/ginkgo/v2 v2.6.0 + github.com/onsi/gomega v1.24.1 github.com/openshift/api v3.9.0+incompatible github.com/openshift/client-go v0.0.0-20220525160904-9e1acff93e4a - github.com/operator-framework/api v0.17.3 + github.com/operator-framework/api v0.17.6 github.com/operator-framework/operator-registry v1.17.5 github.com/otiai10/copy v1.2.0 github.com/pkg/errors v0.9.1 - github.com/prometheus/client_golang v1.12.2 - github.com/prometheus/client_model v0.2.0 - github.com/prometheus/common v0.32.1 - github.com/sirupsen/logrus v1.8.1 - github.com/spf13/cobra v1.4.0 + github.com/prometheus/client_golang v1.14.0 + github.com/prometheus/client_model v0.3.0 + github.com/prometheus/common v0.37.0 + github.com/sirupsen/logrus v1.9.0 + github.com/spf13/cobra v1.6.1 github.com/spf13/pflag v1.0.5 - github.com/stretchr/testify v1.8.0 - golang.org/x/net v0.0.0-20220909164309-bea034e7d591 - golang.org/x/time v0.0.0-20220609170525-579cf78fd858 - google.golang.org/grpc v1.47.0 + github.com/stretchr/testify v1.8.2 + golang.org/x/net v0.7.0 + golang.org/x/time v0.3.0 + google.golang.org/grpc v1.52.0 gopkg.in/yaml.v2 v2.4.0 - helm.sh/helm/v3 v3.9.0 - k8s.io/api v0.25.3 - k8s.io/apiextensions-apiserver v0.25.3 - k8s.io/apimachinery v0.25.3 - k8s.io/apiserver v0.25.3 - k8s.io/client-go v0.25.3 - k8s.io/code-generator v0.25.3 - k8s.io/component-base v0.25.3 + helm.sh/helm/v3 v3.11.1 + k8s.io/api v0.26.1 + k8s.io/apiextensions-apiserver v0.26.1 + k8s.io/apimachinery v0.26.1 + k8s.io/apiserver v0.26.1 + k8s.io/client-go v0.26.1 + k8s.io/code-generator v0.26.1 + k8s.io/component-base v0.26.1 k8s.io/klog v1.0.0 k8s.io/kube-aggregator v0.25.3 - k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 - k8s.io/utils v0.0.0-20220823124924-e9cbc92d1a73 - sigs.k8s.io/controller-runtime v0.13.0 + k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 + k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 + sigs.k8s.io/controller-runtime v0.14.5 sigs.k8s.io/controller-tools v0.8.0 sigs.k8s.io/kind v0.16.0 ) replace google.golang.org/grpc => google.golang.org/grpc v1.40.0 -replace ( - go.opentelemetry.io/contrib => go.opentelemetry.io/contrib v0.20.0 - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp => go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0 - go.opentelemetry.io/otel/exporters/otlp => go.opentelemetry.io/otel/exporters/otlp v0.20.0 - go.opentelemetry.io/otel/metric => go.opentelemetry.io/otel/metric v0.20.0 - go.opentelemetry.io/otel/oteltest => go.opentelemetry.io/otel/oteltest v0.20.0 - go.opentelemetry.io/otel/sdk/export/metric => go.opentelemetry.io/otel/sdk/export/metric v0.20.0 - go.opentelemetry.io/otel/sdk/metric => go.opentelemetry.io/otel/sdk/metric v0.20.0 - go.opentelemetry.io/otel/trace => go.opentelemetry.io/otel/trace v0.20.0 - go.opentelemetry.io/proto/otlp => go.opentelemetry.io/proto/otlp v0.7.0 -) - require ( - cloud.google.com/go v0.99.0 // indirect + cloud.google.com/go/compute v1.10.0 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect - github.com/Azure/go-autorest v14.2.0+incompatible // indirect - github.com/Azure/go-autorest/autorest v0.11.27 // indirect - github.com/Azure/go-autorest/autorest/adal v0.9.20 // indirect - github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect - github.com/Azure/go-autorest/logger v0.2.1 // indirect - github.com/Azure/go-autorest/tracing v0.6.0 // indirect - github.com/BurntSushi/toml v1.0.0 // indirect - github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd // indirect + github.com/BurntSushi/toml v1.2.1 // indirect + github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect - github.com/Masterminds/semver/v3 v3.1.1 // indirect - github.com/Masterminds/sprig/v3 v3.2.2 // indirect - github.com/Masterminds/squirrel v1.5.2 // indirect + github.com/Masterminds/semver/v3 v3.2.0 // indirect + github.com/Masterminds/sprig/v3 v3.2.3 // indirect + github.com/Masterminds/squirrel v1.5.3 // indirect github.com/Masterminds/vcs v1.13.3 // indirect - github.com/Microsoft/go-winio v0.5.1 // indirect - github.com/Microsoft/hcsshim v0.9.2 // indirect + github.com/Microsoft/go-winio v0.5.2 // indirect + github.com/Microsoft/hcsshim v0.9.6 // indirect github.com/NYTimes/gziphandler v1.1.1 // indirect - github.com/PuerkitoBio/purell v1.1.1 // indirect - github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect github.com/alessio/shellescape v1.4.1 // indirect - github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220418222510-f25a4f6275ed // indirect + github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 // indirect github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver v3.5.1+incompatible // indirect + github.com/cenkalti/backoff/v4 v4.2.0 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect - github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 // indirect - github.com/containerd/cgroups v1.0.3 // indirect - github.com/containerd/containerd v1.6.3 // indirect - github.com/containerd/continuity v0.2.2 // indirect + github.com/chai2010/gettext-go v1.0.2 // indirect + github.com/containerd/cgroups v1.0.4 // indirect + github.com/containerd/containerd v1.6.18 // indirect + github.com/containerd/continuity v0.3.0 // indirect github.com/containerd/ttrpc v1.1.0 // indirect github.com/coreos/go-systemd/v22 v22.3.2 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/cyphar/filepath-securejoin v0.2.3 // indirect - github.com/docker/cli v20.10.11+incompatible // indirect - github.com/docker/distribution v2.8.1+incompatible // indirect - github.com/docker/docker v20.10.14+incompatible // indirect - github.com/docker/docker-credential-helpers v0.6.4 // indirect + github.com/docker/cli v20.10.21+incompatible // indirect + github.com/docker/distribution v2.8.2+incompatible // indirect + github.com/docker/docker v20.10.24+incompatible // indirect + github.com/docker/docker-credential-helpers v0.7.0 // indirect github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-metrics v0.0.1 // indirect github.com/docker/go-units v0.4.0 // indirect - github.com/emicklei/go-restful/v3 v3.8.0 // indirect - github.com/evanphx/json-patch v4.12.0+incompatible // indirect + github.com/emicklei/go-restful/v3 v3.9.0 // indirect + github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect github.com/fatih/color v1.13.0 // indirect - github.com/felixge/httpsnoop v1.0.1 // indirect + github.com/felixge/httpsnoop v1.0.3 // indirect + github.com/fvbommel/sortorder v1.0.1 // indirect github.com/go-errors/errors v1.0.1 // indirect github.com/go-gorp/gorp/v3 v3.0.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/zapr v1.2.3 // indirect github.com/go-openapi/jsonpointer v0.19.5 // indirect - github.com/go-openapi/jsonreference v0.19.5 // indirect + github.com/go-openapi/jsonreference v0.20.0 // indirect github.com/go-openapi/swag v0.19.14 // indirect github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect github.com/gobuffalo/flect v0.2.3 // indirect @@ -130,29 +113,28 @@ require ( github.com/goccy/go-yaml v1.8.1 // indirect github.com/gofrs/flock v0.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt/v4 v4.2.0 // indirect github.com/golang-migrate/migrate/v4 v4.6.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/btree v1.0.1 // indirect - github.com/google/cel-go v0.12.5 // indirect + github.com/google/cel-go v0.12.6 // indirect github.com/google/gnostic v0.5.7-v3refs // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/google/uuid v1.2.0 // indirect + github.com/google/uuid v1.3.0 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/gosuri/uitable v0.0.4 // indirect github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect - github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect github.com/h2non/filetype v1.1.1 // indirect github.com/h2non/go-is-svg v0.0.0-20160927212452-35e8c4b0612c // indirect - github.com/huandu/xstrings v1.3.2 // indirect + github.com/huandu/xstrings v1.3.3 // indirect github.com/imdario/mergo v0.3.12 // indirect - github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/inconshreveable/mousetrap v1.0.1 // indirect github.com/itchyny/astgen-go v0.0.0-20200519013840-cf3ea398f645 // indirect - github.com/jmoiron/sqlx v1.3.4 // indirect + github.com/jmoiron/sqlx v1.3.5 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/kisielk/errcheck v1.5.0 // indirect @@ -161,35 +143,34 @@ require ( github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect github.com/lestrrat-go/strftime v1.0.1 // indirect - github.com/lib/pq v1.10.4 // indirect + github.com/lib/pq v1.10.7 // indirect github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect github.com/mailru/easyjson v0.7.6 // indirect github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-isatty v0.0.14 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect - github.com/mattn/go-sqlite3 v1.14.6 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect + github.com/mattn/go-sqlite3 v1.14.14 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-wordwrap v1.0.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/moby/locker v1.0.1 // indirect github.com/moby/spdystream v0.2.0 // indirect github.com/moby/sys/mountinfo v0.5.0 // indirect - github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect + github.com/moby/term v0.0.0-20221205130635-1aeaba878587 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect github.com/morikuni/aec v1.0.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect + github.com/opencontainers/image-spec v1.1.0-rc2 // indirect github.com/pbnjay/strptime v0.0.0-20140226051138-5c05b0d668c9 // indirect - github.com/pelletier/go-toml v1.9.4 // indirect + github.com/pelletier/go-toml v1.9.5 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/procfs v0.7.3 // indirect - github.com/rubenv/sql-migrate v1.1.1 // indirect - github.com/russross/blackfriday v1.5.2 // indirect + github.com/prometheus/procfs v0.8.0 // indirect + github.com/rubenv/sql-migrate v1.2.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/shopspring/decimal v1.2.0 // indirect github.com/spf13/cast v1.4.1 // indirect @@ -197,55 +178,55 @@ require ( github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect - github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca // indirect + github.com/xlab/treeprint v1.1.0 // indirect go.etcd.io/bbolt v1.3.6 // indirect - go.etcd.io/etcd/api/v3 v3.5.4 // indirect - go.etcd.io/etcd/client/pkg/v3 v3.5.4 // indirect - go.etcd.io/etcd/client/v3 v3.5.4 // indirect + go.etcd.io/etcd/api/v3 v3.5.5 // indirect + go.etcd.io/etcd/client/pkg/v3 v3.5.5 // indirect + go.etcd.io/etcd/client/v3 v3.5.5 // indirect go.opencensus.io v0.23.0 // indirect - go.opentelemetry.io/contrib v1.3.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.28.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0 // indirect - go.opentelemetry.io/otel v1.3.0 // indirect - go.opentelemetry.io/otel/exporters/otlp v0.20.0 // indirect - go.opentelemetry.io/otel/metric v0.20.0 // indirect - go.opentelemetry.io/otel/sdk v1.3.0 // indirect - go.opentelemetry.io/otel/sdk/export/metric v0.20.0 // indirect - go.opentelemetry.io/otel/sdk/metric v0.20.0 // indirect - go.opentelemetry.io/otel/trace v1.3.0 // indirect - go.opentelemetry.io/proto/otlp v0.12.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.35.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.35.0 // indirect + go.opentelemetry.io/otel v1.12.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.12.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.12.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.12.0 // indirect + go.opentelemetry.io/otel/metric v0.31.0 // indirect + go.opentelemetry.io/otel/sdk v1.12.0 // indirect + go.opentelemetry.io/otel/trace v1.12.0 // indirect + go.opentelemetry.io/proto/otlp v0.19.0 // indirect go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect - go.uber.org/zap v1.21.0 // indirect - golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd // indirect + go.uber.org/zap v1.24.0 // indirect + golang.org/x/crypto v0.5.0 // indirect golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect - golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect - golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 // indirect - golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect - golang.org/x/sys v0.0.0-20220907062415-87db552b00fd // indirect - golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect - golang.org/x/text v0.3.7 // indirect - golang.org/x/tools v0.1.12 // indirect - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + golang.org/x/mod v0.6.0 // indirect + golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect + golang.org/x/sync v0.1.0 // indirect + golang.org/x/sys v0.5.0 // indirect + golang.org/x/term v0.5.0 // indirect + golang.org/x/text v0.7.0 // indirect + golang.org/x/tools v0.2.0 // indirect + golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 // indirect - google.golang.org/protobuf v1.28.0 // indirect + google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 // indirect + google.golang.org/protobuf v1.28.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/cli-runtime v0.24.0 // indirect - k8s.io/gengo v0.0.0-20211129171323-c02415ce4185 // indirect + k8s.io/cli-runtime v0.26.0 // indirect + k8s.io/gengo v0.0.0-20220902162205-c0856e24416d // indirect k8s.io/klog/v2 v2.80.1 // indirect - k8s.io/kubectl v0.24.0 // indirect - oras.land/oras-go v1.1.0 // indirect + k8s.io/kms v0.26.1 // indirect + k8s.io/kubectl v0.26.0 // indirect + oras.land/oras-go v1.2.2 // indirect rsc.io/letsencrypt v0.0.3 // indirect - sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.33 // indirect + sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.35 // indirect sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect - sigs.k8s.io/kustomize/api v0.11.4 // indirect - sigs.k8s.io/kustomize/kyaml v0.13.6 // indirect + sigs.k8s.io/kustomize/api v0.12.1 // indirect + sigs.k8s.io/kustomize/kyaml v0.13.9 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect sigs.k8s.io/yaml v1.3.0 // indirect ) @@ -254,7 +235,4 @@ replace ( // controller runtime github.com/openshift/api => github.com/openshift/api v0.0.0-20221021112143-4226c2167e40 // release-4.12 github.com/openshift/client-go => github.com/openshift/client-go v0.0.0-20221019143426-16aed247da5c // release-4.12 - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc => go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0 - go.opentelemetry.io/otel => go.opentelemetry.io/otel v0.20.0 - go.opentelemetry.io/otel/sdk => go.opentelemetry.io/otel/sdk v0.20.0 ) diff --git a/staging/operator-lifecycle-manager/go.sum b/staging/operator-lifecycle-manager/go.sum index a0d4642a96..36b992be73 100644 --- a/staging/operator-lifecycle-manager/go.sum +++ b/staging/operator-lifecycle-manager/go.sum @@ -1,5 +1,4 @@ bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= -bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -20,21 +19,14 @@ cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmW cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= -cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= -cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= -cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= -cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= -cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= -cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= -cloud.google.com/go v0.99.0 h1:y/cM2iqGgGi5D5DQZl6D9STN/3dR/Vx5Mp8s752oJTY= -cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/compute v1.10.0 h1:aoLIYaA1fX3ywihqpBk2APQKOo20nXsp1GEZQbx5Jk4= +cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= @@ -53,54 +45,42 @@ github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= -github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= -github.com/Azure/go-autorest/autorest v0.11.27 h1:F3R3q42aWytozkV8ihzcgMO4OA4cuqr3bNlsEuF6//A= -github.com/Azure/go-autorest/autorest v0.11.27/go.mod h1:7l8ybrIdUmGqZMTD0sRtAr8NvbHjfofbf8RSP2q7w7U= github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= -github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= -github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= -github.com/Azure/go-autorest/autorest/adal v0.9.20 h1:gJ3E98kMpFB1MFqQCvA1yFab8vthOeD4VlFRQULxahg= -github.com/Azure/go-autorest/autorest/adal v0.9.20/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= -github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/autorest/mocks v0.4.2 h1:PGN4EDXnuQbojHbU0UWoNvmu9AGVwYHG9/fkDYhtAfw= -github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= -github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= -github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU= github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= +github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= -github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd h1:sjQovDkwrZp8u+gxLtPgKGjk5hCxuy2hrRejBTA9xFU= github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= +github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= +github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= -github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= -github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= -github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= -github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8= -github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= -github.com/Masterminds/squirrel v1.5.2 h1:UiOEi2ZX4RCSkpiNDQN5kro/XIBpSRk9iTqdIRPzUXE= -github.com/Masterminds/squirrel v1.5.2/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= +github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= +github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/Masterminds/sprig/v3 v3.2.0/go.mod h1:tWhwTbUTndesPNeF0C900vKoq283u6zp4APT9vaF3SI= +github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= +github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= +github.com/Masterminds/squirrel v1.5.3 h1:YPpoceAcxuzIljlr5iWpNKaql7hLeG1KLSrhvdHpkZc= +github.com/Masterminds/squirrel v1.5.3/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= github.com/Masterminds/vcs v1.13.3 h1:IIA2aBdXvfbIM+yl/eTnL4hb1XwdpvuQLglAix1gweE= github.com/Masterminds/vcs v1.13.3/go.mod h1:TiE7xuEjl1N4j016moRd6vezp6e6Lz23gypeXfzXeW8= github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= @@ -111,8 +91,8 @@ github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugX github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY= -github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= +github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= @@ -121,8 +101,8 @@ github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2 github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= -github.com/Microsoft/hcsshim v0.9.2 h1:wB06W5aYFfUB3IvootYAY2WnOmIdgPGfqSI6tufQNnY= -github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= +github.com/Microsoft/hcsshim v0.9.6 h1:VwnDOgLeoi2du6dAznfmspNqTiwczvjv4K7NxuY9jsY= +github.com/Microsoft/hcsshim v0.9.6/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= @@ -132,10 +112,8 @@ github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8 github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= @@ -154,8 +132,8 @@ github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:C github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220418222510-f25a4f6275ed h1:ue9pVfIcP+QMEjfgo/Ez4ZjNZfonGgR6NgjMaJMu1Cg= -github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220418222510-f25a4f6275ed/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= +github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 h1:yL7+Jz0jTC6yykIK/Wh74gnTJnrGr5AyrNMXuA0gves= +github.com/antlr/antlr4/runtime/Go/antlr v1.4.10/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= @@ -169,7 +147,6 @@ github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 h1:4daAzAu0 github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -201,13 +178,16 @@ github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3k github.com/bugsnag/panicwrap v1.2.0 h1:OzrKrRvXis8qEvOkfcxNcYbOd2O7xXS2nnKMEMABFQA= github.com/bugsnag/panicwrap v1.2.0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4= +github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 h1:7aWHqerlJ41y6FOsEUvknqgXnGmJyJSbjhAWq5pO4F8= github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= +github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= +github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= @@ -237,8 +217,8 @@ github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4S github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= -github.com/containerd/cgroups v1.0.3 h1:ADZftAkglvCiD44c77s5YmMqaP2pzVCFZvBmAlBdAP4= -github.com/containerd/cgroups v1.0.3/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8= +github.com/containerd/cgroups v1.0.4 h1:jN/mbWBEaz+T1pi5OFtnkQ+8qnmEbAr1Oo1FRm5B0dA= +github.com/containerd/cgroups v1.0.4/go.mod h1:nLNQtsF7Sl2HxNebu77i1R0oDlhiTG+kO4JTrUzo6IA= github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= @@ -259,8 +239,8 @@ github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09Zvgq github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g= github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c= -github.com/containerd/containerd v1.6.3 h1:JfgUEIAH07xDWk6kqz0P3ArZt+KJ9YeihSC9uyFtSKg= -github.com/containerd/containerd v1.6.3/go.mod h1:gCVGrYRYFm2E8GmuUIbj/NGD7DLZQLzSJQazjVKDOig= +github.com/containerd/containerd v1.6.18 h1:qZbsLvmyu+Vlty0/Ex5xc0z2YtKpIsb5n45mAMI+2Ns= +github.com/containerd/containerd v1.6.18/go.mod h1:1RdCUu95+gc2v9t3IL+zIlpClSmew7/0YS8O5eQZrOw= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= @@ -269,8 +249,8 @@ github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cE github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ= github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= -github.com/containerd/continuity v0.2.2 h1:QSqfxcn8c+12slxwu00AtzXrsami0MJb/MQs9lOLHLA= -github.com/containerd/continuity v0.2.2/go.mod h1:pWygW9u7LtS1o4N/Tn0FoCFDIXZ7rxcMX7HX1Dmibvk= +github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= +github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= @@ -340,12 +320,12 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= -github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI= github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= @@ -363,7 +343,6 @@ github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1S github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8= github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I= -github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7hqDjlFjiygg= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -377,28 +356,28 @@ github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8 github.com/dhui/dktest v0.3.0/go.mod h1:cyzIUfGsBEbZ6BT7tnXqAShHSXCZhSNmFl70sZ7c1yc= github.com/distribution/distribution v2.7.1+incompatible h1:aGFx4EvJWKEh//lHPLwFhFgwFHKH06TzNVPamrMn04M= github.com/distribution/distribution v2.7.1+incompatible/go.mod h1:EgLm2NgWtdKgzF9NpMzUKgzmR7AMmb0VQi2B+ZzDRjc= -github.com/distribution/distribution/v3 v3.0.0-20211118083504-a29a3c99a684 h1:DBZ2sN7CK6dgvHVpQsQj4sRMCbWTmd17l+5SUCjnQSY= +github.com/distribution/distribution/v3 v3.0.0-20221208165359-362910506bc2 h1:aBfCb7iqHmDEIp6fBvC/hQUddQfg+3qdYjwzaiP9Hnc= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli v0.0.0-20200130152716-5d0cf8839492/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/cli v20.10.11+incompatible h1:tXU1ezXcruZQRrMP8RN2z9N91h+6egZTS1gsPsKantc= -github.com/docker/cli v20.10.11+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v20.10.21+incompatible h1:qVkgyYUnOLQ98LtXBrwd/duVqPT2X4SHndOuGsfwyhU= +github.com/docker/cli v20.10.21+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= github.com/docker/distribution v2.7.0+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= -github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= +github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v0.7.3-0.20190103212154-2b7e084dc98b/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v0.7.3-0.20190817195342-4760db040282/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v1.4.2-0.20200203170920-46ec8731fbce/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v20.10.14+incompatible h1:+T9/PRYWNDo5SZl5qS1r9Mo/0Q8AwxKKPtu9S1yxM0w= -github.com/docker/docker v20.10.14+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.24+incompatible h1:Ugvxm7a8+Gz6vqQYQQ2W7GYq5EUPaAiuPgIfVyI3dYE= +github.com/docker/docker v20.10.24+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= -github.com/docker/docker-credential-helpers v0.6.4 h1:axCks+yV+2MR3/kZhAmy07yC56WZ2Pwu/fKWtKuZB0o= -github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c= +github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= +github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= @@ -426,8 +405,8 @@ github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7fo github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= 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.8.0 h1:eCZ8ulSerjdAiaNpF7GxXIE7ZCMo1moN1qX+S609eVw= -github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= +github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= @@ -435,9 +414,8 @@ github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMi github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= -github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= +github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.2.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= @@ -450,24 +428,23 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= -github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= +github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c= -github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= 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/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= -github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/fsouza/fake-gcs-server v1.7.0/go.mod h1:5XIRs4YvwNbNoz+1JF8j6KLAyDh7RHGAyAK3EP2EsNk= github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= +github.com/fvbommel/sortorder v1.0.1 h1:dSnXLt4mJYH25uDDGa3biZNQsozaUWDSWeKJ0qqFfzE= github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= github.com/garyburd/redigo v1.6.0 h1:0VruCpn7yAIIu7pWVClQC8wxCJEcG3nyzpMSHKi1PQc= github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= -github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -497,9 +474,11 @@ github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3I github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v0.3.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= @@ -507,8 +486,9 @@ github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbV github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v0.2.0/go.mod h1:qhKdvif7YF5GI9NWEpyxTSSBdGmzkNguibrdCNVPunU= -github.com/go-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro= github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= @@ -531,8 +511,8 @@ github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3Hfo github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM= -github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= +github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= +github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= @@ -563,8 +543,9 @@ github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85n github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= @@ -602,13 +583,12 @@ github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= -github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-migrate/migrate/v4 v4.6.2 h1:LDDOHo/q1W5UDj6PbkxdCv7lv9yunyZHXvxuwDkGo3k= github.com/golang-migrate/migrate/v4 v4.6.2/go.mod h1:JYi6reN3+Z734VZ0akNuyOJNcrg45ZL7LDBMW3WGJL0= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= +github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -647,7 +627,6 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golangplus/bytes v0.0.0-20160111154220-45c989fe5450/go.mod h1:Bk6SMAONeMXrxql8uvOKuAZSu8aM5RUGv+1C6IJaEho= github.com/golangplus/fmt v0.0.0-20150411045040-2a5d6d7d2995/go.mod h1:lJgMEyOkYFkPcDKwRXegd+iM6E7matEszMG5HhwytU8= github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk= @@ -656,8 +635,8 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= -github.com/google/cel-go v0.12.5 h1:DmzaiSgoaqGCjtpPQWl26/gND+yRpim56H1jCVev6d8= -github.com/google/cel-go v0.12.5/go.mod h1:Jk7ljRzLBhkmiAwBoUxB1sZSCVBAzkqPF25olK/iRDw= +github.com/google/cel-go v0.12.6 h1:kjeKudqV0OygrAqA9fX6J55S8gj+Jre2tckIm5RoG4M= +github.com/google/cel-go v0.12.6/go.mod h1:Jk7ljRzLBhkmiAwBoUxB1sZSCVBAzkqPF25olK/iRDw= github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -672,8 +651,8 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= @@ -684,7 +663,6 @@ github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -696,8 +674,6 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= @@ -706,12 +682,11 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3 github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= -github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= @@ -747,6 +722,8 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 h1:BZHcxBETFHIdVyhyEfOvn/RdU/QGdLI4y34qQGjGWO0= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= github.com/grpc-ecosystem/grpc-health-probe v0.3.2/go.mod h1:izVOQ4RWbjUR6lm4nn+VLJyQ+FyaiGmprEYgI04Gs7U= github.com/h2non/filetype v1.1.1 h1:xvOwnXKAckvtLWsN398qS9QhlxlnVXBjXBydK2/UFB4= github.com/h2non/filetype v1.1.1/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY= @@ -770,6 +747,7 @@ github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= @@ -779,8 +757,9 @@ github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/J github.com/hokaccha/go-prettyjson v0.0.0-20190818114111-108c894c2c0e/go.mod h1:pFlLw2CfqZiIBOx6BuCeRLCrfxBJipTY0nIOF/VbGcI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4= +github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= @@ -789,8 +768,9 @@ github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= +github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/itchyny/astgen-go v0.0.0-20200519013840-cf3ea398f645 h1:3gyXljUyTWWTv/NMFPvwgxJSdE9Mamg2r3x8HMBl+Uo= github.com/itchyny/astgen-go v0.0.0-20200519013840-cf3ea398f645/go.mod h1:296z3W7Xsrp2mlIY88ruDKscuvrkL6zXCNRtaYVshzw= github.com/itchyny/go-flags v1.5.0/go.mod h1:lenkYuCobuxLBAd/HGFE4LRoW8D3B6iXRQfWYJ+MNbA= @@ -808,15 +788,14 @@ github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmoiron/sqlx v1.3.4 h1:wv+0IJZfL5z0uZoUjlpKgHkgaFSYD+r9CfrXjEXsO7w= -github.com/jmoiron/sqlx v1.3.4/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= +github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= +github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= github.com/joefitzgerald/rainbow-reporter v0.1.0 h1:AuMG652zjdzI0YCCnXAqATtRBpGXMcAnrajcaTrSeuo= github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= github.com/joelanford/ignore v0.0.0-20210607151042-0d25dc18b62d h1:A2/B900ip/Z20TzkLeGRNy1s6J2HmH9AmGt+dHyqb4I= github.com/joelanford/ignore v0.0.0-20210607151042-0d25dc18b62d/go.mod h1:7HQupe4vyNxMKXmM5DFuwXHsqwMyglcYmZBtlDPIcZ8= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= -github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= @@ -876,8 +855,8 @@ github.com/lestrrat-go/strftime v1.0.1/go.mod h1:E1nN3pCbtMSu1yjSVeyuRFVm/U0xoR7 github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk= -github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= +github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo= @@ -918,7 +897,6 @@ github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9 github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-oci8 v0.1.1/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= @@ -926,11 +904,13 @@ github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vq github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= -github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v1.14.14 h1:qZgc/Rwetq+MtyE18WhzjokPD93dNqLGNT3QJuLvBGw= +github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2 h1:g+4J5sZg6osfvEfkRZxJ1em0VT95/UOZgi/l7zi1/oE= github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= @@ -939,7 +919,7 @@ github.com/mikefarah/yq/v3 v3.0.0-20201202084205-8846255d1c37 h1:lPmsut5Sk7eK2Bm github.com/mikefarah/yq/v3 v3.0.0-20201202084205-8846255d1c37/go.mod h1:dYWq+UWoFCDY1TndvFUQuhBbIYmZpjreC8adEAx93zE= github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/cli v1.1.2/go.mod h1:6iaV0fGdElS6dPBx0EApTxHrcWvmJphyh2n8YBLPPZ4= +github.com/mitchellh/cli v1.1.4/go.mod h1:vTLESy5mRhKOs9KDp0/RATawxP1UqBmdrpVRMnpcvKQ= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= @@ -970,8 +950,8 @@ github.com/moby/sys/mountinfo v0.5.0 h1:2Ks8/r6lopsxWi9m58nlwjaeSzUX9iiL1vj5qB/9 github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= -github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc= -github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= +github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA= +github.com/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -998,7 +978,6 @@ github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -1010,11 +989,10 @@ github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+ github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo/v2 v2.1.6 h1:Fx2POJZfKRQcM1pH49qSZiYeu319wji004qX+GDovrU= -github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= +github.com/onsi/ginkgo/v2 v2.6.0 h1:9t9b9vRUbFq3C4qKFCGkVuq/fIHji802N1nrtkh1mNc= +github.com/onsi/ginkgo/v2 v2.6.0/go.mod h1:63DOGlLAH8+REH8jUGdL3YpCpu7JODesutUjdENfUAc= github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -1026,8 +1004,8 @@ github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoT 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.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= -github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q= -github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= +github.com/onsi/gomega v1.24.1 h1:KORJXNNTzJXzu4ScJWssJfJMnJ+2QJqhoQSRwNlze9E= +github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM= github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= @@ -1037,8 +1015,8 @@ github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3I github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 h1:rc3tiVYb5z54aKaDfakKn0dDjIyPpTtszkjuMzyt7ec= -github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034= +github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ= github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= @@ -1062,8 +1040,8 @@ github.com/openshift/client-go v0.0.0-20221019143426-16aed247da5c h1:CV76yFOTXmq github.com/openshift/client-go v0.0.0-20221019143426-16aed247da5c/go.mod h1:lFMO8mLHXWFzSdYvGNo8ivF9SfF6zInA8ZGw4phRnUE= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/operator-framework/api v0.7.1/go.mod h1:L7IvLd/ckxJEJg/t4oTTlnHKAJIP/p51AvEslW3wYdY= -github.com/operator-framework/api v0.17.3 h1:wddE1SLKTNiIzwt28DbBIO+vPG2GOV6dkB9xBkDfT3o= -github.com/operator-framework/api v0.17.3/go.mod h1:34tb98EwTN5SZLkgoxwvRkhMJKLHUWHOrrcv1ZwvEeA= +github.com/operator-framework/api v0.17.6 h1:E6+vlvYUKafvoXYtCuHlDZrXX4vl8AT+r93OxNlzjpU= +github.com/operator-framework/api v0.17.6/go.mod h1:l/cuwtPxkVUY7fzYgdust2m9tlmb8I4pOvbsUufRb24= github.com/operator-framework/operator-registry v1.17.5 h1:LR8m1rFz5Gcyje8WK6iYt+gIhtzqo52zMRALdmTYHT0= github.com/operator-framework/operator-registry v1.17.5/go.mod h1:sRQIgDMZZdUcmHltzyCnM6RUoDF+WS8Arj1BQIARDS8= github.com/otiai10/copy v1.2.0 h1:HvG945u96iNadPoG2/Ja2+AUJeW5YuFQMixq9yirC+k= @@ -1080,12 +1058,13 @@ github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtP github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM= github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= +github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc= github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= +github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -1110,15 +1089,16 @@ github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.12.2 h1:51L9cDoUHVrXx4zWYlcLQIZ+d+VXHgqnYKkIuq4g/34= -github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= +github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= @@ -1127,8 +1107,9 @@ github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= +github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= @@ -1141,17 +1122,17 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= +github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= -github.com/rubenv/sql-migrate v1.1.1 h1:haR5Hn8hbW9/SpAICrXoZqXnywS7Q5WijwkQENPeNWY= -github.com/rubenv/sql-migrate v1.1.1/go.mod h1:/7TZymwxN8VWumcIxw1jjHEcR1djpdkMHQPT4FWdnbQ= -github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= +github.com/rubenv/sql-migrate v1.2.0 h1:fOXMPLMd41sK7Tg75SXDec15k3zg5WNV6SjuDRiNfcU= +github.com/rubenv/sql-migrate v1.2.0/go.mod h1:Z5uVnq7vrIrPmHbVFfR4YLHRZquxeHpckCnRq0P/K9Y= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= @@ -1177,8 +1158,9 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= @@ -1187,7 +1169,6 @@ github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= @@ -1199,8 +1180,9 @@ github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tL github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= -github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= +github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= +github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= @@ -1220,8 +1202,9 @@ github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -1231,8 +1214,9 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= @@ -1245,7 +1229,6 @@ github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhV github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA= -github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= @@ -1274,8 +1257,8 @@ github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17 github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI= -github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= +github.com/xlab/treeprint v1.1.0 h1:G/1DjNkPpfZCFt9CSh6b5/nY4VimlbHF3Rh4obvtzDk= +github.com/xlab/treeprint v1.1.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -1283,7 +1266,7 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= github.com/yvasiyarov/go-metrics v0.0.0-20150112132944-c25f46c4b940 h1:p7OofyZ509h8DmPLh8Hn+EIIZm/xYhdZHJ9GnXHdr6U= github.com/yvasiyarov/go-metrics v0.0.0-20150112132944-c25f46c4b940/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= @@ -1305,18 +1288,18 @@ go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mI go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489 h1:1JFLBqwIgdyHN1ZtgjTBwO+blA6gVOmZurpiMEsETKo= go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/api/v3 v3.5.4 h1:OHVyt3TopwtUQ2GKdd5wu3PmmipR4FTwCqoEjSyRdIc= -go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A= +go.etcd.io/etcd/api/v3 v3.5.5 h1:BX4JIbQ7hl7+jL+g+2j5UAr0o1bctCm6/Ct+ArBGkf0= +go.etcd.io/etcd/api/v3 v3.5.5/go.mod h1:KFtNaxGDw4Yx/BA4iPPwevUTAuqcsPxzyX8PHydchN8= go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/pkg/v3 v3.5.4 h1:lrneYvz923dvC14R54XcA7FXoZ3mlGZAgmwhfm7HqOg= -go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/pkg/v3 v3.5.5 h1:9S0JUVvmrVl7wCF39iTQthdaaNIiAaQbmK75ogO6GU8= +go.etcd.io/etcd/client/pkg/v3 v3.5.5/go.mod h1:ggrwbk069qxpKPq8/FKkQ3Xq9y39kbFR4LnKszpRXeQ= go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= -go.etcd.io/etcd/client/v2 v2.305.4 h1:Dcx3/MYyfKcPNLpR4VVQUP5KgYrBeJtktBwEKkw08Ao= -go.etcd.io/etcd/client/v3 v3.5.4 h1:p83BUL3tAYS0OT/r0qglgc3M1JjhM0diV8DSWAhVXv4= -go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY= -go.etcd.io/etcd/pkg/v3 v3.5.4 h1:V5Dvl7S39ZDwjkKqJG2BfXgxZ3QREqqKifWQgIw5IM0= -go.etcd.io/etcd/raft/v3 v3.5.4 h1:YGrnAgRfgXloBNuqa+oBI/aRZMcK/1GS6trJePJ/Gqc= -go.etcd.io/etcd/server/v3 v3.5.4 h1:CMAZd0g8Bn5NRhynW6pKhc4FRg41/0QYy3d7aNm9874= +go.etcd.io/etcd/client/v2 v2.305.5 h1:DktRP60//JJpnPC0VBymAN/7V71GHMdjDCBt4ZPXDjI= +go.etcd.io/etcd/client/v3 v3.5.5 h1:q++2WTJbUgpQu4B6hCuT7VkdwaTP7Qz6Daak3WzbrlI= +go.etcd.io/etcd/client/v3 v3.5.5/go.mod h1:aApjR4WGlSumpnJ2kloS75h6aHUmAyaPLjHMxpc7E7c= +go.etcd.io/etcd/pkg/v3 v3.5.5 h1:Ablg7T7OkR+AeeeU32kdVhw/AGDsitkKPl7aW73ssjU= +go.etcd.io/etcd/raft/v3 v3.5.5 h1:Ibz6XyZ60OYyRopu73lLM/P+qco3YtlZMOhnXNS051I= +go.etcd.io/etcd/server/v3 v3.5.5 h1:jNjYm/9s+f9A9r6+SC4RvNaz6AqixpOvhrFdT0PvIj0= go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.0/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= @@ -1331,30 +1314,27 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opentelemetry.io/contrib v0.20.0 h1:ubFQUn0VCZ0gPwIoJfBJVpeBlyRMxu8Mm/huKWYd9p0= -go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0 h1:sO4WKdPAudZGKPcpZT4MJn6JaDmpyLrMPDGGyA1SttE= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0 h1:Q3C9yzW6I9jqEc8sawxzxZmY48fs9u220KXq6d5s3XU= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= -go.opentelemetry.io/otel v0.20.0 h1:eaP0Fqu7SXHwvjiqDq83zImeehOHX8doTvU9AwXON8g= -go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= -go.opentelemetry.io/otel/exporters/otlp v0.20.0 h1:PTNgq9MRmQqqJY0REVbZFvwkYOA85vbdQU/nVfxDyqg= -go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= -go.opentelemetry.io/otel/metric v0.20.0 h1:4kzhXFP+btKm4jwxpjIqjs41A7MakRFUS86bqLHTIw8= -go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= -go.opentelemetry.io/otel/oteltest v0.20.0 h1:HiITxCawalo5vQzdHfKeZurV8x7ljcqAgiWzF6Vaeaw= -go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= -go.opentelemetry.io/otel/sdk v0.20.0 h1:JsxtGXd06J8jrnya7fdI/U/MR6yXA5DtbZy+qoHQlr8= -go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= -go.opentelemetry.io/otel/sdk/export/metric v0.20.0 h1:c5VRjxCXdQlx1HjzwGdQHzZaVI82b5EbBgOu2ljD92g= -go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= -go.opentelemetry.io/otel/sdk/metric v0.20.0 h1:7ao1wpzHRVKf0OQ7GIxiQJA6X7DLX9o14gmVon7mMK8= -go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= -go.opentelemetry.io/otel/trace v0.20.0 h1:1DL6EXUdcg95gukhuRRvLDO/4X5THh/5dIV52lqtnbw= -go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= -go.opentelemetry.io/proto/otlp v0.7.0 h1:rwOQPCuKAKmwGKq2aVNnYIibI6wnV7EvzgfTCzcdGg8= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.35.0 h1:xFSRQBbXF6VvYRf2lqMJXxoB72XI1K/azav8TekHHSw= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.35.0/go.mod h1:h8TWwRAhQpOd0aM5nYsRD8+flnkj+526GEIVlarH7eY= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.35.0 h1:Ajldaqhxqw/gNzQA45IKFWLdG7jZuXX/wBW1d5qvbUI= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.35.0/go.mod h1:9NiG9I2aHTKkcxqCILhjtyNA1QEiCjdBACv4IvrFQ+c= +go.opentelemetry.io/otel v1.12.0 h1:IgfC7kqQrRccIKuB7Cl+SRUmsKbEwSGPr0Eu+/ht1SQ= +go.opentelemetry.io/otel v1.12.0/go.mod h1:geaoz0L0r1BEOR81k7/n9W4TCXYCJ7bPO7K374jQHG0= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.12.0 h1:UfDENi+LTcLjQ/JhaXimjlIgn7wWjwbEMmdREm2Gyng= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.12.0/go.mod h1:rqbht/LlhVBgn5+k3M5QK96K5Xb0DvXpMJ5SFQpY6uw= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.12.0 h1:ZVqtSAxrR4+ofzayuww0/EKamCjjnwnXTMRZzMudJoU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.12.0/go.mod h1:IlaGLENJkAl9+Xoo3J0unkdOwtL+rmqZ3ryMjUtYA94= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.12.0 h1:+tsVdWosoqDfX6cdHAeacZozjQS94ySBd+aUXFwnNKA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.12.0/go.mod h1:jSqjV+Knu1Jyvh+l3fx7V210Ev3HHgNQAi8YqpXaQP8= +go.opentelemetry.io/otel/metric v0.31.0 h1:6SiklT+gfWAwWUR0meEMxQBtihpiEs4c+vL9spDTqUs= +go.opentelemetry.io/otel/metric v0.31.0/go.mod h1:ohmwj9KTSIeBnDBm/ZwH2PSZxZzoOaG2xZeekTRzL5A= +go.opentelemetry.io/otel/sdk v1.12.0 h1:8npliVYV7qc0t1FKdpU08eMnOjgPFMnriPhn0HH4q3o= +go.opentelemetry.io/otel/sdk v1.12.0/go.mod h1:WYcvtgquYvgODEvxOry5owO2y9MyciW7JqMz6cpXShE= +go.opentelemetry.io/otel/trace v1.12.0 h1:p28in++7Kd0r2d8gSt931O57fdjUyWxkVbESuILAeUc= +go.opentelemetry.io/otel/trace v1.12.0/go.mod h1:pHlgBynn6s25qJ2szD+Bv+iwKJttjHSI3lUAyf0GNuQ= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw= +go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 h1:+FNtrFTmVw0YZGpBGX56XDee331t6JAXeK2bcyhLOOc= go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -1363,8 +1343,6 @@ go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= @@ -1376,8 +1354,8 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= -go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= +go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1404,10 +1382,9 @@ golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38= -golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= +golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1443,9 +1420,9 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I= +golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1502,15 +1479,15 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220909164309-bea034e7d591 h1:D0B/7al0LLrVC8aWF4+oxpv/m8bc7ViFfVS8/gXGdqI= -golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1525,12 +1502,10 @@ golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 h1:OSnWWcOd/CtWQC2cYSBgbTSJv3ciqd8r54ySIW2y3RE= -golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 h1:nt+Q6cXKz4MosCSpnbMtqiQ8Oz0pxTef2B4Vca2lvfk= +golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1542,8 +1517,9 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1640,29 +1616,27 @@ golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220907062415-87db552b00fd h1:AZeIEzg+8RCELJYq8w+ODLVxFgLMMigSwO/ffKPEd9U= -golang.org/x/sys v0.0.0-20220907062415-87db552b00fd/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1672,17 +1646,18 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220609170525-579cf78fd858 h1:Dpdu/EMxGMFgq0CeYMh4fazTD2vtlZRYE7wyynxJb9U= -golang.org/x/time v0.0.0-20220609170525-579cf78fd858/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1751,18 +1726,16 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= -golang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= -golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE= +golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= gomodules.xyz/jsonpatch/v2 v2.1.0/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU= gomodules.xyz/jsonpatch/v2 v2.2.0 h1:4pT439QV83L+G9FkcCriY6EkpcK6r6bK+A5FBUMI7qY= gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY= @@ -1791,15 +1764,6 @@ google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjR google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= -google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= -google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= -google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= -google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= -google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= -google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= -google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1856,31 +1820,13 @@ google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= -google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 h1:hrbNEivu7Zn1pxvHk6MBrq9iE22woVILTHqexqBxe6I= -google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 h1:a2S6M0+660BgMNl++4JPlcAO/CjkqYItDEZwkoDQK7c= +google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc/cmd/protoc-gen-go-grpc v0.0.0-20200709232328-d8193ee9cc3e/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1894,8 +1840,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1949,8 +1895,8 @@ gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81 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= -helm.sh/helm/v3 v3.9.0 h1:qDSWViuF6SzZX5s5AB/NVRGWmdao7T5j4S4ebIkMGag= -helm.sh/helm/v3 v3.9.0/go.mod h1:fzZfyslcPAWwSdkXrXlpKexFeE2Dei8N27FFQWt+PN0= +helm.sh/helm/v3 v3.11.1 h1:cmL9fFohOoNQf+wnp2Wa0OhNFH0KFnSzEkVxi3fcc3I= +helm.sh/helm/v3 v3.11.1/go.mod h1:z/Bu/BylToGno/6dtNGuSmjRqxKq5gaH+FU0BPO+AQ8= 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= @@ -1962,54 +1908,48 @@ k8s.io/api v0.18.2/go.mod h1:SJCWI7OLzhZSvbY7U8zwNl9UA4o1fizoug34OV/2r78= k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8= -k8s.io/api v0.24.0/go.mod h1:5Jl90IUrJHUJYEMANRURMiVvJ0g7Ax7r3R1bqO8zx8I= -k8s.io/api v0.25.3 h1:Q1v5UFfYe87vi5H7NU0p4RXC26PPMT8KOpr1TLQbCMQ= -k8s.io/api v0.25.3/go.mod h1:o42gKscFrEVjHdQnyRenACrMtbuJsVdP+WVjqejfzmI= +k8s.io/api v0.26.1 h1:f+SWYiPd/GsiWwVRz+NbFyCgvv75Pk9NK6dlkZgpCRQ= +k8s.io/api v0.26.1/go.mod h1:xd/GBNgR0f707+ATNyPmQ1oyKSgndzXij81FzWGsejg= k8s.io/apiextensions-apiserver v0.18.2/go.mod h1:q3faSnRGmYimiocj6cHQ1I3WpLqmDgJFlKL37fC4ZvY= k8s.io/apiextensions-apiserver v0.20.1/go.mod h1:ntnrZV+6a3dB504qwC5PN/Yg9PBiDNt1EVqbW2kORVk= k8s.io/apiextensions-apiserver v0.20.6/go.mod h1:qO8YMqeMmZH+lV21LUNzV41vfpoE9QVAJRA+MNqj0mo= -k8s.io/apiextensions-apiserver v0.25.3 h1:bfI4KS31w2f9WM1KLGwnwuVlW3RSRPuIsfNF/3HzR0k= -k8s.io/apiextensions-apiserver v0.25.3/go.mod h1:ZJqwpCkxIx9itilmZek7JgfUAM0dnTsA48I4krPqRmo= +k8s.io/apiextensions-apiserver v0.26.1 h1:cB8h1SRk6e/+i3NOrQgSFij1B2S0Y0wDoNl66bn8RMI= +k8s.io/apiextensions-apiserver v0.26.1/go.mod h1:AptjOSXDGuE0JICx/Em15PaoO7buLwTs0dGleIHixSM= k8s.io/apimachinery v0.18.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA= k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= k8s.io/apimachinery v0.20.2/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc= -k8s.io/apimachinery v0.24.0/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= -k8s.io/apimachinery v0.25.3 h1:7o9ium4uyUOM76t6aunP0nZuex7gDf8VGwkR5RcJnQc= -k8s.io/apimachinery v0.25.3/go.mod h1:jaF9C/iPNM1FuLl7Zuy5b9v+n35HGSh6AQ4HYRkCqwo= +k8s.io/apimachinery v0.26.1 h1:8EZ/eGJL+hY/MYCNwhmDzVqq2lPl3N3Bo8rvweJwXUQ= +k8s.io/apimachinery v0.26.1/go.mod h1:tnPmbONNJ7ByJNz9+n9kMjNP8ON+1qoAIIC70lztu74= k8s.io/apiserver v0.18.2/go.mod h1:Xbh066NqrZO8cbsoenCwyDJ1OSi8Ag8I2lezeHxzwzw= k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM= k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= -k8s.io/apiserver v0.25.3 h1:m7+xGuG5+KYAnEsqaFtDyWMkmMMEOFYlu+NlWv5qSBI= -k8s.io/apiserver v0.25.3/go.mod h1:9bT47iM2fzRuhICJpM/RcQR9sqDDfZ7Yw60h0p3JW08= +k8s.io/apiserver v0.26.1 h1:6vmnAqCDO194SVCPU3MU8NcDgSqsUA62tBUSWrFXhsc= +k8s.io/apiserver v0.26.1/go.mod h1:wr75z634Cv+sifswE9HlAo5FQ7UoUauIICRlOE+5dCg= k8s.io/cli-runtime v0.20.6/go.mod h1:JVERW478qcxWrUjJuWQSqyJeiz9QC4T6jmBznHFBC8w= -k8s.io/cli-runtime v0.24.0 h1:ot3Qf49T852uEyNApABO1UHHpFIckKK/NqpheZYN2gM= -k8s.io/cli-runtime v0.24.0/go.mod h1:9XxoZDsEkRFUThnwqNviqzljtT/LdHtNWvcNFrAXl0A= +k8s.io/cli-runtime v0.26.0 h1:aQHa1SyUhpqxAw1fY21x2z2OS5RLtMJOCj7tN4oq8mw= +k8s.io/cli-runtime v0.26.0/go.mod h1:o+4KmwHzO/UK0wepE1qpRk6l3o60/txUZ1fEXWGIKTY= k8s.io/client-go v0.18.2/go.mod h1:Xcm5wVGXX9HAA2JJ2sSBUn3tCJ+4SVlCbl2MNNv+CIU= k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k= k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0= -k8s.io/client-go v0.24.0/go.mod h1:VFPQET+cAFpYxh6Bq6f4xyMY80G6jKKktU6G0m00VDw= -k8s.io/client-go v0.25.3 h1:oB4Dyl8d6UbfDHD8Bv8evKylzs3BXzzufLiO27xuPs0= -k8s.io/client-go v0.25.3/go.mod h1:t39LPczAIMwycjcXkVc+CB+PZV69jQuNx4um5ORDjQA= +k8s.io/client-go v0.26.1 h1:87CXzYJnAMGaa/IDDfRdhTzxk/wzGZ+/HUQpqgVSZXU= +k8s.io/client-go v0.26.1/go.mod h1:IWNSglg+rQ3OcvDkhY6+QLeasV4OYHDjdqeWkDQZwGE= k8s.io/code-generator v0.18.2/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc= k8s.io/code-generator v0.19.7/go.mod h1:lwEq3YnLYb/7uVXLorOJfxg+cUu2oihFhHZ0n9NIla0= k8s.io/code-generator v0.20.1/go.mod h1:UsqdF+VX4PU2g46NC2JRs4gc+IfrctnwHb76RNbWHJg= k8s.io/code-generator v0.20.6/go.mod h1:i6FmG+QxaLxvJsezvZp0q/gAEzzOz3U53KFibghWToU= -k8s.io/code-generator v0.24.0/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w= -k8s.io/code-generator v0.25.3 h1:BEH+wDi90bGyrYcY4abGtUqaOX7G94RRrEu8l+SvIeo= -k8s.io/code-generator v0.25.3/go.mod h1:9F5fuVZOMWRme7MYj2YT3L9ropPWPokd9VRhVyD3+0w= +k8s.io/code-generator v0.26.1 h1:dusFDsnNSKlMFYhzIM0jAO1OlnTN5WYwQQ+Ai12IIlo= +k8s.io/code-generator v0.26.1/go.mod h1:OMoJ5Dqx1wgaQzKgc+ZWaZPfGjdRq/Y3WubFrZmeI3I= k8s.io/component-base v0.18.2/go.mod h1:kqLlMuhJNHQ9lz8Z7V5bxUUtjFZnrypArGl58gmDfUM= k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI= k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM= -k8s.io/component-base v0.24.0/go.mod h1:Dgazgon0i7KYUsS8krG8muGiMVtUZxG037l1MKyXgrA= -k8s.io/component-base v0.25.3 h1:UrsxciGdrCY03ULT1h/S/gXFCOPnLhUVwSyx+hM/zq4= -k8s.io/component-base v0.25.3/go.mod h1:WYoS8L+IlTZgU7rhAl5Ctpw0WdMxDfCC5dkxcEFa/TI= +k8s.io/component-base v0.26.1 h1:4ahudpeQXHZL5kko+iDHqLj/FSGAEUnSVO0EBbgDd+4= +k8s.io/component-base v0.26.1/go.mod h1:VHrLR0b58oC035w6YQiBSbtsf0ThuSwXP+p5dD/kAWU= k8s.io/component-helpers v0.20.6/go.mod h1:d4rFhZS/wxrZCxRiJJiWf1mVGVeMB5/ey3Yv8/rOp78= -k8s.io/component-helpers v0.24.0/go.mod h1:Q2SlLm4h6g6lPTC9GMMfzdywfLSvJT2f1hOnnjaWD8c= k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM= k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= @@ -2019,9 +1959,8 @@ k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8 k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/gengo v0.0.0-20211129171323-c02415ce4185 h1:TT1WdmqqXareKxZ/oNXEUSwKlLiHzPMyB0t8BaFeBYI= -k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/gengo v0.0.0-20220902162205-c0856e24416d h1:U9tB195lKdzwqicbJvyJeOXV7Klv+wNAWENRnXEGi08= +k8s.io/gengo v0.0.0-20220902162205-c0856e24416d/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= @@ -2029,32 +1968,28 @@ k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kms v0.26.1 h1:JE0n4J4+8/Z+egvXz2BTJeJ9ecsm4ZSLKF7ttVXXm/4= +k8s.io/kms v0.26.1/go.mod h1:ReC1IEGuxgfN+PDCIpR6w8+XMmDE7uJhxcCwMZFdIYc= k8s.io/kube-aggregator v0.25.3 h1:eOG9S4GPICAXWIFeQDHjnhqYaYPpgLIC1NunJu9pZCs= k8s.io/kube-aggregator v0.25.3/go.mod h1:w87nqmzJMf7S73FRYcnexqfYW0AFiLJiCkvVCwM3feE= k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= -k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= -k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk= -k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 h1:MQ8BAZPZlWk3S9K4a9NCkIFQtZShWqoha7snGixVgEA= -k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU= +k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E= +k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4= k8s.io/kubectl v0.20.6/go.mod h1:yTCGVrlkBuQhFbKA1R65+lQ9hH7XeyOqUd0FUPFicPg= -k8s.io/kubectl v0.24.0 h1:nA+WtMLVdXUs4wLogGd1mPTAesnLdBpCVgCmz3I7dXo= -k8s.io/kubectl v0.24.0/go.mod h1:pdXkmCyHiRTqjYfyUJiXtbVNURhv0/Q1TyRhy2d5ic0= +k8s.io/kubectl v0.26.0 h1:xmrzoKR9CyNdzxBmXV7jW9Ln8WMrwRK6hGbbf69o4T0= +k8s.io/kubectl v0.26.0/go.mod h1:eInP0b+U9XUJWSYeU9XZnTA+cVYuWyl3iYPGtru0qhQ= k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= k8s.io/metrics v0.20.6/go.mod h1:d+OAIaXutom9kGWcBit/M8OkDpIzBKTsm47+KcUt7VI= -k8s.io/metrics v0.24.0/go.mod h1:jrLlFGdKl3X+szubOXPG0Lf2aVxuV3QJcbsgVRAM6fI= k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20220823124924-e9cbc92d1a73 h1:H9TCJUUx+2VA0ZiD9lvtaX8fthFsMoD+Izn93E/hm8U= -k8s.io/utils v0.0.0-20220823124924-e9cbc92d1a73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -oras.land/oras-go v1.1.0 h1:tfWM1RT7PzUwWphqHU6ptPU3ZhwVnSw/9nEGf519rYg= -oras.land/oras-go v1.1.0/go.mod h1:1A7vR/0KknT2UkJVWh+xMi95I/AhK8ZrxrnUSmXN0bQ= +k8s.io/utils v0.0.0-20221128185143-99ec85e7a448 h1:KTgPnR10d5zhztWptI952TNtt/4u5h3IzDXkdIMuo2Y= +k8s.io/utils v0.0.0-20221128185143-99ec85e7a448/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +oras.land/oras-go v1.2.2 h1:0E9tOHUfrNH7TCDk5KU0jVBEzCqbfdyuVfGmJ7ZeRPE= +oras.land/oras-go v1.2.2/go.mod h1:Apa81sKoZPpP7CDciE006tSZ0x3Q3+dOoBcMZ/aNxvw= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/letsencrypt v0.0.3 h1:H7xDfhkaFFSYEJlKeq38RwX2jYcnTeHuDQyT+mMNMwM= rsc.io/letsencrypt v0.0.3/go.mod h1:buyQKZ6IXrRnB7TdkHP0RyEybLx18HHyOSoTyoOLqNY= @@ -2063,33 +1998,29 @@ rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.33 h1:LYqFq+6Cj2D0gFfrJvL7iElD4ET6ir3VDdhDdTK7rgc= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.33/go.mod h1:soWkSNf2tZC7aMibXEqVhCd73GOY5fJikn8qbdzemB0= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.35 h1:+xBL5uTc+BkPBwmMi3vYfUJjq+N3K+H6PXeETwf5cPI= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.35/go.mod h1:WxjusMwXlKzfAs4p9km6XJRndVt2FROgMVCE4cdohFo= sigs.k8s.io/controller-runtime v0.8.0/go.mod h1:v9Lbj5oX443uR7GXYY46E0EE2o7k2YxQ58GxVNeXSW4= -sigs.k8s.io/controller-runtime v0.13.0 h1:iqa5RNciy7ADWnIc8QxCbOX5FEKVR3uxVxKHRMc2WIQ= -sigs.k8s.io/controller-runtime v0.13.0/go.mod h1:Zbz+el8Yg31jubvAEyglRZGdLAjplZl+PgtYNI6WNTI= +sigs.k8s.io/controller-runtime v0.14.5 h1:6xaWFqzT5KuAQ9ufgUaj1G/+C4Y1GRkhrxl+BJ9i+5s= +sigs.k8s.io/controller-runtime v0.14.5/go.mod h1:WqIdsAY6JBsjfc/CqO0CORmNtoCtE4S6qbPc9s68h+0= sigs.k8s.io/controller-tools v0.4.1/go.mod h1:G9rHdZMVlBDocIxGkK3jHLWqcTMNvveypYJwrvYKjWU= sigs.k8s.io/controller-tools v0.8.0 h1:uUkfTGEwrguqYYfcI2RRGUnC8mYdCFDqfwPKUcNJh1o= sigs.k8s.io/controller-tools v0.8.0/go.mod h1:qE2DXhVOiEq5ijmINcFbqi9GZrrUjzB1TuJU0xa6eoY= -sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY= sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/kind v0.11.1/go.mod h1:fRpgVhtqAWrtLB9ED7zQahUimpUXuG/iHT88xYqEGIA= sigs.k8s.io/kind v0.16.0 h1:GFXyyxtPnHFKqXr3ZG8/X0+0K9sl69lejStlPn2WQyM= sigs.k8s.io/kind v0.16.0/go.mod h1:cKTqagdRyUQmihhBOd+7p43DpOPRn9rHsUC08K1Jbsk= sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU= -sigs.k8s.io/kustomize/api v0.11.4 h1:/0Mr3kfBBNcNPOW5Qwk/3eb8zkswCwnqQxxKtmrTkRo= -sigs.k8s.io/kustomize/api v0.11.4/go.mod h1:k+8RsqYbgpkIrJ4p9jcdPqe8DprLxFUUO0yNOq8C+xI= -sigs.k8s.io/kustomize/cmd/config v0.10.6/go.mod h1:/S4A4nUANUa4bZJ/Edt7ZQTyKOY9WCER0uBS1SW2Rco= -sigs.k8s.io/kustomize/kustomize/v4 v4.5.4/go.mod h1:Zo/Xc5FKD6sHl0lilbrieeGeZHVYCA4BzxeAaLI05Bg= -sigs.k8s.io/kustomize/kyaml v0.13.6 h1:eF+wsn4J7GOAXlvajv6OknSunxpcOBQQqsnPxObtkGs= -sigs.k8s.io/kustomize/kyaml v0.13.6/go.mod h1:yHP031rn1QX1lr/Xd934Ri/xdVNG8BE2ECa78Ht/kEg= +sigs.k8s.io/kustomize/api v0.12.1 h1:7YM7gW3kYBwtKvoY216ZzY+8hM+lV53LUayghNRJ0vM= +sigs.k8s.io/kustomize/api v0.12.1/go.mod h1:y3JUhimkZkR6sbLNwfJHxvo1TCLwuwm14sCYnkH6S1s= +sigs.k8s.io/kustomize/kyaml v0.13.9 h1:Qz53EAaFFANyNgyOEJbT/yoIHygK40/ZcvU3rgry2Tk= +sigs.k8s.io/kustomize/kyaml v0.13.9/go.mod h1:QsRbD0/KcU+wdk0/L0fIp2KLnohkVzs6fQ85/nOXac4= sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= diff --git a/staging/operator-lifecycle-manager/pkg/api/client/clientset/versioned/clientset.go b/staging/operator-lifecycle-manager/pkg/api/client/clientset/versioned/clientset.go index aa24543eef..6d1cbfb097 100644 --- a/staging/operator-lifecycle-manager/pkg/api/client/clientset/versioned/clientset.go +++ b/staging/operator-lifecycle-manager/pkg/api/client/clientset/versioned/clientset.go @@ -39,8 +39,7 @@ type Interface interface { OperatorsV2() operatorsv2.OperatorsV2Interface } -// Clientset contains the clients for groups. Each group has exactly one -// version included in a Clientset. +// Clientset contains the clients for groups. type Clientset struct { *discovery.DiscoveryClient operatorsV1alpha1 *operatorsv1alpha1.OperatorsV1alpha1Client diff --git a/staging/operator-lifecycle-manager/pkg/api/client/clientset/versioned/fake/decorator.go b/staging/operator-lifecycle-manager/pkg/api/client/clientset/versioned/fake/decorator.go index 1a90295744..154b595519 100644 --- a/staging/operator-lifecycle-manager/pkg/api/client/clientset/versioned/fake/decorator.go +++ b/staging/operator-lifecycle-manager/pkg/api/client/clientset/versioned/fake/decorator.go @@ -5,7 +5,7 @@ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, diff --git a/staging/operator-lifecycle-manager/pkg/api/client/informers/externalversions/factory.go b/staging/operator-lifecycle-manager/pkg/api/client/informers/externalversions/factory.go index f037340b49..3a265e8e4c 100644 --- a/staging/operator-lifecycle-manager/pkg/api/client/informers/externalversions/factory.go +++ b/staging/operator-lifecycle-manager/pkg/api/client/informers/externalversions/factory.go @@ -47,6 +47,11 @@ type sharedInformerFactory struct { // startedInformers is used for tracking which informers have been started. // This allows Start() to be called multiple times safely. startedInformers map[reflect.Type]bool + // wg tracks how many goroutines were started. + wg sync.WaitGroup + // shuttingDown is true when Shutdown has been called. It may still be running + // because it needs to wait for goroutines. + shuttingDown bool } // WithCustomResyncConfig sets a custom resync period for the specified informer types. @@ -107,20 +112,39 @@ func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResy return factory } -// Start initializes all requested informers. func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { f.lock.Lock() defer f.lock.Unlock() + if f.shuttingDown { + return + } + for informerType, informer := range f.informers { if !f.startedInformers[informerType] { - go informer.Run(stopCh) + f.wg.Add(1) + // We need a new variable in each loop iteration, + // otherwise the goroutine would use the loop variable + // and that keeps changing. + informer := informer + go func() { + defer f.wg.Done() + informer.Run(stopCh) + }() f.startedInformers[informerType] = true } } } -// WaitForCacheSync waits for all started informers' cache were synced. +func (f *sharedInformerFactory) Shutdown() { + f.lock.Lock() + f.shuttingDown = true + f.lock.Unlock() + + // Will return immediately if there is nothing to wait for. + f.wg.Wait() +} + func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool { informers := func() map[reflect.Type]cache.SharedIndexInformer { f.lock.Lock() @@ -167,11 +191,58 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal // SharedInformerFactory provides shared informers for resources in all known // API group versions. +// +// It is typically used like this: +// +// ctx, cancel := context.Background() +// defer cancel() +// factory := NewSharedInformerFactory(client, resyncPeriod) +// defer factory.WaitForStop() // Returns immediately if nothing was started. +// genericInformer := factory.ForResource(resource) +// typedInformer := factory.SomeAPIGroup().V1().SomeType() +// factory.Start(ctx.Done()) // Start processing these informers. +// synced := factory.WaitForCacheSync(ctx.Done()) +// for v, ok := range synced { +// if !ok { +// fmt.Fprintf(os.Stderr, "caches failed to sync: %v", v) +// return +// } +// } +// +// // Creating informers can also be created after Start, but then +// // Start must be called again: +// anotherGenericInformer := factory.ForResource(resource) +// factory.Start(ctx.Done()) type SharedInformerFactory interface { internalinterfaces.SharedInformerFactory - ForResource(resource schema.GroupVersionResource) (GenericInformer, error) + + // Start initializes all requested informers. They are handled in goroutines + // which run until the stop channel gets closed. + Start(stopCh <-chan struct{}) + + // Shutdown marks a factory as shutting down. At that point no new + // informers can be started anymore and Start will return without + // doing anything. + // + // In addition, Shutdown blocks until all goroutines have terminated. For that + // to happen, the close channel(s) that they were started with must be closed, + // either before Shutdown gets called or while it is waiting. + // + // Shutdown may be called multiple times, even concurrently. All such calls will + // block until all goroutines have terminated. + Shutdown() + + // WaitForCacheSync blocks until all started informers' caches were synced + // or the stop channel gets closed. WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool + // ForResource gives generic access to a shared informer of the matching type. + ForResource(resource schema.GroupVersionResource) (GenericInformer, error) + + // InternalInformerFor returns the SharedIndexInformer for obj using an internal + // client. + InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer + Operators() operators.Interface } diff --git a/staging/operator-lifecycle-manager/pkg/controller/bundle/bundle_unpacker.go b/staging/operator-lifecycle-manager/pkg/controller/bundle/bundle_unpacker.go index 6abfc808ac..c7b71c0670 100644 --- a/staging/operator-lifecycle-manager/pkg/controller/bundle/bundle_unpacker.go +++ b/staging/operator-lifecycle-manager/pkg/controller/bundle/bundle_unpacker.go @@ -26,6 +26,7 @@ import ( "github.com/operator-framework/api/pkg/operators/reference" operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" + v1listers "github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/listers/operators/v1" listersoperatorsv1alpha1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/listers/operators/v1alpha1" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/install" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/projection" @@ -33,12 +34,8 @@ import ( ) const ( - // TODO: Move to operator-framework/api/pkg/operators/v1alpha1 - // BundleLookupFailed describes conditions types for when BundleLookups fail - BundleLookupFailed operatorsv1alpha1.BundleLookupConditionType = "BundleLookupFailed" - // TODO: This can be a spec field - // BundleUnpackTimeoutAnnotationKey allows setting a bundle unpack timeout per InstallPlan + // BundleUnpackTimeoutAnnotationKey allows setting a bundle unpack timeout per OperatorGroup // and overrides the default specified by the --bundle-unpack-timeout flag // The time duration should be in the same format as accepted by time.ParseDuration() // e.g 1m30s @@ -211,6 +208,9 @@ func (c *ConfigMapUnpacker) job(cmRef *corev1.ObjectReference, bundlePath string }, }, }, + NodeSelector: map[string]string{ + "kubernetes.io/os": "linux", + }, }, }, }, @@ -422,7 +422,7 @@ func (c *ConfigMapUnpacker) UnpackBundle(lookup *operatorsv1alpha1.BundleLookup, result = newBundleUnpackResult(lookup) // if bundle lookup failed condition already present, then there is nothing more to do - failedCond := result.GetCondition(BundleLookupFailed) + failedCond := result.GetCondition(operatorsv1alpha1.BundleLookupFailed) if failedCond.Status == corev1.ConditionTrue { return result, nil } @@ -768,3 +768,30 @@ func getCondition(job *batchv1.Job, conditionType batchv1.JobConditionType) (con } return } + +// OperatorGroupBundleUnpackTimeout returns bundle timeout from annotation if specified. +// If the timeout annotation is not set, return timeout < 0 which is subsequently ignored. +// This is to overrides the --bundle-unpack-timeout flag value on per-OperatorGroup basis. +func OperatorGroupBundleUnpackTimeout(ogLister v1listers.OperatorGroupNamespaceLister) (time.Duration, error) { + ignoreTimeout := -1 * time.Minute + + ogs, err := ogLister.List(k8slabels.Everything()) + if err != nil { + return ignoreTimeout, err + } + if len(ogs) != 1 { + return ignoreTimeout, fmt.Errorf("found %d operatorGroups, expected 1", len(ogs)) + } + + timeoutStr, ok := ogs[0].GetAnnotations()[BundleUnpackTimeoutAnnotationKey] + if !ok { + return ignoreTimeout, nil + } + + d, err := time.ParseDuration(timeoutStr) + if err != nil { + return ignoreTimeout, fmt.Errorf("failed to parse unpack timeout annotation(%s: %s): %w", BundleUnpackTimeoutAnnotationKey, timeoutStr, err) + } + + return d, nil +} diff --git a/staging/operator-lifecycle-manager/pkg/controller/bundle/bundle_unpacker_test.go b/staging/operator-lifecycle-manager/pkg/controller/bundle/bundle_unpacker_test.go index 8a4fc5c0a0..a9a7c61a3f 100644 --- a/staging/operator-lifecycle-manager/pkg/controller/bundle/bundle_unpacker_test.go +++ b/staging/operator-lifecycle-manager/pkg/controller/bundle/bundle_unpacker_test.go @@ -2,10 +2,12 @@ package bundle import ( "context" + "errors" "fmt" "testing" "time" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" @@ -15,11 +17,14 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/informers" k8sfake "k8s.io/client-go/kubernetes/fake" + "k8s.io/client-go/tools/cache" "k8s.io/utils/pointer" + operatorsv1 "github.com/operator-framework/api/pkg/operators/v1" operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" crfake "github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/clientset/versioned/fake" crinformers "github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/informers/externalversions" + v1listers "github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/listers/operators/v1" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/install" "github.com/operator-framework/operator-registry/pkg/api" "github.com/operator-framework/operator-registry/pkg/configmap" @@ -329,6 +334,9 @@ func TestConfigMapUnpacker(t *testing.T) { }, }, }, + NodeSelector: map[string]string{ + "kubernetes.io/os": "linux", + }, }, }, }, @@ -531,6 +539,9 @@ func TestConfigMapUnpacker(t *testing.T) { }, }, }, + NodeSelector: map[string]string{ + "kubernetes.io/os": "linux", + }, }, }, }, @@ -774,6 +785,9 @@ func TestConfigMapUnpacker(t *testing.T) { }, }, }, + NodeSelector: map[string]string{ + "kubernetes.io/os": "linux", + }, }, }, }, @@ -1011,6 +1025,9 @@ func TestConfigMapUnpacker(t *testing.T) { }, }, }, + NodeSelector: map[string]string{ + "kubernetes.io/os": "linux", + }, }, }, }, @@ -1218,6 +1235,9 @@ func TestConfigMapUnpacker(t *testing.T) { }, }, }, + NodeSelector: map[string]string{ + "kubernetes.io/os": "linux", + }, }, }, }, @@ -1298,7 +1318,7 @@ func TestConfigMapUnpacker(t *testing.T) { LastTransitionTime: &start, }, { - Type: BundleLookupFailed, + Type: operatorsv1alpha1.BundleLookupFailed, Status: corev1.ConditionTrue, Reason: "DeadlineExceeded", Message: "Job was active longer than specified deadline", @@ -1436,6 +1456,9 @@ func TestConfigMapUnpacker(t *testing.T) { }, }, }, + NodeSelector: map[string]string{ + "kubernetes.io/os": "linux", + }, }, }, }, @@ -1554,3 +1577,114 @@ func TestConfigMapUnpacker(t *testing.T) { }) } } + +func TestOperatorGroupBundleUnpackTimeout(t *testing.T) { + nsName := "fake-ns" + + for _, tc := range []struct { + name string + operatorGroups []*operatorsv1.OperatorGroup + expectedTimeout time.Duration + expectedError error + }{ + { + name: "No operator groups exist", + expectedTimeout: -1 * time.Minute, + expectedError: errors.New("found 0 operatorGroups, expected 1"), + }, + { + name: "Multiple operator groups exist", + operatorGroups: []*operatorsv1.OperatorGroup{ + { + TypeMeta: metav1.TypeMeta{ + Kind: operatorsv1.OperatorGroupKind, + APIVersion: operatorsv1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "og1", + Namespace: nsName, + }, + }, + { + TypeMeta: metav1.TypeMeta{ + Kind: operatorsv1.OperatorGroupKind, + APIVersion: operatorsv1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "og2", + Namespace: nsName, + }, + }, + }, + expectedTimeout: -1 * time.Minute, + expectedError: errors.New("found 2 operatorGroups, expected 1"), + }, + { + name: "One operator group exists with valid timeout annotation", + operatorGroups: []*operatorsv1.OperatorGroup{ + { + TypeMeta: metav1.TypeMeta{ + Kind: operatorsv1.OperatorGroupKind, + APIVersion: operatorsv1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "og", + Namespace: nsName, + Annotations: map[string]string{BundleUnpackTimeoutAnnotationKey: "1m"}, + }, + }, + }, + expectedTimeout: 1 * time.Minute, + expectedError: nil, + }, + { + name: "One operator group exists with no timeout annotation", + operatorGroups: []*operatorsv1.OperatorGroup{ + { + TypeMeta: metav1.TypeMeta{ + Kind: operatorsv1.OperatorGroupKind, + APIVersion: operatorsv1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "og", + Namespace: nsName, + }, + }, + }, + expectedTimeout: -1 * time.Minute, + }, + { + name: "One operator group exists with invalid timeout annotation", + operatorGroups: []*operatorsv1.OperatorGroup{ + { + TypeMeta: metav1.TypeMeta{ + Kind: operatorsv1.OperatorGroupKind, + APIVersion: operatorsv1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "og", + Namespace: nsName, + Annotations: map[string]string{BundleUnpackTimeoutAnnotationKey: "invalid"}, + }, + }, + }, + expectedTimeout: -1 * time.Minute, + expectedError: fmt.Errorf("failed to parse unpack timeout annotation(operatorframework.io/bundle-unpack-timeout: invalid): %w", errors.New("time: invalid duration \"invalid\"")), + }, + } { + t.Run(tc.name, func(t *testing.T) { + ogIndexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{}) + ogLister := v1listers.NewOperatorGroupLister(ogIndexer).OperatorGroups(nsName) + + for _, og := range tc.operatorGroups { + err := ogIndexer.Add(og) + assert.NoError(t, err) + } + + timeout, err := OperatorGroupBundleUnpackTimeout(ogLister) + + assert.Equal(t, tc.expectedTimeout, timeout) + assert.Equal(t, tc.expectedError, err) + }) + } +} diff --git a/staging/operator-lifecycle-manager/pkg/controller/install/deployment.go b/staging/operator-lifecycle-manager/pkg/controller/install/deployment.go index 559520aad7..43aab8e1ce 100644 --- a/staging/operator-lifecycle-manager/pkg/controller/install/deployment.go +++ b/staging/operator-lifecycle-manager/pkg/controller/install/deployment.go @@ -175,7 +175,7 @@ func (i *StrategyDeploymentInstaller) deploymentForSpec(name string, spec appsv1 // By default, each deployment created by OLM could spawn up to 10 replicaSets. // By setting the deployments revisionHistoryLimit to 1, OLM will only create up // to 2 ReplicaSets per deployment it manages, saving memory. - dep.Spec.RevisionHistoryLimit = pointer.Int32Ptr(1) + dep.Spec.RevisionHistoryLimit = pointer.Int32(1) hash = HashDeploymentSpec(dep.Spec) dep.Labels[DeploymentSpecHashLabelKey] = hash diff --git a/staging/operator-lifecycle-manager/pkg/controller/operators/catalog/operator.go b/staging/operator-lifecycle-manager/pkg/controller/operators/catalog/operator.go index 0c3531e780..0d24b363d3 100644 --- a/staging/operator-lifecycle-manager/pkg/controller/operators/catalog/operator.go +++ b/staging/operator-lifecycle-manager/pkg/controller/operators/catalog/operator.go @@ -934,7 +934,13 @@ func (o *Operator) syncResolvingNamespace(obj interface{}) error { return err } - failForwardEnabled, err := resolver.IsFailForwardEnabled(o.lister.OperatorsV1().OperatorGroupLister().OperatorGroups(namespace)) + ogLister := o.lister.OperatorsV1().OperatorGroupLister().OperatorGroups(namespace) + failForwardEnabled, err := resolver.IsFailForwardEnabled(ogLister) + if err != nil { + return err + } + + unpackTimeout, err := bundle.OperatorGroupBundleUnpackTimeout(ogLister) if err != nil { return err } @@ -1028,6 +1034,80 @@ func (o *Operator) syncResolvingNamespace(obj interface{}) error { return err } + // Attempt to unpack bundles before installing + // Note: This should probably use the attenuated client to prevent users from resolving resources they otherwise don't have access to. + if len(bundleLookups) > 0 { + logger.Debug("unpacking bundles") + + var unpacked bool + unpacked, steps, bundleLookups, err = o.unpackBundles(namespace, steps, bundleLookups, unpackTimeout) + if err != nil { + // If the error was fatal capture and fail + if olmerrors.IsFatal(err) { + _, updateErr := o.updateSubscriptionStatuses( + o.setSubsCond(subs, v1alpha1.SubscriptionCondition{ + Type: v1alpha1.SubscriptionBundleUnpackFailed, + Reason: "ErrorPreventedUnpacking", + Message: err.Error(), + Status: corev1.ConditionTrue, + })) + if updateErr != nil { + logger.WithError(updateErr).Debug("failed to update subs conditions") + return updateErr + } + return nil + } + // Retry sync if non-fatal error + return fmt.Errorf("bundle unpacking failed with an error: %w", err) + } + + // Check BundleLookup status conditions to see if the BundleLookupFailed condtion is true + // which means bundle lookup has failed and subscriptions need to be updated + // with a condition indicating the failure. + isFailed, cond := hasBundleLookupFailureCondition(bundleLookups) + if isFailed { + err := fmt.Errorf("bundle unpacking failed. Reason: %v, and Message: %v", cond.Reason, cond.Message) + logger.Infof("%v", err) + + _, updateErr := o.updateSubscriptionStatuses( + o.setSubsCond(subs, v1alpha1.SubscriptionCondition{ + Type: v1alpha1.SubscriptionBundleUnpackFailed, + Reason: "BundleUnpackFailed", + Message: err.Error(), + Status: corev1.ConditionTrue, + })) + if updateErr != nil { + logger.WithError(updateErr).Debug("failed to update subs conditions") + return updateErr + } + // Since this is likely requires intervention we do not want to + // requeue too often. We return no error here and rely on a + // periodic resync which will help to automatically resolve + // some issues such as unreachable bundle images caused by + // bad catalog updates. + return nil + } + + // This means that the unpack job is still running (most likely) or + // there was some issue which we did not handle above. + if !unpacked { + _, updateErr := o.updateSubscriptionStatuses( + o.setSubsCond(subs, v1alpha1.SubscriptionCondition{ + Type: v1alpha1.SubscriptionBundleUnpacking, + Reason: "UnpackingInProgress", + Status: corev1.ConditionTrue, + })) + if updateErr != nil { + logger.WithError(updateErr).Debug("failed to update subs conditions") + return updateErr + } + + logger.Debug("unpacking is not complete yet, requeueing") + o.nsResolveQueue.AddAfter(namespace, 5*time.Second) + return nil + } + } + // create installplan if anything updated if len(updatedSubs) > 0 { logger.Debug("resolution caused subscription changes, creating installplan") @@ -1062,8 +1142,17 @@ func (o *Operator) syncResolvingNamespace(obj interface{}) error { logger.Debugf("no subscriptions were updated") } + // Make sure that we no longer indicate unpacking progress + subs = o.setSubsCond(subs, v1alpha1.SubscriptionCondition{ + Type: v1alpha1.SubscriptionBundleUnpacking, + Status: corev1.ConditionFalse, + }) + + // Remove BundleUnpackFailed condition from subscriptions + o.removeSubsCond(subs, v1alpha1.SubscriptionBundleUnpackFailed) + // Remove resolutionfailed condition from subscriptions - subs = o.removeSubsCond(subs, v1alpha1.SubscriptionResolutionFailed) + o.removeSubsCond(subs, v1alpha1.SubscriptionResolutionFailed) newSub := true for _, updatedSub := range updatedSubs { updatedSub.Status.RemoveConditions(v1alpha1.SubscriptionResolutionFailed) @@ -1408,35 +1497,30 @@ type UnpackedBundleReference struct { Properties string `json:"properties"` } -func (o *Operator) unpackBundles(plan *v1alpha1.InstallPlan) (bool, *v1alpha1.InstallPlan, error) { - out := plan.DeepCopy() +func (o *Operator) unpackBundles(namespace string, installPlanSteps []*v1alpha1.Step, bundleLookups []v1alpha1.BundleLookup, unpackTimeout time.Duration) (bool, []*v1alpha1.Step, []v1alpha1.BundleLookup, error) { unpacked := true - // The bundle timeout annotation if specified overrides the --bundle-unpack-timeout flag value - // If the timeout cannot be parsed it's set to < 0 and subsequently ignored - unpackTimeout := -1 * time.Minute - timeoutStr, ok := plan.GetAnnotations()[bundle.BundleUnpackTimeoutAnnotationKey] - if ok { - d, err := time.ParseDuration(timeoutStr) - if err != nil { - o.logger.Errorf("failed to parse unpack timeout annotation(%s: %s): %v", bundle.BundleUnpackTimeoutAnnotationKey, timeoutStr, err) - } else { - unpackTimeout = d - } + outBundleLookups := make([]v1alpha1.BundleLookup, len(bundleLookups)) + for i := range bundleLookups { + bundleLookups[i].DeepCopyInto(&outBundleLookups[i]) + } + outInstallPlanSteps := make([]*v1alpha1.Step, len(installPlanSteps)) + for i := range installPlanSteps { + outInstallPlanSteps[i] = installPlanSteps[i].DeepCopy() } var errs []error - for i := 0; i < len(out.Status.BundleLookups); i++ { - lookup := out.Status.BundleLookups[i] + for i := 0; i < len(outBundleLookups); i++ { + lookup := outBundleLookups[i] res, err := o.bundleUnpacker.UnpackBundle(&lookup, unpackTimeout) if err != nil { errs = append(errs, err) continue } - out.Status.BundleLookups[i] = *res.BundleLookup + outBundleLookups[i] = *res.BundleLookup // if the failed condition is present it means the bundle unpacking has failed - failedCondition := res.GetCondition(bundle.BundleLookupFailed) + failedCondition := res.GetCondition(v1alpha1.BundleLookupFailed) if failedCondition.Status == corev1.ConditionTrue { unpacked = false continue @@ -1455,11 +1539,11 @@ func (o *Operator) unpackBundles(plan *v1alpha1.InstallPlan) (bool, *v1alpha1.In continue } - // Ensure that bundle can be applied by the current version of OLM by converting to steps - steps, err := resolver.NewStepsFromBundle(res.Bundle(), out.GetNamespace(), res.Replaces, res.CatalogSourceRef.Name, res.CatalogSourceRef.Namespace) + // Ensure that bundle can be applied by the current version of OLM by converting to bundleSteps + bundleSteps, err := resolver.NewStepsFromBundle(res.Bundle(), namespace, res.Replaces, res.CatalogSourceRef.Name, res.CatalogSourceRef.Namespace) if err != nil { if fatal := olmerrors.IsFatal(err); fatal { - return false, nil, err + return false, nil, nil, err } errs = append(errs, fmt.Errorf("failed to turn bundle into steps: %v", err)) @@ -1468,7 +1552,7 @@ func (o *Operator) unpackBundles(plan *v1alpha1.InstallPlan) (bool, *v1alpha1.In } // step manifests are replaced with references to the configmap containing them - for i, s := range steps { + for i, s := range bundleSteps { ref := UnpackedBundleReference{ Kind: "ConfigMap", Namespace: res.CatalogSourceRef.Namespace, @@ -1485,19 +1569,19 @@ func (o *Operator) unpackBundles(plan *v1alpha1.InstallPlan) (bool, *v1alpha1.In continue } s.Resource.Manifest = string(r) - steps[i] = s + bundleSteps[i] = s } res.RemoveCondition(resolver.BundleLookupConditionPacked) - out.Status.BundleLookups[i] = *res.BundleLookup - out.Status.Plan = append(out.Status.Plan, steps...) + outBundleLookups[i] = *res.BundleLookup + outInstallPlanSteps = append(outInstallPlanSteps, bundleSteps...) } if err := utilerrors.NewAggregate(errs); err != nil { o.logger.Debugf("failed to unpack bundles: %v", err) - return false, nil, err + return false, nil, nil, err } - return unpacked, out, nil + return unpacked, outInstallPlanSteps, outBundleLookups, nil } // gcInstallPlans garbage collects installplans that are too old @@ -1599,7 +1683,6 @@ func (o *Operator) syncInstallPlans(obj interface{}) (syncError error) { querier := o.serviceAccountQuerier.NamespaceQuerier(plan.GetNamespace()) ref, err := querier() - out := plan.DeepCopy() if err != nil { // Set status condition/message and retry sync if any error @@ -1645,65 +1728,6 @@ func (o *Operator) syncInstallPlans(obj interface{}) (syncError error) { } } - // Attempt to unpack bundles before installing - // Note: This should probably use the attenuated client to prevent users from resolving resources they otherwise don't have access to. - if len(plan.Status.BundleLookups) > 0 { - unpacked, out, err := o.unpackBundles(plan) - if err != nil { - // If the error was fatal capture and fail - if fatal := olmerrors.IsFatal(err); fatal { - if err := o.transitionInstallPlanToFailed(plan, logger, v1alpha1.InstallPlanReasonInstallCheckFailed, err.Error()); err != nil { - // retry for failure to update status - syncError = err - return - } - } - // Retry sync if non-fatal error - syncError = fmt.Errorf("bundle unpacking failed: %v", err) - return - } - - if !reflect.DeepEqual(plan.Status, out.Status) { - logger.Warnf("status not equal, updating...") - if _, err := o.client.OperatorsV1alpha1().InstallPlans(out.GetNamespace()).UpdateStatus(context.TODO(), out, metav1.UpdateOptions{}); err != nil { - syncError = fmt.Errorf("failed to update installplan bundle lookups: %v", err) - } - - return - } - - // Check BundleLookup status conditions to see if the BundleLookupPending condtion is false - // which means bundle lookup has failed and the InstallPlan should be failed as well - isFailed, cond := hasBundleLookupFailureCondition(plan) - if isFailed { - err := fmt.Errorf("bundle unpacking failed. Reason: %v, and Message: %v", cond.Reason, cond.Message) - // Mark the InstallPlan as failed for a fatal bundle unpack error - logger.Infof("%v", err) - - if err := o.transitionInstallPlanToFailed(plan, logger, v1alpha1.InstallPlanReasonInstallCheckFailed, err.Error()); err != nil { - // retry for failure to update status - syncError = err - return - } - - // Requeue subscription to propagate SubscriptionInstallPlanFailed condtion to subscription - o.requeueSubscriptionForInstallPlan(plan, logger) - return - } - - // TODO: Remove in favor of job and configmap informer requeuing - if !unpacked { - err := o.ipQueueSet.RequeueAfter(plan.GetNamespace(), plan.GetName(), 5*time.Second) - if err != nil { - syncError = err - return - } - logger.Debug("install plan not yet populated from bundle image, requeueing") - - return - } - } - outInstallPlan, syncError := transitionInstallPlanState(logger.Logger, o, *plan, o.now(), o.installPlanTimeout) if syncError != nil { @@ -1731,10 +1755,10 @@ func (o *Operator) syncInstallPlans(obj interface{}) (syncError error) { return } -func hasBundleLookupFailureCondition(plan *v1alpha1.InstallPlan) (bool, *v1alpha1.BundleLookupCondition) { - for _, bundleLookup := range plan.Status.BundleLookups { +func hasBundleLookupFailureCondition(bundleLookups []v1alpha1.BundleLookup) (bool, *v1alpha1.BundleLookupCondition) { + for _, bundleLookup := range bundleLookups { for _, cond := range bundleLookup.Conditions { - if cond.Type == bundle.BundleLookupFailed && cond.Status == corev1.ConditionTrue { + if cond.Type == v1alpha1.BundleLookupFailed && cond.Status == corev1.ConditionTrue { return true, &cond } } @@ -1742,27 +1766,6 @@ func hasBundleLookupFailureCondition(plan *v1alpha1.InstallPlan) (bool, *v1alpha return false, nil } -func (o *Operator) transitionInstallPlanToFailed(plan *v1alpha1.InstallPlan, logger logrus.FieldLogger, reason v1alpha1.InstallPlanConditionReason, message string) error { - now := o.now() - out := plan.DeepCopy() - out.Status.SetCondition(v1alpha1.ConditionFailed(v1alpha1.InstallPlanInstalled, - reason, message, &now)) - out.Status.Phase = v1alpha1.InstallPlanPhaseFailed - - logger.Info("transitioning InstallPlan to failed") - _, err := o.client.OperatorsV1alpha1().InstallPlans(plan.GetNamespace()).UpdateStatus(context.TODO(), out, metav1.UpdateOptions{}) - if err == nil { - return nil - } - - updateErr := errors.New("error updating InstallPlan status: " + err.Error()) - logger = logger.WithField("updateError", updateErr) - logger.Errorf("error transitioning InstallPlan to failed") - - // retry sync with error to update InstallPlan status - return fmt.Errorf("installplan failed: %s and error updating InstallPlan status as failed: %s", message, updateErr) -} - func (o *Operator) requeueSubscriptionForInstallPlan(plan *v1alpha1.InstallPlan, logger *logrus.Entry) { // Notify subscription loop of installplan changes owners := ownerutil.GetOwnersByKind(plan, v1alpha1.SubscriptionKind) diff --git a/staging/operator-lifecycle-manager/pkg/controller/operators/catalog/operator_test.go b/staging/operator-lifecycle-manager/pkg/controller/operators/catalog/operator_test.go index 903be19679..cdf31e4d5a 100644 --- a/staging/operator-lifecycle-manager/pkg/controller/operators/catalog/operator_test.go +++ b/staging/operator-lifecycle-manager/pkg/controller/operators/catalog/operator_test.go @@ -5,8 +5,8 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" "math/rand" + "os" "reflect" "strings" "testing" @@ -49,6 +49,8 @@ import ( "github.com/operator-framework/api/pkg/operators/v1alpha1" "github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/clientset/versioned/fake" "github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/informers/externalversions" + "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/bundle" + "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/bundle/bundlefakes" olmerrors "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/errors" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/grpc" @@ -1125,19 +1127,25 @@ func TestSyncCatalogSources(t *testing.T) { func TestSyncResolvingNamespace(t *testing.T) { clockFake := utilclocktesting.NewFakeClock(time.Date(2018, time.January, 26, 20, 40, 0, 0, time.UTC)) + now := metav1.NewTime(clockFake.Now()) testNamespace := "testNamespace" + og := &operatorsv1.OperatorGroup{ + ObjectMeta: metav1.ObjectMeta{ + Name: "og", + Namespace: testNamespace, + }, + } type fields struct { - clientOptions []clientfake.Option - sourcesLastUpdate metav1.Time - resolveErr error - existingOLMObjs []runtime.Object - existingObjects []runtime.Object + clientOptions []clientfake.Option + resolveErr error + existingOLMObjs []runtime.Object } tests := []struct { - name string - fields fields - wantErr error + name string + fields fields + wantSubscriptions []*v1alpha1.Subscription + wantErr error }{ { name: "NoError", @@ -1164,6 +1172,33 @@ func TestSyncResolvingNamespace(t *testing.T) { }, }, }, + wantSubscriptions: []*v1alpha1.Subscription{ + { + TypeMeta: metav1.TypeMeta{ + Kind: v1alpha1.SubscriptionKind, + APIVersion: v1alpha1.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "sub", + Namespace: testNamespace, + }, + Spec: &v1alpha1.SubscriptionSpec{ + CatalogSource: "src", + CatalogSourceNamespace: testNamespace, + }, + Status: v1alpha1.SubscriptionStatus{ + CurrentCSV: "", + State: "", + Conditions: []v1alpha1.SubscriptionCondition{ + { + Type: v1alpha1.SubscriptionBundleUnpacking, + Status: corev1.ConditionFalse, + }, + }, + LastUpdated: now, + }, + }, + }, }, { name: "NotSatisfiableError", @@ -1196,6 +1231,35 @@ func TestSyncResolvingNamespace(t *testing.T) { }, }, }, + wantSubscriptions: []*v1alpha1.Subscription{ + { + TypeMeta: metav1.TypeMeta{ + Kind: v1alpha1.SubscriptionKind, + APIVersion: v1alpha1.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "sub", + Namespace: testNamespace, + }, + Spec: &v1alpha1.SubscriptionSpec{ + CatalogSource: "src", + CatalogSourceNamespace: testNamespace, + }, + Status: v1alpha1.SubscriptionStatus{ + CurrentCSV: "", + State: "", + Conditions: []v1alpha1.SubscriptionCondition{ + { + Type: v1alpha1.SubscriptionResolutionFailed, + Reason: "ConstraintsNotSatisfiable", + Message: "constraints not satisfiable: something", + Status: corev1.ConditionTrue, + }, + }, + LastUpdated: now, + }, + }, + }, }, { name: "OtherError", @@ -1232,6 +1296,35 @@ func TestSyncResolvingNamespace(t *testing.T) { }, resolveErr: fmt.Errorf("some error"), }, + wantSubscriptions: []*v1alpha1.Subscription{ + { + TypeMeta: metav1.TypeMeta{ + Kind: v1alpha1.SubscriptionKind, + APIVersion: v1alpha1.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "sub", + Namespace: testNamespace, + }, + Spec: &v1alpha1.SubscriptionSpec{ + CatalogSource: "src", + CatalogSourceNamespace: testNamespace, + }, + Status: v1alpha1.SubscriptionStatus{ + CurrentCSV: "", + State: "", + Conditions: []v1alpha1.SubscriptionCondition{ + { + Type: v1alpha1.SubscriptionResolutionFailed, + Reason: "ErrorPreventedResolution", + Message: "some error", + Status: corev1.ConditionTrue, + }, + }, + LastUpdated: now, + }, + }, + }, wantErr: fmt.Errorf("some error"), }, } @@ -1241,7 +1334,7 @@ func TestSyncResolvingNamespace(t *testing.T) { ctx, cancel := context.WithCancel(context.TODO()) defer cancel() - o, err := NewFakeOperator(ctx, testNamespace, []string{testNamespace}, withClock(clockFake), withClientObjs(tt.fields.existingOLMObjs...), withK8sObjs(tt.fields.existingObjects...), withFakeClientOptions(tt.fields.clientOptions...)) + o, err := NewFakeOperator(ctx, testNamespace, []string{testNamespace}, withClock(clockFake), withClientObjs(append(tt.fields.existingOLMObjs, og)...), withFakeClientOptions(tt.fields.clientOptions...)) require.NoError(t, err) o.reconciler = &fakes.FakeRegistryReconcilerFactory{ @@ -1254,7 +1347,6 @@ func TestSyncResolvingNamespace(t *testing.T) { }, } - o.sourcesLastUpdate.Set(tt.fields.sourcesLastUpdate.Time) o.resolver = &fakes.FakeStepResolver{ ResolveStepsStub: func(string) ([]*v1alpha1.Step, []v1alpha1.BundleLookup, []*v1alpha1.Subscription, error) { return nil, nil, nil, tt.fields.resolveErr @@ -1273,6 +1365,12 @@ func TestSyncResolvingNamespace(t *testing.T) { } else { require.NoError(t, err) } + + for _, s := range tt.wantSubscriptions { + fetched, err := o.client.OperatorsV1alpha1().Subscriptions(testNamespace).Get(context.TODO(), s.GetName(), metav1.GetOptions{}) + require.NoError(t, err) + require.Equal(t, s, fetched) + } }) } } @@ -1333,7 +1431,8 @@ func TestCompetingCRDOwnersExist(t *testing.T) { expectedResult: true, }, } - for _, tt := range tests { + for _, xt := range tests { + tt := xt t.Run(tt.name, func(t *testing.T) { t.Parallel() @@ -1353,7 +1452,7 @@ func TestCompetingCRDOwnersExist(t *testing.T) { func TestValidateExistingCRs(t *testing.T) { unstructuredForFile := func(file string) *unstructured.Unstructured { - data, err := ioutil.ReadFile(file) + data, err := os.ReadFile(file) require.NoError(t, err) dec := utilyaml.NewYAMLOrJSONDecoder(strings.NewReader(string(data)), 30) k8sFile := &unstructured.Unstructured{} @@ -1362,7 +1461,7 @@ func TestValidateExistingCRs(t *testing.T) { } unversionedCRDForV1beta1File := func(file string) *apiextensions.CustomResourceDefinition { - data, err := ioutil.ReadFile(file) + data, err := os.ReadFile(file) require.NoError(t, err) dec := utilyaml.NewYAMLOrJSONDecoder(strings.NewReader(string(data)), 30) k8sFile := &apiextensionsv1beta1.CustomResourceDefinition{} @@ -1476,17 +1575,18 @@ func fakeConfigMapData() map[string]string { // fakeOperatorConfig is the configuration for a fake operator. type fakeOperatorConfig struct { - clock utilclock.Clock - clientObjs []runtime.Object - k8sObjs []runtime.Object - extObjs []runtime.Object - regObjs []runtime.Object - clientOptions []clientfake.Option - logger *logrus.Logger - resolver resolver.StepResolver - recorder record.EventRecorder - reconciler reconciler.RegistryReconcilerFactory - sources []sourceAddress + clock utilclock.Clock + clientObjs []runtime.Object + k8sObjs []runtime.Object + extObjs []runtime.Object + regObjs []runtime.Object + clientOptions []clientfake.Option + logger *logrus.Logger + resolver resolver.StepResolver + recorder record.EventRecorder + reconciler reconciler.RegistryReconcilerFactory + bundleUnpacker bundle.Unpacker + sources []sourceAddress } // fakeOperatorOption applies an option to the given fake operator configuration. @@ -1498,6 +1598,12 @@ func withResolver(res resolver.StepResolver) fakeOperatorOption { } } +func withBundleUnpacker(bundleUnpacker bundle.Unpacker) fakeOperatorOption { + return func(config *fakeOperatorConfig) { + config.bundleUnpacker = bundleUnpacker + } +} + func withSources(sources ...sourceAddress) fakeOperatorOption { return func(config *fakeOperatorConfig) { config.sources = sources @@ -1543,10 +1649,11 @@ type sourceAddress struct { func NewFakeOperator(ctx context.Context, namespace string, namespaces []string, fakeOptions ...fakeOperatorOption) (*Operator, error) { // Apply options to default config config := &fakeOperatorConfig{ - logger: logrus.StandardLogger(), - clock: utilclock.RealClock{}, - resolver: &fakes.FakeStepResolver{}, - recorder: &record.FakeRecorder{}, + logger: logrus.StandardLogger(), + clock: utilclock.RealClock{}, + resolver: &fakes.FakeStepResolver{}, + recorder: &record.FakeRecorder{}, + bundleUnpacker: &bundlefakes.FakeUnpacker{}, } for _, option := range fakeOptions { option(config) @@ -1585,12 +1692,14 @@ func NewFakeOperator(ctx context.Context, namespace string, namespaces []string, subInformer := operatorsFactory.Operators().V1alpha1().Subscriptions() ipInformer := operatorsFactory.Operators().V1alpha1().InstallPlans() csvInformer := operatorsFactory.Operators().V1alpha1().ClusterServiceVersions() - sharedInformers = append(sharedInformers, catsrcInformer.Informer(), subInformer.Informer(), ipInformer.Informer(), csvInformer.Informer()) + ogInformer := operatorsFactory.Operators().V1().OperatorGroups() + sharedInformers = append(sharedInformers, catsrcInformer.Informer(), subInformer.Informer(), ipInformer.Informer(), csvInformer.Informer(), ogInformer.Informer()) lister.OperatorsV1alpha1().RegisterCatalogSourceLister(metav1.NamespaceAll, catsrcInformer.Lister()) lister.OperatorsV1alpha1().RegisterSubscriptionLister(metav1.NamespaceAll, subInformer.Lister()) lister.OperatorsV1alpha1().RegisterInstallPlanLister(metav1.NamespaceAll, ipInformer.Lister()) lister.OperatorsV1alpha1().RegisterClusterServiceVersionLister(metav1.NamespaceAll, csvInformer.Lister()) + lister.OperatorsV1().RegisterOperatorGroupLister(metav1.NamespaceAll, ogInformer.Lister()) factory := informers.NewSharedInformerFactoryWithOptions(opClientFake.KubernetesInterface(), wakeupInterval, informers.WithNamespace(metav1.NamespaceAll)) roleInformer := factory.Rbac().V1().Roles() @@ -1638,6 +1747,7 @@ func NewFakeOperator(ctx context.Context, namespace string, namespaces []string, recorder: config.recorder, clientAttenuator: scoped.NewClientAttenuator(logger, &rest.Config{}, opClientFake), serviceAccountQuerier: scoped.NewUserDefinedServiceAccountQuerier(logger, clientFake), + bundleUnpacker: config.bundleUnpacker, catsrcQueueSet: queueinformer.NewEmptyResourceQueueSet(), clientFactory: &stubClientFactory{ operatorClient: opClientFake, @@ -1792,7 +1902,7 @@ func objectReference(name string) *corev1.ObjectReference { } func yamlFromFilePath(t *testing.T, fileName string) string { - yaml, err := ioutil.ReadFile(fileName) + yaml, err := os.ReadFile(fileName) require.NoError(t, err) return string(yaml) diff --git a/staging/operator-lifecycle-manager/pkg/controller/operators/catalog/subscriptions_test.go b/staging/operator-lifecycle-manager/pkg/controller/operators/catalog/subscriptions_test.go index 48d84e0b1a..b84d24c9e1 100644 --- a/staging/operator-lifecycle-manager/pkg/controller/operators/catalog/subscriptions_test.go +++ b/staging/operator-lifecycle-manager/pkg/controller/operators/catalog/subscriptions_test.go @@ -2,6 +2,7 @@ package catalog import ( "context" + "errors" "fmt" "testing" "time" @@ -10,9 +11,13 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + utilerrors "k8s.io/apimachinery/pkg/util/errors" utilclocktesting "k8s.io/utils/clock/testing" + operatorsv1 "github.com/operator-framework/api/pkg/operators/v1" "github.com/operator-framework/api/pkg/operators/v1alpha1" + "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/bundle" + "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/bundle/bundlefakes" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/reconciler" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver" "github.com/operator-framework/operator-lifecycle-manager/pkg/fakes" @@ -23,16 +28,20 @@ func TestSyncSubscriptions(t *testing.T) { clockFake := utilclocktesting.NewFakeClock(time.Date(2018, time.January, 26, 20, 40, 0, 0, time.UTC)) now := metav1.NewTime(clockFake.Now()) testNamespace := "testNamespace" + og := &operatorsv1.OperatorGroup{ + ObjectMeta: metav1.ObjectMeta{ + Name: "og", + Namespace: testNamespace, + }, + } type fields struct { - clientOptions []clientfake.Option - sourcesLastUpdate metav1.Time - resolveSteps []*v1alpha1.Step - resolveSubs []*v1alpha1.Subscription - bundleLookups []v1alpha1.BundleLookup - resolveErr error - existingOLMObjs []runtime.Object - existingObjects []runtime.Object + clientOptions []clientfake.Option + resolveSteps []*v1alpha1.Step + resolveSubs []*v1alpha1.Subscription + resolveBundleLookups []v1alpha1.BundleLookup + unpackBundleErr error + existingOLMObjs []runtime.Object } type args struct { obj interface{} @@ -378,7 +387,7 @@ func TestSyncSubscriptions(t *testing.T) { }, }, }, - bundleLookups: []v1alpha1.BundleLookup{ + resolveBundleLookups: []v1alpha1.BundleLookup{ { Path: "bundle-path-a", Identifier: "bundle-a", @@ -388,11 +397,10 @@ func TestSyncSubscriptions(t *testing.T) { }, Conditions: []v1alpha1.BundleLookupCondition{ { - Type: v1alpha1.BundleLookupPending, - Status: corev1.ConditionTrue, - Reason: "JobIncomplete", - Message: "unpack job not completed", - LastTransitionTime: &now, + Type: v1alpha1.BundleLookupPending, + Status: corev1.ConditionTrue, + Reason: "JobIncomplete", + Message: "unpack job not completed", }, }, }, @@ -433,56 +441,203 @@ func TestSyncSubscriptions(t *testing.T) { CatalogSourceNamespace: testNamespace, }, Status: v1alpha1.SubscriptionStatus{ - CurrentCSV: "", - State: v1alpha1.SubscriptionStateUpgradePending, - Install: &v1alpha1.InstallPlanReference{ - Kind: v1alpha1.InstallPlanKind, - APIVersion: v1alpha1.InstallPlanAPIVersion, + CurrentCSV: "", + State: "", + LastUpdated: now, + Conditions: []v1alpha1.SubscriptionCondition{ + { + Type: v1alpha1.SubscriptionBundleUnpacking, + Status: corev1.ConditionTrue, + Reason: "UnpackingInProgress", + }, }, - InstallPlanRef: &corev1.ObjectReference{ - Namespace: testNamespace, - Kind: v1alpha1.InstallPlanKind, - APIVersion: v1alpha1.InstallPlanAPIVersion, + }, + }, + }, + }, + { + name: "NoStatus/NoCurrentCSV/BundleUnpackFailed", + fields: fields{ + clientOptions: []clientfake.Option{clientfake.WithSelfLinks(t)}, + existingOLMObjs: []runtime.Object{ + &v1alpha1.Subscription{ + TypeMeta: metav1.TypeMeta{ + Kind: v1alpha1.SubscriptionKind, + APIVersion: v1alpha1.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "sub", + Namespace: testNamespace, + }, + Spec: &v1alpha1.SubscriptionSpec{ + CatalogSource: "src", + CatalogSourceNamespace: testNamespace, + }, + Status: v1alpha1.SubscriptionStatus{ + CurrentCSV: "", + State: "", + }, + }, + }, + resolveSubs: []*v1alpha1.Subscription{ + { + TypeMeta: metav1.TypeMeta{ + Kind: v1alpha1.SubscriptionKind, + APIVersion: v1alpha1.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "sub", + Namespace: testNamespace, + }, + Spec: &v1alpha1.SubscriptionSpec{ + CatalogSource: "src", + CatalogSourceNamespace: testNamespace, + }, + Status: v1alpha1.SubscriptionStatus{ + CurrentCSV: "", + State: v1alpha1.SubscriptionStateUpgradePending, + }, + }, + }, + resolveBundleLookups: []v1alpha1.BundleLookup{ + { + Path: "bundle-path-a", + Identifier: "bundle-a", + CatalogSourceRef: &corev1.ObjectReference{ + Namespace: testNamespace, + Name: "src", + }, + Conditions: []v1alpha1.BundleLookupCondition{ + { + Type: v1alpha1.BundleLookupFailed, + Status: corev1.ConditionTrue, + Reason: "JobFailed", + Message: "unpack job failed", + LastTransitionTime: &now, + }, }, - InstallPlanGeneration: 1, - LastUpdated: now, }, }, }, - wantInstallPlans: []v1alpha1.InstallPlan{ + args: args{ + obj: &v1alpha1.Subscription{ + TypeMeta: metav1.TypeMeta{ + Kind: v1alpha1.SubscriptionKind, + APIVersion: v1alpha1.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "sub", + Namespace: testNamespace, + }, + Spec: &v1alpha1.SubscriptionSpec{ + CatalogSource: "src", + CatalogSourceNamespace: testNamespace, + }, + Status: v1alpha1.SubscriptionStatus{ + CurrentCSV: "", + State: "", + }, + }, + }, + wantSubscriptions: []*v1alpha1.Subscription{ { - Spec: v1alpha1.InstallPlanSpec{ - ClusterServiceVersionNames: []string{"bundle-a"}, - Approval: v1alpha1.ApprovalAutomatic, - Approved: true, - Generation: 1, + TypeMeta: metav1.TypeMeta{ + Kind: v1alpha1.SubscriptionKind, + APIVersion: v1alpha1.SubscriptionCRDAPIVersion, }, - Status: v1alpha1.InstallPlanStatus{ - Phase: v1alpha1.InstallPlanPhaseInstalling, - CatalogSources: []string{}, - BundleLookups: []v1alpha1.BundleLookup{ + ObjectMeta: metav1.ObjectMeta{ + Name: "sub", + Namespace: testNamespace, + }, + Spec: &v1alpha1.SubscriptionSpec{ + CatalogSource: "src", + CatalogSourceNamespace: testNamespace, + }, + Status: v1alpha1.SubscriptionStatus{ + CurrentCSV: "", + State: "", + LastUpdated: now, + Conditions: []v1alpha1.SubscriptionCondition{ { - Path: "bundle-path-a", - Identifier: "bundle-a", - CatalogSourceRef: &corev1.ObjectReference{ - Namespace: testNamespace, - Name: "src", - }, - Conditions: []v1alpha1.BundleLookupCondition{ - { - Type: v1alpha1.BundleLookupPending, - Status: corev1.ConditionTrue, - Reason: "JobIncomplete", - Message: "unpack job not completed", - LastTransitionTime: &now, - }, - }, + Type: v1alpha1.SubscriptionBundleUnpackFailed, + Reason: "BundleUnpackFailed", + Message: "bundle unpacking failed. Reason: JobFailed, and Message: unpack job failed", + Status: corev1.ConditionTrue, }, }, }, }, }, }, + { + name: "NoStatus/NoCurrentCSV/BundleLookupError", + fields: fields{ + clientOptions: []clientfake.Option{clientfake.WithSelfLinks(t)}, + existingOLMObjs: []runtime.Object{ + &v1alpha1.Subscription{ + TypeMeta: metav1.TypeMeta{ + Kind: v1alpha1.SubscriptionKind, + APIVersion: v1alpha1.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "sub", + Namespace: testNamespace, + }, + Spec: &v1alpha1.SubscriptionSpec{ + CatalogSource: "src", + CatalogSourceNamespace: testNamespace, + }, + Status: v1alpha1.SubscriptionStatus{ + CurrentCSV: "", + State: "", + }, + }, + }, + resolveBundleLookups: []v1alpha1.BundleLookup{{}}, + unpackBundleErr: errors.New("fake unpack error"), + }, + args: args{ + obj: &v1alpha1.Subscription{ + TypeMeta: metav1.TypeMeta{ + Kind: v1alpha1.SubscriptionKind, + APIVersion: v1alpha1.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "sub", + Namespace: testNamespace, + }, + Spec: &v1alpha1.SubscriptionSpec{ + CatalogSource: "src", + CatalogSourceNamespace: testNamespace, + }, + Status: v1alpha1.SubscriptionStatus{ + CurrentCSV: "", + State: "", + }, + }, + }, + wantSubscriptions: []*v1alpha1.Subscription{ + { + TypeMeta: metav1.TypeMeta{ + Kind: v1alpha1.SubscriptionKind, + APIVersion: v1alpha1.SubscriptionCRDAPIVersion, + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "sub", + Namespace: testNamespace, + }, + Spec: &v1alpha1.SubscriptionSpec{ + CatalogSource: "src", + CatalogSourceNamespace: testNamespace, + }, + Status: v1alpha1.SubscriptionStatus{ + CurrentCSV: "", + State: "", + }, + }, + }, + wantErr: fmt.Errorf("bundle unpacking failed with an error: %w", utilerrors.NewAggregate([]error{errors.New("fake unpack error")})), + }, { name: "Status/HaveCurrentCSV/UpdateFoundInCatalog", fields: fields{ @@ -1016,7 +1171,12 @@ func TestSyncSubscriptions(t *testing.T) { ctx, cancel := context.WithCancel(context.TODO()) defer cancel() - o, err := NewFakeOperator(ctx, testNamespace, []string{testNamespace}, withClock(clockFake), withClientObjs(tt.fields.existingOLMObjs...), withK8sObjs(tt.fields.existingObjects...), withFakeClientOptions(tt.fields.clientOptions...)) + fakeBundleUnpacker := &bundlefakes.FakeUnpacker{ + UnpackBundleStub: func(lookup *v1alpha1.BundleLookup, timeout time.Duration) (*bundle.BundleUnpackResult, error) { + return &bundle.BundleUnpackResult{BundleLookup: lookup.DeepCopy()}, tt.fields.unpackBundleErr + }, + } + o, err := NewFakeOperator(ctx, testNamespace, []string{testNamespace}, withClock(clockFake), withClientObjs(append(tt.fields.existingOLMObjs, og)...), withFakeClientOptions(tt.fields.clientOptions...), withBundleUnpacker(fakeBundleUnpacker)) require.NoError(t, err) o.reconciler = &fakes.FakeRegistryReconcilerFactory{ @@ -1029,10 +1189,9 @@ func TestSyncSubscriptions(t *testing.T) { }, } - o.sourcesLastUpdate.Set(tt.fields.sourcesLastUpdate.Time) o.resolver = &fakes.FakeStepResolver{ ResolveStepsStub: func(string) ([]*v1alpha1.Step, []v1alpha1.BundleLookup, []*v1alpha1.Subscription, error) { - return tt.fields.resolveSteps, tt.fields.bundleLookups, tt.fields.resolveSubs, tt.fields.resolveErr + return tt.fields.resolveSteps, tt.fields.resolveBundleLookups, tt.fields.resolveSubs, nil }, } diff --git a/staging/operator-lifecycle-manager/pkg/controller/operators/olm/operator.go b/staging/operator-lifecycle-manager/pkg/controller/operators/olm/operator.go index 6964fe9917..18de7df998 100644 --- a/staging/operator-lifecycle-manager/pkg/controller/operators/olm/operator.go +++ b/staging/operator-lifecycle-manager/pkg/controller/operators/olm/operator.go @@ -1246,7 +1246,7 @@ func (a *Operator) removeDanglingChildCSVs(csv *v1alpha1.ClusterServiceVersion) func (a *Operator) deleteChild(csv *v1alpha1.ClusterServiceVersion, logger *logrus.Entry) error { logger.Debug("gcing csv") - return a.client.OperatorsV1alpha1().ClusterServiceVersions(csv.GetNamespace()).Delete(context.TODO(), csv.GetName(), *metav1.NewDeleteOptions(0)) + return a.client.OperatorsV1alpha1().ClusterServiceVersions(csv.GetNamespace()).Delete(context.TODO(), csv.GetName(), metav1.DeleteOptions{}) } // syncClusterServiceVersion is the method that gets called when we see a CSV event in the cluster @@ -2287,7 +2287,7 @@ func (a *Operator) transitionCSVState(in v1alpha1.ClusterServiceVersion) (out *v syncError = fmt.Errorf("marked as replacement, but no replacement CSV found in cluster") } case v1alpha1.CSVPhaseDeleting: - syncError = a.client.OperatorsV1alpha1().ClusterServiceVersions(out.GetNamespace()).Delete(context.TODO(), out.GetName(), *metav1.NewDeleteOptions(0)) + syncError = a.client.OperatorsV1alpha1().ClusterServiceVersions(out.GetNamespace()).Delete(context.TODO(), out.GetName(), metav1.DeleteOptions{}) if syncError != nil { logger.Debugf("unable to get delete csv marked for deletion: %s", syncError.Error()) } diff --git a/staging/operator-lifecycle-manager/pkg/controller/operators/olm/operator_test.go b/staging/operator-lifecycle-manager/pkg/controller/operators/olm/operator_test.go index f3fba8603f..8377073c23 100644 --- a/staging/operator-lifecycle-manager/pkg/controller/operators/olm/operator_test.go +++ b/staging/operator-lifecycle-manager/pkg/controller/operators/olm/operator_test.go @@ -3852,7 +3852,8 @@ func TestUpdates(t *testing.T) { in: []*v1alpha1.ClusterServiceVersion{c, a, b}, }, } - for _, tt := range tests { + for _, xt := range tests { + tt := xt t.Run(tt.name, func(t *testing.T) { t.Parallel() @@ -3923,9 +3924,10 @@ func TestUpdates(t *testing.T) { simulateSuccessfulRollout(current, op.opClient) } for current.Status.Phase != e.whenIn.phase { - fmt.Printf("waiting for (when) %s to be %s\n", e.whenIn.name, e.whenIn.phase) csvsToSync = syncCSVs(csvsToSync, deletedCSVs(e.shouldBe)) current = csvsToSync[e.whenIn.name] + fmt.Printf("waiting for (when) %s to be %s\n", e.whenIn.name, e.whenIn.phase) + time.Sleep(1 * time.Millisecond) } // sync the other csvs until they're in the expected status diff --git a/staging/operator-lifecycle-manager/pkg/controller/operators/olm/overrides/inject/inject.go b/staging/operator-lifecycle-manager/pkg/controller/operators/olm/overrides/inject/inject.go index 50432767c9..8d105fbfa5 100644 --- a/staging/operator-lifecycle-manager/pkg/controller/operators/olm/overrides/inject/inject.go +++ b/staging/operator-lifecycle-manager/pkg/controller/operators/olm/overrides/inject/inject.go @@ -235,10 +235,12 @@ func InjectNodeSelectorIntoDeployment(podSpec *corev1.PodSpec, nodeSelector map[ // with the given corev1.Affinity. Any nil top-level sub-attributes (e.g. NodeAffinity, PodAffinity, and PodAntiAffinity) // will be ignored. Hint: to overwrite those top-level attributes, empty them out. I.e. use the empty/default object ({}) // e.g. NodeAffinity{}. In yaml: -// affinity: -// nodeAffinity: {} -// podAffinity: {} -// podAntiAffinity: {} +// +// affinity: +// nodeAffinity: {} +// podAffinity: {} +// podAntiAffinity: {} +// // will completely remove the deployment podSpec.affinity and is equivalent to // affinity: {} func OverrideDeploymentAffinity(podSpec *corev1.PodSpec, affinity *corev1.Affinity) error { diff --git a/staging/operator-lifecycle-manager/pkg/controller/registry/reconciler/reconciler.go b/staging/operator-lifecycle-manager/pkg/controller/registry/reconciler/reconciler.go index ebcbd86849..dfb7b87049 100644 --- a/staging/operator-lifecycle-manager/pkg/controller/registry/reconciler/reconciler.go +++ b/staging/operator-lifecycle-manager/pkg/controller/registry/reconciler/reconciler.go @@ -214,6 +214,11 @@ func Pod(source *operatorsv1alpha1.CatalogSource, name string, img string, saNam pod.Spec.Tolerations[index] = *toleration.DeepCopy() } } + + // Override affinity + if grpcPodConfig.Affinity != nil { + pod.Spec.Affinity = grpcPodConfig.Affinity.DeepCopy() + } } // Set priorityclass if its annotation exists diff --git a/staging/operator-lifecycle-manager/pkg/controller/registry/reconciler/reconciler_test.go b/staging/operator-lifecycle-manager/pkg/controller/registry/reconciler/reconciler_test.go index cc6035fe7d..eafb629f48 100644 --- a/staging/operator-lifecycle-manager/pkg/controller/registry/reconciler/reconciler_test.go +++ b/staging/operator-lifecycle-manager/pkg/controller/registry/reconciler/reconciler_test.go @@ -254,11 +254,33 @@ func TestPodSchedulingOverrides(t *testing.T) { }, } + var overriddenAffinity = &corev1.Affinity{ + NodeAffinity: &corev1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{ + NodeSelectorTerms: []corev1.NodeSelectorTerm{ + { + MatchExpressions: []corev1.NodeSelectorRequirement{ + { + Key: "kubernetes.io/arch", + Operator: corev1.NodeSelectorOpIn, + Values: []string{ + "amd64", + "arm", + }, + }, + }, + }, + }, + }, + }, + } + testCases := []struct { title string catalogSource *v1alpha1.CatalogSource expectedNodeSelectors map[string]string expectedTolerations []corev1.Toleration + expectedAffinity *corev1.Affinity expectedPriorityClassName string annotations map[string]string }{ @@ -275,6 +297,7 @@ func TestPodSchedulingOverrides(t *testing.T) { }, }, expectedTolerations: nil, + expectedAffinity: nil, expectedPriorityClassName: defaultPriorityClassName, expectedNodeSelectors: defaultNodeSelectors, }, { @@ -293,6 +316,7 @@ func TestPodSchedulingOverrides(t *testing.T) { }, }, expectedTolerations: nil, + expectedAffinity: nil, expectedPriorityClassName: defaultPriorityClassName, expectedNodeSelectors: overriddenNodeSelectors, }, { @@ -311,6 +335,7 @@ func TestPodSchedulingOverrides(t *testing.T) { }, }, expectedTolerations: nil, + expectedAffinity: nil, expectedPriorityClassName: overriddenPriorityClassName, expectedNodeSelectors: defaultNodeSelectors, }, { @@ -329,6 +354,7 @@ func TestPodSchedulingOverrides(t *testing.T) { }, }, expectedTolerations: nil, + expectedAffinity: nil, expectedPriorityClassName: defaultPriorityClassName, expectedNodeSelectors: defaultNodeSelectors, }, { @@ -347,6 +373,26 @@ func TestPodSchedulingOverrides(t *testing.T) { }, }, expectedTolerations: overriddenTolerations, + expectedAffinity: nil, + expectedPriorityClassName: defaultPriorityClassName, + expectedNodeSelectors: defaultNodeSelectors, + }, { + title: "Override affinity", + catalogSource: &v1alpha1.CatalogSource{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "testns", + }, + Spec: v1alpha1.CatalogSourceSpec{ + SourceType: v1alpha1.SourceTypeGrpc, + Image: "repo/image:tag", + GrpcPodConfig: &v1alpha1.GrpcPodConfig{ + Affinity: overriddenAffinity, + }, + }, + }, + expectedTolerations: nil, + expectedAffinity: overriddenAffinity, expectedPriorityClassName: defaultPriorityClassName, expectedNodeSelectors: defaultNodeSelectors, }, { @@ -363,10 +409,12 @@ func TestPodSchedulingOverrides(t *testing.T) { NodeSelector: overriddenNodeSelectors, PriorityClassName: &overriddenPriorityClassName, Tolerations: overriddenTolerations, + Affinity: overriddenAffinity, }, }, }, expectedTolerations: overriddenTolerations, + expectedAffinity: overriddenAffinity, expectedPriorityClassName: overriddenPriorityClassName, expectedNodeSelectors: overriddenNodeSelectors, }, { @@ -385,6 +433,7 @@ func TestPodSchedulingOverrides(t *testing.T) { }, }, expectedTolerations: nil, + expectedAffinity: nil, annotations: map[string]string{ CatalogPriorityClassKey: "some-OTHER-prio-class", }, @@ -398,5 +447,6 @@ func TestPodSchedulingOverrides(t *testing.T) { require.Equal(t, testCase.expectedNodeSelectors, pod.Spec.NodeSelector) require.Equal(t, testCase.expectedPriorityClassName, pod.Spec.PriorityClassName) require.Equal(t, testCase.expectedTolerations, pod.Spec.Tolerations) + require.Equal(t, testCase.expectedAffinity, pod.Spec.Affinity) } } diff --git a/staging/operator-lifecycle-manager/pkg/controller/registry/resolver/fail_forward.go b/staging/operator-lifecycle-manager/pkg/controller/registry/resolver/fail_forward.go index ba522ba9c3..fe1575c647 100644 --- a/staging/operator-lifecycle-manager/pkg/controller/registry/resolver/fail_forward.go +++ b/staging/operator-lifecycle-manager/pkg/controller/registry/resolver/fail_forward.go @@ -17,8 +17,8 @@ import ( // backwards compatible. func IsFailForwardEnabled(ogLister v1listers.OperatorGroupNamespaceLister) (bool, error) { ogs, err := ogLister.List(labels.Everything()) - if err != nil || len(ogs) == 0 { - return false, nil + if err != nil { + return false, err } if len(ogs) != 1 { return false, fmt.Errorf("found %d operatorGroups, expected 1", len(ogs)) diff --git a/staging/operator-lifecycle-manager/pkg/controller/registry/resolver/resolver_test.go b/staging/operator-lifecycle-manager/pkg/controller/registry/resolver/resolver_test.go index 8c95fb5078..86bfaf282a 100644 --- a/staging/operator-lifecycle-manager/pkg/controller/registry/resolver/resolver_test.go +++ b/staging/operator-lifecycle-manager/pkg/controller/registry/resolver/resolver_test.go @@ -12,8 +12,10 @@ import ( "github.com/sirupsen/logrus/hooks/test" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/operator-framework/api/pkg/constraints" + operatorsv1 "github.com/operator-framework/api/pkg/operators/v1" "github.com/operator-framework/api/pkg/operators/v1alpha1" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/cache" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/solver" @@ -1373,6 +1375,12 @@ func TestSolveOperators_TransferApiOwnership(t *testing.T) { namespace := "olm" catalog := cache.SourceKey{Name: "community", Namespace: namespace} + og := &operatorsv1.OperatorGroup{ + ObjectMeta: metav1.ObjectMeta{ + Name: "og", + Namespace: namespace, + }, + } phases := []struct { subs []*v1alpha1.Subscription @@ -1442,7 +1450,7 @@ func TestSolveOperators_TransferApiOwnership(t *testing.T) { key: cache.NewVirtualSourceKey(namespace), csvLister: &csvs, subLister: fakeSubscriptionLister(p.subs), - ogLister: fakeOperatorGroupLister{}, + ogLister: fakeOperatorGroupLister{og}, logger: logger, }, }), diff --git a/staging/operator-lifecycle-manager/pkg/controller/registry/resolver/source_csvs_test.go b/staging/operator-lifecycle-manager/pkg/controller/registry/resolver/source_csvs_test.go index 22d226669e..56ae33415d 100644 --- a/staging/operator-lifecycle-manager/pkg/controller/registry/resolver/source_csvs_test.go +++ b/staging/operator-lifecycle-manager/pkg/controller/registry/resolver/source_csvs_test.go @@ -467,6 +467,12 @@ func (f fakeOperatorGroupLister) Get(name string) (*operatorsv1.OperatorGroup, e } func TestPropertiesAnnotationHonored(t *testing.T) { + og := &operatorsv1.OperatorGroup{ + ObjectMeta: metav1.ObjectMeta{ + Name: "og", + Namespace: "fake-ns", + }, + } src := &csvSource{ csvLister: fakeCSVLister{ &v1alpha1.ClusterServiceVersion{ @@ -478,7 +484,7 @@ func TestPropertiesAnnotationHonored(t *testing.T) { }, }, subLister: fakeSubscriptionLister{}, - ogLister: fakeOperatorGroupLister{}, + ogLister: fakeOperatorGroupLister{og}, } ss, err := src.Snapshot(context.Background()) require.NoError(t, err) diff --git a/staging/operator-lifecycle-manager/pkg/controller/registry/resolver/step_resolver_test.go b/staging/operator-lifecycle-manager/pkg/controller/registry/resolver/step_resolver_test.go index c75da4affc..528b163950 100644 --- a/staging/operator-lifecycle-manager/pkg/controller/registry/resolver/step_resolver_test.go +++ b/staging/operator-lifecycle-manager/pkg/controller/registry/resolver/step_resolver_test.go @@ -335,6 +335,7 @@ func TestResolver(t *testing.T) { name: "SubscriptionOmitsChannel", clusterState: []runtime.Object{ newSub(namespace, "package", "", catalog), + newOperatorGroup("foo", namespace), }, bundlesByCatalog: map[resolvercache.SourceKey][]*api.Bundle{ catalog: { @@ -354,6 +355,7 @@ func TestResolver(t *testing.T) { name: "SubscriptionWithNoCandidates/Error", clusterState: []runtime.Object{ newSub(namespace, "a", "alpha", catalog), + newOperatorGroup("foo", namespace), }, out: resolverTestOut{ solverError: solver.NotSatisfiable{ @@ -372,6 +374,7 @@ func TestResolver(t *testing.T) { name: "SubscriptionWithNoCandidatesInPackage/Error", clusterState: []runtime.Object{ newSub(namespace, "a", "alpha", catalog), + newOperatorGroup("foo", namespace), }, bundlesByCatalog: map[resolvercache.SourceKey][]*api.Bundle{ catalog: { @@ -395,6 +398,7 @@ func TestResolver(t *testing.T) { name: "SubscriptionWithNoCandidatesInChannel/Error", clusterState: []runtime.Object{ newSub(namespace, "a", "alpha", catalog), + newOperatorGroup("foo", namespace), }, bundlesByCatalog: map[resolvercache.SourceKey][]*api.Bundle{ catalog: { @@ -418,6 +422,7 @@ func TestResolver(t *testing.T) { name: "SubscriptionWithNoCandidatesWithStartingCSVName/Error", clusterState: []runtime.Object{ newSub(namespace, "a", "alpha", catalog, withStartingCSV("notfound")), + newOperatorGroup("foo", namespace), }, bundlesByCatalog: map[resolvercache.SourceKey][]*api.Bundle{ catalog: { @@ -441,6 +446,7 @@ func TestResolver(t *testing.T) { name: "SingleNewSubscription/NoDeps", clusterState: []runtime.Object{ newSub(namespace, "a", "alpha", catalog), + newOperatorGroup("foo", namespace), }, bundlesByCatalog: map[resolvercache.SourceKey][]*api.Bundle{ catalog: { @@ -460,6 +466,7 @@ func TestResolver(t *testing.T) { name: "SingleNewSubscription/ResolveOne", clusterState: []runtime.Object{ newSub(namespace, "a", "alpha", catalog), + newOperatorGroup("foo", namespace), }, bundlesByCatalog: map[resolvercache.SourceKey][]*api.Bundle{ catalog: { @@ -482,6 +489,7 @@ func TestResolver(t *testing.T) { name: "SingleNewSubscription/ResolveOne/BundlePath", clusterState: []runtime.Object{ newSub(namespace, "a", "alpha", catalog), + newOperatorGroup("foo", namespace), }, bundlesByCatalog: map[resolvercache.SourceKey][]*api.Bundle{ catalog: { @@ -528,6 +536,7 @@ func TestResolver(t *testing.T) { name: "SingleNewSubscription/ResolveOne/AdditionalBundleObjects", clusterState: []runtime.Object{ newSub(namespace, "a", "alpha", catalog), + newOperatorGroup("foo", namespace), }, bundlesByCatalog: map[resolvercache.SourceKey][]*api.Bundle{ catalog: { @@ -550,6 +559,7 @@ func TestResolver(t *testing.T) { name: "SingleNewSubscription/ResolveOne/AdditionalBundleObjects/Service", clusterState: []runtime.Object{ newSub(namespace, "a", "alpha", catalog), + newOperatorGroup("foo", namespace), }, bundlesByCatalog: map[resolvercache.SourceKey][]*api.Bundle{ catalog: { @@ -572,6 +582,7 @@ func TestResolver(t *testing.T) { name: "SingleNewSubscription/DependencyMissing", clusterState: []runtime.Object{ newSub(namespace, "a", "alpha", catalog), + newOperatorGroup("foo", namespace), }, bundlesByCatalog: map[resolvercache.SourceKey][]*api.Bundle{ catalog: { @@ -606,6 +617,7 @@ func TestResolver(t *testing.T) { clusterState: []runtime.Object{ existingSub(namespace, "a.v1", "a", "alpha", catalog), existingOperator(namespace, "a.v1", "a", "alpha", "", Provides1, nil, nil, nil), + newOperatorGroup("foo", namespace), }, bundlesByCatalog: map[resolvercache.SourceKey][]*api.Bundle{ catalog: { @@ -620,6 +632,7 @@ func TestResolver(t *testing.T) { existingSub(namespace, "a.v1", "a", "alpha", catalog), existingSub(namespace, "b.v1", "b", "alpha", catalog), existingOperator(namespace, "a.v1", "a", "alpha", "", Provides1, nil, nil, nil), + newOperatorGroup("foo", namespace), }, bundlesByCatalog: map[resolvercache.SourceKey][]*api.Bundle{ catalog: { @@ -638,6 +651,7 @@ func TestResolver(t *testing.T) { clusterState: []runtime.Object{ newSub(namespace, "a", "alpha", catalog), newSub(namespace, "a", "beta", catalog), + newOperatorGroup("foo", namespace), }, bundlesByCatalog: map[resolvercache.SourceKey][]*api.Bundle{ catalog: { @@ -664,6 +678,7 @@ func TestResolver(t *testing.T) { s.Name = s.Name + "-2" return }(), + newOperatorGroup("foo", namespace), }, bundlesByCatalog: map[resolvercache.SourceKey][]*api.Bundle{ catalog: { @@ -689,6 +704,7 @@ func TestResolver(t *testing.T) { clusterState: []runtime.Object{ existingOperator("ns1", "a.v1", "a", "alpha", "", nil, nil, nil, nil), existingOperator("ns2", "a.v1", "a", "alpha", "", nil, nil, nil, nil), + newOperatorGroup("foo", namespace), }, out: nothing, }, @@ -697,6 +713,7 @@ func TestResolver(t *testing.T) { clusterState: []runtime.Object{ existingSub(namespace, "a.v1", "a", "alpha", catalog), existingOperator(namespace, "a.v1", "a", "alpha", "", Provides1, nil, nil, nil), + newOperatorGroup("foo", namespace), }, bundlesByCatalog: map[resolvercache.SourceKey][]*api.Bundle{ catalog: { @@ -718,6 +735,7 @@ func TestResolver(t *testing.T) { clusterState: []runtime.Object{ existingSub(namespace, "a.v1", "a", "alpha", catalog), existingOperator(namespace, "a.v1", "a", "alpha", "", Provides1, nil, nil, nil), + newOperatorGroup("foo", namespace), }, bundlesByCatalog: map[resolvercache.SourceKey][]*api.Bundle{catalog: { stripManifests(withBundlePath(bundle("a.v2", "a", "alpha", "a.v1", Provides1, nil, nil, nil), "quay.io/test/bundle@sha256:abcd"))}, @@ -759,6 +777,7 @@ func TestResolver(t *testing.T) { name: "InstalledSub/NoRunningOperator", clusterState: []runtime.Object{ existingSub(namespace, "a.v1", "a", "alpha", catalog), + newOperatorGroup("foo", namespace), }, bundlesByCatalog: map[resolvercache.SourceKey][]*api.Bundle{ catalog: { @@ -778,6 +797,7 @@ func TestResolver(t *testing.T) { clusterState: []runtime.Object{ existingSub(namespace, "a.v1", "a", "alpha", catalog), existingOperator(namespace, "a.v1", "a", "alpha", "", Provides1, nil, nil, nil), + newOperatorGroup("foo", namespace), }, bundlesByCatalog: map[resolvercache.SourceKey][]*api.Bundle{ catalog: { @@ -802,6 +822,7 @@ func TestResolver(t *testing.T) { clusterState: []runtime.Object{ existingSub(namespace, "a.v1", "a", "alpha", catalog), existingOperator(namespace, "a.v1", "a", "alpha", "", nil, nil, Provides1, nil), + newOperatorGroup("foo", namespace), }, bundlesByCatalog: map[resolvercache.SourceKey][]*api.Bundle{ catalog: { @@ -827,6 +848,7 @@ func TestResolver(t *testing.T) { existingSub(namespace, "a.v1", "a", "alpha", catalog), existingOperator(namespace, "a.v1", "a", "alpha", "", Provides1, nil, nil, nil), newSub(namespace, "b", "beta", catalog), + newOperatorGroup("foo", namespace), }, bundlesByCatalog: map[resolvercache.SourceKey][]*api.Bundle{ catalog: { @@ -851,6 +873,7 @@ func TestResolver(t *testing.T) { clusterState: []runtime.Object{ existingSub(namespace, "a.v1", "a", "alpha", catalog), newSub(namespace, "b", "beta", catalog), + newOperatorGroup("foo", namespace), }, bundlesByCatalog: map[resolvercache.SourceKey][]*api.Bundle{ catalog: { @@ -873,6 +896,7 @@ func TestResolver(t *testing.T) { clusterState: []runtime.Object{ existingSub(namespace, "a.v1", "a", "alpha", catalog), newSub(namespace, "b", "beta", catalog), + newOperatorGroup("foo", namespace), }, bundlesByCatalog: map[resolvercache.SourceKey][]*api.Bundle{ catalog: { @@ -898,6 +922,7 @@ func TestResolver(t *testing.T) { existingOperator(namespace, "a.v1", "a", "alpha", "", Provides1, Requires2, nil, nil), existingSub(namespace, "b.v1", "b", "alpha", catalog), existingOperator(namespace, "b.v1", "b", "alpha", "", Provides2, Requires1, nil, nil), + newOperatorGroup("foo", namespace), }, bundlesByCatalog: map[resolvercache.SourceKey][]*api.Bundle{ catalog: { @@ -924,6 +949,7 @@ func TestResolver(t *testing.T) { existingOperator(namespace, "a.v1", "a", "alpha", "", Provides1, nil, nil, nil), existingSub(namespace, "b.v1", "b", "alpha", catalog), existingOperator(namespace, "b.v1", "b", "alpha", "", nil, Requires1, nil, nil), + newOperatorGroup("foo", namespace), }, bundlesByCatalog: map[resolvercache.SourceKey][]*api.Bundle{ catalog: { @@ -946,6 +972,7 @@ func TestResolver(t *testing.T) { name: "PicksOlderProvider", clusterState: []runtime.Object{ newSub(namespace, "b", "alpha", catalog), + newOperatorGroup("foo", namespace), }, bundlesByCatalog: map[resolvercache.SourceKey][]*api.Bundle{ catalog: { @@ -970,6 +997,7 @@ func TestResolver(t *testing.T) { clusterState: []runtime.Object{ existingSub(namespace, "a.v1", "a", "alpha", catalog), existingOperator(namespace, "a.v1", "a", "alpha", "", Provides1, nil, nil, nil), + newOperatorGroup("foo", namespace), }, bundlesByCatalog: map[resolvercache.SourceKey][]*api.Bundle{catalog: { bundle("a.v3", "a", "alpha", "a.v2", nil, nil, nil, nil, withVersion("1.0.0"), withSkipRange("< 1.0.0")), @@ -990,6 +1018,7 @@ func TestResolver(t *testing.T) { existingSub(namespace, "b.v1", "b", "beta", catalog), existingOperator(namespace, "a.v1", "a", "alpha", "", nil, Requires1, nil, nil), existingOperator(namespace, "b.v1", "b", "beta", "", Provides1, nil, nil, nil), + newOperatorGroup("foo", namespace), }, bundlesByCatalog: map[resolvercache.SourceKey][]*api.Bundle{ catalog: { @@ -1015,6 +1044,7 @@ func TestResolver(t *testing.T) { clusterState: []runtime.Object{ existingSub(namespace, "a.v1", "a", "alpha", catalog), existingOperator(namespace, "a.v1", "a", "alpha", "", Provides1, nil, nil, nil), + newOperatorGroup("foo", namespace), }, bundlesByCatalog: map[resolvercache.SourceKey][]*api.Bundle{catalog: { bundle("a.v2", "a", "alpha", "", nil, nil, nil, nil, withVersion("1.0.0"), withSkipRange("< 1.0.0")), @@ -1034,6 +1064,7 @@ func TestResolver(t *testing.T) { name: "NewSub/StartingCSV", clusterState: []runtime.Object{ newSub(namespace, "a", "alpha", catalog, withStartingCSV("a.v2")), + newOperatorGroup("foo", namespace), }, bundlesByCatalog: map[resolvercache.SourceKey][]*api.Bundle{catalog: { bundle("a.v1", "a", "alpha", "", nil, nil, nil, nil), @@ -1054,6 +1085,7 @@ func TestResolver(t *testing.T) { clusterState: []runtime.Object{ existingSub(namespace, "a.v1", "a", "alpha", catalog), existingOperator(namespace, "a.v1", "a", "alpha", "", Provides1, nil, nil, nil), + newOperatorGroup("foo", namespace), }, bundlesByCatalog: map[resolvercache.SourceKey][]*api.Bundle{catalog: { bundle("a.v2", "a", "alpha", "", nil, nil, nil, nil, withVersion("1.0.0"), withSkips([]string{"a.v1"})), @@ -1074,6 +1106,7 @@ func TestResolver(t *testing.T) { existingSub(namespace, "a.v2", "a", "alpha", catalog), existingOperator(namespace, "a.v1", "a", "alpha", "", Provides1, nil, nil, nil, withPhase(v1alpha1.CSVPhaseReplacing)), existingOperator(namespace, "a.v2", "a", "alpha", "a.v1", Provides1, nil, nil, nil, withPhase(v1alpha1.CSVPhaseFailed)), + newOperatorGroup("foo", namespace), }, bundlesByCatalog: map[resolvercache.SourceKey][]*api.Bundle{catalog: { bundle("a.v1", "a", "alpha", "", Provides1, nil, nil, nil, withVersion("1.0.0")), @@ -1121,6 +1154,7 @@ func TestResolver(t *testing.T) { existingOperator(namespace, "a.v1", "a", "alpha", "", Provides1, nil, nil, nil, withPhase(v1alpha1.CSVPhaseReplacing)), existingOperator(namespace, "a.v2", "a", "alpha", "a.v1", Provides1, nil, nil, nil, withPhase(v1alpha1.CSVPhaseReplacing)), existingOperator(namespace, "a.v3", "a", "alpha", "a.v2", Provides1, nil, nil, nil, withPhase(v1alpha1.CSVPhaseFailed)), + newOperatorGroup("foo", namespace), }, bundlesByCatalog: map[resolvercache.SourceKey][]*api.Bundle{catalog: { bundle("a.v1", "a", "alpha", "", Provides1, nil, nil, nil, withVersion("1.0.0")), @@ -1182,7 +1216,7 @@ func TestResolver(t *testing.T) { steps: [][]*v1alpha1.Step{}, subs: []*v1alpha1.Subscription{}, errAssert: func(t *testing.T, err error) { - assert.Contains(t, err.Error(), "failed to populate resolver cache from source @existing/catsrc-namespace: csv catsrc-namespace/a.v1") + assert.Contains(t, err.Error(), "failed to populate resolver cache from source @existing/catsrc-namespace: csv") assert.Contains(t, err.Error(), "in phase Failed instead of Replacing") }, }, diff --git a/staging/operator-lifecycle-manager/pkg/lib/catalogsource/catalogsource_update.go b/staging/operator-lifecycle-manager/pkg/lib/catalogsource/catalogsource_update.go index c8a58caaea..821ed00b96 100644 --- a/staging/operator-lifecycle-manager/pkg/lib/catalogsource/catalogsource_update.go +++ b/staging/operator-lifecycle-manager/pkg/lib/catalogsource/catalogsource_update.go @@ -12,7 +12,8 @@ import ( "github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/clientset/versioned" ) -/* UpdateStatus can be used to update the status of the provided catalog source. Note that +/* +UpdateStatus can be used to update the status of the provided catalog source. Note that the caller is responsible for ensuring accurate status values in the catsrc argument (i.e. the status is used as-is). @@ -34,7 +35,8 @@ func UpdateStatus(logger *logrus.Entry, client versioned.Interface, catsrc *v1al return nil } -/* UpdateStatusWithConditions can be used to update the status conditions for the provided catalog source. +/* +UpdateStatusWithConditions can be used to update the status conditions for the provided catalog source. This function will make no changes to the other status fields (those fields will be used as-is). If the provided conditions do not result in any status condition changes, then the API server will not be updated. Note that the caller is responsible for ensuring accurate status values for all other fields. @@ -71,7 +73,8 @@ func UpdateStatusWithConditions(logger *logrus.Entry, client versioned.Interface return nil } -/* UpdateSpecAndStatusConditions can be used to update the catalog source with the provided status conditions. +/* +UpdateSpecAndStatusConditions can be used to update the catalog source with the provided status conditions. This will update the spec and status portions of the catalog source. Calls to the API server will occur even if the provided conditions result in no changes. @@ -98,7 +101,8 @@ func UpdateSpecAndStatusConditions(logger *logrus.Entry, client versioned.Interf return nil } -/* RemoveStatusConditions can be used to remove the status conditions for the provided catalog source. +/* +RemoveStatusConditions can be used to remove the status conditions for the provided catalog source. This function will make no changes to the other status fields (those fields will be used as-is). If the provided conditions do not result in any status condition changes, then the API server will not be updated. Note that the caller is responsible for ensuring accurate status values for all other fields. diff --git a/staging/operator-lifecycle-manager/pkg/lib/controller-runtime/client/fake_ssa.go b/staging/operator-lifecycle-manager/pkg/lib/controller-runtime/client/fake_ssa.go index a7e04cb873..3044cd6d9b 100644 --- a/staging/operator-lifecycle-manager/pkg/lib/controller-runtime/client/fake_ssa.go +++ b/staging/operator-lifecycle-manager/pkg/lib/controller-runtime/client/fake_ssa.go @@ -35,8 +35,7 @@ type fakeStatusWriter struct { k8scontrollerclient.StatusWriter } -func (c fakeStatusWriter) Patch(ctx context.Context, obj k8scontrollerclient.Object, patch k8scontrollerclient.Patch, opts ...k8scontrollerclient.PatchOption) error { - patch, opts = convertApplyToMergePatch(patch, opts...) +func (c fakeStatusWriter) Patch(ctx context.Context, obj k8scontrollerclient.Object, patch k8scontrollerclient.Patch, opts ...k8scontrollerclient.SubResourcePatchOption) error { return c.StatusWriter.Patch(ctx, obj, patch, opts...) } diff --git a/staging/operator-lifecycle-manager/pkg/lib/controller-runtime/client/ssa.go b/staging/operator-lifecycle-manager/pkg/lib/controller-runtime/client/ssa.go index b13f923b3d..74eb4784e2 100644 --- a/staging/operator-lifecycle-manager/pkg/lib/controller-runtime/client/ssa.go +++ b/staging/operator-lifecycle-manager/pkg/lib/controller-runtime/client/ssa.go @@ -87,13 +87,13 @@ type ServerSideApplier struct { // The underlying value of the given resource pointer is updated to reflect the latest cluster state each time the closure is successfully invoked. // Ex. Change the spec of an existing InstallPlan // -// plan := &InstallPlan{} -// plan.SetNamespace("ns") -// plan.SetName("install-123def") -// Eventually(c.Apply(plan, func(p *v1alpha1.InstallPlan) error { +// plan := &InstallPlan{} +// plan.SetNamespace("ns") +// plan.SetName("install-123def") +// Eventually(c.Apply(plan, func(p *v1alpha1.InstallPlan) error { // p.Spec.Approved = true // return nil -// })).Should(Succeed()) +// })).Should(Succeed()) func (c *ServerSideApplier) Apply(ctx context.Context, obj Object, changeFunc interface{}) func() error { // Ensure given object is a pointer objType := reflect.TypeOf(obj) @@ -182,7 +182,10 @@ func (c *ServerSideApplier) Apply(ctx context.Context, obj Object, changeFunc in return err } - if err := c.client.Status().Patch(ctx, cp, k8scontrollerclient.Apply, k8scontrollerclient.ForceOwnership, c.Owner); err != nil { + pos := &k8scontrollerclient.SubResourcePatchOptions{} + k8scontrollerclient.ForceOwnership.ApplyToPatch(&pos.PatchOptions) + + if err := c.client.Status().Patch(ctx, cp, k8scontrollerclient.Apply, pos, c.Owner); err != nil { fmt.Printf("second patch error: %s\n", err) return err } diff --git a/staging/operator-lifecycle-manager/pkg/lib/filemonitor/cabundle_updater.go b/staging/operator-lifecycle-manager/pkg/lib/filemonitor/cabundle_updater.go index 4fcee4e457..58f577ef45 100644 --- a/staging/operator-lifecycle-manager/pkg/lib/filemonitor/cabundle_updater.go +++ b/staging/operator-lifecycle-manager/pkg/lib/filemonitor/cabundle_updater.go @@ -2,7 +2,7 @@ package filemonitor import ( "crypto/x509" - "io/ioutil" + "os" "sync" "github.com/fsnotify/fsnotify" @@ -16,7 +16,7 @@ type certPoolStore struct { } func NewCertPoolStore(clientCAPath string) (*certPoolStore, error) { - pem, err := ioutil.ReadFile(clientCAPath) + pem, err := os.ReadFile(clientCAPath) if err != nil { return nil, err } @@ -31,7 +31,7 @@ func NewCertPoolStore(clientCAPath string) (*certPoolStore, error) { } func (c *certPoolStore) storeCABundle(clientCAPath string) error { - pem, err := ioutil.ReadFile(clientCAPath) + pem, err := os.ReadFile(clientCAPath) if err == nil { c.mutex.Lock() defer c.mutex.Unlock() diff --git a/staging/operator-lifecycle-manager/pkg/lib/filemonitor/cert_updater_test.go b/staging/operator-lifecycle-manager/pkg/lib/filemonitor/cert_updater_test.go index 022b22fc30..039e5ceac2 100644 --- a/staging/operator-lifecycle-manager/pkg/lib/filemonitor/cert_updater_test.go +++ b/staging/operator-lifecycle-manager/pkg/lib/filemonitor/cert_updater_test.go @@ -6,7 +6,6 @@ import ( "crypto/x509" "fmt" "html" - "io/ioutil" "net" "net/http" "os" @@ -88,7 +87,7 @@ func TestOLMGetCertRotationFn(t *testing.T) { } }() - caCert, err := ioutil.ReadFile(caCrt) + caCert, err := os.ReadFile(caCrt) require.NoError(t, err) caCertPool := x509.NewCertPool() caCertPool.AppendCertsFromPEM(caCert) diff --git a/staging/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac/v1/zz_generated.conversion.go b/staging/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac/v1/zz_generated.conversion.go index b3d5891bb7..04e9556e17 100644 --- a/staging/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac/v1/zz_generated.conversion.go +++ b/staging/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac/v1/zz_generated.conversion.go @@ -1,3 +1,4 @@ +//go:build !ignore_autogenerated // +build !ignore_autogenerated /* diff --git a/staging/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac/v1/zz_generated.deepcopy.go b/staging/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac/v1/zz_generated.deepcopy.go index 7bf8d13745..a4ff45d659 100644 --- a/staging/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac/v1/zz_generated.deepcopy.go +++ b/staging/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac/v1/zz_generated.deepcopy.go @@ -1,3 +1,4 @@ +//go:build !ignore_autogenerated // +build !ignore_autogenerated /* diff --git a/staging/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac/v1/zz_generated.defaults.go b/staging/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac/v1/zz_generated.defaults.go index f0d53c1721..ba7fdabd85 100644 --- a/staging/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac/v1/zz_generated.defaults.go +++ b/staging/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac/v1/zz_generated.defaults.go @@ -1,3 +1,4 @@ +//go:build !ignore_autogenerated // +build !ignore_autogenerated /* diff --git a/staging/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac/zz_generated.deepcopy.go b/staging/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac/zz_generated.deepcopy.go index 33518a9868..0f7023a2db 100644 --- a/staging/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac/zz_generated.deepcopy.go +++ b/staging/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac/zz_generated.deepcopy.go @@ -1,3 +1,4 @@ +//go:build !ignore_autogenerated // +build !ignore_autogenerated /* diff --git a/staging/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/printers/tablegenerator.go b/staging/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/printers/tablegenerator.go index add7c3896e..f96239dc0d 100644 --- a/staging/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/printers/tablegenerator.go +++ b/staging/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/printers/tablegenerator.go @@ -150,7 +150,9 @@ func (h *HumanReadableGenerator) TableHandler(columnDefinitions []metav1beta1.Ta // ValidateRowPrintHandlerFunc validates print handler signature. // printFunc is the function that will be called to print an object. // It must be of the following type: -// func printFunc(object ObjectType, options GenerateOptions) ([]metav1beta1.TableRow, error) +// +// func printFunc(object ObjectType, options GenerateOptions) ([]metav1beta1.TableRow, error) +// // where ObjectType is the type of the object that will be printed, and the first // return value is an array of rows, with each row containing a number of cells that // match the number of columns defined for that printer function. diff --git a/staging/operator-lifecycle-manager/pkg/lib/operatorlister/lister.go b/staging/operator-lifecycle-manager/pkg/lib/operatorlister/lister.go index 99e41817da..0bf77a89e4 100644 --- a/staging/operator-lifecycle-manager/pkg/lib/operatorlister/lister.go +++ b/staging/operator-lifecycle-manager/pkg/lib/operatorlister/lister.go @@ -28,6 +28,7 @@ import ( //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -o ./operatorlisterfakes/fake_clusterserviceversion_v1alpha1_namespace_lister.go ../../api/client/listers/operators/v1alpha1.ClusterServiceVersionNamespaceLister // OperatorLister is a union of versioned informer listers +// //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . OperatorLister type OperatorLister interface { AppsV1() AppsV1Lister diff --git a/staging/operator-lifecycle-manager/pkg/lib/operatorstatus/csv_handler.go b/staging/operator-lifecycle-manager/pkg/lib/operatorstatus/csv_handler.go index eb8c57ab20..bf2b9b51b7 100644 --- a/staging/operator-lifecycle-manager/pkg/lib/operatorstatus/csv_handler.go +++ b/staging/operator-lifecycle-manager/pkg/lib/operatorstatus/csv_handler.go @@ -86,8 +86,8 @@ type handler struct { // OnAddOrUpdate is invoked when a CSV has been added or edited. We tap into // this notification and do the following: // -// a. Make sure this is the CSV related to the cluster operator resource we are -// tracking. Otherwise, do nothing. +// a. Make sure this is the CSV related to the cluster operator resource we are tracking. Otherwise, do nothing. +// // b. If this is the right CSV then send it to the monitor. func (h *handler) OnAddOrUpdate(in *v1alpha1.ClusterServiceVersion) { h.onNotification(in, false) @@ -96,8 +96,8 @@ func (h *handler) OnAddOrUpdate(in *v1alpha1.ClusterServiceVersion) { // OnDelete is invoked when a CSV has been deleted. We tap into // this notification and do the following: // -// a. Make sure this is the CSV related to the cluster operator resource we are -// tracking. Otherwise, do nothing. +// a. Make sure this is the CSV related to the cluster operator resource we are tracking. Otherwise, do nothing. +// // b. If this is the right CSV then send it to the monitor. func (h *handler) OnDelete(in *v1alpha1.ClusterServiceVersion) { h.onNotification(in, true) diff --git a/staging/operator-lifecycle-manager/pkg/lib/proxy/overridden.go b/staging/operator-lifecycle-manager/pkg/lib/proxy/overridden.go index 8ad45f1a78..42eec7acd6 100644 --- a/staging/operator-lifecycle-manager/pkg/lib/proxy/overridden.go +++ b/staging/operator-lifecycle-manager/pkg/lib/proxy/overridden.go @@ -6,8 +6,9 @@ import ( // IsOverridden returns true if the given container overrides proxy env variable(s). // We apply the following rule: -// If a container already defines any of the proxy env variable then it -// overrides all of these. +// +// If a container already defines any of the proxy env variable then it +// overrides all of these. func IsOverridden(envVar []corev1.EnvVar) (overrides bool) { for _, envVarName := range allProxyEnvVarNames { _, found := find(envVar, envVarName) diff --git a/staging/operator-lifecycle-manager/pkg/package-server/client/clientset/internalversion/clientset.go b/staging/operator-lifecycle-manager/pkg/package-server/client/clientset/internalversion/clientset.go index c62d34765e..7869695b27 100644 --- a/staging/operator-lifecycle-manager/pkg/package-server/client/clientset/internalversion/clientset.go +++ b/staging/operator-lifecycle-manager/pkg/package-server/client/clientset/internalversion/clientset.go @@ -33,8 +33,7 @@ type Interface interface { Operators() operatorsinternalversion.OperatorsInterface } -// Clientset contains the clients for groups. Each group has exactly one -// version included in a Clientset. +// Clientset contains the clients for groups. type Clientset struct { *discovery.DiscoveryClient operators *operatorsinternalversion.OperatorsClient diff --git a/staging/operator-lifecycle-manager/pkg/package-server/client/clientset/versioned/clientset.go b/staging/operator-lifecycle-manager/pkg/package-server/client/clientset/versioned/clientset.go index b14e68fa0c..54c1733ce5 100644 --- a/staging/operator-lifecycle-manager/pkg/package-server/client/clientset/versioned/clientset.go +++ b/staging/operator-lifecycle-manager/pkg/package-server/client/clientset/versioned/clientset.go @@ -33,8 +33,7 @@ type Interface interface { OperatorsV1() operatorsv1.OperatorsV1Interface } -// Clientset contains the clients for groups. Each group has exactly one -// version included in a Clientset. +// Clientset contains the clients for groups. type Clientset struct { *discovery.DiscoveryClient operatorsV1 *operatorsv1.OperatorsV1Client diff --git a/staging/operator-lifecycle-manager/pkg/package-server/client/informers/externalversions/factory.go b/staging/operator-lifecycle-manager/pkg/package-server/client/informers/externalversions/factory.go index 659f23161f..4a778610e6 100644 --- a/staging/operator-lifecycle-manager/pkg/package-server/client/informers/externalversions/factory.go +++ b/staging/operator-lifecycle-manager/pkg/package-server/client/informers/externalversions/factory.go @@ -47,6 +47,11 @@ type sharedInformerFactory struct { // startedInformers is used for tracking which informers have been started. // This allows Start() to be called multiple times safely. startedInformers map[reflect.Type]bool + // wg tracks how many goroutines were started. + wg sync.WaitGroup + // shuttingDown is true when Shutdown has been called. It may still be running + // because it needs to wait for goroutines. + shuttingDown bool } // WithCustomResyncConfig sets a custom resync period for the specified informer types. @@ -107,20 +112,39 @@ func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResy return factory } -// Start initializes all requested informers. func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { f.lock.Lock() defer f.lock.Unlock() + if f.shuttingDown { + return + } + for informerType, informer := range f.informers { if !f.startedInformers[informerType] { - go informer.Run(stopCh) + f.wg.Add(1) + // We need a new variable in each loop iteration, + // otherwise the goroutine would use the loop variable + // and that keeps changing. + informer := informer + go func() { + defer f.wg.Done() + informer.Run(stopCh) + }() f.startedInformers[informerType] = true } } } -// WaitForCacheSync waits for all started informers' cache were synced. +func (f *sharedInformerFactory) Shutdown() { + f.lock.Lock() + f.shuttingDown = true + f.lock.Unlock() + + // Will return immediately if there is nothing to wait for. + f.wg.Wait() +} + func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool { informers := func() map[reflect.Type]cache.SharedIndexInformer { f.lock.Lock() @@ -167,11 +191,58 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal // SharedInformerFactory provides shared informers for resources in all known // API group versions. +// +// It is typically used like this: +// +// ctx, cancel := context.Background() +// defer cancel() +// factory := NewSharedInformerFactory(client, resyncPeriod) +// defer factory.WaitForStop() // Returns immediately if nothing was started. +// genericInformer := factory.ForResource(resource) +// typedInformer := factory.SomeAPIGroup().V1().SomeType() +// factory.Start(ctx.Done()) // Start processing these informers. +// synced := factory.WaitForCacheSync(ctx.Done()) +// for v, ok := range synced { +// if !ok { +// fmt.Fprintf(os.Stderr, "caches failed to sync: %v", v) +// return +// } +// } +// +// // Creating informers can also be created after Start, but then +// // Start must be called again: +// anotherGenericInformer := factory.ForResource(resource) +// factory.Start(ctx.Done()) type SharedInformerFactory interface { internalinterfaces.SharedInformerFactory - ForResource(resource schema.GroupVersionResource) (GenericInformer, error) + + // Start initializes all requested informers. They are handled in goroutines + // which run until the stop channel gets closed. + Start(stopCh <-chan struct{}) + + // Shutdown marks a factory as shutting down. At that point no new + // informers can be started anymore and Start will return without + // doing anything. + // + // In addition, Shutdown blocks until all goroutines have terminated. For that + // to happen, the close channel(s) that they were started with must be closed, + // either before Shutdown gets called or while it is waiting. + // + // Shutdown may be called multiple times, even concurrently. All such calls will + // block until all goroutines have terminated. + Shutdown() + + // WaitForCacheSync blocks until all started informers' caches were synced + // or the stop channel gets closed. WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool + // ForResource gives generic access to a shared informer of the matching type. + ForResource(resource schema.GroupVersionResource) (GenericInformer, error) + + // InternalInformerFor returns the SharedIndexInformer for obj using an internal + // client. + InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer + Operators() operators.Interface } diff --git a/staging/operator-lifecycle-manager/pkg/package-server/client/informers/internalversion/factory.go b/staging/operator-lifecycle-manager/pkg/package-server/client/informers/internalversion/factory.go index bb656715a5..f984dc4e56 100644 --- a/staging/operator-lifecycle-manager/pkg/package-server/client/informers/internalversion/factory.go +++ b/staging/operator-lifecycle-manager/pkg/package-server/client/informers/internalversion/factory.go @@ -47,6 +47,11 @@ type sharedInformerFactory struct { // startedInformers is used for tracking which informers have been started. // This allows Start() to be called multiple times safely. startedInformers map[reflect.Type]bool + // wg tracks how many goroutines were started. + wg sync.WaitGroup + // shuttingDown is true when Shutdown has been called. It may still be running + // because it needs to wait for goroutines. + shuttingDown bool } // WithCustomResyncConfig sets a custom resync period for the specified informer types. @@ -107,20 +112,39 @@ func NewSharedInformerFactoryWithOptions(client internalversion.Interface, defau return factory } -// Start initializes all requested informers. func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { f.lock.Lock() defer f.lock.Unlock() + if f.shuttingDown { + return + } + for informerType, informer := range f.informers { if !f.startedInformers[informerType] { - go informer.Run(stopCh) + f.wg.Add(1) + // We need a new variable in each loop iteration, + // otherwise the goroutine would use the loop variable + // and that keeps changing. + informer := informer + go func() { + defer f.wg.Done() + informer.Run(stopCh) + }() f.startedInformers[informerType] = true } } } -// WaitForCacheSync waits for all started informers' cache were synced. +func (f *sharedInformerFactory) Shutdown() { + f.lock.Lock() + f.shuttingDown = true + f.lock.Unlock() + + // Will return immediately if there is nothing to wait for. + f.wg.Wait() +} + func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool { informers := func() map[reflect.Type]cache.SharedIndexInformer { f.lock.Lock() @@ -167,11 +191,58 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal // SharedInformerFactory provides shared informers for resources in all known // API group versions. +// +// It is typically used like this: +// +// ctx, cancel := context.Background() +// defer cancel() +// factory := NewSharedInformerFactory(client, resyncPeriod) +// defer factory.WaitForStop() // Returns immediately if nothing was started. +// genericInformer := factory.ForResource(resource) +// typedInformer := factory.SomeAPIGroup().V1().SomeType() +// factory.Start(ctx.Done()) // Start processing these informers. +// synced := factory.WaitForCacheSync(ctx.Done()) +// for v, ok := range synced { +// if !ok { +// fmt.Fprintf(os.Stderr, "caches failed to sync: %v", v) +// return +// } +// } +// +// // Creating informers can also be created after Start, but then +// // Start must be called again: +// anotherGenericInformer := factory.ForResource(resource) +// factory.Start(ctx.Done()) type SharedInformerFactory interface { internalinterfaces.SharedInformerFactory - ForResource(resource schema.GroupVersionResource) (GenericInformer, error) + + // Start initializes all requested informers. They are handled in goroutines + // which run until the stop channel gets closed. + Start(stopCh <-chan struct{}) + + // Shutdown marks a factory as shutting down. At that point no new + // informers can be started anymore and Start will return without + // doing anything. + // + // In addition, Shutdown blocks until all goroutines have terminated. For that + // to happen, the close channel(s) that they were started with must be closed, + // either before Shutdown gets called or while it is waiting. + // + // Shutdown may be called multiple times, even concurrently. All such calls will + // block until all goroutines have terminated. + Shutdown() + + // WaitForCacheSync blocks until all started informers' caches were synced + // or the stop channel gets closed. WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool + // ForResource gives generic access to a shared informer of the matching type. + ForResource(resource schema.GroupVersionResource) (GenericInformer, error) + + // InternalInformerFor returns the SharedIndexInformer for obj using an internal + // client. + InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer + Operators() operators.Interface } diff --git a/staging/operator-lifecycle-manager/pkg/package-server/client/openapi/zz_generated.openapi.go b/staging/operator-lifecycle-manager/pkg/package-server/client/openapi/zz_generated.openapi.go index e4fcd10386..2ef8406a65 100644 --- a/staging/operator-lifecycle-manager/pkg/package-server/client/openapi/zz_generated.openapi.go +++ b/staging/operator-lifecycle-manager/pkg/package-server/client/openapi/zz_generated.openapi.go @@ -141,28 +141,31 @@ func schema_api_pkg_operators_v1alpha1_APIResourceReference(ref common.Reference return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "APIResourceReference is a Kubernetes resource type used by a custom resource", + Description: "APIResourceReference is a reference to a Kubernetes resource type that the referrer utilizes.", Type: []string{"object"}, Properties: map[string]spec.Schema{ "name": { SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", + Description: "Plural name of the referenced resource type (CustomResourceDefinition.Spec.Names[].Plural). Empty string if the referenced resource type is not a custom resource.", + Default: "", + Type: []string{"string"}, + Format: "", }, }, "kind": { SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", + Description: "Kind of the referenced resource type.", + Default: "", + Type: []string{"string"}, + Format: "", }, }, "version": { SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", + Description: "API Version of the referenced resource type.", + Default: "", + Type: []string{"string"}, + Format: "", }, }, }, @@ -679,20 +682,23 @@ func schema_api_pkg_operators_v1alpha1_ClusterServiceVersionSpec(ref common.Refe }, "displayName": { SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", + Description: "The name of the operator in display format.", + Default: "", + Type: []string{"string"}, + Format: "", }, }, "description": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Description: "Description of the operator. Can include the features, limitations or use-cases of the operator.", + Type: []string{"string"}, + Format: "", }, }, "keywords": { SchemaProps: spec.SchemaProps{ - Type: []string{"array"}, + Description: "A list of keywords describing the operator.", + Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -706,7 +712,8 @@ func schema_api_pkg_operators_v1alpha1_ClusterServiceVersionSpec(ref common.Refe }, "maintainers": { SchemaProps: spec.SchemaProps{ - Type: []string{"array"}, + Description: "A list of organizational entities maintaining the operator.", + Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -719,13 +726,15 @@ func schema_api_pkg_operators_v1alpha1_ClusterServiceVersionSpec(ref common.Refe }, "provider": { SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("github.com/operator-framework/api/pkg/operators/v1alpha1.AppLink"), + Description: "The publishing entity behind the operator.", + Default: map[string]interface{}{}, + Ref: ref("github.com/operator-framework/api/pkg/operators/v1alpha1.AppLink"), }, }, "links": { SchemaProps: spec.SchemaProps{ - Type: []string{"array"}, + Description: "A list of links related to the operator.", + Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -738,7 +747,8 @@ func schema_api_pkg_operators_v1alpha1_ClusterServiceVersionSpec(ref common.Refe }, "icon": { SchemaProps: spec.SchemaProps{ - Type: []string{"array"}, + Description: "The icon for this operator.", + Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ diff --git a/staging/operator-lifecycle-manager/pkg/package-server/storage/subresources.go b/staging/operator-lifecycle-manager/pkg/package-server/storage/subresources.go index a851ee215a..24bc799e69 100644 --- a/staging/operator-lifecycle-manager/pkg/package-server/storage/subresources.go +++ b/staging/operator-lifecycle-manager/pkg/package-server/storage/subresources.go @@ -3,7 +3,7 @@ package storage import ( "context" "encoding/base64" - "io/ioutil" + "io" "net/http" "strconv" "strings" @@ -72,7 +72,7 @@ func (s *LogoStorage) Connect(ctx context.Context, name string, options runtime. etag := `"` + strings.Join([]string{name, pkgChannel.Name, pkgChannel.CurrentCSV}, ".") + `"` reader := base64.NewDecoder(base64.StdEncoding, strings.NewReader(data)) - imgBytes, _ := ioutil.ReadAll(reader) + imgBytes, _ := io.ReadAll(reader) return imgBytes, mimeType, etag } diff --git a/staging/operator-lifecycle-manager/scripts/build_local.sh b/staging/operator-lifecycle-manager/scripts/build_local.sh index 47fc6c926f..e30ea18a0e 100755 --- a/staging/operator-lifecycle-manager/scripts/build_local.sh +++ b/staging/operator-lifecycle-manager/scripts/build_local.sh @@ -22,7 +22,7 @@ if [ -n "$KIND" ]; then # kind will use the cluster named kind by default, so if there is only one cluster, specify it if [[ ${#CLUSTERS[@]} == 1 ]]; then KIND_FLAGS="--name ${CLUSTERS[0]}" - echo 'Use cluster ${CLUSTERS[0]}' + echo "Use cluster ${CLUSTERS[0]}" fi kind load docker-image quay.io/operator-framework/olm:local ${KIND_FLAGS} diff --git a/staging/operator-lifecycle-manager/test/e2e/catalog_e2e_test.go b/staging/operator-lifecycle-manager/test/e2e/catalog_e2e_test.go index b582f9ab68..41c6cca141 100644 --- a/staging/operator-lifecycle-manager/test/e2e/catalog_e2e_test.go +++ b/staging/operator-lifecycle-manager/test/e2e/catalog_e2e_test.go @@ -1010,7 +1010,7 @@ var _ = Describe("Starting CatalogSource e2e tests", func() { catSrcImage := "quay.io/olmtest/busybox-dependencies-index" - // Create gRPC CatalogSource + By("creating gRPC CatalogSource") source := &v1alpha1.CatalogSource{ TypeMeta: metav1.TypeMeta{ Kind: v1alpha1.CatalogSourceKind, @@ -1028,7 +1028,6 @@ var _ = Describe("Starting CatalogSource e2e tests", func() { }, }, } - source, err := crc.OperatorsV1alpha1().CatalogSources(source.GetNamespace()).Create(context.Background(), source, metav1.CreateOptions{}) Expect(err).ShouldNot(HaveOccurred()) defer func() { @@ -1036,22 +1035,22 @@ var _ = Describe("Starting CatalogSource e2e tests", func() { Expect(err).ShouldNot(HaveOccurred()) }() - // Wait for the CatalogSource to be ready + By("waiting for the CatalogSource to be ready") _, err = fetchCatalogSourceOnStatus(crc, source.GetName(), source.GetNamespace(), catalogSourceRegistryPodSynced) Expect(err).ToNot(HaveOccurred(), "catalog source did not become ready") - // Create a Subscription for busybox + By("creating a Subscription for busybox") subscriptionName := genName("sub-") cleanupSubscription := createSubscriptionForCatalog(crc, source.GetNamespace(), subscriptionName, source.GetName(), packageName, channelName, "", v1alpha1.ApprovalAutomatic) defer cleanupSubscription() - // Wait for the Subscription to succeed + By("waiting for the Subscription to succeed") subscription, err := fetchSubscription(crc, ns.GetName(), subscriptionName, subscriptionStateAtLatestChecker) Expect(err).ShouldNot(HaveOccurred()) Expect(subscription).ShouldNot(BeNil()) Expect(subscription.Status.InstalledCSV).To(Equal("busybox.v1.0.0")) - // Confirm that a subscription was created for busybox-dependency + By("confirming that a subscription was created for busybox-dependency") subscriptionList, err := crc.OperatorsV1alpha1().Subscriptions(source.GetNamespace()).List(context.Background(), metav1.ListOptions{}) Expect(err).ShouldNot(HaveOccurred()) dependencySubscriptionName := "" @@ -1062,13 +1061,13 @@ var _ = Describe("Starting CatalogSource e2e tests", func() { } Expect(dependencySubscriptionName).ToNot(BeEmpty()) - // Wait for the Subscription to succeed + By("waiting for the Subscription to succeed") subscription, err = fetchSubscription(crc, ns.GetName(), dependencySubscriptionName, subscriptionStateAtLatestChecker) Expect(err).ShouldNot(HaveOccurred()) Expect(subscription).ShouldNot(BeNil()) Expect(subscription.Status.InstalledCSV).To(Equal("busybox-dependency.v1.0.0")) - // Update the catalog image + By("updating the catalog image") Eventually(func() error { existingSource, err := crc.OperatorsV1alpha1().CatalogSources(source.GetNamespace()).Get(context.Background(), sourceName, metav1.GetOptions{}) if err != nil { @@ -1080,11 +1079,11 @@ var _ = Describe("Starting CatalogSource e2e tests", func() { return err }).Should(Succeed()) - // Wait for the CatalogSource to be ready + By("waiting for the CatalogSource to be ready") _, err = fetchCatalogSourceOnStatus(crc, source.GetName(), source.GetNamespace(), catalogSourceRegistryPodSynced) Expect(err).ToNot(HaveOccurred(), "catalog source did not become ready") - // Wait for the busybox v2 Subscription to succeed + By("waiting for the busybox v2 Subscription to succeed") subChecker := func(sub *v1alpha1.Subscription) bool { return sub.Status.InstalledCSV == "busybox.v2.0.0" } @@ -1092,12 +1091,12 @@ var _ = Describe("Starting CatalogSource e2e tests", func() { Expect(err).ShouldNot(HaveOccurred()) Expect(subscription).ShouldNot(BeNil()) - // Wait for busybox v2 csv to succeed and check the replaces field + By("waiting for busybox v2 csv to succeed and check the replaces field") csv, err := fetchCSV(crc, subscription.Status.CurrentCSV, subscription.GetNamespace(), csvSucceededChecker) Expect(err).ShouldNot(HaveOccurred()) Expect(csv.Spec.Replaces).To(Equal("busybox.v1.0.0")) - // Wait for the busybox-dependency v2 Subscription to succeed + By("waiting for the busybox-dependency v2 Subscription to succeed") subChecker = func(sub *v1alpha1.Subscription) bool { return sub.Status.InstalledCSV == "busybox-dependency.v2.0.0" } @@ -1105,7 +1104,7 @@ var _ = Describe("Starting CatalogSource e2e tests", func() { Expect(err).ShouldNot(HaveOccurred()) Expect(subscription).ShouldNot(BeNil()) - // Wait for busybox-dependency v2 csv to succeed and check the replaces field + By("waiting for busybox-dependency v2 csv to succeed and check the replaces field") csv, err = fetchCSV(crc, subscription.Status.CurrentCSV, subscription.GetNamespace(), csvSucceededChecker) Expect(err).ShouldNot(HaveOccurred()) Expect(csv.Spec.Replaces).To(Equal("busybox-dependency.v1.0.0")) @@ -1403,21 +1402,15 @@ var _ = Describe("Starting CatalogSource e2e tests", func() { Expect(c.Create(context.Background(), subscription)).To(BeNil()) }) - It("fails with a ResolutionFailed error condition, and a message that highlights the missing field in the CSV", func() { - - subscription, err := fetchSubscription(crc, subscription.GetNamespace(), subscription.GetName(), subscriptionHasInstallPlanChecker) - Expect(err).Should(BeNil()) - installPlanName := subscription.Status.Install.Name - - // ensure we wait for the installPlan to fail before moving forward then fetch the subscription again - _, err = fetchInstallPlan(GinkgoT(), crc, installPlanName, subscription.GetNamespace(), buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseFailed)) - Expect(err).To(BeNil()) - subscription, err = fetchSubscription(crc, subscription.GetNamespace(), subscription.GetName(), subscriptionHasInstallPlanChecker) - Expect(err).To(BeNil()) + It("fails with a BundleUnpackFailed error condition, and a message that highlights the missing field in the CSV", func() { + Eventually(func(g Gomega) string { + fetchedSubscription, err := crc.OperatorsV1alpha1().Subscriptions(ns.GetName()).Get(context.Background(), subscription.GetName(), metav1.GetOptions{}) + g.Expect(err).NotTo(HaveOccurred()) - // expect the message that API missing - failingCondition := subscription.Status.GetCondition(operatorsv1alpha1.SubscriptionInstallPlanFailed) - Expect(failingCondition.Message).To(ContainSubstring("missing APIVersion")) + // expect the message that API missing + failingCondition := fetchedSubscription.Status.GetCondition(v1alpha1.SubscriptionBundleUnpackFailed) + return failingCondition.Message + }).Should(ContainSubstring("missing APIVersion")) }) }) }) diff --git a/staging/operator-lifecycle-manager/test/e2e/ctx/installer_helm.go b/staging/operator-lifecycle-manager/test/e2e/ctx/installer_helm.go index 918995e2e5..3cc2a3d9fa 100644 --- a/staging/operator-lifecycle-manager/test/e2e/ctx/installer_helm.go +++ b/staging/operator-lifecycle-manager/test/e2e/ctx/installer_helm.go @@ -1,3 +1,4 @@ +//go:build helm // +build helm package ctx diff --git a/staging/operator-lifecycle-manager/test/e2e/ctx/installer_none.go b/staging/operator-lifecycle-manager/test/e2e/ctx/installer_none.go index e21484cd99..48375d6d1b 100644 --- a/staging/operator-lifecycle-manager/test/e2e/ctx/installer_none.go +++ b/staging/operator-lifecycle-manager/test/e2e/ctx/installer_none.go @@ -1,3 +1,4 @@ +//go:build !helm // +build !helm package ctx diff --git a/staging/operator-lifecycle-manager/test/e2e/ctx/provisioner_kind.go b/staging/operator-lifecycle-manager/test/e2e/ctx/provisioner_kind.go index 27f6d7c78c..6ac0ab976c 100644 --- a/staging/operator-lifecycle-manager/test/e2e/ctx/provisioner_kind.go +++ b/staging/operator-lifecycle-manager/test/e2e/ctx/provisioner_kind.go @@ -7,7 +7,6 @@ import ( "encoding/csv" "flag" "fmt" - "io/ioutil" "os" "path/filepath" "strings" @@ -78,7 +77,7 @@ func (kl kindLogAdapter) V(level log.Level) log.InfoLogger { } func Provision(ctx *TestContext) (func(), error) { - dir, err := ioutil.TempDir("", "kind.") + dir, err := os.MkdirTemp("", "kind.") if err != nil { return nil, fmt.Errorf("failed to create temporary directory: %s", err.Error()) } diff --git a/staging/operator-lifecycle-manager/test/e2e/ctx/provisioner_kubeconfig.go b/staging/operator-lifecycle-manager/test/e2e/ctx/provisioner_kubeconfig.go index fa3a6eec3a..1ce1980d71 100644 --- a/staging/operator-lifecycle-manager/test/e2e/ctx/provisioner_kubeconfig.go +++ b/staging/operator-lifecycle-manager/test/e2e/ctx/provisioner_kubeconfig.go @@ -1,3 +1,4 @@ +//go:build !kind // +build !kind package ctx diff --git a/staging/operator-lifecycle-manager/test/e2e/fail_forward_e2e_test.go b/staging/operator-lifecycle-manager/test/e2e/fail_forward_e2e_test.go index be4575a6b0..3df0768f61 100644 --- a/staging/operator-lifecycle-manager/test/e2e/fail_forward_e2e_test.go +++ b/staging/operator-lifecycle-manager/test/e2e/fail_forward_e2e_test.go @@ -9,6 +9,7 @@ import ( . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" operatorsv1 "github.com/operator-framework/api/pkg/operators/v1" @@ -27,6 +28,7 @@ var _ = Describe("Fail Forward Upgrades", func() { ns corev1.Namespace crclient versioned.Interface c client.Client + ogName string ) BeforeEach(func() { @@ -45,6 +47,7 @@ var _ = Describe("Fail Forward Upgrades", func() { }, } ns = SetupGeneratedTestNamespaceWithOperatorGroup(namespaceName, og) + ogName = og.GetName() }) AfterEach(func() { @@ -55,15 +58,21 @@ var _ = Describe("Fail Forward Upgrades", func() { When("an InstallPlan is reporting a failed state", func() { var ( - magicCatalog *MagicCatalog - catalogSourceName string - subscription *operatorsv1alpha1.Subscription + magicCatalog *MagicCatalog + catalogSourceName string + subscription *operatorsv1alpha1.Subscription + originalInstallPlanRef *corev1.ObjectReference + failedInstallPlanRef *corev1.ObjectReference ) BeforeEach(func() { + By("creating a service account with no permission") + saNameWithNoPerms := genName("scoped-sa-") + newServiceAccount(ctx.Ctx().KubeClient(), ns.GetName(), saNameWithNoPerms) + + By("deploying the testing catalog") provider, err := NewFileBasedFiledBasedCatalogProvider(filepath.Join(testdataDir, failForwardTestDataBaseDir, "example-operator.v0.1.0.yaml")) Expect(err).To(BeNil()) - catalogSourceName = genName("mc-ip-failed-") magicCatalog = NewMagicCatalog(c, ns.GetName(), catalogSourceName, provider) Expect(magicCatalog.DeployCatalog(context.Background())).To(BeNil()) @@ -87,16 +96,18 @@ var _ = Describe("Fail Forward Upgrades", func() { subscription, err := fetchSubscription(crclient, subscription.GetNamespace(), subscription.GetName(), subscriptionHasInstallPlanChecker) Expect(err).Should(BeNil()) - originalInstallPlanRef := subscription.Status.InstallPlanRef + originalInstallPlanRef = subscription.Status.InstallPlanRef By("waiting for the v0.1.0 CSV to report a succeeded phase") _, err = fetchCSV(crclient, subscription.Status.CurrentCSV, ns.GetName(), buildCSVConditionChecker(operatorsv1alpha1.CSVPhaseSucceeded)) Expect(err).ShouldNot(HaveOccurred()) - By("updating the catalog with a broken v0.2.0 bundle image") + By("updating the operator group to use the service account without required permissions to simulate InstallPlan failure") + Eventually(operatorGroupServiceAccountNameSetter(crclient, ns.GetName(), ogName, saNameWithNoPerms)).Should(Succeed()) + + By("updating the catalog with v0.2.0 bundle image") brokenProvider, err := NewFileBasedFiledBasedCatalogProvider(filepath.Join(testdataDir, failForwardTestDataBaseDir, "example-operator.v0.2.0.yaml")) Expect(err).To(BeNil()) - err = magicCatalog.UpdateCatalog(context.Background(), brokenProvider) Expect(err).To(BeNil()) @@ -104,91 +115,108 @@ var _ = Describe("Fail Forward Upgrades", func() { subscription, err = fetchSubscription(crclient, subscription.GetNamespace(), subscription.GetName(), subscriptionHasInstallPlanDifferentChecker(originalInstallPlanRef.Name)) Expect(err).Should(BeNil()) - By("patching the installplan to reduce the bundle unpacking timeout") - addBundleUnpackTimeoutIPAnnotation(context.Background(), c, objectRefToNamespacedName(subscription.Status.InstallPlanRef), "1s") - By("waiting for the bad InstallPlan to report a failed installation state") - ref := subscription.Status.InstallPlanRef - _, err = fetchInstallPlan(GinkgoT(), crclient, ref.Name, ref.Namespace, buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseFailed)) + failedInstallPlanRef = subscription.Status.InstallPlanRef + _, err = fetchInstallPlan(GinkgoT(), crclient, failedInstallPlanRef.Name, failedInstallPlanRef.Namespace, buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseFailed)) Expect(err).To(BeNil()) + By("updating the operator group remove service account without permissions") + Eventually(operatorGroupServiceAccountNameSetter(crclient, ns.GetName(), ogName, "")).Should(Succeed()) }) AfterEach(func() { By("removing the testing catalog resources") Expect(magicCatalog.UndeployCatalog(context.Background())).To(BeNil()) }) It("eventually reports a successful state when multiple bad versions are rolled forward", func() { - By("patching the catalog with another bad bundle version") - badProvider, err := NewFileBasedFiledBasedCatalogProvider(filepath.Join(testdataDir, "fail-forward/multiple-bad-versions", "example-operator.v0.2.1.yaml")) - Expect(err).To(BeNil()) + By("patching the OperatorGroup to reduce the bundle unpacking timeout") + addBundleUnpackTimeoutOGAnnotation(context.Background(), c, types.NamespacedName{Name: ogName, Namespace: ns.GetName()}, "1s") + By("patching the catalog with a bad bundle version") + badProvider, err := NewFileBasedFiledBasedCatalogProvider(filepath.Join(testdataDir, "fail-forward/multiple-bad-versions", "example-operator.v0.2.1-non-existent-tag.yaml")) + Expect(err).To(BeNil()) err = magicCatalog.UpdateCatalog(context.Background(), badProvider) Expect(err).To(BeNil()) - By("waiting for the subscription to have the example-operator.v0.2.1 status.updatedCSV") - subscription, err = fetchSubscription(crclient, subscription.GetNamespace(), subscription.GetName(), subscriptionHasCurrentCSV("example-operator.v0.2.1")) - Expect(err).Should(BeNil()) - - By("patching the installplan to reduce the bundle unpacking timeout") - addBundleUnpackTimeoutIPAnnotation(context.Background(), c, objectRefToNamespacedName(subscription.Status.InstallPlanRef), "1s") + By("waiting for the subscription to maintain the example-operator.v0.2.0 status.currentCSV") + Consistently(subscriptionCurrentCSVGetter(crclient, subscription.GetNamespace(), subscription.GetName())).Should(Equal("example-operator.v0.2.0")) - By("waiting for the bad v0.2.1 InstallPlan to report a failed installation state") - ref := subscription.Status.InstallPlanRef - _, err = fetchInstallPlan(GinkgoT(), crclient, ref.Name, ref.Namespace, buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseFailed)) - Expect(err).To(BeNil()) + By("patching the OperatorGroup to increase the bundle unpacking timeout") + addBundleUnpackTimeoutOGAnnotation(context.Background(), c, types.NamespacedName{Name: ogName, Namespace: ns.GetName()}, "5m") By("patching the catalog with a fixed version") fixedProvider, err := NewFileBasedFiledBasedCatalogProvider(filepath.Join(testdataDir, "fail-forward/multiple-bad-versions", "example-operator.v0.3.0.yaml")) Expect(err).To(BeNil()) - err = magicCatalog.UpdateCatalog(context.Background(), fixedProvider) Expect(err).To(BeNil()) - By("waiting for the subscription to have the example-operator.v0.3.0 status.updatedCSV") - subscription, err = fetchSubscription(crclient, subscription.GetNamespace(), subscription.GetName(), subscriptionHasCurrentCSV("example-operator.v0.3.0")) + By("waiting for the subscription to have the example-operator.v0.3.0 status.currentCSV") + _, err = fetchSubscription(crclient, subscription.GetNamespace(), subscription.GetName(), subscriptionHasCurrentCSV("example-operator.v0.3.0")) Expect(err).Should(BeNil()) + + By("verifying the subscription is referencing a new InstallPlan") + subscription, err = fetchSubscription(crclient, subscription.GetNamespace(), subscription.GetName(), subscriptionHasInstallPlanDifferentChecker(originalInstallPlanRef.Name)) + Expect(err).Should(BeNil()) + + By("waiting for the fixed v0.3.0 InstallPlan to report a successful state") + ref := subscription.Status.InstallPlanRef + _, err = fetchInstallPlan(GinkgoT(), crclient, ref.Name, ref.Namespace, buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseComplete)) + Expect(err).To(BeNil()) }) It("eventually reports a successful state when using skip ranges", func() { By("patching the catalog with a fixed version") fixedProvider, err := NewFileBasedFiledBasedCatalogProvider(filepath.Join(testdataDir, "fail-forward/skip-range", "example-operator.v0.3.0.yaml")) Expect(err).To(BeNil()) - err = magicCatalog.UpdateCatalog(context.Background(), fixedProvider) Expect(err).To(BeNil()) - By("waiting for the subscription to have the example-operator.v0.3.0 status.updatedCSV") - subscription, err = fetchSubscription(crclient, subscription.GetNamespace(), subscription.GetName(), subscriptionHasCurrentCSV("example-operator.v0.3.0")) + By("waiting for the subscription to have the example-operator.v0.3.0 status.currentCSV") + _, err = fetchSubscription(crclient, subscription.GetNamespace(), subscription.GetName(), subscriptionHasCurrentCSV("example-operator.v0.3.0")) + Expect(err).Should(BeNil()) + + By("verifying the subscription is referencing a new InstallPlan") + subscription, err = fetchSubscription(crclient, subscription.GetNamespace(), subscription.GetName(), subscriptionHasInstallPlanDifferentChecker(originalInstallPlanRef.Name)) Expect(err).Should(BeNil()) + + By("waiting for the fixed v0.3.0 InstallPlan to report a successful state") + ref := subscription.Status.InstallPlanRef + _, err = fetchInstallPlan(GinkgoT(), crclient, ref.Name, ref.Namespace, buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseComplete)) + Expect(err).To(BeNil()) }) It("eventually reports a successful state when using skips", func() { By("patching the catalog with a fixed version") fixedProvider, err := NewFileBasedFiledBasedCatalogProvider(filepath.Join(testdataDir, "fail-forward/skips", "example-operator.v0.3.0.yaml")) Expect(err).To(BeNil()) - err = magicCatalog.UpdateCatalog(context.Background(), fixedProvider) Expect(err).To(BeNil()) - By("waiting for the subscription to have the example-operator.v0.3.0 status.updatedCSV") - subscription, err = fetchSubscription(crclient, subscription.GetNamespace(), subscription.GetName(), subscriptionHasCurrentCSV("example-operator.v0.3.0")) + By("waiting for the subscription to have the example-operator.v0.3.0 status.currentCSV") + _, err = fetchSubscription(crclient, subscription.GetNamespace(), subscription.GetName(), subscriptionHasCurrentCSV("example-operator.v0.3.0")) Expect(err).Should(BeNil()) + + By("verifying the subscription is referencing a new InstallPlan") + subscription, err = fetchSubscription(crclient, subscription.GetNamespace(), subscription.GetName(), subscriptionHasInstallPlanDifferentChecker(originalInstallPlanRef.Name)) + Expect(err).Should(BeNil()) + + By("waiting for the fixed v0.3.0 InstallPlan to report a successful state") + ref := subscription.Status.InstallPlanRef + _, err = fetchInstallPlan(GinkgoT(), crclient, ref.Name, ref.Namespace, buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseComplete)) + Expect(err).To(BeNil()) }) It("eventually reports a failed state when using replaces", func() { By("patching the catalog with a fixed version") fixedProvider, err := NewFileBasedFiledBasedCatalogProvider(filepath.Join(testdataDir, "fail-forward/replaces", "example-operator.v0.3.0.yaml")) Expect(err).To(BeNil()) - err = magicCatalog.UpdateCatalog(context.Background(), fixedProvider) Expect(err).To(BeNil()) - By("waiting for the subscription to maintain the example-operator.v0.2.0 status.updatedCSV") - Consistently(func() string { - subscription, err := crclient.OperatorsV1alpha1().Subscriptions(subscription.GetNamespace()).Get(context.Background(), subscription.GetName(), metav1.GetOptions{}) - if err != nil || subscription == nil { - return "" - } - return subscription.Status.CurrentCSV - }).Should(Equal("example-operator.v0.2.0")) + By("waiting for the subscription to maintain the example-operator.v0.2.0 status.currentCSV") + Consistently(subscriptionCurrentCSVGetter(crclient, subscription.GetNamespace(), subscription.GetName())).Should(Equal("example-operator.v0.2.0")) + + By("verifying the subscription is referencing the same InstallPlan") + subscription, err = fetchSubscription(crclient, subscription.GetNamespace(), subscription.GetName(), subscriptionHasInstallPlanChecker) + Expect(err).Should(BeNil()) + Expect(subscription.Status.InstallPlanRef.Name).To(Equal(failedInstallPlanRef.Name)) }) }) When("a CSV resource is in a failed state", func() { @@ -200,9 +228,9 @@ var _ = Describe("Fail Forward Upgrades", func() { ) BeforeEach(func() { + By("deploying the testing catalog") provider, err := NewFileBasedFiledBasedCatalogProvider(filepath.Join(testdataDir, failForwardTestDataBaseDir, "example-operator.v0.1.0.yaml")) Expect(err).To(BeNil()) - catalogSourceName = genName("mc-csv-failed-") magicCatalog = NewMagicCatalog(c, ns.GetName(), catalogSourceName, provider) Expect(magicCatalog.DeployCatalog(context.Background())).To(BeNil()) @@ -231,7 +259,7 @@ var _ = Describe("Fail Forward Upgrades", func() { Expect(err).ShouldNot(HaveOccurred()) By("updating the catalog with a broken v0.2.0 csv") - brokenProvider, err := NewFileBasedFiledBasedCatalogProvider(filepath.Join(testdataDir, failForwardTestDataBaseDir, "example-operator.v0.2.0-2.yaml")) + brokenProvider, err := NewFileBasedFiledBasedCatalogProvider(filepath.Join(testdataDir, failForwardTestDataBaseDir, "example-operator.v0.2.0-invalid-csv.yaml")) Expect(err).To(BeNil()) err = magicCatalog.UpdateCatalog(context.Background(), brokenProvider) @@ -261,7 +289,7 @@ var _ = Describe("Fail Forward Upgrades", func() { err = magicCatalog.UpdateCatalog(context.Background(), fixedProvider) Expect(err).To(BeNil()) - By("waiting for the subscription to have the example-operator.v0.3.0 status.updatedCSV") + By("waiting for the subscription to have the example-operator.v0.3.0 status.currentCSV") subscription, err = fetchSubscription(crclient, subscription.GetNamespace(), subscription.GetName(), subscriptionHasCurrentCSV("example-operator.v0.3.0")) Expect(err).Should(BeNil()) }) @@ -274,7 +302,7 @@ var _ = Describe("Fail Forward Upgrades", func() { err = magicCatalog.UpdateCatalog(context.Background(), fixedProvider) Expect(err).To(BeNil()) - By("waiting for the subscription to have the example-operator.v0.3.0 status.updatedCSV") + By("waiting for the subscription to have the example-operator.v0.3.0 status.currentCSV") subscription, err = fetchSubscription(crclient, subscription.GetNamespace(), subscription.GetName(), subscriptionHasCurrentCSV("example-operator.v0.3.0")) Expect(err).Should(BeNil()) }) @@ -287,7 +315,7 @@ var _ = Describe("Fail Forward Upgrades", func() { err = magicCatalog.UpdateCatalog(context.Background(), fixedProvider) Expect(err).To(BeNil()) - By("waiting for the subscription to have the example-operator.v0.3.0 status.updatedCSV") + By("waiting for the subscription to have the example-operator.v0.3.0 status.currentCSV") subscription, err = fetchSubscription(crclient, subscription.GetNamespace(), subscription.GetName(), subscriptionHasCurrentCSV("example-operator.v0.3.0")) Expect(err).Should(BeNil()) }) diff --git a/staging/operator-lifecycle-manager/test/e2e/installplan_e2e_test.go b/staging/operator-lifecycle-manager/test/e2e/installplan_e2e_test.go index 244f01b2a3..92d2c4c3e0 100644 --- a/staging/operator-lifecycle-manager/test/e2e/installplan_e2e_test.go +++ b/staging/operator-lifecycle-manager/test/e2e/installplan_e2e_test.go @@ -41,7 +41,6 @@ import ( operatorsv1 "github.com/operator-framework/api/pkg/operators/v1" operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" "github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/clientset/versioned" - "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/bundle" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/operators/catalog" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry" "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac" @@ -3062,90 +3061,6 @@ var _ = Describe("Install Plan", func() { require.Equal(GinkgoT(), operatorsv1alpha1.InstallPlanPhaseComplete, fetchedInstallPlan.Status.Phase) }) - It("unpacks bundle image", func() { - ns, err := c.KubernetesInterface().CoreV1().Namespaces().Create(context.Background(), &corev1.Namespace{ - ObjectMeta: metav1.ObjectMeta{ - Name: genName("ns-"), - }, - }, metav1.CreateOptions{}) - require.NoError(GinkgoT(), err) - - og := &operatorsv1.OperatorGroup{} - og.SetName("og") - _, err = crc.OperatorsV1().OperatorGroups(ns.GetName()).Create(context.Background(), og, metav1.CreateOptions{}) - require.NoError(GinkgoT(), err) - - deleteOpts := &metav1.DeleteOptions{} - defer func() { - require.NoError(GinkgoT(), c.KubernetesInterface().CoreV1().Namespaces().Delete(context.Background(), ns.GetName(), *deleteOpts)) - }() - - catsrc := &operatorsv1alpha1.CatalogSource{ - ObjectMeta: metav1.ObjectMeta{ - Name: genName("kiali-"), - Namespace: ns.GetName(), - Labels: map[string]string{"olm.catalogSource": "kaili-catalog"}, - }, - Spec: operatorsv1alpha1.CatalogSourceSpec{ - Image: "quay.io/operator-framework/ci-index:latest", - SourceType: operatorsv1alpha1.SourceTypeGrpc, - GrpcPodConfig: &operatorsv1alpha1.GrpcPodConfig{ - SecurityContextConfig: operatorsv1alpha1.Restricted, - }, - }, - } - catsrc, err = crc.OperatorsV1alpha1().CatalogSources(catsrc.GetNamespace()).Create(context.Background(), catsrc, metav1.CreateOptions{}) - require.NoError(GinkgoT(), err) - defer func() { - Eventually(func() error { - return client.IgnoreNotFound(ctx.Ctx().Client().Delete(context.Background(), catsrc)) - }).Should(Succeed()) - }() - - // Wait for the CatalogSource to be ready - catsrc, err = fetchCatalogSourceOnStatus(crc, catsrc.GetName(), catsrc.GetNamespace(), catalogSourceRegistryPodSynced) - require.NoError(GinkgoT(), err) - - // Generate a Subscription - subName := genName("kiali-") - cleanUpSubscriptionFn := createSubscriptionForCatalog(crc, catsrc.GetNamespace(), subName, catsrc.GetName(), "kiali", stableChannel, "", operatorsv1alpha1.ApprovalAutomatic) - defer cleanUpSubscriptionFn() - - sub, err := fetchSubscription(crc, catsrc.GetNamespace(), subName, subscriptionHasInstallPlanChecker) - require.NoError(GinkgoT(), err) - - // Wait for the expected InstallPlan's execution to either fail or succeed - ipName := sub.Status.InstallPlanRef.Name - ip, err := waitForInstallPlan(crc, ipName, sub.GetNamespace(), buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseFailed, operatorsv1alpha1.InstallPlanPhaseComplete)) - require.NoError(GinkgoT(), err) - require.Equal(GinkgoT(), operatorsv1alpha1.InstallPlanPhaseComplete, ip.Status.Phase, "InstallPlan not complete") - - // Ensure the InstallPlan contains the steps resolved from the bundle image - operatorName := "kiali-operator" - expectedSteps := map[registry.ResourceKey]struct{}{ - {Name: operatorName, Kind: "ClusterServiceVersion"}: {}, - {Name: "kialis.kiali.io", Kind: "CustomResourceDefinition"}: {}, - {Name: "monitoringdashboards.monitoring.kiali.io", Kind: "CustomResourceDefinition"}: {}, - {Name: operatorName, Kind: "ServiceAccount"}: {}, - {Name: operatorName, Kind: "ClusterRole"}: {}, - {Name: operatorName, Kind: "ClusterRoleBinding"}: {}, - } - require.Lenf(GinkgoT(), ip.Status.Plan, len(expectedSteps), "number of expected steps does not match installed: %v", ip.Status.Plan) - - for _, step := range ip.Status.Plan { - key := registry.ResourceKey{ - Name: step.Resource.Name, - Kind: step.Resource.Kind, - } - for expected := range expectedSteps { - if strings.HasPrefix(key.Name, expected.Name) && key.Kind == expected.Kind { - delete(expectedSteps, expected) - } - } - } - require.Lenf(GinkgoT(), expectedSteps, 0, "Actual resource steps do not match expected: %#v", expectedSteps) - }) - // This It spec verifies that, in cases where there are multiple options to fulfil a dependency // across multiple catalogs, we only generate one installplan with one set of resolved resources. //issue: https://github.com/operator-framework/operator-lifecycle-manager/issues/2633 @@ -3402,218 +3317,6 @@ var _ = Describe("Install Plan", func() { }) }) - When("waiting on the bundle unpacking job", func() { - var ( - ns *corev1.Namespace - catsrcName string - ip *operatorsv1alpha1.InstallPlan - ) - - BeforeEach(func() { - ns = &corev1.Namespace{} - ns.SetName(genName("ns-")) - Eventually(func() error { - return ctx.Ctx().Client().Create(context.Background(), ns) - }, timeout, interval).Should(Succeed(), "could not create Namespace") - - // Create a dummy CatalogSource to bypass the bundle unpacker's check for a CatalogSource - catsrc := &operatorsv1alpha1.CatalogSource{ - ObjectMeta: metav1.ObjectMeta{ - Name: genName("dummy-catsrc-"), - Namespace: ns.GetName(), - }, - Spec: operatorsv1alpha1.CatalogSourceSpec{ - Image: "localhost:0/not/exist:catsrc", - SourceType: operatorsv1alpha1.SourceTypeGrpc, - GrpcPodConfig: &operatorsv1alpha1.GrpcPodConfig{ - SecurityContextConfig: operatorsv1alpha1.Restricted, - }, - }, - } - Eventually(func() error { - return ctx.Ctx().Client().Create(context.Background(), catsrc) - }, timeout, interval).Should(Succeed(), "could not create CatalogSource") - - catsrcName = catsrc.GetName() - - // Create the OperatorGroup - og := &operatorsv1.OperatorGroup{ - ObjectMeta: metav1.ObjectMeta{ - Name: "og", - Namespace: ns.GetName(), - }, - Spec: operatorsv1.OperatorGroupSpec{ - TargetNamespaces: []string{ns.GetName()}, - }, - } - Eventually(func() error { - return ctx.Ctx().Client().Create(context.Background(), og) - }, timeout, interval).Should(Succeed(), "could not create OperatorGroup") - - // Wait for the OperatorGroup to be synced so the InstallPlan doesn't have to be resynced due to an invalid OperatorGroup - Eventually( - func() ([]string, error) { - err := ctx.Ctx().Client().Get(context.Background(), client.ObjectKeyFromObject(og), og) - ctx.Ctx().Logf("Waiting for OperatorGroup(%v) to be synced with status.namespaces: %v", og.Name, og.Status.Namespaces) - return og.Status.Namespaces, err - }, - 1*time.Minute, - interval, - ).Should(ContainElement(ns.GetName())) - - ip = &operatorsv1alpha1.InstallPlan{ - ObjectMeta: metav1.ObjectMeta{ - Name: "ip", - Namespace: ns.GetName(), - }, - Spec: operatorsv1alpha1.InstallPlanSpec{ - ClusterServiceVersionNames: []string{"foobar"}, - Approval: operatorsv1alpha1.ApprovalAutomatic, - Approved: true, - }, - } - }) - - AfterEach(func() { - Eventually(func() error { - return client.IgnoreNotFound(ctx.Ctx().Client().Delete(context.Background(), ns)) - }, timeout, interval).Should(Succeed(), "could not delete Namespace") - Eventually(func() error { - return client.IgnoreNotFound(ctx.Ctx().Client().Delete(context.Background(), ip)) - }, timeout, interval).Should(Succeed(), "could not delete Namespace") - }) - - It("should show an error on the bundlelookup condition for a non-existent bundle image", func() { - // We wait for some time over the bundle unpack timeout (i.e ActiveDeadlineSeconds) so that the Job can eventually fail - // Since the default --bundle-unpack-timeout=10m, we override with a shorter timeout via the - // unpack timeout annotation on the InstallPlan - annotations := make(map[string]string) - annotations[bundle.BundleUnpackTimeoutAnnotationKey] = "1m" - ip.SetAnnotations(annotations) - - Eventually(func() error { - return ctx.Ctx().Client().Create(context.Background(), ip) - }, timeout, interval).Should(Succeed(), "could not create InstallPlan") - - now := metav1.Now() - // Create an InstallPlan status.bundleLookups.Path specified for a non-existent bundle image - ip.Status = operatorsv1alpha1.InstallPlanStatus{ - Phase: operatorsv1alpha1.InstallPlanPhaseInstalling, - CatalogSources: []string{}, - BundleLookups: []operatorsv1alpha1.BundleLookup{ - { - Path: "localhost:0/not/exist:v0.0.1", - Identifier: "foobar.v0.0.1", - CatalogSourceRef: &corev1.ObjectReference{ - Namespace: ns.GetName(), - Name: catsrcName, - }, - Conditions: []operatorsv1alpha1.BundleLookupCondition{ - { - Type: operatorsv1alpha1.BundleLookupPending, - Status: corev1.ConditionTrue, - Reason: "JobIncomplete", - Message: "unpack job not completed", - LastTransitionTime: &now, - }, - }, - }, - }, - } - - // The status gets ignored on create so we need to update it else the InstallPlan sync ignores - // InstallPlans without any steps or bundle lookups - Eventually(func() error { - return ctx.Ctx().Client().Status().Update(context.Background(), ip) - }, timeout, interval).Should(Succeed(), "could not update InstallPlan status") - - // The InstallPlan's status.bundleLookup.conditions should have a BundleLookupPending condition - // with the container status from unpack pod that mentions an image pull failure for the non-existent - // image, e.g ErrImagePull or ImagePullBackOff - Eventually( - func() (string, error) { - err := ctx.Ctx().Client().Get(context.Background(), client.ObjectKeyFromObject(ip), ip) - if err != nil { - return "", err - } - for _, bl := range ip.Status.BundleLookups { - for _, cond := range bl.Conditions { - if cond.Type != operatorsv1alpha1.BundleLookupPending { - continue - } - return cond.Message, nil - } - } - return "", fmt.Errorf("%s condition not found", operatorsv1alpha1.BundleLookupPending) - }, - 1*time.Minute, - interval, - ).Should(ContainSubstring("ErrImagePull")) - - waitFor := 1*time.Minute + 30*time.Second - // The InstallPlan should eventually fail due to the ActiveDeadlineSeconds limit - Eventually( - func() (*operatorsv1alpha1.InstallPlan, error) { - err := ctx.Ctx().Client().Get(context.Background(), client.ObjectKeyFromObject(ip), ip) - return ip, err - }, - waitFor, - interval, - ).Should(HavePhase(operatorsv1alpha1.InstallPlanPhaseFailed)) - }) - - It("should timeout and fail the InstallPlan for an invalid bundle image", func() { - Eventually(func() error { - return ctx.Ctx().Client().Create(context.Background(), ip) - }, timeout, interval).Should(Succeed(), "could not create InstallPlan") - - // The status gets ignored on create so we need to update it else the InstallPlan sync ignores - // InstallPlans without any steps or bundle lookups - // Create an InstallPlan status.bundleLookups.Path specified for an invalid bundle image - now := metav1.Now() - ip.Status = operatorsv1alpha1.InstallPlanStatus{ - Phase: operatorsv1alpha1.InstallPlanPhaseInstalling, - CatalogSources: []string{}, - BundleLookups: []operatorsv1alpha1.BundleLookup{ - { - Path: "alpine:3.13", - Identifier: "foobar.v0.0.1", - CatalogSourceRef: &corev1.ObjectReference{ - Namespace: ns.GetName(), - Name: catsrcName, - }, - Conditions: []operatorsv1alpha1.BundleLookupCondition{ - { - Type: operatorsv1alpha1.BundleLookupPending, - Status: corev1.ConditionTrue, - Reason: "JobIncomplete", - Message: "unpack job not completed", - LastTransitionTime: &now, - }, - }, - }, - }, - } - - Eventually(func() error { - return ctx.Ctx().Client().Status().Update(context.Background(), ip) - }, timeout, interval).Should(Succeed(), "could not update InstallPlan status") - - // The InstallPlan should fail after the unpack pod keeps failing and exceeds the job's - // BackoffLimit(set to 3), which for 4 failures is an exponential backoff (10s + 20s + 40s + 80s)= 2m30s - // so we wait a little over that. - Eventually( - func() (*operatorsv1alpha1.InstallPlan, error) { - err := ctx.Ctx().Client().Get(context.Background(), client.ObjectKeyFromObject(ip), ip) - return ip, err - }, - 5*time.Minute, - interval, - ).Should(HavePhase(operatorsv1alpha1.InstallPlanPhaseFailed)) - }) - - }) - It("compresses installplan step resource manifests to configmap references", func() { // Test ensures that all steps for index-based catalogs are references to configmaps. This avoids the problem // of installplans growing beyond the etcd size limit when manifests are written to the ip status. diff --git a/staging/operator-lifecycle-manager/test/e2e/magic_catalog.go b/staging/operator-lifecycle-manager/test/e2e/magic_catalog.go index 983340b083..c558506505 100644 --- a/staging/operator-lifecycle-manager/test/e2e/magic_catalog.go +++ b/staging/operator-lifecycle-manager/test/e2e/magic_catalog.go @@ -257,7 +257,7 @@ func (c *MagicCatalog) makeCatalogSource() *operatorsv1alpha1.CatalogSource { func (c *MagicCatalog) makeCatalogSourcePod() *corev1.Pod { const ( - image = "quay.io/operator-framework/upstream-opm-builder" + image = "quay.io/operator-framework/opm" readinessDelay int32 = 5 livenessDelay int32 = 10 volumeMountName string = "fbc-catalog" diff --git a/staging/operator-lifecycle-manager/test/e2e/setup_bare_test.go b/staging/operator-lifecycle-manager/test/e2e/setup_bare_test.go index 354e41cf68..f21ae71a98 100644 --- a/staging/operator-lifecycle-manager/test/e2e/setup_bare_test.go +++ b/staging/operator-lifecycle-manager/test/e2e/setup_bare_test.go @@ -7,7 +7,6 @@ import ( "context" "flag" "io" - "io/ioutil" "os" "strings" "testing" @@ -65,7 +64,7 @@ func TestMain(m *testing.M) { testNamespace = *namespace if testNamespace == "" { - testNamespaceBytes, err := ioutil.ReadFile("e2e.namespace") + testNamespaceBytes, err := os.ReadFile("e2e.namespace") if err != nil || testNamespaceBytes == nil { panic("no namespace set") } diff --git a/staging/operator-lifecycle-manager/test/e2e/split/main.go b/staging/operator-lifecycle-manager/test/e2e/split/main.go index 30745d0cab..1637fdb567 100644 --- a/staging/operator-lifecycle-manager/test/e2e/split/main.go +++ b/staging/operator-lifecycle-manager/test/e2e/split/main.go @@ -4,7 +4,6 @@ import ( "flag" "fmt" "io" - "io/ioutil" "log" "math" "os" @@ -106,7 +105,7 @@ func findDescribes(logger logrus.FieldLogger, dir string) ([]string, error) { return nil, err } for _, match := range matches { - b, err := ioutil.ReadFile(match) + b, err := os.ReadFile(match) if err != nil { return nil, err } diff --git a/staging/operator-lifecycle-manager/test/e2e/subscription_e2e_test.go b/staging/operator-lifecycle-manager/test/e2e/subscription_e2e_test.go index 766c0a5317..0c968997fb 100644 --- a/staging/operator-lifecycle-manager/test/e2e/subscription_e2e_test.go +++ b/staging/operator-lifecycle-manager/test/e2e/subscription_e2e_test.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "path/filepath" "reflect" "strings" "sync" @@ -22,11 +23,14 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/discovery" "sigs.k8s.io/controller-runtime/pkg/client" "github.com/operator-framework/api/pkg/lib/version" + operatorsv1 "github.com/operator-framework/api/pkg/operators/v1" + "github.com/operator-framework/api/pkg/operators/v1alpha1" operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" "github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/clientset/versioned" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/install" @@ -50,6 +54,7 @@ const ( var _ = Describe("Subscription", func() { var ( generatedNamespace corev1.Namespace + operatorGroup operatorsv1.OperatorGroup c operatorclient.ClientInterface crc versioned.Interface ) @@ -57,7 +62,15 @@ var _ = Describe("Subscription", func() { BeforeEach(func() { c = ctx.Ctx().KubeClient() crc = ctx.Ctx().OperatorClient() - generatedNamespace = SetupGeneratedTestNamespace(genName("subscription-e2e-")) + + nsName := genName("subscription-e2e-") + operatorGroup = operatorsv1.OperatorGroup{ + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("%s-operatorgroup", nsName), + Namespace: nsName, + }, + } + generatedNamespace = SetupGeneratedTestNamespaceWithOperatorGroup(nsName, operatorGroup) }) AfterEach(func() { @@ -2329,6 +2342,186 @@ var _ = Describe("Subscription", func() { ))) }) }) + + It("unpacks bundle image", func() { + catsrc := &operatorsv1alpha1.CatalogSource{ + ObjectMeta: metav1.ObjectMeta{ + Name: genName("kiali-"), + Namespace: generatedNamespace.GetName(), + Labels: map[string]string{"olm.catalogSource": "kaili-catalog"}, + }, + Spec: operatorsv1alpha1.CatalogSourceSpec{ + Image: "quay.io/operator-framework/ci-index:latest", + SourceType: operatorsv1alpha1.SourceTypeGrpc, + GrpcPodConfig: &operatorsv1alpha1.GrpcPodConfig{ + SecurityContextConfig: operatorsv1alpha1.Restricted, + }, + }, + } + catsrc, err := crc.OperatorsV1alpha1().CatalogSources(catsrc.GetNamespace()).Create(context.Background(), catsrc, metav1.CreateOptions{}) + require.NoError(GinkgoT(), err) + defer func() { + Eventually(func() error { + return client.IgnoreNotFound(ctx.Ctx().Client().Delete(context.Background(), catsrc)) + }).Should(Succeed()) + }() + + By("waiting for the CatalogSource to be ready") + catsrc, err = fetchCatalogSourceOnStatus(crc, catsrc.GetName(), catsrc.GetNamespace(), catalogSourceRegistryPodSynced) + require.NoError(GinkgoT(), err) + + By("generating a Subscription") + subName := genName("kiali-") + cleanUpSubscriptionFn := createSubscriptionForCatalog(crc, catsrc.GetNamespace(), subName, catsrc.GetName(), "kiali", stableChannel, "", operatorsv1alpha1.ApprovalAutomatic) + defer cleanUpSubscriptionFn() + + By("waiting for the InstallPlan to get created for the subscription") + sub, err := fetchSubscription(crc, catsrc.GetNamespace(), subName, subscriptionHasInstallPlanChecker) + require.NoError(GinkgoT(), err) + + By("waiting for the expected InstallPlan's execution to either fail or succeed") + ipName := sub.Status.InstallPlanRef.Name + ip, err := waitForInstallPlan(crc, ipName, sub.GetNamespace(), buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseFailed, operatorsv1alpha1.InstallPlanPhaseComplete)) + require.NoError(GinkgoT(), err) + require.Equal(GinkgoT(), operatorsv1alpha1.InstallPlanPhaseComplete, ip.Status.Phase, "InstallPlan not complete") + + By("ensuring the InstallPlan contains the steps resolved from the bundle image") + operatorName := "kiali-operator" + expectedSteps := map[registry.ResourceKey]struct{}{ + {Name: operatorName, Kind: "ClusterServiceVersion"}: {}, + {Name: "kialis.kiali.io", Kind: "CustomResourceDefinition"}: {}, + {Name: "monitoringdashboards.monitoring.kiali.io", Kind: "CustomResourceDefinition"}: {}, + {Name: operatorName, Kind: "ServiceAccount"}: {}, + {Name: operatorName, Kind: "ClusterRole"}: {}, + {Name: operatorName, Kind: "ClusterRoleBinding"}: {}, + } + require.Lenf(GinkgoT(), ip.Status.Plan, len(expectedSteps), "number of expected steps does not match installed: %v", ip.Status.Plan) + + for _, step := range ip.Status.Plan { + key := registry.ResourceKey{ + Name: step.Resource.Name, + Kind: step.Resource.Kind, + } + for expected := range expectedSteps { + if strings.HasPrefix(key.Name, expected.Name) && key.Kind == expected.Kind { + delete(expectedSteps, expected) + } + } + } + require.Lenf(GinkgoT(), expectedSteps, 0, "Actual resource steps do not match expected: %#v", expectedSteps) + }) + + When("unpacking bundle", func() { + var ( + magicCatalog *MagicCatalog + catalogSourceName string + subName string + ) + + BeforeEach(func() { + By("deploying the testing catalog") + provider, err := NewFileBasedFiledBasedCatalogProvider(filepath.Join(testdataDir, failForwardTestDataBaseDir, "example-operator.v0.1.0.yaml")) + Expect(err).To(BeNil()) + catalogSourceName = fmt.Sprintf("%s-catsrc", generatedNamespace.GetName()) + magicCatalog = NewMagicCatalog(ctx.Ctx().Client(), generatedNamespace.GetName(), catalogSourceName, provider) + Expect(magicCatalog.DeployCatalog(context.Background())).To(BeNil()) + + By("creating the testing subscription") + subName = fmt.Sprintf("%s-packagea-sub", generatedNamespace.GetName()) + createSubscriptionForCatalog(crc, generatedNamespace.GetName(), subName, catalogSourceName, "packageA", stableChannel, "", operatorsv1alpha1.ApprovalAutomatic) + + By("waiting until the subscription has an IP reference") + subscription, err := fetchSubscription(crc, generatedNamespace.GetName(), subName, subscriptionHasInstallPlanChecker) + Expect(err).Should(BeNil()) + + By("waiting for the v0.1.0 CSV to report a succeeded phase") + _, err = fetchCSV(crc, subscription.Status.CurrentCSV, generatedNamespace.GetName(), buildCSVConditionChecker(operatorsv1alpha1.CSVPhaseSucceeded)) + Expect(err).ShouldNot(HaveOccurred()) + }) + + It("should not report unpacking progress or errors after successfull unpacking", func() { + By("verifying that the subscription is not reporting unpacking progress") + Eventually( + func() (corev1.ConditionStatus, error) { + fetched, err := crc.OperatorsV1alpha1().Subscriptions(generatedNamespace.GetName()).Get(context.Background(), subName, metav1.GetOptions{}) + if err != nil { + return "", err + } + cond := fetched.Status.GetCondition(v1alpha1.SubscriptionBundleUnpacking) + return cond.Status, nil + }, + 5*time.Minute, + interval, + ).Should(Equal(corev1.ConditionFalse)) + + By("verifying that the subscription is not reporting unpacking errors") + Eventually( + func() (corev1.ConditionStatus, error) { + fetched, err := crc.OperatorsV1alpha1().Subscriptions(generatedNamespace.GetName()).Get(context.Background(), subName, metav1.GetOptions{}) + if err != nil { + return "", err + } + cond := fetched.Status.GetCondition(v1alpha1.SubscriptionBundleUnpackFailed) + return cond.Status, nil + }, + 5*time.Minute, + interval, + ).Should(Equal(corev1.ConditionUnknown)) + }) + + Context("with bundle which OLM will fail to unpack", func() { + BeforeEach(func() { + By("patching the OperatorGroup to reduce the bundle unpacking timeout") + ogNN := types.NamespacedName{Name: operatorGroup.GetName(), Namespace: generatedNamespace.GetName()} + addBundleUnpackTimeoutOGAnnotation(context.Background(), ctx.Ctx().Client(), ogNN, "1s") + + By("updating the catalog with a broken v0.2.0 bundle image") + brokenProvider, err := NewFileBasedFiledBasedCatalogProvider(filepath.Join(testdataDir, failForwardTestDataBaseDir, "example-operator.v0.2.0-non-existent-tag.yaml")) + Expect(err).To(BeNil()) + err = magicCatalog.UpdateCatalog(context.Background(), brokenProvider) + Expect(err).To(BeNil()) + }) + + It("should expose a condition indicating failure to unpack", func() { + By("verifying that the subscription is reporting bundle unpack failure condition") + Eventually( + func() (string, error) { + fetched, err := crc.OperatorsV1alpha1().Subscriptions(generatedNamespace.GetName()).Get(context.Background(), subName, metav1.GetOptions{}) + if err != nil { + return "", err + } + cond := fetched.Status.GetCondition(v1alpha1.SubscriptionBundleUnpackFailed) + if cond.Status != corev1.ConditionTrue || cond.Reason != "BundleUnpackFailed" { + return "", fmt.Errorf("%s condition not found", v1alpha1.SubscriptionBundleUnpackFailed) + } + + return cond.Message, nil + }, + 5*time.Minute, + interval, + ).Should(ContainSubstring("bundle unpacking failed. Reason: DeadlineExceeded")) + + By("waiting for the subscription to maintain the example-operator.v0.1.0 status.currentCSV") + Consistently(subscriptionCurrentCSVGetter(crc, generatedNamespace.GetName(), subName)).Should(Equal("example-operator.v0.1.0")) + }) + + It("should be able to recover when catalog gets updated with a fixed version", func() { + By("patching the OperatorGroup to reduce the bundle unpacking timeout") + ogNN := types.NamespacedName{Name: operatorGroup.GetName(), Namespace: generatedNamespace.GetName()} + addBundleUnpackTimeoutOGAnnotation(context.Background(), ctx.Ctx().Client(), ogNN, "5m") + + By("updating the catalog with a fixed v0.2.0 bundle image") + brokenProvider, err := NewFileBasedFiledBasedCatalogProvider(filepath.Join(testdataDir, failForwardTestDataBaseDir, "example-operator.v0.2.0.yaml")) + Expect(err).To(BeNil()) + err = magicCatalog.UpdateCatalog(context.Background(), brokenProvider) + Expect(err).To(BeNil()) + + By("waiting for the subscription to have v0.2.0 installed") + _, err = fetchSubscription(crc, generatedNamespace.GetName(), subName, subscriptionHasCurrentCSV("example-operator.v0.2.0")) + Expect(err).Should(BeNil()) + }) + }) + }) }) const ( @@ -2951,3 +3144,25 @@ func updateCatSrcPriority(crClient versioned.Interface, namespace string, catsrc _, err := crClient.OperatorsV1alpha1().CatalogSources(namespace).Update(context.Background(), catsrc, metav1.UpdateOptions{}) Expect(err).Should(BeNil()) } + +func subscriptionCurrentCSVGetter(crclient versioned.Interface, namespace, subName string) func() string { + return func() string { + subscription, err := crclient.OperatorsV1alpha1().Subscriptions(namespace).Get(context.Background(), subName, metav1.GetOptions{}) + if err != nil || subscription == nil { + return "" + } + return subscription.Status.CurrentCSV + } +} + +func operatorGroupServiceAccountNameSetter(crclient versioned.Interface, namespace, name, saName string) func() error { + return func() error { + toUpdate, err := crclient.OperatorsV1().OperatorGroups(namespace).Get(context.Background(), name, metav1.GetOptions{}) + if err != nil { + return err + } + toUpdate.Spec.ServiceAccountName = saName + _, err = crclient.OperatorsV1().OperatorGroups(namespace).Update(context.Background(), toUpdate, metav1.UpdateOptions{}) + return err + } +} diff --git a/staging/operator-lifecycle-manager/test/e2e/testdata/fail-forward/base/example-operator.v0.2.0-2.yaml b/staging/operator-lifecycle-manager/test/e2e/testdata/fail-forward/base/example-operator.v0.2.0-invalid-csv.yaml similarity index 100% rename from staging/operator-lifecycle-manager/test/e2e/testdata/fail-forward/base/example-operator.v0.2.0-2.yaml rename to staging/operator-lifecycle-manager/test/e2e/testdata/fail-forward/base/example-operator.v0.2.0-invalid-csv.yaml diff --git a/staging/operator-lifecycle-manager/test/e2e/testdata/fail-forward/base/example-operator.v0.2.0-non-existent-tag.yaml b/staging/operator-lifecycle-manager/test/e2e/testdata/fail-forward/base/example-operator.v0.2.0-non-existent-tag.yaml new file mode 100644 index 0000000000..555242e536 --- /dev/null +++ b/staging/operator-lifecycle-manager/test/e2e/testdata/fail-forward/base/example-operator.v0.2.0-non-existent-tag.yaml @@ -0,0 +1,26 @@ +--- +schema: olm.package +name: packageA +defaultChannel: stable +--- +schema: olm.channel +package: packageA +name: stable +entries: + - name: example-operator.v0.2.0 + replaces: example-operator.v0.1.0 +--- +schema: olm.bundle +name: example-operator.v0.2.0 +package: packageA +image: quay.io/olmtest/example-operator-bundle:non-existent-tag +properties: + - type: olm.gvk + value: + group: example.com + kind: TestA + version: v1alpha1 + - type: olm.package + value: + packageName: packageA + version: 1.0.1 diff --git a/staging/operator-lifecycle-manager/test/e2e/testdata/fail-forward/base/example-operator.v0.2.0.yaml b/staging/operator-lifecycle-manager/test/e2e/testdata/fail-forward/base/example-operator.v0.2.0.yaml index 555242e536..3058376dd5 100644 --- a/staging/operator-lifecycle-manager/test/e2e/testdata/fail-forward/base/example-operator.v0.2.0.yaml +++ b/staging/operator-lifecycle-manager/test/e2e/testdata/fail-forward/base/example-operator.v0.2.0.yaml @@ -13,7 +13,7 @@ entries: schema: olm.bundle name: example-operator.v0.2.0 package: packageA -image: quay.io/olmtest/example-operator-bundle:non-existent-tag +image: quay.io/olmtest/example-operator-bundle:0.2.0 properties: - type: olm.gvk value: diff --git a/staging/operator-lifecycle-manager/test/e2e/testdata/fail-forward/multiple-bad-versions/example-operator.v0.2.1.yaml b/staging/operator-lifecycle-manager/test/e2e/testdata/fail-forward/multiple-bad-versions/example-operator.v0.2.1-non-existent-tag.yaml similarity index 100% rename from staging/operator-lifecycle-manager/test/e2e/testdata/fail-forward/multiple-bad-versions/example-operator.v0.2.1.yaml rename to staging/operator-lifecycle-manager/test/e2e/testdata/fail-forward/multiple-bad-versions/example-operator.v0.2.1-non-existent-tag.yaml diff --git a/staging/operator-lifecycle-manager/test/e2e/util.go b/staging/operator-lifecycle-manager/test/e2e/util.go index 9b0943aaab..1764292bf6 100644 --- a/staging/operator-lifecycle-manager/test/e2e/util.go +++ b/staging/operator-lifecycle-manager/test/e2e/util.go @@ -89,21 +89,20 @@ func objectRefToNamespacedName(ip *corev1.ObjectReference) types.NamespacedName } } -// addBundleUnpackTimeoutIPAnnotation is a helper function that's responsible for -// adding the "operatorframework.io/bundle-unpack-timeout" annotation to an InstallPlan -// resource. This allows you to have more control over the bundle unpack timeout when interacting -// with test InstallPlan resources. -func addBundleUnpackTimeoutIPAnnotation(ctx context.Context, c k8scontrollerclient.Client, ipNN types.NamespacedName, timeout string) { +// addBundleUnpackTimeoutOGAnnotation is a helper function that's responsible for +// adding the "operatorframework.io/bundle-unpack-timeout" annotation to an OperatorGroup +// resource. +func addBundleUnpackTimeoutOGAnnotation(ctx context.Context, c k8scontrollerclient.Client, ogNN types.NamespacedName, timeout string) { Eventually(func() error { - ip := &operatorsv1alpha1.InstallPlan{} - if err := c.Get(ctx, ipNN, ip); err != nil { + og := &operatorsv1.OperatorGroup{} + if err := c.Get(ctx, ogNN, og); err != nil { return err } - annotations := make(map[string]string) + annotations := og.GetAnnotations() annotations[bundle.BundleUnpackTimeoutAnnotationKey] = timeout - ip.SetAnnotations(annotations) + og.SetAnnotations(annotations) - return c.Update(ctx, ip) + return c.Update(ctx, og) }).Should(Succeed()) } diff --git a/staging/operator-lifecycle-manager/test/e2e/util/resource_queue.go b/staging/operator-lifecycle-manager/test/e2e/util/resource_queue.go index eabe5db77a..03eca665f6 100644 --- a/staging/operator-lifecycle-manager/test/e2e/util/resource_queue.go +++ b/staging/operator-lifecycle-manager/test/e2e/util/resource_queue.go @@ -79,7 +79,7 @@ func (q *ResourceQueue) DequeueHead() (k8scontrollerclient.Object, bool) { func (q *ResourceQueue) DequeueTail() (k8scontrollerclient.Object, bool) { q.lock.Lock() defer q.lock.Unlock() - + if len(q.queue) == 0 { return nil, false } diff --git a/staging/operator-lifecycle-manager/util/cpb/main.go b/staging/operator-lifecycle-manager/util/cpb/main.go index ae9912bf97..5b1769bb37 100644 --- a/staging/operator-lifecycle-manager/util/cpb/main.go +++ b/staging/operator-lifecycle-manager/util/cpb/main.go @@ -2,7 +2,6 @@ package main import ( "fmt" - "io/ioutil" "os" "path/filepath" @@ -118,7 +117,7 @@ func getMetadata() (m *metadata, err error) { m.annotationsFile = path // Unmarshal metadata - content, err := ioutil.ReadFile(path) + content, err := os.ReadFile(path) if err != nil { return fmt.Errorf("couldn't get content of annotations.yaml file: %s", path) } diff --git a/staging/operator-registry/.github/workflows/build.yaml b/staging/operator-registry/.github/workflows/build.yaml index 80a591d3cd..345c8e9b64 100644 --- a/staging/operator-registry/.github/workflows/build.yaml +++ b/staging/operator-registry/.github/workflows/build.yaml @@ -12,8 +12,8 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-go@v2 + - uses: actions/checkout@v3 + - uses: actions/setup-go@v4 with: - go-version: '~1.18' + go-version-file: "go.mod" - run: make build diff --git a/staging/operator-registry/.github/workflows/codecov.sh b/staging/operator-registry/.github/workflows/codecov.sh deleted file mode 100755 index 914a56277f..0000000000 --- a/staging/operator-registry/.github/workflows/codecov.sh +++ /dev/null @@ -1,1884 +0,0 @@ -#!/usr/bin/env bash - -# Apache License Version 2.0, January 2004 -# https://github.com/codecov/codecov-bash/blob/master/LICENSE - -set -e +o pipefail - -VERSION="1.0.1" - -codecov_flags=( ) -url="https://codecov.io" -env="$CODECOV_ENV" -service="" -token="" -search_in="" -# shellcheck disable=SC2153 -flags="$CODECOV_FLAGS" -exit_with=0 -curlargs="" -curlawsargs="" -dump="0" -clean="0" -curl_s="-s" -name="$CODECOV_NAME" -include_cov="" -exclude_cov="" -ddp="$HOME/Library/Developer/Xcode/DerivedData" -xp="" -files="" -save_to="" -direct_file_upload="" -cacert="$CODECOV_CA_BUNDLE" -gcov_ignore="-not -path './bower_components/**' -not -path './node_modules/**' -not -path './vendor/**'" -gcov_include="" - -ft_gcov="1" -ft_coveragepy="1" -ft_fix="1" -ft_search="1" -ft_s3="1" -ft_network="1" -ft_xcodellvm="1" -ft_xcodeplist="0" -ft_gcovout="1" -ft_html="0" -ft_yaml="0" - -_git_root=$(git rev-parse --show-toplevel 2>/dev/null || hg root 2>/dev/null || echo "$PWD") -git_root="$_git_root" -remote_addr="" -if [ "$git_root" = "$PWD" ]; -then - git_root="." -fi - -branch_o="" -build_o="" -commit_o="" -pr_o="" -prefix_o="" -network_filter_o="" -search_in_o="" -slug_o="" -tag_o="" -url_o="" -git_ls_files_recurse_submodules_o="" -package="bash" - -commit="$VCS_COMMIT_ID" -branch="$VCS_BRANCH_NAME" -pr="$VCS_PULL_REQUEST" -slug="$VCS_SLUG" -tag="$VCS_TAG" -build_url="$CI_BUILD_URL" -build="$CI_BUILD_ID" -job="$CI_JOB_ID" - -beta_xcode_partials="" - -proj_root="$git_root" -gcov_exe="gcov" -gcov_arg="" - -b="\033[0;36m" -g="\033[0;32m" -r="\033[0;31m" -e="\033[0;90m" -y="\033[0;33m" -x="\033[0m" - -show_help() { -cat << EOF - - Codecov Bash $VERSION - - Global report uploading tool for Codecov - Documentation at https://docs.codecov.io/docs - Contribute at https://github.com/codecov/codecov-bash - - - -h Display this help and exit - -f FILE Target file(s) to upload - - -f "path/to/file" only upload this file - skips searching unless provided patterns below - - -f '!*.bar' ignore all files at pattern *.bar - -f '*.foo' include all files at pattern *.foo - Must use single quotes. - This is non-exclusive, use -s "*.foo" to match specific paths. - - -s DIR Directory to search for coverage reports. - Already searches project root and artifact folders. - -t TOKEN Set the private repository token - (option) set environment variable CODECOV_TOKEN=:uuid - - -t @/path/to/token_file - -t uuid - - -n NAME Custom defined name of the upload. Visible in Codecov UI - - -e ENV Specify environment variables to be included with this build - Also accepting environment variables: CODECOV_ENV=VAR,VAR2 - - -e VAR,VAR2 - - -k prefix Prefix filepaths to help resolve path fixing - - -i prefix Only include files in the network with a certain prefix. Useful for upload-specific path fixing - - -X feature Toggle functionalities - - -X gcov Disable gcov - -X coveragepy Disable python coverage - -X fix Disable report fixing - -X search Disable searching for reports - -X xcode Disable xcode processing - -X network Disable uploading the file network - -X gcovout Disable gcov output - -X html Enable coverage for HTML files - -X recursesubs Enable recurse submodules in git projects when searching for source files - -X yaml Enable coverage for YAML files - - -N The commit SHA of the parent for which you are uploading coverage. If not present, - the parent will be determined using the API of your repository provider. - When using the repository provider's API, the parent is determined via finding - the closest ancestor to the commit. - - -R root dir Used when not in git/hg project to identify project root directory - -F flag Flag the upload to group coverage metrics - - -F unittests This upload is only unittests - -F integration This upload is only integration tests - -F ui,chrome This upload is Chrome - UI tests - - -c Move discovered coverage reports to the trash - -z FILE Upload specified file directly to Codecov and bypass all report generation. - This is inteded to be used only with a pre-formatted Codecov report and is not - expected to work under any other circumstances. - -Z Exit with 1 if not successful. Default will Exit with 0 - - -- xcode -- - -D Custom Derived Data Path for Coverage.profdata and gcov processing - Default '~/Library/Developer/Xcode/DerivedData' - -J Specify packages to build coverage. Uploader will only build these packages. - This can significantly reduces time to build coverage reports. - - -J 'MyAppName' Will match "MyAppName" and "MyAppNameTests" - -J '^ExampleApp$' Will match only "ExampleApp" not "ExampleAppTests" - - -- gcov -- - -g GLOB Paths to ignore during gcov gathering - -G GLOB Paths to include during gcov gathering - -p dir Project root directory - Also used when preparing gcov - -x gcovexe gcov executable to run. Defaults to 'gcov' - -a gcovargs extra arguments to pass to gcov - - -- Override CI Environment Variables -- - These variables are automatically detected by popular CI providers - - -B branch Specify the branch name - -C sha Specify the commit sha - -P pr Specify the pull request number - -b build Specify the build number - -T tag Specify the git tag - - -- Enterprise -- - -u URL Set the target url for Enterprise customers - Not required when retrieving the bash uploader from your CCE - (option) Set environment variable CODECOV_URL=https://my-hosted-codecov.com - -r SLUG owner/repo slug used instead of the private repo token in Enterprise - (option) set environment variable CODECOV_SLUG=:owner/:repo - (option) set in your codecov.yml "codecov.slug" - -S PATH File path to your cacert.pem file used to verify ssl with Codecov Enterprise (optional) - (option) Set environment variable: CODECOV_CA_BUNDLE="/path/to/ca.pem" - -U curlargs Extra curl arguments to communicate with Codecov. e.g., -U "--proxy http://http-proxy" - -A curlargs Extra curl arguments to communicate with AWS. - - -- Debugging -- - -d Don't upload, but dump upload file to stdout - -q PATH Write upload file to path - -K Remove color from the output - -v Verbose mode - -EOF -} - - -say() { - echo -e "$1" -} - - -urlencode() { - echo "$1" | curl -Gso /dev/null -w "%{url_effective}" --data-urlencode @- "" | cut -c 3- | sed -e 's/%0A//' -} - -swiftcov() { - _dir=$(dirname "$1" | sed 's/\(Build\).*/\1/g') - for _type in app framework xctest - do - find "$_dir" -name "*.$_type" | while read -r f - do - _proj=${f##*/} - _proj=${_proj%."$_type"} - if [ "$2" = "" ] || [ "$(echo "$_proj" | grep -i "$2")" != "" ]; - then - say " $g+$x Building reports for $_proj $_type" - dest=$([ -f "$f/$_proj" ] && echo "$f/$_proj" || echo "$f/Contents/MacOS/$_proj") - # shellcheck disable=SC2001 - _proj_name=$(echo "$_proj" | sed -e 's/[[:space:]]//g') - # shellcheck disable=SC2086 - xcrun llvm-cov show $beta_xcode_partials -instr-profile "$1" "$dest" > "$_proj_name.$_type.coverage.txt" \ - || say " ${r}x>${x} llvm-cov failed to produce results for $dest" - fi - done - done -} - - -# Credits to: https://gist.github.com/pkuczynski/8665367 -parse_yaml() { - local prefix=$2 - local s='[[:space:]]*' w='[a-zA-Z0-9_]*' - local fs - fs=$(echo @|tr @ '\034') - sed -ne "s|^\($s\)\($w\)$s:$s\"\(.*\)\"$s\$|\1$fs\2$fs\3|p" \ - -e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" "$1" | - awk -F"$fs" '{ - indent = length($1)/2; - vname[indent] = $2; - for (i in vname) {if (i > indent) {delete vname[i]}} - if (length($3) > 0) { - vn=""; if (indent > 0) {vn=(vn)(vname[0])("_")} - printf("%s%s%s=\"%s\"\n", "'"$prefix"'",vn, $2, $3); - } - }' -} - -if [ $# != 0 ]; -then - while getopts "a:A:b:B:cC:dD:e:f:F:g:G:hi:J:k:Kn:p:P:Q:q:r:R:s:S:t:T:u:U:vx:X:Zz:N:-" o - do - codecov_flags+=( "$o" ) - case "$o" in - "-") - echo -e "${r}Long options are not supported${x}" - exit 2 - ;; - "?") - ;; - "N") - parent=$OPTARG - ;; - "a") - gcov_arg=$OPTARG - ;; - "A") - curlawsargs="$OPTARG" - ;; - "b") - build_o="$OPTARG" - ;; - "B") - branch_o="$OPTARG" - ;; - "c") - clean="1" - ;; - "C") - commit_o="$OPTARG" - ;; - "d") - dump="1" - ;; - "D") - ddp="$OPTARG" - ;; - "e") - env="$env,$OPTARG" - ;; - "f") - if [ "${OPTARG::1}" = "!" ]; - then - exclude_cov="$exclude_cov -not -path '${OPTARG:1}'" - - elif [[ "$OPTARG" = *"*"* ]]; - then - include_cov="$include_cov -or -path '$OPTARG'" - - else - ft_search=0 - if [ "$files" = "" ]; - then - files="$OPTARG" - else - files="$files -$OPTARG" - fi - fi - ;; - "F") - if [ "$flags" = "" ]; - then - flags="$OPTARG" - else - flags="$flags,$OPTARG" - fi - ;; - "g") - gcov_ignore="$gcov_ignore -not -path '$OPTARG'" - ;; - "G") - gcov_include="$gcov_include -path '$OPTARG'" - ;; - "h") - show_help - exit 0; - ;; - "i") - network_filter_o="$OPTARG" - ;; - "J") - ft_xcodellvm="1" - ft_xcodeplist="0" - if [ "$xp" = "" ]; - then - xp="$OPTARG" - else - xp="$xp\|$OPTARG" - fi - ;; - "k") - prefix_o=$(echo "$OPTARG" | sed -e 's:^/*::' -e 's:/*$::') - ;; - "K") - b="" - g="" - r="" - e="" - x="" - ;; - "n") - name="$OPTARG" - ;; - "p") - proj_root="$OPTARG" - ;; - "P") - pr_o="$OPTARG" - ;; - "Q") - # this is only meant for Codecov packages to overwrite - package="$OPTARG" - ;; - "q") - save_to="$OPTARG" - ;; - "r") - slug_o="$OPTARG" - ;; - "R") - git_root="$OPTARG" - ;; - "s") - if [ "$search_in_o" = "" ]; - then - search_in_o="$OPTARG" - else - search_in_o="$search_in_o $OPTARG" - fi - ;; - "S") - # shellcheck disable=SC2089 - cacert="--cacert \"$OPTARG\"" - ;; - "t") - if [ "${OPTARG::1}" = "@" ]; - then - token=$(< "${OPTARG:1}" tr -d ' \n') - else - token="$OPTARG" - fi - ;; - "T") - tag_o="$OPTARG" - ;; - "u") - url_o=$(echo "$OPTARG" | sed -e 's/\/$//') - ;; - "U") - curlargs="$OPTARG" - ;; - "v") - set -x - curl_s="" - ;; - "x") - gcov_exe=$OPTARG - ;; - "X") - if [ "$OPTARG" = "gcov" ]; - then - ft_gcov="0" - elif [ "$OPTARG" = "coveragepy" ] || [ "$OPTARG" = "py" ]; - then - ft_coveragepy="0" - elif [ "$OPTARG" = "gcovout" ]; - then - ft_gcovout="0" - elif [ "$OPTARG" = "xcodellvm" ]; - then - ft_xcodellvm="1" - ft_xcodeplist="0" - elif [ "$OPTARG" = "fix" ] || [ "$OPTARG" = "fixes" ]; - then - ft_fix="0" - elif [ "$OPTARG" = "xcode" ]; - then - ft_xcodellvm="0" - ft_xcodeplist="0" - elif [ "$OPTARG" = "search" ]; - then - ft_search="0" - elif [ "$OPTARG" = "xcodepartials" ]; - then - beta_xcode_partials="-use-color" - elif [ "$OPTARG" = "network" ]; - then - ft_network="0" - elif [ "$OPTARG" = "s3" ]; - then - ft_s3="0" - elif [ "$OPTARG" = "html" ]; - then - ft_html="1" - elif [ "$OPTARG" = "recursesubs" ]; - then - git_ls_files_recurse_submodules_o="--recurse-submodules" - elif [ "$OPTARG" = "yaml" ]; - then - ft_yaml="1" - fi - ;; - "Z") - exit_with=1 - ;; - "z") - direct_file_upload="$OPTARG" - ft_gcov="0" - ft_coveragepy="0" - ft_fix="0" - ft_search="0" - ft_network="0" - ft_xcodellvm="0" - ft_gcovout="0" - include_cov="" - ;; - *) - echo -e "${r}Unexpected flag not supported${x}" - ;; - esac - done -fi - -say " - _____ _ - / ____| | | -| | ___ __| | ___ ___ _____ __ -| | / _ \\ / _\` |/ _ \\/ __/ _ \\ \\ / / -| |___| (_) | (_| | __/ (_| (_) \\ V / - \\_____\\___/ \\__,_|\\___|\\___\\___/ \\_/ - Bash-$VERSION - -" - -# check for installed tools -# git/hg -if [ "$direct_file_upload" = "" ]; -then - if [ -x "$(command -v git)" ]; - then - say "$b==>$x $(git --version) found" - else - say "$y==>$x git not installed, testing for mercurial" - if [ -x "$(command -v hg)" ]; - then - say "$b==>$x $(hg --version) found" - else - say "$r==>$x git nor mercurial are installed. Uploader may fail or have unintended consequences" - fi - fi -fi -# curl -if [ -x "$(command -v curl)" ]; -then - say "$b==>$x $(curl --version)" -else - say "$r==>$x curl not installed. Exiting." - exit ${exit_with}; -fi - -search_in="$proj_root" - -#shellcheck disable=SC2154 -if [ "$JENKINS_URL" != "" ]; -then - say "$e==>$x Jenkins CI detected." - # https://wiki.jenkins-ci.org/display/JENKINS/Building+a+software+project - # https://wiki.jenkins-ci.org/display/JENKINS/GitHub+pull+request+builder+plugin#GitHubpullrequestbuilderplugin-EnvironmentVariables - service="jenkins" - - # shellcheck disable=SC2154 - if [ "$ghprbSourceBranch" != "" ]; - then - branch="$ghprbSourceBranch" - elif [ "$GIT_BRANCH" != "" ]; - then - branch="$GIT_BRANCH" - elif [ "$BRANCH_NAME" != "" ]; - then - branch="$BRANCH_NAME" - fi - - # shellcheck disable=SC2154 - if [ "$ghprbActualCommit" != "" ]; - then - commit="$ghprbActualCommit" - elif [ "$GIT_COMMIT" != "" ]; - then - commit="$GIT_COMMIT" - fi - - # shellcheck disable=SC2154 - if [ "$ghprbPullId" != "" ]; - then - pr="$ghprbPullId" - elif [ "$CHANGE_ID" != "" ]; - then - pr="$CHANGE_ID" - fi - - build="$BUILD_NUMBER" - # shellcheck disable=SC2153 - build_url=$(urlencode "$BUILD_URL") - -elif [ "$CI" = "true" ] && [ "$TRAVIS" = "true" ] && [ "$SHIPPABLE" != "true" ]; -then - say "$e==>$x Travis CI detected." - # https://docs.travis-ci.com/user/environment-variables/ - service="travis" - commit="${TRAVIS_PULL_REQUEST_SHA:-$TRAVIS_COMMIT}" - build="$TRAVIS_JOB_NUMBER" - pr="$TRAVIS_PULL_REQUEST" - job="$TRAVIS_JOB_ID" - slug="$TRAVIS_REPO_SLUG" - env="$env,TRAVIS_OS_NAME" - tag="$TRAVIS_TAG" - if [ "$TRAVIS_BRANCH" != "$TRAVIS_TAG" ]; - then - branch="${TRAVIS_PULL_REQUEST_BRANCH:-$TRAVIS_BRANCH}" - fi - - language=$(compgen -A variable | grep "^TRAVIS_.*_VERSION$" | head -1) - if [ "$language" != "" ]; - then - env="$env,${!language}" - fi - -elif [ "$CODEBUILD_CI" = "true" ]; -then - say "$e==>$x AWS Codebuild detected." - # https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-env-vars.html - service="codebuild" - commit="$CODEBUILD_RESOLVED_SOURCE_VERSION" - build="$CODEBUILD_BUILD_ID" - branch="$(echo "$CODEBUILD_WEBHOOK_HEAD_REF" | sed 's/^refs\/heads\///')" - if [ "${CODEBUILD_SOURCE_VERSION/pr}" = "$CODEBUILD_SOURCE_VERSION" ] ; then - pr="false" - else - pr="$(echo "$CODEBUILD_SOURCE_VERSION" | sed 's/^pr\///')" - fi - job="$CODEBUILD_BUILD_ID" - slug="$(echo "$CODEBUILD_SOURCE_REPO_URL" | sed 's/^.*:\/\/[^\/]*\///' | sed 's/\.git$//')" - -elif [ "$CI" = "true" ] && [ "$CI_NAME" = "codeship" ]; -then - say "$e==>$x Codeship CI detected." - # https://www.codeship.io/documentation/continuous-integration/set-environment-variables/ - service="codeship" - branch="$CI_BRANCH" - build="$CI_BUILD_NUMBER" - build_url=$(urlencode "$CI_BUILD_URL") - commit="$CI_COMMIT_ID" - -elif [ -n "$CF_BUILD_URL" ] && [ -n "$CF_BUILD_ID" ]; -then - say "$e==>$x Codefresh CI detected." - # https://docs.codefresh.io/v1.0/docs/variables - service="codefresh" - branch="$CF_BRANCH" - build="$CF_BUILD_ID" - build_url=$(urlencode "$CF_BUILD_URL") - commit="$CF_REVISION" - -elif [ "$TEAMCITY_VERSION" != "" ]; -then - say "$e==>$x TeamCity CI detected." - # https://confluence.jetbrains.com/display/TCD8/Predefined+Build+Parameters - # https://confluence.jetbrains.com/plugins/servlet/mobile#content/view/74847298 - if [ "$TEAMCITY_BUILD_BRANCH" = '' ]; - then - echo " Teamcity does not automatically make build parameters available as environment variables." - echo " Add the following environment parameters to the build configuration" - echo " env.TEAMCITY_BUILD_BRANCH = %teamcity.build.branch%" - echo " env.TEAMCITY_BUILD_ID = %teamcity.build.id%" - echo " env.TEAMCITY_BUILD_URL = %teamcity.serverUrl%/viewLog.html?buildId=%teamcity.build.id%" - echo " env.TEAMCITY_BUILD_COMMIT = %system.build.vcs.number%" - echo " env.TEAMCITY_BUILD_REPOSITORY = %vcsroot..url%" - fi - service="teamcity" - branch="$TEAMCITY_BUILD_BRANCH" - build="$TEAMCITY_BUILD_ID" - build_url=$(urlencode "$TEAMCITY_BUILD_URL") - if [ "$TEAMCITY_BUILD_COMMIT" != "" ]; - then - commit="$TEAMCITY_BUILD_COMMIT" - else - commit="$BUILD_VCS_NUMBER" - fi - remote_addr="$TEAMCITY_BUILD_REPOSITORY" - -elif [ "$CI" = "true" ] && [ "$CIRCLECI" = "true" ]; -then - say "$e==>$x Circle CI detected." - # https://circleci.com/docs/environment-variables - service="circleci" - branch="$CIRCLE_BRANCH" - build="$CIRCLE_BUILD_NUM" - job="$CIRCLE_NODE_INDEX" - if [ "$CIRCLE_PROJECT_REPONAME" != "" ]; - then - slug="$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME" - else - # git@github.com:owner/repo.git - slug="${CIRCLE_REPOSITORY_URL##*:}" - # owner/repo.git - slug="${slug%%.git}" - fi - pr="${CIRCLE_PULL_REQUEST##*/}" - commit="$CIRCLE_SHA1" - search_in="$search_in $CIRCLE_ARTIFACTS $CIRCLE_TEST_REPORTS" - -elif [ "$BUDDYBUILD_BRANCH" != "" ]; -then - say "$e==>$x buddybuild detected" - # http://docs.buddybuild.com/v6/docs/custom-prebuild-and-postbuild-steps - service="buddybuild" - branch="$BUDDYBUILD_BRANCH" - build="$BUDDYBUILD_BUILD_NUMBER" - build_url="https://dashboard.buddybuild.com/public/apps/$BUDDYBUILD_APP_ID/build/$BUDDYBUILD_BUILD_ID" - # BUDDYBUILD_TRIGGERED_BY - if [ "$ddp" = "$HOME/Library/Developer/Xcode/DerivedData" ]; - then - ddp="/private/tmp/sandbox/${BUDDYBUILD_APP_ID}/bbtest" - fi - -elif [ "${bamboo_planRepository_revision}" != "" ]; -then - say "$e==>$x Bamboo detected" - # https://confluence.atlassian.com/bamboo/bamboo-variables-289277087.html#Bamboovariables-Build-specificvariables - service="bamboo" - commit="${bamboo_planRepository_revision}" - # shellcheck disable=SC2154 - branch="${bamboo_planRepository_branch}" - # shellcheck disable=SC2154 - build="${bamboo_buildNumber}" - # shellcheck disable=SC2154 - build_url="${bamboo_buildResultsUrl}" - # shellcheck disable=SC2154 - remote_addr="${bamboo_planRepository_repositoryUrl}" - -elif [ "$CI" = "true" ] && [ "$BITRISE_IO" = "true" ]; -then - # http://devcenter.bitrise.io/faq/available-environment-variables/ - say "$e==>$x Bitrise CI detected." - service="bitrise" - branch="$BITRISE_GIT_BRANCH" - build="$BITRISE_BUILD_NUMBER" - build_url=$(urlencode "$BITRISE_BUILD_URL") - pr="$BITRISE_PULL_REQUEST" - if [ "$GIT_CLONE_COMMIT_HASH" != "" ]; - then - commit="$GIT_CLONE_COMMIT_HASH" - fi - -elif [ "$CI" = "true" ] && [ "$SEMAPHORE" = "true" ]; -then - say "$e==>$x Semaphore CI detected." -# https://docs.semaphoreci.com/ci-cd-environment/environment-variables/#semaphore-related - service="semaphore" - branch="$SEMAPHORE_GIT_BRANCH" - build="$SEMAPHORE_WORKFLOW_NUMBER" - job="$SEMAPHORE_JOB_ID" - pr="$PULL_REQUEST_NUMBER" - slug="$SEMAPHORE_REPO_SLUG" - commit="$REVISION" - env="$env,SEMAPHORE_TRIGGER_SOURCE" - -elif [ "$CI" = "true" ] && [ "$BUILDKITE" = "true" ]; -then - say "$e==>$x Buildkite CI detected." - # https://buildkite.com/docs/guides/environment-variables - service="buildkite" - branch="$BUILDKITE_BRANCH" - build="$BUILDKITE_BUILD_NUMBER" - job="$BUILDKITE_JOB_ID" - build_url=$(urlencode "$BUILDKITE_BUILD_URL") - slug="$BUILDKITE_PROJECT_SLUG" - commit="$BUILDKITE_COMMIT" - if [[ "$BUILDKITE_PULL_REQUEST" != "false" ]]; then - pr="$BUILDKITE_PULL_REQUEST" - fi - tag="$BUILDKITE_TAG" - -elif [ "$CI" = "drone" ] || [ "$DRONE" = "true" ]; -then - say "$e==>$x Drone CI detected." - # http://docs.drone.io/env.html - # drone commits are not full shas - service="drone.io" - branch="$DRONE_BRANCH" - build="$DRONE_BUILD_NUMBER" - build_url=$(urlencode "${DRONE_BUILD_LINK}") - pr="$DRONE_PULL_REQUEST" - job="$DRONE_JOB_NUMBER" - tag="$DRONE_TAG" - -elif [ "$CI" = "true" ] && [ "$HEROKU_TEST_RUN_BRANCH" != "" ]; -then - say "$e==>$x Heroku CI detected." - # https://devcenter.heroku.com/articles/heroku-ci#environment-variables - service="heroku" - branch="$HEROKU_TEST_RUN_BRANCH" - build="$HEROKU_TEST_RUN_ID" - commit="$HEROKU_TEST_RUN_COMMIT_VERSION" - -elif [[ "$CI" = "true" || "$CI" = "True" ]] && [[ "$APPVEYOR" = "true" || "$APPVEYOR" = "True" ]]; -then - say "$e==>$x Appveyor CI detected." - # http://www.appveyor.com/docs/environment-variables - service="appveyor" - branch="$APPVEYOR_REPO_BRANCH" - build=$(urlencode "$APPVEYOR_JOB_ID") - pr="$APPVEYOR_PULL_REQUEST_NUMBER" - job="$APPVEYOR_ACCOUNT_NAME%2F$APPVEYOR_PROJECT_SLUG%2F$APPVEYOR_BUILD_VERSION" - slug="$APPVEYOR_REPO_NAME" - commit="$APPVEYOR_REPO_COMMIT" - build_url=$(urlencode "${APPVEYOR_URL}/project/${APPVEYOR_REPO_NAME}/builds/$APPVEYOR_BUILD_ID/job/${APPVEYOR_JOB_ID}") - -elif [ "$CI" = "true" ] && [ "$WERCKER_GIT_BRANCH" != "" ]; -then - say "$e==>$x Wercker CI detected." - # http://devcenter.wercker.com/articles/steps/variables.html - service="wercker" - branch="$WERCKER_GIT_BRANCH" - build="$WERCKER_MAIN_PIPELINE_STARTED" - slug="$WERCKER_GIT_OWNER/$WERCKER_GIT_REPOSITORY" - commit="$WERCKER_GIT_COMMIT" - -elif [ "$CI" = "true" ] && [ "$MAGNUM" = "true" ]; -then - say "$e==>$x Magnum CI detected." - # https://magnum-ci.com/docs/environment - service="magnum" - branch="$CI_BRANCH" - build="$CI_BUILD_NUMBER" - commit="$CI_COMMIT" - -elif [ "$SHIPPABLE" = "true" ]; -then - say "$e==>$x Shippable CI detected." - # http://docs.shippable.com/ci_configure/ - service="shippable" - # shellcheck disable=SC2153 - branch=$([ "$HEAD_BRANCH" != "" ] && echo "$HEAD_BRANCH" || echo "$BRANCH") - build="$BUILD_NUMBER" - build_url=$(urlencode "$BUILD_URL") - pr="$PULL_REQUEST" - slug="$REPO_FULL_NAME" - # shellcheck disable=SC2153 - commit="$COMMIT" - -elif [ "$TDDIUM" = "true" ]; -then - say "Solano CI detected." - # http://docs.solanolabs.com/Setup/tddium-set-environment-variables/ - service="solano" - commit="$TDDIUM_CURRENT_COMMIT" - branch="$TDDIUM_CURRENT_BRANCH" - build="$TDDIUM_TID" - pr="$TDDIUM_PR_ID" - -elif [ "$GREENHOUSE" = "true" ]; -then - say "$e==>$x Greenhouse CI detected." - # http://docs.greenhouseci.com/docs/environment-variables-files - service="greenhouse" - branch="$GREENHOUSE_BRANCH" - build="$GREENHOUSE_BUILD_NUMBER" - build_url=$(urlencode "$GREENHOUSE_BUILD_URL") - pr="$GREENHOUSE_PULL_REQUEST" - commit="$GREENHOUSE_COMMIT" - search_in="$search_in $GREENHOUSE_EXPORT_DIR" - -elif [ "$GITLAB_CI" != "" ]; -then - say "$e==>$x GitLab CI detected." - # http://doc.gitlab.com/ce/ci/variables/README.html - service="gitlab" - branch="${CI_BUILD_REF_NAME:-$CI_COMMIT_REF_NAME}" - build="${CI_BUILD_ID:-$CI_JOB_ID}" - remote_addr="${CI_BUILD_REPO:-$CI_REPOSITORY_URL}" - commit="${CI_BUILD_REF:-$CI_COMMIT_SHA}" - slug="${CI_PROJECT_PATH}" - -elif [ "$GITHUB_ACTIONS" != "" ]; -then - say "$e==>$x GitHub Actions detected." - say " Env vars used:" - say " -> GITHUB_ACTIONS: ${GITHUB_ACTIONS}" - say " -> GITHUB_HEAD_REF: ${GITHUB_HEAD_REF}" - say " -> GITHUB_REF: ${GITHUB_REF}" - say " -> GITHUB_REPOSITORY: ${GITHUB_REPOSITORY}" - say " -> GITHUB_RUN_ID: ${GITHUB_RUN_ID}" - say " -> GITHUB_SHA: ${GITHUB_SHA}" - say " -> GITHUB_WORKFLOW: ${GITHUB_WORKFLOW}" - - # https://github.com/features/actions - service="github-actions" - - # https://help.github.com/en/articles/virtual-environments-for-github-actions#environment-variables - branch="${GITHUB_REF#refs/heads/}" - if [ "$GITHUB_HEAD_REF" != "" ]; - then - # PR refs are in the format: refs/pull/7/merge - pr="${GITHUB_REF#refs/pull/}" - pr="${pr%/merge}" - branch="${GITHUB_HEAD_REF}" - fi - commit="${GITHUB_SHA}" - slug="${GITHUB_REPOSITORY}" - build="${GITHUB_RUN_ID}" - build_url=$(urlencode "http://github.com/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}") - job="$(urlencode "${GITHUB_WORKFLOW}")" - - # actions/checkout runs in detached HEAD - mc= - if [ -n "$pr" ] && [ "$pr" != false ] && [ "$commit_o" == "" ]; - then - mc=$(git show --no-patch --format="%P" 2>/dev/null || echo "") - - if [[ "$mc" =~ ^[a-z0-9]{40}[[:space:]][a-z0-9]{40}$ ]]; - then - mc=$(echo "$mc" | cut -d' ' -f2) - say " Fixing merge commit SHA $commit -> $mc" - commit=$mc - elif [[ "$mc" = "" ]]; - then - say "$r-> Issue detecting commit SHA. Please run actions/checkout with fetch-depth > 1 or set to 0$x" - fi - fi - -elif [ "$SYSTEM_TEAMFOUNDATIONSERVERURI" != "" ]; -then - say "$e==>$x Azure Pipelines detected." - # https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=vsts - # https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&viewFallbackFrom=vsts&tabs=yaml - service="azure_pipelines" - commit="$BUILD_SOURCEVERSION" - build="$BUILD_BUILDNUMBER" - if [ -z "$SYSTEM_PULLREQUEST_PULLREQUESTNUMBER" ]; - then - pr="$SYSTEM_PULLREQUEST_PULLREQUESTID" - else - pr="$SYSTEM_PULLREQUEST_PULLREQUESTNUMBER" - fi - project="${SYSTEM_TEAMPROJECT}" - server_uri="${SYSTEM_TEAMFOUNDATIONSERVERURI}" - job="${BUILD_BUILDID}" - branch="${BUILD_SOURCEBRANCH#"refs/heads/"}" - build_url=$(urlencode "${SYSTEM_TEAMFOUNDATIONSERVERURI}${SYSTEM_TEAMPROJECT}/_build/results?buildId=${BUILD_BUILDID}") - - # azure/pipelines runs in detached HEAD - mc= - if [ -n "$pr" ] && [ "$pr" != false ]; - then - mc=$(git show --no-patch --format="%P" 2>/dev/null || echo "") - - if [[ "$mc" =~ ^[a-z0-9]{40}[[:space:]][a-z0-9]{40}$ ]]; - then - mc=$(echo "$mc" | cut -d' ' -f2) - say " Fixing merge commit SHA $commit -> $mc" - commit=$mc - fi - fi - -elif [ "$CI" = "true" ] && [ "$BITBUCKET_BUILD_NUMBER" != "" ]; -then - say "$e==>$x Bitbucket detected." - # https://confluence.atlassian.com/bitbucket/variables-in-pipelines-794502608.html - service="bitbucket" - branch="$BITBUCKET_BRANCH" - build="$BITBUCKET_BUILD_NUMBER" - slug="$BITBUCKET_REPO_OWNER/$BITBUCKET_REPO_SLUG" - job="$BITBUCKET_BUILD_NUMBER" - pr="$BITBUCKET_PR_ID" - commit="$BITBUCKET_COMMIT" - # See https://jira.atlassian.com/browse/BCLOUD-19393 - if [ "${#commit}" = 12 ]; - then - commit=$(git rev-parse "$BITBUCKET_COMMIT") - fi - -elif [ "$CI" = "true" ] && [ "$BUDDY" = "true" ]; -then - say "$e==>$x Buddy CI detected." - # https://buddy.works/docs/pipelines/environment-variables - service="buddy" - branch="$BUDDY_EXECUTION_BRANCH" - build="$BUDDY_EXECUTION_ID" - build_url=$(urlencode "$BUDDY_EXECUTION_URL") - commit="$BUDDY_EXECUTION_REVISION" - pr="$BUDDY_EXECUTION_PULL_REQUEST_NO" - tag="$BUDDY_EXECUTION_TAG" - slug="$BUDDY_REPO_SLUG" - -elif [ "$CIRRUS_CI" != "" ]; -then - say "$e==>$x Cirrus CI detected." - # https://cirrus-ci.org/guide/writing-tasks/#environment-variables - service="cirrus-ci" - slug="$CIRRUS_REPO_FULL_NAME" - branch="$CIRRUS_BRANCH" - pr="$CIRRUS_PR" - commit="$CIRRUS_CHANGE_IN_REPO" - build="$CIRRUS_BUILD_ID" - build_url=$(urlencode "https://cirrus-ci.com/task/$CIRRUS_TASK_ID") - job="$CIRRUS_TASK_NAME" - -elif [ "$DOCKER_REPO" != "" ]; -then - say "$e==>$x Docker detected." - # https://docs.docker.com/docker-cloud/builds/advanced/ - service="docker" - branch="$SOURCE_BRANCH" - commit="$SOURCE_COMMIT" - slug="$DOCKER_REPO" - tag="$CACHE_TAG" - env="$env,IMAGE_NAME" - -else - say "${r}x>${x} No CI provider detected." - say " Testing inside Docker? ${b}http://docs.codecov.io/docs/testing-with-docker${x}" - say " Testing with Tox? ${b}https://docs.codecov.io/docs/python#section-testing-with-tox${x}" - -fi - -say " ${e}project root:${x} $git_root" - -# find branch, commit, repo from git command -if [ "$GIT_BRANCH" != "" ]; -then - branch="$GIT_BRANCH" - -elif [ "$branch" = "" ]; -then - branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || hg branch 2>/dev/null || echo "") - if [ "$branch" = "HEAD" ]; - then - branch="" - fi -fi - -if [ "$commit_o" = "" ]; -then - if [ "$GIT_COMMIT" != "" ]; - then - commit="$GIT_COMMIT" - elif [ "$commit" = "" ]; - then - commit=$(git log -1 --format="%H" 2>/dev/null || hg id -i --debug 2>/dev/null | tr -d '+' || echo "") - fi -else - commit="$commit_o" -fi - -if [ "$CODECOV_TOKEN" != "" ] && [ "$token" = "" ]; -then - say "${e}-->${x} token set from env" - token="$CODECOV_TOKEN" -fi - -if [ "$CODECOV_URL" != "" ] && [ "$url_o" = "" ]; -then - say "${e}-->${x} url set from env" - url_o=$(echo "$CODECOV_URL" | sed -e 's/\/$//') -fi - -if [ "$CODECOV_SLUG" != "" ]; -then - say "${e}-->${x} slug set from env" - slug_o="$CODECOV_SLUG" - -elif [ "$slug" = "" ]; -then - if [ "$remote_addr" = "" ]; - then - remote_addr=$(git config --get remote.origin.url || hg paths default || echo '') - fi - if [ "$remote_addr" != "" ]; - then - if echo "$remote_addr" | grep -q "//"; then - # https - slug=$(echo "$remote_addr" | cut -d / -f 4,5 | sed -e 's/\.git$//') - else - # ssh - slug=$(echo "$remote_addr" | cut -d : -f 2 | sed -e 's/\.git$//') - fi - fi - if [ "$slug" = "/" ]; - then - slug="" - fi -fi - -yaml=$(cd "$git_root" && \ - git ls-files "*codecov.yml" "*codecov.yaml" 2>/dev/null \ - || hg locate "*codecov.yml" "*codecov.yaml" 2>/dev/null \ - || cd "$proj_root" && find . -maxdepth 1 -type f -name '*codecov.y*ml' 2>/dev/null \ - || echo '') -yaml=$(echo "$yaml" | head -1) - -if [ "$yaml" != "" ]; -then - say " ${e}Yaml found at:${x} $yaml" - if [[ "$yaml" != /* ]]; then - # relative path for yaml file given, assume relative to the repo root - yaml="$git_root/$yaml" - fi - config=$(parse_yaml "$yaml" || echo '') - - # TODO validate the yaml here - - if [ "$(echo "$config" | grep 'codecov_token="')" != "" ] && [ "$token" = "" ]; - then - say "${e}-->${x} token set from yaml" - token="$(echo "$config" | grep 'codecov_token="' | sed -e 's/codecov_token="//' | sed -e 's/"\.*//')" - fi - - if [ "$(echo "$config" | grep 'codecov_url="')" != "" ] && [ "$url_o" = "" ]; - then - say "${e}-->${x} url set from yaml" - url_o="$(echo "$config" | grep 'codecov_url="' | sed -e 's/codecov_url="//' | sed -e 's/"\.*//')" - fi - - if [ "$(echo "$config" | grep 'codecov_slug="')" != "" ] && [ "$slug_o" = "" ]; - then - say "${e}-->${x} slug set from yaml" - slug_o="$(echo "$config" | grep 'codecov_slug="' | sed -e 's/codecov_slug="//' | sed -e 's/"\.*//')" - fi -else - say " ${g}Yaml not found, that's ok! Learn more at${x} ${b}http://docs.codecov.io/docs/codecov-yaml${x}" -fi - -if [ "$branch_o" != "" ]; -then - branch=$(urlencode "$branch_o") -else - branch=$(urlencode "$branch") -fi - -if [ "$slug_o" = "" ]; -then - urlencoded_slug=$(urlencode "$slug") -else - urlencoded_slug=$(urlencode "$slug_o") -fi - -query="branch=$branch\ - &commit=$commit\ - &build=$([ "$build_o" = "" ] && echo "$build" || echo "$build_o")\ - &build_url=$build_url\ - &name=$(urlencode "$name")\ - &tag=$([ "$tag_o" = "" ] && echo "$tag" || echo "$tag_o")\ - &slug=$urlencoded_slug\ - &service=$service\ - &flags=$flags\ - &pr=$([ "$pr_o" = "" ] && echo "${pr##\#}" || echo "${pr_o##\#}")\ - &job=$job\ - &cmd_args=$(IFS=,; echo "${codecov_flags[*]}")" - -if [ -n "$project" ] && [ -n "$server_uri" ]; -then - query=$(echo "$query&project=$project&server_uri=$server_uri" | tr -d ' ') -fi - -if [ "$parent" != "" ]; -then - query=$(echo "parent=$parent&$query" | tr -d ' ') -fi - -if [ "$ft_search" = "1" ]; -then - # detect bower comoponents location - bower_components="bower_components" - bower_rc=$(cd "$git_root" && cat .bowerrc 2>/dev/null || echo "") - if [ "$bower_rc" != "" ]; - then - bower_components=$(echo "$bower_rc" | tr -d '\n' | grep '"directory"' | cut -d'"' -f4 | sed -e 's/\/$//') - if [ "$bower_components" = "" ]; - then - bower_components="bower_components" - fi - fi - - # Swift Coverage - if [ "$ft_xcodellvm" = "1" ] && [ -d "$ddp" ]; - then - say "${e}==>${x} Processing Xcode reports via llvm-cov" - say " DerivedData folder: $ddp" - profdata_files=$(find "$ddp" -name '*.profdata' 2>/dev/null || echo '') - if [ "$profdata_files" != "" ]; - then - # xcode via profdata - if [ "$xp" = "" ]; - then - # xp=$(xcodebuild -showBuildSettings 2>/dev/null | grep -i "^\s*PRODUCT_NAME" | sed -e 's/.*= \(.*\)/\1/') - # say " ${e}->${x} Speed up Xcode processing by adding ${e}-J '$xp'${x}" - say " ${g}hint${x} Speed up Swift processing by using use ${g}-J 'AppName'${x} (regexp accepted)" - say " ${g}hint${x} This will remove Pods/ from your report. Also ${b}https://docs.codecov.io/docs/ignoring-paths${x}" - fi - while read -r profdata; - do - if [ "$profdata" != "" ]; - then - swiftcov "$profdata" "$xp" - fi - done <<< "$profdata_files" - else - say " ${e}->${x} No Swift coverage found" - fi - - # Obj-C Gcov Coverage - if [ "$ft_gcov" = "1" ]; - then - say " ${e}->${x} Running $gcov_exe for Obj-C" - if [ "$ft_gcovout" = "0" ]; - then - # suppress gcov output - bash -c "find $ddp -type f -name '*.gcda' $gcov_include $gcov_ignore -exec $gcov_exe -p $gcov_arg {} +" >/dev/null 2>&1 || true - else - bash -c "find $ddp -type f -name '*.gcda' $gcov_include $gcov_ignore -exec $gcov_exe -p $gcov_arg {} +" || true - fi - fi - fi - - if [ "$ft_xcodeplist" = "1" ] && [ -d "$ddp" ]; - then - say "${e}==>${x} Processing Xcode plists" - plists_files=$(find "$ddp" -name '*.xccoverage' 2>/dev/null || echo '') - if [ "$plists_files" != "" ]; - then - while read -r plist; - do - if [ "$plist" != "" ]; - then - say " ${g}Found${x} plist file at $plist" - plutil -convert xml1 -o "$(basename "$plist").plist" -- "$plist" - fi - done <<< "$plists_files" - fi - fi - - # Gcov Coverage - if [ "$ft_gcov" = "1" ]; - then - say "${e}==>${x} Running $gcov_exe in $proj_root ${e}(disable via -X gcov)${x}" - if [ "$ft_gcovout" = "0" ]; - then - # suppress gcov output - bash -c "find $proj_root -type f -name '*.gcno' $gcov_include $gcov_ignore -exec $gcov_exe -pb $gcov_arg {} +" >/dev/null 2>&1 || true - else - bash -c "find $proj_root -type f -name '*.gcno' $gcov_include $gcov_ignore -exec $gcov_exe -pb $gcov_arg {} +" || true - fi - else - say "${e}==>${x} gcov disabled" - fi - - # Python Coverage - if [ "$ft_coveragepy" = "1" ]; - then - if [ ! -f coverage.xml ]; - then - if command -v coverage >/dev/null 2>&1; - then - say "${e}==>${x} Python coveragepy exists ${e}disable via -X coveragepy${x}" - - dotcoverage=$(find "$git_root" -name '.coverage' -or -name '.coverage.*' | head -1 || echo '') - if [ "$dotcoverage" != "" ]; - then - cd "$(dirname "$dotcoverage")" - if [ ! -f .coverage ]; - then - say " ${e}->${x} Running coverage combine" - coverage combine -a - fi - say " ${e}->${x} Running coverage xml" - if [ "$(coverage xml -i)" != "No data to report." ]; - then - files="$files -$PWD/coverage.xml" - else - say " ${r}No data to report.${x}" - fi - cd "$proj_root" - else - say " ${r}No .coverage file found.${x}" - fi - else - say "${e}==>${x} Python coveragepy not found" - fi - fi - else - say "${e}==>${x} Python coveragepy disabled" - fi - - if [ "$search_in_o" != "" ]; - then - # location override - search_in="$search_in_o" - fi - - say "$e==>$x Searching for coverage reports in:" - for _path in $search_in - do - say " ${g}+${x} $_path" - done - - patterns="find $search_in \( \ - -name vendor \ - -or -name '$bower_components' \ - -or -name '.egg-info*' \ - -or -name 'conftest_*.c.gcov' \ - -or -name .env \ - -or -name .envs \ - -or -name .git \ - -or -name .hg \ - -or -name .tox \ - -or -name .venv \ - -or -name .venvs \ - -or -name .virtualenv \ - -or -name .virtualenvs \ - -or -name .yarn-cache \ - -or -name __pycache__ \ - -or -name env \ - -or -name envs \ - -or -name htmlcov \ - -or -name js/generated/coverage \ - -or -name node_modules \ - -or -name venv \ - -or -name venvs \ - -or -name virtualenv \ - -or -name virtualenvs \ - \) -prune -or \ - -type f \( -name '*coverage*.*' \ - -or -name '*.clover' \ - -or -name '*.codecov.*' \ - -or -name '*.gcov' \ - -or -name '*.lcov' \ - -or -name '*.lst' \ - -or -name 'clover.xml' \ - -or -name 'cobertura.xml' \ - -or -name 'codecov.*' \ - -or -name 'cover.out' \ - -or -name 'codecov-result.json' \ - -or -name 'coverage-final.json' \ - -or -name 'excoveralls.json' \ - -or -name 'gcov.info' \ - -or -name 'jacoco*.xml' \ - -or -name '*Jacoco*.xml' \ - -or -name 'lcov.dat' \ - -or -name 'lcov.info' \ - -or -name 'luacov.report.out' \ - -or -name 'naxsi.info' \ - -or -name 'nosetests.xml' \ - -or -name 'report.xml' \ - $include_cov \) \ - $exclude_cov \ - -not -name '*.am' \ - -not -name '*.bash' \ - -not -name '*.bat' \ - -not -name '*.bw' \ - -not -name '*.cfg' \ - -not -name '*.class' \ - -not -name '*.cmake' \ - -not -name '*.cmake' \ - -not -name '*.conf' \ - -not -name '*.coverage' \ - -not -name '*.cp' \ - -not -name '*.cpp' \ - -not -name '*.crt' \ - -not -name '*.css' \ - -not -name '*.csv' \ - -not -name '*.csv' \ - -not -name '*.data' \ - -not -name '*.db' \ - -not -name '*.dox' \ - -not -name '*.ec' \ - -not -name '*.ec' \ - -not -name '*.egg' \ - -not -name '*.el' \ - -not -name '*.env' \ - -not -name '*.erb' \ - -not -name '*.exe' \ - -not -name '*.ftl' \ - -not -name '*.gif' \ - -not -name '*.gradle' \ - -not -name '*.gz' \ - -not -name '*.h' \ - -not -name '*.html' \ - -not -name '*.in' \ - -not -name '*.jade' \ - -not -name '*.jar*' \ - -not -name '*.jpeg' \ - -not -name '*.jpg' \ - -not -name '*.js' \ - -not -name '*.less' \ - -not -name '*.log' \ - -not -name '*.m4' \ - -not -name '*.mak*' \ - -not -name '*.md' \ - -not -name '*.o' \ - -not -name '*.p12' \ - -not -name '*.pem' \ - -not -name '*.png' \ - -not -name '*.pom*' \ - -not -name '*.profdata' \ - -not -name '*.proto' \ - -not -name '*.ps1' \ - -not -name '*.pth' \ - -not -name '*.py' \ - -not -name '*.pyc' \ - -not -name '*.pyo' \ - -not -name '*.rb' \ - -not -name '*.rsp' \ - -not -name '*.rst' \ - -not -name '*.ru' \ - -not -name '*.sbt' \ - -not -name '*.scss' \ - -not -name '*.scss' \ - -not -name '*.serialized' \ - -not -name '*.sh' \ - -not -name '*.snapshot' \ - -not -name '*.sql' \ - -not -name '*.svg' \ - -not -name '*.tar.tz' \ - -not -name '*.template' \ - -not -name '*.whl' \ - -not -name '*.xcconfig' \ - -not -name '*.xcoverage.*' \ - -not -name '*/classycle/report.xml' \ - -not -name '*codecov.yml' \ - -not -name '*~' \ - -not -name '.*coveragerc' \ - -not -name '.coverage*' \ - -not -name 'coverage-summary.json' \ - -not -name 'createdFiles.lst' \ - -not -name 'fullLocaleNames.lst' \ - -not -name 'include.lst' \ - -not -name 'inputFiles.lst' \ - -not -name 'phpunit-code-coverage.xml' \ - -not -name 'phpunit-coverage.xml' \ - -not -name 'remapInstanbul.coverage*.json' \ - -not -name 'scoverage.measurements.*' \ - -not -name 'test_*_coverage.txt' \ - -not -name 'testrunner-coverage*' \ - -print 2>/dev/null" - files=$(eval "$patterns" || echo '') - -elif [ "$include_cov" != "" ]; -then - files=$(eval "find $search_in -type f \( ${include_cov:5} \)$exclude_cov 2>/dev/null" || echo '') -elif [ "$direct_file_upload" != "" ]; -then - files=$direct_file_upload -fi - -num_of_files=$(echo "$files" | wc -l | tr -d ' ') -if [ "$num_of_files" != '' ] && [ "$files" != '' ]; -then - say " ${e}->${x} Found $num_of_files reports" -fi - -# no files found -if [ "$files" = "" ]; -then - say "${r}-->${x} No coverage report found." - say " Please visit ${b}http://docs.codecov.io/docs/supported-languages${x}" - exit ${exit_with}; -fi - -if [ "$ft_network" == "1" ]; -then - say "${e}==>${x} Detecting git/mercurial file structure" - network=$(cd "$git_root" && git ls-files $git_ls_files_recurse_submodules_o 2>/dev/null || hg locate 2>/dev/null || echo "") - if [ "$network" = "" ]; - then - network=$(find "$git_root" \( \ - -name virtualenv \ - -name .virtualenv \ - -name virtualenvs \ - -name .virtualenvs \ - -name '*.png' \ - -name '*.gif' \ - -name '*.jpg' \ - -name '*.jpeg' \ - -name '*.md' \ - -name .env \ - -name .envs \ - -name env \ - -name envs \ - -name .venv \ - -name .venvs \ - -name venv \ - -name venvs \ - -name .git \ - -name .egg-info \ - -name shunit2-2.1.6 \ - -name vendor \ - -name __pycache__ \ - -name node_modules \ - -path "*/$bower_components/*" \ - -path '*/target/delombok/*' \ - -path '*/build/lib/*' \ - -path '*/js/generated/coverage/*' \ - \) -prune -or \ - -type f -print 2>/dev/null || echo '') - fi - - if [ "$network_filter_o" != "" ]; - then - network=$(echo "$network" | grep -e "$network_filter_o/*") - fi - if [ "$prefix_o" != "" ]; - then - network=$(echo "$network" | awk "{print \"$prefix_o/\"\$0}") - fi -fi - -upload_file=$(mktemp /tmp/codecov.XXXXXX) -adjustments_file=$(mktemp /tmp/codecov.adjustments.XXXXXX) - -cleanup() { - rm -f "$upload_file" "$adjustments_file" "$upload_file.gz" -} - -trap cleanup INT ABRT TERM - - -if [ "$env" != "" ]; -then - inc_env="" - say "${e}==>${x} Appending build variables" - for varname in $(echo "$env" | tr ',' ' ') - do - if [ "$varname" != "" ]; - then - say " ${g}+${x} $varname" - inc_env="${inc_env}${varname}=$(eval echo "\$${varname}") -" - fi - done - echo "$inc_env<<<<<< ENV" >> "$upload_file" -fi - -# Append git file list -# write discovered yaml location -if [ "$direct_file_upload" = "" ]; -then - echo "$yaml" >> "$upload_file" -fi - -if [ "$ft_network" == "1" ]; -then - i="woff|eot|otf" # fonts - i="$i|gif|png|jpg|jpeg|psd" # images - i="$i|ptt|pptx|numbers|pages|md|txt|xlsx|docx|doc|pdf|csv" # docs - i="$i|.gitignore" # supporting docs - - if [ "$ft_html" != "1" ]; - then - i="$i|html" - fi - - if [ "$ft_yaml" != "1" ]; - then - i="$i|yml|yaml" - fi - - echo "$network" | grep -vwE "($i)$" >> "$upload_file" -fi -echo "<<<<<< network" >> "$upload_file" - -if [ "$direct_file_upload" = "" ]; -then - fr=0 - say "${e}==>${x} Reading reports" - while IFS='' read -r file; - do - # read the coverage file - if [ "$(echo "$file" | tr -d ' ')" != '' ]; - then - if [ -f "$file" ]; - then - report_len=$(wc -c < "$file") - if [ "$report_len" -ne 0 ]; - then - say " ${g}+${x} $file ${e}bytes=$(echo "$report_len" | tr -d ' ')${x}" - # append to to upload - _filename=$(basename "$file") - if [ "${_filename##*.}" = 'gcov' ]; - then - { - echo "# path=$(echo "$file.reduced" | sed "s|^$git_root/||")"; - # get file name - head -1 "$file"; - } >> "$upload_file" - # 1. remove source code - # 2. remove ending bracket lines - # 3. remove whitespace - # 4. remove contextual lines - # 5. remove function names - awk -F': *' '{print $1":"$2":"}' "$file" \ - | sed '\/: *} *$/d' \ - | sed 's/^ *//' \ - | sed '/^-/d' \ - | sed 's/^function.*/func/' >> "$upload_file" - else - { - echo "# path=${file//^$git_root/||}"; - cat "$file"; - } >> "$upload_file" - fi - echo "<<<<<< EOF" >> "$upload_file" - fr=1 - if [ "$clean" = "1" ]; - then - rm "$file" - fi - else - say " ${r}-${x} Skipping empty file $file" - fi - else - say " ${r}-${x} file not found at $file" - fi - fi - done <<< "$(echo -e "$files")" - - if [ "$fr" = "0" ]; - then - say "${r}-->${x} No coverage data found." - say " Please visit ${b}http://docs.codecov.io/docs/supported-languages${x}" - say " search for your projects language to learn how to collect reports." - exit ${exit_with}; - fi -else - cp "$direct_file_upload" "$upload_file" - if [ "$clean" = "1" ]; - then - rm "$direct_file_upload" - fi -fi - -if [ "$ft_fix" = "1" ]; -then - say "${e}==>${x} Appending adjustments" - say " ${b}https://docs.codecov.io/docs/fixing-reports${x}" - - empty_line='^[[:space:]]*$' - # // - syntax_comment='^[[:space:]]*//.*' - # /* or */ - syntax_comment_block='^[[:space:]]*(\/\*|\*\/)[[:space:]]*$' - # { or } - syntax_bracket='^[[:space:]]*[\{\}][[:space:]]*(//.*)?$' - # [ or ] - syntax_list='^[[:space:]]*[][][[:space:]]*(//.*)?$' - # func ... { - syntax_go_func='^[[:space:]]*[func].*[\{][[:space:]]*$' - - # shellcheck disable=SC2089 - skip_dirs="-not -path '*/$bower_components/*' \ - -not -path '*/node_modules/*'" - - cut_and_join() { - awk 'BEGIN { FS=":" } - $3 ~ /\/\*/ || $3 ~ /\*\// { print $0 ; next } - $1!=key { if (key!="") print out ; key=$1 ; out=$1":"$2 ; next } - { out=out","$2 } - END { print out }' 2>/dev/null - } - - if echo "$network" | grep -m1 '.kt$' 1>/dev/null; - then - # skip brackets and comments - cd "$git_root" && \ - find . -type f \ - -name '*.kt' \ - -exec \ - grep -nIHE -e "$syntax_bracket" \ - -e "$syntax_comment_block" {} \; \ - | cut_and_join \ - >> "$adjustments_file" \ - || echo '' - - # last line in file - cd "$git_root" && \ - find . -type f \ - -name '*.kt' -exec \ - wc -l {} \; \ - | while read -r l; do echo "EOF: $l"; done \ - 2>/dev/null \ - >> "$adjustments_file" \ - || echo '' - fi - - if echo "$network" | grep -m1 '.go$' 1>/dev/null; - then - # skip empty lines, comments, and brackets - cd "$git_root" && \ - find . -type f \ - -not -path '*/vendor/*' \ - -not -path '*/caches/*' \ - -name '*.go' \ - -exec \ - grep -nIHE \ - -e "$empty_line" \ - -e "$syntax_comment" \ - -e "$syntax_comment_block" \ - -e "$syntax_bracket" \ - -e "$syntax_go_func" \ - {} \; \ - | cut_and_join \ - >> "$adjustments_file" \ - || echo '' - fi - - if echo "$network" | grep -m1 '.dart$' 1>/dev/null; - then - # skip brackets - cd "$git_root" && \ - find . -type f \ - -name '*.dart' \ - -exec \ - grep -nIHE \ - -e "$syntax_bracket" \ - {} \; \ - | cut_and_join \ - >> "$adjustments_file" \ - || echo '' - fi - - if echo "$network" | grep -m1 '.php$' 1>/dev/null; - then - # skip empty lines, comments, and brackets - cd "$git_root" && \ - find . -type f \ - -not -path "*/vendor/*" \ - -name '*.php' \ - -exec \ - grep -nIHE \ - -e "$syntax_list" \ - -e "$syntax_bracket" \ - -e '^[[:space:]]*\);[[:space:]]*(//.*)?$' \ - {} \; \ - | cut_and_join \ - >> "$adjustments_file" \ - || echo '' - fi - - if echo "$network" | grep -m1 '\(.c\.cpp\|.cxx\|.h\|.hpp\|.m\|.swift\|.vala\)$' 1>/dev/null; - then - # skip brackets - # shellcheck disable=SC2086,SC2090 - cd "$git_root" && \ - find . -type f \ - $skip_dirs \ - \( \ - -name '*.c' \ - -or -name '*.cpp' \ - -or -name '*.cxx' \ - -or -name '*.h' \ - -or -name '*.hpp' \ - -or -name '*.m' \ - -or -name '*.swift' \ - -or -name '*.vala' \ - \) -exec \ - grep -nIHE \ - -e "$empty_line" \ - -e "$syntax_bracket" \ - -e '// LCOV_EXCL' \ - {} \; \ - | cut_and_join \ - >> "$adjustments_file" \ - || echo '' - - # skip brackets - # shellcheck disable=SC2086,SC2090 - cd "$git_root" && \ - find . -type f \ - $skip_dirs \ - \( \ - -name '*.c' \ - -or -name '*.cpp' \ - -or -name '*.cxx' \ - -or -name '*.h' \ - -or -name '*.hpp' \ - -or -name '*.m' \ - -or -name '*.swift' \ - -or -name '*.vala' \ - \) -exec \ - grep -nIH '// LCOV_EXCL' \ - {} \; \ - >> "$adjustments_file" \ - || echo '' - - fi - - found=$(< "$adjustments_file" tr -d ' ') - - if [ "$found" != "" ]; - then - say " ${g}+${x} Found adjustments" - { - echo "# path=fixes"; - cat "$adjustments_file"; - echo "<<<<<< EOF"; - } >> "$upload_file" - rm -rf "$adjustments_file" - else - say " ${e}->${x} No adjustments found" - fi -fi - -if [ "$url_o" != "" ]; -then - url="$url_o" -fi - -if [ "$dump" != "0" ]; -then - # trim whitespace from query - say " ${e}->${x} Dumping upload file (no upload)" - echo "$url/upload/v4?$(echo "package=$package-$VERSION&token=$token&$query" | tr -d ' ')" - cat "$upload_file" -else - if [ "$save_to" != "" ]; - then - say "${e}==>${x} Copying upload file to ${save_to}" - mkdir -p "$(dirname "$save_to")" - cp "$upload_file" "$save_to" - fi - - say "${e}==>${x} Gzipping contents" - gzip -nf9 "$upload_file" - say " $(du -h "$upload_file.gz")" - - query=$(echo "${query}" | tr -d ' ') - say "${e}==>${x} Uploading reports" - say " ${e}url:${x} $url" - say " ${e}query:${x} $query" - - # Full query without token (to display on terminal output) - queryNoToken=$(echo "package=$package-$VERSION&token=secret&$query" | tr -d ' ') - # now add token to query - query=$(echo "package=$package-$VERSION&token=$token&$query" | tr -d ' ') - - if [ "$ft_s3" = "1" ]; - then - say "${e}->${x} Pinging Codecov" - say "$url/upload/v4?$queryNoToken" - # shellcheck disable=SC2086,2090 - res=$(curl $curl_s -X POST $cacert \ - --retry 5 --retry-delay 2 --connect-timeout 2 \ - -H 'X-Reduced-Redundancy: false' \ - -H 'X-Content-Type: application/x-gzip' \ - -H 'Content-Length: 0' \ - --write-out "\n%{response_code}\n" \ - $curlargs \ - "$url/upload/v4?$query" || true) - # a good reply is "https://codecov.io" + "\n" + "https://storage.googleapis.com/codecov/..." - s3target=$(echo "$res" | sed -n 2p) - status=$(tail -n1 <<< "$res") - - if [ "$status" = "200" ] && [ "$s3target" != "" ]; - then - say "${e}->${x} Uploading to" - say "${s3target}" - - # shellcheck disable=SC2086 - s3=$(curl -fiX PUT \ - --data-binary @"$upload_file.gz" \ - -H 'Content-Type: application/x-gzip' \ - -H 'Content-Encoding: gzip' \ - $curlawsargs \ - "$s3target" || true) - - if [ "$s3" != "" ]; - then - say " ${g}->${x} Reports have been successfully queued for processing at ${b}$(echo "$res" | sed -n 1p)${x}" - exit 0 - else - say " ${r}X>${x} Failed to upload" - fi - elif [ "$status" = "400" ]; - then - # 400 Error - say "${r}${res}${x}" - exit ${exit_with} - else - say "${r}${res}${x}" - fi - fi - - say "${e}==>${x} Uploading to Codecov" - - # shellcheck disable=SC2086,2090 - res=$(curl -X POST $cacert \ - --data-binary @"$upload_file.gz" \ - --retry 5 --retry-delay 2 --connect-timeout 2 \ - -H 'Content-Type: text/plain' \ - -H 'Content-Encoding: gzip' \ - -H 'X-Content-Encoding: gzip' \ - -H 'Accept: text/plain' \ - $curlargs \ - "$url/upload/v2?$query&attempt=$i" || echo 'HTTP 500') - # HTTP 200 - # http://.... - status=$(echo "$res" | head -1 | cut -d' ' -f2) - if [ "$status" = "" ] || [ "$status" = "200" ]; - then - say " Reports have been successfully queued for processing at ${b}$(echo "$res" | head -2 | tail -1)${x}" - exit 0 - else - say " ${g}${res}${x}" - exit ${exit_with} - fi - - say " ${r}X> Failed to upload coverage reports${x}" -fi - -exit ${exit_with} diff --git a/staging/operator-registry/.github/workflows/go-apidiff.yaml b/staging/operator-registry/.github/workflows/go-apidiff.yaml index 4f1657eb16..e8f521db31 100644 --- a/staging/operator-registry/.github/workflows/go-apidiff.yaml +++ b/staging/operator-registry/.github/workflows/go-apidiff.yaml @@ -14,14 +14,14 @@ jobs: if: github.event_name == 'pull_request' runs-on: ubuntu-latest steps: - - name: Set up Go - uses: actions/setup-go@v2 - with: - go-version: '~1.18' - id: go - name: Check out code into the Go module directory - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 0 + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version-file: 'go.mod' + id: go - name: Run go-apidiff uses: joelanford/go-apidiff@main diff --git a/staging/operator-registry/.github/workflows/goreleaser.yaml b/staging/operator-registry/.github/workflows/goreleaser.yaml index 5779f83015..b19cc5899d 100644 --- a/staging/operator-registry/.github/workflows/goreleaser.yaml +++ b/staging/operator-registry/.github/workflows/goreleaser.yaml @@ -18,8 +18,8 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/download-artifact@v2 + - uses: actions/checkout@v3 + - uses: actions/download-artifact@v3 - run: | for dist in dist-*; do @@ -48,15 +48,14 @@ jobs: build-windows: runs-on: windows-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: # GoReleaser requires fetch-depth: 0 to correctly # run git describe fetch-depth: 0 - - uses: actions/setup-go@v2 + - uses: actions/setup-go@v4 with: - go-version: '~1.18' - + go-version-file: "go.mod" - name: "Run GoReleaser" run: make release env: @@ -72,16 +71,15 @@ jobs: build-darwin: runs-on: macos-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: # GoReleaser requires fetch-depth: 0 to correctly # run git describe fetch-depth: 0 - - uses: actions/setup-go@v2 + - uses: actions/setup-go@v4 with: - go-version: '~1.18' - + go-version-file: "go.mod" - name: "Run GoReleaser" run: make release env: @@ -97,16 +95,15 @@ jobs: build-linux: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: # GoReleaser requires fetch-depth: 0 to correctly # run git describe fetch-depth: 0 - - uses: actions/setup-go@v2 + - uses: actions/setup-go@v4 with: - go-version: '~1.18' - + go-version-file: "go.mod" - name: "Install linux cross-compilers" run: | sudo apt-get update diff --git a/staging/operator-registry/.github/workflows/sanity.yaml b/staging/operator-registry/.github/workflows/sanity.yaml index 8008817f8c..20f8edadd4 100644 --- a/staging/operator-registry/.github/workflows/sanity.yaml +++ b/staging/operator-registry/.github/workflows/sanity.yaml @@ -13,11 +13,11 @@ jobs: sanity: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-go@v2 + - uses: actions/checkout@v3 + - uses: actions/setup-go@v4 with: - go-version: '~1.18' + go-version-file: "go.mod" - name: Install goimports run: go install golang.org/x/tools/cmd/goimports@latest - name: Run sanity checks - run: make vendor && make lint && git diff --exit-code + run: make lint && git diff --exit-code diff --git a/staging/operator-registry/.github/workflows/test.yml b/staging/operator-registry/.github/workflows/test.yml index 5d54944f0b..397db968cc 100644 --- a/staging/operator-registry/.github/workflows/test.yml +++ b/staging/operator-registry/.github/workflows/test.yml @@ -11,10 +11,10 @@ jobs: e2e: runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v2 - - uses: actions/setup-go@v2 + - uses: actions/checkout@v3 + - uses: actions/setup-go@v4 with: - go-version: '~1.18' + go-version-file: 'go.mod' - name: Install podman run: | . /etc/os-release diff --git a/staging/operator-registry/.github/workflows/unit.yaml b/staging/operator-registry/.github/workflows/unit.yaml index 4d5bcbc382..8ec90418b9 100644 --- a/staging/operator-registry/.github/workflows/unit.yaml +++ b/staging/operator-registry/.github/workflows/unit.yaml @@ -13,10 +13,14 @@ jobs: unit: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-go@v2 + - uses: actions/checkout@v3 + - uses: actions/setup-go@v4 with: - go-version: '~1.18' + go-version-file: "go.mod" - run: make unit - run: sed -i'' "s:^github.com/$GITHUB_REPOSITORY/::" coverage.out - - run: .github/workflows/codecov.sh -Z -f coverage.out + - uses: codecov/codecov-action@v3 + with: + files: coverage.out + fail_ci_if_error: true + functionalities: fixes diff --git a/staging/operator-registry/Dockerfile b/staging/operator-registry/Dockerfile deleted file mode 100644 index a4e7fb317e..0000000000 --- a/staging/operator-registry/Dockerfile +++ /dev/null @@ -1,37 +0,0 @@ -FROM registry.ci.openshift.org/ocp/builder:rhel-8-golang-1.18-openshift-4.11 AS builder - -ENV GOPATH /go -ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH - -WORKDIR /src - -COPY . . -RUN make build cross - -# copy and build vendored grpc_health_probe -RUN CGO_ENABLED=0 go build -mod=vendor -tags netgo -ldflags "-w" ./vendor/github.com/grpc-ecosystem/grpc-health-probe/... - -FROM registry.ci.openshift.org/ocp/4.8:base - -COPY --from=builder /src/bin/* /bin/registry/ -COPY --from=builder /src/grpc-health-probe /bin/grpc_health_probe - -RUN ln -s /bin/registry/* /bin - -RUN mkdir /registry -RUN chgrp -R 0 /registry && \ - chmod -R g+rwx /registry -WORKDIR /registry - -# This image doesn't need to run as root user -USER 1001 - -EXPOSE 50051 - -ENTRYPOINT ["/bin/registry-server"] -CMD ["--database", "/bundles.db"] - -LABEL io.k8s.display-name="OpenShift Operator Registry" \ - io.k8s.description="This is a component of OpenShift Operator Lifecycle Manager and is the base for operator catalog API containers." \ - maintainer="Odin Team " \ - summary="Operator Registry runs in a Kubernetes or OpenShift cluster to provide operator catalog data to Operator Lifecycle Manager." diff --git a/staging/operator-registry/Makefile b/staging/operator-registry/Makefile index 7ea7aef2ea..df4ac5072b 100644 --- a/staging/operator-registry/Makefile +++ b/staging/operator-registry/Makefile @@ -1,5 +1,5 @@ SHELL = /bin/bash -GO := GOFLAGS="-mod=vendor" go +GO := go CMDS := $(addprefix bin/, $(shell ls ./cmd | grep -v opm)) OPM := $(addprefix bin/, opm) SPECIFIC_UNIT_TEST := $(if $(TEST),-run $(TEST),) @@ -74,23 +74,14 @@ sanity-check: docker run --rm -it -v "$(shell pwd)"/pkg/lib/indexer/testdata/:/database sanity-container \ ./bin/opm registry serve --database /database/bundles.db --timeout-seconds 1 -.PHONY: image -image: - docker build . .PHONY: image-upstream image-upstream: docker build -f upstream-example.Dockerfile . -.PHONY: vendor -vendor: - $(GO) mod tidy - $(GO) mod vendor - $(GO) mod verify - .PHONY: lint lint: - find . -name '*.go' -not -path "./vendor/*" | xargs goimports -w + find . -name '*.go' | xargs goimports -w .PHONY: codegen codegen: @@ -99,13 +90,6 @@ codegen: protoc -I pkg/api/grpc_health_v1 --go_out=pkg/api/grpc_health_v1 pkg/api/grpc_health_v1/*.proto protoc -I pkg/api/grpc_health_v1 --go-grpc_out=pkg/api/grpc_health_v1 pkg/api/grpc_health_v1/*.proto -.PHONY: container-codegen -container-codegen: - docker build -t operator-registry:codegen -f codegen.Dockerfile . - docker run --name temp-codegen operator-registry:codegen /bin/true - docker cp temp-codegen:/codegen/pkg/api/. ./pkg/api - docker rm temp-codegen - .PHONY: generate-fakes generate-fakes: $(GO) generate ./... diff --git a/staging/operator-registry/OWNERS b/staging/operator-registry/OWNERS index c1c32e681c..67ce7f24c5 100644 --- a/staging/operator-registry/OWNERS +++ b/staging/operator-registry/OWNERS @@ -1,26 +1,32 @@ # approval == this is a good idea /approve approvers: - - ecordell - - njhale + - awgreene - dinhxuanvu - - kevinrizza - - benluddy + - grokspawn - joelanford + - kevinrizza + - njhale + - oceanc80 + - perdasilva # review == this code is good /lgtm reviewers: - - ecordell - - njhale - - dinhxuanvu - - kevinrizza - - gallettilance - anik120 - - exdx + - ankitathomas - awgreene - benluddy - - hasbro17 - - ankitathomas - - joelanford + - dinhxuanvu + - everettraven + - exdx + - gallettilance + - grokspawn - jmrodri - - timflannagan + - joelanford + - kevinrizza + - njhale + - oceanc80 + - perdasilva + - rashmigottipati + - theishshah + - varshaprasad96 # Bugzilla component component: "OLM" diff --git a/staging/operator-registry/alpha/action/migrate.go b/staging/operator-registry/alpha/action/migrate.go index 8cca8b8974..c5880f0006 100644 --- a/staging/operator-registry/alpha/action/migrate.go +++ b/staging/operator-registry/alpha/action/migrate.go @@ -1,13 +1,10 @@ package action import ( - "bytes" "context" "fmt" - "io" "io/ioutil" "os" - "path/filepath" "github.com/operator-framework/operator-registry/alpha/declcfg" "github.com/operator-framework/operator-registry/pkg/image" @@ -17,13 +14,11 @@ type Migrate struct { CatalogRef string OutputDir string - WriteFunc WriteFunc + WriteFunc declcfg.WriteFunc FileExt string Registry image.Registry } -type WriteFunc func(config declcfg.DeclarativeConfig, w io.Writer) error - func (m Migrate) Run(ctx context.Context) error { entries, err := ioutil.ReadDir(m.OutputDir) if err != nil && !os.IsNotExist(err) { @@ -52,48 +47,5 @@ func (m Migrate) Run(ctx context.Context) error { return fmt.Errorf("render catalog image: %w", err) } - return writeToFS(*cfg, m.OutputDir, m.WriteFunc, m.FileExt) -} - -func writeToFS(cfg declcfg.DeclarativeConfig, rootDir string, writeFunc WriteFunc, fileExt string) error { - channelsByPackage := map[string][]declcfg.Channel{} - for _, c := range cfg.Channels { - channelsByPackage[c.Package] = append(channelsByPackage[c.Package], c) - } - bundlesByPackage := map[string][]declcfg.Bundle{} - for _, b := range cfg.Bundles { - bundlesByPackage[b.Package] = append(bundlesByPackage[b.Package], b) - } - - if err := os.MkdirAll(rootDir, 0777); err != nil { - return err - } - - for _, p := range cfg.Packages { - fcfg := declcfg.DeclarativeConfig{ - Packages: []declcfg.Package{p}, - Channels: channelsByPackage[p.Name], - Bundles: bundlesByPackage[p.Name], - } - pkgDir := filepath.Join(rootDir, p.Name) - if err := os.MkdirAll(pkgDir, 0777); err != nil { - return err - } - filename := filepath.Join(pkgDir, fmt.Sprintf("catalog%s", fileExt)) - if err := writeFile(fcfg, filename, writeFunc); err != nil { - return err - } - } - return nil -} - -func writeFile(cfg declcfg.DeclarativeConfig, filename string, writeFunc WriteFunc) error { - buf := &bytes.Buffer{} - if err := writeFunc(cfg, buf); err != nil { - return fmt.Errorf("write to buffer for %q: %v", filename, err) - } - if err := ioutil.WriteFile(filename, buf.Bytes(), 0666); err != nil { - return fmt.Errorf("write file %q: %v", filename, err) - } - return nil + return declcfg.WriteFS(*cfg, m.OutputDir, m.WriteFunc, m.FileExt) } diff --git a/staging/operator-registry/alpha/action/migrate_test.go b/staging/operator-registry/alpha/action/migrate_test.go index ecaa0b3675..5f6be7b95e 100644 --- a/staging/operator-registry/alpha/action/migrate_test.go +++ b/staging/operator-registry/alpha/action/migrate_test.go @@ -2,7 +2,6 @@ package action_test import ( "context" - "fmt" "io/fs" "os" "path/filepath" @@ -111,7 +110,6 @@ func TestMigrate(t *testing.T) { path := filepath.Join(s.migrate.OutputDir, file) actualData, err := os.ReadFile(path) require.NoError(t, err) - fmt.Println(string(actualData)) require.Equal(t, expectedData, string(actualData)) } }) @@ -212,12 +210,18 @@ properties: value: packageName: bar versionRange: <0.1.0 -- type: olm.bundle.object +- type: olm.csv.metadata value: - data: eyJhcGlWZXJzaW9uIjoib3BlcmF0b3JzLmNvcmVvcy5jb20vdjFhbHBoYTEiLCJraW5kIjoiQ2x1c3RlclNlcnZpY2VWZXJzaW9uIiwibWV0YWRhdGEiOnsiYW5ub3RhdGlvbnMiOnsib2xtLnNraXBSYW5nZSI6Ilx1MDAzYzAuMS4wIn0sIm5hbWUiOiJmb28udjAuMS4wIn0sInNwZWMiOnsiY3VzdG9tcmVzb3VyY2VkZWZpbml0aW9ucyI6eyJvd25lZCI6W3siZ3JvdXAiOiJ0ZXN0LmZvbyIsImtpbmQiOiJGb28iLCJuYW1lIjoiZm9vcy50ZXN0LmZvbyIsInZlcnNpb24iOiJ2MSJ9XX0sImRpc3BsYXlOYW1lIjoiRm9vIE9wZXJhdG9yIiwicmVsYXRlZEltYWdlcyI6W3siaW1hZ2UiOiJ0ZXN0LnJlZ2lzdHJ5L2Zvby1vcGVyYXRvci9mb286djAuMS4wIiwibmFtZSI6Im9wZXJhdG9yIn1dLCJ2ZXJzaW9uIjoiMC4xLjAifX0= -- type: olm.bundle.object - value: - data: eyJhcGlWZXJzaW9uIjoiYXBpZXh0ZW5zaW9ucy5rOHMuaW8vdjEiLCJraW5kIjoiQ3VzdG9tUmVzb3VyY2VEZWZpbml0aW9uIiwibWV0YWRhdGEiOnsibmFtZSI6ImZvb3MudGVzdC5mb28ifSwic3BlYyI6eyJncm91cCI6InRlc3QuZm9vIiwibmFtZXMiOnsia2luZCI6IkZvbyIsInBsdXJhbCI6ImZvb3MifSwidmVyc2lvbnMiOlt7Im5hbWUiOiJ2MSJ9XX19 + annotations: + olm.skipRange: <0.1.0 + apiServiceDefinitions: {} + crdDescriptions: + owned: + - kind: Foo + name: foos.test.foo + version: v1 + displayName: Foo Operator + provider: {} relatedImages: - image: test.registry/foo-operator/foo-bundle:v0.1.0 name: "" @@ -247,12 +251,18 @@ properties: value: packageName: bar versionRange: <0.1.0 -- type: olm.bundle.object - value: - data: eyJhcGlWZXJzaW9uIjoib3BlcmF0b3JzLmNvcmVvcy5jb20vdjFhbHBoYTEiLCJraW5kIjoiQ2x1c3RlclNlcnZpY2VWZXJzaW9uIiwibWV0YWRhdGEiOnsiYW5ub3RhdGlvbnMiOnsib2xtLnNraXBSYW5nZSI6Ilx1MDAzYzAuMi4wIn0sIm5hbWUiOiJmb28udjAuMi4wIn0sInNwZWMiOnsiY3VzdG9tcmVzb3VyY2VkZWZpbml0aW9ucyI6eyJvd25lZCI6W3siZ3JvdXAiOiJ0ZXN0LmZvbyIsImtpbmQiOiJGb28iLCJuYW1lIjoiZm9vcy50ZXN0LmZvbyIsInZlcnNpb24iOiJ2MSJ9XX0sImRpc3BsYXlOYW1lIjoiRm9vIE9wZXJhdG9yIiwiaW5zdGFsbCI6eyJzcGVjIjp7ImRlcGxveW1lbnRzIjpbeyJuYW1lIjoiZm9vLW9wZXJhdG9yIiwic3BlYyI6eyJ0ZW1wbGF0ZSI6eyJzcGVjIjp7ImNvbnRhaW5lcnMiOlt7ImltYWdlIjoidGVzdC5yZWdpc3RyeS9mb28tb3BlcmF0b3IvZm9vOnYwLjIuMCJ9XSwiaW5pdENvbnRhaW5lcnMiOlt7ImltYWdlIjoidGVzdC5yZWdpc3RyeS9mb28tb3BlcmF0b3IvZm9vLWluaXQ6djAuMi4wIn1dfX19fSx7Im5hbWUiOiJmb28tb3BlcmF0b3ItMiIsInNwZWMiOnsidGVtcGxhdGUiOnsic3BlYyI6eyJjb250YWluZXJzIjpbeyJpbWFnZSI6InRlc3QucmVnaXN0cnkvZm9vLW9wZXJhdG9yL2Zvby0yOnYwLjIuMCJ9XSwiaW5pdENvbnRhaW5lcnMiOlt7ImltYWdlIjoidGVzdC5yZWdpc3RyeS9mb28tb3BlcmF0b3IvZm9vLWluaXQtMjp2MC4yLjAifV19fX19XX0sInN0cmF0ZWd5IjoiZGVwbG95bWVudCJ9LCJyZWxhdGVkSW1hZ2VzIjpbeyJpbWFnZSI6InRlc3QucmVnaXN0cnkvZm9vLW9wZXJhdG9yL2Zvbzp2MC4yLjAiLCJuYW1lIjoib3BlcmF0b3IifSx7ImltYWdlIjoidGVzdC5yZWdpc3RyeS9mb28tb3BlcmF0b3IvZm9vLW90aGVyOnYwLjIuMCIsIm5hbWUiOiJvdGhlciJ9XSwicmVwbGFjZXMiOiJmb28udjAuMS4wIiwic2tpcHMiOlsiZm9vLnYwLjEuMSIsImZvby52MC4xLjIiXSwidmVyc2lvbiI6IjAuMi4wIn19 -- type: olm.bundle.object +- type: olm.csv.metadata value: - data: eyJhcGlWZXJzaW9uIjoiYXBpZXh0ZW5zaW9ucy5rOHMuaW8vdjEiLCJraW5kIjoiQ3VzdG9tUmVzb3VyY2VEZWZpbml0aW9uIiwibWV0YWRhdGEiOnsibmFtZSI6ImZvb3MudGVzdC5mb28ifSwic3BlYyI6eyJncm91cCI6InRlc3QuZm9vIiwibmFtZXMiOnsia2luZCI6IkZvbyIsInBsdXJhbCI6ImZvb3MifSwidmVyc2lvbnMiOlt7Im5hbWUiOiJ2MSJ9XX19 + annotations: + olm.skipRange: <0.2.0 + apiServiceDefinitions: {} + crdDescriptions: + owned: + - kind: Foo + name: foos.test.foo + version: v1 + displayName: Foo Operator + provider: {} relatedImages: - image: test.registry/foo-operator/foo-2:v0.2.0 name: "" @@ -299,12 +309,15 @@ properties: value: packageName: bar version: 0.1.0 -- type: olm.bundle.object +- type: olm.csv.metadata value: - data: eyJhcGlWZXJzaW9uIjoib3BlcmF0b3JzLmNvcmVvcy5jb20vdjFhbHBoYTEiLCJraW5kIjoiQ2x1c3RlclNlcnZpY2VWZXJzaW9uIiwibWV0YWRhdGEiOnsibmFtZSI6ImJhci52MC4xLjAifSwic3BlYyI6eyJjdXN0b21yZXNvdXJjZWRlZmluaXRpb25zIjp7Im93bmVkIjpbeyJncm91cCI6InRlc3QuYmFyIiwia2luZCI6IkJhciIsIm5hbWUiOiJiYXJzLnRlc3QuYmFyIiwidmVyc2lvbiI6InYxYWxwaGExIn1dfSwicmVsYXRlZEltYWdlcyI6W3siaW1hZ2UiOiJ0ZXN0LnJlZ2lzdHJ5L2Jhci1vcGVyYXRvci9iYXI6djAuMS4wIiwibmFtZSI6Im9wZXJhdG9yIn1dLCJ2ZXJzaW9uIjoiMC4xLjAifX0= -- type: olm.bundle.object - value: - data: eyJhcGlWZXJzaW9uIjoiYXBpZXh0ZW5zaW9ucy5rOHMuaW8vdjEiLCJraW5kIjoiQ3VzdG9tUmVzb3VyY2VEZWZpbml0aW9uIiwibWV0YWRhdGEiOnsibmFtZSI6ImJhcnMudGVzdC5iYXIifSwic3BlYyI6eyJncm91cCI6InRlc3QuYmFyIiwibmFtZXMiOnsia2luZCI6IkJhciIsInBsdXJhbCI6ImJhcnMifSwidmVyc2lvbnMiOlt7Im5hbWUiOiJ2MWFscGhhMSJ9XX19 + apiServiceDefinitions: {} + crdDescriptions: + owned: + - kind: Bar + name: bars.test.bar + version: v1alpha1 + provider: {} relatedImages: - image: test.registry/bar-operator/bar-bundle:v0.1.0 name: "" @@ -325,12 +338,17 @@ properties: value: packageName: bar version: 0.2.0 -- type: olm.bundle.object - value: - data: eyJhcGlWZXJzaW9uIjoib3BlcmF0b3JzLmNvcmVvcy5jb20vdjFhbHBoYTEiLCJraW5kIjoiQ2x1c3RlclNlcnZpY2VWZXJzaW9uIiwibWV0YWRhdGEiOnsiYW5ub3RhdGlvbnMiOnsib2xtLnNraXBSYW5nZSI6Ilx1MDAzYzAuMi4wIn0sIm5hbWUiOiJiYXIudjAuMi4wIn0sInNwZWMiOnsiY3VzdG9tcmVzb3VyY2VkZWZpbml0aW9ucyI6eyJvd25lZCI6W3siZ3JvdXAiOiJ0ZXN0LmJhciIsImtpbmQiOiJCYXIiLCJuYW1lIjoiYmFycy50ZXN0LmJhciIsInZlcnNpb24iOiJ2MWFscGhhMSJ9XX0sInJlbGF0ZWRJbWFnZXMiOlt7ImltYWdlIjoidGVzdC5yZWdpc3RyeS9iYXItb3BlcmF0b3IvYmFyOnYwLjIuMCIsIm5hbWUiOiJvcGVyYXRvciJ9XSwic2tpcHMiOlsiYmFyLnYwLjEuMCJdLCJ2ZXJzaW9uIjoiMC4yLjAifX0= -- type: olm.bundle.object +- type: olm.csv.metadata value: - data: eyJhcGlWZXJzaW9uIjoiYXBpZXh0ZW5zaW9ucy5rOHMuaW8vdjEiLCJraW5kIjoiQ3VzdG9tUmVzb3VyY2VEZWZpbml0aW9uIiwibWV0YWRhdGEiOnsibmFtZSI6ImJhcnMudGVzdC5iYXIifSwic3BlYyI6eyJncm91cCI6InRlc3QuYmFyIiwibmFtZXMiOnsia2luZCI6IkJhciIsInBsdXJhbCI6ImJhcnMifSwidmVyc2lvbnMiOlt7Im5hbWUiOiJ2MWFscGhhMSJ9XX19 + annotations: + olm.skipRange: <0.2.0 + apiServiceDefinitions: {} + crdDescriptions: + owned: + - kind: Bar + name: bars.test.bar + version: v1alpha1 + provider: {} relatedImages: - image: test.registry/bar-operator/bar-bundle:v0.2.0 name: "" diff --git a/staging/operator-registry/alpha/action/render.go b/staging/operator-registry/alpha/action/render.go index 3f38390a0e..b1e5bd7541 100644 --- a/staging/operator-registry/alpha/action/render.go +++ b/staging/operator-registry/alpha/action/render.go @@ -82,7 +82,7 @@ func (r Render) Run(ctx context.Context) (*declcfg.DeclarativeConfig, error) { if err != nil { return nil, fmt.Errorf("render reference %q: %w", ref, err) } - renderBundleObjects(cfg) + moveBundleObjectsToEndOfPropertySlices(cfg) for _, b := range cfg.Bundles { sort.Slice(b.RelatedImages, func(i, j int) bool { @@ -122,7 +122,7 @@ func (r Render) renderReference(ctx context.Context, ref string) (*declcfg.Decla if !r.AllowedRefMask.Allowed(RefDCDir) { return nil, fmt.Errorf("cannot render declarative config directory: %w", ErrNotAllowed) } - return declcfg.LoadFS(os.DirFS(ref)) + return declcfg.LoadFS(ctx, os.DirFS(ref)) } else { // The only supported file type is an sqlite DB file, // since declarative configs will be in a directory. @@ -169,7 +169,7 @@ func (r Render) imageToDeclcfg(ctx context.Context, imageRef string) (*declcfg.D if !r.AllowedRefMask.Allowed(RefDCImage) { return nil, fmt.Errorf("cannot render declarative config image: %w", ErrNotAllowed) } - cfg, err = declcfg.LoadFS(os.DirFS(filepath.Join(tmpDir, configsDir))) + cfg, err = declcfg.LoadFS(ctx, os.DirFS(filepath.Join(tmpDir, configsDir))) if err != nil { return nil, err } @@ -304,6 +304,7 @@ func bundleToDeclcfg(bundle *registry.Bundle) (*declcfg.DeclarativeConfig, error if err != nil { return nil, fmt.Errorf("get related images for bundle %q: %v", bundle.Name, err) } + var csvJson []byte for _, obj := range bundle.Objects { if obj.GetKind() == "ClusterServiceVersion" { @@ -376,19 +377,21 @@ func getRelatedImages(b *registry.Bundle) ([]declcfg.RelatedImage, error) { return relatedImages, nil } -func renderBundleObjects(cfg *declcfg.DeclarativeConfig) { +func moveBundleObjectsToEndOfPropertySlices(cfg *declcfg.DeclarativeConfig) { for bi, b := range cfg.Bundles { - props := b.Properties[:0] + var ( + others []property.Property + objs []property.Property + ) for _, p := range b.Properties { - if p.Type != property.TypeBundleObject { - props = append(props, p) + switch p.Type { + case property.TypeBundleObject, property.TypeCSVMetadata: + objs = append(objs, p) + default: + others = append(others, p) } } - - for _, obj := range b.Objects { - props = append(props, property.MustBuildBundleObjectData([]byte(obj))) - } - cfg.Bundles[bi].Properties = props + cfg.Bundles[bi].Properties = append(others, objs...) } } diff --git a/staging/operator-registry/alpha/action/render_test.go b/staging/operator-registry/alpha/action/render_test.go index c3385dabd9..976da69220 100644 --- a/staging/operator-registry/alpha/action/render_test.go +++ b/staging/operator-registry/alpha/action/render_test.go @@ -1,16 +1,19 @@ package action_test import ( + "bytes" "context" "embed" "encoding/json" "errors" + "io" "io/fs" "os" "path/filepath" "testing" "testing/fstest" + "github.com/operator-framework/api/pkg/operators/v1alpha1" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "k8s.io/apimachinery/pkg/util/yaml" @@ -105,8 +108,7 @@ func TestRender(t *testing.T) { property.MustBuildGVKRequired("test.bar", "v1alpha1", "Bar"), property.MustBuildPackage("foo", "0.1.0"), property.MustBuildPackageRequired("bar", "<0.1.0"), - property.MustBuildBundleObjectData(foov1csv), - property.MustBuildBundleObjectData(foov1crd), + mustBuildCSVMetadata(bytes.NewReader(foov1csv)), }, RelatedImages: []declcfg.RelatedImage{ { @@ -130,8 +132,7 @@ func TestRender(t *testing.T) { property.MustBuildGVKRequired("test.bar", "v1alpha1", "Bar"), property.MustBuildPackage("foo", "0.2.0"), property.MustBuildPackageRequired("bar", "<0.1.0"), - property.MustBuildBundleObjectData(foov2csv), - property.MustBuildBundleObjectData(foov2crd), + mustBuildCSVMetadata(bytes.NewReader(foov2csv)), }, RelatedImages: []declcfg.RelatedImage{ { @@ -197,8 +198,7 @@ func TestRender(t *testing.T) { property.MustBuildGVKRequired("test.bar", "v1alpha1", "Bar"), property.MustBuildPackage("foo", "0.1.0"), property.MustBuildPackageRequired("bar", "<0.1.0"), - property.MustBuildBundleObjectData(foov1csv), - property.MustBuildBundleObjectData(foov1crd), + mustBuildCSVMetadata(bytes.NewReader(foov1csv)), }, RelatedImages: []declcfg.RelatedImage{ { @@ -222,8 +222,7 @@ func TestRender(t *testing.T) { property.MustBuildGVKRequired("test.bar", "v1alpha1", "Bar"), property.MustBuildPackage("foo", "0.2.0"), property.MustBuildPackageRequired("bar", "<0.1.0"), - property.MustBuildBundleObjectData(foov2csv), - property.MustBuildBundleObjectData(foov2crd), + mustBuildCSVMetadata(bytes.NewReader(foov2csv)), }, RelatedImages: []declcfg.RelatedImage{ { @@ -468,8 +467,7 @@ func TestRender(t *testing.T) { property.MustBuildGVKRequired("test.bar", "v1alpha1", "Bar"), property.MustBuildPackage("foo", "0.2.0"), property.MustBuildPackageRequired("bar", "<0.1.0"), - property.MustBuildBundleObjectData(foov2csv), - property.MustBuildBundleObjectData(foov2crd), + mustBuildCSVMetadata(bytes.NewReader(foov2csv)), }, Objects: []string{string(foov2csv), string(foov2crd)}, CsvJSON: string(foov2csv), @@ -518,8 +516,7 @@ func TestRender(t *testing.T) { property.MustBuildGVKRequired("test.bar", "v1alpha1", "Bar"), property.MustBuildPackage("foo", "0.2.0"), property.MustBuildPackageRequired("bar", "<0.1.0"), - property.MustBuildBundleObjectData(foov2csvNoRelatedImages), - property.MustBuildBundleObjectData(foov2crdNoRelatedImages), + mustBuildCSVMetadata(bytes.NewReader(foov2csvNoRelatedImages)), }, Objects: []string{string(foov2csvNoRelatedImages), string(foov2crdNoRelatedImages)}, CsvJSON: string(foov2csvNoRelatedImages), @@ -551,7 +548,17 @@ func TestRender(t *testing.T) { t.Run(s.name, func(t *testing.T) { actualCfg, actualErr := s.render.Run(context.Background()) s.assertion(t, actualErr) - require.Equal(t, s.expectCfg, actualCfg) + require.Equal(t, len(s.expectCfg.Packages), len(actualCfg.Packages)) + require.Equal(t, s.expectCfg.Packages, actualCfg.Packages) + require.Equal(t, len(s.expectCfg.Channels), len(actualCfg.Channels)) + require.Equal(t, s.expectCfg.Channels, actualCfg.Channels) + require.Equal(t, len(s.expectCfg.Bundles), len(actualCfg.Bundles)) + for i := range s.expectCfg.Bundles { + actual, expected := actualCfg.Bundles[i], s.expectCfg.Bundles[i] + require.Equal(t, expected, actual, "bundle %d", i) + } + require.Equal(t, len(s.expectCfg.Others), len(actualCfg.Others)) + require.Equal(t, s.expectCfg.Others, actualCfg.Others) }) } } @@ -880,3 +887,11 @@ func generateSqliteFile(path string, imageMap map[image.Reference]string) error } return nil } + +func mustBuildCSVMetadata(r io.Reader) property.Property { + var csv v1alpha1.ClusterServiceVersion + if err := json.NewDecoder(r).Decode(&csv); err != nil { + panic(err) + } + return property.MustBuildCSVMetadata(csv) +} diff --git a/staging/operator-registry/alpha/declcfg/declcfg.go b/staging/operator-registry/alpha/declcfg/declcfg.go index a4169c28c5..994d47a0b7 100644 --- a/staging/operator-registry/alpha/declcfg/declcfg.go +++ b/staging/operator-registry/alpha/declcfg/declcfg.go @@ -1,7 +1,14 @@ package declcfg import ( + "bytes" "encoding/json" + "errors" + "fmt" + + "golang.org/x/text/cases" + utilerrors "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/apimachinery/pkg/util/sets" "github.com/operator-framework/operator-registry/alpha/property" ) @@ -52,11 +59,11 @@ type ChannelEntry struct { // Top-level fields are the source of truth, i.e. not CSV values. // // Notes: -// - Any field slice type field or type containing a slice somewhere -// where two types/fields are equal if their contents are equal regardless -// of order must have a `hash:"set"` field tag for bundle comparison. -// - Any fields that have a `json:"-"` tag must be included in the equality -// evaluation in bundlesEqual(). +// - Any field slice type field or type containing a slice somewhere +// where two types/fields are equal if their contents are equal regardless +// of order must have a `hash:"set"` field tag for bundle comparison. +// - Any fields that have a `json:"-"` tag must be included in the equality +// evaluation in bundlesEqual(). type Bundle struct { Schema string `json:"schema"` Name string `json:"name"` @@ -84,6 +91,7 @@ type RelatedImage struct { type Meta struct { Schema string Package string + Name string Blob json.RawMessage } @@ -93,17 +101,81 @@ func (m Meta) MarshalJSON() ([]byte, error) { } func (m *Meta) UnmarshalJSON(blob []byte) error { - type tmp struct { - Schema string `json:"schema"` - Package string `json:"package,omitempty"` - Properties []property.Property `json:"properties,omitempty"` + blobMap := map[string]interface{}{} + if err := json.Unmarshal(blob, &blobMap); err != nil { + // TODO: unfortunately, there are libraries between here and the original caller + // that eat our error type and return a generic error, such that we lose the + // ability to errors.As to get this error on the other side. For now, just return + // a string error that includes the pretty printed message. + return errors.New(newJSONUnmarshalError(blob, err).Pretty()) } - var t tmp - if err := json.Unmarshal(blob, &t); err != nil { + + // TODO: this function ensures we do not break backwards compatibility with + // the documented examples of FBC templates, which use upper camel case + // for JSON field names. We need to decide if we want to continue supporting + // case insensitive JSON field names, or if we want to enforce a specific + // case-sensitive key value for each field. + if err := extractUniqueMetaKeys(blobMap, m); err != nil { + return err + } + + buf := bytes.Buffer{} + enc := json.NewEncoder(&buf) + enc.SetEscapeHTML(false) + if err := enc.Encode(blobMap); err != nil { return err } - m.Schema = t.Schema - m.Package = t.Package - m.Blob = blob + m.Blob = buf.Bytes() + return nil +} + +// extractUniqueMetaKeys enables a case-insensitive key lookup for the schema, package, and name +// fields of the Meta struct. If the blobMap contains duplicate keys (that is, keys have the same folded value), +// an error is returned. +func extractUniqueMetaKeys(blobMap map[string]any, m *Meta) error { + keySets := map[string]sets.Set[string]{} + folder := cases.Fold() + for key := range blobMap { + foldKey := folder.String(key) + if _, ok := keySets[foldKey]; !ok { + keySets[foldKey] = sets.New[string]() + } + keySets[foldKey].Insert(key) + } + + dupErrs := []error{} + for foldedKey, keys := range keySets { + if len(keys) != 1 { + dupErrs = append(dupErrs, fmt.Errorf("duplicate keys for key %q: %v", foldedKey, sets.List(keys))) + } + } + if len(dupErrs) > 0 { + return utilerrors.NewAggregate(dupErrs) + } + + metaMap := map[string]*string{ + folder.String("schema"): &m.Schema, + folder.String("package"): &m.Package, + folder.String("name"): &m.Name, + } + + for foldedKey, ptr := range metaMap { + // if the folded key doesn't exist in the key set derived from the blobMap, that means + // the key doesn't exist in the blobMap, so we can skip it + if _, ok := keySets[foldedKey]; !ok { + continue + } + + // reset key to the unfolded key, which we know is the one that appears in the blobMap + key := keySets[foldedKey].UnsortedList()[0] + if _, ok := blobMap[key]; !ok { + continue + } + v, ok := blobMap[key].(string) + if !ok { + return fmt.Errorf("expected value for key %q to be a string, got %t: %v", key, blobMap[key], blobMap[key]) + } + *ptr = v + } return nil } diff --git a/staging/operator-registry/alpha/declcfg/errors.go b/staging/operator-registry/alpha/declcfg/errors.go new file mode 100644 index 0000000000..f5ef115233 --- /dev/null +++ b/staging/operator-registry/alpha/declcfg/errors.go @@ -0,0 +1,93 @@ +package declcfg + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "strings" +) + +type jsonUnmarshalError struct { + data []byte + offset int64 + err error +} + +func newJSONUnmarshalError(data []byte, err error) *jsonUnmarshalError { + var te *json.UnmarshalTypeError + if errors.As(err, &te) { + return &jsonUnmarshalError{data: data, offset: te.Offset, err: te} + } + var se *json.SyntaxError + if errors.As(err, &se) { + return &jsonUnmarshalError{data: data, offset: se.Offset, err: se} + } + return &jsonUnmarshalError{data: data, offset: -1, err: err} +} + +func (e *jsonUnmarshalError) Error() string { + return e.err.Error() +} + +func (e *jsonUnmarshalError) Pretty() string { + if len(e.data) == 0 || e.offset < 0 || e.offset > int64(len(e.data)) { + return e.err.Error() + } + + const marker = " <==" + + var sb strings.Builder + _, _ = sb.WriteString(fmt.Sprintf("%s at offset %d (indicated by%s)\n", e.err.Error(), e.offset, marker)) + + prettyBuf := bytes.NewBuffer(make([]byte, 0, len(e.data))) + err := json.Indent(prettyBuf, e.data, "", " ") + + // If there was an error indenting the JSON, just treat the original data as the pretty data. + if err != nil { + prettyBuf = bytes.NewBuffer(e.data) + } + + // If the offset is at the end of the data, just print the pretty data and the marker at the end. + if int(e.offset) == len(e.data) { + _, _ = sb.WriteString(prettyBuf.String()) + _, _ = sb.WriteString(marker) + return sb.String() + } + + // If the offset is within the data, find the corresponding offset in the pretty data. + var ( + pIndex int + pOffset int + ) + pretty := prettyBuf.Bytes() + for dIndex, b := range e.data { + // If we've reached the offset, record it and break out of the loop + if dIndex == int(e.offset) { + pOffset = pIndex + break + } + + // Fast-forward the pretty index until we find the byte in the pretty data + // that matches the byte in the original data. + for pretty[pIndex] != b { + pIndex++ + if pIndex >= len(pretty) { + // Something went wrong. For example, if the pretty data somehow reordered + // the bytes or is missing a byte + return e.err.Error() + } + } + + // We found the byte in the pretty data that matches the byte in the original data, + // so increment the pretty index. + pIndex++ + + } + + _, _ = sb.Write(pretty[:pOffset]) + _, _ = sb.WriteString(fmt.Sprintf("%s ", marker)) + _, _ = sb.Write(pretty[pOffset:]) + + return sb.String() +} diff --git a/staging/operator-registry/alpha/declcfg/errors_test.go b/staging/operator-registry/alpha/declcfg/errors_test.go new file mode 100644 index 0000000000..9da8f86b91 --- /dev/null +++ b/staging/operator-registry/alpha/declcfg/errors_test.go @@ -0,0 +1,154 @@ +package declcfg + +import ( + "encoding/json" + "errors" + "fmt" + "reflect" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestJsonUnmarshalError(t *testing.T) { + type testCase struct { + name string + data []byte + inErr error + expectErrorString string + expectPrettyString string + } + validData := []byte(`{"messages": ["Hello", "world!"]}`) + invalidData := []byte(`{"messages": ["Hello", "world!"]`) + for _, tc := range []testCase{ + { + name: "unknown error", + data: validData, + inErr: errors.New("unknown error"), + expectErrorString: "unknown error", + expectPrettyString: "unknown error", + }, + { + name: "unmarshal type error: no data", + data: nil, + inErr: &json.UnmarshalTypeError{Value: "foo", Type: reflect.TypeOf(""), Offset: 0}, + expectErrorString: `json: cannot unmarshal foo into Go value of type string`, + expectPrettyString: `json: cannot unmarshal foo into Go value of type string`, + }, + { + name: "unmarshal type error: negative offset", + data: validData, + inErr: &json.UnmarshalTypeError{Value: "foo", Type: reflect.TypeOf(""), Offset: -1}, + expectErrorString: `json: cannot unmarshal foo into Go value of type string`, + expectPrettyString: `json: cannot unmarshal foo into Go value of type string`, + }, + { + name: "unmarshal type error: greater than length", + data: validData, + inErr: &json.UnmarshalTypeError{Value: "foo", Type: reflect.TypeOf(""), Offset: int64(len(validData) + 1)}, + expectErrorString: `json: cannot unmarshal foo into Go value of type string`, + expectPrettyString: `json: cannot unmarshal foo into Go value of type string`, + }, + { + name: "unmarshal type error: offset at beginning", + data: validData, + inErr: &json.UnmarshalTypeError{Value: "foo", Type: reflect.TypeOf(""), Offset: 0}, + expectErrorString: `json: cannot unmarshal foo into Go value of type string`, + expectPrettyString: `json: cannot unmarshal foo into Go value of type string at offset 0 (indicated by <==) + <== { + "messages": [ + "Hello", + "world!" + ] +}`, + }, + { + name: "unmarshal type error: offset at 1", + data: validData, + inErr: &json.UnmarshalTypeError{Value: "foo", Type: reflect.TypeOf(""), Offset: 1}, + expectErrorString: `json: cannot unmarshal foo into Go value of type string`, + expectPrettyString: `json: cannot unmarshal foo into Go value of type string at offset 1 (indicated by <==) +{ <== + "messages": [ + "Hello", + "world!" + ] +}`, + }, + { + name: "unmarshal type error: offset at end", + data: validData, + inErr: &json.UnmarshalTypeError{Value: "foo", Type: reflect.TypeOf(""), Offset: int64(len(validData))}, + expectErrorString: `json: cannot unmarshal foo into Go value of type string`, + expectPrettyString: fmt.Sprintf(`json: cannot unmarshal foo into Go value of type string at offset %d (indicated by <==) +{ + "messages": [ + "Hello", + "world!" + ] +} <==`, len(validData)), + }, + { + name: "syntax error: no data", + data: nil, + inErr: json.Unmarshal(invalidData, nil), + expectErrorString: `unexpected end of JSON input`, + expectPrettyString: `unexpected end of JSON input`, + }, + { + name: "syntax error: negative offset", + data: invalidData, + inErr: customOffsetSyntaxError(invalidData, -1), + expectErrorString: `unexpected end of JSON input`, + expectPrettyString: `unexpected end of JSON input`, + }, + { + name: "syntax error: greater than length", + data: invalidData, + inErr: customOffsetSyntaxError(invalidData, int64(len(invalidData)+1)), + expectErrorString: `unexpected end of JSON input`, + expectPrettyString: `unexpected end of JSON input`, + }, + { + name: "syntax error: offset at beginning", + data: invalidData, + inErr: customOffsetSyntaxError(invalidData, 0), + expectErrorString: `unexpected end of JSON input`, + expectPrettyString: `unexpected end of JSON input at offset 0 (indicated by <==) + <== {"messages": ["Hello", "world!"]`, + }, + { + name: "syntax error: offset at 1", + data: invalidData, + inErr: customOffsetSyntaxError(invalidData, 1), + expectErrorString: `unexpected end of JSON input`, + expectPrettyString: `unexpected end of JSON input at offset 1 (indicated by <==) +{ <== "messages": ["Hello", "world!"]`, + }, + { + name: "syntax error: offset at end", + data: invalidData, + inErr: customOffsetSyntaxError(invalidData, int64(len(invalidData))), + expectErrorString: `unexpected end of JSON input`, + expectPrettyString: fmt.Sprintf(`unexpected end of JSON input at offset %d (indicated by <==) +{"messages": ["Hello", "world!"] <==`, len(invalidData)), + }, + } { + t.Run(tc.name, func(t *testing.T) { + actualErr := newJSONUnmarshalError(tc.data, tc.inErr) + assert.Equal(t, tc.expectErrorString, actualErr.Error()) + assert.Equal(t, tc.expectPrettyString, actualErr.Pretty()) + }) + } +} + +// customOffsetSyntaxError returns a json.SyntaxError with the given offset. +// json.SyntaxError does not have a public constructor, so we have to use +// json.Unmarshal to create one and then set the offset manually. +// +// If the data does not cause a syntax error, this function will panic. +func customOffsetSyntaxError(data []byte, offset int64) *json.SyntaxError { + err := json.Unmarshal(data, nil).(*json.SyntaxError) + err.Offset = offset + return err +} diff --git a/staging/operator-registry/alpha/declcfg/load.go b/staging/operator-registry/alpha/declcfg/load.go index 98b25da02a..43864f7921 100644 --- a/staging/operator-registry/alpha/declcfg/load.go +++ b/staging/operator-registry/alpha/declcfg/load.go @@ -1,17 +1,19 @@ package declcfg import ( - "bytes" + "context" "encoding/json" "errors" "fmt" "io" "io/fs" "path/filepath" - "strings" + "runtime" + "sync" "github.com/joelanford/ignore" "github.com/operator-framework/api/pkg/operators" + "golang.org/x/sync/errgroup" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/util/yaml" @@ -22,6 +24,46 @@ const ( indexIgnoreFilename = ".indexignore" ) +type WalkMetasFSFunc func(path string, meta *Meta, err error) error + +func WalkMetasFS(root fs.FS, walkFn WalkMetasFSFunc) error { + return walkFiles(root, func(root fs.FS, path string, err error) error { + if err != nil { + return walkFn(path, nil, err) + } + + f, err := root.Open(path) + if err != nil { + return walkFn(path, nil, err) + } + defer f.Close() + + return WalkMetasReader(f, func(meta *Meta, err error) error { + return walkFn(path, meta, err) + }) + }) +} + +type WalkMetasReaderFunc func(meta *Meta, err error) error + +func WalkMetasReader(r io.Reader, walkFn WalkMetasReaderFunc) error { + dec := yaml.NewYAMLOrJSONDecoder(r, 4096) + for { + var in Meta + if err := dec.Decode(&in); err != nil { + if errors.Is(err, io.EOF) { + break + } + return walkFn(nil, err) + } + + if err := walkFn(&in, nil); err != nil { + return err + } + } + return nil +} + type WalkFunc func(path string, cfg *DeclarativeConfig, err error) error // WalkFS walks root using a gitignore-style filename matcher to skip files @@ -29,6 +71,21 @@ type WalkFunc func(path string, cfg *DeclarativeConfig, err error) error // It calls walkFn for each declarative config file it finds. If WalkFS encounters // an error loading or parsing any file, the error will be immediately returned. func WalkFS(root fs.FS, walkFn WalkFunc) error { + return walkFiles(root, func(root fs.FS, path string, err error) error { + if err != nil { + return walkFn(path, nil, err) + } + + cfg, err := LoadFile(root, path) + if err != nil { + return walkFn(path, cfg, err) + } + + return walkFn(path, cfg, nil) + }) +} + +func walkFiles(root fs.FS, fn func(root fs.FS, path string, err error) error) error { if root == nil { return fmt.Errorf("no declarative config filesystem provided") } @@ -40,7 +97,7 @@ func WalkFS(root fs.FS, walkFn WalkFunc) error { return fs.WalkDir(root, ".", func(path string, info fs.DirEntry, err error) error { if err != nil { - return walkFn(path, nil, err) + return fn(root, path, err) } // avoid validating a directory, an .indexignore file, or any file that matches // an ignore pattern outlined in a .indexignore file. @@ -48,35 +105,136 @@ func WalkFS(root fs.FS, walkFn WalkFunc) error { return nil } - cfg, err := LoadFile(root, path) - if err != nil { - return walkFn(path, cfg, err) - } - - return walkFn(path, cfg, err) + return fn(root, path, nil) }) } +type LoadOptions struct { + concurrency int +} + +type LoadOption func(*LoadOptions) + +func WithConcurrency(concurrency int) LoadOption { + return func(opts *LoadOptions) { + opts.concurrency = concurrency + } +} + // LoadFS loads a declarative config from the provided root FS. LoadFS walks the // filesystem from root and uses a gitignore-style filename matcher to skip files // that match patterns found in .indexignore files found throughout the filesystem. // If LoadFS encounters an error loading or parsing any file, the error will be // immediately returned. -func LoadFS(root fs.FS) (*DeclarativeConfig, error) { - cfg := &DeclarativeConfig{} - if err := WalkFS(root, func(path string, fcfg *DeclarativeConfig, err error) error { +func LoadFS(ctx context.Context, root fs.FS, opts ...LoadOption) (*DeclarativeConfig, error) { + if root == nil { + return nil, fmt.Errorf("no declarative config filesystem provided") + } + + options := LoadOptions{ + concurrency: runtime.NumCPU(), + } + for _, opt := range opts { + opt(&options) + } + + var ( + fcfg = &DeclarativeConfig{} + pathChan = make(chan string, options.concurrency) + cfgChan = make(chan *DeclarativeConfig, options.concurrency) + ) + + // Create an errgroup to manage goroutines. The context is closed when any + // goroutine returns an error. Goroutines should check the context + // to see if they should return early (in the case of another goroutine + // returning an error). + eg, ctx := errgroup.WithContext(ctx) + + // Walk the FS and send paths to a channel for parsing. + eg.Go(func() error { + return sendPaths(ctx, root, pathChan) + }) + + // Parse paths concurrently. The waitgroup ensures that all paths are parsed + // before the cfgChan is closed. + var wg sync.WaitGroup + for i := 0; i < options.concurrency; i++ { + wg.Add(1) + eg.Go(func() error { + defer wg.Done() + return parsePaths(ctx, root, pathChan, cfgChan) + }) + } + + // Merge parsed configs into a single config. + eg.Go(func() error { + return mergeCfgs(ctx, cfgChan, fcfg) + }) + + // Wait for all path parsing goroutines to finish before closing cfgChan. + wg.Wait() + close(cfgChan) + + // Wait for all goroutines to finish. + if err := eg.Wait(); err != nil { + return nil, err + } + return fcfg, nil +} + +func sendPaths(ctx context.Context, root fs.FS, pathChan chan<- string) error { + defer close(pathChan) + return walkFiles(root, func(_ fs.FS, path string, err error) error { if err != nil { return err } - cfg.Packages = append(cfg.Packages, fcfg.Packages...) - cfg.Channels = append(cfg.Channels, fcfg.Channels...) - cfg.Bundles = append(cfg.Bundles, fcfg.Bundles...) - cfg.Others = append(cfg.Others, fcfg.Others...) + select { + case pathChan <- path: + case <-ctx.Done(): // don't block on sending to pathChan + return ctx.Err() + } return nil - }); err != nil { - return nil, err + }) +} + +func parsePaths(ctx context.Context, root fs.FS, pathChan <-chan string, cfgChan chan<- *DeclarativeConfig) error { + for { + select { + case <-ctx.Done(): // don't block on receiving from pathChan + return ctx.Err() + case path, ok := <-pathChan: + if !ok { + return nil + } + cfg, err := LoadFile(root, path) + if err != nil { + return err + } + select { + case cfgChan <- cfg: + case <-ctx.Done(): // don't block on sending to cfgChan + return ctx.Err() + } + } + } +} + +func mergeCfgs(ctx context.Context, cfgChan <-chan *DeclarativeConfig, fcfg *DeclarativeConfig) error { + for { + select { + case <-ctx.Done(): // don't block on receiving from cfgChan + return ctx.Err() + case cfg, ok := <-cfgChan: + if !ok { + return nil + } + fcfg.Packages = append(fcfg.Packages, cfg.Packages...) + fcfg.Channels = append(fcfg.Channels, cfg.Channels...) + fcfg.Bundles = append(fcfg.Bundles, cfg.Bundles...) + fcfg.Others = append(fcfg.Others, cfg.Others...) + } + } - return cfg, nil } func readBundleObjects(bundles []Bundle, root fs.FS, path string) error { @@ -123,46 +281,38 @@ func extractCSV(objs []string) string { // Path references will not be de-referenced so callers are responsible for de-referencing if necessary. func LoadReader(r io.Reader) (*DeclarativeConfig, error) { cfg := &DeclarativeConfig{} - dec := yaml.NewYAMLOrJSONDecoder(r, 4096) - for { - doc := json.RawMessage{} - if err := dec.Decode(&doc); err != nil { - if errors.Is(err, io.EOF) { - break - } - return nil, err - } - doc = []byte(strings.NewReplacer(`\u003c`, "<", `\u003e`, ">", `\u0026`, "&").Replace(string(doc))) - var in Meta - if err := json.Unmarshal(doc, &in); err != nil { - return nil, fmt.Errorf("unmarshal error: %s", resolveUnmarshalErr(doc, err)) + if err := WalkMetasReader(r, func(in *Meta, err error) error { + if err != nil { + return err } - switch in.Schema { case SchemaPackage: var p Package - if err := json.Unmarshal(doc, &p); err != nil { - return nil, fmt.Errorf("parse package: %v", err) + if err := json.Unmarshal(in.Blob, &p); err != nil { + return fmt.Errorf("parse package: %v", err) } cfg.Packages = append(cfg.Packages, p) case SchemaChannel: var c Channel - if err := json.Unmarshal(doc, &c); err != nil { - return nil, fmt.Errorf("parse channel: %v", err) + if err := json.Unmarshal(in.Blob, &c); err != nil { + return fmt.Errorf("parse channel: %v", err) } cfg.Channels = append(cfg.Channels, c) case SchemaBundle: var b Bundle - if err := json.Unmarshal(doc, &b); err != nil { - return nil, fmt.Errorf("parse bundle: %v", err) + if err := json.Unmarshal(in.Blob, &b); err != nil { + return fmt.Errorf("parse bundle: %v", err) } cfg.Bundles = append(cfg.Bundles, b) case "": - return nil, fmt.Errorf("object '%s' is missing root schema field", string(doc)) + return fmt.Errorf("object '%s' is missing root schema field", string(in.Blob)) default: - cfg.Others = append(cfg.Others, in) + cfg.Others = append(cfg.Others, *in) } + return nil + }); err != nil { + return nil, err } return cfg, nil } @@ -187,47 +337,3 @@ func LoadFile(root fs.FS, path string) (*DeclarativeConfig, error) { return cfg, nil } - -func resolveUnmarshalErr(data []byte, err error) string { - var te *json.UnmarshalTypeError - if errors.As(err, &te) { - return formatUnmarshallErrorString(data, te.Error(), te.Offset) - } - var se *json.SyntaxError - if errors.As(err, &se) { - return formatUnmarshallErrorString(data, se.Error(), se.Offset) - } - return err.Error() -} - -func formatUnmarshallErrorString(data []byte, errmsg string, offset int64) string { - sb := new(strings.Builder) - _, _ = sb.WriteString(fmt.Sprintf("%s at offset %d (indicated by <==)\n ", errmsg, offset)) - // attempt to present the erroneous JSON in indented, human-readable format - // errors result in presenting the original, unformatted output - var pretty bytes.Buffer - err := json.Indent(&pretty, data, "", " ") - if err == nil { - pString := pretty.String() - // calc the prettified string offset which correlates to the original string offset - var pOffset, origOffset int64 - origOffset = 0 - for origOffset = 0; origOffset < offset; { - pOffset++ - if pString[pOffset] != '\n' && pString[pOffset] != ' ' { - origOffset++ - } - } - _, _ = sb.WriteString(pString[:pOffset]) - _, _ = sb.WriteString(" <== ") - _, _ = sb.WriteString(pString[pOffset:]) - } else { - for i := int64(0); i < offset; i++ { - _ = sb.WriteByte(data[i]) - } - _, _ = sb.WriteString(" <== ") - _, _ = sb.Write(data[offset:]) - } - - return sb.String() -} diff --git a/staging/operator-registry/alpha/declcfg/load_benchmark_test.go b/staging/operator-registry/alpha/declcfg/load_benchmark_test.go new file mode 100644 index 0000000000..780620c5cb --- /dev/null +++ b/staging/operator-registry/alpha/declcfg/load_benchmark_test.go @@ -0,0 +1,298 @@ +package declcfg_test + +import ( + "context" + "encoding/base64" + "fmt" + "math/rand" + "os" + "runtime" + "testing" + + "github.com/blang/semver/v4" + "github.com/operator-framework/api/pkg/lib/version" + "github.com/operator-framework/api/pkg/operators/v1alpha1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/operator-framework/operator-registry/alpha/declcfg" + "github.com/operator-framework/operator-registry/alpha/property" +) + +func BenchmarkLoadFS(b *testing.B) { + fbc := generateFBC(b, 300, 450, 3000) + b.ResetTimer() + + for _, n := range []int{1, runtime.NumCPU(), 2 * runtime.NumCPU()} { + b.Run(fmt.Sprintf("%d routines", n), func(b *testing.B) { + for i := 0; i < b.N; i++ { + b.StopTimer() + tempDir := b.TempDir() + if err := declcfg.WriteFS(*fbc, tempDir, declcfg.WriteJSON, ".json"); err != nil { + b.Error(err) + } + b.StartTimer() + + _, err := declcfg.LoadFS(context.Background(), os.DirFS(tempDir), declcfg.WithConcurrency(n)) + if err != nil { + b.Error(err) + } + } + }) + } +} + +const randomPng = "iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAAAXNSR0IArs4c6QAAIABJREFUeF7t3dGR5UiupGGmMK3UlDCdLUxdpUaYXOu7r5v4xtqXVj0zf74yyUMiEAgPhwPx8TxfX8/19/lxXn4+79u/ft73f/zA/c99/x/P5/l+v+P6c//8/e3P83z8AfN8vvt+f3zcz9cH/P5zu//5gV+Qff8H9/8D1+Gez0/c//L7//Fjs+/n8/v5AZpf6+/LPzh/Mf+fdXzlX/IP3P/xscWnjzXAIP5+vhxfFD8ezV9N339u8VPzQ+//9YX1CePP52P90v1yH60/Xwg/HwEADsH5DxqAtydoAADjFwCYHDwAEAA4HSgAcAP0AEAMwOUhK0MRAAgAXBaIAdgYqhgA2C8AEAC4LCCKkhRiKYDTwQIAAYAAwGGBUgD3BFEKRfxRACAAEAD43gKlAMYdxJojLgWgEH5eLwVQCqAUwF+fQl+lAEoBlAI4LKAdRADg3mFAZFcKoBQAtqh/fXX7807NXzz9IxHgxNBIg5YIsCqAaYfH6PCyin5WiccAcAhPgIoqEabwqgKY7P9UBXDaryoA4IeqAGCBMQcmBFYKoBTAsgIowEljEwMQAxAD8L0FKgNEHwAFGAU37RA+n7uQXip59gEQB8IPuP9h/v2RQlOA5wKy5qiww14pvt8xflRpo85XIkr9Pt1HdeRrHfLbO0R9oAA0/Fv+Sw0CKGT1KeHnrX1MRv/j/H3Zf2QfbXB0v65z/N/uI6P4M/aBkf2+fpOF7uuKv+wDEAAIAJwWCACc5lkBiu5/nSJW/AkA3BvsAIA8aEpRaoMpEd66gVsZ4ABADMA0QbSD4g4iBuAOQCODpAV8piBjAO75g06lmnzaAHEBCgDIxAGAwwIxABDxrQiO3ok64vn3SwFMC/C6wJYC2FoVq1WpVOICsKSASwFMDJQYJMVH7WB1v65z/EsB3OOP+VEKQB4YALgtVApgCsAxADgrQ1UIAYDJ/wIA8L80AGqlBRECEFoiQCEQaBBw2EwpABwmhcOUEgHCP9MApAHYQlgpgFIA31ugKoAAwGWBUgA3wBFFq/nF2B4ACADQSf76P5QC+Ou2+/POqgBGEZc0cmkAwACNnb60Aw8ABABOD0wEeE9QHfeO9UcAc1u+nicAsFmQAODrCzIeiNT0A1/3ceb8Oom05IBSUVKEBBEiGORHvy8DyL66n3XQCgAKoLif448Mk85TVw6d9ln/Qe+vPlTj/BBA5edJw7Gm8ATAlWEUw6AP1PN1P36fAHTthDj2UdDnMUWIKgY9XyLQR51E1clTL4BW4msZHxk0vb++X/6HPgRafz4CABCBBACmHUQA4DYf7aMAty5wAQAMEBguNXoKANwG1AKoBVTzIwBwWigAABGdEF4MwL0CcYHTDhoEVQyAIiCuBwACAIcF5vmlMucAwOZ/MQD3Dl4USCkArMClALAFxOVSAJP92GdA+GdlSETBxgDcIxAA2BgQ+V8AIABweti4gK8aghiAUgA3B4kVPA3AaSBtYISP0gAgw/m5pYgfpTDEgAQA7gFIBIgpHgBQDNyuK4URAxADcFkAOWqJ6AIAmL5pANIAXBbQBEoDAAhaFcA9wQIAAYAAwPcW0A5YO2jB9wBAACAAcFigMkCFkGkBo0i0MsBJBMXBSwNwZwif2wETAf6HpwCez1tmIxGd6jgVAEXhsxEEGs3w/RVBRgSp3xcDIfswx64+DjpMYy1jEkUulb9+HzsINWrS8KsRkShaPV+nya292uV/er91frMNwMqQSGSm+SsRn+rg17NCUGbMHPKYQnjG+9WnhOMvlacYxt+Az7U+CICv8RONOrQ+cn4ixatW+x8BgHdzSArAAYA7xaDjWLVABQAYQu5/AMBSAOMCEAC47S8KfFzAAwCYHwEAGGgMENrhxgCgyuFtBKsduAJQDMCdgwMDEwOwBWgtcOzkFwNw+6922AB46vQp/9cGiwzF2/EzBuCewAGAscrhbQcOANwOLAoa61cpAEgARv8OAGwMp1JcXGADADeAgn3I35UCQABBjogGVg5xbMRQCqAUwK3S2lRs2iHR/0eGrxTAyyIyMXACqOP9AQDErxiAGIDLAgGAAEAA4HsLrCLXGIAYgMsCq3+JwfsKAAQAAgDfW0A5wESAMQBnBBl3uGkANo1FDEAMwJTjSAOQBuBE6NIgVAZ4zr9SAPcCFwAIACwA89+eAfj6eRdirh+oOlY9X3WMqhJYy8T0fCFg5VhJQekBKlORSlciK4nYUEet8dPnyf66X+Mv/9T9KoPT+xEAo058LXPU7wtAyP91v+yrMnGd566zLNTo5o9xgOm/ysHLgVRlM5ZZzvYFBa7Pe/s6GUhUgcwA8mUGS1UUHwEAiHR+3tcVAOXAAYDbQgygMvDaanQUwen1tACrFXUAABaGSjoAAIYEImcCrADAbeAAwJ1D0Q6SC8RIEev5AYBt/LRAyv66nztMNVoJANwpPjFMqsIRQBtPQ+MChR1eDMAIsAIAAYDLAqUAuIRNDiSAsjIQosAE4PT1AYCbgYoBGBeoAMAN8GIAbvusraRjALYdJBeIGIBbJJYG4F5BYgBiAIRSj+uMT2kABuvut6YBSAR4epEmsHbYctF1Bz536goABAAOC0jEJ//X/UzRlAJAkh6XEwHeAFaHkSUC3OocpbIuBSCIgOtVAUwLuPxTC9QoEn8SAcK/AwABgDFEninoAEBlgJeDxAAg/lQGOIWnAEAAYHKgygBH82GD+5/OAHxCJssFcDzNjBQhcmRS6X4+N8e9dppTDmkWwaEOXDvQNcUgkZ9aXa513Hp/1SmvC+z6/opO7JWvF8B56VLBq05Y70cGRQYYc+Ca/7/jA+jfakQ1nhUi89D/VxGaAAT8T/FN9uf4oQxb9hODJxEt1w9VOYDB0u2cX9IoYfw+AgCYAaOBNUHkwKoDDwDcFgwAIAIBQAQAEB8CALeGCg4UAMAKsJYpBwBiAAQyzhyZdhiCsGMOlzsglCkFAAIAk3/HAJzhQxucGABEXx31EQC4DSgESQpHEzwG4ByAUgALvHoe7bCVYhKFXwoAnTwFcBUfYgBiAC4LlAK4IU4agHsBKQUAEWIMAHIgMQAxAIcF0gCA4QCDPDKguj0NQCLA00HTAKQBuCNYACAAEAD4zgKJAKsCuFeQUgClAK74qVapyBCUAthSKEoBKgddFQAYtqoAXo1/MQA6LCQGIAZgWIATAcYAxADEAMQA/L8t8KcE5owQopgVYIXvdb+uK0fOHMoo4uH7oY71jx/o1QkDsk+DTmvDz2v8Nb7SeKgT5NqnQWX0aqWs71MrXN2v6/KvVeQq/9PzpQLX/Rpf2Vf20fzQ95NBGBkgjT+rYCRiRCMb+r9Oa4RKfR0/ja9ErvIv2Z/xiVt4/cJ9XSkK+adeLwAQAJgYBrl3AEAW2jQM6wKrBVDPDwBs46u7AwDYoXyik5+qODAAAQDZ/3PbwQrh6XoMAMqcYgDuKa7jOBUgYF8FeF2X/2uB1g4oAHDPH+2w1IlS46vrAQAtQAGAewcHjUcpABhoLTMrBXD7J1pJawFTq89SAHedVwAgAHBO0FIAp3nYB0UID9dLAYBhiAGIAcAMjQE4LBAACAAEAL63QCkAMTClAM75s4qQBCD1fIlwWIa2ZXieNAAawTQAlwXkv0qRaH4IAJUCgP8mAtwmeAzAvcJwguO0vKoAbg8LAGzzVwvU9vTnkf+nAcAOfkzBBQACAJcFSgHEAMQAHBaIAdggQABgY0hiANDrVyLYNAD/2RoAHQfMHYYKDdfT4NAoiDmatQ5W55WvpzlpfRgbIenxuq7x1/06rGYGCPA/imiwQ5R/8fuQQtH7yb4CCFSRQ+Sq+/V+qjOXfb8wf9XJj++H45BlX80Pvf/ayXC1r+yjMk8xJFoe9PuriFf+xd/HP2h86Z86jvs+ioCvr9//CADAhgEAOtn5D3LwFeAFAO4dCgKIytgCAEhRPjgsBgAmAKAVFtfBYAQA7h14AEAUWAAgAHBZQAAnBuD0HwXoeYcl740BuPH7c1NEMQA3BawdOBnEGIB7Bq8BRBTaEwBQCEWSdjsOmuMbAxADsHhoACAAMPjPDFC1gQgABAAuC4hCHHz7f29VjpPPl4OXAqAJTwICIlxR+KUAboCaBiAG4Jp/AQCpPBIBTgFeDEQAAJ3uUCYqlbgYCFJ4pQBKARwW0Pwlxf5yDjwR4B2+AwABgNtD0CiD6KAqgJviLgVQCoCT6PiHUgClAAb/CQAEAAIAJ0edBuBM4aiRFYKTKOpSADJgKYBz+iYCvAH2WqaqFOnbGoCvL1Rarip5zL+3KTC1+hzA3//eOlN0OE1OAX4+C0EGQCOQtY5dFLxeTxS9OnV9vNzqWO+/+qfsR/sogOm8ex3Hqj4cax8NNapBClLxR+On+fehQnYtAKN/6vc1P9ZOqqt9Ff/UR0QpVKn0f3kKBAyy4ofs9xEA0BS/rwcAtgilBUyjwwUODFUAAGVMAYDTBQMA9wwNACiC4XoAAAsMGAohpHF4YgBGCjsA8C6AIkCKAZhCQAAgAHBaQAyXvC8AEAC4fEQBiBSeHLAUwJ0DRBmjzLsCVAGoAMC7C5Tmnyj4tYpE/qXfLwVw54hKAaQBuClAHaenMp00AIphN8D+cU9gBbhSAKUAFgcMALwLsJTDTgOwnaabBmCZ/YkAn0SAmwPFAGw50CcRIBjoDSCTQXy5TDkAAID1IwBwWmgNsArviQDfzWHL/qS4EwHeKYw0AHKxRICXBQIAt/+kAdgoonWBDQBM8e3RDisGYLPv6p9pAGD/ygBvAKg+LmpkFgD4NwcAz12ouuZIReGo1/zXT7R6FQWi4zrxfC2Aso8asfAwIsS3D2gItDxxfNBrnvfD/hTZ/NwYBi2wAphrr3zVGa+dxKRx0PjTf2F+3j8eR/yoz4DmLxYoje/8+0hRrPbT+i0Kf2XQtAFYAapEkvJvjp/6VCj+okx21ShofdD4Kb5+fAUA7iF+ewJLZCkHDABMKaAAwO1g0riuC9jrC3AA4FURbQAA80dVQjptViJyiKADADEAp4dyBx8DcFOo2uH+CbGPvxgAINwYgI1iBoWvHaQYpgBAAGBbYMYFWhTvmmIoBbCpTGV/IVRRiKIA5R8xADEAdwADgFMK4m0GUSKzAMAEwBVfxGCVAtAOMgAgH7spvFIApQAGDyKFnwbgXkACAKd9BODFQKQBAAFUCgA71BFgxADEAJwUfimALUWynjWgBTgNQBqAIQUnbB0DoBReDMBtoUSA0w5CE7QUAHYQ2OEnAiwFcHlQGoA0AGkALoSp85wDAAGAwwIsI2QdWADgsoB2cCwjEwORBmBiIEoBvJwC+ISHq9c1EaBOixsbTWgCsw4fW0g9XztQXdcOS8eJq0709RQGREg6jET2UQCQyEYMgESK+n0uEOq0hyoB2Ucqbd0vDYCqRCSi1HGwer6u6/c1f+U/nD+coBoB7CAB8BR/t19/HuXw1+fz/vEwMq1fik/qQ/OMKSb5t67LfvLvjwAAEJZylBoBXA8AKId0Iww5eABgYwAUgLQABwC2ACGAFwC4c1gBAM7/u9BWBpQD6n51qloRVgwAHeD8B9ovBuC2XwzAliKEhkgAJAZgAyAxAAhwMQAbAgsAiCLAdWkIfnEOUhQbw9NnDMBlI+0QZd9SALCQ5k8pALnYdr0UwGQ/MaSlAGBe7SCm0XmepxRAKYDFhwIA9wZE81cBMg3AdhbH4tv/e28AYDKh/DsAEAAoBXBZAAxEIsB7gUgDMMXvRwBPKdjt1xMBJgKEil8OmAbgnoIxADEAS5DWAqFnlwIoBXBZIA1AGoBzhgQAFGIDAJOF0gDcDM3LfQCqAri9d9a4YHII4Cn+TnPviQGIAVjr+EcRjQ6LkYOrzlsTTCLFD/TiVw5G76/rKnPT/WRo7kZoj/oQyD56P1UhiGKWSpzr59inYn4/pajW0wbHMlf5t3q9a35z/uo8d4hkNX/WHbD8n/Yb44vsrwVO93P+olGSnr/6x/p+0iBQA6rDmvSCY/xRfJs1AFogZUAhaDmA7McAIgvpNK1xgur9dV0BTPcHAGChcQIGAG4EqfnN+RsAOB1YC2wAACs0NrABAAXIGACtwdP1AADKUCWyEEKXf6MOOAAQALgmeAzAu/6h4CoApA1sAEABMgAgH5yuBwACAOcCo0ZEpQDO+VcKQDlAaJxKAUzxnQw7NiAiuEsByEKlAG4HRo5VOVDNjjQAEKGlAZj8UwA6ABAAOB1M5hHDqACoDXYA4LYgc4gBAEB4eGgA4DRQKYB3Kd6vNABpALSIHtdLAYynAZKiKAUwuKdv1Q5GT0gEmAhQPjLlsH8EACb7jSLjRIBbiiINQGWAN8IeJ+gSfP+8NwCQBiANwGGBygBvBnvM0St+aYctgLJWiazv9x8PAL6+bh3jh3KMcCAacMxx6P3kQMrxaYHV/XJAnXbIOnvssNTnQJ3glIPX94kC1/1K4XB8UQUg/1kDmOwvFbHsJ/+TBkMqdI0P58dYhaFGN/p+vb/ik8qUlYKQf/H98A/yf82fR62u5xe8GSDNL42P/EOvzz4hesDbKdDf9AL3dQGsjwAAepn/wA7z53hYhkQccrAAwDkDNMEVoBWgNMECAJgfEEkpwAcA7jKOAMC9QCo+cPlVfAZDrOevAF3xKQCABZw7nADA6cPawWoCKIBpB6QJHgDQCNzXOT9iADYDxwDc8UUpathP8YGDFwAYOymVArh9TA4WAxADcFigFABC+ChSLgUghFIKgCDi+IcYAFDk2sFxhxgDcPpnGoAb4IpiKwVQCmBZAHSv4psYtDQAYwpXG7RSAHDhGIAYgMMCCmAKgKL4BCDTAJQCuCwQAxADcFlADJwAXgxADMDpI+sOtCqAjaJc7V8VAAAGcryJABMBahG9rmuDwGfHAKQBoJNc/1AVwGm+GICtCkU7kHWHkQgQKSKUUU+x43keMWCaP6UA/stTAM/nvQf5/NwCEB1cIhyMjwLYHABfXqA5AT+3HSoDtKoYxMDgMBlpCFQloE6FKhNTAFQA1Q5zZgAwQcjQvFwnLA3Dan/GB/yD3m+2n+a/PkC94NFLXikq/TztAwqK80NVHvJv9ZkZD7Pi641nvcj+uj7HR8RvxaePAACGSAFAFBBU+gEAAExQwOsCxAA3TjAFYAWIeQFTAB6rSFb76/t1Xfad7af5rxcMANwpzADAaR9ukMb4FADQDkoBIABwOvCMcAMAt33lvwGAzX6a/wEAWSAAcFhgjo8BgNv/SgGMKZxSAHcAG3fQip7zDjYAEAA4LKBWx2TIyLEjPscAxABcFlgDYAAgAHD5FwPciLBFUQcAZIH7uuy7xg+e1aHXLwUQAxADcFggEeAdQhIB3ggZKYJEgNiBjQxGGgBRLLieCPBmaBIBnvZZRcppAJRDVQ4wDUAagAvhP9oCYoEeq2C4QQ0A3CbS/KeBAwAnw1sKoBRAKYDDAjEAMQAXwBCA1QY1ABAAuMLPc9f5ro10VObITosqQ1aZf2WAdyGoVIofGoDfBZHv62sZxPbrz7OeR71S0Hr/lQJiDhwiH43/AwCj71OOV/er054CEJ+P89TVp4J9GmR/NZrB+6nPh75f9+v7VaesBWAkWB76B+Kb7KP4+YBB1PPX67K/ns/4MZ61Iv96/fpzL2D0T43vmAJXfNX4MAUgB9YCoPvlYAGA20IBgF9LsaqPgxbAAAAaXSEHHABQBEWKSX1K8HgtMIpP8v/XF3g0utMGLgAQA3BOETmQJpCmtyaYEL5+XxSfAKAQqr4vBuDmMMlgxADcLiYRXgwA4htSBDEAt//FAJQC0CJ4XQ8AxADcEfoWIWqHJd/U/WJABFC5w9o0lqUAYgCmDRz9sxSAQkgAYLFQACAAEAAYZlAMwGA8H0ak+FQKACkaiRihsRLDmwZA7g+KZq2D1gDp9TTBtMPS75cCUBL03oJqB6wASPsnAtQUKQVwWEDxQcZl/CgFUApATnRdTwR4Wy8AEAMQAzBEmBiAwXgxAKUAEgFOOSQhaM3OAEAAIACgWXJcDwAMxgsA/NsDgE/ItLnA/PP2H4mERHHKO8kQoI6a96PV7INGEuolLhX318+bYhaFJ4ChKgXZn9fHOnnZj78vEY4eMKaA5N/yP82ftcyW/rfW2Wl+yP66rk59b4sEx052Mq8O65F5VKY6V+moTFMviPFZU6xr/Hx7gad5pAHQA6AR+AgAbOfRBwDezZEHAG7/DADA/wIA2KGBAhHBFgCYcvxav3WYle4XwAsAwMK/xwDQxxYKWiK5AEAA4PSvGAAs8EBAa6fOAEAA4LKAKExRpFp9RKHq+bw/AKAhmAJQAOBe4DV/YgBiABYArh2iJj8pcj2gFMBpoRgAOBAX8DQAd3xAr2vNX15PA3CaSP4bAICHxQBMADwAMLailsYIGiLFzwBAAOBGiOjklQhQUwzXEwFuBkwEeNsPO+BEgGDIdFjPKKImwxEAAADFYQui6BV9tIPS83l/KQANwbQDKQVQCmBysBiAaf7FAMQAnBaoDBB1GNrhIECxDGtEsDEA0/IyHwe9AtBSAKUAJg9GCi4A8F8OAL5+3idis1UpdsjKYXAHKI0P+hBAAsDDQDT5tIDrfl5XDl11omp0MraS1fvL/vSP+zjuh/Yf7UcKdny+7Kcy04/V/wVglcPE/Xy/32iB+x/EAICiXePbWqcugP76BuzlVr0SqYqBJQBW/JN7rf6L+LT2eZB/yD4CeB8BAHkIUnhaQLfHP2rkoQX2hnfPvIDq8/R+AQBYcA1QCpABgHMAVAYcANjKVAMA9w4tABADcFpAC2wAAIf1YIGMAXgZoMQA3AAEO3QxLNohimEQQ6LnxwBIAxoA0CbyvK4JsC6QejlS0HqArq8UcymACUAFAAIAlwViAGIA7gUqAHAH4HEHEABAgA4ABAAuC5QCKAVwWCAG4I6vYjjSAIBiTQSIBTwG4AbY0mCM9osBiAGIAfjeAqUAlKOOAYgBEM1/XR8XsDQAaQBO94sBiAGIAfjWAmSYqwK4t/hUeZcCuOFBACAG4LAAA1RVAKf/iOKuCuDdRlVVAfzNRYAMMFrAUUcsivVLSRTtrtcyqhXhKQDr/XFal+wz21cagj+QI4N/KADLPLq+qpzXBUC//6jOfjut9VGA1ft9oNW07M/rY6Oat897p/3UB0UU3Pj9si/toz4Sin96ATHkSOHp/XVa6Ifik74PfSQ4PzS+sI9E7BShohMv+wAEAOTByPEEAKYd2BhfHi1wAiABgBGBaAAVIAWAx06Z6vUeANAAbtdVRRUAuO0bAJD/xQDcGgwxLDEAN4DBDlAAJAZgO69eC4R2aAEAMHjaISv+av8UA3DHZ2wgAwBywABAAOCwQAwANDylAM75I4ZIKTh1+lQrV4U/AqRSALcJSwFsOV7tcDRBlOPWBJh7qQsB6zjPUgClAC4LpAG4p3ApAIa46x8CACPDEQAIAJwWCADcDEMiwHsCBQACAJcFAICEDgIAAYDLAokAVwosABAAOCyQBgBLVCLACQAFAG4LVAWAFJ9OA6wKQCoWOGApgFIApQC+t0AAIABwWEAMRmWAW5+Gj6+vu1CVZTDjedLcIWH9lYjr81ESXxgaFBJU9GqEtP3686hOlBoLlFHJvuv7a/z1++v98g8exwn/0v2/YwBVJkX7a4HFA9jrXC+AHKo0Qiqj18/LftQYoQqG8RFVIuv3zd+P+a/xkQpd85PvD4ZWrYjfnl9vz29VqYjhkIg0ACAPVIAMAEwWVIAIAIx1+AGAO0U1lsEGAO4dqOa3gocY6ACAUmx3/AgAyAMDAKOF7tsVIAIAAYDFAWMAbv8hxQ6RagzA3WpwZSBiAEoB3DsYaAxKASBHNlL4awphDRBcHGMAYgCWHHsA4PSfUgBpAE4HSQMQA3BZIABAio0Y5/qHGIAYgMU/5HwBgABAAECz5LheCgBlOmiVStPHAMQAxAB8awEBRM2vAEAAIACgWRIA+NYCMQAxAMP04a1a4NIAbBqbAEAAIADAMPT9P8QAxABgiz541/NwAawK4LZvGoD/bA3A83xNEEgISCIp1eFSZepC+NvBp693bFKd5hda5eo0s9n+Ok4VdbiqM6WFQFGrDp1lWACofD/8g8ZHz5f/S0Mi95/PwpDIFNc1frKP1ue36+hX/5J/aP6KIVrfT1U2it8aPzIMeADfD+fda35ofeH3K34hvqvPguyr+KAyyY8AgEy8XQ8AwH6aQOjjtAbAbXSfRwFezw8ACGG9myLQ+Kz+Jf8IANwjEAC47RMAEMRDr/63dxABgADAZYEAQADgskAMwNbqVstDDEApAG0CpusBgABAAGCYQr8YwMcAbK3USwHA93UaqPAxUnClAH5xAAkABAACAAGA7yxQCqAUwDA7nlIA4ngCAKd/CaGrF3ciwE1FWgpAW5w0AJcFVoaCOfbxMDXFFy1+fL9EgKcJYwACAAEARZnhukReenQAIACQBuB7CwQAEgGeFpBI5leXEZUCKAVQCkAw6Lj+iwH8usMWQCwFUApgmB17CuDruXXwPEzmCzNU54H/Aw6AJIcoDmcI3u2VrSqDGSCgTl99BtY6VH3fDMDgPwqwD8oM5T8CmGujGeXwVEfPBUrn0Sv6/MQO5Mc9f7jAqU8DRFKMTzquWw48lqlqftP/ZB8RKG/38RC+f3BanvwT/ieGQO69NiLj87UAafxu8z2KD4pPf3YaP2cwJ1gA4B5CpIgVILSAK0ev+wMAOM8cE1gTbKb41z4ICrCKYAGAO4WG8dH8DgBAxh4A2PwPZ4kEALADoIhFZRwBgAkgPTEAp/1iAMDgxQDc8+9zE7EKP5IBEkANAAQALgsIQYuBIcOBVrncQQcAAgBXintspRsACABcE0wM4VzFUwpg06iVAkgDcIrEdFZAGgDscG6NigBkGoA0AOf8LAVwOkgMABB+ACAAEAA4LFAKoBTAxaDyks8mAAAgAElEQVQohVcKoBTAYYFEgIkA7xxLKYCNwl/LuAIAAYAAgFLt314vBXCbLgAQAAgA/OXw8sB7nqcywBsBVQYIirQywGV2PgGAAMCpEfkcVSDKkUrFLe/+1Q6s99P1L5RJSsSl86hVZqYyZ73/+n6qw1cdq96P11cGAvevp4mxygR9MgSwBDBoP6nEVSev89DHPiB6f84fzE+VedK/X/7+Nf6qj4b8U3X40tho+VF8W+ef/Efjq/fX/SrTln3FYDyYXx8BALrA9A8BgHsFDQAAYQQApvkXALjNFwCAewHgBgBUZ6dOgLB/DMAtMxZCjgGAg6kMOgYAIjIAvJd3wEIHAYAAgHzkvB4AQA4lAHBrCEoB3PbZjhv33C4FYBtd/1EK4G8NgEoB3BoSAUBOjgBAAIBOcvxDKYBSAJf/KMeqHF4aAKzPOM5W8zMNwD1/laNOA7AxZLJvGgDtUJbV+//DvQowq8iuFIBySKUAJjfW/EoEeDNcL6dAYgBiAE4HTAQ4hb/55gBADEAMwGGBqgDOGKMNQgAgABAAmJfp9x4QAAgABAACAN9aYARAAYAAwAQAvn7iOGCc960cpspMWCe5isRGFffvL59WpRzOnAMSQ67xHeukmaLQ++mwHFxf64RXAKfxXXP8+r63/VfQWd9P/8b84/f/vB1Ev6/v03WJ0N7ula8qKmm41yoi2UcaC60vGj/ZX+uPNAy6rjJBfR/jg6rslAIIAOA8+ADAOYc5gaVSCwDcFvibA1gF+ADAvYMJAOA0R7RiDwBgBgYAbgNxBxEACAAcFmCOFjtQIvwAwJ0jx/xcAYgAjq5rBxoACAAsFD477QYAAgCXBZSiEQUeAwAGKQBwL+A/NgaOAL4UwGn/UgDbceGlAEDRaIFRDmZuFfs330GtOxTdrx2KxicAgDpoNNvn+IytfrkAvsxgyb/0/aJwpWHg9wcAAgCXBVDGqgVe19MAQGQWANhESgqwCtABALRaHjs5cnwCAKeLBgCgcv0JCck/7+sxADEAZxKGC0QMwEZxjjsULjAS2VUFcO+QAgDCkPcCvvp3VQC3/QMAp32kwdAGVDt8XY8BiAF4N0AqxxwAmAKEUiCJAG8HE0AtBfDHxIA8AYBpfgcAvu5KTwY4cEgft39zdyGEpQDDOtixVae+bz3vmQbCP6wIWL/P8Xk5B63xf37oC0Chjn0IIBF4RMF+oBBbdcRi8BQAVw2O5od2SBq9uc8E7EuVvgfw/AT6x9oHRRsAxGfO73EDovFllcz4ffx9/YNaZfN+iNTwfPmnxu/jKwBwD5HKKDCBAgBbDpM7RAWgAMDt3+rlPy5AAYARYI721/qj8dECQgCuF9B1aWQCADcD8nnH3wBADICm4ORgEnGJwgwAbHXSMQBYgGMAtvktAD5Fl+eJAbjnfwwAHLAUALYQOu9aKQYgzADAbUAzyAGAy4KlALYVNgZgs9+awlIKTs8PAAQAbgSP89DpgAGA0wJcwFcNQRqA2/5rq+kYgBiABQOkAUCOIRHg6V6iuBff/PPeRICbBSnSwgI/3x8ACABsLnzeHQMwGjcAEAA4KUpoDAIA9wSUfShCSgR4GzgRIBg0lOmRAoIGQQxRIsBphRbAmR7+vzusO0XH5ysFWxXA1ms9DUAaAE7C4x/mHbwCvBiEGIAYgMWBca8WyKoAlAP9dwcAjyIMDKDziHE7d3hC2JoceD+ppCkywvhrgglBrr8v84wpVHnPo+evde76PgJA4KO3Dztae9nP3w+GivMDnRL5fh+bypkiU70AGunodqrUx/go/+X7YQepRleav/z9X92oSPFfrZLFwKCMH6vroz47AmCyv8rQ/5x+kBkHALAFmXJsAYBN5a4JoACqRjcBAIxPAOB2wQDAHR+1AIMh0wKr43LX+ECAhA1iAEDHgcYA3AFmZKDowFph9ftAyDEAW4pLw8MAFwMgE97X1agmABAAOCwQAAgAbDlOLcAKb6KwdL9+PwBwWrAUQCmAy0EE4DQ9yTCKwVnjQymAe/5DZFQKIAYgBoBR7vt/UAAtBXAbNw0AnC8G4DZQACAAcFkgEaAkGIDg2oFr8VwRvn4/BiAG4LCANBbqdJYIEBM8EeCWgkgECAcbc1wBgADA5WE67Y74RiKjqgDuAInjvKkixwAFAMDAwH/l/6UANvuKIaSGKhHgPQABgABAAOB7C7DRkRZYAaBEgFxDz38oBVAK4AxgWP9+tQbgExCRAQgTQCrH9fmqs5eIghSiKG4FYNQ5r734ifB/3hw8c+RjJ0OO7xZ+eVqYdpiyv3YA8j9JWGYRIDodro2MdFqj/EfDK/sqfqytrhkfcNYINzA6qwQMC1Mg4/tpfDR/9f16vsaPfVDwA5pf+n3ZX/6j+Cz7iAGlRkfxPwCgVm0aIlBMAYDNgLobADQAcBtQACUAcMcHLYBaQBXAtQDp+Xo/Ta+3n68FOACADZxSdAEA1Fk/AYCTwYoBuHPkOOxKC6x2KArATwzAvYah17p2cLK/FljdHwC4RTgBgADAFIA5wQMAp33VSnINgNqB8HoMwD0/hG/VaW0s49L4lQIY+yCUAjhdTABbDIQYGK0vpQCQhBRCVq9t5WA1QGkAQBHHAEwANAYA/oUqjDQAOI0wABAAOCxADUEaAG2RtIdJA3BZgABvM28iwFIApQAOC4ih0/TT/F2frx14KYBSANMOLAagKoDTgZAjFkUtBioGIAbgskAagDQApwZLIr5EgNgAfCYCPAPQWCeuHYB2ENqB8HoagDQAlwUSAXIKLQye5r9+PAYAAPltAPD1dR+oqDIq5RhWB5EDcYEBRSqRCDUCEkkJoaGVlN6PE2g87IOn9eH5aw5X/iUVvOyn8dX3yz91XZ30NP8oUnqww5J/qNMn5pe+n30KoEHR+Gv8ZH91eqN/jTl6zu91gdAHqg8K/EPx/3dRZPK/cQOg+cP3g4PP8W+Mr4xvAYCRIQgA3CIcdbrSAoUApwWAARpVIFpAtMDpuhagAAAsKA0EDoyX/bU+0r8CAOcAcoENAEzxNQAQAwCVoi6jVfGIUNcdTgDgVonTvjEAmgB3AAaAFEOpHTLHLwbgToGhEVsMQCmAG6GqT0AMwIRQ1wAXAAgAnBqXGIBzflJlXwpAJN678W/cYMUAxABMOxxR4KJQ5xxYKYBz/LSDIcCKAZjmRymA23xiOEoBbBodxdcAQABgCnABAG2Bpg3CIwCVBiANwGUBiWRVZhgDgEZLEikmArzrzIUAt/D5PMqxvU0R87CUqgCwgwUCjgGIAbgskAjwzoGP8QcZlOepCqAUwGWBAABEdJUB3jnKAEAAIADwrQViAEBwJgK8AeLXgz4AgIDMQaIRjxgWUtCjClbvzxzKKDJiJznUQes8dtmXCP8meB7mQCWiBMMuCvxZG72MZYD0H50Hr0ZM6JWvMjXOHz0AIlcyeC/3CVCnT72f7tf8kf/r93WdOfJxfur3dZ3xUZ3Wx7NG3ta4vJ1CYXzDADD+KL4FAJADkgEDAKeLKkAIgHCCBABuhC//DADcDBQWsADAbaC10ZMY5ADAuH4FAEYDKsBCZR0DsFF4MQDSeG4pKGlctEOUBkf3awHRDl7P1/0xALcFBfA1futx4wGAcf0KAIwGDADEABwWkEiVKZxSALcGAinGAAAoDBkI1wMAyMGsKc5SANjBpAGYKExR8GKIRYEqQOj3SwEgAiD+pAG47RcDsCEAze8YgJHhDAAEAC4f4A5SGwCVuY8iIwWIAMA9w3UcsQBaACAAsC3xpQAuC6x9FLjBCQAEAAIAhwUSASYCHFa4GIDBeM/zCODHAMQATBQ1dzClACb7ageuHWYpAGhIKgOcVhgtIFrA9eO6PxFgDMB/NAPwPF/nFlutStUJiipgUdAvHwcpFbkCgBZQUTxq5EH7IcJxgcYCpQA618mOhympDlbvLxWx7hcFuC5gEhE+OA9dAE7+y/tlIPURUCc/1ZGPZXrcwUrkCwO9Pv6yHwdYAzheXxk6BOC1F/5sHmlwlIKFebX+yL80eh8BgHsENQByoAAAZkgA4JyjAQBoJAIAUwpIC8R8PQAwmVDrTwAAOyAtwDEAG0SNAbgBjiaoKOgAQADgtEAMwA2gx06kXL1jAGAitQItBXAbUPYrBcA5ev1DKQCYDwGOxi8FcJpoBoABgAAAJ+H3/1AKABSVKJhSAO92mhPDkAZgXMAFwAMAp4F/uQYkABAACAAcCAenQZUCKAUwzJ/nly8AiQDP4aMIdj3rIxHgPX3SACzh5dEGVClG/XgMQAyAfOQWGa3njScCvHcwqtIIAAQADguojHqa/P/KzQGAf8VK3/5PAKAywMmBuAPSAiOGOQBwAyQQLHMOOAAQAAgAfGsBlXkqhcvg++8uAvx8Ps8soERSqmNXDpd9BpSD1GELd58Wju/8D7d5H30/TwvcGPxHp7293mp4BXgY37dPG5s1CDrMBv6jFJb8lzsMRUgxaDrMSC84tqJm/MJpnexzovdXjl59Dn7DD+D53ACMKRB9vubH73JA/AD7AIx9BPR9us7vU/zT9/+4HUi//xEA0BCO1wMAtwE1AVTmGQCYHFTxlxRyAOC2fwDgTnHJAbUAIgmuBVAAYppcf7ZK1vcp/un7AwC3hbSDXgeY9wcAAgCHBZQCAEH3xADcO6AYAOwQYwAYwpd/CAAoRywKrhTA6X8CmHReifD+eT+Bv68yMyHgGIB7ALAD1/hr/GIAZMGNopeKWykstQovBXADoBiANADjDMftMQAxADEAf32OpQGYUgwBgADA5UBpAP56aPrX7gwABAACAP/aXPl//VcAIABwWEA7eFHwuv+vO+7/vVO/v4pM/0gDcA9RGgC4cCmA00DKIUvlrACSBgAWCgAEAAIA31ogAFAZoNaY+3oAIABwWCANwDa9lKNPA7DVMWsHrx247h9H/+/PAHz9RKHvWsaiOmCIwNRHQDswnabGOnfU4a7vt+4w5eA6z505wrGOlu+nGSYRqA6b0fN12BIA5hpA1KhEC4Q+TyI/lfmLQfvC/Ob943G+mj9q1cw+GBAxqwpDDI+uqwqE3yeCZe1DoEZUiu8QGcs+HP+fOK1T46sJtopw1ecBvz8zAAGA28JS4QYAtkYUml8CMArgfH4A4DQRF/AAwM0godGTFrgAwFjmGQC453cAIABwWUA7eO2AdT8X6BgAmuj6hxgAOJBSYNohjr3uAwC3e8s+MQDbBuwjABAACAAcFigFcE6QUgA3wOACNraCLgVwU1Brq3qi71IAWEDTALwqMuMOe1RR6/kxAJuIKQ3AHT+kUeEOUDmkGIAb4ClHnQaAGOFk6GTfNAD3FiwRIBagAMA9hdIApAE4LCCNTyJArFCJADeAFQAIACwUvTZA2mHFAGCHOsr0YwBiAG6K8I5/pQBKASzrQxoA9bqvDPCMT6UASgFcDsIqgsoAoYILAFwGYgqoKoCb4eNxwBCpSATEVoe/uM+AGnX86h2yFlhOgPGwJW1wqTJXjlUAbFtfH9W5yz9XClgJQs6fsQpC7/8l/9AH6P1eFlFKZCf7fnxggYV9dL9SBCzz0/iAYled+Go/uYfm1zNqCBS/Gb+gUWP81fqoHL9SkOpzIvthgHwWgD5wFPm9PYB0QAxAAAAiTy3QAYBJRa8UjvogBABu/9UCLoCk+wMAWIG0gOm00Jc3kAGAAMDpwW/nyOmAD3Jg2kFgB0cEHQDgJuhUAQtAa4ctgLUex62v0/vFAGwUv+ZvDIAo7gmAM/5qfYwBQAR5GcHFAGiFxw5JrUIDAFoipwAUA4D1UwFYnQpLAWz+Ke/XDj4G4LZgKQBQ0NpByQFLAWwIOgCgELgFWO2wYwAm+4rCLwUwuffDDVgAIABwWYAUdADgDoCiEEUQxABgC6oVegSwenwAIABwWCAR4Db/SgGMFBsRYCmA00PpgGkAMMOxg1GjkrEXvPZPUqmXAigFcFogDcDGYFYF8HnKdOYykZGCjwEYT8OKAbhXkACAMApEIrg9ESAQzFaGqA1WDEAMABj2GwCoUxmjx0hRqtXvrwYoqjNnI5RVJYoBYBnjcwOMD30gDsNQnwC+nx6g7weCVB8F+Z/mx/p9ylGrzEzmW99P839msMZGLszh/4EvuMPjw+dDZCj7cXzH+KH5ze9b7QeKSxtA9lEYn6/5o/C4AjTFF5UBCwCyDwBfQB4cALhzlOMElvkZ4AMApwkDAFJ53h4YAAAFogksgD3GjwAAGAK5v4Z3TNFw/cX6GgB4WSQoBBgDgAUCAER9FhQ/1wUoAKAIGAA4KdYYgHsDNO7QYwAw/36A4VUrYCIQReAYgBiAwwJkKMjBvbsABQACAJeHkSIPAAQArviHBZrrbwzAHaCosh5FijEAd52a1u8AABC6FhBRxONhO7+agflKA/DqBqIUQCmAM4tBBBIDcFqgFEApgMsCWmATAd4Acz3rQPOTFPN6WJDipwBeGoBXGQZtYLQBTARYCuBVBK/4wR12IsBEgIcFBFDof2MVRgwAGLYAQABgSDFUBVAK4GYwBHG1Q/k3p6DTAKQBSAPwvQVmBiUR4Bl/ycCvGoDn+boLGRDgtQNgDl4PGFuh6rxpqcS5A3q5kQwpKDEs/7wNrD4KcsCVYeDwr62I8QN6f/UJ0A6V34fx0fyh/4rhkX11mA7qwOW/aw6anRJVpiX/YCH6Nr/kH7r+un3H+CYAre9T/FWK7EsOMsZPzU99n95f9yv+fCC+fAQA7ggoB1SORzlKNvrQBmx04ADA2GkRIjVNYE1QBZgAACwcALgpcnUKDQDc9lOZOdwzAMAIiX8Yj0tkABXEHidIAOAeX23ANDxyrxiA20ICIKKANT4xAPJQjA82CLN9x/gWA4D4piof4VtVycQA3BYMAIABAYWsBVQpBIW/AMDov6UA5GLndcUHPVwMm+7X9dcBVgAgBkBOeF3XDoLPTgNwm6gUAF3o+gcBmDQA2MGkATgNFADQYQG3fykFKwo9DQDmbxqANACXi2gHrwVU92v1jgGIATgtoA1CGoB7B5sG4HavUaTL+FYKACbSBE8DMDmwdihawAMAclAg8DHAiKLW+BFgVQWgGB4DcFggDQDmfwAgAHCmUKoCuHcwsg/cSwCmFEApgAUBCGAvz/7z3jQAN8VTCgDz9+u5O72sKlKphNlqU2VWPzCFxkYJv/9Er3bt4MZOXesCJQTO7/uBCSYVqu4XBTlGSO6QHUFvhkV19AIoYrAEYHCYCBcgnHcv/9Hzv+T/wv+YX3QPfJ/uX+uspYGif64i3NG/dd48y1g1/v/YAKb8T/FN46/jdMmwoZGa5pfeTxsUVZn9SUCcET4AEAA4GYoAwMZQBACmFJYCpDYYuj8AMKawAgB3iujZRJIBgBiAycGEkNXIiAEyBuCOoAGAAMBhAe0wxRBKRa9GeTEAW5m0NtAxAKDotMA8AYAAwGEBUqwjRUoRXSkAbbIDAAGAby2gFHIpAKh00cq/FAByqNwhpwG4A3gMQAzAAAGUY+aj0wCAw980VBofakDSANCFr38oBRADEAMQA/CtBbRDUo5cFKWezwUA4U8LDKNnACAAQCf5/h8SAULF+AUVtygcBaBSANthNQrgZDi0g08EmAjwsEAA4F59mKKqCuDe4HwiR48qLmGDAEAAYMpRMgCCwZDIRxRQAGDs9Ig+P2kAbvvS/2MATgskArwdRAyUNjj/9QDgE1twGlAUPFpxiiF4O4DMdbprnwAdJ4nDOIhQ1/dbTxujzBhTUK1cV/uMh+UogMi/5P8KcLoujSPwvT7v4fCOZ1Xo/aWyFkPpDwSDjk5uAuAC8Hx/NaIc549E1tygYIcu/1UVg84CUB285iePe5cGbIzvq38+0lgEAEaKbl1gRwcJAGD8JPIMAGwxRgtQAAAanTsABADQh0WtdKGCDwDEAJwTlDm6AMCdA+cWMQbgVPmOOyjtoGMARvwTAzDl6GMANv/j3TEAt4mEAAMAEhGPvbjlwSOFSYYkBkAjIAe4r8cAxAAcFggAbNOPdwcAAgCXBVRmpR0kc7AxAKcDpgHA/Fw1KC+fNaEcdBoAVDFJxY8AJPunAQB+TwOQBuCyQACAGPtOgYzH6WqHpOsav1IA2/hqAQoABABOD4OIefPO50kEOKo0SwGIAS4FcAKoAMDNgGh+xgBoAoJCwRKiBWgtUx41LFUBjBCgFEApgFIA31tAddaq89f0lMakFEApgBNAKoWhKoxRQ1MZIPCXAOxY5aX4wusCAF9fOA4YpxWKglQfAZ02xw/EP3wpB60+BSozwe+LAhTCVR0q7QMHIMMx5uBUxqQFUN/3OsWNHdKsocAOVwBC7i0AQ/uNIj52+tQHwAH0ffKf9brin67LPnP80AcKQIynVYqCVvxRnwR9nuKP3E99DhS/lSJ6u9Ot1tePAAAQXgDgpnBhH03AAMDGUCmAaYEMAGgJua9rgdf1AMDW6lyjp/ij+RMAiAGQj53XZwSvHJ3eLgZAFrqvxwDcABAUqBY4MnQxAKcFtAOl88cAnCYKAAQAOIeufwgA3BEmBiAGYJlgYjiWZ/8r92qHr+sCSHP80EcEAAIAlwUUoOXgaQBuBEUEHwNwTlBS2BJBKUDGAMQAHBZQ/NP1AEApgHOC6awdaXRwmmsagESAE8VIkct6XDQW6AAANCwSGeL6owBTCuBOAaIMLgAQAAgAaBc2XGeOMQAQALgsEAMQAxAD8Ncj8KhBqgoAphdAjwFAkisAEAAIAHxvAQWYGIAYgMsCAYA7hfkT69MvTwGMZXDqxSxoyTpoPEAahq/f8AA4sMpI9H2iWFVHSwoeL6he/nx/HbcJ+6pO9W0GhyKr8bCgOUXxMgNB/9P8EgDA/cqRs1ETehmrDEx16NToIH5LRa759baGSv6vHbjsq/ir8dd12U/XFf8Vn7S+zfMf/iURrNZPawACAEiyysU2CicA8C6DowDIBWjNsUukGAC4UxABgCkAyf8DAJig2gBJY6P5HwCY/PsRAhUC1AIcA3B7qOwrhB0DAPypVqQKQGOnN3VC1OzVDo8ALAAgE98piueuUgoABAAmBxNFooeLwtD9AQDU4a/HwQkBlwK4XVQ7gBiAGIDDAgLQio8xAADYENFpfSsFgAVCDhoAgIOqFW8agGkHxB1oKQBN4dv+Og9eGowYgM3+MQA3wAwAaIsilY9aTWGDpNOUJFJCJ0NR1KUAtvGVfbWDKQVQCuCygESsEqklAiwFcPpXACAAAA5yQuBUYes4xxiAe3hgH1GgMQAbANHkSANwW6gqAIlY5GHYYI4pylIAsn8pgNtCEmEFAKYcusokAwCawAGAZQNQGeDtPwKAur557/OsDOW/PQB4PjcVmAz4x48bwWmHpQEmBSiZ/toIaAU4I8BVgJGKV/blAvnz/gCqxD/vAVh/f/Y/+MdKIQugiMJ+JBIEhanzyNcUjfxznf9i0Oh/ynCpla8mEK5rh0//hcqMImjEn3X8VKeuVsj0T1XBqM8LGu1ofeHwY314G+Ao/n8EALDDUR+EAMC9QVKjmADAab8AAELs2qkwAHBaIADwbgo8AACVrxCWENrbIjJRQHp/longAZqgQoB6v3UHzh1YACAAICe8rgcAbgAuEXQMADI8AYA7QIFiIYUVAFjC3xMAuCPY7H+lAO75jxSb/LMUwOi/pQCm9ekpBZAG4PIg5WhjANIAXP6jXvLyr1IApQAm/4oBuB0oABAACAB8b4FSAHf8SAR49/mIAbj9JxHgTbElApwI4kcp4ESAVQGcHhYACABcFpDGJgAQALgDTABgW+LvuwMAlQFO/hUACAAEAKYpdN4cAxAAeM+7HjMAXz+RAkAjGq2vqtNlq11YZ61zVQKEOVoZQCLSrVPyQ/vKfmOduJxXdeS6XzlwUvDqU6Dv1/hKhf7y82U/iSC1QyAAlAht7FRJ/1Z8kv+rzBf3i6LW+EiEJgZFz9f4rvNLZWy8/my93sVAve4/0FhofHjWDfp8cP3UccIBgHuIAgAbQgkAYIczAgwFmADANr9l3wDALQIOANweFABYEfyoco0B2Cg4BcgAQABgSSG8voOLATinsBg2LvDopCiGQvElBkAUFwBwDMC2Q6ADlgLQHD6vrxSlcqwCKBzfUgDn+M0M2nhWhpxP76f7YwBiAOQjJwBWBqQUABboGIDF/x4ugD9LAZwGDgAEAJYZiDr0NACg0NcU2ssMtFyjFMDLA8BWu2MZIHeIMQCaAzEAlwW0A4Z10wBsDJ+cNwYgBkA+EgNwWSAAsPhPVQA4bqwUAAI0VNhVAWAHOjJkVQGIA48BOC2g9bMqAKyvMQD3DnwMcEoxCP2kAZCF7usxADEA5w70C50cAbATAW7z85enAD5xIDN3UON5zDotTgZaRTxv73B0VoC+j+e967jdzT8fpVB4GiMCDPs46DxvIGCqmMc6ZJn3bf8SBS0AoPmt+6Xi5vePh4HJ/vRPAFx9v35/PewI66/nJ0770/xWlZRS8KriYPzX/B97+dM/aSAAcDGU6qMhjdt4GN9HAOC28HqYSwDg3mEEAHCYkhrpjAtYAAA74B9YQYEAAgBgYMYNpFIoAoABgBiA00MDAJjA2CKIwg8ABAC0i16uawFYGRS9WwAgAHBZgOtLDMC7ObwVATIF8XnvMEoBQOQjCrAUwGlAUdgxADEAtwgIEEdVwiqTjQE4DbxukDT/SwE8pQBOkRAYUO6w0gC8yjCtO9gAQAAgAPC9BbRDFwMkDZKeHwBAlQh34BihGADswAMAmuPn9bf9KwAwpqhGDYWcoxRAKYBSAIcFqAINANwUUVUANwWuMqaqAKYUQlUA9wIXAAgABAACAN9aIA1AGoDLAmK4YgBiAE7/qQzwVYZODNDfPgXwPF9nKxwFGJZhyAEh8iJDoCodteKVxkUqTP3+2MpV5z0rR7Q26pCD67p+XzkwTSDtQNWqWb3WtYNbNU5bs9gAACAASURBVBD6PtlX9pN/oAhIP8/rih+a33o/ja/q6PUB9N+fdwCQCEvPX79/rePn/MD3r+uDvp8ptnF8NL/Up0XfP9tXDqz1LQCAHUQAYHIxBThNMC2QAQCUEcJ/FWCnwX+eJwCw9crX+AgABQA2gKb4FABQJ6YYgC2GosxNOzwtwLq+vfzz6PmaYAEA5JjHTmJaYNbxDwAEAJYUhfwzBmCboR8xADEAmwvddwcAtl7rGhsBKAFEBVj9vq4HAAIAAYDvLVAKIA3AHUNjACDiuctERJFyAqJXfRqA230DAAGAAEAA4FsLfAUAAgCHBUoBlAK4LCCAlwjQKrDrPwiQEwHeBkaKfLavKDgPf1UAJ0JNBDi5WCmAUgDn/FIfi8+7jCcAgF68qoLC7fMCNWrElKJKAzCF5z8PcwwABAA2J7ruDgAEAAIA31tA80MLoABQVQBVAZzz7+vn7SKs08XaQQcf1561DGzN4er136aw9fv8PhzoLQqVjYx0WAgpKuwA0cpVdbj6PtmX36/v03G/OEtB7ycRoN6f9699MLBD5PeNVUbyD+6AdV78/9xfoPiq8cH0fd72b/mHxo8AZ5zfBEB8QU3g+zr952WNkcbnIwCABWYMwAGAbYYRwIwB4u0Aqa9np7/R/xQAtMDw/gDAPcQBgNs+SvGM8zsAAAAaAAgAnBSRdlg4q0E7FC6QmMFSmWuHFwBAgHhbAxMDcA6AAJrm19v+LYCo+R0DgEZein/jaasxAKOB5eAxALIQFiCNz7hDeDtA6utjAGQh+IcAKqqMBBBJ4ZYC2AYwBuC0HxnQAMBWB74aWN4fAJCFAgCXBb5KAdwBMgAw2UezUwxEDEAagNMCiQDRCATH0VLlS43Ku2VUChCiKBWACNBiAO4FQBS+jtvW/WkA0gBoEl/XYwBiACb/GRdQLjDjDiwGYBnd5+H4BAACAIcF1GisFMA9PwXwYwBiAGIADgsEAAIAlwXSAIz+UQqgFMCZQ9v8i3evjZT+7mWA63nWRJCog9YArBT58xM56B8jha46lE940EiRqc6Y9lWrZtiHz9cOHg+Qf+r3f9cE1AIDCl0AUL8v99H3aYemFB3fT+MD++owI6WQxBDJPuokJ/vour5P/qHnU0UvBnMtUxxTQIpP0li+Hb8pAkUrZMWndX7J/+XfrALQB8hBAwDoxRkAUIw+r8s/9XBNQFUJyL8V4PX7AQAA9NFACpCKb7oeAMD4oRV0AGDzf/l3ACAG4PQw5VA/YgBugAIEEQDAFhIEmXZAAoAKkFrgdT0AEAC4LMD5DweW/8u/AwABgADAYYEYAHG8d4QihaotXgDgNrBShKUA7viGHBP9txTAHSBEkUoEJQSfBuCOkMqx0b5pAO4AkgbgZkDSAEwMkRiGNADvargCAD9Qx/4ZALhcUBTNkwZAGCQNwGChRIDYQD93owMtwLpeCqAUQCmAi2KtCmCj+KCijwG4zascXCmAUgCXBwUAgE6VYk0EOMB790lJAyDzykErAzwtmAgQOfBEgKeBtEOuDBAALA3AFJ+UQv6vTwE8/9AKOl7XefGootOvU2MACl4q+Lft83cvI5N9xEBwBwWRDcd/rVJYRULIgauKTeMv+ylHrBSUNXrjaZqoQ397fsl/CEDUJ0JFDrp/PW1TGxztwF/WAGmH+qlOr2BAVSbM58sBYN+3f38FKKwCeH0CBgAmkZAobC0wCoDKIQcA7gi+jk8AQB768nVVIWgBDwCcAxQA2A6zCwBg/scAbAEyAHCvAJyAMQC3A8YAnPZRFZU2qOyUFwNw218GjgHYFhjZd97BSmRYCuDOoek0OFGECDCisH8vBXDvoFCFUwrg3fhEkWgMQAzAYYE1BcENCOJnKYAAQADgsMAsEooBiAE4LEAAkQbg3qGnAbhFtgGArRe/ctxvaySUA15zzNoflQIoBXD5iPpcfI2d6N6eX/J/MZRcwGMAYgBiAC4IjClYFcCN8MYdpgJgACAAEAD43gIBgC1AJwJMBHivQZt/PYkAtcTf1wMAAYAAQADgOwusfUACAL8YADzP17jEYv0eKcC1jnKtc6YIUWWMWn9HFakaqSiFIBEe68BVBqUcJuyj92cKRHXQa58A+DfffzxMhCKiMUcq/yJFjgk0ayxG+8l/lOLQ9Fb80f2an3z/l+enNlhf8D99vwCG/EfjxxSVXhBVLFq/5vmlRp1oFPURABhTEAGAW6QTAJhEOgogAYA7Asp+XEC5A0D80Fkfuh1VHnz/AMAdn7RBDQDIAjEAk4ViAE7zcQctDUQMwG1fHPY171BiAKbwEAOATpOgoGIAbvvFAIhCUYIkBiAG4LAAAcxIYccAxACcGo0YgBiAwwIBgADAPUHeLmNKAzDt0AMAAYAAwCHSFANVCiAR4L0CYoWKAYgBiAH41gKkYNfDlkYGhTn0NADn/E4EeK8P1KBQZX0/X2Wo6gQaAxADEAMwZGmlIi4FsOVw11anDMDQkAjA0HUSAdJEJ4Px8nHsmr98+aoAEgHSSa5/SASYCPBiECDSKwVQCqAUQCmAby3AMsDPjeNSq1ydB8/TrrS66jSxH3iARH7j73MH8jKFqdPA9HkaP6qU1+/TYUDr+I7+IwpO8+PB+887ULk/cqCieNXIRRQ7/XMcXzIwL1eRyD6af6rC0Pjo+doBz43AsIOXfeg/ytCK4cUCqT4DWj05PuNZNFpftEH4eAIAmiP39ZUCWhfIMYDp4wMAWw4uAIAIDAZMAEkBOACwMbQBAIi8sIEMAOi86bFRzDPu4BRAtEDq94XQdNwt7w8AIMJhBEf/iQG4z4vmDi4AcDpoDIC28BtAl0guBkAU4ngefCmAd3OYpFhFoQHAlQIA/sD80A63FIAC0H09BiAG4LRAKYBtDyyKUxRyACAAcE1QMSRaQOndMQBnfBSFOedwYwBiAA4LkEHSBkYEQgCAIfI0cQAAOxC1Wk0DcAfARIDMQi3/QBHYx53kDABs9tHYlQLQCl4K4LJAIsBRRawJmgbgnqDawVPjEACgCy7/EADYRIo6rU4ASWMXAAgAXD6i+BkACAAoxtwUcBqA2z7qtZ4G4Pa/UgClAEoBfGsBMewzAPj6iRSA6pQVAEeVv3KQq0pTq6PKYCSC03WpUPV+Om+bDoLjRtWpUiJD7ZC0AxXDIg0AVfrwT42/xkfX5R/Kger79PsKMBo/7XD1fevv8/vQalj3077IIT/qBIj7ZV+9/2z/cQPA93vuCaj4rk6R+n3NL90//z4CLEWsYkj/gRRJAAAGuqucHk0wXQ8AoM72bZFeAOBmOMZGLvL/AMC7GoLZ/gGAc34EAGIATgfRBAwABAAuB9IOhTtUbGHWBVg7VPn/+vvaoWkHqftp3xgAmfCOjzEAN8CAA0pj9cQATP75iAJWgNP1AEAAIADwvQWUgtDsDgDcOzQCsBiAGIDLAkLIa51/GoA7xKUBQApnZKgEALUA6boAYgzAdlhHACAAsABszd9SAGOAlYEDAAGA0wIvi1QDAFuOWgCHO1BoEBQ/AgABgADAwbAlAkwEeFmgKgAtMdt1LZAxADEAi4fJvwjASgGUAigF8L0FNMF0PQ1AGoBlh6IUnBYPLgBVAdwmTAQoF0sEeFhAjZ7eLwP8uvsAiAJdA4jqZLmATu73PKuKUj+vFIZU1HIQPV/2FQDR+6nTlOyj6+wTgAfIf/X9/H3gFy3Q1MigDJJnbagRkVTCKIPl+2N8FODkH2JIlKNVfFF80/vpusZP/qnnc/6iD4jso/i5fp/mn+Y3318UJ+Y3+6CMDIriv9pc6DCxj68AwD2HECA1AbVAa4LKAfT8AABGSIeBfGmFRwpp1cgEAE4DBwBAUDw3gtMCqesBAMz/AAByeOiUJQfUAqzrcmDVUer5WqADALcFtQOg/bGD1Q6Lvy98EAC4c6iiSDDAAYAAwGUBrR/aYGmHHQMAipF1vAGAe4cDikoAIwYgBuC0QCmA0zylALbDvkoBAKAhBbMClFIA2kGMvZS5A12PUw0AyMTndeUIYwBAYaYBmPxPN68LpJ4vhlE7ZF0Xg7p+nxg4zW++fxqARIDLDkkTUDt0TVAhQD0/BiAGYPFvBdhEgIoAW45YAFW/rviiBVLXAwDb+NK+I0CJAYgBAAc1NnpBL28FKF3XDkD3awFTgOXvpwHQEKQBOCyw7pBl/AAAUhjjApsGIA3ATUGXAlCMunOwUuHj6QEAGCgNQBqAwwLcoSKFugIcAXDNb77/fzsA+MQWiHXeEPGJIhSFrV73Wl3++LEhQNUpy8HsX9sOXN+vFMKj43axQNA+YAjWHYpEWhp/+bdayUrELv+Qip07DDTq0fyRSFfjQwpY7yeANzIstP+oAVrjF/0TIjH5v+LDukAzxYgX4Pu/3Op7jV8CKHq+5s86fvL/jwDADRA0gDJwAOD304e1wNC+YKAYYMfjSAMA9/wRwFAAVRnWbP8AwJQiDADcCFXrRwAAFLl2MEJIWgC0Q9YAcoFCHbhEGlog9f36vhiAG6DEANxlAApgAQAsEGAoGV/U6VEpMjSqkUYmABAAuHNod3x9VgpNC2AAAAikFMDtv9iCzjvQB+PzEypjUew/7wClBVoANABwp/C0gVF8CgDA/8dGW9zgiSFECkvP1/zR+qYUjvynFAA4eg2gDFwKoBTANYnTACjJvy0Amp8MwBJJjgxmAABLXBqAW2Q+thoOAAQA7hmYCPCegNiBcAGKAcAKHwC4LEARXSmA0wLc4MUAgMOvCuCmkNMAJAI8LBADEANwTRAByADAjXBUhRYAqAxwQ4gq0wkABAACAN9aoCqAO0AEADYGKACAKp3n824FrBz2fffzzAhrFGFJRLE6CHdweoG3RV6jylciJn0eT1PEBlDnuev3NT56/pojZpWFPgA5UL0/FxAQfGsZnj5PKvO1CmOd37If3x8iTNlnFXnJf/V8ft/Yx0Hfr/VF80vfp/FlFdUYv/T78l/NT8WHjwDA7YICMFpg6OABgJuBUY4cBtb4aIIogBLgqMpCDhIAmDQYCqCa3wrQXCADAPJwcPi4HfMrABADcOfosQNSgNACQ+8PAAQALgsEAAIAhwUEUARgtUAS4MQATPFL4ycAGwOAHLsWYBk4AACOSwZGFcHqwPp5AbQYAFhQGr1x/nGBGVOA6/xWgOb7xwBoisYAHBaQ/67xsxRADMDNkIwBjBT5mENTdAkA3Cv0GmDUCEnjwwU0AHCaUAAlBuD2QNpPIrgxfun31/mpDU4AIAAQADgsoABKgJMGABEYnfQCAAGAywJpAKYURAAgABAACAB8b4FSABuAGRk05ei1gxSA1fPJ0KQBmBZgjV8MwLgDEAUpA6cBSANw+pA0DjEA2wI6zv91fitAc4EMACgEpwH4lRqAr5+stLwRDk6z0ujrPHbdrzp1Ilz8gAIA60RHikqdvtRLXPZ7+/31+0qxPaiSeKCS5/1awPEBBIj4wPkwrLFXOsdHfQLwgI/7MMFHC6hOm5P/KAdK/x8ZEAEQ2Z/XBTDHVt7S0LytAdH3K/4rRSf/lH8pvig+r+uf5ofm10cA4GWRSADgTjFIRR4AuB00ADBRsAGAewIGAABBEJ8CANph47CFFQHGANwWZAAcAQzHLwCwaTACAAGAywIxAKd/xACUAjgdpBTAvYSvAGul2EoBYHwEsIDQVgpbAVYUpShO+U8pgHuAmcJCJ85SALAvUuSlAGIA7h3gb5uDaQceAyALjQE0DQBybHcZYAAA/pkG4DYQGBABVAHMNACJAG8HHCn0RIAIgIkAb4ozBuC0DwFwIsBX/YsMkBgqVVkEAO7xSwSIDQqO+2UACQDcDIcWqESAt4OmAUgDkAbgewsEAAIAC8mbBiANwGUB5lBLAZQCWAKQ7i0FUArgssDnnWL7+Pra+gDoMAI9XXXQ8v8vdaLCA/T7Oo98FRlpAREAIYX2eXOYynF9YAA/n7vQm53IftwOqudLRKM6YYkYJYJb/YfzA3X06/txfmmCI4Wv89r1+yqjWhk41Ynr/fh92oF+bP6v95N93vZfxTfFB42Pcviyj1KsH4hPfP44f2Q//b7iYwAAEzAAsAUoTXBNsADAPcUDAMghjTtkBdgAwG0hLWCKDwEA5UhBsEFkHwAIANw5ohiA2z6j/8QAYAGByFg73HWBDgBABQkGKADwrv3knzEApQBOC5QCeHeHLQYpABAAOFO4SLFpARBAKgUAjVMpAK2guA6EKAeUg6cBeLeOOg0AAkQMwG0gUfCY4GkAdJjCbcAAAAA++qwoRcn1KQ3AFkBp4ESASAIlArwMlAgQAXIMYKTgAwCnBaSBUXwMAAQAzvhXFcC9gxaFWxVAVQDXBJP/lAIoBVAK4LCAqig2guSpCqAywDtHjh1QACAAEAA4LFAK4IwvSoHGAIBBDgCAQbrP8/4zg6kt8JbjU6tWUYA4jELHVWqBFoUmFaXqzNcyFpV56f1XFa4ocvUheHsH/Pbvr/ZbDyta7S//oP++PH/1fuv8o4ZgPewGjVZ0loH6fIjCl/1UJ68d8Oq/ul+HCck++v7VfsqA6SwAzl98gL5f17V+BAA0AKijZAAdKSwNoCbAuoDRgREAAwAYIbQ6Xu0v/6D/BgCgsdlEuArg6wIWANjq6AMAa6evlwNIDAByqIDYasSxLkABgACAQMidA78pTAGYGIBNBKcdvHbAuj8GAPgSZ9EIQGoDGQMQA3DnKP8pAymDtDXC0A6mFIAQOhYAnab2MoAXOCgFsO1gNX9KAcADEb4EgLiBUngNANwTIAYgBuCywMpArCkU7YDmAKIcNAKMdtB8/1HDEwBAfFOnLq1fOksCdfAc//G0zhiAGIDTAhLxBQACAAEALaPfXw8A3AuwFigxUIkAb9+UfUVxy/NXDUUaADGMKvN5mUIMAAQAAgAKgwGA7yyg+KEFKgAA30P8l30DADdAlX3SAKDMR6FzzUFWBpgG4PSxqgBO86zzLxFgIkDF+FsEhbvX+ft31wCIghcC0XVRNBSxQCOzIsx1hyCRzdxrGiIuiVA0PmsA5vd93gBB7yf/0eRnjv/tHOwtcn9EQa7zU/ah/X+CQoeIdH2+ctSyz+o/sh9bIYsh1QKDw2p4Vgrw+Rw/4R+0H8qoad+xDFv+yfioCfyrx1eNgDSBaCCoGDUBAwBA8AEAxpDrHwIAmwhpLSNV/NDzAwCowtFZKQGAm4GSCl99YgIAm8o1ABAAuCwgACl0EAAIAMhHpuurRupX7xDBsM4ATsaNATgtNDM8MQBbmaEoslIAf+9OaQGAAIDWoOl6AGAynzRUpQBE4dzmZyOgUgBbmVAAIABwTUGpdMUgrvNT0Xnd4a0alFIACOBpAG4DpQG4NY4xADEAl4dQ5CINAgLUr66TjgGIARAImq7HAEzmiwF4WeMRAAgABAC+t8CqMaCGpSqAc4GIAYgBOC0ggBUDEANwLnCqUhiPCy0FUAqgFMD3FlhTDFUBvLxDTAR4LqBkSJXD+9UiTzEAD+K3djhrpyzyR+iF/vnczbAVgLSA8/3GOl82MkGdusZHZe7KMev7uYMGguf3rwBNZ61ogo517qv/qc/CrBKGfeQ/jB9/qpCOP85flGHpfvmvArxSWIp/PKsCL/gBA6vV8zq/eJaFNAo6jArfz/dXnwqlKPH7q305/8EQKr7LvykC5ATGYROaAJxA+oIAwE3x6DAQBPgAACjYAMBtIG0gAgCKcPf8DgBMKSQBaA1OACAAcPtIDMBtnxiA0z5ioBTAYgAUoG73jAHADkEMWQzAzXAhBa0qoRiAGIAYgMMC7NNQCuD2n1IAQAiow0Z8KgUA+5UCmOK7GIxSAEJgOi9bFo4BiAG4ctyj/8UA3EnSNAD3Asscug5TiwE445vsmwYAh8FofZXGQAGAAxAA4BBc/5AIcDzOE/4XAAgAXPNvzVHrMLREgBvA4vqTCBDrTymAiSKSijsRYCLAc4FRCiUR4K3xUJkYwl9VAOjjUhXAvT5UBng7kERY3B6XAigFUArgWwt8VAXAEHL9QwAgALA40McnOHRRQHJAlfmtO1BSKC+XuUklTJEPcmhqdEKR29hpTs9XCkbOKZW6WvVq/HVdKQr9vr5Pz5eKVwBUvfalItZhKkwxoI5bOVDFF5Uh6/01f8RwcX7ruF3t4FGkQP9Fjp7fJw2KGB7FL53mJ5EfA9D9gNm/xvfT74+f96zrZwBAIhdlIF4+D1oBTA7EBUCHSSkAIAWjBTIAcFsoAAAPUitYMHBcIDW/AwD3AAUAbgpe8RXuHwAYEawCgBYw7hCU4xOCRgALAGwiO+3QYwDQajYGQCFi0ujEAGwrpHbgZJhiAHAcriwIlf+KYDRB1udrdgcAoPISgsUOSguwxl/XAwAQOY6NXEoBwL6lAE4Daf4rPgcAeJz9zeHKgGkA7iR7GgBQ3AGA00ClAEoBXBZQfBbDKYCsDZTKAHmc77jDDgDcFtD4pwFIA7DlqNIAnPYTw5AIUK0GAwABAC3z318XQBKBrV8WQ6HfVwpXvy+AFgCoCgAcJC4rBRcACAAcFigFUApAi9h1XQusnq0FOABQGaB86LyeBiANwLlDW49rVidAnEbIKhCo6CsDRIqvKoA7flYFsDGsWJ1mBoCNgPAC0gAwB67ld1tfHonwhQBF0fL1xzp85djWOnB9n3KEui776Lpy4NxhaoboLBL5n8oodVwrHFQUoeyjMlJRhBofjb8AiHZ4SqGs81vfpz4DAkjqg8LfH/9B9tfjFR/m56MRlOyn6a34OcePsQxV81vjo/knBsSHAQUANAbndU4QLUA6bGPcAWqCy8F0fTLe8zxa4OYJLPsHAG4GTGW4AMABgHWG3Pcz/ii+o0phfn4AYHIAxd8AwBjgtUBq9DhB9H4BgNPEAQB44NgIR/6tACT/DwDIwtt12V9PV/ybnx8A0BBMADwAoAVWh5UAAWv0OEH0fgGAAMBhATEkpQA0Q3F91EiIwh7fjrcz/sQAnBZgCqoUADqFMUkHDxQFqymgBTYAMCFM7QA1PLquBS4GIAbgzsHJwwIAlwViAFAGFQAIAFwTiAhcACUGIAYgBuB7C2j+rBuIGIAbX0nkLIahFMCEULUBKwUwBgghYI1eAEAWuq/HAGz2KQWw+V9VAPC/AMBtoPEsF3lvAEAWCgCcFhLAkYPpuoZH1wMAAYDbgV9OIcYAxABcFvh3TwF8ohGQGt0ogOu6joPVAqU6UPYpwGlm2kHp+1jniU566qOwPl/vr+ufz62SFEDQAk/7rxTvy3X8qkOWfefrYyOWD1C09E/0QZD/SISlKgLZj/65ljH+RA4ZO8S5T8nb8QUGln05PjqOWX00xj4cej/Nb/WJ0PonCZ3WN70/zwIIAMiE9/V1gWaAfblVr75eAVwBIAAgC4/XAwCnAemfAYDJAWVfPVzrD+NjAOAm0GIAsAUUQocHBwBuhBIAUAgcrwcAAgCHBbiAaoMRA3AvsDpOW62kR4ZS0SMGoBSAfOQOoKUAbvuhimMy/r9ycwAgABAA+NYCAkCcYqrSCgDcJlQOJA3ADQFXhoEOLoQfAAgAHBZQjlIppDQASDGqUVkagNOAAYBEgPcMKwUQAzDsoCQSWgEY748BiAEY/JcbDG0QcFaE/DcNAACgVKIwcCmAUgCagwGAIYAGAO4yjRgATL+1U2kMQAzAxdAlAkwEuCAABXCpgBMBLtb/F+6NAYgBGABsDADm2L+7BuDr6+YQVGf7O+pc2at9vF8UkRYovb9CrOo8df8XGIgPHPer5yPD89A+zy0DVoBYF3g+Hypl5aBlP+UI9X4CQPLf9TAZ2h8AYdbgYHz0foofsu/bfUI4P7ED5/i+fD/n/xifFV9X+2l+an4rPvD5o8hX64fWB/ZJEUAJAGx1LhpAOaAGmBNEP4AAwgAQADgtHABAjjIAcBvoEwxkAOBVCj8AEAOgJfReAFDmoYcHAMYFJAbgDpC/wQNjAG77rQzdywv4yiBwAxADcE+gGIA7AovCE0Wk+0Whrg6uBTwG4LaQKF5RWNphrxSvxlcUoN5PFLX8lwFeGrIAwA3g1SkuAHDaT/FZ8Z0M5yhi1PyOAYgBkI/EABwW0AIYALgBcgDgnn5aYASwVoA4M3QxAHf8lMYpAHBPEJWppwG4O2UIoQodxADEAFwW0AIVAAgAnBZ4GUCsDKkAmuJrDMBd5ykAKgZVZcgfiQATAV4B6PdEgIkADwtwh50IMBHgxSDGAEwalAAAjotcEW4MQGWAlw8oBRIDsDFE2mHKvgQoaQDOAdIOXuOj+2MA/uYMgOqANQG1gK7X9ftfOM5T36c6ep1loO/T7/P9cV47AdC6wx+PS+X4YQf5B95fFPtqH/4+WqFqfJ//gQeNKn75pxZQfb8YJP0+KUwdtgIRnxYw+Y/e/+34MMen8bS59fvk30yxvlxGqfiksyrkH4r/+n35p8aHKYD1BWWA9boMpACr75snGD5Qv8/3DwDcKdSVIQLA0AK4+qcC5BMAmCjUAMAdoKiS13G2CvAAuAGATUQcAIgBuCm+GIDJPgGAO0DFAGCLPW4Q5g1KDMC9gQCDFwMwnvYkgKjr6w5LO/B5go0TPAbgNiAX4BgATaF7Bz2mYAIAAYDTwWIAJgBSCmDMsQYARpFfGoBpAgvglQIARZ0G4AZwouhjAKb5GwMQAzDtsARAtEB8pAFIA3BYQP4l500ECIQLAyoHK/tz/NQoJwBwmxgiQjHMAYAAgObweV0TPABQCuC0QCLARICHBQhAYgBiAC4LaIESQppWx3/hZv0+F9C7UeCTBuAeBNlXx0lz/MYctHJklQFifEf7pwFIA5AG4HsLrOur4psAIMsAlYNUmYYOU6GISzl+nQanTmRrgANHKope9lEdtMrAHsWfuw/Fsy7gwnA8KwA7XL0fFyB8v8ZP36fDfNbv1/spAKz20/ylffAPbCSznsYpilwfbaUdcwAABE9JREFUABGbygzlnyrDE4AVwNYGZ32+Ukj6vrfnD9c3dCqUfXVd7qX75T9aPwIAAYDTB7VAyEHl4OsCqPfjBAkAnEMk+wUAkKL6sZVJaoFcF+gAwD1+6lSo+Kfrio+6X/MzABADAI4XAQy9buWgcvAAACykHD9EoDEAcP8YgDsH/tw5Us3/GIDtrBnZNwBQCgAQFgtMKYDTQKLYBXDepjD1fgGAAMC9wt8BYGUYAgABgJtiVi/3NAB3BMMOMQ2AKCDgJ+ywAwBbgJP90gC8u0CXAigFcHvY2KlJIjflEEWBEGEq/qcBSANwWEA7bC1gMQC00K1B+IlGVYkA7w2+yrTRRyAG4PZfrU+6rtmh+0sBlAIoBXBYgBMkEWAiQEXh63pVAKf1uEHDccxvA+iqAL4wAjEAd4CsDHAJn08iwESAlwVKAZQCuPxjjR//9QDgU0kgxCdRFEKAAoBaXVQGpvu1Q4QI/tH3K4A9P7SBvwPAF8471/ezThkUrO7X77OV5tqpTCIIMAC6XWU2+n710XidglWK7Lf7CzT+6/gqPihFI/tp/q/jqz4dagTDBU4O9os1Qop/KrNTozF9vhZ4+a+ez+8bz6rQ78u/9P0fAYDtMJwAwCYCWxcI1UlLg6IFJgAQAGAQvv5BZZzoRBoAmKz/aAEMAMQAnB4WA3Av8PMEEkUUAzCJvGjeGIB7hfk5LkABgDu+otNeDMCWIhQAigFAGWIAIABwTsFxgSgFgAA3ijRLAcC+L7cKJ0UeANgQplI80vCVAigFsIiwYgC2+RsACABMIje5nxaIAIAseF4nwEkDsE1wjU4iQM3gMYebCPBVijgAsMWHRIAjRazwMXYK5QIZA6Al7r4ugBcDcNtPKuBSAKUASgF8bwExQKvIUyLNAEAA4LTA2KdBqzMBTgzAhvA1ADEAgvAxAKcFKgO8zVMZoELQtEOrDPA2XyLAEeCJAXg+b4ytMrfP5/fzDSnCUavPkSLSBFu/T52q+PzxrAPWKYsiUngTvhhFWrKfilTUB2HdoQpgcgcg/1UVJUSG+j75n8rMlKKQ/VnnDYCh35f7qgyUZaTraYF4wTU+yf9m/5B/4vvU6l3vL/9hfHh5/OR/ih+cn7I/4oPs9xEAuC0sgKMFTAOs6yrjCgDcCEUBUBS1JvAawNbx1ffRv8YFOACgJeC+HgCACBsAOgAA/4L9AgDYgQcAthSOcrQCUJzg6ISoBTIAgAAy5jC1A1kZCC2/MQDY4KwMZAzAaQFtIAjQYwC2HNGKsAMAAYDLAjEANwMTAIgBeHP+cINQCuB0wBiAGABEqADAmwGsFMDGQMQAbFU68w40BiAG4LJAIsCXKTh1oksEeE7QUgDbApwGQBAkBuBNAB0DkAbgpjhw2IYQcCmAGIA3A1gMwAZAtPymAXh5AxIDEAMQA/C9BQgwVhFODMA9AX/cATAGYFuAYwAEQWIA3gTQMQAbA/B/AM2Qn43fOboKAAAAAElFTkSuQmCC" + +func generateFBC(b *testing.B, numPackages, numChannels, numBundles int) *declcfg.DeclarativeConfig { + pngData, err := base64.StdEncoding.DecodeString(randomPng) + if err != nil { + b.Error(err) + } + + fbc := &declcfg.DeclarativeConfig{} + + for i := 0; i < numPackages; i++ { + pkgName := fmt.Sprintf("pkg-%d", i) + fbc.Packages = append(fbc.Packages, declcfg.Package{ + Schema: declcfg.SchemaPackage, + Name: pkgName, + Description: fmt.Sprintf("%s description", pkgName), + Icon: &declcfg.Icon{ + Data: pngData, + MediaType: "image/png", + }, + }) + } + for i := 0; i < numChannels; i++ { + pkgName := fbc.Packages[rand.Intn(numPackages)].Name + channelName := fmt.Sprintf("channel-%d", i) + fbc.Channels = append(fbc.Channels, declcfg.Channel{ + Schema: declcfg.SchemaChannel, + Package: pkgName, + Name: channelName, + }) + } + for i := 0; i < numBundles; i++ { + pkgName := fbc.Packages[rand.Intn(numPackages)].Name + bundleName := fmt.Sprintf("bundle-%d", i) + version := fmt.Sprintf("0.%d.0", i) + bundle := declcfg.Bundle{ + Schema: declcfg.SchemaBundle, + Package: pkgName, + Image: fmt.Sprintf("bundles/%s", bundleName), + Properties: []property.Property{ + property.MustBuildPackage(pkgName, version), + property.MustBuildGVK("apps", "Deployment", "v1"), + property.MustBuildGVK("apps", "DaemonSet", "v1"), + property.MustBuildGVKRequired("", "Service", "v1"), + property.MustBuildPackageRequired("foo", "0.0.1"), + }, + } + + csv := genCsv(pkgName, version) + bundle.Properties = append(bundle.Properties, property.MustBuildCSVMetadata(csv)) + fbc.Bundles = append(fbc.Bundles, bundle) + + chIdx := rand.Intn(numChannels) + ch := fbc.Channels[chIdx] + replaces := "" + if len(ch.Entries) > 0 { + replaces = ch.Entries[len(ch.Entries)-1].Name + } + ch.Entries = append(ch.Entries, declcfg.ChannelEntry{ + Name: bundleName, + Replaces: replaces, + }) + fbc.Channels[chIdx] = ch + } + + return fbc +} + +func genCsv(pkgName, ver string) v1alpha1.ClusterServiceVersion { + csv := v1alpha1.ClusterServiceVersion{ + TypeMeta: metav1.TypeMeta{ + Kind: "ClusterServiceVersion", + APIVersion: "operators.coreos.com/v1alpha1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("%s.v%s", pkgName, ver), + Annotations: map[string]string{ + "alm-examples": `[ + { + "apiVersion": "example.com/v1alpha1", + "kind": "Example", + "metadata": { + "name": "example-sample" + }, + "spec": { + "image":{ + "repository":"example/example", + "tag":"v0.0.1", + "pullPolicy":"IfNotPresent", + "credentials":{} + }, + "labels":{}, + "conf":{ + "log":{"enabled":false,"config":{}}, + "logtostderr":"INFO", + "port":26257, + "http-port":8080, + "store":{"enabled":false,"type":null,"size":null,"attrs":null}}, + "statefulset":{ + "replicas":3, + "updateStrategy":{"type":"RollingUpdate"}, + "podManagementPolicy":"Parallel", + "budget":{"maxUnavailable":1}, + "args":[], + "env":[], + "secretMounts":[], + "labels":{"app.kubernetes.io/component":"example"}, + "annotations":{}, + "nodeAffinity":{}, + "podAffinity":{}, + "podAntiAffinity":{"topologyKey":"kubernetes.io/hostname","type":"soft","weight":100}, + "nodeSelector":{}, + "priorityClassName":"", + "tolerations":[], + "topologySpreadConstraints":{"maxSkew":1,"topologyKey":"topology.kubernetes.io/zone","whenUnsatisfiable":"ScheduleAnyway"}, + "resources":{}, + "customLivenessProbe":{}, + "customReadinessProbe":{} + }, + "ingress":{"enabled":false,"labels":{},"annotations":{},"paths":["/"],"hosts":[],"tls":[]}, + "prometheus":{"enabled":true}, + "serviceMonitor":{"enabled":false,"labels":{},"annotations":{},"interval":"10s","namespaced":false}, + "storage":{"hostPath":"","persistentVolume":{"enabled":true,"size":"100Gi","storageClass":"","labels":{},"annotations":{}}} + } + } + } + ]`, + "capabilities": "Basic Install", + "categories": "Application", + "certified": "false", + "containerImage": "quay.io/example/example:v0.0.1", + "createdAt": "1970-01-01T00-00-00Z", + "description": "Example Operator", + "operators.operatorframework.io/builder": "operator-sdk-v1.0.0", + "operators.operatorframework.io/project_layout": "go.sdk.operatorframework.io/v3", + "repository": "https://github.com/example/example", + "support": "Example, Inc.", + "olm.skipRange": "<0.0.1", + }, + }, + Spec: v1alpha1.ClusterServiceVersionSpec{ + Icon: []v1alpha1.Icon{ + { + Data: randomPng, + MediaType: "image/png", + }, + }, + CustomResourceDefinitions: v1alpha1.CustomResourceDefinitions{ + Owned: []v1alpha1.CRDDescription{ + { + Description: "Represents an Example instance", + DisplayName: "Example", + Kind: "Example", + Version: "v1alpha1", + Name: "examples.example.com", + Resources: []v1alpha1.APIResourceReference{ + { + Kind: "Deployment", + Version: "apps/v1", + }, + { + Kind: "Service", + Version: "v1", + }, + { + Kind: "ReplicaSet", + Version: "apps/v1", + }, + { + Kind: "Pod", + Version: "v1", + }, + { + Kind: "Secret", + Version: "v1", + }, + { + Kind: "ConfigMap", + Version: "v1", + }, + { + Kind: "PresistentVolumeClaim", + Version: "v1", + }, + { + Kind: "StatefulSet", + Version: "apps/v1", + }, + { + Kind: "Job", + Version: "batch/v1", + }, + }, + }, + }, + }, + DisplayName: "Example Operator", + InstallModes: []v1alpha1.InstallMode{ + { + Type: v1alpha1.InstallModeTypeOwnNamespace, + Supported: false, + }, + { + Type: v1alpha1.InstallModeTypeSingleNamespace, + Supported: false, + }, + { + Type: v1alpha1.InstallModeTypeMultiNamespace, + Supported: false, + }, + { + Type: v1alpha1.InstallModeTypeAllNamespaces, + Supported: true, + }, + }, + Keywords: []string{"example", "application", "sample", "foobar"}, + Links: []v1alpha1.AppLink{ + { + Name: "Example Operator", + URL: "https://www.example.com/operator", + }, + { + Name: "Example Operator Documentation", + URL: "https://www.example.com/operator/docs", + }, + { + Name: "Example Operator Support", + URL: "https://www.example.com/operator/support", + }, + { + Name: "Example Operator Source Code", + URL: "https://github.com/example/operator", + }, + }, + Maintainers: []v1alpha1.Maintainer{ + { + Email: "janedoe@example.com", + Name: "Jane Doe", + }, + { + Email: "johndoe@example.com", + Name: "John Doe", + }, + }, + Maturity: "alpha", + MinKubeVersion: "1.21.0", + Provider: v1alpha1.AppLink{ + Name: "Example, Inc.", + URL: "https://www.example.com", + }, + Version: version.OperatorVersion{Version: semver.MustParse(ver)}, + }, + } + return csv +} diff --git a/staging/operator-registry/alpha/declcfg/load_test.go b/staging/operator-registry/alpha/declcfg/load_test.go index 301002f164..c3f769c9b5 100644 --- a/staging/operator-registry/alpha/declcfg/load_test.go +++ b/staging/operator-registry/alpha/declcfg/load_test.go @@ -1,6 +1,7 @@ package declcfg import ( + "context" "encoding/json" "io/fs" "os" @@ -92,6 +93,73 @@ func TestLoadReader(t *testing.T) { } } +func TestWalkMetasFS(t *testing.T) { + type spec struct { + name string + fsys fs.FS + assertion require.ErrorAssertionFunc + expectNumPackages int + expectNumChannels int + expectNumBundles int + expectNumOthers int + } + specs := []spec{ + { + name: "Error/NilFS", + fsys: nil, + assertion: require.Error, + }, + { + name: "Error/NonExistentDir", + fsys: os.DirFS("non/existent/dir/"), + assertion: require.Error, + }, + { + name: "Error/Invalid", + fsys: invalidFS, + assertion: require.Error, + }, + { + name: "Success/ValidDir", + fsys: validFS, + assertion: require.NoError, + expectNumPackages: 3, + expectNumChannels: 0, + expectNumBundles: 12, + expectNumOthers: 1, + }, + } + + for _, s := range specs { + t.Run(s.name, func(t *testing.T) { + numPackages, numChannels, numBundles, numOthers := 0, 0, 0, 0 + err := WalkMetasFS(s.fsys, func(path string, meta *Meta, err error) error { + if err != nil { + return err + } + switch meta.Schema { + case SchemaPackage: + numPackages++ + case SchemaChannel: + numChannels++ + case SchemaBundle: + numBundles++ + default: + numOthers++ + } + return nil + }) + s.assertion(t, err) + if err == nil { + assert.Equal(t, s.expectNumPackages, numPackages, "unexpected package count") + assert.Equal(t, s.expectNumChannels, numChannels, "unexpected channel count") + assert.Equal(t, s.expectNumBundles, numBundles, "unexpected bundle count") + assert.Equal(t, s.expectNumOthers, numOthers, "unexpected others count") + } + }) + } +} + func TestLoadFS(t *testing.T) { type spec struct { name string @@ -271,7 +339,7 @@ func TestLoadFS(t *testing.T) { for _, s := range specs { t.Run(s.name, func(t *testing.T) { - cfg, err := LoadFS(s.fsys) + cfg, err := LoadFS(context.Background(), s.fsys) s.assertion(t, err) if err == nil { require.NotNil(t, cfg) diff --git a/staging/operator-registry/alpha/declcfg/write.go b/staging/operator-registry/alpha/declcfg/write.go index 96e132bc29..2f149e5afd 100644 --- a/staging/operator-registry/alpha/declcfg/write.go +++ b/staging/operator-registry/alpha/declcfg/write.go @@ -6,13 +6,15 @@ import ( "fmt" "io" "os" + "path/filepath" "sort" "strings" "github.com/blang/semver/v4" - "github.com/operator-framework/operator-registry/alpha/property" "k8s.io/apimachinery/pkg/util/sets" "sigs.k8s.io/yaml" + + "github.com/operator-framework/operator-registry/alpha/property" ) type MermaidWriter struct { @@ -124,12 +126,12 @@ func (writer *MermaidWriter) WriteChannels(cfg DeclarativeConfig, out io.Writer) if len(ce.Replaces) > 0 { replacesId := fmt.Sprintf("%s-%s", channelID, ce.Replaces) - pkgBuilder.WriteString(fmt.Sprintf(" %s[%q]-- %s --> %s[%q]\n", entryId, ce.Name, "replaces", replacesId, ce.Replaces)) + pkgBuilder.WriteString(fmt.Sprintf(" %s[%q]-- %s --> %s[%q]\n", replacesId, ce.Replaces, "replace", entryId, ce.Name)) } if len(ce.Skips) > 0 { for _, s := range ce.Skips { skipsId := fmt.Sprintf("%s-%s", channelID, s) - pkgBuilder.WriteString(fmt.Sprintf(" %s[%q]-- %s --> %s[%q]\n", entryId, ce.Name, "skips", skipsId, s)) + pkgBuilder.WriteString(fmt.Sprintf(" %s[%q]-- %s --> %s[%q]\n", skipsId, s, "skip", entryId, ce.Name)) } } if len(ce.SkipRange) > 0 { @@ -138,7 +140,7 @@ func (writer *MermaidWriter) WriteChannels(cfg DeclarativeConfig, out io.Writer) for _, edgeName := range filteredChannel.Entries { if skipRange(versionMap[edgeName.Name]) { skipRangeId := fmt.Sprintf("%s-%s", channelID, edgeName.Name) - pkgBuilder.WriteString(fmt.Sprintf(" %s[%q]-- \"%s(%s)\" --> %s[%q]\n", entryId, ce.Name, "skipRange", ce.SkipRange, skipRangeId, edgeName.Name)) + pkgBuilder.WriteString(fmt.Sprintf(" %s[%q]-- \"%s(%s)\" --> %s[%q]\n", skipRangeId, edgeName.Name, "skipRange", ce.SkipRange, entryId, ce.Name)) } } } else { @@ -425,3 +427,48 @@ func writeToEncoder(cfg DeclarativeConfig, enc encoder) error { } return nil } + +type WriteFunc func(config DeclarativeConfig, w io.Writer) error + +func WriteFS(cfg DeclarativeConfig, rootDir string, writeFunc WriteFunc, fileExt string) error { + channelsByPackage := map[string][]Channel{} + for _, c := range cfg.Channels { + channelsByPackage[c.Package] = append(channelsByPackage[c.Package], c) + } + bundlesByPackage := map[string][]Bundle{} + for _, b := range cfg.Bundles { + bundlesByPackage[b.Package] = append(bundlesByPackage[b.Package], b) + } + + if err := os.MkdirAll(rootDir, 0777); err != nil { + return err + } + + for _, p := range cfg.Packages { + fcfg := DeclarativeConfig{ + Packages: []Package{p}, + Channels: channelsByPackage[p.Name], + Bundles: bundlesByPackage[p.Name], + } + pkgDir := filepath.Join(rootDir, p.Name) + if err := os.MkdirAll(pkgDir, 0777); err != nil { + return err + } + filename := filepath.Join(pkgDir, fmt.Sprintf("catalog%s", fileExt)) + if err := writeFile(fcfg, filename, writeFunc); err != nil { + return err + } + } + return nil +} + +func writeFile(cfg DeclarativeConfig, filename string, writeFunc WriteFunc) error { + buf := &bytes.Buffer{} + if err := writeFunc(cfg, buf); err != nil { + return fmt.Errorf("write to buffer for %q: %v", filename, err) + } + if err := os.WriteFile(filename, buf.Bytes(), 0666); err != nil { + return fmt.Errorf("write file %q: %v", filename, err) + } + return nil +} diff --git a/staging/operator-registry/alpha/declcfg/write_test.go b/staging/operator-registry/alpha/declcfg/write_test.go index 46f6d68f8d..bbbd3482bf 100644 --- a/staging/operator-registry/alpha/declcfg/write_test.go +++ b/staging/operator-registry/alpha/declcfg/write_test.go @@ -491,16 +491,16 @@ func TestWriteMermaidChannels(t *testing.T) { subgraph anakin-dark["dark"] anakin-dark-anakin.v0.0.1["anakin.v0.0.1"] anakin-dark-anakin.v0.1.0["anakin.v0.1.0"] - anakin-dark-anakin.v0.1.0["anakin.v0.1.0"]-- replaces --> anakin-dark-anakin.v0.0.1["anakin.v0.0.1"] + anakin-dark-anakin.v0.0.1["anakin.v0.0.1"]-- replace --> anakin-dark-anakin.v0.1.0["anakin.v0.1.0"] anakin-dark-anakin.v0.1.1["anakin.v0.1.1"] - anakin-dark-anakin.v0.1.1["anakin.v0.1.1"]-- replaces --> anakin-dark-anakin.v0.0.1["anakin.v0.0.1"] - anakin-dark-anakin.v0.1.1["anakin.v0.1.1"]-- skips --> anakin-dark-anakin.v0.1.0["anakin.v0.1.0"] + anakin-dark-anakin.v0.0.1["anakin.v0.0.1"]-- replace --> anakin-dark-anakin.v0.1.1["anakin.v0.1.1"] + anakin-dark-anakin.v0.1.0["anakin.v0.1.0"]-- skip --> anakin-dark-anakin.v0.1.1["anakin.v0.1.1"] end %% channel "light" subgraph anakin-light["light"] anakin-light-anakin.v0.0.1["anakin.v0.0.1"] anakin-light-anakin.v0.1.0["anakin.v0.1.0"] - anakin-light-anakin.v0.1.0["anakin.v0.1.0"]-- replaces --> anakin-light-anakin.v0.0.1["anakin.v0.0.1"] + anakin-light-anakin.v0.0.1["anakin.v0.0.1"]-- replace --> anakin-light-anakin.v0.1.0["anakin.v0.1.0"] end end %% package "boba-fett" @@ -509,7 +509,7 @@ func TestWriteMermaidChannels(t *testing.T) { subgraph boba-fett-mando["mando"] boba-fett-mando-boba-fett.v1.0.0["boba-fett.v1.0.0"] boba-fett-mando-boba-fett.v2.0.0["boba-fett.v2.0.0"] - boba-fett-mando-boba-fett.v2.0.0["boba-fett.v2.0.0"]-- replaces --> boba-fett-mando-boba-fett.v1.0.0["boba-fett.v1.0.0"] + boba-fett-mando-boba-fett.v1.0.0["boba-fett.v1.0.0"]-- replace --> boba-fett-mando-boba-fett.v2.0.0["boba-fett.v2.0.0"] end end `, @@ -526,7 +526,7 @@ func TestWriteMermaidChannels(t *testing.T) { subgraph anakin-dark["dark"] anakin-dark-anakin.v0.1.0["anakin.v0.1.0"] anakin-dark-anakin.v0.1.1["anakin.v0.1.1"] - anakin-dark-anakin.v0.1.1["anakin.v0.1.1"]-- skips --> anakin-dark-anakin.v0.1.0["anakin.v0.1.0"] + anakin-dark-anakin.v0.1.0["anakin.v0.1.0"]-- skip --> anakin-dark-anakin.v0.1.1["anakin.v0.1.1"] end %% channel "light" subgraph anakin-light["light"] @@ -547,7 +547,7 @@ func TestWriteMermaidChannels(t *testing.T) { subgraph boba-fett-mando["mando"] boba-fett-mando-boba-fett.v1.0.0["boba-fett.v1.0.0"] boba-fett-mando-boba-fett.v2.0.0["boba-fett.v2.0.0"] - boba-fett-mando-boba-fett.v2.0.0["boba-fett.v2.0.0"]-- replaces --> boba-fett-mando-boba-fett.v1.0.0["boba-fett.v1.0.0"] + boba-fett-mando-boba-fett.v1.0.0["boba-fett.v1.0.0"]-- replace --> boba-fett-mando-boba-fett.v2.0.0["boba-fett.v2.0.0"] end end `, diff --git a/staging/operator-registry/alpha/model/model.go b/staging/operator-registry/alpha/model/model.go index a6ca060420..48861e49cd 100644 --- a/staging/operator-registry/alpha/model/model.go +++ b/staging/operator-registry/alpha/model/model.go @@ -141,8 +141,9 @@ type Channel struct { } // TODO(joelanford): This function determines the channel head by finding the bundle that has 0 -// incoming edges, based on replaces and skips. It also expects to find exactly one such bundle. -// Is this the correct algorithm? +// +// incoming edges, based on replaces and skips. It also expects to find exactly one such bundle. +// Is this the correct algorithm? func (c Channel) Head() (*Bundle, error) { incoming := map[string]int{} for _, b := range c.Bundles { @@ -210,11 +211,11 @@ func (c *Channel) Validate() error { // validateReplacesChain checks the replaces chain of a channel. // Specifically the following rules must be followed: -// 1. There must be exactly 1 channel head. -// 2. Beginning at the head, the replaces chain must reach all non-skipped entries. -// Non-skipped entries are defined as entries that are not skipped by any other entry in the channel. -// 3. There must be no cycles in the replaces chain. -// 4. The tail entry in the replaces chain is permitted to replace a non-existent entry. +// 1. There must be exactly 1 channel head. +// 2. Beginning at the head, the replaces chain must reach all non-skipped entries. +// Non-skipped entries are defined as entries that are not skipped by any other entry in the channel. +// 3. There must be no cycles in the replaces chain. +// 4. The tail entry in the replaces chain is permitted to replace a non-existent entry. func (c *Channel) validateReplacesChain() error { head, err := c.Head() if err != nil { diff --git a/staging/operator-registry/alpha/property/property.go b/staging/operator-registry/alpha/property/property.go index 695bfd6da8..5cb876846b 100644 --- a/staging/operator-registry/alpha/property/property.go +++ b/staging/operator-registry/alpha/property/property.go @@ -9,6 +9,9 @@ import ( "io/ioutil" "path/filepath" "reflect" + + "github.com/operator-framework/api/pkg/operators/v1alpha1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) type Property struct { @@ -40,8 +43,9 @@ type Package struct { } // NOTICE: The Channel properties are for internal use only. -// DO NOT use it for any public-facing functionalities. -// This API is in alpha stage and it is subject to change. +// +// DO NOT use it for any public-facing functionalities. +// This API is in alpha stage and it is subject to change. type Channel struct { ChannelName string `json:"channelName"` //Priority string `json:"priority"` @@ -69,6 +73,23 @@ type BundleObject struct { File `json:",inline"` } +type CSVMetadata struct { + Annotations map[string]string `json:"annotations,omitempty"` + APIServiceDefinitions v1alpha1.APIServiceDefinitions `json:"apiServiceDefinitions,omitempty"` + CustomResourceDefinitions v1alpha1.CustomResourceDefinitions `json:"crdDescriptions,omitempty"` + Description string `json:"description,omitempty"` + DisplayName string `json:"displayName,omitempty"` + InstallModes []v1alpha1.InstallMode `json:"installModes,omitempty"` + Keywords []string `json:"keywords,omitempty"` + Labels map[string]string `json:"labels,omitempty"` + Links []v1alpha1.AppLink `json:"links,omitempty"` + Maintainers []v1alpha1.Maintainer `json:"maintainers,omitempty"` + Maturity string `json:"maturity,omitempty"` + MinKubeVersion string `json:"minKubeVersion,omitempty"` + NativeAPIs []metav1.GroupVersionKind `json:"nativeAPIs,omitempty"` + Provider v1alpha1.AppLink `json:"provider,omitempty"` +} + type File struct { ref string data []byte @@ -128,6 +149,7 @@ type Properties struct { GVKsRequired []GVKRequired `hash:"set"` BundleObjects []BundleObject `hash:"set"` Channels []Channel `hash:"set"` + CSVMetadatas []CSVMetadata `hash:"set"` Others []Property `hash:"set"` } @@ -138,6 +160,7 @@ const ( TypeGVK = "olm.gvk" TypeGVKRequired = "olm.gvk.required" TypeBundleObject = "olm.bundle.object" + TypeCSVMetadata = "olm.csv.metadata" TypeChannel = "olm.channel" ) @@ -175,6 +198,12 @@ func Parse(in []Property) (*Properties, error) { return nil, ParseError{Idx: i, Typ: prop.Type, Err: err} } out.BundleObjects = append(out.BundleObjects, p) + case TypeCSVMetadata: + var p CSVMetadata + if err := json.Unmarshal(prop.Value, &p); err != nil { + return nil, ParseError{Idx: i, Typ: prop.Type, Err: err} + } + out.CSVMetadatas = append(out.CSVMetadatas, p) // NOTICE: The Channel properties are for internal use only. // DO NOT use it for any public-facing functionalities. // This API is in alpha stage and it is subject to change. @@ -286,9 +315,29 @@ func MustBuildBundleObjectData(data []byte) Property { return MustBuild(&BundleObject{File: File{data: data}}) } +func MustBuildCSVMetadata(csv v1alpha1.ClusterServiceVersion) Property { + return MustBuild(&CSVMetadata{ + Annotations: csv.GetAnnotations(), + APIServiceDefinitions: csv.Spec.APIServiceDefinitions, + CustomResourceDefinitions: csv.Spec.CustomResourceDefinitions, + Description: csv.Spec.Description, + DisplayName: csv.Spec.DisplayName, + InstallModes: csv.Spec.InstallModes, + Keywords: csv.Spec.Keywords, + Labels: csv.GetLabels(), + Links: csv.Spec.Links, + Maintainers: csv.Spec.Maintainers, + Maturity: csv.Spec.Maturity, + MinKubeVersion: csv.Spec.MinKubeVersion, + NativeAPIs: csv.Spec.NativeAPIs, + Provider: csv.Spec.Provider, + }) +} + // NOTICE: The Channel properties are for internal use only. -// DO NOT use it for any public-facing functionalities. -// This API is in alpha stage and it is subject to change. +// +// DO NOT use it for any public-facing functionalities. +// This API is in alpha stage and it is subject to change. func MustBuildChannelPriority(name string, priority int) Property { return MustBuild(&Channel{ChannelName: name, Priority: priority}) } diff --git a/staging/operator-registry/alpha/property/scheme.go b/staging/operator-registry/alpha/property/scheme.go index 28d8a5d147..ab176856fa 100644 --- a/staging/operator-registry/alpha/property/scheme.go +++ b/staging/operator-registry/alpha/property/scheme.go @@ -12,6 +12,7 @@ func init() { reflect.TypeOf(&GVK{}): TypeGVK, reflect.TypeOf(&GVKRequired{}): TypeGVKRequired, reflect.TypeOf(&BundleObject{}): TypeBundleObject, + reflect.TypeOf(&CSVMetadata{}): TypeCSVMetadata, // NOTICE: The Channel properties are for internal use only. // DO NOT use it for any public-facing functionalities. // This API is in alpha stage and it is subject to change. diff --git a/staging/operator-registry/alpha/template/composite/builder.go b/staging/operator-registry/alpha/template/composite/builder.go index 3d1f7af95d..953868f3e7 100644 --- a/staging/operator-registry/alpha/template/composite/builder.go +++ b/staging/operator-registry/alpha/template/composite/builder.go @@ -27,21 +27,14 @@ const ( CustomBuilderSchema = "olm.builder.custom" ) -type ContainerConfig struct { - ContainerTool string - BaseImage string - WorkingDir string -} - type BuilderConfig struct { - ContainerCfg ContainerConfig - OutputType string - InputDirectory string + WorkingDir string + OutputType string } type Builder interface { Build(ctx context.Context, reg image.Registry, dir string, td TemplateDefinition) error - Validate(dir string) error + Validate(ctx context.Context, dir string) error } type BasicBuilder struct { @@ -96,13 +89,13 @@ func (bb *BasicBuilder) Build(ctx context.Context, reg image.Registry, dir strin return fmt.Errorf("error rendering basic template: %v", err) } - destPath := path.Join(bb.builderCfg.ContainerCfg.WorkingDir, dir, basicConfig.Output) + destPath := path.Join(bb.builderCfg.WorkingDir, dir, basicConfig.Output) return build(dcfg, destPath, bb.builderCfg.OutputType) } -func (bb *BasicBuilder) Validate(dir string) error { - return validate(bb.builderCfg.ContainerCfg, dir) +func (bb *BasicBuilder) Validate(ctx context.Context, dir string) error { + return validate(ctx, bb.builderCfg, dir) } type SemverBuilder struct { @@ -158,13 +151,13 @@ func (sb *SemverBuilder) Build(ctx context.Context, reg image.Registry, dir stri return fmt.Errorf("error rendering semver template: %v", err) } - destPath := path.Join(sb.builderCfg.ContainerCfg.WorkingDir, dir, semverConfig.Output) + destPath := path.Join(sb.builderCfg.WorkingDir, dir, semverConfig.Output) return build(dcfg, destPath, sb.builderCfg.OutputType) } -func (sb *SemverBuilder) Validate(dir string) error { - return validate(sb.builderCfg.ContainerCfg, dir) +func (sb *SemverBuilder) Validate(ctx context.Context, dir string) error { + return validate(ctx, sb.builderCfg, dir) } type RawBuilder struct { @@ -218,13 +211,13 @@ func (rb *RawBuilder) Build(ctx context.Context, _ image.Registry, dir string, t return fmt.Errorf("error parsing raw input file: %s, %v", rawConfig.Input, err) } - destPath := path.Join(rb.builderCfg.ContainerCfg.WorkingDir, dir, rawConfig.Output) + destPath := path.Join(rb.builderCfg.WorkingDir, dir, rawConfig.Output) return build(dcfg, destPath, rb.builderCfg.OutputType) } -func (rb *RawBuilder) Validate(dir string) error { - return validate(rb.builderCfg.ContainerCfg, dir) +func (rb *RawBuilder) Validate(ctx context.Context, dir string) error { + return validate(ctx, rb.builderCfg, dir) } type CustomBuilder struct { @@ -268,13 +261,12 @@ func (cb *CustomBuilder) Build(ctx context.Context, reg image.Registry, dir stri } // build the command to execute cmd := exec.Command(customConfig.Command, customConfig.Args...) - cmd.Dir = cb.builderCfg.ContainerCfg.WorkingDir // custom template should output a valid FBC to STDOUT so we can // build the FBC just like all the other templates. v, err := cmd.Output() if err != nil { - return fmt.Errorf("running command %q: %v", cmd.String(), err) + return fmt.Errorf("running command %q: %v: %v", cmd.String(), err, v) } reader := bytes.NewReader(v) @@ -286,15 +278,15 @@ func (cb *CustomBuilder) Build(ctx context.Context, reg image.Registry, dir stri return fmt.Errorf("error parsing custom command output: %s, %v", strings.Join(cmdString, "'"), err) } - destPath := path.Join(cb.builderCfg.ContainerCfg.WorkingDir, dir, customConfig.Output) + destPath := path.Join(cb.builderCfg.WorkingDir, dir, customConfig.Output) // custom template should output a valid FBC to STDOUT so we can // build the FBC just like all the other templates. return build(dcfg, destPath, cb.builderCfg.OutputType) } -func (cb *CustomBuilder) Validate(dir string) error { - return validate(cb.builderCfg.ContainerCfg, dir) +func (cb *CustomBuilder) Validate(ctx context.Context, dir string) error { + return validate(ctx, cb.builderCfg, dir) } func writeDeclCfg(dcfg declcfg.DeclarativeConfig, w io.Writer, output string) error { @@ -308,18 +300,18 @@ func writeDeclCfg(dcfg declcfg.DeclarativeConfig, w io.Writer, output string) er } } -func validate(containerCfg ContainerConfig, dir string) error { +func validate(ctx context.Context, builderCfg BuilderConfig, dir string) error { - path := path.Join(containerCfg.WorkingDir, dir) + path := path.Join(builderCfg.WorkingDir, dir) s, err := os.Stat(path) if err != nil { - return fmt.Errorf("directory not found. validation path needs to be composed of ContainerConfig.WorkingDir+Component[].Destination.Path: %q: %v", path, err) + return fmt.Errorf("directory not found. validation path needs to be composed of BuilderConfig.WorkingDir+Component[].Destination.Path: %q: %v", path, err) } if !s.IsDir() { return fmt.Errorf("%q is not a directory", path) } - if err := config.Validate(os.DirFS(path)); err != nil { + if err := config.Validate(ctx, os.DirFS(path)); err != nil { return fmt.Errorf("validation failure in path %q: %v", path, err) } return nil diff --git a/staging/operator-registry/alpha/template/composite/builder_test.go b/staging/operator-registry/alpha/template/composite/builder_test.go index af7850b076..63a127a974 100644 --- a/staging/operator-registry/alpha/template/composite/builder_test.go +++ b/staging/operator-registry/alpha/template/composite/builder_test.go @@ -8,8 +8,9 @@ import ( "path" "testing" - "github.com/operator-framework/operator-registry/pkg/image/containerdregistry" "github.com/stretchr/testify/require" + + "github.com/operator-framework/operator-registry/pkg/image/containerdregistry" ) // TODO: Should we consolidate all these tests into a singular test function? @@ -36,11 +37,7 @@ func TestBasicBuilder(t *testing.T) { name: "successful basic build yaml output", validate: true, basicBuilder: NewBasicBuilder(BuilderConfig{ - ContainerCfg: ContainerConfig{ - ContainerTool: "docker", - BaseImage: "quay.io/operator-framework/opm:latest", - WorkingDir: testDir, - }, + WorkingDir: testDir, OutputType: "yaml", }), templateDefinition: TemplateDefinition{ @@ -71,11 +68,7 @@ func TestBasicBuilder(t *testing.T) { name: "successful basic build json output", validate: true, basicBuilder: NewBasicBuilder(BuilderConfig{ - ContainerCfg: ContainerConfig{ - ContainerTool: "docker", - BaseImage: "quay.io/operator-framework/opm:latest", - WorkingDir: testDir, - }, + WorkingDir: testDir, OutputType: "json", }), templateDefinition: TemplateDefinition{ @@ -106,11 +99,7 @@ func TestBasicBuilder(t *testing.T) { name: "invalid template configuration", validate: false, basicBuilder: NewBasicBuilder(BuilderConfig{ - ContainerCfg: ContainerConfig{ - ContainerTool: "docker", - BaseImage: "quay.io/operator-framework/opm:latest", - WorkingDir: testDir, - }, + WorkingDir: testDir, OutputType: "yaml", }), templateDefinition: TemplateDefinition{ @@ -129,11 +118,7 @@ func TestBasicBuilder(t *testing.T) { name: "invalid output type", validate: false, basicBuilder: NewBasicBuilder(BuilderConfig{ - ContainerCfg: ContainerConfig{ - ContainerTool: "docker", - BaseImage: "quay.io/operator-framework/opm:latest", - WorkingDir: testDir, - }, + WorkingDir: testDir, OutputType: "invalid", }), templateDefinition: TemplateDefinition{ @@ -152,11 +137,7 @@ func TestBasicBuilder(t *testing.T) { name: "invalid schema", validate: false, basicBuilder: NewBasicBuilder(BuilderConfig{ - ContainerCfg: ContainerConfig{ - ContainerTool: "docker", - BaseImage: "quay.io/operator-framework/opm:latest", - WorkingDir: testDir, - }, + WorkingDir: testDir, OutputType: "yaml", }), templateDefinition: TemplateDefinition{ @@ -172,11 +153,7 @@ func TestBasicBuilder(t *testing.T) { name: "template config has empty input", validate: false, basicBuilder: NewBasicBuilder(BuilderConfig{ - ContainerCfg: ContainerConfig{ - ContainerTool: "docker", - BaseImage: "quay.io/operator-framework/opm:latest", - WorkingDir: testDir, - }, + WorkingDir: testDir, OutputType: "yaml", }), templateDefinition: TemplateDefinition{ @@ -197,11 +174,7 @@ func TestBasicBuilder(t *testing.T) { name: "template config has empty output", validate: false, basicBuilder: NewBasicBuilder(BuilderConfig{ - ContainerCfg: ContainerConfig{ - ContainerTool: "docker", - BaseImage: "quay.io/operator-framework/opm:latest", - WorkingDir: testDir, - }, + WorkingDir: testDir, OutputType: "yaml", }), templateDefinition: TemplateDefinition{ @@ -222,11 +195,7 @@ func TestBasicBuilder(t *testing.T) { name: "template config has empty input & output", validate: false, basicBuilder: NewBasicBuilder(BuilderConfig{ - ContainerCfg: ContainerConfig{ - ContainerTool: "docker", - BaseImage: "quay.io/operator-framework/opm:latest", - WorkingDir: testDir, - }, + WorkingDir: testDir, OutputType: "yaml", }), templateDefinition: TemplateDefinition{ @@ -244,7 +213,6 @@ func TestBasicBuilder(t *testing.T) { } for i, tc := range testCases { - tc.basicBuilder.builderCfg.InputDirectory = testDir t.Run(tc.name, func(t *testing.T) { outDir := fmt.Sprintf("basic-%d", i) outPath := path.Join(testDir, outDir) @@ -274,7 +242,7 @@ func TestBasicBuilder(t *testing.T) { tc.buildAssertions(t, outPath, buildErr) if tc.validate { - validateErr := tc.basicBuilder.Validate(outDir) + validateErr := tc.basicBuilder.Validate(context.Background(), outDir) tc.validateAssertions(t, validateErr) } }) @@ -326,15 +294,55 @@ properties: value: packageName: webhook-operator version: 0.0.1 -- type: olm.bundle.object - value: - data: eyJhcGlWZXJzaW9uIjoicmJhYy5hdXRob3JpemF0aW9uLms4cy5pby92MWJldGExIiwia2luZCI6IkNsdXN0ZXJSb2xlIiwibWV0YWRhdGEiOnsiY3JlYXRpb25UaW1lc3RhbXAiOm51bGwsIm5hbWUiOiJ3ZWJob29rLW9wZXJhdG9yLW1ldHJpY3MtcmVhZGVyIn0sInJ1bGVzIjpbeyJub25SZXNvdXJjZVVSTHMiOlsiL21ldHJpY3MiXSwidmVyYnMiOlsiZ2V0Il19XX0= -- type: olm.bundle.object +- type: olm.csv.metadata value: - data: eyJhcGlWZXJzaW9uIjoib3BlcmF0b3JzLmNvcmVvcy5jb20vdjFhbHBoYTEiLCJraW5kIjoiQ2x1c3RlclNlcnZpY2VWZXJzaW9uIiwibWV0YWRhdGEiOnsiYW5ub3RhdGlvbnMiOnsiYWxtLWV4YW1wbGVzIjoiW1xuICB7XG4gICAgXCJhcGlWZXJzaW9uXCI6IFwid2ViaG9vay5vcGVyYXRvcnMuY29yZW9zLmlvL3YxXCIsXG4gICAgXCJraW5kXCI6IFwiV2ViaG9va1Rlc3RcIixcbiAgICBcIm1ldGFkYXRhXCI6IHtcbiAgICAgIFwibmFtZVwiOiBcIndlYmhvb2t0ZXN0LXNhbXBsZVwiLFxuICAgICAgXCJuYW1lc3BhY2VcIjogXCJ3ZWJob29rLW9wZXJhdG9yLXN5c3RlbVwiXG4gICAgfSxcbiAgICBcInNwZWNcIjoge1xuICAgICAgXCJ2YWxpZFwiOiB0cnVlXG4gICAgfVxuICB9XG5dIiwiY2FwYWJpbGl0aWVzIjoiQmFzaWMgSW5zdGFsbCIsIm9wZXJhdG9ycy5vcGVyYXRvcmZyYW1ld29yay5pby9idWlsZGVyIjoib3BlcmF0b3Itc2RrLXYxLjAuMCIsIm9wZXJhdG9ycy5vcGVyYXRvcmZyYW1ld29yay5pby9wcm9qZWN0X2xheW91dCI6ImdvIn0sIm5hbWUiOiJ3ZWJob29rLW9wZXJhdG9yLnYwLjAuMSIsIm5hbWVzcGFjZSI6InBsYWNlaG9sZGVyIn0sInNwZWMiOnsiYXBpc2VydmljZWRlZmluaXRpb25zIjp7fSwiY3VzdG9tcmVzb3VyY2VkZWZpbml0aW9ucyI6eyJvd25lZCI6W3sia2luZCI6IldlYmhvb2tUZXN0IiwibmFtZSI6IndlYmhvb2t0ZXN0cy53ZWJob29rLm9wZXJhdG9ycy5jb3Jlb3MuaW8iLCJ2ZXJzaW9uIjoidjEifV19LCJkZXNjcmlwdGlvbiI6IldlYmhvb2sgT3BlcmF0b3IgZGVzY3JpcHRpb24uIFRPRE8uIiwiZGlzcGxheU5hbWUiOiJXZWJob29rIE9wZXJhdG9yIiwiaWNvbiI6W3siYmFzZTY0ZGF0YSI6IiIsIm1lZGlhdHlwZSI6IiJ9XSwiaW5zdGFsbCI6eyJzcGVjIjp7ImNsdXN0ZXJQZXJtaXNzaW9ucyI6W3sicnVsZXMiOlt7ImFwaUdyb3VwcyI6WyJ3ZWJob29rLm9wZXJhdG9ycy5jb3Jlb3MuaW8iXSwicmVzb3VyY2VzIjpbIndlYmhvb2t0ZXN0cyJdLCJ2ZXJicyI6WyJjcmVhdGUiLCJkZWxldGUiLCJnZXQiLCJsaXN0IiwicGF0Y2giLCJ1cGRhdGUiLCJ3YXRjaCJdfSx7ImFwaUdyb3VwcyI6WyJ3ZWJob29rLm9wZXJhdG9ycy5jb3Jlb3MuaW8iXSwicmVzb3VyY2VzIjpbIndlYmhvb2t0ZXN0cy9zdGF0dXMiXSwidmVyYnMiOlsiZ2V0IiwicGF0Y2giLCJ1cGRhdGUiXX0seyJhcGlHcm91cHMiOlsiYXV0aGVudGljYXRpb24uazhzLmlvIl0sInJlc291cmNlcyI6WyJ0b2tlbnJldmlld3MiXSwidmVyYnMiOlsiY3JlYXRlIl19LHsiYXBpR3JvdXBzIjpbImF1dGhvcml6YXRpb24uazhzLmlvIl0sInJlc291cmNlcyI6WyJzdWJqZWN0YWNjZXNzcmV2aWV3cyJdLCJ2ZXJicyI6WyJjcmVhdGUiXX1dLCJzZXJ2aWNlQWNjb3VudE5hbWUiOiJkZWZhdWx0In1dLCJkZXBsb3ltZW50cyI6W3sibmFtZSI6IndlYmhvb2stb3BlcmF0b3Itd2ViaG9vayIsInNwZWMiOnsicmVwbGljYXMiOjEsInNlbGVjdG9yIjp7Im1hdGNoTGFiZWxzIjp7ImNvbnRyb2wtcGxhbmUiOiJjb250cm9sbGVyLW1hbmFnZXIifX0sInN0cmF0ZWd5Ijp7fSwidGVtcGxhdGUiOnsibWV0YWRhdGEiOnsibGFiZWxzIjp7ImNvbnRyb2wtcGxhbmUiOiJjb250cm9sbGVyLW1hbmFnZXIifX0sInNwZWMiOnsiY29udGFpbmVycyI6W3siYXJncyI6WyItLXNlY3VyZS1saXN0ZW4tYWRkcmVzcz0wLjAuMC4wOjg0NDMiLCItLXVwc3RyZWFtPWh0dHA6Ly8xMjcuMC4wLjE6ODA4MC8iLCItLWxvZ3Rvc3RkZXJyPXRydWUiLCItLXY9MTAiXSwiaW1hZ2UiOiJnY3IuaW8va3ViZWJ1aWxkZXIva3ViZS1yYmFjLXByb3h5OnYwLjUuMCIsIm5hbWUiOiJrdWJlLXJiYWMtcHJveHkiLCJwb3J0cyI6W3siY29udGFpbmVyUG9ydCI6ODQ0MywibmFtZSI6Imh0dHBzIn1dLCJyZXNvdXJjZXMiOnt9fSx7ImFyZ3MiOlsiLS1tZXRyaWNzLWFkZHI9MTI3LjAuMC4xOjgwODAiLCItLWVuYWJsZS1sZWFkZXItZWxlY3Rpb24iXSwiY29tbWFuZCI6WyIvbWFuYWdlciJdLCJpbWFnZSI6InF1YXkuaW8vb2xtdGVzdC93ZWJob29rLW9wZXJhdG9yOjAuMC4zIiwibmFtZSI6Im1hbmFnZXIiLCJwb3J0cyI6W3siY29udGFpbmVyUG9ydCI6OTQ0MywibmFtZSI6IndlYmhvb2stc2VydmVyIiwicHJvdG9jb2wiOiJUQ1AifV0sInJlc291cmNlcyI6eyJsaW1pdHMiOnsiY3B1IjoiMTAwbSIsIm1lbW9yeSI6IjMwTWkifSwicmVxdWVzdHMiOnsiY3B1IjoiMTAwbSIsIm1lbW9yeSI6IjIwTWkifX19XSwidGVybWluYXRpb25HcmFjZVBlcmlvZFNlY29uZHMiOjEwfX19fV0sInBlcm1pc3Npb25zIjpbeyJydWxlcyI6W3siYXBpR3JvdXBzIjpbIiJdLCJyZXNvdXJjZXMiOlsiY29uZmlnbWFwcyJdLCJ2ZXJicyI6WyJnZXQiLCJsaXN0Iiwid2F0Y2giLCJjcmVhdGUiLCJ1cGRhdGUiLCJwYXRjaCIsImRlbGV0ZSJdfSx7ImFwaUdyb3VwcyI6WyIiXSwicmVzb3VyY2VzIjpbImNvbmZpZ21hcHMvc3RhdHVzIl0sInZlcmJzIjpbImdldCIsInVwZGF0ZSIsInBhdGNoIl19LHsiYXBpR3JvdXBzIjpbIiJdLCJyZXNvdXJjZXMiOlsiZXZlbnRzIl0sInZlcmJzIjpbImNyZWF0ZSJdfV0sInNlcnZpY2VBY2NvdW50TmFtZSI6ImRlZmF1bHQifV19LCJzdHJhdGVneSI6ImRlcGxveW1lbnQifSwiaW5zdGFsbE1vZGVzIjpbeyJzdXBwb3J0ZWQiOmZhbHNlLCJ0eXBlIjoiT3duTmFtZXNwYWNlIn0seyJzdXBwb3J0ZWQiOmZhbHNlLCJ0eXBlIjoiU2luZ2xlTmFtZXNwYWNlIn0seyJzdXBwb3J0ZWQiOmZhbHNlLCJ0eXBlIjoiTXVsdGlOYW1lc3BhY2UifSx7InN1cHBvcnRlZCI6dHJ1ZSwidHlwZSI6IkFsbE5hbWVzcGFjZXMifV0sImtleXdvcmRzIjpbIndlYmhvb2stb3BlcmF0b3IiXSwibGlua3MiOlt7Im5hbWUiOiJXZWJob29rIE9wZXJhdG9yIiwidXJsIjoiaHR0cHM6Ly93ZWJob29rLW9wZXJhdG9yLmRvbWFpbiJ9XSwibWFpbnRhaW5lcnMiOlt7ImVtYWlsIjoieW91ckBlbWFpbC5jb20iLCJuYW1lIjoiTWFpbnRhaW5lciBOYW1lIn1dLCJtYXR1cml0eSI6ImFscGhhIiwicHJvdmlkZXIiOnsibmFtZSI6IlByb3ZpZGVyIE5hbWUiLCJ1cmwiOiJodHRwczovL3lvdXIuZG9tYWluIn0sInZlcnNpb24iOiIwLjAuMSIsIndlYmhvb2tkZWZpbml0aW9ucyI6W3siYWRtaXNzaW9uUmV2aWV3VmVyc2lvbnMiOlsidjFiZXRhMSIsInYxIl0sImNvbnRhaW5lclBvcnQiOjQ0MywiZGVwbG95bWVudE5hbWUiOiJ3ZWJob29rLW9wZXJhdG9yLXdlYmhvb2siLCJmYWlsdXJlUG9saWN5IjoiRmFpbCIsImdlbmVyYXRlTmFtZSI6InZ3ZWJob29rdGVzdC5rYi5pbyIsInJ1bGVzIjpbeyJhcGlHcm91cHMiOlsid2ViaG9vay5vcGVyYXRvcnMuY29yZW9zLmlvIl0sImFwaVZlcnNpb25zIjpbInYxIl0sIm9wZXJhdGlvbnMiOlsiQ1JFQVRFIiwiVVBEQVRFIl0sInJlc291cmNlcyI6WyJ3ZWJob29rdGVzdHMiXX1dLCJzaWRlRWZmZWN0cyI6Ik5vbmUiLCJ0YXJnZXRQb3J0Ijo0MzQzLCJ0eXBlIjoiVmFsaWRhdGluZ0FkbWlzc2lvbldlYmhvb2siLCJ3ZWJob29rUGF0aCI6Ii92YWxpZGF0ZS13ZWJob29rLW9wZXJhdG9ycy1jb3Jlb3MtaW8tdjEtd2ViaG9va3Rlc3QifSx7ImFkbWlzc2lvblJldmlld1ZlcnNpb25zIjpbInYxYmV0YTEiLCJ2MSJdLCJjb250YWluZXJQb3J0Ijo0NDMsImRlcGxveW1lbnROYW1lIjoid2ViaG9vay1vcGVyYXRvci13ZWJob29rIiwiZmFpbHVyZVBvbGljeSI6IkZhaWwiLCJnZW5lcmF0ZU5hbWUiOiJtd2ViaG9va3Rlc3Qua2IuaW8iLCJydWxlcyI6W3siYXBpR3JvdXBzIjpbIndlYmhvb2sub3BlcmF0b3JzLmNvcmVvcy5pbyJdLCJhcGlWZXJzaW9ucyI6WyJ2MSJdLCJvcGVyYXRpb25zIjpbIkNSRUFURSIsIlVQREFURSJdLCJyZXNvdXJjZXMiOlsid2ViaG9va3Rlc3RzIl19XSwic2lkZUVmZmVjdHMiOiJOb25lIiwidGFyZ2V0UG9ydCI6NDM0MywidHlwZSI6Ik11dGF0aW5nQWRtaXNzaW9uV2ViaG9vayIsIndlYmhvb2tQYXRoIjoiL211dGF0ZS13ZWJob29rLW9wZXJhdG9ycy1jb3Jlb3MtaW8tdjEtd2ViaG9va3Rlc3QifSx7ImFkbWlzc2lvblJldmlld1ZlcnNpb25zIjpbInYxYmV0YTEiLCJ2MSJdLCJjb250YWluZXJQb3J0Ijo0NDMsImNvbnZlcnNpb25DUkRzIjpbIndlYmhvb2t0ZXN0cy53ZWJob29rLm9wZXJhdG9ycy5jb3Jlb3MuaW8iXSwiZGVwbG95bWVudE5hbWUiOiJ3ZWJob29rLW9wZXJhdG9yLXdlYmhvb2siLCJmYWlsdXJlUG9saWN5IjoiRmFpbCIsImdlbmVyYXRlTmFtZSI6ImN3ZWJob29rdGVzdC5rYi5pbyIsInJ1bGVzIjpbeyJhcGlHcm91cHMiOlsid2ViaG9vay5vcGVyYXRvcnMuY29yZW9zLmlvIl0sImFwaVZlcnNpb25zIjpbInYxIl0sIm9wZXJhdGlvbnMiOlsiQ1JFQVRFIiwiVVBEQVRFIl0sInJlc291cmNlcyI6WyJ3ZWJob29rdGVzdHMiXX1dLCJzaWRlRWZmZWN0cyI6Ik5vbmUiLCJ0YXJnZXRQb3J0Ijo0MzQzLCJ0eXBlIjoiQ29udmVyc2lvbldlYmhvb2siLCJ3ZWJob29rUGF0aCI6Ii9jb252ZXJ0In1dfX0= -- type: olm.bundle.object - value: - data: eyJhcGlWZXJzaW9uIjoiYXBpZXh0ZW5zaW9ucy5rOHMuaW8vdjFiZXRhMSIsImtpbmQiOiJDdXN0b21SZXNvdXJjZURlZmluaXRpb24iLCJtZXRhZGF0YSI6eyJhbm5vdGF0aW9ucyI6eyJjb250cm9sbGVyLWdlbi5rdWJlYnVpbGRlci5pby92ZXJzaW9uIjoidjAuMy4wIn0sImNyZWF0aW9uVGltZXN0YW1wIjpudWxsLCJuYW1lIjoid2ViaG9va3Rlc3RzLndlYmhvb2sub3BlcmF0b3JzLmNvcmVvcy5pbyJ9LCJzcGVjIjp7Imdyb3VwIjoid2ViaG9vay5vcGVyYXRvcnMuY29yZW9zLmlvIiwibmFtZXMiOnsia2luZCI6IldlYmhvb2tUZXN0IiwibGlzdEtpbmQiOiJXZWJob29rVGVzdExpc3QiLCJwbHVyYWwiOiJ3ZWJob29rdGVzdHMiLCJzaW5ndWxhciI6IndlYmhvb2t0ZXN0In0sInByZXNlcnZlVW5rbm93bkZpZWxkcyI6ZmFsc2UsInNjb3BlIjoiTmFtZXNwYWNlZCIsInZlcnNpb24iOiJ2MSIsInZlcnNpb25zIjpbeyJuYW1lIjoidjEiLCJzY2hlbWEiOnsib3BlbkFQSVYzU2NoZW1hIjp7ImRlc2NyaXB0aW9uIjoiV2ViaG9va1Rlc3QgaXMgdGhlIFNjaGVtYSBmb3IgdGhlIHdlYmhvb2t0ZXN0cyBBUEkiLCJwcm9wZXJ0aWVzIjp7ImFwaVZlcnNpb24iOnsiZGVzY3JpcHRpb24iOiJBUElWZXJzaW9uIGRlZmluZXMgdGhlIHZlcnNpb25lZCBzY2hlbWEgb2YgdGhpcyByZXByZXNlbnRhdGlvbiBvZiBhbiBvYmplY3QuIFNlcnZlcnMgc2hvdWxkIGNvbnZlcnQgcmVjb2duaXplZCBzY2hlbWFzIHRvIHRoZSBsYXRlc3QgaW50ZXJuYWwgdmFsdWUsIGFuZCBtYXkgcmVqZWN0IHVucmVjb2duaXplZCB2YWx1ZXMuIE1vcmUgaW5mbzogaHR0cHM6Ly9naXQuazhzLmlvL2NvbW11bml0eS9jb250cmlidXRvcnMvZGV2ZWwvc2lnLWFyY2hpdGVjdHVyZS9hcGktY29udmVudGlvbnMubWQjcmVzb3VyY2VzIiwidHlwZSI6InN0cmluZyJ9LCJraW5kIjp7ImRlc2NyaXB0aW9uIjoiS2luZCBpcyBhIHN0cmluZyB2YWx1ZSByZXByZXNlbnRpbmcgdGhlIFJFU1QgcmVzb3VyY2UgdGhpcyBvYmplY3QgcmVwcmVzZW50cy4gU2VydmVycyBtYXkgaW5mZXIgdGhpcyBmcm9tIHRoZSBlbmRwb2ludCB0aGUgY2xpZW50IHN1Ym1pdHMgcmVxdWVzdHMgdG8uIENhbm5vdCBiZSB1cGRhdGVkLiBJbiBDYW1lbENhc2UuIE1vcmUgaW5mbzogaHR0cHM6Ly9naXQuazhzLmlvL2NvbW11bml0eS9jb250cmlidXRvcnMvZGV2ZWwvc2lnLWFyY2hpdGVjdHVyZS9hcGktY29udmVudGlvbnMubWQjdHlwZXMta2luZHMiLCJ0eXBlIjoic3RyaW5nIn0sIm1ldGFkYXRhIjp7InR5cGUiOiJvYmplY3QifSwic3BlYyI6eyJkZXNjcmlwdGlvbiI6IldlYmhvb2tUZXN0U3BlYyBkZWZpbmVzIHRoZSBkZXNpcmVkIHN0YXRlIG9mIFdlYmhvb2tUZXN0IiwicHJvcGVydGllcyI6eyJtdXRhdGUiOnsiZGVzY3JpcHRpb24iOiJNdXRhdGUgaXMgYSBmaWVsZCB0aGF0IHdpbGwgYmUgc2V0IHRvIHRydWUgYnkgdGhlIG11dGF0aW5nIHdlYmhvb2suIiwidHlwZSI6ImJvb2xlYW4ifSwidmFsaWQiOnsiZGVzY3JpcHRpb24iOiJWYWxpZCBtdXN0IGJlIHNldCB0byB0cnVlIG9yIHRoZSB2YWxpZGF0aW9uIHdlYmhvb2sgd2lsbCByZWplY3QgdGhlIHJlc291cmNlLiIsInR5cGUiOiJib29sZWFuIn19LCJyZXF1aXJlZCI6WyJ2YWxpZCJdLCJ0eXBlIjoib2JqZWN0In0sInN0YXR1cyI6eyJkZXNjcmlwdGlvbiI6IldlYmhvb2tUZXN0U3RhdHVzIGRlZmluZXMgdGhlIG9ic2VydmVkIHN0YXRlIG9mIFdlYmhvb2tUZXN0IiwidHlwZSI6Im9iamVjdCJ9fSwidHlwZSI6Im9iamVjdCJ9fSwic2VydmVkIjp0cnVlLCJzdG9yYWdlIjp0cnVlfSx7Im5hbWUiOiJ2MiIsInNjaGVtYSI6eyJvcGVuQVBJVjNTY2hlbWEiOnsiZGVzY3JpcHRpb24iOiJXZWJob29rVGVzdCBpcyB0aGUgU2NoZW1hIGZvciB0aGUgd2ViaG9va3Rlc3RzIEFQSSIsInByb3BlcnRpZXMiOnsiYXBpVmVyc2lvbiI6eyJkZXNjcmlwdGlvbiI6IkFQSVZlcnNpb24gZGVmaW5lcyB0aGUgdmVyc2lvbmVkIHNjaGVtYSBvZiB0aGlzIHJlcHJlc2VudGF0aW9uIG9mIGFuIG9iamVjdC4gU2VydmVycyBzaG91bGQgY29udmVydCByZWNvZ25pemVkIHNjaGVtYXMgdG8gdGhlIGxhdGVzdCBpbnRlcm5hbCB2YWx1ZSwgYW5kIG1heSByZWplY3QgdW5yZWNvZ25pemVkIHZhbHVlcy4gTW9yZSBpbmZvOiBodHRwczovL2dpdC5rOHMuaW8vY29tbXVuaXR5L2NvbnRyaWJ1dG9ycy9kZXZlbC9zaWctYXJjaGl0ZWN0dXJlL2FwaS1jb252ZW50aW9ucy5tZCNyZXNvdXJjZXMiLCJ0eXBlIjoic3RyaW5nIn0sImtpbmQiOnsiZGVzY3JpcHRpb24iOiJLaW5kIGlzIGEgc3RyaW5nIHZhbHVlIHJlcHJlc2VudGluZyB0aGUgUkVTVCByZXNvdXJjZSB0aGlzIG9iamVjdCByZXByZXNlbnRzLiBTZXJ2ZXJzIG1heSBpbmZlciB0aGlzIGZyb20gdGhlIGVuZHBvaW50IHRoZSBjbGllbnQgc3VibWl0cyByZXF1ZXN0cyB0by4gQ2Fubm90IGJlIHVwZGF0ZWQuIEluIENhbWVsQ2FzZS4gTW9yZSBpbmZvOiBodHRwczovL2dpdC5rOHMuaW8vY29tbXVuaXR5L2NvbnRyaWJ1dG9ycy9kZXZlbC9zaWctYXJjaGl0ZWN0dXJlL2FwaS1jb252ZW50aW9ucy5tZCN0eXBlcy1raW5kcyIsInR5cGUiOiJzdHJpbmcifSwibWV0YWRhdGEiOnsidHlwZSI6Im9iamVjdCJ9LCJzcGVjIjp7ImRlc2NyaXB0aW9uIjoiV2ViaG9va1Rlc3RTcGVjIGRlZmluZXMgdGhlIGRlc2lyZWQgc3RhdGUgb2YgV2ViaG9va1Rlc3QiLCJwcm9wZXJ0aWVzIjp7ImNvbnZlcnNpb24iOnsiZGVzY3JpcHRpb24iOiJDb252ZXJzaW9uIGlzIGFuIGV4YW1wbGUgZmllbGQgb2YgV2ViaG9va1Rlc3QuIEVkaXQgV2ViaG9va1Rlc3RfdHlwZXMuZ28gdG8gcmVtb3ZlL3VwZGF0ZSIsInByb3BlcnRpZXMiOnsibXV0YXRlIjp7ImRlc2NyaXB0aW9uIjoiTXV0YXRlIGlzIGEgZmllbGQgdGhhdCB3aWxsIGJlIHNldCB0byB0cnVlIGJ5IHRoZSBtdXRhdGluZyB3ZWJob29rLiIsInR5cGUiOiJib29sZWFuIn0sInZhbGlkIjp7ImRlc2NyaXB0aW9uIjoiVmFsaWQgbXVzdCBiZSBzZXQgdG8gdHJ1ZSBvciB0aGUgdmFsaWRhdGlvbiB3ZWJob29rIHdpbGwgcmVqZWN0IHRoZSByZXNvdXJjZS4iLCJ0eXBlIjoiYm9vbGVhbiJ9fSwicmVxdWlyZWQiOlsidmFsaWQiXSwidHlwZSI6Im9iamVjdCJ9fSwicmVxdWlyZWQiOlsiY29udmVyc2lvbiJdLCJ0eXBlIjoib2JqZWN0In0sInN0YXR1cyI6eyJkZXNjcmlwdGlvbiI6IldlYmhvb2tUZXN0U3RhdHVzIGRlZmluZXMgdGhlIG9ic2VydmVkIHN0YXRlIG9mIFdlYmhvb2tUZXN0IiwidHlwZSI6Im9iamVjdCJ9fSwidHlwZSI6Im9iamVjdCJ9fSwic2VydmVkIjp0cnVlLCJzdG9yYWdlIjpmYWxzZX1dfSwic3RhdHVzIjp7ImFjY2VwdGVkTmFtZXMiOnsia2luZCI6IiIsInBsdXJhbCI6IiJ9LCJjb25kaXRpb25zIjpbXSwic3RvcmVkVmVyc2lvbnMiOltdfX0= + annotations: + alm-examples: |- + [ + { + "apiVersion": "webhook.operators.coreos.io/v1", + "kind": "WebhookTest", + "metadata": { + "name": "webhooktest-sample", + "namespace": "webhook-operator-system" + }, + "spec": { + "valid": true + } + } + ] + capabilities: Basic Install + operators.operatorframework.io/builder: operator-sdk-v1.0.0 + operators.operatorframework.io/project_layout: go + apiServiceDefinitions: {} + crdDescriptions: + owned: + - kind: WebhookTest + name: webhooktests.webhook.operators.coreos.io + version: v1 + description: Webhook Operator description. TODO. + displayName: Webhook Operator + installModes: + - supported: false + type: OwnNamespace + - supported: false + type: SingleNamespace + - supported: false + type: MultiNamespace + - supported: true + type: AllNamespaces + keywords: + - webhook-operator + links: + - name: Webhook Operator + url: https://webhook-operator.domain + maintainers: + - email: your@email.com + name: Maintainer Name + maturity: alpha + provider: + name: Provider Name + url: https://your.domain relatedImages: - image: gcr.io/kubebuilder/kube-rbac-proxy:v0.5.0 name: "" @@ -390,21 +398,64 @@ const basicBuiltFbcJson = `{ } }, { - "type": "olm.bundle.object", - "value": { - "data": "eyJhcGlWZXJzaW9uIjoicmJhYy5hdXRob3JpemF0aW9uLms4cy5pby92MWJldGExIiwia2luZCI6IkNsdXN0ZXJSb2xlIiwibWV0YWRhdGEiOnsiY3JlYXRpb25UaW1lc3RhbXAiOm51bGwsIm5hbWUiOiJ3ZWJob29rLW9wZXJhdG9yLW1ldHJpY3MtcmVhZGVyIn0sInJ1bGVzIjpbeyJub25SZXNvdXJjZVVSTHMiOlsiL21ldHJpY3MiXSwidmVyYnMiOlsiZ2V0Il19XX0=" - } - }, - { - "type": "olm.bundle.object", + "type": "olm.csv.metadata", "value": { - "data": "eyJhcGlWZXJzaW9uIjoib3BlcmF0b3JzLmNvcmVvcy5jb20vdjFhbHBoYTEiLCJraW5kIjoiQ2x1c3RlclNlcnZpY2VWZXJzaW9uIiwibWV0YWRhdGEiOnsiYW5ub3RhdGlvbnMiOnsiYWxtLWV4YW1wbGVzIjoiW1xuICB7XG4gICAgXCJhcGlWZXJzaW9uXCI6IFwid2ViaG9vay5vcGVyYXRvcnMuY29yZW9zLmlvL3YxXCIsXG4gICAgXCJraW5kXCI6IFwiV2ViaG9va1Rlc3RcIixcbiAgICBcIm1ldGFkYXRhXCI6IHtcbiAgICAgIFwibmFtZVwiOiBcIndlYmhvb2t0ZXN0LXNhbXBsZVwiLFxuICAgICAgXCJuYW1lc3BhY2VcIjogXCJ3ZWJob29rLW9wZXJhdG9yLXN5c3RlbVwiXG4gICAgfSxcbiAgICBcInNwZWNcIjoge1xuICAgICAgXCJ2YWxpZFwiOiB0cnVlXG4gICAgfVxuICB9XG5dIiwiY2FwYWJpbGl0aWVzIjoiQmFzaWMgSW5zdGFsbCIsIm9wZXJhdG9ycy5vcGVyYXRvcmZyYW1ld29yay5pby9idWlsZGVyIjoib3BlcmF0b3Itc2RrLXYxLjAuMCIsIm9wZXJhdG9ycy5vcGVyYXRvcmZyYW1ld29yay5pby9wcm9qZWN0X2xheW91dCI6ImdvIn0sIm5hbWUiOiJ3ZWJob29rLW9wZXJhdG9yLnYwLjAuMSIsIm5hbWVzcGFjZSI6InBsYWNlaG9sZGVyIn0sInNwZWMiOnsiYXBpc2VydmljZWRlZmluaXRpb25zIjp7fSwiY3VzdG9tcmVzb3VyY2VkZWZpbml0aW9ucyI6eyJvd25lZCI6W3sia2luZCI6IldlYmhvb2tUZXN0IiwibmFtZSI6IndlYmhvb2t0ZXN0cy53ZWJob29rLm9wZXJhdG9ycy5jb3Jlb3MuaW8iLCJ2ZXJzaW9uIjoidjEifV19LCJkZXNjcmlwdGlvbiI6IldlYmhvb2sgT3BlcmF0b3IgZGVzY3JpcHRpb24uIFRPRE8uIiwiZGlzcGxheU5hbWUiOiJXZWJob29rIE9wZXJhdG9yIiwiaWNvbiI6W3siYmFzZTY0ZGF0YSI6IiIsIm1lZGlhdHlwZSI6IiJ9XSwiaW5zdGFsbCI6eyJzcGVjIjp7ImNsdXN0ZXJQZXJtaXNzaW9ucyI6W3sicnVsZXMiOlt7ImFwaUdyb3VwcyI6WyJ3ZWJob29rLm9wZXJhdG9ycy5jb3Jlb3MuaW8iXSwicmVzb3VyY2VzIjpbIndlYmhvb2t0ZXN0cyJdLCJ2ZXJicyI6WyJjcmVhdGUiLCJkZWxldGUiLCJnZXQiLCJsaXN0IiwicGF0Y2giLCJ1cGRhdGUiLCJ3YXRjaCJdfSx7ImFwaUdyb3VwcyI6WyJ3ZWJob29rLm9wZXJhdG9ycy5jb3Jlb3MuaW8iXSwicmVzb3VyY2VzIjpbIndlYmhvb2t0ZXN0cy9zdGF0dXMiXSwidmVyYnMiOlsiZ2V0IiwicGF0Y2giLCJ1cGRhdGUiXX0seyJhcGlHcm91cHMiOlsiYXV0aGVudGljYXRpb24uazhzLmlvIl0sInJlc291cmNlcyI6WyJ0b2tlbnJldmlld3MiXSwidmVyYnMiOlsiY3JlYXRlIl19LHsiYXBpR3JvdXBzIjpbImF1dGhvcml6YXRpb24uazhzLmlvIl0sInJlc291cmNlcyI6WyJzdWJqZWN0YWNjZXNzcmV2aWV3cyJdLCJ2ZXJicyI6WyJjcmVhdGUiXX1dLCJzZXJ2aWNlQWNjb3VudE5hbWUiOiJkZWZhdWx0In1dLCJkZXBsb3ltZW50cyI6W3sibmFtZSI6IndlYmhvb2stb3BlcmF0b3Itd2ViaG9vayIsInNwZWMiOnsicmVwbGljYXMiOjEsInNlbGVjdG9yIjp7Im1hdGNoTGFiZWxzIjp7ImNvbnRyb2wtcGxhbmUiOiJjb250cm9sbGVyLW1hbmFnZXIifX0sInN0cmF0ZWd5Ijp7fSwidGVtcGxhdGUiOnsibWV0YWRhdGEiOnsibGFiZWxzIjp7ImNvbnRyb2wtcGxhbmUiOiJjb250cm9sbGVyLW1hbmFnZXIifX0sInNwZWMiOnsiY29udGFpbmVycyI6W3siYXJncyI6WyItLXNlY3VyZS1saXN0ZW4tYWRkcmVzcz0wLjAuMC4wOjg0NDMiLCItLXVwc3RyZWFtPWh0dHA6Ly8xMjcuMC4wLjE6ODA4MC8iLCItLWxvZ3Rvc3RkZXJyPXRydWUiLCItLXY9MTAiXSwiaW1hZ2UiOiJnY3IuaW8va3ViZWJ1aWxkZXIva3ViZS1yYmFjLXByb3h5OnYwLjUuMCIsIm5hbWUiOiJrdWJlLXJiYWMtcHJveHkiLCJwb3J0cyI6W3siY29udGFpbmVyUG9ydCI6ODQ0MywibmFtZSI6Imh0dHBzIn1dLCJyZXNvdXJjZXMiOnt9fSx7ImFyZ3MiOlsiLS1tZXRyaWNzLWFkZHI9MTI3LjAuMC4xOjgwODAiLCItLWVuYWJsZS1sZWFkZXItZWxlY3Rpb24iXSwiY29tbWFuZCI6WyIvbWFuYWdlciJdLCJpbWFnZSI6InF1YXkuaW8vb2xtdGVzdC93ZWJob29rLW9wZXJhdG9yOjAuMC4zIiwibmFtZSI6Im1hbmFnZXIiLCJwb3J0cyI6W3siY29udGFpbmVyUG9ydCI6OTQ0MywibmFtZSI6IndlYmhvb2stc2VydmVyIiwicHJvdG9jb2wiOiJUQ1AifV0sInJlc291cmNlcyI6eyJsaW1pdHMiOnsiY3B1IjoiMTAwbSIsIm1lbW9yeSI6IjMwTWkifSwicmVxdWVzdHMiOnsiY3B1IjoiMTAwbSIsIm1lbW9yeSI6IjIwTWkifX19XSwidGVybWluYXRpb25HcmFjZVBlcmlvZFNlY29uZHMiOjEwfX19fV0sInBlcm1pc3Npb25zIjpbeyJydWxlcyI6W3siYXBpR3JvdXBzIjpbIiJdLCJyZXNvdXJjZXMiOlsiY29uZmlnbWFwcyJdLCJ2ZXJicyI6WyJnZXQiLCJsaXN0Iiwid2F0Y2giLCJjcmVhdGUiLCJ1cGRhdGUiLCJwYXRjaCIsImRlbGV0ZSJdfSx7ImFwaUdyb3VwcyI6WyIiXSwicmVzb3VyY2VzIjpbImNvbmZpZ21hcHMvc3RhdHVzIl0sInZlcmJzIjpbImdldCIsInVwZGF0ZSIsInBhdGNoIl19LHsiYXBpR3JvdXBzIjpbIiJdLCJyZXNvdXJjZXMiOlsiZXZlbnRzIl0sInZlcmJzIjpbImNyZWF0ZSJdfV0sInNlcnZpY2VBY2NvdW50TmFtZSI6ImRlZmF1bHQifV19LCJzdHJhdGVneSI6ImRlcGxveW1lbnQifSwiaW5zdGFsbE1vZGVzIjpbeyJzdXBwb3J0ZWQiOmZhbHNlLCJ0eXBlIjoiT3duTmFtZXNwYWNlIn0seyJzdXBwb3J0ZWQiOmZhbHNlLCJ0eXBlIjoiU2luZ2xlTmFtZXNwYWNlIn0seyJzdXBwb3J0ZWQiOmZhbHNlLCJ0eXBlIjoiTXVsdGlOYW1lc3BhY2UifSx7InN1cHBvcnRlZCI6dHJ1ZSwidHlwZSI6IkFsbE5hbWVzcGFjZXMifV0sImtleXdvcmRzIjpbIndlYmhvb2stb3BlcmF0b3IiXSwibGlua3MiOlt7Im5hbWUiOiJXZWJob29rIE9wZXJhdG9yIiwidXJsIjoiaHR0cHM6Ly93ZWJob29rLW9wZXJhdG9yLmRvbWFpbiJ9XSwibWFpbnRhaW5lcnMiOlt7ImVtYWlsIjoieW91ckBlbWFpbC5jb20iLCJuYW1lIjoiTWFpbnRhaW5lciBOYW1lIn1dLCJtYXR1cml0eSI6ImFscGhhIiwicHJvdmlkZXIiOnsibmFtZSI6IlByb3ZpZGVyIE5hbWUiLCJ1cmwiOiJodHRwczovL3lvdXIuZG9tYWluIn0sInZlcnNpb24iOiIwLjAuMSIsIndlYmhvb2tkZWZpbml0aW9ucyI6W3siYWRtaXNzaW9uUmV2aWV3VmVyc2lvbnMiOlsidjFiZXRhMSIsInYxIl0sImNvbnRhaW5lclBvcnQiOjQ0MywiZGVwbG95bWVudE5hbWUiOiJ3ZWJob29rLW9wZXJhdG9yLXdlYmhvb2siLCJmYWlsdXJlUG9saWN5IjoiRmFpbCIsImdlbmVyYXRlTmFtZSI6InZ3ZWJob29rdGVzdC5rYi5pbyIsInJ1bGVzIjpbeyJhcGlHcm91cHMiOlsid2ViaG9vay5vcGVyYXRvcnMuY29yZW9zLmlvIl0sImFwaVZlcnNpb25zIjpbInYxIl0sIm9wZXJhdGlvbnMiOlsiQ1JFQVRFIiwiVVBEQVRFIl0sInJlc291cmNlcyI6WyJ3ZWJob29rdGVzdHMiXX1dLCJzaWRlRWZmZWN0cyI6Ik5vbmUiLCJ0YXJnZXRQb3J0Ijo0MzQzLCJ0eXBlIjoiVmFsaWRhdGluZ0FkbWlzc2lvbldlYmhvb2siLCJ3ZWJob29rUGF0aCI6Ii92YWxpZGF0ZS13ZWJob29rLW9wZXJhdG9ycy1jb3Jlb3MtaW8tdjEtd2ViaG9va3Rlc3QifSx7ImFkbWlzc2lvblJldmlld1ZlcnNpb25zIjpbInYxYmV0YTEiLCJ2MSJdLCJjb250YWluZXJQb3J0Ijo0NDMsImRlcGxveW1lbnROYW1lIjoid2ViaG9vay1vcGVyYXRvci13ZWJob29rIiwiZmFpbHVyZVBvbGljeSI6IkZhaWwiLCJnZW5lcmF0ZU5hbWUiOiJtd2ViaG9va3Rlc3Qua2IuaW8iLCJydWxlcyI6W3siYXBpR3JvdXBzIjpbIndlYmhvb2sub3BlcmF0b3JzLmNvcmVvcy5pbyJdLCJhcGlWZXJzaW9ucyI6WyJ2MSJdLCJvcGVyYXRpb25zIjpbIkNSRUFURSIsIlVQREFURSJdLCJyZXNvdXJjZXMiOlsid2ViaG9va3Rlc3RzIl19XSwic2lkZUVmZmVjdHMiOiJOb25lIiwidGFyZ2V0UG9ydCI6NDM0MywidHlwZSI6Ik11dGF0aW5nQWRtaXNzaW9uV2ViaG9vayIsIndlYmhvb2tQYXRoIjoiL211dGF0ZS13ZWJob29rLW9wZXJhdG9ycy1jb3Jlb3MtaW8tdjEtd2ViaG9va3Rlc3QifSx7ImFkbWlzc2lvblJldmlld1ZlcnNpb25zIjpbInYxYmV0YTEiLCJ2MSJdLCJjb250YWluZXJQb3J0Ijo0NDMsImNvbnZlcnNpb25DUkRzIjpbIndlYmhvb2t0ZXN0cy53ZWJob29rLm9wZXJhdG9ycy5jb3Jlb3MuaW8iXSwiZGVwbG95bWVudE5hbWUiOiJ3ZWJob29rLW9wZXJhdG9yLXdlYmhvb2siLCJmYWlsdXJlUG9saWN5IjoiRmFpbCIsImdlbmVyYXRlTmFtZSI6ImN3ZWJob29rdGVzdC5rYi5pbyIsInJ1bGVzIjpbeyJhcGlHcm91cHMiOlsid2ViaG9vay5vcGVyYXRvcnMuY29yZW9zLmlvIl0sImFwaVZlcnNpb25zIjpbInYxIl0sIm9wZXJhdGlvbnMiOlsiQ1JFQVRFIiwiVVBEQVRFIl0sInJlc291cmNlcyI6WyJ3ZWJob29rdGVzdHMiXX1dLCJzaWRlRWZmZWN0cyI6Ik5vbmUiLCJ0YXJnZXRQb3J0Ijo0MzQzLCJ0eXBlIjoiQ29udmVyc2lvbldlYmhvb2siLCJ3ZWJob29rUGF0aCI6Ii9jb252ZXJ0In1dfX0=" - } - }, - { - "type": "olm.bundle.object", - "value": { - "data": "eyJhcGlWZXJzaW9uIjoiYXBpZXh0ZW5zaW9ucy5rOHMuaW8vdjFiZXRhMSIsImtpbmQiOiJDdXN0b21SZXNvdXJjZURlZmluaXRpb24iLCJtZXRhZGF0YSI6eyJhbm5vdGF0aW9ucyI6eyJjb250cm9sbGVyLWdlbi5rdWJlYnVpbGRlci5pby92ZXJzaW9uIjoidjAuMy4wIn0sImNyZWF0aW9uVGltZXN0YW1wIjpudWxsLCJuYW1lIjoid2ViaG9va3Rlc3RzLndlYmhvb2sub3BlcmF0b3JzLmNvcmVvcy5pbyJ9LCJzcGVjIjp7Imdyb3VwIjoid2ViaG9vay5vcGVyYXRvcnMuY29yZW9zLmlvIiwibmFtZXMiOnsia2luZCI6IldlYmhvb2tUZXN0IiwibGlzdEtpbmQiOiJXZWJob29rVGVzdExpc3QiLCJwbHVyYWwiOiJ3ZWJob29rdGVzdHMiLCJzaW5ndWxhciI6IndlYmhvb2t0ZXN0In0sInByZXNlcnZlVW5rbm93bkZpZWxkcyI6ZmFsc2UsInNjb3BlIjoiTmFtZXNwYWNlZCIsInZlcnNpb24iOiJ2MSIsInZlcnNpb25zIjpbeyJuYW1lIjoidjEiLCJzY2hlbWEiOnsib3BlbkFQSVYzU2NoZW1hIjp7ImRlc2NyaXB0aW9uIjoiV2ViaG9va1Rlc3QgaXMgdGhlIFNjaGVtYSBmb3IgdGhlIHdlYmhvb2t0ZXN0cyBBUEkiLCJwcm9wZXJ0aWVzIjp7ImFwaVZlcnNpb24iOnsiZGVzY3JpcHRpb24iOiJBUElWZXJzaW9uIGRlZmluZXMgdGhlIHZlcnNpb25lZCBzY2hlbWEgb2YgdGhpcyByZXByZXNlbnRhdGlvbiBvZiBhbiBvYmplY3QuIFNlcnZlcnMgc2hvdWxkIGNvbnZlcnQgcmVjb2duaXplZCBzY2hlbWFzIHRvIHRoZSBsYXRlc3QgaW50ZXJuYWwgdmFsdWUsIGFuZCBtYXkgcmVqZWN0IHVucmVjb2duaXplZCB2YWx1ZXMuIE1vcmUgaW5mbzogaHR0cHM6Ly9naXQuazhzLmlvL2NvbW11bml0eS9jb250cmlidXRvcnMvZGV2ZWwvc2lnLWFyY2hpdGVjdHVyZS9hcGktY29udmVudGlvbnMubWQjcmVzb3VyY2VzIiwidHlwZSI6InN0cmluZyJ9LCJraW5kIjp7ImRlc2NyaXB0aW9uIjoiS2luZCBpcyBhIHN0cmluZyB2YWx1ZSByZXByZXNlbnRpbmcgdGhlIFJFU1QgcmVzb3VyY2UgdGhpcyBvYmplY3QgcmVwcmVzZW50cy4gU2VydmVycyBtYXkgaW5mZXIgdGhpcyBmcm9tIHRoZSBlbmRwb2ludCB0aGUgY2xpZW50IHN1Ym1pdHMgcmVxdWVzdHMgdG8uIENhbm5vdCBiZSB1cGRhdGVkLiBJbiBDYW1lbENhc2UuIE1vcmUgaW5mbzogaHR0cHM6Ly9naXQuazhzLmlvL2NvbW11bml0eS9jb250cmlidXRvcnMvZGV2ZWwvc2lnLWFyY2hpdGVjdHVyZS9hcGktY29udmVudGlvbnMubWQjdHlwZXMta2luZHMiLCJ0eXBlIjoic3RyaW5nIn0sIm1ldGFkYXRhIjp7InR5cGUiOiJvYmplY3QifSwic3BlYyI6eyJkZXNjcmlwdGlvbiI6IldlYmhvb2tUZXN0U3BlYyBkZWZpbmVzIHRoZSBkZXNpcmVkIHN0YXRlIG9mIFdlYmhvb2tUZXN0IiwicHJvcGVydGllcyI6eyJtdXRhdGUiOnsiZGVzY3JpcHRpb24iOiJNdXRhdGUgaXMgYSBmaWVsZCB0aGF0IHdpbGwgYmUgc2V0IHRvIHRydWUgYnkgdGhlIG11dGF0aW5nIHdlYmhvb2suIiwidHlwZSI6ImJvb2xlYW4ifSwidmFsaWQiOnsiZGVzY3JpcHRpb24iOiJWYWxpZCBtdXN0IGJlIHNldCB0byB0cnVlIG9yIHRoZSB2YWxpZGF0aW9uIHdlYmhvb2sgd2lsbCByZWplY3QgdGhlIHJlc291cmNlLiIsInR5cGUiOiJib29sZWFuIn19LCJyZXF1aXJlZCI6WyJ2YWxpZCJdLCJ0eXBlIjoib2JqZWN0In0sInN0YXR1cyI6eyJkZXNjcmlwdGlvbiI6IldlYmhvb2tUZXN0U3RhdHVzIGRlZmluZXMgdGhlIG9ic2VydmVkIHN0YXRlIG9mIFdlYmhvb2tUZXN0IiwidHlwZSI6Im9iamVjdCJ9fSwidHlwZSI6Im9iamVjdCJ9fSwic2VydmVkIjp0cnVlLCJzdG9yYWdlIjp0cnVlfSx7Im5hbWUiOiJ2MiIsInNjaGVtYSI6eyJvcGVuQVBJVjNTY2hlbWEiOnsiZGVzY3JpcHRpb24iOiJXZWJob29rVGVzdCBpcyB0aGUgU2NoZW1hIGZvciB0aGUgd2ViaG9va3Rlc3RzIEFQSSIsInByb3BlcnRpZXMiOnsiYXBpVmVyc2lvbiI6eyJkZXNjcmlwdGlvbiI6IkFQSVZlcnNpb24gZGVmaW5lcyB0aGUgdmVyc2lvbmVkIHNjaGVtYSBvZiB0aGlzIHJlcHJlc2VudGF0aW9uIG9mIGFuIG9iamVjdC4gU2VydmVycyBzaG91bGQgY29udmVydCByZWNvZ25pemVkIHNjaGVtYXMgdG8gdGhlIGxhdGVzdCBpbnRlcm5hbCB2YWx1ZSwgYW5kIG1heSByZWplY3QgdW5yZWNvZ25pemVkIHZhbHVlcy4gTW9yZSBpbmZvOiBodHRwczovL2dpdC5rOHMuaW8vY29tbXVuaXR5L2NvbnRyaWJ1dG9ycy9kZXZlbC9zaWctYXJjaGl0ZWN0dXJlL2FwaS1jb252ZW50aW9ucy5tZCNyZXNvdXJjZXMiLCJ0eXBlIjoic3RyaW5nIn0sImtpbmQiOnsiZGVzY3JpcHRpb24iOiJLaW5kIGlzIGEgc3RyaW5nIHZhbHVlIHJlcHJlc2VudGluZyB0aGUgUkVTVCByZXNvdXJjZSB0aGlzIG9iamVjdCByZXByZXNlbnRzLiBTZXJ2ZXJzIG1heSBpbmZlciB0aGlzIGZyb20gdGhlIGVuZHBvaW50IHRoZSBjbGllbnQgc3VibWl0cyByZXF1ZXN0cyB0by4gQ2Fubm90IGJlIHVwZGF0ZWQuIEluIENhbWVsQ2FzZS4gTW9yZSBpbmZvOiBodHRwczovL2dpdC5rOHMuaW8vY29tbXVuaXR5L2NvbnRyaWJ1dG9ycy9kZXZlbC9zaWctYXJjaGl0ZWN0dXJlL2FwaS1jb252ZW50aW9ucy5tZCN0eXBlcy1raW5kcyIsInR5cGUiOiJzdHJpbmcifSwibWV0YWRhdGEiOnsidHlwZSI6Im9iamVjdCJ9LCJzcGVjIjp7ImRlc2NyaXB0aW9uIjoiV2ViaG9va1Rlc3RTcGVjIGRlZmluZXMgdGhlIGRlc2lyZWQgc3RhdGUgb2YgV2ViaG9va1Rlc3QiLCJwcm9wZXJ0aWVzIjp7ImNvbnZlcnNpb24iOnsiZGVzY3JpcHRpb24iOiJDb252ZXJzaW9uIGlzIGFuIGV4YW1wbGUgZmllbGQgb2YgV2ViaG9va1Rlc3QuIEVkaXQgV2ViaG9va1Rlc3RfdHlwZXMuZ28gdG8gcmVtb3ZlL3VwZGF0ZSIsInByb3BlcnRpZXMiOnsibXV0YXRlIjp7ImRlc2NyaXB0aW9uIjoiTXV0YXRlIGlzIGEgZmllbGQgdGhhdCB3aWxsIGJlIHNldCB0byB0cnVlIGJ5IHRoZSBtdXRhdGluZyB3ZWJob29rLiIsInR5cGUiOiJib29sZWFuIn0sInZhbGlkIjp7ImRlc2NyaXB0aW9uIjoiVmFsaWQgbXVzdCBiZSBzZXQgdG8gdHJ1ZSBvciB0aGUgdmFsaWRhdGlvbiB3ZWJob29rIHdpbGwgcmVqZWN0IHRoZSByZXNvdXJjZS4iLCJ0eXBlIjoiYm9vbGVhbiJ9fSwicmVxdWlyZWQiOlsidmFsaWQiXSwidHlwZSI6Im9iamVjdCJ9fSwicmVxdWlyZWQiOlsiY29udmVyc2lvbiJdLCJ0eXBlIjoib2JqZWN0In0sInN0YXR1cyI6eyJkZXNjcmlwdGlvbiI6IldlYmhvb2tUZXN0U3RhdHVzIGRlZmluZXMgdGhlIG9ic2VydmVkIHN0YXRlIG9mIFdlYmhvb2tUZXN0IiwidHlwZSI6Im9iamVjdCJ9fSwidHlwZSI6Im9iamVjdCJ9fSwic2VydmVkIjp0cnVlLCJzdG9yYWdlIjpmYWxzZX1dfSwic3RhdHVzIjp7ImFjY2VwdGVkTmFtZXMiOnsia2luZCI6IiIsInBsdXJhbCI6IiJ9LCJjb25kaXRpb25zIjpbXSwic3RvcmVkVmVyc2lvbnMiOltdfX0=" + "annotations": { + "alm-examples": "[\n {\n \"apiVersion\": \"webhook.operators.coreos.io/v1\",\n \"kind\": \"WebhookTest\",\n \"metadata\": {\n \"name\": \"webhooktest-sample\",\n \"namespace\": \"webhook-operator-system\"\n },\n \"spec\": {\n \"valid\": true\n }\n }\n]", + "capabilities": "Basic Install", + "operators.operatorframework.io/builder": "operator-sdk-v1.0.0", + "operators.operatorframework.io/project_layout": "go" + }, + "apiServiceDefinitions": {}, + "crdDescriptions": { + "owned": [ + { + "name": "webhooktests.webhook.operators.coreos.io", + "version": "v1", + "kind": "WebhookTest" + } + ] + }, + "description": "Webhook Operator description. TODO.", + "displayName": "Webhook Operator", + "installModes": [ + { + "type": "OwnNamespace", + "supported": false + }, + { + "type": "SingleNamespace", + "supported": false + }, + { + "type": "MultiNamespace", + "supported": false + }, + { + "type": "AllNamespaces", + "supported": true + } + ], + "keywords": [ + "webhook-operator" + ], + "links": [ + { + "name": "Webhook Operator", + "url": "https://webhook-operator.domain" + } + ], + "maintainers": [ + { + "name": "Maintainer Name", + "email": "your@email.com" + } + ], + "maturity": "alpha", + "provider": { + "name": "Provider Name", + "url": "https://your.domain" + } } } ], @@ -447,11 +498,7 @@ func TestSemverBuilder(t *testing.T) { name: "successful semver build yaml output", validate: true, semverBuilder: NewSemverBuilder(BuilderConfig{ - ContainerCfg: ContainerConfig{ - ContainerTool: "docker", - BaseImage: "quay.io/operator-framework/opm:latest", - WorkingDir: testDir, - }, + WorkingDir: testDir, OutputType: "yaml", }), templateDefinition: TemplateDefinition{ @@ -472,7 +519,7 @@ func TestSemverBuilder(t *testing.T) { defer file.Close() fileData, err := io.ReadAll(file) require.NoError(t, err) - require.Equal(t, string(fileData), semverBuiltFbcYaml) + require.Equal(t, semverBuiltFbcYaml, string(fileData)) }, validateAssertions: func(t *testing.T, validateErr error) { require.NoError(t, validateErr) @@ -482,11 +529,7 @@ func TestSemverBuilder(t *testing.T) { name: "successful semver build json output", validate: true, semverBuilder: NewSemverBuilder(BuilderConfig{ - ContainerCfg: ContainerConfig{ - ContainerTool: "docker", - BaseImage: "quay.io/operator-framework/opm:latest", - WorkingDir: testDir, - }, + WorkingDir: testDir, OutputType: "json", }), templateDefinition: TemplateDefinition{ @@ -507,7 +550,7 @@ func TestSemverBuilder(t *testing.T) { defer file.Close() fileData, err := io.ReadAll(file) require.NoError(t, err) - require.Equal(t, string(fileData), semverBuiltFbcJson) + require.Equal(t, semverBuiltFbcJson, string(fileData)) }, validateAssertions: func(t *testing.T, validateErr error) { require.NoError(t, validateErr) @@ -517,11 +560,7 @@ func TestSemverBuilder(t *testing.T) { name: "invalid template configuration", validate: false, semverBuilder: NewSemverBuilder(BuilderConfig{ - ContainerCfg: ContainerConfig{ - ContainerTool: "docker", - BaseImage: "quay.io/operator-framework/opm:latest", - WorkingDir: testDir, - }, + WorkingDir: testDir, OutputType: "yaml", }), templateDefinition: TemplateDefinition{ @@ -540,11 +579,7 @@ func TestSemverBuilder(t *testing.T) { name: "invalid output type", validate: false, semverBuilder: NewSemverBuilder(BuilderConfig{ - ContainerCfg: ContainerConfig{ - ContainerTool: "docker", - BaseImage: "quay.io/operator-framework/opm:latest", - WorkingDir: testDir, - }, + WorkingDir: testDir, OutputType: "invalid", }), templateDefinition: TemplateDefinition{ @@ -563,11 +598,7 @@ func TestSemverBuilder(t *testing.T) { name: "invalid schema", validate: false, semverBuilder: NewSemverBuilder(BuilderConfig{ - ContainerCfg: ContainerConfig{ - ContainerTool: "docker", - BaseImage: "quay.io/operator-framework/opm:latest", - WorkingDir: testDir, - }, + WorkingDir: testDir, OutputType: "yaml", }), templateDefinition: TemplateDefinition{ @@ -584,11 +615,7 @@ func TestSemverBuilder(t *testing.T) { name: "template config has empty input", validate: false, semverBuilder: NewSemverBuilder(BuilderConfig{ - ContainerCfg: ContainerConfig{ - ContainerTool: "docker", - BaseImage: "quay.io/operator-framework/opm:latest", - WorkingDir: testDir, - }, + WorkingDir: testDir, OutputType: "yaml", }), templateDefinition: TemplateDefinition{ @@ -609,11 +636,7 @@ func TestSemverBuilder(t *testing.T) { name: "template config has empty output", validate: false, semverBuilder: NewSemverBuilder(BuilderConfig{ - ContainerCfg: ContainerConfig{ - ContainerTool: "docker", - BaseImage: "quay.io/operator-framework/opm:latest", - WorkingDir: testDir, - }, + WorkingDir: testDir, OutputType: "yaml", }), templateDefinition: TemplateDefinition{ @@ -626,19 +649,15 @@ func TestSemverBuilder(t *testing.T) { buildAssertions: func(t *testing.T, dir string, buildErr error) { require.Error(t, buildErr) require.Equal(t, - buildErr.Error(), - "semver template configuration is invalid: semver template config must have a non-empty output (templateDefinition.config.output)") + "semver template configuration is invalid: semver template config must have a non-empty output (templateDefinition.config.output)", + buildErr.Error()) }, }, { name: "template config has empty input & output", validate: false, semverBuilder: NewSemverBuilder(BuilderConfig{ - ContainerCfg: ContainerConfig{ - ContainerTool: "docker", - BaseImage: "quay.io/operator-framework/opm:latest", - WorkingDir: testDir, - }, + WorkingDir: testDir, OutputType: "yaml", }), templateDefinition: TemplateDefinition{ @@ -649,14 +668,14 @@ func TestSemverBuilder(t *testing.T) { buildAssertions: func(t *testing.T, dir string, buildErr error) { require.Error(t, buildErr) require.Equal(t, + "semver template configuration is invalid: semver template config must have a non-empty input (templateDefinition.config.input),semver template config must have a non-empty output (templateDefinition.config.output)", buildErr.Error(), - "semver template configuration is invalid: semver template config must have a non-empty input (templateDefinition.config.input),semver template config must have a non-empty output (templateDefinition.config.output)") + ) }, }, } for i, tc := range testCases { - tc.semverBuilder.builderCfg.InputDirectory = testDir t.Run(tc.name, func(t *testing.T) { outDir := fmt.Sprintf("semver-%d", i) outPath := path.Join(testDir, outDir) @@ -687,7 +706,7 @@ func TestSemverBuilder(t *testing.T) { tc.buildAssertions(t, outPath, buildErr) if tc.validate { - validateErr := tc.semverBuilder.Validate(outDir) + validateErr := tc.semverBuilder.Validate(context.Background(), outDir) tc.validateAssertions(t, validateErr) } }) @@ -704,7 +723,7 @@ Stable: ` const semverBuiltFbcYaml = `--- -defaultChannel: stable-v0 +defaultChannel: stable-v0.0 name: webhook-operator schema: olm.package --- @@ -738,15 +757,55 @@ properties: value: packageName: webhook-operator version: 0.0.1 -- type: olm.bundle.object +- type: olm.csv.metadata value: - data: eyJhcGlWZXJzaW9uIjoicmJhYy5hdXRob3JpemF0aW9uLms4cy5pby92MWJldGExIiwia2luZCI6IkNsdXN0ZXJSb2xlIiwibWV0YWRhdGEiOnsiY3JlYXRpb25UaW1lc3RhbXAiOm51bGwsIm5hbWUiOiJ3ZWJob29rLW9wZXJhdG9yLW1ldHJpY3MtcmVhZGVyIn0sInJ1bGVzIjpbeyJub25SZXNvdXJjZVVSTHMiOlsiL21ldHJpY3MiXSwidmVyYnMiOlsiZ2V0Il19XX0= -- type: olm.bundle.object - value: - data: eyJhcGlWZXJzaW9uIjoib3BlcmF0b3JzLmNvcmVvcy5jb20vdjFhbHBoYTEiLCJraW5kIjoiQ2x1c3RlclNlcnZpY2VWZXJzaW9uIiwibWV0YWRhdGEiOnsiYW5ub3RhdGlvbnMiOnsiYWxtLWV4YW1wbGVzIjoiW1xuICB7XG4gICAgXCJhcGlWZXJzaW9uXCI6IFwid2ViaG9vay5vcGVyYXRvcnMuY29yZW9zLmlvL3YxXCIsXG4gICAgXCJraW5kXCI6IFwiV2ViaG9va1Rlc3RcIixcbiAgICBcIm1ldGFkYXRhXCI6IHtcbiAgICAgIFwibmFtZVwiOiBcIndlYmhvb2t0ZXN0LXNhbXBsZVwiLFxuICAgICAgXCJuYW1lc3BhY2VcIjogXCJ3ZWJob29rLW9wZXJhdG9yLXN5c3RlbVwiXG4gICAgfSxcbiAgICBcInNwZWNcIjoge1xuICAgICAgXCJ2YWxpZFwiOiB0cnVlXG4gICAgfVxuICB9XG5dIiwiY2FwYWJpbGl0aWVzIjoiQmFzaWMgSW5zdGFsbCIsIm9wZXJhdG9ycy5vcGVyYXRvcmZyYW1ld29yay5pby9idWlsZGVyIjoib3BlcmF0b3Itc2RrLXYxLjAuMCIsIm9wZXJhdG9ycy5vcGVyYXRvcmZyYW1ld29yay5pby9wcm9qZWN0X2xheW91dCI6ImdvIn0sIm5hbWUiOiJ3ZWJob29rLW9wZXJhdG9yLnYwLjAuMSIsIm5hbWVzcGFjZSI6InBsYWNlaG9sZGVyIn0sInNwZWMiOnsiYXBpc2VydmljZWRlZmluaXRpb25zIjp7fSwiY3VzdG9tcmVzb3VyY2VkZWZpbml0aW9ucyI6eyJvd25lZCI6W3sia2luZCI6IldlYmhvb2tUZXN0IiwibmFtZSI6IndlYmhvb2t0ZXN0cy53ZWJob29rLm9wZXJhdG9ycy5jb3Jlb3MuaW8iLCJ2ZXJzaW9uIjoidjEifV19LCJkZXNjcmlwdGlvbiI6IldlYmhvb2sgT3BlcmF0b3IgZGVzY3JpcHRpb24uIFRPRE8uIiwiZGlzcGxheU5hbWUiOiJXZWJob29rIE9wZXJhdG9yIiwiaWNvbiI6W3siYmFzZTY0ZGF0YSI6IiIsIm1lZGlhdHlwZSI6IiJ9XSwiaW5zdGFsbCI6eyJzcGVjIjp7ImNsdXN0ZXJQZXJtaXNzaW9ucyI6W3sicnVsZXMiOlt7ImFwaUdyb3VwcyI6WyJ3ZWJob29rLm9wZXJhdG9ycy5jb3Jlb3MuaW8iXSwicmVzb3VyY2VzIjpbIndlYmhvb2t0ZXN0cyJdLCJ2ZXJicyI6WyJjcmVhdGUiLCJkZWxldGUiLCJnZXQiLCJsaXN0IiwicGF0Y2giLCJ1cGRhdGUiLCJ3YXRjaCJdfSx7ImFwaUdyb3VwcyI6WyJ3ZWJob29rLm9wZXJhdG9ycy5jb3Jlb3MuaW8iXSwicmVzb3VyY2VzIjpbIndlYmhvb2t0ZXN0cy9zdGF0dXMiXSwidmVyYnMiOlsiZ2V0IiwicGF0Y2giLCJ1cGRhdGUiXX0seyJhcGlHcm91cHMiOlsiYXV0aGVudGljYXRpb24uazhzLmlvIl0sInJlc291cmNlcyI6WyJ0b2tlbnJldmlld3MiXSwidmVyYnMiOlsiY3JlYXRlIl19LHsiYXBpR3JvdXBzIjpbImF1dGhvcml6YXRpb24uazhzLmlvIl0sInJlc291cmNlcyI6WyJzdWJqZWN0YWNjZXNzcmV2aWV3cyJdLCJ2ZXJicyI6WyJjcmVhdGUiXX1dLCJzZXJ2aWNlQWNjb3VudE5hbWUiOiJkZWZhdWx0In1dLCJkZXBsb3ltZW50cyI6W3sibmFtZSI6IndlYmhvb2stb3BlcmF0b3Itd2ViaG9vayIsInNwZWMiOnsicmVwbGljYXMiOjEsInNlbGVjdG9yIjp7Im1hdGNoTGFiZWxzIjp7ImNvbnRyb2wtcGxhbmUiOiJjb250cm9sbGVyLW1hbmFnZXIifX0sInN0cmF0ZWd5Ijp7fSwidGVtcGxhdGUiOnsibWV0YWRhdGEiOnsibGFiZWxzIjp7ImNvbnRyb2wtcGxhbmUiOiJjb250cm9sbGVyLW1hbmFnZXIifX0sInNwZWMiOnsiY29udGFpbmVycyI6W3siYXJncyI6WyItLXNlY3VyZS1saXN0ZW4tYWRkcmVzcz0wLjAuMC4wOjg0NDMiLCItLXVwc3RyZWFtPWh0dHA6Ly8xMjcuMC4wLjE6ODA4MC8iLCItLWxvZ3Rvc3RkZXJyPXRydWUiLCItLXY9MTAiXSwiaW1hZ2UiOiJnY3IuaW8va3ViZWJ1aWxkZXIva3ViZS1yYmFjLXByb3h5OnYwLjUuMCIsIm5hbWUiOiJrdWJlLXJiYWMtcHJveHkiLCJwb3J0cyI6W3siY29udGFpbmVyUG9ydCI6ODQ0MywibmFtZSI6Imh0dHBzIn1dLCJyZXNvdXJjZXMiOnt9fSx7ImFyZ3MiOlsiLS1tZXRyaWNzLWFkZHI9MTI3LjAuMC4xOjgwODAiLCItLWVuYWJsZS1sZWFkZXItZWxlY3Rpb24iXSwiY29tbWFuZCI6WyIvbWFuYWdlciJdLCJpbWFnZSI6InF1YXkuaW8vb2xtdGVzdC93ZWJob29rLW9wZXJhdG9yOjAuMC4zIiwibmFtZSI6Im1hbmFnZXIiLCJwb3J0cyI6W3siY29udGFpbmVyUG9ydCI6OTQ0MywibmFtZSI6IndlYmhvb2stc2VydmVyIiwicHJvdG9jb2wiOiJUQ1AifV0sInJlc291cmNlcyI6eyJsaW1pdHMiOnsiY3B1IjoiMTAwbSIsIm1lbW9yeSI6IjMwTWkifSwicmVxdWVzdHMiOnsiY3B1IjoiMTAwbSIsIm1lbW9yeSI6IjIwTWkifX19XSwidGVybWluYXRpb25HcmFjZVBlcmlvZFNlY29uZHMiOjEwfX19fV0sInBlcm1pc3Npb25zIjpbeyJydWxlcyI6W3siYXBpR3JvdXBzIjpbIiJdLCJyZXNvdXJjZXMiOlsiY29uZmlnbWFwcyJdLCJ2ZXJicyI6WyJnZXQiLCJsaXN0Iiwid2F0Y2giLCJjcmVhdGUiLCJ1cGRhdGUiLCJwYXRjaCIsImRlbGV0ZSJdfSx7ImFwaUdyb3VwcyI6WyIiXSwicmVzb3VyY2VzIjpbImNvbmZpZ21hcHMvc3RhdHVzIl0sInZlcmJzIjpbImdldCIsInVwZGF0ZSIsInBhdGNoIl19LHsiYXBpR3JvdXBzIjpbIiJdLCJyZXNvdXJjZXMiOlsiZXZlbnRzIl0sInZlcmJzIjpbImNyZWF0ZSJdfV0sInNlcnZpY2VBY2NvdW50TmFtZSI6ImRlZmF1bHQifV19LCJzdHJhdGVneSI6ImRlcGxveW1lbnQifSwiaW5zdGFsbE1vZGVzIjpbeyJzdXBwb3J0ZWQiOmZhbHNlLCJ0eXBlIjoiT3duTmFtZXNwYWNlIn0seyJzdXBwb3J0ZWQiOmZhbHNlLCJ0eXBlIjoiU2luZ2xlTmFtZXNwYWNlIn0seyJzdXBwb3J0ZWQiOmZhbHNlLCJ0eXBlIjoiTXVsdGlOYW1lc3BhY2UifSx7InN1cHBvcnRlZCI6dHJ1ZSwidHlwZSI6IkFsbE5hbWVzcGFjZXMifV0sImtleXdvcmRzIjpbIndlYmhvb2stb3BlcmF0b3IiXSwibGlua3MiOlt7Im5hbWUiOiJXZWJob29rIE9wZXJhdG9yIiwidXJsIjoiaHR0cHM6Ly93ZWJob29rLW9wZXJhdG9yLmRvbWFpbiJ9XSwibWFpbnRhaW5lcnMiOlt7ImVtYWlsIjoieW91ckBlbWFpbC5jb20iLCJuYW1lIjoiTWFpbnRhaW5lciBOYW1lIn1dLCJtYXR1cml0eSI6ImFscGhhIiwicHJvdmlkZXIiOnsibmFtZSI6IlByb3ZpZGVyIE5hbWUiLCJ1cmwiOiJodHRwczovL3lvdXIuZG9tYWluIn0sInZlcnNpb24iOiIwLjAuMSIsIndlYmhvb2tkZWZpbml0aW9ucyI6W3siYWRtaXNzaW9uUmV2aWV3VmVyc2lvbnMiOlsidjFiZXRhMSIsInYxIl0sImNvbnRhaW5lclBvcnQiOjQ0MywiZGVwbG95bWVudE5hbWUiOiJ3ZWJob29rLW9wZXJhdG9yLXdlYmhvb2siLCJmYWlsdXJlUG9saWN5IjoiRmFpbCIsImdlbmVyYXRlTmFtZSI6InZ3ZWJob29rdGVzdC5rYi5pbyIsInJ1bGVzIjpbeyJhcGlHcm91cHMiOlsid2ViaG9vay5vcGVyYXRvcnMuY29yZW9zLmlvIl0sImFwaVZlcnNpb25zIjpbInYxIl0sIm9wZXJhdGlvbnMiOlsiQ1JFQVRFIiwiVVBEQVRFIl0sInJlc291cmNlcyI6WyJ3ZWJob29rdGVzdHMiXX1dLCJzaWRlRWZmZWN0cyI6Ik5vbmUiLCJ0YXJnZXRQb3J0Ijo0MzQzLCJ0eXBlIjoiVmFsaWRhdGluZ0FkbWlzc2lvbldlYmhvb2siLCJ3ZWJob29rUGF0aCI6Ii92YWxpZGF0ZS13ZWJob29rLW9wZXJhdG9ycy1jb3Jlb3MtaW8tdjEtd2ViaG9va3Rlc3QifSx7ImFkbWlzc2lvblJldmlld1ZlcnNpb25zIjpbInYxYmV0YTEiLCJ2MSJdLCJjb250YWluZXJQb3J0Ijo0NDMsImRlcGxveW1lbnROYW1lIjoid2ViaG9vay1vcGVyYXRvci13ZWJob29rIiwiZmFpbHVyZVBvbGljeSI6IkZhaWwiLCJnZW5lcmF0ZU5hbWUiOiJtd2ViaG9va3Rlc3Qua2IuaW8iLCJydWxlcyI6W3siYXBpR3JvdXBzIjpbIndlYmhvb2sub3BlcmF0b3JzLmNvcmVvcy5pbyJdLCJhcGlWZXJzaW9ucyI6WyJ2MSJdLCJvcGVyYXRpb25zIjpbIkNSRUFURSIsIlVQREFURSJdLCJyZXNvdXJjZXMiOlsid2ViaG9va3Rlc3RzIl19XSwic2lkZUVmZmVjdHMiOiJOb25lIiwidGFyZ2V0UG9ydCI6NDM0MywidHlwZSI6Ik11dGF0aW5nQWRtaXNzaW9uV2ViaG9vayIsIndlYmhvb2tQYXRoIjoiL211dGF0ZS13ZWJob29rLW9wZXJhdG9ycy1jb3Jlb3MtaW8tdjEtd2ViaG9va3Rlc3QifSx7ImFkbWlzc2lvblJldmlld1ZlcnNpb25zIjpbInYxYmV0YTEiLCJ2MSJdLCJjb250YWluZXJQb3J0Ijo0NDMsImNvbnZlcnNpb25DUkRzIjpbIndlYmhvb2t0ZXN0cy53ZWJob29rLm9wZXJhdG9ycy5jb3Jlb3MuaW8iXSwiZGVwbG95bWVudE5hbWUiOiJ3ZWJob29rLW9wZXJhdG9yLXdlYmhvb2siLCJmYWlsdXJlUG9saWN5IjoiRmFpbCIsImdlbmVyYXRlTmFtZSI6ImN3ZWJob29rdGVzdC5rYi5pbyIsInJ1bGVzIjpbeyJhcGlHcm91cHMiOlsid2ViaG9vay5vcGVyYXRvcnMuY29yZW9zLmlvIl0sImFwaVZlcnNpb25zIjpbInYxIl0sIm9wZXJhdGlvbnMiOlsiQ1JFQVRFIiwiVVBEQVRFIl0sInJlc291cmNlcyI6WyJ3ZWJob29rdGVzdHMiXX1dLCJzaWRlRWZmZWN0cyI6Ik5vbmUiLCJ0YXJnZXRQb3J0Ijo0MzQzLCJ0eXBlIjoiQ29udmVyc2lvbldlYmhvb2siLCJ3ZWJob29rUGF0aCI6Ii9jb252ZXJ0In1dfX0= -- type: olm.bundle.object - value: - data: eyJhcGlWZXJzaW9uIjoiYXBpZXh0ZW5zaW9ucy5rOHMuaW8vdjFiZXRhMSIsImtpbmQiOiJDdXN0b21SZXNvdXJjZURlZmluaXRpb24iLCJtZXRhZGF0YSI6eyJhbm5vdGF0aW9ucyI6eyJjb250cm9sbGVyLWdlbi5rdWJlYnVpbGRlci5pby92ZXJzaW9uIjoidjAuMy4wIn0sImNyZWF0aW9uVGltZXN0YW1wIjpudWxsLCJuYW1lIjoid2ViaG9va3Rlc3RzLndlYmhvb2sub3BlcmF0b3JzLmNvcmVvcy5pbyJ9LCJzcGVjIjp7Imdyb3VwIjoid2ViaG9vay5vcGVyYXRvcnMuY29yZW9zLmlvIiwibmFtZXMiOnsia2luZCI6IldlYmhvb2tUZXN0IiwibGlzdEtpbmQiOiJXZWJob29rVGVzdExpc3QiLCJwbHVyYWwiOiJ3ZWJob29rdGVzdHMiLCJzaW5ndWxhciI6IndlYmhvb2t0ZXN0In0sInByZXNlcnZlVW5rbm93bkZpZWxkcyI6ZmFsc2UsInNjb3BlIjoiTmFtZXNwYWNlZCIsInZlcnNpb24iOiJ2MSIsInZlcnNpb25zIjpbeyJuYW1lIjoidjEiLCJzY2hlbWEiOnsib3BlbkFQSVYzU2NoZW1hIjp7ImRlc2NyaXB0aW9uIjoiV2ViaG9va1Rlc3QgaXMgdGhlIFNjaGVtYSBmb3IgdGhlIHdlYmhvb2t0ZXN0cyBBUEkiLCJwcm9wZXJ0aWVzIjp7ImFwaVZlcnNpb24iOnsiZGVzY3JpcHRpb24iOiJBUElWZXJzaW9uIGRlZmluZXMgdGhlIHZlcnNpb25lZCBzY2hlbWEgb2YgdGhpcyByZXByZXNlbnRhdGlvbiBvZiBhbiBvYmplY3QuIFNlcnZlcnMgc2hvdWxkIGNvbnZlcnQgcmVjb2duaXplZCBzY2hlbWFzIHRvIHRoZSBsYXRlc3QgaW50ZXJuYWwgdmFsdWUsIGFuZCBtYXkgcmVqZWN0IHVucmVjb2duaXplZCB2YWx1ZXMuIE1vcmUgaW5mbzogaHR0cHM6Ly9naXQuazhzLmlvL2NvbW11bml0eS9jb250cmlidXRvcnMvZGV2ZWwvc2lnLWFyY2hpdGVjdHVyZS9hcGktY29udmVudGlvbnMubWQjcmVzb3VyY2VzIiwidHlwZSI6InN0cmluZyJ9LCJraW5kIjp7ImRlc2NyaXB0aW9uIjoiS2luZCBpcyBhIHN0cmluZyB2YWx1ZSByZXByZXNlbnRpbmcgdGhlIFJFU1QgcmVzb3VyY2UgdGhpcyBvYmplY3QgcmVwcmVzZW50cy4gU2VydmVycyBtYXkgaW5mZXIgdGhpcyBmcm9tIHRoZSBlbmRwb2ludCB0aGUgY2xpZW50IHN1Ym1pdHMgcmVxdWVzdHMgdG8uIENhbm5vdCBiZSB1cGRhdGVkLiBJbiBDYW1lbENhc2UuIE1vcmUgaW5mbzogaHR0cHM6Ly9naXQuazhzLmlvL2NvbW11bml0eS9jb250cmlidXRvcnMvZGV2ZWwvc2lnLWFyY2hpdGVjdHVyZS9hcGktY29udmVudGlvbnMubWQjdHlwZXMta2luZHMiLCJ0eXBlIjoic3RyaW5nIn0sIm1ldGFkYXRhIjp7InR5cGUiOiJvYmplY3QifSwic3BlYyI6eyJkZXNjcmlwdGlvbiI6IldlYmhvb2tUZXN0U3BlYyBkZWZpbmVzIHRoZSBkZXNpcmVkIHN0YXRlIG9mIFdlYmhvb2tUZXN0IiwicHJvcGVydGllcyI6eyJtdXRhdGUiOnsiZGVzY3JpcHRpb24iOiJNdXRhdGUgaXMgYSBmaWVsZCB0aGF0IHdpbGwgYmUgc2V0IHRvIHRydWUgYnkgdGhlIG11dGF0aW5nIHdlYmhvb2suIiwidHlwZSI6ImJvb2xlYW4ifSwidmFsaWQiOnsiZGVzY3JpcHRpb24iOiJWYWxpZCBtdXN0IGJlIHNldCB0byB0cnVlIG9yIHRoZSB2YWxpZGF0aW9uIHdlYmhvb2sgd2lsbCByZWplY3QgdGhlIHJlc291cmNlLiIsInR5cGUiOiJib29sZWFuIn19LCJyZXF1aXJlZCI6WyJ2YWxpZCJdLCJ0eXBlIjoib2JqZWN0In0sInN0YXR1cyI6eyJkZXNjcmlwdGlvbiI6IldlYmhvb2tUZXN0U3RhdHVzIGRlZmluZXMgdGhlIG9ic2VydmVkIHN0YXRlIG9mIFdlYmhvb2tUZXN0IiwidHlwZSI6Im9iamVjdCJ9fSwidHlwZSI6Im9iamVjdCJ9fSwic2VydmVkIjp0cnVlLCJzdG9yYWdlIjp0cnVlfSx7Im5hbWUiOiJ2MiIsInNjaGVtYSI6eyJvcGVuQVBJVjNTY2hlbWEiOnsiZGVzY3JpcHRpb24iOiJXZWJob29rVGVzdCBpcyB0aGUgU2NoZW1hIGZvciB0aGUgd2ViaG9va3Rlc3RzIEFQSSIsInByb3BlcnRpZXMiOnsiYXBpVmVyc2lvbiI6eyJkZXNjcmlwdGlvbiI6IkFQSVZlcnNpb24gZGVmaW5lcyB0aGUgdmVyc2lvbmVkIHNjaGVtYSBvZiB0aGlzIHJlcHJlc2VudGF0aW9uIG9mIGFuIG9iamVjdC4gU2VydmVycyBzaG91bGQgY29udmVydCByZWNvZ25pemVkIHNjaGVtYXMgdG8gdGhlIGxhdGVzdCBpbnRlcm5hbCB2YWx1ZSwgYW5kIG1heSByZWplY3QgdW5yZWNvZ25pemVkIHZhbHVlcy4gTW9yZSBpbmZvOiBodHRwczovL2dpdC5rOHMuaW8vY29tbXVuaXR5L2NvbnRyaWJ1dG9ycy9kZXZlbC9zaWctYXJjaGl0ZWN0dXJlL2FwaS1jb252ZW50aW9ucy5tZCNyZXNvdXJjZXMiLCJ0eXBlIjoic3RyaW5nIn0sImtpbmQiOnsiZGVzY3JpcHRpb24iOiJLaW5kIGlzIGEgc3RyaW5nIHZhbHVlIHJlcHJlc2VudGluZyB0aGUgUkVTVCByZXNvdXJjZSB0aGlzIG9iamVjdCByZXByZXNlbnRzLiBTZXJ2ZXJzIG1heSBpbmZlciB0aGlzIGZyb20gdGhlIGVuZHBvaW50IHRoZSBjbGllbnQgc3VibWl0cyByZXF1ZXN0cyB0by4gQ2Fubm90IGJlIHVwZGF0ZWQuIEluIENhbWVsQ2FzZS4gTW9yZSBpbmZvOiBodHRwczovL2dpdC5rOHMuaW8vY29tbXVuaXR5L2NvbnRyaWJ1dG9ycy9kZXZlbC9zaWctYXJjaGl0ZWN0dXJlL2FwaS1jb252ZW50aW9ucy5tZCN0eXBlcy1raW5kcyIsInR5cGUiOiJzdHJpbmcifSwibWV0YWRhdGEiOnsidHlwZSI6Im9iamVjdCJ9LCJzcGVjIjp7ImRlc2NyaXB0aW9uIjoiV2ViaG9va1Rlc3RTcGVjIGRlZmluZXMgdGhlIGRlc2lyZWQgc3RhdGUgb2YgV2ViaG9va1Rlc3QiLCJwcm9wZXJ0aWVzIjp7ImNvbnZlcnNpb24iOnsiZGVzY3JpcHRpb24iOiJDb252ZXJzaW9uIGlzIGFuIGV4YW1wbGUgZmllbGQgb2YgV2ViaG9va1Rlc3QuIEVkaXQgV2ViaG9va1Rlc3RfdHlwZXMuZ28gdG8gcmVtb3ZlL3VwZGF0ZSIsInByb3BlcnRpZXMiOnsibXV0YXRlIjp7ImRlc2NyaXB0aW9uIjoiTXV0YXRlIGlzIGEgZmllbGQgdGhhdCB3aWxsIGJlIHNldCB0byB0cnVlIGJ5IHRoZSBtdXRhdGluZyB3ZWJob29rLiIsInR5cGUiOiJib29sZWFuIn0sInZhbGlkIjp7ImRlc2NyaXB0aW9uIjoiVmFsaWQgbXVzdCBiZSBzZXQgdG8gdHJ1ZSBvciB0aGUgdmFsaWRhdGlvbiB3ZWJob29rIHdpbGwgcmVqZWN0IHRoZSByZXNvdXJjZS4iLCJ0eXBlIjoiYm9vbGVhbiJ9fSwicmVxdWlyZWQiOlsidmFsaWQiXSwidHlwZSI6Im9iamVjdCJ9fSwicmVxdWlyZWQiOlsiY29udmVyc2lvbiJdLCJ0eXBlIjoib2JqZWN0In0sInN0YXR1cyI6eyJkZXNjcmlwdGlvbiI6IldlYmhvb2tUZXN0U3RhdHVzIGRlZmluZXMgdGhlIG9ic2VydmVkIHN0YXRlIG9mIFdlYmhvb2tUZXN0IiwidHlwZSI6Im9iamVjdCJ9fSwidHlwZSI6Im9iamVjdCJ9fSwic2VydmVkIjp0cnVlLCJzdG9yYWdlIjpmYWxzZX1dfSwic3RhdHVzIjp7ImFjY2VwdGVkTmFtZXMiOnsia2luZCI6IiIsInBsdXJhbCI6IiJ9LCJjb25kaXRpb25zIjpbXSwic3RvcmVkVmVyc2lvbnMiOltdfX0= + annotations: + alm-examples: |- + [ + { + "apiVersion": "webhook.operators.coreos.io/v1", + "kind": "WebhookTest", + "metadata": { + "name": "webhooktest-sample", + "namespace": "webhook-operator-system" + }, + "spec": { + "valid": true + } + } + ] + capabilities: Basic Install + operators.operatorframework.io/builder: operator-sdk-v1.0.0 + operators.operatorframework.io/project_layout: go + apiServiceDefinitions: {} + crdDescriptions: + owned: + - kind: WebhookTest + name: webhooktests.webhook.operators.coreos.io + version: v1 + description: Webhook Operator description. TODO. + displayName: Webhook Operator + installModes: + - supported: false + type: OwnNamespace + - supported: false + type: SingleNamespace + - supported: false + type: MultiNamespace + - supported: true + type: AllNamespaces + keywords: + - webhook-operator + links: + - name: Webhook Operator + url: https://webhook-operator.domain + maintainers: + - email: your@email.com + name: Maintainer Name + maturity: alpha + provider: + name: Provider Name + url: https://your.domain relatedImages: - image: gcr.io/kubebuilder/kube-rbac-proxy:v0.5.0 name: "" @@ -760,7 +819,7 @@ schema: olm.bundle const semverBuiltFbcJson = `{ "schema": "olm.package", "name": "webhook-operator", - "defaultChannel": "stable-v0" + "defaultChannel": "stable-v0.0" } { "schema": "olm.channel", @@ -812,21 +871,64 @@ const semverBuiltFbcJson = `{ } }, { - "type": "olm.bundle.object", + "type": "olm.csv.metadata", "value": { - "data": "eyJhcGlWZXJzaW9uIjoicmJhYy5hdXRob3JpemF0aW9uLms4cy5pby92MWJldGExIiwia2luZCI6IkNsdXN0ZXJSb2xlIiwibWV0YWRhdGEiOnsiY3JlYXRpb25UaW1lc3RhbXAiOm51bGwsIm5hbWUiOiJ3ZWJob29rLW9wZXJhdG9yLW1ldHJpY3MtcmVhZGVyIn0sInJ1bGVzIjpbeyJub25SZXNvdXJjZVVSTHMiOlsiL21ldHJpY3MiXSwidmVyYnMiOlsiZ2V0Il19XX0=" - } - }, - { - "type": "olm.bundle.object", - "value": { - "data": "eyJhcGlWZXJzaW9uIjoib3BlcmF0b3JzLmNvcmVvcy5jb20vdjFhbHBoYTEiLCJraW5kIjoiQ2x1c3RlclNlcnZpY2VWZXJzaW9uIiwibWV0YWRhdGEiOnsiYW5ub3RhdGlvbnMiOnsiYWxtLWV4YW1wbGVzIjoiW1xuICB7XG4gICAgXCJhcGlWZXJzaW9uXCI6IFwid2ViaG9vay5vcGVyYXRvcnMuY29yZW9zLmlvL3YxXCIsXG4gICAgXCJraW5kXCI6IFwiV2ViaG9va1Rlc3RcIixcbiAgICBcIm1ldGFkYXRhXCI6IHtcbiAgICAgIFwibmFtZVwiOiBcIndlYmhvb2t0ZXN0LXNhbXBsZVwiLFxuICAgICAgXCJuYW1lc3BhY2VcIjogXCJ3ZWJob29rLW9wZXJhdG9yLXN5c3RlbVwiXG4gICAgfSxcbiAgICBcInNwZWNcIjoge1xuICAgICAgXCJ2YWxpZFwiOiB0cnVlXG4gICAgfVxuICB9XG5dIiwiY2FwYWJpbGl0aWVzIjoiQmFzaWMgSW5zdGFsbCIsIm9wZXJhdG9ycy5vcGVyYXRvcmZyYW1ld29yay5pby9idWlsZGVyIjoib3BlcmF0b3Itc2RrLXYxLjAuMCIsIm9wZXJhdG9ycy5vcGVyYXRvcmZyYW1ld29yay5pby9wcm9qZWN0X2xheW91dCI6ImdvIn0sIm5hbWUiOiJ3ZWJob29rLW9wZXJhdG9yLnYwLjAuMSIsIm5hbWVzcGFjZSI6InBsYWNlaG9sZGVyIn0sInNwZWMiOnsiYXBpc2VydmljZWRlZmluaXRpb25zIjp7fSwiY3VzdG9tcmVzb3VyY2VkZWZpbml0aW9ucyI6eyJvd25lZCI6W3sia2luZCI6IldlYmhvb2tUZXN0IiwibmFtZSI6IndlYmhvb2t0ZXN0cy53ZWJob29rLm9wZXJhdG9ycy5jb3Jlb3MuaW8iLCJ2ZXJzaW9uIjoidjEifV19LCJkZXNjcmlwdGlvbiI6IldlYmhvb2sgT3BlcmF0b3IgZGVzY3JpcHRpb24uIFRPRE8uIiwiZGlzcGxheU5hbWUiOiJXZWJob29rIE9wZXJhdG9yIiwiaWNvbiI6W3siYmFzZTY0ZGF0YSI6IiIsIm1lZGlhdHlwZSI6IiJ9XSwiaW5zdGFsbCI6eyJzcGVjIjp7ImNsdXN0ZXJQZXJtaXNzaW9ucyI6W3sicnVsZXMiOlt7ImFwaUdyb3VwcyI6WyJ3ZWJob29rLm9wZXJhdG9ycy5jb3Jlb3MuaW8iXSwicmVzb3VyY2VzIjpbIndlYmhvb2t0ZXN0cyJdLCJ2ZXJicyI6WyJjcmVhdGUiLCJkZWxldGUiLCJnZXQiLCJsaXN0IiwicGF0Y2giLCJ1cGRhdGUiLCJ3YXRjaCJdfSx7ImFwaUdyb3VwcyI6WyJ3ZWJob29rLm9wZXJhdG9ycy5jb3Jlb3MuaW8iXSwicmVzb3VyY2VzIjpbIndlYmhvb2t0ZXN0cy9zdGF0dXMiXSwidmVyYnMiOlsiZ2V0IiwicGF0Y2giLCJ1cGRhdGUiXX0seyJhcGlHcm91cHMiOlsiYXV0aGVudGljYXRpb24uazhzLmlvIl0sInJlc291cmNlcyI6WyJ0b2tlbnJldmlld3MiXSwidmVyYnMiOlsiY3JlYXRlIl19LHsiYXBpR3JvdXBzIjpbImF1dGhvcml6YXRpb24uazhzLmlvIl0sInJlc291cmNlcyI6WyJzdWJqZWN0YWNjZXNzcmV2aWV3cyJdLCJ2ZXJicyI6WyJjcmVhdGUiXX1dLCJzZXJ2aWNlQWNjb3VudE5hbWUiOiJkZWZhdWx0In1dLCJkZXBsb3ltZW50cyI6W3sibmFtZSI6IndlYmhvb2stb3BlcmF0b3Itd2ViaG9vayIsInNwZWMiOnsicmVwbGljYXMiOjEsInNlbGVjdG9yIjp7Im1hdGNoTGFiZWxzIjp7ImNvbnRyb2wtcGxhbmUiOiJjb250cm9sbGVyLW1hbmFnZXIifX0sInN0cmF0ZWd5Ijp7fSwidGVtcGxhdGUiOnsibWV0YWRhdGEiOnsibGFiZWxzIjp7ImNvbnRyb2wtcGxhbmUiOiJjb250cm9sbGVyLW1hbmFnZXIifX0sInNwZWMiOnsiY29udGFpbmVycyI6W3siYXJncyI6WyItLXNlY3VyZS1saXN0ZW4tYWRkcmVzcz0wLjAuMC4wOjg0NDMiLCItLXVwc3RyZWFtPWh0dHA6Ly8xMjcuMC4wLjE6ODA4MC8iLCItLWxvZ3Rvc3RkZXJyPXRydWUiLCItLXY9MTAiXSwiaW1hZ2UiOiJnY3IuaW8va3ViZWJ1aWxkZXIva3ViZS1yYmFjLXByb3h5OnYwLjUuMCIsIm5hbWUiOiJrdWJlLXJiYWMtcHJveHkiLCJwb3J0cyI6W3siY29udGFpbmVyUG9ydCI6ODQ0MywibmFtZSI6Imh0dHBzIn1dLCJyZXNvdXJjZXMiOnt9fSx7ImFyZ3MiOlsiLS1tZXRyaWNzLWFkZHI9MTI3LjAuMC4xOjgwODAiLCItLWVuYWJsZS1sZWFkZXItZWxlY3Rpb24iXSwiY29tbWFuZCI6WyIvbWFuYWdlciJdLCJpbWFnZSI6InF1YXkuaW8vb2xtdGVzdC93ZWJob29rLW9wZXJhdG9yOjAuMC4zIiwibmFtZSI6Im1hbmFnZXIiLCJwb3J0cyI6W3siY29udGFpbmVyUG9ydCI6OTQ0MywibmFtZSI6IndlYmhvb2stc2VydmVyIiwicHJvdG9jb2wiOiJUQ1AifV0sInJlc291cmNlcyI6eyJsaW1pdHMiOnsiY3B1IjoiMTAwbSIsIm1lbW9yeSI6IjMwTWkifSwicmVxdWVzdHMiOnsiY3B1IjoiMTAwbSIsIm1lbW9yeSI6IjIwTWkifX19XSwidGVybWluYXRpb25HcmFjZVBlcmlvZFNlY29uZHMiOjEwfX19fV0sInBlcm1pc3Npb25zIjpbeyJydWxlcyI6W3siYXBpR3JvdXBzIjpbIiJdLCJyZXNvdXJjZXMiOlsiY29uZmlnbWFwcyJdLCJ2ZXJicyI6WyJnZXQiLCJsaXN0Iiwid2F0Y2giLCJjcmVhdGUiLCJ1cGRhdGUiLCJwYXRjaCIsImRlbGV0ZSJdfSx7ImFwaUdyb3VwcyI6WyIiXSwicmVzb3VyY2VzIjpbImNvbmZpZ21hcHMvc3RhdHVzIl0sInZlcmJzIjpbImdldCIsInVwZGF0ZSIsInBhdGNoIl19LHsiYXBpR3JvdXBzIjpbIiJdLCJyZXNvdXJjZXMiOlsiZXZlbnRzIl0sInZlcmJzIjpbImNyZWF0ZSJdfV0sInNlcnZpY2VBY2NvdW50TmFtZSI6ImRlZmF1bHQifV19LCJzdHJhdGVneSI6ImRlcGxveW1lbnQifSwiaW5zdGFsbE1vZGVzIjpbeyJzdXBwb3J0ZWQiOmZhbHNlLCJ0eXBlIjoiT3duTmFtZXNwYWNlIn0seyJzdXBwb3J0ZWQiOmZhbHNlLCJ0eXBlIjoiU2luZ2xlTmFtZXNwYWNlIn0seyJzdXBwb3J0ZWQiOmZhbHNlLCJ0eXBlIjoiTXVsdGlOYW1lc3BhY2UifSx7InN1cHBvcnRlZCI6dHJ1ZSwidHlwZSI6IkFsbE5hbWVzcGFjZXMifV0sImtleXdvcmRzIjpbIndlYmhvb2stb3BlcmF0b3IiXSwibGlua3MiOlt7Im5hbWUiOiJXZWJob29rIE9wZXJhdG9yIiwidXJsIjoiaHR0cHM6Ly93ZWJob29rLW9wZXJhdG9yLmRvbWFpbiJ9XSwibWFpbnRhaW5lcnMiOlt7ImVtYWlsIjoieW91ckBlbWFpbC5jb20iLCJuYW1lIjoiTWFpbnRhaW5lciBOYW1lIn1dLCJtYXR1cml0eSI6ImFscGhhIiwicHJvdmlkZXIiOnsibmFtZSI6IlByb3ZpZGVyIE5hbWUiLCJ1cmwiOiJodHRwczovL3lvdXIuZG9tYWluIn0sInZlcnNpb24iOiIwLjAuMSIsIndlYmhvb2tkZWZpbml0aW9ucyI6W3siYWRtaXNzaW9uUmV2aWV3VmVyc2lvbnMiOlsidjFiZXRhMSIsInYxIl0sImNvbnRhaW5lclBvcnQiOjQ0MywiZGVwbG95bWVudE5hbWUiOiJ3ZWJob29rLW9wZXJhdG9yLXdlYmhvb2siLCJmYWlsdXJlUG9saWN5IjoiRmFpbCIsImdlbmVyYXRlTmFtZSI6InZ3ZWJob29rdGVzdC5rYi5pbyIsInJ1bGVzIjpbeyJhcGlHcm91cHMiOlsid2ViaG9vay5vcGVyYXRvcnMuY29yZW9zLmlvIl0sImFwaVZlcnNpb25zIjpbInYxIl0sIm9wZXJhdGlvbnMiOlsiQ1JFQVRFIiwiVVBEQVRFIl0sInJlc291cmNlcyI6WyJ3ZWJob29rdGVzdHMiXX1dLCJzaWRlRWZmZWN0cyI6Ik5vbmUiLCJ0YXJnZXRQb3J0Ijo0MzQzLCJ0eXBlIjoiVmFsaWRhdGluZ0FkbWlzc2lvbldlYmhvb2siLCJ3ZWJob29rUGF0aCI6Ii92YWxpZGF0ZS13ZWJob29rLW9wZXJhdG9ycy1jb3Jlb3MtaW8tdjEtd2ViaG9va3Rlc3QifSx7ImFkbWlzc2lvblJldmlld1ZlcnNpb25zIjpbInYxYmV0YTEiLCJ2MSJdLCJjb250YWluZXJQb3J0Ijo0NDMsImRlcGxveW1lbnROYW1lIjoid2ViaG9vay1vcGVyYXRvci13ZWJob29rIiwiZmFpbHVyZVBvbGljeSI6IkZhaWwiLCJnZW5lcmF0ZU5hbWUiOiJtd2ViaG9va3Rlc3Qua2IuaW8iLCJydWxlcyI6W3siYXBpR3JvdXBzIjpbIndlYmhvb2sub3BlcmF0b3JzLmNvcmVvcy5pbyJdLCJhcGlWZXJzaW9ucyI6WyJ2MSJdLCJvcGVyYXRpb25zIjpbIkNSRUFURSIsIlVQREFURSJdLCJyZXNvdXJjZXMiOlsid2ViaG9va3Rlc3RzIl19XSwic2lkZUVmZmVjdHMiOiJOb25lIiwidGFyZ2V0UG9ydCI6NDM0MywidHlwZSI6Ik11dGF0aW5nQWRtaXNzaW9uV2ViaG9vayIsIndlYmhvb2tQYXRoIjoiL211dGF0ZS13ZWJob29rLW9wZXJhdG9ycy1jb3Jlb3MtaW8tdjEtd2ViaG9va3Rlc3QifSx7ImFkbWlzc2lvblJldmlld1ZlcnNpb25zIjpbInYxYmV0YTEiLCJ2MSJdLCJjb250YWluZXJQb3J0Ijo0NDMsImNvbnZlcnNpb25DUkRzIjpbIndlYmhvb2t0ZXN0cy53ZWJob29rLm9wZXJhdG9ycy5jb3Jlb3MuaW8iXSwiZGVwbG95bWVudE5hbWUiOiJ3ZWJob29rLW9wZXJhdG9yLXdlYmhvb2siLCJmYWlsdXJlUG9saWN5IjoiRmFpbCIsImdlbmVyYXRlTmFtZSI6ImN3ZWJob29rdGVzdC5rYi5pbyIsInJ1bGVzIjpbeyJhcGlHcm91cHMiOlsid2ViaG9vay5vcGVyYXRvcnMuY29yZW9zLmlvIl0sImFwaVZlcnNpb25zIjpbInYxIl0sIm9wZXJhdGlvbnMiOlsiQ1JFQVRFIiwiVVBEQVRFIl0sInJlc291cmNlcyI6WyJ3ZWJob29rdGVzdHMiXX1dLCJzaWRlRWZmZWN0cyI6Ik5vbmUiLCJ0YXJnZXRQb3J0Ijo0MzQzLCJ0eXBlIjoiQ29udmVyc2lvbldlYmhvb2siLCJ3ZWJob29rUGF0aCI6Ii9jb252ZXJ0In1dfX0=" - } - }, - { - "type": "olm.bundle.object", - "value": { - "data": "eyJhcGlWZXJzaW9uIjoiYXBpZXh0ZW5zaW9ucy5rOHMuaW8vdjFiZXRhMSIsImtpbmQiOiJDdXN0b21SZXNvdXJjZURlZmluaXRpb24iLCJtZXRhZGF0YSI6eyJhbm5vdGF0aW9ucyI6eyJjb250cm9sbGVyLWdlbi5rdWJlYnVpbGRlci5pby92ZXJzaW9uIjoidjAuMy4wIn0sImNyZWF0aW9uVGltZXN0YW1wIjpudWxsLCJuYW1lIjoid2ViaG9va3Rlc3RzLndlYmhvb2sub3BlcmF0b3JzLmNvcmVvcy5pbyJ9LCJzcGVjIjp7Imdyb3VwIjoid2ViaG9vay5vcGVyYXRvcnMuY29yZW9zLmlvIiwibmFtZXMiOnsia2luZCI6IldlYmhvb2tUZXN0IiwibGlzdEtpbmQiOiJXZWJob29rVGVzdExpc3QiLCJwbHVyYWwiOiJ3ZWJob29rdGVzdHMiLCJzaW5ndWxhciI6IndlYmhvb2t0ZXN0In0sInByZXNlcnZlVW5rbm93bkZpZWxkcyI6ZmFsc2UsInNjb3BlIjoiTmFtZXNwYWNlZCIsInZlcnNpb24iOiJ2MSIsInZlcnNpb25zIjpbeyJuYW1lIjoidjEiLCJzY2hlbWEiOnsib3BlbkFQSVYzU2NoZW1hIjp7ImRlc2NyaXB0aW9uIjoiV2ViaG9va1Rlc3QgaXMgdGhlIFNjaGVtYSBmb3IgdGhlIHdlYmhvb2t0ZXN0cyBBUEkiLCJwcm9wZXJ0aWVzIjp7ImFwaVZlcnNpb24iOnsiZGVzY3JpcHRpb24iOiJBUElWZXJzaW9uIGRlZmluZXMgdGhlIHZlcnNpb25lZCBzY2hlbWEgb2YgdGhpcyByZXByZXNlbnRhdGlvbiBvZiBhbiBvYmplY3QuIFNlcnZlcnMgc2hvdWxkIGNvbnZlcnQgcmVjb2duaXplZCBzY2hlbWFzIHRvIHRoZSBsYXRlc3QgaW50ZXJuYWwgdmFsdWUsIGFuZCBtYXkgcmVqZWN0IHVucmVjb2duaXplZCB2YWx1ZXMuIE1vcmUgaW5mbzogaHR0cHM6Ly9naXQuazhzLmlvL2NvbW11bml0eS9jb250cmlidXRvcnMvZGV2ZWwvc2lnLWFyY2hpdGVjdHVyZS9hcGktY29udmVudGlvbnMubWQjcmVzb3VyY2VzIiwidHlwZSI6InN0cmluZyJ9LCJraW5kIjp7ImRlc2NyaXB0aW9uIjoiS2luZCBpcyBhIHN0cmluZyB2YWx1ZSByZXByZXNlbnRpbmcgdGhlIFJFU1QgcmVzb3VyY2UgdGhpcyBvYmplY3QgcmVwcmVzZW50cy4gU2VydmVycyBtYXkgaW5mZXIgdGhpcyBmcm9tIHRoZSBlbmRwb2ludCB0aGUgY2xpZW50IHN1Ym1pdHMgcmVxdWVzdHMgdG8uIENhbm5vdCBiZSB1cGRhdGVkLiBJbiBDYW1lbENhc2UuIE1vcmUgaW5mbzogaHR0cHM6Ly9naXQuazhzLmlvL2NvbW11bml0eS9jb250cmlidXRvcnMvZGV2ZWwvc2lnLWFyY2hpdGVjdHVyZS9hcGktY29udmVudGlvbnMubWQjdHlwZXMta2luZHMiLCJ0eXBlIjoic3RyaW5nIn0sIm1ldGFkYXRhIjp7InR5cGUiOiJvYmplY3QifSwic3BlYyI6eyJkZXNjcmlwdGlvbiI6IldlYmhvb2tUZXN0U3BlYyBkZWZpbmVzIHRoZSBkZXNpcmVkIHN0YXRlIG9mIFdlYmhvb2tUZXN0IiwicHJvcGVydGllcyI6eyJtdXRhdGUiOnsiZGVzY3JpcHRpb24iOiJNdXRhdGUgaXMgYSBmaWVsZCB0aGF0IHdpbGwgYmUgc2V0IHRvIHRydWUgYnkgdGhlIG11dGF0aW5nIHdlYmhvb2suIiwidHlwZSI6ImJvb2xlYW4ifSwidmFsaWQiOnsiZGVzY3JpcHRpb24iOiJWYWxpZCBtdXN0IGJlIHNldCB0byB0cnVlIG9yIHRoZSB2YWxpZGF0aW9uIHdlYmhvb2sgd2lsbCByZWplY3QgdGhlIHJlc291cmNlLiIsInR5cGUiOiJib29sZWFuIn19LCJyZXF1aXJlZCI6WyJ2YWxpZCJdLCJ0eXBlIjoib2JqZWN0In0sInN0YXR1cyI6eyJkZXNjcmlwdGlvbiI6IldlYmhvb2tUZXN0U3RhdHVzIGRlZmluZXMgdGhlIG9ic2VydmVkIHN0YXRlIG9mIFdlYmhvb2tUZXN0IiwidHlwZSI6Im9iamVjdCJ9fSwidHlwZSI6Im9iamVjdCJ9fSwic2VydmVkIjp0cnVlLCJzdG9yYWdlIjp0cnVlfSx7Im5hbWUiOiJ2MiIsInNjaGVtYSI6eyJvcGVuQVBJVjNTY2hlbWEiOnsiZGVzY3JpcHRpb24iOiJXZWJob29rVGVzdCBpcyB0aGUgU2NoZW1hIGZvciB0aGUgd2ViaG9va3Rlc3RzIEFQSSIsInByb3BlcnRpZXMiOnsiYXBpVmVyc2lvbiI6eyJkZXNjcmlwdGlvbiI6IkFQSVZlcnNpb24gZGVmaW5lcyB0aGUgdmVyc2lvbmVkIHNjaGVtYSBvZiB0aGlzIHJlcHJlc2VudGF0aW9uIG9mIGFuIG9iamVjdC4gU2VydmVycyBzaG91bGQgY29udmVydCByZWNvZ25pemVkIHNjaGVtYXMgdG8gdGhlIGxhdGVzdCBpbnRlcm5hbCB2YWx1ZSwgYW5kIG1heSByZWplY3QgdW5yZWNvZ25pemVkIHZhbHVlcy4gTW9yZSBpbmZvOiBodHRwczovL2dpdC5rOHMuaW8vY29tbXVuaXR5L2NvbnRyaWJ1dG9ycy9kZXZlbC9zaWctYXJjaGl0ZWN0dXJlL2FwaS1jb252ZW50aW9ucy5tZCNyZXNvdXJjZXMiLCJ0eXBlIjoic3RyaW5nIn0sImtpbmQiOnsiZGVzY3JpcHRpb24iOiJLaW5kIGlzIGEgc3RyaW5nIHZhbHVlIHJlcHJlc2VudGluZyB0aGUgUkVTVCByZXNvdXJjZSB0aGlzIG9iamVjdCByZXByZXNlbnRzLiBTZXJ2ZXJzIG1heSBpbmZlciB0aGlzIGZyb20gdGhlIGVuZHBvaW50IHRoZSBjbGllbnQgc3VibWl0cyByZXF1ZXN0cyB0by4gQ2Fubm90IGJlIHVwZGF0ZWQuIEluIENhbWVsQ2FzZS4gTW9yZSBpbmZvOiBodHRwczovL2dpdC5rOHMuaW8vY29tbXVuaXR5L2NvbnRyaWJ1dG9ycy9kZXZlbC9zaWctYXJjaGl0ZWN0dXJlL2FwaS1jb252ZW50aW9ucy5tZCN0eXBlcy1raW5kcyIsInR5cGUiOiJzdHJpbmcifSwibWV0YWRhdGEiOnsidHlwZSI6Im9iamVjdCJ9LCJzcGVjIjp7ImRlc2NyaXB0aW9uIjoiV2ViaG9va1Rlc3RTcGVjIGRlZmluZXMgdGhlIGRlc2lyZWQgc3RhdGUgb2YgV2ViaG9va1Rlc3QiLCJwcm9wZXJ0aWVzIjp7ImNvbnZlcnNpb24iOnsiZGVzY3JpcHRpb24iOiJDb252ZXJzaW9uIGlzIGFuIGV4YW1wbGUgZmllbGQgb2YgV2ViaG9va1Rlc3QuIEVkaXQgV2ViaG9va1Rlc3RfdHlwZXMuZ28gdG8gcmVtb3ZlL3VwZGF0ZSIsInByb3BlcnRpZXMiOnsibXV0YXRlIjp7ImRlc2NyaXB0aW9uIjoiTXV0YXRlIGlzIGEgZmllbGQgdGhhdCB3aWxsIGJlIHNldCB0byB0cnVlIGJ5IHRoZSBtdXRhdGluZyB3ZWJob29rLiIsInR5cGUiOiJib29sZWFuIn0sInZhbGlkIjp7ImRlc2NyaXB0aW9uIjoiVmFsaWQgbXVzdCBiZSBzZXQgdG8gdHJ1ZSBvciB0aGUgdmFsaWRhdGlvbiB3ZWJob29rIHdpbGwgcmVqZWN0IHRoZSByZXNvdXJjZS4iLCJ0eXBlIjoiYm9vbGVhbiJ9fSwicmVxdWlyZWQiOlsidmFsaWQiXSwidHlwZSI6Im9iamVjdCJ9fSwicmVxdWlyZWQiOlsiY29udmVyc2lvbiJdLCJ0eXBlIjoib2JqZWN0In0sInN0YXR1cyI6eyJkZXNjcmlwdGlvbiI6IldlYmhvb2tUZXN0U3RhdHVzIGRlZmluZXMgdGhlIG9ic2VydmVkIHN0YXRlIG9mIFdlYmhvb2tUZXN0IiwidHlwZSI6Im9iamVjdCJ9fSwidHlwZSI6Im9iamVjdCJ9fSwic2VydmVkIjp0cnVlLCJzdG9yYWdlIjpmYWxzZX1dfSwic3RhdHVzIjp7ImFjY2VwdGVkTmFtZXMiOnsia2luZCI6IiIsInBsdXJhbCI6IiJ9LCJjb25kaXRpb25zIjpbXSwic3RvcmVkVmVyc2lvbnMiOltdfX0=" + "annotations": { + "alm-examples": "[\n {\n \"apiVersion\": \"webhook.operators.coreos.io/v1\",\n \"kind\": \"WebhookTest\",\n \"metadata\": {\n \"name\": \"webhooktest-sample\",\n \"namespace\": \"webhook-operator-system\"\n },\n \"spec\": {\n \"valid\": true\n }\n }\n]", + "capabilities": "Basic Install", + "operators.operatorframework.io/builder": "operator-sdk-v1.0.0", + "operators.operatorframework.io/project_layout": "go" + }, + "apiServiceDefinitions": {}, + "crdDescriptions": { + "owned": [ + { + "name": "webhooktests.webhook.operators.coreos.io", + "version": "v1", + "kind": "WebhookTest" + } + ] + }, + "description": "Webhook Operator description. TODO.", + "displayName": "Webhook Operator", + "installModes": [ + { + "type": "OwnNamespace", + "supported": false + }, + { + "type": "SingleNamespace", + "supported": false + }, + { + "type": "MultiNamespace", + "supported": false + }, + { + "type": "AllNamespaces", + "supported": true + } + ], + "keywords": [ + "webhook-operator" + ], + "links": [ + { + "name": "Webhook Operator", + "url": "https://webhook-operator.domain" + } + ], + "maintainers": [ + { + "name": "Maintainer Name", + "email": "your@email.com" + } + ], + "maturity": "alpha", + "provider": { + "name": "Provider Name", + "url": "https://your.domain" + } } } ], @@ -869,11 +971,7 @@ func TestRawBuilder(t *testing.T) { name: "successful raw build yaml output", validate: true, rawBuilder: NewRawBuilder(BuilderConfig{ - ContainerCfg: ContainerConfig{ - ContainerTool: "docker", - BaseImage: "quay.io/operator-framework/opm:latest", - WorkingDir: testDir, - }, + WorkingDir: testDir, OutputType: "yaml", }), templateDefinition: TemplateDefinition{ @@ -904,11 +1002,7 @@ func TestRawBuilder(t *testing.T) { name: "successful raw build json output", validate: true, rawBuilder: NewRawBuilder(BuilderConfig{ - ContainerCfg: ContainerConfig{ - ContainerTool: "docker", - BaseImage: "quay.io/operator-framework/opm:latest", - WorkingDir: testDir, - }, + WorkingDir: testDir, OutputType: "json", }), templateDefinition: TemplateDefinition{ @@ -939,11 +1033,7 @@ func TestRawBuilder(t *testing.T) { name: "invalid template configuration", validate: false, rawBuilder: NewRawBuilder(BuilderConfig{ - ContainerCfg: ContainerConfig{ - ContainerTool: "docker", - BaseImage: "quay.io/operator-framework/opm:latest", - WorkingDir: testDir, - }, + WorkingDir: testDir, OutputType: "yaml", }), templateDefinition: TemplateDefinition{ @@ -962,11 +1052,7 @@ func TestRawBuilder(t *testing.T) { name: "invalid output type", validate: false, rawBuilder: NewRawBuilder(BuilderConfig{ - ContainerCfg: ContainerConfig{ - ContainerTool: "docker", - BaseImage: "quay.io/operator-framework/opm:latest", - WorkingDir: testDir, - }, + WorkingDir: testDir, OutputType: "invalid", }), templateDefinition: TemplateDefinition{ @@ -985,11 +1071,7 @@ func TestRawBuilder(t *testing.T) { name: "invalid schema", validate: false, rawBuilder: NewRawBuilder(BuilderConfig{ - ContainerCfg: ContainerConfig{ - ContainerTool: "docker", - BaseImage: "quay.io/operator-framework/opm:latest", - WorkingDir: testDir, - }, + WorkingDir: testDir, OutputType: "yaml", }), templateDefinition: TemplateDefinition{ @@ -1005,11 +1087,7 @@ func TestRawBuilder(t *testing.T) { name: "template config has empty input", validate: false, rawBuilder: NewRawBuilder(BuilderConfig{ - ContainerCfg: ContainerConfig{ - ContainerTool: "docker", - BaseImage: "quay.io/operator-framework/opm:latest", - WorkingDir: testDir, - }, + WorkingDir: testDir, OutputType: "yaml", }), templateDefinition: TemplateDefinition{ @@ -1030,11 +1108,7 @@ func TestRawBuilder(t *testing.T) { name: "template config has empty output", validate: false, rawBuilder: NewRawBuilder(BuilderConfig{ - ContainerCfg: ContainerConfig{ - ContainerTool: "docker", - BaseImage: "quay.io/operator-framework/opm:latest", - WorkingDir: testDir, - }, + WorkingDir: testDir, OutputType: "yaml", }), templateDefinition: TemplateDefinition{ @@ -1055,11 +1129,7 @@ func TestRawBuilder(t *testing.T) { name: "template config has empty input & output", validate: false, rawBuilder: NewRawBuilder(BuilderConfig{ - ContainerCfg: ContainerConfig{ - ContainerTool: "docker", - BaseImage: "quay.io/operator-framework/opm:latest", - WorkingDir: testDir, - }, + WorkingDir: testDir, OutputType: "yaml", }), templateDefinition: TemplateDefinition{ @@ -1077,7 +1147,6 @@ func TestRawBuilder(t *testing.T) { } for i, tc := range testCases { - tc.rawBuilder.builderCfg.InputDirectory = testDir t.Run(tc.name, func(t *testing.T) { outDir := fmt.Sprintf("raw-%d", i) outPath := path.Join(testDir, outDir) @@ -1107,7 +1176,7 @@ func TestRawBuilder(t *testing.T) { tc.buildAssertions(t, outPath, buildErr) if tc.validate { - validateErr := tc.rawBuilder.Validate(outDir) + validateErr := tc.rawBuilder.Validate(context.Background(), outDir) tc.validateAssertions(t, validateErr) } }) @@ -1313,11 +1382,7 @@ func TestCustomBuilder(t *testing.T) { name: "successful custom build yaml output", validate: true, customBuilder: NewCustomBuilder(BuilderConfig{ - ContainerCfg: ContainerConfig{ - ContainerTool: "docker", - BaseImage: "quay.io/operator-framework/opm:latest", - WorkingDir: testDir, - }, + WorkingDir: testDir, OutputType: "yaml", }), templateDefinition: TemplateDefinition{ @@ -1348,11 +1413,7 @@ func TestCustomBuilder(t *testing.T) { name: "successful custom build json output", validate: true, customBuilder: NewCustomBuilder(BuilderConfig{ - ContainerCfg: ContainerConfig{ - ContainerTool: "docker", - BaseImage: "quay.io/operator-framework/opm:latest", - WorkingDir: testDir, - }, + WorkingDir: testDir, OutputType: "json", }), templateDefinition: TemplateDefinition{ @@ -1383,11 +1444,7 @@ func TestCustomBuilder(t *testing.T) { name: "invalid template configuration", validate: false, customBuilder: NewCustomBuilder(BuilderConfig{ - ContainerCfg: ContainerConfig{ - ContainerTool: "docker", - BaseImage: "quay.io/operator-framework/opm:latest", - WorkingDir: testDir, - }, + WorkingDir: testDir, OutputType: "yaml", }), templateDefinition: TemplateDefinition{ @@ -1406,11 +1463,7 @@ func TestCustomBuilder(t *testing.T) { name: "invalid schema", validate: false, customBuilder: NewCustomBuilder(BuilderConfig{ - ContainerCfg: ContainerConfig{ - ContainerTool: "docker", - BaseImage: "quay.io/operator-framework/opm:latest", - WorkingDir: testDir, - }, + WorkingDir: testDir, OutputType: "yaml", }), templateDefinition: TemplateDefinition{ @@ -1430,11 +1483,7 @@ func TestCustomBuilder(t *testing.T) { name: "template config has empty command", validate: false, customBuilder: NewCustomBuilder(BuilderConfig{ - ContainerCfg: ContainerConfig{ - ContainerTool: "docker", - BaseImage: "quay.io/operator-framework/opm:latest", - WorkingDir: testDir, - }, + WorkingDir: testDir, OutputType: "yaml", }), templateDefinition: TemplateDefinition{ @@ -1456,11 +1505,7 @@ func TestCustomBuilder(t *testing.T) { name: "template config has empty output", validate: false, customBuilder: NewCustomBuilder(BuilderConfig{ - ContainerCfg: ContainerConfig{ - ContainerTool: "docker", - BaseImage: "quay.io/operator-framework/opm:latest", - WorkingDir: testDir, - }, + WorkingDir: testDir, OutputType: "yaml", }), templateDefinition: TemplateDefinition{ @@ -1482,11 +1527,7 @@ func TestCustomBuilder(t *testing.T) { name: "template config has empty command & output", validate: false, customBuilder: NewCustomBuilder(BuilderConfig{ - ContainerCfg: ContainerConfig{ - ContainerTool: "docker", - BaseImage: "quay.io/operator-framework/opm:latest", - WorkingDir: testDir, - }, + WorkingDir: testDir, OutputType: "yaml", }), templateDefinition: TemplateDefinition{ @@ -1505,7 +1546,6 @@ func TestCustomBuilder(t *testing.T) { } for i, tc := range testCases { - tc.customBuilder.builderCfg.InputDirectory = testDir t.Run(tc.name, func(t *testing.T) { outDir := fmt.Sprintf("custom-%d", i) outPath := path.Join(testDir, outDir) @@ -1535,7 +1575,7 @@ func TestCustomBuilder(t *testing.T) { tc.buildAssertions(t, outPath, buildErr) if tc.validate { - validateErr := tc.customBuilder.Validate(outDir) + validateErr := tc.customBuilder.Validate(context.Background(), outDir) tc.validateAssertions(t, validateErr) } }) @@ -1719,7 +1759,7 @@ const customBuiltFbcJson = `{ ` func TestValidateFailure(t *testing.T) { - err := validate(ContainerConfig{}, "") + err := validate(context.Background(), BuilderConfig{}, "") require.Error(t, err) require.Contains(t, err.Error(), "no such file or directory") } diff --git a/staging/operator-registry/alpha/template/composite/composite.go b/staging/operator-registry/alpha/template/composite/composite.go index 422017c974..68d261994b 100644 --- a/staging/operator-registry/alpha/template/composite/composite.go +++ b/staging/operator-registry/alpha/template/composite/composite.go @@ -2,35 +2,139 @@ package composite import ( "context" + "encoding/json" "fmt" + "io" + "net/http" + "net/url" + "os" "github.com/operator-framework/operator-registry/pkg/image" + "k8s.io/apimachinery/pkg/util/yaml" ) type BuilderMap map[string]Builder type CatalogBuilderMap map[string]BuilderMap +type builderFunc func(BuilderConfig) Builder + type Template struct { - CatalogBuilders CatalogBuilderMap - Registry image.Registry + catalogFile io.Reader + contributionFile io.Reader + validate bool + outputType string + registry image.Registry + registeredBuilders map[string]builderFunc +} + +type TemplateOption func(t *Template) + +func WithCatalogFile(catalogFile io.Reader) TemplateOption { + return func(t *Template) { + t.catalogFile = catalogFile + } +} + +func WithContributionFile(contribFile io.Reader) TemplateOption { + return func(t *Template) { + t.contributionFile = contribFile + } +} + +func WithOutputType(outputType string) TemplateOption { + return func(t *Template) { + t.outputType = outputType + } +} + +func WithRegistry(reg image.Registry) TemplateOption { + return func(t *Template) { + t.registry = reg + } +} + +func WithValidate(validate bool) TemplateOption { + return func(t *Template) { + t.validate = validate + } +} + +func NewTemplate(opts ...TemplateOption) *Template { + temp := &Template{ + // Default registered builders when creating a new Template + registeredBuilders: map[string]builderFunc{ + BasicBuilderSchema: func(bc BuilderConfig) Builder { return NewBasicBuilder(bc) }, + SemverBuilderSchema: func(bc BuilderConfig) Builder { return NewSemverBuilder(bc) }, + RawBuilderSchema: func(bc BuilderConfig) Builder { return NewRawBuilder(bc) }, + CustomBuilderSchema: func(bc BuilderConfig) Builder { return NewCustomBuilder(bc) }, + }, + } + + for _, opt := range opts { + opt(temp) + } + + return temp +} + +type HttpGetter interface { + Get(url string) (*http.Response, error) +} + +// FetchCatalogConfig will fetch the catalog configuration file from the given path. +// The path can be a local file path OR a URL that returns the raw contents of the catalog +// configuration file. +func FetchCatalogConfig(path string, httpGetter HttpGetter) (io.ReadCloser, error) { + var tempCatalog io.ReadCloser + catalogURI, err := url.ParseRequestURI(path) + if err != nil { + tempCatalog, err = os.Open(path) + if err != nil { + return nil, fmt.Errorf("opening catalog config file %q: %v", path, err) + } + } else { + tempResp, err := httpGetter.Get(catalogURI.String()) + if err != nil { + return nil, fmt.Errorf("fetching remote catalog config file %q: %v", path, err) + } + tempCatalog = tempResp.Body + } + + return tempCatalog, nil } // TODO(everettraven): do we need the context here? If so, how should it be used? -func (t *Template) Render(ctx context.Context, config *CompositeConfig, validate bool) error { +func (t *Template) Render(ctx context.Context, validate bool) error { + + catalogFile, err := t.parseCatalogsSpec() + if err != nil { + return err + } + + contributionFile, err := t.parseContributionSpec() + if err != nil { + return err + } + + catalogBuilderMap, err := t.newCatalogBuilderMap(catalogFile.Catalogs, t.outputType) + if err != nil { + return err + } + // TODO(everettraven): should we return aggregated errors? - for _, component := range config.Components { - if builderMap, ok := t.CatalogBuilders[component.Name]; ok { + for _, component := range contributionFile.Components { + if builderMap, ok := (*catalogBuilderMap)[component.Name]; ok { if builder, ok := builderMap[component.Strategy.Template.Schema]; ok { // run the builder corresponding to the schema - err := builder.Build(ctx, t.Registry, component.Destination.Path, component.Strategy.Template) + err := builder.Build(ctx, t.registry, component.Destination.Path, component.Strategy.Template) if err != nil { return fmt.Errorf("building component %q: %w", component.Name, err) } if validate { // run the validation for the builder - err = builder.Validate(component.Destination.Path) + err = builder.Validate(ctx, component.Destination.Path) if err != nil { return fmt.Errorf("validating component %q: %w", component.Name, err) } @@ -40,7 +144,7 @@ func (t *Template) Render(ctx context.Context, config *CompositeConfig, validate } } else { allowedComponents := []string{} - for k := range t.CatalogBuilders { + for k := range *catalogBuilderMap { allowedComponents = append(allowedComponents, k) } return fmt.Errorf("building component %q: component does not exist in the catalog configuration. Available components are: %s", component.Name, allowedComponents) @@ -48,3 +152,111 @@ func (t *Template) Render(ctx context.Context, config *CompositeConfig, validate } return nil } + +func (t *Template) builderForSchema(schema string, builderCfg BuilderConfig) (Builder, error) { + builderFunc, ok := t.registeredBuilders[schema] + if !ok { + return nil, fmt.Errorf("unknown schema %q", schema) + } + + return builderFunc(builderCfg), nil +} + +func (t *Template) parseCatalogsSpec() (*CatalogConfig, error) { + + // get catalog configurations + catalogConfig := &CatalogConfig{} + catalogDoc := json.RawMessage{} + catalogDecoder := yaml.NewYAMLOrJSONDecoder(t.catalogFile, 4096) + err := catalogDecoder.Decode(&catalogDoc) + if err != nil { + return nil, fmt.Errorf("decoding catalog config: %v", err) + } + err = json.Unmarshal(catalogDoc, catalogConfig) + if err != nil { + return nil, fmt.Errorf("unmarshalling catalog config: %v", err) + } + + if catalogConfig.Schema != CatalogSchema { + return nil, fmt.Errorf("catalog configuration file has unknown schema, should be %q", CatalogSchema) + } + + return catalogConfig, nil +} + +func (t *Template) parseContributionSpec() (*CompositeConfig, error) { + + // parse data to composite config + compositeConfig := &CompositeConfig{} + compositeDoc := json.RawMessage{} + compositeDecoder := yaml.NewYAMLOrJSONDecoder(t.contributionFile, 4096) + err := compositeDecoder.Decode(&compositeDoc) + if err != nil { + return nil, fmt.Errorf("decoding composite config: %v", err) + } + err = json.Unmarshal(compositeDoc, compositeConfig) + if err != nil { + return nil, fmt.Errorf("unmarshalling composite config: %v", err) + } + + if compositeConfig.Schema != CompositeSchema { + return nil, fmt.Errorf("composite configuration file has unknown schema, should be %q", CompositeSchema) + } + + return compositeConfig, nil +} + +func (t *Template) newCatalogBuilderMap(catalogs []Catalog, outputType string) (*CatalogBuilderMap, error) { + + catalogBuilderMap := make(CatalogBuilderMap) + + // setup the builders for each catalog + setupFailed := false + setupErrors := map[string][]string{} + for _, catalog := range catalogs { + errs := []string{} + // if catalog.Destination.BaseImage == "" { + // errs = append(errs, "destination.baseImage must not be an empty string") + // } + + if catalog.Destination.WorkingDir == "" { + errs = append(errs, "destination.workingDir must not be an empty string") + } + + // check for validation errors and skip builder creation if there are any errors + if len(errs) > 0 { + setupFailed = true + setupErrors[catalog.Name] = errs + continue + } + + if _, ok := catalogBuilderMap[catalog.Name]; !ok { + builderMap := make(BuilderMap) + for _, schema := range catalog.Builders { + builder, err := t.builderForSchema(schema, BuilderConfig{ + OutputType: outputType, + }) + if err != nil { + return nil, fmt.Errorf("getting builder %q for catalog %q: %v", schema, catalog.Name, err) + } + builderMap[schema] = builder + } + catalogBuilderMap[catalog.Name] = builderMap + } + } + + // if there were errors validating the catalog configuration then exit + if setupFailed { + //build the error message + var errMsg string + for cat, errs := range setupErrors { + errMsg += fmt.Sprintf("\nCatalog %v:\n", cat) + for _, err := range errs { + errMsg += fmt.Sprintf(" - %v\n", err) + } + } + return nil, fmt.Errorf("catalog configuration file field validation failed: %s", errMsg) + } + + return &catalogBuilderMap, nil +} diff --git a/staging/operator-registry/alpha/template/composite/composite_test.go b/staging/operator-registry/alpha/template/composite/composite_test.go index c2b28fac7b..fb0212c414 100644 --- a/staging/operator-registry/alpha/template/composite/composite_test.go +++ b/staging/operator-registry/alpha/template/composite/composite_test.go @@ -2,44 +2,100 @@ package composite import ( "context" - "encoding/json" - "errors" "fmt" + "io" + "net/http" + "os" + "path" + "strings" "testing" "github.com/operator-framework/operator-registry/pkg/image" "github.com/stretchr/testify/require" ) -type TestBuilder struct { - buildError bool - validateError bool -} +var _ Builder = &TestBuilder{} -const buildErr = "TestBuilder Build() error" -const validateErr = "TestBuilder Validate() error" +var TestBuilderSchema = "olm.builder.test" -var _ Builder = &TestBuilder{} +type TestBuilder struct { + buildShouldError bool + validateShouldError bool +} -func (tb *TestBuilder) Build(ctx context.Context, reg image.Registry, dir string, vd TemplateDefinition) error { - if tb.buildError { - return errors.New(buildErr) +func (tb *TestBuilder) Build(ctx context.Context, reg image.Registry, dir string, td TemplateDefinition) error { + if tb.buildShouldError { + return fmt.Errorf("build error!") } return nil } -func (tb *TestBuilder) Validate(dir string) error { - if tb.validateError { - return errors.New(validateErr) +func (tb *TestBuilder) Validate(ctx context.Context, dir string) error { + if tb.validateShouldError { + return fmt.Errorf("validate error!") } return nil } +var renderValidCatalog = ` +schema: olm.composite.catalogs +catalogs: + - name: first-catalog + destination: + workingDir: contributions/first-catalog + builders: + - olm.builder.test +` + +var renderValidComposite = ` +schema: olm.composite +components: + - name: first-catalog + destination: + path: my-operator + strategy: + name: test + template: + schema: olm.builder.test + config: + input: components/contribution1.yaml + output: catalog.yaml +` + +var renderInvalidComponentComposite = ` +schema: olm.composite +components: + - name: missing-catalog + destination: + path: my-operator + strategy: + name: test + template: + schema: olm.builder.test + config: + input: components/contribution1.yaml + output: catalog.yaml +` + +var renderInvalidBuilderComposite = ` +schema: olm.composite +components: + - name: first-catalog + destination: + path: my-operator + strategy: + name: test + template: + schema: olm.builder.invalid + config: + input: components/contribution1.yaml + output: catalog.yaml +` + func TestCompositeRender(t *testing.T) { type testCase struct { name string compositeTemplate Template - compositeCfg CompositeConfig validate bool assertions func(t *testing.T, err error) } @@ -49,28 +105,10 @@ func TestCompositeRender(t *testing.T) { name: "successful render", validate: true, compositeTemplate: Template{ - CatalogBuilders: CatalogBuilderMap{ - "testcatalog": BuilderMap{ - "olm.builder.test": &TestBuilder{}, - }, - }, - }, - compositeCfg: CompositeConfig{ - Schema: CompositeSchema, - Components: []Component{ - { - Name: "testcatalog", - Destination: ComponentDestination{ - Path: "testcatalog/mypackage", - }, - Strategy: BuildStrategy{ - Name: "testbuild", - Template: TemplateDefinition{ - Schema: "olm.builder.test", - Config: json.RawMessage{}, - }, - }, - }, + catalogFile: strings.NewReader(renderValidCatalog), + contributionFile: strings.NewReader(renderValidComposite), + registeredBuilders: map[string]builderFunc{ + TestBuilderSchema: func(bc BuilderConfig) Builder { return &TestBuilder{} }, }, }, assertions: func(t *testing.T, err error) { @@ -78,181 +116,499 @@ func TestCompositeRender(t *testing.T) { }, }, { - name: "component not in catalog config", + name: "Component build failure", validate: true, compositeTemplate: Template{ - CatalogBuilders: CatalogBuilderMap{ - "testcatalog": BuilderMap{ - "olm.builder.test": &TestBuilder{}, - }, - }, - }, - compositeCfg: CompositeConfig{ - Schema: CompositeSchema, - Components: []Component{ - { - Name: "invalid", - Destination: ComponentDestination{ - Path: "testcatalog/mypackage", - }, - Strategy: BuildStrategy{ - Name: "testbuild", - Template: TemplateDefinition{ - Schema: "olm.builder.test", - Config: json.RawMessage{}, - }, - }, - }, + catalogFile: strings.NewReader(renderValidCatalog), + contributionFile: strings.NewReader(renderValidComposite), + registeredBuilders: map[string]builderFunc{ + TestBuilderSchema: func(bc BuilderConfig) Builder { return &TestBuilder{buildShouldError: true} }, }, }, assertions: func(t *testing.T, err error) { require.Error(t, err) - expectedErr := fmt.Sprintf("building component %q: component does not exist in the catalog configuration. Available components are: %s", "invalid", []string{"testcatalog"}) - require.Equal(t, expectedErr, err.Error()) + require.Equal(t, "building component \"first-catalog\": build error!", err.Error()) }, }, { - name: "builder not in catalog config", + name: "Component validate failure", validate: true, compositeTemplate: Template{ - CatalogBuilders: CatalogBuilderMap{ - "testcatalog": BuilderMap{ - "olm.builder.test": &TestBuilder{}, - }, - }, - }, - compositeCfg: CompositeConfig{ - Schema: CompositeSchema, - Components: []Component{ - { - Name: "testcatalog", - Destination: ComponentDestination{ - Path: "testcatalog/mypackage", - }, - Strategy: BuildStrategy{ - Name: "testbuild", - Template: TemplateDefinition{ - Schema: "olm.builder.invalid", - Config: json.RawMessage{}, - }, - }, - }, + catalogFile: strings.NewReader(renderValidCatalog), + contributionFile: strings.NewReader(renderValidComposite), + registeredBuilders: map[string]builderFunc{ + TestBuilderSchema: func(bc BuilderConfig) Builder { return &TestBuilder{validateShouldError: true} }, }, }, assertions: func(t *testing.T, err error) { require.Error(t, err) - expectedErr := fmt.Sprintf("building component %q: no builder found for template schema %q", "testcatalog", "olm.builder.invalid") - require.Equal(t, expectedErr, err.Error()) + require.Equal(t, "validating component \"first-catalog\": validate error!", err.Error()) }, }, { - name: "build step error", - validate: true, + name: "Skipping validation", + validate: false, compositeTemplate: Template{ - CatalogBuilders: CatalogBuilderMap{ - "testcatalog": BuilderMap{ - "olm.builder.test": &TestBuilder{buildError: true}, - }, + catalogFile: strings.NewReader(renderValidCatalog), + contributionFile: strings.NewReader(renderValidComposite), + registeredBuilders: map[string]builderFunc{ + TestBuilderSchema: func(bc BuilderConfig) Builder { return &TestBuilder{validateShouldError: true} }, }, }, - compositeCfg: CompositeConfig{ - Schema: CompositeSchema, - Components: []Component{ - { - Name: "testcatalog", - Destination: ComponentDestination{ - Path: "testcatalog/mypackage", - }, - Strategy: BuildStrategy{ - Name: "testbuild", - Template: TemplateDefinition{ - Schema: "olm.builder.test", - Config: json.RawMessage{}, - }, - }, - }, + assertions: func(t *testing.T, err error) { + // We are skipping validation so we shouldn't receive + // the validation error from the TestBuilder + require.NoError(t, err) + }, + }, + { + name: "component not in catalog config", + validate: true, + compositeTemplate: Template{ + catalogFile: strings.NewReader(renderValidCatalog), + contributionFile: strings.NewReader(renderInvalidComponentComposite), + registeredBuilders: map[string]builderFunc{ + TestBuilderSchema: func(bc BuilderConfig) Builder { return &TestBuilder{} }, }, }, assertions: func(t *testing.T, err error) { require.Error(t, err) - expectedErr := fmt.Sprintf("building component %q: %s", "testcatalog", buildErr) + expectedErr := fmt.Sprintf("building component %q: component does not exist in the catalog configuration. Available components are: %s", "missing-catalog", []string{"first-catalog"}) require.Equal(t, expectedErr, err.Error()) }, }, { - name: "validate step error", + name: "builder not in catalog config", validate: true, compositeTemplate: Template{ - CatalogBuilders: CatalogBuilderMap{ - "testcatalog": BuilderMap{ - "olm.builder.test": &TestBuilder{validateError: true}, - }, + catalogFile: strings.NewReader(renderValidCatalog), + contributionFile: strings.NewReader(renderInvalidBuilderComposite), + registeredBuilders: map[string]builderFunc{ + TestBuilderSchema: func(bc BuilderConfig) Builder { return &TestBuilder{} }, }, }, - compositeCfg: CompositeConfig{ - Schema: CompositeSchema, - Components: []Component{ - { - Name: "testcatalog", - Destination: ComponentDestination{ - Path: "testcatalog/mypackage", - }, - Strategy: BuildStrategy{ - Name: "testbuild", - Template: TemplateDefinition{ - Schema: "olm.builder.test", - Config: json.RawMessage{}, - }, - }, - }, - }, + assertions: func(t *testing.T, err error) { + require.Error(t, err) + require.Equal(t, "building component \"first-catalog\": no builder found for template schema \"olm.builder.invalid\"", err.Error()) + }, + }, + { + name: "error parsing catalog spec", + validate: true, + compositeTemplate: Template{ + catalogFile: strings.NewReader(invalidSchemaCatalog), }, assertions: func(t *testing.T, err error) { require.Error(t, err) - expectedErr := fmt.Sprintf("validating component %q: %s", "testcatalog", validateErr) - require.Equal(t, expectedErr, err.Error()) + require.Equal(t, "catalog configuration file has unknown schema, should be \"olm.composite.catalogs\"", err.Error()) }, }, { - name: "validation step skipped", - validate: false, + name: "error parsing contribution spec", + validate: true, compositeTemplate: Template{ - CatalogBuilders: CatalogBuilderMap{ - "testcatalog": BuilderMap{ - "olm.builder.test": &TestBuilder{validateError: true}, + catalogFile: strings.NewReader(renderValidCatalog), + contributionFile: strings.NewReader(invalidSchemaComposite), + }, + assertions: func(t *testing.T, err error) { + require.Error(t, err) + require.Equal(t, "composite configuration file has unknown schema, should be \"olm.composite\"", err.Error()) + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + err := tc.compositeTemplate.Render(context.Background(), tc.validate) + tc.assertions(t, err) + }) + } +} + +func TestBuilderForSchema(t *testing.T) { + type testCase struct { + name string + builderSchema string + builderCfg BuilderConfig + assertions func(t *testing.T, builder Builder, err error) + } + + testCases := []testCase{ + { + name: "Basic Builder Schema", + builderSchema: BasicBuilderSchema, + builderCfg: BuilderConfig{}, + assertions: func(t *testing.T, builder Builder, err error) { + require.NoError(t, err) + require.IsType(t, &BasicBuilder{}, builder) + }, + }, + { + name: "Semver Builder Schema", + builderSchema: SemverBuilderSchema, + builderCfg: BuilderConfig{}, + assertions: func(t *testing.T, builder Builder, err error) { + require.NoError(t, err) + require.IsType(t, &SemverBuilder{}, builder) + }, + }, + { + name: "Raw Builder Schema", + builderSchema: RawBuilderSchema, + builderCfg: BuilderConfig{}, + assertions: func(t *testing.T, builder Builder, err error) { + require.NoError(t, err) + require.IsType(t, &RawBuilder{}, builder) + }, + }, + { + name: "Custom Builder Schema", + builderSchema: CustomBuilderSchema, + builderCfg: BuilderConfig{}, + assertions: func(t *testing.T, builder Builder, err error) { + require.NoError(t, err) + require.IsType(t, &CustomBuilder{}, builder) + }, + }, + { + name: "Invalid Builder Schema", + builderSchema: "invalid", + builderCfg: BuilderConfig{}, + assertions: func(t *testing.T, builder Builder, err error) { + require.Error(t, err) + require.Equal(t, fmt.Sprintf("unknown schema %q", "invalid"), err.Error()) + require.Nil(t, builder) + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + template := NewTemplate() + builder, err := template.builderForSchema(tc.builderSchema, tc.builderCfg) + tc.assertions(t, builder, err) + }) + } + +} + +var validCatalog = ` +schema: olm.composite.catalogs +catalogs: + - name: first-catalog + destination: + workingDir: contributions/first-catalog + builders: + - olm.builder.semver + - olm.builder.basic + - name: second-catalog + destination: + workingDir: contributions/second-catalog + builders: + - olm.builder.semver + - name: test-catalog + destination: + workingDir: contributions/test-catalog + builders: + - olm.builder.custom` + +var unmarshalFail = ` +invalid +` + +var invalidSchemaCatalog = ` +schema: invalid +catalogs: + - name: first-catalog + destination: + workingDir: contributions/first-catalog + builders: + - olm.builder.semver + - olm.builder.basic +` + +func TestParseCatalogSpec(t *testing.T) { + type testCase struct { + name string + catalog string + assertions func(t *testing.T, catalog *CatalogConfig, err error) + } + + testCases := []testCase{ + { + name: "Valid catalog configuration", + catalog: validCatalog, + assertions: func(t *testing.T, catalog *CatalogConfig, err error) { + require.NoError(t, err) + require.Equal(t, 3, len(catalog.Catalogs)) + }, + }, + { + name: "Unmarshal failure", + catalog: unmarshalFail, + assertions: func(t *testing.T, catalog *CatalogConfig, err error) { + require.Error(t, err) + require.Equal(t, "unmarshalling catalog config: json: cannot unmarshal string into Go value of type composite.CatalogConfig", err.Error()) + }, + }, + { + name: "Invalid schema", + catalog: invalidSchemaCatalog, + assertions: func(t *testing.T, catalog *CatalogConfig, err error) { + require.Error(t, err) + require.Equal(t, fmt.Sprintf("catalog configuration file has unknown schema, should be %q", CatalogSchema), err.Error()) + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + template := NewTemplate(WithCatalogFile(strings.NewReader(tc.catalog))) + catalog, err := template.parseCatalogsSpec() + tc.assertions(t, catalog, err) + }) + } +} + +var validComposite = ` +schema: olm.composite +components: + - name: first-catalog + destination: + path: my-operator + strategy: + name: semver + template: + schema: olm.builder.semver + config: + input: components/contribution1.yaml + output: catalog.yaml +` + +var invalidSchemaComposite = ` +schema: invalid +components: + - name: first-catalog + destination: + path: my-operator + strategy: + name: semver + template: + schema: olm.builder.semver + config: + input: components/contribution1.yaml + output: catalog.yaml +` + +func TestParseContributionSpec(t *testing.T) { + type testCase struct { + name string + composite string + assertions func(t *testing.T, composite *CompositeConfig, err error) + } + + testCases := []testCase{ + { + name: "Valid composite", + composite: validComposite, + assertions: func(t *testing.T, composite *CompositeConfig, err error) { + require.NoError(t, err) + require.Equal(t, 1, len(composite.Components)) + }, + }, + { + name: "Unmarshal failure", + composite: unmarshalFail, + assertions: func(t *testing.T, composite *CompositeConfig, err error) { + require.Error(t, err) + require.Equal(t, "unmarshalling composite config: json: cannot unmarshal string into Go value of type composite.CompositeConfig", err.Error()) + }, + }, + { + name: "Invalid schema", + composite: invalidSchemaComposite, + assertions: func(t *testing.T, composite *CompositeConfig, err error) { + require.Error(t, err) + require.Equal(t, fmt.Sprintf("composite configuration file has unknown schema, should be %q", CompositeSchema), err.Error()) + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + template := NewTemplate(WithContributionFile(strings.NewReader(tc.composite))) + contrib, err := template.parseContributionSpec() + tc.assertions(t, contrib, err) + }) + } +} + +func TestNewCatalogBuilderMap(t *testing.T) { + type testCase struct { + name string + catalogs []Catalog + assertions func(t *testing.T, builderMap *CatalogBuilderMap, err error) + } + + testCases := []testCase{ + { + name: "Valid Catalogs", + catalogs: []Catalog{ + { + Name: "test-catalog", + Destination: CatalogDestination{ + WorkingDir: "/", + // BaseImage: "base", + }, + Builders: []string{ + BasicBuilderSchema, }, }, }, - compositeCfg: CompositeConfig{ - Schema: CompositeSchema, - Components: []Component{ - { - Name: "testcatalog", - Destination: ComponentDestination{ - Path: "testcatalog/mypackage", - }, - Strategy: BuildStrategy{ - Name: "testbuild", - Template: TemplateDefinition{ - Schema: "olm.builder.test", - Config: json.RawMessage{}, - }, - }, + assertions: func(t *testing.T, builderMap *CatalogBuilderMap, err error) { + require.NoError(t, err) + //TODO: More assertions here + }, + }, + { + name: "Invalid Builder", + catalogs: []Catalog{ + { + Name: "test-catalog", + Destination: CatalogDestination{ + WorkingDir: "/", + // BaseImage: "base", + }, + Builders: []string{ + "invalid", }, }, }, - assertions: func(t *testing.T, err error) { - // the validate step would error but since - // we are skipping it we expect no error to occur + assertions: func(t *testing.T, builderMap *CatalogBuilderMap, err error) { + require.Error(t, err) + require.Equal(t, "getting builder \"invalid\" for catalog \"test-catalog\": unknown schema \"invalid\"", err.Error()) + }, + }, + // { + // name: "BaseImage+WorkingDir invalid", + // catalogs: []Catalog{ + // { + // Name: "test-catalog", + // Destination: CatalogDestination{}, + // Builders: []string{ + // BasicBuilderSchema, + // }, + // }, + // }, + // assertions: func(t *testing.T, builderMap *CatalogBuilderMap, err error) { + // require.Error(t, err) + // require.Equal(t, "catalog configuration file field validation failed: \nCatalog test-catalog:\n - destination.baseImage must not be an empty string\n - destination.workingDir must not be an empty string\n", err.Error()) + // }, + // }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + template := NewTemplate() + builderMap, err := template.newCatalogBuilderMap(tc.catalogs, "yaml") + tc.assertions(t, builderMap, err) + }) + } +} + +type fakeGetter struct { + catalog string + shouldError bool +} + +func (fg *fakeGetter) Get(url string) (*http.Response, error) { + if fg.shouldError { + return nil, fmt.Errorf("error!") + } + + return &http.Response{ + Body: io.NopCloser(strings.NewReader(fg.catalog)), + }, nil +} + +func TestFetchCatalogConfig(t *testing.T) { + type testCase struct { + name string + fakeGetter *fakeGetter + path string + createFile bool + assertions func(t *testing.T, rc io.ReadCloser, err error) + } + + testCases := []testCase{ + { + name: "Successful HTTP fetch", + path: "http://some-path.com", + fakeGetter: &fakeGetter{ + catalog: validCatalog, + }, + assertions: func(t *testing.T, rc io.ReadCloser, err error) { + require.NoError(t, err) + require.NotNil(t, rc) + }, + }, + { + name: "Failed HTTP fetch", + path: "http://some-path.com", + fakeGetter: &fakeGetter{ + catalog: validCatalog, + shouldError: true, + }, + assertions: func(t *testing.T, rc io.ReadCloser, err error) { + require.Error(t, err) + require.Equal(t, "fetching remote catalog config file \"http://some-path.com\": error!", err.Error()) + }, + }, + // TODO: for some reason this is triggering the fakeGetter.Get() function instead of using os.Open() + { + name: "Successful file fetch", + path: "file/test.yaml", + fakeGetter: &fakeGetter{ + catalog: validCatalog, + }, + createFile: true, + assertions: func(t *testing.T, rc io.ReadCloser, err error) { require.NoError(t, err) + require.NotNil(t, rc) + }, + }, + { + name: "Failed file fetch", + path: "file/test.yaml", + fakeGetter: &fakeGetter{ + catalog: validCatalog, + }, + createFile: false, + assertions: func(t *testing.T, rc io.ReadCloser, err error) { + require.Error(t, err) + require.Equal(t, "opening catalog config file \"file/test.yaml\": open file/test.yaml: no such file or directory", err.Error()) }, }, } + testDir := t.TempDir() + for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - err := tc.compositeTemplate.Render(context.Background(), &tc.compositeCfg, tc.validate) - tc.assertions(t, err) + filepath := tc.path + if tc.createFile { + err := os.MkdirAll(path.Join(testDir, path.Dir(tc.path)), 0o777) + require.NoError(t, err) + file, err := os.Create(path.Join(testDir, tc.path)) + require.NoError(t, err) + _, err = file.WriteString(tc.fakeGetter.catalog) + require.NoError(t, err) + + filepath = path.Join(testDir, tc.path) + } + + rc, err := FetchCatalogConfig(filepath, tc.fakeGetter) + tc.assertions(t, rc, err) }) } } diff --git a/staging/operator-registry/alpha/template/composite/config.go b/staging/operator-registry/alpha/template/composite/config.go index 70a480d4e8..21d4ac5ee0 100644 --- a/staging/operator-registry/alpha/template/composite/config.go +++ b/staging/operator-registry/alpha/template/composite/config.go @@ -37,6 +37,6 @@ type Catalog struct { } type CatalogDestination struct { - BaseImage string + // BaseImage string WorkingDir string } diff --git a/staging/operator-registry/alpha/template/semver/semver.go b/staging/operator-registry/alpha/template/semver/semver.go index 8cf2412874..ec6b6829e7 100644 --- a/staging/operator-registry/alpha/template/semver/semver.go +++ b/staging/operator-registry/alpha/template/semver/semver.go @@ -74,17 +74,42 @@ func readFile(reader io.Reader) (*semverTemplate, error) { return nil, err } - // default behavior is to generate only minor channels - sv := semverTemplate{ - GenerateMajorChannels: false, - GenerateMinorChannels: true, - } + sv := semverTemplate{} if err := yaml.UnmarshalStrict(data, &sv); err != nil { return nil, err } + if sv.Schema != schema { return nil, fmt.Errorf("readFile: input file has unknown schema, should be %q", schema) } + + // if no generate option is selected, default to GenerateMinorChannels + if !sv.GenerateMajorChannels && !sv.GenerateMinorChannels { + sv.GenerateMinorChannels = true + } + + // for default channel preference, + // if un-set, default to align to the selected generate option + // if set, error out if we mismatch the two + switch sv.DefaultChannelTypePreference { + case defaultStreamType: + if sv.GenerateMinorChannels { + sv.DefaultChannelTypePreference = minorStreamType + } else if sv.GenerateMajorChannels { + sv.DefaultChannelTypePreference = majorStreamType + } + case minorStreamType: + if !sv.GenerateMinorChannels { + return nil, fmt.Errorf("schema attribute mismatch: DefaultChannelTypePreference set to 'minor' doesn't make sense if not generating minor-version channels") + } + case majorStreamType: + if !sv.GenerateMajorChannels { + return nil, fmt.Errorf("schema attribute mismatch: DefaultChannelTypePreference set to 'major' doesn't make sense if not generating major-version channels") + } + default: + return nil, fmt.Errorf("unknown DefaultChannelTypePreference: %q\nValid values are 'major' or 'minor'", sv.DefaultChannelTypePreference) + } + return &sv, nil } @@ -240,8 +265,8 @@ func (sv *semverTemplate) generateChannels(semverChannels *bundleVersions) []dec unlinkedChannels[cName] = ch - hwcCandidate := highwaterChannel{archetype: archetype, version: bundles[bundleName], name: cName} - if hwcCandidate.gt(&hwc) { + hwcCandidate := highwaterChannel{archetype: archetype, kind: cKey, version: bundles[bundleName], name: cName} + if hwcCandidate.gt(&hwc, sv.DefaultChannelTypePreference) { hwc = hwcCandidate } } @@ -419,3 +444,31 @@ func stripBuildMetadata(v semver.Version) string { v.Build = nil return v.String() } + +// prefer (in descending order of preference): +// - higher-rank archetype, +// - semver version, +// - a channel type matching the set preference, or +// - a 'better' (higher value) channel type +func (h *highwaterChannel) gt(ih *highwaterChannel, pref streamType) bool { + if channelPriorities[h.archetype] != channelPriorities[ih.archetype] { + return channelPriorities[h.archetype] > channelPriorities[ih.archetype] + } + if h.version.NE(ih.version) { + return h.version.GT(ih.version) + } + if h.kind != ih.kind { + if h.kind == pref { + return true + } + if ih.kind == pref { + return false + } + return h.kind.gt((*ih).kind) + } + return false +} + +func (t streamType) gt(in streamType) bool { + return streamTypePriorities[t] > streamTypePriorities[in] +} diff --git a/staging/operator-registry/alpha/template/semver/semver_test.go b/staging/operator-registry/alpha/template/semver/semver_test.go index 9d55579c31..8fe470b6e2 100644 --- a/staging/operator-registry/alpha/template/semver/semver_test.go +++ b/staging/operator-registry/alpha/template/semver/semver_test.go @@ -1,13 +1,15 @@ package semver import ( + "fmt" "strings" "testing" "github.com/blang/semver/v4" + "github.com/stretchr/testify/require" + "github.com/operator-framework/operator-registry/alpha/declcfg" "github.com/operator-framework/operator-registry/alpha/property" - "github.com/stretchr/testify/require" ) func TestLinkChannels(t *testing.T) { @@ -143,97 +145,195 @@ func TestGenerateChannels(t *testing.T) { }, } + majorLinkedChannels := []declcfg.Channel{ + { + Schema: "olm.channel", + Name: "stable-v0", + Package: "a", + Entries: []declcfg.ChannelEntry{ + {Name: "a-v0.1.0", Replaces: ""}, + {Name: "a-v0.1.1", Replaces: "", Skips: []string{"a-v0.1.0"}}, + }, + }, + { + Schema: "olm.channel", + Name: "stable-v1", + Package: "a", + Entries: []declcfg.ChannelEntry{ + {Name: "a-v1.1.0", Replaces: "", Skips: []string{}}, + {Name: "a-v1.2.1", Replaces: "a-v1.1.0", Skips: []string{}}, + {Name: "a-v1.3.1-alpha", Replaces: ""}, + {Name: "a-v1.3.1-beta", Replaces: ""}, + {Name: "a-v1.3.1", Replaces: "a-v1.2.1", Skips: []string{"a-v1.1.0", "a-v1.3.1-alpha", "a-v1.3.1-beta"}}, + {Name: "a-v1.4.1-beta1", Replaces: ""}, + {Name: "a-v1.4.1-beta2", Replaces: ""}, + {Name: "a-v1.4.1", Replaces: "a-v1.3.1", Skips: []string{"a-v1.1.0", "a-v1.2.1", "a-v1.3.1-alpha", "a-v1.3.1-beta", "a-v1.4.1-beta1", "a-v1.4.1-beta2"}}, + }, + }, + { + Schema: "olm.channel", + Name: "stable-v2", + Package: "a", + Entries: []declcfg.ChannelEntry{ + {Name: "a-v2.1.0", Replaces: ""}, + {Name: "a-v2.1.1", Replaces: "", Skips: []string{"a-v2.1.0"}}, + {Name: "a-v2.3.1", Replaces: ""}, + {Name: "a-v2.3.2", Replaces: "a-v2.1.1", Skips: []string{"a-v2.1.0", "a-v2.3.1"}}, + }, + }, + { + Schema: "olm.channel", + Name: "stable-v3", + Package: "a", + Entries: []declcfg.ChannelEntry{ + {Name: "a-v3.1.0", Replaces: ""}, + {Name: "a-v3.1.1", Replaces: "", Skips: []string{"a-v3.1.0"}}, + }, + }, + } + + minorLinkedChannels := []declcfg.Channel{ + { + Schema: "olm.channel", + Name: "stable-v0.1", + Package: "a", + Entries: []declcfg.ChannelEntry{ + {Name: "a-v0.1.0", Replaces: ""}, + {Name: "a-v0.1.1", Replaces: "", Skips: []string{"a-v0.1.0"}}, + }, + }, + { + Schema: "olm.channel", + Name: "stable-v1.1", + Package: "a", + Entries: []declcfg.ChannelEntry{ + {Name: "a-v1.1.0", Replaces: "", Skips: []string{}}, + }, + }, + { + Schema: "olm.channel", + Name: "stable-v1.2", + Package: "a", + Entries: []declcfg.ChannelEntry{ + {Name: "a-v1.2.1", Replaces: "a-v1.1.0", Skips: []string{}}, + }, + }, + { + Schema: "olm.channel", + Name: "stable-v1.3", + Package: "a", + Entries: []declcfg.ChannelEntry{ + {Name: "a-v1.3.1-alpha", Replaces: ""}, + {Name: "a-v1.3.1-beta", Replaces: ""}, + {Name: "a-v1.3.1", Replaces: "a-v1.2.1", Skips: []string{"a-v1.1.0", "a-v1.3.1-alpha", "a-v1.3.1-beta"}}, + }, + }, + { + Schema: "olm.channel", + Name: "stable-v1.4", + Package: "a", + Entries: []declcfg.ChannelEntry{ + {Name: "a-v1.4.1-beta1", Replaces: ""}, + {Name: "a-v1.4.1-beta2", Replaces: ""}, + {Name: "a-v1.4.1", Replaces: "a-v1.3.1", Skips: []string{"a-v1.1.0", "a-v1.2.1", "a-v1.3.1-alpha", "a-v1.3.1-beta", "a-v1.4.1-beta1", "a-v1.4.1-beta2"}}, + }, + }, + { + Schema: "olm.channel", + Name: "stable-v2.1", + Package: "a", + Entries: []declcfg.ChannelEntry{ + {Name: "a-v2.1.0", Replaces: ""}, + {Name: "a-v2.1.1", Replaces: "", Skips: []string{"a-v2.1.0"}}, + }, + }, + { + Schema: "olm.channel", + Name: "stable-v2.3", + Package: "a", + Entries: []declcfg.ChannelEntry{ + {Name: "a-v2.3.1", Replaces: ""}, + {Name: "a-v2.3.2", Replaces: "a-v2.1.1", Skips: []string{"a-v2.1.0", "a-v2.3.1"}}, + }, + }, + { + Schema: "olm.channel", + Name: "stable-v3.1", + Package: "a", + Entries: []declcfg.ChannelEntry{ + {Name: "a-v3.1.0", Replaces: ""}, + {Name: "a-v3.1.1", Replaces: "", Skips: []string{"a-v3.1.0"}}, + }, + }, + } + + var combinedLinkedChannels []declcfg.Channel + combinedLinkedChannels = append(combinedLinkedChannels, minorLinkedChannels...) + combinedLinkedChannels = append(combinedLinkedChannels, majorLinkedChannels...) + tests := []struct { name string generateMinorChannels bool generateMajorChannels bool + defaultChannel string + channelTypePreference streamType out []declcfg.Channel }{ { name: "Edges between minor channels", generateMinorChannels: true, generateMajorChannels: false, - out: []declcfg.Channel{ - { - Schema: "olm.channel", - Name: "stable-v0.1", - Package: "a", - Entries: []declcfg.ChannelEntry{ - {Name: "a-v0.1.0", Replaces: ""}, - {Name: "a-v0.1.1", Replaces: "", Skips: []string{"a-v0.1.0"}}, - }, - }, - { - Schema: "olm.channel", - Name: "stable-v1.1", - Package: "a", - Entries: []declcfg.ChannelEntry{ - {Name: "a-v1.1.0", Replaces: "", Skips: []string{}}, - }, - }, - { - Schema: "olm.channel", - Name: "stable-v1.2", - Package: "a", - Entries: []declcfg.ChannelEntry{ - {Name: "a-v1.2.1", Replaces: "a-v1.1.0", Skips: []string{}}, - }, - }, - { - Schema: "olm.channel", - Name: "stable-v1.3", - Package: "a", - Entries: []declcfg.ChannelEntry{ - {Name: "a-v1.3.1-alpha", Replaces: ""}, - {Name: "a-v1.3.1-beta", Replaces: ""}, - {Name: "a-v1.3.1", Replaces: "a-v1.2.1", Skips: []string{"a-v1.1.0", "a-v1.3.1-alpha", "a-v1.3.1-beta"}}, - }, - }, - { - Schema: "olm.channel", - Name: "stable-v1.4", - Package: "a", - Entries: []declcfg.ChannelEntry{ - {Name: "a-v1.4.1-beta1", Replaces: ""}, - {Name: "a-v1.4.1-beta2", Replaces: ""}, - {Name: "a-v1.4.1", Replaces: "a-v1.3.1", Skips: []string{"a-v1.1.0", "a-v1.2.1", "a-v1.3.1-alpha", "a-v1.3.1-beta", "a-v1.4.1-beta1", "a-v1.4.1-beta2"}}, - }, - }, - { - Schema: "olm.channel", - Name: "stable-v2.1", - Package: "a", - Entries: []declcfg.ChannelEntry{ - {Name: "a-v2.1.0", Replaces: ""}, - {Name: "a-v2.1.1", Replaces: "", Skips: []string{"a-v2.1.0"}}, - }, - }, - { - Schema: "olm.channel", - Name: "stable-v2.3", - Package: "a", - Entries: []declcfg.ChannelEntry{ - {Name: "a-v2.3.1", Replaces: ""}, - {Name: "a-v2.3.2", Replaces: "a-v2.1.1", Skips: []string{"a-v2.1.0", "a-v2.3.1"}}, - }, - }, - { - Schema: "olm.channel", - Name: "stable-v3.1", - Package: "a", - Entries: []declcfg.ChannelEntry{ - {Name: "a-v3.1.0", Replaces: ""}, - {Name: "a-v3.1.1", Replaces: "", Skips: []string{"a-v3.1.0"}}, - }, - }, - }, + defaultChannel: "stable-v3.1", + channelTypePreference: minorStreamType, + out: minorLinkedChannels, + }, + { + name: "No edges between major channels", + generateMinorChannels: false, + generateMajorChannels: true, + defaultChannel: "stable-v3", + channelTypePreference: majorStreamType, + out: majorLinkedChannels, + }, + { + name: "Preference for minor default channel", + generateMinorChannels: true, + generateMajorChannels: true, + defaultChannel: "stable-v3.1", + channelTypePreference: minorStreamType, + out: combinedLinkedChannels, + }, + { + name: "Preference for major default channel", + generateMinorChannels: true, + generateMajorChannels: true, + defaultChannel: "stable-v3", + channelTypePreference: majorStreamType, + out: combinedLinkedChannels, + }, + { + name: "Mismatch generate/preference minor/major default channel", + generateMinorChannels: true, + generateMajorChannels: false, + defaultChannel: "stable-v3.1", + channelTypePreference: majorStreamType, + out: minorLinkedChannels, + }, + { + name: "Mismatch generate/preference major/minor default channel", + generateMinorChannels: false, + generateMajorChannels: true, + defaultChannel: "stable-v3", + channelTypePreference: minorStreamType, + out: majorLinkedChannels, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - sv := &semverTemplate{GenerateMajorChannels: tt.generateMajorChannels, GenerateMinorChannels: tt.generateMinorChannels, pkg: "a"} + sv := &semverTemplate{GenerateMajorChannels: tt.generateMajorChannels, GenerateMinorChannels: tt.generateMinorChannels, pkg: "a", DefaultChannelTypePreference: tt.channelTypePreference} require.ElementsMatch(t, tt.out, sv.generateChannels(&channelOperatorVersions)) + require.Equal(t, tt.defaultChannel, sv.defaultChannel) }) } } @@ -363,18 +463,12 @@ func TestBailOnVersionBuildMetadata(t *testing.T) { } func TestReadFile(t *testing.T) { - type testCase struct { - name string - input string - assertions func(*testing.T, *semverTemplate, error) - } - testCases := []testCase{ - { - name: "valid", - input: `--- + + templateFstr := `--- schema: olm.semver -generateMajorChannels: true -generateMinorChannels: true +generateMajorChannels: %s +generateMinorChannels: %s +defaultChannelTypePreference: %s candidate: bundles: - image: quay.io/foo/olm:testoperator.v0.1.0 @@ -398,7 +492,17 @@ fast: stable: bundles: - image: quay.io/foo/olm:testoperator.v1.0.1 -`, +` + + type testCase struct { + name string + input string + assertions func(*testing.T, *semverTemplate, error) + } + testCases := []testCase{ + { + name: "valid", + input: fmt.Sprintf(templateFstr, "true", "true", "minor"), assertions: func(t *testing.T, template *semverTemplate, err error) { require.NotNil(t, template) require.NoError(t, err) @@ -442,6 +546,30 @@ invalid: require.EqualError(t, err, `error unmarshaling JSON: while decoding JSON: json: unknown field "invalid"`) }, }, + { + name: "generate/default mismatch, minor/major", + input: fmt.Sprintf(templateFstr, "true", "false", "minor"), + assertions: func(t *testing.T, template *semverTemplate, err error) { + require.Nil(t, template) + require.ErrorContains(t, err, "schema attribute mismatch") + }, + }, + { + name: "generate/default mismatch, major/minor", + input: fmt.Sprintf(templateFstr, "false", "true", "major"), + assertions: func(t *testing.T, template *semverTemplate, err error) { + require.Nil(t, template) + require.ErrorContains(t, err, "schema attribute mismatch") + }, + }, + { + name: "unknown defaultchanneltypepreference", + input: fmt.Sprintf(templateFstr, "false", "true", "foo"), + assertions: func(t *testing.T, template *semverTemplate, err error) { + require.Nil(t, template) + require.ErrorContains(t, err, "unknown DefaultChannelTypePreference") + }, + }, } for _, tc := range testCases { diff --git a/staging/operator-registry/alpha/template/semver/types.go b/staging/operator-registry/alpha/template/semver/types.go index de948f3723..de68504c65 100644 --- a/staging/operator-registry/alpha/template/semver/types.go +++ b/staging/operator-registry/alpha/template/semver/types.go @@ -24,12 +24,13 @@ type semverTemplateChannelBundles struct { } type semverTemplate struct { - Schema string `json:"schema"` - GenerateMajorChannels bool `json:"generateMajorChannels,omitempty"` - GenerateMinorChannels bool `json:"generateMinorChannels,omitempty"` - Candidate semverTemplateChannelBundles `json:"candidate,omitempty"` - Fast semverTemplateChannelBundles `json:"fast,omitempty"` - Stable semverTemplateChannelBundles `json:"stable,omitempty"` + Schema string `json:"schema"` + GenerateMajorChannels bool `json:"generateMajorChannels,omitempty"` + GenerateMinorChannels bool `json:"generateMinorChannels,omitempty"` + DefaultChannelTypePreference streamType `json:"defaultChannelTypePreference,omitempty"` + Candidate semverTemplateChannelBundles `json:"candidate,omitempty"` + Fast semverTemplateChannelBundles `json:"fast,omitempty"` + Stable semverTemplateChannelBundles `json:"stable,omitempty"` pkg string `json:"-"` // the derived package name defaultChannel string `json:"-"` // detected "most stable" channel head @@ -62,10 +63,12 @@ func (b byChannelPriority) Swap(i, j int) { b[i], b[j] = b[j], b[i] } type streamType string +const defaultStreamType streamType = "" const minorStreamType streamType = "minor" const majorStreamType streamType = "major" -var streamTypePriorities = map[streamType]int{minorStreamType: 0, majorStreamType: 1} +// general preference for minor channels +var streamTypePriorities = map[streamType]int{minorStreamType: 2, majorStreamType: 1, defaultStreamType: 0} // map of archetypes --> bundles --> bundle-version from the input file type bundleVersions map[channelArchetype]map[string]semver.Version // e.g. srcv["stable"]["example-operator.v1.0.0"] = 1.0.0 @@ -74,14 +77,11 @@ type bundleVersions map[channelArchetype]map[string]semver.Version // e.g. srcv[ // later as the package's defaultChannel attribute type highwaterChannel struct { archetype channelArchetype + kind streamType version semver.Version name string } -func (h *highwaterChannel) gt(ih *highwaterChannel) bool { - return (channelPriorities[h.archetype] > channelPriorities[ih.archetype]) || (h.version.GT(ih.version)) -} - type entryTuple struct { arch channelArchetype kind streamType diff --git a/staging/operator-registry/cmd/opm/alpha/template/composite.go b/staging/operator-registry/cmd/opm/alpha/template/composite.go index 1d8b9df0cb..df44998766 100644 --- a/staging/operator-registry/cmd/opm/alpha/template/composite.go +++ b/staging/operator-registry/cmd/opm/alpha/template/composite.go @@ -1,13 +1,11 @@ package template import ( - "encoding/json" - "fmt" "log" + "net/http" "os" "github.com/spf13/cobra" - "k8s.io/apimachinery/pkg/util/yaml" "github.com/operator-framework/operator-registry/alpha/template/composite" "github.com/operator-framework/operator-registry/cmd/opm/internal/util" @@ -15,9 +13,7 @@ import ( func newCompositeTemplateCmd() *cobra.Command { var ( - template composite.Template output string - containerTool string validate bool compositeFile string catalogFile string @@ -30,154 +26,52 @@ and a 'composite template' file`, and a 'composite template' file`, Args: cobra.MaximumNArgs(0), Run: func(cmd *cobra.Command, args []string) { - containerTool = "docker" - catalogData, err := os.Open(catalogFile) - if err != nil { - log.Fatalf("opening catalog config file %q: %s", catalogFile, err) - } - defer catalogData.Close() - - // get catalog configurations - catalogConfig := &composite.CatalogConfig{} - catalogDoc := json.RawMessage{} - catalogDecoder := yaml.NewYAMLOrJSONDecoder(catalogData, 4096) - err = catalogDecoder.Decode(&catalogDoc) - if err != nil { - log.Fatalf("decoding catalog config: %s", err) - } - err = json.Unmarshal(catalogDoc, catalogConfig) - if err != nil { - log.Fatalf("unmarshalling catalog config: %s", err) - } - if catalogConfig.Schema != composite.CatalogSchema { - log.Fatalf("catalog configuration file has unknown schema, should be %q", composite.CatalogSchema) + switch output { + case "yaml": + // do nothing + case "json": + // do nothing + default: + log.Fatalf("invalid --output value %q, expected (json|yaml)", output) } - catalogBuilderMap := make(composite.CatalogBuilderMap) - - wd, err := os.Getwd() - if err != nil { - log.Fatalf("getting current working directory: %s", err) - } - - // setup the builders for each catalog - setupFailed := false - setupErrors := map[string][]string{} - for _, catalog := range catalogConfig.Catalogs { - errs := []string{} - if catalog.Destination.BaseImage == "" { - errs = append(errs, "destination.baseImage must not be an empty string") - } - - if catalog.Destination.WorkingDir == "" { - errs = append(errs, "destination.workingDir must not be an empty string") - } - - // check for validation errors and skip builder creation if there are any errors - if len(errs) > 0 { - setupFailed = true - setupErrors[catalog.Name] = errs - continue - } - - if _, ok := catalogBuilderMap[catalog.Name]; !ok { - builderMap := make(composite.BuilderMap) - for _, schema := range catalog.Builders { - builder, err := builderForSchema(schema, composite.BuilderConfig{ - ContainerCfg: composite.ContainerConfig{ - ContainerTool: containerTool, - BaseImage: catalog.Destination.BaseImage, - WorkingDir: catalog.Destination.WorkingDir, - }, - OutputType: output, - // BUGBUG: JEK: This is a strong assumption that input is always local to execution which we need to eliminate in a later PR - InputDirectory: wd, - }) - if err != nil { - log.Fatalf("getting builder %q for catalog %q: %s", schema, catalog.Name, err) - } - builderMap[schema] = builder - } - catalogBuilderMap[catalog.Name] = builderMap - } - } - - // if there were errors validating the catalog configuration then exit - if setupFailed { - //build the error message - var errMsg string - for cat, errs := range setupErrors { - errMsg += fmt.Sprintf("\nCatalog %s:\n", cat) - for _, err := range errs { - errMsg += fmt.Sprintf(" - %s\n", err) - } - } - log.Fatalf("catalog configuration file field validation failed: %s", errMsg) - } - - template.CatalogBuilders = catalogBuilderMap - reg, err := util.CreateCLIRegistry(cmd) if err != nil { log.Fatalf("creating containerd registry: %v", err) } defer reg.Destroy() - template.Registry = reg - - compositeData, err := os.Open(compositeFile) + // operator author's 'composite.yaml' file + compositeReader, err := os.Open(compositeFile) if err != nil { - log.Fatalf("opening composite config file %q: %s", compositeFile, err) + log.Fatalf("opening composite config file %q: %v", compositeFile, err) } - defer compositeData.Close() + defer compositeReader.Close() - // parse data to composite config - compositeConfig := &composite.CompositeConfig{} - compositeDoc := json.RawMessage{} - compositeDecoder := yaml.NewYAMLOrJSONDecoder(compositeData, 4096) - err = compositeDecoder.Decode(&compositeDoc) + // catalog maintainer's 'catalogs.yaml' file + tempCatalog, err := composite.FetchCatalogConfig(catalogFile, http.DefaultClient) if err != nil { - log.Fatalf("decoding composite config: %s", err) - } - err = json.Unmarshal(compositeDoc, compositeConfig) - if err != nil { - log.Fatalf("unmarshalling composite config: %s", err) + log.Fatalf(err.Error()) } + defer tempCatalog.Close() - if compositeConfig.Schema != composite.CompositeSchema { - log.Fatalf("%q has unknown schema, should be %q", compositeFile, composite.CompositeSchema) - } + template := composite.NewTemplate( + composite.WithCatalogFile(tempCatalog), + composite.WithContributionFile(compositeReader), + composite.WithOutputType(output), + composite.WithRegistry(reg), + ) - err = template.Render(cmd.Context(), compositeConfig, validate) + err = template.Render(cmd.Context(), validate) if err != nil { - log.Fatalf("rendering the composite template: %s", err) + log.Fatalf("rendering the composite template: %v", err) } }, } cmd.Flags().StringVarP(&output, "output", "o", "json", "Output format (json|yaml)") - // TODO: Investigate ways to do this without using a cli tool like docker/podman - // cmd.Flags().StringVar(&containerTool, "container-tool", "docker", "container tool to be used when rendering templates (should be an equivalent replacement to docker - similar to podman)") cmd.Flags().BoolVar(&validate, "validate", true, "whether or not the created FBC should be validated (i.e 'opm validate')") - cmd.Flags().StringVarP(&compositeFile, "composite-config", "c", "catalog/config.yaml", "File to use as the composite configuration file") + cmd.Flags().StringVarP(&compositeFile, "composite-config", "c", "composite.yaml", "File to use as the composite configuration file") cmd.Flags().StringVarP(&catalogFile, "catalog-config", "f", "catalogs.yaml", "File to use as the catalog configuration file") return cmd } - -func builderForSchema(schema string, builderCfg composite.BuilderConfig) (composite.Builder, error) { - var builder composite.Builder - switch schema { - case composite.BasicBuilderSchema: - builder = composite.NewBasicBuilder(builderCfg) - case composite.SemverBuilderSchema: - builder = composite.NewSemverBuilder(builderCfg) - case composite.RawBuilderSchema: - builder = composite.NewRawBuilder(builderCfg) - case composite.CustomBuilderSchema: - builder = composite.NewCustomBuilder(builderCfg) - default: - return nil, fmt.Errorf("unknown schema %q", schema) - } - - return builder, nil -} diff --git a/staging/operator-registry/cmd/opm/migrate/cmd.go b/staging/operator-registry/cmd/opm/migrate/cmd.go index 6405060b0a..36c73abc7a 100644 --- a/staging/operator-registry/cmd/opm/migrate/cmd.go +++ b/staging/operator-registry/cmd/opm/migrate/cmd.go @@ -21,6 +21,10 @@ func NewCmd() *cobra.Command { Short: "Migrate a sqlite-based index image or database file to a file-based catalog", Long: `Migrate a sqlite-based index image or database file to a file-based catalog. +NOTE: the --output=json format produces streamable, concatenated JSON files. +These are suitable to opm and jq, but may not be supported by arbitrary JSON +parsers that assume that a file contains exactly one valid JSON object. + ` + sqlite.DeprecationMessage, Args: cobra.ExactArgs(2), PersistentPreRun: func(_ *cobra.Command, _ []string) { diff --git a/staging/operator-registry/cmd/opm/render/cmd.go b/staging/operator-registry/cmd/opm/render/cmd.go index 448097a73a..03cdbcbd3e 100644 --- a/staging/operator-registry/cmd/opm/render/cmd.go +++ b/staging/operator-registry/cmd/opm/render/cmd.go @@ -22,8 +22,10 @@ func NewCmd() *cobra.Command { ) cmd := &cobra.Command{ Use: "render [index-image | bundle-image | sqlite-file]...", - Short: "Generate a declarative config blob from catalogs and bundles", - Long: `Generate a declarative config blob from the provided index images, bundle images, and sqlite database files + Short: "Generate a stream of file-based catalog objects from catalogs and bundles", + Long: `Generate a stream of file-based catalog objects to stdout from the provided +catalog images, file-based catalog directories, bundle images, and sqlite +database files. ` + sqlite.DeprecationMessage, Args: cobra.MinimumNArgs(1), @@ -63,7 +65,7 @@ func NewCmd() *cobra.Command { } }, } - cmd.Flags().StringVarP(&output, "output", "o", "json", "Output format (json|yaml)") + cmd.Flags().StringVarP(&output, "output", "o", "json", "Output format of the streamed file-based catalog objects (json|yaml)") return cmd } diff --git a/staging/operator-registry/cmd/opm/serve/serve.go b/staging/operator-registry/cmd/opm/serve/serve.go index 8b7d280764..fc3c482ff8 100644 --- a/staging/operator-registry/cmd/opm/serve/serve.go +++ b/staging/operator-registry/cmd/opm/serve/serve.go @@ -136,7 +136,7 @@ func (s *serve) run(ctx context.Context) error { return err } } else { - if err := cache.LoadOrRebuild(store, os.DirFS(s.configDir)); err != nil { + if err := cache.LoadOrRebuild(ctx, store, os.DirFS(s.configDir)); err != nil { return err } } diff --git a/staging/operator-registry/cmd/opm/validate/validate.go b/staging/operator-registry/cmd/opm/validate/validate.go index 9132ce578e..4579f5e120 100644 --- a/staging/operator-registry/cmd/opm/validate/validate.go +++ b/staging/operator-registry/cmd/opm/validate/validate.go @@ -17,7 +17,7 @@ func NewCmd() *cobra.Command { Short: "Validate the declarative index config", Long: "Validate the declarative config JSON file(s) in a given directory", Args: cobra.ExactArgs(1), - RunE: func(_ *cobra.Command, args []string) error { + RunE: func(c *cobra.Command, args []string) error { directory := args[0] s, err := os.Stat(directory) if err != nil { @@ -27,7 +27,7 @@ func NewCmd() *cobra.Command { return fmt.Errorf("%q is not a directory", directory) } - if err := config.Validate(os.DirFS(directory)); err != nil { + if err := config.Validate(c.Context(), os.DirFS(directory)); err != nil { logger.Fatal(err) } return nil diff --git a/staging/operator-registry/codegen.Dockerfile b/staging/operator-registry/codegen.Dockerfile deleted file mode 100644 index 38bbfb429c..0000000000 --- a/staging/operator-registry/codegen.Dockerfile +++ /dev/null @@ -1,19 +0,0 @@ -FROM golang:1.18-alpine - -RUN apk update && \ - apk add make git protobuf - -ENV MODULE google.golang.org -ENV SRC ${GOPATH}/src/${MODULE} -COPY vendor/${MODULE} ${SRC} -RUN echo $(ls ${SRC}) -RUN go install ${SRC}/protobuf/proto ${SRC}/protobuf/cmd/protoc-gen-go ${SRC}/grpc/cmd/protoc-gen-go-grpc - - -WORKDIR /codegen - -COPY pkg pkg -COPY Makefile Makefile -RUN make codegen - -LABEL maintainer="Odin Team " diff --git a/staging/operator-registry/docs/contributors/e2e_tests.md b/staging/operator-registry/docs/contributors/e2e_tests.md index 5fb48b4d6e..6ff63fa832 100644 --- a/staging/operator-registry/docs/contributors/e2e_tests.md +++ b/staging/operator-registry/docs/contributors/e2e_tests.md @@ -32,7 +32,7 @@ running even after the test suite has completed. make file and use `--dry-run` with `--focus` and see if the regex would trigger your specific test(s). ```bash - GOFLAGS="-mod=vendor" go run github.com/onsi/ginkgo/v2/ginkgo --v --randomize-all --randomize-suites --race --dry-run --focus 'builds and manipulates bundle and index images' -tags=json1,kind ./test/e2e + go run github.com/onsi/ginkgo/v2/ginkgo --v --randomize-all --randomize-suites --race --dry-run --focus 'builds and manipulates bundle and index images' -tags=json1,kind ./test/e2e ``` ## Kind with SSL @@ -59,7 +59,7 @@ make file and use `--dry-run` with `--focus` and see if the regex would trigger make file and use `--dry-run` with `--focus` and see if the regex would trigger your specific test(s). ```bash - GOFLAGS="-mod=vendor" go run github.com/onsi/ginkgo/v2/ginkgo --v --randomize-all --randomize-suites --race --dry-run --focus 'builds and manipulates bundle and index images' -tags=json1,kind ./test/e2e + go run github.com/onsi/ginkgo/v2/ginkgo --v --randomize-all --randomize-suites --race --dry-run --focus 'builds and manipulates bundle and index images' -tags=json1,kind ./test/e2e ``` ## Minikube (or other type) using kubeconfig without SSL @@ -94,7 +94,7 @@ make file and use `--dry-run` with `--focus` and see if the regex would trigger make file and use `--dry-run` with `--focus` and see if the regex would trigger your specific test(s). ```bash - GOFLAGS="-mod=vendor" go run github.com/onsi/ginkgo/v2/ginkgo --v --randomize-all --randomize-suites --race --dry-run --focus 'builds and manipulates bundle and index images' -tags=json1 ./test/e2e + go run github.com/onsi/ginkgo/v2/ginkgo --v --randomize-all --randomize-suites --race --dry-run --focus 'builds and manipulates bundle and index images' -tags=json1 ./test/e2e ``` TIP: use a non-dynamic `kind` server by using `kind get kubeconfig --name "kind" > /tmp/kindconfig` and set `KUBECONFIG="/tmp/kindconfig"` @@ -131,7 +131,7 @@ TIP: use a non-dynamic `kind` server by using `kind get kubeconfig --name "kind" make file and use `--dry-run` with `--focus` and see if the regex would trigger your specific test(s). ```bash - GOFLAGS="-mod=vendor" go run github.com/onsi/ginkgo/v2/ginkgo --v --randomize-all --randomize-suites --race --dry-run --focus 'builds and manipulates bundle and index images' -tags=json1 ./test/e2e + go run github.com/onsi/ginkgo/v2/ginkgo --v --randomize-all --randomize-suites --race --dry-run --focus 'builds and manipulates bundle and index images' -tags=json1 ./test/e2e ``` TIP: use a non-dynamic `kind` server by using `kind get kubeconfig --name "kind" > /tmp/kindconfig` and set `KUBECONFIG="/tmp/kindconfig"` diff --git a/staging/operator-registry/go.mod b/staging/operator-registry/go.mod index c6f9412fe9..9c8af7e0c8 100644 --- a/staging/operator-registry/go.mod +++ b/staging/operator-registry/go.mod @@ -1,134 +1,133 @@ module github.com/operator-framework/operator-registry -go 1.18 +go 1.19 require ( github.com/adrg/xdg v0.4.0 github.com/blang/semver/v4 v4.0.0 - github.com/containerd/containerd v1.5.13 + github.com/containerd/containerd v1.5.18 github.com/docker/cli v20.10.12+incompatible - github.com/docker/distribution v2.8.1+incompatible - github.com/docker/docker v1.4.2-0.20200203170920-46ec8731fbce + github.com/docker/distribution v2.8.2+incompatible + github.com/docker/docker v20.10.24+incompatible github.com/ghodss/yaml v1.0.0 - github.com/golang-migrate/migrate/v4 v4.6.2 + github.com/golang-migrate/migrate/v4 v4.16.1 github.com/golang/mock v1.5.0 - github.com/google/go-cmp v0.5.6 + github.com/google/go-cmp v0.5.9 github.com/grpc-ecosystem/grpc-health-probe v0.4.11 github.com/h2non/filetype v1.1.1 github.com/h2non/go-is-svg v0.0.0-20160927212452-35e8c4b0612c github.com/joelanford/ignore v0.0.0-20210607151042-0d25dc18b62d - github.com/mattn/go-sqlite3 v1.14.10 + github.com/mattn/go-sqlite3 v1.14.16 github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2 - github.com/onsi/ginkgo/v2 v2.1.3 - github.com/onsi/gomega v1.18.1 + github.com/onsi/ginkgo/v2 v2.9.5 + github.com/onsi/gomega v1.27.7 github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/image-spec v1.0.2 - github.com/operator-framework/api v0.15.0 + github.com/operator-framework/api v0.17.4-0.20230223191600-0131a6301e42 github.com/otiai10/copy v1.2.0 github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 github.com/pkg/errors v0.9.1 - github.com/sirupsen/logrus v1.8.1 - github.com/spf13/cobra v1.4.0 - github.com/stretchr/testify v1.7.0 + github.com/sirupsen/logrus v1.9.2 + github.com/spf13/cobra v1.6.0 + github.com/stretchr/testify v1.8.1 go.etcd.io/bbolt v1.3.6 - golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 - golang.org/x/net v0.4.0 - golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 - golang.org/x/sys v0.3.0 - google.golang.org/grpc v1.47.0 + golang.org/x/mod v0.10.0 + golang.org/x/net v0.10.0 + golang.org/x/sync v0.2.0 + golang.org/x/sys v0.8.0 + golang.org/x/text v0.9.0 + google.golang.org/grpc v1.51.0 google.golang.org/grpc/cmd/protoc-gen-go-grpc v0.0.0-20200709232328-d8193ee9cc3e - google.golang.org/protobuf v1.28.0 + google.golang.org/protobuf v1.30.0 gopkg.in/yaml.v2 v2.4.0 - k8s.io/api v0.24.0 - k8s.io/apiextensions-apiserver v0.24.0 - k8s.io/apimachinery v0.24.0 - k8s.io/client-go v0.24.0 - k8s.io/kubectl v0.24.0 - sigs.k8s.io/controller-runtime v0.12.1 + k8s.io/api v0.27.2 + k8s.io/apiextensions-apiserver v0.27.2 + k8s.io/apimachinery v0.27.2 + k8s.io/client-go v0.27.2 + k8s.io/kubectl v0.27.1 + sigs.k8s.io/controller-runtime v0.15.0 sigs.k8s.io/kind v0.11.1 sigs.k8s.io/yaml v1.3.0 ) require ( - github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect + github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/BurntSushi/toml v0.3.1 // indirect - github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd // indirect - github.com/Microsoft/go-winio v0.4.17 // indirect - github.com/Microsoft/hcsshim v0.8.24 // indirect - github.com/PuerkitoBio/purell v1.1.1 // indirect - github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect + github.com/MakeNowJust/heredoc v1.0.0 // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/Microsoft/hcsshim v0.8.25 // indirect github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d // indirect github.com/alessio/shellescape v1.4.1 // indirect - github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220418222510-f25a4f6275ed // indirect + github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 // indirect github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/blang/semver v3.5.1+incompatible // indirect github.com/bshuster-repo/logrus-logstash-hook v0.4.1 // indirect github.com/bugsnag/bugsnag-go v1.5.3 // indirect github.com/bugsnag/panicwrap v1.2.0 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cenkalti/backoff/v4 v4.1.3 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/containerd/cgroups v1.0.3 // indirect - github.com/containerd/continuity v0.1.0 // indirect + github.com/containerd/continuity v0.3.0 // indirect github.com/containerd/ttrpc v1.1.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/docker/docker-credential-helpers v0.6.3 // indirect github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-metrics v0.0.1 // indirect - github.com/docker/go-units v0.4.0 // indirect + github.com/docker/go-units v0.5.0 // indirect github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect - github.com/emicklei/go-restful v2.9.5+incompatible // indirect + github.com/emicklei/go-restful/v3 v3.9.0 // indirect github.com/evanphx/json-patch v4.12.0+incompatible // indirect - github.com/evanphx/json-patch/v5 v5.2.0 // indirect - github.com/felixge/httpsnoop v1.0.1 // indirect + github.com/evanphx/json-patch/v5 v5.6.0 // indirect + github.com/felixge/httpsnoop v1.0.3 // indirect github.com/garyburd/redigo v1.6.0 // indirect github.com/go-git/gcfg v1.5.0 // indirect github.com/go-git/go-billy/v5 v5.1.0 // indirect github.com/go-git/go-git/v5 v5.3.0 // indirect - github.com/go-logr/logr v1.2.0 // indirect - github.com/go-openapi/jsonpointer v0.19.5 // indirect - github.com/go-openapi/jsonreference v0.19.5 // indirect - github.com/go-openapi/swag v0.19.14 // indirect - github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect + github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-openapi/jsonpointer v0.19.6 // indirect + github.com/go-openapi/jsonreference v0.20.1 // indirect + github.com/go-openapi/swag v0.22.3 // indirect + github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/gofrs/uuid v3.3.0+incompatible // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.2 // indirect - github.com/golang/snappy v0.0.3 // indirect - github.com/google/cel-go v0.12.4 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/google/cel-go v0.12.6 // indirect github.com/google/gnostic v0.5.7-v3refs // indirect github.com/google/gofuzz v1.1.0 // indirect - github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect - github.com/google/uuid v1.2.0 // indirect + github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect + github.com/google/uuid v1.3.0 // indirect github.com/gorilla/handlers v1.4.2 // indirect github.com/gorilla/mux v1.8.0 // indirect - github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 // indirect github.com/imdario/mergo v0.3.12 // indirect - github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/inconshreveable/mousetrap v1.0.1 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect - github.com/klauspost/compress v1.12.3 // indirect - github.com/mailru/easyjson v0.7.6 // indirect + github.com/klauspost/compress v1.13.6 // indirect + github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-isatty v0.0.12 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mitchellh/go-wordwrap v1.0.0 // indirect github.com/mitchellh/mapstructure v1.4.1 // indirect github.com/moby/locker v1.0.1 // indirect github.com/moby/spdystream v0.2.0 // indirect github.com/moby/sys/mountinfo v0.4.1 // indirect - github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect + github.com/moby/term v0.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c // indirect + github.com/morikuni/aec v1.0.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pelletier/go-toml v1.9.3 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.12.1 // indirect - github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.32.1 // indirect - github.com/prometheus/procfs v0.7.3 // indirect - github.com/russross/blackfriday v1.5.2 // indirect + github.com/prometheus/client_golang v1.15.1 // indirect + github.com/prometheus/client_model v0.4.0 // indirect + github.com/prometheus/common v0.42.0 // indirect + github.com/prometheus/procfs v0.9.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/spiffe/go-spiffe/v2 v2.0.0 // indirect github.com/stoewer/go-strcase v1.2.0 // indirect @@ -136,38 +135,35 @@ require ( github.com/yvasiyarov/gorelic v0.0.7 // indirect github.com/yvasiyarov/newrelic_platform_go v0.0.0-20160601141957-9c099fbc30e9 // indirect github.com/zeebo/errs v1.3.0 // indirect - go.opencensus.io v0.23.0 // indirect - go.opentelemetry.io/contrib v0.20.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0 // indirect - go.opentelemetry.io/otel v0.20.0 // indirect - go.opentelemetry.io/otel/exporters/otlp v0.20.0 // indirect - go.opentelemetry.io/otel/metric v0.20.0 // indirect - go.opentelemetry.io/otel/sdk v0.20.0 // indirect - go.opentelemetry.io/otel/sdk/export/metric v0.20.0 // indirect - go.opentelemetry.io/otel/sdk/metric v0.20.0 // indirect - go.opentelemetry.io/otel/trace v0.20.0 // indirect - go.opentelemetry.io/proto/otlp v0.7.0 // indirect - golang.org/x/crypto v0.0.0-20220408190544-5352b0902921 // indirect - golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect - golang.org/x/term v0.3.0 // indirect - golang.org/x/text v0.5.0 // indirect - golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect - golang.org/x/tools v0.1.12 // indirect - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect + go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.35.1 // indirect + go.opentelemetry.io/otel v1.10.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.10.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.10.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.10.0 // indirect + go.opentelemetry.io/otel/metric v0.31.0 // indirect + go.opentelemetry.io/otel/sdk v1.10.0 // indirect + go.opentelemetry.io/otel/trace v1.10.0 // indirect + go.opentelemetry.io/proto/otlp v0.19.0 // indirect + golang.org/x/crypto v0.7.0 // indirect + golang.org/x/oauth2 v0.5.0 // indirect + golang.org/x/term v0.8.0 // indirect + golang.org/x/time v0.3.0 // indirect + golang.org/x/tools v0.9.1 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 // indirect + google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect - k8s.io/apiserver v0.24.0 // indirect - k8s.io/component-base v0.24.0 // indirect - k8s.io/klog/v2 v2.60.1 // indirect - k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42 // indirect - k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 // indirect - sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.30 // indirect - sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/apiserver v0.27.2 // indirect + k8s.io/component-base v0.27.2 // indirect + k8s.io/klog/v2 v2.90.1 // indirect + k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // indirect + k8s.io/utils v0.0.0-20230209194617-a36077c30491 // indirect + sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect ) // latest tag resolves to a very old version. this is only used for spinning up local test registries diff --git a/staging/operator-registry/go.sum b/staging/operator-registry/go.sum index 938204fd83..eed9c7da5c 100644 --- a/staging/operator-registry/go.sum +++ b/staging/operator-registry/go.sum @@ -1,7 +1,6 @@ bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= @@ -15,11 +14,6 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -40,57 +34,38 @@ cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RX cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= -github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= -github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= -github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd h1:sjQovDkwrZp8u+gxLtPgKGjk5hCxuy2hrRejBTA9xFU= -github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= -github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= +github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= +github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/Microsoft/go-winio v0.4.17 h1:iT12IBVClFevaf8PuVyi3UmZOVh4OqnaLxDTW2O6j3w= github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/hcsshim v0.8.24 h1:jP+GMeRXIR1sH1kG4lJr9ShmSjVrua5jmFZDtfYGkn4= -github.com/Microsoft/hcsshim v0.8.24/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/Microsoft/hcsshim v0.8.25 h1:fRMwXiwk3qDwc0P05eHnh+y2v07JdtsfQ1fuAc69m9g= +github.com/Microsoft/hcsshim v0.8.25/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= -github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= -github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= -github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= -github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls= github.com/adrg/xdg v0.4.0/go.mod h1:N6ag73EX4wyxeaoeHctc1mas01KZgsj5tYiAIwqJE/E= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alessio/shellescape v1.4.1 h1:V7yhSDDn8LP4lc4jS8pFkt0zCnzVJlG5JXy9BVKJUX0= github.com/alessio/shellescape v1.4.1/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210826220005-b48c857c3a0e/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= -github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220418222510-f25a4f6275ed h1:ue9pVfIcP+QMEjfgo/Ez4ZjNZfonGgR6NgjMaJMu1Cg= -github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220418222510-f25a4f6275ed/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= -github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 h1:yL7+Jz0jTC6yykIK/Wh74gnTJnrGr5AyrNMXuA0gves= +github.com/antlr/antlr4/runtime/Go/antlr v1.4.10/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= @@ -100,23 +75,15 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkY github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= -github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y= github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= -github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= -github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= -github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= @@ -130,43 +97,36 @@ github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3k github.com/bugsnag/panicwrap v1.2.0 h1:OzrKrRvXis8qEvOkfcxNcYbOd2O7xXS2nnKMEMABFQA= github.com/bugsnag/panicwrap v1.2.0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= +github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= -github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= -github.com/cockroachdb/cockroach-go v0.0.0-20181001143604-e0a95dfd547c/go.mod h1:XGLbWH/ujMcbPbhZq52Nv6UrCghb1yGn//133kEsvDk= -github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= -github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= -github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= github.com/containerd/cgroups v1.0.3 h1:ADZftAkglvCiD44c77s5YmMqaP2pzVCFZvBmAlBdAP4= github.com/containerd/cgroups v1.0.3/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8= github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= -github.com/containerd/containerd v1.2.7/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.4.9/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.5.13 h1:XqvKw9i4P7/mFrC3TSM7yV5cwFZ9avXe6M3YANKnzEE= -github.com/containerd/containerd v1.5.13/go.mod h1:3AlCrzKROjIuP3JALsY14n8YtntaUDBu7vek+rPN5Vc= -github.com/containerd/continuity v0.1.0 h1:UFRRY5JemiAhPZrr/uE0n8fMTLcZsUvySPr1+D7pgr8= +github.com/containerd/containerd v1.5.18 h1:doHr6cNxfOLTotWmZs6aZF6LrfJFcjmYFcWlRmQgYPM= +github.com/containerd/containerd v1.5.18/go.mod h1:7IN9MtIzTZH4WPEmD1gNH8bbTQXVX68yd3ZXxSHYCis= github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= +github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= +github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= github.com/containerd/ttrpc v1.1.0 h1:GbtyLRxb0gOLR0TYQWt3O6B0NvT8tMdorEHqIQo/lWI= @@ -176,7 +136,6 @@ github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcD github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= @@ -185,39 +144,23 @@ github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= -github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/cznic/b v0.0.0-20180115125044-35e9bbe41f07/go.mod h1:URriBxXwVq5ijiJ12C7iIZqlA69nTlI+LgI6/pwftG8= -github.com/cznic/fileutil v0.0.0-20180108211300-6a051e75936f/go.mod h1:8S58EK26zhXSxzv7NQFpnliaOQsmDUxvoQO3rt154Vg= -github.com/cznic/golex v0.0.0-20170803123110-4ab7c5e190e4/go.mod h1:+bmmJDNmKlhWNG+gwWCkaBoTy39Fs+bzRxVBzoTQbIc= -github.com/cznic/internal v0.0.0-20180608152220-f44710a21d00/go.mod h1:olo7eAdKwJdXxb55TKGLiJ6xt1H0/tiiRCWKVLmtjY4= -github.com/cznic/lldb v1.1.0/go.mod h1:FIZVUmYUVhPwRiPzL8nD/mpFcJ/G7SSXjjXYG4uRI3A= -github.com/cznic/mathutil v0.0.0-20180504122225-ca4c9f2c1369/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM= -github.com/cznic/ql v1.2.0/go.mod h1:FbpzhyZrqr0PVlK6ury+PoW3T0ODUV22OeWIxcaOrSE= -github.com/cznic/sortutil v0.0.0-20150617083342-4c7342852e65/go.mod h1:q2w6Bg5jeox1B+QkJ6Wp/+Vn0G/bo3f1uY7Fn3vivIQ= -github.com/cznic/strutil v0.0.0-20171016134553-529a34b1c186/go.mod h1:AHHPPPXTw0h6pVabbcbyGRK1DckRn7r/STdZEeIDzZc= -github.com/cznic/zappy v0.0.0-20160723133515-2533cb5b45cc/go.mod h1:Y1SNZ4dRUOKXshKUbwUapqNncRrho4mkjQebgEHZLj8= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE= -github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM= github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/dhui/dktest v0.3.0/go.mod h1:cyzIUfGsBEbZ6BT7tnXqAShHSXCZhSNmFl70sZ7c1yc= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/docker/cli v20.10.12+incompatible h1:lZlz0uzG+GH+c0plStMUdF/qk3ppmgnswpR5EbqzVGA= github.com/docker/cli v20.10.12+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v0.0.0-20191216044856-a8371794149d h1:jC8tT/S0OGx2cswpeUTn4gOIea8P08lD3VFQT0cOZ50= github.com/docker/distribution v0.0.0-20191216044856-a8371794149d/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= -github.com/docker/docker v0.7.3-0.20190103212154-2b7e084dc98b/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v0.7.3-0.20190817195342-4760db040282/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v1.4.2-0.20200203170920-46ec8731fbce h1:KXS1Jg+ddGcWA8e1N7cupxaHHZhit5rB9tfDU+mfjyY= -github.com/docker/docker v1.4.2-0.20200203170920-46ec8731fbce/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.24+incompatible h1:Ugvxm7a8+Gz6vqQYQQ2W7GYq5EUPaAiuPgIfVyI3dYE= +github.com/docker/docker v20.10.24+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.6.3 h1:zI2p9+1NQYdnG6sMU26EX4aVGlqbInSQxQXLvzJ4RPQ= github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= @@ -225,64 +168,48 @@ github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5Xh github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= -github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4= github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= -github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= -github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= -github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= 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 h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk= -github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= +github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch/v5 v5.2.0 h1:8ozOH5xxoMYDt5/u+yMTsVXydVCbTORFnOOoq2lumco= github.com/evanphx/json-patch/v5 v5.2.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= -github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= -github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= +github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= +github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= -github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= +github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= -github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= 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/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= -github.com/fsouza/fake-gcs-server v1.7.0/go.mod h1:5XIRs4YvwNbNoz+1JF8j6KLAyDh7RHGAyAK3EP2EsNk= -github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= github.com/garyburd/redigo v1.6.0 h1:0VruCpn7yAIIu7pWVClQC8wxCJEcG3nyzpMSHKi1PQc= github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= -github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= -github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= -github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= @@ -296,48 +223,46 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v1.2.0 h1:QK40JKJyMdUDz+h+xvCsru/bJhvG0UxvePV0ufL/AcE= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/zapr v1.2.0 h1:n4JnPI1T3Qq1SFEi/F8rwLrZERp2bso19PJZDB9dayk= -github.com/go-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM= -github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= +github.com/go-openapi/jsonreference v0.20.1 h1:FBLnyygC4/IZZr893oiomc9XaghoveYTrLC1F86HID8= +github.com/go-openapi/jsonreference v0.20.1/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng= -github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/gocql/gocql v0.0.0-20190301043612-f6df8288f9b4/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/uuid v3.3.0+incompatible h1:8K4tyRfvU1CYPgJsveYFQMhpFd/wXNM7iK6rR7UHz84= github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-migrate/migrate/v4 v4.6.2 h1:LDDOHo/q1W5UDj6PbkxdCv7lv9yunyZHXvxuwDkGo3k= -github.com/golang-migrate/migrate/v4 v4.6.2/go.mod h1:JYi6reN3+Z734VZ0akNuyOJNcrg45ZL7LDBMW3WGJL0= +github.com/golang-migrate/migrate/v4 v4.16.1 h1:O+0C55RbMN66pWm5MjO6mw0px6usGpY0+bkSGW9zCo0= +github.com/golang-migrate/migrate/v4 v4.16.1/go.mod h1:qXiwa/3Zeqaltm1MxOCZDYysW/F6folYiBgBG03l9hc= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -369,22 +294,13 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= -github.com/google/cel-go v0.10.1/go.mod h1:U7ayypeSkw23szu4GaQTPJGx66c20mx8JklMSxrmI1w= -github.com/google/cel-go v0.12.4 h1:YINKfuHZ8n72tPOqSPZBwGiDpew2CJS48mdM5W8LZQU= -github.com/google/cel-go v0.12.4/go.mod h1:Av7CU6r6X3YmcHR9GXqVDaEJYfEtSxl6wvIjUQTriCw= -github.com/google/cel-spec v0.6.0/go.mod h1:Nwjgxy5CbjlPrtCWjeDjUyKMl8w41YBYGjsyDdqk0xA= +github.com/google/cel-go v0.12.6 h1:kjeKudqV0OygrAqA9fX6J55S8gj+Jre2tckIm5RoG4M= +github.com/google/cel-go v0.12.6/go.mod h1:Jk7ljRzLBhkmiAwBoUxB1sZSCVBAzkqPF25olK/iRDw= github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -398,16 +314,14 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= -github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -415,55 +329,46 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= -github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= -github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/handlers v1.4.2 h1:0QniY0USkHQ1RGCLfKxeNHK9bkDHGRYGNDFBCS+YARg= github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= -github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0 h1:BZHcxBETFHIdVyhyEfOvn/RdU/QGdLI4y34qQGjGWO0= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.0/go.mod h1:hgWBS7lorOAVIJEQMi4ZsPv9hVvWI6+ch50m39Pf2Ks= github.com/grpc-ecosystem/grpc-health-probe v0.4.11 h1:eKVQDIIJhRkfJHjQzTmu+RangfB8/MyrthCCnsvne/s= github.com/grpc-ecosystem/grpc-health-probe v0.4.11/go.mod h1:Ew6du240dK067iM38yVbni1pLpWUFnuyc0PefrB81Uc= github.com/h2non/filetype v1.1.1 h1:xvOwnXKAckvtLWsN398qS9QhlxlnVXBjXBydK2/UFB4= github.com/h2non/filetype v1.1.1/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY= github.com/h2non/go-is-svg v0.0.0-20160927212452-35e8c4b0612c h1:fEE5/5VNnYUoBOj2I9TP8Jc+a7lge3QWn9DKE7NCwfc= github.com/h2non/go-is-svg v0.0.0-20160927212452-35e8c4b0612c/go.mod h1:ObS/W+h8RYb1Y7fYivughjxojTmIu5iAIjSrSLCLeqE= -github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= @@ -480,40 +385,33 @@ github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/J github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ= -github.com/jackc/pgx v3.2.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I= +github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= +github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/joefitzgerald/rainbow-reporter v0.1.0 h1:AuMG652zjdzI0YCCnXAqATtRBpGXMcAnrajcaTrSeuo= github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= github.com/joelanford/ignore v0.0.0-20210607151042-0d25dc18b62d h1:A2/B900ip/Z20TzkLeGRNy1s6J2HmH9AmGt+dHyqb4I= github.com/joelanford/ignore v0.0.0-20210607151042-0d25dc18b62d/go.mod h1:7HQupe4vyNxMKXmM5DFuwXHsqwMyglcYmZBtlDPIcZ8= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA= github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= @@ -521,46 +419,36 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.12.3 h1:G5AfA94pHPysR56qqrkO2pxEexdDzrpFJ6yt/VqWxVU= -github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= 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= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kshvakov/clickhouse v1.3.5/go.mod h1:DMzX7FxRymoNkVgizH0DWAL8Cur7wHLgx3MUnGwJqpE= -github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= -github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= +github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= -github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= -github.com/mattn/go-sqlite3 v1.14.10 h1:MLn+5bFRlWMGoSRmJour3CL1w/qL96mvipqpwQW/Sfk= -github.com/mattn/go-sqlite3 v1.14.10/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= +github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2 h1:g+4J5sZg6osfvEfkRZxJ1em0VT95/UOZgi/l7zi1/oE= github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= @@ -583,8 +471,8 @@ github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8 github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= github.com/moby/sys/mountinfo v0.4.1 h1:1O+1cHA1aujwEwwVMa2Xm2l+gIpUHyd3+D+d7LZh1kM= github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= -github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc= -github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -592,59 +480,38 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= -github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c h1:nXxl5PrvVm2L/wCy8dQu6DMTwH4oIuGN8GJDAlqDdVE= -github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8/go.mod h1:86wM1zFnC6/uDBfZGNwB65O+pR2OFi5q/YQaEUid1qA= github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.1.3 h1:e/3Cwtogj0HA+25nMP1jCMDIf8RtRYbGwGGuBIFztkc= -github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q= +github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 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= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= -github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= +github.com/onsi/gomega v1.27.7 h1:fVih9JD6ogIiHUN6ePK7HJidyEDpWGVB5mzM7cWNXoU= +github.com/onsi/gomega v1.27.7/go.mod h1:1p8OOlwo2iUUDsHnOrjE5UKYJ+e3W8eQ3qSlRahPmr4= github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= 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/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= -github.com/operator-framework/api v0.15.0 h1:4f9i0drtqHj7ykLoHxv92GR43S7MmQHhmFQkfm5YaGI= -github.com/operator-framework/api v0.15.0/go.mod h1:scnY9xqSeCsOdtJtNoHIXd7OtHZ14gj1hkDA4+DlgLY= +github.com/operator-framework/api v0.17.4-0.20230223191600-0131a6301e42 h1:d/Pnr19TnmIq3zQ6ebewC+5jt5zqYbRkvYd37YZENQY= +github.com/operator-framework/api v0.17.4-0.20230223191600-0131a6301e42/go.mod h1:l/cuwtPxkVUY7fzYgdust2m9tlmb8I4pOvbsUufRb24= github.com/otiai10/copy v1.2.0 h1:HvG945u96iNadPoG2/Ja2+AUJeW5YuFQMixq9yirC+k= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= @@ -657,64 +524,50 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9 github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc= github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= -github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.15.1 h1:8tXpTmJbyH5lydzFPoxSIJ0J46jdh3tylbvM1xCv0LI= +github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= +github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= +github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= +github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= -github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +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/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= @@ -722,43 +575,33 @@ github.com/sclevine/spec v1.2.0 h1:1Jwdf9jSfDl9NVmt8ndHqbTZ7XCCPbh1jI3hkDBHVYA= github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.2 h1:oxx1eChJGI6Uks2ZC4W1zpLlVgqB8ner4EuQwV4Ik1Y= +github.com/sirupsen/logrus v1.9.2/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= -github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= -github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= -github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= -github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= +github.com/spf13/cobra v1.6.0 h1:42a0n6jwCot1pUmomAp4T7DeMD+20LFv4Q54pxLf2LI= +github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/spiffe/go-spiffe/v2 v2.0.0 h1:y6N7BZAxgaFZYELyrIdxSMm2e2tWpzgQewUts9h1hfM= github.com/spiffe/go-spiffe/v2 v2.0.0/go.mod h1:TEfgrEcyFhuSuvqohJt6IxENUNeHfndWCCV1EX7UaVk= github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU= @@ -766,32 +609,30 @@ github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs= github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= -github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= -github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= github.com/yvasiyarov/go-metrics v0.0.0-20150112132944-c25f46c4b940 h1:p7OofyZ509h8DmPLh8Hn+EIIZm/xYhdZHJ9GnXHdr6U= github.com/yvasiyarov/go-metrics v0.0.0-20150112132944-c25f46c4b940/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= @@ -804,85 +645,55 @@ github.com/yvasiyarov/newrelic_platform_go v0.0.0-20160601141957-9c099fbc30e9/go github.com/zeebo/errs v1.2.2/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4= github.com/zeebo/errs v1.3.0 h1:hmiaKqgYZzcVgRL1Vkc1Mn2914BbzB0IBxs+ebeutGs= github.com/zeebo/errs v1.3.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4= -gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= -go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= -go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= -go.etcd.io/etcd/client/v3 v3.5.1/go.mod h1:OnjH4M8OnAotwaB2l9bVgZzRFKru7/ZMoS46OtKyd3Q= -go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= -go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= -go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= -go.mongodb.org/mongo-driver v1.1.0/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= -go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opentelemetry.io/contrib v0.20.0 h1:ubFQUn0VCZ0gPwIoJfBJVpeBlyRMxu8Mm/huKWYd9p0= -go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0 h1:Q3C9yzW6I9jqEc8sawxzxZmY48fs9u220KXq6d5s3XU= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= -go.opentelemetry.io/otel v0.20.0 h1:eaP0Fqu7SXHwvjiqDq83zImeehOHX8doTvU9AwXON8g= -go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= -go.opentelemetry.io/otel/exporters/otlp v0.20.0 h1:PTNgq9MRmQqqJY0REVbZFvwkYOA85vbdQU/nVfxDyqg= -go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= -go.opentelemetry.io/otel/metric v0.20.0 h1:4kzhXFP+btKm4jwxpjIqjs41A7MakRFUS86bqLHTIw8= -go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= -go.opentelemetry.io/otel/oteltest v0.20.0 h1:HiITxCawalo5vQzdHfKeZurV8x7ljcqAgiWzF6Vaeaw= -go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= -go.opentelemetry.io/otel/sdk v0.20.0 h1:JsxtGXd06J8jrnya7fdI/U/MR6yXA5DtbZy+qoHQlr8= -go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= -go.opentelemetry.io/otel/sdk/export/metric v0.20.0 h1:c5VRjxCXdQlx1HjzwGdQHzZaVI82b5EbBgOu2ljD92g= -go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= -go.opentelemetry.io/otel/sdk/metric v0.20.0 h1:7ao1wpzHRVKf0OQ7GIxiQJA6X7DLX9o14gmVon7mMK8= -go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= -go.opentelemetry.io/otel/trace v0.20.0 h1:1DL6EXUdcg95gukhuRRvLDO/4X5THh/5dIV52lqtnbw= -go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= -go.opentelemetry.io/proto/otlp v0.7.0 h1:rwOQPCuKAKmwGKq2aVNnYIibI6wnV7EvzgfTCzcdGg8= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.35.1 h1:sxoY9kG1s1WpSYNyzm24rlwH4lnRYFXUVVBmKMBfRgw= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.35.1/go.mod h1:9NiG9I2aHTKkcxqCILhjtyNA1QEiCjdBACv4IvrFQ+c= +go.opentelemetry.io/otel v1.10.0 h1:Y7DTJMR6zs1xkS/upamJYk0SxxN4C9AqRd77jmZnyY4= +go.opentelemetry.io/otel v1.10.0/go.mod h1:NbvWjCthWHKBEUMpf0/v8ZRZlni86PpGFEMA9pnQSnQ= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.10.0 h1:TaB+1rQhddO1sF71MpZOZAuSPW1klK2M8XxfrBMfK7Y= +go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.10.0/go.mod h1:78XhIg8Ht9vR4tbLNUhXsiOnE2HOuSeKAiAcoVQEpOY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.10.0 h1:pDDYmo0QadUPal5fwXoY1pmMpFcdyhXOmL5drCrI3vU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.10.0/go.mod h1:Krqnjl22jUJ0HgMzw5eveuCvFDXY4nSYb4F8t5gdrag= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.10.0 h1:KtiUEhQmj/Pa874bVYKGNVdq8NPKiacPbaRRtgXi+t4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.10.0/go.mod h1:OfUCyyIiDvNXHWpcWgbF+MWvqPZiNa3YDEnivcnYsV0= +go.opentelemetry.io/otel/metric v0.31.0 h1:6SiklT+gfWAwWUR0meEMxQBtihpiEs4c+vL9spDTqUs= +go.opentelemetry.io/otel/metric v0.31.0/go.mod h1:ohmwj9KTSIeBnDBm/ZwH2PSZxZzoOaG2xZeekTRzL5A= +go.opentelemetry.io/otel/sdk v1.10.0 h1:jZ6K7sVn04kk/3DNUdJ4mqRlGDiXAVuIG+MMENpTNdY= +go.opentelemetry.io/otel/sdk v1.10.0/go.mod h1:vO06iKzD5baltJz1zarxMCNHFpUlUiOy4s65ECtn6kE= +go.opentelemetry.io/otel/trace v1.10.0 h1:npQMbR8o7mum8uF95yFbOEJffhs1sbCOfDh8zAJiH5E= +go.opentelemetry.io/otel/trace v1.10.0/go.mod h1:Sij3YYczqAdz+EhmGhE6TpTxUO5/F/AzrK+kxfGqySM= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o= +go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw= +go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI= +go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220408190544-5352b0902921 h1:iU7T1X1J6yxDr0rda54sWGkHgOp5XJrqm79gcNlC2VM= -golang.org/x/crypto v0.0.0-20220408190544-5352b0902921/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -905,8 +716,6 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -915,26 +724,20 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= +golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181108082009-03003ca0c849/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190424112056-4829fb13d2c6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= @@ -955,46 +758,25 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU= -golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.5.0 h1:HuArIo48skDwlrvM3sEdHXElYslAMsf3KwRkkW4MC4s= +golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1006,8 +788,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= +golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/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= @@ -1015,13 +797,10 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190102155601-82a175fd1598/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190426135247-a129542de9ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1031,16 +810,12 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1053,47 +828,27 @@ golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI= -golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= +golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1101,19 +856,14 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220609170525-579cf78fd858 h1:Dpdu/EMxGMFgq0CeYMh4fazTD2vtlZRYE7wyynxJb9U= -golang.org/x/time v0.0.0-20220609170525-579cf78fd858/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1123,7 +873,6 @@ golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190425222832-ad9eeb80039a/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= @@ -1135,7 +884,6 @@ golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDq golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1156,7 +904,6 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -1164,28 +911,16 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= -golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= +golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gomodules.xyz/jsonpatch/v2 v2.2.0 h1:4pT439QV83L+G9FkcCriY6EkpcK6r6bK+A5FBUMI7qY= +gomodules.xyz/jsonpatch/v2 v2.3.0 h1:8NFhfS6gzxNqjLIYnZxg319wZ5Qjnx4m/CcX+Klzazc= google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= -google.golang.org/api v0.3.2/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -1202,14 +937,7 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= @@ -1220,7 +948,6 @@ google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1240,7 +967,6 @@ google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= @@ -1251,25 +977,11 @@ google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200806141610-86f49bd18e98/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201102152239-715cce707fb0/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 h1:hrbNEivu7Zn1pxvHk6MBrq9iE22woVILTHqexqBxe6I= -google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w= +google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1283,19 +995,13 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.47.0 h1:9n77onPX5F3qfFCqjy9dhn8PbNQsIKeVU04J9G7umt8= -google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U= +google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= google.golang.org/grpc/cmd/protoc-gen-go-grpc v0.0.0-20200709232328-d8193ee9cc3e h1:4BwkYybqoRhPKm97iNO3ACkxj26G0hC18CaO9QXOxto= google.golang.org/grpc/cmd/protoc-gen-go-grpc v0.0.0-20200709232328-d8193ee9cc3e/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/grpc/examples v0.0.0-20201130180447-c456688b1860/go.mod h1:Ly7ZA/ARzg8fnPU9TyZIxoz33sEUuWX7txiqs8lPTgE= @@ -1312,8 +1018,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1327,14 +1033,10 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.4.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= @@ -1343,21 +1045,17 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= -gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= -gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= +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.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 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= @@ -1365,58 +1063,45 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.24.0 h1:J0hann2hfxWr1hinZIDefw7Q96wmCBx6SSB8IY0MdDg= -k8s.io/api v0.24.0/go.mod h1:5Jl90IUrJHUJYEMANRURMiVvJ0g7Ax7r3R1bqO8zx8I= -k8s.io/apiextensions-apiserver v0.24.0 h1:JfgFqbA8gKJ/uDT++feAqk9jBIwNnL9YGdQvaI9DLtY= -k8s.io/apiextensions-apiserver v0.24.0/go.mod h1:iuVe4aEpe6827lvO6yWQVxiPSpPoSKVjkq+MIdg84cM= +k8s.io/api v0.27.2 h1:+H17AJpUMvl+clT+BPnKf0E3ksMAzoBBg7CntpSuADo= +k8s.io/api v0.27.2/go.mod h1:ENmbocXfBT2ADujUXcBhHV55RIT31IIEvkntP6vZKS4= +k8s.io/apiextensions-apiserver v0.27.2 h1:iwhyoeS4xj9Y7v8YExhUwbVuBhMr3Q4bd/laClBV6Bo= +k8s.io/apiextensions-apiserver v0.27.2/go.mod h1:Oz9UdvGguL3ULgRdY9QMUzL2RZImotgxvGjdWRq6ZXQ= k8s.io/apimachinery v0.20.2/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= -k8s.io/apimachinery v0.24.0 h1:ydFCyC/DjCvFCHK5OPMKBlxayQytB8pxy8YQInd5UyQ= -k8s.io/apimachinery v0.24.0/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= -k8s.io/apiserver v0.24.0 h1:GR7kGsjOMfilRvlG3Stxv/3uz/ryvJ/aZXc5pqdsNV0= -k8s.io/apiserver v0.24.0/go.mod h1:WFx2yiOMawnogNToVvUYT9nn1jaIkMKj41ZYCVycsBA= -k8s.io/cli-runtime v0.24.0/go.mod h1:9XxoZDsEkRFUThnwqNviqzljtT/LdHtNWvcNFrAXl0A= -k8s.io/client-go v0.24.0 h1:lbE4aB1gTHvYFSwm6eD3OF14NhFDKCejlnsGYlSJe5U= -k8s.io/client-go v0.24.0/go.mod h1:VFPQET+cAFpYxh6Bq6f4xyMY80G6jKKktU6G0m00VDw= -k8s.io/code-generator v0.24.0/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w= -k8s.io/component-base v0.24.0 h1:h5jieHZQoHrY/lHG+HyrSbJeyfuitheBvqvKwKHVC0g= -k8s.io/component-base v0.24.0/go.mod h1:Dgazgon0i7KYUsS8krG8muGiMVtUZxG037l1MKyXgrA= -k8s.io/component-helpers v0.24.0/go.mod h1:Q2SlLm4h6g6lPTC9GMMfzdywfLSvJT2f1hOnnjaWD8c= +k8s.io/apimachinery v0.27.2 h1:vBjGaKKieaIreI+oQwELalVG4d8f3YAMNpWLzDXkxeg= +k8s.io/apimachinery v0.27.2/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E= +k8s.io/apiserver v0.27.2 h1:p+tjwrcQEZDrEorCZV2/qE8osGTINPuS5ZNqWAvKm5E= +k8s.io/apiserver v0.27.2/go.mod h1:EsOf39d75rMivgvvwjJ3OW/u9n1/BmUMK5otEOJrb1Y= +k8s.io/client-go v0.27.2 h1:vDLSeuYvCHKeoQRhCXjxXO45nHVv2Ip4Fe0MfioMrhE= +k8s.io/client-go v0.27.2/go.mod h1:tY0gVmUsHrAmjzHX9zs7eCjxcBsf8IiNe7KQ52biTcQ= +k8s.io/component-base v0.27.2 h1:neju+7s/r5O4x4/txeUONNTS9r1HsPbyoPBAtHsDCpo= +k8s.io/component-base v0.27.2/go.mod h1:5UPk7EjfgrfgRIuDBFtsEFAe4DAvP3U+M8RTzoSJkpo= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.60.1 h1:VW25q3bZx9uE3vvdL6M8ezOX79vA2Aq1nEWLqNQclHc= -k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw= +k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= -k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= -k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42 h1:Gii5eqf+GmIEwGNKQYQClCayuJCe2/4fZUvF7VG99sU= -k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk= -k8s.io/kubectl v0.24.0 h1:nA+WtMLVdXUs4wLogGd1mPTAesnLdBpCVgCmz3I7dXo= -k8s.io/kubectl v0.24.0/go.mod h1:pdXkmCyHiRTqjYfyUJiXtbVNURhv0/Q1TyRhy2d5ic0= -k8s.io/metrics v0.24.0/go.mod h1:jrLlFGdKl3X+szubOXPG0Lf2aVxuV3QJcbsgVRAM6fI= -k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 h1:HNSDgDCrr/6Ly3WEGKZftiE7IY19Vz2GdbOCyI4qqhc= -k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f h1:2kWPakN3i/k81b0gvD5C5FJ2kxm1WrQFanWchyKuqGg= +k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f/go.mod h1:byini6yhqGC14c3ebc/QwanvYwhuMWF6yz2F8uwW8eg= +k8s.io/kubectl v0.27.1 h1:9T5c5KdpburYiW8XKQSH0Uly1kMNE90aGSnbYUZNdcA= +k8s.io/kubectl v0.27.1/go.mod h1:QsAkSmrRsKTPlAFzF8kODGDl4p35BIwQnc9XFhkcsy8= +k8s.io/utils v0.0.0-20230209194617-a36077c30491 h1:r0BAOLElQnnFhE/ApUsg3iHdVYYPBjNSSOMowRZxxsY= +k8s.io/utils v0.0.0-20230209194617-a36077c30491/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.30 h1:dUk62HQ3ZFhD48Qr8MIXCiKA8wInBQCtuE4QGfFW7yA= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.30/go.mod h1:fEO7lRTdivWO2qYVCVG7dEADOMo/MLDCVr8So2g88Uw= -sigs.k8s.io/controller-runtime v0.12.1 h1:4BJY01xe9zKQti8oRjj/NeHKRXthf1YkYJAgLONFFoI= -sigs.k8s.io/controller-runtime v0.12.1/go.mod h1:BKhxlA4l7FPK4AQcsuL4X6vZeWnKDXez/vp1Y8dxTU0= -sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 h1:kDi4JBNAsJWfz1aEXhO8Jg87JJaPNLh5tIzYHgStQ9Y= -sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2 h1:trsWhjU5jZrx6UvFu4WzQDrN7Pga4a7Qg+zcfcj64PA= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2/go.mod h1:+qG7ISXqCDVVcyO8hLn12AKVYYUjM7ftlqsqmrhMZE0= +sigs.k8s.io/controller-runtime v0.15.0 h1:ML+5Adt3qZnMSYxZ7gAverBLNPSMQEibtzAgp0UPojU= +sigs.k8s.io/controller-runtime v0.15.0/go.mod h1:7ngYvp1MLT+9GeZ+6lH3LOlcHkp/+tzA/fmHa4iq9kk= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/kind v0.11.1 h1:pVzOkhUwMBrCB0Q/WllQDO3v14Y+o2V0tFgjTqIUjwA= sigs.k8s.io/kind v0.11.1/go.mod h1:fRpgVhtqAWrtLB9ED7zQahUimpUXuG/iHT88xYqEGIA= -sigs.k8s.io/kustomize/api v0.11.4/go.mod h1:k+8RsqYbgpkIrJ4p9jcdPqe8DprLxFUUO0yNOq8C+xI= -sigs.k8s.io/kustomize/cmd/config v0.10.6/go.mod h1:/S4A4nUANUa4bZJ/Edt7ZQTyKOY9WCER0uBS1SW2Rco= -sigs.k8s.io/kustomize/kustomize/v4 v4.5.4/go.mod h1:Zo/Xc5FKD6sHl0lilbrieeGeZHVYCA4BzxeAaLI05Bg= -sigs.k8s.io/kustomize/kyaml v0.13.6/go.mod h1:yHP031rn1QX1lr/Xd934Ri/xdVNG8BE2ECa78Ht/kEg= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.2.1 h1:bKCqE9GvQ5tiVHn5rfn1r+yao3aLQEaLzkkmAkf+A6Y= -sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= diff --git a/staging/operator-registry/pkg/api/api_to_model.go b/staging/operator-registry/pkg/api/api_to_model.go index d203f40b4a..06645f7c6b 100644 --- a/staging/operator-registry/pkg/api/api_to_model.go +++ b/staging/operator-registry/pkg/api/api_to_model.go @@ -5,6 +5,8 @@ import ( "fmt" "sort" + "github.com/operator-framework/api/pkg/operators/v1alpha1" + "github.com/operator-framework/operator-registry/alpha/model" "github.com/operator-framework/operator-registry/alpha/property" ) @@ -106,8 +108,17 @@ func convertAPIBundleToModelProperties(b *Bundle) ([]property.Property, error) { out = append(out, property.MustBuildGVKRequired(p.Group, p.Version, p.Kind)) } - for _, obj := range b.Object { - out = append(out, property.MustBuildBundleObjectData([]byte(obj))) + // If there is a bundle image reference and a valid CSV, create an + // olm.csv.metadata property. Otherwise, create a bundle object property for + // each object in the bundle. + var csv v1alpha1.ClusterServiceVersion + csvErr := json.Unmarshal([]byte(b.CsvJson), &csv) + if csvErr == nil && b.BundlePath != "" { + out = append(out, property.MustBuildCSVMetadata(csv)) + } else { + for _, obj := range b.Object { + out = append(out, property.MustBuildBundleObjectData([]byte(obj))) + } } sort.Slice(out, func(i, j int) bool { diff --git a/staging/operator-registry/pkg/api/conversion_test.go b/staging/operator-registry/pkg/api/conversion_test.go index 0a332b91a4..55dc94904e 100644 --- a/staging/operator-registry/pkg/api/conversion_test.go +++ b/staging/operator-registry/pkg/api/conversion_test.go @@ -1,8 +1,10 @@ package api import ( + "encoding/json" "testing" + "github.com/operator-framework/api/pkg/operators/v1alpha1" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -12,7 +14,7 @@ import ( func TestConvertAPIBundleToModelBundle(t *testing.T) { apiBundle := testAPIBundle() - expected := testModelBundle() + expected := testModelBundle(t) actual, err := ConvertAPIBundleToModelBundle(&apiBundle) require.NoError(t, err) @@ -20,7 +22,7 @@ func TestConvertAPIBundleToModelBundle(t *testing.T) { } func TestConvertModelBundleToAPIBundle(t *testing.T) { - modelBundle := testModelBundle() + modelBundle := testModelBundle(t) modelBundle.Package = &model.Package{Name: "etcd"} modelBundle.Channel = &model.Channel{Name: "singlenamespace-alpha"} expected := testAPIBundle() @@ -41,7 +43,12 @@ const ( crdrestores = `{"apiVersion":"apiextensions.k8s.io/v1beta1","kind":"CustomResourceDefinition","metadata":{"name":"etcdrestores.etcd.database.coreos.com"},"spec":{"group":"etcd.database.coreos.com","names":{"kind":"EtcdRestore","listKind":"EtcdRestoreList","plural":"etcdrestores","singular":"etcdrestore"},"scope":"Namespaced","version":"v1beta2"}}` ) -func testModelBundle() model.Bundle { +func testModelBundle(t *testing.T) model.Bundle { + t.Helper() + var csv v1alpha1.ClusterServiceVersion + if err := json.Unmarshal([]byte(csvJson), &csv); err != nil { + t.Fatalf("failed to unmarshal csv json: %v", err) + } b := model.Bundle{ Name: "etcdoperator.v0.9.4", Image: "quay.io/operatorhubio/etcd:v0.9.4", @@ -52,10 +59,7 @@ func testModelBundle() model.Bundle { property.MustBuildPackageRequired("test", ">=1.2.3 <2.0.0-0"), property.MustBuildGVKRequired("testapi.coreos.com", "v1", "Testapi"), property.MustBuildGVK("etcd.database.coreos.com", "v1beta2", "EtcdBackup"), - property.MustBuildBundleObjectData([]byte(crdbackups)), - property.MustBuildBundleObjectData([]byte(crdclusters)), - property.MustBuildBundleObjectData([]byte(csvJson)), - property.MustBuildBundleObjectData([]byte(crdrestores)), + property.MustBuildCSVMetadata(csv), }, CsvJSON: csvJson, Objects: []string{ diff --git a/staging/operator-registry/pkg/api/model_to_api.go b/staging/operator-registry/pkg/api/model_to_api.go index 26f8b745c3..1abe1cf6be 100644 --- a/staging/operator-registry/pkg/api/model_to_api.go +++ b/staging/operator-registry/pkg/api/model_to_api.go @@ -1,9 +1,15 @@ package api import ( + "encoding/base64" "encoding/json" "fmt" + "github.com/operator-framework/api/pkg/lib/version" + "github.com/operator-framework/api/pkg/operators" + "github.com/operator-framework/api/pkg/operators/v1alpha1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/operator-framework/operator-registry/alpha/model" "github.com/operator-framework/operator-registry/alpha/property" ) @@ -14,6 +20,38 @@ func ConvertModelBundleToAPIBundle(b model.Bundle) (*Bundle, error) { return nil, fmt.Errorf("parse properties: %v", err) } + csvJson := b.CsvJSON + if csvJson == "" && len(props.CSVMetadatas) == 1 { + var icons []v1alpha1.Icon + if b.Package.Icon != nil { + icons = []v1alpha1.Icon{{ + Data: base64.StdEncoding.EncodeToString(b.Package.Icon.Data), + MediaType: b.Package.Icon.MediaType, + }} + } + csv := csvMetadataToCsv(props.CSVMetadatas[0]) + csv.Name = b.Name + csv.Spec.Icon = icons + csv.Spec.InstallStrategy = v1alpha1.NamedInstallStrategy{ + // This stub is required to avoid a panic in OLM's package server that results in + // attemptint to write to a nil map. + StrategyName: "deployment", + } + csv.Spec.Version = version.OperatorVersion{b.Version} + csv.Spec.RelatedImages = convertModelRelatedImagesToCSVRelatedImages(b.RelatedImages) + if csv.Spec.Description == "" { + csv.Spec.Description = b.Package.Description + } + csvData, err := json.Marshal(csv) + if err != nil { + return nil, err + } + csvJson = string(csvData) + if len(b.Objects) == 0 { + b.Objects = []string{csvJson} + } + } + apiDeps, err := convertModelPropertiesToAPIDependencies(b.Properties) if err != nil { return nil, fmt.Errorf("convert model properties to api dependencies: %v", err) @@ -31,7 +69,7 @@ func ConvertModelBundleToAPIBundle(b model.Bundle) (*Bundle, error) { Properties: convertModelPropertiesToAPIProperties(b.Properties), Replaces: b.Replaces, Skips: b.Skips, - CsvJson: b.CsvJSON, + CsvJson: csvJson, Object: b.Objects, }, nil } @@ -46,9 +84,40 @@ func parseProperties(in []property.Property) (*property.Properties, error) { return nil, fmt.Errorf("expected exactly 1 property of type %q, found %d", property.TypePackage, len(props.Packages)) } + if len(props.CSVMetadatas) > 1 { + return nil, fmt.Errorf("expected at most 1 property of type %q, found %d", property.TypeCSVMetadata, len(props.CSVMetadatas)) + } + return props, nil } +func csvMetadataToCsv(m property.CSVMetadata) v1alpha1.ClusterServiceVersion { + return v1alpha1.ClusterServiceVersion{ + TypeMeta: metav1.TypeMeta{ + Kind: operators.ClusterServiceVersionKind, + APIVersion: v1alpha1.ClusterServiceVersionAPIVersion, + }, + ObjectMeta: metav1.ObjectMeta{ + Annotations: m.Annotations, + Labels: m.Labels, + }, + Spec: v1alpha1.ClusterServiceVersionSpec{ + APIServiceDefinitions: m.APIServiceDefinitions, + CustomResourceDefinitions: m.CustomResourceDefinitions, + Description: m.Description, + DisplayName: m.DisplayName, + InstallModes: m.InstallModes, + Keywords: m.Keywords, + Links: m.Links, + Maintainers: m.Maintainers, + Maturity: m.Maturity, + MinKubeVersion: m.MinKubeVersion, + NativeAPIs: m.NativeAPIs, + Provider: m.Provider, + }, + } +} + func gvksProvidedtoAPIGVKs(in []property.GVK) []*GroupVersionKind { var out []*GroupVersionKind for _, gvk := range in { @@ -82,7 +151,7 @@ func convertModelPropertiesToAPIProperties(props []property.Property) []*Propert // in its `Data` field, this CSV annotation projection would cause the size of the on-cluster // CSV to at least double, which is untenable since CSVs already have known issues running up // against etcd size constraints. - if prop.Type == property.TypeBundleObject { + if prop.Type == property.TypeBundleObject || prop.Type == property.TypeCSVMetadata { continue } @@ -117,3 +186,14 @@ func convertModelPropertiesToAPIDependencies(props []property.Property) ([]*Depe } return out, nil } + +func convertModelRelatedImagesToCSVRelatedImages(in []model.RelatedImage) []v1alpha1.RelatedImage { + var out []v1alpha1.RelatedImage + for _, ri := range in { + out = append(out, v1alpha1.RelatedImage{ + Name: ri.Name, + Image: ri.Image, + }) + } + return out +} diff --git a/staging/operator-registry/pkg/cache/cache.go b/staging/operator-registry/pkg/cache/cache.go index 7df08d6f50..faf65d9934 100644 --- a/staging/operator-registry/pkg/cache/cache.go +++ b/staging/operator-registry/pkg/cache/cache.go @@ -18,13 +18,13 @@ type Cache interface { registry.GRPCQuery CheckIntegrity(fbc fs.FS) error - Build(fbc fs.FS) error + Build(ctx context.Context, fbc fs.FS) error Load() error } -func LoadOrRebuild(c Cache, fbc fs.FS) error { +func LoadOrRebuild(ctx context.Context, c Cache, fbc fs.FS) error { if err := c.CheckIntegrity(fbc); err != nil { - if err := c.Build(fbc); err != nil { + if err := c.Build(ctx, fbc); err != nil { return err } } diff --git a/staging/operator-registry/pkg/cache/cache_test.go b/staging/operator-registry/pkg/cache/cache_test.go index a7140d6111..07a2edf20c 100644 --- a/staging/operator-registry/pkg/cache/cache_test.go +++ b/staging/operator-registry/pkg/cache/cache_test.go @@ -205,7 +205,7 @@ func genTestCaches(t *testing.T, fbcFS fs.FS) []Cache { } for _, c := range caches { - err := c.Build(fbcFS) + err := c.Build(context.Background(), fbcFS) require.NoError(t, err) err = c.Load() require.NoError(t, err) diff --git a/staging/operator-registry/pkg/cache/json.go b/staging/operator-registry/pkg/cache/json.go index 47a54952ba..0899a6f4f8 100644 --- a/staging/operator-registry/pkg/cache/json.go +++ b/staging/operator-registry/pkg/cache/json.go @@ -14,6 +14,7 @@ import ( "github.com/operator-framework/operator-registry/alpha/declcfg" "github.com/operator-framework/operator-registry/pkg/api" "github.com/operator-framework/operator-registry/pkg/registry" + "k8s.io/apimachinery/pkg/util/sets" ) var _ Cache = &JSON{} @@ -58,8 +59,13 @@ func (q *JSON) ListBundles(ctx context.Context) ([]*api.Bundle, error) { func (q *JSON) SendBundles(_ context.Context, s registry.BundleSender) error { for _, pkg := range q.packageIndex { - for _, ch := range pkg.Channels { - for _, b := range ch.Bundles { + channels := sets.KeySet(pkg.Channels) + for _, chName := range sets.List(channels) { + ch := pkg.Channels[chName] + + bundles := sets.KeySet(ch.Bundles) + for _, bName := range sets.List(bundles) { + b := ch.Bundles[bName] apiBundle, err := q.loadAPIBundle(apiBundleKey{pkg.Name, ch.Name, b.Name}) if err != nil { return fmt.Errorf("convert bundle %q: %v", b.Name, err) @@ -172,7 +178,7 @@ func (q *JSON) computeDigest(fbcFsys fs.FS) (string, error) { return fmt.Sprintf("%x", computedHasher.Sum(nil)), nil } -func (q *JSON) Build(fbcFsys fs.FS) error { +func (q *JSON) Build(ctx context.Context, fbcFsys fs.FS) error { // ensure that generated cache is available to all future users oldUmask := umask(000) defer umask(oldUmask) @@ -184,7 +190,7 @@ func (q *JSON) Build(fbcFsys fs.FS) error { return fmt.Errorf("ensure clean base directory: %v", err) } - fbc, err := declcfg.LoadFS(fbcFsys) + fbc, err := declcfg.LoadFS(ctx, fbcFsys) if err != nil { return err } diff --git a/staging/operator-registry/pkg/cache/json_test.go b/staging/operator-registry/pkg/cache/json_test.go index dee58bacda..af8282646d 100644 --- a/staging/operator-registry/pkg/cache/json_test.go +++ b/staging/operator-registry/pkg/cache/json_test.go @@ -1,6 +1,7 @@ package cache import ( + "context" "io/fs" "os" "path/filepath" @@ -12,7 +13,7 @@ import ( func TestJSON_StableDigest(t *testing.T) { cacheDir := t.TempDir() c := NewJSON(cacheDir) - require.NoError(t, c.Build(validFS)) + require.NoError(t, c.Build(context.Background(), validFS)) actualDigest, err := c.existingDigest() require.NoError(t, err) @@ -96,7 +97,7 @@ func TestJSON_CheckIntegrity(t *testing.T) { c := NewJSON(cacheDir) if tc.build { - require.NoError(t, c.Build(tc.fbcFS)) + require.NoError(t, c.Build(context.Background(), tc.fbcFS)) } if tc.mod != nil { require.NoError(t, tc.mod(&tc, cacheDir)) diff --git a/staging/operator-registry/pkg/cache/pkgs.go b/staging/operator-registry/pkg/cache/pkgs.go index d387ddbd09..af24c397c9 100644 --- a/staging/operator-registry/pkg/cache/pkgs.go +++ b/staging/operator-registry/pkg/cache/pkgs.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "sort" + "strings" "github.com/operator-framework/operator-registry/alpha/declcfg" "github.com/operator-framework/operator-registry/alpha/model" @@ -34,6 +35,7 @@ func (pkgs packageIndex) GetPackage(_ context.Context, name string) (*registry.P CurrentCSVName: ch.Head, }) } + sort.Slice(channels, func(i, j int) bool { return strings.Compare(channels[i].Name, channels[j].Name) < 0 }) return ®istry.PackageManifest{ PackageName: pkg.Name, Channels: channels, diff --git a/staging/operator-registry/pkg/lib/config/validate.go b/staging/operator-registry/pkg/lib/config/validate.go index 5017d3da71..34f2bf0411 100644 --- a/staging/operator-registry/pkg/lib/config/validate.go +++ b/staging/operator-registry/pkg/lib/config/validate.go @@ -1,6 +1,7 @@ package config import ( + "context" "io/fs" "github.com/operator-framework/operator-registry/alpha/declcfg" @@ -13,9 +14,9 @@ import ( // directory: a filesystem where declarative config file(s) exist // Outputs: // error: a wrapped error that contains a tree of error strings -func Validate(root fs.FS) error { +func Validate(ctx context.Context, root fs.FS) error { // Load config files and convert them to declcfg objects - cfg, err := declcfg.LoadFS(root) + cfg, err := declcfg.LoadFS(ctx, root) if err != nil { return err } diff --git a/staging/operator-registry/pkg/lib/indexer/interfaces.go b/staging/operator-registry/pkg/lib/indexer/interfaces.go index df9e6e47a2..5ebefdd1e3 100644 --- a/staging/operator-registry/pkg/lib/indexer/interfaces.go +++ b/staging/operator-registry/pkg/lib/indexer/interfaces.go @@ -9,6 +9,7 @@ import ( // IndexAdder allows the creation of index container images from scratch or // based on previous index images +// //counterfeiter:generate . IndexAdder type IndexAdder interface { AddToIndex(AddToIndexRequest) error @@ -29,6 +30,7 @@ func NewIndexAdder(buildTool, pullTool containertools.ContainerTool, logger *log // IndexDeleter takes indexes and deletes all references to an operator // from them +// //counterfeiter:generate . IndexDeleter type IndexDeleter interface { DeleteFromIndex(DeleteFromIndexRequest) error diff --git a/staging/operator-registry/pkg/lib/log/writerhook.go b/staging/operator-registry/pkg/lib/log/writerhook.go index aa51229bc6..7609ae27f7 100644 --- a/staging/operator-registry/pkg/lib/log/writerhook.go +++ b/staging/operator-registry/pkg/lib/log/writerhook.go @@ -44,7 +44,7 @@ func AddHooks(hooks ...*WriterHook) { } func AddDefaultWriterHooks(terminationLogPath string) error { - terminationLogFile, err := os.OpenFile(terminationLogPath, os.O_WRONLY|os.O_CREATE, 0755) + terminationLogFile, err := os.OpenFile(terminationLogPath, os.O_WRONLY|os.O_CREATE, 0644) if err != nil { return err } diff --git a/staging/operator-registry/pkg/lib/registry/registry_test.go b/staging/operator-registry/pkg/lib/registry/registry_test.go index 4b74a671b8..43f4d3998f 100644 --- a/staging/operator-registry/pkg/lib/registry/registry_test.go +++ b/staging/operator-registry/pkg/lib/registry/registry_test.go @@ -102,7 +102,7 @@ func newCache(t *testing.T, bundles []*model.Bundle) cache.Cache { reg, err := cache.New(cacheDir) require.NoError(t, err) - require.NoError(t, reg.Build(os.DirFS(fbcDir))) + require.NoError(t, reg.Build(context.Background(), os.DirFS(fbcDir))) require.NoError(t, reg.Load()) return reg diff --git a/staging/operator-registry/pkg/registry/registry_to_model.go b/staging/operator-registry/pkg/registry/registry_to_model.go index 14b6e7b004..869b8a5c7a 100644 --- a/staging/operator-registry/pkg/registry/registry_to_model.go +++ b/staging/operator-registry/pkg/registry/registry_to_model.go @@ -5,6 +5,9 @@ import ( "fmt" "sort" + "github.com/operator-framework/api/pkg/operators" + "github.com/operator-framework/api/pkg/operators/v1alpha1" + "github.com/operator-framework/operator-registry/alpha/property" ) @@ -99,8 +102,21 @@ func ObjectsAndPropertiesFromBundle(b *Bundle) ([]string, []property.Property, e if err != nil { return nil, nil, fmt.Errorf("marshal object %s/%s (%s) to json: %v", obj.GetName(), obj.GetNamespace(), obj.GroupVersionKind(), err) } - props = append(props, property.MustBuildBundleObjectData(objData)) objects = append(objects, string(objData)) + + // Make an olm.bundle.object property if there is no bundle image set. + // Otherwise, make a olm.csv.metadata property if the object is a CSV + // (and fallback to olm.bundle.object if parsing the CSV fails). + if b.BundleImage == "" { + props = append(props, property.MustBuildBundleObjectData(objData)) + } else if obj.GetKind() == operators.ClusterServiceVersionKind { + var csv v1alpha1.ClusterServiceVersion + if err := json.Unmarshal(objData, &csv); err != nil { + props = append(props, property.MustBuildBundleObjectData(objData)) + } else { + props = append(props, property.MustBuildCSVMetadata(csv)) + } + } } if packageProvidedProperty == nil { diff --git a/staging/operator-registry/pkg/registry/registry_to_model_test.go b/staging/operator-registry/pkg/registry/registry_to_model_test.go index 8d9f7dcb95..264507fd76 100644 --- a/staging/operator-registry/pkg/registry/registry_to_model_test.go +++ b/staging/operator-registry/pkg/registry/registry_to_model_test.go @@ -4,6 +4,7 @@ import ( "encoding/json" "testing" + "github.com/operator-framework/api/pkg/operators/v1alpha1" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -17,7 +18,7 @@ func TestObjectsAndPropertiesFromBundle(t *testing.T) { actualObjs, actualProps, err := ObjectsAndPropertiesFromBundle(registryBundle) require.NoError(t, err) assert.ElementsMatch(t, testExpectedObjects(), actualObjs) - assert.ElementsMatch(t, testExpectedProperties(), actualProps) + assert.ElementsMatch(t, testExpectedProperties(t), actualProps) } const testBundleDir = "../../bundles/etcd.0.9.2" @@ -28,16 +29,23 @@ func testRegistryBundle(t *testing.T) *Bundle { return input.Bundle } +const expectedCSV = "{\"apiVersion\":\"operators.coreos.com/v1alpha1\",\"kind\":\"ClusterServiceVersion\",\"metadata\":{\"annotations\":{\"alm-examples\":\"[{\\\"apiVersion\\\":\\\"etcd.database.coreos.com/v1beta2\\\",\\\"kind\\\":\\\"EtcdCluster\\\",\\\"metadata\\\":{\\\"name\\\":\\\"example\\\",\\\"namespace\\\":\\\"default\\\"},\\\"spec\\\":{\\\"size\\\":3,\\\"version\\\":\\\"3.2.13\\\"}},{\\\"apiVersion\\\":\\\"etcd.database.coreos.com/v1beta2\\\",\\\"kind\\\":\\\"EtcdRestore\\\",\\\"metadata\\\":{\\\"name\\\":\\\"example-etcd-cluster\\\"},\\\"spec\\\":{\\\"etcdCluster\\\":{\\\"name\\\":\\\"example-etcd-cluster\\\"},\\\"backupStorageType\\\":\\\"S3\\\",\\\"s3\\\":{\\\"path\\\":\\\"\\u003cfull-s3-path\\u003e\\\",\\\"awsSecret\\\":\\\"\\u003caws-secret\\u003e\\\"}}},{\\\"apiVersion\\\":\\\"etcd.database.coreos.com/v1beta2\\\",\\\"kind\\\":\\\"EtcdBackup\\\",\\\"metadata\\\":{\\\"name\\\":\\\"example-etcd-cluster-backup\\\"},\\\"spec\\\":{\\\"etcdEndpoints\\\":[\\\"\\u003cetcd-cluster-endpoints\\u003e\\\"],\\\"storageType\\\":\\\"S3\\\",\\\"s3\\\":{\\\"path\\\":\\\"\\u003cfull-s3-path\\u003e\\\",\\\"awsSecret\\\":\\\"\\u003caws-secret\\u003e\\\"}}}]\",\"tectonic-visibility\":\"ocs\"},\"name\":\"etcdoperator.v0.9.2\",\"namespace\":\"placeholder\"},\"spec\":{\"customresourcedefinitions\":{\"owned\":[{\"description\":\"Represents a cluster of etcd nodes.\",\"displayName\":\"etcd Cluster\",\"kind\":\"EtcdCluster\",\"name\":\"etcdclusters.etcd.database.coreos.com\",\"resources\":[{\"kind\":\"Service\",\"version\":\"v1\"},{\"kind\":\"Pod\",\"version\":\"v1\"}],\"specDescriptors\":[{\"description\":\"The desired number of member Pods for the etcd cluster.\",\"displayName\":\"Size\",\"path\":\"size\",\"x-descriptors\":[\"urn:alm:descriptor:com.tectonic.ui:podCount\"]},{\"description\":\"Limits describes the minimum/maximum amount of compute resources required/allowed\",\"displayName\":\"Resource Requirements\",\"path\":\"pod.resources\",\"x-descriptors\":[\"urn:alm:descriptor:com.tectonic.ui:resourceRequirements\"]}],\"statusDescriptors\":[{\"description\":\"The status of each of the member Pods for the etcd cluster.\",\"displayName\":\"Member Status\",\"path\":\"members\",\"x-descriptors\":[\"urn:alm:descriptor:com.tectonic.ui:podStatuses\"]},{\"description\":\"The service at which the running etcd cluster can be accessed.\",\"displayName\":\"Service\",\"path\":\"serviceName\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes:Service\"]},{\"description\":\"The current size of the etcd cluster.\",\"displayName\":\"Cluster Size\",\"path\":\"size\"},{\"description\":\"The current version of the etcd cluster.\",\"displayName\":\"Current Version\",\"path\":\"currentVersion\"},{\"description\":\"The target version of the etcd cluster, after upgrading.\",\"displayName\":\"Target Version\",\"path\":\"targetVersion\"},{\"description\":\"The current status of the etcd cluster.\",\"displayName\":\"Status\",\"path\":\"phase\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes.phase\"]},{\"description\":\"Explanation for the current status of the cluster.\",\"displayName\":\"Status Details\",\"path\":\"reason\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes.phase:reason\"]}],\"version\":\"v1beta2\"},{\"description\":\"Represents the intent to backup an etcd cluster.\",\"displayName\":\"etcd Backup\",\"kind\":\"EtcdBackup\",\"name\":\"etcdbackups.etcd.database.coreos.com\",\"specDescriptors\":[{\"description\":\"Specifies the endpoints of an etcd cluster.\",\"displayName\":\"etcd Endpoint(s)\",\"path\":\"etcdEndpoints\",\"x-descriptors\":[\"urn:alm:descriptor:etcd:endpoint\"]},{\"description\":\"The full AWS S3 path where the backup is saved.\",\"displayName\":\"S3 Path\",\"path\":\"s3.path\",\"x-descriptors\":[\"urn:alm:descriptor:aws:s3:path\"]},{\"description\":\"The name of the secret object that stores the AWS credential and config files.\",\"displayName\":\"AWS Secret\",\"path\":\"s3.awsSecret\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes:Secret\"]}],\"statusDescriptors\":[{\"description\":\"Indicates if the backup was successful.\",\"displayName\":\"Succeeded\",\"path\":\"succeeded\",\"x-descriptors\":[\"urn:alm:descriptor:text\"]},{\"description\":\"Indicates the reason for any backup related failures.\",\"displayName\":\"Reason\",\"path\":\"reason\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes.phase:reason\"]}],\"version\":\"v1beta2\"},{\"description\":\"Represents the intent to restore an etcd cluster from a backup.\",\"displayName\":\"etcd Restore\",\"kind\":\"EtcdRestore\",\"name\":\"etcdrestores.etcd.database.coreos.com\",\"specDescriptors\":[{\"description\":\"References the EtcdCluster which should be restored,\",\"displayName\":\"etcd Cluster\",\"path\":\"etcdCluster.name\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes:EtcdCluster\",\"urn:alm:descriptor:text\"]},{\"description\":\"The full AWS S3 path where the backup is saved.\",\"displayName\":\"S3 Path\",\"path\":\"s3.path\",\"x-descriptors\":[\"urn:alm:descriptor:aws:s3:path\"]},{\"description\":\"The name of the secret object that stores the AWS credential and config files.\",\"displayName\":\"AWS Secret\",\"path\":\"s3.awsSecret\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes:Secret\"]}],\"statusDescriptors\":[{\"description\":\"Indicates if the restore was successful.\",\"displayName\":\"Succeeded\",\"path\":\"succeeded\",\"x-descriptors\":[\"urn:alm:descriptor:text\"]},{\"description\":\"Indicates the reason for any restore related failures.\",\"displayName\":\"Reason\",\"path\":\"reason\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes.phase:reason\"]}],\"version\":\"v1beta2\"}],\"required\":[{\"description\":\"Represents a cluster of etcd nodes.\",\"displayName\":\"etcd Cluster\",\"kind\":\"EtcdCluster\",\"name\":\"etcdclusters.etcd.database.coreos.com\",\"resources\":[{\"kind\":\"Service\",\"version\":\"v1\"},{\"kind\":\"Pod\",\"version\":\"v1\"}],\"specDescriptors\":[{\"description\":\"The desired number of member Pods for the etcd cluster.\",\"displayName\":\"Size\",\"path\":\"size\",\"x-descriptors\":[\"urn:alm:descriptor:com.tectonic.ui:podCount\"]}],\"version\":\"v1beta2\"}]},\"description\":\"etcd is a distributed key value store that provides a reliable way to store data across a cluster of machines. It’s open-source and available on GitHub. etcd gracefully handles leader elections during network partitions and will tolerate machine failure, including the leader. Your applications can read and write data into etcd.\\nA simple use-case is to store database connection details or feature flags within etcd as key value pairs. These values can be watched, allowing your app to reconfigure itself when they change. Advanced uses take advantage of the consistency guarantees to implement database leader elections or do distributed locking across a cluster of workers.\\n\\n_The etcd Open Cloud Service is Public Alpha. The goal before Beta is to fully implement backup features._\\n\\n### Reading and writing to etcd\\n\\nCommunicate with etcd though its command line utility `etcdctl` or with the API using the automatically generated Kubernetes Service.\\n\\n[Read the complete guide to using the etcd Open Cloud Service](https://coreos.com/tectonic/docs/latest/alm/etcd-ocs.html)\\n\\n### Supported Features\\n\\n\\n**High availability**\\n\\n\\nMultiple instances of etcd are networked together and secured. Individual failures or networking issues are transparently handled to keep your cluster up and running.\\n\\n\\n**Automated updates**\\n\\n\\nRolling out a new etcd version works like all Kubernetes rolling updates. Simply declare the desired version, and the etcd service starts a safe rolling update to the new version automatically.\\n\\n\\n**Backups included**\\n\\n\\nComing soon, the ability to schedule backups to happen on or off cluster.\\n\",\"displayName\":\"etcd\",\"icon\":[{\"base64data\":\"iVBORw0KGgoAAAANSUhEUgAAAOEAAADZCAYAAADWmle6AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAEKlJREFUeNrsndt1GzkShmEev4sTgeiHfRYdgVqbgOgITEVgOgLTEQydwIiKwFQCayoCU6+7DyYjsBiBFyVVz7RkXvqCSxXw/+f04XjGQ6IL+FBVuL769euXgZ7r39f/G9iP0X+u/jWDNZzZdGI/Ftama1jjuV4BwmcNpbAf1Fgu+V/9YRvNAyzT2a59+/GT/3hnn5m16wKWedJrmOCxkYztx9Q+py/+E0GJxtJdReWfz+mxNt+QzS2Mc0AI+HbBBwj9QViKbH5t64DsP2fvmGXUkWU4WgO+Uve2YQzBUGd7r+zH2ZG/tiUQc4QxKwgbwFfVGwwmdLL5wH78aPC/ZBem9jJpCAX3xtcNASSNgJLzUPSQyjB1zQNl8IQJ9MIU4lx2+Jo72ysXYKl1HSzN02BMa/vbZ5xyNJIshJzwf3L0dQhJw4Sih/SFw9Tk8sVeghVPoefaIYCkMZCKbrcP9lnZuk0uPUjGE/KE8JQry7W2tgfuC3vXgvNV+qSQbyFtAtyWk7zWiYevvuUQ9QEQCvJ+5mmu6dTjz1zFHLFj8Eb87MtxaZh/IQFIHom+9vgTWwZxAQjT9X4vtbEVPojwjiV471s00mhAckpwGuCn1HtFtRDaSh6y9zsL+LNBvCG/24ThcxHObdlWc1v+VQJe8LcO0jwtuF8BwnAAUgP9M8JPU2Me+Oh12auPGT6fHuTePE3bLDy+x9pTLnhMn+07TQGh//Bz1iI0c6kvtqInjvPZcYR3KsPVmUsPYt9nFig9SCY8VQNhpPBzn952bbgcsk2EvM89wzh3UEffBbyPqvBUBYQ8ODGPFOLsa7RF096WJ69L+E4EmnpjWu5o4ChlKaRTKT39RMMaVPEQRsz/nIWlDN80chjdJlSd1l0pJCAMVZsniobQVuxceMM9OFoaMd9zqZtjMEYYDW38Drb8Y0DYPLShxn0pvIFuOSxd7YCPet9zk452wsh54FJoeN05hcgSQoG5RR0Qh9Q4E4VvL4wcZq8UACgaRFEQKgSwWrkr5WFnGxiHSutqJGlXjBgIOayhwYBTA0ER0oisIVSUV0AAMT0IASCUO4hRIQSAEECMCCEPwqyQA0JCQBzEGjWNAqHiUVAoXUWbvggOIQCEAOJzxTjoaQ4AIaE64/aZridUsBYUgkhB15oGg1DBIl8IqirYwV6hPSGBSFteMCUBSVXwfYixBmamRubeMyjzMJQBDDowE3OesDD+zwqFoDqiEwXoXJpljB+PvWJGy75BKF1FPxhKygJuqUdYQGlLxNEXkrYyjQ0GbaAwEnUIlLRNvVjQDYUAsJB0HKLE4y0AIpQNgCIhBIhQTgCKhZBBpAN/v6LtQI50JfUgYOnnjmLUFHKhjxbAmdTCaTiBm3ovLPqG2urWAij6im0Nd9aTN9ygLUEt9LgSRnohxUPIKxlGaE+/6Y7znFf0yX+GnkvFFWmarkab2o9PmTeq8sbd2a7DaysXz7i64VeznN4jCQhN9gdDbRiuWrfrsq0mHIrlaq+hlotCtd3Um9u0BYWY8y5D67wccJoZjFca7iUs9VqZcfsZwTd1sbWGG+OcYaTnPAP7rTQVVlM4Sg3oGvB1tmNh0t/HKXZ1jFoIMwCQjtqbhNxUmkGYqgZEDZP11HN/S3gAYRozf0l8C5kKEKUvW0t1IfeWG/5MwgheZTT1E0AEhDkAePQO+Ig2H3DncAkQM4cwUQCD530dU4B5Yvmi2LlDqXfWrxMCcMth51RToRMNUXFnfc2KJ0+Ryl0VNOUwlhh6NoxK5gnViTgQpUG4SqSyt5z3zRJpuKmt3Q1614QaCBPaN6je+2XiFcWAKOXcUfIYKRyL/1lb7pe5VxSxxjQ6hImshqGRt5GWZVKO6q2wHwujfwDtIvaIdexj8Cm8+a68EqMfox6x/voMouZF4dHnEGNeCDMwT6vdNfekH1MafMk4PI06YtqLVGl95aEM9Z5vAeCTOA++YLtoVJRrsqNCaJ6WRmkdYaNec5BT/lcTRMqrhmwfjbpkj55+OKp8IEbU/JLgPJE6Wa3TTe9sHS+ShVD5QIyqIxMEwKh12olC6mHIed5ewEop80CNlfIOADYOT2nd6ZXCop+Ebqchc0JqxKcKASxChycJgUh1rnHA5ow9eTrhqNI7JWiAYYwBGGdpyNLoGw0Pkh96h1BpHihyywtATDM/7Hk2fN9EnH8BgKJCU4ooBkbXFMZJiPbrOyecGl3zgQDQL4hk10IZiOe+5w99Q/gBAEIJgPhJM4QAEEoFREAIAAEiIASAkD8Qt4AQAEIAERAGFlX4CACKAXGVM4ivMwWwCLFAlyeoaa70QePKm5Dlp+/n+ye/5dYgva6YsUaVeMa+tzNFeJtWwc+udbJ0Fg399kLielQJ5Ze61c2+7ytA6EZetiPxZC6tj22yJCv6jUwOyj/zcbqAxOMyAKEbfeHtNa7DtYXptjsk2kJxR+eIeim/tHNofUKYy8DMrQcAKWz6brpvzyIAlpwPhQ49l6b7skJf5Z+YTOYQc4FwLDxvoTDwaygQK+U/kVr+ytSFBG01Q3gnJJR4cNiAhx4HDub8/b5DULXlj6SVZghFiE+LdvE9vo/o8Lp1RmH5hzm0T6wdbZ6n+D6i44zDRc3ln6CpAEJfXiRU45oqLz8gFAThWsh7ughrRibc0QynHgZpNJa/ENJ+loCwu/qOGnFIjYR/n7TfgycULhcQhu6VC+HfF+L3BoAQ4WiZTw1M+FPCnA2gKC6/FAhXgDC+ojQGh3NuWsvfF1L/D5ohlCKtl1j2ldu9a/nPAKFwN56Bst10zCG0CPleXN/zXPgHQZXaZaBgrbzyY5V/mUA+6F0hwtGN9rwu5DVZPuwWqfxdFz1LWbJ2lwKEa+0Qsm4Dl3fp+Pu0lV97PgwIPfSsS+UQhj5Oo+vvFULazRIQyvGEcxPuNLCth2MvFsrKn8UOilAQShkh7TTczYNMoS6OdP47msrPi82lXKGWhCdMZYS0bFy+vcnGAjP1CIfvgbKNA9glecEH9RD6Ol4wRuWyN/G9MHnksS6o/GPf5XcwNSUlHzQhDuAKtWJmkwKElU7lylP5rgIcsquh/FI8YZCDpkJBuE4FQm7Icw8N+SrUGaQKyi8FwiDt1ve5o+Vu7qYHy/psgK8cvh+FTYuO77bhEC7GuaPiys/L1X4IgXDL+e3M5+ovLxBy5VLuIebw1oqcHoPfoaMJUsHays878r8KbDc3xtPx/84gZPBG/JwaufrsY/SRG/OY3//8QMNdsvdZCFtbW6f8pFuf5bflILAlX7O+4fdfugKyFYS8T2zAsXthdG0VurPGKwI06oF5vkBgHWkNp6ry29+lsPZMU3vijnXFNmoclr+6+Ou/FIb8yb30sS8YGjmTqCLyQsi5N/6ZwKs0Yenj68pfPjF6N782Dp2FzV9CTyoSeY8mLK16qGxIkLI8oa1n8tz9juP40DlK0epxYEbojbq+9QfurBeVIlCO9D2396bxiV4lkYQ3hOAFw2pbhqMGISkkQOMcQ9EqhDmGZZdo92JC0YHRNTfoSg+5e0IT+opqCKHoIU+4ztQIgBD1EFNrQAgIpYSil9lDmPHqkROPt+JC6AgPquSuumJmg0YARVCuneDfvPVeJokZ6pIXDkNxQtGzTF9/BQjRG0tQznfb74RwCQghpALBtIQnfK4zhxdyQvVCUeknMIT3hLyY+T5jo0yABqKPQNpUNw/09tGZod5jgCaYFxyYvJcNPkv9eof+I3pnCFEHIETjSM8L9tHZHYCQT9PaZGycU6yg8S4akDnJ+P03L0+t23XGzCLzRgII/Wqa+fv/xlfvmKvMUOcOrlCDdoei1MGdZm6G5VEIfRzzjd4aQs69n699Rx7ewhvCGzr2gmTPs8zNsJOrXt24FbkhhOjCfT4ICA/rPbyhUy94Dks0gJCX1NzCZui9YUd3oei+c257TalFbgg19ILHrlrL2gvWgXAL26EX76gZTNASQnad8Ibwhl284NhgXpB0c+jKhWO3Ms1hP9ihJYB9eMF6qd1BCPk0qA1s+LimFIu7m4nsdQIzPK4VbQ8hYvrnuSH2G9b2ggP78QmWqBdF9Vx8SSY6QYdUW7BTA1schZATyhvY8lHvcRbNUS9YGFy2U+qmzh2YPVc0I7yAOFyHfRpyUwtCSzOdPXMHmz7qDIM0e0V2wZTEk+6Ym6N63eBLp/b5Bts+2cKCSJ/LuoZO3ANSiE5hKAZjnvNSS4931jcw9jpwT0feV/qSJ1pVtCyfHKDkvK8Ejx7pUxGh2xFNSwx8QTi2H9ceC0/nni64MS/5N5dG39pDqvRV+WgGk71c9VFXF9b+xYvOw/d61iv7m3MvEHryhvecwC52jSSx4VIIgwnMNT/UsTxIgpPt3K/ARj15CptwL3Zd/ceDSATj2DGQjbxgWwhdeMMte7zpy5On9vymRm/YxBYljGVjKWF9VJf7I1+sex3wY8w/V1QPTborW/72gkdsRDaZMJBdbdHIC7aCkAu9atlLbtnrzerMnyToDaGwelOnk3/hHSem/ZK7e/t7jeeR20LYBgqa8J80gS8jbwi5F02Uj1u2NYJxap8PLkJfLxA2hIJyvnHX/AfeEPLpBfe0uSFHbnXaea3Qd5d6HcpYZ8L6M7lnFwMQ3MNg+RxUR1+6AshtbsVgfXTEg1sIGax9UND2p7f270wdG3eK9gXVGHdw2k5sOyZv+Nbs39Z308XR9DqWb2J+PwKDhuKHPobfuXf7gnYGHdCs7bhDDadD4entDug7LWNsnRNW4mYqwJ9dk+GGSTPBiA2j0G8RWNM5upZtcG4/3vMfP7KnbK2egx6CCnDPhRn7NgD3cghLIad5WcM2SO38iqHvvMOosyeMpQ5zlVCaaj06GVs9xUbHdiKoqrHWgquFEFMWUEWfXUxJAML23hAHFOctmjZQffKD2pywkhtSGHKNtpitLroscAeE7kCkSsC60vxEl6yMtL9EL5HKGCMszU5bk8gdkklAyEn5FO0yK419rIxBOIqwFMooDE0tHEVYijAUECIshRCGIhxFWIowFJ5QkEYIS5PTJrUwNGlPyN6QQPyKtpuM1E/K5+YJDV/MiA3AaehzqgAm7QnZG9IGYKo8bHnSK7VblLL3hOwNHziPuEGOqE5brrdR6i+atCfckyeWD47HkAkepRGLY/e8A8J0gCwYSNypF08bBm+e6zVz2UL4AshhBUjML/rXLefqC82bcQFhGC9JDwZ1uuu+At0S5gCETYHsV4DUeD9fDN2Zfy5OXaW2zAwQygCzBLJ8cvaW5OXKC1FxfTggFAHmoAJnSiOw2wps9KwRWgJCLaEswaj5NqkLwAYIU4BxqTSXbHXpJdRMPZgAOiAMqABCNGYIEEJutEK5IUAIwYMDQgiCACEEAcJs1Vda7gGqDhCmoiEghAAhBAHCrKXVo2C1DCBMRlp37uMIEECoX7xrX3P5C9QiINSuIcoPAUI0YkAICLNWgfJDh4T9hH7zqYH9+JHAq7zBqWjwhPAicTVCVQJCNF50JghHocahKK0X/ZnQKyEkhSdUpzG8OgQI42qC94EQjsYLRSmH+pbgq73L6bYkeEJ4DYTYmeg1TOBFc/usTTp3V9DdEuXJ2xDCUbXhaXk0/kAYmBvuMB4qkC35E5e5AMKkwSQgyxufyuPy6fMMgAFCSI73LFXU/N8AmEL9X4ABACNSKMHAgb34AAAAAElFTkSuQmCC\",\"mediatype\":\"image/png\"}],\"install\":{\"spec\":{\"deployments\":[{\"name\":\"etcd-operator\",\"spec\":{\"replicas\":1,\"selector\":{\"matchLabels\":{\"name\":\"etcd-operator-alm-owned\"}},\"template\":{\"metadata\":{\"labels\":{\"name\":\"etcd-operator-alm-owned\"},\"name\":\"etcd-operator-alm-owned\"},\"spec\":{\"containers\":[{\"command\":[\"etcd-operator\",\"--create-crd=false\"],\"env\":[{\"name\":\"MY_POD_NAMESPACE\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"metadata.namespace\"}}},{\"name\":\"MY_POD_NAME\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"metadata.name\"}}}],\"image\":\"quay.io/coreos/etcd-operator@sha256:c0301e4686c3ed4206e370b42de5a3bd2229b9fb4906cf85f3f30650424abec2\",\"name\":\"etcd-operator\"},{\"command\":[\"etcd-backup-operator\",\"--create-crd=false\"],\"env\":[{\"name\":\"MY_POD_NAMESPACE\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"metadata.namespace\"}}},{\"name\":\"MY_POD_NAME\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"metadata.name\"}}}],\"image\":\"quay.io/coreos/etcd-operator@sha256:c0301e4686c3ed4206e370b42de5a3bd2229b9fb4906cf85f3f30650424abec2\",\"name\":\"etcd-backup-operator\"},{\"command\":[\"etcd-restore-operator\",\"--create-crd=false\"],\"env\":[{\"name\":\"MY_POD_NAMESPACE\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"metadata.namespace\"}}},{\"name\":\"MY_POD_NAME\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"metadata.name\"}}}],\"image\":\"quay.io/coreos/etcd-operator@sha256:c0301e4686c3ed4206e370b42de5a3bd2229b9fb4906cf85f3f30650424abec2\",\"name\":\"etcd-restore-operator\"}],\"serviceAccountName\":\"etcd-operator\"}}}}],\"permissions\":[{\"rules\":[{\"apiGroups\":[\"etcd.database.coreos.com\"],\"resources\":[\"etcdclusters\",\"etcdbackups\",\"etcdrestores\"],\"verbs\":[\"*\"]},{\"apiGroups\":[\"\"],\"resources\":[\"pods\",\"services\",\"endpoints\",\"persistentvolumeclaims\",\"events\"],\"verbs\":[\"*\"]},{\"apiGroups\":[\"apps\"],\"resources\":[\"deployments\"],\"verbs\":[\"*\"]},{\"apiGroups\":[\"\"],\"resources\":[\"secrets\"],\"verbs\":[\"get\"]}],\"serviceAccountName\":\"etcd-operator\"}]},\"strategy\":\"deployment\"},\"keywords\":[\"etcd\",\"key value\",\"database\",\"coreos\",\"open source\"],\"labels\":{\"alm-owner-etcd\":\"etcdoperator\",\"operated-by\":\"etcdoperator\"},\"links\":[{\"name\":\"Blog\",\"url\":\"https://coreos.com/etcd\"},{\"name\":\"Documentation\",\"url\":\"https://coreos.com/operators/etcd/docs/latest/\"},{\"name\":\"etcd Operator Source Code\",\"url\":\"https://github.com/coreos/etcd-operator\"}],\"maintainers\":[{\"email\":\"support@coreos.com\",\"name\":\"CoreOS, Inc\"}],\"maturity\":\"alpha\",\"provider\":{\"name\":\"CoreOS, Inc\"},\"replaces\":\"etcdoperator.v0.9.0\",\"selector\":{\"matchLabels\":{\"alm-owner-etcd\":\"etcdoperator\",\"operated-by\":\"etcdoperator\"}},\"skips\":[\"etcdoperator.v0.9.1\"],\"version\":\"0.9.2\"}}" + func testExpectedObjects() []string { return []string{ "{\"apiVersion\":\"apiextensions.k8s.io/v1beta1\",\"kind\":\"CustomResourceDefinition\",\"metadata\":{\"name\":\"etcdbackups.etcd.database.coreos.com\"},\"spec\":{\"group\":\"etcd.database.coreos.com\",\"names\":{\"kind\":\"EtcdBackup\",\"listKind\":\"EtcdBackupList\",\"plural\":\"etcdbackups\",\"singular\":\"etcdbackup\"},\"scope\":\"Namespaced\",\"version\":\"v1beta2\"}}", "{\"apiVersion\":\"apiextensions.k8s.io/v1beta1\",\"kind\":\"CustomResourceDefinition\",\"metadata\":{\"name\":\"etcdclusters.etcd.database.coreos.com\"},\"spec\":{\"group\":\"etcd.database.coreos.com\",\"names\":{\"kind\":\"EtcdCluster\",\"listKind\":\"EtcdClusterList\",\"plural\":\"etcdclusters\",\"shortNames\":[\"etcdclus\",\"etcd\"],\"singular\":\"etcdcluster\"},\"scope\":\"Namespaced\",\"version\":\"v1beta2\"}}", - "{\"apiVersion\":\"operators.coreos.com/v1alpha1\",\"kind\":\"ClusterServiceVersion\",\"metadata\":{\"annotations\":{\"alm-examples\":\"[{\\\"apiVersion\\\":\\\"etcd.database.coreos.com/v1beta2\\\",\\\"kind\\\":\\\"EtcdCluster\\\",\\\"metadata\\\":{\\\"name\\\":\\\"example\\\",\\\"namespace\\\":\\\"default\\\"},\\\"spec\\\":{\\\"size\\\":3,\\\"version\\\":\\\"3.2.13\\\"}},{\\\"apiVersion\\\":\\\"etcd.database.coreos.com/v1beta2\\\",\\\"kind\\\":\\\"EtcdRestore\\\",\\\"metadata\\\":{\\\"name\\\":\\\"example-etcd-cluster\\\"},\\\"spec\\\":{\\\"etcdCluster\\\":{\\\"name\\\":\\\"example-etcd-cluster\\\"},\\\"backupStorageType\\\":\\\"S3\\\",\\\"s3\\\":{\\\"path\\\":\\\"\\u003cfull-s3-path\\u003e\\\",\\\"awsSecret\\\":\\\"\\u003caws-secret\\u003e\\\"}}},{\\\"apiVersion\\\":\\\"etcd.database.coreos.com/v1beta2\\\",\\\"kind\\\":\\\"EtcdBackup\\\",\\\"metadata\\\":{\\\"name\\\":\\\"example-etcd-cluster-backup\\\"},\\\"spec\\\":{\\\"etcdEndpoints\\\":[\\\"\\u003cetcd-cluster-endpoints\\u003e\\\"],\\\"storageType\\\":\\\"S3\\\",\\\"s3\\\":{\\\"path\\\":\\\"\\u003cfull-s3-path\\u003e\\\",\\\"awsSecret\\\":\\\"\\u003caws-secret\\u003e\\\"}}}]\",\"tectonic-visibility\":\"ocs\"},\"name\":\"etcdoperator.v0.9.2\",\"namespace\":\"placeholder\"},\"spec\":{\"customresourcedefinitions\":{\"owned\":[{\"description\":\"Represents a cluster of etcd nodes.\",\"displayName\":\"etcd Cluster\",\"kind\":\"EtcdCluster\",\"name\":\"etcdclusters.etcd.database.coreos.com\",\"resources\":[{\"kind\":\"Service\",\"version\":\"v1\"},{\"kind\":\"Pod\",\"version\":\"v1\"}],\"specDescriptors\":[{\"description\":\"The desired number of member Pods for the etcd cluster.\",\"displayName\":\"Size\",\"path\":\"size\",\"x-descriptors\":[\"urn:alm:descriptor:com.tectonic.ui:podCount\"]},{\"description\":\"Limits describes the minimum/maximum amount of compute resources required/allowed\",\"displayName\":\"Resource Requirements\",\"path\":\"pod.resources\",\"x-descriptors\":[\"urn:alm:descriptor:com.tectonic.ui:resourceRequirements\"]}],\"statusDescriptors\":[{\"description\":\"The status of each of the member Pods for the etcd cluster.\",\"displayName\":\"Member Status\",\"path\":\"members\",\"x-descriptors\":[\"urn:alm:descriptor:com.tectonic.ui:podStatuses\"]},{\"description\":\"The service at which the running etcd cluster can be accessed.\",\"displayName\":\"Service\",\"path\":\"serviceName\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes:Service\"]},{\"description\":\"The current size of the etcd cluster.\",\"displayName\":\"Cluster Size\",\"path\":\"size\"},{\"description\":\"The current version of the etcd cluster.\",\"displayName\":\"Current Version\",\"path\":\"currentVersion\"},{\"description\":\"The target version of the etcd cluster, after upgrading.\",\"displayName\":\"Target Version\",\"path\":\"targetVersion\"},{\"description\":\"The current status of the etcd cluster.\",\"displayName\":\"Status\",\"path\":\"phase\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes.phase\"]},{\"description\":\"Explanation for the current status of the cluster.\",\"displayName\":\"Status Details\",\"path\":\"reason\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes.phase:reason\"]}],\"version\":\"v1beta2\"},{\"description\":\"Represents the intent to backup an etcd cluster.\",\"displayName\":\"etcd Backup\",\"kind\":\"EtcdBackup\",\"name\":\"etcdbackups.etcd.database.coreos.com\",\"specDescriptors\":[{\"description\":\"Specifies the endpoints of an etcd cluster.\",\"displayName\":\"etcd Endpoint(s)\",\"path\":\"etcdEndpoints\",\"x-descriptors\":[\"urn:alm:descriptor:etcd:endpoint\"]},{\"description\":\"The full AWS S3 path where the backup is saved.\",\"displayName\":\"S3 Path\",\"path\":\"s3.path\",\"x-descriptors\":[\"urn:alm:descriptor:aws:s3:path\"]},{\"description\":\"The name of the secret object that stores the AWS credential and config files.\",\"displayName\":\"AWS Secret\",\"path\":\"s3.awsSecret\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes:Secret\"]}],\"statusDescriptors\":[{\"description\":\"Indicates if the backup was successful.\",\"displayName\":\"Succeeded\",\"path\":\"succeeded\",\"x-descriptors\":[\"urn:alm:descriptor:text\"]},{\"description\":\"Indicates the reason for any backup related failures.\",\"displayName\":\"Reason\",\"path\":\"reason\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes.phase:reason\"]}],\"version\":\"v1beta2\"},{\"description\":\"Represents the intent to restore an etcd cluster from a backup.\",\"displayName\":\"etcd Restore\",\"kind\":\"EtcdRestore\",\"name\":\"etcdrestores.etcd.database.coreos.com\",\"specDescriptors\":[{\"description\":\"References the EtcdCluster which should be restored,\",\"displayName\":\"etcd Cluster\",\"path\":\"etcdCluster.name\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes:EtcdCluster\",\"urn:alm:descriptor:text\"]},{\"description\":\"The full AWS S3 path where the backup is saved.\",\"displayName\":\"S3 Path\",\"path\":\"s3.path\",\"x-descriptors\":[\"urn:alm:descriptor:aws:s3:path\"]},{\"description\":\"The name of the secret object that stores the AWS credential and config files.\",\"displayName\":\"AWS Secret\",\"path\":\"s3.awsSecret\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes:Secret\"]}],\"statusDescriptors\":[{\"description\":\"Indicates if the restore was successful.\",\"displayName\":\"Succeeded\",\"path\":\"succeeded\",\"x-descriptors\":[\"urn:alm:descriptor:text\"]},{\"description\":\"Indicates the reason for any restore related failures.\",\"displayName\":\"Reason\",\"path\":\"reason\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes.phase:reason\"]}],\"version\":\"v1beta2\"}],\"required\":[{\"description\":\"Represents a cluster of etcd nodes.\",\"displayName\":\"etcd Cluster\",\"kind\":\"EtcdCluster\",\"name\":\"etcdclusters.etcd.database.coreos.com\",\"resources\":[{\"kind\":\"Service\",\"version\":\"v1\"},{\"kind\":\"Pod\",\"version\":\"v1\"}],\"specDescriptors\":[{\"description\":\"The desired number of member Pods for the etcd cluster.\",\"displayName\":\"Size\",\"path\":\"size\",\"x-descriptors\":[\"urn:alm:descriptor:com.tectonic.ui:podCount\"]}],\"version\":\"v1beta2\"}]},\"description\":\"etcd is a distributed key value store that provides a reliable way to store data across a cluster of machines. It’s open-source and available on GitHub. etcd gracefully handles leader elections during network partitions and will tolerate machine failure, including the leader. Your applications can read and write data into etcd.\\nA simple use-case is to store database connection details or feature flags within etcd as key value pairs. These values can be watched, allowing your app to reconfigure itself when they change. Advanced uses take advantage of the consistency guarantees to implement database leader elections or do distributed locking across a cluster of workers.\\n\\n_The etcd Open Cloud Service is Public Alpha. The goal before Beta is to fully implement backup features._\\n\\n### Reading and writing to etcd\\n\\nCommunicate with etcd though its command line utility `etcdctl` or with the API using the automatically generated Kubernetes Service.\\n\\n[Read the complete guide to using the etcd Open Cloud Service](https://coreos.com/tectonic/docs/latest/alm/etcd-ocs.html)\\n\\n### Supported Features\\n\\n\\n**High availability**\\n\\n\\nMultiple instances of etcd are networked together and secured. Individual failures or networking issues are transparently handled to keep your cluster up and running.\\n\\n\\n**Automated updates**\\n\\n\\nRolling out a new etcd version works like all Kubernetes rolling updates. Simply declare the desired version, and the etcd service starts a safe rolling update to the new version automatically.\\n\\n\\n**Backups included**\\n\\n\\nComing soon, the ability to schedule backups to happen on or off cluster.\\n\",\"displayName\":\"etcd\",\"icon\":[{\"base64data\":\"iVBORw0KGgoAAAANSUhEUgAAAOEAAADZCAYAAADWmle6AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAEKlJREFUeNrsndt1GzkShmEev4sTgeiHfRYdgVqbgOgITEVgOgLTEQydwIiKwFQCayoCU6+7DyYjsBiBFyVVz7RkXvqCSxXw/+f04XjGQ6IL+FBVuL769euXgZ7r39f/G9iP0X+u/jWDNZzZdGI/Ftama1jjuV4BwmcNpbAf1Fgu+V/9YRvNAyzT2a59+/GT/3hnn5m16wKWedJrmOCxkYztx9Q+py/+E0GJxtJdReWfz+mxNt+QzS2Mc0AI+HbBBwj9QViKbH5t64DsP2fvmGXUkWU4WgO+Uve2YQzBUGd7r+zH2ZG/tiUQc4QxKwgbwFfVGwwmdLL5wH78aPC/ZBem9jJpCAX3xtcNASSNgJLzUPSQyjB1zQNl8IQJ9MIU4lx2+Jo72ysXYKl1HSzN02BMa/vbZ5xyNJIshJzwf3L0dQhJw4Sih/SFw9Tk8sVeghVPoefaIYCkMZCKbrcP9lnZuk0uPUjGE/KE8JQry7W2tgfuC3vXgvNV+qSQbyFtAtyWk7zWiYevvuUQ9QEQCvJ+5mmu6dTjz1zFHLFj8Eb87MtxaZh/IQFIHom+9vgTWwZxAQjT9X4vtbEVPojwjiV471s00mhAckpwGuCn1HtFtRDaSh6y9zsL+LNBvCG/24ThcxHObdlWc1v+VQJe8LcO0jwtuF8BwnAAUgP9M8JPU2Me+Oh12auPGT6fHuTePE3bLDy+x9pTLnhMn+07TQGh//Bz1iI0c6kvtqInjvPZcYR3KsPVmUsPYt9nFig9SCY8VQNhpPBzn952bbgcsk2EvM89wzh3UEffBbyPqvBUBYQ8ODGPFOLsa7RF096WJ69L+E4EmnpjWu5o4ChlKaRTKT39RMMaVPEQRsz/nIWlDN80chjdJlSd1l0pJCAMVZsniobQVuxceMM9OFoaMd9zqZtjMEYYDW38Drb8Y0DYPLShxn0pvIFuOSxd7YCPet9zk452wsh54FJoeN05hcgSQoG5RR0Qh9Q4E4VvL4wcZq8UACgaRFEQKgSwWrkr5WFnGxiHSutqJGlXjBgIOayhwYBTA0ER0oisIVSUV0AAMT0IASCUO4hRIQSAEECMCCEPwqyQA0JCQBzEGjWNAqHiUVAoXUWbvggOIQCEAOJzxTjoaQ4AIaE64/aZridUsBYUgkhB15oGg1DBIl8IqirYwV6hPSGBSFteMCUBSVXwfYixBmamRubeMyjzMJQBDDowE3OesDD+zwqFoDqiEwXoXJpljB+PvWJGy75BKF1FPxhKygJuqUdYQGlLxNEXkrYyjQ0GbaAwEnUIlLRNvVjQDYUAsJB0HKLE4y0AIpQNgCIhBIhQTgCKhZBBpAN/v6LtQI50JfUgYOnnjmLUFHKhjxbAmdTCaTiBm3ovLPqG2urWAij6im0Nd9aTN9ygLUEt9LgSRnohxUPIKxlGaE+/6Y7znFf0yX+GnkvFFWmarkab2o9PmTeq8sbd2a7DaysXz7i64VeznN4jCQhN9gdDbRiuWrfrsq0mHIrlaq+hlotCtd3Um9u0BYWY8y5D67wccJoZjFca7iUs9VqZcfsZwTd1sbWGG+OcYaTnPAP7rTQVVlM4Sg3oGvB1tmNh0t/HKXZ1jFoIMwCQjtqbhNxUmkGYqgZEDZP11HN/S3gAYRozf0l8C5kKEKUvW0t1IfeWG/5MwgheZTT1E0AEhDkAePQO+Ig2H3DncAkQM4cwUQCD530dU4B5Yvmi2LlDqXfWrxMCcMth51RToRMNUXFnfc2KJ0+Ryl0VNOUwlhh6NoxK5gnViTgQpUG4SqSyt5z3zRJpuKmt3Q1614QaCBPaN6je+2XiFcWAKOXcUfIYKRyL/1lb7pe5VxSxxjQ6hImshqGRt5GWZVKO6q2wHwujfwDtIvaIdexj8Cm8+a68EqMfox6x/voMouZF4dHnEGNeCDMwT6vdNfekH1MafMk4PI06YtqLVGl95aEM9Z5vAeCTOA++YLtoVJRrsqNCaJ6WRmkdYaNec5BT/lcTRMqrhmwfjbpkj55+OKp8IEbU/JLgPJE6Wa3TTe9sHS+ShVD5QIyqIxMEwKh12olC6mHIed5ewEop80CNlfIOADYOT2nd6ZXCop+Ebqchc0JqxKcKASxChycJgUh1rnHA5ow9eTrhqNI7JWiAYYwBGGdpyNLoGw0Pkh96h1BpHihyywtATDM/7Hk2fN9EnH8BgKJCU4ooBkbXFMZJiPbrOyecGl3zgQDQL4hk10IZiOe+5w99Q/gBAEIJgPhJM4QAEEoFREAIAAEiIASAkD8Qt4AQAEIAERAGFlX4CACKAXGVM4ivMwWwCLFAlyeoaa70QePKm5Dlp+/n+ye/5dYgva6YsUaVeMa+tzNFeJtWwc+udbJ0Fg399kLielQJ5Ze61c2+7ytA6EZetiPxZC6tj22yJCv6jUwOyj/zcbqAxOMyAKEbfeHtNa7DtYXptjsk2kJxR+eIeim/tHNofUKYy8DMrQcAKWz6brpvzyIAlpwPhQ49l6b7skJf5Z+YTOYQc4FwLDxvoTDwaygQK+U/kVr+ytSFBG01Q3gnJJR4cNiAhx4HDub8/b5DULXlj6SVZghFiE+LdvE9vo/o8Lp1RmH5hzm0T6wdbZ6n+D6i44zDRc3ln6CpAEJfXiRU45oqLz8gFAThWsh7ughrRibc0QynHgZpNJa/ENJ+loCwu/qOGnFIjYR/n7TfgycULhcQhu6VC+HfF+L3BoAQ4WiZTw1M+FPCnA2gKC6/FAhXgDC+ojQGh3NuWsvfF1L/D5ohlCKtl1j2ldu9a/nPAKFwN56Bst10zCG0CPleXN/zXPgHQZXaZaBgrbzyY5V/mUA+6F0hwtGN9rwu5DVZPuwWqfxdFz1LWbJ2lwKEa+0Qsm4Dl3fp+Pu0lV97PgwIPfSsS+UQhj5Oo+vvFULazRIQyvGEcxPuNLCth2MvFsrKn8UOilAQShkh7TTczYNMoS6OdP47msrPi82lXKGWhCdMZYS0bFy+vcnGAjP1CIfvgbKNA9glecEH9RD6Ol4wRuWyN/G9MHnksS6o/GPf5XcwNSUlHzQhDuAKtWJmkwKElU7lylP5rgIcsquh/FI8YZCDpkJBuE4FQm7Icw8N+SrUGaQKyi8FwiDt1ve5o+Vu7qYHy/psgK8cvh+FTYuO77bhEC7GuaPiys/L1X4IgXDL+e3M5+ovLxBy5VLuIebw1oqcHoPfoaMJUsHays878r8KbDc3xtPx/84gZPBG/JwaufrsY/SRG/OY3//8QMNdsvdZCFtbW6f8pFuf5bflILAlX7O+4fdfugKyFYS8T2zAsXthdG0VurPGKwI06oF5vkBgHWkNp6ry29+lsPZMU3vijnXFNmoclr+6+Ou/FIb8yb30sS8YGjmTqCLyQsi5N/6ZwKs0Yenj68pfPjF6N782Dp2FzV9CTyoSeY8mLK16qGxIkLI8oa1n8tz9juP40DlK0epxYEbojbq+9QfurBeVIlCO9D2396bxiV4lkYQ3hOAFw2pbhqMGISkkQOMcQ9EqhDmGZZdo92JC0YHRNTfoSg+5e0IT+opqCKHoIU+4ztQIgBD1EFNrQAgIpYSil9lDmPHqkROPt+JC6AgPquSuumJmg0YARVCuneDfvPVeJokZ6pIXDkNxQtGzTF9/BQjRG0tQznfb74RwCQghpALBtIQnfK4zhxdyQvVCUeknMIT3hLyY+T5jo0yABqKPQNpUNw/09tGZod5jgCaYFxyYvJcNPkv9eof+I3pnCFEHIETjSM8L9tHZHYCQT9PaZGycU6yg8S4akDnJ+P03L0+t23XGzCLzRgII/Wqa+fv/xlfvmKvMUOcOrlCDdoei1MGdZm6G5VEIfRzzjd4aQs69n699Rx7ewhvCGzr2gmTPs8zNsJOrXt24FbkhhOjCfT4ICA/rPbyhUy94Dks0gJCX1NzCZui9YUd3oei+c257TalFbgg19ILHrlrL2gvWgXAL26EX76gZTNASQnad8Ibwhl284NhgXpB0c+jKhWO3Ms1hP9ihJYB9eMF6qd1BCPk0qA1s+LimFIu7m4nsdQIzPK4VbQ8hYvrnuSH2G9b2ggP78QmWqBdF9Vx8SSY6QYdUW7BTA1schZATyhvY8lHvcRbNUS9YGFy2U+qmzh2YPVc0I7yAOFyHfRpyUwtCSzOdPXMHmz7qDIM0e0V2wZTEk+6Ym6N63eBLp/b5Bts+2cKCSJ/LuoZO3ANSiE5hKAZjnvNSS4931jcw9jpwT0feV/qSJ1pVtCyfHKDkvK8Ejx7pUxGh2xFNSwx8QTi2H9ceC0/nni64MS/5N5dG39pDqvRV+WgGk71c9VFXF9b+xYvOw/d61iv7m3MvEHryhvecwC52jSSx4VIIgwnMNT/UsTxIgpPt3K/ARj15CptwL3Zd/ceDSATj2DGQjbxgWwhdeMMte7zpy5On9vymRm/YxBYljGVjKWF9VJf7I1+sex3wY8w/V1QPTborW/72gkdsRDaZMJBdbdHIC7aCkAu9atlLbtnrzerMnyToDaGwelOnk3/hHSem/ZK7e/t7jeeR20LYBgqa8J80gS8jbwi5F02Uj1u2NYJxap8PLkJfLxA2hIJyvnHX/AfeEPLpBfe0uSFHbnXaea3Qd5d6HcpYZ8L6M7lnFwMQ3MNg+RxUR1+6AshtbsVgfXTEg1sIGax9UND2p7f270wdG3eK9gXVGHdw2k5sOyZv+Nbs39Z308XR9DqWb2J+PwKDhuKHPobfuXf7gnYGHdCs7bhDDadD4entDug7LWNsnRNW4mYqwJ9dk+GGSTPBiA2j0G8RWNM5upZtcG4/3vMfP7KnbK2egx6CCnDPhRn7NgD3cghLIad5WcM2SO38iqHvvMOosyeMpQ5zlVCaaj06GVs9xUbHdiKoqrHWgquFEFMWUEWfXUxJAML23hAHFOctmjZQffKD2pywkhtSGHKNtpitLroscAeE7kCkSsC60vxEl6yMtL9EL5HKGCMszU5bk8gdkklAyEn5FO0yK419rIxBOIqwFMooDE0tHEVYijAUECIshRCGIhxFWIowFJ5QkEYIS5PTJrUwNGlPyN6QQPyKtpuM1E/K5+YJDV/MiA3AaehzqgAm7QnZG9IGYKo8bHnSK7VblLL3hOwNHziPuEGOqE5brrdR6i+atCfckyeWD47HkAkepRGLY/e8A8J0gCwYSNypF08bBm+e6zVz2UL4AshhBUjML/rXLefqC82bcQFhGC9JDwZ1uuu+At0S5gCETYHsV4DUeD9fDN2Zfy5OXaW2zAwQygCzBLJ8cvaW5OXKC1FxfTggFAHmoAJnSiOw2wps9KwRWgJCLaEswaj5NqkLwAYIU4BxqTSXbHXpJdRMPZgAOiAMqABCNGYIEEJutEK5IUAIwYMDQgiCACEEAcJs1Vda7gGqDhCmoiEghAAhBAHCrKXVo2C1DCBMRlp37uMIEECoX7xrX3P5C9QiINSuIcoPAUI0YkAICLNWgfJDh4T9hH7zqYH9+JHAq7zBqWjwhPAicTVCVQJCNF50JghHocahKK0X/ZnQKyEkhSdUpzG8OgQI42qC94EQjsYLRSmH+pbgq73L6bYkeEJ4DYTYmeg1TOBFc/usTTp3V9DdEuXJ2xDCUbXhaXk0/kAYmBvuMB4qkC35E5e5AMKkwSQgyxufyuPy6fMMgAFCSI73LFXU/N8AmEL9X4ABACNSKMHAgb34AAAAAElFTkSuQmCC\",\"mediatype\":\"image/png\"}],\"install\":{\"spec\":{\"deployments\":[{\"name\":\"etcd-operator\",\"spec\":{\"replicas\":1,\"selector\":{\"matchLabels\":{\"name\":\"etcd-operator-alm-owned\"}},\"template\":{\"metadata\":{\"labels\":{\"name\":\"etcd-operator-alm-owned\"},\"name\":\"etcd-operator-alm-owned\"},\"spec\":{\"containers\":[{\"command\":[\"etcd-operator\",\"--create-crd=false\"],\"env\":[{\"name\":\"MY_POD_NAMESPACE\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"metadata.namespace\"}}},{\"name\":\"MY_POD_NAME\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"metadata.name\"}}}],\"image\":\"quay.io/coreos/etcd-operator@sha256:c0301e4686c3ed4206e370b42de5a3bd2229b9fb4906cf85f3f30650424abec2\",\"name\":\"etcd-operator\"},{\"command\":[\"etcd-backup-operator\",\"--create-crd=false\"],\"env\":[{\"name\":\"MY_POD_NAMESPACE\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"metadata.namespace\"}}},{\"name\":\"MY_POD_NAME\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"metadata.name\"}}}],\"image\":\"quay.io/coreos/etcd-operator@sha256:c0301e4686c3ed4206e370b42de5a3bd2229b9fb4906cf85f3f30650424abec2\",\"name\":\"etcd-backup-operator\"},{\"command\":[\"etcd-restore-operator\",\"--create-crd=false\"],\"env\":[{\"name\":\"MY_POD_NAMESPACE\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"metadata.namespace\"}}},{\"name\":\"MY_POD_NAME\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"metadata.name\"}}}],\"image\":\"quay.io/coreos/etcd-operator@sha256:c0301e4686c3ed4206e370b42de5a3bd2229b9fb4906cf85f3f30650424abec2\",\"name\":\"etcd-restore-operator\"}],\"serviceAccountName\":\"etcd-operator\"}}}}],\"permissions\":[{\"rules\":[{\"apiGroups\":[\"etcd.database.coreos.com\"],\"resources\":[\"etcdclusters\",\"etcdbackups\",\"etcdrestores\"],\"verbs\":[\"*\"]},{\"apiGroups\":[\"\"],\"resources\":[\"pods\",\"services\",\"endpoints\",\"persistentvolumeclaims\",\"events\"],\"verbs\":[\"*\"]},{\"apiGroups\":[\"apps\"],\"resources\":[\"deployments\"],\"verbs\":[\"*\"]},{\"apiGroups\":[\"\"],\"resources\":[\"secrets\"],\"verbs\":[\"get\"]}],\"serviceAccountName\":\"etcd-operator\"}]},\"strategy\":\"deployment\"},\"keywords\":[\"etcd\",\"key value\",\"database\",\"coreos\",\"open source\"],\"labels\":{\"alm-owner-etcd\":\"etcdoperator\",\"operated-by\":\"etcdoperator\"},\"links\":[{\"name\":\"Blog\",\"url\":\"https://coreos.com/etcd\"},{\"name\":\"Documentation\",\"url\":\"https://coreos.com/operators/etcd/docs/latest/\"},{\"name\":\"etcd Operator Source Code\",\"url\":\"https://github.com/coreos/etcd-operator\"}],\"maintainers\":[{\"email\":\"support@coreos.com\",\"name\":\"CoreOS, Inc\"}],\"maturity\":\"alpha\",\"provider\":{\"name\":\"CoreOS, Inc\"},\"replaces\":\"etcdoperator.v0.9.0\",\"selector\":{\"matchLabels\":{\"alm-owner-etcd\":\"etcdoperator\",\"operated-by\":\"etcdoperator\"}},\"skips\":[\"etcdoperator.v0.9.1\"],\"version\":\"0.9.2\"}}", + expectedCSV, "{\"apiVersion\":\"apiextensions.k8s.io/v1beta1\",\"kind\":\"CustomResourceDefinition\",\"metadata\":{\"name\":\"etcdrestores.etcd.database.coreos.com\"},\"spec\":{\"group\":\"etcd.database.coreos.com\",\"names\":{\"kind\":\"EtcdRestore\",\"listKind\":\"EtcdRestoreList\",\"plural\":\"etcdrestores\",\"singular\":\"etcdrestore\"},\"scope\":\"Namespaced\",\"version\":\"v1beta2\"}}", } } -func testExpectedProperties() []property.Property { +func testExpectedProperties(t *testing.T) []property.Property { + t.Helper() + var csv v1alpha1.ClusterServiceVersion + if err := json.Unmarshal([]byte(expectedCSV), &csv); err != nil { + t.Fatalf("failed to unmarshal CSV: %v", err) + } props := []property.Property{ property.MustBuildPackage("etcd", "0.9.2"), property.MustBuildGVKRequired("etcd.database.coreos.com", "v1beta2", "EtcdCluster"), @@ -49,10 +57,7 @@ func testExpectedProperties() []property.Property { Type: "olm.constraint", Value: json.RawMessage(`{"cel":{"rule":"properties.exists(p, p.type == \"certified\")"},"failureMessage":"require to have \"certified\""}`), }, - } - - for _, obj := range testExpectedObjects() { - props = append(props, property.MustBuildBundleObjectData([]byte(obj))) + property.MustBuildCSVMetadata(csv), } return props } diff --git a/staging/operator-registry/pkg/registry/tar.go b/staging/operator-registry/pkg/registry/tar.go new file mode 100644 index 0000000000..f62a15da85 --- /dev/null +++ b/staging/operator-registry/pkg/registry/tar.go @@ -0,0 +1,66 @@ +package registry + +import ( + "archive/tar" + "fmt" + "io" + "io/fs" + "os" + "time" +) + +// fsToTar writes the filesystem represented by fsys to w as a tar archive. +// This function unsets user and group information in the tar archive so that readers +// of archives produced by this function do not need to account for differences in +// permissions between source and destination filesystems. +func fsToTar(w io.Writer, fsys fs.FS) error { + tw := tar.NewWriter(w) + if err := fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + + if d.Type()&os.ModeSymlink != 0 { + return nil + } + info, err := d.Info() + if err != nil { + return fmt.Errorf("get file info for %q: %v", path, err) + } + + h, err := tar.FileInfoHeader(info, "") + if err != nil { + return fmt.Errorf("build tar file info header for %q: %v", path, err) + } + h.Uid = 0 + h.Gid = 0 + h.Uname = "" + h.Gname = "" + h.AccessTime = time.Time{} + h.ChangeTime = time.Time{} + h.ModTime = time.Time{} + h.Name = path + + if err := tw.WriteHeader(h); err != nil { + return fmt.Errorf("write tar header for %q: %v", path, err) + } + if d.IsDir() { + return nil + } + f, err := fsys.Open(path) + if err != nil { + return fmt.Errorf("open file %q: %v", path, err) + } + defer f.Close() + if _, err := io.Copy(tw, f); err != nil { + return fmt.Errorf("write tar data for %q: %v", path, err) + } + return nil + }); err != nil { + return fmt.Errorf("write tar: %w", err) + } + if err := tw.Close(); err != nil { + return err + } + return nil +} diff --git a/staging/operator-registry/pkg/server/server_test.go b/staging/operator-registry/pkg/server/server_test.go index a3f001d123..03cf206462 100644 --- a/staging/operator-registry/pkg/server/server_test.go +++ b/staging/operator-registry/pkg/server/server_test.go @@ -1,6 +1,7 @@ package server import ( + "fmt" "io" "net" "os" @@ -50,10 +51,13 @@ func createDBStore(dbPath string) *sqlite.SQLQuerier { if err := loader.Populate(); err != nil { logrus.Fatal(err) } + if _, err := db.Exec("UPDATE operatorbundle SET bundlepath = 'fake/etcd-operator:v0.9.2' WHERE name = 'etcdoperator.v0.9.2'"); err != nil { + logrus.Fatal(err) + } if err := db.Close(); err != nil { logrus.Fatal(err) } - store, err := sqlite.NewSQLLiteQuerier(dbPath) + store, err := sqlite.NewSQLLiteQuerier(dbPath, sqlite.OmitManifests(true)) if err != nil { logrus.Fatal(err) } @@ -62,7 +66,7 @@ func createDBStore(dbPath string) *sqlite.SQLQuerier { func fbcJsonCache(catalogDir, cacheDir string) (cache2.Cache, error) { store := cache2.NewJSON(cacheDir) - if err := store.Build(os.DirFS(catalogDir)); err != nil { + if err := store.Build(context.Background(), os.DirFS(catalogDir)); err != nil { return nil, err } if err := store.Load(); err != nil { @@ -217,8 +221,8 @@ func testGetPackage(addr string) func(*testing.T) { } func TestGetBundle(t *testing.T) { - t.Run("Sqlite", testGetBundle(dbAddress, etcdoperator_v0_9_2("alpha", false, false))) - t.Run("FBCJsonCache", testGetBundle(jsonCacheAddress, etcdoperator_v0_9_2("alpha", false, true))) + t.Run("Sqlite", testGetBundle(dbAddress, etcdoperator_v0_9_2("alpha", false, false, includeManifestsAll))) + t.Run("FBCJsonCache", testGetBundle(jsonCacheAddress, etcdoperator_v0_9_2("alpha", false, true, includeManifestsCSVOnly))) } func testGetBundle(addr string, expected *api.Bundle) func(*testing.T) { @@ -235,13 +239,13 @@ func testGetBundle(addr string, expected *api.Bundle) func(*testing.T) { func TestGetBundleForChannel(t *testing.T) { { - b := etcdoperator_v0_9_2("alpha", false, false) + b := etcdoperator_v0_9_2("alpha", false, false, includeManifestsAll) t.Run("Sqlite", testGetBundleForChannel(dbAddress, &api.Bundle{ CsvName: b.CsvName, CsvJson: b.CsvJson + "\n", })) } - t.Run("FBCJsonCache", testGetBundleForChannel(jsonCacheAddress, etcdoperator_v0_9_2("alpha", false, true))) + t.Run("FBCJsonCache", testGetBundleForChannel(jsonCacheAddress, etcdoperator_v0_9_2("alpha", false, true, includeManifestsCSVOnly))) } func testGetBundleForChannel(addr string, expected *api.Bundle) func(*testing.T) { @@ -332,8 +336,8 @@ func testGetChannelEntriesThatReplace(addr string) func(*testing.T) { } func TestGetBundleThatReplaces(t *testing.T) { - t.Run("Sqlite", testGetBundleThatReplaces(dbAddress, etcdoperator_v0_9_2("alpha", false, false))) - t.Run("FBCJsonCache", testGetBundleThatReplaces(jsonCacheAddress, etcdoperator_v0_9_2("alpha", false, true))) + t.Run("Sqlite", testGetBundleThatReplaces(dbAddress, etcdoperator_v0_9_2("alpha", false, false, includeManifestsAll))) + t.Run("FBCJsonCache", testGetBundleThatReplaces(jsonCacheAddress, etcdoperator_v0_9_2("alpha", false, true, includeManifestsCSVOnly))) } func testGetBundleThatReplaces(addr string, expected *api.Bundle) func(*testing.T) { @@ -348,8 +352,8 @@ func testGetBundleThatReplaces(addr string, expected *api.Bundle) func(*testing. } func TestGetBundleThatReplacesSynthetic(t *testing.T) { - t.Run("Sqlite", testGetBundleThatReplacesSynthetic(dbAddress, etcdoperator_v0_9_2("alpha", false, false))) - t.Run("FBCJsonCache", testGetBundleThatReplacesSynthetic(jsonCacheAddress, etcdoperator_v0_9_2("alpha", false, true))) + t.Run("Sqlite", testGetBundleThatReplacesSynthetic(dbAddress, etcdoperator_v0_9_2("alpha", false, false, includeManifestsAll))) + t.Run("FBCJsonCache", testGetBundleThatReplacesSynthetic(jsonCacheAddress, etcdoperator_v0_9_2("alpha", false, true, includeManifestsCSVOnly))) } func testGetBundleThatReplacesSynthetic(addr string, expected *api.Bundle) func(*testing.T) { @@ -558,8 +562,8 @@ func testGetLatestChannelEntriesThatProvide(addr string) func(t *testing.T) { } func TestGetDefaultBundleThatProvides(t *testing.T) { - t.Run("Sqlite", testGetDefaultBundleThatProvides(dbAddress, etcdoperator_v0_9_2("alpha", false, false))) - t.Run("FBCJsonCache", testGetDefaultBundleThatProvides(jsonCacheAddress, etcdoperator_v0_9_2("alpha", false, true))) + t.Run("Sqlite", testGetDefaultBundleThatProvides(dbAddress, etcdoperator_v0_9_2("alpha", false, false, includeManifestsAll))) + t.Run("FBCJsonCache", testGetDefaultBundleThatProvides(jsonCacheAddress, etcdoperator_v0_9_2("alpha", false, true, includeManifestsCSVOnly))) } func testGetDefaultBundleThatProvides(addr string, expected *api.Bundle) func(*testing.T) { @@ -575,11 +579,11 @@ func testGetDefaultBundleThatProvides(addr string, expected *api.Bundle) func(*t func TestListBundles(t *testing.T) { t.Run("Sqlite", testListBundles(dbAddress, - etcdoperator_v0_9_2("alpha", true, false), - etcdoperator_v0_9_2("stable", true, false))) + etcdoperator_v0_9_2("alpha", true, false, includeManifestsNone), + etcdoperator_v0_9_2("stable", true, false, includeManifestsNone))) t.Run("FBCJsonCache", testListBundles(jsonCacheAddress, - etcdoperator_v0_9_2("alpha", true, true), - etcdoperator_v0_9_2("stable", true, true))) + etcdoperator_v0_9_2("alpha", true, true, includeManifestsNone), + etcdoperator_v0_9_2("stable", true, true, includeManifestsNone))) } func testListBundles(addr string, etcdAlpha *api.Bundle, etcdStable *api.Bundle) func(*testing.T) { @@ -695,19 +699,20 @@ func stripPlural(gvks []*api.GroupVersionKind) { } } -func etcdoperator_v0_9_2(channel string, addSkipsReplaces, addExtraProperties bool) *api.Bundle { +type includeManifests string + +const ( + includeManifestsAll includeManifests = "all" + includeManifestsNone includeManifests = "none" + includeManifestsCSVOnly includeManifests = "csvOnly" +) + +func etcdoperator_v0_9_2(channel string, addSkipsReplaces, addExtraProperties bool, includeManifests includeManifests) *api.Bundle { b := &api.Bundle{ CsvName: "etcdoperator.v0.9.2", PackageName: "etcd", ChannelName: channel, - CsvJson: "{\"apiVersion\":\"operators.coreos.com/v1alpha1\",\"kind\":\"ClusterServiceVersion\",\"metadata\":{\"annotations\":{\"alm-examples\":\"[{\\\"apiVersion\\\":\\\"etcd.database.coreos.com/v1beta2\\\",\\\"kind\\\":\\\"EtcdCluster\\\",\\\"metadata\\\":{\\\"name\\\":\\\"example\\\",\\\"namespace\\\":\\\"default\\\"},\\\"spec\\\":{\\\"size\\\":3,\\\"version\\\":\\\"3.2.13\\\"}},{\\\"apiVersion\\\":\\\"etcd.database.coreos.com/v1beta2\\\",\\\"kind\\\":\\\"EtcdRestore\\\",\\\"metadata\\\":{\\\"name\\\":\\\"example-etcd-cluster\\\"},\\\"spec\\\":{\\\"etcdCluster\\\":{\\\"name\\\":\\\"example-etcd-cluster\\\"},\\\"backupStorageType\\\":\\\"S3\\\",\\\"s3\\\":{\\\"path\\\":\\\"\\u003cfull-s3-path\\u003e\\\",\\\"awsSecret\\\":\\\"\\u003caws-secret\\u003e\\\"}}},{\\\"apiVersion\\\":\\\"etcd.database.coreos.com/v1beta2\\\",\\\"kind\\\":\\\"EtcdBackup\\\",\\\"metadata\\\":{\\\"name\\\":\\\"example-etcd-cluster-backup\\\"},\\\"spec\\\":{\\\"etcdEndpoints\\\":[\\\"\\u003cetcd-cluster-endpoints\\u003e\\\"],\\\"storageType\\\":\\\"S3\\\",\\\"s3\\\":{\\\"path\\\":\\\"\\u003cfull-s3-path\\u003e\\\",\\\"awsSecret\\\":\\\"\\u003caws-secret\\u003e\\\"}}}]\",\"olm.properties\":\"[{\\\"type\\\":\\\"other\\\",\\\"value\\\":{\\\"its\\\":\\\"notdefined\\\"}},{\\\"type\\\":\\\"olm.label\\\",\\\"value\\\":{\\\"label\\\":\\\"testlabel\\\"}},{\\\"type\\\":\\\"olm.label\\\",\\\"value\\\":{\\\"label\\\":\\\"testlabel1\\\"}}]\",\"olm.skipRange\":\"\\u003c 0.6.0\",\"tectonic-visibility\":\"ocs\"},\"name\":\"etcdoperator.v0.9.2\",\"namespace\":\"placeholder\"},\"spec\":{\"customresourcedefinitions\":{\"owned\":[{\"description\":\"Represents a cluster of etcd nodes.\",\"displayName\":\"etcd Cluster\",\"kind\":\"EtcdCluster\",\"name\":\"etcdclusters.etcd.database.coreos.com\",\"resources\":[{\"kind\":\"Service\",\"version\":\"v1\"},{\"kind\":\"Pod\",\"version\":\"v1\"}],\"specDescriptors\":[{\"description\":\"The desired number of member Pods for the etcd cluster.\",\"displayName\":\"Size\",\"path\":\"size\",\"x-descriptors\":[\"urn:alm:descriptor:com.tectonic.ui:podCount\"]},{\"description\":\"Limits describes the minimum/maximum amount of compute resources required/allowed\",\"displayName\":\"Resource Requirements\",\"path\":\"pod.resources\",\"x-descriptors\":[\"urn:alm:descriptor:com.tectonic.ui:resourceRequirements\"]}],\"statusDescriptors\":[{\"description\":\"The status of each of the member Pods for the etcd cluster.\",\"displayName\":\"Member Status\",\"path\":\"members\",\"x-descriptors\":[\"urn:alm:descriptor:com.tectonic.ui:podStatuses\"]},{\"description\":\"The service at which the running etcd cluster can be accessed.\",\"displayName\":\"Service\",\"path\":\"serviceName\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes:Service\"]},{\"description\":\"The current size of the etcd cluster.\",\"displayName\":\"Cluster Size\",\"path\":\"size\"},{\"description\":\"The current version of the etcd cluster.\",\"displayName\":\"Current Version\",\"path\":\"currentVersion\"},{\"description\":\"The target version of the etcd cluster, after upgrading.\",\"displayName\":\"Target Version\",\"path\":\"targetVersion\"},{\"description\":\"The current status of the etcd cluster.\",\"displayName\":\"Status\",\"path\":\"phase\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes.phase\"]},{\"description\":\"Explanation for the current status of the cluster.\",\"displayName\":\"Status Details\",\"path\":\"reason\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes.phase:reason\"]}],\"version\":\"v1beta2\"},{\"description\":\"Represents the intent to backup an etcd cluster.\",\"displayName\":\"etcd Backup\",\"kind\":\"EtcdBackup\",\"name\":\"etcdbackups.etcd.database.coreos.com\",\"specDescriptors\":[{\"description\":\"Specifies the endpoints of an etcd cluster.\",\"displayName\":\"etcd Endpoint(s)\",\"path\":\"etcdEndpoints\",\"x-descriptors\":[\"urn:alm:descriptor:etcd:endpoint\"]},{\"description\":\"The full AWS S3 path where the backup is saved.\",\"displayName\":\"S3 Path\",\"path\":\"s3.path\",\"x-descriptors\":[\"urn:alm:descriptor:aws:s3:path\"]},{\"description\":\"The name of the secret object that stores the AWS credential and config files.\",\"displayName\":\"AWS Secret\",\"path\":\"s3.awsSecret\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes:Secret\"]}],\"statusDescriptors\":[{\"description\":\"Indicates if the backup was successful.\",\"displayName\":\"Succeeded\",\"path\":\"succeeded\",\"x-descriptors\":[\"urn:alm:descriptor:text\"]},{\"description\":\"Indicates the reason for any backup related failures.\",\"displayName\":\"Reason\",\"path\":\"reason\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes.phase:reason\"]}],\"version\":\"v1beta2\"},{\"description\":\"Represents the intent to restore an etcd cluster from a backup.\",\"displayName\":\"etcd Restore\",\"kind\":\"EtcdRestore\",\"name\":\"etcdrestores.etcd.database.coreos.com\",\"specDescriptors\":[{\"description\":\"References the EtcdCluster which should be restored,\",\"displayName\":\"etcd Cluster\",\"path\":\"etcdCluster.name\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes:EtcdCluster\",\"urn:alm:descriptor:text\"]},{\"description\":\"The full AWS S3 path where the backup is saved.\",\"displayName\":\"S3 Path\",\"path\":\"s3.path\",\"x-descriptors\":[\"urn:alm:descriptor:aws:s3:path\"]},{\"description\":\"The name of the secret object that stores the AWS credential and config files.\",\"displayName\":\"AWS Secret\",\"path\":\"s3.awsSecret\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes:Secret\"]}],\"statusDescriptors\":[{\"description\":\"Indicates if the restore was successful.\",\"displayName\":\"Succeeded\",\"path\":\"succeeded\",\"x-descriptors\":[\"urn:alm:descriptor:text\"]},{\"description\":\"Indicates the reason for any restore related failures.\",\"displayName\":\"Reason\",\"path\":\"reason\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes.phase:reason\"]}],\"version\":\"v1beta2\"}],\"required\":[{\"description\":\"Represents a cluster of etcd nodes.\",\"displayName\":\"etcd Cluster\",\"kind\":\"EtcdCluster\",\"name\":\"etcdclusters.etcd.database.coreos.com\",\"resources\":[{\"kind\":\"Service\",\"version\":\"v1\"},{\"kind\":\"Pod\",\"version\":\"v1\"}],\"specDescriptors\":[{\"description\":\"The desired number of member Pods for the etcd cluster.\",\"displayName\":\"Size\",\"path\":\"size\",\"x-descriptors\":[\"urn:alm:descriptor:com.tectonic.ui:podCount\"]}],\"version\":\"v1beta2\"}]},\"description\":\"etcd is a distributed key value store that provides a reliable way to store data across a cluster of machines. It’s open-source and available on GitHub. etcd gracefully handles leader elections during network partitions and will tolerate machine failure, including the leader. Your applications can read and write data into etcd.\\nA simple use-case is to store database connection details or feature flags within etcd as key value pairs. These values can be watched, allowing your app to reconfigure itself when they change. Advanced uses take advantage of the consistency guarantees to implement database leader elections or do distributed locking across a cluster of workers.\\n\\n_The etcd Open Cloud Service is Public Alpha. The goal before Beta is to fully implement backup features._\\n\\n### Reading and writing to etcd\\n\\nCommunicate with etcd though its command line utility `etcdctl` or with the API using the automatically generated Kubernetes Service.\\n\\n[Read the complete guide to using the etcd Open Cloud Service](https://coreos.com/tectonic/docs/latest/alm/etcd-ocs.html)\\n\\n### Supported Features\\n\\n\\n**High availability**\\n\\n\\nMultiple instances of etcd are networked together and secured. Individual failures or networking issues are transparently handled to keep your cluster up and running.\\n\\n\\n**Automated updates**\\n\\n\\nRolling out a new etcd version works like all Kubernetes rolling updates. Simply declare the desired version, and the etcd service starts a safe rolling update to the new version automatically.\\n\\n\\n**Backups included**\\n\\n\\nComing soon, the ability to schedule backups to happen on or off cluster.\\n\",\"displayName\":\"etcd\",\"icon\":[{\"base64data\":\"iVBORw0KGgoAAAANSUhEUgAAAOEAAADZCAYAAADWmle6AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAEKlJREFUeNrsndt1GzkShmEev4sTgeiHfRYdgVqbgOgITEVgOgLTEQydwIiKwFQCayoCU6+7DyYjsBiBFyVVz7RkXvqCSxXw/+f04XjGQ6IL+FBVuL769euXgZ7r39f/G9iP0X+u/jWDNZzZdGI/Ftama1jjuV4BwmcNpbAf1Fgu+V/9YRvNAyzT2a59+/GT/3hnn5m16wKWedJrmOCxkYztx9Q+py/+E0GJxtJdReWfz+mxNt+QzS2Mc0AI+HbBBwj9QViKbH5t64DsP2fvmGXUkWU4WgO+Uve2YQzBUGd7r+zH2ZG/tiUQc4QxKwgbwFfVGwwmdLL5wH78aPC/ZBem9jJpCAX3xtcNASSNgJLzUPSQyjB1zQNl8IQJ9MIU4lx2+Jo72ysXYKl1HSzN02BMa/vbZ5xyNJIshJzwf3L0dQhJw4Sih/SFw9Tk8sVeghVPoefaIYCkMZCKbrcP9lnZuk0uPUjGE/KE8JQry7W2tgfuC3vXgvNV+qSQbyFtAtyWk7zWiYevvuUQ9QEQCvJ+5mmu6dTjz1zFHLFj8Eb87MtxaZh/IQFIHom+9vgTWwZxAQjT9X4vtbEVPojwjiV471s00mhAckpwGuCn1HtFtRDaSh6y9zsL+LNBvCG/24ThcxHObdlWc1v+VQJe8LcO0jwtuF8BwnAAUgP9M8JPU2Me+Oh12auPGT6fHuTePE3bLDy+x9pTLnhMn+07TQGh//Bz1iI0c6kvtqInjvPZcYR3KsPVmUsPYt9nFig9SCY8VQNhpPBzn952bbgcsk2EvM89wzh3UEffBbyPqvBUBYQ8ODGPFOLsa7RF096WJ69L+E4EmnpjWu5o4ChlKaRTKT39RMMaVPEQRsz/nIWlDN80chjdJlSd1l0pJCAMVZsniobQVuxceMM9OFoaMd9zqZtjMEYYDW38Drb8Y0DYPLShxn0pvIFuOSxd7YCPet9zk452wsh54FJoeN05hcgSQoG5RR0Qh9Q4E4VvL4wcZq8UACgaRFEQKgSwWrkr5WFnGxiHSutqJGlXjBgIOayhwYBTA0ER0oisIVSUV0AAMT0IASCUO4hRIQSAEECMCCEPwqyQA0JCQBzEGjWNAqHiUVAoXUWbvggOIQCEAOJzxTjoaQ4AIaE64/aZridUsBYUgkhB15oGg1DBIl8IqirYwV6hPSGBSFteMCUBSVXwfYixBmamRubeMyjzMJQBDDowE3OesDD+zwqFoDqiEwXoXJpljB+PvWJGy75BKF1FPxhKygJuqUdYQGlLxNEXkrYyjQ0GbaAwEnUIlLRNvVjQDYUAsJB0HKLE4y0AIpQNgCIhBIhQTgCKhZBBpAN/v6LtQI50JfUgYOnnjmLUFHKhjxbAmdTCaTiBm3ovLPqG2urWAij6im0Nd9aTN9ygLUEt9LgSRnohxUPIKxlGaE+/6Y7znFf0yX+GnkvFFWmarkab2o9PmTeq8sbd2a7DaysXz7i64VeznN4jCQhN9gdDbRiuWrfrsq0mHIrlaq+hlotCtd3Um9u0BYWY8y5D67wccJoZjFca7iUs9VqZcfsZwTd1sbWGG+OcYaTnPAP7rTQVVlM4Sg3oGvB1tmNh0t/HKXZ1jFoIMwCQjtqbhNxUmkGYqgZEDZP11HN/S3gAYRozf0l8C5kKEKUvW0t1IfeWG/5MwgheZTT1E0AEhDkAePQO+Ig2H3DncAkQM4cwUQCD530dU4B5Yvmi2LlDqXfWrxMCcMth51RToRMNUXFnfc2KJ0+Ryl0VNOUwlhh6NoxK5gnViTgQpUG4SqSyt5z3zRJpuKmt3Q1614QaCBPaN6je+2XiFcWAKOXcUfIYKRyL/1lb7pe5VxSxxjQ6hImshqGRt5GWZVKO6q2wHwujfwDtIvaIdexj8Cm8+a68EqMfox6x/voMouZF4dHnEGNeCDMwT6vdNfekH1MafMk4PI06YtqLVGl95aEM9Z5vAeCTOA++YLtoVJRrsqNCaJ6WRmkdYaNec5BT/lcTRMqrhmwfjbpkj55+OKp8IEbU/JLgPJE6Wa3TTe9sHS+ShVD5QIyqIxMEwKh12olC6mHIed5ewEop80CNlfIOADYOT2nd6ZXCop+Ebqchc0JqxKcKASxChycJgUh1rnHA5ow9eTrhqNI7JWiAYYwBGGdpyNLoGw0Pkh96h1BpHihyywtATDM/7Hk2fN9EnH8BgKJCU4ooBkbXFMZJiPbrOyecGl3zgQDQL4hk10IZiOe+5w99Q/gBAEIJgPhJM4QAEEoFREAIAAEiIASAkD8Qt4AQAEIAERAGFlX4CACKAXGVM4ivMwWwCLFAlyeoaa70QePKm5Dlp+/n+ye/5dYgva6YsUaVeMa+tzNFeJtWwc+udbJ0Fg399kLielQJ5Ze61c2+7ytA6EZetiPxZC6tj22yJCv6jUwOyj/zcbqAxOMyAKEbfeHtNa7DtYXptjsk2kJxR+eIeim/tHNofUKYy8DMrQcAKWz6brpvzyIAlpwPhQ49l6b7skJf5Z+YTOYQc4FwLDxvoTDwaygQK+U/kVr+ytSFBG01Q3gnJJR4cNiAhx4HDub8/b5DULXlj6SVZghFiE+LdvE9vo/o8Lp1RmH5hzm0T6wdbZ6n+D6i44zDRc3ln6CpAEJfXiRU45oqLz8gFAThWsh7ughrRibc0QynHgZpNJa/ENJ+loCwu/qOGnFIjYR/n7TfgycULhcQhu6VC+HfF+L3BoAQ4WiZTw1M+FPCnA2gKC6/FAhXgDC+ojQGh3NuWsvfF1L/D5ohlCKtl1j2ldu9a/nPAKFwN56Bst10zCG0CPleXN/zXPgHQZXaZaBgrbzyY5V/mUA+6F0hwtGN9rwu5DVZPuwWqfxdFz1LWbJ2lwKEa+0Qsm4Dl3fp+Pu0lV97PgwIPfSsS+UQhj5Oo+vvFULazRIQyvGEcxPuNLCth2MvFsrKn8UOilAQShkh7TTczYNMoS6OdP47msrPi82lXKGWhCdMZYS0bFy+vcnGAjP1CIfvgbKNA9glecEH9RD6Ol4wRuWyN/G9MHnksS6o/GPf5XcwNSUlHzQhDuAKtWJmkwKElU7lylP5rgIcsquh/FI8YZCDpkJBuE4FQm7Icw8N+SrUGaQKyi8FwiDt1ve5o+Vu7qYHy/psgK8cvh+FTYuO77bhEC7GuaPiys/L1X4IgXDL+e3M5+ovLxBy5VLuIebw1oqcHoPfoaMJUsHays878r8KbDc3xtPx/84gZPBG/JwaufrsY/SRG/OY3//8QMNdsvdZCFtbW6f8pFuf5bflILAlX7O+4fdfugKyFYS8T2zAsXthdG0VurPGKwI06oF5vkBgHWkNp6ry29+lsPZMU3vijnXFNmoclr+6+Ou/FIb8yb30sS8YGjmTqCLyQsi5N/6ZwKs0Yenj68pfPjF6N782Dp2FzV9CTyoSeY8mLK16qGxIkLI8oa1n8tz9juP40DlK0epxYEbojbq+9QfurBeVIlCO9D2396bxiV4lkYQ3hOAFw2pbhqMGISkkQOMcQ9EqhDmGZZdo92JC0YHRNTfoSg+5e0IT+opqCKHoIU+4ztQIgBD1EFNrQAgIpYSil9lDmPHqkROPt+JC6AgPquSuumJmg0YARVCuneDfvPVeJokZ6pIXDkNxQtGzTF9/BQjRG0tQznfb74RwCQghpALBtIQnfK4zhxdyQvVCUeknMIT3hLyY+T5jo0yABqKPQNpUNw/09tGZod5jgCaYFxyYvJcNPkv9eof+I3pnCFEHIETjSM8L9tHZHYCQT9PaZGycU6yg8S4akDnJ+P03L0+t23XGzCLzRgII/Wqa+fv/xlfvmKvMUOcOrlCDdoei1MGdZm6G5VEIfRzzjd4aQs69n699Rx7ewhvCGzr2gmTPs8zNsJOrXt24FbkhhOjCfT4ICA/rPbyhUy94Dks0gJCX1NzCZui9YUd3oei+c257TalFbgg19ILHrlrL2gvWgXAL26EX76gZTNASQnad8Ibwhl284NhgXpB0c+jKhWO3Ms1hP9ihJYB9eMF6qd1BCPk0qA1s+LimFIu7m4nsdQIzPK4VbQ8hYvrnuSH2G9b2ggP78QmWqBdF9Vx8SSY6QYdUW7BTA1schZATyhvY8lHvcRbNUS9YGFy2U+qmzh2YPVc0I7yAOFyHfRpyUwtCSzOdPXMHmz7qDIM0e0V2wZTEk+6Ym6N63eBLp/b5Bts+2cKCSJ/LuoZO3ANSiE5hKAZjnvNSS4931jcw9jpwT0feV/qSJ1pVtCyfHKDkvK8Ejx7pUxGh2xFNSwx8QTi2H9ceC0/nni64MS/5N5dG39pDqvRV+WgGk71c9VFXF9b+xYvOw/d61iv7m3MvEHryhvecwC52jSSx4VIIgwnMNT/UsTxIgpPt3K/ARj15CptwL3Zd/ceDSATj2DGQjbxgWwhdeMMte7zpy5On9vymRm/YxBYljGVjKWF9VJf7I1+sex3wY8w/V1QPTborW/72gkdsRDaZMJBdbdHIC7aCkAu9atlLbtnrzerMnyToDaGwelOnk3/hHSem/ZK7e/t7jeeR20LYBgqa8J80gS8jbwi5F02Uj1u2NYJxap8PLkJfLxA2hIJyvnHX/AfeEPLpBfe0uSFHbnXaea3Qd5d6HcpYZ8L6M7lnFwMQ3MNg+RxUR1+6AshtbsVgfXTEg1sIGax9UND2p7f270wdG3eK9gXVGHdw2k5sOyZv+Nbs39Z308XR9DqWb2J+PwKDhuKHPobfuXf7gnYGHdCs7bhDDadD4entDug7LWNsnRNW4mYqwJ9dk+GGSTPBiA2j0G8RWNM5upZtcG4/3vMfP7KnbK2egx6CCnDPhRn7NgD3cghLIad5WcM2SO38iqHvvMOosyeMpQ5zlVCaaj06GVs9xUbHdiKoqrHWgquFEFMWUEWfXUxJAML23hAHFOctmjZQffKD2pywkhtSGHKNtpitLroscAeE7kCkSsC60vxEl6yMtL9EL5HKGCMszU5bk8gdkklAyEn5FO0yK419rIxBOIqwFMooDE0tHEVYijAUECIshRCGIhxFWIowFJ5QkEYIS5PTJrUwNGlPyN6QQPyKtpuM1E/K5+YJDV/MiA3AaehzqgAm7QnZG9IGYKo8bHnSK7VblLL3hOwNHziPuEGOqE5brrdR6i+atCfckyeWD47HkAkepRGLY/e8A8J0gCwYSNypF08bBm+e6zVz2UL4AshhBUjML/rXLefqC82bcQFhGC9JDwZ1uuu+At0S5gCETYHsV4DUeD9fDN2Zfy5OXaW2zAwQygCzBLJ8cvaW5OXKC1FxfTggFAHmoAJnSiOw2wps9KwRWgJCLaEswaj5NqkLwAYIU4BxqTSXbHXpJdRMPZgAOiAMqABCNGYIEEJutEK5IUAIwYMDQgiCACEEAcJs1Vda7gGqDhCmoiEghAAhBAHCrKXVo2C1DCBMRlp37uMIEECoX7xrX3P5C9QiINSuIcoPAUI0YkAICLNWgfJDh4T9hH7zqYH9+JHAq7zBqWjwhPAicTVCVQJCNF50JghHocahKK0X/ZnQKyEkhSdUpzG8OgQI42qC94EQjsYLRSmH+pbgq73L6bYkeEJ4DYTYmeg1TOBFc/usTTp3V9DdEuXJ2xDCUbXhaXk0/kAYmBvuMB4qkC35E5e5AMKkwSQgyxufyuPy6fMMgAFCSI73LFXU/N8AmEL9X4ABACNSKMHAgb34AAAAAElFTkSuQmCC\",\"mediatype\":\"image/png\"}],\"install\":{\"spec\":{\"deployments\":[{\"name\":\"etcd-operator\",\"spec\":{\"replicas\":1,\"selector\":{\"matchLabels\":{\"name\":\"etcd-operator-alm-owned\"}},\"template\":{\"metadata\":{\"labels\":{\"name\":\"etcd-operator-alm-owned\"},\"name\":\"etcd-operator-alm-owned\"},\"spec\":{\"containers\":[{\"command\":[\"etcd-operator\",\"--create-crd=false\"],\"env\":[{\"name\":\"MY_POD_NAMESPACE\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"metadata.namespace\"}}},{\"name\":\"MY_POD_NAME\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"metadata.name\"}}}],\"image\":\"quay.io/coreos/etcd-operator@sha256:c0301e4686c3ed4206e370b42de5a3bd2229b9fb4906cf85f3f30650424abec2\",\"name\":\"etcd-operator\"},{\"command\":[\"etcd-backup-operator\",\"--create-crd=false\"],\"env\":[{\"name\":\"MY_POD_NAMESPACE\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"metadata.namespace\"}}},{\"name\":\"MY_POD_NAME\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"metadata.name\"}}}],\"image\":\"quay.io/coreos/etcd-operator@sha256:c0301e4686c3ed4206e370b42de5a3bd2229b9fb4906cf85f3f30650424abec2\",\"name\":\"etcd-backup-operator\"},{\"command\":[\"etcd-restore-operator\",\"--create-crd=false\"],\"env\":[{\"name\":\"MY_POD_NAMESPACE\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"metadata.namespace\"}}},{\"name\":\"MY_POD_NAME\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"metadata.name\"}}}],\"image\":\"quay.io/coreos/etcd-operator@sha256:c0301e4686c3ed4206e370b42de5a3bd2229b9fb4906cf85f3f30650424abec2\",\"name\":\"etcd-restore-operator\"}],\"serviceAccountName\":\"etcd-operator\"}}}}],\"permissions\":[{\"rules\":[{\"apiGroups\":[\"etcd.database.coreos.com\"],\"resources\":[\"etcdclusters\",\"etcdbackups\",\"etcdrestores\"],\"verbs\":[\"*\"]},{\"apiGroups\":[\"\"],\"resources\":[\"pods\",\"services\",\"endpoints\",\"persistentvolumeclaims\",\"events\"],\"verbs\":[\"*\"]},{\"apiGroups\":[\"apps\"],\"resources\":[\"deployments\"],\"verbs\":[\"*\"]},{\"apiGroups\":[\"\"],\"resources\":[\"secrets\"],\"verbs\":[\"get\"]}],\"serviceAccountName\":\"etcd-operator\"}]},\"strategy\":\"deployment\"},\"keywords\":[\"etcd\",\"key value\",\"database\",\"coreos\",\"open source\"],\"labels\":{\"alm-owner-etcd\":\"etcdoperator\",\"operated-by\":\"etcdoperator\"},\"links\":[{\"name\":\"Blog\",\"url\":\"https://coreos.com/etcd\"},{\"name\":\"Documentation\",\"url\":\"https://coreos.com/operators/etcd/docs/latest/\"},{\"name\":\"etcd Operator Source Code\",\"url\":\"https://github.com/coreos/etcd-operator\"}],\"maintainers\":[{\"email\":\"support@coreos.com\",\"name\":\"CoreOS, Inc\"}],\"maturity\":\"alpha\",\"provider\":{\"name\":\"CoreOS, Inc\"},\"relatedImages\":[{\"image\":\"quay.io/coreos/etcd@sha256:3816b6daf9b66d6ced6f0f966314e2d4f894982c6b1493061502f8c2bf86ac84\",\"name\":\"etcd-v3.4.0\"},{\"image\":\"quay.io/coreos/etcd@sha256:49d3d4a81e0d030d3f689e7167f23e120abf955f7d08dbedf3ea246485acee9f\",\"name\":\"etcd-3.4.1\"}],\"replaces\":\"etcdoperator.v0.9.0\",\"selector\":{\"matchLabels\":{\"alm-owner-etcd\":\"etcdoperator\",\"operated-by\":\"etcdoperator\"}},\"skips\":[\"etcdoperator.v0.9.1\"],\"version\":\"0.9.2\"}}", - Object: []string{ - "{\"apiVersion\":\"apiextensions.k8s.io/v1beta1\",\"kind\":\"CustomResourceDefinition\",\"metadata\":{\"name\":\"etcdbackups.etcd.database.coreos.com\"},\"spec\":{\"group\":\"etcd.database.coreos.com\",\"names\":{\"kind\":\"EtcdBackup\",\"listKind\":\"EtcdBackupList\",\"plural\":\"etcdbackups\",\"singular\":\"etcdbackup\"},\"scope\":\"Namespaced\",\"version\":\"v1beta2\"}}", - "{\"apiVersion\":\"apiextensions.k8s.io/v1beta1\",\"kind\":\"CustomResourceDefinition\",\"metadata\":{\"name\":\"etcdclusters.etcd.database.coreos.com\"},\"spec\":{\"group\":\"etcd.database.coreos.com\",\"names\":{\"kind\":\"EtcdCluster\",\"listKind\":\"EtcdClusterList\",\"plural\":\"etcdclusters\",\"shortNames\":[\"etcdclus\",\"etcd\"],\"singular\":\"etcdcluster\"},\"scope\":\"Namespaced\",\"version\":\"v1beta2\"}}", - "{\"apiVersion\":\"operators.coreos.com/v1alpha1\",\"kind\":\"ClusterServiceVersion\",\"metadata\":{\"annotations\":{\"alm-examples\":\"[{\\\"apiVersion\\\":\\\"etcd.database.coreos.com/v1beta2\\\",\\\"kind\\\":\\\"EtcdCluster\\\",\\\"metadata\\\":{\\\"name\\\":\\\"example\\\",\\\"namespace\\\":\\\"default\\\"},\\\"spec\\\":{\\\"size\\\":3,\\\"version\\\":\\\"3.2.13\\\"}},{\\\"apiVersion\\\":\\\"etcd.database.coreos.com/v1beta2\\\",\\\"kind\\\":\\\"EtcdRestore\\\",\\\"metadata\\\":{\\\"name\\\":\\\"example-etcd-cluster\\\"},\\\"spec\\\":{\\\"etcdCluster\\\":{\\\"name\\\":\\\"example-etcd-cluster\\\"},\\\"backupStorageType\\\":\\\"S3\\\",\\\"s3\\\":{\\\"path\\\":\\\"\\u003cfull-s3-path\\u003e\\\",\\\"awsSecret\\\":\\\"\\u003caws-secret\\u003e\\\"}}},{\\\"apiVersion\\\":\\\"etcd.database.coreos.com/v1beta2\\\",\\\"kind\\\":\\\"EtcdBackup\\\",\\\"metadata\\\":{\\\"name\\\":\\\"example-etcd-cluster-backup\\\"},\\\"spec\\\":{\\\"etcdEndpoints\\\":[\\\"\\u003cetcd-cluster-endpoints\\u003e\\\"],\\\"storageType\\\":\\\"S3\\\",\\\"s3\\\":{\\\"path\\\":\\\"\\u003cfull-s3-path\\u003e\\\",\\\"awsSecret\\\":\\\"\\u003caws-secret\\u003e\\\"}}}]\",\"olm.properties\":\"[{\\\"type\\\":\\\"other\\\",\\\"value\\\":{\\\"its\\\":\\\"notdefined\\\"}},{\\\"type\\\":\\\"olm.label\\\",\\\"value\\\":{\\\"label\\\":\\\"testlabel\\\"}},{\\\"type\\\":\\\"olm.label\\\",\\\"value\\\":{\\\"label\\\":\\\"testlabel1\\\"}}]\",\"olm.skipRange\":\"\\u003c 0.6.0\",\"tectonic-visibility\":\"ocs\"},\"name\":\"etcdoperator.v0.9.2\",\"namespace\":\"placeholder\"},\"spec\":{\"customresourcedefinitions\":{\"owned\":[{\"description\":\"Represents a cluster of etcd nodes.\",\"displayName\":\"etcd Cluster\",\"kind\":\"EtcdCluster\",\"name\":\"etcdclusters.etcd.database.coreos.com\",\"resources\":[{\"kind\":\"Service\",\"version\":\"v1\"},{\"kind\":\"Pod\",\"version\":\"v1\"}],\"specDescriptors\":[{\"description\":\"The desired number of member Pods for the etcd cluster.\",\"displayName\":\"Size\",\"path\":\"size\",\"x-descriptors\":[\"urn:alm:descriptor:com.tectonic.ui:podCount\"]},{\"description\":\"Limits describes the minimum/maximum amount of compute resources required/allowed\",\"displayName\":\"Resource Requirements\",\"path\":\"pod.resources\",\"x-descriptors\":[\"urn:alm:descriptor:com.tectonic.ui:resourceRequirements\"]}],\"statusDescriptors\":[{\"description\":\"The status of each of the member Pods for the etcd cluster.\",\"displayName\":\"Member Status\",\"path\":\"members\",\"x-descriptors\":[\"urn:alm:descriptor:com.tectonic.ui:podStatuses\"]},{\"description\":\"The service at which the running etcd cluster can be accessed.\",\"displayName\":\"Service\",\"path\":\"serviceName\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes:Service\"]},{\"description\":\"The current size of the etcd cluster.\",\"displayName\":\"Cluster Size\",\"path\":\"size\"},{\"description\":\"The current version of the etcd cluster.\",\"displayName\":\"Current Version\",\"path\":\"currentVersion\"},{\"description\":\"The target version of the etcd cluster, after upgrading.\",\"displayName\":\"Target Version\",\"path\":\"targetVersion\"},{\"description\":\"The current status of the etcd cluster.\",\"displayName\":\"Status\",\"path\":\"phase\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes.phase\"]},{\"description\":\"Explanation for the current status of the cluster.\",\"displayName\":\"Status Details\",\"path\":\"reason\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes.phase:reason\"]}],\"version\":\"v1beta2\"},{\"description\":\"Represents the intent to backup an etcd cluster.\",\"displayName\":\"etcd Backup\",\"kind\":\"EtcdBackup\",\"name\":\"etcdbackups.etcd.database.coreos.com\",\"specDescriptors\":[{\"description\":\"Specifies the endpoints of an etcd cluster.\",\"displayName\":\"etcd Endpoint(s)\",\"path\":\"etcdEndpoints\",\"x-descriptors\":[\"urn:alm:descriptor:etcd:endpoint\"]},{\"description\":\"The full AWS S3 path where the backup is saved.\",\"displayName\":\"S3 Path\",\"path\":\"s3.path\",\"x-descriptors\":[\"urn:alm:descriptor:aws:s3:path\"]},{\"description\":\"The name of the secret object that stores the AWS credential and config files.\",\"displayName\":\"AWS Secret\",\"path\":\"s3.awsSecret\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes:Secret\"]}],\"statusDescriptors\":[{\"description\":\"Indicates if the backup was successful.\",\"displayName\":\"Succeeded\",\"path\":\"succeeded\",\"x-descriptors\":[\"urn:alm:descriptor:text\"]},{\"description\":\"Indicates the reason for any backup related failures.\",\"displayName\":\"Reason\",\"path\":\"reason\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes.phase:reason\"]}],\"version\":\"v1beta2\"},{\"description\":\"Represents the intent to restore an etcd cluster from a backup.\",\"displayName\":\"etcd Restore\",\"kind\":\"EtcdRestore\",\"name\":\"etcdrestores.etcd.database.coreos.com\",\"specDescriptors\":[{\"description\":\"References the EtcdCluster which should be restored,\",\"displayName\":\"etcd Cluster\",\"path\":\"etcdCluster.name\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes:EtcdCluster\",\"urn:alm:descriptor:text\"]},{\"description\":\"The full AWS S3 path where the backup is saved.\",\"displayName\":\"S3 Path\",\"path\":\"s3.path\",\"x-descriptors\":[\"urn:alm:descriptor:aws:s3:path\"]},{\"description\":\"The name of the secret object that stores the AWS credential and config files.\",\"displayName\":\"AWS Secret\",\"path\":\"s3.awsSecret\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes:Secret\"]}],\"statusDescriptors\":[{\"description\":\"Indicates if the restore was successful.\",\"displayName\":\"Succeeded\",\"path\":\"succeeded\",\"x-descriptors\":[\"urn:alm:descriptor:text\"]},{\"description\":\"Indicates the reason for any restore related failures.\",\"displayName\":\"Reason\",\"path\":\"reason\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes.phase:reason\"]}],\"version\":\"v1beta2\"}],\"required\":[{\"description\":\"Represents a cluster of etcd nodes.\",\"displayName\":\"etcd Cluster\",\"kind\":\"EtcdCluster\",\"name\":\"etcdclusters.etcd.database.coreos.com\",\"resources\":[{\"kind\":\"Service\",\"version\":\"v1\"},{\"kind\":\"Pod\",\"version\":\"v1\"}],\"specDescriptors\":[{\"description\":\"The desired number of member Pods for the etcd cluster.\",\"displayName\":\"Size\",\"path\":\"size\",\"x-descriptors\":[\"urn:alm:descriptor:com.tectonic.ui:podCount\"]}],\"version\":\"v1beta2\"}]},\"description\":\"etcd is a distributed key value store that provides a reliable way to store data across a cluster of machines. It’s open-source and available on GitHub. etcd gracefully handles leader elections during network partitions and will tolerate machine failure, including the leader. Your applications can read and write data into etcd.\\nA simple use-case is to store database connection details or feature flags within etcd as key value pairs. These values can be watched, allowing your app to reconfigure itself when they change. Advanced uses take advantage of the consistency guarantees to implement database leader elections or do distributed locking across a cluster of workers.\\n\\n_The etcd Open Cloud Service is Public Alpha. The goal before Beta is to fully implement backup features._\\n\\n### Reading and writing to etcd\\n\\nCommunicate with etcd though its command line utility `etcdctl` or with the API using the automatically generated Kubernetes Service.\\n\\n[Read the complete guide to using the etcd Open Cloud Service](https://coreos.com/tectonic/docs/latest/alm/etcd-ocs.html)\\n\\n### Supported Features\\n\\n\\n**High availability**\\n\\n\\nMultiple instances of etcd are networked together and secured. Individual failures or networking issues are transparently handled to keep your cluster up and running.\\n\\n\\n**Automated updates**\\n\\n\\nRolling out a new etcd version works like all Kubernetes rolling updates. Simply declare the desired version, and the etcd service starts a safe rolling update to the new version automatically.\\n\\n\\n**Backups included**\\n\\n\\nComing soon, the ability to schedule backups to happen on or off cluster.\\n\",\"displayName\":\"etcd\",\"icon\":[{\"base64data\":\"iVBORw0KGgoAAAANSUhEUgAAAOEAAADZCAYAAADWmle6AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAEKlJREFUeNrsndt1GzkShmEev4sTgeiHfRYdgVqbgOgITEVgOgLTEQydwIiKwFQCayoCU6+7DyYjsBiBFyVVz7RkXvqCSxXw/+f04XjGQ6IL+FBVuL769euXgZ7r39f/G9iP0X+u/jWDNZzZdGI/Ftama1jjuV4BwmcNpbAf1Fgu+V/9YRvNAyzT2a59+/GT/3hnn5m16wKWedJrmOCxkYztx9Q+py/+E0GJxtJdReWfz+mxNt+QzS2Mc0AI+HbBBwj9QViKbH5t64DsP2fvmGXUkWU4WgO+Uve2YQzBUGd7r+zH2ZG/tiUQc4QxKwgbwFfVGwwmdLL5wH78aPC/ZBem9jJpCAX3xtcNASSNgJLzUPSQyjB1zQNl8IQJ9MIU4lx2+Jo72ysXYKl1HSzN02BMa/vbZ5xyNJIshJzwf3L0dQhJw4Sih/SFw9Tk8sVeghVPoefaIYCkMZCKbrcP9lnZuk0uPUjGE/KE8JQry7W2tgfuC3vXgvNV+qSQbyFtAtyWk7zWiYevvuUQ9QEQCvJ+5mmu6dTjz1zFHLFj8Eb87MtxaZh/IQFIHom+9vgTWwZxAQjT9X4vtbEVPojwjiV471s00mhAckpwGuCn1HtFtRDaSh6y9zsL+LNBvCG/24ThcxHObdlWc1v+VQJe8LcO0jwtuF8BwnAAUgP9M8JPU2Me+Oh12auPGT6fHuTePE3bLDy+x9pTLnhMn+07TQGh//Bz1iI0c6kvtqInjvPZcYR3KsPVmUsPYt9nFig9SCY8VQNhpPBzn952bbgcsk2EvM89wzh3UEffBbyPqvBUBYQ8ODGPFOLsa7RF096WJ69L+E4EmnpjWu5o4ChlKaRTKT39RMMaVPEQRsz/nIWlDN80chjdJlSd1l0pJCAMVZsniobQVuxceMM9OFoaMd9zqZtjMEYYDW38Drb8Y0DYPLShxn0pvIFuOSxd7YCPet9zk452wsh54FJoeN05hcgSQoG5RR0Qh9Q4E4VvL4wcZq8UACgaRFEQKgSwWrkr5WFnGxiHSutqJGlXjBgIOayhwYBTA0ER0oisIVSUV0AAMT0IASCUO4hRIQSAEECMCCEPwqyQA0JCQBzEGjWNAqHiUVAoXUWbvggOIQCEAOJzxTjoaQ4AIaE64/aZridUsBYUgkhB15oGg1DBIl8IqirYwV6hPSGBSFteMCUBSVXwfYixBmamRubeMyjzMJQBDDowE3OesDD+zwqFoDqiEwXoXJpljB+PvWJGy75BKF1FPxhKygJuqUdYQGlLxNEXkrYyjQ0GbaAwEnUIlLRNvVjQDYUAsJB0HKLE4y0AIpQNgCIhBIhQTgCKhZBBpAN/v6LtQI50JfUgYOnnjmLUFHKhjxbAmdTCaTiBm3ovLPqG2urWAij6im0Nd9aTN9ygLUEt9LgSRnohxUPIKxlGaE+/6Y7znFf0yX+GnkvFFWmarkab2o9PmTeq8sbd2a7DaysXz7i64VeznN4jCQhN9gdDbRiuWrfrsq0mHIrlaq+hlotCtd3Um9u0BYWY8y5D67wccJoZjFca7iUs9VqZcfsZwTd1sbWGG+OcYaTnPAP7rTQVVlM4Sg3oGvB1tmNh0t/HKXZ1jFoIMwCQjtqbhNxUmkGYqgZEDZP11HN/S3gAYRozf0l8C5kKEKUvW0t1IfeWG/5MwgheZTT1E0AEhDkAePQO+Ig2H3DncAkQM4cwUQCD530dU4B5Yvmi2LlDqXfWrxMCcMth51RToRMNUXFnfc2KJ0+Ryl0VNOUwlhh6NoxK5gnViTgQpUG4SqSyt5z3zRJpuKmt3Q1614QaCBPaN6je+2XiFcWAKOXcUfIYKRyL/1lb7pe5VxSxxjQ6hImshqGRt5GWZVKO6q2wHwujfwDtIvaIdexj8Cm8+a68EqMfox6x/voMouZF4dHnEGNeCDMwT6vdNfekH1MafMk4PI06YtqLVGl95aEM9Z5vAeCTOA++YLtoVJRrsqNCaJ6WRmkdYaNec5BT/lcTRMqrhmwfjbpkj55+OKp8IEbU/JLgPJE6Wa3TTe9sHS+ShVD5QIyqIxMEwKh12olC6mHIed5ewEop80CNlfIOADYOT2nd6ZXCop+Ebqchc0JqxKcKASxChycJgUh1rnHA5ow9eTrhqNI7JWiAYYwBGGdpyNLoGw0Pkh96h1BpHihyywtATDM/7Hk2fN9EnH8BgKJCU4ooBkbXFMZJiPbrOyecGl3zgQDQL4hk10IZiOe+5w99Q/gBAEIJgPhJM4QAEEoFREAIAAEiIASAkD8Qt4AQAEIAERAGFlX4CACKAXGVM4ivMwWwCLFAlyeoaa70QePKm5Dlp+/n+ye/5dYgva6YsUaVeMa+tzNFeJtWwc+udbJ0Fg399kLielQJ5Ze61c2+7ytA6EZetiPxZC6tj22yJCv6jUwOyj/zcbqAxOMyAKEbfeHtNa7DtYXptjsk2kJxR+eIeim/tHNofUKYy8DMrQcAKWz6brpvzyIAlpwPhQ49l6b7skJf5Z+YTOYQc4FwLDxvoTDwaygQK+U/kVr+ytSFBG01Q3gnJJR4cNiAhx4HDub8/b5DULXlj6SVZghFiE+LdvE9vo/o8Lp1RmH5hzm0T6wdbZ6n+D6i44zDRc3ln6CpAEJfXiRU45oqLz8gFAThWsh7ughrRibc0QynHgZpNJa/ENJ+loCwu/qOGnFIjYR/n7TfgycULhcQhu6VC+HfF+L3BoAQ4WiZTw1M+FPCnA2gKC6/FAhXgDC+ojQGh3NuWsvfF1L/D5ohlCKtl1j2ldu9a/nPAKFwN56Bst10zCG0CPleXN/zXPgHQZXaZaBgrbzyY5V/mUA+6F0hwtGN9rwu5DVZPuwWqfxdFz1LWbJ2lwKEa+0Qsm4Dl3fp+Pu0lV97PgwIPfSsS+UQhj5Oo+vvFULazRIQyvGEcxPuNLCth2MvFsrKn8UOilAQShkh7TTczYNMoS6OdP47msrPi82lXKGWhCdMZYS0bFy+vcnGAjP1CIfvgbKNA9glecEH9RD6Ol4wRuWyN/G9MHnksS6o/GPf5XcwNSUlHzQhDuAKtWJmkwKElU7lylP5rgIcsquh/FI8YZCDpkJBuE4FQm7Icw8N+SrUGaQKyi8FwiDt1ve5o+Vu7qYHy/psgK8cvh+FTYuO77bhEC7GuaPiys/L1X4IgXDL+e3M5+ovLxBy5VLuIebw1oqcHoPfoaMJUsHays878r8KbDc3xtPx/84gZPBG/JwaufrsY/SRG/OY3//8QMNdsvdZCFtbW6f8pFuf5bflILAlX7O+4fdfugKyFYS8T2zAsXthdG0VurPGKwI06oF5vkBgHWkNp6ry29+lsPZMU3vijnXFNmoclr+6+Ou/FIb8yb30sS8YGjmTqCLyQsi5N/6ZwKs0Yenj68pfPjF6N782Dp2FzV9CTyoSeY8mLK16qGxIkLI8oa1n8tz9juP40DlK0epxYEbojbq+9QfurBeVIlCO9D2396bxiV4lkYQ3hOAFw2pbhqMGISkkQOMcQ9EqhDmGZZdo92JC0YHRNTfoSg+5e0IT+opqCKHoIU+4ztQIgBD1EFNrQAgIpYSil9lDmPHqkROPt+JC6AgPquSuumJmg0YARVCuneDfvPVeJokZ6pIXDkNxQtGzTF9/BQjRG0tQznfb74RwCQghpALBtIQnfK4zhxdyQvVCUeknMIT3hLyY+T5jo0yABqKPQNpUNw/09tGZod5jgCaYFxyYvJcNPkv9eof+I3pnCFEHIETjSM8L9tHZHYCQT9PaZGycU6yg8S4akDnJ+P03L0+t23XGzCLzRgII/Wqa+fv/xlfvmKvMUOcOrlCDdoei1MGdZm6G5VEIfRzzjd4aQs69n699Rx7ewhvCGzr2gmTPs8zNsJOrXt24FbkhhOjCfT4ICA/rPbyhUy94Dks0gJCX1NzCZui9YUd3oei+c257TalFbgg19ILHrlrL2gvWgXAL26EX76gZTNASQnad8Ibwhl284NhgXpB0c+jKhWO3Ms1hP9ihJYB9eMF6qd1BCPk0qA1s+LimFIu7m4nsdQIzPK4VbQ8hYvrnuSH2G9b2ggP78QmWqBdF9Vx8SSY6QYdUW7BTA1schZATyhvY8lHvcRbNUS9YGFy2U+qmzh2YPVc0I7yAOFyHfRpyUwtCSzOdPXMHmz7qDIM0e0V2wZTEk+6Ym6N63eBLp/b5Bts+2cKCSJ/LuoZO3ANSiE5hKAZjnvNSS4931jcw9jpwT0feV/qSJ1pVtCyfHKDkvK8Ejx7pUxGh2xFNSwx8QTi2H9ceC0/nni64MS/5N5dG39pDqvRV+WgGk71c9VFXF9b+xYvOw/d61iv7m3MvEHryhvecwC52jSSx4VIIgwnMNT/UsTxIgpPt3K/ARj15CptwL3Zd/ceDSATj2DGQjbxgWwhdeMMte7zpy5On9vymRm/YxBYljGVjKWF9VJf7I1+sex3wY8w/V1QPTborW/72gkdsRDaZMJBdbdHIC7aCkAu9atlLbtnrzerMnyToDaGwelOnk3/hHSem/ZK7e/t7jeeR20LYBgqa8J80gS8jbwi5F02Uj1u2NYJxap8PLkJfLxA2hIJyvnHX/AfeEPLpBfe0uSFHbnXaea3Qd5d6HcpYZ8L6M7lnFwMQ3MNg+RxUR1+6AshtbsVgfXTEg1sIGax9UND2p7f270wdG3eK9gXVGHdw2k5sOyZv+Nbs39Z308XR9DqWb2J+PwKDhuKHPobfuXf7gnYGHdCs7bhDDadD4entDug7LWNsnRNW4mYqwJ9dk+GGSTPBiA2j0G8RWNM5upZtcG4/3vMfP7KnbK2egx6CCnDPhRn7NgD3cghLIad5WcM2SO38iqHvvMOosyeMpQ5zlVCaaj06GVs9xUbHdiKoqrHWgquFEFMWUEWfXUxJAML23hAHFOctmjZQffKD2pywkhtSGHKNtpitLroscAeE7kCkSsC60vxEl6yMtL9EL5HKGCMszU5bk8gdkklAyEn5FO0yK419rIxBOIqwFMooDE0tHEVYijAUECIshRCGIhxFWIowFJ5QkEYIS5PTJrUwNGlPyN6QQPyKtpuM1E/K5+YJDV/MiA3AaehzqgAm7QnZG9IGYKo8bHnSK7VblLL3hOwNHziPuEGOqE5brrdR6i+atCfckyeWD47HkAkepRGLY/e8A8J0gCwYSNypF08bBm+e6zVz2UL4AshhBUjML/rXLefqC82bcQFhGC9JDwZ1uuu+At0S5gCETYHsV4DUeD9fDN2Zfy5OXaW2zAwQygCzBLJ8cvaW5OXKC1FxfTggFAHmoAJnSiOw2wps9KwRWgJCLaEswaj5NqkLwAYIU4BxqTSXbHXpJdRMPZgAOiAMqABCNGYIEEJutEK5IUAIwYMDQgiCACEEAcJs1Vda7gGqDhCmoiEghAAhBAHCrKXVo2C1DCBMRlp37uMIEECoX7xrX3P5C9QiINSuIcoPAUI0YkAICLNWgfJDh4T9hH7zqYH9+JHAq7zBqWjwhPAicTVCVQJCNF50JghHocahKK0X/ZnQKyEkhSdUpzG8OgQI42qC94EQjsYLRSmH+pbgq73L6bYkeEJ4DYTYmeg1TOBFc/usTTp3V9DdEuXJ2xDCUbXhaXk0/kAYmBvuMB4qkC35E5e5AMKkwSQgyxufyuPy6fMMgAFCSI73LFXU/N8AmEL9X4ABACNSKMHAgb34AAAAAElFTkSuQmCC\",\"mediatype\":\"image/png\"}],\"install\":{\"spec\":{\"deployments\":[{\"name\":\"etcd-operator\",\"spec\":{\"replicas\":1,\"selector\":{\"matchLabels\":{\"name\":\"etcd-operator-alm-owned\"}},\"template\":{\"metadata\":{\"labels\":{\"name\":\"etcd-operator-alm-owned\"},\"name\":\"etcd-operator-alm-owned\"},\"spec\":{\"containers\":[{\"command\":[\"etcd-operator\",\"--create-crd=false\"],\"env\":[{\"name\":\"MY_POD_NAMESPACE\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"metadata.namespace\"}}},{\"name\":\"MY_POD_NAME\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"metadata.name\"}}}],\"image\":\"quay.io/coreos/etcd-operator@sha256:c0301e4686c3ed4206e370b42de5a3bd2229b9fb4906cf85f3f30650424abec2\",\"name\":\"etcd-operator\"},{\"command\":[\"etcd-backup-operator\",\"--create-crd=false\"],\"env\":[{\"name\":\"MY_POD_NAMESPACE\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"metadata.namespace\"}}},{\"name\":\"MY_POD_NAME\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"metadata.name\"}}}],\"image\":\"quay.io/coreos/etcd-operator@sha256:c0301e4686c3ed4206e370b42de5a3bd2229b9fb4906cf85f3f30650424abec2\",\"name\":\"etcd-backup-operator\"},{\"command\":[\"etcd-restore-operator\",\"--create-crd=false\"],\"env\":[{\"name\":\"MY_POD_NAMESPACE\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"metadata.namespace\"}}},{\"name\":\"MY_POD_NAME\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"metadata.name\"}}}],\"image\":\"quay.io/coreos/etcd-operator@sha256:c0301e4686c3ed4206e370b42de5a3bd2229b9fb4906cf85f3f30650424abec2\",\"name\":\"etcd-restore-operator\"}],\"serviceAccountName\":\"etcd-operator\"}}}}],\"permissions\":[{\"rules\":[{\"apiGroups\":[\"etcd.database.coreos.com\"],\"resources\":[\"etcdclusters\",\"etcdbackups\",\"etcdrestores\"],\"verbs\":[\"*\"]},{\"apiGroups\":[\"\"],\"resources\":[\"pods\",\"services\",\"endpoints\",\"persistentvolumeclaims\",\"events\"],\"verbs\":[\"*\"]},{\"apiGroups\":[\"apps\"],\"resources\":[\"deployments\"],\"verbs\":[\"*\"]},{\"apiGroups\":[\"\"],\"resources\":[\"secrets\"],\"verbs\":[\"get\"]}],\"serviceAccountName\":\"etcd-operator\"}]},\"strategy\":\"deployment\"},\"keywords\":[\"etcd\",\"key value\",\"database\",\"coreos\",\"open source\"],\"labels\":{\"alm-owner-etcd\":\"etcdoperator\",\"operated-by\":\"etcdoperator\"},\"links\":[{\"name\":\"Blog\",\"url\":\"https://coreos.com/etcd\"},{\"name\":\"Documentation\",\"url\":\"https://coreos.com/operators/etcd/docs/latest/\"},{\"name\":\"etcd Operator Source Code\",\"url\":\"https://github.com/coreos/etcd-operator\"}],\"maintainers\":[{\"email\":\"support@coreos.com\",\"name\":\"CoreOS, Inc\"}],\"maturity\":\"alpha\",\"provider\":{\"name\":\"CoreOS, Inc\"},\"relatedImages\":[{\"image\":\"quay.io/coreos/etcd@sha256:3816b6daf9b66d6ced6f0f966314e2d4f894982c6b1493061502f8c2bf86ac84\",\"name\":\"etcd-v3.4.0\"},{\"image\":\"quay.io/coreos/etcd@sha256:49d3d4a81e0d030d3f689e7167f23e120abf955f7d08dbedf3ea246485acee9f\",\"name\":\"etcd-3.4.1\"}],\"replaces\":\"etcdoperator.v0.9.0\",\"selector\":{\"matchLabels\":{\"alm-owner-etcd\":\"etcdoperator\",\"operated-by\":\"etcdoperator\"}},\"skips\":[\"etcdoperator.v0.9.1\"],\"version\":\"0.9.2\"}}", - "{\"apiVersion\":\"apiextensions.k8s.io/v1beta1\",\"kind\":\"CustomResourceDefinition\",\"metadata\":{\"name\":\"etcdrestores.etcd.database.coreos.com\"},\"spec\":{\"group\":\"etcd.database.coreos.com\",\"names\":{\"kind\":\"EtcdRestore\",\"listKind\":\"EtcdRestoreList\",\"plural\":\"etcdrestores\",\"singular\":\"etcdrestore\"},\"scope\":\"Namespaced\",\"version\":\"v1beta2\"}}", - }, - BundlePath: "", + BundlePath: "fake/etcd-operator:v0.9.2", Dependencies: []*api.Dependency{ { Type: "olm.gvk", @@ -764,5 +769,21 @@ func etcdoperator_v0_9_2(channel string, addSkipsReplaces, addExtraProperties bo {Type: "olm.gvk.required", Value: `{"group":"etcd.database.coreos.com","kind":"EtcdCluster","version":"v1beta2"}`}, }...) } + switch includeManifests { + case includeManifestsAll: + b.CsvJson = "{\"apiVersion\":\"operators.coreos.com/v1alpha1\",\"kind\":\"ClusterServiceVersion\",\"metadata\":{\"annotations\":{\"alm-examples\":\"[{\\\"apiVersion\\\":\\\"etcd.database.coreos.com/v1beta2\\\",\\\"kind\\\":\\\"EtcdCluster\\\",\\\"metadata\\\":{\\\"name\\\":\\\"example\\\",\\\"namespace\\\":\\\"default\\\"},\\\"spec\\\":{\\\"size\\\":3,\\\"version\\\":\\\"3.2.13\\\"}},{\\\"apiVersion\\\":\\\"etcd.database.coreos.com/v1beta2\\\",\\\"kind\\\":\\\"EtcdRestore\\\",\\\"metadata\\\":{\\\"name\\\":\\\"example-etcd-cluster\\\"},\\\"spec\\\":{\\\"etcdCluster\\\":{\\\"name\\\":\\\"example-etcd-cluster\\\"},\\\"backupStorageType\\\":\\\"S3\\\",\\\"s3\\\":{\\\"path\\\":\\\"\\u003cfull-s3-path\\u003e\\\",\\\"awsSecret\\\":\\\"\\u003caws-secret\\u003e\\\"}}},{\\\"apiVersion\\\":\\\"etcd.database.coreos.com/v1beta2\\\",\\\"kind\\\":\\\"EtcdBackup\\\",\\\"metadata\\\":{\\\"name\\\":\\\"example-etcd-cluster-backup\\\"},\\\"spec\\\":{\\\"etcdEndpoints\\\":[\\\"\\u003cetcd-cluster-endpoints\\u003e\\\"],\\\"storageType\\\":\\\"S3\\\",\\\"s3\\\":{\\\"path\\\":\\\"\\u003cfull-s3-path\\u003e\\\",\\\"awsSecret\\\":\\\"\\u003caws-secret\\u003e\\\"}}}]\",\"olm.properties\":\"[{\\\"type\\\":\\\"other\\\",\\\"value\\\":{\\\"its\\\":\\\"notdefined\\\"}},{\\\"type\\\":\\\"olm.label\\\",\\\"value\\\":{\\\"label\\\":\\\"testlabel\\\"}},{\\\"type\\\":\\\"olm.label\\\",\\\"value\\\":{\\\"label\\\":\\\"testlabel1\\\"}}]\",\"olm.skipRange\":\"\\u003c 0.6.0\",\"tectonic-visibility\":\"ocs\"},\"name\":\"etcdoperator.v0.9.2\",\"namespace\":\"placeholder\"},\"spec\":{\"customresourcedefinitions\":{\"owned\":[{\"description\":\"Represents a cluster of etcd nodes.\",\"displayName\":\"etcd Cluster\",\"kind\":\"EtcdCluster\",\"name\":\"etcdclusters.etcd.database.coreos.com\",\"resources\":[{\"kind\":\"Service\",\"version\":\"v1\"},{\"kind\":\"Pod\",\"version\":\"v1\"}],\"specDescriptors\":[{\"description\":\"The desired number of member Pods for the etcd cluster.\",\"displayName\":\"Size\",\"path\":\"size\",\"x-descriptors\":[\"urn:alm:descriptor:com.tectonic.ui:podCount\"]},{\"description\":\"Limits describes the minimum/maximum amount of compute resources required/allowed\",\"displayName\":\"Resource Requirements\",\"path\":\"pod.resources\",\"x-descriptors\":[\"urn:alm:descriptor:com.tectonic.ui:resourceRequirements\"]}],\"statusDescriptors\":[{\"description\":\"The status of each of the member Pods for the etcd cluster.\",\"displayName\":\"Member Status\",\"path\":\"members\",\"x-descriptors\":[\"urn:alm:descriptor:com.tectonic.ui:podStatuses\"]},{\"description\":\"The service at which the running etcd cluster can be accessed.\",\"displayName\":\"Service\",\"path\":\"serviceName\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes:Service\"]},{\"description\":\"The current size of the etcd cluster.\",\"displayName\":\"Cluster Size\",\"path\":\"size\"},{\"description\":\"The current version of the etcd cluster.\",\"displayName\":\"Current Version\",\"path\":\"currentVersion\"},{\"description\":\"The target version of the etcd cluster, after upgrading.\",\"displayName\":\"Target Version\",\"path\":\"targetVersion\"},{\"description\":\"The current status of the etcd cluster.\",\"displayName\":\"Status\",\"path\":\"phase\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes.phase\"]},{\"description\":\"Explanation for the current status of the cluster.\",\"displayName\":\"Status Details\",\"path\":\"reason\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes.phase:reason\"]}],\"version\":\"v1beta2\"},{\"description\":\"Represents the intent to backup an etcd cluster.\",\"displayName\":\"etcd Backup\",\"kind\":\"EtcdBackup\",\"name\":\"etcdbackups.etcd.database.coreos.com\",\"specDescriptors\":[{\"description\":\"Specifies the endpoints of an etcd cluster.\",\"displayName\":\"etcd Endpoint(s)\",\"path\":\"etcdEndpoints\",\"x-descriptors\":[\"urn:alm:descriptor:etcd:endpoint\"]},{\"description\":\"The full AWS S3 path where the backup is saved.\",\"displayName\":\"S3 Path\",\"path\":\"s3.path\",\"x-descriptors\":[\"urn:alm:descriptor:aws:s3:path\"]},{\"description\":\"The name of the secret object that stores the AWS credential and config files.\",\"displayName\":\"AWS Secret\",\"path\":\"s3.awsSecret\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes:Secret\"]}],\"statusDescriptors\":[{\"description\":\"Indicates if the backup was successful.\",\"displayName\":\"Succeeded\",\"path\":\"succeeded\",\"x-descriptors\":[\"urn:alm:descriptor:text\"]},{\"description\":\"Indicates the reason for any backup related failures.\",\"displayName\":\"Reason\",\"path\":\"reason\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes.phase:reason\"]}],\"version\":\"v1beta2\"},{\"description\":\"Represents the intent to restore an etcd cluster from a backup.\",\"displayName\":\"etcd Restore\",\"kind\":\"EtcdRestore\",\"name\":\"etcdrestores.etcd.database.coreos.com\",\"specDescriptors\":[{\"description\":\"References the EtcdCluster which should be restored,\",\"displayName\":\"etcd Cluster\",\"path\":\"etcdCluster.name\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes:EtcdCluster\",\"urn:alm:descriptor:text\"]},{\"description\":\"The full AWS S3 path where the backup is saved.\",\"displayName\":\"S3 Path\",\"path\":\"s3.path\",\"x-descriptors\":[\"urn:alm:descriptor:aws:s3:path\"]},{\"description\":\"The name of the secret object that stores the AWS credential and config files.\",\"displayName\":\"AWS Secret\",\"path\":\"s3.awsSecret\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes:Secret\"]}],\"statusDescriptors\":[{\"description\":\"Indicates if the restore was successful.\",\"displayName\":\"Succeeded\",\"path\":\"succeeded\",\"x-descriptors\":[\"urn:alm:descriptor:text\"]},{\"description\":\"Indicates the reason for any restore related failures.\",\"displayName\":\"Reason\",\"path\":\"reason\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes.phase:reason\"]}],\"version\":\"v1beta2\"}],\"required\":[{\"description\":\"Represents a cluster of etcd nodes.\",\"displayName\":\"etcd Cluster\",\"kind\":\"EtcdCluster\",\"name\":\"etcdclusters.etcd.database.coreos.com\",\"resources\":[{\"kind\":\"Service\",\"version\":\"v1\"},{\"kind\":\"Pod\",\"version\":\"v1\"}],\"specDescriptors\":[{\"description\":\"The desired number of member Pods for the etcd cluster.\",\"displayName\":\"Size\",\"path\":\"size\",\"x-descriptors\":[\"urn:alm:descriptor:com.tectonic.ui:podCount\"]}],\"version\":\"v1beta2\"}]},\"description\":\"etcd is a distributed key value store that provides a reliable way to store data across a cluster of machines. It’s open-source and available on GitHub. etcd gracefully handles leader elections during network partitions and will tolerate machine failure, including the leader. Your applications can read and write data into etcd.\\nA simple use-case is to store database connection details or feature flags within etcd as key value pairs. These values can be watched, allowing your app to reconfigure itself when they change. Advanced uses take advantage of the consistency guarantees to implement database leader elections or do distributed locking across a cluster of workers.\\n\\n_The etcd Open Cloud Service is Public Alpha. The goal before Beta is to fully implement backup features._\\n\\n### Reading and writing to etcd\\n\\nCommunicate with etcd though its command line utility `etcdctl` or with the API using the automatically generated Kubernetes Service.\\n\\n[Read the complete guide to using the etcd Open Cloud Service](https://coreos.com/tectonic/docs/latest/alm/etcd-ocs.html)\\n\\n### Supported Features\\n\\n\\n**High availability**\\n\\n\\nMultiple instances of etcd are networked together and secured. Individual failures or networking issues are transparently handled to keep your cluster up and running.\\n\\n\\n**Automated updates**\\n\\n\\nRolling out a new etcd version works like all Kubernetes rolling updates. Simply declare the desired version, and the etcd service starts a safe rolling update to the new version automatically.\\n\\n\\n**Backups included**\\n\\n\\nComing soon, the ability to schedule backups to happen on or off cluster.\\n\",\"displayName\":\"etcd\",\"icon\":[{\"base64data\":\"iVBORw0KGgoAAAANSUhEUgAAAOEAAADZCAYAAADWmle6AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAEKlJREFUeNrsndt1GzkShmEev4sTgeiHfRYdgVqbgOgITEVgOgLTEQydwIiKwFQCayoCU6+7DyYjsBiBFyVVz7RkXvqCSxXw/+f04XjGQ6IL+FBVuL769euXgZ7r39f/G9iP0X+u/jWDNZzZdGI/Ftama1jjuV4BwmcNpbAf1Fgu+V/9YRvNAyzT2a59+/GT/3hnn5m16wKWedJrmOCxkYztx9Q+py/+E0GJxtJdReWfz+mxNt+QzS2Mc0AI+HbBBwj9QViKbH5t64DsP2fvmGXUkWU4WgO+Uve2YQzBUGd7r+zH2ZG/tiUQc4QxKwgbwFfVGwwmdLL5wH78aPC/ZBem9jJpCAX3xtcNASSNgJLzUPSQyjB1zQNl8IQJ9MIU4lx2+Jo72ysXYKl1HSzN02BMa/vbZ5xyNJIshJzwf3L0dQhJw4Sih/SFw9Tk8sVeghVPoefaIYCkMZCKbrcP9lnZuk0uPUjGE/KE8JQry7W2tgfuC3vXgvNV+qSQbyFtAtyWk7zWiYevvuUQ9QEQCvJ+5mmu6dTjz1zFHLFj8Eb87MtxaZh/IQFIHom+9vgTWwZxAQjT9X4vtbEVPojwjiV471s00mhAckpwGuCn1HtFtRDaSh6y9zsL+LNBvCG/24ThcxHObdlWc1v+VQJe8LcO0jwtuF8BwnAAUgP9M8JPU2Me+Oh12auPGT6fHuTePE3bLDy+x9pTLnhMn+07TQGh//Bz1iI0c6kvtqInjvPZcYR3KsPVmUsPYt9nFig9SCY8VQNhpPBzn952bbgcsk2EvM89wzh3UEffBbyPqvBUBYQ8ODGPFOLsa7RF096WJ69L+E4EmnpjWu5o4ChlKaRTKT39RMMaVPEQRsz/nIWlDN80chjdJlSd1l0pJCAMVZsniobQVuxceMM9OFoaMd9zqZtjMEYYDW38Drb8Y0DYPLShxn0pvIFuOSxd7YCPet9zk452wsh54FJoeN05hcgSQoG5RR0Qh9Q4E4VvL4wcZq8UACgaRFEQKgSwWrkr5WFnGxiHSutqJGlXjBgIOayhwYBTA0ER0oisIVSUV0AAMT0IASCUO4hRIQSAEECMCCEPwqyQA0JCQBzEGjWNAqHiUVAoXUWbvggOIQCEAOJzxTjoaQ4AIaE64/aZridUsBYUgkhB15oGg1DBIl8IqirYwV6hPSGBSFteMCUBSVXwfYixBmamRubeMyjzMJQBDDowE3OesDD+zwqFoDqiEwXoXJpljB+PvWJGy75BKF1FPxhKygJuqUdYQGlLxNEXkrYyjQ0GbaAwEnUIlLRNvVjQDYUAsJB0HKLE4y0AIpQNgCIhBIhQTgCKhZBBpAN/v6LtQI50JfUgYOnnjmLUFHKhjxbAmdTCaTiBm3ovLPqG2urWAij6im0Nd9aTN9ygLUEt9LgSRnohxUPIKxlGaE+/6Y7znFf0yX+GnkvFFWmarkab2o9PmTeq8sbd2a7DaysXz7i64VeznN4jCQhN9gdDbRiuWrfrsq0mHIrlaq+hlotCtd3Um9u0BYWY8y5D67wccJoZjFca7iUs9VqZcfsZwTd1sbWGG+OcYaTnPAP7rTQVVlM4Sg3oGvB1tmNh0t/HKXZ1jFoIMwCQjtqbhNxUmkGYqgZEDZP11HN/S3gAYRozf0l8C5kKEKUvW0t1IfeWG/5MwgheZTT1E0AEhDkAePQO+Ig2H3DncAkQM4cwUQCD530dU4B5Yvmi2LlDqXfWrxMCcMth51RToRMNUXFnfc2KJ0+Ryl0VNOUwlhh6NoxK5gnViTgQpUG4SqSyt5z3zRJpuKmt3Q1614QaCBPaN6je+2XiFcWAKOXcUfIYKRyL/1lb7pe5VxSxxjQ6hImshqGRt5GWZVKO6q2wHwujfwDtIvaIdexj8Cm8+a68EqMfox6x/voMouZF4dHnEGNeCDMwT6vdNfekH1MafMk4PI06YtqLVGl95aEM9Z5vAeCTOA++YLtoVJRrsqNCaJ6WRmkdYaNec5BT/lcTRMqrhmwfjbpkj55+OKp8IEbU/JLgPJE6Wa3TTe9sHS+ShVD5QIyqIxMEwKh12olC6mHIed5ewEop80CNlfIOADYOT2nd6ZXCop+Ebqchc0JqxKcKASxChycJgUh1rnHA5ow9eTrhqNI7JWiAYYwBGGdpyNLoGw0Pkh96h1BpHihyywtATDM/7Hk2fN9EnH8BgKJCU4ooBkbXFMZJiPbrOyecGl3zgQDQL4hk10IZiOe+5w99Q/gBAEIJgPhJM4QAEEoFREAIAAEiIASAkD8Qt4AQAEIAERAGFlX4CACKAXGVM4ivMwWwCLFAlyeoaa70QePKm5Dlp+/n+ye/5dYgva6YsUaVeMa+tzNFeJtWwc+udbJ0Fg399kLielQJ5Ze61c2+7ytA6EZetiPxZC6tj22yJCv6jUwOyj/zcbqAxOMyAKEbfeHtNa7DtYXptjsk2kJxR+eIeim/tHNofUKYy8DMrQcAKWz6brpvzyIAlpwPhQ49l6b7skJf5Z+YTOYQc4FwLDxvoTDwaygQK+U/kVr+ytSFBG01Q3gnJJR4cNiAhx4HDub8/b5DULXlj6SVZghFiE+LdvE9vo/o8Lp1RmH5hzm0T6wdbZ6n+D6i44zDRc3ln6CpAEJfXiRU45oqLz8gFAThWsh7ughrRibc0QynHgZpNJa/ENJ+loCwu/qOGnFIjYR/n7TfgycULhcQhu6VC+HfF+L3BoAQ4WiZTw1M+FPCnA2gKC6/FAhXgDC+ojQGh3NuWsvfF1L/D5ohlCKtl1j2ldu9a/nPAKFwN56Bst10zCG0CPleXN/zXPgHQZXaZaBgrbzyY5V/mUA+6F0hwtGN9rwu5DVZPuwWqfxdFz1LWbJ2lwKEa+0Qsm4Dl3fp+Pu0lV97PgwIPfSsS+UQhj5Oo+vvFULazRIQyvGEcxPuNLCth2MvFsrKn8UOilAQShkh7TTczYNMoS6OdP47msrPi82lXKGWhCdMZYS0bFy+vcnGAjP1CIfvgbKNA9glecEH9RD6Ol4wRuWyN/G9MHnksS6o/GPf5XcwNSUlHzQhDuAKtWJmkwKElU7lylP5rgIcsquh/FI8YZCDpkJBuE4FQm7Icw8N+SrUGaQKyi8FwiDt1ve5o+Vu7qYHy/psgK8cvh+FTYuO77bhEC7GuaPiys/L1X4IgXDL+e3M5+ovLxBy5VLuIebw1oqcHoPfoaMJUsHays878r8KbDc3xtPx/84gZPBG/JwaufrsY/SRG/OY3//8QMNdsvdZCFtbW6f8pFuf5bflILAlX7O+4fdfugKyFYS8T2zAsXthdG0VurPGKwI06oF5vkBgHWkNp6ry29+lsPZMU3vijnXFNmoclr+6+Ou/FIb8yb30sS8YGjmTqCLyQsi5N/6ZwKs0Yenj68pfPjF6N782Dp2FzV9CTyoSeY8mLK16qGxIkLI8oa1n8tz9juP40DlK0epxYEbojbq+9QfurBeVIlCO9D2396bxiV4lkYQ3hOAFw2pbhqMGISkkQOMcQ9EqhDmGZZdo92JC0YHRNTfoSg+5e0IT+opqCKHoIU+4ztQIgBD1EFNrQAgIpYSil9lDmPHqkROPt+JC6AgPquSuumJmg0YARVCuneDfvPVeJokZ6pIXDkNxQtGzTF9/BQjRG0tQznfb74RwCQghpALBtIQnfK4zhxdyQvVCUeknMIT3hLyY+T5jo0yABqKPQNpUNw/09tGZod5jgCaYFxyYvJcNPkv9eof+I3pnCFEHIETjSM8L9tHZHYCQT9PaZGycU6yg8S4akDnJ+P03L0+t23XGzCLzRgII/Wqa+fv/xlfvmKvMUOcOrlCDdoei1MGdZm6G5VEIfRzzjd4aQs69n699Rx7ewhvCGzr2gmTPs8zNsJOrXt24FbkhhOjCfT4ICA/rPbyhUy94Dks0gJCX1NzCZui9YUd3oei+c257TalFbgg19ILHrlrL2gvWgXAL26EX76gZTNASQnad8Ibwhl284NhgXpB0c+jKhWO3Ms1hP9ihJYB9eMF6qd1BCPk0qA1s+LimFIu7m4nsdQIzPK4VbQ8hYvrnuSH2G9b2ggP78QmWqBdF9Vx8SSY6QYdUW7BTA1schZATyhvY8lHvcRbNUS9YGFy2U+qmzh2YPVc0I7yAOFyHfRpyUwtCSzOdPXMHmz7qDIM0e0V2wZTEk+6Ym6N63eBLp/b5Bts+2cKCSJ/LuoZO3ANSiE5hKAZjnvNSS4931jcw9jpwT0feV/qSJ1pVtCyfHKDkvK8Ejx7pUxGh2xFNSwx8QTi2H9ceC0/nni64MS/5N5dG39pDqvRV+WgGk71c9VFXF9b+xYvOw/d61iv7m3MvEHryhvecwC52jSSx4VIIgwnMNT/UsTxIgpPt3K/ARj15CptwL3Zd/ceDSATj2DGQjbxgWwhdeMMte7zpy5On9vymRm/YxBYljGVjKWF9VJf7I1+sex3wY8w/V1QPTborW/72gkdsRDaZMJBdbdHIC7aCkAu9atlLbtnrzerMnyToDaGwelOnk3/hHSem/ZK7e/t7jeeR20LYBgqa8J80gS8jbwi5F02Uj1u2NYJxap8PLkJfLxA2hIJyvnHX/AfeEPLpBfe0uSFHbnXaea3Qd5d6HcpYZ8L6M7lnFwMQ3MNg+RxUR1+6AshtbsVgfXTEg1sIGax9UND2p7f270wdG3eK9gXVGHdw2k5sOyZv+Nbs39Z308XR9DqWb2J+PwKDhuKHPobfuXf7gnYGHdCs7bhDDadD4entDug7LWNsnRNW4mYqwJ9dk+GGSTPBiA2j0G8RWNM5upZtcG4/3vMfP7KnbK2egx6CCnDPhRn7NgD3cghLIad5WcM2SO38iqHvvMOosyeMpQ5zlVCaaj06GVs9xUbHdiKoqrHWgquFEFMWUEWfXUxJAML23hAHFOctmjZQffKD2pywkhtSGHKNtpitLroscAeE7kCkSsC60vxEl6yMtL9EL5HKGCMszU5bk8gdkklAyEn5FO0yK419rIxBOIqwFMooDE0tHEVYijAUECIshRCGIhxFWIowFJ5QkEYIS5PTJrUwNGlPyN6QQPyKtpuM1E/K5+YJDV/MiA3AaehzqgAm7QnZG9IGYKo8bHnSK7VblLL3hOwNHziPuEGOqE5brrdR6i+atCfckyeWD47HkAkepRGLY/e8A8J0gCwYSNypF08bBm+e6zVz2UL4AshhBUjML/rXLefqC82bcQFhGC9JDwZ1uuu+At0S5gCETYHsV4DUeD9fDN2Zfy5OXaW2zAwQygCzBLJ8cvaW5OXKC1FxfTggFAHmoAJnSiOw2wps9KwRWgJCLaEswaj5NqkLwAYIU4BxqTSXbHXpJdRMPZgAOiAMqABCNGYIEEJutEK5IUAIwYMDQgiCACEEAcJs1Vda7gGqDhCmoiEghAAhBAHCrKXVo2C1DCBMRlp37uMIEECoX7xrX3P5C9QiINSuIcoPAUI0YkAICLNWgfJDh4T9hH7zqYH9+JHAq7zBqWjwhPAicTVCVQJCNF50JghHocahKK0X/ZnQKyEkhSdUpzG8OgQI42qC94EQjsYLRSmH+pbgq73L6bYkeEJ4DYTYmeg1TOBFc/usTTp3V9DdEuXJ2xDCUbXhaXk0/kAYmBvuMB4qkC35E5e5AMKkwSQgyxufyuPy6fMMgAFCSI73LFXU/N8AmEL9X4ABACNSKMHAgb34AAAAAElFTkSuQmCC\",\"mediatype\":\"image/png\"}],\"install\":{\"spec\":{\"deployments\":[{\"name\":\"etcd-operator\",\"spec\":{\"replicas\":1,\"selector\":{\"matchLabels\":{\"name\":\"etcd-operator-alm-owned\"}},\"template\":{\"metadata\":{\"labels\":{\"name\":\"etcd-operator-alm-owned\"},\"name\":\"etcd-operator-alm-owned\"},\"spec\":{\"containers\":[{\"command\":[\"etcd-operator\",\"--create-crd=false\"],\"env\":[{\"name\":\"MY_POD_NAMESPACE\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"metadata.namespace\"}}},{\"name\":\"MY_POD_NAME\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"metadata.name\"}}}],\"image\":\"quay.io/coreos/etcd-operator@sha256:c0301e4686c3ed4206e370b42de5a3bd2229b9fb4906cf85f3f30650424abec2\",\"name\":\"etcd-operator\"},{\"command\":[\"etcd-backup-operator\",\"--create-crd=false\"],\"env\":[{\"name\":\"MY_POD_NAMESPACE\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"metadata.namespace\"}}},{\"name\":\"MY_POD_NAME\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"metadata.name\"}}}],\"image\":\"quay.io/coreos/etcd-operator@sha256:c0301e4686c3ed4206e370b42de5a3bd2229b9fb4906cf85f3f30650424abec2\",\"name\":\"etcd-backup-operator\"},{\"command\":[\"etcd-restore-operator\",\"--create-crd=false\"],\"env\":[{\"name\":\"MY_POD_NAMESPACE\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"metadata.namespace\"}}},{\"name\":\"MY_POD_NAME\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"metadata.name\"}}}],\"image\":\"quay.io/coreos/etcd-operator@sha256:c0301e4686c3ed4206e370b42de5a3bd2229b9fb4906cf85f3f30650424abec2\",\"name\":\"etcd-restore-operator\"}],\"serviceAccountName\":\"etcd-operator\"}}}}],\"permissions\":[{\"rules\":[{\"apiGroups\":[\"etcd.database.coreos.com\"],\"resources\":[\"etcdclusters\",\"etcdbackups\",\"etcdrestores\"],\"verbs\":[\"*\"]},{\"apiGroups\":[\"\"],\"resources\":[\"pods\",\"services\",\"endpoints\",\"persistentvolumeclaims\",\"events\"],\"verbs\":[\"*\"]},{\"apiGroups\":[\"apps\"],\"resources\":[\"deployments\"],\"verbs\":[\"*\"]},{\"apiGroups\":[\"\"],\"resources\":[\"secrets\"],\"verbs\":[\"get\"]}],\"serviceAccountName\":\"etcd-operator\"}]},\"strategy\":\"deployment\"},\"keywords\":[\"etcd\",\"key value\",\"database\",\"coreos\",\"open source\"],\"labels\":{\"alm-owner-etcd\":\"etcdoperator\",\"operated-by\":\"etcdoperator\"},\"links\":[{\"name\":\"Blog\",\"url\":\"https://coreos.com/etcd\"},{\"name\":\"Documentation\",\"url\":\"https://coreos.com/operators/etcd/docs/latest/\"},{\"name\":\"etcd Operator Source Code\",\"url\":\"https://github.com/coreos/etcd-operator\"}],\"maintainers\":[{\"email\":\"support@coreos.com\",\"name\":\"CoreOS, Inc\"}],\"maturity\":\"alpha\",\"provider\":{\"name\":\"CoreOS, Inc\"},\"relatedImages\":[{\"image\":\"quay.io/coreos/etcd@sha256:3816b6daf9b66d6ced6f0f966314e2d4f894982c6b1493061502f8c2bf86ac84\",\"name\":\"etcd-v3.4.0\"},{\"image\":\"quay.io/coreos/etcd@sha256:49d3d4a81e0d030d3f689e7167f23e120abf955f7d08dbedf3ea246485acee9f\",\"name\":\"etcd-3.4.1\"}],\"replaces\":\"etcdoperator.v0.9.0\",\"selector\":{\"matchLabels\":{\"alm-owner-etcd\":\"etcdoperator\",\"operated-by\":\"etcdoperator\"}},\"skips\":[\"etcdoperator.v0.9.1\"],\"version\":\"0.9.2\"}}" + b.Object = []string{ + "{\"apiVersion\":\"apiextensions.k8s.io/v1beta1\",\"kind\":\"CustomResourceDefinition\",\"metadata\":{\"name\":\"etcdbackups.etcd.database.coreos.com\"},\"spec\":{\"group\":\"etcd.database.coreos.com\",\"names\":{\"kind\":\"EtcdBackup\",\"listKind\":\"EtcdBackupList\",\"plural\":\"etcdbackups\",\"singular\":\"etcdbackup\"},\"scope\":\"Namespaced\",\"version\":\"v1beta2\"}}", + "{\"apiVersion\":\"apiextensions.k8s.io/v1beta1\",\"kind\":\"CustomResourceDefinition\",\"metadata\":{\"name\":\"etcdclusters.etcd.database.coreos.com\"},\"spec\":{\"group\":\"etcd.database.coreos.com\",\"names\":{\"kind\":\"EtcdCluster\",\"listKind\":\"EtcdClusterList\",\"plural\":\"etcdclusters\",\"shortNames\":[\"etcdclus\",\"etcd\"],\"singular\":\"etcdcluster\"},\"scope\":\"Namespaced\",\"version\":\"v1beta2\"}}", + b.CsvJson, + "{\"apiVersion\":\"apiextensions.k8s.io/v1beta1\",\"kind\":\"CustomResourceDefinition\",\"metadata\":{\"name\":\"etcdrestores.etcd.database.coreos.com\"},\"spec\":{\"group\":\"etcd.database.coreos.com\",\"names\":{\"kind\":\"EtcdRestore\",\"listKind\":\"EtcdRestoreList\",\"plural\":\"etcdrestores\",\"singular\":\"etcdrestore\"},\"scope\":\"Namespaced\",\"version\":\"v1beta2\"}}", + } + case includeManifestsNone: + case includeManifestsCSVOnly: + b.CsvJson = "{\"kind\":\"ClusterServiceVersion\",\"apiVersion\":\"operators.coreos.com/v1alpha1\",\"metadata\":{\"name\":\"etcdoperator.v0.9.2\",\"creationTimestamp\":null,\"annotations\":{\"alm-examples\":\"[{\\\"apiVersion\\\":\\\"etcd.database.coreos.com/v1beta2\\\",\\\"kind\\\":\\\"EtcdCluster\\\",\\\"metadata\\\":{\\\"name\\\":\\\"example\\\",\\\"namespace\\\":\\\"default\\\"},\\\"spec\\\":{\\\"size\\\":3,\\\"version\\\":\\\"3.2.13\\\"}},{\\\"apiVersion\\\":\\\"etcd.database.coreos.com/v1beta2\\\",\\\"kind\\\":\\\"EtcdRestore\\\",\\\"metadata\\\":{\\\"name\\\":\\\"example-etcd-cluster\\\"},\\\"spec\\\":{\\\"etcdCluster\\\":{\\\"name\\\":\\\"example-etcd-cluster\\\"},\\\"backupStorageType\\\":\\\"S3\\\",\\\"s3\\\":{\\\"path\\\":\\\"\\u003cfull-s3-path\\u003e\\\",\\\"awsSecret\\\":\\\"\\u003caws-secret\\u003e\\\"}}},{\\\"apiVersion\\\":\\\"etcd.database.coreos.com/v1beta2\\\",\\\"kind\\\":\\\"EtcdBackup\\\",\\\"metadata\\\":{\\\"name\\\":\\\"example-etcd-cluster-backup\\\"},\\\"spec\\\":{\\\"etcdEndpoints\\\":[\\\"\\u003cetcd-cluster-endpoints\\u003e\\\"],\\\"storageType\\\":\\\"S3\\\",\\\"s3\\\":{\\\"path\\\":\\\"\\u003cfull-s3-path\\u003e\\\",\\\"awsSecret\\\":\\\"\\u003caws-secret\\u003e\\\"}}}]\",\"olm.properties\":\"[{\\\"type\\\":\\\"other\\\",\\\"value\\\":{\\\"its\\\":\\\"notdefined\\\"}},{\\\"type\\\":\\\"olm.label\\\",\\\"value\\\":{\\\"label\\\":\\\"testlabel\\\"}},{\\\"type\\\":\\\"olm.label\\\",\\\"value\\\":{\\\"label\\\":\\\"testlabel1\\\"}}]\",\"olm.skipRange\":\"\\u003c 0.6.0\",\"tectonic-visibility\":\"ocs\"}},\"spec\":{\"install\":{\"strategy\":\"deployment\",\"spec\":{\"deployments\":null}},\"version\":\"0.9.2\",\"maturity\":\"alpha\",\"customresourcedefinitions\":{\"owned\":[{\"name\":\"etcdclusters.etcd.database.coreos.com\",\"version\":\"v1beta2\",\"kind\":\"EtcdCluster\",\"displayName\":\"etcd Cluster\",\"description\":\"Represents a cluster of etcd nodes.\",\"resources\":[{\"name\":\"\",\"kind\":\"Service\",\"version\":\"v1\"},{\"name\":\"\",\"kind\":\"Pod\",\"version\":\"v1\"}],\"statusDescriptors\":[{\"path\":\"members\",\"displayName\":\"Member Status\",\"description\":\"The status of each of the member Pods for the etcd cluster.\",\"x-descriptors\":[\"urn:alm:descriptor:com.tectonic.ui:podStatuses\"]},{\"path\":\"serviceName\",\"displayName\":\"Service\",\"description\":\"The service at which the running etcd cluster can be accessed.\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes:Service\"]},{\"path\":\"size\",\"displayName\":\"Cluster Size\",\"description\":\"The current size of the etcd cluster.\"},{\"path\":\"currentVersion\",\"displayName\":\"Current Version\",\"description\":\"The current version of the etcd cluster.\"},{\"path\":\"targetVersion\",\"displayName\":\"Target Version\",\"description\":\"The target version of the etcd cluster, after upgrading.\"},{\"path\":\"phase\",\"displayName\":\"Status\",\"description\":\"The current status of the etcd cluster.\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes.phase\"]},{\"path\":\"reason\",\"displayName\":\"Status Details\",\"description\":\"Explanation for the current status of the cluster.\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes.phase:reason\"]}],\"specDescriptors\":[{\"path\":\"size\",\"displayName\":\"Size\",\"description\":\"The desired number of member Pods for the etcd cluster.\",\"x-descriptors\":[\"urn:alm:descriptor:com.tectonic.ui:podCount\"]},{\"path\":\"pod.resources\",\"displayName\":\"Resource Requirements\",\"description\":\"Limits describes the minimum/maximum amount of compute resources required/allowed\",\"x-descriptors\":[\"urn:alm:descriptor:com.tectonic.ui:resourceRequirements\"]}]},{\"name\":\"etcdbackups.etcd.database.coreos.com\",\"version\":\"v1beta2\",\"kind\":\"EtcdBackup\",\"displayName\":\"etcd Backup\",\"description\":\"Represents the intent to backup an etcd cluster.\",\"statusDescriptors\":[{\"path\":\"succeeded\",\"displayName\":\"Succeeded\",\"description\":\"Indicates if the backup was successful.\",\"x-descriptors\":[\"urn:alm:descriptor:text\"]},{\"path\":\"reason\",\"displayName\":\"Reason\",\"description\":\"Indicates the reason for any backup related failures.\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes.phase:reason\"]}],\"specDescriptors\":[{\"path\":\"etcdEndpoints\",\"displayName\":\"etcd Endpoint(s)\",\"description\":\"Specifies the endpoints of an etcd cluster.\",\"x-descriptors\":[\"urn:alm:descriptor:etcd:endpoint\"]},{\"path\":\"s3.path\",\"displayName\":\"S3 Path\",\"description\":\"The full AWS S3 path where the backup is saved.\",\"x-descriptors\":[\"urn:alm:descriptor:aws:s3:path\"]},{\"path\":\"s3.awsSecret\",\"displayName\":\"AWS Secret\",\"description\":\"The name of the secret object that stores the AWS credential and config files.\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes:Secret\"]}]},{\"name\":\"etcdrestores.etcd.database.coreos.com\",\"version\":\"v1beta2\",\"kind\":\"EtcdRestore\",\"displayName\":\"etcd Restore\",\"description\":\"Represents the intent to restore an etcd cluster from a backup.\",\"statusDescriptors\":[{\"path\":\"succeeded\",\"displayName\":\"Succeeded\",\"description\":\"Indicates if the restore was successful.\",\"x-descriptors\":[\"urn:alm:descriptor:text\"]},{\"path\":\"reason\",\"displayName\":\"Reason\",\"description\":\"Indicates the reason for any restore related failures.\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes.phase:reason\"]}],\"specDescriptors\":[{\"path\":\"etcdCluster.name\",\"displayName\":\"etcd Cluster\",\"description\":\"References the EtcdCluster which should be restored,\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes:EtcdCluster\",\"urn:alm:descriptor:text\"]},{\"path\":\"s3.path\",\"displayName\":\"S3 Path\",\"description\":\"The full AWS S3 path where the backup is saved.\",\"x-descriptors\":[\"urn:alm:descriptor:aws:s3:path\"]},{\"path\":\"s3.awsSecret\",\"displayName\":\"AWS Secret\",\"description\":\"The name of the secret object that stores the AWS credential and config files.\",\"x-descriptors\":[\"urn:alm:descriptor:io.kubernetes:Secret\"]}]}],\"required\":[{\"name\":\"etcdclusters.etcd.database.coreos.com\",\"version\":\"v1beta2\",\"kind\":\"EtcdCluster\",\"displayName\":\"etcd Cluster\",\"description\":\"Represents a cluster of etcd nodes.\",\"resources\":[{\"name\":\"\",\"kind\":\"Service\",\"version\":\"v1\"},{\"name\":\"\",\"kind\":\"Pod\",\"version\":\"v1\"}],\"specDescriptors\":[{\"path\":\"size\",\"displayName\":\"Size\",\"description\":\"The desired number of member Pods for the etcd cluster.\",\"x-descriptors\":[\"urn:alm:descriptor:com.tectonic.ui:podCount\"]}]}]},\"apiservicedefinitions\":{},\"displayName\":\"etcd\",\"description\":\"etcd is a distributed key value store that provides a reliable way to store data across a cluster of machines. It’s open-source and available on GitHub. etcd gracefully handles leader elections during network partitions and will tolerate machine failure, including the leader. Your applications can read and write data into etcd.\\nA simple use-case is to store database connection details or feature flags within etcd as key value pairs. These values can be watched, allowing your app to reconfigure itself when they change. Advanced uses take advantage of the consistency guarantees to implement database leader elections or do distributed locking across a cluster of workers.\\n\\n_The etcd Open Cloud Service is Public Alpha. The goal before Beta is to fully implement backup features._\\n\\n### Reading and writing to etcd\\n\\nCommunicate with etcd though its command line utility `etcdctl` or with the API using the automatically generated Kubernetes Service.\\n\\n[Read the complete guide to using the etcd Open Cloud Service](https://coreos.com/tectonic/docs/latest/alm/etcd-ocs.html)\\n\\n### Supported Features\\n\\n\\n**High availability**\\n\\n\\nMultiple instances of etcd are networked together and secured. Individual failures or networking issues are transparently handled to keep your cluster up and running.\\n\\n\\n**Automated updates**\\n\\n\\nRolling out a new etcd version works like all Kubernetes rolling updates. Simply declare the desired version, and the etcd service starts a safe rolling update to the new version automatically.\\n\\n\\n**Backups included**\\n\\n\\nComing soon, the ability to schedule backups to happen on or off cluster.\\n\",\"keywords\":[\"etcd\",\"key value\",\"database\",\"coreos\",\"open source\"],\"maintainers\":[{\"name\":\"CoreOS, Inc\",\"email\":\"support@coreos.com\"}],\"provider\":{\"name\":\"CoreOS, Inc\"},\"links\":[{\"name\":\"Blog\",\"url\":\"https://coreos.com/etcd\"},{\"name\":\"Documentation\",\"url\":\"https://coreos.com/operators/etcd/docs/latest/\"},{\"name\":\"etcd Operator Source Code\",\"url\":\"https://github.com/coreos/etcd-operator\"}],\"icon\":[{\"base64data\":\"iVBORw0KGgoAAAANSUhEUgAAAOEAAADZCAYAAADWmle6AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAEKlJREFUeNrsndt1GzkShmEev4sTgeiHfRYdgVqbgOgITEVgOgLTEQydwIiKwFQCayoCU6+7DyYjsBiBFyVVz7RkXvqCSxXw/+f04XjGQ6IL+FBVuL769euXgZ7r39f/G9iP0X+u/jWDNZzZdGI/Ftama1jjuV4BwmcNpbAf1Fgu+V/9YRvNAyzT2a59+/GT/3hnn5m16wKWedJrmOCxkYztx9Q+py/+E0GJxtJdReWfz+mxNt+QzS2Mc0AI+HbBBwj9QViKbH5t64DsP2fvmGXUkWU4WgO+Uve2YQzBUGd7r+zH2ZG/tiUQc4QxKwgbwFfVGwwmdLL5wH78aPC/ZBem9jJpCAX3xtcNASSNgJLzUPSQyjB1zQNl8IQJ9MIU4lx2+Jo72ysXYKl1HSzN02BMa/vbZ5xyNJIshJzwf3L0dQhJw4Sih/SFw9Tk8sVeghVPoefaIYCkMZCKbrcP9lnZuk0uPUjGE/KE8JQry7W2tgfuC3vXgvNV+qSQbyFtAtyWk7zWiYevvuUQ9QEQCvJ+5mmu6dTjz1zFHLFj8Eb87MtxaZh/IQFIHom+9vgTWwZxAQjT9X4vtbEVPojwjiV471s00mhAckpwGuCn1HtFtRDaSh6y9zsL+LNBvCG/24ThcxHObdlWc1v+VQJe8LcO0jwtuF8BwnAAUgP9M8JPU2Me+Oh12auPGT6fHuTePE3bLDy+x9pTLnhMn+07TQGh//Bz1iI0c6kvtqInjvPZcYR3KsPVmUsPYt9nFig9SCY8VQNhpPBzn952bbgcsk2EvM89wzh3UEffBbyPqvBUBYQ8ODGPFOLsa7RF096WJ69L+E4EmnpjWu5o4ChlKaRTKT39RMMaVPEQRsz/nIWlDN80chjdJlSd1l0pJCAMVZsniobQVuxceMM9OFoaMd9zqZtjMEYYDW38Drb8Y0DYPLShxn0pvIFuOSxd7YCPet9zk452wsh54FJoeN05hcgSQoG5RR0Qh9Q4E4VvL4wcZq8UACgaRFEQKgSwWrkr5WFnGxiHSutqJGlXjBgIOayhwYBTA0ER0oisIVSUV0AAMT0IASCUO4hRIQSAEECMCCEPwqyQA0JCQBzEGjWNAqHiUVAoXUWbvggOIQCEAOJzxTjoaQ4AIaE64/aZridUsBYUgkhB15oGg1DBIl8IqirYwV6hPSGBSFteMCUBSVXwfYixBmamRubeMyjzMJQBDDowE3OesDD+zwqFoDqiEwXoXJpljB+PvWJGy75BKF1FPxhKygJuqUdYQGlLxNEXkrYyjQ0GbaAwEnUIlLRNvVjQDYUAsJB0HKLE4y0AIpQNgCIhBIhQTgCKhZBBpAN/v6LtQI50JfUgYOnnjmLUFHKhjxbAmdTCaTiBm3ovLPqG2urWAij6im0Nd9aTN9ygLUEt9LgSRnohxUPIKxlGaE+/6Y7znFf0yX+GnkvFFWmarkab2o9PmTeq8sbd2a7DaysXz7i64VeznN4jCQhN9gdDbRiuWrfrsq0mHIrlaq+hlotCtd3Um9u0BYWY8y5D67wccJoZjFca7iUs9VqZcfsZwTd1sbWGG+OcYaTnPAP7rTQVVlM4Sg3oGvB1tmNh0t/HKXZ1jFoIMwCQjtqbhNxUmkGYqgZEDZP11HN/S3gAYRozf0l8C5kKEKUvW0t1IfeWG/5MwgheZTT1E0AEhDkAePQO+Ig2H3DncAkQM4cwUQCD530dU4B5Yvmi2LlDqXfWrxMCcMth51RToRMNUXFnfc2KJ0+Ryl0VNOUwlhh6NoxK5gnViTgQpUG4SqSyt5z3zRJpuKmt3Q1614QaCBPaN6je+2XiFcWAKOXcUfIYKRyL/1lb7pe5VxSxxjQ6hImshqGRt5GWZVKO6q2wHwujfwDtIvaIdexj8Cm8+a68EqMfox6x/voMouZF4dHnEGNeCDMwT6vdNfekH1MafMk4PI06YtqLVGl95aEM9Z5vAeCTOA++YLtoVJRrsqNCaJ6WRmkdYaNec5BT/lcTRMqrhmwfjbpkj55+OKp8IEbU/JLgPJE6Wa3TTe9sHS+ShVD5QIyqIxMEwKh12olC6mHIed5ewEop80CNlfIOADYOT2nd6ZXCop+Ebqchc0JqxKcKASxChycJgUh1rnHA5ow9eTrhqNI7JWiAYYwBGGdpyNLoGw0Pkh96h1BpHihyywtATDM/7Hk2fN9EnH8BgKJCU4ooBkbXFMZJiPbrOyecGl3zgQDQL4hk10IZiOe+5w99Q/gBAEIJgPhJM4QAEEoFREAIAAEiIASAkD8Qt4AQAEIAERAGFlX4CACKAXGVM4ivMwWwCLFAlyeoaa70QePKm5Dlp+/n+ye/5dYgva6YsUaVeMa+tzNFeJtWwc+udbJ0Fg399kLielQJ5Ze61c2+7ytA6EZetiPxZC6tj22yJCv6jUwOyj/zcbqAxOMyAKEbfeHtNa7DtYXptjsk2kJxR+eIeim/tHNofUKYy8DMrQcAKWz6brpvzyIAlpwPhQ49l6b7skJf5Z+YTOYQc4FwLDxvoTDwaygQK+U/kVr+ytSFBG01Q3gnJJR4cNiAhx4HDub8/b5DULXlj6SVZghFiE+LdvE9vo/o8Lp1RmH5hzm0T6wdbZ6n+D6i44zDRc3ln6CpAEJfXiRU45oqLz8gFAThWsh7ughrRibc0QynHgZpNJa/ENJ+loCwu/qOGnFIjYR/n7TfgycULhcQhu6VC+HfF+L3BoAQ4WiZTw1M+FPCnA2gKC6/FAhXgDC+ojQGh3NuWsvfF1L/D5ohlCKtl1j2ldu9a/nPAKFwN56Bst10zCG0CPleXN/zXPgHQZXaZaBgrbzyY5V/mUA+6F0hwtGN9rwu5DVZPuwWqfxdFz1LWbJ2lwKEa+0Qsm4Dl3fp+Pu0lV97PgwIPfSsS+UQhj5Oo+vvFULazRIQyvGEcxPuNLCth2MvFsrKn8UOilAQShkh7TTczYNMoS6OdP47msrPi82lXKGWhCdMZYS0bFy+vcnGAjP1CIfvgbKNA9glecEH9RD6Ol4wRuWyN/G9MHnksS6o/GPf5XcwNSUlHzQhDuAKtWJmkwKElU7lylP5rgIcsquh/FI8YZCDpkJBuE4FQm7Icw8N+SrUGaQKyi8FwiDt1ve5o+Vu7qYHy/psgK8cvh+FTYuO77bhEC7GuaPiys/L1X4IgXDL+e3M5+ovLxBy5VLuIebw1oqcHoPfoaMJUsHays878r8KbDc3xtPx/84gZPBG/JwaufrsY/SRG/OY3//8QMNdsvdZCFtbW6f8pFuf5bflILAlX7O+4fdfugKyFYS8T2zAsXthdG0VurPGKwI06oF5vkBgHWkNp6ry29+lsPZMU3vijnXFNmoclr+6+Ou/FIb8yb30sS8YGjmTqCLyQsi5N/6ZwKs0Yenj68pfPjF6N782Dp2FzV9CTyoSeY8mLK16qGxIkLI8oa1n8tz9juP40DlK0epxYEbojbq+9QfurBeVIlCO9D2396bxiV4lkYQ3hOAFw2pbhqMGISkkQOMcQ9EqhDmGZZdo92JC0YHRNTfoSg+5e0IT+opqCKHoIU+4ztQIgBD1EFNrQAgIpYSil9lDmPHqkROPt+JC6AgPquSuumJmg0YARVCuneDfvPVeJokZ6pIXDkNxQtGzTF9/BQjRG0tQznfb74RwCQghpALBtIQnfK4zhxdyQvVCUeknMIT3hLyY+T5jo0yABqKPQNpUNw/09tGZod5jgCaYFxyYvJcNPkv9eof+I3pnCFEHIETjSM8L9tHZHYCQT9PaZGycU6yg8S4akDnJ+P03L0+t23XGzCLzRgII/Wqa+fv/xlfvmKvMUOcOrlCDdoei1MGdZm6G5VEIfRzzjd4aQs69n699Rx7ewhvCGzr2gmTPs8zNsJOrXt24FbkhhOjCfT4ICA/rPbyhUy94Dks0gJCX1NzCZui9YUd3oei+c257TalFbgg19ILHrlrL2gvWgXAL26EX76gZTNASQnad8Ibwhl284NhgXpB0c+jKhWO3Ms1hP9ihJYB9eMF6qd1BCPk0qA1s+LimFIu7m4nsdQIzPK4VbQ8hYvrnuSH2G9b2ggP78QmWqBdF9Vx8SSY6QYdUW7BTA1schZATyhvY8lHvcRbNUS9YGFy2U+qmzh2YPVc0I7yAOFyHfRpyUwtCSzOdPXMHmz7qDIM0e0V2wZTEk+6Ym6N63eBLp/b5Bts+2cKCSJ/LuoZO3ANSiE5hKAZjnvNSS4931jcw9jpwT0feV/qSJ1pVtCyfHKDkvK8Ejx7pUxGh2xFNSwx8QTi2H9ceC0/nni64MS/5N5dG39pDqvRV+WgGk71c9VFXF9b+xYvOw/d61iv7m3MvEHryhvecwC52jSSx4VIIgwnMNT/UsTxIgpPt3K/ARj15CptwL3Zd/ceDSATj2DGQjbxgWwhdeMMte7zpy5On9vymRm/YxBYljGVjKWF9VJf7I1+sex3wY8w/V1QPTborW/72gkdsRDaZMJBdbdHIC7aCkAu9atlLbtnrzerMnyToDaGwelOnk3/hHSem/ZK7e/t7jeeR20LYBgqa8J80gS8jbwi5F02Uj1u2NYJxap8PLkJfLxA2hIJyvnHX/AfeEPLpBfe0uSFHbnXaea3Qd5d6HcpYZ8L6M7lnFwMQ3MNg+RxUR1+6AshtbsVgfXTEg1sIGax9UND2p7f270wdG3eK9gXVGHdw2k5sOyZv+Nbs39Z308XR9DqWb2J+PwKDhuKHPobfuXf7gnYGHdCs7bhDDadD4entDug7LWNsnRNW4mYqwJ9dk+GGSTPBiA2j0G8RWNM5upZtcG4/3vMfP7KnbK2egx6CCnDPhRn7NgD3cghLIad5WcM2SO38iqHvvMOosyeMpQ5zlVCaaj06GVs9xUbHdiKoqrHWgquFEFMWUEWfXUxJAML23hAHFOctmjZQffKD2pywkhtSGHKNtpitLroscAeE7kCkSsC60vxEl6yMtL9EL5HKGCMszU5bk8gdkklAyEn5FO0yK419rIxBOIqwFMooDE0tHEVYijAUECIshRCGIhxFWIowFJ5QkEYIS5PTJrUwNGlPyN6QQPyKtpuM1E/K5+YJDV/MiA3AaehzqgAm7QnZG9IGYKo8bHnSK7VblLL3hOwNHziPuEGOqE5brrdR6i+atCfckyeWD47HkAkepRGLY/e8A8J0gCwYSNypF08bBm+e6zVz2UL4AshhBUjML/rXLefqC82bcQFhGC9JDwZ1uuu+At0S5gCETYHsV4DUeD9fDN2Zfy5OXaW2zAwQygCzBLJ8cvaW5OXKC1FxfTggFAHmoAJnSiOw2wps9KwRWgJCLaEswaj5NqkLwAYIU4BxqTSXbHXpJdRMPZgAOiAMqABCNGYIEEJutEK5IUAIwYMDQgiCACEEAcJs1Vda7gGqDhCmoiEghAAhBAHCrKXVo2C1DCBMRlp37uMIEECoX7xrX3P5C9QiINSuIcoPAUI0YkAICLNWgfJDh4T9hH7zqYH9+JHAq7zBqWjwhPAicTVCVQJCNF50JghHocahKK0X/ZnQKyEkhSdUpzG8OgQI42qC94EQjsYLRSmH+pbgq73L6bYkeEJ4DYTYmeg1TOBFc/usTTp3V9DdEuXJ2xDCUbXhaXk0/kAYmBvuMB4qkC35E5e5AMKkwSQgyxufyuPy6fMMgAFCSI73LFXU/N8AmEL9X4ABACNSKMHAgb34AAAAAElFTkSuQmCC\",\"mediatype\":\"image/png\"}],\"cleanup\":{\"enabled\":false},\"relatedImages\":[{\"name\":\"\",\"image\":\"quay.io/coreos/etcd-operator@sha256:c0301e4686c3ed4206e370b42de5a3bd2229b9fb4906cf85f3f30650424abec2\"},{\"name\":\"etcd-v3.4.0\",\"image\":\"quay.io/coreos/etcd@sha256:3816b6daf9b66d6ced6f0f966314e2d4f894982c6b1493061502f8c2bf86ac84\"},{\"name\":\"etcd-3.4.1\",\"image\":\"quay.io/coreos/etcd@sha256:49d3d4a81e0d030d3f689e7167f23e120abf955f7d08dbedf3ea246485acee9f\"}]},\"status\":{\"cleanup\":{}}}" + b.Object = []string{b.CsvJson} + default: + panic(fmt.Sprintf("unexpected includeManifests value: %q", includeManifests)) + } return b } diff --git a/staging/operator-registry/registry.Dockerfile b/staging/operator-registry/registry.Dockerfile index e87459c1af..f87672614b 100644 --- a/staging/operator-registry/registry.Dockerfile +++ b/staging/operator-registry/registry.Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.18-alpine as builder +FROM golang:1.19-alpine as builder RUN apk update && apk add sqlite build-base git mercurial bash WORKDIR /build diff --git a/staging/operator-registry/test/e2e/bundle_image_test.go b/staging/operator-registry/test/e2e/bundle_image_test.go index 1088d38f29..c72359087b 100644 --- a/staging/operator-registry/test/e2e/bundle_image_test.go +++ b/staging/operator-registry/test/e2e/bundle_image_test.go @@ -84,12 +84,12 @@ func buildContainer(tag, dockerfilePath, dockerContext string, w io.Writer) { var _ = Describe("Launch bundle", func() { namespace := "default" - initImage := dockerHost + "/olmtest/init-operator-manifest:test" Context("Deploy bundle job", func() { DescribeTable("should populate specified configmap", func(bundleName, bundleDirectory string, gzip bool) { // these permissions are only necessary for the e2e (and not OLM using the feature) By("configuring configmap service account") + initImage := imageRegistry + "/init-operator-manifest:test" kubeclient, err := kubernetes.NewForConfig(ctx.Ctx().RESTConfig()) Expect(err).NotTo(HaveOccurred()) @@ -133,7 +133,7 @@ var _ = Describe("Launch bundle", func() { Expect(err).NotTo(HaveOccurred()) By("building required images") - bundleImage := dockerHost + "/olmtest/" + bundleName + ":test" + bundleImage := imageRegistry + "/" + bundleName + ":test" buildContainer(initImage, imageDirectory+"serve.Dockerfile", "../../bin", GinkgoWriter) buildContainer(bundleImage, imageDirectory+"bundle.Dockerfile", bundleDirectory, GinkgoWriter) diff --git a/staging/operator-registry/test/e2e/e2e_suite_test.go b/staging/operator-registry/test/e2e/e2e_suite_test.go index 6f2bdf91cd..a7a6e69ce7 100644 --- a/staging/operator-registry/test/e2e/e2e_suite_test.go +++ b/staging/operator-registry/test/e2e/e2e_suite_test.go @@ -24,6 +24,10 @@ var ( dockerPassword = os.Getenv("DOCKER_PASSWORD") dockerHost = os.Getenv("DOCKER_REGISTRY_HOST") // 'DOCKER_HOST' is reserved for the docker daemon + // default domain name of the test image (overwritten by "IMAGE_DOMAIN" env variable) + imageDomain = "olmtest" + imageRegistry = dockerHost + "/" + imageDomain + // opm command under test. opm *cobra.Command @@ -42,6 +46,13 @@ var deprovision func() = func() {} var _ = BeforeSuite(func() { // Configure test registry (hostnames, credentials, etc.) configureRegistry() + + val, ok := os.LookupEnv("IMAGE_DOMAIN") + if ok { + imageDomain = val + imageRegistry = dockerHost + "/" + imageDomain + } + deprovision = ctx.MustProvision(ctx.Ctx()) opm = opmroot.NewCmd() // Creating multiple instances would cause flag registration conflicts @@ -60,6 +71,7 @@ func configureRegistry() { case dockerHost == "" && dockerUsername != "" && dockerPassword != "": // Set host to default registry dockerHost = defaultRegistry + imageRegistry = dockerHost + "/" + imageDomain } // FIXME: Since podman login doesn't work with daemonless image pulling, we need to login with docker first so podman tests don't fail. diff --git a/staging/operator-registry/test/e2e/opm_bundle_test.go b/staging/operator-registry/test/e2e/opm_bundle_test.go index c9406dfa6a..d129d31924 100644 --- a/staging/operator-registry/test/e2e/opm_bundle_test.go +++ b/staging/operator-registry/test/e2e/opm_bundle_test.go @@ -53,7 +53,7 @@ var _ = Describe("opm alpha bundle", func() { Expect(err).ToNot(HaveOccurred()) // Create a bundle ref using the local registry host name and the namespace/name of a bundle we already know the content of - bundleRef = host + "/olmtest/kiali@sha256:a1bec450c104ceddbb25b252275eb59f1f1e6ca68e0ced76462042f72f7057d8" + bundleRef = host + "/" + imageDomain + "/kiali@sha256:a1bec450c104ceddbb25b252275eb59f1f1e6ca68e0ced76462042f72f7057d8" // Generate a checksum of the expected content for the bundle under test bundleChecksum, err = dirhash.HashDir(filepath.Join(goldenFiles, "bundles/kiali"), "", dirhash.DefaultHash) diff --git a/staging/operator-registry/test/e2e/opm_test.go b/staging/operator-registry/test/e2e/opm_test.go index 5531c7dd0e..ad39e461b1 100644 --- a/staging/operator-registry/test/e2e/opm_test.go +++ b/staging/operator-registry/test/e2e/opm_test.go @@ -43,11 +43,11 @@ var ( indexTag2 = rand.String(6) indexTag3 = rand.String(6) - bundleImage = dockerHost + "/olmtest/e2e-bundle" - indexImage = dockerHost + "/olmtest/e2e-index" - indexImage1 = dockerHost + "/olmtest/e2e-index:" + indexTag1 - indexImage2 = dockerHost + "/olmtest/e2e-index:" + indexTag2 - indexImage3 = dockerHost + "/olmtest/e2e-index:" + indexTag3 + bundleImage string + indexImage string + indexImage1 string + indexImage2 string + indexImage3 string fbcIndexImageTag = dockerHost + "/olmtest/e2e-fbc" fbcPackageName = "webhook-operator" @@ -270,6 +270,15 @@ func initialize() error { return loader.Populate() } +var _ = BeforeEach(func() { + bundleImage = imageRegistry + "/e2e-bundle" + indexImage = imageRegistry + "/e2e-index" + indexImage1 = imageRegistry + "/e2e-index:" + indexTag1 + indexImage2 = imageRegistry + "/e2e-index:" + indexTag2 + indexImage3 = imageRegistry + "/e2e-index:" + indexTag3 + +}) + var _ = Describe("opm", func() { IncludeSharedSpecs := func(containerTool string) { It("builds and validates a bundle image", func() { diff --git a/staging/operator-registry/upstream-builder.Dockerfile b/staging/operator-registry/upstream-builder.Dockerfile index 20fc9b9d50..687ab3520c 100644 --- a/staging/operator-registry/upstream-builder.Dockerfile +++ b/staging/operator-registry/upstream-builder.Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.18-alpine as builder +FROM golang:1.19-alpine as builder RUN apk update && apk add sqlite build-base git mercurial bash WORKDIR /build diff --git a/staging/operator-registry/upstream-opm-builder.Dockerfile b/staging/operator-registry/upstream-opm-builder.Dockerfile index 9951433bdd..9d7ad9b4fe 100644 --- a/staging/operator-registry/upstream-opm-builder.Dockerfile +++ b/staging/operator-registry/upstream-opm-builder.Dockerfile @@ -3,7 +3,7 @@ ## GoReleaser to build and push multi-arch images for opm ## -FROM golang:1.18-alpine AS builder +FROM golang:1.19-alpine AS builder RUN apk update && apk add ca-certificates COPY ["nsswitch.conf", "/etc/nsswitch.conf"] diff --git a/vendor/cloud.google.com/go/LICENSE b/vendor/cloud.google.com/go/LICENSE deleted file mode 100644 index d645695673..0000000000 --- a/vendor/cloud.google.com/go/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/cloud.google.com/go/compute/metadata/metadata.go b/vendor/cloud.google.com/go/compute/metadata/metadata.go deleted file mode 100644 index 5dbe77cc79..0000000000 --- a/vendor/cloud.google.com/go/compute/metadata/metadata.go +++ /dev/null @@ -1,536 +0,0 @@ -// Copyright 2014 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package metadata provides access to Google Compute Engine (GCE) -// metadata and API service accounts. -// -// This package is a wrapper around the GCE metadata service, -// as documented at https://developers.google.com/compute/docs/metadata. -package metadata // import "cloud.google.com/go/compute/metadata" - -import ( - "context" - "encoding/json" - "fmt" - "io/ioutil" - "net" - "net/http" - "net/url" - "os" - "runtime" - "strings" - "sync" - "time" -) - -const ( - // metadataIP is the documented metadata server IP address. - metadataIP = "169.254.169.254" - - // metadataHostEnv is the environment variable specifying the - // GCE metadata hostname. If empty, the default value of - // metadataIP ("169.254.169.254") is used instead. - // This is variable name is not defined by any spec, as far as - // I know; it was made up for the Go package. - metadataHostEnv = "GCE_METADATA_HOST" - - userAgent = "gcloud-golang/0.1" -) - -type cachedValue struct { - k string - trim bool - mu sync.Mutex - v string -} - -var ( - projID = &cachedValue{k: "project/project-id", trim: true} - projNum = &cachedValue{k: "project/numeric-project-id", trim: true} - instID = &cachedValue{k: "instance/id", trim: true} -) - -var defaultClient = &Client{hc: &http.Client{ - Transport: &http.Transport{ - Dial: (&net.Dialer{ - Timeout: 2 * time.Second, - KeepAlive: 30 * time.Second, - }).Dial, - }, -}} - -// NotDefinedError is returned when requested metadata is not defined. -// -// The underlying string is the suffix after "/computeMetadata/v1/". -// -// This error is not returned if the value is defined to be the empty -// string. -type NotDefinedError string - -func (suffix NotDefinedError) Error() string { - return fmt.Sprintf("metadata: GCE metadata %q not defined", string(suffix)) -} - -func (c *cachedValue) get(cl *Client) (v string, err error) { - defer c.mu.Unlock() - c.mu.Lock() - if c.v != "" { - return c.v, nil - } - if c.trim { - v, err = cl.getTrimmed(c.k) - } else { - v, err = cl.Get(c.k) - } - if err == nil { - c.v = v - } - return -} - -var ( - onGCEOnce sync.Once - onGCE bool -) - -// OnGCE reports whether this process is running on Google Compute Engine. -func OnGCE() bool { - onGCEOnce.Do(initOnGCE) - return onGCE -} - -func initOnGCE() { - onGCE = testOnGCE() -} - -func testOnGCE() bool { - // The user explicitly said they're on GCE, so trust them. - if os.Getenv(metadataHostEnv) != "" { - return true - } - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - resc := make(chan bool, 2) - - // Try two strategies in parallel. - // See https://github.com/googleapis/google-cloud-go/issues/194 - go func() { - req, _ := http.NewRequest("GET", "http://"+metadataIP, nil) - req.Header.Set("User-Agent", userAgent) - res, err := defaultClient.hc.Do(req.WithContext(ctx)) - if err != nil { - resc <- false - return - } - defer res.Body.Close() - resc <- res.Header.Get("Metadata-Flavor") == "Google" - }() - - go func() { - addrs, err := net.DefaultResolver.LookupHost(ctx, "metadata.google.internal") - if err != nil || len(addrs) == 0 { - resc <- false - return - } - resc <- strsContains(addrs, metadataIP) - }() - - tryHarder := systemInfoSuggestsGCE() - if tryHarder { - res := <-resc - if res { - // The first strategy succeeded, so let's use it. - return true - } - // Wait for either the DNS or metadata server probe to - // contradict the other one and say we are running on - // GCE. Give it a lot of time to do so, since the system - // info already suggests we're running on a GCE BIOS. - timer := time.NewTimer(5 * time.Second) - defer timer.Stop() - select { - case res = <-resc: - return res - case <-timer.C: - // Too slow. Who knows what this system is. - return false - } - } - - // There's no hint from the system info that we're running on - // GCE, so use the first probe's result as truth, whether it's - // true or false. The goal here is to optimize for speed for - // users who are NOT running on GCE. We can't assume that - // either a DNS lookup or an HTTP request to a blackholed IP - // address is fast. Worst case this should return when the - // metaClient's Transport.ResponseHeaderTimeout or - // Transport.Dial.Timeout fires (in two seconds). - return <-resc -} - -// systemInfoSuggestsGCE reports whether the local system (without -// doing network requests) suggests that we're running on GCE. If this -// returns true, testOnGCE tries a bit harder to reach its metadata -// server. -func systemInfoSuggestsGCE() bool { - if runtime.GOOS != "linux" { - // We don't have any non-Linux clues available, at least yet. - return false - } - slurp, _ := ioutil.ReadFile("/sys/class/dmi/id/product_name") - name := strings.TrimSpace(string(slurp)) - return name == "Google" || name == "Google Compute Engine" -} - -// Subscribe calls Client.Subscribe on the default client. -func Subscribe(suffix string, fn func(v string, ok bool) error) error { - return defaultClient.Subscribe(suffix, fn) -} - -// Get calls Client.Get on the default client. -func Get(suffix string) (string, error) { return defaultClient.Get(suffix) } - -// ProjectID returns the current instance's project ID string. -func ProjectID() (string, error) { return defaultClient.ProjectID() } - -// NumericProjectID returns the current instance's numeric project ID. -func NumericProjectID() (string, error) { return defaultClient.NumericProjectID() } - -// InternalIP returns the instance's primary internal IP address. -func InternalIP() (string, error) { return defaultClient.InternalIP() } - -// ExternalIP returns the instance's primary external (public) IP address. -func ExternalIP() (string, error) { return defaultClient.ExternalIP() } - -// Email calls Client.Email on the default client. -func Email(serviceAccount string) (string, error) { return defaultClient.Email(serviceAccount) } - -// Hostname returns the instance's hostname. This will be of the form -// ".c..internal". -func Hostname() (string, error) { return defaultClient.Hostname() } - -// InstanceTags returns the list of user-defined instance tags, -// assigned when initially creating a GCE instance. -func InstanceTags() ([]string, error) { return defaultClient.InstanceTags() } - -// InstanceID returns the current VM's numeric instance ID. -func InstanceID() (string, error) { return defaultClient.InstanceID() } - -// InstanceName returns the current VM's instance ID string. -func InstanceName() (string, error) { return defaultClient.InstanceName() } - -// Zone returns the current VM's zone, such as "us-central1-b". -func Zone() (string, error) { return defaultClient.Zone() } - -// InstanceAttributes calls Client.InstanceAttributes on the default client. -func InstanceAttributes() ([]string, error) { return defaultClient.InstanceAttributes() } - -// ProjectAttributes calls Client.ProjectAttributes on the default client. -func ProjectAttributes() ([]string, error) { return defaultClient.ProjectAttributes() } - -// InstanceAttributeValue calls Client.InstanceAttributeValue on the default client. -func InstanceAttributeValue(attr string) (string, error) { - return defaultClient.InstanceAttributeValue(attr) -} - -// ProjectAttributeValue calls Client.ProjectAttributeValue on the default client. -func ProjectAttributeValue(attr string) (string, error) { - return defaultClient.ProjectAttributeValue(attr) -} - -// Scopes calls Client.Scopes on the default client. -func Scopes(serviceAccount string) ([]string, error) { return defaultClient.Scopes(serviceAccount) } - -func strsContains(ss []string, s string) bool { - for _, v := range ss { - if v == s { - return true - } - } - return false -} - -// A Client provides metadata. -type Client struct { - hc *http.Client -} - -// NewClient returns a Client that can be used to fetch metadata. -// Returns the client that uses the specified http.Client for HTTP requests. -// If nil is specified, returns the default client. -func NewClient(c *http.Client) *Client { - if c == nil { - return defaultClient - } - - return &Client{hc: c} -} - -// getETag returns a value from the metadata service as well as the associated ETag. -// This func is otherwise equivalent to Get. -func (c *Client) getETag(suffix string) (value, etag string, err error) { - ctx := context.TODO() - // Using a fixed IP makes it very difficult to spoof the metadata service in - // a container, which is an important use-case for local testing of cloud - // deployments. To enable spoofing of the metadata service, the environment - // variable GCE_METADATA_HOST is first inspected to decide where metadata - // requests shall go. - host := os.Getenv(metadataHostEnv) - if host == "" { - // Using 169.254.169.254 instead of "metadata" here because Go - // binaries built with the "netgo" tag and without cgo won't - // know the search suffix for "metadata" is - // ".google.internal", and this IP address is documented as - // being stable anyway. - host = metadataIP - } - suffix = strings.TrimLeft(suffix, "/") - u := "http://" + host + "/computeMetadata/v1/" + suffix - req, err := http.NewRequest("GET", u, nil) - if err != nil { - return "", "", err - } - req.Header.Set("Metadata-Flavor", "Google") - req.Header.Set("User-Agent", userAgent) - var res *http.Response - var reqErr error - retryer := newRetryer() - for { - res, reqErr = c.hc.Do(req) - var code int - if res != nil { - code = res.StatusCode - } - if delay, shouldRetry := retryer.Retry(code, reqErr); shouldRetry { - if err := sleep(ctx, delay); err != nil { - return "", "", err - } - continue - } - break - } - if reqErr != nil { - return "", "", reqErr - } - defer res.Body.Close() - if res.StatusCode == http.StatusNotFound { - return "", "", NotDefinedError(suffix) - } - all, err := ioutil.ReadAll(res.Body) - if err != nil { - return "", "", err - } - if res.StatusCode != 200 { - return "", "", &Error{Code: res.StatusCode, Message: string(all)} - } - return string(all), res.Header.Get("Etag"), nil -} - -// Get returns a value from the metadata service. -// The suffix is appended to "http://${GCE_METADATA_HOST}/computeMetadata/v1/". -// -// If the GCE_METADATA_HOST environment variable is not defined, a default of -// 169.254.169.254 will be used instead. -// -// If the requested metadata is not defined, the returned error will -// be of type NotDefinedError. -func (c *Client) Get(suffix string) (string, error) { - val, _, err := c.getETag(suffix) - return val, err -} - -func (c *Client) getTrimmed(suffix string) (s string, err error) { - s, err = c.Get(suffix) - s = strings.TrimSpace(s) - return -} - -func (c *Client) lines(suffix string) ([]string, error) { - j, err := c.Get(suffix) - if err != nil { - return nil, err - } - s := strings.Split(strings.TrimSpace(j), "\n") - for i := range s { - s[i] = strings.TrimSpace(s[i]) - } - return s, nil -} - -// ProjectID returns the current instance's project ID string. -func (c *Client) ProjectID() (string, error) { return projID.get(c) } - -// NumericProjectID returns the current instance's numeric project ID. -func (c *Client) NumericProjectID() (string, error) { return projNum.get(c) } - -// InstanceID returns the current VM's numeric instance ID. -func (c *Client) InstanceID() (string, error) { return instID.get(c) } - -// InternalIP returns the instance's primary internal IP address. -func (c *Client) InternalIP() (string, error) { - return c.getTrimmed("instance/network-interfaces/0/ip") -} - -// Email returns the email address associated with the service account. -// The account may be empty or the string "default" to use the instance's -// main account. -func (c *Client) Email(serviceAccount string) (string, error) { - if serviceAccount == "" { - serviceAccount = "default" - } - return c.getTrimmed("instance/service-accounts/" + serviceAccount + "/email") -} - -// ExternalIP returns the instance's primary external (public) IP address. -func (c *Client) ExternalIP() (string, error) { - return c.getTrimmed("instance/network-interfaces/0/access-configs/0/external-ip") -} - -// Hostname returns the instance's hostname. This will be of the form -// ".c..internal". -func (c *Client) Hostname() (string, error) { - return c.getTrimmed("instance/hostname") -} - -// InstanceTags returns the list of user-defined instance tags, -// assigned when initially creating a GCE instance. -func (c *Client) InstanceTags() ([]string, error) { - var s []string - j, err := c.Get("instance/tags") - if err != nil { - return nil, err - } - if err := json.NewDecoder(strings.NewReader(j)).Decode(&s); err != nil { - return nil, err - } - return s, nil -} - -// InstanceName returns the current VM's instance ID string. -func (c *Client) InstanceName() (string, error) { - return c.getTrimmed("instance/name") -} - -// Zone returns the current VM's zone, such as "us-central1-b". -func (c *Client) Zone() (string, error) { - zone, err := c.getTrimmed("instance/zone") - // zone is of the form "projects//zones/". - if err != nil { - return "", err - } - return zone[strings.LastIndex(zone, "/")+1:], nil -} - -// InstanceAttributes returns the list of user-defined attributes, -// assigned when initially creating a GCE VM instance. The value of an -// attribute can be obtained with InstanceAttributeValue. -func (c *Client) InstanceAttributes() ([]string, error) { return c.lines("instance/attributes/") } - -// ProjectAttributes returns the list of user-defined attributes -// applying to the project as a whole, not just this VM. The value of -// an attribute can be obtained with ProjectAttributeValue. -func (c *Client) ProjectAttributes() ([]string, error) { return c.lines("project/attributes/") } - -// InstanceAttributeValue returns the value of the provided VM -// instance attribute. -// -// If the requested attribute is not defined, the returned error will -// be of type NotDefinedError. -// -// InstanceAttributeValue may return ("", nil) if the attribute was -// defined to be the empty string. -func (c *Client) InstanceAttributeValue(attr string) (string, error) { - return c.Get("instance/attributes/" + attr) -} - -// ProjectAttributeValue returns the value of the provided -// project attribute. -// -// If the requested attribute is not defined, the returned error will -// be of type NotDefinedError. -// -// ProjectAttributeValue may return ("", nil) if the attribute was -// defined to be the empty string. -func (c *Client) ProjectAttributeValue(attr string) (string, error) { - return c.Get("project/attributes/" + attr) -} - -// Scopes returns the service account scopes for the given account. -// The account may be empty or the string "default" to use the instance's -// main account. -func (c *Client) Scopes(serviceAccount string) ([]string, error) { - if serviceAccount == "" { - serviceAccount = "default" - } - return c.lines("instance/service-accounts/" + serviceAccount + "/scopes") -} - -// Subscribe subscribes to a value from the metadata service. -// The suffix is appended to "http://${GCE_METADATA_HOST}/computeMetadata/v1/". -// The suffix may contain query parameters. -// -// Subscribe calls fn with the latest metadata value indicated by the provided -// suffix. If the metadata value is deleted, fn is called with the empty string -// and ok false. Subscribe blocks until fn returns a non-nil error or the value -// is deleted. Subscribe returns the error value returned from the last call to -// fn, which may be nil when ok == false. -func (c *Client) Subscribe(suffix string, fn func(v string, ok bool) error) error { - const failedSubscribeSleep = time.Second * 5 - - // First check to see if the metadata value exists at all. - val, lastETag, err := c.getETag(suffix) - if err != nil { - return err - } - - if err := fn(val, true); err != nil { - return err - } - - ok := true - if strings.ContainsRune(suffix, '?') { - suffix += "&wait_for_change=true&last_etag=" - } else { - suffix += "?wait_for_change=true&last_etag=" - } - for { - val, etag, err := c.getETag(suffix + url.QueryEscape(lastETag)) - if err != nil { - if _, deleted := err.(NotDefinedError); !deleted { - time.Sleep(failedSubscribeSleep) - continue // Retry on other errors. - } - ok = false - } - lastETag = etag - - if err := fn(val, ok); err != nil || !ok { - return err - } - } -} - -// Error contains an error response from the server. -type Error struct { - // Code is the HTTP response status code. - Code int - // Message is the server response message. - Message string -} - -func (e *Error) Error() string { - return fmt.Sprintf("compute: Received %d `%s`", e.Code, e.Message) -} diff --git a/vendor/cloud.google.com/go/compute/metadata/retry.go b/vendor/cloud.google.com/go/compute/metadata/retry.go deleted file mode 100644 index 0f18f3cda1..0000000000 --- a/vendor/cloud.google.com/go/compute/metadata/retry.go +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2021 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package metadata - -import ( - "context" - "io" - "math/rand" - "net/http" - "time" -) - -const ( - maxRetryAttempts = 5 -) - -var ( - syscallRetryable = func(err error) bool { return false } -) - -// defaultBackoff is basically equivalent to gax.Backoff without the need for -// the dependency. -type defaultBackoff struct { - max time.Duration - mul float64 - cur time.Duration -} - -func (b *defaultBackoff) Pause() time.Duration { - d := time.Duration(1 + rand.Int63n(int64(b.cur))) - b.cur = time.Duration(float64(b.cur) * b.mul) - if b.cur > b.max { - b.cur = b.max - } - return d -} - -// sleep is the equivalent of gax.Sleep without the need for the dependency. -func sleep(ctx context.Context, d time.Duration) error { - t := time.NewTimer(d) - select { - case <-ctx.Done(): - t.Stop() - return ctx.Err() - case <-t.C: - return nil - } -} - -func newRetryer() *metadataRetryer { - return &metadataRetryer{bo: &defaultBackoff{ - cur: 100 * time.Millisecond, - max: 30 * time.Second, - mul: 2, - }} -} - -type backoff interface { - Pause() time.Duration -} - -type metadataRetryer struct { - bo backoff - attempts int -} - -func (r *metadataRetryer) Retry(status int, err error) (time.Duration, bool) { - if status == http.StatusOK { - return 0, false - } - retryOk := shouldRetry(status, err) - if !retryOk { - return 0, false - } - if r.attempts == maxRetryAttempts { - return 0, false - } - r.attempts++ - return r.bo.Pause(), true -} - -func shouldRetry(status int, err error) bool { - if 500 <= status && status <= 599 { - return true - } - if err == io.ErrUnexpectedEOF { - return true - } - // Transient network errors should be retried. - if syscallRetryable(err) { - return true - } - if err, ok := err.(interface{ Temporary() bool }); ok { - if err.Temporary() { - return true - } - } - if err, ok := err.(interface{ Unwrap() error }); ok { - return shouldRetry(status, err.Unwrap()) - } - return false -} diff --git a/vendor/cloud.google.com/go/compute/metadata/retry_linux.go b/vendor/cloud.google.com/go/compute/metadata/retry_linux.go deleted file mode 100644 index bb412f8917..0000000000 --- a/vendor/cloud.google.com/go/compute/metadata/retry_linux.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2021 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//go:build linux -// +build linux - -package metadata - -import "syscall" - -func init() { - // Initialize syscallRetryable to return true on transient socket-level - // errors. These errors are specific to Linux. - syscallRetryable = func(err error) bool { return err == syscall.ECONNRESET || err == syscall.ECONNREFUSED } -} diff --git a/vendor/github.com/Azure/go-ansiterm/SECURITY.md b/vendor/github.com/Azure/go-ansiterm/SECURITY.md new file mode 100644 index 0000000000..e138ec5d6a --- /dev/null +++ b/vendor/github.com/Azure/go-ansiterm/SECURITY.md @@ -0,0 +1,41 @@ + + +## Security + +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). + +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). + +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). + +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + + * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) + * Full paths of source file(s) related to the manifestation of the issue + * The location of the affected source code (tag/branch/commit or direct URL) + * Any special configuration required to reproduce the issue + * Step-by-step instructions to reproduce the issue + * Proof-of-concept or exploit code (if possible) + * Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. + +## Preferred Languages + +We prefer all communications to be in English. + +## Policy + +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). + + diff --git a/vendor/github.com/Azure/go-autorest/.gitignore b/vendor/github.com/Azure/go-autorest/.gitignore deleted file mode 100644 index 3350aaf706..0000000000 --- a/vendor/github.com/Azure/go-autorest/.gitignore +++ /dev/null @@ -1,32 +0,0 @@ -# The standard Go .gitignore file follows. (Sourced from: github.com/github/gitignore/master/Go.gitignore) -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test -.DS_Store -.idea/ -.vscode/ - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe -*.test -*.prof - -# go-autorest specific -vendor/ -autorest/azure/example/example diff --git a/vendor/github.com/Azure/go-autorest/CHANGELOG.md b/vendor/github.com/Azure/go-autorest/CHANGELOG.md deleted file mode 100644 index d1f596bfc9..0000000000 --- a/vendor/github.com/Azure/go-autorest/CHANGELOG.md +++ /dev/null @@ -1,1004 +0,0 @@ -# CHANGELOG - -## v14.2.0 - -- Added package comment to make `github.com/Azure/go-autorest` importable. - -## v14.1.1 - -### Bug Fixes - -- Change `x-ms-authorization-auxiliary` header value separator to comma. - -## v14.1.0 - -### New Features - -- Added `azure.SetEnvironment()` that will update the global environments map with the specified values. - -## v14.0.1 - -### Bug Fixes - -- Fix race condition when refreshing token. -- Fixed some tests to work with Go 1.14. - -## v14.0.0 - -## Breaking Changes - -- By default, the `DoRetryForStatusCodes` functions will no longer infinitely retry a request when the response returns an HTTP status code of 429 (StatusTooManyRequests). To opt in to the old behavior set `autorest.Count429AsRetry` to `false`. - -## New Features - -- Variable `autorest.Max429Delay` can be used to control the maximum delay between retries when a 429 is received with no `Retry-After` header. The default is zero which means there is no cap. - -## v13.4.0 - -## New Features - -- Added field `SendDecorators` to the `Client` type. This can be used to specify a custom chain of SendDecorators per client. -- Added method `Client.Send()` which includes logic for selecting the preferred chain of SendDecorators. - -## v13.3.3 - -### Bug Fixes - -- Fixed connection leak when retrying requests. -- Enabled exponential back-off with a 2-minute cap when retrying on 429. -- Fixed some cases where errors were inadvertently dropped. - -## v13.3.2 - -### Bug Fixes - -- Updated `autorest.AsStringSlice()` to convert slice elements to their string representation. - -## v13.3.1 - -- Updated external dependencies. - -### Bug Fixes - -## v13.3.0 - -### New Features - -- Added support for shared key and shared access signature token authorization. - - `autorest.NewSharedKeyAuthorizer()` and dependent types. - - `autorest.NewSASTokenAuthorizer()` and dependent types. -- Added `ServicePrincipalToken.SetCustomRefresh()` so a custom refresh function can be invoked when a token has expired. - -### Bug Fixes - -- Fixed `cli.AccessTokensPath()` to respect `AZURE_CONFIG_DIR` when set. -- Support parsing error messages in XML responses. - -## v13.2.0 - -### New Features - -- Added the following functions to replace their versions that don't take a context. - - `adal.InitiateDeviceAuthWithContext()` - - `adal.CheckForUserCompletionWithContext()` - - `adal.WaitForUserCompletionWithContext()` - -## v13.1.0 - -### New Features - -- Added support for MSI authentication on Azure App Service and Azure Functions. - -## v13.0.2 - -### Bug Fixes - -- Always retry a request even if the sender returns a non-nil error. - -## v13.0.1 - -## Bug Fixes - -- Fixed `autorest.WithQueryParameters()` so that it properly encodes multi-value query parameters. - -## v13.0.0 - -## Breaking Changes - -The `tracing` package has been rewritten to provide a common interface for consumers to wire in the tracing package of their choice. -What this means is that by default no tracing provider will be compiled into your program and setting the `AZURE_SDK_TRACING_ENABLED` -environment variable will have no effect. To enable this previous behavior you must now add the following import to your source file. -```go - import _ "github.com/Azure/go-autorest/tracing/opencensus" -``` -The APIs required by autorest-generated code have remained but some APIs have been removed and new ones added. -The following APIs and variables have been removed (the majority of them were moved to the `opencensus` package). -- tracing.Transport -- tracing.Enable() -- tracing.EnableWithAIForwarding() -- tracing.Disable() - -The following APIs and types have been added -- tracing.Tracer -- tracing.Register() - -To hook up a tracer simply call `tracing.Register()` passing in a type that satisfies the `tracing.Tracer` interface. - -## v12.4.3 - -### Bug Fixes - -- `autorest.MultiTenantServicePrincipalTokenAuthorizer` will now properly add its auxiliary bearer tokens. - -## v12.4.2 - -### Bug Fixes - -- Improvements to the fixes made in v12.4.1. - - Remove `override` stanza from Gopkg.toml and `replace` directive from go.mod as they don't apply when being consumed as a dependency. - - Switched to latest version of `ocagent` that still depends on protobuf v1.2. - - Add indirect dependencies to the `required` clause with matching `constraint` stanzas so that `dep` dependencies match go.sum. - -## v12.4.1 - -### Bug Fixes - -- Updated OpenCensus and OCAgent versions to versions that don't depend on v1.3+ of protobuf as it was breaking kubernetes. -- Pinned opencensus-proto to a version that's compatible with our versions of OpenCensus and OCAgent. - -## v12.4.0 - -### New Features - -- Added `autorest.WithPrepareDecorators` and `autorest.GetPrepareDecorators` for adding and retrieving a custom chain of PrepareDecorators to the provided context. - -## v12.3.0 - -### New Features - -- Support for multi-tenant via x-ms-authorization-auxiliary header has been added for client credentials with - secret scenario; this basically bundles multiple OAuthConfig and ServicePrincipalToken types into corresponding - MultiTenant* types along with a new authorizer that adds the primary and auxiliary token headers to the reqest. - The authenticaion helpers have been updated to support this scenario; if environment var AZURE_AUXILIARY_TENANT_IDS - is set with a semicolon delimited list of tenants the multi-tenant codepath will kick in to create the appropriate authorizer. - See `adal.NewMultiTenantOAuthConfig`, `adal.NewMultiTenantServicePrincipalToken` and `autorest.NewMultiTenantServicePrincipalTokenAuthorizer` - along with their supporting types and methods. -- Added `autorest.WithSendDecorators` and `autorest.GetSendDecorators` for adding and retrieving a custom chain of SendDecorators to the provided context. -- Added `autorest.DoRetryForStatusCodesWithCap` and `autorest.DelayForBackoffWithCap` to enforce an upper bound on the duration between retries. - -## v12.2.0 - -### New Features - -- Added `autorest.WithXML`, `autorest.AsMerge`, `autorest.WithBytes` preparer decorators. -- Added `autorest.ByUnmarshallingBytes` response decorator. -- Added `Response.IsHTTPStatus` and `Response.HasHTTPStatus` helper methods for inspecting HTTP status code in `autorest.Response` types. - -### Bug Fixes - -- `autorest.DelayWithRetryAfter` now supports HTTP-Dates in the `Retry-After` header and is not limited to just 429 status codes. - -## v12.1.0 - -### New Features - -- Added `to.ByteSlicePtr()`. -- Added blob/queue storage resource ID to `azure.ResourceIdentifier`. - -## v12.0.0 - -### Breaking Changes - -In preparation for modules the following deprecated content has been removed. - - - async.NewFuture() - - async.Future.Done() - - async.Future.WaitForCompletion() - - async.DoPollForAsynchronous() - - The `utils` package - - validation.NewErrorWithValidationError() - - The `version` package - -## v11.9.0 - -### New Features - -- Add `ResourceIdentifiers` field to `azure.Environment` containing resource IDs for public and sovereign clouds. - -## v11.8.0 - -### New Features - -- Added `autorest.NewClientWithOptions()` to support endpoints that require free renegotiation. - -## v11.7.1 - -### Bug Fixes - -- Fix missing support for http(s) proxy when using the default sender. - -## v11.7.0 - -### New Features - -- Added methods to obtain a ServicePrincipalToken on the various credential configuration types in the `auth` package. - -## v11.6.1 - -### Bug Fixes - -- Fix ACR DNS endpoint for government clouds. -- Add Cosmos DB DNS endpoints. -- Update dependencies to resolve build breaks in OpenCensus. - -## v11.6.0 - -### New Features - -- Added type `autorest.BasicAuthorizer` to support Basic authentication. - -## v11.5.2 - -### Bug Fixes - -- Fixed `GetTokenFromCLI` did not work with zsh. - -## v11.5.1 - -### Bug Fixes - -- In `Client.sender()` set the minimum TLS version on HTTP clients to 1.2. - -## v11.5.0 - -### New Features - -- The `auth` package has been refactored so that the environment and file settings are now available. -- The methods used in `auth.NewAuthorizerFromEnvironment()` are now exported so that custom authorization chains can be created. -- Added support for certificate authorization for file-based config. - -## v11.4.0 - -### New Features - -- Added `adal.AddToUserAgent()` so callers can append custom data to the user-agent header used for ADAL requests. -- Exported `adal.UserAgent()` for parity with `autorest.Client`. - -## v11.3.2 - -### Bug Fixes - -- In `Future.WaitForCompletionRef()` if the provided context has a deadline don't add the default deadline. - -## v11.3.1 - -### Bug Fixes - -- For an LRO PUT operation the final GET URL was incorrectly set to the Location polling header in some cases. - -## v11.3.0 - -### New Features - -- Added method `ServicePrincipalToken()` to `DeviceFlowConfig` type. - -## v11.2.8 - -### Bug Fixes - -- Deprecate content in the `version` package. The functionality has been superseded by content in the `autorest` package. - -## v11.2.7 - -### Bug Fixes - -- Fix environment variable name for enabling tracing from `AZURE_SDK_TRACING_ENABELD` to `AZURE_SDK_TRACING_ENABLED`. - Note that for backward compatibility reasons, both will work until the next major version release of the package. - -## v11.2.6 - -### Bug Fixes - -- If zero bytes are read from a polling response body don't attempt to unmarshal them. - -## v11.2.5 - -### Bug Fixes - -- Removed race condition in `autorest.DoRetryForStatusCodes`. - -## v11.2.4 - -### Bug Fixes - -- Function `cli.ProfilePath` now respects environment `AZURE_CONFIG_DIR` if available. - -## v11.2.1 - -NOTE: Versions of Go prior to 1.10 have been removed from CI as they no -longer work with golint. - -### Bug Fixes - -- Method `MSIConfig.Authorizer` now supports user-assigned identities. -- The adal package now reports its own user-agent string. - -## v11.2.0 - -### New Features - -- Added `tracing` package that enables instrumentation of HTTP and API calls. - Setting the env variable `AZURE_SDK_TRACING_ENABLED` or calling `tracing.Enable` - will start instrumenting the code for metrics and traces. - Additionally, setting the env variable `OCAGENT_TRACE_EXPORTER_ENDPOINT` or - calling `tracing.EnableWithAIForwarding` will start the instrumentation and connect to an - App Insights Local Forwarder that is needs to be running. Note that if the - AI Local Forwarder is not running tracking will still be enabled. - By default, instrumentation is disabled. Once enabled, instrumentation can also - be programatically disabled by calling `Disable`. -- Added `DoneWithContext` call for checking LRO status. `Done` has been deprecated. - -### Bug Fixes - -- Don't use the initial request's context for LRO polling. -- Don't override the `refreshLock` and the `http.Client` when unmarshalling `ServicePrincipalToken` if - it is already set. - -## v11.1.1 - -### Bug Fixes - -- When creating a future always include the polling tracker even if there's a failure; this allows the underlying response to be obtained by the caller. - -## v11.1.0 - -### New Features - -- Added `auth.NewAuthorizerFromCLI` to create an authorizer configured from the Azure 2.0 CLI. -- Added `adal.NewOAuthConfigWithAPIVersion` to create an OAuthConfig with the specified API version. - -## v11.0.1 - -### New Features - -- Added `x5c` header to client assertion for certificate Issuer+Subject Name authentication. - -## v11.0.0 - -### Breaking Changes - -- To handle differences between ADFS and AAD the following fields have had their types changed from `string` to `json.Number` - - ExpiresIn - - ExpiresOn - - NotBefore - -### New Features - -- Added `auth.NewAuthorizerFromFileWithResource` to create an authorizer from the config file with the specified resource. -- Setting a client's `PollingDuration` to zero will use the provided context to control a LRO's polling duration. - -## v10.15.5 - -### Bug Fixes - -- In `DoRetryForStatusCodes`, if a request's context is cancelled return the last response. - -## v10.15.4 - -### Bug Fixes - -- If a polling operation returns a failure status code return the associated error. - -## v10.15.3 - -### Bug Fixes - -- Initialize the polling URL and method for an LRO tracker on each iteration, favoring the Azure-AsyncOperation header. - -## v10.15.2 - -### Bug Fixes - -- Use fmt.Fprint when printing request/response so that any escape sequences aren't treated as format specifiers. - -## v10.15.1 - -### Bug Fixes - -- If an LRO API returns a `Failed` provisioning state in the initial response return an error at that point so the caller doesn't have to poll. -- For failed LROs without an OData v4 error include the response body in the error's `AdditionalInfo` field to aid in diagnosing the failure. - -## v10.15.0 - -### New Features - -- Add initial support for request/response logging via setting environment variables. - Setting `AZURE_GO_SDK_LOG_LEVEL` to `LogInfo` will log request/response - without their bodies. To include the bodies set the log level to `LogDebug`. - By default the logger writes to strerr, however it can also write to stdout or a file - if specified in `AZURE_GO_SDK_LOG_FILE`. Note that if the specified file - already exists it will be truncated. - IMPORTANT: by default the logger will redact the Authorization and Ocp-Apim-Subscription-Key - headers. Any other secrets will _not_ be redacted. - -## v10.14.0 - -### New Features - -- Added package version that contains version constants and user-agent data. - -### Bug Fixes - -- Add the user-agent to token requests. - -## v10.13.0 - -- Added support for additionalInfo in ServiceError type. - -## v10.12.0 - -### New Features - -- Added field ServicePrincipalToken.MaxMSIRefreshAttempts to configure the maximun number of attempts to refresh an MSI token. - -## v10.11.4 - -### Bug Fixes - -- If an LRO returns http.StatusOK on the initial response with no async headers return the response body from Future.GetResult(). -- If there is no "final GET URL" return an error from Future.GetResult(). - -## v10.11.3 - -### Bug Fixes - -- In IMDS retry logic, if we don't receive a response don't retry. - - Renamed the retry function so it's clear it's meant for IMDS only. -- For error response bodies that aren't OData-v4 compliant stick the raw JSON in the ServiceError.Details field so the information isn't lost. - - Also add the raw HTTP response to the DetailedResponse. -- Removed superfluous wrapping of response error in azure.DoRetryWithRegistration(). - -## v10.11.2 - -### Bug Fixes - -- Validation for integers handles int and int64 types. - -## v10.11.1 - -### Bug Fixes - -- Adding User information to authorization config as parsed from CLI cache. - -## v10.11.0 - -### New Features - -- Added NewServicePrincipalTokenFromManualTokenSecret for creating a new SPT using a manual token and secret -- Added method ServicePrincipalToken.MarshalTokenJSON() to marshall the inner Token - -## v10.10.0 - -### New Features - -- Most ServicePrincipalTokens can now be marshalled/unmarshall to/from JSON (ServicePrincipalCertificateSecret and ServicePrincipalMSISecret are not supported). -- Added method ServicePrincipalToken.SetRefreshCallbacks(). - -## v10.9.2 - -### Bug Fixes - -- Refreshing a refresh token obtained from a web app authorization code now works. - -## v10.9.1 - -### Bug Fixes - -- The retry logic for MSI token requests now uses exponential backoff per the guidelines. -- IsTemporaryNetworkError() will return true for errors that don't implement the net.Error interface. - -## v10.9.0 - -### Deprecated Methods - -| Old Method | New Method | -| -------------------------: | :---------------------------: | -| azure.NewFuture() | azure.NewFutureFromResponse() | -| Future.WaitForCompletion() | Future.WaitForCompletionRef() | - -### New Features - -- Added azure.NewFutureFromResponse() for creating a Future from the initial response from an async operation. -- Added Future.GetResult() for making the final GET call to retrieve the result from an async operation. - -### Bug Fixes - -- Some futures failed to return their results, this should now be fixed. - -## v10.8.2 - -### Bug Fixes - -- Add nil-gaurd to token retry logic. - -## v10.8.1 - -### Bug Fixes - -- Return a TokenRefreshError if the sender fails on the initial request. -- Don't retry on non-temporary network errors. - -## v10.8.0 - -- Added NewAuthorizerFromEnvironmentWithResource() helper function. - -## v10.7.0 - -### New Features - -- Added \*WithContext() methods to ADAL token refresh operations. - -## v10.6.2 - -- Fixed a bug on device authentication. - -## v10.6.1 - -- Added retries to MSI token get request. - -## v10.6.0 - -- Changed MSI token implementation. Now, the token endpoint is the IMDS endpoint. - -## v10.5.1 - -### Bug Fixes - -- `DeviceFlowConfig.Authorizer()` now prints the device code message when running `go test`. `-v` flag is required. - -## v10.5.0 - -### New Features - -- Added NewPollingRequestWithContext() for use with polling asynchronous operations. - -### Bug Fixes - -- Make retry logic use the request's context instead of the deprecated Cancel object. - -## v10.4.0 - -### New Features - -- Added helper for parsing Azure Resource ID's. -- Added deprecation message to utils.GetEnvVarOrExit() - -## v10.3.0 - -### New Features - -- Added EnvironmentFromURL method to load an Environment from a given URL. This function is particularly useful in the private and hybrid Cloud model, where one may define their own endpoints -- Added TokenAudience endpoint to Environment structure. This is useful in private and hybrid cloud models where TokenAudience endpoint can be different from ResourceManagerEndpoint - -## v10.2.0 - -### New Features - -- Added endpoints for batch management. - -## v10.1.3 - -### Bug Fixes - -- In Client.Do() invoke WithInspection() last so that it will inspect WithAuthorization(). -- Fixed authorization methods to invoke p.Prepare() first, aligning them with the other preparers. - -## v10.1.2 - -- Corrected comment for auth.NewAuthorizerFromFile() function. - -## v10.1.1 - -- Updated version number to match current release. - -## v10.1.0 - -### New Features - -- Expose the polling URL for futures. - -### Bug Fixes - -- Add validation.NewErrorWithValidationError back to prevent breaking changes (it is deprecated). - -## v10.0.0 - -### New Features - -- Added target and innererror fields to ServiceError to comply with OData v4 spec. -- The Done() method on futures will now return a ServiceError object when available (it used to return a partial value of such errors). -- Added helper methods for obtaining authorizers. -- Expose the polling URL for futures. - -### Bug Fixes - -- Switched from glide to dep for dependency management. -- Fixed unmarshaling of ServiceError for JSON bodies that don't conform to the OData spec. -- Fixed a race condition in token refresh. - -### Breaking Changes - -- The ServiceError.Details field type has been changed to match the OData v4 spec. -- Go v1.7 has been dropped from CI. -- API parameter validation failures will now return a unique error type validation.Error. -- The adal.Token type has been decomposed from adal.ServicePrincipalToken (this was necessary in order to fix the token refresh race). - -## v9.10.0 - -- Fix the Service Bus suffix in Azure public env -- Add Service Bus Endpoint (AAD ResourceURI) for use in [Azure Service Bus RBAC Preview](https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-role-based-access-control) - -## v9.9.0 - -### New Features - -- Added EventGridKeyAuthorizer for key authorization with event grid topics. - -### Bug Fixes - -- Fixed race condition when auto-refreshing service principal tokens. - -## v9.8.1 - -### Bug Fixes - -- Added http.StatusNoContent (204) to the list of expected status codes for long-running operations. -- Updated runtime version info so it's current. - -## v9.8.0 - -### New Features - -- Added type azure.AsyncOpIncompleteError to be returned from a future's Result() method when the operation has not completed. - -## v9.7.1 - -### Bug Fixes - -- Use correct AAD and Graph endpoints for US Gov environment. - -## v9.7.0 - -### New Features - -- Added support for application/octet-stream MIME types. - -## v9.6.1 - -### Bug Fixes - -- Ensure Authorization header is added to request when polling for registration status. - -## v9.6.0 - -### New Features - -- Added support for acquiring tokens via MSI with a user assigned identity. - -## v9.5.3 - -### Bug Fixes - -- Don't remove encoding of existing URL Query parameters when calling autorest.WithQueryParameters. -- Set correct Content Type when using autorest.WithFormData. - -## v9.5.2 - -### Bug Fixes - -- Check for nil \*http.Response before dereferencing it. - -## v9.5.1 - -### Bug Fixes - -- Don't count http.StatusTooManyRequests (429) against the retry cap. -- Use retry logic when SkipResourceProviderRegistration is set to true. - -## v9.5.0 - -### New Features - -- Added support for username + password, API key, authoriazation code and cognitive services authentication. -- Added field SkipResourceProviderRegistration to clients to provide a way to skip auto-registration of RPs. -- Added utility function AsStringSlice() to convert its parameters to a string slice. - -### Bug Fixes - -- When checking for authentication failures look at the error type not the status code as it could vary. - -## v9.4.2 - -### Bug Fixes - -- Validate parameters when creating credentials. -- Don't retry requests if the returned status is a 401 (http.StatusUnauthorized) as it will never succeed. - -## v9.4.1 - -### Bug Fixes - -- Update the AccessTokensPath() to read access tokens path through AZURE_ACCESS_TOKEN_FILE. If this - environment variable is not set, it will fall back to use default path set by Azure CLI. -- Use case-insensitive string comparison for polling states. - -## v9.4.0 - -### New Features - -- Added WaitForCompletion() to Future as a default polling implementation. - -### Bug Fixes - -- Method Future.Done() shouldn't update polling status for unexpected HTTP status codes. - -## v9.3.1 - -### Bug Fixes - -- DoRetryForStatusCodes will retry if sender.Do returns a non-nil error. - -## v9.3.0 - -### New Features - -- Added PollingMethod() to Future so callers know what kind of polling mechanism is used. -- Added azure.ChangeToGet() which transforms an http.Request into a GET (to be used with LROs). - -## v9.2.0 - -### New Features - -- Added support for custom Azure Stack endpoints. -- Added type azure.Future used to track the status of long-running operations. - -### Bug Fixes - -- Preserve the original error in DoRetryWithRegistration when registration fails. - -## v9.1.1 - -- Fixes a bug regarding the cookie jar on `autorest.Client.Sender`. - -## v9.1.0 - -### New Features - -- In cases where there is a non-empty error from the service, attempt to unmarshal it instead of uniformly calling it an "Unknown" error. -- Support for loading Azure CLI Authentication files. -- Automatically register your subscription with the Azure Resource Provider if it hadn't been previously. - -### Bug Fixes - -- RetriableRequest can now tolerate a ReadSeekable body being read but not reset. -- Adding missing Apache Headers - -## v9.0.0 - -> **IMPORTANT:** This release was intially labeled incorrectly as `v8.4.0`. From the time it was released, it should have been marked `v9.0.0` because it contains breaking changes to the MSI packages. We appologize for any inconvenience this causes. - -Adding MSI Endpoint Support and CLI token rehydration. - -## v8.3.1 - -Pick up bug fix in adal for MSI support. - -## v8.3.0 - -Updates to Error string formats for clarity. Also, adding a copy of the http.Response to errors for an improved debugging experience. - -## v8.2.0 - -### New Features - -- Add support for bearer authentication callbacks -- Support 429 response codes that include "Retry-After" header -- Support validation constraint "Pattern" for map keys - -### Bug Fixes - -- Make RetriableRequest work with multiple versions of Go - -## v8.1.1 - -Updates the RetriableRequest to take advantage of GetBody() added in Go 1.8. - -## v8.1.0 - -Adds RetriableRequest type for more efficient handling of retrying HTTP requests. - -## v8.0.0 - -ADAL refactored into its own package. -Support for UNIX time. - -## v7.3.1 - -- Version Testing now removed from production bits that are shipped with the library. - -## v7.3.0 - -- Exposing new `RespondDecorator`, `ByDiscardingBody`. This allows operations - to acknowledge that they do not need either the entire or a trailing portion - of accepts response body. In doing so, Go's http library can reuse HTTP - connections more readily. -- Adding `PrepareDecorator` to target custom BaseURLs. -- Adding ACR suffix to public cloud environment. -- Updating Glide dependencies. - -## v7.2.5 - -- Fixed the Active Directory endpoint for the China cloud. -- Removes UTF-8 BOM if present in response payload. -- Added telemetry. - -## v7.2.3 - -- Fixing bug in calls to `DelayForBackoff` that caused doubling of delay - duration. - -## v7.2.2 - -- autorest/azure: added ASM and ARM VM DNS suffixes. - -## v7.2.1 - -- fixed parsing of UTC times that are not RFC3339 conformant. - -## v7.2.0 - -- autorest/validation: Reformat validation error for better error message. - -## v7.1.0 - -- preparer: Added support for multipart formdata - WithMultiPartFormdata() -- preparer: Added support for sending file in request body - WithFile -- client: Added RetryDuration parameter. -- autorest/validation: new package for validation code for Azure Go SDK. - -## v7.0.7 - -- Add trailing / to endpoint -- azure: add EnvironmentFromName - -## v7.0.6 - -- Add retry logic for 408, 500, 502, 503 and 504 status codes. -- Change url path and query encoding logic. -- Fix DelayForBackoff for proper exponential delay. -- Add CookieJar in Client. - -## v7.0.5 - -- Add check to start polling only when status is in [200,201,202]. -- Refactoring for unchecked errors. -- azure/persist changes. -- Fix 'file in use' issue in renewing token in deviceflow. -- Store header RetryAfter for subsequent requests in polling. -- Add attribute details in service error. - -## v7.0.4 - -- Better error messages for long running operation failures - -## v7.0.3 - -- Corrected DoPollForAsynchronous to properly handle the initial response - -## v7.0.2 - -- Corrected DoPollForAsynchronous to continue using the polling method first discovered - -## v7.0.1 - -- Fixed empty JSON input error in ByUnmarshallingJSON -- Fixed polling support for GET calls -- Changed format name from TimeRfc1123 to TimeRFC1123 - -## v7.0.0 - -- Added ByCopying responder with supporting TeeReadCloser -- Rewrote Azure asynchronous handling -- Reverted to only unmarshalling JSON -- Corrected handling of RFC3339 time strings and added support for Rfc1123 time format - -The `json.Decoder` does not catch bad data as thoroughly as `json.Unmarshal`. Since -`encoding/json` successfully deserializes all core types, and extended types normally provide -their custom JSON serialization handlers, the code has been reverted back to using -`json.Unmarshal`. The original change to use `json.Decode` was made to reduce duplicate -code; there is no loss of function, and there is a gain in accuracy, by reverting. - -Additionally, Azure services indicate requests to be polled by multiple means. The existing code -only checked for one of those (that is, the presence of the `Azure-AsyncOperation` header). -The new code correctly covers all cases and aligns with the other Azure SDKs. - -## v6.1.0 - -- Introduced `date.ByUnmarshallingJSONDate` and `date.ByUnmarshallingJSONTime` to enable JSON encoded values. - -## v6.0.0 - -- Completely reworked the handling of polled and asynchronous requests -- Removed unnecessary routines -- Reworked `mocks.Sender` to replay a series of `http.Response` objects -- Added `PrepareDecorators` for primitive types (e.g., bool, int32) - -Handling polled and asynchronous requests is no longer part of `Client#Send`. Instead new -`SendDecorators` implement different styles of polled behavior. See`autorest.DoPollForStatusCodes` -and `azure.DoPollForAsynchronous` for examples. - -## v5.0.0 - -- Added new RespondDecorators unmarshalling primitive types -- Corrected application of inspection and authorization PrependDecorators - -## v4.0.0 - -- Added support for Azure long-running operations. -- Added cancelation support to all decorators and functions that may delay. -- Breaking: `DelayForBackoff` now accepts a channel, which may be nil. - -## v3.1.0 - -- Add support for OAuth Device Flow authorization. -- Add support for ServicePrincipalTokens that are backed by an existing token, rather than other secret material. -- Add helpers for persisting and restoring Tokens. -- Increased code coverage in the github.com/Azure/autorest/azure package - -## v3.0.0 - -- Breaking: `NewErrorWithError` no longer takes `statusCode int`. -- Breaking: `NewErrorWithStatusCode` is replaced with `NewErrorWithResponse`. -- Breaking: `Client#Send()` no longer takes `codes ...int` argument. -- Add: XML unmarshaling support with `ByUnmarshallingXML()` -- Stopped vending dependencies locally and switched to [Glide](https://github.com/Masterminds/glide). - Applications using this library should either use Glide or vendor dependencies locally some other way. -- Add: `azure.WithErrorUnlessStatusCode()` decorator to handle Azure errors. -- Fix: use `net/http.DefaultClient` as base client. -- Fix: Missing inspection for polling responses added. -- Add: CopyAndDecode helpers. -- Improved `./autorest/to` with `[]string` helpers. -- Removed golint suppressions in .travis.yml. - -## v2.1.0 - -- Added `StatusCode` to `Error` for more easily obtaining the HTTP Reponse StatusCode (if any) - -## v2.0.0 - -- Changed `to.StringMapPtr` method signature to return a pointer -- Changed `ServicePrincipalCertificateSecret` and `NewServicePrincipalTokenFromCertificate` to support generic certificate and private keys - -## v1.0.0 - -- Added Logging inspectors to trace http.Request / Response -- Added support for User-Agent header -- Changed WithHeader PrepareDecorator to use set vs. add -- Added JSON to error when unmarshalling fails -- Added Client#Send method -- Corrected case of "Azure" in package paths -- Added "to" helpers, Azure helpers, and improved ease-of-use -- Corrected golint issues - -## v1.0.1 - -- Added CHANGELOG.md - -## v1.1.0 - -- Added mechanism to retrieve a ServicePrincipalToken using a certificate-signed JWT -- Added an example of creating a certificate-based ServicePrincipal and retrieving an OAuth token using the certificate - -## v1.1.1 - -- Introduce godeps and vendor dependencies introduced in v1.1.1 diff --git a/vendor/github.com/Azure/go-autorest/GNUmakefile b/vendor/github.com/Azure/go-autorest/GNUmakefile deleted file mode 100644 index a434e73ac4..0000000000 --- a/vendor/github.com/Azure/go-autorest/GNUmakefile +++ /dev/null @@ -1,23 +0,0 @@ -DIR?=./autorest/ - -default: build - -build: fmt - go install $(DIR) - -test: - go test $(DIR) || exit 1 - -vet: - @echo "go vet ." - @go vet $(DIR)... ; if [ $$? -eq 1 ]; then \ - echo ""; \ - echo "Vet found suspicious constructs. Please check the reported constructs"; \ - echo "and fix them if necessary before submitting the code for review."; \ - exit 1; \ - fi - -fmt: - gofmt -w $(DIR) - -.PHONY: build test vet fmt diff --git a/vendor/github.com/Azure/go-autorest/Gopkg.lock b/vendor/github.com/Azure/go-autorest/Gopkg.lock deleted file mode 100644 index dc6e3e633e..0000000000 --- a/vendor/github.com/Azure/go-autorest/Gopkg.lock +++ /dev/null @@ -1,324 +0,0 @@ -# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. - - -[[projects]] - digest = "1:892e39e5c083d0943f1e80ab8351690f183c6a5ab24e1d280adcad424c26255e" - name = "contrib.go.opencensus.io/exporter/ocagent" - packages = ["."] - pruneopts = "UT" - revision = "a8a6f458bbc1d5042322ad1f9b65eeb0b69be9ea" - version = "v0.6.0" - -[[projects]] - digest = "1:8f5acd4d4462b5136af644d25101f0968a7a94ee90fcb2059cec5b7cc42e0b20" - name = "github.com/census-instrumentation/opencensus-proto" - packages = [ - "gen-go/agent/common/v1", - "gen-go/agent/metrics/v1", - "gen-go/agent/trace/v1", - "gen-go/metrics/v1", - "gen-go/resource/v1", - "gen-go/trace/v1", - ] - pruneopts = "UT" - revision = "d89fa54de508111353cb0b06403c00569be780d8" - version = "v0.2.1" - -[[projects]] - digest = "1:ffe9824d294da03b391f44e1ae8281281b4afc1bdaa9588c9097785e3af10cec" - name = "github.com/davecgh/go-spew" - packages = ["spew"] - pruneopts = "UT" - revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73" - version = "v1.1.1" - -[[projects]] - digest = "1:76dc72490af7174349349838f2fe118996381b31ea83243812a97e5a0fd5ed55" - name = "github.com/dgrijalva/jwt-go" - packages = ["."] - pruneopts = "UT" - revision = "06ea1031745cb8b3dab3f6a236daf2b0aa468b7e" - version = "v3.2.0" - -[[projects]] - digest = "1:cf0d2e435fd4ce45b789e93ef24b5f08e86be0e9807a16beb3694e2d8c9af965" - name = "github.com/dimchansky/utfbom" - packages = ["."] - pruneopts = "UT" - revision = "d2133a1ce379ef6fa992b0514a77146c60db9d1c" - version = "v1.1.0" - -[[projects]] - branch = "master" - digest = "1:b7cb6054d3dff43b38ad2e92492f220f57ae6087ee797dca298139776749ace8" - name = "github.com/golang/groupcache" - packages = ["lru"] - pruneopts = "UT" - revision = "611e8accdfc92c4187d399e95ce826046d4c8d73" - -[[projects]] - digest = "1:e3839df32927e8d3403cd5aa7253d966e8ff80fc8f10e2e35d146461cd83fcfa" - name = "github.com/golang/protobuf" - packages = [ - "descriptor", - "jsonpb", - "proto", - "protoc-gen-go/descriptor", - "ptypes", - "ptypes/any", - "ptypes/duration", - "ptypes/struct", - "ptypes/timestamp", - "ptypes/wrappers", - ] - pruneopts = "UT" - revision = "6c65a5562fc06764971b7c5d05c76c75e84bdbf7" - version = "v1.3.2" - -[[projects]] - digest = "1:c560cd79300fac84f124b96225181a637a70b60155919a3c36db50b7cca6b806" - name = "github.com/grpc-ecosystem/grpc-gateway" - packages = [ - "internal", - "runtime", - "utilities", - ] - pruneopts = "UT" - revision = "f7120437bb4f6c71f7f5076ad65a45310de2c009" - version = "v1.12.1" - -[[projects]] - digest = "1:5d231480e1c64a726869bc4142d270184c419749d34f167646baa21008eb0a79" - name = "github.com/mitchellh/go-homedir" - packages = ["."] - pruneopts = "UT" - revision = "af06845cf3004701891bf4fdb884bfe4920b3727" - version = "v1.1.0" - -[[projects]] - digest = "1:0028cb19b2e4c3112225cd871870f2d9cf49b9b4276531f03438a88e94be86fe" - name = "github.com/pmezard/go-difflib" - packages = ["difflib"] - pruneopts = "UT" - revision = "792786c7400a136282c1664665ae0a8db921c6c2" - version = "v1.0.0" - -[[projects]] - digest = "1:99d32780e5238c2621fff621123997c3e3cca96db8be13179013aea77dfab551" - name = "github.com/stretchr/testify" - packages = [ - "assert", - "require", - ] - pruneopts = "UT" - revision = "221dbe5ed46703ee255b1da0dec05086f5035f62" - version = "v1.4.0" - -[[projects]] - digest = "1:7c5e00383399fe13de0b4b65c9fdde16275407ce8ac02d867eafeaa916edcc71" - name = "go.opencensus.io" - packages = [ - ".", - "internal", - "internal/tagencoding", - "metric/metricdata", - "metric/metricproducer", - "plugin/ocgrpc", - "plugin/ochttp", - "plugin/ochttp/propagation/b3", - "plugin/ochttp/propagation/tracecontext", - "resource", - "stats", - "stats/internal", - "stats/view", - "tag", - "trace", - "trace/internal", - "trace/propagation", - "trace/tracestate", - ] - pruneopts = "UT" - revision = "aad2c527c5defcf89b5afab7f37274304195a6b2" - version = "v0.22.2" - -[[projects]] - branch = "master" - digest = "1:f604f5e2ee721b6757d962dfe7bab4f28aae50c456e39cfb2f3819762a44a6ae" - name = "golang.org/x/crypto" - packages = [ - "pkcs12", - "pkcs12/internal/rc2", - ] - pruneopts = "UT" - revision = "e9b2fee46413994441b28dfca259d911d963dfed" - -[[projects]] - branch = "master" - digest = "1:334b27eac455cb6567ea28cd424230b07b1a64334a2f861a8075ac26ce10af43" - name = "golang.org/x/lint" - packages = [ - ".", - "golint", - ] - pruneopts = "UT" - revision = "fdd1cda4f05fd1fd86124f0ef9ce31a0b72c8448" - -[[projects]] - branch = "master" - digest = "1:257a75d024975428ab9192bfc334c3490882f8cb21322ea5784ca8eca000a910" - name = "golang.org/x/net" - packages = [ - "http/httpguts", - "http2", - "http2/hpack", - "idna", - "internal/timeseries", - "trace", - ] - pruneopts = "UT" - revision = "1ddd1de85cb0337b623b740a609d35817d516a8d" - -[[projects]] - branch = "master" - digest = "1:382bb5a7fb4034db3b6a2d19e5a4a6bcf52f4750530603c01ca18a172fa3089b" - name = "golang.org/x/sync" - packages = ["semaphore"] - pruneopts = "UT" - revision = "cd5d95a43a6e21273425c7ae415d3df9ea832eeb" - -[[projects]] - branch = "master" - digest = "1:4da420ceda5f68e8d748aa2169d0ed44ffadb1bbd6537cf778a49563104189b8" - name = "golang.org/x/sys" - packages = ["unix"] - pruneopts = "UT" - revision = "ce4227a45e2eb77e5c847278dcc6a626742e2945" - -[[projects]] - digest = "1:8d8faad6b12a3a4c819a3f9618cb6ee1fa1cfc33253abeeea8b55336721e3405" - name = "golang.org/x/text" - packages = [ - "collate", - "collate/build", - "internal/colltab", - "internal/gen", - "internal/language", - "internal/language/compact", - "internal/tag", - "internal/triegen", - "internal/ucd", - "language", - "secure/bidirule", - "transform", - "unicode/bidi", - "unicode/cldr", - "unicode/norm", - "unicode/rangetable", - ] - pruneopts = "UT" - revision = "342b2e1fbaa52c93f31447ad2c6abc048c63e475" - version = "v0.3.2" - -[[projects]] - branch = "master" - digest = "1:4eb5ea8395fb60212dd58b92c9db80bab59d5e99c7435f9a6a0a528c373b60e7" - name = "golang.org/x/tools" - packages = [ - "go/ast/astutil", - "go/gcexportdata", - "go/internal/gcimporter", - "go/types/typeutil", - ] - pruneopts = "UT" - revision = "259af5ff87bdcd4abf2ecda8edc3f13f04f26a42" - -[[projects]] - digest = "1:964bb30febc27fabfbec4759fa530c6ec35e77a7c85fed90b9317ea39a054877" - name = "google.golang.org/api" - packages = ["support/bundler"] - pruneopts = "UT" - revision = "8a410c21381766a810817fd6200fce8838ecb277" - version = "v0.14.0" - -[[projects]] - branch = "master" - digest = "1:a8d5c2c6e746b3485e36908ab2a9e3d77b86b81f8156d88403c7d2b462431dfd" - name = "google.golang.org/genproto" - packages = [ - "googleapis/api/httpbody", - "googleapis/rpc/status", - "protobuf/field_mask", - ] - pruneopts = "UT" - revision = "51378566eb590fa106d1025ea12835a4416dda84" - -[[projects]] - digest = "1:b59ce3ddb11daeeccccc9cb3183b58ebf8e9a779f1c853308cd91612e817a301" - name = "google.golang.org/grpc" - packages = [ - ".", - "backoff", - "balancer", - "balancer/base", - "balancer/roundrobin", - "binarylog/grpc_binarylog_v1", - "codes", - "connectivity", - "credentials", - "credentials/internal", - "encoding", - "encoding/proto", - "grpclog", - "internal", - "internal/backoff", - "internal/balancerload", - "internal/binarylog", - "internal/buffer", - "internal/channelz", - "internal/envconfig", - "internal/grpcrand", - "internal/grpcsync", - "internal/resolver/dns", - "internal/resolver/passthrough", - "internal/syscall", - "internal/transport", - "keepalive", - "metadata", - "naming", - "peer", - "resolver", - "serviceconfig", - "stats", - "status", - "tap", - ] - pruneopts = "UT" - revision = "1a3960e4bd028ac0cec0a2afd27d7d8e67c11514" - version = "v1.25.1" - -[[projects]] - digest = "1:b75b3deb2bce8bc079e16bb2aecfe01eb80098f5650f9e93e5643ca8b7b73737" - name = "gopkg.in/yaml.v2" - packages = ["."] - pruneopts = "UT" - revision = "1f64d6156d11335c3f22d9330b0ad14fc1e789ce" - version = "v2.2.7" - -[solve-meta] - analyzer-name = "dep" - analyzer-version = 1 - input-imports = [ - "contrib.go.opencensus.io/exporter/ocagent", - "github.com/dgrijalva/jwt-go", - "github.com/dimchansky/utfbom", - "github.com/mitchellh/go-homedir", - "github.com/stretchr/testify/require", - "go.opencensus.io/plugin/ochttp", - "go.opencensus.io/plugin/ochttp/propagation/tracecontext", - "go.opencensus.io/stats/view", - "go.opencensus.io/trace", - "golang.org/x/crypto/pkcs12", - "golang.org/x/lint/golint", - ] - solver-name = "gps-cdcl" - solver-version = 1 diff --git a/vendor/github.com/Azure/go-autorest/Gopkg.toml b/vendor/github.com/Azure/go-autorest/Gopkg.toml deleted file mode 100644 index 1fc2865969..0000000000 --- a/vendor/github.com/Azure/go-autorest/Gopkg.toml +++ /dev/null @@ -1,59 +0,0 @@ -# Gopkg.toml example -# -# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html -# for detailed Gopkg.toml documentation. -# -# required = ["github.com/user/thing/cmd/thing"] -# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] -# -# [[constraint]] -# name = "github.com/user/project" -# version = "1.0.0" -# -# [[constraint]] -# name = "github.com/user/project2" -# branch = "dev" -# source = "github.com/myfork/project2" -# -# [[override]] -# name = "github.com/x/y" -# version = "2.4.0" -# -# [prune] -# non-go = false -# go-tests = true -# unused-packages = true - -required = ["golang.org/x/lint/golint"] - -[prune] - go-tests = true - unused-packages = true - -[[constraint]] - name = "contrib.go.opencensus.io/exporter/ocagent" - version = "0.6.0" - -[[constraint]] - name = "github.com/dgrijalva/jwt-go" - version = "3.2.0" - -[[constraint]] - name = "github.com/dimchansky/utfbom" - version = "1.1.0" - -[[constraint]] - name = "github.com/mitchellh/go-homedir" - version = "1.1.0" - -[[constraint]] - name = "github.com/stretchr/testify" - version = "1.3.0" - -[[constraint]] - name = "go.opencensus.io" - version = "0.22.0" - -[[constraint]] - branch = "master" - name = "golang.org/x/crypto" diff --git a/vendor/github.com/Azure/go-autorest/LICENSE b/vendor/github.com/Azure/go-autorest/LICENSE deleted file mode 100644 index b9d6a27ea9..0000000000 --- a/vendor/github.com/Azure/go-autorest/LICENSE +++ /dev/null @@ -1,191 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - Copyright 2015 Microsoft Corporation - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/Azure/go-autorest/README.md b/vendor/github.com/Azure/go-autorest/README.md deleted file mode 100644 index de1e19a44d..0000000000 --- a/vendor/github.com/Azure/go-autorest/README.md +++ /dev/null @@ -1,165 +0,0 @@ -# go-autorest - -[![GoDoc](https://godoc.org/github.com/Azure/go-autorest/autorest?status.png)](https://godoc.org/github.com/Azure/go-autorest/autorest) -[![Build Status](https://dev.azure.com/azure-sdk/public/_apis/build/status/go/Azure.go-autorest?branchName=master)](https://dev.azure.com/azure-sdk/public/_build/latest?definitionId=625&branchName=master) -[![Go Report Card](https://goreportcard.com/badge/Azure/go-autorest)](https://goreportcard.com/report/Azure/go-autorest) - -Package go-autorest provides an HTTP request client for use with [Autorest](https://github.com/Azure/autorest.go)-generated API client packages. - -An authentication client tested with Azure Active Directory (AAD) is also -provided in this repo in the package -`github.com/Azure/go-autorest/autorest/adal`. Despite its name, this package -is maintained only as part of the Azure Go SDK and is not related to other -"ADAL" libraries in [github.com/AzureAD](https://github.com/AzureAD). - -## Overview - -Package go-autorest implements an HTTP request pipeline suitable for use across -multiple goroutines and provides the shared routines used by packages generated -by [Autorest](https://github.com/Azure/autorest.go). - -The package breaks sending and responding to HTTP requests into three phases: Preparing, Sending, -and Responding. A typical pattern is: - -```go - req, err := Prepare(&http.Request{}, - token.WithAuthorization()) - - resp, err := Send(req, - WithLogging(logger), - DoErrorIfStatusCode(http.StatusInternalServerError), - DoCloseIfError(), - DoRetryForAttempts(5, time.Second)) - - err = Respond(resp, - ByDiscardingBody(), - ByClosing()) -``` - -Each phase relies on decorators to modify and / or manage processing. Decorators may first modify -and then pass the data along, pass the data first and then modify the result, or wrap themselves -around passing the data (such as a logger might do). Decorators run in the order provided. For -example, the following: - -```go - req, err := Prepare(&http.Request{}, - WithBaseURL("https://microsoft.com/"), - WithPath("a"), - WithPath("b"), - WithPath("c")) -``` - -will set the URL to: - -``` - https://microsoft.com/a/b/c -``` - -Preparers and Responders may be shared and re-used (assuming the underlying decorators support -sharing and re-use). Performant use is obtained by creating one or more Preparers and Responders -shared among multiple go-routines, and a single Sender shared among multiple sending go-routines, -all bound together by means of input / output channels. - -Decorators hold their passed state within a closure (such as the path components in the example -above). Be careful to share Preparers and Responders only in a context where such held state -applies. For example, it may not make sense to share a Preparer that applies a query string from a -fixed set of values. Similarly, sharing a Responder that reads the response body into a passed -struct (e.g., `ByUnmarshallingJson`) is likely incorrect. - -Errors raised by autorest objects and methods will conform to the `autorest.Error` interface. - -See the included examples for more detail. For details on the suggested use of this package by -generated clients, see the Client described below. - -## Helpers - -### Handling Swagger Dates - -The Swagger specification (https://swagger.io) that drives AutoRest -(https://github.com/Azure/autorest/) precisely defines two date forms: date and date-time. The -github.com/Azure/go-autorest/autorest/date package provides time.Time derivations to ensure correct -parsing and formatting. - -### Handling Empty Values - -In JSON, missing values have different semantics than empty values. This is especially true for -services using the HTTP PATCH verb. The JSON submitted with a PATCH request generally contains -only those values to modify. Missing values are to be left unchanged. Developers, then, require a -means to both specify an empty value and to leave the value out of the submitted JSON. - -The Go JSON package (`encoding/json`) supports the `omitempty` tag. When specified, it omits -empty values from the rendered JSON. Since Go defines default values for all base types (such as "" -for string and 0 for int) and provides no means to mark a value as actually empty, the JSON package -treats default values as meaning empty, omitting them from the rendered JSON. This means that, using -the Go base types encoded through the default JSON package, it is not possible to create JSON to -clear a value at the server. - -The workaround within the Go community is to use pointers to base types in lieu of base types within -structures that map to JSON. For example, instead of a value of type `string`, the workaround uses -`*string`. While this enables distinguishing empty values from those to be unchanged, creating -pointers to a base type (notably constant, in-line values) requires additional variables. This, for -example, - -```go - s := struct { - S *string - }{ S: &"foo" } -``` -fails, while, this - -```go - v := "foo" - s := struct { - S *string - }{ S: &v } -``` -succeeds. - -To ease using pointers, the subpackage `to` contains helpers that convert to and from pointers for -Go base types which have Swagger analogs. It also provides a helper that converts between -`map[string]string` and `map[string]*string`, enabling the JSON to specify that the value -associated with a key should be cleared. With the helpers, the previous example becomes - -```go - s := struct { - S *string - }{ S: to.StringPtr("foo") } -``` - -## Install - -```bash -go get github.com/Azure/go-autorest/autorest -go get github.com/Azure/go-autorest/autorest/azure -go get github.com/Azure/go-autorest/autorest/date -go get github.com/Azure/go-autorest/autorest/to -``` - -### Using with Go Modules -In [v12.0.1](https://github.com/Azure/go-autorest/pull/386), this repository introduced the following modules. - -- autorest/adal -- autorest/azure/auth -- autorest/azure/cli -- autorest/date -- autorest/mocks -- autorest/to -- autorest/validation -- autorest -- logger -- tracing - -Tagging cumulative SDK releases as a whole (e.g. `v12.3.0`) is still enabled to support consumers of this repo that have not yet migrated to modules. - -## License - -See LICENSE file. - ------ - -This project has adopted the [Microsoft Open Source Code of -Conduct](https://opensource.microsoft.com/codeofconduct/). For more information -see the [Code of Conduct -FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact -[opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional -questions or comments. diff --git a/vendor/github.com/Azure/go-autorest/autorest/LICENSE b/vendor/github.com/Azure/go-autorest/autorest/LICENSE deleted file mode 100644 index b9d6a27ea9..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/LICENSE +++ /dev/null @@ -1,191 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - Copyright 2015 Microsoft Corporation - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/Azure/go-autorest/autorest/adal/LICENSE b/vendor/github.com/Azure/go-autorest/autorest/adal/LICENSE deleted file mode 100644 index b9d6a27ea9..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/adal/LICENSE +++ /dev/null @@ -1,191 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - Copyright 2015 Microsoft Corporation - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/Azure/go-autorest/autorest/adal/README.md b/vendor/github.com/Azure/go-autorest/autorest/adal/README.md deleted file mode 100644 index b11eb07884..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/adal/README.md +++ /dev/null @@ -1,294 +0,0 @@ -# NOTE: This module will go out of support by March 31, 2023. For authenticating with Azure AD, use module [azidentity](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity) instead. For help migrating from `adal` to `azidentiy` please consult the [migration guide](https://aka.ms/azsdk/go/identity/migration). General information about the retirement of this and other legacy modules can be found [here](https://azure.microsoft.com/updates/support-for-azure-sdk-libraries-that-do-not-conform-to-our-current-azure-sdk-guidelines-will-be-retired-as-of-31-march-2023/). - -# Azure Active Directory authentication for Go - -This is a standalone package for authenticating with Azure Active -Directory from other Go libraries and applications, in particular the [Azure SDK -for Go](https://github.com/Azure/azure-sdk-for-go). - -Note: Despite the package's name it is not related to other "ADAL" libraries -maintained in the [github.com/AzureAD](https://github.com/AzureAD) org. Issues -should be opened in [this repo's](https://github.com/Azure/go-autorest/issues) -or [the SDK's](https://github.com/Azure/azure-sdk-for-go/issues) issue -trackers. - -## Install - -```bash -go get -u github.com/Azure/go-autorest/autorest/adal -``` - -## Usage - -An Active Directory application is required in order to use this library. An application can be registered in the [Azure Portal](https://portal.azure.com/) by following these [guidelines](https://docs.microsoft.com/azure/active-directory/develop/active-directory-integrating-applications) or using the [Azure CLI](https://github.com/Azure/azure-cli). - -### Register an Azure AD Application with secret - - -1. Register a new application with a `secret` credential - - ``` - az ad app create \ - --display-name example-app \ - --homepage https://example-app/home \ - --identifier-uris https://example-app/app \ - --password secret - ``` - -2. Create a service principal using the `Application ID` from previous step - - ``` - az ad sp create --id "Application ID" - ``` - - * Replace `Application ID` with `appId` from step 1. - -### Register an Azure AD Application with certificate - -1. Create a private key - - ``` - openssl genrsa -out "example-app.key" 2048 - ``` - -2. Create the certificate - - ``` - openssl req -new -key "example-app.key" -subj "/CN=example-app" -out "example-app.csr" - openssl x509 -req -in "example-app.csr" -signkey "example-app.key" -out "example-app.crt" -days 10000 - ``` - -3. Create the PKCS12 version of the certificate containing also the private key - - ``` - openssl pkcs12 -export -out "example-app.pfx" -inkey "example-app.key" -in "example-app.crt" -passout pass: - - ``` - -4. Register a new application with the certificate content form `example-app.crt` - - ``` - certificateContents="$(tail -n+2 "example-app.crt" | head -n-1)" - - az ad app create \ - --display-name example-app \ - --homepage https://example-app/home \ - --identifier-uris https://example-app/app \ - --key-usage Verify --end-date 2018-01-01 \ - --key-value "${certificateContents}" - ``` - -5. Create a service principal using the `Application ID` from previous step - - ``` - az ad sp create --id "APPLICATION_ID" - ``` - - * Replace `APPLICATION_ID` with `appId` from step 4. - - -### Grant the necessary permissions - -Azure relies on a Role-Based Access Control (RBAC) model to manage the access to resources at a fine-grained -level. There is a set of [pre-defined roles](https://docs.microsoft.com/azure/active-directory/role-based-access-built-in-roles) -which can be assigned to a service principal of an Azure AD application depending of your needs. - -``` -az role assignment create --assigner "SERVICE_PRINCIPAL_ID" --role "ROLE_NAME" -``` - -* Replace the `SERVICE_PRINCIPAL_ID` with the `appId` from previous step. -* Replace the `ROLE_NAME` with a role name of your choice. - -It is also possible to define custom role definitions. - -``` -az role definition create --role-definition role-definition.json -``` - -* Check [custom roles](https://docs.microsoft.com/azure/active-directory/role-based-access-control-custom-roles) for more details regarding the content of `role-definition.json` file. - - -### Acquire Access Token - -The common configuration used by all flows: - -```Go -const activeDirectoryEndpoint = "https://login.microsoftonline.com/" -tenantID := "TENANT_ID" -oauthConfig, err := adal.NewOAuthConfig(activeDirectoryEndpoint, tenantID) - -applicationID := "APPLICATION_ID" - -callback := func(token adal.Token) error { - // This is called after the token is acquired -} - -// The resource for which the token is acquired -resource := "https://management.core.windows.net/" -``` - -* Replace the `TENANT_ID` with your tenant ID. -* Replace the `APPLICATION_ID` with the value from previous section. - -#### Client Credentials - -```Go -applicationSecret := "APPLICATION_SECRET" - -spt, err := adal.NewServicePrincipalToken( - *oauthConfig, - appliationID, - applicationSecret, - resource, - callbacks...) -if err != nil { - return nil, err -} - -// Acquire a new access token -err = spt.Refresh() -if (err == nil) { - token := spt.Token -} -``` - -* Replace the `APPLICATION_SECRET` with the `password` value from previous section. - -#### Client Certificate - -```Go -certificatePath := "./example-app.pfx" - -certData, err := ioutil.ReadFile(certificatePath) -if err != nil { - return nil, fmt.Errorf("failed to read the certificate file (%s): %v", certificatePath, err) -} - -// Get the certificate and private key from pfx file -certificate, rsaPrivateKey, err := decodePkcs12(certData, "") -if err != nil { - return nil, fmt.Errorf("failed to decode pkcs12 certificate while creating spt: %v", err) -} - -spt, err := adal.NewServicePrincipalTokenFromCertificate( - *oauthConfig, - applicationID, - certificate, - rsaPrivateKey, - resource, - callbacks...) - -// Acquire a new access token -err = spt.Refresh() -if (err == nil) { - token := spt.Token -} -``` - -* Update the certificate path to point to the example-app.pfx file which was created in previous section. - - -#### Device Code - -```Go -oauthClient := &http.Client{} - -// Acquire the device code -deviceCode, err := adal.InitiateDeviceAuth( - oauthClient, - *oauthConfig, - applicationID, - resource) -if err != nil { - return nil, fmt.Errorf("Failed to start device auth flow: %s", err) -} - -// Display the authentication message -fmt.Println(*deviceCode.Message) - -// Wait here until the user is authenticated -token, err := adal.WaitForUserCompletion(oauthClient, deviceCode) -if err != nil { - return nil, fmt.Errorf("Failed to finish device auth flow: %s", err) -} - -spt, err := adal.NewServicePrincipalTokenFromManualToken( - *oauthConfig, - applicationID, - resource, - *token, - callbacks...) - -if (err == nil) { - token := spt.Token -} -``` - -#### Username password authenticate - -```Go -spt, err := adal.NewServicePrincipalTokenFromUsernamePassword( - *oauthConfig, - applicationID, - username, - password, - resource, - callbacks...) - -if (err == nil) { - token := spt.Token -} -``` - -#### Authorization code authenticate - -``` Go -spt, err := adal.NewServicePrincipalTokenFromAuthorizationCode( - *oauthConfig, - applicationID, - clientSecret, - authorizationCode, - redirectURI, - resource, - callbacks...) - -err = spt.Refresh() -if (err == nil) { - token := spt.Token -} -``` - -### Command Line Tool - -A command line tool is available in `cmd/adal.go` that can acquire a token for a given resource. It supports all flows mentioned above. - -``` -adal -h - -Usage of ./adal: - -applicationId string - application id - -certificatePath string - path to pk12/PFC application certificate - -mode string - authentication mode (device, secret, cert, refresh) (default "device") - -resource string - resource for which the token is requested - -secret string - application secret - -tenantId string - tenant id - -tokenCachePath string - location of oath token cache (default "/home/cgc/.adal/accessToken.json") -``` - -Example acquire a token for `https://management.core.windows.net/` using device code flow: - -``` -adal -mode device \ - -applicationId "APPLICATION_ID" \ - -tenantId "TENANT_ID" \ - -resource https://management.core.windows.net/ - -``` diff --git a/vendor/github.com/Azure/go-autorest/autorest/adal/config.go b/vendor/github.com/Azure/go-autorest/autorest/adal/config.go deleted file mode 100644 index fa5964742f..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/adal/config.go +++ /dev/null @@ -1,151 +0,0 @@ -package adal - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "errors" - "fmt" - "net/url" -) - -const ( - activeDirectoryEndpointTemplate = "%s/oauth2/%s%s" -) - -// OAuthConfig represents the endpoints needed -// in OAuth operations -type OAuthConfig struct { - AuthorityEndpoint url.URL `json:"authorityEndpoint"` - AuthorizeEndpoint url.URL `json:"authorizeEndpoint"` - TokenEndpoint url.URL `json:"tokenEndpoint"` - DeviceCodeEndpoint url.URL `json:"deviceCodeEndpoint"` -} - -// IsZero returns true if the OAuthConfig object is zero-initialized. -func (oac OAuthConfig) IsZero() bool { - return oac == OAuthConfig{} -} - -func validateStringParam(param, name string) error { - if len(param) == 0 { - return fmt.Errorf("parameter '" + name + "' cannot be empty") - } - return nil -} - -// NewOAuthConfig returns an OAuthConfig with tenant specific urls -func NewOAuthConfig(activeDirectoryEndpoint, tenantID string) (*OAuthConfig, error) { - apiVer := "1.0" - return NewOAuthConfigWithAPIVersion(activeDirectoryEndpoint, tenantID, &apiVer) -} - -// NewOAuthConfigWithAPIVersion returns an OAuthConfig with tenant specific urls. -// If apiVersion is not nil the "api-version" query parameter will be appended to the endpoint URLs with the specified value. -func NewOAuthConfigWithAPIVersion(activeDirectoryEndpoint, tenantID string, apiVersion *string) (*OAuthConfig, error) { - if err := validateStringParam(activeDirectoryEndpoint, "activeDirectoryEndpoint"); err != nil { - return nil, err - } - api := "" - // it's legal for tenantID to be empty so don't validate it - if apiVersion != nil { - if err := validateStringParam(*apiVersion, "apiVersion"); err != nil { - return nil, err - } - api = fmt.Sprintf("?api-version=%s", *apiVersion) - } - u, err := url.Parse(activeDirectoryEndpoint) - if err != nil { - return nil, err - } - authorityURL, err := u.Parse(tenantID) - if err != nil { - return nil, err - } - authorizeURL, err := u.Parse(fmt.Sprintf(activeDirectoryEndpointTemplate, tenantID, "authorize", api)) - if err != nil { - return nil, err - } - tokenURL, err := u.Parse(fmt.Sprintf(activeDirectoryEndpointTemplate, tenantID, "token", api)) - if err != nil { - return nil, err - } - deviceCodeURL, err := u.Parse(fmt.Sprintf(activeDirectoryEndpointTemplate, tenantID, "devicecode", api)) - if err != nil { - return nil, err - } - - return &OAuthConfig{ - AuthorityEndpoint: *authorityURL, - AuthorizeEndpoint: *authorizeURL, - TokenEndpoint: *tokenURL, - DeviceCodeEndpoint: *deviceCodeURL, - }, nil -} - -// MultiTenantOAuthConfig provides endpoints for primary and aulixiary tenant IDs. -type MultiTenantOAuthConfig interface { - PrimaryTenant() *OAuthConfig - AuxiliaryTenants() []*OAuthConfig -} - -// OAuthOptions contains optional OAuthConfig creation arguments. -type OAuthOptions struct { - APIVersion string -} - -func (c OAuthOptions) apiVersion() string { - if c.APIVersion != "" { - return fmt.Sprintf("?api-version=%s", c.APIVersion) - } - return "1.0" -} - -// NewMultiTenantOAuthConfig creates an object that support multitenant OAuth configuration. -// See https://docs.microsoft.com/en-us/azure/azure-resource-manager/authenticate-multi-tenant for more information. -func NewMultiTenantOAuthConfig(activeDirectoryEndpoint, primaryTenantID string, auxiliaryTenantIDs []string, options OAuthOptions) (MultiTenantOAuthConfig, error) { - if len(auxiliaryTenantIDs) == 0 || len(auxiliaryTenantIDs) > 3 { - return nil, errors.New("must specify one to three auxiliary tenants") - } - mtCfg := multiTenantOAuthConfig{ - cfgs: make([]*OAuthConfig, len(auxiliaryTenantIDs)+1), - } - apiVer := options.apiVersion() - pri, err := NewOAuthConfigWithAPIVersion(activeDirectoryEndpoint, primaryTenantID, &apiVer) - if err != nil { - return nil, fmt.Errorf("failed to create OAuthConfig for primary tenant: %v", err) - } - mtCfg.cfgs[0] = pri - for i := range auxiliaryTenantIDs { - aux, err := NewOAuthConfig(activeDirectoryEndpoint, auxiliaryTenantIDs[i]) - if err != nil { - return nil, fmt.Errorf("failed to create OAuthConfig for tenant '%s': %v", auxiliaryTenantIDs[i], err) - } - mtCfg.cfgs[i+1] = aux - } - return mtCfg, nil -} - -type multiTenantOAuthConfig struct { - // first config in the slice is the primary tenant - cfgs []*OAuthConfig -} - -func (m multiTenantOAuthConfig) PrimaryTenant() *OAuthConfig { - return m.cfgs[0] -} - -func (m multiTenantOAuthConfig) AuxiliaryTenants() []*OAuthConfig { - return m.cfgs[1:] -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/adal/devicetoken.go b/vendor/github.com/Azure/go-autorest/autorest/adal/devicetoken.go deleted file mode 100644 index 9daa4b58b8..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/adal/devicetoken.go +++ /dev/null @@ -1,273 +0,0 @@ -package adal - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/* - This file is largely based on rjw57/oauth2device's code, with the follow differences: - * scope -> resource, and only allow a single one - * receive "Message" in the DeviceCode struct and show it to users as the prompt - * azure-xplat-cli has the following behavior that this emulates: - - does not send client_secret during the token exchange - - sends resource again in the token exchange request -*/ - -import ( - "context" - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "net/url" - "strings" - "time" -) - -const ( - logPrefix = "autorest/adal/devicetoken:" -) - -var ( - // ErrDeviceGeneric represents an unknown error from the token endpoint when using device flow - ErrDeviceGeneric = fmt.Errorf("%s Error while retrieving OAuth token: Unknown Error", logPrefix) - - // ErrDeviceAccessDenied represents an access denied error from the token endpoint when using device flow - ErrDeviceAccessDenied = fmt.Errorf("%s Error while retrieving OAuth token: Access Denied", logPrefix) - - // ErrDeviceAuthorizationPending represents the server waiting on the user to complete the device flow - ErrDeviceAuthorizationPending = fmt.Errorf("%s Error while retrieving OAuth token: Authorization Pending", logPrefix) - - // ErrDeviceCodeExpired represents the server timing out and expiring the code during device flow - ErrDeviceCodeExpired = fmt.Errorf("%s Error while retrieving OAuth token: Code Expired", logPrefix) - - // ErrDeviceSlowDown represents the service telling us we're polling too often during device flow - ErrDeviceSlowDown = fmt.Errorf("%s Error while retrieving OAuth token: Slow Down", logPrefix) - - // ErrDeviceCodeEmpty represents an empty device code from the device endpoint while using device flow - ErrDeviceCodeEmpty = fmt.Errorf("%s Error while retrieving device code: Device Code Empty", logPrefix) - - // ErrOAuthTokenEmpty represents an empty OAuth token from the token endpoint when using device flow - ErrOAuthTokenEmpty = fmt.Errorf("%s Error while retrieving OAuth token: Token Empty", logPrefix) - - errCodeSendingFails = "Error occurred while sending request for Device Authorization Code" - errCodeHandlingFails = "Error occurred while handling response from the Device Endpoint" - errTokenSendingFails = "Error occurred while sending request with device code for a token" - errTokenHandlingFails = "Error occurred while handling response from the Token Endpoint (during device flow)" - errStatusNotOK = "Error HTTP status != 200" -) - -// DeviceCode is the object returned by the device auth endpoint -// It contains information to instruct the user to complete the auth flow -type DeviceCode struct { - DeviceCode *string `json:"device_code,omitempty"` - UserCode *string `json:"user_code,omitempty"` - VerificationURL *string `json:"verification_url,omitempty"` - ExpiresIn *int64 `json:"expires_in,string,omitempty"` - Interval *int64 `json:"interval,string,omitempty"` - - Message *string `json:"message"` // Azure specific - Resource string // store the following, stored when initiating, used when exchanging - OAuthConfig OAuthConfig - ClientID string -} - -// TokenError is the object returned by the token exchange endpoint -// when something is amiss -type TokenError struct { - Error *string `json:"error,omitempty"` - ErrorCodes []int `json:"error_codes,omitempty"` - ErrorDescription *string `json:"error_description,omitempty"` - Timestamp *string `json:"timestamp,omitempty"` - TraceID *string `json:"trace_id,omitempty"` -} - -// DeviceToken is the object return by the token exchange endpoint -// It can either look like a Token or an ErrorToken, so put both here -// and check for presence of "Error" to know if we are in error state -type deviceToken struct { - Token - TokenError -} - -// InitiateDeviceAuth initiates a device auth flow. It returns a DeviceCode -// that can be used with CheckForUserCompletion or WaitForUserCompletion. -// Deprecated: use InitiateDeviceAuthWithContext() instead. -func InitiateDeviceAuth(sender Sender, oauthConfig OAuthConfig, clientID, resource string) (*DeviceCode, error) { - return InitiateDeviceAuthWithContext(context.Background(), sender, oauthConfig, clientID, resource) -} - -// InitiateDeviceAuthWithContext initiates a device auth flow. It returns a DeviceCode -// that can be used with CheckForUserCompletion or WaitForUserCompletion. -func InitiateDeviceAuthWithContext(ctx context.Context, sender Sender, oauthConfig OAuthConfig, clientID, resource string) (*DeviceCode, error) { - v := url.Values{ - "client_id": []string{clientID}, - "resource": []string{resource}, - } - - s := v.Encode() - body := ioutil.NopCloser(strings.NewReader(s)) - - req, err := http.NewRequest(http.MethodPost, oauthConfig.DeviceCodeEndpoint.String(), body) - if err != nil { - return nil, fmt.Errorf("%s %s: %s", logPrefix, errCodeSendingFails, err.Error()) - } - - req.ContentLength = int64(len(s)) - req.Header.Set(contentType, mimeTypeFormPost) - resp, err := sender.Do(req.WithContext(ctx)) - if err != nil { - return nil, fmt.Errorf("%s %s: %s", logPrefix, errCodeSendingFails, err.Error()) - } - defer resp.Body.Close() - - rb, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, fmt.Errorf("%s %s: %s", logPrefix, errCodeHandlingFails, err.Error()) - } - - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("%s %s: %s", logPrefix, errCodeHandlingFails, errStatusNotOK) - } - - if len(strings.Trim(string(rb), " ")) == 0 { - return nil, ErrDeviceCodeEmpty - } - - var code DeviceCode - err = json.Unmarshal(rb, &code) - if err != nil { - return nil, fmt.Errorf("%s %s: %s", logPrefix, errCodeHandlingFails, err.Error()) - } - - code.ClientID = clientID - code.Resource = resource - code.OAuthConfig = oauthConfig - - return &code, nil -} - -// CheckForUserCompletion takes a DeviceCode and checks with the Azure AD OAuth endpoint -// to see if the device flow has: been completed, timed out, or otherwise failed -// Deprecated: use CheckForUserCompletionWithContext() instead. -func CheckForUserCompletion(sender Sender, code *DeviceCode) (*Token, error) { - return CheckForUserCompletionWithContext(context.Background(), sender, code) -} - -// CheckForUserCompletionWithContext takes a DeviceCode and checks with the Azure AD OAuth endpoint -// to see if the device flow has: been completed, timed out, or otherwise failed -func CheckForUserCompletionWithContext(ctx context.Context, sender Sender, code *DeviceCode) (*Token, error) { - v := url.Values{ - "client_id": []string{code.ClientID}, - "code": []string{*code.DeviceCode}, - "grant_type": []string{OAuthGrantTypeDeviceCode}, - "resource": []string{code.Resource}, - } - - s := v.Encode() - body := ioutil.NopCloser(strings.NewReader(s)) - - req, err := http.NewRequest(http.MethodPost, code.OAuthConfig.TokenEndpoint.String(), body) - if err != nil { - return nil, fmt.Errorf("%s %s: %s", logPrefix, errTokenSendingFails, err.Error()) - } - - req.ContentLength = int64(len(s)) - req.Header.Set(contentType, mimeTypeFormPost) - resp, err := sender.Do(req.WithContext(ctx)) - if err != nil { - return nil, fmt.Errorf("%s %s: %s", logPrefix, errTokenSendingFails, err.Error()) - } - defer resp.Body.Close() - - rb, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, fmt.Errorf("%s %s: %s", logPrefix, errTokenHandlingFails, err.Error()) - } - - if resp.StatusCode != http.StatusOK && len(strings.Trim(string(rb), " ")) == 0 { - return nil, fmt.Errorf("%s %s: %s", logPrefix, errTokenHandlingFails, errStatusNotOK) - } - if len(strings.Trim(string(rb), " ")) == 0 { - return nil, ErrOAuthTokenEmpty - } - - var token deviceToken - err = json.Unmarshal(rb, &token) - if err != nil { - return nil, fmt.Errorf("%s %s: %s", logPrefix, errTokenHandlingFails, err.Error()) - } - - if token.Error == nil { - return &token.Token, nil - } - - switch *token.Error { - case "authorization_pending": - return nil, ErrDeviceAuthorizationPending - case "slow_down": - return nil, ErrDeviceSlowDown - case "access_denied": - return nil, ErrDeviceAccessDenied - case "code_expired": - return nil, ErrDeviceCodeExpired - default: - // return a more meaningful error message if available - if token.ErrorDescription != nil { - return nil, fmt.Errorf("%s %s: %s", logPrefix, *token.Error, *token.ErrorDescription) - } - return nil, ErrDeviceGeneric - } -} - -// WaitForUserCompletion calls CheckForUserCompletion repeatedly until a token is granted or an error state occurs. -// This prevents the user from looping and checking against 'ErrDeviceAuthorizationPending'. -// Deprecated: use WaitForUserCompletionWithContext() instead. -func WaitForUserCompletion(sender Sender, code *DeviceCode) (*Token, error) { - return WaitForUserCompletionWithContext(context.Background(), sender, code) -} - -// WaitForUserCompletionWithContext calls CheckForUserCompletion repeatedly until a token is granted or an error -// state occurs. This prevents the user from looping and checking against 'ErrDeviceAuthorizationPending'. -func WaitForUserCompletionWithContext(ctx context.Context, sender Sender, code *DeviceCode) (*Token, error) { - intervalDuration := time.Duration(*code.Interval) * time.Second - waitDuration := intervalDuration - - for { - token, err := CheckForUserCompletionWithContext(ctx, sender, code) - - if err == nil { - return token, nil - } - - switch err { - case ErrDeviceSlowDown: - waitDuration += waitDuration - case ErrDeviceAuthorizationPending: - // noop - default: // everything else is "fatal" to us - return nil, err - } - - if waitDuration > (intervalDuration * 3) { - return nil, fmt.Errorf("%s Error waiting for user to complete device flow. Server told us to slow_down too much", logPrefix) - } - - select { - case <-time.After(waitDuration): - // noop - case <-ctx.Done(): - return nil, ctx.Err() - } - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/adal/go_mod_tidy_hack.go b/vendor/github.com/Azure/go-autorest/autorest/adal/go_mod_tidy_hack.go deleted file mode 100644 index 647a61bb8c..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/adal/go_mod_tidy_hack.go +++ /dev/null @@ -1,25 +0,0 @@ -//go:build modhack -// +build modhack - -package adal - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// This file, and the github.com/Azure/go-autorest import, won't actually become part of -// the resultant binary. - -// Necessary for safely adding multi-module repo. -// See: https://github.com/golang/go/wiki/Modules#is-it-possible-to-add-a-module-to-a-multi-module-repository -import _ "github.com/Azure/go-autorest" diff --git a/vendor/github.com/Azure/go-autorest/autorest/adal/persist.go b/vendor/github.com/Azure/go-autorest/autorest/adal/persist.go deleted file mode 100644 index 2a974a39b3..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/adal/persist.go +++ /dev/null @@ -1,135 +0,0 @@ -package adal - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "crypto/rsa" - "crypto/x509" - "encoding/json" - "errors" - "fmt" - "io/ioutil" - "os" - "path/filepath" - - "golang.org/x/crypto/pkcs12" -) - -var ( - // ErrMissingCertificate is returned when no local certificate is found in the provided PFX data. - ErrMissingCertificate = errors.New("adal: certificate missing") - - // ErrMissingPrivateKey is returned when no private key is found in the provided PFX data. - ErrMissingPrivateKey = errors.New("adal: private key missing") -) - -// LoadToken restores a Token object from a file located at 'path'. -func LoadToken(path string) (*Token, error) { - file, err := os.Open(path) - if err != nil { - return nil, fmt.Errorf("failed to open file (%s) while loading token: %v", path, err) - } - defer file.Close() - - var token Token - - dec := json.NewDecoder(file) - if err = dec.Decode(&token); err != nil { - return nil, fmt.Errorf("failed to decode contents of file (%s) into Token representation: %v", path, err) - } - return &token, nil -} - -// SaveToken persists an oauth token at the given location on disk. -// It moves the new file into place so it can safely be used to replace an existing file -// that maybe accessed by multiple processes. -func SaveToken(path string, mode os.FileMode, token Token) error { - dir := filepath.Dir(path) - err := os.MkdirAll(dir, os.ModePerm) - if err != nil { - return fmt.Errorf("failed to create directory (%s) to store token in: %v", dir, err) - } - - newFile, err := ioutil.TempFile(dir, "token") - if err != nil { - return fmt.Errorf("failed to create the temp file to write the token: %v", err) - } - tempPath := newFile.Name() - - if err := json.NewEncoder(newFile).Encode(token); err != nil { - return fmt.Errorf("failed to encode token to file (%s) while saving token: %v", tempPath, err) - } - if err := newFile.Close(); err != nil { - return fmt.Errorf("failed to close temp file %s: %v", tempPath, err) - } - - // Atomic replace to avoid multi-writer file corruptions - if err := os.Rename(tempPath, path); err != nil { - return fmt.Errorf("failed to move temporary token to desired output location. src=%s dst=%s: %v", tempPath, path, err) - } - if err := os.Chmod(path, mode); err != nil { - return fmt.Errorf("failed to chmod the token file %s: %v", path, err) - } - return nil -} - -// DecodePfxCertificateData extracts the x509 certificate and RSA private key from the provided PFX data. -// The PFX data must contain a private key along with a certificate whose public key matches that of the -// private key or an error is returned. -// If the private key is not password protected pass the empty string for password. -func DecodePfxCertificateData(pfxData []byte, password string) (*x509.Certificate, *rsa.PrivateKey, error) { - blocks, err := pkcs12.ToPEM(pfxData, password) - if err != nil { - return nil, nil, err - } - // first extract the private key - var priv *rsa.PrivateKey - for _, block := range blocks { - if block.Type == "PRIVATE KEY" { - priv, err = x509.ParsePKCS1PrivateKey(block.Bytes) - if err != nil { - return nil, nil, err - } - break - } - } - if priv == nil { - return nil, nil, ErrMissingPrivateKey - } - // now find the certificate with the matching public key of our private key - var cert *x509.Certificate - for _, block := range blocks { - if block.Type == "CERTIFICATE" { - pcert, err := x509.ParseCertificate(block.Bytes) - if err != nil { - return nil, nil, err - } - certKey, ok := pcert.PublicKey.(*rsa.PublicKey) - if !ok { - // keep looking - continue - } - if priv.E == certKey.E && priv.N.Cmp(certKey.N) == 0 { - // found a match - cert = pcert - break - } - } - } - if cert == nil { - return nil, nil, ErrMissingCertificate - } - return cert, priv, nil -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/adal/sender.go b/vendor/github.com/Azure/go-autorest/autorest/adal/sender.go deleted file mode 100644 index eb649bce9f..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/adal/sender.go +++ /dev/null @@ -1,101 +0,0 @@ -package adal - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "crypto/tls" - "net" - "net/http" - "net/http/cookiejar" - "sync" - "time" - - "github.com/Azure/go-autorest/tracing" -) - -const ( - contentType = "Content-Type" - mimeTypeFormPost = "application/x-www-form-urlencoded" -) - -// DO NOT ACCESS THIS DIRECTLY. go through sender() -var defaultSender Sender -var defaultSenderInit = &sync.Once{} - -// Sender is the interface that wraps the Do method to send HTTP requests. -// -// The standard http.Client conforms to this interface. -type Sender interface { - Do(*http.Request) (*http.Response, error) -} - -// SenderFunc is a method that implements the Sender interface. -type SenderFunc func(*http.Request) (*http.Response, error) - -// Do implements the Sender interface on SenderFunc. -func (sf SenderFunc) Do(r *http.Request) (*http.Response, error) { - return sf(r) -} - -// SendDecorator takes and possibly decorates, by wrapping, a Sender. Decorators may affect the -// http.Request and pass it along or, first, pass the http.Request along then react to the -// http.Response result. -type SendDecorator func(Sender) Sender - -// CreateSender creates, decorates, and returns, as a Sender, the default http.Client. -func CreateSender(decorators ...SendDecorator) Sender { - return DecorateSender(sender(), decorators...) -} - -// DecorateSender accepts a Sender and a, possibly empty, set of SendDecorators, which is applies to -// the Sender. Decorators are applied in the order received, but their affect upon the request -// depends on whether they are a pre-decorator (change the http.Request and then pass it along) or a -// post-decorator (pass the http.Request along and react to the results in http.Response). -func DecorateSender(s Sender, decorators ...SendDecorator) Sender { - for _, decorate := range decorators { - s = decorate(s) - } - return s -} - -func sender() Sender { - // note that we can't init defaultSender in init() since it will - // execute before calling code has had a chance to enable tracing - defaultSenderInit.Do(func() { - // copied from http.DefaultTransport with a TLS minimum version. - transport := &http.Transport{ - Proxy: http.ProxyFromEnvironment, - DialContext: (&net.Dialer{ - Timeout: 30 * time.Second, - KeepAlive: 30 * time.Second, - }).DialContext, - ForceAttemptHTTP2: true, - MaxIdleConns: 100, - IdleConnTimeout: 90 * time.Second, - TLSHandshakeTimeout: 10 * time.Second, - ExpectContinueTimeout: 1 * time.Second, - TLSClientConfig: &tls.Config{ - MinVersion: tls.VersionTLS12, - }, - } - var roundTripper http.RoundTripper = transport - if tracing.IsEnabled() { - roundTripper = tracing.NewTransport(transport) - } - j, _ := cookiejar.New(nil) - defaultSender = &http.Client{Jar: j, Transport: roundTripper} - }) - return defaultSender -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/adal/token.go b/vendor/github.com/Azure/go-autorest/autorest/adal/token.go deleted file mode 100644 index 1a9c8ab537..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/adal/token.go +++ /dev/null @@ -1,1396 +0,0 @@ -package adal - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "context" - "crypto/rand" - "crypto/rsa" - "crypto/sha1" - "crypto/x509" - "encoding/base64" - "encoding/json" - "errors" - "fmt" - "io" - "io/ioutil" - "math" - "net/http" - "net/url" - "os" - "strconv" - "strings" - "sync" - "time" - - "github.com/Azure/go-autorest/autorest/date" - "github.com/Azure/go-autorest/logger" - "github.com/golang-jwt/jwt/v4" -) - -const ( - defaultRefresh = 5 * time.Minute - - // OAuthGrantTypeDeviceCode is the "grant_type" identifier used in device flow - OAuthGrantTypeDeviceCode = "device_code" - - // OAuthGrantTypeClientCredentials is the "grant_type" identifier used in credential flows - OAuthGrantTypeClientCredentials = "client_credentials" - - // OAuthGrantTypeUserPass is the "grant_type" identifier used in username and password auth flows - OAuthGrantTypeUserPass = "password" - - // OAuthGrantTypeRefreshToken is the "grant_type" identifier used in refresh token flows - OAuthGrantTypeRefreshToken = "refresh_token" - - // OAuthGrantTypeAuthorizationCode is the "grant_type" identifier used in authorization code flows - OAuthGrantTypeAuthorizationCode = "authorization_code" - - // metadataHeader is the header required by MSI extension - metadataHeader = "Metadata" - - // msiEndpoint is the well known endpoint for getting MSI authentications tokens - msiEndpoint = "http://169.254.169.254/metadata/identity/oauth2/token" - - // the API version to use for the MSI endpoint - msiAPIVersion = "2018-02-01" - - // the default number of attempts to refresh an MSI authentication token - defaultMaxMSIRefreshAttempts = 5 - - // asMSIEndpointEnv is the environment variable used to store the endpoint on App Service and Functions - msiEndpointEnv = "MSI_ENDPOINT" - - // asMSISecretEnv is the environment variable used to store the request secret on App Service and Functions - msiSecretEnv = "MSI_SECRET" - - // the API version to use for the legacy App Service MSI endpoint - appServiceAPIVersion2017 = "2017-09-01" - - // secret header used when authenticating against app service MSI endpoint - secretHeader = "Secret" - - // the format for expires_on in UTC with AM/PM - expiresOnDateFormatPM = "1/2/2006 15:04:05 PM +00:00" - - // the format for expires_on in UTC without AM/PM - expiresOnDateFormat = "1/2/2006 15:04:05 +00:00" -) - -// OAuthTokenProvider is an interface which should be implemented by an access token retriever -type OAuthTokenProvider interface { - OAuthToken() string -} - -// MultitenantOAuthTokenProvider provides tokens used for multi-tenant authorization. -type MultitenantOAuthTokenProvider interface { - PrimaryOAuthToken() string - AuxiliaryOAuthTokens() []string -} - -// TokenRefreshError is an interface used by errors returned during token refresh. -type TokenRefreshError interface { - error - Response() *http.Response -} - -// Refresher is an interface for token refresh functionality -type Refresher interface { - Refresh() error - RefreshExchange(resource string) error - EnsureFresh() error -} - -// RefresherWithContext is an interface for token refresh functionality -type RefresherWithContext interface { - RefreshWithContext(ctx context.Context) error - RefreshExchangeWithContext(ctx context.Context, resource string) error - EnsureFreshWithContext(ctx context.Context) error -} - -// TokenRefreshCallback is the type representing callbacks that will be called after -// a successful token refresh -type TokenRefreshCallback func(Token) error - -// TokenRefresh is a type representing a custom callback to refresh a token -type TokenRefresh func(ctx context.Context, resource string) (*Token, error) - -// Token encapsulates the access token used to authorize Azure requests. -// https://docs.microsoft.com/en-us/azure/active-directory/develop/v1-oauth2-client-creds-grant-flow#service-to-service-access-token-response -type Token struct { - AccessToken string `json:"access_token"` - RefreshToken string `json:"refresh_token"` - - ExpiresIn json.Number `json:"expires_in"` - ExpiresOn json.Number `json:"expires_on"` - NotBefore json.Number `json:"not_before"` - - Resource string `json:"resource"` - Type string `json:"token_type"` -} - -func newToken() Token { - return Token{ - ExpiresIn: "0", - ExpiresOn: "0", - NotBefore: "0", - } -} - -// IsZero returns true if the token object is zero-initialized. -func (t Token) IsZero() bool { - return t == Token{} -} - -// Expires returns the time.Time when the Token expires. -func (t Token) Expires() time.Time { - s, err := t.ExpiresOn.Float64() - if err != nil { - s = -3600 - } - - expiration := date.NewUnixTimeFromSeconds(s) - - return time.Time(expiration).UTC() -} - -// IsExpired returns true if the Token is expired, false otherwise. -func (t Token) IsExpired() bool { - return t.WillExpireIn(0) -} - -// WillExpireIn returns true if the Token will expire after the passed time.Duration interval -// from now, false otherwise. -func (t Token) WillExpireIn(d time.Duration) bool { - return !t.Expires().After(time.Now().Add(d)) -} - -//OAuthToken return the current access token -func (t *Token) OAuthToken() string { - return t.AccessToken -} - -// ServicePrincipalSecret is an interface that allows various secret mechanism to fill the form -// that is submitted when acquiring an oAuth token. -type ServicePrincipalSecret interface { - SetAuthenticationValues(spt *ServicePrincipalToken, values *url.Values) error -} - -// ServicePrincipalNoSecret represents a secret type that contains no secret -// meaning it is not valid for fetching a fresh token. This is used by Manual -type ServicePrincipalNoSecret struct { -} - -// SetAuthenticationValues is a method of the interface ServicePrincipalSecret -// It only returns an error for the ServicePrincipalNoSecret type -func (noSecret *ServicePrincipalNoSecret) SetAuthenticationValues(spt *ServicePrincipalToken, v *url.Values) error { - return fmt.Errorf("Manually created ServicePrincipalToken does not contain secret material to retrieve a new access token") -} - -// MarshalJSON implements the json.Marshaler interface. -func (noSecret ServicePrincipalNoSecret) MarshalJSON() ([]byte, error) { - type tokenType struct { - Type string `json:"type"` - } - return json.Marshal(tokenType{ - Type: "ServicePrincipalNoSecret", - }) -} - -// ServicePrincipalTokenSecret implements ServicePrincipalSecret for client_secret type authorization. -type ServicePrincipalTokenSecret struct { - ClientSecret string `json:"value"` -} - -// SetAuthenticationValues is a method of the interface ServicePrincipalSecret. -// It will populate the form submitted during oAuth Token Acquisition using the client_secret. -func (tokenSecret *ServicePrincipalTokenSecret) SetAuthenticationValues(spt *ServicePrincipalToken, v *url.Values) error { - v.Set("client_secret", tokenSecret.ClientSecret) - return nil -} - -// MarshalJSON implements the json.Marshaler interface. -func (tokenSecret ServicePrincipalTokenSecret) MarshalJSON() ([]byte, error) { - type tokenType struct { - Type string `json:"type"` - Value string `json:"value"` - } - return json.Marshal(tokenType{ - Type: "ServicePrincipalTokenSecret", - Value: tokenSecret.ClientSecret, - }) -} - -// ServicePrincipalCertificateSecret implements ServicePrincipalSecret for generic RSA cert auth with signed JWTs. -type ServicePrincipalCertificateSecret struct { - Certificate *x509.Certificate - PrivateKey *rsa.PrivateKey -} - -// SignJwt returns the JWT signed with the certificate's private key. -func (secret *ServicePrincipalCertificateSecret) SignJwt(spt *ServicePrincipalToken) (string, error) { - hasher := sha1.New() - _, err := hasher.Write(secret.Certificate.Raw) - if err != nil { - return "", err - } - - thumbprint := base64.URLEncoding.EncodeToString(hasher.Sum(nil)) - - // The jti (JWT ID) claim provides a unique identifier for the JWT. - jti := make([]byte, 20) - _, err = rand.Read(jti) - if err != nil { - return "", err - } - - token := jwt.New(jwt.SigningMethodRS256) - token.Header["x5t"] = thumbprint - x5c := []string{base64.StdEncoding.EncodeToString(secret.Certificate.Raw)} - token.Header["x5c"] = x5c - token.Claims = jwt.MapClaims{ - "aud": spt.inner.OauthConfig.TokenEndpoint.String(), - "iss": spt.inner.ClientID, - "sub": spt.inner.ClientID, - "jti": base64.URLEncoding.EncodeToString(jti), - "nbf": time.Now().Unix(), - "exp": time.Now().Add(24 * time.Hour).Unix(), - } - - signedString, err := token.SignedString(secret.PrivateKey) - return signedString, err -} - -// SetAuthenticationValues is a method of the interface ServicePrincipalSecret. -// It will populate the form submitted during oAuth Token Acquisition using a JWT signed with a certificate. -func (secret *ServicePrincipalCertificateSecret) SetAuthenticationValues(spt *ServicePrincipalToken, v *url.Values) error { - jwt, err := secret.SignJwt(spt) - if err != nil { - return err - } - - v.Set("client_assertion", jwt) - v.Set("client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer") - return nil -} - -// MarshalJSON implements the json.Marshaler interface. -func (secret ServicePrincipalCertificateSecret) MarshalJSON() ([]byte, error) { - return nil, errors.New("marshalling ServicePrincipalCertificateSecret is not supported") -} - -// ServicePrincipalMSISecret implements ServicePrincipalSecret for machines running the MSI Extension. -type ServicePrincipalMSISecret struct { - msiType msiType - clientResourceID string -} - -// SetAuthenticationValues is a method of the interface ServicePrincipalSecret. -func (msiSecret *ServicePrincipalMSISecret) SetAuthenticationValues(spt *ServicePrincipalToken, v *url.Values) error { - return nil -} - -// MarshalJSON implements the json.Marshaler interface. -func (msiSecret ServicePrincipalMSISecret) MarshalJSON() ([]byte, error) { - return nil, errors.New("marshalling ServicePrincipalMSISecret is not supported") -} - -// ServicePrincipalUsernamePasswordSecret implements ServicePrincipalSecret for username and password auth. -type ServicePrincipalUsernamePasswordSecret struct { - Username string `json:"username"` - Password string `json:"password"` -} - -// SetAuthenticationValues is a method of the interface ServicePrincipalSecret. -func (secret *ServicePrincipalUsernamePasswordSecret) SetAuthenticationValues(spt *ServicePrincipalToken, v *url.Values) error { - v.Set("username", secret.Username) - v.Set("password", secret.Password) - return nil -} - -// MarshalJSON implements the json.Marshaler interface. -func (secret ServicePrincipalUsernamePasswordSecret) MarshalJSON() ([]byte, error) { - type tokenType struct { - Type string `json:"type"` - Username string `json:"username"` - Password string `json:"password"` - } - return json.Marshal(tokenType{ - Type: "ServicePrincipalUsernamePasswordSecret", - Username: secret.Username, - Password: secret.Password, - }) -} - -// ServicePrincipalAuthorizationCodeSecret implements ServicePrincipalSecret for authorization code auth. -type ServicePrincipalAuthorizationCodeSecret struct { - ClientSecret string `json:"value"` - AuthorizationCode string `json:"authCode"` - RedirectURI string `json:"redirect"` -} - -// SetAuthenticationValues is a method of the interface ServicePrincipalSecret. -func (secret *ServicePrincipalAuthorizationCodeSecret) SetAuthenticationValues(spt *ServicePrincipalToken, v *url.Values) error { - v.Set("code", secret.AuthorizationCode) - v.Set("client_secret", secret.ClientSecret) - v.Set("redirect_uri", secret.RedirectURI) - return nil -} - -// MarshalJSON implements the json.Marshaler interface. -func (secret ServicePrincipalAuthorizationCodeSecret) MarshalJSON() ([]byte, error) { - type tokenType struct { - Type string `json:"type"` - Value string `json:"value"` - AuthCode string `json:"authCode"` - Redirect string `json:"redirect"` - } - return json.Marshal(tokenType{ - Type: "ServicePrincipalAuthorizationCodeSecret", - Value: secret.ClientSecret, - AuthCode: secret.AuthorizationCode, - Redirect: secret.RedirectURI, - }) -} - -// ServicePrincipalFederatedSecret implements ServicePrincipalSecret for Federated JWTs. -type ServicePrincipalFederatedSecret struct { - jwt string -} - -// SetAuthenticationValues is a method of the interface ServicePrincipalSecret. -// It will populate the form submitted during OAuth Token Acquisition using a JWT signed by an OIDC issuer. -func (secret *ServicePrincipalFederatedSecret) SetAuthenticationValues(spt *ServicePrincipalToken, v *url.Values) error { - - v.Set("client_assertion", secret.jwt) - v.Set("client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer") - return nil -} - -// MarshalJSON implements the json.Marshaler interface. -func (secret ServicePrincipalFederatedSecret) MarshalJSON() ([]byte, error) { - return nil, errors.New("marshalling ServicePrincipalFederatedSecret is not supported") -} - -// ServicePrincipalToken encapsulates a Token created for a Service Principal. -type ServicePrincipalToken struct { - inner servicePrincipalToken - refreshLock *sync.RWMutex - sender Sender - customRefreshFunc TokenRefresh - refreshCallbacks []TokenRefreshCallback - // MaxMSIRefreshAttempts is the maximum number of attempts to refresh an MSI token. - // Settings this to a value less than 1 will use the default value. - MaxMSIRefreshAttempts int -} - -// MarshalTokenJSON returns the marshalled inner token. -func (spt ServicePrincipalToken) MarshalTokenJSON() ([]byte, error) { - return json.Marshal(spt.inner.Token) -} - -// SetRefreshCallbacks replaces any existing refresh callbacks with the specified callbacks. -func (spt *ServicePrincipalToken) SetRefreshCallbacks(callbacks []TokenRefreshCallback) { - spt.refreshCallbacks = callbacks -} - -// SetCustomRefreshFunc sets a custom refresh function used to refresh the token. -func (spt *ServicePrincipalToken) SetCustomRefreshFunc(customRefreshFunc TokenRefresh) { - spt.customRefreshFunc = customRefreshFunc -} - -// MarshalJSON implements the json.Marshaler interface. -func (spt ServicePrincipalToken) MarshalJSON() ([]byte, error) { - return json.Marshal(spt.inner) -} - -// UnmarshalJSON implements the json.Unmarshaler interface. -func (spt *ServicePrincipalToken) UnmarshalJSON(data []byte) error { - // need to determine the token type - raw := map[string]interface{}{} - err := json.Unmarshal(data, &raw) - if err != nil { - return err - } - secret := raw["secret"].(map[string]interface{}) - switch secret["type"] { - case "ServicePrincipalNoSecret": - spt.inner.Secret = &ServicePrincipalNoSecret{} - case "ServicePrincipalTokenSecret": - spt.inner.Secret = &ServicePrincipalTokenSecret{} - case "ServicePrincipalCertificateSecret": - return errors.New("unmarshalling ServicePrincipalCertificateSecret is not supported") - case "ServicePrincipalMSISecret": - return errors.New("unmarshalling ServicePrincipalMSISecret is not supported") - case "ServicePrincipalUsernamePasswordSecret": - spt.inner.Secret = &ServicePrincipalUsernamePasswordSecret{} - case "ServicePrincipalAuthorizationCodeSecret": - spt.inner.Secret = &ServicePrincipalAuthorizationCodeSecret{} - case "ServicePrincipalFederatedSecret": - return errors.New("unmarshalling ServicePrincipalFederatedSecret is not supported") - default: - return fmt.Errorf("unrecognized token type '%s'", secret["type"]) - } - err = json.Unmarshal(data, &spt.inner) - if err != nil { - return err - } - // Don't override the refreshLock or the sender if those have been already set. - if spt.refreshLock == nil { - spt.refreshLock = &sync.RWMutex{} - } - if spt.sender == nil { - spt.sender = sender() - } - return nil -} - -// internal type used for marshalling/unmarshalling -type servicePrincipalToken struct { - Token Token `json:"token"` - Secret ServicePrincipalSecret `json:"secret"` - OauthConfig OAuthConfig `json:"oauth"` - ClientID string `json:"clientID"` - Resource string `json:"resource"` - AutoRefresh bool `json:"autoRefresh"` - RefreshWithin time.Duration `json:"refreshWithin"` -} - -func validateOAuthConfig(oac OAuthConfig) error { - if oac.IsZero() { - return fmt.Errorf("parameter 'oauthConfig' cannot be zero-initialized") - } - return nil -} - -// NewServicePrincipalTokenWithSecret create a ServicePrincipalToken using the supplied ServicePrincipalSecret implementation. -func NewServicePrincipalTokenWithSecret(oauthConfig OAuthConfig, id string, resource string, secret ServicePrincipalSecret, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) { - if err := validateOAuthConfig(oauthConfig); err != nil { - return nil, err - } - if err := validateStringParam(id, "id"); err != nil { - return nil, err - } - if err := validateStringParam(resource, "resource"); err != nil { - return nil, err - } - if secret == nil { - return nil, fmt.Errorf("parameter 'secret' cannot be nil") - } - spt := &ServicePrincipalToken{ - inner: servicePrincipalToken{ - Token: newToken(), - OauthConfig: oauthConfig, - Secret: secret, - ClientID: id, - Resource: resource, - AutoRefresh: true, - RefreshWithin: defaultRefresh, - }, - refreshLock: &sync.RWMutex{}, - sender: sender(), - refreshCallbacks: callbacks, - } - return spt, nil -} - -// NewServicePrincipalTokenFromManualToken creates a ServicePrincipalToken using the supplied token -func NewServicePrincipalTokenFromManualToken(oauthConfig OAuthConfig, clientID string, resource string, token Token, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) { - if err := validateOAuthConfig(oauthConfig); err != nil { - return nil, err - } - if err := validateStringParam(clientID, "clientID"); err != nil { - return nil, err - } - if err := validateStringParam(resource, "resource"); err != nil { - return nil, err - } - if token.IsZero() { - return nil, fmt.Errorf("parameter 'token' cannot be zero-initialized") - } - spt, err := NewServicePrincipalTokenWithSecret( - oauthConfig, - clientID, - resource, - &ServicePrincipalNoSecret{}, - callbacks...) - if err != nil { - return nil, err - } - - spt.inner.Token = token - - return spt, nil -} - -// NewServicePrincipalTokenFromManualTokenSecret creates a ServicePrincipalToken using the supplied token and secret -func NewServicePrincipalTokenFromManualTokenSecret(oauthConfig OAuthConfig, clientID string, resource string, token Token, secret ServicePrincipalSecret, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) { - if err := validateOAuthConfig(oauthConfig); err != nil { - return nil, err - } - if err := validateStringParam(clientID, "clientID"); err != nil { - return nil, err - } - if err := validateStringParam(resource, "resource"); err != nil { - return nil, err - } - if secret == nil { - return nil, fmt.Errorf("parameter 'secret' cannot be nil") - } - if token.IsZero() { - return nil, fmt.Errorf("parameter 'token' cannot be zero-initialized") - } - spt, err := NewServicePrincipalTokenWithSecret( - oauthConfig, - clientID, - resource, - secret, - callbacks...) - if err != nil { - return nil, err - } - - spt.inner.Token = token - - return spt, nil -} - -// NewServicePrincipalToken creates a ServicePrincipalToken from the supplied Service Principal -// credentials scoped to the named resource. -func NewServicePrincipalToken(oauthConfig OAuthConfig, clientID string, secret string, resource string, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) { - if err := validateOAuthConfig(oauthConfig); err != nil { - return nil, err - } - if err := validateStringParam(clientID, "clientID"); err != nil { - return nil, err - } - if err := validateStringParam(secret, "secret"); err != nil { - return nil, err - } - if err := validateStringParam(resource, "resource"); err != nil { - return nil, err - } - return NewServicePrincipalTokenWithSecret( - oauthConfig, - clientID, - resource, - &ServicePrincipalTokenSecret{ - ClientSecret: secret, - }, - callbacks..., - ) -} - -// NewServicePrincipalTokenFromCertificate creates a ServicePrincipalToken from the supplied pkcs12 bytes. -func NewServicePrincipalTokenFromCertificate(oauthConfig OAuthConfig, clientID string, certificate *x509.Certificate, privateKey *rsa.PrivateKey, resource string, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) { - if err := validateOAuthConfig(oauthConfig); err != nil { - return nil, err - } - if err := validateStringParam(clientID, "clientID"); err != nil { - return nil, err - } - if err := validateStringParam(resource, "resource"); err != nil { - return nil, err - } - if certificate == nil { - return nil, fmt.Errorf("parameter 'certificate' cannot be nil") - } - if privateKey == nil { - return nil, fmt.Errorf("parameter 'privateKey' cannot be nil") - } - return NewServicePrincipalTokenWithSecret( - oauthConfig, - clientID, - resource, - &ServicePrincipalCertificateSecret{ - PrivateKey: privateKey, - Certificate: certificate, - }, - callbacks..., - ) -} - -// NewServicePrincipalTokenFromUsernamePassword creates a ServicePrincipalToken from the username and password. -func NewServicePrincipalTokenFromUsernamePassword(oauthConfig OAuthConfig, clientID string, username string, password string, resource string, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) { - if err := validateOAuthConfig(oauthConfig); err != nil { - return nil, err - } - if err := validateStringParam(clientID, "clientID"); err != nil { - return nil, err - } - if err := validateStringParam(username, "username"); err != nil { - return nil, err - } - if err := validateStringParam(password, "password"); err != nil { - return nil, err - } - if err := validateStringParam(resource, "resource"); err != nil { - return nil, err - } - return NewServicePrincipalTokenWithSecret( - oauthConfig, - clientID, - resource, - &ServicePrincipalUsernamePasswordSecret{ - Username: username, - Password: password, - }, - callbacks..., - ) -} - -// NewServicePrincipalTokenFromAuthorizationCode creates a ServicePrincipalToken from the -func NewServicePrincipalTokenFromAuthorizationCode(oauthConfig OAuthConfig, clientID string, clientSecret string, authorizationCode string, redirectURI string, resource string, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) { - - if err := validateOAuthConfig(oauthConfig); err != nil { - return nil, err - } - if err := validateStringParam(clientID, "clientID"); err != nil { - return nil, err - } - if err := validateStringParam(clientSecret, "clientSecret"); err != nil { - return nil, err - } - if err := validateStringParam(authorizationCode, "authorizationCode"); err != nil { - return nil, err - } - if err := validateStringParam(redirectURI, "redirectURI"); err != nil { - return nil, err - } - if err := validateStringParam(resource, "resource"); err != nil { - return nil, err - } - - return NewServicePrincipalTokenWithSecret( - oauthConfig, - clientID, - resource, - &ServicePrincipalAuthorizationCodeSecret{ - ClientSecret: clientSecret, - AuthorizationCode: authorizationCode, - RedirectURI: redirectURI, - }, - callbacks..., - ) -} - -// NewServicePrincipalTokenFromFederatedToken creates a ServicePrincipalToken from the supplied federated OIDC JWT. -func NewServicePrincipalTokenFromFederatedToken(oauthConfig OAuthConfig, clientID string, jwt string, resource string, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) { - if err := validateOAuthConfig(oauthConfig); err != nil { - return nil, err - } - if err := validateStringParam(clientID, "clientID"); err != nil { - return nil, err - } - if err := validateStringParam(resource, "resource"); err != nil { - return nil, err - } - if jwt == "" { - return nil, fmt.Errorf("parameter 'jwt' cannot be empty") - } - return NewServicePrincipalTokenWithSecret( - oauthConfig, - clientID, - resource, - &ServicePrincipalFederatedSecret{ - jwt: jwt, - }, - callbacks..., - ) -} - -type msiType int - -const ( - msiTypeUnavailable msiType = iota - msiTypeAppServiceV20170901 - msiTypeCloudShell - msiTypeIMDS -) - -func (m msiType) String() string { - switch m { - case msiTypeAppServiceV20170901: - return "AppServiceV20170901" - case msiTypeCloudShell: - return "CloudShell" - case msiTypeIMDS: - return "IMDS" - default: - return fmt.Sprintf("unhandled MSI type %d", m) - } -} - -// returns the MSI type and endpoint, or an error -func getMSIType() (msiType, string, error) { - if endpointEnvVar := os.Getenv(msiEndpointEnv); endpointEnvVar != "" { - // if the env var MSI_ENDPOINT is set - if secretEnvVar := os.Getenv(msiSecretEnv); secretEnvVar != "" { - // if BOTH the env vars MSI_ENDPOINT and MSI_SECRET are set the msiType is AppService - return msiTypeAppServiceV20170901, endpointEnvVar, nil - } - // if ONLY the env var MSI_ENDPOINT is set the msiType is CloudShell - return msiTypeCloudShell, endpointEnvVar, nil - } - // if MSI_ENDPOINT is NOT set assume the msiType is IMDS - return msiTypeIMDS, msiEndpoint, nil -} - -// GetMSIVMEndpoint gets the MSI endpoint on Virtual Machines. -// NOTE: this always returns the IMDS endpoint, it does not work for app services or cloud shell. -// Deprecated: NewServicePrincipalTokenFromMSI() and variants will automatically detect the endpoint. -func GetMSIVMEndpoint() (string, error) { - return msiEndpoint, nil -} - -// GetMSIAppServiceEndpoint get the MSI endpoint for App Service and Functions. -// It will return an error when not running in an app service/functions environment. -// Deprecated: NewServicePrincipalTokenFromMSI() and variants will automatically detect the endpoint. -func GetMSIAppServiceEndpoint() (string, error) { - msiType, endpoint, err := getMSIType() - if err != nil { - return "", err - } - switch msiType { - case msiTypeAppServiceV20170901: - return endpoint, nil - default: - return "", fmt.Errorf("%s is not app service environment", msiType) - } -} - -// GetMSIEndpoint get the appropriate MSI endpoint depending on the runtime environment -// Deprecated: NewServicePrincipalTokenFromMSI() and variants will automatically detect the endpoint. -func GetMSIEndpoint() (string, error) { - _, endpoint, err := getMSIType() - return endpoint, err -} - -// NewServicePrincipalTokenFromMSI creates a ServicePrincipalToken via the MSI VM Extension. -// It will use the system assigned identity when creating the token. -// msiEndpoint - empty string, or pass a non-empty string to override the default value. -// Deprecated: use NewServicePrincipalTokenFromManagedIdentity() instead. -func NewServicePrincipalTokenFromMSI(msiEndpoint, resource string, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) { - return newServicePrincipalTokenFromMSI(msiEndpoint, resource, "", "", callbacks...) -} - -// NewServicePrincipalTokenFromMSIWithUserAssignedID creates a ServicePrincipalToken via the MSI VM Extension. -// It will use the clientID of specified user assigned identity when creating the token. -// msiEndpoint - empty string, or pass a non-empty string to override the default value. -// Deprecated: use NewServicePrincipalTokenFromManagedIdentity() instead. -func NewServicePrincipalTokenFromMSIWithUserAssignedID(msiEndpoint, resource string, userAssignedID string, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) { - if err := validateStringParam(userAssignedID, "userAssignedID"); err != nil { - return nil, err - } - return newServicePrincipalTokenFromMSI(msiEndpoint, resource, userAssignedID, "", callbacks...) -} - -// NewServicePrincipalTokenFromMSIWithIdentityResourceID creates a ServicePrincipalToken via the MSI VM Extension. -// It will use the azure resource id of user assigned identity when creating the token. -// msiEndpoint - empty string, or pass a non-empty string to override the default value. -// Deprecated: use NewServicePrincipalTokenFromManagedIdentity() instead. -func NewServicePrincipalTokenFromMSIWithIdentityResourceID(msiEndpoint, resource string, identityResourceID string, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) { - if err := validateStringParam(identityResourceID, "identityResourceID"); err != nil { - return nil, err - } - return newServicePrincipalTokenFromMSI(msiEndpoint, resource, "", identityResourceID, callbacks...) -} - -// ManagedIdentityOptions contains optional values for configuring managed identity authentication. -type ManagedIdentityOptions struct { - // ClientID is the user-assigned identity to use during authentication. - // It is mutually exclusive with IdentityResourceID. - ClientID string - - // IdentityResourceID is the resource ID of the user-assigned identity to use during authentication. - // It is mutually exclusive with ClientID. - IdentityResourceID string -} - -// NewServicePrincipalTokenFromManagedIdentity creates a ServicePrincipalToken using a managed identity. -// It supports the following managed identity environments. -// - App Service Environment (API version 2017-09-01 only) -// - Cloud shell -// - IMDS with a system or user assigned identity -func NewServicePrincipalTokenFromManagedIdentity(resource string, options *ManagedIdentityOptions, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) { - if options == nil { - options = &ManagedIdentityOptions{} - } - return newServicePrincipalTokenFromMSI("", resource, options.ClientID, options.IdentityResourceID, callbacks...) -} - -func newServicePrincipalTokenFromMSI(msiEndpoint, resource, userAssignedID, identityResourceID string, callbacks ...TokenRefreshCallback) (*ServicePrincipalToken, error) { - if err := validateStringParam(resource, "resource"); err != nil { - return nil, err - } - if userAssignedID != "" && identityResourceID != "" { - return nil, errors.New("cannot specify userAssignedID and identityResourceID") - } - msiType, endpoint, err := getMSIType() - if err != nil { - logger.Instance.Writef(logger.LogError, "Error determining managed identity environment: %v\n", err) - return nil, err - } - logger.Instance.Writef(logger.LogInfo, "Managed identity environment is %s, endpoint is %s\n", msiType, endpoint) - if msiEndpoint != "" { - endpoint = msiEndpoint - logger.Instance.Writef(logger.LogInfo, "Managed identity custom endpoint is %s\n", endpoint) - } - msiEndpointURL, err := url.Parse(endpoint) - if err != nil { - return nil, err - } - // cloud shell sends its data in the request body - if msiType != msiTypeCloudShell { - v := url.Values{} - v.Set("resource", resource) - clientIDParam := "client_id" - switch msiType { - case msiTypeAppServiceV20170901: - clientIDParam = "clientid" - v.Set("api-version", appServiceAPIVersion2017) - break - case msiTypeIMDS: - v.Set("api-version", msiAPIVersion) - } - if userAssignedID != "" { - v.Set(clientIDParam, userAssignedID) - } else if identityResourceID != "" { - v.Set("mi_res_id", identityResourceID) - } - msiEndpointURL.RawQuery = v.Encode() - } - - spt := &ServicePrincipalToken{ - inner: servicePrincipalToken{ - Token: newToken(), - OauthConfig: OAuthConfig{ - TokenEndpoint: *msiEndpointURL, - }, - Secret: &ServicePrincipalMSISecret{ - msiType: msiType, - clientResourceID: identityResourceID, - }, - Resource: resource, - AutoRefresh: true, - RefreshWithin: defaultRefresh, - ClientID: userAssignedID, - }, - refreshLock: &sync.RWMutex{}, - sender: sender(), - refreshCallbacks: callbacks, - MaxMSIRefreshAttempts: defaultMaxMSIRefreshAttempts, - } - - return spt, nil -} - -// internal type that implements TokenRefreshError -type tokenRefreshError struct { - message string - resp *http.Response -} - -// Error implements the error interface which is part of the TokenRefreshError interface. -func (tre tokenRefreshError) Error() string { - return tre.message -} - -// Response implements the TokenRefreshError interface, it returns the raw HTTP response from the refresh operation. -func (tre tokenRefreshError) Response() *http.Response { - return tre.resp -} - -func newTokenRefreshError(message string, resp *http.Response) TokenRefreshError { - return tokenRefreshError{message: message, resp: resp} -} - -// EnsureFresh will refresh the token if it will expire within the refresh window (as set by -// RefreshWithin) and autoRefresh flag is on. This method is safe for concurrent use. -func (spt *ServicePrincipalToken) EnsureFresh() error { - return spt.EnsureFreshWithContext(context.Background()) -} - -// EnsureFreshWithContext will refresh the token if it will expire within the refresh window (as set by -// RefreshWithin) and autoRefresh flag is on. This method is safe for concurrent use. -func (spt *ServicePrincipalToken) EnsureFreshWithContext(ctx context.Context) error { - // must take the read lock when initially checking the token's expiration - if spt.inner.AutoRefresh && spt.Token().WillExpireIn(spt.inner.RefreshWithin) { - // take the write lock then check again to see if the token was already refreshed - spt.refreshLock.Lock() - defer spt.refreshLock.Unlock() - if spt.inner.Token.WillExpireIn(spt.inner.RefreshWithin) { - return spt.refreshInternal(ctx, spt.inner.Resource) - } - } - return nil -} - -// InvokeRefreshCallbacks calls any TokenRefreshCallbacks that were added to the SPT during initialization -func (spt *ServicePrincipalToken) InvokeRefreshCallbacks(token Token) error { - if spt.refreshCallbacks != nil { - for _, callback := range spt.refreshCallbacks { - err := callback(spt.inner.Token) - if err != nil { - return fmt.Errorf("adal: TokenRefreshCallback handler failed. Error = '%v'", err) - } - } - } - return nil -} - -// Refresh obtains a fresh token for the Service Principal. -// This method is safe for concurrent use. -func (spt *ServicePrincipalToken) Refresh() error { - return spt.RefreshWithContext(context.Background()) -} - -// RefreshWithContext obtains a fresh token for the Service Principal. -// This method is safe for concurrent use. -func (spt *ServicePrincipalToken) RefreshWithContext(ctx context.Context) error { - spt.refreshLock.Lock() - defer spt.refreshLock.Unlock() - return spt.refreshInternal(ctx, spt.inner.Resource) -} - -// RefreshExchange refreshes the token, but for a different resource. -// This method is safe for concurrent use. -func (spt *ServicePrincipalToken) RefreshExchange(resource string) error { - return spt.RefreshExchangeWithContext(context.Background(), resource) -} - -// RefreshExchangeWithContext refreshes the token, but for a different resource. -// This method is safe for concurrent use. -func (spt *ServicePrincipalToken) RefreshExchangeWithContext(ctx context.Context, resource string) error { - spt.refreshLock.Lock() - defer spt.refreshLock.Unlock() - return spt.refreshInternal(ctx, resource) -} - -func (spt *ServicePrincipalToken) getGrantType() string { - switch spt.inner.Secret.(type) { - case *ServicePrincipalUsernamePasswordSecret: - return OAuthGrantTypeUserPass - case *ServicePrincipalAuthorizationCodeSecret: - return OAuthGrantTypeAuthorizationCode - default: - return OAuthGrantTypeClientCredentials - } -} - -func (spt *ServicePrincipalToken) refreshInternal(ctx context.Context, resource string) error { - if spt.customRefreshFunc != nil { - token, err := spt.customRefreshFunc(ctx, resource) - if err != nil { - return err - } - spt.inner.Token = *token - return spt.InvokeRefreshCallbacks(spt.inner.Token) - } - req, err := http.NewRequest(http.MethodPost, spt.inner.OauthConfig.TokenEndpoint.String(), nil) - if err != nil { - return fmt.Errorf("adal: Failed to build the refresh request. Error = '%v'", err) - } - req.Header.Add("User-Agent", UserAgent()) - req = req.WithContext(ctx) - var resp *http.Response - authBodyFilter := func(b []byte) []byte { - if logger.Level() != logger.LogAuth { - return []byte("**REDACTED** authentication body") - } - return b - } - if msiSecret, ok := spt.inner.Secret.(*ServicePrincipalMSISecret); ok { - switch msiSecret.msiType { - case msiTypeAppServiceV20170901: - req.Method = http.MethodGet - req.Header.Set("secret", os.Getenv(msiSecretEnv)) - break - case msiTypeCloudShell: - req.Header.Set("Metadata", "true") - data := url.Values{} - data.Set("resource", spt.inner.Resource) - if spt.inner.ClientID != "" { - data.Set("client_id", spt.inner.ClientID) - } else if msiSecret.clientResourceID != "" { - data.Set("msi_res_id", msiSecret.clientResourceID) - } - req.Body = ioutil.NopCloser(strings.NewReader(data.Encode())) - req.Header.Set("Content-Type", "application/x-www-form-urlencoded") - break - case msiTypeIMDS: - req.Method = http.MethodGet - req.Header.Set("Metadata", "true") - break - } - logger.Instance.WriteRequest(req, logger.Filter{Body: authBodyFilter}) - resp, err = retryForIMDS(spt.sender, req, spt.MaxMSIRefreshAttempts) - } else { - v := url.Values{} - v.Set("client_id", spt.inner.ClientID) - v.Set("resource", resource) - - if spt.inner.Token.RefreshToken != "" { - v.Set("grant_type", OAuthGrantTypeRefreshToken) - v.Set("refresh_token", spt.inner.Token.RefreshToken) - // web apps must specify client_secret when refreshing tokens - // see https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-protocols-oauth-code#refreshing-the-access-tokens - if spt.getGrantType() == OAuthGrantTypeAuthorizationCode { - err := spt.inner.Secret.SetAuthenticationValues(spt, &v) - if err != nil { - return err - } - } - } else { - v.Set("grant_type", spt.getGrantType()) - err := spt.inner.Secret.SetAuthenticationValues(spt, &v) - if err != nil { - return err - } - } - - s := v.Encode() - body := ioutil.NopCloser(strings.NewReader(s)) - req.ContentLength = int64(len(s)) - req.Header.Set(contentType, mimeTypeFormPost) - req.Body = body - logger.Instance.WriteRequest(req, logger.Filter{Body: authBodyFilter}) - resp, err = spt.sender.Do(req) - } - - // don't return a TokenRefreshError here; this will allow retry logic to apply - if err != nil { - return fmt.Errorf("adal: Failed to execute the refresh request. Error = '%v'", err) - } else if resp == nil { - return fmt.Errorf("adal: received nil response and error") - } - - logger.Instance.WriteResponse(resp, logger.Filter{Body: authBodyFilter}) - defer resp.Body.Close() - rb, err := ioutil.ReadAll(resp.Body) - - if resp.StatusCode != http.StatusOK { - if err != nil { - return newTokenRefreshError(fmt.Sprintf("adal: Refresh request failed. Status Code = '%d'. Failed reading response body: %v Endpoint %s", resp.StatusCode, err, req.URL.String()), resp) - } - return newTokenRefreshError(fmt.Sprintf("adal: Refresh request failed. Status Code = '%d'. Response body: %s Endpoint %s", resp.StatusCode, string(rb), req.URL.String()), resp) - } - - // for the following error cases don't return a TokenRefreshError. the operation succeeded - // but some transient failure happened during deserialization. by returning a generic error - // the retry logic will kick in (we don't retry on TokenRefreshError). - - if err != nil { - return fmt.Errorf("adal: Failed to read a new service principal token during refresh. Error = '%v'", err) - } - if len(strings.Trim(string(rb), " ")) == 0 { - return fmt.Errorf("adal: Empty service principal token received during refresh") - } - token := struct { - AccessToken string `json:"access_token"` - RefreshToken string `json:"refresh_token"` - - // AAD returns expires_in as a string, ADFS returns it as an int - ExpiresIn json.Number `json:"expires_in"` - // expires_on can be in three formats, a UTC time stamp, or the number of seconds as a string *or* int. - ExpiresOn interface{} `json:"expires_on"` - NotBefore json.Number `json:"not_before"` - - Resource string `json:"resource"` - Type string `json:"token_type"` - }{} - // return a TokenRefreshError in the follow error cases as the token is in an unexpected format - err = json.Unmarshal(rb, &token) - if err != nil { - return newTokenRefreshError(fmt.Sprintf("adal: Failed to unmarshal the service principal token during refresh. Error = '%v' JSON = '%s'", err, string(rb)), resp) - } - expiresOn := json.Number("") - // ADFS doesn't include the expires_on field - if token.ExpiresOn != nil { - if expiresOn, err = parseExpiresOn(token.ExpiresOn); err != nil { - return newTokenRefreshError(fmt.Sprintf("adal: failed to parse expires_on: %v value '%s'", err, token.ExpiresOn), resp) - } - } - spt.inner.Token.AccessToken = token.AccessToken - spt.inner.Token.RefreshToken = token.RefreshToken - spt.inner.Token.ExpiresIn = token.ExpiresIn - spt.inner.Token.ExpiresOn = expiresOn - spt.inner.Token.NotBefore = token.NotBefore - spt.inner.Token.Resource = token.Resource - spt.inner.Token.Type = token.Type - - return spt.InvokeRefreshCallbacks(spt.inner.Token) -} - -// converts expires_on to the number of seconds -func parseExpiresOn(s interface{}) (json.Number, error) { - // the JSON unmarshaler treats JSON numbers unmarshaled into an interface{} as float64 - asFloat64, ok := s.(float64) - if ok { - // this is the number of seconds as int case - return json.Number(strconv.FormatInt(int64(asFloat64), 10)), nil - } - asStr, ok := s.(string) - if !ok { - return "", fmt.Errorf("unexpected expires_on type %T", s) - } - // convert the expiration date to the number of seconds from the unix epoch - timeToDuration := func(t time.Time) json.Number { - return json.Number(strconv.FormatInt(t.UTC().Unix(), 10)) - } - if _, err := json.Number(asStr).Int64(); err == nil { - // this is the number of seconds case, no conversion required - return json.Number(asStr), nil - } else if eo, err := time.Parse(expiresOnDateFormatPM, asStr); err == nil { - return timeToDuration(eo), nil - } else if eo, err := time.Parse(expiresOnDateFormat, asStr); err == nil { - return timeToDuration(eo), nil - } else { - // unknown format - return json.Number(""), err - } -} - -// retry logic specific to retrieving a token from the IMDS endpoint -func retryForIMDS(sender Sender, req *http.Request, maxAttempts int) (resp *http.Response, err error) { - // copied from client.go due to circular dependency - retries := []int{ - http.StatusRequestTimeout, // 408 - http.StatusTooManyRequests, // 429 - http.StatusInternalServerError, // 500 - http.StatusBadGateway, // 502 - http.StatusServiceUnavailable, // 503 - http.StatusGatewayTimeout, // 504 - } - // extra retry status codes specific to IMDS - retries = append(retries, - http.StatusNotFound, - http.StatusGone, - // all remaining 5xx - http.StatusNotImplemented, - http.StatusHTTPVersionNotSupported, - http.StatusVariantAlsoNegotiates, - http.StatusInsufficientStorage, - http.StatusLoopDetected, - http.StatusNotExtended, - http.StatusNetworkAuthenticationRequired) - - // see https://docs.microsoft.com/en-us/azure/active-directory/managed-service-identity/how-to-use-vm-token#retry-guidance - - const maxDelay time.Duration = 60 * time.Second - - attempt := 0 - delay := time.Duration(0) - - // maxAttempts is user-specified, ensure that its value is greater than zero else no request will be made - if maxAttempts < 1 { - maxAttempts = defaultMaxMSIRefreshAttempts - } - - for attempt < maxAttempts { - if resp != nil && resp.Body != nil { - io.Copy(ioutil.Discard, resp.Body) - resp.Body.Close() - } - resp, err = sender.Do(req) - // we want to retry if err is not nil or the status code is in the list of retry codes - if err == nil && !responseHasStatusCode(resp, retries...) { - return - } - - // perform exponential backoff with a cap. - // must increment attempt before calculating delay. - attempt++ - // the base value of 2 is the "delta backoff" as specified in the guidance doc - delay += (time.Duration(math.Pow(2, float64(attempt))) * time.Second) - if delay > maxDelay { - delay = maxDelay - } - - select { - case <-time.After(delay): - // intentionally left blank - case <-req.Context().Done(): - err = req.Context().Err() - return - } - } - return -} - -func responseHasStatusCode(resp *http.Response, codes ...int) bool { - if resp != nil { - for _, i := range codes { - if i == resp.StatusCode { - return true - } - } - } - return false -} - -// SetAutoRefresh enables or disables automatic refreshing of stale tokens. -func (spt *ServicePrincipalToken) SetAutoRefresh(autoRefresh bool) { - spt.inner.AutoRefresh = autoRefresh -} - -// SetRefreshWithin sets the interval within which if the token will expire, EnsureFresh will -// refresh the token. -func (spt *ServicePrincipalToken) SetRefreshWithin(d time.Duration) { - spt.inner.RefreshWithin = d - return -} - -// SetSender sets the http.Client used when obtaining the Service Principal token. An -// undecorated http.Client is used by default. -func (spt *ServicePrincipalToken) SetSender(s Sender) { spt.sender = s } - -// OAuthToken implements the OAuthTokenProvider interface. It returns the current access token. -func (spt *ServicePrincipalToken) OAuthToken() string { - spt.refreshLock.RLock() - defer spt.refreshLock.RUnlock() - return spt.inner.Token.OAuthToken() -} - -// Token returns a copy of the current token. -func (spt *ServicePrincipalToken) Token() Token { - spt.refreshLock.RLock() - defer spt.refreshLock.RUnlock() - return spt.inner.Token -} - -// MultiTenantServicePrincipalToken contains tokens for multi-tenant authorization. -type MultiTenantServicePrincipalToken struct { - PrimaryToken *ServicePrincipalToken - AuxiliaryTokens []*ServicePrincipalToken -} - -// PrimaryOAuthToken returns the primary authorization token. -func (mt *MultiTenantServicePrincipalToken) PrimaryOAuthToken() string { - return mt.PrimaryToken.OAuthToken() -} - -// AuxiliaryOAuthTokens returns one to three auxiliary authorization tokens. -func (mt *MultiTenantServicePrincipalToken) AuxiliaryOAuthTokens() []string { - tokens := make([]string, len(mt.AuxiliaryTokens)) - for i := range mt.AuxiliaryTokens { - tokens[i] = mt.AuxiliaryTokens[i].OAuthToken() - } - return tokens -} - -// NewMultiTenantServicePrincipalToken creates a new MultiTenantServicePrincipalToken with the specified credentials and resource. -func NewMultiTenantServicePrincipalToken(multiTenantCfg MultiTenantOAuthConfig, clientID string, secret string, resource string) (*MultiTenantServicePrincipalToken, error) { - if err := validateStringParam(clientID, "clientID"); err != nil { - return nil, err - } - if err := validateStringParam(secret, "secret"); err != nil { - return nil, err - } - if err := validateStringParam(resource, "resource"); err != nil { - return nil, err - } - auxTenants := multiTenantCfg.AuxiliaryTenants() - m := MultiTenantServicePrincipalToken{ - AuxiliaryTokens: make([]*ServicePrincipalToken, len(auxTenants)), - } - primary, err := NewServicePrincipalToken(*multiTenantCfg.PrimaryTenant(), clientID, secret, resource) - if err != nil { - return nil, fmt.Errorf("failed to create SPT for primary tenant: %v", err) - } - m.PrimaryToken = primary - for i := range auxTenants { - aux, err := NewServicePrincipalToken(*auxTenants[i], clientID, secret, resource) - if err != nil { - return nil, fmt.Errorf("failed to create SPT for auxiliary tenant: %v", err) - } - m.AuxiliaryTokens[i] = aux - } - return &m, nil -} - -// NewMultiTenantServicePrincipalTokenFromCertificate creates a new MultiTenantServicePrincipalToken with the specified certificate credentials and resource. -func NewMultiTenantServicePrincipalTokenFromCertificate(multiTenantCfg MultiTenantOAuthConfig, clientID string, certificate *x509.Certificate, privateKey *rsa.PrivateKey, resource string) (*MultiTenantServicePrincipalToken, error) { - if err := validateStringParam(clientID, "clientID"); err != nil { - return nil, err - } - if err := validateStringParam(resource, "resource"); err != nil { - return nil, err - } - if certificate == nil { - return nil, fmt.Errorf("parameter 'certificate' cannot be nil") - } - if privateKey == nil { - return nil, fmt.Errorf("parameter 'privateKey' cannot be nil") - } - auxTenants := multiTenantCfg.AuxiliaryTenants() - m := MultiTenantServicePrincipalToken{ - AuxiliaryTokens: make([]*ServicePrincipalToken, len(auxTenants)), - } - primary, err := NewServicePrincipalTokenWithSecret( - *multiTenantCfg.PrimaryTenant(), - clientID, - resource, - &ServicePrincipalCertificateSecret{ - PrivateKey: privateKey, - Certificate: certificate, - }, - ) - if err != nil { - return nil, fmt.Errorf("failed to create SPT for primary tenant: %v", err) - } - m.PrimaryToken = primary - for i := range auxTenants { - aux, err := NewServicePrincipalTokenWithSecret( - *auxTenants[i], - clientID, - resource, - &ServicePrincipalCertificateSecret{ - PrivateKey: privateKey, - Certificate: certificate, - }, - ) - if err != nil { - return nil, fmt.Errorf("failed to create SPT for auxiliary tenant: %v", err) - } - m.AuxiliaryTokens[i] = aux - } - return &m, nil -} - -// MSIAvailable returns true if the MSI endpoint is available for authentication. -func MSIAvailable(ctx context.Context, s Sender) bool { - msiType, _, err := getMSIType() - - if err != nil { - return false - } - - if msiType != msiTypeIMDS { - return true - } - - if s == nil { - s = sender() - } - - resp, err := getMSIEndpoint(ctx, s) - - if err == nil { - resp.Body.Close() - } - - return err == nil -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/adal/token_1.13.go b/vendor/github.com/Azure/go-autorest/autorest/adal/token_1.13.go deleted file mode 100644 index 89190a4213..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/adal/token_1.13.go +++ /dev/null @@ -1,76 +0,0 @@ -//go:build go1.13 -// +build go1.13 - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package adal - -import ( - "context" - "fmt" - "net/http" - "time" -) - -func getMSIEndpoint(ctx context.Context, sender Sender) (*http.Response, error) { - tempCtx, cancel := context.WithTimeout(ctx, 2*time.Second) - defer cancel() - // http.NewRequestWithContext() was added in Go 1.13 - req, _ := http.NewRequestWithContext(tempCtx, http.MethodGet, msiEndpoint, nil) - q := req.URL.Query() - q.Add("api-version", msiAPIVersion) - req.URL.RawQuery = q.Encode() - return sender.Do(req) -} - -// EnsureFreshWithContext will refresh the token if it will expire within the refresh window (as set by -// RefreshWithin) and autoRefresh flag is on. This method is safe for concurrent use. -func (mt *MultiTenantServicePrincipalToken) EnsureFreshWithContext(ctx context.Context) error { - if err := mt.PrimaryToken.EnsureFreshWithContext(ctx); err != nil { - return fmt.Errorf("failed to refresh primary token: %w", err) - } - for _, aux := range mt.AuxiliaryTokens { - if err := aux.EnsureFreshWithContext(ctx); err != nil { - return fmt.Errorf("failed to refresh auxiliary token: %w", err) - } - } - return nil -} - -// RefreshWithContext obtains a fresh token for the Service Principal. -func (mt *MultiTenantServicePrincipalToken) RefreshWithContext(ctx context.Context) error { - if err := mt.PrimaryToken.RefreshWithContext(ctx); err != nil { - return fmt.Errorf("failed to refresh primary token: %w", err) - } - for _, aux := range mt.AuxiliaryTokens { - if err := aux.RefreshWithContext(ctx); err != nil { - return fmt.Errorf("failed to refresh auxiliary token: %w", err) - } - } - return nil -} - -// RefreshExchangeWithContext refreshes the token, but for a different resource. -func (mt *MultiTenantServicePrincipalToken) RefreshExchangeWithContext(ctx context.Context, resource string) error { - if err := mt.PrimaryToken.RefreshExchangeWithContext(ctx, resource); err != nil { - return fmt.Errorf("failed to refresh primary token: %w", err) - } - for _, aux := range mt.AuxiliaryTokens { - if err := aux.RefreshExchangeWithContext(ctx, resource); err != nil { - return fmt.Errorf("failed to refresh auxiliary token: %w", err) - } - } - return nil -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/adal/token_legacy.go b/vendor/github.com/Azure/go-autorest/autorest/adal/token_legacy.go deleted file mode 100644 index 27ec4efad7..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/adal/token_legacy.go +++ /dev/null @@ -1,75 +0,0 @@ -//go:build !go1.13 -// +build !go1.13 - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package adal - -import ( - "context" - "net/http" - "time" -) - -func getMSIEndpoint(ctx context.Context, sender Sender) (*http.Response, error) { - tempCtx, cancel := context.WithTimeout(ctx, 2*time.Second) - defer cancel() - req, _ := http.NewRequest(http.MethodGet, msiEndpoint, nil) - req = req.WithContext(tempCtx) - q := req.URL.Query() - q.Add("api-version", msiAPIVersion) - req.URL.RawQuery = q.Encode() - return sender.Do(req) -} - -// EnsureFreshWithContext will refresh the token if it will expire within the refresh window (as set by -// RefreshWithin) and autoRefresh flag is on. This method is safe for concurrent use. -func (mt *MultiTenantServicePrincipalToken) EnsureFreshWithContext(ctx context.Context) error { - if err := mt.PrimaryToken.EnsureFreshWithContext(ctx); err != nil { - return err - } - for _, aux := range mt.AuxiliaryTokens { - if err := aux.EnsureFreshWithContext(ctx); err != nil { - return err - } - } - return nil -} - -// RefreshWithContext obtains a fresh token for the Service Principal. -func (mt *MultiTenantServicePrincipalToken) RefreshWithContext(ctx context.Context) error { - if err := mt.PrimaryToken.RefreshWithContext(ctx); err != nil { - return err - } - for _, aux := range mt.AuxiliaryTokens { - if err := aux.RefreshWithContext(ctx); err != nil { - return err - } - } - return nil -} - -// RefreshExchangeWithContext refreshes the token, but for a different resource. -func (mt *MultiTenantServicePrincipalToken) RefreshExchangeWithContext(ctx context.Context, resource string) error { - if err := mt.PrimaryToken.RefreshExchangeWithContext(ctx, resource); err != nil { - return err - } - for _, aux := range mt.AuxiliaryTokens { - if err := aux.RefreshExchangeWithContext(ctx, resource); err != nil { - return err - } - } - return nil -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/adal/version.go b/vendor/github.com/Azure/go-autorest/autorest/adal/version.go deleted file mode 100644 index c867b34843..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/adal/version.go +++ /dev/null @@ -1,45 +0,0 @@ -package adal - -import ( - "fmt" - "runtime" -) - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -const number = "v1.0.0" - -var ( - ua = fmt.Sprintf("Go/%s (%s-%s) go-autorest/adal/%s", - runtime.Version(), - runtime.GOARCH, - runtime.GOOS, - number, - ) -) - -// UserAgent returns a string containing the Go version, system architecture and OS, and the adal version. -func UserAgent() string { - return ua -} - -// AddToUserAgent adds an extension to the current user agent -func AddToUserAgent(extension string) error { - if extension != "" { - ua = fmt.Sprintf("%s %s", ua, extension) - return nil - } - return fmt.Errorf("Extension was empty, User Agent remained as '%s'", ua) -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/authorization.go b/vendor/github.com/Azure/go-autorest/autorest/authorization.go deleted file mode 100644 index 1226c41115..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/authorization.go +++ /dev/null @@ -1,353 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "crypto/tls" - "encoding/base64" - "fmt" - "net/http" - "net/url" - "strings" - - "github.com/Azure/go-autorest/autorest/adal" -) - -const ( - bearerChallengeHeader = "Www-Authenticate" - bearer = "Bearer" - tenantID = "tenantID" - apiKeyAuthorizerHeader = "Ocp-Apim-Subscription-Key" - bingAPISdkHeader = "X-BingApis-SDK-Client" - golangBingAPISdkHeaderValue = "Go-SDK" - authorization = "Authorization" - basic = "Basic" -) - -// Authorizer is the interface that provides a PrepareDecorator used to supply request -// authorization. Most often, the Authorizer decorator runs last so it has access to the full -// state of the formed HTTP request. -type Authorizer interface { - WithAuthorization() PrepareDecorator -} - -// NullAuthorizer implements a default, "do nothing" Authorizer. -type NullAuthorizer struct{} - -// WithAuthorization returns a PrepareDecorator that does nothing. -func (na NullAuthorizer) WithAuthorization() PrepareDecorator { - return WithNothing() -} - -// APIKeyAuthorizer implements API Key authorization. -type APIKeyAuthorizer struct { - headers map[string]interface{} - queryParameters map[string]interface{} -} - -// NewAPIKeyAuthorizerWithHeaders creates an ApiKeyAuthorizer with headers. -func NewAPIKeyAuthorizerWithHeaders(headers map[string]interface{}) *APIKeyAuthorizer { - return NewAPIKeyAuthorizer(headers, nil) -} - -// NewAPIKeyAuthorizerWithQueryParameters creates an ApiKeyAuthorizer with query parameters. -func NewAPIKeyAuthorizerWithQueryParameters(queryParameters map[string]interface{}) *APIKeyAuthorizer { - return NewAPIKeyAuthorizer(nil, queryParameters) -} - -// NewAPIKeyAuthorizer creates an ApiKeyAuthorizer with headers. -func NewAPIKeyAuthorizer(headers map[string]interface{}, queryParameters map[string]interface{}) *APIKeyAuthorizer { - return &APIKeyAuthorizer{headers: headers, queryParameters: queryParameters} -} - -// WithAuthorization returns a PrepareDecorator that adds an HTTP headers and Query Parameters. -func (aka *APIKeyAuthorizer) WithAuthorization() PrepareDecorator { - return func(p Preparer) Preparer { - return DecoratePreparer(p, WithHeaders(aka.headers), WithQueryParameters(aka.queryParameters)) - } -} - -// CognitiveServicesAuthorizer implements authorization for Cognitive Services. -type CognitiveServicesAuthorizer struct { - subscriptionKey string -} - -// NewCognitiveServicesAuthorizer is -func NewCognitiveServicesAuthorizer(subscriptionKey string) *CognitiveServicesAuthorizer { - return &CognitiveServicesAuthorizer{subscriptionKey: subscriptionKey} -} - -// WithAuthorization is -func (csa *CognitiveServicesAuthorizer) WithAuthorization() PrepareDecorator { - headers := make(map[string]interface{}) - headers[apiKeyAuthorizerHeader] = csa.subscriptionKey - headers[bingAPISdkHeader] = golangBingAPISdkHeaderValue - - return NewAPIKeyAuthorizerWithHeaders(headers).WithAuthorization() -} - -// BearerAuthorizer implements the bearer authorization -type BearerAuthorizer struct { - tokenProvider adal.OAuthTokenProvider -} - -// NewBearerAuthorizer crates a BearerAuthorizer using the given token provider -func NewBearerAuthorizer(tp adal.OAuthTokenProvider) *BearerAuthorizer { - return &BearerAuthorizer{tokenProvider: tp} -} - -// WithAuthorization returns a PrepareDecorator that adds an HTTP Authorization header whose -// value is "Bearer " followed by the token. -// -// By default, the token will be automatically refreshed through the Refresher interface. -func (ba *BearerAuthorizer) WithAuthorization() PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err == nil { - // the ordering is important here, prefer RefresherWithContext if available - if refresher, ok := ba.tokenProvider.(adal.RefresherWithContext); ok { - err = refresher.EnsureFreshWithContext(r.Context()) - } else if refresher, ok := ba.tokenProvider.(adal.Refresher); ok { - err = refresher.EnsureFresh() - } - if err != nil { - var resp *http.Response - if tokError, ok := err.(adal.TokenRefreshError); ok { - resp = tokError.Response() - } - return r, NewErrorWithError(err, "azure.BearerAuthorizer", "WithAuthorization", resp, - "Failed to refresh the Token for request to %s", r.URL) - } - return Prepare(r, WithHeader(headerAuthorization, fmt.Sprintf("Bearer %s", ba.tokenProvider.OAuthToken()))) - } - return r, err - }) - } -} - -// TokenProvider returns OAuthTokenProvider so that it can be used for authorization outside the REST. -func (ba *BearerAuthorizer) TokenProvider() adal.OAuthTokenProvider { - return ba.tokenProvider -} - -// BearerAuthorizerCallbackFunc is the authentication callback signature. -type BearerAuthorizerCallbackFunc func(tenantID, resource string) (*BearerAuthorizer, error) - -// BearerAuthorizerCallback implements bearer authorization via a callback. -type BearerAuthorizerCallback struct { - sender Sender - callback BearerAuthorizerCallbackFunc -} - -// NewBearerAuthorizerCallback creates a bearer authorization callback. The callback -// is invoked when the HTTP request is submitted. -func NewBearerAuthorizerCallback(s Sender, callback BearerAuthorizerCallbackFunc) *BearerAuthorizerCallback { - if s == nil { - s = sender(tls.RenegotiateNever) - } - return &BearerAuthorizerCallback{sender: s, callback: callback} -} - -// WithAuthorization returns a PrepareDecorator that adds an HTTP Authorization header whose value -// is "Bearer " followed by the token. The BearerAuthorizer is obtained via a user-supplied callback. -// -// By default, the token will be automatically refreshed through the Refresher interface. -func (bacb *BearerAuthorizerCallback) WithAuthorization() PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err == nil { - // make a copy of the request and remove the body as it's not - // required and avoids us having to create a copy of it. - rCopy := *r - removeRequestBody(&rCopy) - - resp, err := bacb.sender.Do(&rCopy) - if err != nil { - return r, err - } - DrainResponseBody(resp) - if resp.StatusCode == 401 && hasBearerChallenge(resp.Header) { - bc, err := newBearerChallenge(resp.Header) - if err != nil { - return r, err - } - if bacb.callback != nil { - ba, err := bacb.callback(bc.values[tenantID], bc.values["resource"]) - if err != nil { - return r, err - } - return Prepare(r, ba.WithAuthorization()) - } - } - } - return r, err - }) - } -} - -// returns true if the HTTP response contains a bearer challenge -func hasBearerChallenge(header http.Header) bool { - authHeader := header.Get(bearerChallengeHeader) - if len(authHeader) == 0 || strings.Index(authHeader, bearer) < 0 { - return false - } - return true -} - -type bearerChallenge struct { - values map[string]string -} - -func newBearerChallenge(header http.Header) (bc bearerChallenge, err error) { - challenge := strings.TrimSpace(header.Get(bearerChallengeHeader)) - trimmedChallenge := challenge[len(bearer)+1:] - - // challenge is a set of key=value pairs that are comma delimited - pairs := strings.Split(trimmedChallenge, ",") - if len(pairs) < 1 { - err = fmt.Errorf("challenge '%s' contains no pairs", challenge) - return bc, err - } - - bc.values = make(map[string]string) - for i := range pairs { - trimmedPair := strings.TrimSpace(pairs[i]) - pair := strings.Split(trimmedPair, "=") - if len(pair) == 2 { - // remove the enclosing quotes - key := strings.Trim(pair[0], "\"") - value := strings.Trim(pair[1], "\"") - - switch key { - case "authorization", "authorization_uri": - // strip the tenant ID from the authorization URL - asURL, err := url.Parse(value) - if err != nil { - return bc, err - } - bc.values[tenantID] = asURL.Path[1:] - default: - bc.values[key] = value - } - } - } - - return bc, err -} - -// EventGridKeyAuthorizer implements authorization for event grid using key authentication. -type EventGridKeyAuthorizer struct { - topicKey string -} - -// NewEventGridKeyAuthorizer creates a new EventGridKeyAuthorizer -// with the specified topic key. -func NewEventGridKeyAuthorizer(topicKey string) EventGridKeyAuthorizer { - return EventGridKeyAuthorizer{topicKey: topicKey} -} - -// WithAuthorization returns a PrepareDecorator that adds the aeg-sas-key authentication header. -func (egta EventGridKeyAuthorizer) WithAuthorization() PrepareDecorator { - headers := map[string]interface{}{ - "aeg-sas-key": egta.topicKey, - } - return NewAPIKeyAuthorizerWithHeaders(headers).WithAuthorization() -} - -// BasicAuthorizer implements basic HTTP authorization by adding the Authorization HTTP header -// with the value "Basic " where is a base64-encoded username:password tuple. -type BasicAuthorizer struct { - userName string - password string -} - -// NewBasicAuthorizer creates a new BasicAuthorizer with the specified username and password. -func NewBasicAuthorizer(userName, password string) *BasicAuthorizer { - return &BasicAuthorizer{ - userName: userName, - password: password, - } -} - -// WithAuthorization returns a PrepareDecorator that adds an HTTP Authorization header whose -// value is "Basic " followed by the base64-encoded username:password tuple. -func (ba *BasicAuthorizer) WithAuthorization() PrepareDecorator { - headers := make(map[string]interface{}) - headers[authorization] = basic + " " + base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", ba.userName, ba.password))) - - return NewAPIKeyAuthorizerWithHeaders(headers).WithAuthorization() -} - -// MultiTenantServicePrincipalTokenAuthorizer provides authentication across tenants. -type MultiTenantServicePrincipalTokenAuthorizer interface { - WithAuthorization() PrepareDecorator -} - -// NewMultiTenantServicePrincipalTokenAuthorizer crates a BearerAuthorizer using the given token provider -func NewMultiTenantServicePrincipalTokenAuthorizer(tp adal.MultitenantOAuthTokenProvider) MultiTenantServicePrincipalTokenAuthorizer { - return NewMultiTenantBearerAuthorizer(tp) -} - -// MultiTenantBearerAuthorizer implements bearer authorization across multiple tenants. -type MultiTenantBearerAuthorizer struct { - tp adal.MultitenantOAuthTokenProvider -} - -// NewMultiTenantBearerAuthorizer creates a MultiTenantBearerAuthorizer using the given token provider. -func NewMultiTenantBearerAuthorizer(tp adal.MultitenantOAuthTokenProvider) *MultiTenantBearerAuthorizer { - return &MultiTenantBearerAuthorizer{tp: tp} -} - -// WithAuthorization returns a PrepareDecorator that adds an HTTP Authorization header using the -// primary token along with the auxiliary authorization header using the auxiliary tokens. -// -// By default, the token will be automatically refreshed through the Refresher interface. -func (mt *MultiTenantBearerAuthorizer) WithAuthorization() PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err != nil { - return r, err - } - if refresher, ok := mt.tp.(adal.RefresherWithContext); ok { - err = refresher.EnsureFreshWithContext(r.Context()) - if err != nil { - var resp *http.Response - if tokError, ok := err.(adal.TokenRefreshError); ok { - resp = tokError.Response() - } - return r, NewErrorWithError(err, "azure.multiTenantSPTAuthorizer", "WithAuthorization", resp, - "Failed to refresh one or more Tokens for request to %s", r.URL) - } - } - r, err = Prepare(r, WithHeader(headerAuthorization, fmt.Sprintf("Bearer %s", mt.tp.PrimaryOAuthToken()))) - if err != nil { - return r, err - } - auxTokens := mt.tp.AuxiliaryOAuthTokens() - for i := range auxTokens { - auxTokens[i] = fmt.Sprintf("Bearer %s", auxTokens[i]) - } - return Prepare(r, WithHeader(headerAuxAuthorization, strings.Join(auxTokens, ", "))) - }) - } -} - -// TokenProvider returns the underlying MultitenantOAuthTokenProvider for this authorizer. -func (mt *MultiTenantBearerAuthorizer) TokenProvider() adal.MultitenantOAuthTokenProvider { - return mt.tp -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/authorization_sas.go b/vendor/github.com/Azure/go-autorest/autorest/authorization_sas.go deleted file mode 100644 index 66501493bd..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/authorization_sas.go +++ /dev/null @@ -1,66 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "fmt" - "net/http" - "strings" -) - -// SASTokenAuthorizer implements an authorization for SAS Token Authentication -// this can be used for interaction with Blob Storage Endpoints -type SASTokenAuthorizer struct { - sasToken string -} - -// NewSASTokenAuthorizer creates a SASTokenAuthorizer using the given credentials -func NewSASTokenAuthorizer(sasToken string) (*SASTokenAuthorizer, error) { - if strings.TrimSpace(sasToken) == "" { - return nil, fmt.Errorf("sasToken cannot be empty") - } - - token := sasToken - if strings.HasPrefix(sasToken, "?") { - token = strings.TrimPrefix(sasToken, "?") - } - - return &SASTokenAuthorizer{ - sasToken: token, - }, nil -} - -// WithAuthorization returns a PrepareDecorator that adds a shared access signature token to the -// URI's query parameters. This can be used for the Blob, Queue, and File Services. -// -// See https://docs.microsoft.com/en-us/rest/api/storageservices/delegate-access-with-shared-access-signature -func (sas *SASTokenAuthorizer) WithAuthorization() PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err != nil { - return r, err - } - - if r.URL.RawQuery == "" { - r.URL.RawQuery = sas.sasToken - } else if !strings.Contains(r.URL.RawQuery, sas.sasToken) { - r.URL.RawQuery = fmt.Sprintf("%s&%s", r.URL.RawQuery, sas.sasToken) - } - - return Prepare(r) - }) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/authorization_storage.go b/vendor/github.com/Azure/go-autorest/autorest/authorization_storage.go deleted file mode 100644 index 2af5030a1c..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/authorization_storage.go +++ /dev/null @@ -1,307 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "bytes" - "crypto/hmac" - "crypto/sha256" - "encoding/base64" - "fmt" - "net/http" - "net/url" - "sort" - "strings" - "time" -) - -// SharedKeyType defines the enumeration for the various shared key types. -// See https://docs.microsoft.com/en-us/rest/api/storageservices/authorize-with-shared-key for details on the shared key types. -type SharedKeyType string - -const ( - // SharedKey is used to authorize against blobs, files and queues services. - SharedKey SharedKeyType = "sharedKey" - - // SharedKeyForTable is used to authorize against the table service. - SharedKeyForTable SharedKeyType = "sharedKeyTable" - - // SharedKeyLite is used to authorize against blobs, files and queues services. It's provided for - // backwards compatibility with API versions before 2009-09-19. Prefer SharedKey instead. - SharedKeyLite SharedKeyType = "sharedKeyLite" - - // SharedKeyLiteForTable is used to authorize against the table service. It's provided for - // backwards compatibility with older table API versions. Prefer SharedKeyForTable instead. - SharedKeyLiteForTable SharedKeyType = "sharedKeyLiteTable" -) - -const ( - headerAccept = "Accept" - headerAcceptCharset = "Accept-Charset" - headerContentEncoding = "Content-Encoding" - headerContentLength = "Content-Length" - headerContentMD5 = "Content-MD5" - headerContentLanguage = "Content-Language" - headerIfModifiedSince = "If-Modified-Since" - headerIfMatch = "If-Match" - headerIfNoneMatch = "If-None-Match" - headerIfUnmodifiedSince = "If-Unmodified-Since" - headerDate = "Date" - headerXMSDate = "X-Ms-Date" - headerXMSVersion = "x-ms-version" - headerRange = "Range" -) - -const storageEmulatorAccountName = "devstoreaccount1" - -// SharedKeyAuthorizer implements an authorization for Shared Key -// this can be used for interaction with Blob, File and Queue Storage Endpoints -type SharedKeyAuthorizer struct { - accountName string - accountKey []byte - keyType SharedKeyType -} - -// NewSharedKeyAuthorizer creates a SharedKeyAuthorizer using the provided credentials and shared key type. -func NewSharedKeyAuthorizer(accountName, accountKey string, keyType SharedKeyType) (*SharedKeyAuthorizer, error) { - key, err := base64.StdEncoding.DecodeString(accountKey) - if err != nil { - return nil, fmt.Errorf("malformed storage account key: %v", err) - } - return &SharedKeyAuthorizer{ - accountName: accountName, - accountKey: key, - keyType: keyType, - }, nil -} - -// WithAuthorization returns a PrepareDecorator that adds an HTTP Authorization header whose -// value is " " followed by the computed key. -// This can be used for the Blob, Queue, and File Services -// -// from: https://docs.microsoft.com/en-us/rest/api/storageservices/authorize-with-shared-key -// You may use Shared Key authorization to authorize a request made against the -// 2009-09-19 version and later of the Blob and Queue services, -// and version 2014-02-14 and later of the File services. -func (sk *SharedKeyAuthorizer) WithAuthorization() PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err != nil { - return r, err - } - - sk, err := buildSharedKey(sk.accountName, sk.accountKey, r, sk.keyType) - if err != nil { - return r, err - } - return Prepare(r, WithHeader(headerAuthorization, sk)) - }) - } -} - -func buildSharedKey(accName string, accKey []byte, req *http.Request, keyType SharedKeyType) (string, error) { - canRes, err := buildCanonicalizedResource(accName, req.URL.String(), keyType) - if err != nil { - return "", err - } - - if req.Header == nil { - req.Header = http.Header{} - } - - // ensure date is set - if req.Header.Get(headerDate) == "" && req.Header.Get(headerXMSDate) == "" { - date := time.Now().UTC().Format(http.TimeFormat) - req.Header.Set(headerXMSDate, date) - } - canString, err := buildCanonicalizedString(req.Method, req.Header, canRes, keyType) - if err != nil { - return "", err - } - return createAuthorizationHeader(accName, accKey, canString, keyType), nil -} - -func buildCanonicalizedResource(accountName, uri string, keyType SharedKeyType) (string, error) { - errMsg := "buildCanonicalizedResource error: %s" - u, err := url.Parse(uri) - if err != nil { - return "", fmt.Errorf(errMsg, err.Error()) - } - - cr := bytes.NewBufferString("") - if accountName != storageEmulatorAccountName { - cr.WriteString("/") - cr.WriteString(getCanonicalizedAccountName(accountName)) - } - - if len(u.Path) > 0 { - // Any portion of the CanonicalizedResource string that is derived from - // the resource's URI should be encoded exactly as it is in the URI. - // -- https://msdn.microsoft.com/en-gb/library/azure/dd179428.aspx - cr.WriteString(u.EscapedPath()) - } else { - // a slash is required to indicate the root path - cr.WriteString("/") - } - - params, err := url.ParseQuery(u.RawQuery) - if err != nil { - return "", fmt.Errorf(errMsg, err.Error()) - } - - // See https://github.com/Azure/azure-storage-net/blob/master/Lib/Common/Core/Util/AuthenticationUtility.cs#L277 - if keyType == SharedKey { - if len(params) > 0 { - cr.WriteString("\n") - - keys := []string{} - for key := range params { - keys = append(keys, key) - } - sort.Strings(keys) - - completeParams := []string{} - for _, key := range keys { - if len(params[key]) > 1 { - sort.Strings(params[key]) - } - - completeParams = append(completeParams, fmt.Sprintf("%s:%s", key, strings.Join(params[key], ","))) - } - cr.WriteString(strings.Join(completeParams, "\n")) - } - } else { - // search for "comp" parameter, if exists then add it to canonicalizedresource - if v, ok := params["comp"]; ok { - cr.WriteString("?comp=" + v[0]) - } - } - - return string(cr.Bytes()), nil -} - -func getCanonicalizedAccountName(accountName string) string { - // since we may be trying to access a secondary storage account, we need to - // remove the -secondary part of the storage name - return strings.TrimSuffix(accountName, "-secondary") -} - -func buildCanonicalizedString(verb string, headers http.Header, canonicalizedResource string, keyType SharedKeyType) (string, error) { - contentLength := headers.Get(headerContentLength) - if contentLength == "0" { - contentLength = "" - } - date := headers.Get(headerDate) - if v := headers.Get(headerXMSDate); v != "" { - if keyType == SharedKey || keyType == SharedKeyLite { - date = "" - } else { - date = v - } - } - var canString string - switch keyType { - case SharedKey: - canString = strings.Join([]string{ - verb, - headers.Get(headerContentEncoding), - headers.Get(headerContentLanguage), - contentLength, - headers.Get(headerContentMD5), - headers.Get(headerContentType), - date, - headers.Get(headerIfModifiedSince), - headers.Get(headerIfMatch), - headers.Get(headerIfNoneMatch), - headers.Get(headerIfUnmodifiedSince), - headers.Get(headerRange), - buildCanonicalizedHeader(headers), - canonicalizedResource, - }, "\n") - case SharedKeyForTable: - canString = strings.Join([]string{ - verb, - headers.Get(headerContentMD5), - headers.Get(headerContentType), - date, - canonicalizedResource, - }, "\n") - case SharedKeyLite: - canString = strings.Join([]string{ - verb, - headers.Get(headerContentMD5), - headers.Get(headerContentType), - date, - buildCanonicalizedHeader(headers), - canonicalizedResource, - }, "\n") - case SharedKeyLiteForTable: - canString = strings.Join([]string{ - date, - canonicalizedResource, - }, "\n") - default: - return "", fmt.Errorf("key type '%s' is not supported", keyType) - } - return canString, nil -} - -func buildCanonicalizedHeader(headers http.Header) string { - cm := make(map[string]string) - - for k := range headers { - headerName := strings.TrimSpace(strings.ToLower(k)) - if strings.HasPrefix(headerName, "x-ms-") { - cm[headerName] = headers.Get(k) - } - } - - if len(cm) == 0 { - return "" - } - - keys := []string{} - for key := range cm { - keys = append(keys, key) - } - - sort.Strings(keys) - - ch := bytes.NewBufferString("") - - for _, key := range keys { - ch.WriteString(key) - ch.WriteRune(':') - ch.WriteString(cm[key]) - ch.WriteRune('\n') - } - - return strings.TrimSuffix(string(ch.Bytes()), "\n") -} - -func createAuthorizationHeader(accountName string, accountKey []byte, canonicalizedString string, keyType SharedKeyType) string { - h := hmac.New(sha256.New, accountKey) - h.Write([]byte(canonicalizedString)) - signature := base64.StdEncoding.EncodeToString(h.Sum(nil)) - var key string - switch keyType { - case SharedKey, SharedKeyForTable: - key = "SharedKey" - case SharedKeyLite, SharedKeyLiteForTable: - key = "SharedKeyLite" - } - return fmt.Sprintf("%s %s:%s", key, getCanonicalizedAccountName(accountName), signature) -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/autorest.go b/vendor/github.com/Azure/go-autorest/autorest/autorest.go deleted file mode 100644 index aafdf021fd..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/autorest.go +++ /dev/null @@ -1,150 +0,0 @@ -/* -Package autorest implements an HTTP request pipeline suitable for use across multiple go-routines -and provides the shared routines relied on by AutoRest (see https://github.com/Azure/autorest/) -generated Go code. - -The package breaks sending and responding to HTTP requests into three phases: Preparing, Sending, -and Responding. A typical pattern is: - - req, err := Prepare(&http.Request{}, - token.WithAuthorization()) - - resp, err := Send(req, - WithLogging(logger), - DoErrorIfStatusCode(http.StatusInternalServerError), - DoCloseIfError(), - DoRetryForAttempts(5, time.Second)) - - err = Respond(resp, - ByDiscardingBody(), - ByClosing()) - -Each phase relies on decorators to modify and / or manage processing. Decorators may first modify -and then pass the data along, pass the data first and then modify the result, or wrap themselves -around passing the data (such as a logger might do). Decorators run in the order provided. For -example, the following: - - req, err := Prepare(&http.Request{}, - WithBaseURL("https://microsoft.com/"), - WithPath("a"), - WithPath("b"), - WithPath("c")) - -will set the URL to: - - https://microsoft.com/a/b/c - -Preparers and Responders may be shared and re-used (assuming the underlying decorators support -sharing and re-use). Performant use is obtained by creating one or more Preparers and Responders -shared among multiple go-routines, and a single Sender shared among multiple sending go-routines, -all bound together by means of input / output channels. - -Decorators hold their passed state within a closure (such as the path components in the example -above). Be careful to share Preparers and Responders only in a context where such held state -applies. For example, it may not make sense to share a Preparer that applies a query string from a -fixed set of values. Similarly, sharing a Responder that reads the response body into a passed -struct (e.g., ByUnmarshallingJson) is likely incorrect. - -Lastly, the Swagger specification (https://swagger.io) that drives AutoRest -(https://github.com/Azure/autorest/) precisely defines two date forms: date and date-time. The -github.com/Azure/go-autorest/autorest/date package provides time.Time derivations to ensure -correct parsing and formatting. - -Errors raised by autorest objects and methods will conform to the autorest.Error interface. - -See the included examples for more detail. For details on the suggested use of this package by -generated clients, see the Client described below. -*/ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "context" - "net/http" - "time" -) - -const ( - // HeaderLocation specifies the HTTP Location header. - HeaderLocation = "Location" - - // HeaderRetryAfter specifies the HTTP Retry-After header. - HeaderRetryAfter = "Retry-After" -) - -// ResponseHasStatusCode returns true if the status code in the HTTP Response is in the passed set -// and false otherwise. -func ResponseHasStatusCode(resp *http.Response, codes ...int) bool { - if resp == nil { - return false - } - return containsInt(codes, resp.StatusCode) -} - -// GetLocation retrieves the URL from the Location header of the passed response. -func GetLocation(resp *http.Response) string { - return resp.Header.Get(HeaderLocation) -} - -// GetRetryAfter extracts the retry delay from the Retry-After header of the passed response. If -// the header is absent or is malformed, it will return the supplied default delay time.Duration. -func GetRetryAfter(resp *http.Response, defaultDelay time.Duration) time.Duration { - retry := resp.Header.Get(HeaderRetryAfter) - if retry == "" { - return defaultDelay - } - - d, err := time.ParseDuration(retry + "s") - if err != nil { - return defaultDelay - } - - return d -} - -// NewPollingRequest allocates and returns a new http.Request to poll for the passed response. -func NewPollingRequest(resp *http.Response, cancel <-chan struct{}) (*http.Request, error) { - location := GetLocation(resp) - if location == "" { - return nil, NewErrorWithResponse("autorest", "NewPollingRequest", resp, "Location header missing from response that requires polling") - } - - req, err := Prepare(&http.Request{Cancel: cancel}, - AsGet(), - WithBaseURL(location)) - if err != nil { - return nil, NewErrorWithError(err, "autorest", "NewPollingRequest", nil, "Failure creating poll request to %s", location) - } - - return req, nil -} - -// NewPollingRequestWithContext allocates and returns a new http.Request with the specified context to poll for the passed response. -func NewPollingRequestWithContext(ctx context.Context, resp *http.Response) (*http.Request, error) { - location := GetLocation(resp) - if location == "" { - return nil, NewErrorWithResponse("autorest", "NewPollingRequestWithContext", resp, "Location header missing from response that requires polling") - } - - req, err := Prepare((&http.Request{}).WithContext(ctx), - AsGet(), - WithBaseURL(location)) - if err != nil { - return nil, NewErrorWithError(err, "autorest", "NewPollingRequestWithContext", nil, "Failure creating poll request to %s", location) - } - - return req, nil -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/async.go b/vendor/github.com/Azure/go-autorest/autorest/azure/async.go deleted file mode 100644 index 45575eedbf..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/azure/async.go +++ /dev/null @@ -1,995 +0,0 @@ -package azure - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "bytes" - "context" - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "net/url" - "strings" - "time" - - "github.com/Azure/go-autorest/autorest" - "github.com/Azure/go-autorest/logger" - "github.com/Azure/go-autorest/tracing" -) - -const ( - headerAsyncOperation = "Azure-AsyncOperation" -) - -const ( - operationInProgress string = "InProgress" - operationCanceled string = "Canceled" - operationFailed string = "Failed" - operationSucceeded string = "Succeeded" -) - -var pollingCodes = [...]int{http.StatusNoContent, http.StatusAccepted, http.StatusCreated, http.StatusOK} - -// FutureAPI contains the set of methods on the Future type. -type FutureAPI interface { - // Response returns the last HTTP response. - Response() *http.Response - - // Status returns the last status message of the operation. - Status() string - - // PollingMethod returns the method used to monitor the status of the asynchronous operation. - PollingMethod() PollingMethodType - - // DoneWithContext queries the service to see if the operation has completed. - DoneWithContext(context.Context, autorest.Sender) (bool, error) - - // GetPollingDelay returns a duration the application should wait before checking - // the status of the asynchronous request and true; this value is returned from - // the service via the Retry-After response header. If the header wasn't returned - // then the function returns the zero-value time.Duration and false. - GetPollingDelay() (time.Duration, bool) - - // WaitForCompletionRef will return when one of the following conditions is met: the long - // running operation has completed, the provided context is cancelled, or the client's - // polling duration has been exceeded. It will retry failed polling attempts based on - // the retry value defined in the client up to the maximum retry attempts. - // If no deadline is specified in the context then the client.PollingDuration will be - // used to determine if a default deadline should be used. - // If PollingDuration is greater than zero the value will be used as the context's timeout. - // If PollingDuration is zero then no default deadline will be used. - WaitForCompletionRef(context.Context, autorest.Client) error - - // MarshalJSON implements the json.Marshaler interface. - MarshalJSON() ([]byte, error) - - // MarshalJSON implements the json.Unmarshaler interface. - UnmarshalJSON([]byte) error - - // PollingURL returns the URL used for retrieving the status of the long-running operation. - PollingURL() string - - // GetResult should be called once polling has completed successfully. - // It makes the final GET call to retrieve the resultant payload. - GetResult(autorest.Sender) (*http.Response, error) -} - -var _ FutureAPI = (*Future)(nil) - -// Future provides a mechanism to access the status and results of an asynchronous request. -// Since futures are stateful they should be passed by value to avoid race conditions. -type Future struct { - pt pollingTracker -} - -// NewFutureFromResponse returns a new Future object initialized -// with the initial response from an asynchronous operation. -func NewFutureFromResponse(resp *http.Response) (Future, error) { - pt, err := createPollingTracker(resp) - return Future{pt: pt}, err -} - -// Response returns the last HTTP response. -func (f Future) Response() *http.Response { - if f.pt == nil { - return nil - } - return f.pt.latestResponse() -} - -// Status returns the last status message of the operation. -func (f Future) Status() string { - if f.pt == nil { - return "" - } - return f.pt.pollingStatus() -} - -// PollingMethod returns the method used to monitor the status of the asynchronous operation. -func (f Future) PollingMethod() PollingMethodType { - if f.pt == nil { - return PollingUnknown - } - return f.pt.pollingMethod() -} - -// DoneWithContext queries the service to see if the operation has completed. -func (f *Future) DoneWithContext(ctx context.Context, sender autorest.Sender) (done bool, err error) { - ctx = tracing.StartSpan(ctx, "github.com/Azure/go-autorest/autorest/azure/async.DoneWithContext") - defer func() { - sc := -1 - resp := f.Response() - if resp != nil { - sc = resp.StatusCode - } - tracing.EndSpan(ctx, sc, err) - }() - - if f.pt == nil { - return false, autorest.NewError("Future", "Done", "future is not initialized") - } - if f.pt.hasTerminated() { - return true, f.pt.pollingError() - } - if err := f.pt.pollForStatus(ctx, sender); err != nil { - return false, err - } - if err := f.pt.checkForErrors(); err != nil { - return f.pt.hasTerminated(), err - } - if err := f.pt.updatePollingState(f.pt.provisioningStateApplicable()); err != nil { - return false, err - } - if err := f.pt.initPollingMethod(); err != nil { - return false, err - } - if err := f.pt.updatePollingMethod(); err != nil { - return false, err - } - return f.pt.hasTerminated(), f.pt.pollingError() -} - -// GetPollingDelay returns a duration the application should wait before checking -// the status of the asynchronous request and true; this value is returned from -// the service via the Retry-After response header. If the header wasn't returned -// then the function returns the zero-value time.Duration and false. -func (f Future) GetPollingDelay() (time.Duration, bool) { - if f.pt == nil { - return 0, false - } - resp := f.pt.latestResponse() - if resp == nil { - return 0, false - } - - retry := resp.Header.Get(autorest.HeaderRetryAfter) - if retry == "" { - return 0, false - } - - d, err := time.ParseDuration(retry + "s") - if err != nil { - panic(err) - } - - return d, true -} - -// WaitForCompletionRef will return when one of the following conditions is met: the long -// running operation has completed, the provided context is cancelled, or the client's -// polling duration has been exceeded. It will retry failed polling attempts based on -// the retry value defined in the client up to the maximum retry attempts. -// If no deadline is specified in the context then the client.PollingDuration will be -// used to determine if a default deadline should be used. -// If PollingDuration is greater than zero the value will be used as the context's timeout. -// If PollingDuration is zero then no default deadline will be used. -func (f *Future) WaitForCompletionRef(ctx context.Context, client autorest.Client) (err error) { - ctx = tracing.StartSpan(ctx, "github.com/Azure/go-autorest/autorest/azure/async.WaitForCompletionRef") - defer func() { - sc := -1 - resp := f.Response() - if resp != nil { - sc = resp.StatusCode - } - tracing.EndSpan(ctx, sc, err) - }() - cancelCtx := ctx - // if the provided context already has a deadline don't override it - _, hasDeadline := ctx.Deadline() - if d := client.PollingDuration; !hasDeadline && d != 0 { - var cancel context.CancelFunc - cancelCtx, cancel = context.WithTimeout(ctx, d) - defer cancel() - } - // if the initial response has a Retry-After, sleep for the specified amount of time before starting to poll - if delay, ok := f.GetPollingDelay(); ok { - logger.Instance.Writeln(logger.LogInfo, "WaitForCompletionRef: initial polling delay") - if delayElapsed := autorest.DelayForBackoff(delay, 0, cancelCtx.Done()); !delayElapsed { - err = cancelCtx.Err() - return - } - } - done, err := f.DoneWithContext(ctx, client) - for attempts := 0; !done; done, err = f.DoneWithContext(ctx, client) { - if attempts >= client.RetryAttempts { - return autorest.NewErrorWithError(err, "Future", "WaitForCompletion", f.pt.latestResponse(), "the number of retries has been exceeded") - } - // we want delayAttempt to be zero in the non-error case so - // that DelayForBackoff doesn't perform exponential back-off - var delayAttempt int - var delay time.Duration - if err == nil { - // check for Retry-After delay, if not present use the client's polling delay - var ok bool - delay, ok = f.GetPollingDelay() - if !ok { - logger.Instance.Writeln(logger.LogInfo, "WaitForCompletionRef: Using client polling delay") - delay = client.PollingDelay - } - } else { - // there was an error polling for status so perform exponential - // back-off based on the number of attempts using the client's retry - // duration. update attempts after delayAttempt to avoid off-by-one. - logger.Instance.Writef(logger.LogError, "WaitForCompletionRef: %s\n", err) - delayAttempt = attempts - delay = client.RetryDuration - attempts++ - } - // wait until the delay elapses or the context is cancelled - delayElapsed := autorest.DelayForBackoff(delay, delayAttempt, cancelCtx.Done()) - if !delayElapsed { - return autorest.NewErrorWithError(cancelCtx.Err(), "Future", "WaitForCompletion", f.pt.latestResponse(), "context has been cancelled") - } - } - return -} - -// MarshalJSON implements the json.Marshaler interface. -func (f Future) MarshalJSON() ([]byte, error) { - return json.Marshal(f.pt) -} - -// UnmarshalJSON implements the json.Unmarshaler interface. -func (f *Future) UnmarshalJSON(data []byte) error { - // unmarshal into JSON object to determine the tracker type - obj := map[string]interface{}{} - err := json.Unmarshal(data, &obj) - if err != nil { - return err - } - if obj["method"] == nil { - return autorest.NewError("Future", "UnmarshalJSON", "missing 'method' property") - } - method := obj["method"].(string) - switch strings.ToUpper(method) { - case http.MethodDelete: - f.pt = &pollingTrackerDelete{} - case http.MethodPatch: - f.pt = &pollingTrackerPatch{} - case http.MethodPost: - f.pt = &pollingTrackerPost{} - case http.MethodPut: - f.pt = &pollingTrackerPut{} - default: - return autorest.NewError("Future", "UnmarshalJSON", "unsupoorted method '%s'", method) - } - // now unmarshal into the tracker - return json.Unmarshal(data, &f.pt) -} - -// PollingURL returns the URL used for retrieving the status of the long-running operation. -func (f Future) PollingURL() string { - if f.pt == nil { - return "" - } - return f.pt.pollingURL() -} - -// GetResult should be called once polling has completed successfully. -// It makes the final GET call to retrieve the resultant payload. -func (f Future) GetResult(sender autorest.Sender) (*http.Response, error) { - if f.pt.finalGetURL() == "" { - // we can end up in this situation if the async operation returns a 200 - // with no polling URLs. in that case return the response which should - // contain the JSON payload (only do this for successful terminal cases). - if lr := f.pt.latestResponse(); lr != nil && f.pt.hasSucceeded() { - return lr, nil - } - return nil, autorest.NewError("Future", "GetResult", "missing URL for retrieving result") - } - req, err := http.NewRequest(http.MethodGet, f.pt.finalGetURL(), nil) - if err != nil { - return nil, err - } - resp, err := sender.Do(req) - if err == nil && resp.Body != nil { - // copy the body and close it so callers don't have to - defer resp.Body.Close() - b, err := ioutil.ReadAll(resp.Body) - if err != nil { - return resp, err - } - resp.Body = ioutil.NopCloser(bytes.NewReader(b)) - } - return resp, err -} - -type pollingTracker interface { - // these methods can differ per tracker - - // checks the response headers and status code to determine the polling mechanism - updatePollingMethod() error - - // checks the response for tracker-specific error conditions - checkForErrors() error - - // returns true if provisioning state should be checked - provisioningStateApplicable() bool - - // methods common to all trackers - - // initializes a tracker's polling URL and method, called for each iteration. - // these values can be overridden by each polling tracker as required. - initPollingMethod() error - - // initializes the tracker's internal state, call this when the tracker is created - initializeState() error - - // makes an HTTP request to check the status of the LRO - pollForStatus(ctx context.Context, sender autorest.Sender) error - - // updates internal tracker state, call this after each call to pollForStatus - updatePollingState(provStateApl bool) error - - // returns the error response from the service, can be nil - pollingError() error - - // returns the polling method being used - pollingMethod() PollingMethodType - - // returns the state of the LRO as returned from the service - pollingStatus() string - - // returns the URL used for polling status - pollingURL() string - - // returns the URL used for the final GET to retrieve the resource - finalGetURL() string - - // returns true if the LRO is in a terminal state - hasTerminated() bool - - // returns true if the LRO is in a failed terminal state - hasFailed() bool - - // returns true if the LRO is in a successful terminal state - hasSucceeded() bool - - // returns the cached HTTP response after a call to pollForStatus(), can be nil - latestResponse() *http.Response -} - -type pollingTrackerBase struct { - // resp is the last response, either from the submission of the LRO or from polling - resp *http.Response - - // method is the HTTP verb, this is needed for deserialization - Method string `json:"method"` - - // rawBody is the raw JSON response body - rawBody map[string]interface{} - - // denotes if polling is using async-operation or location header - Pm PollingMethodType `json:"pollingMethod"` - - // the URL to poll for status - URI string `json:"pollingURI"` - - // the state of the LRO as returned from the service - State string `json:"lroState"` - - // the URL to GET for the final result - FinalGetURI string `json:"resultURI"` - - // used to hold an error object returned from the service - Err *ServiceError `json:"error,omitempty"` -} - -func (pt *pollingTrackerBase) initializeState() error { - // determine the initial polling state based on response body and/or HTTP status - // code. this is applicable to the initial LRO response, not polling responses! - pt.Method = pt.resp.Request.Method - if err := pt.updateRawBody(); err != nil { - return err - } - switch pt.resp.StatusCode { - case http.StatusOK: - if ps := pt.getProvisioningState(); ps != nil { - pt.State = *ps - if pt.hasFailed() { - pt.updateErrorFromResponse() - return pt.pollingError() - } - } else { - pt.State = operationSucceeded - } - case http.StatusCreated: - if ps := pt.getProvisioningState(); ps != nil { - pt.State = *ps - } else { - pt.State = operationInProgress - } - case http.StatusAccepted: - pt.State = operationInProgress - case http.StatusNoContent: - pt.State = operationSucceeded - default: - pt.State = operationFailed - pt.updateErrorFromResponse() - return pt.pollingError() - } - return pt.initPollingMethod() -} - -func (pt pollingTrackerBase) getProvisioningState() *string { - if pt.rawBody != nil && pt.rawBody["properties"] != nil { - p := pt.rawBody["properties"].(map[string]interface{}) - if ps := p["provisioningState"]; ps != nil { - s := ps.(string) - return &s - } - } - return nil -} - -func (pt *pollingTrackerBase) updateRawBody() error { - pt.rawBody = map[string]interface{}{} - if pt.resp.ContentLength != 0 { - defer pt.resp.Body.Close() - b, err := ioutil.ReadAll(pt.resp.Body) - if err != nil { - return autorest.NewErrorWithError(err, "pollingTrackerBase", "updateRawBody", nil, "failed to read response body") - } - // put the body back so it's available to other callers - pt.resp.Body = ioutil.NopCloser(bytes.NewReader(b)) - // observed in 204 responses over HTTP/2.0; the content length is -1 but body is empty - if len(b) == 0 { - return nil - } - if err = json.Unmarshal(b, &pt.rawBody); err != nil { - return autorest.NewErrorWithError(err, "pollingTrackerBase", "updateRawBody", nil, "failed to unmarshal response body") - } - } - return nil -} - -func (pt *pollingTrackerBase) pollForStatus(ctx context.Context, sender autorest.Sender) error { - req, err := http.NewRequest(http.MethodGet, pt.URI, nil) - if err != nil { - return autorest.NewErrorWithError(err, "pollingTrackerBase", "pollForStatus", nil, "failed to create HTTP request") - } - - req = req.WithContext(ctx) - preparer := autorest.CreatePreparer(autorest.GetPrepareDecorators(ctx)...) - req, err = preparer.Prepare(req) - if err != nil { - return autorest.NewErrorWithError(err, "pollingTrackerBase", "pollForStatus", nil, "failed preparing HTTP request") - } - pt.resp, err = sender.Do(req) - if err != nil { - return autorest.NewErrorWithError(err, "pollingTrackerBase", "pollForStatus", nil, "failed to send HTTP request") - } - if autorest.ResponseHasStatusCode(pt.resp, pollingCodes[:]...) { - // reset the service error on success case - pt.Err = nil - err = pt.updateRawBody() - } else { - // check response body for error content - pt.updateErrorFromResponse() - err = pt.pollingError() - } - return err -} - -// attempts to unmarshal a ServiceError type from the response body. -// if that fails then make a best attempt at creating something meaningful. -// NOTE: this assumes that the async operation has failed. -func (pt *pollingTrackerBase) updateErrorFromResponse() { - var err error - if pt.resp.ContentLength != 0 { - type respErr struct { - ServiceError *ServiceError `json:"error"` - } - re := respErr{} - defer pt.resp.Body.Close() - var b []byte - if b, err = ioutil.ReadAll(pt.resp.Body); err != nil { - goto Default - } - // put the body back so it's available to other callers - pt.resp.Body = ioutil.NopCloser(bytes.NewReader(b)) - if len(b) == 0 { - goto Default - } - if err = json.Unmarshal(b, &re); err != nil { - goto Default - } - // unmarshalling the error didn't yield anything, try unwrapped error - if re.ServiceError == nil { - err = json.Unmarshal(b, &re.ServiceError) - if err != nil { - goto Default - } - } - // the unmarshaller will ensure re.ServiceError is non-nil - // even if there was no content unmarshalled so check the code. - if re.ServiceError.Code != "" { - pt.Err = re.ServiceError - return - } - } -Default: - se := &ServiceError{ - Code: pt.pollingStatus(), - Message: "The async operation failed.", - } - if err != nil { - se.InnerError = make(map[string]interface{}) - se.InnerError["unmarshalError"] = err.Error() - } - // stick the response body into the error object in hopes - // it contains something useful to help diagnose the failure. - if len(pt.rawBody) > 0 { - se.AdditionalInfo = []map[string]interface{}{ - pt.rawBody, - } - } - pt.Err = se -} - -func (pt *pollingTrackerBase) updatePollingState(provStateApl bool) error { - if pt.Pm == PollingAsyncOperation && pt.rawBody["status"] != nil { - pt.State = pt.rawBody["status"].(string) - } else { - if pt.resp.StatusCode == http.StatusAccepted { - pt.State = operationInProgress - } else if provStateApl { - if ps := pt.getProvisioningState(); ps != nil { - pt.State = *ps - } else { - pt.State = operationSucceeded - } - } else { - return autorest.NewError("pollingTrackerBase", "updatePollingState", "the response from the async operation has an invalid status code") - } - } - // if the operation has failed update the error state - if pt.hasFailed() { - pt.updateErrorFromResponse() - } - return nil -} - -func (pt pollingTrackerBase) pollingError() error { - if pt.Err == nil { - return nil - } - return pt.Err -} - -func (pt pollingTrackerBase) pollingMethod() PollingMethodType { - return pt.Pm -} - -func (pt pollingTrackerBase) pollingStatus() string { - return pt.State -} - -func (pt pollingTrackerBase) pollingURL() string { - return pt.URI -} - -func (pt pollingTrackerBase) finalGetURL() string { - return pt.FinalGetURI -} - -func (pt pollingTrackerBase) hasTerminated() bool { - return strings.EqualFold(pt.State, operationCanceled) || strings.EqualFold(pt.State, operationFailed) || strings.EqualFold(pt.State, operationSucceeded) -} - -func (pt pollingTrackerBase) hasFailed() bool { - return strings.EqualFold(pt.State, operationCanceled) || strings.EqualFold(pt.State, operationFailed) -} - -func (pt pollingTrackerBase) hasSucceeded() bool { - return strings.EqualFold(pt.State, operationSucceeded) -} - -func (pt pollingTrackerBase) latestResponse() *http.Response { - return pt.resp -} - -// error checking common to all trackers -func (pt pollingTrackerBase) baseCheckForErrors() error { - // for Azure-AsyncOperations the response body cannot be nil or empty - if pt.Pm == PollingAsyncOperation { - if pt.resp.Body == nil || pt.resp.ContentLength == 0 { - return autorest.NewError("pollingTrackerBase", "baseCheckForErrors", "for Azure-AsyncOperation response body cannot be nil") - } - if pt.rawBody["status"] == nil { - return autorest.NewError("pollingTrackerBase", "baseCheckForErrors", "missing status property in Azure-AsyncOperation response body") - } - } - return nil -} - -// default initialization of polling URL/method. each verb tracker will update this as required. -func (pt *pollingTrackerBase) initPollingMethod() error { - if ao, err := getURLFromAsyncOpHeader(pt.resp); err != nil { - return err - } else if ao != "" { - pt.URI = ao - pt.Pm = PollingAsyncOperation - return nil - } - if lh, err := getURLFromLocationHeader(pt.resp); err != nil { - return err - } else if lh != "" { - pt.URI = lh - pt.Pm = PollingLocation - return nil - } - // it's ok if we didn't find a polling header, this will be handled elsewhere - return nil -} - -// DELETE - -type pollingTrackerDelete struct { - pollingTrackerBase -} - -func (pt *pollingTrackerDelete) updatePollingMethod() error { - // for 201 the Location header is required - if pt.resp.StatusCode == http.StatusCreated { - if lh, err := getURLFromLocationHeader(pt.resp); err != nil { - return err - } else if lh == "" { - return autorest.NewError("pollingTrackerDelete", "updateHeaders", "missing Location header in 201 response") - } else { - pt.URI = lh - } - pt.Pm = PollingLocation - pt.FinalGetURI = pt.URI - } - // for 202 prefer the Azure-AsyncOperation header but fall back to Location if necessary - if pt.resp.StatusCode == http.StatusAccepted { - ao, err := getURLFromAsyncOpHeader(pt.resp) - if err != nil { - return err - } else if ao != "" { - pt.URI = ao - pt.Pm = PollingAsyncOperation - } - // if the Location header is invalid and we already have a polling URL - // then we don't care if the Location header URL is malformed. - if lh, err := getURLFromLocationHeader(pt.resp); err != nil && pt.URI == "" { - return err - } else if lh != "" { - if ao == "" { - pt.URI = lh - pt.Pm = PollingLocation - } - // when both headers are returned we use the value in the Location header for the final GET - pt.FinalGetURI = lh - } - // make sure a polling URL was found - if pt.URI == "" { - return autorest.NewError("pollingTrackerPost", "updateHeaders", "didn't get any suitable polling URLs in 202 response") - } - } - return nil -} - -func (pt pollingTrackerDelete) checkForErrors() error { - return pt.baseCheckForErrors() -} - -func (pt pollingTrackerDelete) provisioningStateApplicable() bool { - return pt.resp.StatusCode == http.StatusOK || pt.resp.StatusCode == http.StatusNoContent -} - -// PATCH - -type pollingTrackerPatch struct { - pollingTrackerBase -} - -func (pt *pollingTrackerPatch) updatePollingMethod() error { - // by default we can use the original URL for polling and final GET - if pt.URI == "" { - pt.URI = pt.resp.Request.URL.String() - } - if pt.FinalGetURI == "" { - pt.FinalGetURI = pt.resp.Request.URL.String() - } - if pt.Pm == PollingUnknown { - pt.Pm = PollingRequestURI - } - // for 201 it's permissible for no headers to be returned - if pt.resp.StatusCode == http.StatusCreated { - if ao, err := getURLFromAsyncOpHeader(pt.resp); err != nil { - return err - } else if ao != "" { - pt.URI = ao - pt.Pm = PollingAsyncOperation - } - } - // for 202 prefer the Azure-AsyncOperation header but fall back to Location if necessary - // note the absence of the "final GET" mechanism for PATCH - if pt.resp.StatusCode == http.StatusAccepted { - ao, err := getURLFromAsyncOpHeader(pt.resp) - if err != nil { - return err - } else if ao != "" { - pt.URI = ao - pt.Pm = PollingAsyncOperation - } - if ao == "" { - if lh, err := getURLFromLocationHeader(pt.resp); err != nil { - return err - } else if lh == "" { - return autorest.NewError("pollingTrackerPatch", "updateHeaders", "didn't get any suitable polling URLs in 202 response") - } else { - pt.URI = lh - pt.Pm = PollingLocation - } - } - } - return nil -} - -func (pt pollingTrackerPatch) checkForErrors() error { - return pt.baseCheckForErrors() -} - -func (pt pollingTrackerPatch) provisioningStateApplicable() bool { - return pt.resp.StatusCode == http.StatusOK || pt.resp.StatusCode == http.StatusCreated -} - -// POST - -type pollingTrackerPost struct { - pollingTrackerBase -} - -func (pt *pollingTrackerPost) updatePollingMethod() error { - // 201 requires Location header - if pt.resp.StatusCode == http.StatusCreated { - if lh, err := getURLFromLocationHeader(pt.resp); err != nil { - return err - } else if lh == "" { - return autorest.NewError("pollingTrackerPost", "updateHeaders", "missing Location header in 201 response") - } else { - pt.URI = lh - pt.FinalGetURI = lh - pt.Pm = PollingLocation - } - } - // for 202 prefer the Azure-AsyncOperation header but fall back to Location if necessary - if pt.resp.StatusCode == http.StatusAccepted { - ao, err := getURLFromAsyncOpHeader(pt.resp) - if err != nil { - return err - } else if ao != "" { - pt.URI = ao - pt.Pm = PollingAsyncOperation - } - // if the Location header is invalid and we already have a polling URL - // then we don't care if the Location header URL is malformed. - if lh, err := getURLFromLocationHeader(pt.resp); err != nil && pt.URI == "" { - return err - } else if lh != "" { - if ao == "" { - pt.URI = lh - pt.Pm = PollingLocation - } - // when both headers are returned we use the value in the Location header for the final GET - pt.FinalGetURI = lh - } - // make sure a polling URL was found - if pt.URI == "" { - return autorest.NewError("pollingTrackerPost", "updateHeaders", "didn't get any suitable polling URLs in 202 response") - } - } - return nil -} - -func (pt pollingTrackerPost) checkForErrors() error { - return pt.baseCheckForErrors() -} - -func (pt pollingTrackerPost) provisioningStateApplicable() bool { - return pt.resp.StatusCode == http.StatusOK || pt.resp.StatusCode == http.StatusNoContent -} - -// PUT - -type pollingTrackerPut struct { - pollingTrackerBase -} - -func (pt *pollingTrackerPut) updatePollingMethod() error { - // by default we can use the original URL for polling and final GET - if pt.URI == "" { - pt.URI = pt.resp.Request.URL.String() - } - if pt.FinalGetURI == "" { - pt.FinalGetURI = pt.resp.Request.URL.String() - } - if pt.Pm == PollingUnknown { - pt.Pm = PollingRequestURI - } - // for 201 it's permissible for no headers to be returned - if pt.resp.StatusCode == http.StatusCreated { - if ao, err := getURLFromAsyncOpHeader(pt.resp); err != nil { - return err - } else if ao != "" { - pt.URI = ao - pt.Pm = PollingAsyncOperation - } - } - // for 202 prefer the Azure-AsyncOperation header but fall back to Location if necessary - if pt.resp.StatusCode == http.StatusAccepted { - ao, err := getURLFromAsyncOpHeader(pt.resp) - if err != nil { - return err - } else if ao != "" { - pt.URI = ao - pt.Pm = PollingAsyncOperation - } - // if the Location header is invalid and we already have a polling URL - // then we don't care if the Location header URL is malformed. - if lh, err := getURLFromLocationHeader(pt.resp); err != nil && pt.URI == "" { - return err - } else if lh != "" { - if ao == "" { - pt.URI = lh - pt.Pm = PollingLocation - } - } - // make sure a polling URL was found - if pt.URI == "" { - return autorest.NewError("pollingTrackerPut", "updateHeaders", "didn't get any suitable polling URLs in 202 response") - } - } - return nil -} - -func (pt pollingTrackerPut) checkForErrors() error { - err := pt.baseCheckForErrors() - if err != nil { - return err - } - // if there are no LRO headers then the body cannot be empty - ao, err := getURLFromAsyncOpHeader(pt.resp) - if err != nil { - return err - } - lh, err := getURLFromLocationHeader(pt.resp) - if err != nil { - return err - } - if ao == "" && lh == "" && len(pt.rawBody) == 0 { - return autorest.NewError("pollingTrackerPut", "checkForErrors", "the response did not contain a body") - } - return nil -} - -func (pt pollingTrackerPut) provisioningStateApplicable() bool { - return pt.resp.StatusCode == http.StatusOK || pt.resp.StatusCode == http.StatusCreated -} - -// creates a polling tracker based on the verb of the original request -func createPollingTracker(resp *http.Response) (pollingTracker, error) { - var pt pollingTracker - switch strings.ToUpper(resp.Request.Method) { - case http.MethodDelete: - pt = &pollingTrackerDelete{pollingTrackerBase: pollingTrackerBase{resp: resp}} - case http.MethodPatch: - pt = &pollingTrackerPatch{pollingTrackerBase: pollingTrackerBase{resp: resp}} - case http.MethodPost: - pt = &pollingTrackerPost{pollingTrackerBase: pollingTrackerBase{resp: resp}} - case http.MethodPut: - pt = &pollingTrackerPut{pollingTrackerBase: pollingTrackerBase{resp: resp}} - default: - return nil, autorest.NewError("azure", "createPollingTracker", "unsupported HTTP method %s", resp.Request.Method) - } - if err := pt.initializeState(); err != nil { - return pt, err - } - // this initializes the polling header values, we do this during creation in case the - // initial response send us invalid values; this way the API call will return a non-nil - // error (not doing this means the error shows up in Future.Done) - return pt, pt.updatePollingMethod() -} - -// gets the polling URL from the Azure-AsyncOperation header. -// ensures the URL is well-formed and absolute. -func getURLFromAsyncOpHeader(resp *http.Response) (string, error) { - s := resp.Header.Get(http.CanonicalHeaderKey(headerAsyncOperation)) - if s == "" { - return "", nil - } - if !isValidURL(s) { - return "", autorest.NewError("azure", "getURLFromAsyncOpHeader", "invalid polling URL '%s'", s) - } - return s, nil -} - -// gets the polling URL from the Location header. -// ensures the URL is well-formed and absolute. -func getURLFromLocationHeader(resp *http.Response) (string, error) { - s := resp.Header.Get(http.CanonicalHeaderKey(autorest.HeaderLocation)) - if s == "" { - return "", nil - } - if !isValidURL(s) { - return "", autorest.NewError("azure", "getURLFromLocationHeader", "invalid polling URL '%s'", s) - } - return s, nil -} - -// verify that the URL is valid and absolute -func isValidURL(s string) bool { - u, err := url.Parse(s) - return err == nil && u.IsAbs() -} - -// PollingMethodType defines a type used for enumerating polling mechanisms. -type PollingMethodType string - -const ( - // PollingAsyncOperation indicates the polling method uses the Azure-AsyncOperation header. - PollingAsyncOperation PollingMethodType = "AsyncOperation" - - // PollingLocation indicates the polling method uses the Location header. - PollingLocation PollingMethodType = "Location" - - // PollingRequestURI indicates the polling method uses the original request URI. - PollingRequestURI PollingMethodType = "RequestURI" - - // PollingUnknown indicates an unknown polling method and is the default value. - PollingUnknown PollingMethodType = "" -) - -// AsyncOpIncompleteError is the type that's returned from a future that has not completed. -type AsyncOpIncompleteError struct { - // FutureType is the name of the type composed of a azure.Future. - FutureType string -} - -// Error returns an error message including the originating type name of the error. -func (e AsyncOpIncompleteError) Error() string { - return fmt.Sprintf("%s: asynchronous operation has not completed", e.FutureType) -} - -// NewAsyncOpIncompleteError creates a new AsyncOpIncompleteError with the specified parameters. -func NewAsyncOpIncompleteError(futureType string) AsyncOpIncompleteError { - return AsyncOpIncompleteError{ - FutureType: futureType, - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/azure.go b/vendor/github.com/Azure/go-autorest/autorest/azure/azure.go deleted file mode 100644 index 1328f1764c..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/azure/azure.go +++ /dev/null @@ -1,388 +0,0 @@ -// Package azure provides Azure-specific implementations used with AutoRest. -// See the included examples for more detail. -package azure - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "bytes" - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "regexp" - "strconv" - "strings" - - "github.com/Azure/go-autorest/autorest" -) - -const ( - // HeaderClientID is the Azure extension header to set a user-specified request ID. - HeaderClientID = "x-ms-client-request-id" - - // HeaderReturnClientID is the Azure extension header to set if the user-specified request ID - // should be included in the response. - HeaderReturnClientID = "x-ms-return-client-request-id" - - // HeaderContentType is the type of the content in the HTTP response. - HeaderContentType = "Content-Type" - - // HeaderRequestID is the Azure extension header of the service generated request ID returned - // in the response. - HeaderRequestID = "x-ms-request-id" -) - -// ServiceError encapsulates the error response from an Azure service. -// It adhears to the OData v4 specification for error responses. -type ServiceError struct { - Code string `json:"code"` - Message string `json:"message"` - Target *string `json:"target"` - Details []map[string]interface{} `json:"details"` - InnerError map[string]interface{} `json:"innererror"` - AdditionalInfo []map[string]interface{} `json:"additionalInfo"` -} - -func (se ServiceError) Error() string { - result := fmt.Sprintf("Code=%q Message=%q", se.Code, se.Message) - - if se.Target != nil { - result += fmt.Sprintf(" Target=%q", *se.Target) - } - - if se.Details != nil { - d, err := json.Marshal(se.Details) - if err != nil { - result += fmt.Sprintf(" Details=%v", se.Details) - } - result += fmt.Sprintf(" Details=%s", d) - } - - if se.InnerError != nil { - d, err := json.Marshal(se.InnerError) - if err != nil { - result += fmt.Sprintf(" InnerError=%v", se.InnerError) - } - result += fmt.Sprintf(" InnerError=%s", d) - } - - if se.AdditionalInfo != nil { - d, err := json.Marshal(se.AdditionalInfo) - if err != nil { - result += fmt.Sprintf(" AdditionalInfo=%v", se.AdditionalInfo) - } - result += fmt.Sprintf(" AdditionalInfo=%s", d) - } - - return result -} - -// UnmarshalJSON implements the json.Unmarshaler interface for the ServiceError type. -func (se *ServiceError) UnmarshalJSON(b []byte) error { - // http://docs.oasis-open.org/odata/odata-json-format/v4.0/os/odata-json-format-v4.0-os.html#_Toc372793091 - - type serviceErrorInternal struct { - Code string `json:"code"` - Message string `json:"message"` - Target *string `json:"target,omitempty"` - AdditionalInfo []map[string]interface{} `json:"additionalInfo,omitempty"` - // not all services conform to the OData v4 spec. - // the following fields are where we've seen discrepancies - - // spec calls for []map[string]interface{} but have seen map[string]interface{} - Details interface{} `json:"details,omitempty"` - - // spec calls for map[string]interface{} but have seen []map[string]interface{} and string - InnerError interface{} `json:"innererror,omitempty"` - } - - sei := serviceErrorInternal{} - if err := json.Unmarshal(b, &sei); err != nil { - return err - } - - // copy the fields we know to be correct - se.AdditionalInfo = sei.AdditionalInfo - se.Code = sei.Code - se.Message = sei.Message - se.Target = sei.Target - - // converts an []interface{} to []map[string]interface{} - arrayOfObjs := func(v interface{}) ([]map[string]interface{}, bool) { - arrayOf, ok := v.([]interface{}) - if !ok { - return nil, false - } - final := []map[string]interface{}{} - for _, item := range arrayOf { - as, ok := item.(map[string]interface{}) - if !ok { - return nil, false - } - final = append(final, as) - } - return final, true - } - - // convert the remaining fields, falling back to raw JSON if necessary - - if c, ok := arrayOfObjs(sei.Details); ok { - se.Details = c - } else if c, ok := sei.Details.(map[string]interface{}); ok { - se.Details = []map[string]interface{}{c} - } else if sei.Details != nil { - // stuff into Details - se.Details = []map[string]interface{}{ - {"raw": sei.Details}, - } - } - - if c, ok := sei.InnerError.(map[string]interface{}); ok { - se.InnerError = c - } else if c, ok := arrayOfObjs(sei.InnerError); ok { - // if there's only one error extract it - if len(c) == 1 { - se.InnerError = c[0] - } else { - // multiple errors, stuff them into the value - se.InnerError = map[string]interface{}{ - "multi": c, - } - } - } else if c, ok := sei.InnerError.(string); ok { - se.InnerError = map[string]interface{}{"error": c} - } else if sei.InnerError != nil { - // stuff into InnerError - se.InnerError = map[string]interface{}{ - "raw": sei.InnerError, - } - } - return nil -} - -// RequestError describes an error response returned by Azure service. -type RequestError struct { - autorest.DetailedError - - // The error returned by the Azure service. - ServiceError *ServiceError `json:"error" xml:"Error"` - - // The request id (from the x-ms-request-id-header) of the request. - RequestID string -} - -// Error returns a human-friendly error message from service error. -func (e RequestError) Error() string { - return fmt.Sprintf("autorest/azure: Service returned an error. Status=%v %v", - e.StatusCode, e.ServiceError) -} - -// IsAzureError returns true if the passed error is an Azure Service error; false otherwise. -func IsAzureError(e error) bool { - _, ok := e.(*RequestError) - return ok -} - -// Resource contains details about an Azure resource. -type Resource struct { - SubscriptionID string - ResourceGroup string - Provider string - ResourceType string - ResourceName string -} - -// String function returns a string in form of azureResourceID -func (r Resource) String() string { - return fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/%s/%s/%s", r.SubscriptionID, r.ResourceGroup, r.Provider, r.ResourceType, r.ResourceName) -} - -// ParseResourceID parses a resource ID into a ResourceDetails struct. -// See https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/template-functions-resource?tabs=json#resourceid. -func ParseResourceID(resourceID string) (Resource, error) { - - const resourceIDPatternText = `(?i)subscriptions/(.+)/resourceGroups/(.+)/providers/(.+?)/(.+?)/(.+)` - resourceIDPattern := regexp.MustCompile(resourceIDPatternText) - match := resourceIDPattern.FindStringSubmatch(resourceID) - - if len(match) == 0 { - return Resource{}, fmt.Errorf("parsing failed for %s. Invalid resource Id format", resourceID) - } - - v := strings.Split(match[5], "/") - resourceName := v[len(v)-1] - - result := Resource{ - SubscriptionID: match[1], - ResourceGroup: match[2], - Provider: match[3], - ResourceType: match[4], - ResourceName: resourceName, - } - - return result, nil -} - -// NewErrorWithError creates a new Error conforming object from the -// passed packageType, method, statusCode of the given resp (UndefinedStatusCode -// if resp is nil), message, and original error. message is treated as a format -// string to which the optional args apply. -func NewErrorWithError(original error, packageType string, method string, resp *http.Response, message string, args ...interface{}) RequestError { - if v, ok := original.(*RequestError); ok { - return *v - } - - statusCode := autorest.UndefinedStatusCode - if resp != nil { - statusCode = resp.StatusCode - } - return RequestError{ - DetailedError: autorest.DetailedError{ - Original: original, - PackageType: packageType, - Method: method, - StatusCode: statusCode, - Message: fmt.Sprintf(message, args...), - }, - } -} - -// WithReturningClientID returns a PrepareDecorator that adds an HTTP extension header of -// x-ms-client-request-id whose value is the passed, undecorated UUID (e.g., -// "0F39878C-5F76-4DB8-A25D-61D2C193C3CA"). It also sets the x-ms-return-client-request-id -// header to true such that UUID accompanies the http.Response. -func WithReturningClientID(uuid string) autorest.PrepareDecorator { - preparer := autorest.CreatePreparer( - WithClientID(uuid), - WithReturnClientID(true)) - - return func(p autorest.Preparer) autorest.Preparer { - return autorest.PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err != nil { - return r, err - } - return preparer.Prepare(r) - }) - } -} - -// WithClientID returns a PrepareDecorator that adds an HTTP extension header of -// x-ms-client-request-id whose value is passed, undecorated UUID (e.g., -// "0F39878C-5F76-4DB8-A25D-61D2C193C3CA"). -func WithClientID(uuid string) autorest.PrepareDecorator { - return autorest.WithHeader(HeaderClientID, uuid) -} - -// WithReturnClientID returns a PrepareDecorator that adds an HTTP extension header of -// x-ms-return-client-request-id whose boolean value indicates if the value of the -// x-ms-client-request-id header should be included in the http.Response. -func WithReturnClientID(b bool) autorest.PrepareDecorator { - return autorest.WithHeader(HeaderReturnClientID, strconv.FormatBool(b)) -} - -// ExtractClientID extracts the client identifier from the x-ms-client-request-id header set on the -// http.Request sent to the service (and returned in the http.Response) -func ExtractClientID(resp *http.Response) string { - return autorest.ExtractHeaderValue(HeaderClientID, resp) -} - -// ExtractRequestID extracts the Azure server generated request identifier from the -// x-ms-request-id header. -func ExtractRequestID(resp *http.Response) string { - return autorest.ExtractHeaderValue(HeaderRequestID, resp) -} - -// WithErrorUnlessStatusCode returns a RespondDecorator that emits an -// azure.RequestError by reading the response body unless the response HTTP status code -// is among the set passed. -// -// If there is a chance service may return responses other than the Azure error -// format and the response cannot be parsed into an error, a decoding error will -// be returned containing the response body. In any case, the Responder will -// return an error if the status code is not satisfied. -// -// If this Responder returns an error, the response body will be replaced with -// an in-memory reader, which needs no further closing. -func WithErrorUnlessStatusCode(codes ...int) autorest.RespondDecorator { - return func(r autorest.Responder) autorest.Responder { - return autorest.ResponderFunc(func(resp *http.Response) error { - err := r.Respond(resp) - if err == nil && !autorest.ResponseHasStatusCode(resp, codes...) { - var e RequestError - defer resp.Body.Close() - - encodedAs := autorest.EncodedAsJSON - if strings.Contains(resp.Header.Get("Content-Type"), "xml") { - encodedAs = autorest.EncodedAsXML - } - - // Copy and replace the Body in case it does not contain an error object. - // This will leave the Body available to the caller. - b, decodeErr := autorest.CopyAndDecode(encodedAs, resp.Body, &e) - resp.Body = ioutil.NopCloser(&b) - if decodeErr != nil { - return fmt.Errorf("autorest/azure: error response cannot be parsed: %q error: %v", b, decodeErr) - } - if e.ServiceError == nil { - // Check if error is unwrapped ServiceError - decoder := autorest.NewDecoder(encodedAs, bytes.NewReader(b.Bytes())) - if err := decoder.Decode(&e.ServiceError); err != nil { - return fmt.Errorf("autorest/azure: error response cannot be parsed: %q error: %v", b, err) - } - - // for example, should the API return the literal value `null` as the response - if e.ServiceError == nil { - e.ServiceError = &ServiceError{ - Code: "Unknown", - Message: "Unknown service error", - Details: []map[string]interface{}{ - { - "HttpResponse.Body": b.String(), - }, - }, - } - } - } - - if e.ServiceError != nil && e.ServiceError.Message == "" { - // if we're here it means the returned error wasn't OData v4 compliant. - // try to unmarshal the body in hopes of getting something. - rawBody := map[string]interface{}{} - decoder := autorest.NewDecoder(encodedAs, bytes.NewReader(b.Bytes())) - if err := decoder.Decode(&rawBody); err != nil { - return fmt.Errorf("autorest/azure: error response cannot be parsed: %q error: %v", b, err) - } - - e.ServiceError = &ServiceError{ - Code: "Unknown", - Message: "Unknown service error", - } - if len(rawBody) > 0 { - e.ServiceError.Details = []map[string]interface{}{rawBody} - } - } - e.Response = resp - e.RequestID = ExtractRequestID(resp) - if e.StatusCode == nil { - e.StatusCode = resp.StatusCode - } - err = &e - } - return err - }) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/environments.go b/vendor/github.com/Azure/go-autorest/autorest/azure/environments.go deleted file mode 100644 index b0a53769f2..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/azure/environments.go +++ /dev/null @@ -1,331 +0,0 @@ -package azure - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "os" - "strings" -) - -const ( - // EnvironmentFilepathName captures the name of the environment variable containing the path to the file - // to be used while populating the Azure Environment. - EnvironmentFilepathName = "AZURE_ENVIRONMENT_FILEPATH" - - // NotAvailable is used for endpoints and resource IDs that are not available for a given cloud. - NotAvailable = "N/A" -) - -var environments = map[string]Environment{ - "AZURECHINACLOUD": ChinaCloud, - "AZUREGERMANCLOUD": GermanCloud, - "AZURECLOUD": PublicCloud, - "AZUREPUBLICCLOUD": PublicCloud, - "AZUREUSGOVERNMENT": USGovernmentCloud, - "AZUREUSGOVERNMENTCLOUD": USGovernmentCloud, //TODO: deprecate -} - -// ResourceIdentifier contains a set of Azure resource IDs. -type ResourceIdentifier struct { - Graph string `json:"graph"` - KeyVault string `json:"keyVault"` - Datalake string `json:"datalake"` - Batch string `json:"batch"` - OperationalInsights string `json:"operationalInsights"` - OSSRDBMS string `json:"ossRDBMS"` - Storage string `json:"storage"` - Synapse string `json:"synapse"` - ServiceBus string `json:"serviceBus"` - SQLDatabase string `json:"sqlDatabase"` - CosmosDB string `json:"cosmosDB"` - ManagedHSM string `json:"managedHSM"` - MicrosoftGraph string `json:"microsoftGraph"` -} - -// Environment represents a set of endpoints for each of Azure's Clouds. -type Environment struct { - Name string `json:"name"` - ManagementPortalURL string `json:"managementPortalURL"` - PublishSettingsURL string `json:"publishSettingsURL"` - ServiceManagementEndpoint string `json:"serviceManagementEndpoint"` - ResourceManagerEndpoint string `json:"resourceManagerEndpoint"` - ActiveDirectoryEndpoint string `json:"activeDirectoryEndpoint"` - GalleryEndpoint string `json:"galleryEndpoint"` - KeyVaultEndpoint string `json:"keyVaultEndpoint"` - ManagedHSMEndpoint string `json:"managedHSMEndpoint"` - GraphEndpoint string `json:"graphEndpoint"` - ServiceBusEndpoint string `json:"serviceBusEndpoint"` - BatchManagementEndpoint string `json:"batchManagementEndpoint"` - MicrosoftGraphEndpoint string `json:"microsoftGraphEndpoint"` - StorageEndpointSuffix string `json:"storageEndpointSuffix"` - CosmosDBDNSSuffix string `json:"cosmosDBDNSSuffix"` - MariaDBDNSSuffix string `json:"mariaDBDNSSuffix"` - MySQLDatabaseDNSSuffix string `json:"mySqlDatabaseDNSSuffix"` - PostgresqlDatabaseDNSSuffix string `json:"postgresqlDatabaseDNSSuffix"` - SQLDatabaseDNSSuffix string `json:"sqlDatabaseDNSSuffix"` - TrafficManagerDNSSuffix string `json:"trafficManagerDNSSuffix"` - KeyVaultDNSSuffix string `json:"keyVaultDNSSuffix"` - ManagedHSMDNSSuffix string `json:"managedHSMDNSSuffix"` - ServiceBusEndpointSuffix string `json:"serviceBusEndpointSuffix"` - ServiceManagementVMDNSSuffix string `json:"serviceManagementVMDNSSuffix"` - ResourceManagerVMDNSSuffix string `json:"resourceManagerVMDNSSuffix"` - ContainerRegistryDNSSuffix string `json:"containerRegistryDNSSuffix"` - TokenAudience string `json:"tokenAudience"` - APIManagementHostNameSuffix string `json:"apiManagementHostNameSuffix"` - SynapseEndpointSuffix string `json:"synapseEndpointSuffix"` - DatalakeSuffix string `json:"datalakeSuffix"` - ResourceIdentifiers ResourceIdentifier `json:"resourceIdentifiers"` -} - -var ( - // PublicCloud is the default public Azure cloud environment - PublicCloud = Environment{ - Name: "AzurePublicCloud", - ManagementPortalURL: "https://manage.windowsazure.com/", - PublishSettingsURL: "https://manage.windowsazure.com/publishsettings/index", - ServiceManagementEndpoint: "https://management.core.windows.net/", - ResourceManagerEndpoint: "https://management.azure.com/", - ActiveDirectoryEndpoint: "https://login.microsoftonline.com/", - GalleryEndpoint: "https://gallery.azure.com/", - KeyVaultEndpoint: "https://vault.azure.net/", - ManagedHSMEndpoint: "https://managedhsm.azure.net/", - GraphEndpoint: "https://graph.windows.net/", - ServiceBusEndpoint: "https://servicebus.windows.net/", - BatchManagementEndpoint: "https://batch.core.windows.net/", - MicrosoftGraphEndpoint: "https://graph.microsoft.com/", - StorageEndpointSuffix: "core.windows.net", - CosmosDBDNSSuffix: "documents.azure.com", - MariaDBDNSSuffix: "mariadb.database.azure.com", - MySQLDatabaseDNSSuffix: "mysql.database.azure.com", - PostgresqlDatabaseDNSSuffix: "postgres.database.azure.com", - SQLDatabaseDNSSuffix: "database.windows.net", - TrafficManagerDNSSuffix: "trafficmanager.net", - KeyVaultDNSSuffix: "vault.azure.net", - ManagedHSMDNSSuffix: "managedhsm.azure.net", - ServiceBusEndpointSuffix: "servicebus.windows.net", - ServiceManagementVMDNSSuffix: "cloudapp.net", - ResourceManagerVMDNSSuffix: "cloudapp.azure.com", - ContainerRegistryDNSSuffix: "azurecr.io", - TokenAudience: "https://management.azure.com/", - APIManagementHostNameSuffix: "azure-api.net", - SynapseEndpointSuffix: "dev.azuresynapse.net", - DatalakeSuffix: "azuredatalakestore.net", - ResourceIdentifiers: ResourceIdentifier{ - Graph: "https://graph.windows.net/", - KeyVault: "https://vault.azure.net", - Datalake: "https://datalake.azure.net/", - Batch: "https://batch.core.windows.net/", - OperationalInsights: "https://api.loganalytics.io", - OSSRDBMS: "https://ossrdbms-aad.database.windows.net", - Storage: "https://storage.azure.com/", - Synapse: "https://dev.azuresynapse.net", - ServiceBus: "https://servicebus.azure.net/", - SQLDatabase: "https://database.windows.net/", - CosmosDB: "https://cosmos.azure.com", - ManagedHSM: "https://managedhsm.azure.net", - MicrosoftGraph: "https://graph.microsoft.com/", - }, - } - - // USGovernmentCloud is the cloud environment for the US Government - USGovernmentCloud = Environment{ - Name: "AzureUSGovernmentCloud", - ManagementPortalURL: "https://manage.windowsazure.us/", - PublishSettingsURL: "https://manage.windowsazure.us/publishsettings/index", - ServiceManagementEndpoint: "https://management.core.usgovcloudapi.net/", - ResourceManagerEndpoint: "https://management.usgovcloudapi.net/", - ActiveDirectoryEndpoint: "https://login.microsoftonline.us/", - GalleryEndpoint: "https://gallery.usgovcloudapi.net/", - KeyVaultEndpoint: "https://vault.usgovcloudapi.net/", - ManagedHSMEndpoint: NotAvailable, - GraphEndpoint: "https://graph.windows.net/", - ServiceBusEndpoint: "https://servicebus.usgovcloudapi.net/", - BatchManagementEndpoint: "https://batch.core.usgovcloudapi.net/", - MicrosoftGraphEndpoint: "https://graph.microsoft.us/", - StorageEndpointSuffix: "core.usgovcloudapi.net", - CosmosDBDNSSuffix: "documents.azure.us", - MariaDBDNSSuffix: "mariadb.database.usgovcloudapi.net", - MySQLDatabaseDNSSuffix: "mysql.database.usgovcloudapi.net", - PostgresqlDatabaseDNSSuffix: "postgres.database.usgovcloudapi.net", - SQLDatabaseDNSSuffix: "database.usgovcloudapi.net", - TrafficManagerDNSSuffix: "usgovtrafficmanager.net", - KeyVaultDNSSuffix: "vault.usgovcloudapi.net", - ManagedHSMDNSSuffix: NotAvailable, - ServiceBusEndpointSuffix: "servicebus.usgovcloudapi.net", - ServiceManagementVMDNSSuffix: "usgovcloudapp.net", - ResourceManagerVMDNSSuffix: "cloudapp.usgovcloudapi.net", - ContainerRegistryDNSSuffix: "azurecr.us", - TokenAudience: "https://management.usgovcloudapi.net/", - APIManagementHostNameSuffix: "azure-api.us", - SynapseEndpointSuffix: "dev.azuresynapse.usgovcloudapi.net", - DatalakeSuffix: NotAvailable, - ResourceIdentifiers: ResourceIdentifier{ - Graph: "https://graph.windows.net/", - KeyVault: "https://vault.usgovcloudapi.net", - Datalake: NotAvailable, - Batch: "https://batch.core.usgovcloudapi.net/", - OperationalInsights: "https://api.loganalytics.us", - OSSRDBMS: "https://ossrdbms-aad.database.usgovcloudapi.net", - Storage: "https://storage.azure.com/", - Synapse: "https://dev.azuresynapse.usgovcloudapi.net", - ServiceBus: "https://servicebus.azure.net/", - SQLDatabase: "https://database.usgovcloudapi.net/", - CosmosDB: "https://cosmos.azure.com", - ManagedHSM: NotAvailable, - MicrosoftGraph: "https://graph.microsoft.us/", - }, - } - - // ChinaCloud is the cloud environment operated in China - ChinaCloud = Environment{ - Name: "AzureChinaCloud", - ManagementPortalURL: "https://manage.chinacloudapi.com/", - PublishSettingsURL: "https://manage.chinacloudapi.com/publishsettings/index", - ServiceManagementEndpoint: "https://management.core.chinacloudapi.cn/", - ResourceManagerEndpoint: "https://management.chinacloudapi.cn/", - ActiveDirectoryEndpoint: "https://login.chinacloudapi.cn/", - GalleryEndpoint: "https://gallery.chinacloudapi.cn/", - KeyVaultEndpoint: "https://vault.azure.cn/", - ManagedHSMEndpoint: NotAvailable, - GraphEndpoint: "https://graph.chinacloudapi.cn/", - ServiceBusEndpoint: "https://servicebus.chinacloudapi.cn/", - BatchManagementEndpoint: "https://batch.chinacloudapi.cn/", - MicrosoftGraphEndpoint: "https://microsoftgraph.chinacloudapi.cn/", - StorageEndpointSuffix: "core.chinacloudapi.cn", - CosmosDBDNSSuffix: "documents.azure.cn", - MariaDBDNSSuffix: "mariadb.database.chinacloudapi.cn", - MySQLDatabaseDNSSuffix: "mysql.database.chinacloudapi.cn", - PostgresqlDatabaseDNSSuffix: "postgres.database.chinacloudapi.cn", - SQLDatabaseDNSSuffix: "database.chinacloudapi.cn", - TrafficManagerDNSSuffix: "trafficmanager.cn", - KeyVaultDNSSuffix: "vault.azure.cn", - ManagedHSMDNSSuffix: NotAvailable, - ServiceBusEndpointSuffix: "servicebus.chinacloudapi.cn", - ServiceManagementVMDNSSuffix: "chinacloudapp.cn", - ResourceManagerVMDNSSuffix: "cloudapp.chinacloudapi.cn", - ContainerRegistryDNSSuffix: "azurecr.cn", - TokenAudience: "https://management.chinacloudapi.cn/", - APIManagementHostNameSuffix: "azure-api.cn", - SynapseEndpointSuffix: "dev.azuresynapse.azure.cn", - DatalakeSuffix: NotAvailable, - ResourceIdentifiers: ResourceIdentifier{ - Graph: "https://graph.chinacloudapi.cn/", - KeyVault: "https://vault.azure.cn", - Datalake: NotAvailable, - Batch: "https://batch.chinacloudapi.cn/", - OperationalInsights: NotAvailable, - OSSRDBMS: "https://ossrdbms-aad.database.chinacloudapi.cn", - Storage: "https://storage.azure.com/", - Synapse: "https://dev.azuresynapse.net", - ServiceBus: "https://servicebus.azure.net/", - SQLDatabase: "https://database.chinacloudapi.cn/", - CosmosDB: "https://cosmos.azure.com", - ManagedHSM: NotAvailable, - MicrosoftGraph: "https://microsoftgraph.chinacloudapi.cn", - }, - } - - // GermanCloud is the cloud environment operated in Germany - GermanCloud = Environment{ - Name: "AzureGermanCloud", - ManagementPortalURL: "http://portal.microsoftazure.de/", - PublishSettingsURL: "https://manage.microsoftazure.de/publishsettings/index", - ServiceManagementEndpoint: "https://management.core.cloudapi.de/", - ResourceManagerEndpoint: "https://management.microsoftazure.de/", - ActiveDirectoryEndpoint: "https://login.microsoftonline.de/", - GalleryEndpoint: "https://gallery.cloudapi.de/", - KeyVaultEndpoint: "https://vault.microsoftazure.de/", - ManagedHSMEndpoint: NotAvailable, - GraphEndpoint: "https://graph.cloudapi.de/", - ServiceBusEndpoint: "https://servicebus.cloudapi.de/", - BatchManagementEndpoint: "https://batch.cloudapi.de/", - MicrosoftGraphEndpoint: NotAvailable, - StorageEndpointSuffix: "core.cloudapi.de", - CosmosDBDNSSuffix: "documents.microsoftazure.de", - MariaDBDNSSuffix: "mariadb.database.cloudapi.de", - MySQLDatabaseDNSSuffix: "mysql.database.cloudapi.de", - PostgresqlDatabaseDNSSuffix: "postgres.database.cloudapi.de", - SQLDatabaseDNSSuffix: "database.cloudapi.de", - TrafficManagerDNSSuffix: "azuretrafficmanager.de", - KeyVaultDNSSuffix: "vault.microsoftazure.de", - ManagedHSMDNSSuffix: NotAvailable, - ServiceBusEndpointSuffix: "servicebus.cloudapi.de", - ServiceManagementVMDNSSuffix: "azurecloudapp.de", - ResourceManagerVMDNSSuffix: "cloudapp.microsoftazure.de", - ContainerRegistryDNSSuffix: NotAvailable, - TokenAudience: "https://management.microsoftazure.de/", - APIManagementHostNameSuffix: NotAvailable, - SynapseEndpointSuffix: NotAvailable, - DatalakeSuffix: NotAvailable, - ResourceIdentifiers: ResourceIdentifier{ - Graph: "https://graph.cloudapi.de/", - KeyVault: "https://vault.microsoftazure.de", - Datalake: NotAvailable, - Batch: "https://batch.cloudapi.de/", - OperationalInsights: NotAvailable, - OSSRDBMS: "https://ossrdbms-aad.database.cloudapi.de", - Storage: "https://storage.azure.com/", - Synapse: NotAvailable, - ServiceBus: "https://servicebus.azure.net/", - SQLDatabase: "https://database.cloudapi.de/", - CosmosDB: "https://cosmos.azure.com", - ManagedHSM: NotAvailable, - MicrosoftGraph: NotAvailable, - }, - } -) - -// EnvironmentFromName returns an Environment based on the common name specified. -func EnvironmentFromName(name string) (Environment, error) { - // IMPORTANT - // As per @radhikagupta5: - // This is technical debt, fundamentally here because Kubernetes is not currently accepting - // contributions to the providers. Once that is an option, the provider should be updated to - // directly call `EnvironmentFromFile`. Until then, we rely on dispatching Azure Stack environment creation - // from this method based on the name that is provided to us. - if strings.EqualFold(name, "AZURESTACKCLOUD") { - return EnvironmentFromFile(os.Getenv(EnvironmentFilepathName)) - } - - name = strings.ToUpper(name) - env, ok := environments[name] - if !ok { - return env, fmt.Errorf("autorest/azure: There is no cloud environment matching the name %q", name) - } - - return env, nil -} - -// EnvironmentFromFile loads an Environment from a configuration file available on disk. -// This function is particularly useful in the Hybrid Cloud model, where one must define their own -// endpoints. -func EnvironmentFromFile(location string) (unmarshaled Environment, err error) { - fileContents, err := ioutil.ReadFile(location) - if err != nil { - return - } - - err = json.Unmarshal(fileContents, &unmarshaled) - - return -} - -// SetEnvironment updates the environment map with the specified values. -func SetEnvironment(name string, env Environment) { - environments[strings.ToUpper(name)] = env -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/metadata_environment.go b/vendor/github.com/Azure/go-autorest/autorest/azure/metadata_environment.go deleted file mode 100644 index 507f9e95cf..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/azure/metadata_environment.go +++ /dev/null @@ -1,245 +0,0 @@ -package azure - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "strings" - - "github.com/Azure/go-autorest/autorest" -) - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -type audience []string - -type authentication struct { - LoginEndpoint string `json:"loginEndpoint"` - Audiences audience `json:"audiences"` -} - -type environmentMetadataInfo struct { - GalleryEndpoint string `json:"galleryEndpoint"` - GraphEndpoint string `json:"graphEndpoint"` - PortalEndpoint string `json:"portalEndpoint"` - Authentication authentication `json:"authentication"` -} - -// EnvironmentProperty represent property names that clients can override -type EnvironmentProperty string - -const ( - // EnvironmentName ... - EnvironmentName EnvironmentProperty = "name" - // EnvironmentManagementPortalURL .. - EnvironmentManagementPortalURL EnvironmentProperty = "managementPortalURL" - // EnvironmentPublishSettingsURL ... - EnvironmentPublishSettingsURL EnvironmentProperty = "publishSettingsURL" - // EnvironmentServiceManagementEndpoint ... - EnvironmentServiceManagementEndpoint EnvironmentProperty = "serviceManagementEndpoint" - // EnvironmentResourceManagerEndpoint ... - EnvironmentResourceManagerEndpoint EnvironmentProperty = "resourceManagerEndpoint" - // EnvironmentActiveDirectoryEndpoint ... - EnvironmentActiveDirectoryEndpoint EnvironmentProperty = "activeDirectoryEndpoint" - // EnvironmentGalleryEndpoint ... - EnvironmentGalleryEndpoint EnvironmentProperty = "galleryEndpoint" - // EnvironmentKeyVaultEndpoint ... - EnvironmentKeyVaultEndpoint EnvironmentProperty = "keyVaultEndpoint" - // EnvironmentGraphEndpoint ... - EnvironmentGraphEndpoint EnvironmentProperty = "graphEndpoint" - // EnvironmentServiceBusEndpoint ... - EnvironmentServiceBusEndpoint EnvironmentProperty = "serviceBusEndpoint" - // EnvironmentBatchManagementEndpoint ... - EnvironmentBatchManagementEndpoint EnvironmentProperty = "batchManagementEndpoint" - // EnvironmentStorageEndpointSuffix ... - EnvironmentStorageEndpointSuffix EnvironmentProperty = "storageEndpointSuffix" - // EnvironmentSQLDatabaseDNSSuffix ... - EnvironmentSQLDatabaseDNSSuffix EnvironmentProperty = "sqlDatabaseDNSSuffix" - // EnvironmentTrafficManagerDNSSuffix ... - EnvironmentTrafficManagerDNSSuffix EnvironmentProperty = "trafficManagerDNSSuffix" - // EnvironmentKeyVaultDNSSuffix ... - EnvironmentKeyVaultDNSSuffix EnvironmentProperty = "keyVaultDNSSuffix" - // EnvironmentServiceBusEndpointSuffix ... - EnvironmentServiceBusEndpointSuffix EnvironmentProperty = "serviceBusEndpointSuffix" - // EnvironmentServiceManagementVMDNSSuffix ... - EnvironmentServiceManagementVMDNSSuffix EnvironmentProperty = "serviceManagementVMDNSSuffix" - // EnvironmentResourceManagerVMDNSSuffix ... - EnvironmentResourceManagerVMDNSSuffix EnvironmentProperty = "resourceManagerVMDNSSuffix" - // EnvironmentContainerRegistryDNSSuffix ... - EnvironmentContainerRegistryDNSSuffix EnvironmentProperty = "containerRegistryDNSSuffix" - // EnvironmentTokenAudience ... - EnvironmentTokenAudience EnvironmentProperty = "tokenAudience" -) - -// OverrideProperty represents property name and value that clients can override -type OverrideProperty struct { - Key EnvironmentProperty - Value string -} - -// EnvironmentFromURL loads an Environment from a URL -// This function is particularly useful in the Hybrid Cloud model, where one may define their own -// endpoints. -func EnvironmentFromURL(resourceManagerEndpoint string, properties ...OverrideProperty) (environment Environment, err error) { - var metadataEnvProperties environmentMetadataInfo - - if resourceManagerEndpoint == "" { - return environment, fmt.Errorf("Metadata resource manager endpoint is empty") - } - - if metadataEnvProperties, err = retrieveMetadataEnvironment(resourceManagerEndpoint); err != nil { - return environment, err - } - - // Give priority to user's override values - overrideProperties(&environment, properties) - - if environment.Name == "" { - environment.Name = "HybridEnvironment" - } - stampDNSSuffix := environment.StorageEndpointSuffix - if stampDNSSuffix == "" { - stampDNSSuffix = strings.TrimSuffix(strings.TrimPrefix(strings.Replace(resourceManagerEndpoint, strings.Split(resourceManagerEndpoint, ".")[0], "", 1), "."), "/") - environment.StorageEndpointSuffix = stampDNSSuffix - } - if environment.KeyVaultDNSSuffix == "" { - environment.KeyVaultDNSSuffix = fmt.Sprintf("%s.%s", "vault", stampDNSSuffix) - } - if environment.KeyVaultEndpoint == "" { - environment.KeyVaultEndpoint = fmt.Sprintf("%s%s", "https://", environment.KeyVaultDNSSuffix) - } - if environment.TokenAudience == "" { - environment.TokenAudience = metadataEnvProperties.Authentication.Audiences[0] - } - if environment.ActiveDirectoryEndpoint == "" { - environment.ActiveDirectoryEndpoint = metadataEnvProperties.Authentication.LoginEndpoint - } - if environment.ResourceManagerEndpoint == "" { - environment.ResourceManagerEndpoint = resourceManagerEndpoint - } - if environment.GalleryEndpoint == "" { - environment.GalleryEndpoint = metadataEnvProperties.GalleryEndpoint - } - if environment.GraphEndpoint == "" { - environment.GraphEndpoint = metadataEnvProperties.GraphEndpoint - } - - return environment, nil -} - -func overrideProperties(environment *Environment, properties []OverrideProperty) { - for _, property := range properties { - switch property.Key { - case EnvironmentName: - { - environment.Name = property.Value - } - case EnvironmentManagementPortalURL: - { - environment.ManagementPortalURL = property.Value - } - case EnvironmentPublishSettingsURL: - { - environment.PublishSettingsURL = property.Value - } - case EnvironmentServiceManagementEndpoint: - { - environment.ServiceManagementEndpoint = property.Value - } - case EnvironmentResourceManagerEndpoint: - { - environment.ResourceManagerEndpoint = property.Value - } - case EnvironmentActiveDirectoryEndpoint: - { - environment.ActiveDirectoryEndpoint = property.Value - } - case EnvironmentGalleryEndpoint: - { - environment.GalleryEndpoint = property.Value - } - case EnvironmentKeyVaultEndpoint: - { - environment.KeyVaultEndpoint = property.Value - } - case EnvironmentGraphEndpoint: - { - environment.GraphEndpoint = property.Value - } - case EnvironmentServiceBusEndpoint: - { - environment.ServiceBusEndpoint = property.Value - } - case EnvironmentBatchManagementEndpoint: - { - environment.BatchManagementEndpoint = property.Value - } - case EnvironmentStorageEndpointSuffix: - { - environment.StorageEndpointSuffix = property.Value - } - case EnvironmentSQLDatabaseDNSSuffix: - { - environment.SQLDatabaseDNSSuffix = property.Value - } - case EnvironmentTrafficManagerDNSSuffix: - { - environment.TrafficManagerDNSSuffix = property.Value - } - case EnvironmentKeyVaultDNSSuffix: - { - environment.KeyVaultDNSSuffix = property.Value - } - case EnvironmentServiceBusEndpointSuffix: - { - environment.ServiceBusEndpointSuffix = property.Value - } - case EnvironmentServiceManagementVMDNSSuffix: - { - environment.ServiceManagementVMDNSSuffix = property.Value - } - case EnvironmentResourceManagerVMDNSSuffix: - { - environment.ResourceManagerVMDNSSuffix = property.Value - } - case EnvironmentContainerRegistryDNSSuffix: - { - environment.ContainerRegistryDNSSuffix = property.Value - } - case EnvironmentTokenAudience: - { - environment.TokenAudience = property.Value - } - } - } -} - -func retrieveMetadataEnvironment(endpoint string) (environment environmentMetadataInfo, err error) { - client := autorest.NewClientWithUserAgent("") - managementEndpoint := fmt.Sprintf("%s%s", strings.TrimSuffix(endpoint, "/"), "/metadata/endpoints?api-version=1.0") - req, _ := http.NewRequest("GET", managementEndpoint, nil) - response, err := client.Do(req) - if err != nil { - return environment, err - } - defer response.Body.Close() - jsonResponse, err := ioutil.ReadAll(response.Body) - if err != nil { - return environment, err - } - err = json.Unmarshal(jsonResponse, &environment) - return environment, err -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/rp.go b/vendor/github.com/Azure/go-autorest/autorest/azure/rp.go deleted file mode 100644 index 5b52357f95..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/azure/rp.go +++ /dev/null @@ -1,204 +0,0 @@ -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package azure - -import ( - "errors" - "fmt" - "net/http" - "net/url" - "strings" - "time" - - "github.com/Azure/go-autorest/autorest" -) - -// DoRetryWithRegistration tries to register the resource provider in case it is unregistered. -// It also handles request retries -func DoRetryWithRegistration(client autorest.Client) autorest.SendDecorator { - return func(s autorest.Sender) autorest.Sender { - return autorest.SenderFunc(func(r *http.Request) (resp *http.Response, err error) { - rr := autorest.NewRetriableRequest(r) - for currentAttempt := 0; currentAttempt < client.RetryAttempts; currentAttempt++ { - err = rr.Prepare() - if err != nil { - return resp, err - } - - resp, err = autorest.SendWithSender(s, rr.Request(), - autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...), - ) - if err != nil { - return resp, err - } - - if resp.StatusCode != http.StatusConflict || client.SkipResourceProviderRegistration { - return resp, err - } - - var re RequestError - if strings.Contains(r.Header.Get("Content-Type"), "xml") { - // XML errors (e.g. Storage Data Plane) only return the inner object - err = autorest.Respond(resp, autorest.ByUnmarshallingXML(&re.ServiceError)) - } else { - err = autorest.Respond(resp, autorest.ByUnmarshallingJSON(&re)) - } - - if err != nil { - return resp, err - } - err = re - - if re.ServiceError != nil && re.ServiceError.Code == "MissingSubscriptionRegistration" { - regErr := register(client, r, re) - if regErr != nil { - return resp, fmt.Errorf("failed auto registering Resource Provider: %s. Original error: %w", regErr, err) - } - } - } - return resp, err - }) - } -} - -func getProvider(re RequestError) (string, error) { - if re.ServiceError != nil && len(re.ServiceError.Details) > 0 { - return re.ServiceError.Details[0]["target"].(string), nil - } - return "", errors.New("provider was not found in the response") -} - -func register(client autorest.Client, originalReq *http.Request, re RequestError) error { - subID := getSubscription(originalReq.URL.Path) - if subID == "" { - return errors.New("missing parameter subscriptionID to register resource provider") - } - providerName, err := getProvider(re) - if err != nil { - return fmt.Errorf("missing parameter provider to register resource provider: %s", err) - } - newURL := url.URL{ - Scheme: originalReq.URL.Scheme, - Host: originalReq.URL.Host, - } - - // taken from the resources SDK - // with almost identical code, this sections are easier to mantain - // It is also not a good idea to import the SDK here - // https://github.com/Azure/azure-sdk-for-go/blob/9f366792afa3e0ddaecdc860e793ba9d75e76c27/arm/resources/resources/providers.go#L252 - pathParameters := map[string]interface{}{ - "resourceProviderNamespace": autorest.Encode("path", providerName), - "subscriptionId": autorest.Encode("path", subID), - } - - const APIVersion = "2016-09-01" - queryParameters := map[string]interface{}{ - "api-version": APIVersion, - } - - preparer := autorest.CreatePreparer( - autorest.AsPost(), - autorest.WithBaseURL(newURL.String()), - autorest.WithPathParameters("/subscriptions/{subscriptionId}/providers/{resourceProviderNamespace}/register", pathParameters), - autorest.WithQueryParameters(queryParameters), - ) - - req, err := preparer.Prepare(&http.Request{}) - if err != nil { - return err - } - req = req.WithContext(originalReq.Context()) - - resp, err := autorest.SendWithSender(client, req, - autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...), - ) - if err != nil { - return err - } - - type Provider struct { - RegistrationState *string `json:"registrationState,omitempty"` - } - var provider Provider - - err = autorest.Respond( - resp, - WithErrorUnlessStatusCode(http.StatusOK), - autorest.ByUnmarshallingJSON(&provider), - autorest.ByClosing(), - ) - if err != nil { - return err - } - - // poll for registered provisioning state - registrationStartTime := time.Now() - for err == nil && (client.PollingDuration == 0 || (client.PollingDuration != 0 && time.Since(registrationStartTime) < client.PollingDuration)) { - // taken from the resources SDK - // https://github.com/Azure/azure-sdk-for-go/blob/9f366792afa3e0ddaecdc860e793ba9d75e76c27/arm/resources/resources/providers.go#L45 - preparer := autorest.CreatePreparer( - autorest.AsGet(), - autorest.WithBaseURL(newURL.String()), - autorest.WithPathParameters("/subscriptions/{subscriptionId}/providers/{resourceProviderNamespace}", pathParameters), - autorest.WithQueryParameters(queryParameters), - ) - req, err = preparer.Prepare(&http.Request{}) - if err != nil { - return err - } - req = req.WithContext(originalReq.Context()) - - resp, err := autorest.SendWithSender(client, req, - autorest.DoRetryForStatusCodes(client.RetryAttempts, client.RetryDuration, autorest.StatusCodesForRetry...), - ) - if err != nil { - return err - } - - err = autorest.Respond( - resp, - WithErrorUnlessStatusCode(http.StatusOK), - autorest.ByUnmarshallingJSON(&provider), - autorest.ByClosing(), - ) - if err != nil { - return err - } - - if provider.RegistrationState != nil && - *provider.RegistrationState == "Registered" { - break - } - - delayed := autorest.DelayWithRetryAfter(resp, originalReq.Context().Done()) - if !delayed && !autorest.DelayForBackoff(client.PollingDelay, 0, originalReq.Context().Done()) { - return originalReq.Context().Err() - } - } - if client.PollingDuration != 0 && !(time.Since(registrationStartTime) < client.PollingDuration) { - return errors.New("polling for resource provider registration has exceeded the polling duration") - } - return err -} - -func getSubscription(path string) string { - parts := strings.Split(path, "/") - for i, v := range parts { - if v == "subscriptions" && (i+1) < len(parts) { - return parts[i+1] - } - } - return "" -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/client.go b/vendor/github.com/Azure/go-autorest/autorest/client.go deleted file mode 100644 index bb5f9396e9..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/client.go +++ /dev/null @@ -1,328 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "bytes" - "crypto/tls" - "errors" - "fmt" - "io" - "io/ioutil" - "log" - "net/http" - "strings" - "time" - - "github.com/Azure/go-autorest/logger" -) - -const ( - // DefaultPollingDelay is a reasonable delay between polling requests. - DefaultPollingDelay = 30 * time.Second - - // DefaultPollingDuration is a reasonable total polling duration. - DefaultPollingDuration = 15 * time.Minute - - // DefaultRetryAttempts is number of attempts for retry status codes (5xx). - DefaultRetryAttempts = 3 - - // DefaultRetryDuration is the duration to wait between retries. - DefaultRetryDuration = 30 * time.Second -) - -var ( - // StatusCodesForRetry are a defined group of status code for which the client will retry - StatusCodesForRetry = []int{ - http.StatusRequestTimeout, // 408 - http.StatusTooManyRequests, // 429 - http.StatusInternalServerError, // 500 - http.StatusBadGateway, // 502 - http.StatusServiceUnavailable, // 503 - http.StatusGatewayTimeout, // 504 - } -) - -const ( - requestFormat = `HTTP Request Begin =================================================== -%s -===================================================== HTTP Request End -` - responseFormat = `HTTP Response Begin =================================================== -%s -===================================================== HTTP Response End -` -) - -// Response serves as the base for all responses from generated clients. It provides access to the -// last http.Response. -type Response struct { - *http.Response `json:"-"` -} - -// IsHTTPStatus returns true if the returned HTTP status code matches the provided status code. -// If there was no response (i.e. the underlying http.Response is nil) the return value is false. -func (r Response) IsHTTPStatus(statusCode int) bool { - if r.Response == nil { - return false - } - return r.Response.StatusCode == statusCode -} - -// HasHTTPStatus returns true if the returned HTTP status code matches one of the provided status codes. -// If there was no response (i.e. the underlying http.Response is nil) or not status codes are provided -// the return value is false. -func (r Response) HasHTTPStatus(statusCodes ...int) bool { - return ResponseHasStatusCode(r.Response, statusCodes...) -} - -// LoggingInspector implements request and response inspectors that log the full request and -// response to a supplied log. -type LoggingInspector struct { - Logger *log.Logger -} - -// WithInspection returns a PrepareDecorator that emits the http.Request to the supplied logger. The -// body is restored after being emitted. -// -// Note: Since it reads the entire Body, this decorator should not be used where body streaming is -// important. It is best used to trace JSON or similar body values. -func (li LoggingInspector) WithInspection() PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - var body, b bytes.Buffer - - defer r.Body.Close() - - r.Body = ioutil.NopCloser(io.TeeReader(r.Body, &body)) - if err := r.Write(&b); err != nil { - return nil, fmt.Errorf("Failed to write response: %v", err) - } - - li.Logger.Printf(requestFormat, b.String()) - - r.Body = ioutil.NopCloser(&body) - return p.Prepare(r) - }) - } -} - -// ByInspecting returns a RespondDecorator that emits the http.Response to the supplied logger. The -// body is restored after being emitted. -// -// Note: Since it reads the entire Body, this decorator should not be used where body streaming is -// important. It is best used to trace JSON or similar body values. -func (li LoggingInspector) ByInspecting() RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - var body, b bytes.Buffer - defer resp.Body.Close() - resp.Body = ioutil.NopCloser(io.TeeReader(resp.Body, &body)) - if err := resp.Write(&b); err != nil { - return fmt.Errorf("Failed to write response: %v", err) - } - - li.Logger.Printf(responseFormat, b.String()) - - resp.Body = ioutil.NopCloser(&body) - return r.Respond(resp) - }) - } -} - -// Client is the base for autorest generated clients. It provides default, "do nothing" -// implementations of an Authorizer, RequestInspector, and ResponseInspector. It also returns the -// standard, undecorated http.Client as a default Sender. -// -// Generated clients should also use Error (see NewError and NewErrorWithError) for errors and -// return responses that compose with Response. -// -// Most customization of generated clients is best achieved by supplying a custom Authorizer, custom -// RequestInspector, and / or custom ResponseInspector. Users may log requests, implement circuit -// breakers (see https://msdn.microsoft.com/en-us/library/dn589784.aspx) or otherwise influence -// sending the request by providing a decorated Sender. -type Client struct { - Authorizer Authorizer - Sender Sender - RequestInspector PrepareDecorator - ResponseInspector RespondDecorator - - // PollingDelay sets the polling frequency used in absence of a Retry-After HTTP header - PollingDelay time.Duration - - // PollingDuration sets the maximum polling time after which an error is returned. - // Setting this to zero will use the provided context to control the duration. - PollingDuration time.Duration - - // RetryAttempts sets the total number of times the client will attempt to make an HTTP request. - // Set the value to 1 to disable retries. DO NOT set the value to less than 1. - RetryAttempts int - - // RetryDuration sets the delay duration for retries. - RetryDuration time.Duration - - // UserAgent, if not empty, will be set as the HTTP User-Agent header on all requests sent - // through the Do method. - UserAgent string - - Jar http.CookieJar - - // Set to true to skip attempted registration of resource providers (false by default). - SkipResourceProviderRegistration bool - - // SendDecorators can be used to override the default chain of SendDecorators. - // This can be used to specify things like a custom retry SendDecorator. - // Set this to an empty slice to use no SendDecorators. - SendDecorators []SendDecorator -} - -// NewClientWithUserAgent returns an instance of a Client with the UserAgent set to the passed -// string. -func NewClientWithUserAgent(ua string) Client { - return newClient(ua, tls.RenegotiateNever) -} - -// ClientOptions contains various Client configuration options. -type ClientOptions struct { - // UserAgent is an optional user-agent string to append to the default user agent. - UserAgent string - - // Renegotiation is an optional setting to control client-side TLS renegotiation. - Renegotiation tls.RenegotiationSupport -} - -// NewClientWithOptions returns an instance of a Client with the specified values. -func NewClientWithOptions(options ClientOptions) Client { - return newClient(options.UserAgent, options.Renegotiation) -} - -func newClient(ua string, renegotiation tls.RenegotiationSupport) Client { - c := Client{ - PollingDelay: DefaultPollingDelay, - PollingDuration: DefaultPollingDuration, - RetryAttempts: DefaultRetryAttempts, - RetryDuration: DefaultRetryDuration, - UserAgent: UserAgent(), - } - c.Sender = c.sender(renegotiation) - c.AddToUserAgent(ua) - return c -} - -// AddToUserAgent adds an extension to the current user agent -func (c *Client) AddToUserAgent(extension string) error { - if extension != "" { - c.UserAgent = fmt.Sprintf("%s %s", c.UserAgent, extension) - return nil - } - return fmt.Errorf("Extension was empty, User Agent stayed as %s", c.UserAgent) -} - -// Do implements the Sender interface by invoking the active Sender after applying authorization. -// If Sender is not set, it uses a new instance of http.Client. In both cases it will, if UserAgent -// is set, apply set the User-Agent header. -func (c Client) Do(r *http.Request) (*http.Response, error) { - if r.UserAgent() == "" { - r, _ = Prepare(r, - WithUserAgent(c.UserAgent)) - } - // NOTE: c.WithInspection() must be last in the list so that it can inspect all preceding operations - r, err := Prepare(r, - c.WithAuthorization(), - c.WithInspection()) - if err != nil { - var resp *http.Response - if detErr, ok := err.(DetailedError); ok { - // if the authorization failed (e.g. invalid credentials) there will - // be a response associated with the error, be sure to return it. - resp = detErr.Response - } - return resp, NewErrorWithError(err, "autorest/Client", "Do", nil, "Preparing request failed") - } - logger.Instance.WriteRequest(r, logger.Filter{ - Header: func(k string, v []string) (bool, []string) { - // remove the auth token from the log - if strings.EqualFold(k, "Authorization") || strings.EqualFold(k, "Ocp-Apim-Subscription-Key") { - v = []string{"**REDACTED**"} - } - return true, v - }, - }) - resp, err := SendWithSender(c.sender(tls.RenegotiateNever), r) - if resp == nil && err == nil { - err = errors.New("autorest: received nil response and error") - } - logger.Instance.WriteResponse(resp, logger.Filter{}) - Respond(resp, c.ByInspecting()) - return resp, err -} - -// sender returns the Sender to which to send requests. -func (c Client) sender(renengotiation tls.RenegotiationSupport) Sender { - if c.Sender == nil { - return sender(renengotiation) - } - return c.Sender -} - -// WithAuthorization is a convenience method that returns the WithAuthorization PrepareDecorator -// from the current Authorizer. If not Authorizer is set, it uses the NullAuthorizer. -func (c Client) WithAuthorization() PrepareDecorator { - return c.authorizer().WithAuthorization() -} - -// authorizer returns the Authorizer to use. -func (c Client) authorizer() Authorizer { - if c.Authorizer == nil { - return NullAuthorizer{} - } - return c.Authorizer -} - -// WithInspection is a convenience method that passes the request to the supplied RequestInspector, -// if present, or returns the WithNothing PrepareDecorator otherwise. -func (c Client) WithInspection() PrepareDecorator { - if c.RequestInspector == nil { - return WithNothing() - } - return c.RequestInspector -} - -// ByInspecting is a convenience method that passes the response to the supplied ResponseInspector, -// if present, or returns the ByIgnoring RespondDecorator otherwise. -func (c Client) ByInspecting() RespondDecorator { - if c.ResponseInspector == nil { - return ByIgnoring() - } - return c.ResponseInspector -} - -// Send sends the provided http.Request using the client's Sender or the default sender. -// It returns the http.Response and possible error. It also accepts a, possibly empty, -// default set of SendDecorators used when sending the request. -// SendDecorators have the following precedence: -// 1. In a request's context via WithSendDecorators() -// 2. Specified on the client in SendDecorators -// 3. The default values specified in this method -func (c Client) Send(req *http.Request, decorators ...SendDecorator) (*http.Response, error) { - if c.SendDecorators != nil { - decorators = c.SendDecorators - } - inCtx := req.Context().Value(ctxSendDecorators{}) - if sd, ok := inCtx.([]SendDecorator); ok { - decorators = sd - } - return SendWithSender(c, req, decorators...) -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/date/LICENSE b/vendor/github.com/Azure/go-autorest/autorest/date/LICENSE deleted file mode 100644 index b9d6a27ea9..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/date/LICENSE +++ /dev/null @@ -1,191 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - Copyright 2015 Microsoft Corporation - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/Azure/go-autorest/autorest/date/date.go b/vendor/github.com/Azure/go-autorest/autorest/date/date.go deleted file mode 100644 index c457106568..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/date/date.go +++ /dev/null @@ -1,96 +0,0 @@ -/* -Package date provides time.Time derivatives that conform to the Swagger.io (https://swagger.io/) -defined date formats: Date and DateTime. Both types may, in most cases, be used in lieu of -time.Time types. And both convert to time.Time through a ToTime method. -*/ -package date - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "fmt" - "time" -) - -const ( - fullDate = "2006-01-02" - fullDateJSON = `"2006-01-02"` - dateFormat = "%04d-%02d-%02d" - jsonFormat = `"%04d-%02d-%02d"` -) - -// Date defines a type similar to time.Time but assumes a layout of RFC3339 full-date (i.e., -// 2006-01-02). -type Date struct { - time.Time -} - -// ParseDate create a new Date from the passed string. -func ParseDate(date string) (d Date, err error) { - return parseDate(date, fullDate) -} - -func parseDate(date string, format string) (Date, error) { - d, err := time.Parse(format, date) - return Date{Time: d}, err -} - -// MarshalBinary preserves the Date as a byte array conforming to RFC3339 full-date (i.e., -// 2006-01-02). -func (d Date) MarshalBinary() ([]byte, error) { - return d.MarshalText() -} - -// UnmarshalBinary reconstitutes a Date saved as a byte array conforming to RFC3339 full-date (i.e., -// 2006-01-02). -func (d *Date) UnmarshalBinary(data []byte) error { - return d.UnmarshalText(data) -} - -// MarshalJSON preserves the Date as a JSON string conforming to RFC3339 full-date (i.e., -// 2006-01-02). -func (d Date) MarshalJSON() (json []byte, err error) { - return []byte(fmt.Sprintf(jsonFormat, d.Year(), d.Month(), d.Day())), nil -} - -// UnmarshalJSON reconstitutes the Date from a JSON string conforming to RFC3339 full-date (i.e., -// 2006-01-02). -func (d *Date) UnmarshalJSON(data []byte) (err error) { - d.Time, err = time.Parse(fullDateJSON, string(data)) - return err -} - -// MarshalText preserves the Date as a byte array conforming to RFC3339 full-date (i.e., -// 2006-01-02). -func (d Date) MarshalText() (text []byte, err error) { - return []byte(fmt.Sprintf(dateFormat, d.Year(), d.Month(), d.Day())), nil -} - -// UnmarshalText reconstitutes a Date saved as a byte array conforming to RFC3339 full-date (i.e., -// 2006-01-02). -func (d *Date) UnmarshalText(data []byte) (err error) { - d.Time, err = time.Parse(fullDate, string(data)) - return err -} - -// String returns the Date formatted as an RFC3339 full-date string (i.e., 2006-01-02). -func (d Date) String() string { - return fmt.Sprintf(dateFormat, d.Year(), d.Month(), d.Day()) -} - -// ToTime returns a Date as a time.Time -func (d Date) ToTime() time.Time { - return d.Time -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/date/go_mod_tidy_hack.go b/vendor/github.com/Azure/go-autorest/autorest/date/go_mod_tidy_hack.go deleted file mode 100644 index 4e05432071..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/date/go_mod_tidy_hack.go +++ /dev/null @@ -1,24 +0,0 @@ -// +build modhack - -package date - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// This file, and the github.com/Azure/go-autorest import, won't actually become part of -// the resultant binary. - -// Necessary for safely adding multi-module repo. -// See: https://github.com/golang/go/wiki/Modules#is-it-possible-to-add-a-module-to-a-multi-module-repository -import _ "github.com/Azure/go-autorest" diff --git a/vendor/github.com/Azure/go-autorest/autorest/date/time.go b/vendor/github.com/Azure/go-autorest/autorest/date/time.go deleted file mode 100644 index b453fad049..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/date/time.go +++ /dev/null @@ -1,103 +0,0 @@ -package date - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "regexp" - "time" -) - -// Azure reports time in UTC but it doesn't include the 'Z' time zone suffix in some cases. -const ( - azureUtcFormatJSON = `"2006-01-02T15:04:05.999999999"` - azureUtcFormat = "2006-01-02T15:04:05.999999999" - rfc3339JSON = `"` + time.RFC3339Nano + `"` - rfc3339 = time.RFC3339Nano - tzOffsetRegex = `(Z|z|\+|-)(\d+:\d+)*"*$` -) - -// Time defines a type similar to time.Time but assumes a layout of RFC3339 date-time (i.e., -// 2006-01-02T15:04:05Z). -type Time struct { - time.Time -} - -// MarshalBinary preserves the Time as a byte array conforming to RFC3339 date-time (i.e., -// 2006-01-02T15:04:05Z). -func (t Time) MarshalBinary() ([]byte, error) { - return t.Time.MarshalText() -} - -// UnmarshalBinary reconstitutes a Time saved as a byte array conforming to RFC3339 date-time -// (i.e., 2006-01-02T15:04:05Z). -func (t *Time) UnmarshalBinary(data []byte) error { - return t.UnmarshalText(data) -} - -// MarshalJSON preserves the Time as a JSON string conforming to RFC3339 date-time (i.e., -// 2006-01-02T15:04:05Z). -func (t Time) MarshalJSON() (json []byte, err error) { - return t.Time.MarshalJSON() -} - -// UnmarshalJSON reconstitutes the Time from a JSON string conforming to RFC3339 date-time -// (i.e., 2006-01-02T15:04:05Z). -func (t *Time) UnmarshalJSON(data []byte) (err error) { - timeFormat := azureUtcFormatJSON - match, err := regexp.Match(tzOffsetRegex, data) - if err != nil { - return err - } else if match { - timeFormat = rfc3339JSON - } - t.Time, err = ParseTime(timeFormat, string(data)) - return err -} - -// MarshalText preserves the Time as a byte array conforming to RFC3339 date-time (i.e., -// 2006-01-02T15:04:05Z). -func (t Time) MarshalText() (text []byte, err error) { - return t.Time.MarshalText() -} - -// UnmarshalText reconstitutes a Time saved as a byte array conforming to RFC3339 date-time -// (i.e., 2006-01-02T15:04:05Z). -func (t *Time) UnmarshalText(data []byte) (err error) { - timeFormat := azureUtcFormat - match, err := regexp.Match(tzOffsetRegex, data) - if err != nil { - return err - } else if match { - timeFormat = rfc3339 - } - t.Time, err = ParseTime(timeFormat, string(data)) - return err -} - -// String returns the Time formatted as an RFC3339 date-time string (i.e., -// 2006-01-02T15:04:05Z). -func (t Time) String() string { - // Note: time.Time.String does not return an RFC3339 compliant string, time.Time.MarshalText does. - b, err := t.MarshalText() - if err != nil { - return "" - } - return string(b) -} - -// ToTime returns a Time as a time.Time -func (t Time) ToTime() time.Time { - return t.Time -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/date/timerfc1123.go b/vendor/github.com/Azure/go-autorest/autorest/date/timerfc1123.go deleted file mode 100644 index 48fb39ba9b..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/date/timerfc1123.go +++ /dev/null @@ -1,100 +0,0 @@ -package date - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "errors" - "time" -) - -const ( - rfc1123JSON = `"` + time.RFC1123 + `"` - rfc1123 = time.RFC1123 -) - -// TimeRFC1123 defines a type similar to time.Time but assumes a layout of RFC1123 date-time (i.e., -// Mon, 02 Jan 2006 15:04:05 MST). -type TimeRFC1123 struct { - time.Time -} - -// UnmarshalJSON reconstitutes the Time from a JSON string conforming to RFC1123 date-time -// (i.e., Mon, 02 Jan 2006 15:04:05 MST). -func (t *TimeRFC1123) UnmarshalJSON(data []byte) (err error) { - t.Time, err = ParseTime(rfc1123JSON, string(data)) - if err != nil { - return err - } - return nil -} - -// MarshalJSON preserves the Time as a JSON string conforming to RFC1123 date-time (i.e., -// Mon, 02 Jan 2006 15:04:05 MST). -func (t TimeRFC1123) MarshalJSON() ([]byte, error) { - if y := t.Year(); y < 0 || y >= 10000 { - return nil, errors.New("Time.MarshalJSON: year outside of range [0,9999]") - } - b := []byte(t.Format(rfc1123JSON)) - return b, nil -} - -// MarshalText preserves the Time as a byte array conforming to RFC1123 date-time (i.e., -// Mon, 02 Jan 2006 15:04:05 MST). -func (t TimeRFC1123) MarshalText() ([]byte, error) { - if y := t.Year(); y < 0 || y >= 10000 { - return nil, errors.New("Time.MarshalText: year outside of range [0,9999]") - } - - b := []byte(t.Format(rfc1123)) - return b, nil -} - -// UnmarshalText reconstitutes a Time saved as a byte array conforming to RFC1123 date-time -// (i.e., Mon, 02 Jan 2006 15:04:05 MST). -func (t *TimeRFC1123) UnmarshalText(data []byte) (err error) { - t.Time, err = ParseTime(rfc1123, string(data)) - if err != nil { - return err - } - return nil -} - -// MarshalBinary preserves the Time as a byte array conforming to RFC1123 date-time (i.e., -// Mon, 02 Jan 2006 15:04:05 MST). -func (t TimeRFC1123) MarshalBinary() ([]byte, error) { - return t.MarshalText() -} - -// UnmarshalBinary reconstitutes a Time saved as a byte array conforming to RFC1123 date-time -// (i.e., Mon, 02 Jan 2006 15:04:05 MST). -func (t *TimeRFC1123) UnmarshalBinary(data []byte) error { - return t.UnmarshalText(data) -} - -// ToTime returns a Time as a time.Time -func (t TimeRFC1123) ToTime() time.Time { - return t.Time -} - -// String returns the Time formatted as an RFC1123 date-time string (i.e., -// Mon, 02 Jan 2006 15:04:05 MST). -func (t TimeRFC1123) String() string { - // Note: time.Time.String does not return an RFC1123 compliant string, time.Time.MarshalText does. - b, err := t.MarshalText() - if err != nil { - return "" - } - return string(b) -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/date/unixtime.go b/vendor/github.com/Azure/go-autorest/autorest/date/unixtime.go deleted file mode 100644 index 7073959b2a..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/date/unixtime.go +++ /dev/null @@ -1,123 +0,0 @@ -package date - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "bytes" - "encoding/binary" - "encoding/json" - "time" -) - -// unixEpoch is the moment in time that should be treated as timestamp 0. -var unixEpoch = time.Date(1970, time.January, 1, 0, 0, 0, 0, time.UTC) - -// UnixTime marshals and unmarshals a time that is represented as the number -// of seconds (ignoring skip-seconds) since the Unix Epoch. -type UnixTime time.Time - -// Duration returns the time as a Duration since the UnixEpoch. -func (t UnixTime) Duration() time.Duration { - return time.Time(t).Sub(unixEpoch) -} - -// NewUnixTimeFromSeconds creates a UnixTime as a number of seconds from the UnixEpoch. -func NewUnixTimeFromSeconds(seconds float64) UnixTime { - return NewUnixTimeFromDuration(time.Duration(seconds * float64(time.Second))) -} - -// NewUnixTimeFromNanoseconds creates a UnixTime as a number of nanoseconds from the UnixEpoch. -func NewUnixTimeFromNanoseconds(nanoseconds int64) UnixTime { - return NewUnixTimeFromDuration(time.Duration(nanoseconds)) -} - -// NewUnixTimeFromDuration creates a UnixTime as a duration of time since the UnixEpoch. -func NewUnixTimeFromDuration(dur time.Duration) UnixTime { - return UnixTime(unixEpoch.Add(dur)) -} - -// UnixEpoch retreives the moment considered the Unix Epoch. I.e. The time represented by '0' -func UnixEpoch() time.Time { - return unixEpoch -} - -// MarshalJSON preserves the UnixTime as a JSON number conforming to Unix Timestamp requirements. -// (i.e. the number of seconds since midnight January 1st, 1970 not considering leap seconds.) -func (t UnixTime) MarshalJSON() ([]byte, error) { - buffer := &bytes.Buffer{} - enc := json.NewEncoder(buffer) - err := enc.Encode(float64(time.Time(t).UnixNano()) / 1e9) - if err != nil { - return nil, err - } - return buffer.Bytes(), nil -} - -// UnmarshalJSON reconstitures a UnixTime saved as a JSON number of the number of seconds since -// midnight January 1st, 1970. -func (t *UnixTime) UnmarshalJSON(text []byte) error { - dec := json.NewDecoder(bytes.NewReader(text)) - - var secondsSinceEpoch float64 - if err := dec.Decode(&secondsSinceEpoch); err != nil { - return err - } - - *t = NewUnixTimeFromSeconds(secondsSinceEpoch) - - return nil -} - -// MarshalText stores the number of seconds since the Unix Epoch as a textual floating point number. -func (t UnixTime) MarshalText() ([]byte, error) { - cast := time.Time(t) - return cast.MarshalText() -} - -// UnmarshalText populates a UnixTime with a value stored textually as a floating point number of seconds since the Unix Epoch. -func (t *UnixTime) UnmarshalText(raw []byte) error { - var unmarshaled time.Time - - if err := unmarshaled.UnmarshalText(raw); err != nil { - return err - } - - *t = UnixTime(unmarshaled) - return nil -} - -// MarshalBinary converts a UnixTime into a binary.LittleEndian float64 of nanoseconds since the epoch. -func (t UnixTime) MarshalBinary() ([]byte, error) { - buf := &bytes.Buffer{} - - payload := int64(t.Duration()) - - if err := binary.Write(buf, binary.LittleEndian, &payload); err != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -// UnmarshalBinary converts a from a binary.LittleEndian float64 of nanoseconds since the epoch into a UnixTime. -func (t *UnixTime) UnmarshalBinary(raw []byte) error { - var nanosecondsSinceEpoch int64 - - if err := binary.Read(bytes.NewReader(raw), binary.LittleEndian, &nanosecondsSinceEpoch); err != nil { - return err - } - *t = NewUnixTimeFromNanoseconds(nanosecondsSinceEpoch) - return nil -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/date/utility.go b/vendor/github.com/Azure/go-autorest/autorest/date/utility.go deleted file mode 100644 index 12addf0ebb..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/date/utility.go +++ /dev/null @@ -1,25 +0,0 @@ -package date - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "strings" - "time" -) - -// ParseTime to parse Time string to specified format. -func ParseTime(format string, t string) (d time.Time, err error) { - return time.Parse(format, strings.ToUpper(t)) -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/error.go b/vendor/github.com/Azure/go-autorest/autorest/error.go deleted file mode 100644 index 35098eda8e..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/error.go +++ /dev/null @@ -1,103 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "fmt" - "net/http" -) - -const ( - // UndefinedStatusCode is used when HTTP status code is not available for an error. - UndefinedStatusCode = 0 -) - -// DetailedError encloses a error with details of the package, method, and associated HTTP -// status code (if any). -type DetailedError struct { - Original error - - // PackageType is the package type of the object emitting the error. For types, the value - // matches that produced the the '%T' format specifier of the fmt package. For other elements, - // such as functions, it is just the package name (e.g., "autorest"). - PackageType string - - // Method is the name of the method raising the error. - Method string - - // StatusCode is the HTTP Response StatusCode (if non-zero) that led to the error. - StatusCode interface{} - - // Message is the error message. - Message string - - // Service Error is the response body of failed API in bytes - ServiceError []byte - - // Response is the response object that was returned during failure if applicable. - Response *http.Response -} - -// NewError creates a new Error conforming object from the passed packageType, method, and -// message. message is treated as a format string to which the optional args apply. -func NewError(packageType string, method string, message string, args ...interface{}) DetailedError { - return NewErrorWithError(nil, packageType, method, nil, message, args...) -} - -// NewErrorWithResponse creates a new Error conforming object from the passed -// packageType, method, statusCode of the given resp (UndefinedStatusCode if -// resp is nil), and message. message is treated as a format string to which the -// optional args apply. -func NewErrorWithResponse(packageType string, method string, resp *http.Response, message string, args ...interface{}) DetailedError { - return NewErrorWithError(nil, packageType, method, resp, message, args...) -} - -// NewErrorWithError creates a new Error conforming object from the -// passed packageType, method, statusCode of the given resp (UndefinedStatusCode -// if resp is nil), message, and original error. message is treated as a format -// string to which the optional args apply. -func NewErrorWithError(original error, packageType string, method string, resp *http.Response, message string, args ...interface{}) DetailedError { - if v, ok := original.(DetailedError); ok { - return v - } - - statusCode := UndefinedStatusCode - if resp != nil { - statusCode = resp.StatusCode - } - - return DetailedError{ - Original: original, - PackageType: packageType, - Method: method, - StatusCode: statusCode, - Message: fmt.Sprintf(message, args...), - Response: resp, - } -} - -// Error returns a formatted containing all available details (i.e., PackageType, Method, -// StatusCode, Message, and original error (if any)). -func (e DetailedError) Error() string { - if e.Original == nil { - return fmt.Sprintf("%s#%s: %s: StatusCode=%d", e.PackageType, e.Method, e.Message, e.StatusCode) - } - return fmt.Sprintf("%s#%s: %s: StatusCode=%d -- Original Error: %v", e.PackageType, e.Method, e.Message, e.StatusCode, e.Original) -} - -// Unwrap returns the original error. -func (e DetailedError) Unwrap() error { - return e.Original -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/go_mod_tidy_hack.go b/vendor/github.com/Azure/go-autorest/autorest/go_mod_tidy_hack.go deleted file mode 100644 index 792f82d4b6..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/go_mod_tidy_hack.go +++ /dev/null @@ -1,25 +0,0 @@ -//go:build modhack -// +build modhack - -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// This file, and the github.com/Azure/go-autorest import, won't actually become part of -// the resultant binary. - -// Necessary for safely adding multi-module repo. -// See: https://github.com/golang/go/wiki/Modules#is-it-possible-to-add-a-module-to-a-multi-module-repository -import _ "github.com/Azure/go-autorest" diff --git a/vendor/github.com/Azure/go-autorest/autorest/preparer.go b/vendor/github.com/Azure/go-autorest/autorest/preparer.go deleted file mode 100644 index 121a66fa88..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/preparer.go +++ /dev/null @@ -1,549 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "bytes" - "context" - "encoding/json" - "encoding/xml" - "fmt" - "io" - "io/ioutil" - "mime/multipart" - "net/http" - "net/url" - "strings" -) - -const ( - mimeTypeJSON = "application/json" - mimeTypeOctetStream = "application/octet-stream" - mimeTypeFormPost = "application/x-www-form-urlencoded" - - headerAuthorization = "Authorization" - headerAuxAuthorization = "x-ms-authorization-auxiliary" - headerContentType = "Content-Type" - headerUserAgent = "User-Agent" -) - -// used as a key type in context.WithValue() -type ctxPrepareDecorators struct{} - -// WithPrepareDecorators adds the specified PrepareDecorators to the provided context. -// If no PrepareDecorators are provided the context is unchanged. -func WithPrepareDecorators(ctx context.Context, prepareDecorator []PrepareDecorator) context.Context { - if len(prepareDecorator) == 0 { - return ctx - } - return context.WithValue(ctx, ctxPrepareDecorators{}, prepareDecorator) -} - -// GetPrepareDecorators returns the PrepareDecorators in the provided context or the provided default PrepareDecorators. -func GetPrepareDecorators(ctx context.Context, defaultPrepareDecorators ...PrepareDecorator) []PrepareDecorator { - inCtx := ctx.Value(ctxPrepareDecorators{}) - if pd, ok := inCtx.([]PrepareDecorator); ok { - return pd - } - return defaultPrepareDecorators -} - -// Preparer is the interface that wraps the Prepare method. -// -// Prepare accepts and possibly modifies an http.Request (e.g., adding Headers). Implementations -// must ensure to not share or hold per-invocation state since Preparers may be shared and re-used. -type Preparer interface { - Prepare(*http.Request) (*http.Request, error) -} - -// PreparerFunc is a method that implements the Preparer interface. -type PreparerFunc func(*http.Request) (*http.Request, error) - -// Prepare implements the Preparer interface on PreparerFunc. -func (pf PreparerFunc) Prepare(r *http.Request) (*http.Request, error) { - return pf(r) -} - -// PrepareDecorator takes and possibly decorates, by wrapping, a Preparer. Decorators may affect the -// http.Request and pass it along or, first, pass the http.Request along then affect the result. -type PrepareDecorator func(Preparer) Preparer - -// CreatePreparer creates, decorates, and returns a Preparer. -// Without decorators, the returned Preparer returns the passed http.Request unmodified. -// Preparers are safe to share and re-use. -func CreatePreparer(decorators ...PrepareDecorator) Preparer { - return DecoratePreparer( - Preparer(PreparerFunc(func(r *http.Request) (*http.Request, error) { return r, nil })), - decorators...) -} - -// DecoratePreparer accepts a Preparer and a, possibly empty, set of PrepareDecorators, which it -// applies to the Preparer. Decorators are applied in the order received, but their affect upon the -// request depends on whether they are a pre-decorator (change the http.Request and then pass it -// along) or a post-decorator (pass the http.Request along and alter it on return). -func DecoratePreparer(p Preparer, decorators ...PrepareDecorator) Preparer { - for _, decorate := range decorators { - p = decorate(p) - } - return p -} - -// Prepare accepts an http.Request and a, possibly empty, set of PrepareDecorators. -// It creates a Preparer from the decorators which it then applies to the passed http.Request. -func Prepare(r *http.Request, decorators ...PrepareDecorator) (*http.Request, error) { - if r == nil { - return nil, NewError("autorest", "Prepare", "Invoked without an http.Request") - } - return CreatePreparer(decorators...).Prepare(r) -} - -// WithNothing returns a "do nothing" PrepareDecorator that makes no changes to the passed -// http.Request. -func WithNothing() PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - return p.Prepare(r) - }) - } -} - -// WithHeader returns a PrepareDecorator that sets the specified HTTP header of the http.Request to -// the passed value. It canonicalizes the passed header name (via http.CanonicalHeaderKey) before -// adding the header. -func WithHeader(header string, value string) PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err == nil { - setHeader(r, http.CanonicalHeaderKey(header), value) - } - return r, err - }) - } -} - -// WithHeaders returns a PrepareDecorator that sets the specified HTTP headers of the http.Request to -// the passed value. It canonicalizes the passed headers name (via http.CanonicalHeaderKey) before -// adding them. -func WithHeaders(headers map[string]interface{}) PrepareDecorator { - h := ensureValueStrings(headers) - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err == nil { - if r.Header == nil { - r.Header = make(http.Header) - } - - for name, value := range h { - r.Header.Set(http.CanonicalHeaderKey(name), value) - } - } - return r, err - }) - } -} - -// WithBearerAuthorization returns a PrepareDecorator that adds an HTTP Authorization header whose -// value is "Bearer " followed by the supplied token. -func WithBearerAuthorization(token string) PrepareDecorator { - return WithHeader(headerAuthorization, fmt.Sprintf("Bearer %s", token)) -} - -// AsContentType returns a PrepareDecorator that adds an HTTP Content-Type header whose value -// is the passed contentType. -func AsContentType(contentType string) PrepareDecorator { - return WithHeader(headerContentType, contentType) -} - -// WithUserAgent returns a PrepareDecorator that adds an HTTP User-Agent header whose value is the -// passed string. -func WithUserAgent(ua string) PrepareDecorator { - return WithHeader(headerUserAgent, ua) -} - -// AsFormURLEncoded returns a PrepareDecorator that adds an HTTP Content-Type header whose value is -// "application/x-www-form-urlencoded". -func AsFormURLEncoded() PrepareDecorator { - return AsContentType(mimeTypeFormPost) -} - -// AsJSON returns a PrepareDecorator that adds an HTTP Content-Type header whose value is -// "application/json". -func AsJSON() PrepareDecorator { - return AsContentType(mimeTypeJSON) -} - -// AsOctetStream returns a PrepareDecorator that adds the "application/octet-stream" Content-Type header. -func AsOctetStream() PrepareDecorator { - return AsContentType(mimeTypeOctetStream) -} - -// WithMethod returns a PrepareDecorator that sets the HTTP method of the passed request. The -// decorator does not validate that the passed method string is a known HTTP method. -func WithMethod(method string) PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r.Method = method - return p.Prepare(r) - }) - } -} - -// AsDelete returns a PrepareDecorator that sets the HTTP method to DELETE. -func AsDelete() PrepareDecorator { return WithMethod("DELETE") } - -// AsGet returns a PrepareDecorator that sets the HTTP method to GET. -func AsGet() PrepareDecorator { return WithMethod("GET") } - -// AsHead returns a PrepareDecorator that sets the HTTP method to HEAD. -func AsHead() PrepareDecorator { return WithMethod("HEAD") } - -// AsMerge returns a PrepareDecorator that sets the HTTP method to MERGE. -func AsMerge() PrepareDecorator { return WithMethod("MERGE") } - -// AsOptions returns a PrepareDecorator that sets the HTTP method to OPTIONS. -func AsOptions() PrepareDecorator { return WithMethod("OPTIONS") } - -// AsPatch returns a PrepareDecorator that sets the HTTP method to PATCH. -func AsPatch() PrepareDecorator { return WithMethod("PATCH") } - -// AsPost returns a PrepareDecorator that sets the HTTP method to POST. -func AsPost() PrepareDecorator { return WithMethod("POST") } - -// AsPut returns a PrepareDecorator that sets the HTTP method to PUT. -func AsPut() PrepareDecorator { return WithMethod("PUT") } - -// WithBaseURL returns a PrepareDecorator that populates the http.Request with a url.URL constructed -// from the supplied baseUrl. Query parameters will be encoded as required. -func WithBaseURL(baseURL string) PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err == nil { - var u *url.URL - if u, err = url.Parse(baseURL); err != nil { - return r, err - } - if u.Scheme == "" { - return r, fmt.Errorf("autorest: No scheme detected in URL %s", baseURL) - } - if u.RawQuery != "" { - // handle unencoded semicolons (ideally the server would send them already encoded) - u.RawQuery = strings.Replace(u.RawQuery, ";", "%3B", -1) - q, err := url.ParseQuery(u.RawQuery) - if err != nil { - return r, err - } - u.RawQuery = q.Encode() - } - r.URL = u - } - return r, err - }) - } -} - -// WithBytes returns a PrepareDecorator that takes a list of bytes -// which passes the bytes directly to the body -func WithBytes(input *[]byte) PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err == nil { - if input == nil { - return r, fmt.Errorf("Input Bytes was nil") - } - - r.ContentLength = int64(len(*input)) - r.Body = ioutil.NopCloser(bytes.NewReader(*input)) - } - return r, err - }) - } -} - -// WithCustomBaseURL returns a PrepareDecorator that replaces brace-enclosed keys within the -// request base URL (i.e., http.Request.URL) with the corresponding values from the passed map. -func WithCustomBaseURL(baseURL string, urlParameters map[string]interface{}) PrepareDecorator { - parameters := ensureValueStrings(urlParameters) - for key, value := range parameters { - baseURL = strings.Replace(baseURL, "{"+key+"}", value, -1) - } - return WithBaseURL(baseURL) -} - -// WithFormData returns a PrepareDecoratore that "URL encodes" (e.g., bar=baz&foo=quux) into the -// http.Request body. -func WithFormData(v url.Values) PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err == nil { - s := v.Encode() - - setHeader(r, http.CanonicalHeaderKey(headerContentType), mimeTypeFormPost) - r.ContentLength = int64(len(s)) - r.Body = ioutil.NopCloser(strings.NewReader(s)) - } - return r, err - }) - } -} - -// WithMultiPartFormData returns a PrepareDecoratore that "URL encodes" (e.g., bar=baz&foo=quux) form parameters -// into the http.Request body. -func WithMultiPartFormData(formDataParameters map[string]interface{}) PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err == nil { - var body bytes.Buffer - writer := multipart.NewWriter(&body) - for key, value := range formDataParameters { - if rc, ok := value.(io.ReadCloser); ok { - var fd io.Writer - if fd, err = writer.CreateFormFile(key, key); err != nil { - return r, err - } - if _, err = io.Copy(fd, rc); err != nil { - return r, err - } - } else { - if err = writer.WriteField(key, ensureValueString(value)); err != nil { - return r, err - } - } - } - if err = writer.Close(); err != nil { - return r, err - } - setHeader(r, http.CanonicalHeaderKey(headerContentType), writer.FormDataContentType()) - r.Body = ioutil.NopCloser(bytes.NewReader(body.Bytes())) - r.ContentLength = int64(body.Len()) - return r, err - } - return r, err - }) - } -} - -// WithFile returns a PrepareDecorator that sends file in request body. -func WithFile(f io.ReadCloser) PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err == nil { - b, err := ioutil.ReadAll(f) - if err != nil { - return r, err - } - r.Body = ioutil.NopCloser(bytes.NewReader(b)) - r.ContentLength = int64(len(b)) - } - return r, err - }) - } -} - -// WithBool returns a PrepareDecorator that encodes the passed bool into the body of the request -// and sets the Content-Length header. -func WithBool(v bool) PrepareDecorator { - return WithString(fmt.Sprintf("%v", v)) -} - -// WithFloat32 returns a PrepareDecorator that encodes the passed float32 into the body of the -// request and sets the Content-Length header. -func WithFloat32(v float32) PrepareDecorator { - return WithString(fmt.Sprintf("%v", v)) -} - -// WithFloat64 returns a PrepareDecorator that encodes the passed float64 into the body of the -// request and sets the Content-Length header. -func WithFloat64(v float64) PrepareDecorator { - return WithString(fmt.Sprintf("%v", v)) -} - -// WithInt32 returns a PrepareDecorator that encodes the passed int32 into the body of the request -// and sets the Content-Length header. -func WithInt32(v int32) PrepareDecorator { - return WithString(fmt.Sprintf("%v", v)) -} - -// WithInt64 returns a PrepareDecorator that encodes the passed int64 into the body of the request -// and sets the Content-Length header. -func WithInt64(v int64) PrepareDecorator { - return WithString(fmt.Sprintf("%v", v)) -} - -// WithString returns a PrepareDecorator that encodes the passed string into the body of the request -// and sets the Content-Length header. -func WithString(v string) PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err == nil { - r.ContentLength = int64(len(v)) - r.Body = ioutil.NopCloser(strings.NewReader(v)) - } - return r, err - }) - } -} - -// WithJSON returns a PrepareDecorator that encodes the data passed as JSON into the body of the -// request and sets the Content-Length header. -func WithJSON(v interface{}) PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err == nil { - b, err := json.Marshal(v) - if err == nil { - r.ContentLength = int64(len(b)) - r.Body = ioutil.NopCloser(bytes.NewReader(b)) - } - } - return r, err - }) - } -} - -// WithXML returns a PrepareDecorator that encodes the data passed as XML into the body of the -// request and sets the Content-Length header. -func WithXML(v interface{}) PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err == nil { - b, err := xml.Marshal(v) - if err == nil { - // we have to tack on an XML header - withHeader := xml.Header + string(b) - bytesWithHeader := []byte(withHeader) - - r.ContentLength = int64(len(bytesWithHeader)) - setHeader(r, headerContentLength, fmt.Sprintf("%d", len(bytesWithHeader))) - r.Body = ioutil.NopCloser(bytes.NewReader(bytesWithHeader)) - } - } - return r, err - }) - } -} - -// WithPath returns a PrepareDecorator that adds the supplied path to the request URL. If the path -// is absolute (that is, it begins with a "/"), it replaces the existing path. -func WithPath(path string) PrepareDecorator { - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err == nil { - if r.URL == nil { - return r, NewError("autorest", "WithPath", "Invoked with a nil URL") - } - if r.URL, err = parseURL(r.URL, path); err != nil { - return r, err - } - } - return r, err - }) - } -} - -// WithEscapedPathParameters returns a PrepareDecorator that replaces brace-enclosed keys within the -// request path (i.e., http.Request.URL.Path) with the corresponding values from the passed map. The -// values will be escaped (aka URL encoded) before insertion into the path. -func WithEscapedPathParameters(path string, pathParameters map[string]interface{}) PrepareDecorator { - parameters := escapeValueStrings(ensureValueStrings(pathParameters)) - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err == nil { - if r.URL == nil { - return r, NewError("autorest", "WithEscapedPathParameters", "Invoked with a nil URL") - } - for key, value := range parameters { - path = strings.Replace(path, "{"+key+"}", value, -1) - } - if r.URL, err = parseURL(r.URL, path); err != nil { - return r, err - } - } - return r, err - }) - } -} - -// WithPathParameters returns a PrepareDecorator that replaces brace-enclosed keys within the -// request path (i.e., http.Request.URL.Path) with the corresponding values from the passed map. -func WithPathParameters(path string, pathParameters map[string]interface{}) PrepareDecorator { - parameters := ensureValueStrings(pathParameters) - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err == nil { - if r.URL == nil { - return r, NewError("autorest", "WithPathParameters", "Invoked with a nil URL") - } - for key, value := range parameters { - path = strings.Replace(path, "{"+key+"}", value, -1) - } - - if r.URL, err = parseURL(r.URL, path); err != nil { - return r, err - } - } - return r, err - }) - } -} - -func parseURL(u *url.URL, path string) (*url.URL, error) { - p := strings.TrimRight(u.String(), "/") - if !strings.HasPrefix(path, "/") { - path = "/" + path - } - return url.Parse(p + path) -} - -// WithQueryParameters returns a PrepareDecorators that encodes and applies the query parameters -// given in the supplied map (i.e., key=value). -func WithQueryParameters(queryParameters map[string]interface{}) PrepareDecorator { - parameters := MapToValues(queryParameters) - return func(p Preparer) Preparer { - return PreparerFunc(func(r *http.Request) (*http.Request, error) { - r, err := p.Prepare(r) - if err == nil { - if r.URL == nil { - return r, NewError("autorest", "WithQueryParameters", "Invoked with a nil URL") - } - v := r.URL.Query() - for key, value := range parameters { - for i := range value { - d, err := url.QueryUnescape(value[i]) - if err != nil { - return r, err - } - value[i] = d - } - v[key] = value - } - r.URL.RawQuery = v.Encode() - } - return r, err - }) - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/responder.go b/vendor/github.com/Azure/go-autorest/autorest/responder.go deleted file mode 100644 index 349e1963a2..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/responder.go +++ /dev/null @@ -1,269 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "bytes" - "encoding/json" - "encoding/xml" - "fmt" - "io" - "io/ioutil" - "net/http" - "strings" -) - -// Responder is the interface that wraps the Respond method. -// -// Respond accepts and reacts to an http.Response. Implementations must ensure to not share or hold -// state since Responders may be shared and re-used. -type Responder interface { - Respond(*http.Response) error -} - -// ResponderFunc is a method that implements the Responder interface. -type ResponderFunc func(*http.Response) error - -// Respond implements the Responder interface on ResponderFunc. -func (rf ResponderFunc) Respond(r *http.Response) error { - return rf(r) -} - -// RespondDecorator takes and possibly decorates, by wrapping, a Responder. Decorators may react to -// the http.Response and pass it along or, first, pass the http.Response along then react. -type RespondDecorator func(Responder) Responder - -// CreateResponder creates, decorates, and returns a Responder. Without decorators, the returned -// Responder returns the passed http.Response unmodified. Responders may or may not be safe to share -// and re-used: It depends on the applied decorators. For example, a standard decorator that closes -// the response body is fine to share whereas a decorator that reads the body into a passed struct -// is not. -// -// To prevent memory leaks, ensure that at least one Responder closes the response body. -func CreateResponder(decorators ...RespondDecorator) Responder { - return DecorateResponder( - Responder(ResponderFunc(func(r *http.Response) error { return nil })), - decorators...) -} - -// DecorateResponder accepts a Responder and a, possibly empty, set of RespondDecorators, which it -// applies to the Responder. Decorators are applied in the order received, but their affect upon the -// request depends on whether they are a pre-decorator (react to the http.Response and then pass it -// along) or a post-decorator (pass the http.Response along and then react). -func DecorateResponder(r Responder, decorators ...RespondDecorator) Responder { - for _, decorate := range decorators { - r = decorate(r) - } - return r -} - -// Respond accepts an http.Response and a, possibly empty, set of RespondDecorators. -// It creates a Responder from the decorators it then applies to the passed http.Response. -func Respond(r *http.Response, decorators ...RespondDecorator) error { - if r == nil { - return nil - } - return CreateResponder(decorators...).Respond(r) -} - -// ByIgnoring returns a RespondDecorator that ignores the passed http.Response passing it unexamined -// to the next RespondDecorator. -func ByIgnoring() RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - return r.Respond(resp) - }) - } -} - -// ByCopying copies the contents of the http.Response Body into the passed bytes.Buffer as -// the Body is read. -func ByCopying(b *bytes.Buffer) RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - err := r.Respond(resp) - if err == nil && resp != nil && resp.Body != nil { - resp.Body = TeeReadCloser(resp.Body, b) - } - return err - }) - } -} - -// ByDiscardingBody returns a RespondDecorator that first invokes the passed Responder after which -// it copies the remaining bytes (if any) in the response body to ioutil.Discard. Since the passed -// Responder is invoked prior to discarding the response body, the decorator may occur anywhere -// within the set. -func ByDiscardingBody() RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - err := r.Respond(resp) - if err == nil && resp != nil && resp.Body != nil { - if _, err := io.Copy(ioutil.Discard, resp.Body); err != nil { - return fmt.Errorf("Error discarding the response body: %v", err) - } - } - return err - }) - } -} - -// ByClosing returns a RespondDecorator that first invokes the passed Responder after which it -// closes the response body. Since the passed Responder is invoked prior to closing the response -// body, the decorator may occur anywhere within the set. -func ByClosing() RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - err := r.Respond(resp) - if resp != nil && resp.Body != nil { - if err := resp.Body.Close(); err != nil { - return fmt.Errorf("Error closing the response body: %v", err) - } - } - return err - }) - } -} - -// ByClosingIfError returns a RespondDecorator that first invokes the passed Responder after which -// it closes the response if the passed Responder returns an error and the response body exists. -func ByClosingIfError() RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - err := r.Respond(resp) - if err != nil && resp != nil && resp.Body != nil { - if err := resp.Body.Close(); err != nil { - return fmt.Errorf("Error closing the response body: %v", err) - } - } - return err - }) - } -} - -// ByUnmarshallingBytes returns a RespondDecorator that copies the Bytes returned in the -// response Body into the value pointed to by v. -func ByUnmarshallingBytes(v *[]byte) RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - err := r.Respond(resp) - if err == nil { - bytes, errInner := ioutil.ReadAll(resp.Body) - if errInner != nil { - err = fmt.Errorf("Error occurred reading http.Response#Body - Error = '%v'", errInner) - } else { - *v = bytes - } - } - return err - }) - } -} - -// ByUnmarshallingJSON returns a RespondDecorator that decodes a JSON document returned in the -// response Body into the value pointed to by v. -func ByUnmarshallingJSON(v interface{}) RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - err := r.Respond(resp) - if err == nil { - b, errInner := ioutil.ReadAll(resp.Body) - // Some responses might include a BOM, remove for successful unmarshalling - b = bytes.TrimPrefix(b, []byte("\xef\xbb\xbf")) - if errInner != nil { - err = fmt.Errorf("Error occurred reading http.Response#Body - Error = '%v'", errInner) - } else if len(strings.Trim(string(b), " ")) > 0 { - errInner = json.Unmarshal(b, v) - if errInner != nil { - err = fmt.Errorf("Error occurred unmarshalling JSON - Error = '%v' JSON = '%s'", errInner, string(b)) - } - } - } - return err - }) - } -} - -// ByUnmarshallingXML returns a RespondDecorator that decodes a XML document returned in the -// response Body into the value pointed to by v. -func ByUnmarshallingXML(v interface{}) RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - err := r.Respond(resp) - if err == nil { - b, errInner := ioutil.ReadAll(resp.Body) - if errInner != nil { - err = fmt.Errorf("Error occurred reading http.Response#Body - Error = '%v'", errInner) - } else { - errInner = xml.Unmarshal(b, v) - if errInner != nil { - err = fmt.Errorf("Error occurred unmarshalling Xml - Error = '%v' Xml = '%s'", errInner, string(b)) - } - } - } - return err - }) - } -} - -// WithErrorUnlessStatusCode returns a RespondDecorator that emits an error unless the response -// StatusCode is among the set passed. On error, response body is fully read into a buffer and -// presented in the returned error, as well as in the response body. -func WithErrorUnlessStatusCode(codes ...int) RespondDecorator { - return func(r Responder) Responder { - return ResponderFunc(func(resp *http.Response) error { - err := r.Respond(resp) - if err == nil && !ResponseHasStatusCode(resp, codes...) { - derr := NewErrorWithResponse("autorest", "WithErrorUnlessStatusCode", resp, "%v %v failed with %s", - resp.Request.Method, - resp.Request.URL, - resp.Status) - if resp.Body != nil { - defer resp.Body.Close() - b, _ := ioutil.ReadAll(resp.Body) - derr.ServiceError = b - resp.Body = ioutil.NopCloser(bytes.NewReader(b)) - } - err = derr - } - return err - }) - } -} - -// WithErrorUnlessOK returns a RespondDecorator that emits an error if the response StatusCode is -// anything other than HTTP 200. -func WithErrorUnlessOK() RespondDecorator { - return WithErrorUnlessStatusCode(http.StatusOK) -} - -// ExtractHeader extracts all values of the specified header from the http.Response. It returns an -// empty string slice if the passed http.Response is nil or the header does not exist. -func ExtractHeader(header string, resp *http.Response) []string { - if resp != nil && resp.Header != nil { - return resp.Header[http.CanonicalHeaderKey(header)] - } - return nil -} - -// ExtractHeaderValue extracts the first value of the specified header from the http.Response. It -// returns an empty string if the passed http.Response is nil or the header does not exist. -func ExtractHeaderValue(header string, resp *http.Response) string { - h := ExtractHeader(header, resp) - if len(h) > 0 { - return h[0] - } - return "" -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/retriablerequest.go b/vendor/github.com/Azure/go-autorest/autorest/retriablerequest.go deleted file mode 100644 index fa11dbed79..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/retriablerequest.go +++ /dev/null @@ -1,52 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "bytes" - "io" - "io/ioutil" - "net/http" -) - -// NewRetriableRequest returns a wrapper around an HTTP request that support retry logic. -func NewRetriableRequest(req *http.Request) *RetriableRequest { - return &RetriableRequest{req: req} -} - -// Request returns the wrapped HTTP request. -func (rr *RetriableRequest) Request() *http.Request { - return rr.req -} - -func (rr *RetriableRequest) prepareFromByteReader() (err error) { - // fall back to making a copy (only do this once) - b := []byte{} - if rr.req.ContentLength > 0 { - b = make([]byte, rr.req.ContentLength) - _, err = io.ReadFull(rr.req.Body, b) - if err != nil { - return err - } - } else { - b, err = ioutil.ReadAll(rr.req.Body) - if err != nil { - return err - } - } - rr.br = bytes.NewReader(b) - rr.req.Body = ioutil.NopCloser(rr.br) - return err -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/retriablerequest_1.7.go b/vendor/github.com/Azure/go-autorest/autorest/retriablerequest_1.7.go deleted file mode 100644 index 4c87030e81..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/retriablerequest_1.7.go +++ /dev/null @@ -1,55 +0,0 @@ -//go:build !go1.8 -// +build !go1.8 - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package autorest - -import ( - "bytes" - "io/ioutil" - "net/http" -) - -// RetriableRequest provides facilities for retrying an HTTP request. -type RetriableRequest struct { - req *http.Request - br *bytes.Reader -} - -// Prepare signals that the request is about to be sent. -func (rr *RetriableRequest) Prepare() (err error) { - // preserve the request body; this is to support retry logic as - // the underlying transport will always close the reqeust body - if rr.req.Body != nil { - if rr.br != nil { - _, err = rr.br.Seek(0, 0 /*io.SeekStart*/) - rr.req.Body = ioutil.NopCloser(rr.br) - } - if err != nil { - return err - } - if rr.br == nil { - // fall back to making a copy (only do this once) - err = rr.prepareFromByteReader() - } - } - return err -} - -func removeRequestBody(req *http.Request) { - req.Body = nil - req.ContentLength = 0 -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/retriablerequest_1.8.go b/vendor/github.com/Azure/go-autorest/autorest/retriablerequest_1.8.go deleted file mode 100644 index 05847c08ba..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/retriablerequest_1.8.go +++ /dev/null @@ -1,67 +0,0 @@ -//go:build go1.8 -// +build go1.8 - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package autorest - -import ( - "bytes" - "io" - "io/ioutil" - "net/http" -) - -// RetriableRequest provides facilities for retrying an HTTP request. -type RetriableRequest struct { - req *http.Request - rc io.ReadCloser - br *bytes.Reader -} - -// Prepare signals that the request is about to be sent. -func (rr *RetriableRequest) Prepare() (err error) { - // preserve the request body; this is to support retry logic as - // the underlying transport will always close the reqeust body - if rr.req.Body != nil { - if rr.rc != nil { - rr.req.Body = rr.rc - } else if rr.br != nil { - _, err = rr.br.Seek(0, io.SeekStart) - rr.req.Body = ioutil.NopCloser(rr.br) - } - if err != nil { - return err - } - if rr.req.GetBody != nil { - // this will allow us to preserve the body without having to - // make a copy. note we need to do this on each iteration - rr.rc, err = rr.req.GetBody() - if err != nil { - return err - } - } else if rr.br == nil { - // fall back to making a copy (only do this once) - err = rr.prepareFromByteReader() - } - } - return err -} - -func removeRequestBody(req *http.Request) { - req.Body = nil - req.GetBody = nil - req.ContentLength = 0 -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/sender.go b/vendor/github.com/Azure/go-autorest/autorest/sender.go deleted file mode 100644 index 118de81411..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/sender.go +++ /dev/null @@ -1,458 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "context" - "crypto/tls" - "fmt" - "log" - "math" - "net" - "net/http" - "net/http/cookiejar" - "strconv" - "sync" - "time" - - "github.com/Azure/go-autorest/logger" - "github.com/Azure/go-autorest/tracing" -) - -// there is one sender per TLS renegotiation type, i.e. count of tls.RenegotiationSupport enums -const defaultSendersCount = 3 - -type defaultSender struct { - sender Sender - init *sync.Once -} - -// each type of sender will be created on demand in sender() -var defaultSenders [defaultSendersCount]defaultSender - -func init() { - for i := 0; i < defaultSendersCount; i++ { - defaultSenders[i].init = &sync.Once{} - } -} - -// used as a key type in context.WithValue() -type ctxSendDecorators struct{} - -// WithSendDecorators adds the specified SendDecorators to the provided context. -// If no SendDecorators are provided the context is unchanged. -func WithSendDecorators(ctx context.Context, sendDecorator []SendDecorator) context.Context { - if len(sendDecorator) == 0 { - return ctx - } - return context.WithValue(ctx, ctxSendDecorators{}, sendDecorator) -} - -// GetSendDecorators returns the SendDecorators in the provided context or the provided default SendDecorators. -func GetSendDecorators(ctx context.Context, defaultSendDecorators ...SendDecorator) []SendDecorator { - inCtx := ctx.Value(ctxSendDecorators{}) - if sd, ok := inCtx.([]SendDecorator); ok { - return sd - } - return defaultSendDecorators -} - -// Sender is the interface that wraps the Do method to send HTTP requests. -// -// The standard http.Client conforms to this interface. -type Sender interface { - Do(*http.Request) (*http.Response, error) -} - -// SenderFunc is a method that implements the Sender interface. -type SenderFunc func(*http.Request) (*http.Response, error) - -// Do implements the Sender interface on SenderFunc. -func (sf SenderFunc) Do(r *http.Request) (*http.Response, error) { - return sf(r) -} - -// SendDecorator takes and possibly decorates, by wrapping, a Sender. Decorators may affect the -// http.Request and pass it along or, first, pass the http.Request along then react to the -// http.Response result. -type SendDecorator func(Sender) Sender - -// CreateSender creates, decorates, and returns, as a Sender, the default http.Client. -func CreateSender(decorators ...SendDecorator) Sender { - return DecorateSender(sender(tls.RenegotiateNever), decorators...) -} - -// DecorateSender accepts a Sender and a, possibly empty, set of SendDecorators, which is applies to -// the Sender. Decorators are applied in the order received, but their affect upon the request -// depends on whether they are a pre-decorator (change the http.Request and then pass it along) or a -// post-decorator (pass the http.Request along and react to the results in http.Response). -func DecorateSender(s Sender, decorators ...SendDecorator) Sender { - for _, decorate := range decorators { - s = decorate(s) - } - return s -} - -// Send sends, by means of the default http.Client, the passed http.Request, returning the -// http.Response and possible error. It also accepts a, possibly empty, set of SendDecorators which -// it will apply the http.Client before invoking the Do method. -// -// Send is a convenience method and not recommended for production. Advanced users should use -// SendWithSender, passing and sharing their own Sender (e.g., instance of http.Client). -// -// Send will not poll or retry requests. -func Send(r *http.Request, decorators ...SendDecorator) (*http.Response, error) { - return SendWithSender(sender(tls.RenegotiateNever), r, decorators...) -} - -// SendWithSender sends the passed http.Request, through the provided Sender, returning the -// http.Response and possible error. It also accepts a, possibly empty, set of SendDecorators which -// it will apply the http.Client before invoking the Do method. -// -// SendWithSender will not poll or retry requests. -func SendWithSender(s Sender, r *http.Request, decorators ...SendDecorator) (*http.Response, error) { - return DecorateSender(s, decorators...).Do(r) -} - -func sender(renengotiation tls.RenegotiationSupport) Sender { - // note that we can't init defaultSenders in init() since it will - // execute before calling code has had a chance to enable tracing - defaultSenders[renengotiation].init.Do(func() { - // copied from http.DefaultTransport with a TLS minimum version. - transport := &http.Transport{ - Proxy: http.ProxyFromEnvironment, - DialContext: (&net.Dialer{ - Timeout: 30 * time.Second, - KeepAlive: 30 * time.Second, - }).DialContext, - ForceAttemptHTTP2: true, - MaxIdleConns: 100, - IdleConnTimeout: 90 * time.Second, - TLSHandshakeTimeout: 10 * time.Second, - ExpectContinueTimeout: 1 * time.Second, - TLSClientConfig: &tls.Config{ - MinVersion: tls.VersionTLS12, - Renegotiation: renengotiation, - }, - } - var roundTripper http.RoundTripper = transport - if tracing.IsEnabled() { - roundTripper = tracing.NewTransport(transport) - } - j, _ := cookiejar.New(nil) - defaultSenders[renengotiation].sender = &http.Client{Jar: j, Transport: roundTripper} - }) - return defaultSenders[renengotiation].sender -} - -// AfterDelay returns a SendDecorator that delays for the passed time.Duration before -// invoking the Sender. The delay may be terminated by closing the optional channel on the -// http.Request. If canceled, no further Senders are invoked. -func AfterDelay(d time.Duration) SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - if !DelayForBackoff(d, 0, r.Context().Done()) { - return nil, fmt.Errorf("autorest: AfterDelay canceled before full delay") - } - return s.Do(r) - }) - } -} - -// AsIs returns a SendDecorator that invokes the passed Sender without modifying the http.Request. -func AsIs() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - return s.Do(r) - }) - } -} - -// DoCloseIfError returns a SendDecorator that first invokes the passed Sender after which -// it closes the response if the passed Sender returns an error and the response body exists. -func DoCloseIfError() SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - resp, err := s.Do(r) - if err != nil { - Respond(resp, ByDiscardingBody(), ByClosing()) - } - return resp, err - }) - } -} - -// DoErrorIfStatusCode returns a SendDecorator that emits an error if the response StatusCode is -// among the set passed. Since these are artificial errors, the response body may still require -// closing. -func DoErrorIfStatusCode(codes ...int) SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - resp, err := s.Do(r) - if err == nil && ResponseHasStatusCode(resp, codes...) { - err = NewErrorWithResponse("autorest", "DoErrorIfStatusCode", resp, "%v %v failed with %s", - resp.Request.Method, - resp.Request.URL, - resp.Status) - } - return resp, err - }) - } -} - -// DoErrorUnlessStatusCode returns a SendDecorator that emits an error unless the response -// StatusCode is among the set passed. Since these are artificial errors, the response body -// may still require closing. -func DoErrorUnlessStatusCode(codes ...int) SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - resp, err := s.Do(r) - if err == nil && !ResponseHasStatusCode(resp, codes...) { - err = NewErrorWithResponse("autorest", "DoErrorUnlessStatusCode", resp, "%v %v failed with %s", - resp.Request.Method, - resp.Request.URL, - resp.Status) - } - return resp, err - }) - } -} - -// DoPollForStatusCodes returns a SendDecorator that polls if the http.Response contains one of the -// passed status codes. It expects the http.Response to contain a Location header providing the -// URL at which to poll (using GET) and will poll until the time passed is equal to or greater than -// the supplied duration. It will delay between requests for the duration specified in the -// RetryAfter header or, if the header is absent, the passed delay. Polling may be canceled by -// closing the optional channel on the http.Request. -func DoPollForStatusCodes(duration time.Duration, delay time.Duration, codes ...int) SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (resp *http.Response, err error) { - resp, err = s.Do(r) - - if err == nil && ResponseHasStatusCode(resp, codes...) { - r, err = NewPollingRequestWithContext(r.Context(), resp) - - for err == nil && ResponseHasStatusCode(resp, codes...) { - Respond(resp, - ByDiscardingBody(), - ByClosing()) - resp, err = SendWithSender(s, r, - AfterDelay(GetRetryAfter(resp, delay))) - } - } - - return resp, err - }) - } -} - -// DoRetryForAttempts returns a SendDecorator that retries a failed request for up to the specified -// number of attempts, exponentially backing off between requests using the supplied backoff -// time.Duration (which may be zero). Retrying may be canceled by closing the optional channel on -// the http.Request. -func DoRetryForAttempts(attempts int, backoff time.Duration) SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (resp *http.Response, err error) { - rr := NewRetriableRequest(r) - for attempt := 0; attempt < attempts; attempt++ { - err = rr.Prepare() - if err != nil { - return resp, err - } - DrainResponseBody(resp) - resp, err = s.Do(rr.Request()) - if err == nil { - return resp, err - } - logger.Instance.Writef(logger.LogError, "DoRetryForAttempts: received error for attempt %d: %v\n", attempt+1, err) - if !DelayForBackoff(backoff, attempt, r.Context().Done()) { - return nil, r.Context().Err() - } - } - return resp, err - }) - } -} - -// Count429AsRetry indicates that a 429 response should be included as a retry attempt. -var Count429AsRetry = true - -// Max429Delay is the maximum duration to wait between retries on a 429 if no Retry-After header was received. -var Max429Delay time.Duration - -// DoRetryForStatusCodes returns a SendDecorator that retries for specified statusCodes for up to the specified -// number of attempts, exponentially backing off between requests using the supplied backoff -// time.Duration (which may be zero). Retrying may be canceled by cancelling the context on the http.Request. -// NOTE: Code http.StatusTooManyRequests (429) will *not* be counted against the number of attempts. -func DoRetryForStatusCodes(attempts int, backoff time.Duration, codes ...int) SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - return doRetryForStatusCodesImpl(s, r, Count429AsRetry, attempts, backoff, 0, codes...) - }) - } -} - -// DoRetryForStatusCodesWithCap returns a SendDecorator that retries for specified statusCodes for up to the -// specified number of attempts, exponentially backing off between requests using the supplied backoff -// time.Duration (which may be zero). To cap the maximum possible delay between iterations specify a value greater -// than zero for cap. Retrying may be canceled by cancelling the context on the http.Request. -func DoRetryForStatusCodesWithCap(attempts int, backoff, cap time.Duration, codes ...int) SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - return doRetryForStatusCodesImpl(s, r, Count429AsRetry, attempts, backoff, cap, codes...) - }) - } -} - -func doRetryForStatusCodesImpl(s Sender, r *http.Request, count429 bool, attempts int, backoff, cap time.Duration, codes ...int) (resp *http.Response, err error) { - rr := NewRetriableRequest(r) - // Increment to add the first call (attempts denotes number of retries) - for attempt, delayCount := 0, 0; attempt < attempts+1; { - err = rr.Prepare() - if err != nil { - return - } - DrainResponseBody(resp) - resp, err = s.Do(rr.Request()) - // we want to retry if err is not nil (e.g. transient network failure). note that for failed authentication - // resp and err will both have a value, so in this case we don't want to retry as it will never succeed. - if err == nil && !ResponseHasStatusCode(resp, codes...) || IsTokenRefreshError(err) { - return resp, err - } - if err != nil { - logger.Instance.Writef(logger.LogError, "DoRetryForStatusCodes: received error for attempt %d: %v\n", attempt+1, err) - } - delayed := DelayWithRetryAfter(resp, r.Context().Done()) - // if this was a 429 set the delay cap as specified. - // applicable only in the absence of a retry-after header. - if resp != nil && resp.StatusCode == http.StatusTooManyRequests { - cap = Max429Delay - } - if !delayed && !DelayForBackoffWithCap(backoff, cap, delayCount, r.Context().Done()) { - return resp, r.Context().Err() - } - // when count429 == false don't count a 429 against the number - // of attempts so that we continue to retry until it succeeds - if count429 || (resp == nil || resp.StatusCode != http.StatusTooManyRequests) { - attempt++ - } - // delay count is tracked separately from attempts to - // ensure that 429 participates in exponential back-off - delayCount++ - } - return resp, err -} - -// DelayWithRetryAfter invokes time.After for the duration specified in the "Retry-After" header. -// The value of Retry-After can be either the number of seconds or a date in RFC1123 format. -// The function returns true after successfully waiting for the specified duration. If there is -// no Retry-After header or the wait is cancelled the return value is false. -func DelayWithRetryAfter(resp *http.Response, cancel <-chan struct{}) bool { - if resp == nil { - return false - } - var dur time.Duration - ra := resp.Header.Get("Retry-After") - if retryAfter, _ := strconv.Atoi(ra); retryAfter > 0 { - dur = time.Duration(retryAfter) * time.Second - } else if t, err := time.Parse(time.RFC1123, ra); err == nil { - dur = t.Sub(time.Now()) - } - if dur > 0 { - select { - case <-time.After(dur): - return true - case <-cancel: - return false - } - } - return false -} - -// DoRetryForDuration returns a SendDecorator that retries the request until the total time is equal -// to or greater than the specified duration, exponentially backing off between requests using the -// supplied backoff time.Duration (which may be zero). Retrying may be canceled by closing the -// optional channel on the http.Request. -func DoRetryForDuration(d time.Duration, backoff time.Duration) SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (resp *http.Response, err error) { - rr := NewRetriableRequest(r) - end := time.Now().Add(d) - for attempt := 0; time.Now().Before(end); attempt++ { - err = rr.Prepare() - if err != nil { - return resp, err - } - DrainResponseBody(resp) - resp, err = s.Do(rr.Request()) - if err == nil { - return resp, err - } - logger.Instance.Writef(logger.LogError, "DoRetryForDuration: received error for attempt %d: %v\n", attempt+1, err) - if !DelayForBackoff(backoff, attempt, r.Context().Done()) { - return nil, r.Context().Err() - } - } - return resp, err - }) - } -} - -// WithLogging returns a SendDecorator that implements simple before and after logging of the -// request. -func WithLogging(logger *log.Logger) SendDecorator { - return func(s Sender) Sender { - return SenderFunc(func(r *http.Request) (*http.Response, error) { - logger.Printf("Sending %s %s", r.Method, r.URL) - resp, err := s.Do(r) - if err != nil { - logger.Printf("%s %s received error '%v'", r.Method, r.URL, err) - } else { - logger.Printf("%s %s received %s", r.Method, r.URL, resp.Status) - } - return resp, err - }) - } -} - -// DelayForBackoff invokes time.After for the supplied backoff duration raised to the power of -// passed attempt (i.e., an exponential backoff delay). Backoff duration is in seconds and can set -// to zero for no delay. The delay may be canceled by closing the passed channel. If terminated early, -// returns false. -// Note: Passing attempt 1 will result in doubling "backoff" duration. Treat this as a zero-based attempt -// count. -func DelayForBackoff(backoff time.Duration, attempt int, cancel <-chan struct{}) bool { - return DelayForBackoffWithCap(backoff, 0, attempt, cancel) -} - -// DelayForBackoffWithCap invokes time.After for the supplied backoff duration raised to the power of -// passed attempt (i.e., an exponential backoff delay). Backoff duration is in seconds and can set -// to zero for no delay. To cap the maximum possible delay specify a value greater than zero for cap. -// The delay may be canceled by closing the passed channel. If terminated early, returns false. -// Note: Passing attempt 1 will result in doubling "backoff" duration. Treat this as a zero-based attempt -// count. -func DelayForBackoffWithCap(backoff, cap time.Duration, attempt int, cancel <-chan struct{}) bool { - d := time.Duration(backoff.Seconds()*math.Pow(2, float64(attempt))) * time.Second - if cap > 0 && d > cap { - d = cap - } - logger.Instance.Writef(logger.LogInfo, "DelayForBackoffWithCap: sleeping for %s\n", d) - select { - case <-time.After(d): - return true - case <-cancel: - return false - } -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/utility.go b/vendor/github.com/Azure/go-autorest/autorest/utility.go deleted file mode 100644 index 3467b8fa60..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/utility.go +++ /dev/null @@ -1,232 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "bytes" - "encoding/json" - "encoding/xml" - "fmt" - "io" - "io/ioutil" - "net" - "net/http" - "net/url" - "reflect" - "strings" -) - -// EncodedAs is a series of constants specifying various data encodings -type EncodedAs string - -const ( - // EncodedAsJSON states that data is encoded as JSON - EncodedAsJSON EncodedAs = "JSON" - - // EncodedAsXML states that data is encoded as Xml - EncodedAsXML EncodedAs = "XML" -) - -// Decoder defines the decoding method json.Decoder and xml.Decoder share -type Decoder interface { - Decode(v interface{}) error -} - -// NewDecoder creates a new decoder appropriate to the passed encoding. -// encodedAs specifies the type of encoding and r supplies the io.Reader containing the -// encoded data. -func NewDecoder(encodedAs EncodedAs, r io.Reader) Decoder { - if encodedAs == EncodedAsJSON { - return json.NewDecoder(r) - } else if encodedAs == EncodedAsXML { - return xml.NewDecoder(r) - } - return nil -} - -// CopyAndDecode decodes the data from the passed io.Reader while making a copy. Having a copy -// is especially useful if there is a chance the data will fail to decode. -// encodedAs specifies the expected encoding, r provides the io.Reader to the data, and v -// is the decoding destination. -func CopyAndDecode(encodedAs EncodedAs, r io.Reader, v interface{}) (bytes.Buffer, error) { - b := bytes.Buffer{} - return b, NewDecoder(encodedAs, io.TeeReader(r, &b)).Decode(v) -} - -// TeeReadCloser returns a ReadCloser that writes to w what it reads from rc. -// It utilizes io.TeeReader to copy the data read and has the same behavior when reading. -// Further, when it is closed, it ensures that rc is closed as well. -func TeeReadCloser(rc io.ReadCloser, w io.Writer) io.ReadCloser { - return &teeReadCloser{rc, io.TeeReader(rc, w)} -} - -type teeReadCloser struct { - rc io.ReadCloser - r io.Reader -} - -func (t *teeReadCloser) Read(p []byte) (int, error) { - return t.r.Read(p) -} - -func (t *teeReadCloser) Close() error { - return t.rc.Close() -} - -func containsInt(ints []int, n int) bool { - for _, i := range ints { - if i == n { - return true - } - } - return false -} - -func escapeValueStrings(m map[string]string) map[string]string { - for key, value := range m { - m[key] = url.QueryEscape(value) - } - return m -} - -func ensureValueStrings(mapOfInterface map[string]interface{}) map[string]string { - mapOfStrings := make(map[string]string) - for key, value := range mapOfInterface { - mapOfStrings[key] = ensureValueString(value) - } - return mapOfStrings -} - -func ensureValueString(value interface{}) string { - if value == nil { - return "" - } - switch v := value.(type) { - case string: - return v - case []byte: - return string(v) - default: - return fmt.Sprintf("%v", v) - } -} - -// MapToValues method converts map[string]interface{} to url.Values. -func MapToValues(m map[string]interface{}) url.Values { - v := url.Values{} - for key, value := range m { - x := reflect.ValueOf(value) - if x.Kind() == reflect.Array || x.Kind() == reflect.Slice { - for i := 0; i < x.Len(); i++ { - v.Add(key, ensureValueString(x.Index(i))) - } - } else { - v.Add(key, ensureValueString(value)) - } - } - return v -} - -// AsStringSlice method converts interface{} to []string. -// s must be of type slice or array or an error is returned. -// Each element of s will be converted to its string representation. -func AsStringSlice(s interface{}) ([]string, error) { - v := reflect.ValueOf(s) - if v.Kind() != reflect.Slice && v.Kind() != reflect.Array { - return nil, NewError("autorest", "AsStringSlice", "the value's type is not a slice or array.") - } - stringSlice := make([]string, 0, v.Len()) - - for i := 0; i < v.Len(); i++ { - stringSlice = append(stringSlice, fmt.Sprintf("%v", v.Index(i))) - } - return stringSlice, nil -} - -// String method converts interface v to string. If interface is a list, it -// joins list elements using the separator. Note that only sep[0] will be used for -// joining if any separator is specified. -func String(v interface{}, sep ...string) string { - if len(sep) == 0 { - return ensureValueString(v) - } - stringSlice, ok := v.([]string) - if ok == false { - var err error - stringSlice, err = AsStringSlice(v) - if err != nil { - panic(fmt.Sprintf("autorest: Couldn't convert value to a string %s.", err)) - } - } - return ensureValueString(strings.Join(stringSlice, sep[0])) -} - -// Encode method encodes url path and query parameters. -func Encode(location string, v interface{}, sep ...string) string { - s := String(v, sep...) - switch strings.ToLower(location) { - case "path": - return pathEscape(s) - case "query": - return queryEscape(s) - default: - return s - } -} - -func pathEscape(s string) string { - return strings.Replace(url.QueryEscape(s), "+", "%20", -1) -} - -func queryEscape(s string) string { - return url.QueryEscape(s) -} - -// ChangeToGet turns the specified http.Request into a GET (it assumes it wasn't). -// This is mainly useful for long-running operations that use the Azure-AsyncOperation -// header, so we change the initial PUT into a GET to retrieve the final result. -func ChangeToGet(req *http.Request) *http.Request { - req.Method = "GET" - req.Body = nil - req.ContentLength = 0 - req.Header.Del("Content-Length") - return req -} - -// IsTemporaryNetworkError returns true if the specified error is a temporary network error or false -// if it's not. If the error doesn't implement the net.Error interface the return value is true. -func IsTemporaryNetworkError(err error) bool { - if netErr, ok := err.(net.Error); !ok || (ok && netErr.Temporary()) { - return true - } - return false -} - -// DrainResponseBody reads the response body then closes it. -func DrainResponseBody(resp *http.Response) error { - if resp != nil && resp.Body != nil { - _, err := io.Copy(ioutil.Discard, resp.Body) - resp.Body.Close() - return err - } - return nil -} - -func setHeader(r *http.Request, key, value string) { - if r.Header == nil { - r.Header = make(http.Header) - } - r.Header.Set(key, value) -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/utility_1.13.go b/vendor/github.com/Azure/go-autorest/autorest/utility_1.13.go deleted file mode 100644 index 3133fcc08e..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/utility_1.13.go +++ /dev/null @@ -1,30 +0,0 @@ -//go:build go1.13 -// +build go1.13 - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package autorest - -import ( - "errors" - - "github.com/Azure/go-autorest/autorest/adal" -) - -// IsTokenRefreshError returns true if the specified error implements the TokenRefreshError interface. -func IsTokenRefreshError(err error) bool { - var tre adal.TokenRefreshError - return errors.As(err, &tre) -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/utility_legacy.go b/vendor/github.com/Azure/go-autorest/autorest/utility_legacy.go deleted file mode 100644 index 851e152db4..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/utility_legacy.go +++ /dev/null @@ -1,32 +0,0 @@ -//go:build !go1.13 -// +build !go1.13 - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package autorest - -import "github.com/Azure/go-autorest/autorest/adal" - -// IsTokenRefreshError returns true if the specified error implements the TokenRefreshError -// interface. If err is a DetailedError it will walk the chain of Original errors. -func IsTokenRefreshError(err error) bool { - if _, ok := err.(adal.TokenRefreshError); ok { - return true - } - if de, ok := err.(DetailedError); ok { - return IsTokenRefreshError(de.Original) - } - return false -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/version.go b/vendor/github.com/Azure/go-autorest/autorest/version.go deleted file mode 100644 index 713e23581d..0000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/version.go +++ /dev/null @@ -1,41 +0,0 @@ -package autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "fmt" - "runtime" -) - -const number = "v14.2.1" - -var ( - userAgent = fmt.Sprintf("Go/%s (%s-%s) go-autorest/%s", - runtime.Version(), - runtime.GOARCH, - runtime.GOOS, - number, - ) -) - -// UserAgent returns a string containing the Go version, system architecture and OS, and the go-autorest version. -func UserAgent() string { - return userAgent -} - -// Version returns the semantic version (see http://semver.org). -func Version() string { - return number -} diff --git a/vendor/github.com/Azure/go-autorest/azure-pipelines.yml b/vendor/github.com/Azure/go-autorest/azure-pipelines.yml deleted file mode 100644 index 6fb8404fd0..0000000000 --- a/vendor/github.com/Azure/go-autorest/azure-pipelines.yml +++ /dev/null @@ -1,105 +0,0 @@ -variables: - GOPATH: '$(system.defaultWorkingDirectory)/work' - sdkPath: '$(GOPATH)/src/github.com/$(build.repository.name)' - -jobs: - - job: 'goautorest' - displayName: 'Run go-autorest CI Checks' - - strategy: - matrix: - Linux_Go113: - vm.image: 'ubuntu-18.04' - go.version: '1.13' - Linux_Go114: - vm.image: 'ubuntu-18.04' - go.version: '1.14' - - pool: - vmImage: '$(vm.image)' - - steps: - - task: GoTool@0 - inputs: - version: '$(go.version)' - displayName: "Select Go Version" - - - script: | - set -e - mkdir -p '$(GOPATH)/bin' - mkdir -p '$(sdkPath)' - shopt -s extglob - mv !(work) '$(sdkPath)' - echo '##vso[task.prependpath]$(GOPATH)/bin' - displayName: 'Create Go Workspace' - - - script: | - set -e - curl -sSL https://raw.githubusercontent.com/golang/dep/master/install.sh | sh - dep ensure -v - go install ./vendor/golang.org/x/lint/golint - go get github.com/jstemmer/go-junit-report - go get github.com/axw/gocov/gocov - go get github.com/AlekSi/gocov-xml - go get -u github.com/matm/gocov-html - workingDirectory: '$(sdkPath)' - displayName: 'Install Dependencies' - - - script: | - go vet ./autorest/... - go vet ./logger/... - go vet ./tracing/... - workingDirectory: '$(sdkPath)' - displayName: 'Vet' - - - script: | - go build -v ./autorest/... - go build -v ./logger/... - go build -v ./tracing/... - workingDirectory: '$(sdkPath)' - displayName: 'Build' - - - script: | - set -e - go test -race -v -coverprofile=coverage.txt -covermode atomic ./autorest/... ./logger/... ./tracing/... 2>&1 | go-junit-report > report.xml - gocov convert coverage.txt > coverage.json - gocov-xml < coverage.json > coverage.xml - gocov-html < coverage.json > coverage.html - workingDirectory: '$(sdkPath)' - displayName: 'Run Tests' - - - script: grep -L -r --include *.go --exclude-dir vendor -P "Copyright (\d{4}|\(c\)) Microsoft" ./ | tee >&2 - workingDirectory: '$(sdkPath)' - displayName: 'Copyright Header Check' - failOnStderr: true - condition: succeededOrFailed() - - - script: | - gofmt -s -l -w ./autorest/. >&2 - gofmt -s -l -w ./logger/. >&2 - gofmt -s -l -w ./tracing/. >&2 - workingDirectory: '$(sdkPath)' - displayName: 'Format Check' - failOnStderr: true - condition: succeededOrFailed() - - - script: | - golint ./autorest/... >&2 - golint ./logger/... >&2 - golint ./tracing/... >&2 - workingDirectory: '$(sdkPath)' - displayName: 'Linter Check' - failOnStderr: true - condition: succeededOrFailed() - - - task: PublishTestResults@2 - inputs: - testRunner: JUnit - testResultsFiles: $(sdkPath)/report.xml - failTaskOnFailedTests: true - - - task: PublishCodeCoverageResults@1 - inputs: - codeCoverageTool: Cobertura - summaryFileLocation: $(sdkPath)/coverage.xml - additionalCodeCoverageFiles: $(sdkPath)/coverage.html diff --git a/vendor/github.com/Azure/go-autorest/doc.go b/vendor/github.com/Azure/go-autorest/doc.go deleted file mode 100644 index 99ae6ca988..0000000000 --- a/vendor/github.com/Azure/go-autorest/doc.go +++ /dev/null @@ -1,18 +0,0 @@ -/* -Package go-autorest provides an HTTP request client for use with Autorest-generated API client packages. -*/ -package go_autorest - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. diff --git a/vendor/github.com/Azure/go-autorest/logger/LICENSE b/vendor/github.com/Azure/go-autorest/logger/LICENSE deleted file mode 100644 index b9d6a27ea9..0000000000 --- a/vendor/github.com/Azure/go-autorest/logger/LICENSE +++ /dev/null @@ -1,191 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - Copyright 2015 Microsoft Corporation - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/Azure/go-autorest/logger/go_mod_tidy_hack.go b/vendor/github.com/Azure/go-autorest/logger/go_mod_tidy_hack.go deleted file mode 100644 index 0aa27680db..0000000000 --- a/vendor/github.com/Azure/go-autorest/logger/go_mod_tidy_hack.go +++ /dev/null @@ -1,24 +0,0 @@ -// +build modhack - -package logger - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// This file, and the github.com/Azure/go-autorest import, won't actually become part of -// the resultant binary. - -// Necessary for safely adding multi-module repo. -// See: https://github.com/golang/go/wiki/Modules#is-it-possible-to-add-a-module-to-a-multi-module-repository -import _ "github.com/Azure/go-autorest" diff --git a/vendor/github.com/Azure/go-autorest/logger/logger.go b/vendor/github.com/Azure/go-autorest/logger/logger.go deleted file mode 100644 index 2f5d8cc1a1..0000000000 --- a/vendor/github.com/Azure/go-autorest/logger/logger.go +++ /dev/null @@ -1,337 +0,0 @@ -package logger - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "bytes" - "fmt" - "io" - "io/ioutil" - "net/http" - "net/url" - "os" - "strings" - "sync" - "time" -) - -// LevelType tells a logger the minimum level to log. When code reports a log entry, -// the LogLevel indicates the level of the log entry. The logger only records entries -// whose level is at least the level it was told to log. See the Log* constants. -// For example, if a logger is configured with LogError, then LogError, LogPanic, -// and LogFatal entries will be logged; lower level entries are ignored. -type LevelType uint32 - -const ( - // LogNone tells a logger not to log any entries passed to it. - LogNone LevelType = iota - - // LogFatal tells a logger to log all LogFatal entries passed to it. - LogFatal - - // LogPanic tells a logger to log all LogPanic and LogFatal entries passed to it. - LogPanic - - // LogError tells a logger to log all LogError, LogPanic and LogFatal entries passed to it. - LogError - - // LogWarning tells a logger to log all LogWarning, LogError, LogPanic and LogFatal entries passed to it. - LogWarning - - // LogInfo tells a logger to log all LogInfo, LogWarning, LogError, LogPanic and LogFatal entries passed to it. - LogInfo - - // LogDebug tells a logger to log all LogDebug, LogInfo, LogWarning, LogError, LogPanic and LogFatal entries passed to it. - LogDebug - - // LogAuth is a special case of LogDebug, it tells a logger to also log the body of an authentication request and response. - // NOTE: this can disclose sensitive information, use with care. - LogAuth -) - -const ( - logNone = "NONE" - logFatal = "FATAL" - logPanic = "PANIC" - logError = "ERROR" - logWarning = "WARNING" - logInfo = "INFO" - logDebug = "DEBUG" - logAuth = "AUTH" - logUnknown = "UNKNOWN" -) - -// ParseLevel converts the specified string into the corresponding LevelType. -func ParseLevel(s string) (lt LevelType, err error) { - switch strings.ToUpper(s) { - case logFatal: - lt = LogFatal - case logPanic: - lt = LogPanic - case logError: - lt = LogError - case logWarning: - lt = LogWarning - case logInfo: - lt = LogInfo - case logDebug: - lt = LogDebug - case logAuth: - lt = LogAuth - default: - err = fmt.Errorf("bad log level '%s'", s) - } - return -} - -// String implements the stringer interface for LevelType. -func (lt LevelType) String() string { - switch lt { - case LogNone: - return logNone - case LogFatal: - return logFatal - case LogPanic: - return logPanic - case LogError: - return logError - case LogWarning: - return logWarning - case LogInfo: - return logInfo - case LogDebug: - return logDebug - case LogAuth: - return logAuth - default: - return logUnknown - } -} - -// Filter defines functions for filtering HTTP request/response content. -type Filter struct { - // URL returns a potentially modified string representation of a request URL. - URL func(u *url.URL) string - - // Header returns a potentially modified set of values for the specified key. - // To completely exclude the header key/values return false. - Header func(key string, val []string) (bool, []string) - - // Body returns a potentially modified request/response body. - Body func(b []byte) []byte -} - -func (f Filter) processURL(u *url.URL) string { - if f.URL == nil { - return u.String() - } - return f.URL(u) -} - -func (f Filter) processHeader(k string, val []string) (bool, []string) { - if f.Header == nil { - return true, val - } - return f.Header(k, val) -} - -func (f Filter) processBody(b []byte) []byte { - if f.Body == nil { - return b - } - return f.Body(b) -} - -// Writer defines methods for writing to a logging facility. -type Writer interface { - // Writeln writes the specified message with the standard log entry header and new-line character. - Writeln(level LevelType, message string) - - // Writef writes the specified format specifier with the standard log entry header and no new-line character. - Writef(level LevelType, format string, a ...interface{}) - - // WriteRequest writes the specified HTTP request to the logger if the log level is greater than - // or equal to LogInfo. The request body, if set, is logged at level LogDebug or higher. - // Custom filters can be specified to exclude URL, header, and/or body content from the log. - // By default no request content is excluded. - WriteRequest(req *http.Request, filter Filter) - - // WriteResponse writes the specified HTTP response to the logger if the log level is greater than - // or equal to LogInfo. The response body, if set, is logged at level LogDebug or higher. - // Custom filters can be specified to exclude URL, header, and/or body content from the log. - // By default no response content is excluded. - WriteResponse(resp *http.Response, filter Filter) -} - -// Instance is the default log writer initialized during package init. -// This can be replaced with a custom implementation as required. -var Instance Writer - -// default log level -var logLevel = LogNone - -// Level returns the value specified in AZURE_GO_AUTOREST_LOG_LEVEL. -// If no value was specified the default value is LogNone. -// Custom loggers can call this to retrieve the configured log level. -func Level() LevelType { - return logLevel -} - -func init() { - // separated for testing purposes - initDefaultLogger() -} - -func initDefaultLogger() { - // init with nilLogger so callers don't have to do a nil check on Default - Instance = nilLogger{} - llStr := strings.ToLower(os.Getenv("AZURE_GO_SDK_LOG_LEVEL")) - if llStr == "" { - return - } - var err error - logLevel, err = ParseLevel(llStr) - if err != nil { - fmt.Fprintf(os.Stderr, "go-autorest: failed to parse log level: %s\n", err.Error()) - return - } - if logLevel == LogNone { - return - } - // default to stderr - dest := os.Stderr - lfStr := os.Getenv("AZURE_GO_SDK_LOG_FILE") - if strings.EqualFold(lfStr, "stdout") { - dest = os.Stdout - } else if lfStr != "" { - lf, err := os.Create(lfStr) - if err == nil { - dest = lf - } else { - fmt.Fprintf(os.Stderr, "go-autorest: failed to create log file, using stderr: %s\n", err.Error()) - } - } - Instance = fileLogger{ - logLevel: logLevel, - mu: &sync.Mutex{}, - logFile: dest, - } -} - -// the nil logger does nothing -type nilLogger struct{} - -func (nilLogger) Writeln(LevelType, string) {} - -func (nilLogger) Writef(LevelType, string, ...interface{}) {} - -func (nilLogger) WriteRequest(*http.Request, Filter) {} - -func (nilLogger) WriteResponse(*http.Response, Filter) {} - -// A File is used instead of a Logger so the stream can be flushed after every write. -type fileLogger struct { - logLevel LevelType - mu *sync.Mutex // for synchronizing writes to logFile - logFile *os.File -} - -func (fl fileLogger) Writeln(level LevelType, message string) { - fl.Writef(level, "%s\n", message) -} - -func (fl fileLogger) Writef(level LevelType, format string, a ...interface{}) { - if fl.logLevel >= level { - fl.mu.Lock() - defer fl.mu.Unlock() - fmt.Fprintf(fl.logFile, "%s %s", entryHeader(level), fmt.Sprintf(format, a...)) - fl.logFile.Sync() - } -} - -func (fl fileLogger) WriteRequest(req *http.Request, filter Filter) { - if req == nil || fl.logLevel < LogInfo { - return - } - b := &bytes.Buffer{} - fmt.Fprintf(b, "%s REQUEST: %s %s\n", entryHeader(LogInfo), req.Method, filter.processURL(req.URL)) - // dump headers - for k, v := range req.Header { - if ok, mv := filter.processHeader(k, v); ok { - fmt.Fprintf(b, "%s: %s\n", k, strings.Join(mv, ",")) - } - } - if fl.shouldLogBody(req.Header, req.Body) { - // dump body - body, err := ioutil.ReadAll(req.Body) - if err == nil { - fmt.Fprintln(b, string(filter.processBody(body))) - if nc, ok := req.Body.(io.Seeker); ok { - // rewind to the beginning - nc.Seek(0, io.SeekStart) - } else { - // recreate the body - req.Body = ioutil.NopCloser(bytes.NewReader(body)) - } - } else { - fmt.Fprintf(b, "failed to read body: %v\n", err) - } - } - fl.mu.Lock() - defer fl.mu.Unlock() - fmt.Fprint(fl.logFile, b.String()) - fl.logFile.Sync() -} - -func (fl fileLogger) WriteResponse(resp *http.Response, filter Filter) { - if resp == nil || fl.logLevel < LogInfo { - return - } - b := &bytes.Buffer{} - fmt.Fprintf(b, "%s RESPONSE: %d %s\n", entryHeader(LogInfo), resp.StatusCode, filter.processURL(resp.Request.URL)) - // dump headers - for k, v := range resp.Header { - if ok, mv := filter.processHeader(k, v); ok { - fmt.Fprintf(b, "%s: %s\n", k, strings.Join(mv, ",")) - } - } - if fl.shouldLogBody(resp.Header, resp.Body) { - // dump body - defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) - if err == nil { - fmt.Fprintln(b, string(filter.processBody(body))) - resp.Body = ioutil.NopCloser(bytes.NewReader(body)) - } else { - fmt.Fprintf(b, "failed to read body: %v\n", err) - } - } - fl.mu.Lock() - defer fl.mu.Unlock() - fmt.Fprint(fl.logFile, b.String()) - fl.logFile.Sync() -} - -// returns true if the provided body should be included in the log -func (fl fileLogger) shouldLogBody(header http.Header, body io.ReadCloser) bool { - ct := header.Get("Content-Type") - return fl.logLevel >= LogDebug && body != nil && !strings.Contains(ct, "application/octet-stream") -} - -// creates standard header for log entries, it contains a timestamp and the log level -func entryHeader(level LevelType) string { - // this format provides a fixed number of digits so the size of the timestamp is constant - return fmt.Sprintf("(%s) %s:", time.Now().Format("2006-01-02T15:04:05.0000000Z07:00"), level.String()) -} diff --git a/vendor/github.com/Azure/go-autorest/tracing/LICENSE b/vendor/github.com/Azure/go-autorest/tracing/LICENSE deleted file mode 100644 index b9d6a27ea9..0000000000 --- a/vendor/github.com/Azure/go-autorest/tracing/LICENSE +++ /dev/null @@ -1,191 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - Copyright 2015 Microsoft Corporation - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/Azure/go-autorest/tracing/go_mod_tidy_hack.go b/vendor/github.com/Azure/go-autorest/tracing/go_mod_tidy_hack.go deleted file mode 100644 index e163975cd4..0000000000 --- a/vendor/github.com/Azure/go-autorest/tracing/go_mod_tidy_hack.go +++ /dev/null @@ -1,24 +0,0 @@ -// +build modhack - -package tracing - -// Copyright 2017 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// This file, and the github.com/Azure/go-autorest import, won't actually become part of -// the resultant binary. - -// Necessary for safely adding multi-module repo. -// See: https://github.com/golang/go/wiki/Modules#is-it-possible-to-add-a-module-to-a-multi-module-repository -import _ "github.com/Azure/go-autorest" diff --git a/vendor/github.com/Azure/go-autorest/tracing/tracing.go b/vendor/github.com/Azure/go-autorest/tracing/tracing.go deleted file mode 100644 index 0e7a6e9625..0000000000 --- a/vendor/github.com/Azure/go-autorest/tracing/tracing.go +++ /dev/null @@ -1,67 +0,0 @@ -package tracing - -// Copyright 2018 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import ( - "context" - "net/http" -) - -// Tracer represents an HTTP tracing facility. -type Tracer interface { - NewTransport(base *http.Transport) http.RoundTripper - StartSpan(ctx context.Context, name string) context.Context - EndSpan(ctx context.Context, httpStatusCode int, err error) -} - -var ( - tracer Tracer -) - -// Register will register the provided Tracer. Pass nil to unregister a Tracer. -func Register(t Tracer) { - tracer = t -} - -// IsEnabled returns true if a Tracer has been registered. -func IsEnabled() bool { - return tracer != nil -} - -// NewTransport creates a new instrumenting http.RoundTripper for the -// registered Tracer. If no Tracer has been registered it returns nil. -func NewTransport(base *http.Transport) http.RoundTripper { - if tracer != nil { - return tracer.NewTransport(base) - } - return nil -} - -// StartSpan starts a trace span with the specified name, associating it with the -// provided context. Has no effect if a Tracer has not been registered. -func StartSpan(ctx context.Context, name string) context.Context { - if tracer != nil { - return tracer.StartSpan(ctx, name) - } - return ctx -} - -// EndSpan ends a previously started span stored in the context. -// Has no effect if a Tracer has not been registered. -func EndSpan(ctx context.Context, httpStatusCode int, err error) { - if tracer != nil { - tracer.EndSpan(ctx, httpStatusCode, err) - } -} diff --git a/vendor/github.com/BurntSushi/toml/.gitignore b/vendor/github.com/BurntSushi/toml/.gitignore index cd11be9653..fe79e3adda 100644 --- a/vendor/github.com/BurntSushi/toml/.gitignore +++ b/vendor/github.com/BurntSushi/toml/.gitignore @@ -1,2 +1,2 @@ -toml.test +/toml.test /toml-test diff --git a/vendor/github.com/BurntSushi/toml/COMPATIBLE b/vendor/github.com/BurntSushi/toml/COMPATIBLE deleted file mode 100644 index f621b01196..0000000000 --- a/vendor/github.com/BurntSushi/toml/COMPATIBLE +++ /dev/null @@ -1 +0,0 @@ -Compatible with TOML version [v1.0.0](https://toml.io/en/v1.0.0). diff --git a/vendor/github.com/BurntSushi/toml/README.md b/vendor/github.com/BurntSushi/toml/README.md index cc13f8667f..3651cfa960 100644 --- a/vendor/github.com/BurntSushi/toml/README.md +++ b/vendor/github.com/BurntSushi/toml/README.md @@ -1,6 +1,5 @@ TOML stands for Tom's Obvious, Minimal Language. This Go package provides a -reflection interface similar to Go's standard library `json` and `xml` -packages. +reflection interface similar to Go's standard library `json` and `xml` packages. Compatible with TOML version [v1.0.0](https://toml.io/en/v1.0.0). @@ -10,7 +9,7 @@ See the [releases page](https://github.com/BurntSushi/toml/releases) for a changelog; this information is also in the git tag annotations (e.g. `git show v0.4.0`). -This library requires Go 1.13 or newer; install it with: +This library requires Go 1.13 or newer; add it to your go.mod with: % go get github.com/BurntSushi/toml@latest @@ -19,16 +18,7 @@ It also comes with a TOML validator CLI tool: % go install github.com/BurntSushi/toml/cmd/tomlv@latest % tomlv some-toml-file.toml -### Testing -This package passes all tests in [toml-test] for both the decoder and the -encoder. - -[toml-test]: https://github.com/BurntSushi/toml-test - ### Examples -This package works similar to how the Go standard library handles XML and JSON. -Namely, data is loaded into Go values via reflection. - For the simplest example, consider some TOML file as just a list of keys and values: @@ -40,7 +30,7 @@ Perfection = [ 6, 28, 496, 8128 ] DOB = 1987-07-05T05:45:00Z ``` -Which could be defined in Go as: +Which can be decoded with: ```go type Config struct { @@ -48,20 +38,15 @@ type Config struct { Cats []string Pi float64 Perfection []int - DOB time.Time // requires `import time` + DOB time.Time } -``` - -And then decoded with: -```go var conf Config -err := toml.Decode(tomlData, &conf) -// handle error +_, err := toml.Decode(tomlData, &conf) ``` -You can also use struct tags if your struct field name doesn't map to a TOML -key value directly: +You can also use struct tags if your struct field name doesn't map to a TOML key +value directly: ```toml some_key_NAME = "wat" @@ -73,139 +58,63 @@ type TOML struct { } ``` -Beware that like other most other decoders **only exported fields** are -considered when encoding and decoding; private fields are silently ignored. +Beware that like other decoders **only exported fields** are considered when +encoding and decoding; private fields are silently ignored. ### Using the `Marshaler` and `encoding.TextUnmarshaler` interfaces -Here's an example that automatically parses duration strings into -`time.Duration` values: +Here's an example that automatically parses values in a `mail.Address`: ```toml -[[song]] -name = "Thunder Road" -duration = "4m49s" - -[[song]] -name = "Stairway to Heaven" -duration = "8m03s" -``` - -Which can be decoded with: - -```go -type song struct { - Name string - Duration duration -} -type songs struct { - Song []song -} -var favorites songs -if _, err := toml.Decode(blob, &favorites); err != nil { - log.Fatal(err) -} - -for _, s := range favorites.Song { - fmt.Printf("%s (%s)\n", s.Name, s.Duration) -} +contacts = [ + "Donald Duck ", + "Scrooge McDuck ", +] ``` -And you'll also need a `duration` type that satisfies the -`encoding.TextUnmarshaler` interface: +Can be decoded with: ```go -type duration struct { - time.Duration +// Create address type which satisfies the encoding.TextUnmarshaler interface. +type address struct { + *mail.Address } -func (d *duration) UnmarshalText(text []byte) error { +func (a *address) UnmarshalText(text []byte) error { var err error - d.Duration, err = time.ParseDuration(string(text)) + a.Address, err = mail.ParseAddress(string(text)) return err } + +// Decode it. +func decode() { + blob := ` + contacts = [ + "Donald Duck ", + "Scrooge McDuck ", + ] + ` + + var contacts struct { + Contacts []address + } + + _, err := toml.Decode(blob, &contacts) + if err != nil { + log.Fatal(err) + } + + for _, c := range contacts.Contacts { + fmt.Printf("%#v\n", c.Address) + } + + // Output: + // &mail.Address{Name:"Donald Duck", Address:"donald@duckburg.com"} + // &mail.Address{Name:"Scrooge McDuck", Address:"scrooge@duckburg.com"} +} ``` To target TOML specifically you can implement `UnmarshalTOML` TOML interface in a similar way. ### More complex usage -Here's an example of how to load the example from the official spec page: - -```toml -# This is a TOML document. Boom. - -title = "TOML Example" - -[owner] -name = "Tom Preston-Werner" -organization = "GitHub" -bio = "GitHub Cofounder & CEO\nLikes tater tots and beer." -dob = 1979-05-27T07:32:00Z # First class dates? Why not? - -[database] -server = "192.168.1.1" -ports = [ 8001, 8001, 8002 ] -connection_max = 5000 -enabled = true - -[servers] - - # You can indent as you please. Tabs or spaces. TOML don't care. - [servers.alpha] - ip = "10.0.0.1" - dc = "eqdc10" - - [servers.beta] - ip = "10.0.0.2" - dc = "eqdc10" - -[clients] -data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it - -# Line breaks are OK when inside arrays -hosts = [ - "alpha", - "omega" -] -``` - -And the corresponding Go types are: - -```go -type tomlConfig struct { - Title string - Owner ownerInfo - DB database `toml:"database"` - Servers map[string]server - Clients clients -} - -type ownerInfo struct { - Name string - Org string `toml:"organization"` - Bio string - DOB time.Time -} - -type database struct { - Server string - Ports []int - ConnMax int `toml:"connection_max"` - Enabled bool -} - -type server struct { - IP string - DC string -} - -type clients struct { - Data [][]interface{} - Hosts []string -} -``` - -Note that a case insensitive match will be tried if an exact match can't be -found. - -A working example of the above can be found in `_example/example.{go,toml}`. +See the [`_example/`](/_example) directory for a more complex example. diff --git a/vendor/github.com/BurntSushi/toml/decode.go b/vendor/github.com/BurntSushi/toml/decode.go index e24f0c5d5c..0ca1dc4fee 100644 --- a/vendor/github.com/BurntSushi/toml/decode.go +++ b/vendor/github.com/BurntSushi/toml/decode.go @@ -1,14 +1,18 @@ package toml import ( + "bytes" "encoding" + "encoding/json" "fmt" "io" "io/ioutil" "math" "os" "reflect" + "strconv" "strings" + "time" ) // Unmarshaler is the interface implemented by objects that can unmarshal a @@ -17,16 +21,35 @@ type Unmarshaler interface { UnmarshalTOML(interface{}) error } -// Unmarshal decodes the contents of `p` in TOML format into a pointer `v`. -func Unmarshal(p []byte, v interface{}) error { - _, err := Decode(string(p), v) +// Unmarshal decodes the contents of data in TOML format into a pointer v. +// +// See [Decoder] for a description of the decoding process. +func Unmarshal(data []byte, v interface{}) error { + _, err := NewDecoder(bytes.NewReader(data)).Decode(v) return err } +// Decode the TOML data in to the pointer v. +// +// See [Decoder] for a description of the decoding process. +func Decode(data string, v interface{}) (MetaData, error) { + return NewDecoder(strings.NewReader(data)).Decode(v) +} + +// DecodeFile reads the contents of a file and decodes it with [Decode]. +func DecodeFile(path string, v interface{}) (MetaData, error) { + fp, err := os.Open(path) + if err != nil { + return MetaData{}, err + } + defer fp.Close() + return NewDecoder(fp).Decode(v) +} + // Primitive is a TOML value that hasn't been decoded into a Go value. // // This type can be used for any value, which will cause decoding to be delayed. -// You can use the PrimitiveDecode() function to "manually" decode these values. +// You can use [PrimitiveDecode] to "manually" decode these values. // // NOTE: The underlying representation of a `Primitive` value is subject to // change. Do not rely on it. @@ -42,36 +65,22 @@ type Primitive struct { // The significand precision for float32 and float64 is 24 and 53 bits; this is // the range a natural number can be stored in a float without loss of data. const ( - maxSafeFloat32Int = 16777215 // 2^24-1 - maxSafeFloat64Int = 9007199254740991 // 2^53-1 + maxSafeFloat32Int = 16777215 // 2^24-1 + maxSafeFloat64Int = int64(9007199254740991) // 2^53-1 ) -// PrimitiveDecode is just like the other `Decode*` functions, except it -// decodes a TOML value that has already been parsed. Valid primitive values -// can *only* be obtained from values filled by the decoder functions, -// including this method. (i.e., `v` may contain more `Primitive` -// values.) -// -// Meta data for primitive values is included in the meta data returned by -// the `Decode*` functions with one exception: keys returned by the Undecoded -// method will only reflect keys that were decoded. Namely, any keys hidden -// behind a Primitive will be considered undecoded. Executing this method will -// update the undecoded keys in the meta data. (See the example.) -func (md *MetaData) PrimitiveDecode(primValue Primitive, v interface{}) error { - md.context = primValue.context - defer func() { md.context = nil }() - return md.unify(primValue.undecoded, rvalue(v)) -} - // Decoder decodes TOML data. // -// TOML tables correspond to Go structs or maps (dealer's choice – they can be -// used interchangeably). +// TOML tables correspond to Go structs or maps; they can be used +// interchangeably, but structs offer better type safety. // // TOML table arrays correspond to either a slice of structs or a slice of maps. // -// TOML datetimes correspond to Go time.Time values. Local datetimes are parsed -// in the local timezone. +// TOML datetimes correspond to [time.Time]. Local datetimes are parsed in the +// local timezone. +// +// [time.Duration] types are treated as nanoseconds if the TOML value is an +// integer, or they're parsed with time.ParseDuration() if they're strings. // // All other TOML types (float, string, int, bool and array) correspond to the // obvious Go types. @@ -80,9 +89,9 @@ func (md *MetaData) PrimitiveDecode(primValue Primitive, v interface{}) error { // interface, in which case any primitive TOML value (floats, strings, integers, // booleans, datetimes) will be converted to a []byte and given to the value's // UnmarshalText method. See the Unmarshaler example for a demonstration with -// time duration strings. +// email addresses. // -// Key mapping +// ### Key mapping // // TOML keys can map to either keys in a Go map or field names in a Go struct. // The special `toml` struct tag can be used to map TOML keys to struct fields @@ -109,6 +118,7 @@ func NewDecoder(r io.Reader) *Decoder { var ( unmarshalToml = reflect.TypeOf((*Unmarshaler)(nil)).Elem() unmarshalText = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem() + primitiveType = reflect.TypeOf((*Primitive)(nil)).Elem() ) // Decode TOML data in to the pointer `v`. @@ -120,10 +130,10 @@ func (dec *Decoder) Decode(v interface{}) (MetaData, error) { s = "%v" } - return MetaData{}, e("cannot decode to non-pointer "+s, reflect.TypeOf(v)) + return MetaData{}, fmt.Errorf("toml: cannot decode to non-pointer "+s, reflect.TypeOf(v)) } if rv.IsNil() { - return MetaData{}, e("cannot decode to nil value of %q", reflect.TypeOf(v)) + return MetaData{}, fmt.Errorf("toml: cannot decode to nil value of %q", reflect.TypeOf(v)) } // Check if this is a supported type: struct, map, interface{}, or something @@ -133,7 +143,7 @@ func (dec *Decoder) Decode(v interface{}) (MetaData, error) { if rv.Kind() != reflect.Struct && rv.Kind() != reflect.Map && !(rv.Kind() == reflect.Interface && rv.NumMethod() == 0) && !rt.Implements(unmarshalToml) && !rt.Implements(unmarshalText) { - return MetaData{}, e("cannot decode to type %s", rt) + return MetaData{}, fmt.Errorf("toml: cannot decode to type %s", rt) } // TODO: parser should read from io.Reader? Or at the very least, make it @@ -150,30 +160,29 @@ func (dec *Decoder) Decode(v interface{}) (MetaData, error) { md := MetaData{ mapping: p.mapping, - types: p.types, + keyInfo: p.keyInfo, keys: p.ordered, decoded: make(map[string]struct{}, len(p.ordered)), context: nil, + data: data, } return md, md.unify(p.mapping, rv) } -// Decode the TOML data in to the pointer v. +// PrimitiveDecode is just like the other Decode* functions, except it decodes a +// TOML value that has already been parsed. Valid primitive values can *only* be +// obtained from values filled by the decoder functions, including this method. +// (i.e., v may contain more [Primitive] values.) // -// See the documentation on Decoder for a description of the decoding process. -func Decode(data string, v interface{}) (MetaData, error) { - return NewDecoder(strings.NewReader(data)).Decode(v) -} - -// DecodeFile is just like Decode, except it will automatically read the -// contents of the file at path and decode it for you. -func DecodeFile(path string, v interface{}) (MetaData, error) { - fp, err := os.Open(path) - if err != nil { - return MetaData{}, err - } - defer fp.Close() - return NewDecoder(fp).Decode(v) +// Meta data for primitive values is included in the meta data returned by the +// Decode* functions with one exception: keys returned by the Undecoded method +// will only reflect keys that were decoded. Namely, any keys hidden behind a +// Primitive will be considered undecoded. Executing this method will update the +// undecoded keys in the meta data. (See the example.) +func (md *MetaData) PrimitiveDecode(primValue Primitive, v interface{}) error { + md.context = primValue.context + defer func() { md.context = nil }() + return md.unify(primValue.undecoded, rvalue(v)) } // unify performs a sort of type unification based on the structure of `rv`, @@ -184,7 +193,7 @@ func DecodeFile(path string, v interface{}) (MetaData, error) { func (md *MetaData) unify(data interface{}, rv reflect.Value) error { // Special case. Look for a `Primitive` value. // TODO: #76 would make this superfluous after implemented. - if rv.Type() == reflect.TypeOf((*Primitive)(nil)).Elem() { + if rv.Type() == primitiveType { // Save the undecoded data and the key context into the primitive // value. context := make(Key, len(md.context)) @@ -196,17 +205,14 @@ func (md *MetaData) unify(data interface{}, rv reflect.Value) error { return nil } - // Special case. Unmarshaler Interface support. - if rv.CanAddr() { - if v, ok := rv.Addr().Interface().(Unmarshaler); ok { - return v.UnmarshalTOML(data) - } + rvi := rv.Interface() + if v, ok := rvi.(Unmarshaler); ok { + return v.UnmarshalTOML(data) } - - // Special case. Look for a value satisfying the TextUnmarshaler interface. - if v, ok := rv.Interface().(encoding.TextUnmarshaler); ok { + if v, ok := rvi.(encoding.TextUnmarshaler); ok { return md.unifyText(data, v) } + // TODO: // The behavior here is incorrect whenever a Go type satisfies the // encoding.TextUnmarshaler interface but also corresponds to a TOML hash or @@ -217,7 +223,6 @@ func (md *MetaData) unify(data interface{}, rv reflect.Value) error { k := rv.Kind() - // laziness if k >= reflect.Int && k <= reflect.Uint64 { return md.unifyInt(data, rv) } @@ -243,15 +248,14 @@ func (md *MetaData) unify(data interface{}, rv reflect.Value) error { case reflect.Bool: return md.unifyBool(data, rv) case reflect.Interface: - // we only support empty interfaces. - if rv.NumMethod() > 0 { - return e("unsupported type %s", rv.Type()) + if rv.NumMethod() > 0 { // Only support empty interfaces are supported. + return md.e("unsupported type %s", rv.Type()) } return md.unifyAnything(data, rv) case reflect.Float32, reflect.Float64: return md.unifyFloat64(data, rv) } - return e("unsupported type %s", rv.Kind()) + return md.e("unsupported type %s", rv.Kind()) } func (md *MetaData) unifyStruct(mapping interface{}, rv reflect.Value) error { @@ -260,7 +264,7 @@ func (md *MetaData) unifyStruct(mapping interface{}, rv reflect.Value) error { if mapping == nil { return nil } - return e("type mismatch for %s: expected table but found %T", + return md.e("type mismatch for %s: expected table but found %T", rv.Type().String(), mapping) } @@ -286,13 +290,14 @@ func (md *MetaData) unifyStruct(mapping interface{}, rv reflect.Value) error { if isUnifiable(subv) { md.decoded[md.context.add(key).String()] = struct{}{} md.context = append(md.context, key) + err := md.unify(datum, subv) if err != nil { return err } md.context = md.context[0 : len(md.context)-1] } else if f.name != "" { - return e("cannot write unexported field %s.%s", rv.Type().String(), f.name) + return md.e("cannot write unexported field %s.%s", rv.Type().String(), f.name) } } } @@ -300,10 +305,10 @@ func (md *MetaData) unifyStruct(mapping interface{}, rv reflect.Value) error { } func (md *MetaData) unifyMap(mapping interface{}, rv reflect.Value) error { - if k := rv.Type().Key().Kind(); k != reflect.String { - return fmt.Errorf( - "toml: cannot decode to a map with non-string key type (%s in %q)", - k, rv.Type()) + keyType := rv.Type().Key().Kind() + if keyType != reflect.String && keyType != reflect.Interface { + return fmt.Errorf("toml: cannot decode to a map with non-string key type (%s in %q)", + keyType, rv.Type()) } tmap, ok := mapping.(map[string]interface{}) @@ -321,13 +326,22 @@ func (md *MetaData) unifyMap(mapping interface{}, rv reflect.Value) error { md.context = append(md.context, k) rvval := reflect.Indirect(reflect.New(rv.Type().Elem())) - if err := md.unify(v, rvval); err != nil { + + err := md.unify(v, indirect(rvval)) + if err != nil { return err } md.context = md.context[0 : len(md.context)-1] rvkey := indirect(reflect.New(rv.Type().Key())) - rvkey.SetString(k) + + switch keyType { + case reflect.Interface: + rvkey.Set(reflect.ValueOf(k)) + case reflect.String: + rvkey.SetString(k) + } + rv.SetMapIndex(rvkey, rvval) } return nil @@ -342,7 +356,7 @@ func (md *MetaData) unifyArray(data interface{}, rv reflect.Value) error { return md.badtype("slice", data) } if l := datav.Len(); l != rv.Len() { - return e("expected array length %d; got TOML array of length %d", rv.Len(), l) + return md.e("expected array length %d; got TOML array of length %d", rv.Len(), l) } return md.unifySliceArray(datav, rv) } @@ -375,6 +389,18 @@ func (md *MetaData) unifySliceArray(data, rv reflect.Value) error { } func (md *MetaData) unifyString(data interface{}, rv reflect.Value) error { + _, ok := rv.Interface().(json.Number) + if ok { + if i, ok := data.(int64); ok { + rv.SetString(strconv.FormatInt(i, 10)) + } else if f, ok := data.(float64); ok { + rv.SetString(strconv.FormatFloat(f, 'f', -1, 64)) + } else { + return md.badtype("string", data) + } + return nil + } + if s, ok := data.(string); ok { rv.SetString(s) return nil @@ -383,11 +409,13 @@ func (md *MetaData) unifyString(data interface{}, rv reflect.Value) error { } func (md *MetaData) unifyFloat64(data interface{}, rv reflect.Value) error { + rvk := rv.Kind() + if num, ok := data.(float64); ok { - switch rv.Kind() { + switch rvk { case reflect.Float32: if num < -math.MaxFloat32 || num > math.MaxFloat32 { - return e("value %f is out of range for float32", num) + return md.parseErr(errParseRange{i: num, size: rvk.String()}) } fallthrough case reflect.Float64: @@ -399,20 +427,11 @@ func (md *MetaData) unifyFloat64(data interface{}, rv reflect.Value) error { } if num, ok := data.(int64); ok { - switch rv.Kind() { - case reflect.Float32: - if num < -maxSafeFloat32Int || num > maxSafeFloat32Int { - return e("value %d is out of range for float32", num) - } - fallthrough - case reflect.Float64: - if num < -maxSafeFloat64Int || num > maxSafeFloat64Int { - return e("value %d is out of range for float64", num) - } - rv.SetFloat(float64(num)) - default: - panic("bug") + if (rvk == reflect.Float32 && (num < -maxSafeFloat32Int || num > maxSafeFloat32Int)) || + (rvk == reflect.Float64 && (num < -maxSafeFloat64Int || num > maxSafeFloat64Int)) { + return md.parseErr(errParseRange{i: num, size: rvk.String()}) } + rv.SetFloat(float64(num)) return nil } @@ -420,50 +439,46 @@ func (md *MetaData) unifyFloat64(data interface{}, rv reflect.Value) error { } func (md *MetaData) unifyInt(data interface{}, rv reflect.Value) error { - if num, ok := data.(int64); ok { - if rv.Kind() >= reflect.Int && rv.Kind() <= reflect.Int64 { - switch rv.Kind() { - case reflect.Int, reflect.Int64: - // No bounds checking necessary. - case reflect.Int8: - if num < math.MinInt8 || num > math.MaxInt8 { - return e("value %d is out of range for int8", num) - } - case reflect.Int16: - if num < math.MinInt16 || num > math.MaxInt16 { - return e("value %d is out of range for int16", num) - } - case reflect.Int32: - if num < math.MinInt32 || num > math.MaxInt32 { - return e("value %d is out of range for int32", num) - } + _, ok := rv.Interface().(time.Duration) + if ok { + // Parse as string duration, and fall back to regular integer parsing + // (as nanosecond) if this is not a string. + if s, ok := data.(string); ok { + dur, err := time.ParseDuration(s) + if err != nil { + return md.parseErr(errParseDuration{s}) } - rv.SetInt(num) - } else if rv.Kind() >= reflect.Uint && rv.Kind() <= reflect.Uint64 { - unum := uint64(num) - switch rv.Kind() { - case reflect.Uint, reflect.Uint64: - // No bounds checking necessary. - case reflect.Uint8: - if num < 0 || unum > math.MaxUint8 { - return e("value %d is out of range for uint8", num) - } - case reflect.Uint16: - if num < 0 || unum > math.MaxUint16 { - return e("value %d is out of range for uint16", num) - } - case reflect.Uint32: - if num < 0 || unum > math.MaxUint32 { - return e("value %d is out of range for uint32", num) - } - } - rv.SetUint(unum) - } else { - panic("unreachable") + rv.SetInt(int64(dur)) + return nil } - return nil } - return md.badtype("integer", data) + + num, ok := data.(int64) + if !ok { + return md.badtype("integer", data) + } + + rvk := rv.Kind() + switch { + case rvk >= reflect.Int && rvk <= reflect.Int64: + if (rvk == reflect.Int8 && (num < math.MinInt8 || num > math.MaxInt8)) || + (rvk == reflect.Int16 && (num < math.MinInt16 || num > math.MaxInt16)) || + (rvk == reflect.Int32 && (num < math.MinInt32 || num > math.MaxInt32)) { + return md.parseErr(errParseRange{i: num, size: rvk.String()}) + } + rv.SetInt(num) + case rvk >= reflect.Uint && rvk <= reflect.Uint64: + unum := uint64(num) + if rvk == reflect.Uint8 && (num < 0 || unum > math.MaxUint8) || + rvk == reflect.Uint16 && (num < 0 || unum > math.MaxUint16) || + rvk == reflect.Uint32 && (num < 0 || unum > math.MaxUint32) { + return md.parseErr(errParseRange{i: num, size: rvk.String()}) + } + rv.SetUint(unum) + default: + panic("unreachable") + } + return nil } func (md *MetaData) unifyBool(data interface{}, rv reflect.Value) error { @@ -488,7 +503,7 @@ func (md *MetaData) unifyText(data interface{}, v encoding.TextUnmarshaler) erro return err } s = string(text) - case TextMarshaler: + case encoding.TextMarshaler: text, err := sdata.MarshalText() if err != nil { return err @@ -514,7 +529,30 @@ func (md *MetaData) unifyText(data interface{}, v encoding.TextUnmarshaler) erro } func (md *MetaData) badtype(dst string, data interface{}) error { - return e("incompatible types: TOML key %q has type %T; destination has type %s", md.context, data, dst) + return md.e("incompatible types: TOML value has type %T; destination has type %s", data, dst) +} + +func (md *MetaData) parseErr(err error) error { + k := md.context.String() + return ParseError{ + LastKey: k, + Position: md.keyInfo[k].pos, + Line: md.keyInfo[k].pos.Line, + err: err, + input: string(md.data), + } +} + +func (md *MetaData) e(format string, args ...interface{}) error { + f := "toml: " + if len(md.context) > 0 { + f = fmt.Sprintf("toml: (last key %q): ", md.context) + p := md.keyInfo[md.context.String()].pos + if p.Line > 0 { + f = fmt.Sprintf("toml: line %d (last key %q): ", p.Line, md.context) + } + } + return fmt.Errorf(f+format, args...) } // rvalue returns a reflect.Value of `v`. All pointers are resolved. @@ -533,7 +571,11 @@ func indirect(v reflect.Value) reflect.Value { if v.Kind() != reflect.Ptr { if v.CanSet() { pv := v.Addr() - if _, ok := pv.Interface().(encoding.TextUnmarshaler); ok { + pvi := pv.Interface() + if _, ok := pvi.(encoding.TextUnmarshaler); ok { + return pv + } + if _, ok := pvi.(Unmarshaler); ok { return pv } } @@ -549,12 +591,12 @@ func isUnifiable(rv reflect.Value) bool { if rv.CanSet() { return true } - if _, ok := rv.Interface().(encoding.TextUnmarshaler); ok { + rvi := rv.Interface() + if _, ok := rvi.(encoding.TextUnmarshaler); ok { + return true + } + if _, ok := rvi.(Unmarshaler); ok { return true } return false } - -func e(format string, args ...interface{}) error { - return fmt.Errorf("toml: "+format, args...) -} diff --git a/vendor/github.com/BurntSushi/toml/decode_go116.go b/vendor/github.com/BurntSushi/toml/decode_go116.go index eddfb641b8..086d0b6866 100644 --- a/vendor/github.com/BurntSushi/toml/decode_go116.go +++ b/vendor/github.com/BurntSushi/toml/decode_go116.go @@ -7,8 +7,8 @@ import ( "io/fs" ) -// DecodeFS is just like Decode, except it will automatically read the contents -// of the file at `path` from a fs.FS instance. +// DecodeFS reads the contents of a file from [fs.FS] and decodes it with +// [Decode]. func DecodeFS(fsys fs.FS, path string, v interface{}) (MetaData, error) { fp, err := fsys.Open(path) if err != nil { diff --git a/vendor/github.com/BurntSushi/toml/doc.go b/vendor/github.com/BurntSushi/toml/doc.go index 099c4a77d2..81a7c0fe9f 100644 --- a/vendor/github.com/BurntSushi/toml/doc.go +++ b/vendor/github.com/BurntSushi/toml/doc.go @@ -1,13 +1,11 @@ -/* -Package toml implements decoding and encoding of TOML files. - -This package supports TOML v1.0.0, as listed on https://toml.io - -There is also support for delaying decoding with the Primitive type, and -querying the set of keys in a TOML document with the MetaData type. - -The github.com/BurntSushi/toml/cmd/tomlv package implements a TOML validator, -and can be used to verify if TOML document is valid. It can also be used to -print the type of each key. -*/ +// Package toml implements decoding and encoding of TOML files. +// +// This package supports TOML v1.0.0, as specified at https://toml.io +// +// There is also support for delaying decoding with the Primitive type, and +// querying the set of keys in a TOML document with the MetaData type. +// +// The github.com/BurntSushi/toml/cmd/tomlv package implements a TOML validator, +// and can be used to verify if TOML document is valid. It can also be used to +// print the type of each key. package toml diff --git a/vendor/github.com/BurntSushi/toml/encode.go b/vendor/github.com/BurntSushi/toml/encode.go index dee4e6d319..930e1d521a 100644 --- a/vendor/github.com/BurntSushi/toml/encode.go +++ b/vendor/github.com/BurntSushi/toml/encode.go @@ -3,6 +3,7 @@ package toml import ( "bufio" "encoding" + "encoding/json" "errors" "fmt" "io" @@ -63,6 +64,12 @@ var dblQuotedReplacer = strings.NewReplacer( "\x7f", `\u007f`, ) +var ( + marshalToml = reflect.TypeOf((*Marshaler)(nil)).Elem() + marshalText = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem() + timeType = reflect.TypeOf((*time.Time)(nil)).Elem() +) + // Marshaler is the interface implemented by types that can marshal themselves // into valid TOML. type Marshaler interface { @@ -72,9 +79,12 @@ type Marshaler interface { // Encoder encodes a Go to a TOML document. // // The mapping between Go values and TOML values should be precisely the same as -// for the Decode* functions. +// for [Decode]. // -// The toml.Marshaler and encoder.TextMarshaler interfaces are supported to +// time.Time is encoded as a RFC 3339 string, and time.Duration as its string +// representation. +// +// The [Marshaler] and [encoding.TextMarshaler] interfaces are supported to // encoding the value as custom TOML. // // If you want to write arbitrary binary data then you will need to use @@ -85,6 +95,17 @@ type Marshaler interface { // // Go maps will be sorted alphabetically by key for deterministic output. // +// The toml struct tag can be used to provide the key name; if omitted the +// struct field name will be used. If the "omitempty" option is present the +// following value will be skipped: +// +// - arrays, slices, maps, and string with len of 0 +// - struct with all zero values +// - bool false +// +// If omitzero is given all int and float types with a value of 0 will be +// skipped. +// // Encoding Go values without a corresponding TOML representation will return an // error. Examples of this includes maps with non-string keys, slices with nil // elements, embedded non-struct types, and nested slices containing maps or @@ -109,7 +130,7 @@ func NewEncoder(w io.Writer) *Encoder { } } -// Encode writes a TOML representation of the Go value to the Encoder's writer. +// Encode writes a TOML representation of the Go value to the [Encoder]'s writer. // // An error is returned if the value given cannot be encoded to a valid TOML // document. @@ -136,18 +157,15 @@ func (enc *Encoder) safeEncode(key Key, rv reflect.Value) (err error) { } func (enc *Encoder) encode(key Key, rv reflect.Value) { - // Special case: time needs to be in ISO8601 format. - // - // Special case: if we can marshal the type to text, then we used that. This - // prevents the encoder for handling these types as generic structs (or - // whatever the underlying type of a TextMarshaler is). - switch t := rv.Interface().(type) { - case time.Time, encoding.TextMarshaler, Marshaler: + // If we can marshal the type to text, then we use that. This prevents the + // encoder for handling these types as generic structs (or whatever the + // underlying type of a TextMarshaler is). + switch { + case isMarshaler(rv): enc.writeKeyValue(key, rv, false) return - // TODO: #76 would make this superfluous after implemented. - case Primitive: - enc.encode(key, reflect.ValueOf(t.undecoded)) + case rv.Type() == primitiveType: // TODO: #76 would make this superfluous after implemented. + enc.encode(key, reflect.ValueOf(rv.Interface().(Primitive).undecoded)) return } @@ -212,18 +230,44 @@ func (enc *Encoder) eElement(rv reflect.Value) { if err != nil { encPanic(err) } - enc.writeQuoted(string(s)) + if s == nil { + encPanic(errors.New("MarshalTOML returned nil and no error")) + } + enc.w.Write(s) return case encoding.TextMarshaler: s, err := v.MarshalText() if err != nil { encPanic(err) } + if s == nil { + encPanic(errors.New("MarshalText returned nil and no error")) + } enc.writeQuoted(string(s)) return + case time.Duration: + enc.writeQuoted(v.String()) + return + case json.Number: + n, _ := rv.Interface().(json.Number) + + if n == "" { /// Useful zero value. + enc.w.WriteByte('0') + return + } else if v, err := n.Int64(); err == nil { + enc.eElement(reflect.ValueOf(v)) + return + } else if v, err := n.Float64(); err == nil { + enc.eElement(reflect.ValueOf(v)) + return + } + encPanic(fmt.Errorf("unable to convert %q to int64 or float64", n)) } switch rv.Kind() { + case reflect.Ptr: + enc.eElement(rv.Elem()) + return case reflect.String: enc.writeQuoted(rv.String()) case reflect.Bool: @@ -259,7 +303,7 @@ func (enc *Encoder) eElement(rv reflect.Value) { case reflect.Interface: enc.eElement(rv.Elem()) default: - encPanic(fmt.Errorf("unexpected primitive type: %T", rv.Interface())) + encPanic(fmt.Errorf("unexpected type: %T", rv.Interface())) } } @@ -280,7 +324,7 @@ func (enc *Encoder) eArrayOrSliceElement(rv reflect.Value) { length := rv.Len() enc.wf("[") for i := 0; i < length; i++ { - elem := rv.Index(i) + elem := eindirect(rv.Index(i)) enc.eElement(elem) if i != length-1 { enc.wf(", ") @@ -294,7 +338,7 @@ func (enc *Encoder) eArrayOfTables(key Key, rv reflect.Value) { encPanic(errNoKey) } for i := 0; i < rv.Len(); i++ { - trv := rv.Index(i) + trv := eindirect(rv.Index(i)) if isNil(trv) { continue } @@ -319,7 +363,7 @@ func (enc *Encoder) eTable(key Key, rv reflect.Value) { } func (enc *Encoder) eMapOrStruct(key Key, rv reflect.Value, inline bool) { - switch rv := eindirect(rv); rv.Kind() { + switch rv.Kind() { case reflect.Map: enc.eMap(key, rv, inline) case reflect.Struct: @@ -341,7 +385,7 @@ func (enc *Encoder) eMap(key Key, rv reflect.Value, inline bool) { var mapKeysDirect, mapKeysSub []string for _, mapKey := range rv.MapKeys() { k := mapKey.String() - if typeIsTable(tomlTypeOfGo(rv.MapIndex(mapKey))) { + if typeIsTable(tomlTypeOfGo(eindirect(rv.MapIndex(mapKey)))) { mapKeysSub = append(mapKeysSub, k) } else { mapKeysDirect = append(mapKeysDirect, k) @@ -351,7 +395,7 @@ func (enc *Encoder) eMap(key Key, rv reflect.Value, inline bool) { var writeMapKeys = func(mapKeys []string, trailC bool) { sort.Strings(mapKeys) for i, mapKey := range mapKeys { - val := rv.MapIndex(reflect.ValueOf(mapKey)) + val := eindirect(rv.MapIndex(reflect.ValueOf(mapKey))) if isNil(val) { continue } @@ -379,6 +423,13 @@ func (enc *Encoder) eMap(key Key, rv reflect.Value, inline bool) { const is32Bit = (32 << (^uint(0) >> 63)) == 32 +func pointerTo(t reflect.Type) reflect.Type { + if t.Kind() == reflect.Ptr { + return pointerTo(t.Elem()) + } + return t +} + func (enc *Encoder) eStruct(key Key, rv reflect.Value, inline bool) { // Write keys for fields directly under this key first, because if we write // a field that creates a new table then all keys under it will be in that @@ -395,31 +446,25 @@ func (enc *Encoder) eStruct(key Key, rv reflect.Value, inline bool) { addFields = func(rt reflect.Type, rv reflect.Value, start []int) { for i := 0; i < rt.NumField(); i++ { f := rt.Field(i) - if f.PkgPath != "" && !f.Anonymous { /// Skip unexported fields. + isEmbed := f.Anonymous && pointerTo(f.Type).Kind() == reflect.Struct + if f.PkgPath != "" && !isEmbed { /// Skip unexported fields. + continue + } + opts := getOptions(f.Tag) + if opts.skip { continue } - frv := rv.Field(i) + frv := eindirect(rv.Field(i)) // Treat anonymous struct fields with tag names as though they are // not anonymous, like encoding/json does. // // Non-struct anonymous fields use the normal encoding logic. - if f.Anonymous { - t := f.Type - switch t.Kind() { - case reflect.Struct: - if getOptions(f.Tag).name == "" { - addFields(t, frv, append(start, f.Index...)) - continue - } - case reflect.Ptr: - if t.Elem().Kind() == reflect.Struct && getOptions(f.Tag).name == "" { - if !frv.IsNil() { - addFields(t.Elem(), frv.Elem(), append(start, f.Index...)) - } - continue - } + if isEmbed { + if getOptions(f.Tag).name == "" && frv.Kind() == reflect.Struct { + addFields(frv.Type(), frv, append(start, f.Index...)) + continue } } @@ -445,7 +490,7 @@ func (enc *Encoder) eStruct(key Key, rv reflect.Value, inline bool) { writeFields := func(fields [][]int) { for _, fieldIndex := range fields { fieldType := rt.FieldByIndex(fieldIndex) - fieldVal := rv.FieldByIndex(fieldIndex) + fieldVal := eindirect(rv.FieldByIndex(fieldIndex)) if isNil(fieldVal) { /// Don't write anything for nil fields. continue @@ -459,7 +504,8 @@ func (enc *Encoder) eStruct(key Key, rv reflect.Value, inline bool) { if opts.name != "" { keyName = opts.name } - if opts.omitempty && isEmpty(fieldVal) { + + if opts.omitempty && enc.isEmpty(fieldVal) { continue } if opts.omitzero && isZero(fieldVal) { @@ -498,6 +544,21 @@ func tomlTypeOfGo(rv reflect.Value) tomlType { if isNil(rv) || !rv.IsValid() { return nil } + + if rv.Kind() == reflect.Struct { + if rv.Type() == timeType { + return tomlDatetime + } + if isMarshaler(rv) { + return tomlString + } + return tomlHash + } + + if isMarshaler(rv) { + return tomlString + } + switch rv.Kind() { case reflect.Bool: return tomlBool @@ -509,7 +570,7 @@ func tomlTypeOfGo(rv reflect.Value) tomlType { case reflect.Float32, reflect.Float64: return tomlFloat case reflect.Array, reflect.Slice: - if typeEqual(tomlHash, tomlArrayType(rv)) { + if isTableArray(rv) { return tomlArrayHash } return tomlArray @@ -519,67 +580,35 @@ func tomlTypeOfGo(rv reflect.Value) tomlType { return tomlString case reflect.Map: return tomlHash - case reflect.Struct: - if _, ok := rv.Interface().(time.Time); ok { - return tomlDatetime - } - if isMarshaler(rv) { - return tomlString - } - return tomlHash default: - if isMarshaler(rv) { - return tomlString - } - encPanic(errors.New("unsupported type: " + rv.Kind().String())) panic("unreachable") } } func isMarshaler(rv reflect.Value) bool { - switch rv.Interface().(type) { - case encoding.TextMarshaler: - return true - case Marshaler: - return true - } - - // Someone used a pointer receiver: we can make it work for pointer values. - if rv.CanAddr() { - if _, ok := rv.Addr().Interface().(encoding.TextMarshaler); ok { - return true - } - if _, ok := rv.Addr().Interface().(Marshaler); ok { - return true - } - } - return false + return rv.Type().Implements(marshalText) || rv.Type().Implements(marshalToml) } -// tomlArrayType returns the element type of a TOML array. The type returned -// may be nil if it cannot be determined (e.g., a nil slice or a zero length -// slize). This function may also panic if it finds a type that cannot be -// expressed in TOML (such as nil elements, heterogeneous arrays or directly -// nested arrays of tables). -func tomlArrayType(rv reflect.Value) tomlType { - if isNil(rv) || !rv.IsValid() || rv.Len() == 0 { - return nil +// isTableArray reports if all entries in the array or slice are a table. +func isTableArray(arr reflect.Value) bool { + if isNil(arr) || !arr.IsValid() || arr.Len() == 0 { + return false } - /// Don't allow nil. - rvlen := rv.Len() - for i := 1; i < rvlen; i++ { - if tomlTypeOfGo(rv.Index(i)) == nil { + ret := true + for i := 0; i < arr.Len(); i++ { + tt := tomlTypeOfGo(eindirect(arr.Index(i))) + // Don't allow nil. + if tt == nil { encPanic(errArrayNilElement) } - } - firstType := tomlTypeOfGo(rv.Index(0)) - if firstType == nil { - encPanic(errArrayNilElement) + if ret && !typeEqual(tomlHash, tt) { + ret = false + } } - return firstType + return ret } type tagOptions struct { @@ -620,10 +649,26 @@ func isZero(rv reflect.Value) bool { return false } -func isEmpty(rv reflect.Value) bool { +func (enc *Encoder) isEmpty(rv reflect.Value) bool { switch rv.Kind() { case reflect.Array, reflect.Slice, reflect.Map, reflect.String: return rv.Len() == 0 + case reflect.Struct: + if rv.Type().Comparable() { + return reflect.Zero(rv.Type()).Interface() == rv.Interface() + } + // Need to also check if all the fields are empty, otherwise something + // like this with uncomparable types will always return true: + // + // type a struct{ field b } + // type b struct{ s []string } + // s := a{field: b{s: []string{"AAA"}}} + for i := 0; i < rv.NumField(); i++ { + if !enc.isEmpty(rv.Field(i)) { + return false + } + } + return true case reflect.Bool: return !rv.Bool() } @@ -638,16 +683,15 @@ func (enc *Encoder) newline() { // Write a key/value pair: // -// key = +// key = // // This is also used for "k = v" in inline tables; so something like this will // be written in three calls: // -// ┌────────────────────┐ -// │ ┌───┐ ┌─────┐│ -// v v v v vv -// key = {k = v, k2 = v2} -// +// ┌───────────────────┐ +// │ ┌───┐ ┌────┐│ +// v v v v vv +// key = {k = 1, k2 = 2} func (enc *Encoder) writeKeyValue(key Key, val reflect.Value, inline bool) { if len(key) == 0 { encPanic(errNoKey) @@ -675,13 +719,25 @@ func encPanic(err error) { panic(tomlEncodeError{err}) } +// Resolve any level of pointers to the actual value (e.g. **string → string). func eindirect(v reflect.Value) reflect.Value { - switch v.Kind() { - case reflect.Ptr, reflect.Interface: - return eindirect(v.Elem()) - default: + if v.Kind() != reflect.Ptr && v.Kind() != reflect.Interface { + if isMarshaler(v) { + return v + } + if v.CanAddr() { /// Special case for marshalers; see #358. + if pv := v.Addr(); isMarshaler(pv) { + return pv + } + } return v } + + if v.IsNil() { + return v + } + + return eindirect(v.Elem()) } func isNil(rv reflect.Value) bool { diff --git a/vendor/github.com/BurntSushi/toml/error.go b/vendor/github.com/BurntSushi/toml/error.go index 36edc46554..f4f390e647 100644 --- a/vendor/github.com/BurntSushi/toml/error.go +++ b/vendor/github.com/BurntSushi/toml/error.go @@ -5,57 +5,60 @@ import ( "strings" ) -// ParseError is returned when there is an error parsing the TOML syntax. -// -// For example invalid syntax, duplicate keys, etc. +// ParseError is returned when there is an error parsing the TOML syntax such as +// invalid syntax, duplicate keys, etc. // // In addition to the error message itself, you can also print detailed location -// information with context by using ErrorWithLocation(): +// information with context by using [ErrorWithPosition]: // -// toml: error: Key 'fruit' was already created and cannot be used as an array. +// toml: error: Key 'fruit' was already created and cannot be used as an array. // -// At line 4, column 2-7: +// At line 4, column 2-7: // -// 2 | fruit = [] -// 3 | -// 4 | [[fruit]] # Not allowed -// ^^^^^ +// 2 | fruit = [] +// 3 | +// 4 | [[fruit]] # Not allowed +// ^^^^^ // -// Furthermore, the ErrorWithUsage() can be used to print the above with some -// more detailed usage guidance: +// [ErrorWithUsage] can be used to print the above with some more detailed usage +// guidance: // -// toml: error: newlines not allowed within inline tables +// toml: error: newlines not allowed within inline tables // -// At line 1, column 18: +// At line 1, column 18: // -// 1 | x = [{ key = 42 # -// ^ +// 1 | x = [{ key = 42 # +// ^ // -// Error help: +// Error help: // -// Inline tables must always be on a single line: +// Inline tables must always be on a single line: // -// table = {key = 42, second = 43} +// table = {key = 42, second = 43} // -// It is invalid to split them over multiple lines like so: +// It is invalid to split them over multiple lines like so: // -// # INVALID -// table = { -// key = 42, -// second = 43 -// } +// # INVALID +// table = { +// key = 42, +// second = 43 +// } // -// Use regular for this: +// Use regular for this: // -// [table] -// key = 42 -// second = 43 +// [table] +// key = 42 +// second = 43 type ParseError struct { Message string // Short technical message. Usage string // Longer message with usage guidance; may be blank. Position Position // Position of the error LastKey string // Last parsed key, may be blank. - Line int // Line the error occurred. Deprecated: use Position. + + // Line the error occurred. + // + // Deprecated: use [Position]. + Line int err error input string @@ -83,7 +86,7 @@ func (pe ParseError) Error() string { // ErrorWithUsage() returns the error with detailed location context. // -// See the documentation on ParseError. +// See the documentation on [ParseError]. func (pe ParseError) ErrorWithPosition() string { if pe.input == "" { // Should never happen, but just in case. return pe.Error() @@ -124,13 +127,17 @@ func (pe ParseError) ErrorWithPosition() string { // ErrorWithUsage() returns the error with detailed location context and usage // guidance. // -// See the documentation on ParseError. +// See the documentation on [ParseError]. func (pe ParseError) ErrorWithUsage() string { m := pe.ErrorWithPosition() if u, ok := pe.err.(interface{ Usage() string }); ok && u.Usage() != "" { - return m + "Error help:\n\n " + - strings.ReplaceAll(strings.TrimSpace(u.Usage()), "\n", "\n ") + - "\n" + lines := strings.Split(strings.TrimSpace(u.Usage()), "\n") + for i := range lines { + if lines[i] != "" { + lines[i] = " " + lines[i] + } + } + return m + "Error help:\n\n" + strings.Join(lines, "\n") + "\n" } return m } @@ -160,6 +167,11 @@ type ( errLexInvalidDate struct{ v string } errLexInlineTableNL struct{} errLexStringNL struct{} + errParseRange struct { + i interface{} // int or float + size string // "int64", "uint16", etc. + } + errParseDuration struct{ d string } ) func (e errLexControl) Error() string { @@ -179,6 +191,10 @@ func (e errLexInlineTableNL) Error() string { return "newlines not allowed withi func (e errLexInlineTableNL) Usage() string { return usageInlineNewline } func (e errLexStringNL) Error() string { return "strings cannot contain newlines" } func (e errLexStringNL) Usage() string { return usageStringNewline } +func (e errParseRange) Error() string { return fmt.Sprintf("%v is out of range for %s", e.i, e.size) } +func (e errParseRange) Usage() string { return usageIntOverflow } +func (e errParseDuration) Error() string { return fmt.Sprintf("invalid duration: %q", e.d) } +func (e errParseDuration) Usage() string { return usageDuration } const usageEscape = ` A '\' inside a "-delimited string is interpreted as an escape character. @@ -227,3 +243,37 @@ Instead use """ or ''' to split strings over multiple lines: string = """Hello, world!""" ` + +const usageIntOverflow = ` +This number is too large; this may be an error in the TOML, but it can also be a +bug in the program that uses too small of an integer. + +The maximum and minimum values are: + + size │ lowest │ highest + ───────┼────────────────┼────────── + int8 │ -128 │ 127 + int16 │ -32,768 │ 32,767 + int32 │ -2,147,483,648 │ 2,147,483,647 + int64 │ -9.2 × 10¹⁷ │ 9.2 × 10¹⁷ + uint8 │ 0 │ 255 + uint16 │ 0 │ 65535 + uint32 │ 0 │ 4294967295 + uint64 │ 0 │ 1.8 × 10¹⁸ + +int refers to int32 on 32-bit systems and int64 on 64-bit systems. +` + +const usageDuration = ` +A duration must be as "number", without any spaces. Valid units are: + + ns nanoseconds (billionth of a second) + us, µs microseconds (millionth of a second) + ms milliseconds (thousands of a second) + s seconds + m minutes + h hours + +You can combine multiple units; for example "5m10s" for 5 minutes and 10 +seconds. +` diff --git a/vendor/github.com/BurntSushi/toml/lex.go b/vendor/github.com/BurntSushi/toml/lex.go index 63ef20f474..d4d70871d8 100644 --- a/vendor/github.com/BurntSushi/toml/lex.go +++ b/vendor/github.com/BurntSushi/toml/lex.go @@ -82,7 +82,7 @@ func (lx *lexer) nextItem() item { return item default: lx.state = lx.state(lx) - //fmt.Printf(" STATE %-24s current: %-10q stack: %s\n", lx.state, lx.current(), lx.stack) + //fmt.Printf(" STATE %-24s current: %-10s stack: %s\n", lx.state, lx.current(), lx.stack) } } } @@ -128,6 +128,11 @@ func (lx lexer) getPos() Position { } func (lx *lexer) emit(typ itemType) { + // Needed for multiline strings ending with an incomplete UTF-8 sequence. + if lx.start > lx.pos { + lx.error(errLexUTF8{lx.input[lx.pos]}) + return + } lx.items <- item{typ: typ, pos: lx.getPos(), val: lx.current()} lx.start = lx.pos } @@ -711,7 +716,17 @@ func lexMultilineString(lx *lexer) stateFn { if lx.peek() == '"' { /// Check if we already lexed 5 's; if so we have 6 now, and /// that's just too many man! - if strings.HasSuffix(lx.current(), `"""""`) { + /// + /// Second check is for the edge case: + /// + /// two quotes allowed. + /// vv + /// """lol \"""""" + /// ^^ ^^^---- closing three + /// escaped + /// + /// But ugly, but it works + if strings.HasSuffix(lx.current(), `"""""`) && !strings.HasSuffix(lx.current(), `\"""""`) { return lx.errorf(`unexpected '""""""'`) } lx.backup() @@ -756,7 +771,7 @@ func lexRawString(lx *lexer) stateFn { } // lexMultilineRawString consumes a raw string. Nothing can be escaped in such -// a string. It assumes that the beginning "'''" has already been consumed and +// a string. It assumes that the beginning ''' has already been consumed and // ignored. func lexMultilineRawString(lx *lexer) stateFn { r := lx.next() @@ -802,8 +817,7 @@ func lexMultilineRawString(lx *lexer) stateFn { // lexMultilineStringEscape consumes an escaped character. It assumes that the // preceding '\\' has already been consumed. func lexMultilineStringEscape(lx *lexer) stateFn { - // Handle the special case first: - if isNL(lx.next()) { + if isNL(lx.next()) { /// \ escaping newline. return lexMultilineString } lx.backup() diff --git a/vendor/github.com/BurntSushi/toml/meta.go b/vendor/github.com/BurntSushi/toml/meta.go index 868619fb97..71847a0415 100644 --- a/vendor/github.com/BurntSushi/toml/meta.go +++ b/vendor/github.com/BurntSushi/toml/meta.go @@ -12,10 +12,11 @@ import ( type MetaData struct { context Key // Used only during decoding. + keyInfo map[string]keyInfo mapping map[string]interface{} - types map[string]tomlType keys []Key decoded map[string]struct{} + data []byte // Input file; for errors. } // IsDefined reports if the key exists in the TOML data. @@ -50,8 +51,8 @@ func (md *MetaData) IsDefined(key ...string) bool { // Type will return the empty string if given an empty key or a key that does // not exist. Keys are case sensitive. func (md *MetaData) Type(key ...string) string { - if typ, ok := md.types[Key(key).String()]; ok { - return typ.typeString() + if ki, ok := md.keyInfo[Key(key).String()]; ok { + return ki.tomlType.typeString() } return "" } @@ -70,7 +71,7 @@ func (md *MetaData) Keys() []Key { // Undecoded returns all keys that have not been decoded in the order in which // they appear in the original TOML document. // -// This includes keys that haven't been decoded because of a Primitive value. +// This includes keys that haven't been decoded because of a [Primitive] value. // Once the Primitive value is decoded, the keys will be considered decoded. // // Also note that decoding into an empty interface will result in no decoding, @@ -88,7 +89,7 @@ func (md *MetaData) Undecoded() []Key { return undecoded } -// Key represents any TOML key, including key groups. Use (MetaData).Keys to get +// Key represents any TOML key, including key groups. Use [MetaData.Keys] to get // values of this type. type Key []string diff --git a/vendor/github.com/BurntSushi/toml/parse.go b/vendor/github.com/BurntSushi/toml/parse.go index 8269cca170..d2542d6f92 100644 --- a/vendor/github.com/BurntSushi/toml/parse.go +++ b/vendor/github.com/BurntSushi/toml/parse.go @@ -16,12 +16,18 @@ type parser struct { currentKey string // Base key name for everything except hashes. pos Position // Current position in the TOML file. - ordered []Key // List of keys in the order that they appear in the TOML data. + ordered []Key // List of keys in the order that they appear in the TOML data. + + keyInfo map[string]keyInfo // Map keyname → info about the TOML key. mapping map[string]interface{} // Map keyname → key value. - types map[string]tomlType // Map keyname → TOML type. implicits map[string]struct{} // Record implicit keys (e.g. "key.group.names"). } +type keyInfo struct { + pos Position + tomlType tomlType +} + func parse(data string) (p *parser, err error) { defer func() { if r := recover(); r != nil { @@ -57,8 +63,8 @@ func parse(data string) (p *parser, err error) { } p = &parser{ + keyInfo: make(map[string]keyInfo), mapping: make(map[string]interface{}), - types: make(map[string]tomlType), lx: lex(data), ordered: make([]Key, 0), implicits: make(map[string]struct{}), @@ -74,6 +80,15 @@ func parse(data string) (p *parser, err error) { return p, nil } +func (p *parser) panicErr(it item, err error) { + panic(ParseError{ + err: err, + Position: it.pos, + Line: it.pos.Len, + LastKey: p.current(), + }) +} + func (p *parser) panicItemf(it item, format string, v ...interface{}) { panic(ParseError{ Message: fmt.Sprintf(format, v...), @@ -94,7 +109,7 @@ func (p *parser) panicf(format string, v ...interface{}) { func (p *parser) next() item { it := p.lx.nextItem() - //fmt.Printf("ITEM %-18s line %-3d │ %q\n", it.typ, it.line, it.val) + //fmt.Printf("ITEM %-18s line %-3d │ %q\n", it.typ, it.pos.Line, it.val) if it.typ == itemError { if it.err != nil { panic(ParseError{ @@ -146,7 +161,7 @@ func (p *parser) topLevel(item item) { p.assertEqual(itemTableEnd, name.typ) p.addContext(key, false) - p.setType("", tomlHash) + p.setType("", tomlHash, item.pos) p.ordered = append(p.ordered, key) case itemArrayTableStart: // [[ .. ]] name := p.nextPos() @@ -158,7 +173,7 @@ func (p *parser) topLevel(item item) { p.assertEqual(itemArrayTableEnd, name.typ) p.addContext(key, true) - p.setType("", tomlArrayHash) + p.setType("", tomlArrayHash, item.pos) p.ordered = append(p.ordered, key) case itemKeyStart: // key = .. outerContext := p.context @@ -181,8 +196,9 @@ func (p *parser) topLevel(item item) { } /// Set value. - val, typ := p.value(p.next(), false) - p.set(p.currentKey, val, typ) + vItem := p.next() + val, typ := p.value(vItem, false) + p.set(p.currentKey, val, typ, vItem.pos) p.ordered = append(p.ordered, p.context.add(p.currentKey)) /// Remove the context we added (preserving any context from [tbl] lines). @@ -220,7 +236,7 @@ func (p *parser) value(it item, parentIsArray bool) (interface{}, tomlType) { case itemString: return p.replaceEscapes(it, it.val), p.typeOfPrimitive(it) case itemMultilineString: - return p.replaceEscapes(it, stripFirstNewline(stripEscapedNewlines(it.val))), p.typeOfPrimitive(it) + return p.replaceEscapes(it, stripFirstNewline(p.stripEscapedNewlines(it.val))), p.typeOfPrimitive(it) case itemRawString: return it.val, p.typeOfPrimitive(it) case itemRawMultilineString: @@ -266,7 +282,7 @@ func (p *parser) valueInteger(it item) (interface{}, tomlType) { // So mark the former as a bug but the latter as a legitimate user // error. if e, ok := err.(*strconv.NumError); ok && e.Err == strconv.ErrRange { - p.panicItemf(it, "Integer '%s' is out of the range of 64-bit signed integers.", it.val) + p.panicErr(it, errParseRange{i: it.val, size: "int64"}) } else { p.bug("Expected integer value, but got '%s'.", it.val) } @@ -304,7 +320,7 @@ func (p *parser) valueFloat(it item) (interface{}, tomlType) { num, err := strconv.ParseFloat(val, 64) if err != nil { if e, ok := err.(*strconv.NumError); ok && e.Err == strconv.ErrRange { - p.panicItemf(it, "Float '%s' is out of the range of 64-bit IEEE-754 floating-point numbers.", it.val) + p.panicErr(it, errParseRange{i: it.val, size: "float64"}) } else { p.panicItemf(it, "Invalid float value: %q", it.val) } @@ -343,9 +359,8 @@ func (p *parser) valueDatetime(it item) (interface{}, tomlType) { } func (p *parser) valueArray(it item) (interface{}, tomlType) { - p.setType(p.currentKey, tomlArray) + p.setType(p.currentKey, tomlArray, it.pos) - // p.setType(p.currentKey, typ) var ( types []tomlType @@ -414,7 +429,7 @@ func (p *parser) valueInlineTable(it item, parentIsArray bool) (interface{}, tom /// Set the value. val, typ := p.value(p.next(), false) - p.set(p.currentKey, val, typ) + p.set(p.currentKey, val, typ, it.pos) p.ordered = append(p.ordered, p.context.add(p.currentKey)) hash[p.currentKey] = val @@ -533,9 +548,10 @@ func (p *parser) addContext(key Key, array bool) { } // set calls setValue and setType. -func (p *parser) set(key string, val interface{}, typ tomlType) { +func (p *parser) set(key string, val interface{}, typ tomlType, pos Position) { p.setValue(key, val) - p.setType(key, typ) + p.setType(key, typ, pos) + } // setValue sets the given key to the given value in the current context. @@ -599,7 +615,7 @@ func (p *parser) setValue(key string, value interface{}) { // // Note that if `key` is empty, then the type given will be applied to the // current context (which is either a table or an array of tables). -func (p *parser) setType(key string, typ tomlType) { +func (p *parser) setType(key string, typ tomlType, pos Position) { keyContext := make(Key, 0, len(p.context)+1) keyContext = append(keyContext, p.context...) if len(key) > 0 { // allow type setting for hashes @@ -611,7 +627,7 @@ func (p *parser) setType(key string, typ tomlType) { if len(keyContext) == 0 { keyContext = Key{""} } - p.types[keyContext.String()] = typ + p.keyInfo[keyContext.String()] = keyInfo{tomlType: typ, pos: pos} } // Implicit keys need to be created when tables are implied in "a.b.c.d = 1" and @@ -619,7 +635,7 @@ func (p *parser) setType(key string, typ tomlType) { func (p *parser) addImplicit(key Key) { p.implicits[key.String()] = struct{}{} } func (p *parser) removeImplicit(key Key) { delete(p.implicits, key.String()) } func (p *parser) isImplicit(key Key) bool { _, ok := p.implicits[key.String()]; return ok } -func (p *parser) isArray(key Key) bool { return p.types[key.String()] == tomlArray } +func (p *parser) isArray(key Key) bool { return p.keyInfo[key.String()].tomlType == tomlArray } func (p *parser) addImplicitContext(key Key) { p.addImplicit(key) p.addContext(key, false) @@ -647,7 +663,7 @@ func stripFirstNewline(s string) string { } // Remove newlines inside triple-quoted strings if a line ends with "\". -func stripEscapedNewlines(s string) string { +func (p *parser) stripEscapedNewlines(s string) string { split := strings.Split(s, "\n") if len(split) < 1 { return s @@ -679,6 +695,10 @@ func stripEscapedNewlines(s string) string { continue } + if i == len(split)-1 { + p.panicf("invalid escape: '\\ '") + } + split[i] = line[:len(line)-1] // Remove \ if len(split)-1 > i { split[i+1] = strings.TrimLeft(split[i+1], " \t\r") @@ -706,10 +726,8 @@ func (p *parser) replaceEscapes(it item, str string) string { switch s[r] { default: p.bug("Expected valid escape code after \\, but got %q.", s[r]) - return "" case ' ', '\t': p.panicItemf(it, "invalid escape: '\\%c'", s[r]) - return "" case 'b': replaced = append(replaced, rune(0x0008)) r += 1 diff --git a/vendor/github.com/MakeNowJust/heredoc/LICENSE b/vendor/github.com/MakeNowJust/heredoc/LICENSE index 8a58c22208..6d0eb9d5d6 100644 --- a/vendor/github.com/MakeNowJust/heredoc/LICENSE +++ b/vendor/github.com/MakeNowJust/heredoc/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014-2017 TSUYUSATO Kitsune +Copyright (c) 2014-2019 TSUYUSATO Kitsune Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/github.com/MakeNowJust/heredoc/README.md b/vendor/github.com/MakeNowJust/heredoc/README.md index a3a65faba1..e9924d2974 100644 --- a/vendor/github.com/MakeNowJust/heredoc/README.md +++ b/vendor/github.com/MakeNowJust/heredoc/README.md @@ -1,4 +1,6 @@ -# heredoc [![CircleCI](https://circleci.com/gh/MakeNowJust/heredoc.svg?style=svg)](https://circleci.com/gh/MakeNowJust/heredoc) [![Go Walker](http://gowalker.org/api/v1/badge)](https://gowalker.org/github.com/MakeNowJust/heredoc) +# heredoc + +[![Build Status](https://circleci.com/gh/MakeNowJust/heredoc.svg?style=svg)](https://circleci.com/gh/MakeNowJust/heredoc) [![GoDoc](https://godoc.org/github.com/MakeNowJusti/heredoc?status.svg)](https://godoc.org/github.com/MakeNowJust/heredoc) ## About @@ -15,8 +17,6 @@ $ go get github.com/MakeNowJust/heredoc ```go // usual import "github.com/MakeNowJust/heredoc" -// shortcuts -import . "github.com/MakeNowJust/heredoc/dot" ``` ## Example @@ -26,11 +26,11 @@ package main import ( "fmt" - . "github.com/MakeNowJust/heredoc/dot" + "github.com/MakeNowJust/heredoc" ) func main() { - fmt.Println(D(` + fmt.Println(heredoc.Doc(` Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, ... @@ -45,8 +45,7 @@ func main() { ## API Document - - [Go Walker - github.com/MakeNowJust/heredoc](https://gowalker.org/github.com/MakeNowJust/heredoc) - - [Go Walker - github.com/MakeNowJust/heredoc/dot](https://gowalker.org/github.com/MakeNowJust/heredoc/dot) + - [heredoc - GoDoc](https://godoc.org/github.com/MakeNowJust/heredoc) ## License diff --git a/vendor/github.com/MakeNowJust/heredoc/heredoc.go b/vendor/github.com/MakeNowJust/heredoc/heredoc.go index fea12e622f..1fc0469555 100644 --- a/vendor/github.com/MakeNowJust/heredoc/heredoc.go +++ b/vendor/github.com/MakeNowJust/heredoc/heredoc.go @@ -1,24 +1,31 @@ -// Copyright (c) 2014-2017 TSUYUSATO Kitsune +// Copyright (c) 2014-2019 TSUYUSATO Kitsune // This software is released under the MIT License. // http://opensource.org/licenses/mit-license.php // Package heredoc provides creation of here-documents from raw strings. // // Golang supports raw-string syntax. +// // doc := ` // Foo // Bar // ` +// // But raw-string cannot recognize indentation. Thus such content is an indented string, equivalent to +// // "\n\tFoo\n\tBar\n" +// // I dont't want this! // // However this problem is solved by package heredoc. +// // doc := heredoc.Doc(` // Foo // Bar // `) +// // Is equivalent to +// // "Foo\nBar\n" package heredoc @@ -33,7 +40,7 @@ const maxInt = int(^uint(0) >> 1) // Doc returns un-indented string as here-document. func Doc(raw string) string { skipFirstLine := false - if raw[0] == '\n' { + if len(raw) > 0 && raw[0] == '\n' { raw = raw[1:] } else { skipFirstLine = true diff --git a/vendor/github.com/Masterminds/semver/v3/.golangci.yml b/vendor/github.com/Masterminds/semver/v3/.golangci.yml index fdbdf1448c..c87d1c4b90 100644 --- a/vendor/github.com/Masterminds/semver/v3/.golangci.yml +++ b/vendor/github.com/Masterminds/semver/v3/.golangci.yml @@ -4,23 +4,27 @@ run: linters: disable-all: true enable: + - misspell + - structcheck + - govet + - staticcheck - deadcode - - dupl - errcheck - - gofmt - - goimports - - golint - - gosimple - - govet + - varcheck + - unparam - ineffassign - - misspell - nakedret - - structcheck + - gocyclo + - dupl + - goimports + - revive + - gosec + - gosimple + - typecheck - unused - - varcheck linters-settings: gofmt: simplify: true dupl: - threshold: 400 + threshold: 600 diff --git a/vendor/github.com/Masterminds/semver/v3/CHANGELOG.md b/vendor/github.com/Masterminds/semver/v3/CHANGELOG.md index 1f90c38d26..f12626423a 100644 --- a/vendor/github.com/Masterminds/semver/v3/CHANGELOG.md +++ b/vendor/github.com/Masterminds/semver/v3/CHANGELOG.md @@ -1,5 +1,25 @@ # Changelog +## 3.2.0 (2022-11-28) + +### Added + +- #190: Added text marshaling and unmarshaling +- #167: Added JSON marshalling for constraints (thanks @SimonTheLeg) +- #173: Implement encoding.TextMarshaler and encoding.TextUnmarshaler on Version (thanks @MarkRosemaker) +- #179: Added New() version constructor (thanks @kazhuravlev) + +### Changed + +- #182/#183: Updated CI testing setup + +### Fixed + +- #186: Fixing issue where validation of constraint section gave false positives +- #176: Fix constraints check with *-0 (thanks @mtt0) +- #181: Fixed Caret operator (^) gives unexpected results when the minor version in constraint is 0 (thanks @arshchimni) +- #161: Fixed godoc (thanks @afirth) + ## 3.1.1 (2020-11-23) ### Fixed diff --git a/vendor/github.com/Masterminds/semver/v3/constraints.go b/vendor/github.com/Masterminds/semver/v3/constraints.go index 547613f044..203072e464 100644 --- a/vendor/github.com/Masterminds/semver/v3/constraints.go +++ b/vendor/github.com/Masterminds/semver/v3/constraints.go @@ -134,6 +134,23 @@ func (cs Constraints) String() string { return strings.Join(buf, " || ") } +// UnmarshalText implements the encoding.TextUnmarshaler interface. +func (cs *Constraints) UnmarshalText(text []byte) error { + temp, err := NewConstraint(string(text)) + if err != nil { + return err + } + + *cs = *temp + + return nil +} + +// MarshalText implements the encoding.TextMarshaler interface. +func (cs Constraints) MarshalText() ([]byte, error) { + return []byte(cs.String()), nil +} + var constraintOps map[string]cfunc var constraintRegex *regexp.Regexp var constraintRangeRegex *regexp.Regexp @@ -180,8 +197,13 @@ func init() { ops, cvRegex)) + // The first time a constraint shows up will look slightly different from + // future times it shows up due to a leading space or comma in a given + // string. validConstraintRegex = regexp.MustCompile(fmt.Sprintf( - `^(\s*(%s)\s*(%s)\s*\,?)+$`, + `^(\s*(%s)\s*(%s)\s*)((?:\s+|,\s*)(%s)\s*(%s)\s*)*$`, + ops, + cvRegex, ops, cvRegex)) } @@ -233,7 +255,7 @@ func parseConstraint(c string) (*constraint, error) { patchDirty := false dirty := false if isX(m[3]) || m[3] == "" { - ver = "0.0.0" + ver = fmt.Sprintf("0.0.0%s", m[6]) dirty = true } else if isX(strings.TrimPrefix(m[4], ".")) || m[4] == "" { minorDirty = true @@ -534,6 +556,10 @@ func constraintCaret(v *Version, c *constraint) (bool, error) { } return false, fmt.Errorf("%s does not have same minor version as %s. Expected minor versions to match when constraint major version is 0", v, c.orig) } + // ^ when the minor is 0 and minor > 0 is =0.0.z + if c.con.Minor() == 0 && v.Minor() > 0 { + return false, fmt.Errorf("%s does not have same minor version as %s", v, c.orig) + } // At this point the major is 0 and the minor is 0 and not dirty. The patch // is not dirty so we need to check if they are equal. If they are not equal diff --git a/vendor/github.com/Masterminds/semver/v3/doc.go b/vendor/github.com/Masterminds/semver/v3/doc.go index 391aa46b76..74f97caa57 100644 --- a/vendor/github.com/Masterminds/semver/v3/doc.go +++ b/vendor/github.com/Masterminds/semver/v3/doc.go @@ -3,12 +3,12 @@ Package semver provides the ability to work with Semantic Versions (http://semve Specifically it provides the ability to: - * Parse semantic versions - * Sort semantic versions - * Check if a semantic version fits within a set of constraints - * Optionally work with a `v` prefix + - Parse semantic versions + - Sort semantic versions + - Check if a semantic version fits within a set of constraints + - Optionally work with a `v` prefix -Parsing Semantic Versions +# Parsing Semantic Versions There are two functions that can parse semantic versions. The `StrictNewVersion` function only parses valid version 2 semantic versions as outlined in the @@ -21,48 +21,48 @@ that can be sorted, compared, and used in constraints. When parsing a version an optional error can be returned if there is an issue parsing the version. For example, - v, err := semver.NewVersion("1.2.3-beta.1+b345") + v, err := semver.NewVersion("1.2.3-beta.1+b345") The version object has methods to get the parts of the version, compare it to other versions, convert the version back into a string, and get the original string. For more details please see the documentation at https://godoc.org/github.com/Masterminds/semver. -Sorting Semantic Versions +# Sorting Semantic Versions A set of versions can be sorted using the `sort` package from the standard library. For example, - raw := []string{"1.2.3", "1.0", "1.3", "2", "0.4.2",} - vs := make([]*semver.Version, len(raw)) - for i, r := range raw { - v, err := semver.NewVersion(r) - if err != nil { - t.Errorf("Error parsing version: %s", err) - } + raw := []string{"1.2.3", "1.0", "1.3", "2", "0.4.2",} + vs := make([]*semver.Version, len(raw)) + for i, r := range raw { + v, err := semver.NewVersion(r) + if err != nil { + t.Errorf("Error parsing version: %s", err) + } - vs[i] = v - } + vs[i] = v + } - sort.Sort(semver.Collection(vs)) + sort.Sort(semver.Collection(vs)) -Checking Version Constraints and Comparing Versions +# Checking Version Constraints and Comparing Versions There are two methods for comparing versions. One uses comparison methods on `Version` instances and the other is using Constraints. There are some important differences to notes between these two methods of comparison. -1. When two versions are compared using functions such as `Compare`, `LessThan`, - and others it will follow the specification and always include prereleases - within the comparison. It will provide an answer valid with the comparison - spec section at https://semver.org/#spec-item-11 -2. When constraint checking is used for checks or validation it will follow a - different set of rules that are common for ranges with tools like npm/js - and Rust/Cargo. This includes considering prereleases to be invalid if the - ranges does not include on. If you want to have it include pre-releases a - simple solution is to include `-0` in your range. -3. Constraint ranges can have some complex rules including the shorthard use of - ~ and ^. For more details on those see the options below. + 1. When two versions are compared using functions such as `Compare`, `LessThan`, + and others it will follow the specification and always include prereleases + within the comparison. It will provide an answer valid with the comparison + spec section at https://semver.org/#spec-item-11 + 2. When constraint checking is used for checks or validation it will follow a + different set of rules that are common for ranges with tools like npm/js + and Rust/Cargo. This includes considering prereleases to be invalid if the + ranges does not include on. If you want to have it include pre-releases a + simple solution is to include `-0` in your range. + 3. Constraint ranges can have some complex rules including the shorthard use of + ~ and ^. For more details on those see the options below. There are differences between the two methods or checking versions because the comparison methods on `Version` follow the specification while comparison ranges @@ -76,19 +76,19 @@ patters with their versions. Checking a version against version constraints is one of the most featureful parts of the package. - c, err := semver.NewConstraint(">= 1.2.3") - if err != nil { - // Handle constraint not being parsable. - } + c, err := semver.NewConstraint(">= 1.2.3") + if err != nil { + // Handle constraint not being parsable. + } - v, err := semver.NewVersion("1.3") - if err != nil { - // Handle version not being parsable. - } - // Check if the version meets the constraints. The a variable will be true. - a := c.Check(v) + v, err := semver.NewVersion("1.3") + if err != nil { + // Handle version not being parsable. + } + // Check if the version meets the constraints. The a variable will be true. + a := c.Check(v) -Basic Comparisons +# Basic Comparisons There are two elements to the comparisons. First, a comparison string is a list of comma or space separated AND comparisons. These are then separated by || (OR) @@ -99,31 +99,31 @@ greater than or equal to 4.2.3. This can also be written as The basic comparisons are: - * `=`: equal (aliased to no operator) - * `!=`: not equal - * `>`: greater than - * `<`: less than - * `>=`: greater than or equal to - * `<=`: less than or equal to + - `=`: equal (aliased to no operator) + - `!=`: not equal + - `>`: greater than + - `<`: less than + - `>=`: greater than or equal to + - `<=`: less than or equal to -Hyphen Range Comparisons +# Hyphen Range Comparisons There are multiple methods to handle ranges and the first is hyphens ranges. These look like: - * `1.2 - 1.4.5` which is equivalent to `>= 1.2, <= 1.4.5` - * `2.3.4 - 4.5` which is equivalent to `>= 2.3.4 <= 4.5` + - `1.2 - 1.4.5` which is equivalent to `>= 1.2, <= 1.4.5` + - `2.3.4 - 4.5` which is equivalent to `>= 2.3.4 <= 4.5` -Wildcards In Comparisons +# Wildcards In Comparisons The `x`, `X`, and `*` characters can be used as a wildcard character. This works for all comparison operators. When used on the `=` operator it falls back to the tilde operation. For example, - * `1.2.x` is equivalent to `>= 1.2.0 < 1.3.0` - * `>= 1.2.x` is equivalent to `>= 1.2.0` - * `<= 2.x` is equivalent to `<= 3` - * `*` is equivalent to `>= 0.0.0` + - `1.2.x` is equivalent to `>= 1.2.0 < 1.3.0` + - `>= 1.2.x` is equivalent to `>= 1.2.0` + - `<= 2.x` is equivalent to `<= 3` + - `*` is equivalent to `>= 0.0.0` Tilde Range Comparisons (Patch) @@ -131,11 +131,11 @@ The tilde (`~`) comparison operator is for patch level ranges when a minor version is specified and major level changes when the minor number is missing. For example, - * `~1.2.3` is equivalent to `>= 1.2.3 < 1.3.0` - * `~1` is equivalent to `>= 1, < 2` - * `~2.3` is equivalent to `>= 2.3 < 2.4` - * `~1.2.x` is equivalent to `>= 1.2.0 < 1.3.0` - * `~1.x` is equivalent to `>= 1 < 2` + - `~1.2.3` is equivalent to `>= 1.2.3 < 1.3.0` + - `~1` is equivalent to `>= 1, < 2` + - `~2.3` is equivalent to `>= 2.3 < 2.4` + - `~1.2.x` is equivalent to `>= 1.2.0 < 1.3.0` + - `~1.x` is equivalent to `>= 1 < 2` Caret Range Comparisons (Major) @@ -144,41 +144,41 @@ The caret (`^`) comparison operator is for major level changes once a stable as the API stability level. This is useful when comparisons of API versions as a major change is API breaking. For example, - * `^1.2.3` is equivalent to `>= 1.2.3, < 2.0.0` - * `^1.2.x` is equivalent to `>= 1.2.0, < 2.0.0` - * `^2.3` is equivalent to `>= 2.3, < 3` - * `^2.x` is equivalent to `>= 2.0.0, < 3` - * `^0.2.3` is equivalent to `>=0.2.3 <0.3.0` - * `^0.2` is equivalent to `>=0.2.0 <0.3.0` - * `^0.0.3` is equivalent to `>=0.0.3 <0.0.4` - * `^0.0` is equivalent to `>=0.0.0 <0.1.0` - * `^0` is equivalent to `>=0.0.0 <1.0.0` + - `^1.2.3` is equivalent to `>= 1.2.3, < 2.0.0` + - `^1.2.x` is equivalent to `>= 1.2.0, < 2.0.0` + - `^2.3` is equivalent to `>= 2.3, < 3` + - `^2.x` is equivalent to `>= 2.0.0, < 3` + - `^0.2.3` is equivalent to `>=0.2.3 <0.3.0` + - `^0.2` is equivalent to `>=0.2.0 <0.3.0` + - `^0.0.3` is equivalent to `>=0.0.3 <0.0.4` + - `^0.0` is equivalent to `>=0.0.0 <0.1.0` + - `^0` is equivalent to `>=0.0.0 <1.0.0` -Validation +# Validation In addition to testing a version against a constraint, a version can be validated against a constraint. When validation fails a slice of errors containing why a version didn't meet the constraint is returned. For example, - c, err := semver.NewConstraint("<= 1.2.3, >= 1.4") - if err != nil { - // Handle constraint not being parseable. - } - - v, _ := semver.NewVersion("1.3") - if err != nil { - // Handle version not being parseable. - } - - // Validate a version against a constraint. - a, msgs := c.Validate(v) - // a is false - for _, m := range msgs { - fmt.Println(m) - - // Loops over the errors which would read - // "1.3 is greater than 1.2.3" - // "1.3 is less than 1.4" - } + c, err := semver.NewConstraint("<= 1.2.3, >= 1.4") + if err != nil { + // Handle constraint not being parseable. + } + + v, _ := semver.NewVersion("1.3") + if err != nil { + // Handle version not being parseable. + } + + // Validate a version against a constraint. + a, msgs := c.Validate(v) + // a is false + for _, m := range msgs { + fmt.Println(m) + + // Loops over the errors which would read + // "1.3 is greater than 1.2.3" + // "1.3 is less than 1.4" + } */ package semver diff --git a/vendor/github.com/Masterminds/semver/v3/version.go b/vendor/github.com/Masterminds/semver/v3/version.go index d6b9cda3ee..7c4bed3347 100644 --- a/vendor/github.com/Masterminds/semver/v3/version.go +++ b/vendor/github.com/Masterminds/semver/v3/version.go @@ -55,14 +55,16 @@ func init() { versionRegex = regexp.MustCompile("^" + semVerRegex + "$") } -const num string = "0123456789" -const allowed string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-" + num +const ( + num string = "0123456789" + allowed string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-" + num +) // StrictNewVersion parses a given version and returns an instance of Version or // an error if unable to parse the version. Only parses valid semantic versions. // Performs checking that can find errors within the version. -// If you want to coerce a version, such as 1 or 1.2, and perse that as the 1.x -// releases of semver provided use the NewSemver() function. +// If you want to coerce a version such as 1 or 1.2 and parse it as the 1.x +// releases of semver did, use the NewVersion() function. func StrictNewVersion(v string) (*Version, error) { // Parsing here does not use RegEx in order to increase performance and reduce // allocations. @@ -207,6 +209,23 @@ func NewVersion(v string) (*Version, error) { return sv, nil } +// New creates a new instance of Version with each of the parts passed in as +// arguments instead of parsing a version string. +func New(major, minor, patch uint64, pre, metadata string) *Version { + v := Version{ + major: major, + minor: minor, + patch: patch, + pre: pre, + metadata: metadata, + original: "", + } + + v.original = v.String() + + return &v +} + // MustParse parses a given version and panics on error. func MustParse(v string) *Version { sv, err := NewVersion(v) @@ -267,7 +286,6 @@ func (v Version) Metadata() string { // originalVPrefix returns the original 'v' prefix if any. func (v Version) originalVPrefix() string { - // Note, only lowercase v is supported as a prefix by the parser. if v.original != "" && v.original[:1] == "v" { return v.original[:1] @@ -436,6 +454,23 @@ func (v Version) MarshalJSON() ([]byte, error) { return json.Marshal(v.String()) } +// UnmarshalText implements the encoding.TextUnmarshaler interface. +func (v *Version) UnmarshalText(text []byte) error { + temp, err := NewVersion(string(text)) + if err != nil { + return err + } + + *v = *temp + + return nil +} + +// MarshalText implements the encoding.TextMarshaler interface. +func (v Version) MarshalText() ([]byte, error) { + return []byte(v.String()), nil +} + // Scan implements the SQL.Scanner interface. func (v *Version) Scan(value interface{}) error { var s string @@ -470,7 +505,6 @@ func compareSegment(v, o uint64) int { } func comparePrerelease(v, o string) int { - // split the prelease versions by their part. The separator, per the spec, // is a . sparts := strings.Split(v, ".") @@ -562,7 +596,6 @@ func comparePrePart(s, o string) int { return 1 } return -1 - } // Like strings.ContainsAny but does an only instead of any. diff --git a/vendor/github.com/Masterminds/sprig/v3/CHANGELOG.md b/vendor/github.com/Masterminds/sprig/v3/CHANGELOG.md index fcdd4e88ae..2ce45dd4ec 100644 --- a/vendor/github.com/Masterminds/sprig/v3/CHANGELOG.md +++ b/vendor/github.com/Masterminds/sprig/v3/CHANGELOG.md @@ -1,8 +1,21 @@ # Changelog +## Release 3.2.3 (2022-11-29) + +### Changed + +- Updated docs (thanks @book987 @aJetHorn @neelayu @pellizzetti @apricote @SaigyoujiYuyuko233 @AlekSi) +- #348: Updated huandu/xstrings which fixed a snake case bug (thanks @yxxhero) +- #353: Updated masterminds/semver which included bug fixes +- #354: Updated golang.org/x/crypto which included bug fixes + +## Release 3.2.2 (2021-02-04) + +This is a re-release of 3.2.1 to satisfy something with the Go module system. + ## Release 3.2.1 (2021-02-04) -### Changed +### Changed - Upgraded `Masterminds/goutils` to `v1.1.1`. see the [Security Advisory](https://github.com/Masterminds/goutils/security/advisories/GHSA-xg2h-wx96-xgxr) diff --git a/vendor/github.com/Masterminds/sprig/v3/README.md b/vendor/github.com/Masterminds/sprig/v3/README.md index c37ba01c21..3e22c60e1a 100644 --- a/vendor/github.com/Masterminds/sprig/v3/README.md +++ b/vendor/github.com/Masterminds/sprig/v3/README.md @@ -17,10 +17,9 @@ JavaScript libraries, such as [underscore.js](http://underscorejs.org/). ## IMPORTANT NOTES Sprig leverages [mergo](https://github.com/imdario/mergo) to handle merges. In -its v0.3.9 release there was a behavior change that impacts merging template -functions in sprig. It is currently recommended to use v0.3.8 of that package. -Using v0.3.9 will cause sprig tests to fail. The issue in mergo is tracked at -https://github.com/imdario/mergo/issues/139. +its v0.3.9 release, there was a behavior change that impacts merging template +functions in sprig. It is currently recommended to use v0.3.10 or later of that package. +Using v0.3.9 will cause sprig tests to fail. ## Package Versions @@ -51,7 +50,7 @@ To load the Sprig `FuncMap`: ```go import ( - "github.com/Masterminds/sprig" + "github.com/Masterminds/sprig/v3" "html/template" ) diff --git a/vendor/github.com/Masterminds/squirrel/part.go b/vendor/github.com/Masterminds/squirrel/part.go index f3a7b1545a..c58f68f1a4 100644 --- a/vendor/github.com/Masterminds/squirrel/part.go +++ b/vendor/github.com/Masterminds/squirrel/part.go @@ -19,7 +19,7 @@ func (p part) ToSql() (sql string, args []interface{}, err error) { case nil: // no-op case Sqlizer: - sql, args, err = pred.ToSql() + sql, args, err = nestedToSql(pred) case string: sql = pred args = p.args diff --git a/vendor/github.com/Masterminds/squirrel/squirrel_ctx.go b/vendor/github.com/Masterminds/squirrel/squirrel_ctx.go index 504e763d2e..c20148ad33 100644 --- a/vendor/github.com/Masterminds/squirrel/squirrel_ctx.go +++ b/vendor/github.com/Masterminds/squirrel/squirrel_ctx.go @@ -32,7 +32,7 @@ type QueryRowerContext interface { QueryRowContext(ctx context.Context, query string, args ...interface{}) RowScanner } -// RunnerContext groups the Runner interface, along with the Contect versions of each of +// RunnerContext groups the Runner interface, along with the Context versions of each of // its methods type RunnerContext interface { Runner diff --git a/vendor/github.com/Microsoft/go-winio/.gitattributes b/vendor/github.com/Microsoft/go-winio/.gitattributes new file mode 100644 index 0000000000..94f480de94 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf \ No newline at end of file diff --git a/vendor/github.com/Microsoft/go-winio/.gitignore b/vendor/github.com/Microsoft/go-winio/.gitignore index b883f1fdc6..815e20660e 100644 --- a/vendor/github.com/Microsoft/go-winio/.gitignore +++ b/vendor/github.com/Microsoft/go-winio/.gitignore @@ -1 +1,10 @@ +.vscode/ + *.exe + +# testing +testdata + +# go workspaces +go.work +go.work.sum diff --git a/vendor/github.com/Microsoft/go-winio/.golangci.yml b/vendor/github.com/Microsoft/go-winio/.golangci.yml new file mode 100644 index 0000000000..7b503d26a3 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/.golangci.yml @@ -0,0 +1,149 @@ +run: + skip-dirs: + - pkg/etw/sample + +linters: + enable: + # style + - containedctx # struct contains a context + - dupl # duplicate code + - errname # erorrs are named correctly + - nolintlint # "//nolint" directives are properly explained + - revive # golint replacement + - unconvert # unnecessary conversions + - wastedassign + + # bugs, performance, unused, etc ... + - contextcheck # function uses a non-inherited context + - errorlint # errors not wrapped for 1.13 + - exhaustive # check exhaustiveness of enum switch statements + - gofmt # files are gofmt'ed + - gosec # security + - nilerr # returns nil even with non-nil error + - unparam # unused function params + +issues: + exclude-rules: + # err is very often shadowed in nested scopes + - linters: + - govet + text: '^shadow: declaration of "err" shadows declaration' + + # ignore long lines for skip autogen directives + - linters: + - revive + text: "^line-length-limit: " + source: "^//(go:generate|sys) " + + #TODO: remove after upgrading to go1.18 + # ignore comment spacing for nolint and sys directives + - linters: + - revive + text: "^comment-spacings: no space between comment delimiter and comment text" + source: "//(cspell:|nolint:|sys |todo)" + + # not on go 1.18 yet, so no any + - linters: + - revive + text: "^use-any: since GO 1.18 'interface{}' can be replaced by 'any'" + + # allow unjustified ignores of error checks in defer statements + - linters: + - nolintlint + text: "^directive `//nolint:errcheck` should provide explanation" + source: '^\s*defer ' + + # allow unjustified ignores of error lints for io.EOF + - linters: + - nolintlint + text: "^directive `//nolint:errorlint` should provide explanation" + source: '[=|!]= io.EOF' + + +linters-settings: + exhaustive: + default-signifies-exhaustive: true + govet: + enable-all: true + disable: + # struct order is often for Win32 compat + # also, ignore pointer bytes/GC issues for now until performance becomes an issue + - fieldalignment + check-shadowing: true + nolintlint: + allow-leading-space: false + require-explanation: true + require-specific: true + revive: + # revive is more configurable than static check, so likely the preferred alternative to static-check + # (once the perf issue is solved: https://github.com/golangci/golangci-lint/issues/2997) + enable-all-rules: + true + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md + rules: + # rules with required arguments + - name: argument-limit + disabled: true + - name: banned-characters + disabled: true + - name: cognitive-complexity + disabled: true + - name: cyclomatic + disabled: true + - name: file-header + disabled: true + - name: function-length + disabled: true + - name: function-result-limit + disabled: true + - name: max-public-structs + disabled: true + # geneally annoying rules + - name: add-constant # complains about any and all strings and integers + disabled: true + - name: confusing-naming # we frequently use "Foo()" and "foo()" together + disabled: true + - name: flag-parameter # excessive, and a common idiom we use + disabled: true + - name: unhandled-error # warns over common fmt.Print* and io.Close; rely on errcheck instead + disabled: true + # general config + - name: line-length-limit + arguments: + - 140 + - name: var-naming + arguments: + - [] + - - CID + - CRI + - CTRD + - DACL + - DLL + - DOS + - ETW + - FSCTL + - GCS + - GMSA + - HCS + - HV + - IO + - LCOW + - LDAP + - LPAC + - LTSC + - MMIO + - NT + - OCI + - PMEM + - PWSH + - RX + - SACl + - SID + - SMB + - TX + - VHD + - VHDX + - VMID + - VPCI + - WCOW + - WIM diff --git a/vendor/github.com/Microsoft/go-winio/README.md b/vendor/github.com/Microsoft/go-winio/README.md index 683be1dcf9..7474b4f0b6 100644 --- a/vendor/github.com/Microsoft/go-winio/README.md +++ b/vendor/github.com/Microsoft/go-winio/README.md @@ -13,16 +13,60 @@ Please see the LICENSE file for licensing information. ## Contributing -This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) -declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com. +This project welcomes contributions and suggestions. +Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that +you have the right to, and actually do, grant us the rights to use your contribution. +For details, visit [Microsoft CLA](https://cla.microsoft.com). -When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR -appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA. +When you submit a pull request, a CLA-bot will automatically determine whether you need to +provide a CLA and decorate the PR appropriately (e.g., label, comment). +Simply follow the instructions provided by the bot. +You will only need to do this once across all repos using our CLA. -We also require that contributors sign their commits using git commit -s or git commit --signoff to certify they either authored the work themselves -or otherwise have permission to use it in this project. Please see https://developercertificate.org/ for more info, as well as to make sure that you can -attest to the rules listed. Our CI uses the DCO Github app to ensure that all commits in a given PR are signed-off. +Additionally, the pull request pipeline requires the following steps to be performed before +mergining. +### Code Sign-Off + +We require that contributors sign their commits using [`git commit --signoff`][git-commit-s] +to certify they either authored the work themselves or otherwise have permission to use it in this project. + +A range of commits can be signed off using [`git rebase --signoff`][git-rebase-s]. + +Please see [the developer certificate](https://developercertificate.org) for more info, +as well as to make sure that you can attest to the rules listed. +Our CI uses the DCO Github app to ensure that all commits in a given PR are signed-off. + +### Linting + +Code must pass a linting stage, which uses [`golangci-lint`][lint]. +The linting settings are stored in [`.golangci.yaml`](./.golangci.yaml), and can be run +automatically with VSCode by adding the following to your workspace or folder settings: + +```json + "go.lintTool": "golangci-lint", + "go.lintOnSave": "package", +``` + +Additional editor [integrations options are also available][lint-ide]. + +Alternatively, `golangci-lint` can be [installed locally][lint-install] and run from the repo root: + +```shell +# use . or specify a path to only lint a package +# to show all lint errors, use flags "--max-issues-per-linter=0 --max-same-issues=0" +> golangci-lint run ./... +``` + +### Go Generate + +The pipeline checks that auto-generated code, via `go generate`, are up to date. + +This can be done for the entire repo: + +```shell +> go generate ./... +``` ## Code of Conduct @@ -30,8 +74,16 @@ This project has adopted the [Microsoft Open Source Code of Conduct](https://ope For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. +## Special Thanks +Thanks to [natefinch][natefinch] for the inspiration for this library. +See [npipe](https://github.com/natefinch/npipe) for another named pipe implementation. -## Special Thanks -Thanks to natefinch for the inspiration for this library. See https://github.com/natefinch/npipe -for another named pipe implementation. +[lint]: https://golangci-lint.run/ +[lint-ide]: https://golangci-lint.run/usage/integrations/#editor-integration +[lint-install]: https://golangci-lint.run/usage/install/#local-installation + +[git-commit-s]: https://git-scm.com/docs/git-commit#Documentation/git-commit.txt--s +[git-rebase-s]: https://git-scm.com/docs/git-rebase#Documentation/git-rebase.txt---signoff + +[natefinch]: https://github.com/natefinch diff --git a/vendor/github.com/Microsoft/go-winio/SECURITY.md b/vendor/github.com/Microsoft/go-winio/SECURITY.md new file mode 100644 index 0000000000..869fdfe2b2 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/SECURITY.md @@ -0,0 +1,41 @@ + + +## Security + +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). + +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). + +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). + +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + + * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) + * Full paths of source file(s) related to the manifestation of the issue + * The location of the affected source code (tag/branch/commit or direct URL) + * Any special configuration required to reproduce the issue + * Step-by-step instructions to reproduce the issue + * Proof-of-concept or exploit code (if possible) + * Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. + +## Preferred Languages + +We prefer all communications to be in English. + +## Policy + +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). + + diff --git a/vendor/github.com/Microsoft/go-winio/backup.go b/vendor/github.com/Microsoft/go-winio/backup.go index 2be34af431..09621c8846 100644 --- a/vendor/github.com/Microsoft/go-winio/backup.go +++ b/vendor/github.com/Microsoft/go-winio/backup.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package winio @@ -7,11 +8,12 @@ import ( "errors" "fmt" "io" - "io/ioutil" "os" "runtime" "syscall" "unicode/utf16" + + "golang.org/x/sys/windows" ) //sys backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupRead @@ -24,7 +26,7 @@ const ( BackupAlternateData BackupLink BackupPropertyData - BackupObjectId + BackupObjectId //revive:disable-line:var-naming ID, not Id BackupReparseData BackupSparseBlock BackupTxfsData @@ -34,14 +36,16 @@ const ( StreamSparseAttributes = uint32(8) ) +//nolint:revive // var-naming: ALL_CAPS const ( - WRITE_DAC = 0x40000 - WRITE_OWNER = 0x80000 - ACCESS_SYSTEM_SECURITY = 0x1000000 + WRITE_DAC = windows.WRITE_DAC + WRITE_OWNER = windows.WRITE_OWNER + ACCESS_SYSTEM_SECURITY = windows.ACCESS_SYSTEM_SECURITY ) // BackupHeader represents a backup stream of a file. type BackupHeader struct { + //revive:disable-next-line:var-naming ID, not Id Id uint32 // The backup stream ID Attributes uint32 // Stream attributes Size int64 // The size of the stream in bytes @@ -49,8 +53,8 @@ type BackupHeader struct { Offset int64 // The offset of the stream in the file (for BackupSparseBlock only). } -type win32StreamId struct { - StreamId uint32 +type win32StreamID struct { + StreamID uint32 Attributes uint32 Size uint64 NameSize uint32 @@ -71,7 +75,7 @@ func NewBackupStreamReader(r io.Reader) *BackupStreamReader { // Next returns the next backup stream and prepares for calls to Read(). It skips the remainder of the current stream if // it was not completely read. func (r *BackupStreamReader) Next() (*BackupHeader, error) { - if r.bytesLeft > 0 { + if r.bytesLeft > 0 { //nolint:nestif // todo: flatten this if s, ok := r.r.(io.Seeker); ok { // Make sure Seek on io.SeekCurrent sometimes succeeds // before trying the actual seek. @@ -82,16 +86,16 @@ func (r *BackupStreamReader) Next() (*BackupHeader, error) { r.bytesLeft = 0 } } - if _, err := io.Copy(ioutil.Discard, r); err != nil { + if _, err := io.Copy(io.Discard, r); err != nil { return nil, err } } - var wsi win32StreamId + var wsi win32StreamID if err := binary.Read(r.r, binary.LittleEndian, &wsi); err != nil { return nil, err } hdr := &BackupHeader{ - Id: wsi.StreamId, + Id: wsi.StreamID, Attributes: wsi.Attributes, Size: int64(wsi.Size), } @@ -102,7 +106,7 @@ func (r *BackupStreamReader) Next() (*BackupHeader, error) { } hdr.Name = syscall.UTF16ToString(name) } - if wsi.StreamId == BackupSparseBlock { + if wsi.StreamID == BackupSparseBlock { if err := binary.Read(r.r, binary.LittleEndian, &hdr.Offset); err != nil { return nil, err } @@ -147,8 +151,8 @@ func (w *BackupStreamWriter) WriteHeader(hdr *BackupHeader) error { return fmt.Errorf("missing %d bytes", w.bytesLeft) } name := utf16.Encode([]rune(hdr.Name)) - wsi := win32StreamId{ - StreamId: hdr.Id, + wsi := win32StreamID{ + StreamID: hdr.Id, Attributes: hdr.Attributes, Size: uint64(hdr.Size), NameSize: uint32(len(name) * 2), @@ -203,7 +207,7 @@ func (r *BackupFileReader) Read(b []byte) (int, error) { var bytesRead uint32 err := backupRead(syscall.Handle(r.f.Fd()), b, &bytesRead, false, r.includeSecurity, &r.ctx) if err != nil { - return 0, &os.PathError{"BackupRead", r.f.Name(), err} + return 0, &os.PathError{Op: "BackupRead", Path: r.f.Name(), Err: err} } runtime.KeepAlive(r.f) if bytesRead == 0 { @@ -216,7 +220,7 @@ func (r *BackupFileReader) Read(b []byte) (int, error) { // the underlying file. func (r *BackupFileReader) Close() error { if r.ctx != 0 { - backupRead(syscall.Handle(r.f.Fd()), nil, nil, true, false, &r.ctx) + _ = backupRead(syscall.Handle(r.f.Fd()), nil, nil, true, false, &r.ctx) runtime.KeepAlive(r.f) r.ctx = 0 } @@ -242,7 +246,7 @@ func (w *BackupFileWriter) Write(b []byte) (int, error) { var bytesWritten uint32 err := backupWrite(syscall.Handle(w.f.Fd()), b, &bytesWritten, false, w.includeSecurity, &w.ctx) if err != nil { - return 0, &os.PathError{"BackupWrite", w.f.Name(), err} + return 0, &os.PathError{Op: "BackupWrite", Path: w.f.Name(), Err: err} } runtime.KeepAlive(w.f) if int(bytesWritten) != len(b) { @@ -255,7 +259,7 @@ func (w *BackupFileWriter) Write(b []byte) (int, error) { // close the underlying file. func (w *BackupFileWriter) Close() error { if w.ctx != 0 { - backupWrite(syscall.Handle(w.f.Fd()), nil, nil, true, false, &w.ctx) + _ = backupWrite(syscall.Handle(w.f.Fd()), nil, nil, true, false, &w.ctx) runtime.KeepAlive(w.f) w.ctx = 0 } @@ -271,7 +275,13 @@ func OpenForBackup(path string, access uint32, share uint32, createmode uint32) if err != nil { return nil, err } - h, err := syscall.CreateFile(&winPath[0], access, share, nil, createmode, syscall.FILE_FLAG_BACKUP_SEMANTICS|syscall.FILE_FLAG_OPEN_REPARSE_POINT, 0) + h, err := syscall.CreateFile(&winPath[0], + access, + share, + nil, + createmode, + syscall.FILE_FLAG_BACKUP_SEMANTICS|syscall.FILE_FLAG_OPEN_REPARSE_POINT, + 0) if err != nil { err = &os.PathError{Op: "open", Path: path, Err: err} return nil, err diff --git a/vendor/github.com/Microsoft/go-winio/backuptar/doc.go b/vendor/github.com/Microsoft/go-winio/backuptar/doc.go new file mode 100644 index 0000000000..965d52ab04 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/backuptar/doc.go @@ -0,0 +1,3 @@ +// This file only exists to allow go get on non-Windows platforms. + +package backuptar diff --git a/vendor/github.com/Microsoft/go-winio/backuptar/noop.go b/vendor/github.com/Microsoft/go-winio/backuptar/noop.go deleted file mode 100644 index d39eccf023..0000000000 --- a/vendor/github.com/Microsoft/go-winio/backuptar/noop.go +++ /dev/null @@ -1,4 +0,0 @@ -// +build !windows -// This file only exists to allow go get on non-Windows platforms. - -package backuptar diff --git a/vendor/github.com/Microsoft/go-winio/backuptar/strconv.go b/vendor/github.com/Microsoft/go-winio/backuptar/strconv.go index 3416096639..455fd798eb 100644 --- a/vendor/github.com/Microsoft/go-winio/backuptar/strconv.go +++ b/vendor/github.com/Microsoft/go-winio/backuptar/strconv.go @@ -1,3 +1,5 @@ +//go:build windows + package backuptar import ( diff --git a/vendor/github.com/Microsoft/go-winio/backuptar/tar.go b/vendor/github.com/Microsoft/go-winio/backuptar/tar.go index 689e4da6bd..6b3b0cd519 100644 --- a/vendor/github.com/Microsoft/go-winio/backuptar/tar.go +++ b/vendor/github.com/Microsoft/go-winio/backuptar/tar.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package backuptar @@ -7,7 +8,6 @@ import ( "encoding/base64" "fmt" "io" - "io/ioutil" "path/filepath" "strconv" "strings" @@ -18,17 +18,18 @@ import ( "golang.org/x/sys/windows" ) +//nolint:deadcode,varcheck // keep unused constants for potential future use const ( - c_ISUID = 04000 // Set uid - c_ISGID = 02000 // Set gid - c_ISVTX = 01000 // Save text (sticky bit) - c_ISDIR = 040000 // Directory - c_ISFIFO = 010000 // FIFO - c_ISREG = 0100000 // Regular file - c_ISLNK = 0120000 // Symbolic link - c_ISBLK = 060000 // Block special file - c_ISCHR = 020000 // Character special file - c_ISSOCK = 0140000 // Socket + cISUID = 0004000 // Set uid + cISGID = 0002000 // Set gid + cISVTX = 0001000 // Save text (sticky bit) + cISDIR = 0040000 // Directory + cISFIFO = 0010000 // FIFO + cISREG = 0100000 // Regular file + cISLNK = 0120000 // Symbolic link + cISBLK = 0060000 // Block special file + cISCHR = 0020000 // Character special file + cISSOCK = 0140000 // Socket ) const ( @@ -44,7 +45,7 @@ const ( // zeroReader is an io.Reader that always returns 0s. type zeroReader struct{} -func (zr zeroReader) Read(b []byte) (int, error) { +func (zeroReader) Read(b []byte) (int, error) { for i := range b { b[i] = 0 } @@ -55,7 +56,7 @@ func copySparse(t *tar.Writer, br *winio.BackupStreamReader) error { curOffset := int64(0) for { bhdr, err := br.Next() - if err == io.EOF { + if err == io.EOF { //nolint:errorlint err = io.ErrUnexpectedEOF } if err != nil { @@ -71,8 +72,8 @@ func copySparse(t *tar.Writer, br *winio.BackupStreamReader) error { } // archive/tar does not support writing sparse files // so just write zeroes to catch up to the current offset. - if _, err := io.CopyN(t, zeroReader{}, bhdr.Offset-curOffset); err != nil { - return fmt.Errorf("seek to offset %d: %s", bhdr.Offset, err) + if _, err = io.CopyN(t, zeroReader{}, bhdr.Offset-curOffset); err != nil { + return fmt.Errorf("seek to offset %d: %w", bhdr.Offset, err) } if bhdr.Size == 0 { // A sparse block with size = 0 is used to mark the end of the sparse blocks. @@ -106,24 +107,84 @@ func BasicInfoHeader(name string, size int64, fileInfo *winio.FileBasicInfo) *ta hdr.PAXRecords[hdrCreationTime] = formatPAXTime(time.Unix(0, fileInfo.CreationTime.Nanoseconds())) if (fileInfo.FileAttributes & syscall.FILE_ATTRIBUTE_DIRECTORY) != 0 { - hdr.Mode |= c_ISDIR + hdr.Mode |= cISDIR hdr.Size = 0 hdr.Typeflag = tar.TypeDir } return hdr } +// SecurityDescriptorFromTarHeader reads the SDDL associated with the header of the current file +// from the tar header and returns the security descriptor into a byte slice. +func SecurityDescriptorFromTarHeader(hdr *tar.Header) ([]byte, error) { + if sdraw, ok := hdr.PAXRecords[hdrRawSecurityDescriptor]; ok { + sd, err := base64.StdEncoding.DecodeString(sdraw) + if err != nil { + // Not returning sd as-is in the error-case, as base64.DecodeString + // may return partially decoded data (not nil or empty slice) in case + // of a failure: https://github.com/golang/go/blob/go1.17.7/src/encoding/base64/base64.go#L382-L387 + return nil, err + } + return sd, nil + } + // Maintaining old SDDL-based behavior for backward compatibility. All new + // tar headers written by this library will have raw binary for the security + // descriptor. + if sddl, ok := hdr.PAXRecords[hdrSecurityDescriptor]; ok { + return winio.SddlToSecurityDescriptor(sddl) + } + return nil, nil +} + +// ExtendedAttributesFromTarHeader reads the EAs associated with the header of the +// current file from the tar header and returns it as a byte slice. +func ExtendedAttributesFromTarHeader(hdr *tar.Header) ([]byte, error) { + var eas []winio.ExtendedAttribute //nolint:prealloc // len(eas) <= len(hdr.PAXRecords); prealloc is wasteful + for k, v := range hdr.PAXRecords { + if !strings.HasPrefix(k, hdrEaPrefix) { + continue + } + data, err := base64.StdEncoding.DecodeString(v) + if err != nil { + return nil, err + } + eas = append(eas, winio.ExtendedAttribute{ + Name: k[len(hdrEaPrefix):], + Value: data, + }) + } + var eaData []byte + var err error + if len(eas) != 0 { + eaData, err = winio.EncodeExtendedAttributes(eas) + if err != nil { + return nil, err + } + } + return eaData, nil +} + +// EncodeReparsePointFromTarHeader reads the ReparsePoint structure from the tar header +// and encodes it into a byte slice. The file for which this function is called must be a +// symlink. +func EncodeReparsePointFromTarHeader(hdr *tar.Header) []byte { + _, isMountPoint := hdr.PAXRecords[hdrMountPoint] + rp := winio.ReparsePoint{ + Target: filepath.FromSlash(hdr.Linkname), + IsMountPoint: isMountPoint, + } + return winio.EncodeReparsePoint(&rp) +} + // WriteTarFileFromBackupStream writes a file to a tar writer using data from a Win32 backup stream. // // This encodes Win32 metadata as tar pax vendor extensions starting with MSWINDOWS. // // The additional Win32 metadata is: // -// MSWINDOWS.fileattr: The Win32 file attributes, as a decimal value -// -// MSWINDOWS.rawsd: The Win32 security descriptor, in raw binary format -// -// MSWINDOWS.mountpoint: If present, this is a mount point and not a symlink, even though the type is '2' (symlink) +// - MSWINDOWS.fileattr: The Win32 file attributes, as a decimal value +// - MSWINDOWS.rawsd: The Win32 security descriptor, in raw binary format +// - MSWINDOWS.mountpoint: If present, this is a mount point and not a symlink, even though the type is '2' (symlink) func WriteTarFileFromBackupStream(t *tar.Writer, r io.Reader, name string, size int64, fileInfo *winio.FileBasicInfo) error { name = filepath.ToSlash(name) hdr := BasicInfoHeader(name, size, fileInfo) @@ -146,7 +207,7 @@ func WriteTarFileFromBackupStream(t *tar.Writer, r io.Reader, name string, size var dataHdr *winio.BackupHeader for dataHdr == nil { bhdr, err := br.Next() - if err == io.EOF { + if err == io.EOF { //nolint:errorlint break } if err != nil { @@ -154,21 +215,21 @@ func WriteTarFileFromBackupStream(t *tar.Writer, r io.Reader, name string, size } switch bhdr.Id { case winio.BackupData: - hdr.Mode |= c_ISREG + hdr.Mode |= cISREG if !readTwice { dataHdr = bhdr } case winio.BackupSecurity: - sd, err := ioutil.ReadAll(br) + sd, err := io.ReadAll(br) if err != nil { return err } hdr.PAXRecords[hdrRawSecurityDescriptor] = base64.StdEncoding.EncodeToString(sd) case winio.BackupReparseData: - hdr.Mode |= c_ISLNK + hdr.Mode |= cISLNK hdr.Typeflag = tar.TypeSymlink - reparseBuffer, err := ioutil.ReadAll(br) + reparseBuffer, _ := io.ReadAll(br) rp, err := winio.DecodeReparsePoint(reparseBuffer) if err != nil { return err @@ -179,7 +240,7 @@ func WriteTarFileFromBackupStream(t *tar.Writer, r io.Reader, name string, size hdr.Linkname = rp.Target case winio.BackupEaData: - eab, err := ioutil.ReadAll(br) + eab, err := io.ReadAll(br) if err != nil { return err } @@ -213,7 +274,7 @@ func WriteTarFileFromBackupStream(t *tar.Writer, r io.Reader, name string, size } for dataHdr == nil { bhdr, err := br.Next() - if err == io.EOF { + if err == io.EOF { //nolint:errorlint break } if err != nil { @@ -248,7 +309,7 @@ func WriteTarFileFromBackupStream(t *tar.Writer, r io.Reader, name string, size // range of the file containing the range contents. Finally there is a sparse block stream with // size = 0 and offset = . - if dataHdr != nil { + if dataHdr != nil { //nolint:nestif // todo: reduce nesting complexity // A data stream was found. Copy the data. // We assume that we will either have a data stream size > 0 XOR have sparse block streams. if dataHdr.Size > 0 || (dataHdr.Attributes&winio.StreamSparseAttributes) == 0 { @@ -256,13 +317,13 @@ func WriteTarFileFromBackupStream(t *tar.Writer, r io.Reader, name string, size return fmt.Errorf("%s: mismatch between file size %d and header size %d", name, size, dataHdr.Size) } if _, err = io.Copy(t, br); err != nil { - return fmt.Errorf("%s: copying contents from data stream: %s", name, err) + return fmt.Errorf("%s: copying contents from data stream: %w", name, err) } } else if size > 0 { // As of a recent OS change, BackupRead now returns a data stream for empty sparse files. // These files have no sparse block streams, so skip the copySparse call if file size = 0. if err = copySparse(t, br); err != nil { - return fmt.Errorf("%s: copying contents from sparse block stream: %s", name, err) + return fmt.Errorf("%s: copying contents from sparse block stream: %w", name, err) } } } @@ -272,7 +333,7 @@ func WriteTarFileFromBackupStream(t *tar.Writer, r io.Reader, name string, size // been written. In practice, this means that we don't get EA or TXF metadata. for { bhdr, err := br.Next() - if err == io.EOF { + if err == io.EOF { //nolint:errorlint break } if err != nil { @@ -280,35 +341,30 @@ func WriteTarFileFromBackupStream(t *tar.Writer, r io.Reader, name string, size } switch bhdr.Id { case winio.BackupAlternateData: - altName := bhdr.Name - if strings.HasSuffix(altName, ":$DATA") { - altName = altName[:len(altName)-len(":$DATA")] - } - if (bhdr.Attributes & winio.StreamSparseAttributes) == 0 { - hdr = &tar.Header{ - Format: hdr.Format, - Name: name + altName, - Mode: hdr.Mode, - Typeflag: tar.TypeReg, - Size: bhdr.Size, - ModTime: hdr.ModTime, - AccessTime: hdr.AccessTime, - ChangeTime: hdr.ChangeTime, - } - err = t.WriteHeader(hdr) - if err != nil { - return err - } - _, err = io.Copy(t, br) - if err != nil { - return err - } - - } else { + if (bhdr.Attributes & winio.StreamSparseAttributes) != 0 { // Unsupported for now, since the size of the alternate stream is not present // in the backup stream until after the data has been read. return fmt.Errorf("%s: tar of sparse alternate data streams is unsupported", name) } + altName := strings.TrimSuffix(bhdr.Name, ":$DATA") + hdr = &tar.Header{ + Format: hdr.Format, + Name: name + altName, + Mode: hdr.Mode, + Typeflag: tar.TypeReg, + Size: bhdr.Size, + ModTime: hdr.ModTime, + AccessTime: hdr.AccessTime, + ChangeTime: hdr.ChangeTime, + } + err = t.WriteHeader(hdr) + if err != nil { + return err + } + _, err = io.Copy(t, br) + if err != nil { + return err + } case winio.BackupEaData, winio.BackupLink, winio.BackupPropertyData, winio.BackupObjectId, winio.BackupTxfsData: // ignore these streams default: @@ -350,7 +406,7 @@ func FileInfoFromHeader(hdr *tar.Header) (name string, size int64, fileInfo *win } fileInfo.CreationTime = windows.NsecToFiletime(creationTime.UnixNano()) } - return + return name, size, fileInfo, err } // WriteBackupStreamFromTarFile writes a Win32 backup stream from the current tar file. Since this function may process multiple @@ -358,21 +414,10 @@ func FileInfoFromHeader(hdr *tar.Header) (name string, size int64, fileInfo *win // tar file that was not processed, or io.EOF is there are no more. func WriteBackupStreamFromTarFile(w io.Writer, t *tar.Reader, hdr *tar.Header) (*tar.Header, error) { bw := winio.NewBackupStreamWriter(w) - var sd []byte - var err error - // Maintaining old SDDL-based behavior for backward compatibility. All new tar headers written - // by this library will have raw binary for the security descriptor. - if sddl, ok := hdr.PAXRecords[hdrSecurityDescriptor]; ok { - sd, err = winio.SddlToSecurityDescriptor(sddl) - if err != nil { - return nil, err - } - } - if sdraw, ok := hdr.PAXRecords[hdrRawSecurityDescriptor]; ok { - sd, err = base64.StdEncoding.DecodeString(sdraw) - if err != nil { - return nil, err - } + + sd, err := SecurityDescriptorFromTarHeader(hdr) + if err != nil { + return nil, err } if len(sd) != 0 { bhdr := winio.BackupHeader{ @@ -388,25 +433,12 @@ func WriteBackupStreamFromTarFile(w io.Writer, t *tar.Reader, hdr *tar.Header) ( return nil, err } } - var eas []winio.ExtendedAttribute - for k, v := range hdr.PAXRecords { - if !strings.HasPrefix(k, hdrEaPrefix) { - continue - } - data, err := base64.StdEncoding.DecodeString(v) - if err != nil { - return nil, err - } - eas = append(eas, winio.ExtendedAttribute{ - Name: k[len(hdrEaPrefix):], - Value: data, - }) + + eadata, err := ExtendedAttributesFromTarHeader(hdr) + if err != nil { + return nil, err } - if len(eas) != 0 { - eadata, err := winio.EncodeExtendedAttributes(eas) - if err != nil { - return nil, err - } + if len(eadata) != 0 { bhdr := winio.BackupHeader{ Id: winio.BackupEaData, Size: int64(len(eadata)), @@ -420,13 +452,9 @@ func WriteBackupStreamFromTarFile(w io.Writer, t *tar.Reader, hdr *tar.Header) ( return nil, err } } + if hdr.Typeflag == tar.TypeSymlink { - _, isMountPoint := hdr.PAXRecords[hdrMountPoint] - rp := winio.ReparsePoint{ - Target: filepath.FromSlash(hdr.Linkname), - IsMountPoint: isMountPoint, - } - reparse := winio.EncodeReparsePoint(&rp) + reparse := EncodeReparsePointFromTarHeader(hdr) bhdr := winio.BackupHeader{ Id: winio.BackupReparseData, Size: int64(len(reparse)), @@ -440,6 +468,7 @@ func WriteBackupStreamFromTarFile(w io.Writer, t *tar.Reader, hdr *tar.Header) ( return nil, err } } + if hdr.Typeflag == tar.TypeReg || hdr.Typeflag == tar.TypeRegA { bhdr := winio.BackupHeader{ Id: winio.BackupData, diff --git a/vendor/github.com/Microsoft/go-winio/doc.go b/vendor/github.com/Microsoft/go-winio/doc.go new file mode 100644 index 0000000000..1f5bfe2d54 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/doc.go @@ -0,0 +1,22 @@ +// This package provides utilities for efficiently performing Win32 IO operations in Go. +// Currently, this package is provides support for genreal IO and management of +// - named pipes +// - files +// - [Hyper-V sockets] +// +// This code is similar to Go's [net] package, and uses IO completion ports to avoid +// blocking IO on system threads, allowing Go to reuse the thread to schedule other goroutines. +// +// This limits support to Windows Vista and newer operating systems. +// +// Additionally, this package provides support for: +// - creating and managing GUIDs +// - writing to [ETW] +// - opening and manageing VHDs +// - parsing [Windows Image files] +// - auto-generating Win32 API code +// +// [Hyper-V sockets]: https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/user-guide/make-integration-service +// [ETW]: https://docs.microsoft.com/en-us/windows-hardware/drivers/devtest/event-tracing-for-windows--etw- +// [Windows Image files]: https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/work-with-windows-images +package winio diff --git a/vendor/github.com/Microsoft/go-winio/ea.go b/vendor/github.com/Microsoft/go-winio/ea.go index 4051c1b33b..e104dbdfdf 100644 --- a/vendor/github.com/Microsoft/go-winio/ea.go +++ b/vendor/github.com/Microsoft/go-winio/ea.go @@ -33,7 +33,7 @@ func parseEa(b []byte) (ea ExtendedAttribute, nb []byte, err error) { err = binary.Read(bytes.NewReader(b), binary.LittleEndian, &info) if err != nil { err = errInvalidEaBuffer - return + return ea, nb, err } nameOffset := fileFullEaInformationSize @@ -43,7 +43,7 @@ func parseEa(b []byte) (ea ExtendedAttribute, nb []byte, err error) { nextOffset := int(info.NextEntryOffset) if valueLen+valueOffset > len(b) || nextOffset < 0 || nextOffset > len(b) { err = errInvalidEaBuffer - return + return ea, nb, err } ea.Name = string(b[nameOffset : nameOffset+nameLen]) @@ -52,7 +52,7 @@ func parseEa(b []byte) (ea ExtendedAttribute, nb []byte, err error) { if info.NextEntryOffset != 0 { nb = b[info.NextEntryOffset:] } - return + return ea, nb, err } // DecodeExtendedAttributes decodes a list of EAs from a FILE_FULL_EA_INFORMATION @@ -67,7 +67,7 @@ func DecodeExtendedAttributes(b []byte) (eas []ExtendedAttribute, err error) { eas = append(eas, ea) b = nb } - return + return eas, err } func writeEa(buf *bytes.Buffer, ea *ExtendedAttribute, last bool) error { diff --git a/vendor/github.com/Microsoft/go-winio/file.go b/vendor/github.com/Microsoft/go-winio/file.go index 0385e41081..175a99d3f4 100644 --- a/vendor/github.com/Microsoft/go-winio/file.go +++ b/vendor/github.com/Microsoft/go-winio/file.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package winio @@ -10,6 +11,8 @@ import ( "sync/atomic" "syscall" "time" + + "golang.org/x/sys/windows" ) //sys cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) = CancelIoEx @@ -23,6 +26,8 @@ type atomicBool int32 func (b *atomicBool) isSet() bool { return atomic.LoadInt32((*int32)(b)) != 0 } func (b *atomicBool) setFalse() { atomic.StoreInt32((*int32)(b), 0) } func (b *atomicBool) setTrue() { atomic.StoreInt32((*int32)(b), 1) } + +//revive:disable-next-line:predeclared Keep "new" to maintain consistency with "atomic" pkg func (b *atomicBool) swap(new bool) bool { var newInt int32 if new { @@ -31,11 +36,6 @@ func (b *atomicBool) swap(new bool) bool { return atomic.SwapInt32((*int32)(b), newInt) == 1 } -const ( - cFILE_SKIP_COMPLETION_PORT_ON_SUCCESS = 1 - cFILE_SKIP_SET_EVENT_ON_HANDLE = 2 -) - var ( ErrFileClosed = errors.New("file has already been closed") ErrTimeout = &timeoutError{} @@ -43,28 +43,28 @@ var ( type timeoutError struct{} -func (e *timeoutError) Error() string { return "i/o timeout" } -func (e *timeoutError) Timeout() bool { return true } -func (e *timeoutError) Temporary() bool { return true } +func (*timeoutError) Error() string { return "i/o timeout" } +func (*timeoutError) Timeout() bool { return true } +func (*timeoutError) Temporary() bool { return true } type timeoutChan chan struct{} var ioInitOnce sync.Once var ioCompletionPort syscall.Handle -// ioResult contains the result of an asynchronous IO operation +// ioResult contains the result of an asynchronous IO operation. type ioResult struct { bytes uint32 err error } -// ioOperation represents an outstanding asynchronous Win32 IO +// ioOperation represents an outstanding asynchronous Win32 IO. type ioOperation struct { o syscall.Overlapped ch chan ioResult } -func initIo() { +func initIO() { h, err := createIoCompletionPort(syscall.InvalidHandle, 0, 0, 0xffffffff) if err != nil { panic(err) @@ -93,15 +93,15 @@ type deadlineHandler struct { timedout atomicBool } -// makeWin32File makes a new win32File from an existing file handle +// makeWin32File makes a new win32File from an existing file handle. func makeWin32File(h syscall.Handle) (*win32File, error) { f := &win32File{handle: h} - ioInitOnce.Do(initIo) + ioInitOnce.Do(initIO) _, err := createIoCompletionPort(h, ioCompletionPort, 0, 0xffffffff) if err != nil { return nil, err } - err = setFileCompletionNotificationModes(h, cFILE_SKIP_COMPLETION_PORT_ON_SUCCESS|cFILE_SKIP_SET_EVENT_ON_HANDLE) + err = setFileCompletionNotificationModes(h, windows.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS|windows.FILE_SKIP_SET_EVENT_ON_HANDLE) if err != nil { return nil, err } @@ -120,14 +120,14 @@ func MakeOpenFile(h syscall.Handle) (io.ReadWriteCloser, error) { return f, nil } -// closeHandle closes the resources associated with a Win32 handle +// closeHandle closes the resources associated with a Win32 handle. func (f *win32File) closeHandle() { f.wgLock.Lock() // Atomically set that we are closing, releasing the resources only once. if !f.closing.swap(true) { f.wgLock.Unlock() // cancel all IO and wait for it to complete - cancelIoEx(f.handle, nil) + _ = cancelIoEx(f.handle, nil) f.wg.Wait() // at this point, no new IO can start syscall.Close(f.handle) @@ -143,9 +143,14 @@ func (f *win32File) Close() error { return nil } -// prepareIo prepares for a new IO operation. +// IsClosed checks if the file has been closed. +func (f *win32File) IsClosed() bool { + return f.closing.isSet() +} + +// prepareIO prepares for a new IO operation. // The caller must call f.wg.Done() when the IO is finished, prior to Close() returning. -func (f *win32File) prepareIo() (*ioOperation, error) { +func (f *win32File) prepareIO() (*ioOperation, error) { f.wgLock.RLock() if f.closing.isSet() { f.wgLock.RUnlock() @@ -158,7 +163,7 @@ func (f *win32File) prepareIo() (*ioOperation, error) { return c, nil } -// ioCompletionProcessor processes completed async IOs forever +// ioCompletionProcessor processes completed async IOs forever. func ioCompletionProcessor(h syscall.Handle) { for { var bytes uint32 @@ -172,15 +177,17 @@ func ioCompletionProcessor(h syscall.Handle) { } } -// asyncIo processes the return value from ReadFile or WriteFile, blocking until +// todo: helsaawy - create an asyncIO version that takes a context + +// asyncIO processes the return value from ReadFile or WriteFile, blocking until // the operation has actually completed. -func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, err error) (int, error) { - if err != syscall.ERROR_IO_PENDING { +func (f *win32File) asyncIO(c *ioOperation, d *deadlineHandler, bytes uint32, err error) (int, error) { + if err != syscall.ERROR_IO_PENDING { //nolint:errorlint // err is Errno return int(bytes), err } if f.closing.isSet() { - cancelIoEx(f.handle, &c.o) + _ = cancelIoEx(f.handle, &c.o) } var timeout timeoutChan @@ -194,7 +201,7 @@ func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, er select { case r = <-c.ch: err = r.err - if err == syscall.ERROR_OPERATION_ABORTED { + if err == syscall.ERROR_OPERATION_ABORTED { //nolint:errorlint // err is Errno if f.closing.isSet() { err = ErrFileClosed } @@ -204,10 +211,10 @@ func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, er err = wsaGetOverlappedResult(f.handle, &c.o, &bytes, false, &flags) } case <-timeout: - cancelIoEx(f.handle, &c.o) + _ = cancelIoEx(f.handle, &c.o) r = <-c.ch err = r.err - if err == syscall.ERROR_OPERATION_ABORTED { + if err == syscall.ERROR_OPERATION_ABORTED { //nolint:errorlint // err is Errno err = ErrTimeout } } @@ -215,13 +222,14 @@ func (f *win32File) asyncIo(c *ioOperation, d *deadlineHandler, bytes uint32, er // runtime.KeepAlive is needed, as c is passed via native // code to ioCompletionProcessor, c must remain alive // until the channel read is complete. + // todo: (de)allocate *ioOperation via win32 heap functions, instead of needing to KeepAlive? runtime.KeepAlive(c) return int(r.bytes), err } // Read reads from a file handle. func (f *win32File) Read(b []byte) (int, error) { - c, err := f.prepareIo() + c, err := f.prepareIO() if err != nil { return 0, err } @@ -233,13 +241,13 @@ func (f *win32File) Read(b []byte) (int, error) { var bytes uint32 err = syscall.ReadFile(f.handle, b, &bytes, &c.o) - n, err := f.asyncIo(c, &f.readDeadline, bytes, err) + n, err := f.asyncIO(c, &f.readDeadline, bytes, err) runtime.KeepAlive(b) // Handle EOF conditions. if err == nil && n == 0 && len(b) != 0 { return 0, io.EOF - } else if err == syscall.ERROR_BROKEN_PIPE { + } else if err == syscall.ERROR_BROKEN_PIPE { //nolint:errorlint // err is Errno return 0, io.EOF } else { return n, err @@ -248,7 +256,7 @@ func (f *win32File) Read(b []byte) (int, error) { // Write writes to a file handle. func (f *win32File) Write(b []byte) (int, error) { - c, err := f.prepareIo() + c, err := f.prepareIO() if err != nil { return 0, err } @@ -260,7 +268,7 @@ func (f *win32File) Write(b []byte) (int, error) { var bytes uint32 err = syscall.WriteFile(f.handle, b, &bytes, &c.o) - n, err := f.asyncIo(c, &f.writeDeadline, bytes, err) + n, err := f.asyncIO(c, &f.writeDeadline, bytes, err) runtime.KeepAlive(b) return n, err } diff --git a/vendor/github.com/Microsoft/go-winio/fileinfo.go b/vendor/github.com/Microsoft/go-winio/fileinfo.go index 3ab6bff69c..702950e72a 100644 --- a/vendor/github.com/Microsoft/go-winio/fileinfo.go +++ b/vendor/github.com/Microsoft/go-winio/fileinfo.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package winio @@ -14,13 +15,18 @@ import ( type FileBasicInfo struct { CreationTime, LastAccessTime, LastWriteTime, ChangeTime windows.Filetime FileAttributes uint32 - pad uint32 // padding + _ uint32 // padding } // GetFileBasicInfo retrieves times and attributes for a file. func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) { bi := &FileBasicInfo{} - if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil { + if err := windows.GetFileInformationByHandleEx( + windows.Handle(f.Fd()), + windows.FileBasicInfo, + (*byte)(unsafe.Pointer(bi)), + uint32(unsafe.Sizeof(*bi)), + ); err != nil { return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err} } runtime.KeepAlive(f) @@ -29,7 +35,12 @@ func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) { // SetFileBasicInfo sets times and attributes for a file. func SetFileBasicInfo(f *os.File, bi *FileBasicInfo) error { - if err := windows.SetFileInformationByHandle(windows.Handle(f.Fd()), windows.FileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil { + if err := windows.SetFileInformationByHandle( + windows.Handle(f.Fd()), + windows.FileBasicInfo, + (*byte)(unsafe.Pointer(bi)), + uint32(unsafe.Sizeof(*bi)), + ); err != nil { return &os.PathError{Op: "SetFileInformationByHandle", Path: f.Name(), Err: err} } runtime.KeepAlive(f) @@ -48,7 +59,10 @@ type FileStandardInfo struct { // GetFileStandardInfo retrieves ended information for the file. func GetFileStandardInfo(f *os.File) (*FileStandardInfo, error) { si := &FileStandardInfo{} - if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileStandardInfo, (*byte)(unsafe.Pointer(si)), uint32(unsafe.Sizeof(*si))); err != nil { + if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), + windows.FileStandardInfo, + (*byte)(unsafe.Pointer(si)), + uint32(unsafe.Sizeof(*si))); err != nil { return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err} } runtime.KeepAlive(f) @@ -65,7 +79,12 @@ type FileIDInfo struct { // GetFileID retrieves the unique (volume, file ID) pair for a file. func GetFileID(f *os.File) (*FileIDInfo, error) { fileID := &FileIDInfo{} - if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileIdInfo, (*byte)(unsafe.Pointer(fileID)), uint32(unsafe.Sizeof(*fileID))); err != nil { + if err := windows.GetFileInformationByHandleEx( + windows.Handle(f.Fd()), + windows.FileIdInfo, + (*byte)(unsafe.Pointer(fileID)), + uint32(unsafe.Sizeof(*fileID)), + ); err != nil { return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err} } runtime.KeepAlive(f) diff --git a/vendor/github.com/Microsoft/go-winio/hvsock.go b/vendor/github.com/Microsoft/go-winio/hvsock.go index b632f8f8bb..c881916583 100644 --- a/vendor/github.com/Microsoft/go-winio/hvsock.go +++ b/vendor/github.com/Microsoft/go-winio/hvsock.go @@ -1,8 +1,11 @@ +//go:build windows // +build windows package winio import ( + "context" + "errors" "fmt" "io" "net" @@ -11,16 +14,87 @@ import ( "time" "unsafe" + "golang.org/x/sys/windows" + + "github.com/Microsoft/go-winio/internal/socket" "github.com/Microsoft/go-winio/pkg/guid" ) -//sys bind(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socketError] = ws2_32.bind +const afHVSock = 34 // AF_HYPERV -const ( - afHvSock = 34 // AF_HYPERV +// Well known Service and VM IDs +// https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/user-guide/make-integration-service#vmid-wildcards - socketError = ^uintptr(0) -) +// HvsockGUIDWildcard is the wildcard VmId for accepting connections from all partitions. +func HvsockGUIDWildcard() guid.GUID { // 00000000-0000-0000-0000-000000000000 + return guid.GUID{} +} + +// HvsockGUIDBroadcast is the wildcard VmId for broadcasting sends to all partitions. +func HvsockGUIDBroadcast() guid.GUID { // ffffffff-ffff-ffff-ffff-ffffffffffff + return guid.GUID{ + Data1: 0xffffffff, + Data2: 0xffff, + Data3: 0xffff, + Data4: [8]uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + } +} + +// HvsockGUIDLoopback is the Loopback VmId for accepting connections to the same partition as the connector. +func HvsockGUIDLoopback() guid.GUID { // e0e16197-dd56-4a10-9195-5ee7a155a838 + return guid.GUID{ + Data1: 0xe0e16197, + Data2: 0xdd56, + Data3: 0x4a10, + Data4: [8]uint8{0x91, 0x95, 0x5e, 0xe7, 0xa1, 0x55, 0xa8, 0x38}, + } +} + +// HvsockGUIDSiloHost is the address of a silo's host partition: +// - The silo host of a hosted silo is the utility VM. +// - The silo host of a silo on a physical host is the physical host. +func HvsockGUIDSiloHost() guid.GUID { // 36bd0c5c-7276-4223-88ba-7d03b654c568 + return guid.GUID{ + Data1: 0x36bd0c5c, + Data2: 0x7276, + Data3: 0x4223, + Data4: [8]byte{0x88, 0xba, 0x7d, 0x03, 0xb6, 0x54, 0xc5, 0x68}, + } +} + +// HvsockGUIDChildren is the wildcard VmId for accepting connections from the connector's child partitions. +func HvsockGUIDChildren() guid.GUID { // 90db8b89-0d35-4f79-8ce9-49ea0ac8b7cd + return guid.GUID{ + Data1: 0x90db8b89, + Data2: 0xd35, + Data3: 0x4f79, + Data4: [8]uint8{0x8c, 0xe9, 0x49, 0xea, 0xa, 0xc8, 0xb7, 0xcd}, + } +} + +// HvsockGUIDParent is the wildcard VmId for accepting connections from the connector's parent partition. +// Listening on this VmId accepts connection from: +// - Inside silos: silo host partition. +// - Inside hosted silo: host of the VM. +// - Inside VM: VM host. +// - Physical host: Not supported. +func HvsockGUIDParent() guid.GUID { // a42e7cda-d03f-480c-9cc2-a4de20abb878 + return guid.GUID{ + Data1: 0xa42e7cda, + Data2: 0xd03f, + Data3: 0x480c, + Data4: [8]uint8{0x9c, 0xc2, 0xa4, 0xde, 0x20, 0xab, 0xb8, 0x78}, + } +} + +// hvsockVsockServiceTemplate is the Service GUID used for the VSOCK protocol. +func hvsockVsockServiceTemplate() guid.GUID { // 00000000-facb-11e6-bd58-64006a7986d3 + return guid.GUID{ + Data2: 0xfacb, + Data3: 0x11e6, + Data4: [8]uint8{0xbd, 0x58, 0x64, 0x00, 0x6a, 0x79, 0x86, 0xd3}, + } +} // An HvsockAddr is an address for a AF_HYPERV socket. type HvsockAddr struct { @@ -35,8 +109,10 @@ type rawHvsockAddr struct { ServiceID guid.GUID } +var _ socket.RawSockaddr = &rawHvsockAddr{} + // Network returns the address's network name, "hvsock". -func (addr *HvsockAddr) Network() string { +func (*HvsockAddr) Network() string { return "hvsock" } @@ -46,14 +122,14 @@ func (addr *HvsockAddr) String() string { // VsockServiceID returns an hvsock service ID corresponding to the specified AF_VSOCK port. func VsockServiceID(port uint32) guid.GUID { - g, _ := guid.FromString("00000000-facb-11e6-bd58-64006a7986d3") + g := hvsockVsockServiceTemplate() // make a copy g.Data1 = port return g } func (addr *HvsockAddr) raw() rawHvsockAddr { return rawHvsockAddr{ - Family: afHvSock, + Family: afHVSock, VMID: addr.VMID, ServiceID: addr.ServiceID, } @@ -64,20 +140,48 @@ func (addr *HvsockAddr) fromRaw(raw *rawHvsockAddr) { addr.ServiceID = raw.ServiceID } +// Sockaddr returns a pointer to and the size of this struct. +// +// Implements the [socket.RawSockaddr] interface, and allows use in +// [socket.Bind] and [socket.ConnectEx]. +func (r *rawHvsockAddr) Sockaddr() (unsafe.Pointer, int32, error) { + return unsafe.Pointer(r), int32(unsafe.Sizeof(rawHvsockAddr{})), nil +} + +// Sockaddr interface allows use with `sockets.Bind()` and `.ConnectEx()`. +func (r *rawHvsockAddr) FromBytes(b []byte) error { + n := int(unsafe.Sizeof(rawHvsockAddr{})) + + if len(b) < n { + return fmt.Errorf("got %d, want %d: %w", len(b), n, socket.ErrBufferSize) + } + + copy(unsafe.Slice((*byte)(unsafe.Pointer(r)), n), b[:n]) + if r.Family != afHVSock { + return fmt.Errorf("got %d, want %d: %w", r.Family, afHVSock, socket.ErrAddrFamily) + } + + return nil +} + // HvsockListener is a socket listener for the AF_HYPERV address family. type HvsockListener struct { sock *win32File addr HvsockAddr } +var _ net.Listener = &HvsockListener{} + // HvsockConn is a connected socket of the AF_HYPERV address family. type HvsockConn struct { sock *win32File local, remote HvsockAddr } -func newHvSocket() (*win32File, error) { - fd, err := syscall.Socket(afHvSock, syscall.SOCK_STREAM, 1) +var _ net.Conn = &HvsockConn{} + +func newHVSocket() (*win32File, error) { + fd, err := syscall.Socket(afHVSock, syscall.SOCK_STREAM, 1) if err != nil { return nil, os.NewSyscallError("socket", err) } @@ -93,12 +197,12 @@ func newHvSocket() (*win32File, error) { // ListenHvsock listens for connections on the specified hvsock address. func ListenHvsock(addr *HvsockAddr) (_ *HvsockListener, err error) { l := &HvsockListener{addr: *addr} - sock, err := newHvSocket() + sock, err := newHVSocket() if err != nil { return nil, l.opErr("listen", err) } sa := addr.raw() - err = bind(sock.handle, unsafe.Pointer(&sa), int32(unsafe.Sizeof(sa))) + err = socket.Bind(windows.Handle(sock.handle), &sa) if err != nil { return nil, l.opErr("listen", os.NewSyscallError("socket", err)) } @@ -120,7 +224,7 @@ func (l *HvsockListener) Addr() net.Addr { // Accept waits for the next connection and returns it. func (l *HvsockListener) Accept() (_ net.Conn, err error) { - sock, err := newHvSocket() + sock, err := newHVSocket() if err != nil { return nil, l.opErr("accept", err) } @@ -129,27 +233,42 @@ func (l *HvsockListener) Accept() (_ net.Conn, err error) { sock.Close() } }() - c, err := l.sock.prepareIo() + c, err := l.sock.prepareIO() if err != nil { return nil, l.opErr("accept", err) } defer l.sock.wg.Done() // AcceptEx, per documentation, requires an extra 16 bytes per address. + // + // https://docs.microsoft.com/en-us/windows/win32/api/mswsock/nf-mswsock-acceptex const addrlen = uint32(16 + unsafe.Sizeof(rawHvsockAddr{})) var addrbuf [addrlen * 2]byte var bytes uint32 - err = syscall.AcceptEx(l.sock.handle, sock.handle, &addrbuf[0], 0, addrlen, addrlen, &bytes, &c.o) - _, err = l.sock.asyncIo(c, nil, bytes, err) - if err != nil { + err = syscall.AcceptEx(l.sock.handle, sock.handle, &addrbuf[0], 0 /* rxdatalen */, addrlen, addrlen, &bytes, &c.o) + if _, err = l.sock.asyncIO(c, nil, bytes, err); err != nil { return nil, l.opErr("accept", os.NewSyscallError("acceptex", err)) } + conn := &HvsockConn{ sock: sock, } + // The local address returned in the AcceptEx buffer is the same as the Listener socket's + // address. However, the service GUID reported by GetSockName is different from the Listeners + // socket, and is sometimes the same as the local address of the socket that dialed the + // address, with the service GUID.Data1 incremented, but othertimes is different. + // todo: does the local address matter? is the listener's address or the actual address appropriate? conn.local.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[0]))) conn.remote.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[addrlen]))) + + // initialize the accepted socket and update its properties with those of the listening socket + if err = windows.Setsockopt(windows.Handle(sock.handle), + windows.SOL_SOCKET, windows.SO_UPDATE_ACCEPT_CONTEXT, + (*byte)(unsafe.Pointer(&l.sock.handle)), int32(unsafe.Sizeof(l.sock.handle))); err != nil { + return nil, conn.opErr("accept", os.NewSyscallError("setsockopt", err)) + } + sock = nil return conn, nil } @@ -159,43 +278,171 @@ func (l *HvsockListener) Close() error { return l.sock.Close() } -/* Need to finish ConnectEx handling -func DialHvsock(ctx context.Context, addr *HvsockAddr) (*HvsockConn, error) { - sock, err := newHvSocket() +// HvsockDialer configures and dials a Hyper-V Socket (ie, [HvsockConn]). +type HvsockDialer struct { + // Deadline is the time the Dial operation must connect before erroring. + Deadline time.Time + + // Retries is the number of additional connects to try if the connection times out, is refused, + // or the host is unreachable + Retries uint + + // RetryWait is the time to wait after a connection error to retry + RetryWait time.Duration + + rt *time.Timer // redial wait timer +} + +// Dial the Hyper-V socket at addr. +// +// See [HvsockDialer.Dial] for more information. +func Dial(ctx context.Context, addr *HvsockAddr) (conn *HvsockConn, err error) { + return (&HvsockDialer{}).Dial(ctx, addr) +} + +// Dial attempts to connect to the Hyper-V socket at addr, and returns a connection if successful. +// Will attempt (HvsockDialer).Retries if dialing fails, waiting (HvsockDialer).RetryWait between +// retries. +// +// Dialing can be cancelled either by providing (HvsockDialer).Deadline, or cancelling ctx. +func (d *HvsockDialer) Dial(ctx context.Context, addr *HvsockAddr) (conn *HvsockConn, err error) { + op := "dial" + // create the conn early to use opErr() + conn = &HvsockConn{ + remote: *addr, + } + + if !d.Deadline.IsZero() { + var cancel context.CancelFunc + ctx, cancel = context.WithDeadline(ctx, d.Deadline) + defer cancel() + } + + // preemptive timeout/cancellation check + if err = ctx.Err(); err != nil { + return nil, conn.opErr(op, err) + } + + sock, err := newHVSocket() if err != nil { - return nil, err + return nil, conn.opErr(op, err) } defer func() { if sock != nil { sock.Close() } }() - c, err := sock.prepareIo() + + sa := addr.raw() + err = socket.Bind(windows.Handle(sock.handle), &sa) if err != nil { - return nil, err + return nil, conn.opErr(op, os.NewSyscallError("bind", err)) + } + + c, err := sock.prepareIO() + if err != nil { + return nil, conn.opErr(op, err) } defer sock.wg.Done() var bytes uint32 - err = windows.ConnectEx(windows.Handle(sock.handle), sa, nil, 0, &bytes, &c.o) - _, err = sock.asyncIo(ctx, c, nil, bytes, err) + for i := uint(0); i <= d.Retries; i++ { + err = socket.ConnectEx( + windows.Handle(sock.handle), + &sa, + nil, // sendBuf + 0, // sendDataLen + &bytes, + (*windows.Overlapped)(unsafe.Pointer(&c.o))) + _, err = sock.asyncIO(c, nil, bytes, err) + if i < d.Retries && canRedial(err) { + if err = d.redialWait(ctx); err == nil { + continue + } + } + break + } if err != nil { - return nil, err + return nil, conn.opErr(op, os.NewSyscallError("connectex", err)) } - conn := &HvsockConn{ - sock: sock, - remote: *addr, + + // update the connection properties, so shutdown can be used + if err = windows.Setsockopt( + windows.Handle(sock.handle), + windows.SOL_SOCKET, + windows.SO_UPDATE_CONNECT_CONTEXT, + nil, // optvalue + 0, // optlen + ); err != nil { + return nil, conn.opErr(op, os.NewSyscallError("setsockopt", err)) + } + + // get the local name + var sal rawHvsockAddr + err = socket.GetSockName(windows.Handle(sock.handle), &sal) + if err != nil { + return nil, conn.opErr(op, os.NewSyscallError("getsockname", err)) + } + conn.local.fromRaw(&sal) + + // one last check for timeout, since asyncIO doesn't check the context + if err = ctx.Err(); err != nil { + return nil, conn.opErr(op, err) } + + conn.sock = sock sock = nil + return conn, nil } -*/ + +// redialWait waits before attempting to redial, resetting the timer as appropriate. +func (d *HvsockDialer) redialWait(ctx context.Context) (err error) { + if d.RetryWait == 0 { + return nil + } + + if d.rt == nil { + d.rt = time.NewTimer(d.RetryWait) + } else { + // should already be stopped and drained + d.rt.Reset(d.RetryWait) + } + + select { + case <-ctx.Done(): + case <-d.rt.C: + return nil + } + + // stop and drain the timer + if !d.rt.Stop() { + <-d.rt.C + } + return ctx.Err() +} + +// assumes error is a plain, unwrapped syscall.Errno provided by direct syscall. +func canRedial(err error) bool { + //nolint:errorlint // guaranteed to be an Errno + switch err { + case windows.WSAECONNREFUSED, windows.WSAENETUNREACH, windows.WSAETIMEDOUT, + windows.ERROR_CONNECTION_REFUSED, windows.ERROR_CONNECTION_UNAVAIL: + return true + default: + return false + } +} func (conn *HvsockConn) opErr(op string, err error) error { + // translate from "file closed" to "socket closed" + if errors.Is(err, ErrFileClosed) { + err = socket.ErrSocketClosed + } return &net.OpError{Op: op, Net: "hvsock", Source: &conn.local, Addr: &conn.remote, Err: err} } func (conn *HvsockConn) Read(b []byte) (int, error) { - c, err := conn.sock.prepareIo() + c, err := conn.sock.prepareIO() if err != nil { return 0, conn.opErr("read", err) } @@ -203,10 +450,11 @@ func (conn *HvsockConn) Read(b []byte) (int, error) { buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))} var flags, bytes uint32 err = syscall.WSARecv(conn.sock.handle, &buf, 1, &bytes, &flags, &c.o, nil) - n, err := conn.sock.asyncIo(c, &conn.sock.readDeadline, bytes, err) + n, err := conn.sock.asyncIO(c, &conn.sock.readDeadline, bytes, err) if err != nil { - if _, ok := err.(syscall.Errno); ok { - err = os.NewSyscallError("wsarecv", err) + var eno windows.Errno + if errors.As(err, &eno) { + err = os.NewSyscallError("wsarecv", eno) } return 0, conn.opErr("read", err) } else if n == 0 { @@ -229,7 +477,7 @@ func (conn *HvsockConn) Write(b []byte) (int, error) { } func (conn *HvsockConn) write(b []byte) (int, error) { - c, err := conn.sock.prepareIo() + c, err := conn.sock.prepareIO() if err != nil { return 0, conn.opErr("write", err) } @@ -237,10 +485,11 @@ func (conn *HvsockConn) write(b []byte) (int, error) { buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))} var bytes uint32 err = syscall.WSASend(conn.sock.handle, &buf, 1, &bytes, 0, &c.o, nil) - n, err := conn.sock.asyncIo(c, &conn.sock.writeDeadline, bytes, err) + n, err := conn.sock.asyncIO(c, &conn.sock.writeDeadline, bytes, err) if err != nil { - if _, ok := err.(syscall.Errno); ok { - err = os.NewSyscallError("wsasend", err) + var eno windows.Errno + if errors.As(err, &eno) { + err = os.NewSyscallError("wsasend", eno) } return 0, conn.opErr("write", err) } @@ -252,29 +501,43 @@ func (conn *HvsockConn) Close() error { return conn.sock.Close() } +func (conn *HvsockConn) IsClosed() bool { + return conn.sock.IsClosed() +} + +// shutdown disables sending or receiving on a socket. func (conn *HvsockConn) shutdown(how int) error { - err := syscall.Shutdown(conn.sock.handle, syscall.SHUT_RD) + if conn.IsClosed() { + return socket.ErrSocketClosed + } + + err := syscall.Shutdown(conn.sock.handle, how) if err != nil { + // If the connection was closed, shutdowns fail with "not connected" + if errors.Is(err, windows.WSAENOTCONN) || + errors.Is(err, windows.WSAESHUTDOWN) { + err = socket.ErrSocketClosed + } return os.NewSyscallError("shutdown", err) } return nil } -// CloseRead shuts down the read end of the socket. +// CloseRead shuts down the read end of the socket, preventing future read operations. func (conn *HvsockConn) CloseRead() error { err := conn.shutdown(syscall.SHUT_RD) if err != nil { - return conn.opErr("close", err) + return conn.opErr("closeread", err) } return nil } -// CloseWrite shuts down the write end of the socket, notifying the other endpoint that -// no more data will be written. +// CloseWrite shuts down the write end of the socket, preventing future write operations and +// notifying the other endpoint that no more data will be written. func (conn *HvsockConn) CloseWrite() error { err := conn.shutdown(syscall.SHUT_WR) if err != nil { - return conn.opErr("close", err) + return conn.opErr("closewrite", err) } return nil } @@ -291,8 +554,13 @@ func (conn *HvsockConn) RemoteAddr() net.Addr { // SetDeadline implements the net.Conn SetDeadline method. func (conn *HvsockConn) SetDeadline(t time.Time) error { - conn.SetReadDeadline(t) - conn.SetWriteDeadline(t) + // todo: implement `SetDeadline` for `win32File` + if err := conn.SetReadDeadline(t); err != nil { + return fmt.Errorf("set read deadline: %w", err) + } + if err := conn.SetWriteDeadline(t); err != nil { + return fmt.Errorf("set write deadline: %w", err) + } return nil } diff --git a/vendor/github.com/Microsoft/go-winio/internal/fs/doc.go b/vendor/github.com/Microsoft/go-winio/internal/fs/doc.go new file mode 100644 index 0000000000..1f65388178 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/internal/fs/doc.go @@ -0,0 +1,2 @@ +// This package contains Win32 filesystem functionality. +package fs diff --git a/vendor/github.com/Microsoft/go-winio/internal/fs/fs.go b/vendor/github.com/Microsoft/go-winio/internal/fs/fs.go new file mode 100644 index 0000000000..509b3ec641 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/internal/fs/fs.go @@ -0,0 +1,202 @@ +//go:build windows + +package fs + +import ( + "golang.org/x/sys/windows" + + "github.com/Microsoft/go-winio/internal/stringbuffer" +) + +//go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zsyscall_windows.go fs.go + +// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew +//sys CreateFile(name string, access AccessMask, mode FileShareMode, sa *syscall.SecurityAttributes, createmode FileCreationDisposition, attrs FileFlagOrAttribute, templatefile windows.Handle) (handle windows.Handle, err error) [failretval==windows.InvalidHandle] = CreateFileW + +const NullHandle windows.Handle = 0 + +// AccessMask defines standard, specific, and generic rights. +// +// Bitmask: +// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 +// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +// +---------------+---------------+-------------------------------+ +// |G|G|G|G|Resvd|A| StandardRights| SpecificRights | +// |R|W|E|A| |S| | | +// +-+-------------+---------------+-------------------------------+ +// +// GR Generic Read +// GW Generic Write +// GE Generic Exectue +// GA Generic All +// Resvd Reserved +// AS Access Security System +// +// https://learn.microsoft.com/en-us/windows/win32/secauthz/access-mask +// +// https://learn.microsoft.com/en-us/windows/win32/secauthz/generic-access-rights +// +// https://learn.microsoft.com/en-us/windows/win32/fileio/file-access-rights-constants +type AccessMask = windows.ACCESS_MASK + +//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API. +const ( + // Not actually any. + // + // For CreateFile: "query certain metadata such as file, directory, or device attributes without accessing that file or device" + // https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew#parameters + FILE_ANY_ACCESS AccessMask = 0 + + // Specific Object Access + // from ntioapi.h + + FILE_READ_DATA AccessMask = (0x0001) // file & pipe + FILE_LIST_DIRECTORY AccessMask = (0x0001) // directory + + FILE_WRITE_DATA AccessMask = (0x0002) // file & pipe + FILE_ADD_FILE AccessMask = (0x0002) // directory + + FILE_APPEND_DATA AccessMask = (0x0004) // file + FILE_ADD_SUBDIRECTORY AccessMask = (0x0004) // directory + FILE_CREATE_PIPE_INSTANCE AccessMask = (0x0004) // named pipe + + FILE_READ_EA AccessMask = (0x0008) // file & directory + FILE_READ_PROPERTIES AccessMask = FILE_READ_EA + + FILE_WRITE_EA AccessMask = (0x0010) // file & directory + FILE_WRITE_PROPERTIES AccessMask = FILE_WRITE_EA + + FILE_EXECUTE AccessMask = (0x0020) // file + FILE_TRAVERSE AccessMask = (0x0020) // directory + + FILE_DELETE_CHILD AccessMask = (0x0040) // directory + + FILE_READ_ATTRIBUTES AccessMask = (0x0080) // all + + FILE_WRITE_ATTRIBUTES AccessMask = (0x0100) // all + + FILE_ALL_ACCESS AccessMask = (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1FF) + FILE_GENERIC_READ AccessMask = (STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE) + FILE_GENERIC_WRITE AccessMask = (STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA | SYNCHRONIZE) + FILE_GENERIC_EXECUTE AccessMask = (STANDARD_RIGHTS_EXECUTE | FILE_READ_ATTRIBUTES | FILE_EXECUTE | SYNCHRONIZE) + + SPECIFIC_RIGHTS_ALL AccessMask = 0x0000FFFF + + // Standard Access + // from ntseapi.h + + DELETE AccessMask = 0x0001_0000 + READ_CONTROL AccessMask = 0x0002_0000 + WRITE_DAC AccessMask = 0x0004_0000 + WRITE_OWNER AccessMask = 0x0008_0000 + SYNCHRONIZE AccessMask = 0x0010_0000 + + STANDARD_RIGHTS_REQUIRED AccessMask = 0x000F_0000 + + STANDARD_RIGHTS_READ AccessMask = READ_CONTROL + STANDARD_RIGHTS_WRITE AccessMask = READ_CONTROL + STANDARD_RIGHTS_EXECUTE AccessMask = READ_CONTROL + + STANDARD_RIGHTS_ALL AccessMask = 0x001F_0000 +) + +type FileShareMode uint32 + +//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API. +const ( + FILE_SHARE_NONE FileShareMode = 0x00 + FILE_SHARE_READ FileShareMode = 0x01 + FILE_SHARE_WRITE FileShareMode = 0x02 + FILE_SHARE_DELETE FileShareMode = 0x04 + FILE_SHARE_VALID_FLAGS FileShareMode = 0x07 +) + +type FileCreationDisposition uint32 + +//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API. +const ( + // from winbase.h + + CREATE_NEW FileCreationDisposition = 0x01 + CREATE_ALWAYS FileCreationDisposition = 0x02 + OPEN_EXISTING FileCreationDisposition = 0x03 + OPEN_ALWAYS FileCreationDisposition = 0x04 + TRUNCATE_EXISTING FileCreationDisposition = 0x05 +) + +// CreateFile and co. take flags or attributes together as one parameter. +// Define alias until we can use generics to allow both + +// https://learn.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants +type FileFlagOrAttribute uint32 + +//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API. +const ( // from winnt.h + FILE_FLAG_WRITE_THROUGH FileFlagOrAttribute = 0x8000_0000 + FILE_FLAG_OVERLAPPED FileFlagOrAttribute = 0x4000_0000 + FILE_FLAG_NO_BUFFERING FileFlagOrAttribute = 0x2000_0000 + FILE_FLAG_RANDOM_ACCESS FileFlagOrAttribute = 0x1000_0000 + FILE_FLAG_SEQUENTIAL_SCAN FileFlagOrAttribute = 0x0800_0000 + FILE_FLAG_DELETE_ON_CLOSE FileFlagOrAttribute = 0x0400_0000 + FILE_FLAG_BACKUP_SEMANTICS FileFlagOrAttribute = 0x0200_0000 + FILE_FLAG_POSIX_SEMANTICS FileFlagOrAttribute = 0x0100_0000 + FILE_FLAG_OPEN_REPARSE_POINT FileFlagOrAttribute = 0x0020_0000 + FILE_FLAG_OPEN_NO_RECALL FileFlagOrAttribute = 0x0010_0000 + FILE_FLAG_FIRST_PIPE_INSTANCE FileFlagOrAttribute = 0x0008_0000 +) + +type FileSQSFlag = FileFlagOrAttribute + +//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API. +const ( // from winbase.h + SECURITY_ANONYMOUS FileSQSFlag = FileSQSFlag(SecurityAnonymous << 16) + SECURITY_IDENTIFICATION FileSQSFlag = FileSQSFlag(SecurityIdentification << 16) + SECURITY_IMPERSONATION FileSQSFlag = FileSQSFlag(SecurityImpersonation << 16) + SECURITY_DELEGATION FileSQSFlag = FileSQSFlag(SecurityDelegation << 16) + + SECURITY_SQOS_PRESENT FileSQSFlag = 0x00100000 + SECURITY_VALID_SQOS_FLAGS FileSQSFlag = 0x001F0000 +) + +// GetFinalPathNameByHandle flags +// +// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfinalpathnamebyhandlew#parameters +type GetFinalPathFlag uint32 + +//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API. +const ( + GetFinalPathDefaultFlag GetFinalPathFlag = 0x0 + + FILE_NAME_NORMALIZED GetFinalPathFlag = 0x0 + FILE_NAME_OPENED GetFinalPathFlag = 0x8 + + VOLUME_NAME_DOS GetFinalPathFlag = 0x0 + VOLUME_NAME_GUID GetFinalPathFlag = 0x1 + VOLUME_NAME_NT GetFinalPathFlag = 0x2 + VOLUME_NAME_NONE GetFinalPathFlag = 0x4 +) + +// getFinalPathNameByHandle facilitates calling the Windows API GetFinalPathNameByHandle +// with the given handle and flags. It transparently takes care of creating a buffer of the +// correct size for the call. +// +// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfinalpathnamebyhandlew +func GetFinalPathNameByHandle(h windows.Handle, flags GetFinalPathFlag) (string, error) { + b := stringbuffer.NewWString() + //TODO: can loop infinitely if Win32 keeps returning the same (or a larger) n? + for { + n, err := windows.GetFinalPathNameByHandle(h, b.Pointer(), b.Cap(), uint32(flags)) + if err != nil { + return "", err + } + // If the buffer wasn't large enough, n will be the total size needed (including null terminator). + // Resize and try again. + if n > b.Cap() { + b.ResizeTo(n) + continue + } + // If the buffer is large enough, n will be the size not including the null terminator. + // Convert to a Go string and return. + return b.String(), nil + } +} diff --git a/vendor/github.com/Microsoft/go-winio/internal/fs/security.go b/vendor/github.com/Microsoft/go-winio/internal/fs/security.go new file mode 100644 index 0000000000..81760ac67e --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/internal/fs/security.go @@ -0,0 +1,12 @@ +package fs + +// https://learn.microsoft.com/en-us/windows/win32/api/winnt/ne-winnt-security_impersonation_level +type SecurityImpersonationLevel int32 // C default enums underlying type is `int`, which is Go `int32` + +// Impersonation levels +const ( + SecurityAnonymous SecurityImpersonationLevel = 0 + SecurityIdentification SecurityImpersonationLevel = 1 + SecurityImpersonation SecurityImpersonationLevel = 2 + SecurityDelegation SecurityImpersonationLevel = 3 +) diff --git a/vendor/github.com/Microsoft/go-winio/internal/fs/zsyscall_windows.go b/vendor/github.com/Microsoft/go-winio/internal/fs/zsyscall_windows.go new file mode 100644 index 0000000000..e2f7bb24e5 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/internal/fs/zsyscall_windows.go @@ -0,0 +1,64 @@ +//go:build windows + +// Code generated by 'go generate' using "github.com/Microsoft/go-winio/tools/mkwinsyscall"; DO NOT EDIT. + +package fs + +import ( + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) + +var _ unsafe.Pointer + +// Do the interface allocations only once for common +// Errno values. +const ( + errnoERROR_IO_PENDING = 997 +) + +var ( + errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) + errERROR_EINVAL error = syscall.EINVAL +) + +// errnoErr returns common boxed Errno values, to prevent +// allocations at runtime. +func errnoErr(e syscall.Errno) error { + switch e { + case 0: + return errERROR_EINVAL + case errnoERROR_IO_PENDING: + return errERROR_IO_PENDING + } + // TODO: add more here, after collecting data on the common + // error values see on Windows. (perhaps when running + // all.bat?) + return e +} + +var ( + modkernel32 = windows.NewLazySystemDLL("kernel32.dll") + + procCreateFileW = modkernel32.NewProc("CreateFileW") +) + +func CreateFile(name string, access AccessMask, mode FileShareMode, sa *syscall.SecurityAttributes, createmode FileCreationDisposition, attrs FileFlagOrAttribute, templatefile windows.Handle) (handle windows.Handle, err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(name) + if err != nil { + return + } + return _CreateFile(_p0, access, mode, sa, createmode, attrs, templatefile) +} + +func _CreateFile(name *uint16, access AccessMask, mode FileShareMode, sa *syscall.SecurityAttributes, createmode FileCreationDisposition, attrs FileFlagOrAttribute, templatefile windows.Handle) (handle windows.Handle, err error) { + r0, _, e1 := syscall.Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0) + handle = windows.Handle(r0) + if handle == windows.InvalidHandle { + err = errnoErr(e1) + } + return +} diff --git a/vendor/github.com/Microsoft/go-winio/internal/socket/rawaddr.go b/vendor/github.com/Microsoft/go-winio/internal/socket/rawaddr.go new file mode 100644 index 0000000000..7e82f9afa9 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/internal/socket/rawaddr.go @@ -0,0 +1,20 @@ +package socket + +import ( + "unsafe" +) + +// RawSockaddr allows structs to be used with [Bind] and [ConnectEx]. The +// struct must meet the Win32 sockaddr requirements specified here: +// https://docs.microsoft.com/en-us/windows/win32/winsock/sockaddr-2 +// +// Specifically, the struct size must be least larger than an int16 (unsigned short) +// for the address family. +type RawSockaddr interface { + // Sockaddr returns a pointer to the RawSockaddr and its struct size, allowing + // for the RawSockaddr's data to be overwritten by syscalls (if necessary). + // + // It is the callers responsibility to validate that the values are valid; invalid + // pointers or size can cause a panic. + Sockaddr() (unsafe.Pointer, int32, error) +} diff --git a/vendor/github.com/Microsoft/go-winio/internal/socket/socket.go b/vendor/github.com/Microsoft/go-winio/internal/socket/socket.go new file mode 100644 index 0000000000..aeb7b7250f --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/internal/socket/socket.go @@ -0,0 +1,179 @@ +//go:build windows + +package socket + +import ( + "errors" + "fmt" + "net" + "sync" + "syscall" + "unsafe" + + "github.com/Microsoft/go-winio/pkg/guid" + "golang.org/x/sys/windows" +) + +//go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zsyscall_windows.go socket.go + +//sys getsockname(s windows.Handle, name unsafe.Pointer, namelen *int32) (err error) [failretval==socketError] = ws2_32.getsockname +//sys getpeername(s windows.Handle, name unsafe.Pointer, namelen *int32) (err error) [failretval==socketError] = ws2_32.getpeername +//sys bind(s windows.Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socketError] = ws2_32.bind + +const socketError = uintptr(^uint32(0)) + +var ( + // todo(helsaawy): create custom error types to store the desired vs actual size and addr family? + + ErrBufferSize = errors.New("buffer size") + ErrAddrFamily = errors.New("address family") + ErrInvalidPointer = errors.New("invalid pointer") + ErrSocketClosed = fmt.Errorf("socket closed: %w", net.ErrClosed) +) + +// todo(helsaawy): replace these with generics, ie: GetSockName[S RawSockaddr](s windows.Handle) (S, error) + +// GetSockName writes the local address of socket s to the [RawSockaddr] rsa. +// If rsa is not large enough, the [windows.WSAEFAULT] is returned. +func GetSockName(s windows.Handle, rsa RawSockaddr) error { + ptr, l, err := rsa.Sockaddr() + if err != nil { + return fmt.Errorf("could not retrieve socket pointer and size: %w", err) + } + + // although getsockname returns WSAEFAULT if the buffer is too small, it does not set + // &l to the correct size, so--apart from doubling the buffer repeatedly--there is no remedy + return getsockname(s, ptr, &l) +} + +// GetPeerName returns the remote address the socket is connected to. +// +// See [GetSockName] for more information. +func GetPeerName(s windows.Handle, rsa RawSockaddr) error { + ptr, l, err := rsa.Sockaddr() + if err != nil { + return fmt.Errorf("could not retrieve socket pointer and size: %w", err) + } + + return getpeername(s, ptr, &l) +} + +func Bind(s windows.Handle, rsa RawSockaddr) (err error) { + ptr, l, err := rsa.Sockaddr() + if err != nil { + return fmt.Errorf("could not retrieve socket pointer and size: %w", err) + } + + return bind(s, ptr, l) +} + +// "golang.org/x/sys/windows".ConnectEx and .Bind only accept internal implementations of the +// their sockaddr interface, so they cannot be used with HvsockAddr +// Replicate functionality here from +// https://cs.opensource.google/go/x/sys/+/master:windows/syscall_windows.go + +// The function pointers to `AcceptEx`, `ConnectEx` and `GetAcceptExSockaddrs` must be loaded at +// runtime via a WSAIoctl call: +// https://docs.microsoft.com/en-us/windows/win32/api/Mswsock/nc-mswsock-lpfn_connectex#remarks + +type runtimeFunc struct { + id guid.GUID + once sync.Once + addr uintptr + err error +} + +func (f *runtimeFunc) Load() error { + f.once.Do(func() { + var s windows.Handle + s, f.err = windows.Socket(windows.AF_INET, windows.SOCK_STREAM, windows.IPPROTO_TCP) + if f.err != nil { + return + } + defer windows.CloseHandle(s) //nolint:errcheck + + var n uint32 + f.err = windows.WSAIoctl(s, + windows.SIO_GET_EXTENSION_FUNCTION_POINTER, + (*byte)(unsafe.Pointer(&f.id)), + uint32(unsafe.Sizeof(f.id)), + (*byte)(unsafe.Pointer(&f.addr)), + uint32(unsafe.Sizeof(f.addr)), + &n, + nil, // overlapped + 0, // completionRoutine + ) + }) + return f.err +} + +var ( + // todo: add `AcceptEx` and `GetAcceptExSockaddrs` + WSAID_CONNECTEX = guid.GUID{ //revive:disable-line:var-naming ALL_CAPS + Data1: 0x25a207b9, + Data2: 0xddf3, + Data3: 0x4660, + Data4: [8]byte{0x8e, 0xe9, 0x76, 0xe5, 0x8c, 0x74, 0x06, 0x3e}, + } + + connectExFunc = runtimeFunc{id: WSAID_CONNECTEX} +) + +func ConnectEx( + fd windows.Handle, + rsa RawSockaddr, + sendBuf *byte, + sendDataLen uint32, + bytesSent *uint32, + overlapped *windows.Overlapped, +) error { + if err := connectExFunc.Load(); err != nil { + return fmt.Errorf("failed to load ConnectEx function pointer: %w", err) + } + ptr, n, err := rsa.Sockaddr() + if err != nil { + return err + } + return connectEx(fd, ptr, n, sendBuf, sendDataLen, bytesSent, overlapped) +} + +// BOOL LpfnConnectex( +// [in] SOCKET s, +// [in] const sockaddr *name, +// [in] int namelen, +// [in, optional] PVOID lpSendBuffer, +// [in] DWORD dwSendDataLength, +// [out] LPDWORD lpdwBytesSent, +// [in] LPOVERLAPPED lpOverlapped +// ) + +func connectEx( + s windows.Handle, + name unsafe.Pointer, + namelen int32, + sendBuf *byte, + sendDataLen uint32, + bytesSent *uint32, + overlapped *windows.Overlapped, +) (err error) { + // todo: after upgrading to 1.18, switch from syscall.Syscall9 to syscall.SyscallN + r1, _, e1 := syscall.Syscall9(connectExFunc.addr, + 7, + uintptr(s), + uintptr(name), + uintptr(namelen), + uintptr(unsafe.Pointer(sendBuf)), + uintptr(sendDataLen), + uintptr(unsafe.Pointer(bytesSent)), + uintptr(unsafe.Pointer(overlapped)), + 0, + 0) + if r1 == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = syscall.EINVAL + } + } + return err +} diff --git a/vendor/github.com/Microsoft/go-winio/internal/socket/zsyscall_windows.go b/vendor/github.com/Microsoft/go-winio/internal/socket/zsyscall_windows.go new file mode 100644 index 0000000000..6d2e1a9e44 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/internal/socket/zsyscall_windows.go @@ -0,0 +1,72 @@ +//go:build windows + +// Code generated by 'go generate' using "github.com/Microsoft/go-winio/tools/mkwinsyscall"; DO NOT EDIT. + +package socket + +import ( + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) + +var _ unsafe.Pointer + +// Do the interface allocations only once for common +// Errno values. +const ( + errnoERROR_IO_PENDING = 997 +) + +var ( + errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) + errERROR_EINVAL error = syscall.EINVAL +) + +// errnoErr returns common boxed Errno values, to prevent +// allocations at runtime. +func errnoErr(e syscall.Errno) error { + switch e { + case 0: + return errERROR_EINVAL + case errnoERROR_IO_PENDING: + return errERROR_IO_PENDING + } + // TODO: add more here, after collecting data on the common + // error values see on Windows. (perhaps when running + // all.bat?) + return e +} + +var ( + modws2_32 = windows.NewLazySystemDLL("ws2_32.dll") + + procbind = modws2_32.NewProc("bind") + procgetpeername = modws2_32.NewProc("getpeername") + procgetsockname = modws2_32.NewProc("getsockname") +) + +func bind(s windows.Handle, name unsafe.Pointer, namelen int32) (err error) { + r1, _, e1 := syscall.Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen)) + if r1 == socketError { + err = errnoErr(e1) + } + return +} + +func getpeername(s windows.Handle, name unsafe.Pointer, namelen *int32) (err error) { + r1, _, e1 := syscall.Syscall(procgetpeername.Addr(), 3, uintptr(s), uintptr(name), uintptr(unsafe.Pointer(namelen))) + if r1 == socketError { + err = errnoErr(e1) + } + return +} + +func getsockname(s windows.Handle, name unsafe.Pointer, namelen *int32) (err error) { + r1, _, e1 := syscall.Syscall(procgetsockname.Addr(), 3, uintptr(s), uintptr(name), uintptr(unsafe.Pointer(namelen))) + if r1 == socketError { + err = errnoErr(e1) + } + return +} diff --git a/vendor/github.com/Microsoft/go-winio/internal/stringbuffer/wstring.go b/vendor/github.com/Microsoft/go-winio/internal/stringbuffer/wstring.go new file mode 100644 index 0000000000..7ad5057024 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/internal/stringbuffer/wstring.go @@ -0,0 +1,132 @@ +package stringbuffer + +import ( + "sync" + "unicode/utf16" +) + +// TODO: worth exporting and using in mkwinsyscall? + +// Uint16BufferSize is the buffer size in the pool, chosen somewhat arbitrarily to accommodate +// large path strings: +// MAX_PATH (260) + size of volume GUID prefix (49) + null terminator = 310. +const MinWStringCap = 310 + +// use *[]uint16 since []uint16 creates an extra allocation where the slice header +// is copied to heap and then referenced via pointer in the interface header that sync.Pool +// stores. +var pathPool = sync.Pool{ // if go1.18+ adds Pool[T], use that to store []uint16 directly + New: func() interface{} { + b := make([]uint16, MinWStringCap) + return &b + }, +} + +func newBuffer() []uint16 { return *(pathPool.Get().(*[]uint16)) } + +// freeBuffer copies the slice header data, and puts a pointer to that in the pool. +// This avoids taking a pointer to the slice header in WString, which can be set to nil. +func freeBuffer(b []uint16) { pathPool.Put(&b) } + +// WString is a wide string buffer ([]uint16) meant for storing UTF-16 encoded strings +// for interacting with Win32 APIs. +// Sizes are specified as uint32 and not int. +// +// It is not thread safe. +type WString struct { + // type-def allows casting to []uint16 directly, use struct to prevent that and allow adding fields in the future. + + // raw buffer + b []uint16 +} + +// NewWString returns a [WString] allocated from a shared pool with an +// initial capacity of at least [MinWStringCap]. +// Since the buffer may have been previously used, its contents are not guaranteed to be empty. +// +// The buffer should be freed via [WString.Free] +func NewWString() *WString { + return &WString{ + b: newBuffer(), + } +} + +func (b *WString) Free() { + if b.empty() { + return + } + freeBuffer(b.b) + b.b = nil +} + +// ResizeTo grows the buffer to at least c and returns the new capacity, freeing the +// previous buffer back into pool. +func (b *WString) ResizeTo(c uint32) uint32 { + // allready sufficient (or n is 0) + if c <= b.Cap() { + return b.Cap() + } + + if c <= MinWStringCap { + c = MinWStringCap + } + // allocate at-least double buffer size, as is done in [bytes.Buffer] and other places + if c <= 2*b.Cap() { + c = 2 * b.Cap() + } + + b2 := make([]uint16, c) + if !b.empty() { + copy(b2, b.b) + freeBuffer(b.b) + } + b.b = b2 + return c +} + +// Buffer returns the underlying []uint16 buffer. +func (b *WString) Buffer() []uint16 { + if b.empty() { + return nil + } + return b.b +} + +// Pointer returns a pointer to the first uint16 in the buffer. +// If the [WString.Free] has already been called, the pointer will be nil. +func (b *WString) Pointer() *uint16 { + if b.empty() { + return nil + } + return &b.b[0] +} + +// String returns the returns the UTF-8 encoding of the UTF-16 string in the buffer. +// +// It assumes that the data is null-terminated. +func (b *WString) String() string { + // Using [windows.UTF16ToString] would require importing "golang.org/x/sys/windows" + // and would make this code Windows-only, which makes no sense. + // So copy UTF16ToString code into here. + // If other windows-specific code is added, switch to [windows.UTF16ToString] + + s := b.b + for i, v := range s { + if v == 0 { + s = s[:i] + break + } + } + return string(utf16.Decode(s)) +} + +// Cap returns the underlying buffer capacity. +func (b *WString) Cap() uint32 { + if b.empty() { + return 0 + } + return b.cap() +} + +func (b *WString) cap() uint32 { return uint32(cap(b.b)) } +func (b *WString) empty() bool { return b == nil || b.cap() == 0 } diff --git a/vendor/github.com/Microsoft/go-winio/pipe.go b/vendor/github.com/Microsoft/go-winio/pipe.go index 96700a73de..25cc811031 100644 --- a/vendor/github.com/Microsoft/go-winio/pipe.go +++ b/vendor/github.com/Microsoft/go-winio/pipe.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package winio @@ -13,18 +14,21 @@ import ( "syscall" "time" "unsafe" + + "golang.org/x/sys/windows" + + "github.com/Microsoft/go-winio/internal/fs" ) //sys connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) = ConnectNamedPipe //sys createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateNamedPipeW -//sys createFile(name string, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateFileW //sys getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) = GetNamedPipeInfo //sys getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) = GetNamedPipeHandleStateW //sys localAlloc(uFlags uint32, length uint32) (ptr uintptr) = LocalAlloc -//sys ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) = ntdll.NtCreateNamedPipeFile -//sys rtlNtStatusToDosError(status ntstatus) (winerr error) = ntdll.RtlNtStatusToDosErrorNoTeb -//sys rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntstatus) = ntdll.RtlDosPathNameToNtPathName_U -//sys rtlDefaultNpAcl(dacl *uintptr) (status ntstatus) = ntdll.RtlDefaultNpAcl +//sys ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntStatus) = ntdll.NtCreateNamedPipeFile +//sys rtlNtStatusToDosError(status ntStatus) (winerr error) = ntdll.RtlNtStatusToDosErrorNoTeb +//sys rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntStatus) = ntdll.RtlDosPathNameToNtPathName_U +//sys rtlDefaultNpAcl(dacl *uintptr) (status ntStatus) = ntdll.RtlDefaultNpAcl type ioStatusBlock struct { Status, Information uintptr @@ -51,45 +55,22 @@ type securityDescriptor struct { Control uint16 Owner uintptr Group uintptr - Sacl uintptr - Dacl uintptr + Sacl uintptr //revive:disable-line:var-naming SACL, not Sacl + Dacl uintptr //revive:disable-line:var-naming DACL, not Dacl } -type ntstatus int32 +type ntStatus int32 -func (status ntstatus) Err() error { +func (status ntStatus) Err() error { if status >= 0 { return nil } return rtlNtStatusToDosError(status) } -const ( - cERROR_PIPE_BUSY = syscall.Errno(231) - cERROR_NO_DATA = syscall.Errno(232) - cERROR_PIPE_CONNECTED = syscall.Errno(535) - cERROR_SEM_TIMEOUT = syscall.Errno(121) - - cSECURITY_SQOS_PRESENT = 0x100000 - cSECURITY_ANONYMOUS = 0 - - cPIPE_TYPE_MESSAGE = 4 - - cPIPE_READMODE_MESSAGE = 2 - - cFILE_OPEN = 1 - cFILE_CREATE = 2 - - cFILE_PIPE_MESSAGE_TYPE = 1 - cFILE_PIPE_REJECT_REMOTE_CLIENTS = 2 - - cSE_DACL_PRESENT = 4 -) - var ( // ErrPipeListenerClosed is returned for pipe operations on listeners that have been closed. - // This error should match net.errClosing since docker takes a dependency on its text. - ErrPipeListenerClosed = errors.New("use of closed network connection") + ErrPipeListenerClosed = net.ErrClosed errPipeWriteClosed = errors.New("pipe has been closed for write") ) @@ -116,9 +97,10 @@ func (f *win32Pipe) RemoteAddr() net.Addr { } func (f *win32Pipe) SetDeadline(t time.Time) error { - f.SetReadDeadline(t) - f.SetWriteDeadline(t) - return nil + if err := f.SetReadDeadline(t); err != nil { + return err + } + return f.SetWriteDeadline(t) } // CloseWrite closes the write side of a message pipe in byte mode. @@ -157,14 +139,14 @@ func (f *win32MessageBytePipe) Read(b []byte) (int, error) { return 0, io.EOF } n, err := f.win32File.Read(b) - if err == io.EOF { + if err == io.EOF { //nolint:errorlint // If this was the result of a zero-byte read, then // it is possible that the read was due to a zero-size // message. Since we are simulating CloseWrite with a // zero-byte message, ensure that all future Read() calls // also return EOF. f.readEOF = true - } else if err == syscall.ERROR_MORE_DATA { + } else if err == syscall.ERROR_MORE_DATA { //nolint:errorlint // err is Errno // ERROR_MORE_DATA indicates that the pipe's read mode is message mode // and the message still has more bytes. Treat this as a success, since // this package presents all named pipes as byte streams. @@ -173,7 +155,7 @@ func (f *win32MessageBytePipe) Read(b []byte) (int, error) { return n, err } -func (s pipeAddress) Network() string { +func (pipeAddress) Network() string { return "pipe" } @@ -182,18 +164,25 @@ func (s pipeAddress) String() string { } // tryDialPipe attempts to dial the pipe at `path` until `ctx` cancellation or timeout. -func tryDialPipe(ctx context.Context, path *string, access uint32) (syscall.Handle, error) { +func tryDialPipe(ctx context.Context, path *string, access fs.AccessMask) (syscall.Handle, error) { for { - select { case <-ctx.Done(): return syscall.Handle(0), ctx.Err() default: - h, err := createFile(*path, access, 0, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_OVERLAPPED|cSECURITY_SQOS_PRESENT|cSECURITY_ANONYMOUS, 0) + wh, err := fs.CreateFile(*path, + access, + 0, // mode + nil, // security attributes + fs.OPEN_EXISTING, + fs.FILE_FLAG_OVERLAPPED|fs.SECURITY_SQOS_PRESENT|fs.SECURITY_ANONYMOUS, + 0, // template file handle + ) + h := syscall.Handle(wh) if err == nil { return h, nil } - if err != cERROR_PIPE_BUSY { + if err != windows.ERROR_PIPE_BUSY { //nolint:errorlint // err is Errno return h, &os.PathError{Err: err, Op: "open", Path: *path} } // Wait 10 msec and try again. This is a rather simplistic @@ -213,9 +202,10 @@ func DialPipe(path string, timeout *time.Duration) (net.Conn, error) { } else { absTimeout = time.Now().Add(2 * time.Second) } - ctx, _ := context.WithDeadline(context.Background(), absTimeout) + ctx, cancel := context.WithDeadline(context.Background(), absTimeout) + defer cancel() conn, err := DialPipeContext(ctx, path) - if err == context.DeadlineExceeded { + if errors.Is(err, context.DeadlineExceeded) { return nil, ErrTimeout } return conn, err @@ -232,7 +222,7 @@ func DialPipeContext(ctx context.Context, path string) (net.Conn, error) { func DialPipeAccess(ctx context.Context, path string, access uint32) (net.Conn, error) { var err error var h syscall.Handle - h, err = tryDialPipe(ctx, &path, access) + h, err = tryDialPipe(ctx, &path, fs.AccessMask(access)) if err != nil { return nil, err } @@ -251,7 +241,7 @@ func DialPipeAccess(ctx context.Context, path string, access uint32) (net.Conn, // If the pipe is in message mode, return a message byte pipe, which // supports CloseWrite(). - if flags&cPIPE_TYPE_MESSAGE != 0 { + if flags&windows.PIPE_TYPE_MESSAGE != 0 { return &win32MessageBytePipe{ win32Pipe: win32Pipe{win32File: f, path: path}, }, nil @@ -283,17 +273,22 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (sy oa.Length = unsafe.Sizeof(oa) var ntPath unicodeString - if err := rtlDosPathNameToNtPathName(&path16[0], &ntPath, 0, 0).Err(); err != nil { + if err := rtlDosPathNameToNtPathName(&path16[0], + &ntPath, + 0, + 0, + ).Err(); err != nil { return 0, &os.PathError{Op: "open", Path: path, Err: err} } defer localFree(ntPath.Buffer) oa.ObjectName = &ntPath + oa.Attributes = windows.OBJ_CASE_INSENSITIVE // The security descriptor is only needed for the first pipe. if first { if sd != nil { - len := uint32(len(sd)) - sdb := localAlloc(0, len) + l := uint32(len(sd)) + sdb := localAlloc(0, l) defer localFree(sdb) copy((*[0xffff]byte)(unsafe.Pointer(sdb))[:], sd) oa.SecurityDescriptor = (*securityDescriptor)(unsafe.Pointer(sdb)) @@ -301,28 +296,28 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (sy // Construct the default named pipe security descriptor. var dacl uintptr if err := rtlDefaultNpAcl(&dacl).Err(); err != nil { - return 0, fmt.Errorf("getting default named pipe ACL: %s", err) + return 0, fmt.Errorf("getting default named pipe ACL: %w", err) } defer localFree(dacl) sdb := &securityDescriptor{ Revision: 1, - Control: cSE_DACL_PRESENT, + Control: windows.SE_DACL_PRESENT, Dacl: dacl, } oa.SecurityDescriptor = sdb } } - typ := uint32(cFILE_PIPE_REJECT_REMOTE_CLIENTS) + typ := uint32(windows.FILE_PIPE_REJECT_REMOTE_CLIENTS) if c.MessageMode { - typ |= cFILE_PIPE_MESSAGE_TYPE + typ |= windows.FILE_PIPE_MESSAGE_TYPE } - disposition := uint32(cFILE_OPEN) + disposition := uint32(windows.FILE_OPEN) access := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE | syscall.SYNCHRONIZE) if first { - disposition = cFILE_CREATE + disposition = windows.FILE_CREATE // By not asking for read or write access, the named pipe file system // will put this pipe into an initially disconnected state, blocking // client connections until the next call with first == false. @@ -335,7 +330,20 @@ func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (sy h syscall.Handle iosb ioStatusBlock ) - err = ntCreateNamedPipeFile(&h, access, &oa, &iosb, syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE, disposition, 0, typ, 0, 0, 0xffffffff, uint32(c.InputBufferSize), uint32(c.OutputBufferSize), &timeout).Err() + err = ntCreateNamedPipeFile(&h, + access, + &oa, + &iosb, + syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE, + disposition, + 0, + typ, + 0, + 0, + 0xffffffff, + uint32(c.InputBufferSize), + uint32(c.OutputBufferSize), + &timeout).Err() if err != nil { return 0, &os.PathError{Op: "open", Path: path, Err: err} } @@ -380,7 +388,7 @@ func (l *win32PipeListener) makeConnectedServerPipe() (*win32File, error) { p.Close() p = nil err = <-ch - if err == nil || err == ErrFileClosed { + if err == nil || err == ErrFileClosed { //nolint:errorlint // err is Errno err = ErrPipeListenerClosed } } @@ -402,12 +410,12 @@ func (l *win32PipeListener) listenerRoutine() { p, err = l.makeConnectedServerPipe() // If the connection was immediately closed by the client, try // again. - if err != cERROR_NO_DATA { + if err != windows.ERROR_NO_DATA { //nolint:errorlint // err is Errno break } } responseCh <- acceptResponse{p, err} - closed = err == ErrPipeListenerClosed + closed = err == ErrPipeListenerClosed //nolint:errorlint // err is Errno } } syscall.Close(l.firstHandle) @@ -469,15 +477,15 @@ func ListenPipe(path string, c *PipeConfig) (net.Listener, error) { } func connectPipe(p *win32File) error { - c, err := p.prepareIo() + c, err := p.prepareIO() if err != nil { return err } defer p.wg.Done() err = connectNamedPipe(p.handle, &c.o) - _, err = p.asyncIo(c, nil, 0, err) - if err != nil && err != cERROR_PIPE_CONNECTED { + _, err = p.asyncIO(c, nil, 0, err) + if err != nil && err != windows.ERROR_PIPE_CONNECTED { //nolint:errorlint // err is Errno return err } return nil diff --git a/vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go b/vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go index f497c0e391..48ce4e9243 100644 --- a/vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go +++ b/vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go @@ -1,5 +1,3 @@ -// +build windows - // Package guid provides a GUID type. The backing structure for a GUID is // identical to that used by the golang.org/x/sys/windows GUID type. // There are two main binary encodings used for a GUID, the big-endian encoding, @@ -9,26 +7,26 @@ package guid import ( "crypto/rand" - "crypto/sha1" + "crypto/sha1" //nolint:gosec // not used for secure application "encoding" "encoding/binary" "fmt" "strconv" - - "golang.org/x/sys/windows" ) +//go:generate go run golang.org/x/tools/cmd/stringer -type=Variant -trimprefix=Variant -linecomment + // Variant specifies which GUID variant (or "type") of the GUID. It determines // how the entirety of the rest of the GUID is interpreted. type Variant uint8 -// The variants specified by RFC 4122. +// The variants specified by RFC 4122 section 4.1.1. const ( // VariantUnknown specifies a GUID variant which does not conform to one of // the variant encodings specified in RFC 4122. VariantUnknown Variant = iota VariantNCS - VariantRFC4122 + VariantRFC4122 // RFC 4122 VariantMicrosoft VariantFuture ) @@ -38,16 +36,13 @@ const ( // hash of an input string. type Version uint8 +func (v Version) String() string { + return strconv.FormatUint(uint64(v), 10) +} + var _ = (encoding.TextMarshaler)(GUID{}) var _ = (encoding.TextUnmarshaler)(&GUID{}) -// GUID represents a GUID/UUID. It has the same structure as -// golang.org/x/sys/windows.GUID so that it can be used with functions expecting -// that type. It is defined as its own type so that stringification and -// marshaling can be supported. The representation matches that used by native -// Windows code. -type GUID windows.GUID - // NewV4 returns a new version 4 (pseudorandom) GUID, as defined by RFC 4122. func NewV4() (GUID, error) { var b [16]byte @@ -70,7 +65,7 @@ func NewV4() (GUID, error) { // big-endian UTF16 stream of bytes. If that is desired, the string can be // encoded as such before being passed to this function. func NewV5(namespace GUID, name []byte) (GUID, error) { - b := sha1.New() + b := sha1.New() //nolint:gosec // not used for secure application namespaceBytes := namespace.ToArray() b.Write(namespaceBytes[:]) b.Write(name) diff --git a/vendor/github.com/Microsoft/go-winio/pkg/guid/guid_nonwindows.go b/vendor/github.com/Microsoft/go-winio/pkg/guid/guid_nonwindows.go new file mode 100644 index 0000000000..805bd35484 --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/pkg/guid/guid_nonwindows.go @@ -0,0 +1,16 @@ +//go:build !windows +// +build !windows + +package guid + +// GUID represents a GUID/UUID. It has the same structure as +// golang.org/x/sys/windows.GUID so that it can be used with functions expecting +// that type. It is defined as its own type as that is only available to builds +// targeted at `windows`. The representation matches that used by native Windows +// code. +type GUID struct { + Data1 uint32 + Data2 uint16 + Data3 uint16 + Data4 [8]byte +} diff --git a/vendor/github.com/Microsoft/go-winio/pkg/guid/guid_windows.go b/vendor/github.com/Microsoft/go-winio/pkg/guid/guid_windows.go new file mode 100644 index 0000000000..27e45ee5cc --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/pkg/guid/guid_windows.go @@ -0,0 +1,13 @@ +//go:build windows +// +build windows + +package guid + +import "golang.org/x/sys/windows" + +// GUID represents a GUID/UUID. It has the same structure as +// golang.org/x/sys/windows.GUID so that it can be used with functions expecting +// that type. It is defined as its own type so that stringification and +// marshaling can be supported. The representation matches that used by native +// Windows code. +type GUID windows.GUID diff --git a/vendor/github.com/Microsoft/go-winio/pkg/guid/variant_string.go b/vendor/github.com/Microsoft/go-winio/pkg/guid/variant_string.go new file mode 100644 index 0000000000..4076d3132f --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/pkg/guid/variant_string.go @@ -0,0 +1,27 @@ +// Code generated by "stringer -type=Variant -trimprefix=Variant -linecomment"; DO NOT EDIT. + +package guid + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[VariantUnknown-0] + _ = x[VariantNCS-1] + _ = x[VariantRFC4122-2] + _ = x[VariantMicrosoft-3] + _ = x[VariantFuture-4] +} + +const _Variant_name = "UnknownNCSRFC 4122MicrosoftFuture" + +var _Variant_index = [...]uint8{0, 7, 10, 18, 27, 33} + +func (i Variant) String() string { + if i >= Variant(len(_Variant_index)-1) { + return "Variant(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _Variant_name[_Variant_index[i]:_Variant_index[i+1]] +} diff --git a/vendor/github.com/Microsoft/go-winio/pkg/security/grantvmgroupaccess.go b/vendor/github.com/Microsoft/go-winio/pkg/security/grantvmgroupaccess.go index fca241590c..bb276fff2f 100644 --- a/vendor/github.com/Microsoft/go-winio/pkg/security/grantvmgroupaccess.go +++ b/vendor/github.com/Microsoft/go-winio/pkg/security/grantvmgroupaccess.go @@ -1,13 +1,13 @@ +//go:build windows // +build windows package security import ( + "fmt" "os" "syscall" "unsafe" - - "github.com/pkg/errors" ) type ( @@ -45,6 +45,7 @@ const ( desiredAccessReadControl desiredAccess = 0x20000 desiredAccessWriteDac desiredAccess = 0x40000 + //cspell:disable-next-line gvmga = "GrantVmGroupAccess:" inheritModeNoInheritance inheritMode = 0x0 @@ -57,9 +58,9 @@ const ( shareModeRead shareMode = 0x1 shareModeWrite shareMode = 0x2 - sidVmGroup = "S-1-5-83-0" + sidVMGroup = "S-1-5-83-0" - trusteeFormIsSid trusteeForm = 0 + trusteeFormIsSID trusteeForm = 0 trusteeTypeWellKnownGroup trusteeType = 5 ) @@ -68,11 +69,13 @@ const ( // include Grant ACE entries for the VM Group SID. This is a golang re- // implementation of the same function in vmcompute, just not exported in // RS5. Which kind of sucks. Sucks a lot :/ +// +//revive:disable-next-line:var-naming VM, not Vm func GrantVmGroupAccess(name string) error { // Stat (to determine if `name` is a directory). s, err := os.Stat(name) if err != nil { - return errors.Wrapf(err, "%s os.Stat %s", gvmga, name) + return fmt.Errorf("%s os.Stat %s: %w", gvmga, name, err) } // Get a handle to the file/directory. Must defer Close on success. @@ -80,7 +83,7 @@ func GrantVmGroupAccess(name string) error { if err != nil { return err // Already wrapped } - defer syscall.CloseHandle(fd) + defer syscall.CloseHandle(fd) //nolint:errcheck // Get the current DACL and Security Descriptor. Must defer LocalFree on success. ot := objectTypeFileObject @@ -88,9 +91,9 @@ func GrantVmGroupAccess(name string) error { sd := uintptr(0) origDACL := uintptr(0) if err := getSecurityInfo(fd, uint32(ot), uint32(si), nil, nil, &origDACL, nil, &sd); err != nil { - return errors.Wrapf(err, "%s GetSecurityInfo %s", gvmga, name) + return fmt.Errorf("%s GetSecurityInfo %s: %w", gvmga, name, err) } - defer syscall.LocalFree((syscall.Handle)(unsafe.Pointer(sd))) + defer syscall.LocalFree((syscall.Handle)(unsafe.Pointer(sd))) //nolint:errcheck // Generate a new DACL which is the current DACL with the required ACEs added. // Must defer LocalFree on success. @@ -98,11 +101,11 @@ func GrantVmGroupAccess(name string) error { if err != nil { return err // Already wrapped } - defer syscall.LocalFree((syscall.Handle)(unsafe.Pointer(newDACL))) + defer syscall.LocalFree((syscall.Handle)(unsafe.Pointer(newDACL))) //nolint:errcheck // And finally use SetSecurityInfo to apply the updated DACL. if err := setSecurityInfo(fd, uint32(ot), uint32(si), uintptr(0), uintptr(0), newDACL, uintptr(0)); err != nil { - return errors.Wrapf(err, "%s SetSecurityInfo %s", gvmga, name) + return fmt.Errorf("%s SetSecurityInfo %s: %w", gvmga, name, err) } return nil @@ -111,16 +114,19 @@ func GrantVmGroupAccess(name string) error { // createFile is a helper function to call [Nt]CreateFile to get a handle to // the file or directory. func createFile(name string, isDir bool) (syscall.Handle, error) { - namep := syscall.StringToUTF16(name) + namep, err := syscall.UTF16FromString(name) + if err != nil { + return syscall.InvalidHandle, fmt.Errorf("could not convernt name to UTF-16: %w", err) + } da := uint32(desiredAccessReadControl | desiredAccessWriteDac) sm := uint32(shareModeRead | shareModeWrite) fa := uint32(syscall.FILE_ATTRIBUTE_NORMAL) if isDir { - fa = uint32(fa | syscall.FILE_FLAG_BACKUP_SEMANTICS) + fa |= syscall.FILE_FLAG_BACKUP_SEMANTICS } fd, err := syscall.CreateFile(&namep[0], da, sm, nil, syscall.OPEN_EXISTING, fa, 0) if err != nil { - return 0, errors.Wrapf(err, "%s syscall.CreateFile %s", gvmga, name) + return syscall.InvalidHandle, fmt.Errorf("%s syscall.CreateFile %s: %w", gvmga, name, err) } return fd, nil } @@ -129,9 +135,9 @@ func createFile(name string, isDir bool) (syscall.Handle, error) { // The caller is responsible for LocalFree of the returned DACL on success. func generateDACLWithAcesAdded(name string, isDir bool, origDACL uintptr) (uintptr, error) { // Generate pointers to the SIDs based on the string SIDs - sid, err := syscall.StringToSid(sidVmGroup) + sid, err := syscall.StringToSid(sidVMGroup) if err != nil { - return 0, errors.Wrapf(err, "%s syscall.StringToSid %s %s", gvmga, name, sidVmGroup) + return 0, fmt.Errorf("%s syscall.StringToSid %s %s: %w", gvmga, name, sidVMGroup, err) } inheritance := inheritModeNoInheritance @@ -140,12 +146,12 @@ func generateDACLWithAcesAdded(name string, isDir bool, origDACL uintptr) (uintp } eaArray := []explicitAccess{ - explicitAccess{ + { accessPermissions: accessMaskDesiredPermission, accessMode: accessModeGrant, inheritance: inheritance, trustee: trustee{ - trusteeForm: trusteeFormIsSid, + trusteeForm: trusteeFormIsSID, trusteeType: trusteeTypeWellKnownGroup, name: uintptr(unsafe.Pointer(sid)), }, @@ -154,7 +160,7 @@ func generateDACLWithAcesAdded(name string, isDir bool, origDACL uintptr) (uintp modifiedDACL := uintptr(0) if err := setEntriesInAcl(uintptr(uint32(1)), uintptr(unsafe.Pointer(&eaArray[0])), origDACL, &modifiedDACL); err != nil { - return 0, errors.Wrapf(err, "%s SetEntriesInAcl %s", gvmga, name) + return 0, fmt.Errorf("%s SetEntriesInAcl %s: %w", gvmga, name, err) } return modifiedDACL, nil diff --git a/vendor/github.com/Microsoft/go-winio/pkg/security/syscall_windows.go b/vendor/github.com/Microsoft/go-winio/pkg/security/syscall_windows.go index d7096716ce..71326e4e46 100644 --- a/vendor/github.com/Microsoft/go-winio/pkg/security/syscall_windows.go +++ b/vendor/github.com/Microsoft/go-winio/pkg/security/syscall_windows.go @@ -1,6 +1,6 @@ package security -//go:generate go run mksyscall_windows.go -output zsyscall_windows.go syscall_windows.go +//go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zsyscall_windows.go syscall_windows.go //sys getSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, ppsidOwner **uintptr, ppsidGroup **uintptr, ppDacl *uintptr, ppSacl *uintptr, ppSecurityDescriptor *uintptr) (win32err error) = advapi32.GetSecurityInfo //sys setSecurityInfo(handle syscall.Handle, objectType uint32, si uint32, psidOwner uintptr, psidGroup uintptr, pDacl uintptr, pSacl uintptr) (win32err error) = advapi32.SetSecurityInfo diff --git a/vendor/github.com/Microsoft/go-winio/pkg/security/zsyscall_windows.go b/vendor/github.com/Microsoft/go-winio/pkg/security/zsyscall_windows.go index 4084680e0f..26c986b88f 100644 --- a/vendor/github.com/Microsoft/go-winio/pkg/security/zsyscall_windows.go +++ b/vendor/github.com/Microsoft/go-winio/pkg/security/zsyscall_windows.go @@ -1,4 +1,6 @@ -// Code generated by 'go generate'; DO NOT EDIT. +//go:build windows + +// Code generated by 'go generate' using "github.com/Microsoft/go-winio/tools/mkwinsyscall"; DO NOT EDIT. package security diff --git a/vendor/github.com/Microsoft/go-winio/privilege.go b/vendor/github.com/Microsoft/go-winio/privilege.go index c3dd7c2176..0ff9dac906 100644 --- a/vendor/github.com/Microsoft/go-winio/privilege.go +++ b/vendor/github.com/Microsoft/go-winio/privilege.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package winio @@ -24,22 +25,17 @@ import ( //sys lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) = advapi32.LookupPrivilegeDisplayNameW const ( - SE_PRIVILEGE_ENABLED = 2 + //revive:disable-next-line:var-naming ALL_CAPS + SE_PRIVILEGE_ENABLED = windows.SE_PRIVILEGE_ENABLED - ERROR_NOT_ALL_ASSIGNED syscall.Errno = 1300 + //revive:disable-next-line:var-naming ALL_CAPS + ERROR_NOT_ALL_ASSIGNED syscall.Errno = windows.ERROR_NOT_ALL_ASSIGNED SeBackupPrivilege = "SeBackupPrivilege" SeRestorePrivilege = "SeRestorePrivilege" SeSecurityPrivilege = "SeSecurityPrivilege" ) -const ( - securityAnonymous = iota - securityIdentification - securityImpersonation - securityDelegation -) - var ( privNames = make(map[string]uint64) privNameMutex sync.Mutex @@ -51,11 +47,9 @@ type PrivilegeError struct { } func (e *PrivilegeError) Error() string { - s := "" + s := "Could not enable privilege " if len(e.privileges) > 1 { s = "Could not enable privileges " - } else { - s = "Could not enable privilege " } for i, p := range e.privileges { if i != 0 { @@ -94,7 +88,7 @@ func RunWithPrivileges(names []string, fn func() error) error { } func mapPrivileges(names []string) ([]uint64, error) { - var privileges []uint64 + privileges := make([]uint64, 0, len(names)) privNameMutex.Lock() defer privNameMutex.Unlock() for _, name := range names { @@ -127,7 +121,7 @@ func enableDisableProcessPrivilege(names []string, action uint32) error { return err } - p, _ := windows.GetCurrentProcess() + p := windows.CurrentProcess() var token windows.Token err = windows.OpenProcessToken(p, windows.TOKEN_ADJUST_PRIVILEGES|windows.TOKEN_QUERY, &token) if err != nil { @@ -140,10 +134,10 @@ func enableDisableProcessPrivilege(names []string, action uint32) error { func adjustPrivileges(token windows.Token, privileges []uint64, action uint32) error { var b bytes.Buffer - binary.Write(&b, binary.LittleEndian, uint32(len(privileges))) + _ = binary.Write(&b, binary.LittleEndian, uint32(len(privileges))) for _, p := range privileges { - binary.Write(&b, binary.LittleEndian, p) - binary.Write(&b, binary.LittleEndian, action) + _ = binary.Write(&b, binary.LittleEndian, p) + _ = binary.Write(&b, binary.LittleEndian, action) } prevState := make([]byte, b.Len()) reqSize := uint32(0) @@ -151,7 +145,7 @@ func adjustPrivileges(token windows.Token, privileges []uint64, action uint32) e if !success { return err } - if err == ERROR_NOT_ALL_ASSIGNED { + if err == ERROR_NOT_ALL_ASSIGNED { //nolint:errorlint // err is Errno return &PrivilegeError{privileges} } return nil @@ -177,7 +171,7 @@ func getPrivilegeName(luid uint64) string { } func newThreadToken() (windows.Token, error) { - err := impersonateSelf(securityImpersonation) + err := impersonateSelf(windows.SecurityImpersonation) if err != nil { return 0, err } diff --git a/vendor/github.com/Microsoft/go-winio/reparse.go b/vendor/github.com/Microsoft/go-winio/reparse.go index fc1ee4d3a3..67d1a104a6 100644 --- a/vendor/github.com/Microsoft/go-winio/reparse.go +++ b/vendor/github.com/Microsoft/go-winio/reparse.go @@ -1,3 +1,6 @@ +//go:build windows +// +build windows + package winio import ( @@ -113,16 +116,16 @@ func EncodeReparsePoint(rp *ReparsePoint) []byte { } var b bytes.Buffer - binary.Write(&b, binary.LittleEndian, &data) + _ = binary.Write(&b, binary.LittleEndian, &data) if !rp.IsMountPoint { flags := uint32(0) if relative { flags |= 1 } - binary.Write(&b, binary.LittleEndian, flags) + _ = binary.Write(&b, binary.LittleEndian, flags) } - binary.Write(&b, binary.LittleEndian, ntTarget16) - binary.Write(&b, binary.LittleEndian, target16) + _ = binary.Write(&b, binary.LittleEndian, ntTarget16) + _ = binary.Write(&b, binary.LittleEndian, target16) return b.Bytes() } diff --git a/vendor/github.com/Microsoft/go-winio/sd.go b/vendor/github.com/Microsoft/go-winio/sd.go index db1b370a1b..5550ef6b61 100644 --- a/vendor/github.com/Microsoft/go-winio/sd.go +++ b/vendor/github.com/Microsoft/go-winio/sd.go @@ -1,23 +1,25 @@ +//go:build windows // +build windows package winio import ( + "errors" "syscall" "unsafe" + + "golang.org/x/sys/windows" ) //sys lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) = advapi32.LookupAccountNameW +//sys lookupAccountSid(systemName *uint16, sid *byte, name *uint16, nameSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) = advapi32.LookupAccountSidW //sys convertSidToStringSid(sid *byte, str **uint16) (err error) = advapi32.ConvertSidToStringSidW +//sys convertStringSidToSid(str *uint16, sid **byte) (err error) = advapi32.ConvertStringSidToSidW //sys convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) = advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW //sys convertSecurityDescriptorToStringSecurityDescriptor(sd *byte, revision uint32, secInfo uint32, sddl **uint16, sddlSize *uint32) (err error) = advapi32.ConvertSecurityDescriptorToStringSecurityDescriptorW //sys localFree(mem uintptr) = LocalFree //sys getSecurityDescriptorLength(sd uintptr) (len uint32) = advapi32.GetSecurityDescriptorLength -const ( - cERROR_NONE_MAPPED = syscall.Errno(1332) -) - type AccountLookupError struct { Name string Err error @@ -28,8 +30,10 @@ func (e *AccountLookupError) Error() string { return "lookup account: empty account name specified" } var s string - switch e.Err { - case cERROR_NONE_MAPPED: + switch { + case errors.Is(e.Err, windows.ERROR_INVALID_SID): + s = "the security ID structure is invalid" + case errors.Is(e.Err, windows.ERROR_NONE_MAPPED): s = "not found" default: s = e.Err.Error() @@ -37,6 +41,8 @@ func (e *AccountLookupError) Error() string { return "lookup account " + e.Name + ": " + s } +func (e *AccountLookupError) Unwrap() error { return e.Err } + type SddlConversionError struct { Sddl string Err error @@ -46,15 +52,19 @@ func (e *SddlConversionError) Error() string { return "convert " + e.Sddl + ": " + e.Err.Error() } +func (e *SddlConversionError) Unwrap() error { return e.Err } + // LookupSidByName looks up the SID of an account by name +// +//revive:disable-next-line:var-naming SID, not Sid func LookupSidByName(name string) (sid string, err error) { if name == "" { - return "", &AccountLookupError{name, cERROR_NONE_MAPPED} + return "", &AccountLookupError{name, windows.ERROR_NONE_MAPPED} } var sidSize, sidNameUse, refDomainSize uint32 err = lookupAccountName(nil, name, nil, &sidSize, nil, &refDomainSize, &sidNameUse) - if err != nil && err != syscall.ERROR_INSUFFICIENT_BUFFER { + if err != nil && err != syscall.ERROR_INSUFFICIENT_BUFFER { //nolint:errorlint // err is Errno return "", &AccountLookupError{name, err} } sidBuffer := make([]byte, sidSize) @@ -73,6 +83,42 @@ func LookupSidByName(name string) (sid string, err error) { return sid, nil } +// LookupNameBySid looks up the name of an account by SID +// +//revive:disable-next-line:var-naming SID, not Sid +func LookupNameBySid(sid string) (name string, err error) { + if sid == "" { + return "", &AccountLookupError{sid, windows.ERROR_NONE_MAPPED} + } + + sidBuffer, err := windows.UTF16PtrFromString(sid) + if err != nil { + return "", &AccountLookupError{sid, err} + } + + var sidPtr *byte + if err = convertStringSidToSid(sidBuffer, &sidPtr); err != nil { + return "", &AccountLookupError{sid, err} + } + defer localFree(uintptr(unsafe.Pointer(sidPtr))) + + var nameSize, refDomainSize, sidNameUse uint32 + err = lookupAccountSid(nil, sidPtr, nil, &nameSize, nil, &refDomainSize, &sidNameUse) + if err != nil && err != windows.ERROR_INSUFFICIENT_BUFFER { //nolint:errorlint // err is Errno + return "", &AccountLookupError{sid, err} + } + + nameBuffer := make([]uint16, nameSize) + refDomainBuffer := make([]uint16, refDomainSize) + err = lookupAccountSid(nil, sidPtr, &nameBuffer[0], &nameSize, &refDomainBuffer[0], &refDomainSize, &sidNameUse) + if err != nil { + return "", &AccountLookupError{sid, err} + } + + name = windows.UTF16ToString(nameBuffer) + return name, nil +} + func SddlToSecurityDescriptor(sddl string) ([]byte, error) { var sdBuffer uintptr err := convertStringSecurityDescriptorToSecurityDescriptor(sddl, 1, &sdBuffer, nil) @@ -87,7 +133,7 @@ func SddlToSecurityDescriptor(sddl string) ([]byte, error) { func SecurityDescriptorToSddl(sd []byte) (string, error) { var sddl *uint16 - // The returned string length seems to including an aribtrary number of terminating NULs. + // The returned string length seems to include an arbitrary number of terminating NULs. // Don't use it. err := convertSecurityDescriptorToStringSecurityDescriptor(&sd[0], 1, 0xff, &sddl, nil) if err != nil { diff --git a/vendor/github.com/Microsoft/go-winio/syscall.go b/vendor/github.com/Microsoft/go-winio/syscall.go index 5955c99fde..a6ca111b39 100644 --- a/vendor/github.com/Microsoft/go-winio/syscall.go +++ b/vendor/github.com/Microsoft/go-winio/syscall.go @@ -1,3 +1,5 @@ +//go:build windows + package winio -//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go file.go pipe.go sd.go fileinfo.go privilege.go backup.go hvsock.go +//go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zsyscall_windows.go ./*.go diff --git a/vendor/github.com/Microsoft/go-winio/tools.go b/vendor/github.com/Microsoft/go-winio/tools.go new file mode 100644 index 0000000000..2aa045843e --- /dev/null +++ b/vendor/github.com/Microsoft/go-winio/tools.go @@ -0,0 +1,5 @@ +//go:build tools + +package winio + +import _ "golang.org/x/tools/cmd/stringer" diff --git a/vendor/github.com/Microsoft/go-winio/vhd/vhd.go b/vendor/github.com/Microsoft/go-winio/vhd/vhd.go index a33a36c0ff..b54cad1127 100644 --- a/vendor/github.com/Microsoft/go-winio/vhd/vhd.go +++ b/vendor/github.com/Microsoft/go-winio/vhd/vhd.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package vhd @@ -7,14 +8,13 @@ import ( "syscall" "github.com/Microsoft/go-winio/pkg/guid" - "github.com/pkg/errors" "golang.org/x/sys/windows" ) -//go:generate go run mksyscall_windows.go -output zvhd_windows.go vhd.go +//go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zvhd_windows.go vhd.go //sys createVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, securityDescriptor *uintptr, createVirtualDiskFlags uint32, providerSpecificFlags uint32, parameters *CreateVirtualDiskParameters, overlapped *syscall.Overlapped, handle *syscall.Handle) (win32err error) = virtdisk.CreateVirtualDisk -//sys openVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *OpenVirtualDiskParameters, handle *syscall.Handle) (win32err error) = virtdisk.OpenVirtualDisk +//sys openVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *openVirtualDiskParameters, handle *syscall.Handle) (win32err error) = virtdisk.OpenVirtualDisk //sys attachVirtualDisk(handle syscall.Handle, securityDescriptor *uintptr, attachVirtualDiskFlag uint32, providerSpecificFlags uint32, parameters *AttachVirtualDiskParameters, overlapped *syscall.Overlapped) (win32err error) = virtdisk.AttachVirtualDisk //sys detachVirtualDisk(handle syscall.Handle, detachVirtualDiskFlags uint32, providerSpecificFlags uint32) (win32err error) = virtdisk.DetachVirtualDisk //sys getVirtualDiskPhysicalPath(handle syscall.Handle, diskPathSizeInBytes *uint32, buffer *uint16) (win32err error) = virtdisk.GetVirtualDiskPhysicalPath @@ -62,20 +62,35 @@ type OpenVirtualDiskParameters struct { Version2 OpenVersion2 } +// The higher level `OpenVersion2` struct uses `bool`s to refer to `GetInfoOnly` and `ReadOnly` for ease of use. However, +// the internal windows structure uses `BOOL`s aka int32s for these types. `openVersion2` is used for translating +// `OpenVersion2` fields to the correct windows internal field types on the `Open____` methods. +type openVersion2 struct { + getInfoOnly int32 + readOnly int32 + resiliencyGUID guid.GUID +} + +type openVirtualDiskParameters struct { + version uint32 + version2 openVersion2 +} + type AttachVersion2 struct { RestrictedOffset uint64 RestrictedLength uint64 } type AttachVirtualDiskParameters struct { - Version uint32 // Must always be set to 2 + Version uint32 Version2 AttachVersion2 } const ( + //revive:disable-next-line:var-naming ALL_CAPS VIRTUAL_STORAGE_TYPE_DEVICE_VHDX = 0x3 - // Access Mask for opening a VHD + // Access Mask for opening a VHD. VirtualDiskAccessNone VirtualDiskAccessMask = 0x00000000 VirtualDiskAccessAttachRO VirtualDiskAccessMask = 0x00010000 VirtualDiskAccessAttachRW VirtualDiskAccessMask = 0x00020000 @@ -87,7 +102,7 @@ const ( VirtualDiskAccessAll VirtualDiskAccessMask = 0x003f0000 VirtualDiskAccessWritable VirtualDiskAccessMask = 0x00320000 - // Flags for creating a VHD + // Flags for creating a VHD. CreateVirtualDiskFlagNone CreateVirtualDiskFlag = 0x0 CreateVirtualDiskFlagFullPhysicalAllocation CreateVirtualDiskFlag = 0x1 CreateVirtualDiskFlagPreventWritesToSourceDisk CreateVirtualDiskFlag = 0x2 @@ -95,12 +110,12 @@ const ( CreateVirtualDiskFlagCreateBackingStorage CreateVirtualDiskFlag = 0x8 CreateVirtualDiskFlagUseChangeTrackingSourceLimit CreateVirtualDiskFlag = 0x10 CreateVirtualDiskFlagPreserveParentChangeTrackingState CreateVirtualDiskFlag = 0x20 - CreateVirtualDiskFlagVhdSetUseOriginalBackingStorage CreateVirtualDiskFlag = 0x40 + CreateVirtualDiskFlagVhdSetUseOriginalBackingStorage CreateVirtualDiskFlag = 0x40 //revive:disable-line:var-naming VHD, not Vhd CreateVirtualDiskFlagSparseFile CreateVirtualDiskFlag = 0x80 - CreateVirtualDiskFlagPmemCompatible CreateVirtualDiskFlag = 0x100 + CreateVirtualDiskFlagPmemCompatible CreateVirtualDiskFlag = 0x100 //revive:disable-line:var-naming PMEM, not Pmem CreateVirtualDiskFlagSupportCompressedVolumes CreateVirtualDiskFlag = 0x200 - // Flags for opening a VHD + // Flags for opening a VHD. OpenVirtualDiskFlagNone VirtualDiskFlag = 0x00000000 OpenVirtualDiskFlagNoParents VirtualDiskFlag = 0x00000001 OpenVirtualDiskFlagBlankFile VirtualDiskFlag = 0x00000002 @@ -113,7 +128,7 @@ const ( OpenVirtualDiskFlagNoWriteHardening VirtualDiskFlag = 0x00000100 OpenVirtualDiskFlagSupportCompressedVolumes VirtualDiskFlag = 0x00000200 - // Flags for attaching a VHD + // Flags for attaching a VHD. AttachVirtualDiskFlagNone AttachVirtualDiskFlag = 0x00000000 AttachVirtualDiskFlagReadOnly AttachVirtualDiskFlag = 0x00000001 AttachVirtualDiskFlagNoDriveLetter AttachVirtualDiskFlag = 0x00000002 @@ -126,12 +141,14 @@ const ( AttachVirtualDiskFlagSinglePartition AttachVirtualDiskFlag = 0x00000100 AttachVirtualDiskFlagRegisterVolume AttachVirtualDiskFlag = 0x00000200 - // Flags for detaching a VHD + // Flags for detaching a VHD. DetachVirtualDiskFlagNone DetachVirtualDiskFlag = 0x0 ) // CreateVhdx is a helper function to create a simple vhdx file at the given path using // default values. +// +//revive:disable-next-line:var-naming VHDX, not Vhdx func CreateVhdx(path string, maxSizeInGb, blockSizeInMb uint32) error { params := CreateVirtualDiskParameters{ Version: 2, @@ -146,21 +163,20 @@ func CreateVhdx(path string, maxSizeInGb, blockSizeInMb uint32) error { return err } - if err := syscall.CloseHandle(handle); err != nil { - return err - } - return nil + return syscall.CloseHandle(handle) } // DetachVirtualDisk detaches a virtual hard disk by handle. func DetachVirtualDisk(handle syscall.Handle) (err error) { if err := detachVirtualDisk(handle, 0, 0); err != nil { - return errors.Wrap(err, "failed to detach virtual disk") + return fmt.Errorf("failed to detach virtual disk: %w", err) } return nil } // DetachVhd detaches a vhd found at `path`. +// +//revive:disable-next-line:var-naming VHD, not Vhd func DetachVhd(path string) error { handle, err := OpenVirtualDisk( path, @@ -170,12 +186,16 @@ func DetachVhd(path string) error { if err != nil { return err } - defer syscall.CloseHandle(handle) + defer syscall.CloseHandle(handle) //nolint:errcheck return DetachVirtualDisk(handle) } // AttachVirtualDisk attaches a virtual hard disk for use. -func AttachVirtualDisk(handle syscall.Handle, attachVirtualDiskFlag AttachVirtualDiskFlag, parameters *AttachVirtualDiskParameters) (err error) { +func AttachVirtualDisk( + handle syscall.Handle, + attachVirtualDiskFlag AttachVirtualDiskFlag, + parameters *AttachVirtualDiskParameters, +) (err error) { // Supports both version 1 and 2 of the attach parameters as version 2 wasn't present in RS5. if err := attachVirtualDisk( handle, @@ -185,13 +205,15 @@ func AttachVirtualDisk(handle syscall.Handle, attachVirtualDiskFlag AttachVirtua parameters, nil, ); err != nil { - return errors.Wrap(err, "failed to attach virtual disk") + return fmt.Errorf("failed to attach virtual disk: %w", err) } return nil } // AttachVhd attaches a virtual hard disk at `path` for use. Attaches using version 2 // of the ATTACH_VIRTUAL_DISK_PARAMETERS. +// +//revive:disable-next-line:var-naming VHD, not Vhd func AttachVhd(path string) (err error) { handle, err := OpenVirtualDisk( path, @@ -202,20 +224,24 @@ func AttachVhd(path string) (err error) { return err } - defer syscall.CloseHandle(handle) + defer syscall.CloseHandle(handle) //nolint:errcheck params := AttachVirtualDiskParameters{Version: 2} if err := AttachVirtualDisk( handle, AttachVirtualDiskFlagNone, ¶ms, ); err != nil { - return errors.Wrap(err, "failed to attach virtual disk") + return fmt.Errorf("failed to attach virtual disk: %w", err) } return nil } // OpenVirtualDisk obtains a handle to a VHD opened with supplied access mask and flags. -func OpenVirtualDisk(vhdPath string, virtualDiskAccessMask VirtualDiskAccessMask, openVirtualDiskFlags VirtualDiskFlag) (syscall.Handle, error) { +func OpenVirtualDisk( + vhdPath string, + virtualDiskAccessMask VirtualDiskAccessMask, + openVirtualDiskFlags VirtualDiskFlag, +) (syscall.Handle, error) { parameters := OpenVirtualDiskParameters{Version: 2} handle, err := OpenVirtualDiskWithParameters( vhdPath, @@ -230,29 +256,55 @@ func OpenVirtualDisk(vhdPath string, virtualDiskAccessMask VirtualDiskAccessMask } // OpenVirtualDiskWithParameters obtains a handle to a VHD opened with supplied access mask, flags and parameters. -func OpenVirtualDiskWithParameters(vhdPath string, virtualDiskAccessMask VirtualDiskAccessMask, openVirtualDiskFlags VirtualDiskFlag, parameters *OpenVirtualDiskParameters) (syscall.Handle, error) { +func OpenVirtualDiskWithParameters( + vhdPath string, + virtualDiskAccessMask VirtualDiskAccessMask, + openVirtualDiskFlags VirtualDiskFlag, + parameters *OpenVirtualDiskParameters, +) (syscall.Handle, error) { var ( handle syscall.Handle defaultType VirtualStorageType + getInfoOnly int32 + readOnly int32 ) if parameters.Version != 2 { return handle, fmt.Errorf("only version 2 VHDs are supported, found version: %d", parameters.Version) } + if parameters.Version2.GetInfoOnly { + getInfoOnly = 1 + } + if parameters.Version2.ReadOnly { + readOnly = 1 + } + params := &openVirtualDiskParameters{ + version: parameters.Version, + version2: openVersion2{ + getInfoOnly, + readOnly, + parameters.Version2.ResiliencyGUID, + }, + } if err := openVirtualDisk( &defaultType, vhdPath, uint32(virtualDiskAccessMask), uint32(openVirtualDiskFlags), - parameters, + params, &handle, ); err != nil { - return 0, errors.Wrap(err, "failed to open virtual disk") + return 0, fmt.Errorf("failed to open virtual disk: %w", err) } return handle, nil } // CreateVirtualDisk creates a virtual harddisk and returns a handle to the disk. -func CreateVirtualDisk(path string, virtualDiskAccessMask VirtualDiskAccessMask, createVirtualDiskFlags CreateVirtualDiskFlag, parameters *CreateVirtualDiskParameters) (syscall.Handle, error) { +func CreateVirtualDisk( + path string, + virtualDiskAccessMask VirtualDiskAccessMask, + createVirtualDiskFlags CreateVirtualDiskFlag, + parameters *CreateVirtualDiskParameters, +) (syscall.Handle, error) { var ( handle syscall.Handle defaultType VirtualStorageType @@ -272,7 +324,7 @@ func CreateVirtualDisk(path string, virtualDiskAccessMask VirtualDiskAccessMask, nil, &handle, ); err != nil { - return handle, errors.Wrap(err, "failed to create virtual disk") + return handle, fmt.Errorf("failed to create virtual disk: %w", err) } return handle, nil } @@ -290,12 +342,14 @@ func GetVirtualDiskPhysicalPath(handle syscall.Handle) (_ string, err error) { &diskPathSizeInBytes, &diskPhysicalPathBuf[0], ); err != nil { - return "", errors.Wrap(err, "failed to get disk physical path") + return "", fmt.Errorf("failed to get disk physical path: %w", err) } return windows.UTF16ToString(diskPhysicalPathBuf[:]), nil } // CreateDiffVhd is a helper function to create a differencing virtual disk. +// +//revive:disable-next-line:var-naming VHD, not Vhd func CreateDiffVhd(diffVhdPath, baseVhdPath string, blockSizeInMB uint32) error { // Setting `ParentPath` is how to signal to create a differencing disk. createParams := &CreateVirtualDiskParameters{ @@ -314,10 +368,10 @@ func CreateDiffVhd(diffVhdPath, baseVhdPath string, blockSizeInMB uint32) error createParams, ) if err != nil { - return fmt.Errorf("failed to create differencing vhd: %s", err) + return fmt.Errorf("failed to create differencing vhd: %w", err) } if err := syscall.CloseHandle(vhdHandle); err != nil { - return fmt.Errorf("failed to close differencing vhd handle: %s", err) + return fmt.Errorf("failed to close differencing vhd handle: %w", err) } return nil } diff --git a/vendor/github.com/Microsoft/go-winio/vhd/zvhd_windows.go b/vendor/github.com/Microsoft/go-winio/vhd/zvhd_windows.go index 7fb5f3651b..d0e917d2be 100644 --- a/vendor/github.com/Microsoft/go-winio/vhd/zvhd_windows.go +++ b/vendor/github.com/Microsoft/go-winio/vhd/zvhd_windows.go @@ -1,4 +1,6 @@ -// Code generated by 'go generate'; DO NOT EDIT. +//go:build windows + +// Code generated by 'go generate' using "github.com/Microsoft/go-winio/tools/mkwinsyscall"; DO NOT EDIT. package vhd @@ -88,7 +90,7 @@ func getVirtualDiskPhysicalPath(handle syscall.Handle, diskPathSizeInBytes *uint return } -func openVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *OpenVirtualDiskParameters, handle *syscall.Handle) (win32err error) { +func openVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *openVirtualDiskParameters, handle *syscall.Handle) (win32err error) { var _p0 *uint16 _p0, win32err = syscall.UTF16PtrFromString(path) if win32err != nil { @@ -97,7 +99,7 @@ func openVirtualDisk(virtualStorageType *VirtualStorageType, path string, virtua return _openVirtualDisk(virtualStorageType, _p0, virtualDiskAccessMask, openVirtualDiskFlags, parameters, handle) } -func _openVirtualDisk(virtualStorageType *VirtualStorageType, path *uint16, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *OpenVirtualDiskParameters, handle *syscall.Handle) (win32err error) { +func _openVirtualDisk(virtualStorageType *VirtualStorageType, path *uint16, virtualDiskAccessMask uint32, openVirtualDiskFlags uint32, parameters *openVirtualDiskParameters, handle *syscall.Handle) (win32err error) { r0, _, _ := syscall.Syscall6(procOpenVirtualDisk.Addr(), 6, uintptr(unsafe.Pointer(virtualStorageType)), uintptr(unsafe.Pointer(path)), uintptr(virtualDiskAccessMask), uintptr(openVirtualDiskFlags), uintptr(unsafe.Pointer(parameters)), uintptr(unsafe.Pointer(handle))) if r0 != 0 { win32err = syscall.Errno(r0) diff --git a/vendor/github.com/Microsoft/go-winio/zsyscall_windows.go b/vendor/github.com/Microsoft/go-winio/zsyscall_windows.go index 176ff75e32..469b16f639 100644 --- a/vendor/github.com/Microsoft/go-winio/zsyscall_windows.go +++ b/vendor/github.com/Microsoft/go-winio/zsyscall_windows.go @@ -1,4 +1,6 @@ -// Code generated by 'go generate'; DO NOT EDIT. +//go:build windows + +// Code generated by 'go generate' using "github.com/Microsoft/go-winio/tools/mkwinsyscall"; DO NOT EDIT. package winio @@ -47,9 +49,11 @@ var ( procConvertSecurityDescriptorToStringSecurityDescriptorW = modadvapi32.NewProc("ConvertSecurityDescriptorToStringSecurityDescriptorW") procConvertSidToStringSidW = modadvapi32.NewProc("ConvertSidToStringSidW") procConvertStringSecurityDescriptorToSecurityDescriptorW = modadvapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW") + procConvertStringSidToSidW = modadvapi32.NewProc("ConvertStringSidToSidW") procGetSecurityDescriptorLength = modadvapi32.NewProc("GetSecurityDescriptorLength") procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf") procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW") + procLookupAccountSidW = modadvapi32.NewProc("LookupAccountSidW") procLookupPrivilegeDisplayNameW = modadvapi32.NewProc("LookupPrivilegeDisplayNameW") procLookupPrivilegeNameW = modadvapi32.NewProc("LookupPrivilegeNameW") procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW") @@ -59,7 +63,6 @@ var ( procBackupWrite = modkernel32.NewProc("BackupWrite") procCancelIoEx = modkernel32.NewProc("CancelIoEx") procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe") - procCreateFileW = modkernel32.NewProc("CreateFileW") procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort") procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW") procGetCurrentThread = modkernel32.NewProc("GetCurrentThread") @@ -74,7 +77,6 @@ var ( procRtlDosPathNameToNtPathName_U = modntdll.NewProc("RtlDosPathNameToNtPathName_U") procRtlNtStatusToDosErrorNoTeb = modntdll.NewProc("RtlNtStatusToDosErrorNoTeb") procWSAGetOverlappedResult = modws2_32.NewProc("WSAGetOverlappedResult") - procbind = modws2_32.NewProc("bind") ) func adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) { @@ -123,6 +125,14 @@ func _convertStringSecurityDescriptorToSecurityDescriptor(str *uint16, revision return } +func convertStringSidToSid(str *uint16, sid **byte) (err error) { + r1, _, e1 := syscall.Syscall(procConvertStringSidToSidW.Addr(), 2, uintptr(unsafe.Pointer(str)), uintptr(unsafe.Pointer(sid)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func getSecurityDescriptorLength(sd uintptr) (len uint32) { r0, _, _ := syscall.Syscall(procGetSecurityDescriptorLength.Addr(), 1, uintptr(sd), 0, 0) len = uint32(r0) @@ -154,6 +164,14 @@ func _lookupAccountName(systemName *uint16, accountName *uint16, sid *byte, sidS return } +func lookupAccountSid(systemName *uint16, sid *byte, name *uint16, nameSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) { + r1, _, e1 := syscall.Syscall9(procLookupAccountSidW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameSize)), uintptr(unsafe.Pointer(refDomain)), uintptr(unsafe.Pointer(refDomainSize)), uintptr(unsafe.Pointer(sidNameUse)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) { var _p0 *uint16 _p0, err = syscall.UTF16PtrFromString(systemName) @@ -286,24 +304,6 @@ func connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) { return } -func createFile(name string, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) { - var _p0 *uint16 - _p0, err = syscall.UTF16PtrFromString(name) - if err != nil { - return - } - return _createFile(_p0, access, mode, sa, createmode, attrs, templatefile) -} - -func _createFile(name *uint16, access uint32, mode uint32, sa *syscall.SecurityAttributes, createmode uint32, attrs uint32, templatefile syscall.Handle) (handle syscall.Handle, err error) { - r0, _, e1 := syscall.Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0) - handle = syscall.Handle(r0) - if handle == syscall.InvalidHandle { - err = errnoErr(e1) - } - return -} - func createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) { r0, _, e1 := syscall.Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(file), uintptr(port), uintptr(key), uintptr(threadCount), 0, 0) newport = syscall.Handle(r0) @@ -380,25 +380,25 @@ func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err erro return } -func ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntstatus) { +func ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntStatus) { r0, _, _ := syscall.Syscall15(procNtCreateNamedPipeFile.Addr(), 14, uintptr(unsafe.Pointer(pipe)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(share), uintptr(disposition), uintptr(options), uintptr(typ), uintptr(readMode), uintptr(completionMode), uintptr(maxInstances), uintptr(inboundQuota), uintptr(outputQuota), uintptr(unsafe.Pointer(timeout)), 0) - status = ntstatus(r0) + status = ntStatus(r0) return } -func rtlDefaultNpAcl(dacl *uintptr) (status ntstatus) { +func rtlDefaultNpAcl(dacl *uintptr) (status ntStatus) { r0, _, _ := syscall.Syscall(procRtlDefaultNpAcl.Addr(), 1, uintptr(unsafe.Pointer(dacl)), 0, 0) - status = ntstatus(r0) + status = ntStatus(r0) return } -func rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntstatus) { +func rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntStatus) { r0, _, _ := syscall.Syscall6(procRtlDosPathNameToNtPathName_U.Addr(), 4, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(ntName)), uintptr(filePart), uintptr(reserved), 0, 0) - status = ntstatus(r0) + status = ntStatus(r0) return } -func rtlNtStatusToDosError(status ntstatus) (winerr error) { +func rtlNtStatusToDosError(status ntStatus) (winerr error) { r0, _, _ := syscall.Syscall(procRtlNtStatusToDosErrorNoTeb.Addr(), 1, uintptr(status), 0, 0) if r0 != 0 { winerr = syscall.Errno(r0) @@ -417,11 +417,3 @@ func wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint } return } - -func bind(s syscall.Handle, name unsafe.Pointer, namelen int32) (err error) { - r1, _, e1 := syscall.Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen)) - if r1 == socketError { - err = errnoErr(e1) - } - return -} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/cow/cow.go b/vendor/github.com/Microsoft/hcsshim/internal/cow/cow.go index 27a62a7238..f46af33bb6 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/cow/cow.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/cow/cow.go @@ -86,6 +86,12 @@ type Container interface { // container to be terminated by some error condition (including calling // Close). Wait() error + // WaitChannel returns the wait channel of the container + WaitChannel() <-chan struct{} + // WaitError returns the container termination error. + // This function should only be called after the channel in WaitChannel() + // is closed. Otherwise it is not thread safe. + WaitError() error // Modify sends a request to modify container resources Modify(ctx context.Context, config interface{}) error } diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcs/errors.go b/vendor/github.com/Microsoft/hcsshim/internal/hcs/errors.go index e21354ffd6..295d4b849c 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/hcs/errors.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/hcs/errors.go @@ -154,7 +154,7 @@ func (e *HcsError) Error() string { func (e *HcsError) Temporary() bool { err, ok := e.Err.(net.Error) - return ok && err.Temporary() + return ok && err.Temporary() //nolint:staticcheck } func (e *HcsError) Timeout() bool { @@ -193,7 +193,7 @@ func (e *SystemError) Error() string { func (e *SystemError) Temporary() bool { err, ok := e.Err.(net.Error) - return ok && err.Temporary() + return ok && err.Temporary() //nolint:staticcheck } func (e *SystemError) Timeout() bool { @@ -224,7 +224,7 @@ func (e *ProcessError) Error() string { func (e *ProcessError) Temporary() bool { err, ok := e.Err.(net.Error) - return ok && err.Temporary() + return ok && err.Temporary() //nolint:staticcheck } func (e *ProcessError) Timeout() bool { diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcs/system.go b/vendor/github.com/Microsoft/hcsshim/internal/hcs/system.go index 75499c967f..a76f6b253e 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/hcs/system.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/hcs/system.go @@ -4,17 +4,22 @@ import ( "context" "encoding/json" "errors" + "fmt" "strings" "sync" "syscall" + "time" "github.com/Microsoft/hcsshim/internal/cow" "github.com/Microsoft/hcsshim/internal/hcs/schema1" hcsschema "github.com/Microsoft/hcsshim/internal/hcs/schema2" + "github.com/Microsoft/hcsshim/internal/jobobject" "github.com/Microsoft/hcsshim/internal/log" + "github.com/Microsoft/hcsshim/internal/logfields" "github.com/Microsoft/hcsshim/internal/oc" "github.com/Microsoft/hcsshim/internal/timeout" "github.com/Microsoft/hcsshim/internal/vmcompute" + "github.com/sirupsen/logrus" "go.opencensus.io/trace" ) @@ -28,7 +33,8 @@ type System struct { waitBlock chan struct{} waitError error exitError error - os, typ string + os, typ, owner string + startTime time.Time } func newSystem(id string) *System { @@ -38,6 +44,11 @@ func newSystem(id string) *System { } } +// Implementation detail for silo naming, this should NOT be relied upon very heavily. +func siloNameFmt(containerID string) string { + return fmt.Sprintf(`\Container_%s`, containerID) +} + // CreateComputeSystem creates a new compute system with the given configuration but does not start it. func CreateComputeSystem(ctx context.Context, id string, hcsDocumentInterface interface{}) (_ *System, err error) { operation := "hcs::CreateComputeSystem" @@ -127,6 +138,7 @@ func (computeSystem *System) getCachedProperties(ctx context.Context) error { } computeSystem.typ = strings.ToLower(props.SystemType) computeSystem.os = strings.ToLower(props.RuntimeOSType) + computeSystem.owner = strings.ToLower(props.Owner) if computeSystem.os == "" && computeSystem.typ == "container" { // Pre-RS5 HCS did not return the OS, but it only supported containers // that ran Windows. @@ -195,7 +207,7 @@ func (computeSystem *System) Start(ctx context.Context) (err error) { if err != nil { return makeSystemError(computeSystem, operation, err, events) } - + computeSystem.startTime = time.Now() return nil } @@ -275,11 +287,19 @@ func (computeSystem *System) waitBackground() { oc.SetSpanStatus(span, err) } +func (computeSystem *System) WaitChannel() <-chan struct{} { + return computeSystem.waitBlock +} + +func (computeSystem *System) WaitError() error { + return computeSystem.waitError +} + // Wait synchronously waits for the compute system to shutdown or terminate. If // the compute system has already exited returns the previous error (if any). func (computeSystem *System) Wait() error { - <-computeSystem.waitBlock - return computeSystem.waitError + <-computeSystem.WaitChannel() + return computeSystem.WaitError() } // ExitError returns an error describing the reason the compute system terminated. @@ -324,11 +344,115 @@ func (computeSystem *System) Properties(ctx context.Context, types ...schema1.Pr return properties, nil } -// PropertiesV2 returns the requested container properties targeting a V2 schema container. -func (computeSystem *System) PropertiesV2(ctx context.Context, types ...hcsschema.PropertyType) (*hcsschema.Properties, error) { - computeSystem.handleLock.RLock() - defer computeSystem.handleLock.RUnlock() +// queryInProc handles querying for container properties without reaching out to HCS. `props` +// will be updated to contain any data returned from the queries present in `types`. If any properties +// failed to be queried they will be tallied up and returned in as the first return value. Failures on +// query are NOT considered errors; the only failure case for this method is if the containers job object +// cannot be opened. +func (computeSystem *System) queryInProc(ctx context.Context, props *hcsschema.Properties, types []hcsschema.PropertyType) ([]hcsschema.PropertyType, error) { + // In the future we can make use of some new functionality in the HCS that allows you + // to pass a job object for HCS to use for the container. Currently, the only way we'll + // be able to open the job/silo is if we're running as SYSTEM. + jobOptions := &jobobject.Options{ + UseNTVariant: true, + Name: siloNameFmt(computeSystem.id), + } + job, err := jobobject.Open(ctx, jobOptions) + if err != nil { + return nil, err + } + defer job.Close() + + var fallbackQueryTypes []hcsschema.PropertyType + for _, propType := range types { + switch propType { + case hcsschema.PTStatistics: + // Handle a bad caller asking for the same type twice. No use in re-querying if this is + // filled in already. + if props.Statistics == nil { + props.Statistics, err = computeSystem.statisticsInProc(job) + if err != nil { + log.G(ctx).WithError(err).Warn("failed to get statistics in-proc") + + fallbackQueryTypes = append(fallbackQueryTypes, propType) + } + } + default: + fallbackQueryTypes = append(fallbackQueryTypes, propType) + } + } + + return fallbackQueryTypes, nil +} + +// statisticsInProc emulates what HCS does to grab statistics for a given container with a small +// change to make grabbing the private working set total much more efficient. +func (computeSystem *System) statisticsInProc(job *jobobject.JobObject) (*hcsschema.Statistics, error) { + // Start timestamp for these stats before we grab them to match HCS + timestamp := time.Now() + + memInfo, err := job.QueryMemoryStats() + if err != nil { + return nil, err + } + + processorInfo, err := job.QueryProcessorStats() + if err != nil { + return nil, err + } + + storageInfo, err := job.QueryStorageStats() + if err != nil { + return nil, err + } + + // This calculates the private working set more efficiently than HCS does. HCS calls NtQuerySystemInformation + // with the class SystemProcessInformation which returns an array containing system information for *every* + // process running on the machine. They then grab the pids that are running in the container and filter down + // the entries in the array to only what's running in that silo and start tallying up the total. This doesn't + // work well as performance should get worse if more processess are running on the machine in general and not + // just in the container. All of the additional information besides the WorkingSetPrivateSize field is ignored + // as well which isn't great and is wasted work to fetch. + // + // HCS only let's you grab statistics in an all or nothing fashion, so we can't just grab the private + // working set ourselves and ask for everything else seperately. The optimization we can make here is + // to open the silo ourselves and do the same queries for the rest of the info, as well as calculating + // the private working set in a more efficient manner by: + // + // 1. Find the pids running in the silo + // 2. Get a process handle for every process (only need PROCESS_QUERY_LIMITED_INFORMATION access) + // 3. Call NtQueryInformationProcess on each process with the class ProcessVmCounters + // 4. Tally up the total using the field PrivateWorkingSetSize in VM_COUNTERS_EX2. + privateWorkingSet, err := job.QueryPrivateWorkingSet() + if err != nil { + return nil, err + } + + return &hcsschema.Statistics{ + Timestamp: timestamp, + ContainerStartTime: computeSystem.startTime, + Uptime100ns: uint64(time.Since(computeSystem.startTime).Nanoseconds()) / 100, + Memory: &hcsschema.MemoryStats{ + MemoryUsageCommitBytes: memInfo.JobMemory, + MemoryUsageCommitPeakBytes: memInfo.PeakJobMemoryUsed, + MemoryUsagePrivateWorkingSetBytes: privateWorkingSet, + }, + Processor: &hcsschema.ProcessorStats{ + RuntimeKernel100ns: uint64(processorInfo.TotalKernelTime), + RuntimeUser100ns: uint64(processorInfo.TotalUserTime), + TotalRuntime100ns: uint64(processorInfo.TotalKernelTime + processorInfo.TotalUserTime), + }, + Storage: &hcsschema.StorageStats{ + ReadCountNormalized: uint64(storageInfo.ReadStats.IoCount), + ReadSizeBytes: storageInfo.ReadStats.TotalSize, + WriteCountNormalized: uint64(storageInfo.WriteStats.IoCount), + WriteSizeBytes: storageInfo.WriteStats.TotalSize, + }, + }, nil +} +// hcsPropertiesV2Query is a helper to make a HcsGetComputeSystemProperties call using the V2 schema property types. +func (computeSystem *System) hcsPropertiesV2Query(ctx context.Context, types []hcsschema.PropertyType) (*hcsschema.Properties, error) { operation := "hcs::System::PropertiesV2" queryBytes, err := json.Marshal(hcsschema.PropertyQuery{PropertyTypes: types}) @@ -345,12 +469,66 @@ func (computeSystem *System) PropertiesV2(ctx context.Context, types ...hcsschem if propertiesJSON == "" { return nil, ErrUnexpectedValue } - properties := &hcsschema.Properties{} - if err := json.Unmarshal([]byte(propertiesJSON), properties); err != nil { + props := &hcsschema.Properties{} + if err := json.Unmarshal([]byte(propertiesJSON), props); err != nil { return nil, makeSystemError(computeSystem, operation, err, nil) } - return properties, nil + return props, nil +} + +// PropertiesV2 returns the requested compute systems properties targeting a V2 schema compute system. +func (computeSystem *System) PropertiesV2(ctx context.Context, types ...hcsschema.PropertyType) (_ *hcsschema.Properties, err error) { + computeSystem.handleLock.RLock() + defer computeSystem.handleLock.RUnlock() + + // Let HCS tally up the total for VM based queries instead of querying ourselves. + if computeSystem.typ != "container" { + return computeSystem.hcsPropertiesV2Query(ctx, types) + } + + // Define a starter Properties struct with the default fields returned from every + // query. Owner is only returned from Statistics but it's harmless to include. + properties := &hcsschema.Properties{ + Id: computeSystem.id, + SystemType: computeSystem.typ, + RuntimeOsType: computeSystem.os, + Owner: computeSystem.owner, + } + + logEntry := log.G(ctx) + // First lets try and query ourselves without reaching to HCS. If any of the queries fail + // we'll take note and fallback to querying HCS for any of the failed types. + fallbackTypes, err := computeSystem.queryInProc(ctx, properties, types) + if err == nil && len(fallbackTypes) == 0 { + return properties, nil + } else if err != nil { + logEntry.WithError(fmt.Errorf("failed to query compute system properties in-proc: %w", err)) + fallbackTypes = types + } + + logEntry.WithFields(logrus.Fields{ + logfields.ContainerID: computeSystem.id, + "propertyTypes": fallbackTypes, + }).Info("falling back to HCS for property type queries") + + hcsProperties, err := computeSystem.hcsPropertiesV2Query(ctx, fallbackTypes) + if err != nil { + return nil, err + } + + // Now add in anything that we might have successfully queried in process. + if properties.Statistics != nil { + hcsProperties.Statistics = properties.Statistics + hcsProperties.Owner = properties.Owner + } + + // For future support for querying processlist in-proc as well. + if properties.ProcessList != nil { + hcsProperties.ProcessList = properties.ProcessList + } + + return hcsProperties, nil } // Pause pauses the execution of the computeSystem. This feature is not enabled in TP5. diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hns/hnspolicy.go b/vendor/github.com/Microsoft/hcsshim/internal/hns/hnspolicy.go index 591a2631e4..84b3682184 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/hns/hnspolicy.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/hns/hnspolicy.go @@ -21,10 +21,11 @@ const ( ) type NatPolicy struct { - Type PolicyType `json:"Type"` - Protocol string `json:",omitempty"` - InternalPort uint16 `json:",omitempty"` - ExternalPort uint16 `json:",omitempty"` + Type PolicyType `json:"Type"` + Protocol string `json:",omitempty"` + InternalPort uint16 `json:",omitempty"` + ExternalPort uint16 `json:",omitempty"` + ExternalPortReserved bool `json:",omitempty"` } type QosPolicy struct { diff --git a/vendor/github.com/Microsoft/hcsshim/internal/jobobject/iocp.go b/vendor/github.com/Microsoft/hcsshim/internal/jobobject/iocp.go new file mode 100644 index 0000000000..5d6acd69e6 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/jobobject/iocp.go @@ -0,0 +1,111 @@ +package jobobject + +import ( + "context" + "fmt" + "sync" + "unsafe" + + "github.com/Microsoft/hcsshim/internal/log" + "github.com/Microsoft/hcsshim/internal/queue" + "github.com/Microsoft/hcsshim/internal/winapi" + "github.com/sirupsen/logrus" + "golang.org/x/sys/windows" +) + +var ( + ioInitOnce sync.Once + initIOErr error + // Global iocp handle that will be re-used for every job object + ioCompletionPort windows.Handle + // Mapping of job handle to queue to place notifications in. + jobMap sync.Map +) + +// MsgAllProcessesExited is a type representing a message that every process in a job has exited. +type MsgAllProcessesExited struct{} + +// MsgUnimplemented represents a message that we are aware of, but that isn't implemented currently. +// This should not be treated as an error. +type MsgUnimplemented struct{} + +// pollIOCP polls the io completion port forever. +func pollIOCP(ctx context.Context, iocpHandle windows.Handle) { + var ( + overlapped uintptr + code uint32 + key uintptr + ) + + for { + err := windows.GetQueuedCompletionStatus(iocpHandle, &code, &key, (**windows.Overlapped)(unsafe.Pointer(&overlapped)), windows.INFINITE) + if err != nil { + log.G(ctx).WithError(err).Error("failed to poll for job object message") + continue + } + if val, ok := jobMap.Load(key); ok { + msq, ok := val.(*queue.MessageQueue) + if !ok { + log.G(ctx).WithField("value", msq).Warn("encountered non queue type in job map") + continue + } + notification, err := parseMessage(code, overlapped) + if err != nil { + log.G(ctx).WithFields(logrus.Fields{ + "code": code, + "overlapped": overlapped, + }).Warn("failed to parse job object message") + continue + } + if err := msq.Enqueue(notification); err == queue.ErrQueueClosed { + // Write will only return an error when the queue is closed. + // The only time a queue would ever be closed is when we call `Close` on + // the job it belongs to which also removes it from the jobMap, so something + // went wrong here. We can't return as this is reading messages for all jobs + // so just log it and move on. + log.G(ctx).WithFields(logrus.Fields{ + "code": code, + "overlapped": overlapped, + }).Warn("tried to write to a closed queue") + continue + } + } else { + log.G(ctx).Warn("received a message for a job not present in the mapping") + } + } +} + +func parseMessage(code uint32, overlapped uintptr) (interface{}, error) { + // Check code and parse out relevant information related to that notification + // that we care about. For now all we handle is the message that all processes + // in the job have exited. + switch code { + case winapi.JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO: + return MsgAllProcessesExited{}, nil + // Other messages for completeness and a check to make sure that if we fall + // into the default case that this is a code we don't know how to handle. + case winapi.JOB_OBJECT_MSG_END_OF_JOB_TIME: + case winapi.JOB_OBJECT_MSG_END_OF_PROCESS_TIME: + case winapi.JOB_OBJECT_MSG_ACTIVE_PROCESS_LIMIT: + case winapi.JOB_OBJECT_MSG_NEW_PROCESS: + case winapi.JOB_OBJECT_MSG_EXIT_PROCESS: + case winapi.JOB_OBJECT_MSG_ABNORMAL_EXIT_PROCESS: + case winapi.JOB_OBJECT_MSG_PROCESS_MEMORY_LIMIT: + case winapi.JOB_OBJECT_MSG_JOB_MEMORY_LIMIT: + case winapi.JOB_OBJECT_MSG_NOTIFICATION_LIMIT: + default: + return nil, fmt.Errorf("unknown job notification type: %d", code) + } + return MsgUnimplemented{}, nil +} + +// Assigns an IO completion port to get notified of events for the registered job +// object. +func attachIOCP(job windows.Handle, iocp windows.Handle) error { + info := winapi.JOBOBJECT_ASSOCIATE_COMPLETION_PORT{ + CompletionKey: job, + CompletionPort: iocp, + } + _, err := windows.SetInformationJobObject(job, windows.JobObjectAssociateCompletionPortInformation, uintptr(unsafe.Pointer(&info)), uint32(unsafe.Sizeof(info))) + return err +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/jobobject/jobobject.go b/vendor/github.com/Microsoft/hcsshim/internal/jobobject/jobobject.go new file mode 100644 index 0000000000..c9fdd921a7 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/jobobject/jobobject.go @@ -0,0 +1,538 @@ +package jobobject + +import ( + "context" + "errors" + "fmt" + "sync" + "unsafe" + + "github.com/Microsoft/hcsshim/internal/queue" + "github.com/Microsoft/hcsshim/internal/winapi" + "golang.org/x/sys/windows" +) + +// This file provides higher level constructs for the win32 job object API. +// Most of the core creation and management functions are already present in "golang.org/x/sys/windows" +// (CreateJobObject, AssignProcessToJobObject, etc.) as well as most of the limit information +// structs and associated limit flags. Whatever is not present from the job object API +// in golang.org/x/sys/windows is located in /internal/winapi. +// +// https://docs.microsoft.com/en-us/windows/win32/procthread/job-objects + +// JobObject is a high level wrapper around a Windows job object. Holds a handle to +// the job, a queue to receive iocp notifications about the lifecycle +// of the job and a mutex for synchronized handle access. +type JobObject struct { + handle windows.Handle + mq *queue.MessageQueue + handleLock sync.RWMutex +} + +// JobLimits represents the resource constraints that can be applied to a job object. +type JobLimits struct { + CPULimit uint32 + CPUWeight uint32 + MemoryLimitInBytes uint64 + MaxIOPS int64 + MaxBandwidth int64 +} + +type CPURateControlType uint32 + +const ( + WeightBased CPURateControlType = iota + RateBased +) + +// Processor resource controls +const ( + cpuLimitMin = 1 + cpuLimitMax = 10000 + cpuWeightMin = 1 + cpuWeightMax = 9 +) + +var ( + ErrAlreadyClosed = errors.New("the handle has already been closed") + ErrNotRegistered = errors.New("job is not registered to receive notifications") +) + +// Options represents the set of configurable options when making or opening a job object. +type Options struct { + // `Name` specifies the name of the job object if a named job object is desired. + Name string + // `Notifications` specifies if the job will be registered to receive notifications. + // Defaults to false. + Notifications bool + // `UseNTVariant` specifies if we should use the `Nt` variant of Open/CreateJobObject. + // Defaults to false. + UseNTVariant bool + // `IOTracking` enables tracking I/O statistics on the job object. More specifically this + // calls SetInformationJobObject with the JobObjectIoAttribution class. + EnableIOTracking bool +} + +// Create creates a job object. +// +// If options.Name is an empty string, the job will not be assigned a name. +// +// If options.Notifications are not enabled `PollNotifications` will return immediately with error `errNotRegistered`. +// +// If `options` is nil, use default option values. +// +// Returns a JobObject structure and an error if there is one. +func Create(ctx context.Context, options *Options) (_ *JobObject, err error) { + if options == nil { + options = &Options{} + } + + var jobName *winapi.UnicodeString + if options.Name != "" { + jobName, err = winapi.NewUnicodeString(options.Name) + if err != nil { + return nil, err + } + } + + var jobHandle windows.Handle + if options.UseNTVariant { + oa := winapi.ObjectAttributes{ + Length: unsafe.Sizeof(winapi.ObjectAttributes{}), + ObjectName: jobName, + Attributes: 0, + } + status := winapi.NtCreateJobObject(&jobHandle, winapi.JOB_OBJECT_ALL_ACCESS, &oa) + if status != 0 { + return nil, winapi.RtlNtStatusToDosError(status) + } + } else { + var jobNameBuf *uint16 + if jobName != nil && jobName.Buffer != nil { + jobNameBuf = jobName.Buffer + } + jobHandle, err = windows.CreateJobObject(nil, jobNameBuf) + if err != nil { + return nil, err + } + } + + defer func() { + if err != nil { + windows.Close(jobHandle) + } + }() + + job := &JobObject{ + handle: jobHandle, + } + + // If the IOCP we'll be using to receive messages for all jobs hasn't been + // created, create it and start polling. + if options.Notifications { + mq, err := setupNotifications(ctx, job) + if err != nil { + return nil, err + } + job.mq = mq + } + + if options.EnableIOTracking { + if err := enableIOTracking(jobHandle); err != nil { + return nil, err + } + } + + return job, nil +} + +// Open opens an existing job object with name provided in `options`. If no name is provided +// return an error since we need to know what job object to open. +// +// If options.Notifications is false `PollNotifications` will return immediately with error `errNotRegistered`. +// +// Returns a JobObject structure and an error if there is one. +func Open(ctx context.Context, options *Options) (_ *JobObject, err error) { + if options == nil || (options != nil && options.Name == "") { + return nil, errors.New("no job object name specified to open") + } + + unicodeJobName, err := winapi.NewUnicodeString(options.Name) + if err != nil { + return nil, err + } + + var jobHandle windows.Handle + if options != nil && options.UseNTVariant { + oa := winapi.ObjectAttributes{ + Length: unsafe.Sizeof(winapi.ObjectAttributes{}), + ObjectName: unicodeJobName, + Attributes: 0, + } + status := winapi.NtOpenJobObject(&jobHandle, winapi.JOB_OBJECT_ALL_ACCESS, &oa) + if status != 0 { + return nil, winapi.RtlNtStatusToDosError(status) + } + } else { + jobHandle, err = winapi.OpenJobObject(winapi.JOB_OBJECT_ALL_ACCESS, false, unicodeJobName.Buffer) + if err != nil { + return nil, err + } + } + + defer func() { + if err != nil { + windows.Close(jobHandle) + } + }() + + job := &JobObject{ + handle: jobHandle, + } + + // If the IOCP we'll be using to receive messages for all jobs hasn't been + // created, create it and start polling. + if options != nil && options.Notifications { + mq, err := setupNotifications(ctx, job) + if err != nil { + return nil, err + } + job.mq = mq + } + + return job, nil +} + +// helper function to setup notifications for creating/opening a job object +func setupNotifications(ctx context.Context, job *JobObject) (*queue.MessageQueue, error) { + job.handleLock.RLock() + defer job.handleLock.RUnlock() + + if job.handle == 0 { + return nil, ErrAlreadyClosed + } + + ioInitOnce.Do(func() { + h, err := windows.CreateIoCompletionPort(windows.InvalidHandle, 0, 0, 0xffffffff) + if err != nil { + initIOErr = err + return + } + ioCompletionPort = h + go pollIOCP(ctx, h) + }) + + if initIOErr != nil { + return nil, initIOErr + } + + mq := queue.NewMessageQueue() + jobMap.Store(uintptr(job.handle), mq) + if err := attachIOCP(job.handle, ioCompletionPort); err != nil { + jobMap.Delete(uintptr(job.handle)) + return nil, fmt.Errorf("failed to attach job to IO completion port: %w", err) + } + return mq, nil +} + +// PollNotification will poll for a job object notification. This call should only be called once +// per job (ideally in a goroutine loop) and will block if there is not a notification ready. +// This call will return immediately with error `ErrNotRegistered` if the job was not registered +// to receive notifications during `Create`. Internally, messages will be queued and there +// is no worry of messages being dropped. +func (job *JobObject) PollNotification() (interface{}, error) { + if job.mq == nil { + return nil, ErrNotRegistered + } + return job.mq.Dequeue() +} + +// UpdateProcThreadAttribute updates the passed in ProcThreadAttributeList to contain what is necessary to +// launch a process in a job at creation time. This can be used to avoid having to call Assign() after a process +// has already started running. +func (job *JobObject) UpdateProcThreadAttribute(attrList *windows.ProcThreadAttributeListContainer) error { + job.handleLock.RLock() + defer job.handleLock.RUnlock() + + if job.handle == 0 { + return ErrAlreadyClosed + } + + if err := attrList.Update( + winapi.PROC_THREAD_ATTRIBUTE_JOB_LIST, + unsafe.Pointer(&job.handle), + unsafe.Sizeof(job.handle), + ); err != nil { + return fmt.Errorf("failed to update proc thread attributes for job object: %w", err) + } + + return nil +} + +// Close closes the job object handle. +func (job *JobObject) Close() error { + job.handleLock.Lock() + defer job.handleLock.Unlock() + + if job.handle == 0 { + return ErrAlreadyClosed + } + + if err := windows.Close(job.handle); err != nil { + return err + } + + if job.mq != nil { + job.mq.Close() + } + // Handles now invalid so if the map entry to receive notifications for this job still + // exists remove it so we can stop receiving notifications. + if _, ok := jobMap.Load(uintptr(job.handle)); ok { + jobMap.Delete(uintptr(job.handle)) + } + + job.handle = 0 + return nil +} + +// Assign assigns a process to the job object. +func (job *JobObject) Assign(pid uint32) error { + job.handleLock.RLock() + defer job.handleLock.RUnlock() + + if job.handle == 0 { + return ErrAlreadyClosed + } + + if pid == 0 { + return errors.New("invalid pid: 0") + } + hProc, err := windows.OpenProcess(winapi.PROCESS_ALL_ACCESS, true, pid) + if err != nil { + return err + } + defer windows.Close(hProc) + return windows.AssignProcessToJobObject(job.handle, hProc) +} + +// Terminate terminates the job, essentially calls TerminateProcess on every process in the +// job. +func (job *JobObject) Terminate(exitCode uint32) error { + job.handleLock.RLock() + defer job.handleLock.RUnlock() + if job.handle == 0 { + return ErrAlreadyClosed + } + return windows.TerminateJobObject(job.handle, exitCode) +} + +// Pids returns all of the process IDs in the job object. +func (job *JobObject) Pids() ([]uint32, error) { + job.handleLock.RLock() + defer job.handleLock.RUnlock() + + if job.handle == 0 { + return nil, ErrAlreadyClosed + } + + info := winapi.JOBOBJECT_BASIC_PROCESS_ID_LIST{} + err := winapi.QueryInformationJobObject( + job.handle, + winapi.JobObjectBasicProcessIdList, + unsafe.Pointer(&info), + uint32(unsafe.Sizeof(info)), + nil, + ) + + // This is either the case where there is only one process or no processes in + // the job. Any other case will result in ERROR_MORE_DATA. Check if info.NumberOfProcessIdsInList + // is 1 and just return this, otherwise return an empty slice. + if err == nil { + if info.NumberOfProcessIdsInList == 1 { + return []uint32{uint32(info.ProcessIdList[0])}, nil + } + // Return empty slice instead of nil to play well with the caller of this. + // Do not return an error if no processes are running inside the job + return []uint32{}, nil + } + + if err != winapi.ERROR_MORE_DATA { + return nil, fmt.Errorf("failed initial query for PIDs in job object: %w", err) + } + + jobBasicProcessIDListSize := unsafe.Sizeof(info) + (unsafe.Sizeof(info.ProcessIdList[0]) * uintptr(info.NumberOfAssignedProcesses-1)) + buf := make([]byte, jobBasicProcessIDListSize) + if err = winapi.QueryInformationJobObject( + job.handle, + winapi.JobObjectBasicProcessIdList, + unsafe.Pointer(&buf[0]), + uint32(len(buf)), + nil, + ); err != nil { + return nil, fmt.Errorf("failed to query for PIDs in job object: %w", err) + } + + bufInfo := (*winapi.JOBOBJECT_BASIC_PROCESS_ID_LIST)(unsafe.Pointer(&buf[0])) + pids := make([]uint32, bufInfo.NumberOfProcessIdsInList) + for i, bufPid := range bufInfo.AllPids() { + pids[i] = uint32(bufPid) + } + return pids, nil +} + +// QueryMemoryStats gets the memory stats for the job object. +func (job *JobObject) QueryMemoryStats() (*winapi.JOBOBJECT_MEMORY_USAGE_INFORMATION, error) { + job.handleLock.RLock() + defer job.handleLock.RUnlock() + + if job.handle == 0 { + return nil, ErrAlreadyClosed + } + + info := winapi.JOBOBJECT_MEMORY_USAGE_INFORMATION{} + if err := winapi.QueryInformationJobObject( + job.handle, + winapi.JobObjectMemoryUsageInformation, + unsafe.Pointer(&info), + uint32(unsafe.Sizeof(info)), + nil, + ); err != nil { + return nil, fmt.Errorf("failed to query for job object memory stats: %w", err) + } + return &info, nil +} + +// QueryProcessorStats gets the processor stats for the job object. +func (job *JobObject) QueryProcessorStats() (*winapi.JOBOBJECT_BASIC_ACCOUNTING_INFORMATION, error) { + job.handleLock.RLock() + defer job.handleLock.RUnlock() + + if job.handle == 0 { + return nil, ErrAlreadyClosed + } + + info := winapi.JOBOBJECT_BASIC_ACCOUNTING_INFORMATION{} + if err := winapi.QueryInformationJobObject( + job.handle, + winapi.JobObjectBasicAccountingInformation, + unsafe.Pointer(&info), + uint32(unsafe.Sizeof(info)), + nil, + ); err != nil { + return nil, fmt.Errorf("failed to query for job object process stats: %w", err) + } + return &info, nil +} + +// QueryStorageStats gets the storage (I/O) stats for the job object. This call will error +// if either `EnableIOTracking` wasn't set to true on creation of the job, or SetIOTracking() +// hasn't been called since creation of the job. +func (job *JobObject) QueryStorageStats() (*winapi.JOBOBJECT_IO_ATTRIBUTION_INFORMATION, error) { + job.handleLock.RLock() + defer job.handleLock.RUnlock() + + if job.handle == 0 { + return nil, ErrAlreadyClosed + } + + info := winapi.JOBOBJECT_IO_ATTRIBUTION_INFORMATION{ + ControlFlags: winapi.JOBOBJECT_IO_ATTRIBUTION_CONTROL_ENABLE, + } + if err := winapi.QueryInformationJobObject( + job.handle, + winapi.JobObjectIoAttribution, + unsafe.Pointer(&info), + uint32(unsafe.Sizeof(info)), + nil, + ); err != nil { + return nil, fmt.Errorf("failed to query for job object storage stats: %w", err) + } + return &info, nil +} + +// QueryPrivateWorkingSet returns the private working set size for the job. This is calculated by adding up the +// private working set for every process running in the job. +func (job *JobObject) QueryPrivateWorkingSet() (uint64, error) { + pids, err := job.Pids() + if err != nil { + return 0, err + } + + openAndQueryWorkingSet := func(pid uint32) (uint64, error) { + h, err := windows.OpenProcess(windows.PROCESS_QUERY_LIMITED_INFORMATION, false, pid) + if err != nil { + // Continue to the next if OpenProcess doesn't return a valid handle (fails). Handles a + // case where one of the pids in the job exited before we open. + return 0, nil + } + defer func() { + _ = windows.Close(h) + }() + // Check if the process is actually running in the job still. There's a small chance + // that the process could have exited and had its pid re-used between grabbing the pids + // in the job and opening the handle to it above. + var inJob int32 + if err := winapi.IsProcessInJob(h, job.handle, &inJob); err != nil { + // This shouldn't fail unless we have incorrect access rights which we control + // here so probably best to error out if this failed. + return 0, err + } + // Don't report stats for this process as it's not running in the job. This shouldn't be + // an error condition though. + if inJob == 0 { + return 0, nil + } + + var vmCounters winapi.VM_COUNTERS_EX2 + status := winapi.NtQueryInformationProcess( + h, + winapi.ProcessVmCounters, + unsafe.Pointer(&vmCounters), + uint32(unsafe.Sizeof(vmCounters)), + nil, + ) + if !winapi.NTSuccess(status) { + return 0, fmt.Errorf("failed to query information for process: %w", winapi.RtlNtStatusToDosError(status)) + } + return uint64(vmCounters.PrivateWorkingSetSize), nil + } + + var jobWorkingSetSize uint64 + for _, pid := range pids { + workingSet, err := openAndQueryWorkingSet(pid) + if err != nil { + return 0, err + } + jobWorkingSetSize += workingSet + } + + return jobWorkingSetSize, nil +} + +// SetIOTracking enables IO tracking for processes in the job object. +// This enables use of the QueryStorageStats method. +func (job *JobObject) SetIOTracking() error { + job.handleLock.RLock() + defer job.handleLock.RUnlock() + + if job.handle == 0 { + return ErrAlreadyClosed + } + + return enableIOTracking(job.handle) +} + +func enableIOTracking(job windows.Handle) error { + info := winapi.JOBOBJECT_IO_ATTRIBUTION_INFORMATION{ + ControlFlags: winapi.JOBOBJECT_IO_ATTRIBUTION_CONTROL_ENABLE, + } + if _, err := windows.SetInformationJobObject( + job, + winapi.JobObjectIoAttribution, + uintptr(unsafe.Pointer(&info)), + uint32(unsafe.Sizeof(info)), + ); err != nil { + return fmt.Errorf("failed to enable IO tracking on job object: %w", err) + } + return nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/jobobject/limits.go b/vendor/github.com/Microsoft/hcsshim/internal/jobobject/limits.go new file mode 100644 index 0000000000..4efde292c4 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/jobobject/limits.go @@ -0,0 +1,315 @@ +package jobobject + +import ( + "errors" + "fmt" + "unsafe" + + "github.com/Microsoft/hcsshim/internal/winapi" + "golang.org/x/sys/windows" +) + +const ( + memoryLimitMax uint64 = 0xffffffffffffffff +) + +func isFlagSet(flag, controlFlags uint32) bool { + return (flag & controlFlags) == flag +} + +// SetResourceLimits sets resource limits on the job object (cpu, memory, storage). +func (job *JobObject) SetResourceLimits(limits *JobLimits) error { + // Go through and check what limits were specified and apply them to the job. + if limits.MemoryLimitInBytes != 0 { + if err := job.SetMemoryLimit(limits.MemoryLimitInBytes); err != nil { + return fmt.Errorf("failed to set job object memory limit: %w", err) + } + } + + if limits.CPULimit != 0 { + if err := job.SetCPULimit(RateBased, limits.CPULimit); err != nil { + return fmt.Errorf("failed to set job object cpu limit: %w", err) + } + } else if limits.CPUWeight != 0 { + if err := job.SetCPULimit(WeightBased, limits.CPUWeight); err != nil { + return fmt.Errorf("failed to set job object cpu limit: %w", err) + } + } + + if limits.MaxBandwidth != 0 || limits.MaxIOPS != 0 { + if err := job.SetIOLimit(limits.MaxBandwidth, limits.MaxIOPS); err != nil { + return fmt.Errorf("failed to set io limit on job object: %w", err) + } + } + return nil +} + +// SetTerminateOnLastHandleClose sets the job object flag that specifies that the job should terminate +// all processes in the job on the last open handle being closed. +func (job *JobObject) SetTerminateOnLastHandleClose() error { + info, err := job.getExtendedInformation() + if err != nil { + return err + } + info.BasicLimitInformation.LimitFlags |= windows.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE + return job.setExtendedInformation(info) +} + +// SetMemoryLimit sets the memory limit of the job object based on the given `memoryLimitInBytes`. +func (job *JobObject) SetMemoryLimit(memoryLimitInBytes uint64) error { + if memoryLimitInBytes >= memoryLimitMax { + return errors.New("memory limit specified exceeds the max size") + } + + info, err := job.getExtendedInformation() + if err != nil { + return err + } + + info.JobMemoryLimit = uintptr(memoryLimitInBytes) + info.BasicLimitInformation.LimitFlags |= windows.JOB_OBJECT_LIMIT_JOB_MEMORY + return job.setExtendedInformation(info) +} + +// GetMemoryLimit gets the memory limit in bytes of the job object. +func (job *JobObject) GetMemoryLimit() (uint64, error) { + info, err := job.getExtendedInformation() + if err != nil { + return 0, err + } + return uint64(info.JobMemoryLimit), nil +} + +// SetCPULimit sets the CPU limit depending on the specified `CPURateControlType` to +// `rateControlValue` for the job object. +func (job *JobObject) SetCPULimit(rateControlType CPURateControlType, rateControlValue uint32) error { + cpuInfo, err := job.getCPURateControlInformation() + if err != nil { + return err + } + switch rateControlType { + case WeightBased: + if rateControlValue < cpuWeightMin || rateControlValue > cpuWeightMax { + return fmt.Errorf("processor weight value of `%d` is invalid", rateControlValue) + } + cpuInfo.ControlFlags |= winapi.JOB_OBJECT_CPU_RATE_CONTROL_ENABLE | winapi.JOB_OBJECT_CPU_RATE_CONTROL_WEIGHT_BASED + cpuInfo.Value = rateControlValue + case RateBased: + if rateControlValue < cpuLimitMin || rateControlValue > cpuLimitMax { + return fmt.Errorf("processor rate of `%d` is invalid", rateControlValue) + } + cpuInfo.ControlFlags |= winapi.JOB_OBJECT_CPU_RATE_CONTROL_ENABLE | winapi.JOB_OBJECT_CPU_RATE_CONTROL_HARD_CAP + cpuInfo.Value = rateControlValue + default: + return errors.New("invalid job object cpu rate control type") + } + return job.setCPURateControlInfo(cpuInfo) +} + +// GetCPULimit gets the cpu limits for the job object. +// `rateControlType` is used to indicate what type of cpu limit to query for. +func (job *JobObject) GetCPULimit(rateControlType CPURateControlType) (uint32, error) { + info, err := job.getCPURateControlInformation() + if err != nil { + return 0, err + } + + if !isFlagSet(winapi.JOB_OBJECT_CPU_RATE_CONTROL_ENABLE, info.ControlFlags) { + return 0, errors.New("the job does not have cpu rate control enabled") + } + + switch rateControlType { + case WeightBased: + if !isFlagSet(winapi.JOB_OBJECT_CPU_RATE_CONTROL_WEIGHT_BASED, info.ControlFlags) { + return 0, errors.New("cannot get cpu weight for job object without cpu weight option set") + } + case RateBased: + if !isFlagSet(winapi.JOB_OBJECT_CPU_RATE_CONTROL_HARD_CAP, info.ControlFlags) { + return 0, errors.New("cannot get cpu rate hard cap for job object without cpu rate hard cap option set") + } + default: + return 0, errors.New("invalid job object cpu rate control type") + } + return info.Value, nil +} + +// SetCPUAffinity sets the processor affinity for the job object. +// The affinity is passed in as a bitmask. +func (job *JobObject) SetCPUAffinity(affinityBitMask uint64) error { + info, err := job.getExtendedInformation() + if err != nil { + return err + } + info.BasicLimitInformation.LimitFlags |= uint32(windows.JOB_OBJECT_LIMIT_AFFINITY) + info.BasicLimitInformation.Affinity = uintptr(affinityBitMask) + return job.setExtendedInformation(info) +} + +// GetCPUAffinity gets the processor affinity for the job object. +// The returned affinity is a bitmask. +func (job *JobObject) GetCPUAffinity() (uint64, error) { + info, err := job.getExtendedInformation() + if err != nil { + return 0, err + } + return uint64(info.BasicLimitInformation.Affinity), nil +} + +// SetIOLimit sets the IO limits specified on the job object. +func (job *JobObject) SetIOLimit(maxBandwidth, maxIOPS int64) error { + ioInfo, err := job.getIOLimit() + if err != nil { + return err + } + ioInfo.ControlFlags |= winapi.JOB_OBJECT_IO_RATE_CONTROL_ENABLE + if maxBandwidth != 0 { + ioInfo.MaxBandwidth = maxBandwidth + } + if maxIOPS != 0 { + ioInfo.MaxIops = maxIOPS + } + return job.setIORateControlInfo(ioInfo) +} + +// GetIOMaxBandwidthLimit gets the max bandwidth for the job object. +func (job *JobObject) GetIOMaxBandwidthLimit() (int64, error) { + info, err := job.getIOLimit() + if err != nil { + return 0, err + } + return info.MaxBandwidth, nil +} + +// GetIOMaxIopsLimit gets the max iops for the job object. +func (job *JobObject) GetIOMaxIopsLimit() (int64, error) { + info, err := job.getIOLimit() + if err != nil { + return 0, err + } + return info.MaxIops, nil +} + +// Helper function for getting a job object's extended information. +func (job *JobObject) getExtendedInformation() (*windows.JOBOBJECT_EXTENDED_LIMIT_INFORMATION, error) { + job.handleLock.RLock() + defer job.handleLock.RUnlock() + + if job.handle == 0 { + return nil, ErrAlreadyClosed + } + + info := windows.JOBOBJECT_EXTENDED_LIMIT_INFORMATION{} + if err := winapi.QueryInformationJobObject( + job.handle, + windows.JobObjectExtendedLimitInformation, + unsafe.Pointer(&info), + uint32(unsafe.Sizeof(info)), + nil, + ); err != nil { + return nil, fmt.Errorf("query %v returned error: %w", info, err) + } + return &info, nil +} + +// Helper function for getting a job object's CPU rate control information. +func (job *JobObject) getCPURateControlInformation() (*winapi.JOBOBJECT_CPU_RATE_CONTROL_INFORMATION, error) { + job.handleLock.RLock() + defer job.handleLock.RUnlock() + + if job.handle == 0 { + return nil, ErrAlreadyClosed + } + + info := winapi.JOBOBJECT_CPU_RATE_CONTROL_INFORMATION{} + if err := winapi.QueryInformationJobObject( + job.handle, + windows.JobObjectCpuRateControlInformation, + unsafe.Pointer(&info), + uint32(unsafe.Sizeof(info)), + nil, + ); err != nil { + return nil, fmt.Errorf("query %v returned error: %w", info, err) + } + return &info, nil +} + +// Helper function for setting a job object's extended information. +func (job *JobObject) setExtendedInformation(info *windows.JOBOBJECT_EXTENDED_LIMIT_INFORMATION) error { + job.handleLock.RLock() + defer job.handleLock.RUnlock() + + if job.handle == 0 { + return ErrAlreadyClosed + } + + if _, err := windows.SetInformationJobObject( + job.handle, + windows.JobObjectExtendedLimitInformation, + uintptr(unsafe.Pointer(info)), + uint32(unsafe.Sizeof(*info)), + ); err != nil { + return fmt.Errorf("failed to set Extended info %v on job object: %w", info, err) + } + return nil +} + +// Helper function for querying job handle for IO limit information. +func (job *JobObject) getIOLimit() (*winapi.JOBOBJECT_IO_RATE_CONTROL_INFORMATION, error) { + job.handleLock.RLock() + defer job.handleLock.RUnlock() + + if job.handle == 0 { + return nil, ErrAlreadyClosed + } + + ioInfo := &winapi.JOBOBJECT_IO_RATE_CONTROL_INFORMATION{} + var blockCount uint32 = 1 + + if _, err := winapi.QueryIoRateControlInformationJobObject( + job.handle, + nil, + &ioInfo, + &blockCount, + ); err != nil { + return nil, fmt.Errorf("query %v returned error: %w", ioInfo, err) + } + + if !isFlagSet(winapi.JOB_OBJECT_IO_RATE_CONTROL_ENABLE, ioInfo.ControlFlags) { + return nil, fmt.Errorf("query %v cannot get IO limits for job object without IO rate control option set", ioInfo) + } + return ioInfo, nil +} + +// Helper function for setting a job object's IO rate control information. +func (job *JobObject) setIORateControlInfo(ioInfo *winapi.JOBOBJECT_IO_RATE_CONTROL_INFORMATION) error { + job.handleLock.RLock() + defer job.handleLock.RUnlock() + + if job.handle == 0 { + return ErrAlreadyClosed + } + + if _, err := winapi.SetIoRateControlInformationJobObject(job.handle, ioInfo); err != nil { + return fmt.Errorf("failed to set IO limit info %v on job object: %w", ioInfo, err) + } + return nil +} + +// Helper function for setting a job object's CPU rate control information. +func (job *JobObject) setCPURateControlInfo(cpuInfo *winapi.JOBOBJECT_CPU_RATE_CONTROL_INFORMATION) error { + job.handleLock.RLock() + defer job.handleLock.RUnlock() + + if job.handle == 0 { + return ErrAlreadyClosed + } + if _, err := windows.SetInformationJobObject( + job.handle, + windows.JobObjectCpuRateControlInformation, + uintptr(unsafe.Pointer(cpuInfo)), + uint32(unsafe.Sizeof(cpuInfo)), + ); err != nil { + return fmt.Errorf("failed to set cpu limit info %v on job object: %w", cpuInfo, err) + } + return nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/queue/mq.go b/vendor/github.com/Microsoft/hcsshim/internal/queue/mq.go new file mode 100644 index 0000000000..4eb9bb9f1f --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/queue/mq.go @@ -0,0 +1,92 @@ +package queue + +import ( + "errors" + "sync" +) + +var ErrQueueClosed = errors.New("the queue is closed for reading and writing") + +// MessageQueue represents a threadsafe message queue to be used to retrieve or +// write messages to. +type MessageQueue struct { + m *sync.RWMutex + c *sync.Cond + messages []interface{} + closed bool +} + +// NewMessageQueue returns a new MessageQueue. +func NewMessageQueue() *MessageQueue { + m := &sync.RWMutex{} + return &MessageQueue{ + m: m, + c: sync.NewCond(m), + messages: []interface{}{}, + } +} + +// Enqueue writes `msg` to the queue. +func (mq *MessageQueue) Enqueue(msg interface{}) error { + mq.m.Lock() + defer mq.m.Unlock() + + if mq.closed { + return ErrQueueClosed + } + mq.messages = append(mq.messages, msg) + // Signal a waiter that there is now a value available in the queue. + mq.c.Signal() + return nil +} + +// Dequeue will read a value from the queue and remove it. If the queue +// is empty, this will block until the queue is closed or a value gets enqueued. +func (mq *MessageQueue) Dequeue() (interface{}, error) { + mq.m.Lock() + defer mq.m.Unlock() + + for !mq.closed && mq.size() == 0 { + mq.c.Wait() + } + + // We got woken up, check if it's because the queue got closed. + if mq.closed { + return nil, ErrQueueClosed + } + + val := mq.messages[0] + mq.messages[0] = nil + mq.messages = mq.messages[1:] + return val, nil +} + +// Size returns the size of the queue. +func (mq *MessageQueue) Size() int { + mq.m.RLock() + defer mq.m.RUnlock() + return mq.size() +} + +// Nonexported size check to check if the queue is empty inside already locked functions. +func (mq *MessageQueue) size() int { + return len(mq.messages) +} + +// Close closes the queue for future writes or reads. Any attempts to read or write from the +// queue after close will return ErrQueueClosed. This is safe to call multiple times. +func (mq *MessageQueue) Close() { + mq.m.Lock() + defer mq.m.Unlock() + + // Already closed, noop + if mq.closed { + return + } + + mq.messages = nil + mq.closed = true + // If there's anybody currently waiting on a value from Dequeue, we need to + // broadcast so the read(s) can return ErrQueueClosed. + mq.c.Broadcast() +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/winapi/iocp.go b/vendor/github.com/Microsoft/hcsshim/internal/winapi/iocp.go deleted file mode 100644 index 4e609cbf1c..0000000000 --- a/vendor/github.com/Microsoft/hcsshim/internal/winapi/iocp.go +++ /dev/null @@ -1,3 +0,0 @@ -package winapi - -//sys GetQueuedCompletionStatus(cphandle windows.Handle, qty *uint32, key *uintptr, overlapped **windows.Overlapped, timeout uint32) (err error) diff --git a/vendor/github.com/Microsoft/hcsshim/internal/winapi/jobobject.go b/vendor/github.com/Microsoft/hcsshim/internal/winapi/jobobject.go index ba12b1ad92..7eb13f8f0a 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/winapi/jobobject.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/winapi/jobobject.go @@ -24,7 +24,10 @@ const ( // Access rights for creating or opening job objects. // // https://docs.microsoft.com/en-us/windows/win32/procthread/job-object-security-and-access-rights -const JOB_OBJECT_ALL_ACCESS = 0x1F001F +const ( + JOB_OBJECT_QUERY = 0x0004 + JOB_OBJECT_ALL_ACCESS = 0x1F001F +) // IO limit flags // @@ -93,7 +96,7 @@ type JOBOBJECT_BASIC_PROCESS_ID_LIST struct { // AllPids returns all the process Ids in the job object. func (p *JOBOBJECT_BASIC_PROCESS_ID_LIST) AllPids() []uintptr { - return (*[(1 << 27) - 1]uintptr)(unsafe.Pointer(&p.ProcessIdList[0]))[:p.NumberOfProcessIdsInList] + return (*[(1 << 27) - 1]uintptr)(unsafe.Pointer(&p.ProcessIdList[0]))[:p.NumberOfProcessIdsInList:p.NumberOfProcessIdsInList] } // https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-jobobject_basic_accounting_information @@ -162,7 +165,7 @@ type JOBOBJECT_ASSOCIATE_COMPLETION_PORT struct { // PBOOL Result // ); // -//sys IsProcessInJob(procHandle windows.Handle, jobHandle windows.Handle, result *bool) (err error) = kernel32.IsProcessInJob +//sys IsProcessInJob(procHandle windows.Handle, jobHandle windows.Handle, result *int32) (err error) = kernel32.IsProcessInJob // BOOL QueryInformationJobObject( // HANDLE hJob, @@ -172,7 +175,7 @@ type JOBOBJECT_ASSOCIATE_COMPLETION_PORT struct { // LPDWORD lpReturnLength // ); // -//sys QueryInformationJobObject(jobHandle windows.Handle, infoClass uint32, jobObjectInfo uintptr, jobObjectInformationLength uint32, lpReturnLength *uint32) (err error) = kernel32.QueryInformationJobObject +//sys QueryInformationJobObject(jobHandle windows.Handle, infoClass uint32, jobObjectInfo unsafe.Pointer, jobObjectInformationLength uint32, lpReturnLength *uint32) (err error) = kernel32.QueryInformationJobObject // HANDLE OpenJobObjectW( // DWORD dwDesiredAccess, diff --git a/vendor/github.com/Microsoft/hcsshim/internal/winapi/process.go b/vendor/github.com/Microsoft/hcsshim/internal/winapi/process.go index 37839435b9..222529f433 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/winapi/process.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/winapi/process.go @@ -6,3 +6,60 @@ const ( PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE = 0x20016 PROC_THREAD_ATTRIBUTE_JOB_LIST = 0x2000D ) + +// ProcessVmCounters corresponds to the _VM_COUNTERS_EX and _VM_COUNTERS_EX2 structures. +const ProcessVmCounters = 3 + +// __kernel_entry NTSTATUS NtQueryInformationProcess( +// [in] HANDLE ProcessHandle, +// [in] PROCESSINFOCLASS ProcessInformationClass, +// [out] PVOID ProcessInformation, +// [in] ULONG ProcessInformationLength, +// [out, optional] PULONG ReturnLength +// ); +// +//sys NtQueryInformationProcess(processHandle windows.Handle, processInfoClass uint32, processInfo unsafe.Pointer, processInfoLength uint32, returnLength *uint32) (status uint32) = ntdll.NtQueryInformationProcess + +// typedef struct _VM_COUNTERS_EX +// { +// SIZE_T PeakVirtualSize; +// SIZE_T VirtualSize; +// ULONG PageFaultCount; +// SIZE_T PeakWorkingSetSize; +// SIZE_T WorkingSetSize; +// SIZE_T QuotaPeakPagedPoolUsage; +// SIZE_T QuotaPagedPoolUsage; +// SIZE_T QuotaPeakNonPagedPoolUsage; +// SIZE_T QuotaNonPagedPoolUsage; +// SIZE_T PagefileUsage; +// SIZE_T PeakPagefileUsage; +// SIZE_T PrivateUsage; +// } VM_COUNTERS_EX, *PVM_COUNTERS_EX; +// +type VM_COUNTERS_EX struct { + PeakVirtualSize uintptr + VirtualSize uintptr + PageFaultCount uint32 + PeakWorkingSetSize uintptr + WorkingSetSize uintptr + QuotaPeakPagedPoolUsage uintptr + QuotaPagedPoolUsage uintptr + QuotaPeakNonPagedPoolUsage uintptr + QuotaNonPagedPoolUsage uintptr + PagefileUsage uintptr + PeakPagefileUsage uintptr + PrivateUsage uintptr +} + +// typedef struct _VM_COUNTERS_EX2 +// { +// VM_COUNTERS_EX CountersEx; +// SIZE_T PrivateWorkingSetSize; +// SIZE_T SharedCommitUsage; +// } VM_COUNTERS_EX2, *PVM_COUNTERS_EX2; +// +type VM_COUNTERS_EX2 struct { + CountersEx VM_COUNTERS_EX + PrivateWorkingSetSize uintptr + SharedCommitUsage uintptr +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/winapi/system.go b/vendor/github.com/Microsoft/hcsshim/internal/winapi/system.go index 327f57d7c2..78fe01a4b4 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/winapi/system.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/winapi/system.go @@ -12,7 +12,8 @@ const STATUS_INFO_LENGTH_MISMATCH = 0xC0000004 // ULONG SystemInformationLength, // PULONG ReturnLength // ); -//sys NtQuerySystemInformation(systemInfoClass int, systemInformation uintptr, systemInfoLength uint32, returnLength *uint32) (status uint32) = ntdll.NtQuerySystemInformation +// +//sys NtQuerySystemInformation(systemInfoClass int, systemInformation unsafe.Pointer, systemInfoLength uint32, returnLength *uint32) (status uint32) = ntdll.NtQuerySystemInformation type SYSTEM_PROCESS_INFORMATION struct { NextEntryOffset uint32 // ULONG diff --git a/vendor/github.com/Microsoft/hcsshim/internal/winapi/winapi.go b/vendor/github.com/Microsoft/hcsshim/internal/winapi/winapi.go index 1d4ba3c4f8..d2cc9d9fba 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/winapi/winapi.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/winapi/winapi.go @@ -2,4 +2,4 @@ // be thought of as an extension to golang.org/x/sys/windows. package winapi -//go:generate go run ..\..\mksyscall_windows.go -output zsyscall_windows.go console.go system.go net.go path.go thread.go iocp.go jobobject.go logon.go memory.go process.go processor.go devices.go filesystem.go errors.go +//go:generate go run ..\..\mksyscall_windows.go -output zsyscall_windows.go user.go console.go system.go net.go path.go thread.go jobobject.go logon.go memory.go process.go processor.go devices.go filesystem.go errors.go diff --git a/vendor/github.com/Microsoft/hcsshim/internal/winapi/zsyscall_windows.go b/vendor/github.com/Microsoft/hcsshim/internal/winapi/zsyscall_windows.go index 4eb64b4c0c..1f16cf0b8e 100644 --- a/vendor/github.com/Microsoft/hcsshim/internal/winapi/zsyscall_windows.go +++ b/vendor/github.com/Microsoft/hcsshim/internal/winapi/zsyscall_windows.go @@ -50,7 +50,6 @@ var ( procSetJobCompartmentId = modiphlpapi.NewProc("SetJobCompartmentId") procSearchPathW = modkernel32.NewProc("SearchPathW") procCreateRemoteThread = modkernel32.NewProc("CreateRemoteThread") - procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus") procIsProcessInJob = modkernel32.NewProc("IsProcessInJob") procQueryInformationJobObject = modkernel32.NewProc("QueryInformationJobObject") procOpenJobObjectW = modkernel32.NewProc("OpenJobObjectW") @@ -61,6 +60,7 @@ var ( procLogonUserW = modadvapi32.NewProc("LogonUserW") procLocalAlloc = modkernel32.NewProc("LocalAlloc") procLocalFree = modkernel32.NewProc("LocalFree") + procNtQueryInformationProcess = modntdll.NewProc("NtQueryInformationProcess") procGetActiveProcessorCount = modkernel32.NewProc("GetActiveProcessorCount") procCM_Get_Device_ID_List_SizeA = modcfgmgr32.NewProc("CM_Get_Device_ID_List_SizeA") procCM_Get_Device_ID_ListA = modcfgmgr32.NewProc("CM_Get_Device_ID_ListA") @@ -100,7 +100,7 @@ func resizePseudoConsole(hPc windows.Handle, size uint32) (hr error) { return } -func NtQuerySystemInformation(systemInfoClass int, systemInformation uintptr, systemInfoLength uint32, returnLength *uint32) (status uint32) { +func NtQuerySystemInformation(systemInfoClass int, systemInformation unsafe.Pointer, systemInfoLength uint32, returnLength *uint32) (status uint32) { r0, _, _ := syscall.Syscall6(procNtQuerySystemInformation.Addr(), 4, uintptr(systemInfoClass), uintptr(systemInformation), uintptr(systemInfoLength), uintptr(unsafe.Pointer(returnLength)), 0, 0) status = uint32(r0) return @@ -140,19 +140,7 @@ func CreateRemoteThread(process windows.Handle, sa *windows.SecurityAttributes, return } -func GetQueuedCompletionStatus(cphandle windows.Handle, qty *uint32, key *uintptr, overlapped **windows.Overlapped, timeout uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(cphandle), uintptr(unsafe.Pointer(qty)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(overlapped)), uintptr(timeout), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func IsProcessInJob(procHandle windows.Handle, jobHandle windows.Handle, result *bool) (err error) { +func IsProcessInJob(procHandle windows.Handle, jobHandle windows.Handle, result *int32) (err error) { r1, _, e1 := syscall.Syscall(procIsProcessInJob.Addr(), 3, uintptr(procHandle), uintptr(jobHandle), uintptr(unsafe.Pointer(result))) if r1 == 0 { if e1 != 0 { @@ -164,7 +152,7 @@ func IsProcessInJob(procHandle windows.Handle, jobHandle windows.Handle, result return } -func QueryInformationJobObject(jobHandle windows.Handle, infoClass uint32, jobObjectInfo uintptr, jobObjectInformationLength uint32, lpReturnLength *uint32) (err error) { +func QueryInformationJobObject(jobHandle windows.Handle, infoClass uint32, jobObjectInfo unsafe.Pointer, jobObjectInformationLength uint32, lpReturnLength *uint32) (err error) { r1, _, e1 := syscall.Syscall6(procQueryInformationJobObject.Addr(), 5, uintptr(jobHandle), uintptr(infoClass), uintptr(jobObjectInfo), uintptr(jobObjectInformationLength), uintptr(unsafe.Pointer(lpReturnLength)), 0) if r1 == 0 { if e1 != 0 { @@ -256,6 +244,12 @@ func LocalFree(ptr uintptr) { return } +func NtQueryInformationProcess(processHandle windows.Handle, processInfoClass uint32, processInfo unsafe.Pointer, processInfoLength uint32, returnLength *uint32) (status uint32) { + r0, _, _ := syscall.Syscall6(procNtQueryInformationProcess.Addr(), 5, uintptr(processHandle), uintptr(processInfoClass), uintptr(processInfo), uintptr(processInfoLength), uintptr(unsafe.Pointer(returnLength)), 0) + status = uint32(r0) + return +} + func GetActiveProcessorCount(groupNumber uint16) (amount uint32) { r0, _, _ := syscall.Syscall(procGetActiveProcessorCount.Addr(), 1, uintptr(groupNumber), 0, 0) amount = uint32(r0) diff --git a/vendor/github.com/PuerkitoBio/purell/.gitignore b/vendor/github.com/PuerkitoBio/purell/.gitignore deleted file mode 100644 index 748e4c8073..0000000000 --- a/vendor/github.com/PuerkitoBio/purell/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -*.sublime-* -.DS_Store -*.swp -*.swo -tags diff --git a/vendor/github.com/PuerkitoBio/purell/.travis.yml b/vendor/github.com/PuerkitoBio/purell/.travis.yml deleted file mode 100644 index cf31e6af6d..0000000000 --- a/vendor/github.com/PuerkitoBio/purell/.travis.yml +++ /dev/null @@ -1,12 +0,0 @@ -language: go - -go: - - 1.4.x - - 1.5.x - - 1.6.x - - 1.7.x - - 1.8.x - - 1.9.x - - "1.10.x" - - "1.11.x" - - tip diff --git a/vendor/github.com/PuerkitoBio/purell/LICENSE b/vendor/github.com/PuerkitoBio/purell/LICENSE deleted file mode 100644 index 4b9986dea7..0000000000 --- a/vendor/github.com/PuerkitoBio/purell/LICENSE +++ /dev/null @@ -1,12 +0,0 @@ -Copyright (c) 2012, Martin Angers -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -* Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/PuerkitoBio/purell/README.md b/vendor/github.com/PuerkitoBio/purell/README.md deleted file mode 100644 index 07de0c4986..0000000000 --- a/vendor/github.com/PuerkitoBio/purell/README.md +++ /dev/null @@ -1,188 +0,0 @@ -# Purell - -Purell is a tiny Go library to normalize URLs. It returns a pure URL. Pure-ell. Sanitizer and all. Yeah, I know... - -Based on the [wikipedia paper][wiki] and the [RFC 3986 document][rfc]. - -[![build status](https://travis-ci.org/PuerkitoBio/purell.svg?branch=master)](http://travis-ci.org/PuerkitoBio/purell) - -## Install - -`go get github.com/PuerkitoBio/purell` - -## Changelog - -* **v1.1.1** : Fix failing test due to Go1.12 changes (thanks to @ianlancetaylor). -* **2016-11-14 (v1.1.0)** : IDN: Conform to RFC 5895: Fold character width (thanks to @beeker1121). -* **2016-07-27 (v1.0.0)** : Normalize IDN to ASCII (thanks to @zenovich). -* **2015-02-08** : Add fix for relative paths issue ([PR #5][pr5]) and add fix for unnecessary encoding of reserved characters ([see issue #7][iss7]). -* **v0.2.0** : Add benchmarks, Attempt IDN support. -* **v0.1.0** : Initial release. - -## Examples - -From `example_test.go` (note that in your code, you would import "github.com/PuerkitoBio/purell", and would prefix references to its methods and constants with "purell."): - -```go -package purell - -import ( - "fmt" - "net/url" -) - -func ExampleNormalizeURLString() { - if normalized, err := NormalizeURLString("hTTp://someWEBsite.com:80/Amazing%3f/url/", - FlagLowercaseScheme|FlagLowercaseHost|FlagUppercaseEscapes); err != nil { - panic(err) - } else { - fmt.Print(normalized) - } - // Output: http://somewebsite.com:80/Amazing%3F/url/ -} - -func ExampleMustNormalizeURLString() { - normalized := MustNormalizeURLString("hTTpS://someWEBsite.com:443/Amazing%fa/url/", - FlagsUnsafeGreedy) - fmt.Print(normalized) - - // Output: http://somewebsite.com/Amazing%FA/url -} - -func ExampleNormalizeURL() { - if u, err := url.Parse("Http://SomeUrl.com:8080/a/b/.././c///g?c=3&a=1&b=9&c=0#target"); err != nil { - panic(err) - } else { - normalized := NormalizeURL(u, FlagsUsuallySafeGreedy|FlagRemoveDuplicateSlashes|FlagRemoveFragment) - fmt.Print(normalized) - } - - // Output: http://someurl.com:8080/a/c/g?c=3&a=1&b=9&c=0 -} -``` - -## API - -As seen in the examples above, purell offers three methods, `NormalizeURLString(string, NormalizationFlags) (string, error)`, `MustNormalizeURLString(string, NormalizationFlags) (string)` and `NormalizeURL(*url.URL, NormalizationFlags) (string)`. They all normalize the provided URL based on the specified flags. Here are the available flags: - -```go -const ( - // Safe normalizations - FlagLowercaseScheme NormalizationFlags = 1 << iota // HTTP://host -> http://host, applied by default in Go1.1 - FlagLowercaseHost // http://HOST -> http://host - FlagUppercaseEscapes // http://host/t%ef -> http://host/t%EF - FlagDecodeUnnecessaryEscapes // http://host/t%41 -> http://host/tA - FlagEncodeNecessaryEscapes // http://host/!"#$ -> http://host/%21%22#$ - FlagRemoveDefaultPort // http://host:80 -> http://host - FlagRemoveEmptyQuerySeparator // http://host/path? -> http://host/path - - // Usually safe normalizations - FlagRemoveTrailingSlash // http://host/path/ -> http://host/path - FlagAddTrailingSlash // http://host/path -> http://host/path/ (should choose only one of these add/remove trailing slash flags) - FlagRemoveDotSegments // http://host/path/./a/b/../c -> http://host/path/a/c - - // Unsafe normalizations - FlagRemoveDirectoryIndex // http://host/path/index.html -> http://host/path/ - FlagRemoveFragment // http://host/path#fragment -> http://host/path - FlagForceHTTP // https://host -> http://host - FlagRemoveDuplicateSlashes // http://host/path//a///b -> http://host/path/a/b - FlagRemoveWWW // http://www.host/ -> http://host/ - FlagAddWWW // http://host/ -> http://www.host/ (should choose only one of these add/remove WWW flags) - FlagSortQuery // http://host/path?c=3&b=2&a=1&b=1 -> http://host/path?a=1&b=1&b=2&c=3 - - // Normalizations not in the wikipedia article, required to cover tests cases - // submitted by jehiah - FlagDecodeDWORDHost // http://1113982867 -> http://66.102.7.147 - FlagDecodeOctalHost // http://0102.0146.07.0223 -> http://66.102.7.147 - FlagDecodeHexHost // http://0x42660793 -> http://66.102.7.147 - FlagRemoveUnnecessaryHostDots // http://.host../path -> http://host/path - FlagRemoveEmptyPortSeparator // http://host:/path -> http://host/path - - // Convenience set of safe normalizations - FlagsSafe NormalizationFlags = FlagLowercaseHost | FlagLowercaseScheme | FlagUppercaseEscapes | FlagDecodeUnnecessaryEscapes | FlagEncodeNecessaryEscapes | FlagRemoveDefaultPort | FlagRemoveEmptyQuerySeparator - - // For convenience sets, "greedy" uses the "remove trailing slash" and "remove www. prefix" flags, - // while "non-greedy" uses the "add (or keep) the trailing slash" and "add www. prefix". - - // Convenience set of usually safe normalizations (includes FlagsSafe) - FlagsUsuallySafeGreedy NormalizationFlags = FlagsSafe | FlagRemoveTrailingSlash | FlagRemoveDotSegments - FlagsUsuallySafeNonGreedy NormalizationFlags = FlagsSafe | FlagAddTrailingSlash | FlagRemoveDotSegments - - // Convenience set of unsafe normalizations (includes FlagsUsuallySafe) - FlagsUnsafeGreedy NormalizationFlags = FlagsUsuallySafeGreedy | FlagRemoveDirectoryIndex | FlagRemoveFragment | FlagForceHTTP | FlagRemoveDuplicateSlashes | FlagRemoveWWW | FlagSortQuery - FlagsUnsafeNonGreedy NormalizationFlags = FlagsUsuallySafeNonGreedy | FlagRemoveDirectoryIndex | FlagRemoveFragment | FlagForceHTTP | FlagRemoveDuplicateSlashes | FlagAddWWW | FlagSortQuery - - // Convenience set of all available flags - FlagsAllGreedy = FlagsUnsafeGreedy | FlagDecodeDWORDHost | FlagDecodeOctalHost | FlagDecodeHexHost | FlagRemoveUnnecessaryHostDots | FlagRemoveEmptyPortSeparator - FlagsAllNonGreedy = FlagsUnsafeNonGreedy | FlagDecodeDWORDHost | FlagDecodeOctalHost | FlagDecodeHexHost | FlagRemoveUnnecessaryHostDots | FlagRemoveEmptyPortSeparator -) -``` - -For convenience, the set of flags `FlagsSafe`, `FlagsUsuallySafe[Greedy|NonGreedy]`, `FlagsUnsafe[Greedy|NonGreedy]` and `FlagsAll[Greedy|NonGreedy]` are provided for the similarly grouped normalizations on [wikipedia's URL normalization page][wiki]. You can add (using the bitwise OR `|` operator) or remove (using the bitwise AND NOT `&^` operator) individual flags from the sets if required, to build your own custom set. - -The [full godoc reference is available on gopkgdoc][godoc]. - -Some things to note: - -* `FlagDecodeUnnecessaryEscapes`, `FlagEncodeNecessaryEscapes`, `FlagUppercaseEscapes` and `FlagRemoveEmptyQuerySeparator` are always implicitly set, because internally, the URL string is parsed as an URL object, which automatically decodes unnecessary escapes, uppercases and encodes necessary ones, and removes empty query separators (an unnecessary `?` at the end of the url). So this operation cannot **not** be done. For this reason, `FlagRemoveEmptyQuerySeparator` (as well as the other three) has been included in the `FlagsSafe` convenience set, instead of `FlagsUnsafe`, where Wikipedia puts it. - -* The `FlagDecodeUnnecessaryEscapes` decodes the following escapes (*from -> to*): - - %24 -> $ - - %26 -> & - - %2B-%3B -> +,-./0123456789:; - - %3D -> = - - %40-%5A -> @ABCDEFGHIJKLMNOPQRSTUVWXYZ - - %5F -> _ - - %61-%7A -> abcdefghijklmnopqrstuvwxyz - - %7E -> ~ - - -* When the `NormalizeURL` function is used (passing an URL object), this source URL object is modified (that is, after the call, the URL object will be modified to reflect the normalization). - -* The *replace IP with domain name* normalization (`http://208.77.188.166/ → http://www.example.com/`) is obviously not possible for a library without making some network requests. This is not implemented in purell. - -* The *remove unused query string parameters* and *remove default query parameters* are also not implemented, since this is a very case-specific normalization, and it is quite trivial to do with an URL object. - -### Safe vs Usually Safe vs Unsafe - -Purell allows you to control the level of risk you take while normalizing an URL. You can aggressively normalize, play it totally safe, or anything in between. - -Consider the following URL: - -`HTTPS://www.RooT.com/toto/t%45%1f///a/./b/../c/?z=3&w=2&a=4&w=1#invalid` - -Normalizing with the `FlagsSafe` gives: - -`https://www.root.com/toto/tE%1F///a/./b/../c/?z=3&w=2&a=4&w=1#invalid` - -With the `FlagsUsuallySafeGreedy`: - -`https://www.root.com/toto/tE%1F///a/c?z=3&w=2&a=4&w=1#invalid` - -And with `FlagsUnsafeGreedy`: - -`http://root.com/toto/tE%1F/a/c?a=4&w=1&w=2&z=3` - -## TODOs - -* Add a class/default instance to allow specifying custom directory index names? At the moment, removing directory index removes `(^|/)((?:default|index)\.\w{1,4})$`. - -## Thanks / Contributions - -@rogpeppe -@jehiah -@opennota -@pchristopher1275 -@zenovich -@beeker1121 - -## License - -The [BSD 3-Clause license][bsd]. - -[bsd]: http://opensource.org/licenses/BSD-3-Clause -[wiki]: http://en.wikipedia.org/wiki/URL_normalization -[rfc]: http://tools.ietf.org/html/rfc3986#section-6 -[godoc]: http://go.pkgdoc.org/github.com/PuerkitoBio/purell -[pr5]: https://github.com/PuerkitoBio/purell/pull/5 -[iss7]: https://github.com/PuerkitoBio/purell/issues/7 diff --git a/vendor/github.com/PuerkitoBio/purell/purell.go b/vendor/github.com/PuerkitoBio/purell/purell.go deleted file mode 100644 index 6d0fc190a1..0000000000 --- a/vendor/github.com/PuerkitoBio/purell/purell.go +++ /dev/null @@ -1,379 +0,0 @@ -/* -Package purell offers URL normalization as described on the wikipedia page: -http://en.wikipedia.org/wiki/URL_normalization -*/ -package purell - -import ( - "bytes" - "fmt" - "net/url" - "regexp" - "sort" - "strconv" - "strings" - - "github.com/PuerkitoBio/urlesc" - "golang.org/x/net/idna" - "golang.org/x/text/unicode/norm" - "golang.org/x/text/width" -) - -// A set of normalization flags determines how a URL will -// be normalized. -type NormalizationFlags uint - -const ( - // Safe normalizations - FlagLowercaseScheme NormalizationFlags = 1 << iota // HTTP://host -> http://host, applied by default in Go1.1 - FlagLowercaseHost // http://HOST -> http://host - FlagUppercaseEscapes // http://host/t%ef -> http://host/t%EF - FlagDecodeUnnecessaryEscapes // http://host/t%41 -> http://host/tA - FlagEncodeNecessaryEscapes // http://host/!"#$ -> http://host/%21%22#$ - FlagRemoveDefaultPort // http://host:80 -> http://host - FlagRemoveEmptyQuerySeparator // http://host/path? -> http://host/path - - // Usually safe normalizations - FlagRemoveTrailingSlash // http://host/path/ -> http://host/path - FlagAddTrailingSlash // http://host/path -> http://host/path/ (should choose only one of these add/remove trailing slash flags) - FlagRemoveDotSegments // http://host/path/./a/b/../c -> http://host/path/a/c - - // Unsafe normalizations - FlagRemoveDirectoryIndex // http://host/path/index.html -> http://host/path/ - FlagRemoveFragment // http://host/path#fragment -> http://host/path - FlagForceHTTP // https://host -> http://host - FlagRemoveDuplicateSlashes // http://host/path//a///b -> http://host/path/a/b - FlagRemoveWWW // http://www.host/ -> http://host/ - FlagAddWWW // http://host/ -> http://www.host/ (should choose only one of these add/remove WWW flags) - FlagSortQuery // http://host/path?c=3&b=2&a=1&b=1 -> http://host/path?a=1&b=1&b=2&c=3 - - // Normalizations not in the wikipedia article, required to cover tests cases - // submitted by jehiah - FlagDecodeDWORDHost // http://1113982867 -> http://66.102.7.147 - FlagDecodeOctalHost // http://0102.0146.07.0223 -> http://66.102.7.147 - FlagDecodeHexHost // http://0x42660793 -> http://66.102.7.147 - FlagRemoveUnnecessaryHostDots // http://.host../path -> http://host/path - FlagRemoveEmptyPortSeparator // http://host:/path -> http://host/path - - // Convenience set of safe normalizations - FlagsSafe NormalizationFlags = FlagLowercaseHost | FlagLowercaseScheme | FlagUppercaseEscapes | FlagDecodeUnnecessaryEscapes | FlagEncodeNecessaryEscapes | FlagRemoveDefaultPort | FlagRemoveEmptyQuerySeparator - - // For convenience sets, "greedy" uses the "remove trailing slash" and "remove www. prefix" flags, - // while "non-greedy" uses the "add (or keep) the trailing slash" and "add www. prefix". - - // Convenience set of usually safe normalizations (includes FlagsSafe) - FlagsUsuallySafeGreedy NormalizationFlags = FlagsSafe | FlagRemoveTrailingSlash | FlagRemoveDotSegments - FlagsUsuallySafeNonGreedy NormalizationFlags = FlagsSafe | FlagAddTrailingSlash | FlagRemoveDotSegments - - // Convenience set of unsafe normalizations (includes FlagsUsuallySafe) - FlagsUnsafeGreedy NormalizationFlags = FlagsUsuallySafeGreedy | FlagRemoveDirectoryIndex | FlagRemoveFragment | FlagForceHTTP | FlagRemoveDuplicateSlashes | FlagRemoveWWW | FlagSortQuery - FlagsUnsafeNonGreedy NormalizationFlags = FlagsUsuallySafeNonGreedy | FlagRemoveDirectoryIndex | FlagRemoveFragment | FlagForceHTTP | FlagRemoveDuplicateSlashes | FlagAddWWW | FlagSortQuery - - // Convenience set of all available flags - FlagsAllGreedy = FlagsUnsafeGreedy | FlagDecodeDWORDHost | FlagDecodeOctalHost | FlagDecodeHexHost | FlagRemoveUnnecessaryHostDots | FlagRemoveEmptyPortSeparator - FlagsAllNonGreedy = FlagsUnsafeNonGreedy | FlagDecodeDWORDHost | FlagDecodeOctalHost | FlagDecodeHexHost | FlagRemoveUnnecessaryHostDots | FlagRemoveEmptyPortSeparator -) - -const ( - defaultHttpPort = ":80" - defaultHttpsPort = ":443" -) - -// Regular expressions used by the normalizations -var rxPort = regexp.MustCompile(`(:\d+)/?$`) -var rxDirIndex = regexp.MustCompile(`(^|/)((?:default|index)\.\w{1,4})$`) -var rxDupSlashes = regexp.MustCompile(`/{2,}`) -var rxDWORDHost = regexp.MustCompile(`^(\d+)((?:\.+)?(?:\:\d*)?)$`) -var rxOctalHost = regexp.MustCompile(`^(0\d*)\.(0\d*)\.(0\d*)\.(0\d*)((?:\.+)?(?:\:\d*)?)$`) -var rxHexHost = regexp.MustCompile(`^0x([0-9A-Fa-f]+)((?:\.+)?(?:\:\d*)?)$`) -var rxHostDots = regexp.MustCompile(`^(.+?)(:\d+)?$`) -var rxEmptyPort = regexp.MustCompile(`:+$`) - -// Map of flags to implementation function. -// FlagDecodeUnnecessaryEscapes has no action, since it is done automatically -// by parsing the string as an URL. Same for FlagUppercaseEscapes and FlagRemoveEmptyQuerySeparator. - -// Since maps have undefined traversing order, make a slice of ordered keys -var flagsOrder = []NormalizationFlags{ - FlagLowercaseScheme, - FlagLowercaseHost, - FlagRemoveDefaultPort, - FlagRemoveDirectoryIndex, - FlagRemoveDotSegments, - FlagRemoveFragment, - FlagForceHTTP, // Must be after remove default port (because https=443/http=80) - FlagRemoveDuplicateSlashes, - FlagRemoveWWW, - FlagAddWWW, - FlagSortQuery, - FlagDecodeDWORDHost, - FlagDecodeOctalHost, - FlagDecodeHexHost, - FlagRemoveUnnecessaryHostDots, - FlagRemoveEmptyPortSeparator, - FlagRemoveTrailingSlash, // These two (add/remove trailing slash) must be last - FlagAddTrailingSlash, -} - -// ... and then the map, where order is unimportant -var flags = map[NormalizationFlags]func(*url.URL){ - FlagLowercaseScheme: lowercaseScheme, - FlagLowercaseHost: lowercaseHost, - FlagRemoveDefaultPort: removeDefaultPort, - FlagRemoveDirectoryIndex: removeDirectoryIndex, - FlagRemoveDotSegments: removeDotSegments, - FlagRemoveFragment: removeFragment, - FlagForceHTTP: forceHTTP, - FlagRemoveDuplicateSlashes: removeDuplicateSlashes, - FlagRemoveWWW: removeWWW, - FlagAddWWW: addWWW, - FlagSortQuery: sortQuery, - FlagDecodeDWORDHost: decodeDWORDHost, - FlagDecodeOctalHost: decodeOctalHost, - FlagDecodeHexHost: decodeHexHost, - FlagRemoveUnnecessaryHostDots: removeUnncessaryHostDots, - FlagRemoveEmptyPortSeparator: removeEmptyPortSeparator, - FlagRemoveTrailingSlash: removeTrailingSlash, - FlagAddTrailingSlash: addTrailingSlash, -} - -// MustNormalizeURLString returns the normalized string, and panics if an error occurs. -// It takes an URL string as input, as well as the normalization flags. -func MustNormalizeURLString(u string, f NormalizationFlags) string { - result, e := NormalizeURLString(u, f) - if e != nil { - panic(e) - } - return result -} - -// NormalizeURLString returns the normalized string, or an error if it can't be parsed into an URL object. -// It takes an URL string as input, as well as the normalization flags. -func NormalizeURLString(u string, f NormalizationFlags) (string, error) { - parsed, err := url.Parse(u) - if err != nil { - return "", err - } - - if f&FlagLowercaseHost == FlagLowercaseHost { - parsed.Host = strings.ToLower(parsed.Host) - } - - // The idna package doesn't fully conform to RFC 5895 - // (https://tools.ietf.org/html/rfc5895), so we do it here. - // Taken from Go 1.8 cycle source, courtesy of bradfitz. - // TODO: Remove when (if?) idna package conforms to RFC 5895. - parsed.Host = width.Fold.String(parsed.Host) - parsed.Host = norm.NFC.String(parsed.Host) - if parsed.Host, err = idna.ToASCII(parsed.Host); err != nil { - return "", err - } - - return NormalizeURL(parsed, f), nil -} - -// NormalizeURL returns the normalized string. -// It takes a parsed URL object as input, as well as the normalization flags. -func NormalizeURL(u *url.URL, f NormalizationFlags) string { - for _, k := range flagsOrder { - if f&k == k { - flags[k](u) - } - } - return urlesc.Escape(u) -} - -func lowercaseScheme(u *url.URL) { - if len(u.Scheme) > 0 { - u.Scheme = strings.ToLower(u.Scheme) - } -} - -func lowercaseHost(u *url.URL) { - if len(u.Host) > 0 { - u.Host = strings.ToLower(u.Host) - } -} - -func removeDefaultPort(u *url.URL) { - if len(u.Host) > 0 { - scheme := strings.ToLower(u.Scheme) - u.Host = rxPort.ReplaceAllStringFunc(u.Host, func(val string) string { - if (scheme == "http" && val == defaultHttpPort) || (scheme == "https" && val == defaultHttpsPort) { - return "" - } - return val - }) - } -} - -func removeTrailingSlash(u *url.URL) { - if l := len(u.Path); l > 0 { - if strings.HasSuffix(u.Path, "/") { - u.Path = u.Path[:l-1] - } - } else if l = len(u.Host); l > 0 { - if strings.HasSuffix(u.Host, "/") { - u.Host = u.Host[:l-1] - } - } -} - -func addTrailingSlash(u *url.URL) { - if l := len(u.Path); l > 0 { - if !strings.HasSuffix(u.Path, "/") { - u.Path += "/" - } - } else if l = len(u.Host); l > 0 { - if !strings.HasSuffix(u.Host, "/") { - u.Host += "/" - } - } -} - -func removeDotSegments(u *url.URL) { - if len(u.Path) > 0 { - var dotFree []string - var lastIsDot bool - - sections := strings.Split(u.Path, "/") - for _, s := range sections { - if s == ".." { - if len(dotFree) > 0 { - dotFree = dotFree[:len(dotFree)-1] - } - } else if s != "." { - dotFree = append(dotFree, s) - } - lastIsDot = (s == "." || s == "..") - } - // Special case if host does not end with / and new path does not begin with / - u.Path = strings.Join(dotFree, "/") - if u.Host != "" && !strings.HasSuffix(u.Host, "/") && !strings.HasPrefix(u.Path, "/") { - u.Path = "/" + u.Path - } - // Special case if the last segment was a dot, make sure the path ends with a slash - if lastIsDot && !strings.HasSuffix(u.Path, "/") { - u.Path += "/" - } - } -} - -func removeDirectoryIndex(u *url.URL) { - if len(u.Path) > 0 { - u.Path = rxDirIndex.ReplaceAllString(u.Path, "$1") - } -} - -func removeFragment(u *url.URL) { - u.Fragment = "" -} - -func forceHTTP(u *url.URL) { - if strings.ToLower(u.Scheme) == "https" { - u.Scheme = "http" - } -} - -func removeDuplicateSlashes(u *url.URL) { - if len(u.Path) > 0 { - u.Path = rxDupSlashes.ReplaceAllString(u.Path, "/") - } -} - -func removeWWW(u *url.URL) { - if len(u.Host) > 0 && strings.HasPrefix(strings.ToLower(u.Host), "www.") { - u.Host = u.Host[4:] - } -} - -func addWWW(u *url.URL) { - if len(u.Host) > 0 && !strings.HasPrefix(strings.ToLower(u.Host), "www.") { - u.Host = "www." + u.Host - } -} - -func sortQuery(u *url.URL) { - q := u.Query() - - if len(q) > 0 { - arKeys := make([]string, len(q)) - i := 0 - for k := range q { - arKeys[i] = k - i++ - } - sort.Strings(arKeys) - buf := new(bytes.Buffer) - for _, k := range arKeys { - sort.Strings(q[k]) - for _, v := range q[k] { - if buf.Len() > 0 { - buf.WriteRune('&') - } - buf.WriteString(fmt.Sprintf("%s=%s", k, urlesc.QueryEscape(v))) - } - } - - // Rebuild the raw query string - u.RawQuery = buf.String() - } -} - -func decodeDWORDHost(u *url.URL) { - if len(u.Host) > 0 { - if matches := rxDWORDHost.FindStringSubmatch(u.Host); len(matches) > 2 { - var parts [4]int64 - - dword, _ := strconv.ParseInt(matches[1], 10, 0) - for i, shift := range []uint{24, 16, 8, 0} { - parts[i] = dword >> shift & 0xFF - } - u.Host = fmt.Sprintf("%d.%d.%d.%d%s", parts[0], parts[1], parts[2], parts[3], matches[2]) - } - } -} - -func decodeOctalHost(u *url.URL) { - if len(u.Host) > 0 { - if matches := rxOctalHost.FindStringSubmatch(u.Host); len(matches) > 5 { - var parts [4]int64 - - for i := 1; i <= 4; i++ { - parts[i-1], _ = strconv.ParseInt(matches[i], 8, 0) - } - u.Host = fmt.Sprintf("%d.%d.%d.%d%s", parts[0], parts[1], parts[2], parts[3], matches[5]) - } - } -} - -func decodeHexHost(u *url.URL) { - if len(u.Host) > 0 { - if matches := rxHexHost.FindStringSubmatch(u.Host); len(matches) > 2 { - // Conversion is safe because of regex validation - parsed, _ := strconv.ParseInt(matches[1], 16, 0) - // Set host as DWORD (base 10) encoded host - u.Host = fmt.Sprintf("%d%s", parsed, matches[2]) - // The rest is the same as decoding a DWORD host - decodeDWORDHost(u) - } - } -} - -func removeUnncessaryHostDots(u *url.URL) { - if len(u.Host) > 0 { - if matches := rxHostDots.FindStringSubmatch(u.Host); len(matches) > 1 { - // Trim the leading and trailing dots - u.Host = strings.Trim(matches[1], ".") - if len(matches) > 2 { - u.Host += matches[2] - } - } - } -} - -func removeEmptyPortSeparator(u *url.URL) { - if len(u.Host) > 0 { - u.Host = rxEmptyPort.ReplaceAllString(u.Host, "") - } -} diff --git a/vendor/github.com/PuerkitoBio/urlesc/.travis.yml b/vendor/github.com/PuerkitoBio/urlesc/.travis.yml deleted file mode 100644 index ba6b225f91..0000000000 --- a/vendor/github.com/PuerkitoBio/urlesc/.travis.yml +++ /dev/null @@ -1,15 +0,0 @@ -language: go - -go: - - 1.4.x - - 1.5.x - - 1.6.x - - 1.7.x - - 1.8.x - - tip - -install: - - go build . - -script: - - go test -v diff --git a/vendor/github.com/PuerkitoBio/urlesc/LICENSE b/vendor/github.com/PuerkitoBio/urlesc/LICENSE deleted file mode 100644 index 7448756763..0000000000 --- a/vendor/github.com/PuerkitoBio/urlesc/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2012 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/PuerkitoBio/urlesc/README.md b/vendor/github.com/PuerkitoBio/urlesc/README.md deleted file mode 100644 index 57aff0a539..0000000000 --- a/vendor/github.com/PuerkitoBio/urlesc/README.md +++ /dev/null @@ -1,16 +0,0 @@ -urlesc [![Build Status](https://travis-ci.org/PuerkitoBio/urlesc.svg?branch=master)](https://travis-ci.org/PuerkitoBio/urlesc) [![GoDoc](http://godoc.org/github.com/PuerkitoBio/urlesc?status.svg)](http://godoc.org/github.com/PuerkitoBio/urlesc) -====== - -Package urlesc implements query escaping as per RFC 3986. - -It contains some parts of the net/url package, modified so as to allow -some reserved characters incorrectly escaped by net/url (see [issue 5684](https://github.com/golang/go/issues/5684)). - -## Install - - go get github.com/PuerkitoBio/urlesc - -## License - -Go license (BSD-3-Clause) - diff --git a/vendor/github.com/PuerkitoBio/urlesc/urlesc.go b/vendor/github.com/PuerkitoBio/urlesc/urlesc.go deleted file mode 100644 index 1b84624594..0000000000 --- a/vendor/github.com/PuerkitoBio/urlesc/urlesc.go +++ /dev/null @@ -1,180 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package urlesc implements query escaping as per RFC 3986. -// It contains some parts of the net/url package, modified so as to allow -// some reserved characters incorrectly escaped by net/url. -// See https://github.com/golang/go/issues/5684 -package urlesc - -import ( - "bytes" - "net/url" - "strings" -) - -type encoding int - -const ( - encodePath encoding = 1 + iota - encodeUserPassword - encodeQueryComponent - encodeFragment -) - -// Return true if the specified character should be escaped when -// appearing in a URL string, according to RFC 3986. -func shouldEscape(c byte, mode encoding) bool { - // §2.3 Unreserved characters (alphanum) - if 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' { - return false - } - - switch c { - case '-', '.', '_', '~': // §2.3 Unreserved characters (mark) - return false - - // §2.2 Reserved characters (reserved) - case ':', '/', '?', '#', '[', ']', '@', // gen-delims - '!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '=': // sub-delims - // Different sections of the URL allow a few of - // the reserved characters to appear unescaped. - switch mode { - case encodePath: // §3.3 - // The RFC allows sub-delims and : @. - // '/', '[' and ']' can be used to assign meaning to individual path - // segments. This package only manipulates the path as a whole, - // so we allow those as well. That leaves only ? and # to escape. - return c == '?' || c == '#' - - case encodeUserPassword: // §3.2.1 - // The RFC allows : and sub-delims in - // userinfo. The parsing of userinfo treats ':' as special so we must escape - // all the gen-delims. - return c == ':' || c == '/' || c == '?' || c == '#' || c == '[' || c == ']' || c == '@' - - case encodeQueryComponent: // §3.4 - // The RFC allows / and ?. - return c != '/' && c != '?' - - case encodeFragment: // §4.1 - // The RFC text is silent but the grammar allows - // everything, so escape nothing but # - return c == '#' - } - } - - // Everything else must be escaped. - return true -} - -// QueryEscape escapes the string so it can be safely placed -// inside a URL query. -func QueryEscape(s string) string { - return escape(s, encodeQueryComponent) -} - -func escape(s string, mode encoding) string { - spaceCount, hexCount := 0, 0 - for i := 0; i < len(s); i++ { - c := s[i] - if shouldEscape(c, mode) { - if c == ' ' && mode == encodeQueryComponent { - spaceCount++ - } else { - hexCount++ - } - } - } - - if spaceCount == 0 && hexCount == 0 { - return s - } - - t := make([]byte, len(s)+2*hexCount) - j := 0 - for i := 0; i < len(s); i++ { - switch c := s[i]; { - case c == ' ' && mode == encodeQueryComponent: - t[j] = '+' - j++ - case shouldEscape(c, mode): - t[j] = '%' - t[j+1] = "0123456789ABCDEF"[c>>4] - t[j+2] = "0123456789ABCDEF"[c&15] - j += 3 - default: - t[j] = s[i] - j++ - } - } - return string(t) -} - -var uiReplacer = strings.NewReplacer( - "%21", "!", - "%27", "'", - "%28", "(", - "%29", ")", - "%2A", "*", -) - -// unescapeUserinfo unescapes some characters that need not to be escaped as per RFC3986. -func unescapeUserinfo(s string) string { - return uiReplacer.Replace(s) -} - -// Escape reassembles the URL into a valid URL string. -// The general form of the result is one of: -// -// scheme:opaque -// scheme://userinfo@host/path?query#fragment -// -// If u.Opaque is non-empty, String uses the first form; -// otherwise it uses the second form. -// -// In the second form, the following rules apply: -// - if u.Scheme is empty, scheme: is omitted. -// - if u.User is nil, userinfo@ is omitted. -// - if u.Host is empty, host/ is omitted. -// - if u.Scheme and u.Host are empty and u.User is nil, -// the entire scheme://userinfo@host/ is omitted. -// - if u.Host is non-empty and u.Path begins with a /, -// the form host/path does not add its own /. -// - if u.RawQuery is empty, ?query is omitted. -// - if u.Fragment is empty, #fragment is omitted. -func Escape(u *url.URL) string { - var buf bytes.Buffer - if u.Scheme != "" { - buf.WriteString(u.Scheme) - buf.WriteByte(':') - } - if u.Opaque != "" { - buf.WriteString(u.Opaque) - } else { - if u.Scheme != "" || u.Host != "" || u.User != nil { - buf.WriteString("//") - if ui := u.User; ui != nil { - buf.WriteString(unescapeUserinfo(ui.String())) - buf.WriteByte('@') - } - if h := u.Host; h != "" { - buf.WriteString(h) - } - } - if u.Path != "" && u.Path[0] != '/' && u.Host != "" { - buf.WriteByte('/') - } - buf.WriteString(escape(u.Path, encodePath)) - } - if u.RawQuery != "" { - buf.WriteByte('?') - buf.WriteString(u.RawQuery) - } - if u.Fragment != "" { - buf.WriteByte('#') - buf.WriteString(escape(u.Fragment, encodeFragment)) - } - return buf.String() -} diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn.go deleted file mode 100644 index a4e2079e65..0000000000 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn.go +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. -// Use of this file is governed by the BSD 3-clause license that -// can be found in the LICENSE.txt file in the project root. - -package antlr - -import "sync" - -var ATNInvalidAltNumber int - -type ATN struct { - // DecisionToState is the decision points for all rules, subrules, optional - // blocks, ()+, ()*, etc. Used to build DFA predictors for them. - DecisionToState []DecisionState - - // grammarType is the ATN type and is used for deserializing ATNs from strings. - grammarType int - - // lexerActions is referenced by action transitions in the ATN for lexer ATNs. - lexerActions []LexerAction - - // maxTokenType is the maximum value for any symbol recognized by a transition in the ATN. - maxTokenType int - - modeNameToStartState map[string]*TokensStartState - - modeToStartState []*TokensStartState - - // ruleToStartState maps from rule index to starting state number. - ruleToStartState []*RuleStartState - - // ruleToStopState maps from rule index to stop state number. - ruleToStopState []*RuleStopState - - // ruleToTokenType maps the rule index to the resulting token type for lexer - // ATNs. For parser ATNs, it maps the rule index to the generated bypass token - // type if ATNDeserializationOptions.isGenerateRuleBypassTransitions was - // specified, and otherwise is nil. - ruleToTokenType []int - - states []ATNState - - mu sync.Mutex - stateMu sync.RWMutex - edgeMu sync.RWMutex -} - -func NewATN(grammarType int, maxTokenType int) *ATN { - return &ATN{ - grammarType: grammarType, - maxTokenType: maxTokenType, - modeNameToStartState: make(map[string]*TokensStartState), - } -} - -// NextTokensInContext computes the set of valid tokens that can occur starting -// in state s. If ctx is nil, the set of tokens will not include what can follow -// the rule surrounding s. In other words, the set will be restricted to tokens -// reachable staying within the rule of s. -func (a *ATN) NextTokensInContext(s ATNState, ctx RuleContext) *IntervalSet { - return NewLL1Analyzer(a).Look(s, nil, ctx) -} - -// NextTokensNoContext computes the set of valid tokens that can occur starting -// in s and staying in same rule. Token.EPSILON is in set if we reach end of -// rule. -func (a *ATN) NextTokensNoContext(s ATNState) *IntervalSet { - a.mu.Lock() - defer a.mu.Unlock() - iset := s.GetNextTokenWithinRule() - if iset == nil { - iset = a.NextTokensInContext(s, nil) - iset.readOnly = true - s.SetNextTokenWithinRule(iset) - } - return iset -} - -func (a *ATN) NextTokens(s ATNState, ctx RuleContext) *IntervalSet { - if ctx == nil { - return a.NextTokensNoContext(s) - } - - return a.NextTokensInContext(s, ctx) -} - -func (a *ATN) addState(state ATNState) { - if state != nil { - state.SetATN(a) - state.SetStateNumber(len(a.states)) - } - - a.states = append(a.states, state) -} - -func (a *ATN) removeState(state ATNState) { - a.states[state.GetStateNumber()] = nil // Just free the memory; don't shift states in the slice -} - -func (a *ATN) defineDecisionState(s DecisionState) int { - a.DecisionToState = append(a.DecisionToState, s) - s.setDecision(len(a.DecisionToState) - 1) - - return s.getDecision() -} - -func (a *ATN) getDecisionState(decision int) DecisionState { - if len(a.DecisionToState) == 0 { - return nil - } - - return a.DecisionToState[decision] -} - -// getExpectedTokens computes the set of input symbols which could follow ATN -// state number stateNumber in the specified full parse context ctx and returns -// the set of potentially valid input symbols which could follow the specified -// state in the specified context. This method considers the complete parser -// context, but does not evaluate semantic predicates (i.e. all predicates -// encountered during the calculation are assumed true). If a path in the ATN -// exists from the starting state to the RuleStopState of the outermost context -// without Matching any symbols, Token.EOF is added to the returned set. -// -// A nil ctx defaults to ParserRuleContext.EMPTY. -// -// It panics if the ATN does not contain state stateNumber. -func (a *ATN) getExpectedTokens(stateNumber int, ctx RuleContext) *IntervalSet { - if stateNumber < 0 || stateNumber >= len(a.states) { - panic("Invalid state number.") - } - - s := a.states[stateNumber] - following := a.NextTokens(s, nil) - - if !following.contains(TokenEpsilon) { - return following - } - - expected := NewIntervalSet() - - expected.addSet(following) - expected.removeOne(TokenEpsilon) - - for ctx != nil && ctx.GetInvokingState() >= 0 && following.contains(TokenEpsilon) { - invokingState := a.states[ctx.GetInvokingState()] - rt := invokingState.GetTransitions()[0] - - following = a.NextTokens(rt.(*RuleTransition).followState, nil) - expected.addSet(following) - expected.removeOne(TokenEpsilon) - ctx = ctx.GetParent().(RuleContext) - } - - if following.contains(TokenEpsilon) { - expected.addOne(TokenEOF) - } - - return expected -} diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/errors.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/errors.go deleted file mode 100644 index 2ef74926ec..0000000000 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/errors.go +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. -// Use of this file is governed by the BSD 3-clause license that -// can be found in the LICENSE.txt file in the project root. - -package antlr - -// The root of the ANTLR exception hierarchy. In general, ANTLR tracks just -// 3 kinds of errors: prediction errors, failed predicate errors, and -// mismatched input errors. In each case, the parser knows where it is -// in the input, where it is in the ATN, the rule invocation stack, -// and what kind of problem occurred. - -type RecognitionException interface { - GetOffendingToken() Token - GetMessage() string - GetInputStream() IntStream -} - -type BaseRecognitionException struct { - message string - recognizer Recognizer - offendingToken Token - offendingState int - ctx RuleContext - input IntStream -} - -func NewBaseRecognitionException(message string, recognizer Recognizer, input IntStream, ctx RuleContext) *BaseRecognitionException { - - // todo - // Error.call(this) - // - // if (!!Error.captureStackTrace) { - // Error.captureStackTrace(this, RecognitionException) - // } else { - // stack := NewError().stack - // } - // TODO may be able to use - "runtime" func Stack(buf []byte, all bool) int - - t := new(BaseRecognitionException) - - t.message = message - t.recognizer = recognizer - t.input = input - t.ctx = ctx - // The current {@link Token} when an error occurred. Since not all streams - // support accessing symbols by index, we have to track the {@link Token} - // instance itself. - t.offendingToken = nil - // Get the ATN state number the parser was in at the time the error - // occurred. For {@link NoViableAltException} and - // {@link LexerNoViableAltException} exceptions, this is the - // {@link DecisionState} number. For others, it is the state whose outgoing - // edge we couldn't Match. - t.offendingState = -1 - if t.recognizer != nil { - t.offendingState = t.recognizer.GetState() - } - - return t -} - -func (b *BaseRecognitionException) GetMessage() string { - return b.message -} - -func (b *BaseRecognitionException) GetOffendingToken() Token { - return b.offendingToken -} - -func (b *BaseRecognitionException) GetInputStream() IntStream { - return b.input -} - -//

If the state number is not known, b method returns -1.

- -// -// Gets the set of input symbols which could potentially follow the -// previously Matched symbol at the time b exception was panicn. -// -//

If the set of expected tokens is not known and could not be computed, -// b method returns {@code nil}.

-// -// @return The set of token types that could potentially follow the current -// state in the ATN, or {@code nil} if the information is not available. -// / -func (b *BaseRecognitionException) getExpectedTokens() *IntervalSet { - if b.recognizer != nil { - return b.recognizer.GetATN().getExpectedTokens(b.offendingState, b.ctx) - } - - return nil -} - -func (b *BaseRecognitionException) String() string { - return b.message -} - -type LexerNoViableAltException struct { - *BaseRecognitionException - - startIndex int - deadEndConfigs ATNConfigSet -} - -func NewLexerNoViableAltException(lexer Lexer, input CharStream, startIndex int, deadEndConfigs ATNConfigSet) *LexerNoViableAltException { - - l := new(LexerNoViableAltException) - - l.BaseRecognitionException = NewBaseRecognitionException("", lexer, input, nil) - - l.startIndex = startIndex - l.deadEndConfigs = deadEndConfigs - - return l -} - -func (l *LexerNoViableAltException) String() string { - symbol := "" - if l.startIndex >= 0 && l.startIndex < l.input.Size() { - symbol = l.input.(CharStream).GetTextFromInterval(NewInterval(l.startIndex, l.startIndex)) - } - return "LexerNoViableAltException" + symbol -} - -type NoViableAltException struct { - *BaseRecognitionException - - startToken Token - offendingToken Token - ctx ParserRuleContext - deadEndConfigs ATNConfigSet -} - -// Indicates that the parser could not decide which of two or more paths -// to take based upon the remaining input. It tracks the starting token -// of the offending input and also knows where the parser was -// in the various paths when the error. Reported by ReportNoViableAlternative() -// -func NewNoViableAltException(recognizer Parser, input TokenStream, startToken Token, offendingToken Token, deadEndConfigs ATNConfigSet, ctx ParserRuleContext) *NoViableAltException { - - if ctx == nil { - ctx = recognizer.GetParserRuleContext() - } - - if offendingToken == nil { - offendingToken = recognizer.GetCurrentToken() - } - - if startToken == nil { - startToken = recognizer.GetCurrentToken() - } - - if input == nil { - input = recognizer.GetInputStream().(TokenStream) - } - - n := new(NoViableAltException) - n.BaseRecognitionException = NewBaseRecognitionException("", recognizer, input, ctx) - - // Which configurations did we try at input.Index() that couldn't Match - // input.LT(1)?// - n.deadEndConfigs = deadEndConfigs - // The token object at the start index the input stream might - // not be buffering tokens so get a reference to it. (At the - // time the error occurred, of course the stream needs to keep a - // buffer all of the tokens but later we might not have access to those.) - n.startToken = startToken - n.offendingToken = offendingToken - - return n -} - -type InputMisMatchException struct { - *BaseRecognitionException -} - -// This signifies any kind of mismatched input exceptions such as -// when the current input does not Match the expected token. -// -func NewInputMisMatchException(recognizer Parser) *InputMisMatchException { - - i := new(InputMisMatchException) - i.BaseRecognitionException = NewBaseRecognitionException("", recognizer, recognizer.GetInputStream(), recognizer.GetParserRuleContext()) - - i.offendingToken = recognizer.GetCurrentToken() - - return i - -} - -// A semantic predicate failed during validation. Validation of predicates -// occurs when normally parsing the alternative just like Matching a token. -// Disambiguating predicate evaluation occurs when we test a predicate during -// prediction. - -type FailedPredicateException struct { - *BaseRecognitionException - - ruleIndex int - predicateIndex int - predicate string -} - -func NewFailedPredicateException(recognizer Parser, predicate string, message string) *FailedPredicateException { - - f := new(FailedPredicateException) - - f.BaseRecognitionException = NewBaseRecognitionException(f.formatMessage(predicate, message), recognizer, recognizer.GetInputStream(), recognizer.GetParserRuleContext()) - - s := recognizer.GetInterpreter().atn.states[recognizer.GetState()] - trans := s.GetTransitions()[0] - if trans2, ok := trans.(*PredicateTransition); ok { - f.ruleIndex = trans2.ruleIndex - f.predicateIndex = trans2.predIndex - } else { - f.ruleIndex = 0 - f.predicateIndex = 0 - } - f.predicate = predicate - f.offendingToken = recognizer.GetCurrentToken() - - return f -} - -func (f *FailedPredicateException) formatMessage(predicate, message string) string { - if message != "" { - return message - } - - return "failed predicate: {" + predicate + "}?" -} - -type ParseCancellationException struct { -} - -func NewParseCancellationException() *ParseCancellationException { - // Error.call(this) - // Error.captureStackTrace(this, ParseCancellationException) - return new(ParseCancellationException) -} diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/parser.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/parser.go deleted file mode 100644 index 2ab2f56052..0000000000 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/parser.go +++ /dev/null @@ -1,718 +0,0 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. -// Use of this file is governed by the BSD 3-clause license that -// can be found in the LICENSE.txt file in the project root. - -package antlr - -import ( - "fmt" - "strconv" -) - -type Parser interface { - Recognizer - - GetInterpreter() *ParserATNSimulator - - GetTokenStream() TokenStream - GetTokenFactory() TokenFactory - GetParserRuleContext() ParserRuleContext - SetParserRuleContext(ParserRuleContext) - Consume() Token - GetParseListeners() []ParseTreeListener - - GetErrorHandler() ErrorStrategy - SetErrorHandler(ErrorStrategy) - GetInputStream() IntStream - GetCurrentToken() Token - GetExpectedTokens() *IntervalSet - NotifyErrorListeners(string, Token, RecognitionException) - IsExpectedToken(int) bool - GetPrecedence() int - GetRuleInvocationStack(ParserRuleContext) []string -} - -type BaseParser struct { - *BaseRecognizer - - Interpreter *ParserATNSimulator - BuildParseTrees bool - - input TokenStream - errHandler ErrorStrategy - precedenceStack IntStack - ctx ParserRuleContext - - tracer *TraceListener - parseListeners []ParseTreeListener - _SyntaxErrors int -} - -// p.is all the parsing support code essentially most of it is error -// recovery stuff.// -func NewBaseParser(input TokenStream) *BaseParser { - - p := new(BaseParser) - - p.BaseRecognizer = NewBaseRecognizer() - - // The input stream. - p.input = nil - // The error handling strategy for the parser. The default value is a new - // instance of {@link DefaultErrorStrategy}. - p.errHandler = NewDefaultErrorStrategy() - p.precedenceStack = make([]int, 0) - p.precedenceStack.Push(0) - // The {@link ParserRuleContext} object for the currently executing rule. - // p.is always non-nil during the parsing process. - p.ctx = nil - // Specifies whether or not the parser should construct a parse tree during - // the parsing process. The default value is {@code true}. - p.BuildParseTrees = true - // When {@link //setTrace}{@code (true)} is called, a reference to the - // {@link TraceListener} is stored here so it can be easily removed in a - // later call to {@link //setTrace}{@code (false)}. The listener itself is - // implemented as a parser listener so p.field is not directly used by - // other parser methods. - p.tracer = nil - // The list of {@link ParseTreeListener} listeners registered to receive - // events during the parse. - p.parseListeners = nil - // The number of syntax errors Reported during parsing. p.value is - // incremented each time {@link //NotifyErrorListeners} is called. - p._SyntaxErrors = 0 - p.SetInputStream(input) - - return p -} - -// p.field maps from the serialized ATN string to the deserialized {@link -// ATN} with -// bypass alternatives. -// -// @see ATNDeserializationOptions//isGenerateRuleBypassTransitions() -// -var bypassAltsAtnCache = make(map[string]int) - -// reset the parser's state// -func (p *BaseParser) reset() { - if p.input != nil { - p.input.Seek(0) - } - p.errHandler.reset(p) - p.ctx = nil - p._SyntaxErrors = 0 - p.SetTrace(nil) - p.precedenceStack = make([]int, 0) - p.precedenceStack.Push(0) - if p.Interpreter != nil { - p.Interpreter.reset() - } -} - -func (p *BaseParser) GetErrorHandler() ErrorStrategy { - return p.errHandler -} - -func (p *BaseParser) SetErrorHandler(e ErrorStrategy) { - p.errHandler = e -} - -// Match current input symbol against {@code ttype}. If the symbol type -// Matches, {@link ANTLRErrorStrategy//ReportMatch} and {@link //consume} are -// called to complete the Match process. -// -//

If the symbol type does not Match, -// {@link ANTLRErrorStrategy//recoverInline} is called on the current error -// strategy to attempt recovery. If {@link //getBuildParseTree} is -// {@code true} and the token index of the symbol returned by -// {@link ANTLRErrorStrategy//recoverInline} is -1, the symbol is added to -// the parse tree by calling {@link ParserRuleContext//addErrorNode}.

-// -// @param ttype the token type to Match -// @return the Matched symbol -// @panics RecognitionException if the current input symbol did not Match -// {@code ttype} and the error strategy could not recover from the -// mismatched symbol - -func (p *BaseParser) Match(ttype int) Token { - - t := p.GetCurrentToken() - - if t.GetTokenType() == ttype { - p.errHandler.ReportMatch(p) - p.Consume() - } else { - t = p.errHandler.RecoverInline(p) - if p.BuildParseTrees && t.GetTokenIndex() == -1 { - // we must have conjured up a Newtoken during single token - // insertion - // if it's not the current symbol - p.ctx.AddErrorNode(t) - } - } - - return t -} - -// Match current input symbol as a wildcard. If the symbol type Matches -// (i.e. has a value greater than 0), {@link ANTLRErrorStrategy//ReportMatch} -// and {@link //consume} are called to complete the Match process. -// -//

If the symbol type does not Match, -// {@link ANTLRErrorStrategy//recoverInline} is called on the current error -// strategy to attempt recovery. If {@link //getBuildParseTree} is -// {@code true} and the token index of the symbol returned by -// {@link ANTLRErrorStrategy//recoverInline} is -1, the symbol is added to -// the parse tree by calling {@link ParserRuleContext//addErrorNode}.

-// -// @return the Matched symbol -// @panics RecognitionException if the current input symbol did not Match -// a wildcard and the error strategy could not recover from the mismatched -// symbol - -func (p *BaseParser) MatchWildcard() Token { - t := p.GetCurrentToken() - if t.GetTokenType() > 0 { - p.errHandler.ReportMatch(p) - p.Consume() - } else { - t = p.errHandler.RecoverInline(p) - if p.BuildParseTrees && t.GetTokenIndex() == -1 { - // we must have conjured up a Newtoken during single token - // insertion - // if it's not the current symbol - p.ctx.AddErrorNode(t) - } - } - return t -} - -func (p *BaseParser) GetParserRuleContext() ParserRuleContext { - return p.ctx -} - -func (p *BaseParser) SetParserRuleContext(v ParserRuleContext) { - p.ctx = v -} - -func (p *BaseParser) GetParseListeners() []ParseTreeListener { - if p.parseListeners == nil { - return make([]ParseTreeListener, 0) - } - return p.parseListeners -} - -// Registers {@code listener} to receive events during the parsing process. -// -//

To support output-preserving grammar transformations (including but not -// limited to left-recursion removal, automated left-factoring, and -// optimized code generation), calls to listener methods during the parse -// may differ substantially from calls made by -// {@link ParseTreeWalker//DEFAULT} used after the parse is complete. In -// particular, rule entry and exit events may occur in a different order -// during the parse than after the parser. In addition, calls to certain -// rule entry methods may be omitted.

-// -//

With the following specific exceptions, calls to listener events are -// deterministic, i.e. for identical input the calls to listener -// methods will be the same.

-// -//
    -//
  • Alterations to the grammar used to generate code may change the -// behavior of the listener calls.
  • -//
  • Alterations to the command line options passed to ANTLR 4 when -// generating the parser may change the behavior of the listener calls.
  • -//
  • Changing the version of the ANTLR Tool used to generate the parser -// may change the behavior of the listener calls.
  • -//
-// -// @param listener the listener to add -// -// @panics nilPointerException if {@code} listener is {@code nil} -// -func (p *BaseParser) AddParseListener(listener ParseTreeListener) { - if listener == nil { - panic("listener") - } - if p.parseListeners == nil { - p.parseListeners = make([]ParseTreeListener, 0) - } - p.parseListeners = append(p.parseListeners, listener) -} - -// -// Remove {@code listener} from the list of parse listeners. -// -//

If {@code listener} is {@code nil} or has not been added as a parse -// listener, p.method does nothing.

-// @param listener the listener to remove -// -func (p *BaseParser) RemoveParseListener(listener ParseTreeListener) { - - if p.parseListeners != nil { - - idx := -1 - for i, v := range p.parseListeners { - if v == listener { - idx = i - break - } - } - - if idx == -1 { - return - } - - // remove the listener from the slice - p.parseListeners = append(p.parseListeners[0:idx], p.parseListeners[idx+1:]...) - - if len(p.parseListeners) == 0 { - p.parseListeners = nil - } - } -} - -// Remove all parse listeners. -func (p *BaseParser) removeParseListeners() { - p.parseListeners = nil -} - -// Notify any parse listeners of an enter rule event. -func (p *BaseParser) TriggerEnterRuleEvent() { - if p.parseListeners != nil { - ctx := p.ctx - for _, listener := range p.parseListeners { - listener.EnterEveryRule(ctx) - ctx.EnterRule(listener) - } - } -} - -// -// Notify any parse listeners of an exit rule event. -// -// @see //addParseListener -// -func (p *BaseParser) TriggerExitRuleEvent() { - if p.parseListeners != nil { - // reverse order walk of listeners - ctx := p.ctx - l := len(p.parseListeners) - 1 - - for i := range p.parseListeners { - listener := p.parseListeners[l-i] - ctx.ExitRule(listener) - listener.ExitEveryRule(ctx) - } - } -} - -func (p *BaseParser) GetInterpreter() *ParserATNSimulator { - return p.Interpreter -} - -func (p *BaseParser) GetATN() *ATN { - return p.Interpreter.atn -} - -func (p *BaseParser) GetTokenFactory() TokenFactory { - return p.input.GetTokenSource().GetTokenFactory() -} - -// Tell our token source and error strategy about a Newway to create tokens.// -func (p *BaseParser) setTokenFactory(factory TokenFactory) { - p.input.GetTokenSource().setTokenFactory(factory) -} - -// The ATN with bypass alternatives is expensive to create so we create it -// lazily. -// -// @panics UnsupportedOperationException if the current parser does not -// implement the {@link //getSerializedATN()} method. -// -func (p *BaseParser) GetATNWithBypassAlts() { - - // TODO - panic("Not implemented!") - - // serializedAtn := p.getSerializedATN() - // if (serializedAtn == nil) { - // panic("The current parser does not support an ATN with bypass alternatives.") - // } - // result := p.bypassAltsAtnCache[serializedAtn] - // if (result == nil) { - // deserializationOptions := NewATNDeserializationOptions(nil) - // deserializationOptions.generateRuleBypassTransitions = true - // result = NewATNDeserializer(deserializationOptions).deserialize(serializedAtn) - // p.bypassAltsAtnCache[serializedAtn] = result - // } - // return result -} - -// The preferred method of getting a tree pattern. For example, here's a -// sample use: -// -//
-// ParseTree t = parser.expr()
-// ParseTreePattern p = parser.compileParseTreePattern("<ID>+0",
-// MyParser.RULE_expr)
-// ParseTreeMatch m = p.Match(t)
-// String id = m.Get("ID")
-// 
- -func (p *BaseParser) compileParseTreePattern(pattern, patternRuleIndex, lexer Lexer) { - - panic("NewParseTreePatternMatcher not implemented!") - // - // if (lexer == nil) { - // if (p.GetTokenStream() != nil) { - // tokenSource := p.GetTokenStream().GetTokenSource() - // if _, ok := tokenSource.(ILexer); ok { - // lexer = tokenSource - // } - // } - // } - // if (lexer == nil) { - // panic("Parser can't discover a lexer to use") - // } - - // m := NewParseTreePatternMatcher(lexer, p) - // return m.compile(pattern, patternRuleIndex) -} - -func (p *BaseParser) GetInputStream() IntStream { - return p.GetTokenStream() -} - -func (p *BaseParser) SetInputStream(input TokenStream) { - p.SetTokenStream(input) -} - -func (p *BaseParser) GetTokenStream() TokenStream { - return p.input -} - -// Set the token stream and reset the parser.// -func (p *BaseParser) SetTokenStream(input TokenStream) { - p.input = nil - p.reset() - p.input = input -} - -// Match needs to return the current input symbol, which gets put -// into the label for the associated token ref e.g., x=ID. -// -func (p *BaseParser) GetCurrentToken() Token { - return p.input.LT(1) -} - -func (p *BaseParser) NotifyErrorListeners(msg string, offendingToken Token, err RecognitionException) { - if offendingToken == nil { - offendingToken = p.GetCurrentToken() - } - p._SyntaxErrors++ - line := offendingToken.GetLine() - column := offendingToken.GetColumn() - listener := p.GetErrorListenerDispatch() - listener.SyntaxError(p, offendingToken, line, column, msg, err) -} - -func (p *BaseParser) Consume() Token { - o := p.GetCurrentToken() - if o.GetTokenType() != TokenEOF { - p.GetInputStream().Consume() - } - hasListener := p.parseListeners != nil && len(p.parseListeners) > 0 - if p.BuildParseTrees || hasListener { - if p.errHandler.InErrorRecoveryMode(p) { - node := p.ctx.AddErrorNode(o) - if p.parseListeners != nil { - for _, l := range p.parseListeners { - l.VisitErrorNode(node) - } - } - - } else { - node := p.ctx.AddTokenNode(o) - if p.parseListeners != nil { - for _, l := range p.parseListeners { - l.VisitTerminal(node) - } - } - } - // node.invokingState = p.state - } - - return o -} - -func (p *BaseParser) addContextToParseTree() { - // add current context to parent if we have a parent - if p.ctx.GetParent() != nil { - p.ctx.GetParent().(ParserRuleContext).AddChild(p.ctx) - } -} - -func (p *BaseParser) EnterRule(localctx ParserRuleContext, state, ruleIndex int) { - p.SetState(state) - p.ctx = localctx - p.ctx.SetStart(p.input.LT(1)) - if p.BuildParseTrees { - p.addContextToParseTree() - } - if p.parseListeners != nil { - p.TriggerEnterRuleEvent() - } -} - -func (p *BaseParser) ExitRule() { - p.ctx.SetStop(p.input.LT(-1)) - // trigger event on ctx, before it reverts to parent - if p.parseListeners != nil { - p.TriggerExitRuleEvent() - } - p.SetState(p.ctx.GetInvokingState()) - if p.ctx.GetParent() != nil { - p.ctx = p.ctx.GetParent().(ParserRuleContext) - } else { - p.ctx = nil - } -} - -func (p *BaseParser) EnterOuterAlt(localctx ParserRuleContext, altNum int) { - localctx.SetAltNumber(altNum) - // if we have Newlocalctx, make sure we replace existing ctx - // that is previous child of parse tree - if p.BuildParseTrees && p.ctx != localctx { - if p.ctx.GetParent() != nil { - p.ctx.GetParent().(ParserRuleContext).RemoveLastChild() - p.ctx.GetParent().(ParserRuleContext).AddChild(localctx) - } - } - p.ctx = localctx -} - -// Get the precedence level for the top-most precedence rule. -// -// @return The precedence level for the top-most precedence rule, or -1 if -// the parser context is not nested within a precedence rule. - -func (p *BaseParser) GetPrecedence() int { - if len(p.precedenceStack) == 0 { - return -1 - } - - return p.precedenceStack[len(p.precedenceStack)-1] -} - -func (p *BaseParser) EnterRecursionRule(localctx ParserRuleContext, state, ruleIndex, precedence int) { - p.SetState(state) - p.precedenceStack.Push(precedence) - p.ctx = localctx - p.ctx.SetStart(p.input.LT(1)) - if p.parseListeners != nil { - p.TriggerEnterRuleEvent() // simulates rule entry for - // left-recursive rules - } -} - -// -// Like {@link //EnterRule} but for recursive rules. - -func (p *BaseParser) PushNewRecursionContext(localctx ParserRuleContext, state, ruleIndex int) { - previous := p.ctx - previous.SetParent(localctx) - previous.SetInvokingState(state) - previous.SetStop(p.input.LT(-1)) - - p.ctx = localctx - p.ctx.SetStart(previous.GetStart()) - if p.BuildParseTrees { - p.ctx.AddChild(previous) - } - if p.parseListeners != nil { - p.TriggerEnterRuleEvent() // simulates rule entry for - // left-recursive rules - } -} - -func (p *BaseParser) UnrollRecursionContexts(parentCtx ParserRuleContext) { - p.precedenceStack.Pop() - p.ctx.SetStop(p.input.LT(-1)) - retCtx := p.ctx // save current ctx (return value) - // unroll so ctx is as it was before call to recursive method - if p.parseListeners != nil { - for p.ctx != parentCtx { - p.TriggerExitRuleEvent() - p.ctx = p.ctx.GetParent().(ParserRuleContext) - } - } else { - p.ctx = parentCtx - } - // hook into tree - retCtx.SetParent(parentCtx) - if p.BuildParseTrees && parentCtx != nil { - // add return ctx into invoking rule's tree - parentCtx.AddChild(retCtx) - } -} - -func (p *BaseParser) GetInvokingContext(ruleIndex int) ParserRuleContext { - ctx := p.ctx - for ctx != nil { - if ctx.GetRuleIndex() == ruleIndex { - return ctx - } - ctx = ctx.GetParent().(ParserRuleContext) - } - return nil -} - -func (p *BaseParser) Precpred(localctx RuleContext, precedence int) bool { - return precedence >= p.precedenceStack[len(p.precedenceStack)-1] -} - -func (p *BaseParser) inContext(context ParserRuleContext) bool { - // TODO: useful in parser? - return false -} - -// -// Checks whether or not {@code symbol} can follow the current state in the -// ATN. The behavior of p.method is equivalent to the following, but is -// implemented such that the complete context-sensitive follow set does not -// need to be explicitly constructed. -// -//
-// return getExpectedTokens().contains(symbol)
-// 
-// -// @param symbol the symbol type to check -// @return {@code true} if {@code symbol} can follow the current state in -// the ATN, otherwise {@code false}. - -func (p *BaseParser) IsExpectedToken(symbol int) bool { - atn := p.Interpreter.atn - ctx := p.ctx - s := atn.states[p.state] - following := atn.NextTokens(s, nil) - if following.contains(symbol) { - return true - } - if !following.contains(TokenEpsilon) { - return false - } - for ctx != nil && ctx.GetInvokingState() >= 0 && following.contains(TokenEpsilon) { - invokingState := atn.states[ctx.GetInvokingState()] - rt := invokingState.GetTransitions()[0] - following = atn.NextTokens(rt.(*RuleTransition).followState, nil) - if following.contains(symbol) { - return true - } - ctx = ctx.GetParent().(ParserRuleContext) - } - if following.contains(TokenEpsilon) && symbol == TokenEOF { - return true - } - - return false -} - -// Computes the set of input symbols which could follow the current parser -// state and context, as given by {@link //GetState} and {@link //GetContext}, -// respectively. -// -// @see ATN//getExpectedTokens(int, RuleContext) -// -func (p *BaseParser) GetExpectedTokens() *IntervalSet { - return p.Interpreter.atn.getExpectedTokens(p.state, p.ctx) -} - -func (p *BaseParser) GetExpectedTokensWithinCurrentRule() *IntervalSet { - atn := p.Interpreter.atn - s := atn.states[p.state] - return atn.NextTokens(s, nil) -} - -// Get a rule's index (i.e., {@code RULE_ruleName} field) or -1 if not found.// -func (p *BaseParser) GetRuleIndex(ruleName string) int { - var ruleIndex, ok = p.GetRuleIndexMap()[ruleName] - if ok { - return ruleIndex - } - - return -1 -} - -// Return List<String> of the rule names in your parser instance -// leading up to a call to the current rule. You could override if -// you want more details such as the file/line info of where -// in the ATN a rule is invoked. -// -// this very useful for error messages. - -func (p *BaseParser) GetRuleInvocationStack(c ParserRuleContext) []string { - if c == nil { - c = p.ctx - } - stack := make([]string, 0) - for c != nil { - // compute what follows who invoked us - ruleIndex := c.GetRuleIndex() - if ruleIndex < 0 { - stack = append(stack, "n/a") - } else { - stack = append(stack, p.GetRuleNames()[ruleIndex]) - } - - vp := c.GetParent() - - if vp == nil { - break - } - - c = vp.(ParserRuleContext) - } - return stack -} - -// For debugging and other purposes.// -func (p *BaseParser) GetDFAStrings() string { - return fmt.Sprint(p.Interpreter.decisionToDFA) -} - -// For debugging and other purposes.// -func (p *BaseParser) DumpDFA() { - seenOne := false - for _, dfa := range p.Interpreter.decisionToDFA { - if dfa.numStates() > 0 { - if seenOne { - fmt.Println() - } - fmt.Println("Decision " + strconv.Itoa(dfa.decision) + ":") - fmt.Print(dfa.String(p.LiteralNames, p.SymbolicNames)) - seenOne = true - } - } -} - -func (p *BaseParser) GetSourceName() string { - return p.GrammarFileName -} - -// During a parse is sometimes useful to listen in on the rule entry and exit -// events as well as token Matches. p.is for quick and dirty debugging. -// -func (p *BaseParser) SetTrace(trace *TraceListener) { - if trace == nil { - p.RemoveParseListener(p.tracer) - p.tracer = nil - } else { - if p.tracer != nil { - p.RemoveParseListener(p.tracer) - } - p.tracer = NewTraceListener(p) - p.AddParseListener(p.tracer) - } -} diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/token.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/token.go deleted file mode 100644 index 2d8e99095d..0000000000 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/token.go +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. -// Use of this file is governed by the BSD 3-clause license that -// can be found in the LICENSE.txt file in the project root. - -package antlr - -import ( - "strconv" - "strings" -) - -type TokenSourceCharStreamPair struct { - tokenSource TokenSource - charStream CharStream -} - -// A token has properties: text, type, line, character position in the line -// (so we can ignore tabs), token channel, index, and source from which -// we obtained this token. - -type Token interface { - GetSource() *TokenSourceCharStreamPair - GetTokenType() int - GetChannel() int - GetStart() int - GetStop() int - GetLine() int - GetColumn() int - - GetText() string - SetText(s string) - - GetTokenIndex() int - SetTokenIndex(v int) - - GetTokenSource() TokenSource - GetInputStream() CharStream -} - -type BaseToken struct { - source *TokenSourceCharStreamPair - tokenType int // token type of the token - channel int // The parser ignores everything not on DEFAULT_CHANNEL - start int // optional return -1 if not implemented. - stop int // optional return -1 if not implemented. - tokenIndex int // from 0..n-1 of the token object in the input stream - line int // line=1..n of the 1st character - column int // beginning of the line at which it occurs, 0..n-1 - text string // text of the token. - readOnly bool -} - -const ( - TokenInvalidType = 0 - - // During lookahead operations, this "token" signifies we hit rule end ATN state - // and did not follow it despite needing to. - TokenEpsilon = -2 - - TokenMinUserTokenType = 1 - - TokenEOF = -1 - - // All tokens go to the parser (unless Skip() is called in that rule) - // on a particular "channel". The parser tunes to a particular channel - // so that whitespace etc... can go to the parser on a "hidden" channel. - - TokenDefaultChannel = 0 - - // Anything on different channel than DEFAULT_CHANNEL is not parsed - // by parser. - - TokenHiddenChannel = 1 -) - -func (b *BaseToken) GetChannel() int { - return b.channel -} - -func (b *BaseToken) GetStart() int { - return b.start -} - -func (b *BaseToken) GetStop() int { - return b.stop -} - -func (b *BaseToken) GetLine() int { - return b.line -} - -func (b *BaseToken) GetColumn() int { - return b.column -} - -func (b *BaseToken) GetTokenType() int { - return b.tokenType -} - -func (b *BaseToken) GetSource() *TokenSourceCharStreamPair { - return b.source -} - -func (b *BaseToken) GetTokenIndex() int { - return b.tokenIndex -} - -func (b *BaseToken) SetTokenIndex(v int) { - b.tokenIndex = v -} - -func (b *BaseToken) GetTokenSource() TokenSource { - return b.source.tokenSource -} - -func (b *BaseToken) GetInputStream() CharStream { - return b.source.charStream -} - -type CommonToken struct { - *BaseToken -} - -func NewCommonToken(source *TokenSourceCharStreamPair, tokenType, channel, start, stop int) *CommonToken { - - t := new(CommonToken) - - t.BaseToken = new(BaseToken) - - t.source = source - t.tokenType = tokenType - t.channel = channel - t.start = start - t.stop = stop - t.tokenIndex = -1 - if t.source.tokenSource != nil { - t.line = source.tokenSource.GetLine() - t.column = source.tokenSource.GetCharPositionInLine() - } else { - t.column = -1 - } - return t -} - -// An empty {@link Pair} which is used as the default value of -// {@link //source} for tokens that do not have a source. - -//CommonToken.EMPTY_SOURCE = [ nil, nil ] - -// Constructs a New{@link CommonToken} as a copy of another {@link Token}. -// -//

-// If {@code oldToken} is also a {@link CommonToken} instance, the newly -// constructed token will share a reference to the {@link //text} field and -// the {@link Pair} stored in {@link //source}. Otherwise, {@link //text} will -// be assigned the result of calling {@link //GetText}, and {@link //source} -// will be constructed from the result of {@link Token//GetTokenSource} and -// {@link Token//GetInputStream}.

-// -// @param oldToken The token to copy. -// -func (c *CommonToken) clone() *CommonToken { - t := NewCommonToken(c.source, c.tokenType, c.channel, c.start, c.stop) - t.tokenIndex = c.GetTokenIndex() - t.line = c.GetLine() - t.column = c.GetColumn() - t.text = c.GetText() - return t -} - -func (c *CommonToken) GetText() string { - if c.text != "" { - return c.text - } - input := c.GetInputStream() - if input == nil { - return "" - } - n := input.Size() - if c.start < n && c.stop < n { - return input.GetTextFromInterval(NewInterval(c.start, c.stop)) - } - return "" -} - -func (c *CommonToken) SetText(text string) { - c.text = text -} - -func (c *CommonToken) String() string { - txt := c.GetText() - if txt != "" { - txt = strings.Replace(txt, "\n", "\\n", -1) - txt = strings.Replace(txt, "\r", "\\r", -1) - txt = strings.Replace(txt, "\t", "\\t", -1) - } else { - txt = "" - } - - var ch string - if c.channel > 0 { - ch = ",channel=" + strconv.Itoa(c.channel) - } else { - ch = "" - } - - return "[@" + strconv.Itoa(c.tokenIndex) + "," + strconv.Itoa(c.start) + ":" + strconv.Itoa(c.stop) + "='" + - txt + "',<" + strconv.Itoa(c.tokenType) + ">" + - ch + "," + strconv.Itoa(c.line) + ":" + strconv.Itoa(c.column) + "]" -} diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/tokenstream_rewriter.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/tokenstream_rewriter.go deleted file mode 100644 index 96a03f02aa..0000000000 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/tokenstream_rewriter.go +++ /dev/null @@ -1,649 +0,0 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. -// Use of this file is governed by the BSD 3-clause license that -// can be found in the LICENSE.txt file in the project root. -package antlr - -import ( -"bytes" -"fmt" -) - - -// -// Useful for rewriting out a buffered input token stream after doing some -// augmentation or other manipulations on it. - -//

-// You can insert stuff, replace, and delete chunks. Note that the operations -// are done lazily--only if you convert the buffer to a {@link String} with -// {@link TokenStream#getText()}. This is very efficient because you are not -// moving data around all the time. As the buffer of tokens is converted to -// strings, the {@link #getText()} method(s) scan the input token stream and -// check to see if there is an operation at the current index. If so, the -// operation is done and then normal {@link String} rendering continues on the -// buffer. This is like having multiple Turing machine instruction streams -// (programs) operating on a single input tape. :)

-//

- -// This rewriter makes no modifications to the token stream. It does not ask the -// stream to fill itself up nor does it advance the input cursor. The token -// stream {@link TokenStream#index()} will return the same value before and -// after any {@link #getText()} call.

- -//

-// The rewriter only works on tokens that you have in the buffer and ignores the -// current input cursor. If you are buffering tokens on-demand, calling -// {@link #getText()} halfway through the input will only do rewrites for those -// tokens in the first half of the file.

- -//

-// Since the operations are done lazily at {@link #getText}-time, operations do -// not screw up the token index values. That is, an insert operation at token -// index {@code i} does not change the index values for tokens -// {@code i}+1..n-1.

- -//

-// Because operations never actually alter the buffer, you may always get the -// original token stream back without undoing anything. Since the instructions -// are queued up, you can easily simulate transactions and roll back any changes -// if there is an error just by removing instructions. For example,

- -//
-// CharStream input = new ANTLRFileStream("input");
-// TLexer lex = new TLexer(input);
-// CommonTokenStream tokens = new CommonTokenStream(lex);
-// T parser = new T(tokens);
-// TokenStreamRewriter rewriter = new TokenStreamRewriter(tokens);
-// parser.startRule();
-// 
- -//

-// Then in the rules, you can execute (assuming rewriter is visible):

- -//
-// Token t,u;
-// ...
-// rewriter.insertAfter(t, "text to put after t");}
-// rewriter.insertAfter(u, "text after u");}
-// System.out.println(rewriter.getText());
-// 
- -//

-// You can also have multiple "instruction streams" and get multiple rewrites -// from a single pass over the input. Just name the instruction streams and use -// that name again when printing the buffer. This could be useful for generating -// a C file and also its header file--all from the same buffer:

- -//
-// rewriter.insertAfter("pass1", t, "text to put after t");}
-// rewriter.insertAfter("pass2", u, "text after u");}
-// System.out.println(rewriter.getText("pass1"));
-// System.out.println(rewriter.getText("pass2"));
-// 
- -//

-// If you don't use named rewrite streams, a "default" stream is used as the -// first example shows.

- - - -const( - Default_Program_Name = "default" - Program_Init_Size = 100 - Min_Token_Index = 0 -) - -// Define the rewrite operation hierarchy - -type RewriteOperation interface { - // Execute the rewrite operation by possibly adding to the buffer. - // Return the index of the next token to operate on. - Execute(buffer *bytes.Buffer) int - String() string - GetInstructionIndex() int - GetIndex() int - GetText() string - GetOpName() string - GetTokens() TokenStream - SetInstructionIndex(val int) - SetIndex(int) - SetText(string) - SetOpName(string) - SetTokens(TokenStream) -} - -type BaseRewriteOperation struct { - //Current index of rewrites list - instruction_index int - //Token buffer index - index int - //Substitution text - text string - //Actual operation name - op_name string - //Pointer to token steam - tokens TokenStream -} - -func (op *BaseRewriteOperation)GetInstructionIndex() int{ - return op.instruction_index -} - -func (op *BaseRewriteOperation)GetIndex() int{ - return op.index -} - -func (op *BaseRewriteOperation)GetText() string{ - return op.text -} - -func (op *BaseRewriteOperation)GetOpName() string{ - return op.op_name -} - -func (op *BaseRewriteOperation)GetTokens() TokenStream{ - return op.tokens -} - -func (op *BaseRewriteOperation)SetInstructionIndex(val int){ - op.instruction_index = val -} - -func (op *BaseRewriteOperation)SetIndex(val int) { - op.index = val -} - -func (op *BaseRewriteOperation)SetText(val string){ - op.text = val -} - -func (op *BaseRewriteOperation)SetOpName(val string){ - op.op_name = val -} - -func (op *BaseRewriteOperation)SetTokens(val TokenStream) { - op.tokens = val -} - - -func (op *BaseRewriteOperation) Execute(buffer *bytes.Buffer) int{ - return op.index -} - -func (op *BaseRewriteOperation) String() string { - return fmt.Sprintf("<%s@%d:\"%s\">", - op.op_name, - op.tokens.Get(op.GetIndex()), - op.text, - ) - -} - - -type InsertBeforeOp struct { - BaseRewriteOperation -} - -func NewInsertBeforeOp(index int, text string, stream TokenStream) *InsertBeforeOp{ - return &InsertBeforeOp{BaseRewriteOperation:BaseRewriteOperation{ - index:index, - text:text, - op_name:"InsertBeforeOp", - tokens:stream, - }} -} - -func (op *InsertBeforeOp) Execute(buffer *bytes.Buffer) int{ - buffer.WriteString(op.text) - if op.tokens.Get(op.index).GetTokenType() != TokenEOF{ - buffer.WriteString(op.tokens.Get(op.index).GetText()) - } - return op.index+1 -} - -func (op *InsertBeforeOp) String() string { - return op.BaseRewriteOperation.String() -} - -// Distinguish between insert after/before to do the "insert afters" -// first and then the "insert befores" at same index. Implementation -// of "insert after" is "insert before index+1". - -type InsertAfterOp struct { - BaseRewriteOperation -} - -func NewInsertAfterOp(index int, text string, stream TokenStream) *InsertAfterOp{ - return &InsertAfterOp{BaseRewriteOperation:BaseRewriteOperation{ - index:index+1, - text:text, - tokens:stream, - }} -} - -func (op *InsertAfterOp) Execute(buffer *bytes.Buffer) int { - buffer.WriteString(op.text) - if op.tokens.Get(op.index).GetTokenType() != TokenEOF{ - buffer.WriteString(op.tokens.Get(op.index).GetText()) - } - return op.index+1 -} - -func (op *InsertAfterOp) String() string { - return op.BaseRewriteOperation.String() -} - -// I'm going to try replacing range from x..y with (y-x)+1 ReplaceOp -// instructions. -type ReplaceOp struct{ - BaseRewriteOperation - LastIndex int -} - -func NewReplaceOp(from, to int, text string, stream TokenStream)*ReplaceOp { - return &ReplaceOp{ - BaseRewriteOperation:BaseRewriteOperation{ - index:from, - text:text, - op_name:"ReplaceOp", - tokens:stream, - }, - LastIndex:to, - } -} - -func (op *ReplaceOp)Execute(buffer *bytes.Buffer) int{ - if op.text != ""{ - buffer.WriteString(op.text) - } - return op.LastIndex +1 -} - -func (op *ReplaceOp) String() string { - if op.text == "" { - return fmt.Sprintf("", - op.tokens.Get(op.index), op.tokens.Get(op.LastIndex)) - } - return fmt.Sprintf("", - op.tokens.Get(op.index), op.tokens.Get(op.LastIndex), op.text) -} - - -type TokenStreamRewriter struct { - //Our source stream - tokens TokenStream - // You may have multiple, named streams of rewrite operations. - // I'm calling these things "programs." - // Maps String (name) → rewrite (List) - programs map[string][]RewriteOperation - last_rewrite_token_indexes map[string]int -} - -func NewTokenStreamRewriter(tokens TokenStream) *TokenStreamRewriter{ - return &TokenStreamRewriter{ - tokens: tokens, - programs: map[string][]RewriteOperation{ - Default_Program_Name:make([]RewriteOperation,0, Program_Init_Size), - }, - last_rewrite_token_indexes: map[string]int{}, - } -} - -func (tsr *TokenStreamRewriter) GetTokenStream() TokenStream{ - return tsr.tokens -} - -// Rollback the instruction stream for a program so that -// the indicated instruction (via instructionIndex) is no -// longer in the stream. UNTESTED! -func (tsr *TokenStreamRewriter) Rollback(program_name string, instruction_index int){ - is, ok := tsr.programs[program_name] - if ok{ - tsr.programs[program_name] = is[Min_Token_Index:instruction_index] - } -} - -func (tsr *TokenStreamRewriter) RollbackDefault(instruction_index int){ - tsr.Rollback(Default_Program_Name, instruction_index) -} -//Reset the program so that no instructions exist -func (tsr *TokenStreamRewriter) DeleteProgram(program_name string){ - tsr.Rollback(program_name, Min_Token_Index) //TODO: double test on that cause lower bound is not included -} - -func (tsr *TokenStreamRewriter) DeleteProgramDefault(){ - tsr.DeleteProgram(Default_Program_Name) -} - -func (tsr *TokenStreamRewriter) InsertAfter(program_name string, index int, text string){ - // to insert after, just insert before next index (even if past end) - var op RewriteOperation = NewInsertAfterOp(index, text, tsr.tokens) - rewrites := tsr.GetProgram(program_name) - op.SetInstructionIndex(len(rewrites)) - tsr.AddToProgram(program_name, op) -} - -func (tsr *TokenStreamRewriter) InsertAfterDefault(index int, text string){ - tsr.InsertAfter(Default_Program_Name, index, text) -} - -func (tsr *TokenStreamRewriter) InsertAfterToken(program_name string, token Token, text string){ - tsr.InsertAfter(program_name, token.GetTokenIndex(), text) -} - -func (tsr* TokenStreamRewriter) InsertBefore(program_name string, index int, text string){ - var op RewriteOperation = NewInsertBeforeOp(index, text, tsr.tokens) - rewrites := tsr.GetProgram(program_name) - op.SetInstructionIndex(len(rewrites)) - tsr.AddToProgram(program_name, op) -} - -func (tsr *TokenStreamRewriter) InsertBeforeDefault(index int, text string){ - tsr.InsertBefore(Default_Program_Name, index, text) -} - -func (tsr *TokenStreamRewriter) InsertBeforeToken(program_name string,token Token, text string){ - tsr.InsertBefore(program_name, token.GetTokenIndex(), text) -} - -func (tsr *TokenStreamRewriter) Replace(program_name string, from, to int, text string){ - if from > to || from < 0 || to < 0 || to >= tsr.tokens.Size(){ - panic(fmt.Sprintf("replace: range invalid: %d..%d(size=%d)", - from, to, tsr.tokens.Size())) - } - var op RewriteOperation = NewReplaceOp(from, to, text, tsr.tokens) - rewrites := tsr.GetProgram(program_name) - op.SetInstructionIndex(len(rewrites)) - tsr.AddToProgram(program_name, op) -} - -func (tsr *TokenStreamRewriter)ReplaceDefault(from, to int, text string) { - tsr.Replace(Default_Program_Name, from, to, text) -} - -func (tsr *TokenStreamRewriter)ReplaceDefaultPos(index int, text string){ - tsr.ReplaceDefault(index, index, text) -} - -func (tsr *TokenStreamRewriter)ReplaceToken(program_name string, from, to Token, text string){ - tsr.Replace(program_name, from.GetTokenIndex(), to.GetTokenIndex(), text) -} - -func (tsr *TokenStreamRewriter)ReplaceTokenDefault(from, to Token, text string){ - tsr.ReplaceToken(Default_Program_Name, from, to, text) -} - -func (tsr *TokenStreamRewriter)ReplaceTokenDefaultPos(index Token, text string){ - tsr.ReplaceTokenDefault(index, index, text) -} - -func (tsr *TokenStreamRewriter)Delete(program_name string, from, to int){ - tsr.Replace(program_name, from, to, "" ) -} - -func (tsr *TokenStreamRewriter)DeleteDefault(from, to int){ - tsr.Delete(Default_Program_Name, from, to) -} - -func (tsr *TokenStreamRewriter)DeleteDefaultPos(index int){ - tsr.DeleteDefault(index,index) -} - -func (tsr *TokenStreamRewriter)DeleteToken(program_name string, from, to Token) { - tsr.ReplaceToken(program_name, from, to, "") -} - -func (tsr *TokenStreamRewriter)DeleteTokenDefault(from,to Token){ - tsr.DeleteToken(Default_Program_Name, from, to) -} - -func (tsr *TokenStreamRewriter)GetLastRewriteTokenIndex(program_name string)int { - i, ok := tsr.last_rewrite_token_indexes[program_name] - if !ok{ - return -1 - } - return i -} - -func (tsr *TokenStreamRewriter)GetLastRewriteTokenIndexDefault()int{ - return tsr.GetLastRewriteTokenIndex(Default_Program_Name) -} - -func (tsr *TokenStreamRewriter)SetLastRewriteTokenIndex(program_name string, i int){ - tsr.last_rewrite_token_indexes[program_name] = i -} - -func (tsr *TokenStreamRewriter)InitializeProgram(name string)[]RewriteOperation{ - is := make([]RewriteOperation, 0, Program_Init_Size) - tsr.programs[name] = is - return is -} - -func (tsr *TokenStreamRewriter)AddToProgram(name string, op RewriteOperation){ - is := tsr.GetProgram(name) - is = append(is, op) - tsr.programs[name] = is -} - -func (tsr *TokenStreamRewriter)GetProgram(name string) []RewriteOperation { - is, ok := tsr.programs[name] - if !ok{ - is = tsr.InitializeProgram(name) - } - return is -} -// Return the text from the original tokens altered per the -// instructions given to this rewriter. -func (tsr *TokenStreamRewriter)GetTextDefault() string{ - return tsr.GetText( - Default_Program_Name, - NewInterval(0, tsr.tokens.Size()-1)) -} -// Return the text from the original tokens altered per the -// instructions given to this rewriter. -func (tsr *TokenStreamRewriter)GetText(program_name string, interval *Interval) string { - rewrites := tsr.programs[program_name] - start := interval.Start - stop := interval.Stop - // ensure start/end are in range - stop = min(stop, tsr.tokens.Size()-1) - start = max(start,0) - if rewrites == nil || len(rewrites) == 0{ - return tsr.tokens.GetTextFromInterval(interval) // no instructions to execute - } - buf := bytes.Buffer{} - // First, optimize instruction stream - indexToOp := reduceToSingleOperationPerIndex(rewrites) - // Walk buffer, executing instructions and emitting tokens - for i:=start; i<=stop && i= tsr.tokens.Size()-1 {buf.WriteString(op.GetText())} - } - } - return buf.String() -} - -// We need to combine operations and report invalid operations (like -// overlapping replaces that are not completed nested). Inserts to -// same index need to be combined etc... Here are the cases: -// -// I.i.u I.j.v leave alone, nonoverlapping -// I.i.u I.i.v combine: Iivu -// -// R.i-j.u R.x-y.v | i-j in x-y delete first R -// R.i-j.u R.i-j.v delete first R -// R.i-j.u R.x-y.v | x-y in i-j ERROR -// R.i-j.u R.x-y.v | boundaries overlap ERROR -// -// Delete special case of replace (text==null): -// D.i-j.u D.x-y.v | boundaries overlap combine to max(min)..max(right) -// -// I.i.u R.x-y.v | i in (x+1)-y delete I (since insert before -// we're not deleting i) -// I.i.u R.x-y.v | i not in (x+1)-y leave alone, nonoverlapping -// R.x-y.v I.i.u | i in x-y ERROR -// R.x-y.v I.x.u R.x-y.uv (combine, delete I) -// R.x-y.v I.i.u | i not in x-y leave alone, nonoverlapping -// -// I.i.u = insert u before op @ index i -// R.x-y.u = replace x-y indexed tokens with u -// -// First we need to examine replaces. For any replace op: -// -// 1. wipe out any insertions before op within that range. -// 2. Drop any replace op before that is contained completely within -// that range. -// 3. Throw exception upon boundary overlap with any previous replace. -// -// Then we can deal with inserts: -// -// 1. for any inserts to same index, combine even if not adjacent. -// 2. for any prior replace with same left boundary, combine this -// insert with replace and delete this replace. -// 3. throw exception if index in same range as previous replace -// -// Don't actually delete; make op null in list. Easier to walk list. -// Later we can throw as we add to index → op map. -// -// Note that I.2 R.2-2 will wipe out I.2 even though, technically, the -// inserted stuff would be before the replace range. But, if you -// add tokens in front of a method body '{' and then delete the method -// body, I think the stuff before the '{' you added should disappear too. -// -// Return a map from token index to operation. -// -func reduceToSingleOperationPerIndex(rewrites []RewriteOperation) map[int]RewriteOperation{ - // WALK REPLACES - for i:=0; i < len(rewrites); i++{ - op := rewrites[i] - if op == nil{continue} - rop, ok := op.(*ReplaceOp) - if !ok{continue} - // Wipe prior inserts within range - for j:=0; j rop.index && iop.index <=rop.LastIndex{ - // delete insert as it's a no-op. - rewrites[iop.instruction_index] = nil - } - } - } - // Drop any prior replaces contained within - for j:=0; j=rop.index && prevop.LastIndex <= rop.LastIndex{ - // delete replace as it's a no-op. - rewrites[prevop.instruction_index] = nil - continue - } - // throw exception unless disjoint or identical - disjoint := prevop.LastIndex < rop.index || prevop.index > rop.LastIndex - // Delete special case of replace (text==null): - // D.i-j.u D.x-y.v | boundaries overlap combine to max(min)..max(right) - if prevop.text == "" && rop.text == "" && !disjoint{ - rewrites[prevop.instruction_index] = nil - rop.index = min(prevop.index, rop.index) - rop.LastIndex = max(prevop.LastIndex, rop.LastIndex) - println("new rop" + rop.String()) //TODO: remove console write, taken from Java version - }else if !disjoint{ - panic("replace op boundaries of " + rop.String() + " overlap with previous " + prevop.String()) - } - } - } - } - // WALK INSERTS - for i:=0; i < len(rewrites); i++ { - op := rewrites[i] - if op == nil{continue} - //hack to replicate inheritance in composition - _, iok := rewrites[i].(*InsertBeforeOp) - _, aok := rewrites[i].(*InsertAfterOp) - if !iok && !aok{continue} - iop := rewrites[i] - // combine current insert with prior if any at same index - // deviating a bit from TokenStreamRewriter.java - hard to incorporate inheritance logic - for j:=0; j= rop.index && iop.GetIndex() <= rop.LastIndex{ - panic("insert op "+iop.String()+" within boundaries of previous "+rop.String()) - } - } - } - } - m := map[int]RewriteOperation{} - for i:=0; i < len(rewrites); i++{ - op := rewrites[i] - if op == nil {continue} - if _, ok := m[op.GetIndex()]; ok{ - panic("should only be one op per index") - } - m[op.GetIndex()] = op - } - return m -} - - -/* - Quick fixing Go lack of overloads - */ - -func max(a,b int)int{ - if a>b{ - return a - }else { - return b - } -} -func min(a,b int)int{ - if a b { - return a - } - return b -} - -// A simple integer stack - -type IntStack []int - -var ErrEmptyStack = errors.New("Stack is empty") - -func (s *IntStack) Pop() (int, error) { - l := len(*s) - 1 - if l < 0 { - return 0, ErrEmptyStack - } - v := (*s)[l] - *s = (*s)[0:l] - return v, nil -} - -func (s *IntStack) Push(e int) { - *s = append(*s, e) -} - -func standardEqualsFunction(a interface{}, b interface{}) bool { - - ac, oka := a.(comparable) - bc, okb := b.(comparable) - - if !oka || !okb { - panic("Not Comparable") - } - - return ac.equals(bc) -} - -func standardHashFunction(a interface{}) int { - if h, ok := a.(hasher); ok { - return h.hash() - } - - panic("Not Hasher") -} - -type hasher interface { - hash() int -} - -const bitsPerWord = 64 - -func indexForBit(bit int) int { - return bit / bitsPerWord -} - -func wordForBit(data []uint64, bit int) uint64 { - idx := indexForBit(bit) - if idx >= len(data) { - return 0 - } - return data[idx] -} - -func maskForBit(bit int) uint64 { - return uint64(1) << (bit % bitsPerWord) -} - -func wordsNeeded(bit int) int { - return indexForBit(bit) + 1 -} - -type BitSet struct { - data []uint64 -} - -func NewBitSet() *BitSet { - return &BitSet{} -} - -func (b *BitSet) add(value int) { - idx := indexForBit(value) - if idx >= len(b.data) { - size := wordsNeeded(value) - data := make([]uint64, size) - copy(data, b.data) - b.data = data - } - b.data[idx] |= maskForBit(value) -} - -func (b *BitSet) clear(index int) { - idx := indexForBit(index) - if idx >= len(b.data) { - return - } - b.data[idx] &= ^maskForBit(index) -} - -func (b *BitSet) or(set *BitSet) { - // Get min size necessary to represent the bits in both sets. - bLen := b.minLen() - setLen := set.minLen() - maxLen := intMax(bLen, setLen) - if maxLen > len(b.data) { - // Increase the size of len(b.data) to repesent the bits in both sets. - data := make([]uint64, maxLen) - copy(data, b.data) - b.data = data - } - // len(b.data) is at least setLen. - for i := 0; i < setLen; i++ { - b.data[i] |= set.data[i] - } -} - -func (b *BitSet) remove(value int) { - b.clear(value) -} - -func (b *BitSet) contains(value int) bool { - idx := indexForBit(value) - if idx >= len(b.data) { - return false - } - return (b.data[idx] & maskForBit(value)) != 0 -} - -func (b *BitSet) minValue() int { - for i, v := range b.data { - if v == 0 { - continue - } - return i*bitsPerWord + bits.TrailingZeros64(v) - } - return 2147483647 -} - -func (b *BitSet) equals(other interface{}) bool { - otherBitSet, ok := other.(*BitSet) - if !ok { - return false - } - - if b == otherBitSet { - return true - } - - // We only compare set bits, so we cannot rely on the two slices having the same size. Its - // possible for two BitSets to have different slice lengths but the same set bits. So we only - // compare the relavent words and ignore the trailing zeros. - bLen := b.minLen() - otherLen := otherBitSet.minLen() - - if bLen != otherLen { - return false - } - - for i := 0; i < bLen; i++ { - if b.data[i] != otherBitSet.data[i] { - return false - } - } - - return true -} - -func (b *BitSet) minLen() int { - for i := len(b.data); i > 0; i-- { - if b.data[i-1] != 0 { - return i - } - } - return 0 -} - -func (b *BitSet) length() int { - cnt := 0 - for _, val := range b.data { - cnt += bits.OnesCount64(val) - } - return cnt -} - -func (b *BitSet) String() string { - vals := make([]string, 0, b.length()) - - for i, v := range b.data { - for v != 0 { - n := bits.TrailingZeros64(v) - vals = append(vals, strconv.Itoa(i*bitsPerWord+n)) - v &= ^(uint64(1) << n) - } - } - - return "{" + strings.Join(vals, ", ") + "}" -} - -type AltDict struct { - data map[string]interface{} -} - -func NewAltDict() *AltDict { - d := new(AltDict) - d.data = make(map[string]interface{}) - return d -} - -func (a *AltDict) Get(key string) interface{} { - key = "k-" + key - return a.data[key] -} - -func (a *AltDict) put(key string, value interface{}) { - key = "k-" + key - a.data[key] = value -} - -func (a *AltDict) values() []interface{} { - vs := make([]interface{}, len(a.data)) - i := 0 - for _, v := range a.data { - vs[i] = v - i++ - } - return vs -} - -type DoubleDict struct { - data map[int]map[int]interface{} -} - -func NewDoubleDict() *DoubleDict { - dd := new(DoubleDict) - dd.data = make(map[int]map[int]interface{}) - return dd -} - -func (d *DoubleDict) Get(a, b int) interface{} { - data := d.data[a] - - if data == nil { - return nil - } - - return data[b] -} - -func (d *DoubleDict) set(a, b int, o interface{}) { - data := d.data[a] - - if data == nil { - data = make(map[int]interface{}) - d.data[a] = data - } - - data[b] = o -} - -func EscapeWhitespace(s string, escapeSpaces bool) string { - - s = strings.Replace(s, "\t", "\\t", -1) - s = strings.Replace(s, "\n", "\\n", -1) - s = strings.Replace(s, "\r", "\\r", -1) - if escapeSpaces { - s = strings.Replace(s, " ", "\u00B7", -1) - } - return s -} - -func TerminalNodeToStringArray(sa []TerminalNode) []string { - st := make([]string, len(sa)) - - for i, s := range sa { - st[i] = fmt.Sprintf("%v", s) - } - - return st -} - -func PrintArrayJavaStyle(sa []string) string { - var buffer bytes.Buffer - - buffer.WriteString("[") - - for i, s := range sa { - buffer.WriteString(s) - if i != len(sa)-1 { - buffer.WriteString(", ") - } - } - - buffer.WriteString("]") - - return buffer.String() -} - -// murmur hash -func murmurInit(seed int) int { - return seed -} - -func murmurUpdate(h int, value int) int { - const c1 uint32 = 0xCC9E2D51 - const c2 uint32 = 0x1B873593 - const r1 uint32 = 15 - const r2 uint32 = 13 - const m uint32 = 5 - const n uint32 = 0xE6546B64 - - k := uint32(value) - k *= c1 - k = (k << r1) | (k >> (32 - r1)) - k *= c2 - - hash := uint32(h) ^ k - hash = (hash << r2) | (hash >> (32 - r2)) - hash = hash*m + n - return int(hash) -} - -func murmurFinish(h int, numberOfWords int) int { - var hash = uint32(h) - hash ^= uint32(numberOfWords) << 2 - hash ^= hash >> 16 - hash *= 0x85ebca6b - hash ^= hash >> 13 - hash *= 0xc2b2ae35 - hash ^= hash >> 16 - - return int(hash) -} diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/LICENSE b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/LICENSE similarity index 100% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/LICENSE rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/LICENSE diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/antlrdoc.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/antlrdoc.go new file mode 100644 index 0000000000..ab51212676 --- /dev/null +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/antlrdoc.go @@ -0,0 +1,68 @@ +/* +Package antlr implements the Go version of the ANTLR 4 runtime. + +# The ANTLR Tool + +ANTLR (ANother Tool for Language Recognition) is a powerful parser generator for reading, processing, executing, +or translating structured text or binary files. It's widely used to build languages, tools, and frameworks. +From a grammar, ANTLR generates a parser that can build parse trees and also generates a listener interface +(or visitor) that makes it easy to respond to the recognition of phrases of interest. + +# Code Generation + +ANTLR supports the generation of code in a number of [target languages], and the generated code is supported by a +runtime library, written specifically to support the generated code in the target language. This library is the +runtime for the Go target. + +To generate code for the go target, it is generally recommended to place the source grammar files in a package of +their own, and use the `.sh` script method of generating code, using the go generate directive. In that same directory +it is usual, though not required, to place the antlr tool that should be used to generate the code. That does mean +that the antlr tool JAR file will be checked in to your source code control though, so you are free to use any other +way of specifying the version of the ANTLR tool to use, such as aliasing in `.zshrc` or equivalent, or a profile in +your IDE, or configuration in your CI system. + +Here is a general template for an ANTLR based recognizer in Go: + + . + ├── myproject + ├── parser + │ ├── mygrammar.g4 + │ ├── antlr-4.12.0-complete.jar + │ ├── error_listeners.go + │ ├── generate.go + │ ├── generate.sh + ├── go.mod + ├── go.sum + ├── main.go + └── main_test.go + +Make sure that the package statement in your grammar file(s) reflects the go package they exist in. +The generate.go file then looks like this: + + package parser + + //go:generate ./generate.sh + +And the generate.sh file will look similar to this: + + #!/bin/sh + + alias antlr4='java -Xmx500M -cp "./antlr4-4.12.0-complete.jar:$CLASSPATH" org.antlr.v4.Tool' + antlr4 -Dlanguage=Go -no-visitor -package parser *.g4 + +depending on whether you want visitors or listeners or any other ANTLR options. + +From the command line at the root of your package “myproject” you can then simply issue the command: + + go generate ./... + +# Copyright Notice + +Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. + +Use of this file is governed by the BSD 3-clause license, which can be found in the [LICENSE.txt] file in the project root. + +[target languages]: https://github.com/antlr/antlr4/tree/master/runtime +[LICENSE.txt]: https://github.com/antlr/antlr4/blob/master/LICENSE.txt +*/ +package antlr diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn.go new file mode 100644 index 0000000000..98010d2e6e --- /dev/null +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn.go @@ -0,0 +1,176 @@ +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. +// Use of this file is governed by the BSD 3-clause license that +// can be found in the LICENSE.txt file in the project root. + +package antlr + +import "sync" + +// ATNInvalidAltNumber is used to represent an ALT number that has yet to be calculated or +// which is invalid for a particular struct such as [*antlr.BaseRuleContext] +var ATNInvalidAltNumber int + +// ATN represents an “[Augmented Transition Network]”, though general in ANTLR the term +// “Augmented Recursive Transition Network” though there are some descriptions of “[Recursive Transition Network]” +// in existence. +// +// ATNs represent the main networks in the system and are serialized by the code generator and support [ALL(*)]. +// +// [Augmented Transition Network]: https://en.wikipedia.org/wiki/Augmented_transition_network +// [ALL(*)]: https://www.antlr.org/papers/allstar-techreport.pdf +// [Recursive Transition Network]: https://en.wikipedia.org/wiki/Recursive_transition_network +type ATN struct { + // DecisionToState is the decision points for all rules, subrules, optional + // blocks, ()+, ()*, etc. Each subrule/rule is a decision point, and we must track them so we + // can go back later and build DFA predictors for them. This includes + // all the rules, subrules, optional blocks, ()+, ()* etc... + DecisionToState []DecisionState + + // grammarType is the ATN type and is used for deserializing ATNs from strings. + grammarType int + + // lexerActions is referenced by action transitions in the ATN for lexer ATNs. + lexerActions []LexerAction + + // maxTokenType is the maximum value for any symbol recognized by a transition in the ATN. + maxTokenType int + + modeNameToStartState map[string]*TokensStartState + + modeToStartState []*TokensStartState + + // ruleToStartState maps from rule index to starting state number. + ruleToStartState []*RuleStartState + + // ruleToStopState maps from rule index to stop state number. + ruleToStopState []*RuleStopState + + // ruleToTokenType maps the rule index to the resulting token type for lexer + // ATNs. For parser ATNs, it maps the rule index to the generated bypass token + // type if ATNDeserializationOptions.isGenerateRuleBypassTransitions was + // specified, and otherwise is nil. + ruleToTokenType []int + + states []ATNState + + mu sync.Mutex + stateMu sync.RWMutex + edgeMu sync.RWMutex +} + +// NewATN returns a new ATN struct representing the given grammarType and is used +// for runtime deserialization of ATNs from the code generated by the ANTLR tool +func NewATN(grammarType int, maxTokenType int) *ATN { + return &ATN{ + grammarType: grammarType, + maxTokenType: maxTokenType, + modeNameToStartState: make(map[string]*TokensStartState), + } +} + +// NextTokensInContext computes and returns the set of valid tokens that can occur starting +// in state s. If ctx is nil, the set of tokens will not include what can follow +// the rule surrounding s. In other words, the set will be restricted to tokens +// reachable staying within the rule of s. +func (a *ATN) NextTokensInContext(s ATNState, ctx RuleContext) *IntervalSet { + return NewLL1Analyzer(a).Look(s, nil, ctx) +} + +// NextTokensNoContext computes and returns the set of valid tokens that can occur starting +// in state s and staying in same rule. [antlr.Token.EPSILON] is in set if we reach end of +// rule. +func (a *ATN) NextTokensNoContext(s ATNState) *IntervalSet { + a.mu.Lock() + defer a.mu.Unlock() + iset := s.GetNextTokenWithinRule() + if iset == nil { + iset = a.NextTokensInContext(s, nil) + iset.readOnly = true + s.SetNextTokenWithinRule(iset) + } + return iset +} + +// NextTokens computes and returns the set of valid tokens starting in state s, by +// calling either [NextTokensNoContext] (ctx == nil) or [NextTokensInContext] (ctx != nil). +func (a *ATN) NextTokens(s ATNState, ctx RuleContext) *IntervalSet { + if ctx == nil { + return a.NextTokensNoContext(s) + } + + return a.NextTokensInContext(s, ctx) +} + +func (a *ATN) addState(state ATNState) { + if state != nil { + state.SetATN(a) + state.SetStateNumber(len(a.states)) + } + + a.states = append(a.states, state) +} + +func (a *ATN) removeState(state ATNState) { + a.states[state.GetStateNumber()] = nil // Just free the memory; don't shift states in the slice +} + +func (a *ATN) defineDecisionState(s DecisionState) int { + a.DecisionToState = append(a.DecisionToState, s) + s.setDecision(len(a.DecisionToState) - 1) + + return s.getDecision() +} + +func (a *ATN) getDecisionState(decision int) DecisionState { + if len(a.DecisionToState) == 0 { + return nil + } + + return a.DecisionToState[decision] +} + +// getExpectedTokens computes the set of input symbols which could follow ATN +// state number stateNumber in the specified full parse context ctx and returns +// the set of potentially valid input symbols which could follow the specified +// state in the specified context. This method considers the complete parser +// context, but does not evaluate semantic predicates (i.e. all predicates +// encountered during the calculation are assumed true). If a path in the ATN +// exists from the starting state to the RuleStopState of the outermost context +// without Matching any symbols, Token.EOF is added to the returned set. +// +// A nil ctx defaults to ParserRuleContext.EMPTY. +// +// It panics if the ATN does not contain state stateNumber. +func (a *ATN) getExpectedTokens(stateNumber int, ctx RuleContext) *IntervalSet { + if stateNumber < 0 || stateNumber >= len(a.states) { + panic("Invalid state number.") + } + + s := a.states[stateNumber] + following := a.NextTokens(s, nil) + + if !following.contains(TokenEpsilon) { + return following + } + + expected := NewIntervalSet() + + expected.addSet(following) + expected.removeOne(TokenEpsilon) + + for ctx != nil && ctx.GetInvokingState() >= 0 && following.contains(TokenEpsilon) { + invokingState := a.states[ctx.GetInvokingState()] + rt := invokingState.GetTransitions()[0] + + following = a.NextTokens(rt.(*RuleTransition).followState, nil) + expected.addSet(following) + expected.removeOne(TokenEpsilon) + ctx = ctx.GetParent().(RuleContext) + } + + if following.contains(TokenEpsilon) { + expected.addOne(TokenEOF) + } + + return expected +} diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_config.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_config.go similarity index 84% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_config.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_config.go index 97ba417f74..7619fa172e 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_config.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_config.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. @@ -8,19 +8,14 @@ import ( "fmt" ) -type comparable interface { - equals(other interface{}) bool -} - // ATNConfig is a tuple: (ATN state, predicted alt, syntactic, semantic // context). The syntactic context is a graph-structured stack node whose // path(s) to the root is the rule invocation(s) chain used to arrive at the // state. The semantic context is the tree of semantic predicates encountered // before reaching an ATN state. type ATNConfig interface { - comparable - - hash() int + Equals(o Collectable[ATNConfig]) bool + Hash() int GetState() ATNState GetAlt() int @@ -47,7 +42,7 @@ type BaseATNConfig struct { reachesIntoOuterContext int } -func NewBaseATNConfig7(old *BaseATNConfig) *BaseATNConfig { // TODO: Dup +func NewBaseATNConfig7(old *BaseATNConfig) ATNConfig { // TODO: Dup return &BaseATNConfig{ state: old.state, alt: old.alt, @@ -135,11 +130,16 @@ func (b *BaseATNConfig) SetReachesIntoOuterContext(v int) { b.reachesIntoOuterContext = v } +// Equals is the default comparison function for an ATNConfig when no specialist implementation is required +// for a collection. +// // An ATN configuration is equal to another if both have the same state, they // predict the same alternative, and syntactic/semantic contexts are the same. -func (b *BaseATNConfig) equals(o interface{}) bool { +func (b *BaseATNConfig) Equals(o Collectable[ATNConfig]) bool { if b == o { return true + } else if o == nil { + return false } var other, ok = o.(*BaseATNConfig) @@ -153,30 +153,32 @@ func (b *BaseATNConfig) equals(o interface{}) bool { if b.context == nil { equal = other.context == nil } else { - equal = b.context.equals(other.context) + equal = b.context.Equals(other.context) } var ( nums = b.state.GetStateNumber() == other.state.GetStateNumber() alts = b.alt == other.alt - cons = b.semanticContext.equals(other.semanticContext) + cons = b.semanticContext.Equals(other.semanticContext) sups = b.precedenceFilterSuppressed == other.precedenceFilterSuppressed ) return nums && alts && cons && sups && equal } -func (b *BaseATNConfig) hash() int { +// Hash is the default hash function for BaseATNConfig, when no specialist hash function +// is required for a collection +func (b *BaseATNConfig) Hash() int { var c int if b.context != nil { - c = b.context.hash() + c = b.context.Hash() } h := murmurInit(7) h = murmurUpdate(h, b.state.GetStateNumber()) h = murmurUpdate(h, b.alt) h = murmurUpdate(h, c) - h = murmurUpdate(h, b.semanticContext.hash()) + h = murmurUpdate(h, b.semanticContext.Hash()) return murmurFinish(h, 4) } @@ -243,7 +245,9 @@ func NewLexerATNConfig1(state ATNState, alt int, context PredictionContext) *Lex return &LexerATNConfig{BaseATNConfig: NewBaseATNConfig5(state, alt, context, SemanticContextNone)} } -func (l *LexerATNConfig) hash() int { +// Hash is the default hash function for LexerATNConfig objects, it can be used directly or via +// the default comparator [ObjEqComparator]. +func (l *LexerATNConfig) Hash() int { var f int if l.passedThroughNonGreedyDecision { f = 1 @@ -253,15 +257,20 @@ func (l *LexerATNConfig) hash() int { h := murmurInit(7) h = murmurUpdate(h, l.state.GetStateNumber()) h = murmurUpdate(h, l.alt) - h = murmurUpdate(h, l.context.hash()) - h = murmurUpdate(h, l.semanticContext.hash()) + h = murmurUpdate(h, l.context.Hash()) + h = murmurUpdate(h, l.semanticContext.Hash()) h = murmurUpdate(h, f) - h = murmurUpdate(h, l.lexerActionExecutor.hash()) + h = murmurUpdate(h, l.lexerActionExecutor.Hash()) h = murmurFinish(h, 6) return h } -func (l *LexerATNConfig) equals(other interface{}) bool { +// Equals is the default comparison function for LexerATNConfig objects, it can be used directly or via +// the default comparator [ObjEqComparator]. +func (l *LexerATNConfig) Equals(other Collectable[ATNConfig]) bool { + if l == other { + return true + } var othert, ok = other.(*LexerATNConfig) if l == other { @@ -275,7 +284,7 @@ func (l *LexerATNConfig) equals(other interface{}) bool { var b bool if l.lexerActionExecutor != nil { - b = !l.lexerActionExecutor.equals(othert.lexerActionExecutor) + b = !l.lexerActionExecutor.Equals(othert.lexerActionExecutor) } else { b = othert.lexerActionExecutor != nil } @@ -284,10 +293,9 @@ func (l *LexerATNConfig) equals(other interface{}) bool { return false } - return l.BaseATNConfig.equals(othert.BaseATNConfig) + return l.BaseATNConfig.Equals(othert.BaseATNConfig) } - func checkNonGreedyDecision(source *LexerATNConfig, target ATNState) bool { var ds, ok = target.(DecisionState) diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_config_set.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_config_set.go similarity index 81% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_config_set.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_config_set.go index 49ad4a7197..43e9b33f3b 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_config_set.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_config_set.go @@ -1,24 +1,25 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. package antlr -import "fmt" +import ( + "fmt" +) type ATNConfigSet interface { - hash() int + Hash() int + Equals(o Collectable[ATNConfig]) bool Add(ATNConfig, *DoubleDict) bool AddAll([]ATNConfig) bool - GetStates() Set + GetStates() *JStore[ATNState, Comparator[ATNState]] GetPredicates() []SemanticContext GetItems() []ATNConfig OptimizeConfigs(interpreter *BaseATNSimulator) - Equals(other interface{}) bool - Length() int IsEmpty() bool Contains(ATNConfig) bool @@ -57,7 +58,7 @@ type BaseATNConfigSet struct { // effectively doubles the number of objects associated with ATNConfigs. All // keys are hashed by (s, i, _, pi), not including the context. Wiped out when // read-only because a set becomes a DFA state. - configLookup Set + configLookup *JStore[ATNConfig, Comparator[ATNConfig]] // configs is the added elements. configs []ATNConfig @@ -83,7 +84,7 @@ type BaseATNConfigSet struct { // readOnly is whether it is read-only. Do not // allow any code to manipulate the set if true because DFA states will point at - // sets and those must not change. It not protect other fields; conflictingAlts + // sets and those must not change. It not, protect other fields; conflictingAlts // in particular, which is assigned after readOnly. readOnly bool @@ -104,7 +105,7 @@ func (b *BaseATNConfigSet) Alts() *BitSet { func NewBaseATNConfigSet(fullCtx bool) *BaseATNConfigSet { return &BaseATNConfigSet{ cachedHash: -1, - configLookup: newArray2DHashSetWithCap(hashATNConfig, equalATNConfigs, 16, 2), + configLookup: NewJStore[ATNConfig, Comparator[ATNConfig]](aConfCompInst), fullCtx: fullCtx, } } @@ -126,9 +127,11 @@ func (b *BaseATNConfigSet) Add(config ATNConfig, mergeCache *DoubleDict) bool { b.dipsIntoOuterContext = true } - existing := b.configLookup.Add(config).(ATNConfig) + existing, present := b.configLookup.Put(config) - if existing == config { + // The config was not already in the set + // + if !present { b.cachedHash = -1 b.configs = append(b.configs, config) // Track order here return true @@ -154,11 +157,14 @@ func (b *BaseATNConfigSet) Add(config ATNConfig, mergeCache *DoubleDict) bool { return true } -func (b *BaseATNConfigSet) GetStates() Set { - states := newArray2DHashSet(nil, nil) +func (b *BaseATNConfigSet) GetStates() *JStore[ATNState, Comparator[ATNState]] { + + // states uses the standard comparator provided by the ATNState instance + // + states := NewJStore[ATNState, Comparator[ATNState]](aStateEqInst) for i := 0; i < len(b.configs); i++ { - states.Add(b.configs[i].GetState()) + states.Put(b.configs[i].GetState()) } return states @@ -214,7 +220,34 @@ func (b *BaseATNConfigSet) AddAll(coll []ATNConfig) bool { return false } -func (b *BaseATNConfigSet) Equals(other interface{}) bool { +// Compare is a hack function just to verify that adding DFAstares to the known +// set works, so long as comparison of ATNConfigSet s works. For that to work, we +// need to make sure that the set of ATNConfigs in two sets are equivalent. We can't +// know the order, so we do this inefficient hack. If this proves the point, then +// we can change the config set to a better structure. +func (b *BaseATNConfigSet) Compare(bs *BaseATNConfigSet) bool { + if len(b.configs) != len(bs.configs) { + return false + } + + for _, c := range b.configs { + found := false + for _, c2 := range bs.configs { + if c.Equals(c2) { + found = true + break + } + } + + if !found { + return false + } + + } + return true +} + +func (b *BaseATNConfigSet) Equals(other Collectable[ATNConfig]) bool { if b == other { return true } else if _, ok := other.(*BaseATNConfigSet); !ok { @@ -224,15 +257,15 @@ func (b *BaseATNConfigSet) Equals(other interface{}) bool { other2 := other.(*BaseATNConfigSet) return b.configs != nil && - // TODO: b.configs.equals(other2.configs) && // TODO: Is b necessary? b.fullCtx == other2.fullCtx && b.uniqueAlt == other2.uniqueAlt && b.conflictingAlts == other2.conflictingAlts && b.hasSemanticContext == other2.hasSemanticContext && - b.dipsIntoOuterContext == other2.dipsIntoOuterContext + b.dipsIntoOuterContext == other2.dipsIntoOuterContext && + b.Compare(other2) } -func (b *BaseATNConfigSet) hash() int { +func (b *BaseATNConfigSet) Hash() int { if b.readOnly { if b.cachedHash == -1 { b.cachedHash = b.hashCodeConfigs() @@ -247,7 +280,7 @@ func (b *BaseATNConfigSet) hash() int { func (b *BaseATNConfigSet) hashCodeConfigs() int { h := 1 for _, config := range b.configs { - h = 31*h + config.hash() + h = 31*h + config.Hash() } return h } @@ -283,7 +316,7 @@ func (b *BaseATNConfigSet) Clear() { b.configs = make([]ATNConfig, 0) b.cachedHash = -1 - b.configLookup = newArray2DHashSet(nil, equalATNConfigs) + b.configLookup = NewJStore[ATNConfig, Comparator[ATNConfig]](atnConfCompInst) } func (b *BaseATNConfigSet) FullContext() bool { @@ -365,7 +398,8 @@ type OrderedATNConfigSet struct { func NewOrderedATNConfigSet() *OrderedATNConfigSet { b := NewBaseATNConfigSet(false) - b.configLookup = newArray2DHashSet(nil, nil) + // This set uses the standard Hash() and Equals() from ATNConfig + b.configLookup = NewJStore[ATNConfig, Comparator[ATNConfig]](aConfEqInst) return &OrderedATNConfigSet{BaseATNConfigSet: b} } @@ -375,7 +409,7 @@ func hashATNConfig(i interface{}) int { hash := 7 hash = 31*hash + o.GetState().GetStateNumber() hash = 31*hash + o.GetAlt() - hash = 31*hash + o.GetSemanticContext().hash() + hash = 31*hash + o.GetSemanticContext().Hash() return hash } @@ -403,5 +437,5 @@ func equalATNConfigs(a, b interface{}) bool { return false } - return ai.GetSemanticContext().equals(bi.GetSemanticContext()) + return ai.GetSemanticContext().Equals(bi.GetSemanticContext()) } diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_deserialization_options.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_deserialization_options.go similarity index 96% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_deserialization_options.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_deserialization_options.go index cb8eafb0b2..3c975ec7bf 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_deserialization_options.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_deserialization_options.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_deserializer.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_deserializer.go similarity index 99% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_deserializer.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_deserializer.go index aea9bbfa93..3888856b4b 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_deserializer.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_deserializer.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_simulator.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_simulator.go similarity index 94% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_simulator.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_simulator.go index d5454d6d5d..41529115fa 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_simulator.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_simulator.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_state.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_state.go similarity index 97% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_state.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_state.go index 3835bb2e93..1f2a56bc31 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_state.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_state.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. @@ -49,7 +49,8 @@ type ATNState interface { AddTransition(Transition, int) String() string - hash() int + Hash() int + Equals(Collectable[ATNState]) bool } type BaseATNState struct { @@ -123,7 +124,7 @@ func (as *BaseATNState) SetNextTokenWithinRule(v *IntervalSet) { as.NextTokenWithinRule = v } -func (as *BaseATNState) hash() int { +func (as *BaseATNState) Hash() int { return as.stateNumber } @@ -131,7 +132,7 @@ func (as *BaseATNState) String() string { return strconv.Itoa(as.stateNumber) } -func (as *BaseATNState) equals(other interface{}) bool { +func (as *BaseATNState) Equals(other Collectable[ATNState]) bool { if ot, ok := other.(ATNState); ok { return as.stateNumber == ot.GetStateNumber() } diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_type.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_type.go similarity index 79% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_type.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_type.go index a7b48976b3..3a515a145f 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/atn_type.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/atn_type.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/char_stream.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/char_stream.go similarity index 82% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/char_stream.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/char_stream.go index 70c1207f7f..c33f0adb5e 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/char_stream.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/char_stream.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/common_token_factory.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/common_token_factory.go similarity index 96% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/common_token_factory.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/common_token_factory.go index 330ff8f31f..1bb0314ea0 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/common_token_factory.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/common_token_factory.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/common_token_stream.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/common_token_stream.go similarity index 98% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/common_token_stream.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/common_token_stream.go index c90e9b8904..c6c9485a20 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/common_token_stream.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/common_token_stream.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. @@ -331,10 +331,12 @@ func (c *CommonTokenStream) GetTextFromRuleContext(interval RuleContext) string func (c *CommonTokenStream) GetTextFromInterval(interval *Interval) string { c.lazyInit() - c.Fill() if interval == nil { + c.Fill() interval = NewInterval(0, len(c.tokens)-1) + } else { + c.Sync(interval.Stop) } start := interval.Start diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/comparators.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/comparators.go new file mode 100644 index 0000000000..9ea3200536 --- /dev/null +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/comparators.go @@ -0,0 +1,147 @@ +package antlr + +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. +// Use of this file is governed by the BSD 3-clause license that +// can be found in the LICENSE.txt file in the project root. + +// This file contains all the implementations of custom comparators used for generic collections when the +// Hash() and Equals() funcs supplied by the struct objects themselves need to be overridden. Normally, we would +// put the comparators in the source file for the struct themselves, but given the organization of this code is +// sorta kinda based upon the Java code, I found it confusing trying to find out which comparator was where and used by +// which instantiation of a collection. For instance, an Array2DHashSet in the Java source, when used with ATNConfig +// collections requires three different comparators depending on what the collection is being used for. Collecting - pun intended - +// all the comparators here, makes it much easier to see which implementation of hash and equals is used by which collection. +// It also makes it easy to verify that the Hash() and Equals() functions marry up with the Java implementations. + +// ObjEqComparator is the equivalent of the Java ObjectEqualityComparator, which is the default instance of +// Equality comparator. We do not have inheritance in Go, only interfaces, so we use generics to enforce some +// type safety and avoid having to implement this for every type that we want to perform comparison on. +// +// This comparator works by using the standard Hash() and Equals() methods of the type T that is being compared. Which +// allows us to use it in any collection instance that does nto require a special hash or equals implementation. +type ObjEqComparator[T Collectable[T]] struct{} + +var ( + aStateEqInst = &ObjEqComparator[ATNState]{} + aConfEqInst = &ObjEqComparator[ATNConfig]{} + aConfCompInst = &ATNConfigComparator[ATNConfig]{} + atnConfCompInst = &BaseATNConfigComparator[ATNConfig]{} + dfaStateEqInst = &ObjEqComparator[*DFAState]{} + semctxEqInst = &ObjEqComparator[SemanticContext]{} + atnAltCfgEqInst = &ATNAltConfigComparator[ATNConfig]{} +) + +// Equals2 delegates to the Equals() method of type T +func (c *ObjEqComparator[T]) Equals2(o1, o2 T) bool { + return o1.Equals(o2) +} + +// Hash1 delegates to the Hash() method of type T +func (c *ObjEqComparator[T]) Hash1(o T) int { + + return o.Hash() +} + +type SemCComparator[T Collectable[T]] struct{} + +// ATNConfigComparator is used as the compartor for the configLookup field of an ATNConfigSet +// and has a custom Equals() and Hash() implementation, because equality is not based on the +// standard Hash() and Equals() methods of the ATNConfig type. +type ATNConfigComparator[T Collectable[T]] struct { +} + +// Equals2 is a custom comparator for ATNConfigs specifically for configLookup +func (c *ATNConfigComparator[T]) Equals2(o1, o2 ATNConfig) bool { + + // Same pointer, must be equal, even if both nil + // + if o1 == o2 { + return true + + } + + // If either are nil, but not both, then the result is false + // + if o1 == nil || o2 == nil { + return false + } + + return o1.GetState().GetStateNumber() == o2.GetState().GetStateNumber() && + o1.GetAlt() == o2.GetAlt() && + o1.GetSemanticContext().Equals(o2.GetSemanticContext()) +} + +// Hash1 is custom hash implementation for ATNConfigs specifically for configLookup +func (c *ATNConfigComparator[T]) Hash1(o ATNConfig) int { + hash := 7 + hash = 31*hash + o.GetState().GetStateNumber() + hash = 31*hash + o.GetAlt() + hash = 31*hash + o.GetSemanticContext().Hash() + return hash +} + +// ATNAltConfigComparator is used as the comparator for mapping configs to Alt Bitsets +type ATNAltConfigComparator[T Collectable[T]] struct { +} + +// Equals2 is a custom comparator for ATNConfigs specifically for configLookup +func (c *ATNAltConfigComparator[T]) Equals2(o1, o2 ATNConfig) bool { + + // Same pointer, must be equal, even if both nil + // + if o1 == o2 { + return true + + } + + // If either are nil, but not both, then the result is false + // + if o1 == nil || o2 == nil { + return false + } + + return o1.GetState().GetStateNumber() == o2.GetState().GetStateNumber() && + o1.GetContext().Equals(o2.GetContext()) +} + +// Hash1 is custom hash implementation for ATNConfigs specifically for configLookup +func (c *ATNAltConfigComparator[T]) Hash1(o ATNConfig) int { + h := murmurInit(7) + h = murmurUpdate(h, o.GetState().GetStateNumber()) + h = murmurUpdate(h, o.GetContext().Hash()) + return murmurFinish(h, 2) +} + +// BaseATNConfigComparator is used as the comparator for the configLookup field of a BaseATNConfigSet +// and has a custom Equals() and Hash() implementation, because equality is not based on the +// standard Hash() and Equals() methods of the ATNConfig type. +type BaseATNConfigComparator[T Collectable[T]] struct { +} + +// Equals2 is a custom comparator for ATNConfigs specifically for baseATNConfigSet +func (c *BaseATNConfigComparator[T]) Equals2(o1, o2 ATNConfig) bool { + + // Same pointer, must be equal, even if both nil + // + if o1 == o2 { + return true + + } + + // If either are nil, but not both, then the result is false + // + if o1 == nil || o2 == nil { + return false + } + + return o1.GetState().GetStateNumber() == o2.GetState().GetStateNumber() && + o1.GetAlt() == o2.GetAlt() && + o1.GetSemanticContext().Equals(o2.GetSemanticContext()) +} + +// Hash1 is custom hash implementation for ATNConfigs specifically for configLookup, but in fact just +// delegates to the standard Hash() method of the ATNConfig type. +func (c *BaseATNConfigComparator[T]) Hash1(o ATNConfig) int { + + return o.Hash() +} diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/dfa.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/dfa.go similarity index 80% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/dfa.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/dfa.go index d55a2a87d5..bfd43e1f73 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/dfa.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/dfa.go @@ -1,13 +1,9 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. package antlr -import ( - "sort" -) - type DFA struct { // atnStartState is the ATN state in which this was created atnStartState DecisionState @@ -15,8 +11,15 @@ type DFA struct { decision int // states is all the DFA states. Use Map to get the old state back; Set can only - // indicate whether it is there. - states map[int]*DFAState + // indicate whether it is there. Go maps implement key hash collisions and so on and are very + // good, but the DFAState is an object and can't be used directly as the key as it can in say JAva + // amd C#, whereby if the hashcode is the same for two objects, then Equals() is called against them + // to see if they really are the same object. + // + // + states *JStore[*DFAState, *ObjEqComparator[*DFAState]] + + numstates int s0 *DFAState @@ -29,7 +32,7 @@ func NewDFA(atnStartState DecisionState, decision int) *DFA { dfa := &DFA{ atnStartState: atnStartState, decision: decision, - states: make(map[int]*DFAState), + states: NewJStore[*DFAState, *ObjEqComparator[*DFAState]](dfaStateEqInst), } if s, ok := atnStartState.(*StarLoopEntryState); ok && s.precedenceRuleDecision { dfa.precedenceDfa = true @@ -92,7 +95,8 @@ func (d *DFA) getPrecedenceDfa() bool { // true or nil otherwise, and d.precedenceDfa is updated. func (d *DFA) setPrecedenceDfa(precedenceDfa bool) { if d.getPrecedenceDfa() != precedenceDfa { - d.setStates(make(map[int]*DFAState)) + d.states = NewJStore[*DFAState, *ObjEqComparator[*DFAState]](dfaStateEqInst) + d.numstates = 0 if precedenceDfa { precedenceState := NewDFAState(-1, NewBaseATNConfigSet(false)) @@ -117,38 +121,12 @@ func (d *DFA) setS0(s *DFAState) { d.s0 = s } -func (d *DFA) getState(hash int) (*DFAState, bool) { - s, ok := d.states[hash] - return s, ok -} - -func (d *DFA) setStates(states map[int]*DFAState) { - d.states = states -} - -func (d *DFA) setState(hash int, state *DFAState) { - d.states[hash] = state -} - -func (d *DFA) numStates() int { - return len(d.states) -} - -type dfaStateList []*DFAState - -func (d dfaStateList) Len() int { return len(d) } -func (d dfaStateList) Less(i, j int) bool { return d[i].stateNumber < d[j].stateNumber } -func (d dfaStateList) Swap(i, j int) { d[i], d[j] = d[j], d[i] } - // sortedStates returns the states in d sorted by their state number. func (d *DFA) sortedStates() []*DFAState { - vs := make([]*DFAState, 0, len(d.states)) - - for _, v := range d.states { - vs = append(vs, v) - } - sort.Sort(dfaStateList(vs)) + vs := d.states.SortedSlice(func(i, j *DFAState) bool { + return i.stateNumber < j.stateNumber + }) return vs } diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/dfa_serializer.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/dfa_serializer.go similarity index 97% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/dfa_serializer.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/dfa_serializer.go index bf2ccc06cd..84d0a31e53 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/dfa_serializer.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/dfa_serializer.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/dfa_state.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/dfa_state.go similarity index 90% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/dfa_state.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/dfa_state.go index 970ed19865..c90dec55c8 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/dfa_state.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/dfa_state.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. @@ -90,16 +90,16 @@ func NewDFAState(stateNumber int, configs ATNConfigSet) *DFAState { } // GetAltSet gets the set of all alts mentioned by all ATN configurations in d. -func (d *DFAState) GetAltSet() Set { - alts := newArray2DHashSet(nil, nil) +func (d *DFAState) GetAltSet() []int { + var alts []int if d.configs != nil { for _, c := range d.configs.GetItems() { - alts.Add(c.GetAlt()) + alts = append(alts, c.GetAlt()) } } - if alts.Len() == 0 { + if len(alts) == 0 { return nil } @@ -130,27 +130,6 @@ func (d *DFAState) setPrediction(v int) { d.prediction = v } -// equals returns whether d equals other. Two DFAStates are equal if their ATN -// configuration sets are the same. This method is used to see if a state -// already exists. -// -// Because the number of alternatives and number of ATN configurations are -// finite, there is a finite number of DFA states that can be processed. This is -// necessary to show that the algorithm terminates. -// -// Cannot test the DFA state numbers here because in -// ParserATNSimulator.addDFAState we need to know if any other state exists that -// has d exact set of ATN configurations. The stateNumber is irrelevant. -func (d *DFAState) equals(other interface{}) bool { - if d == other { - return true - } else if _, ok := other.(*DFAState); !ok { - return false - } - - return d.configs.Equals(other.(*DFAState).configs) -} - func (d *DFAState) String() string { var s string if d.isAcceptState { @@ -164,8 +143,27 @@ func (d *DFAState) String() string { return fmt.Sprintf("%d:%s%s", d.stateNumber, fmt.Sprint(d.configs), s) } -func (d *DFAState) hash() int { +func (d *DFAState) Hash() int { h := murmurInit(7) - h = murmurUpdate(h, d.configs.hash()) + h = murmurUpdate(h, d.configs.Hash()) return murmurFinish(h, 1) } + +// Equals returns whether d equals other. Two DFAStates are equal if their ATN +// configuration sets are the same. This method is used to see if a state +// already exists. +// +// Because the number of alternatives and number of ATN configurations are +// finite, there is a finite number of DFA states that can be processed. This is +// necessary to show that the algorithm terminates. +// +// Cannot test the DFA state numbers here because in +// ParserATNSimulator.addDFAState we need to know if any other state exists that +// has d exact set of ATN configurations. The stateNumber is irrelevant. +func (d *DFAState) Equals(o Collectable[*DFAState]) bool { + if d == o { + return true + } + + return d.configs.Equals(o.(*DFAState).configs) +} diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/diagnostic_error_listener.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/diagnostic_error_listener.go similarity index 98% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/diagnostic_error_listener.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/diagnostic_error_listener.go index 1fec43d9dc..c55bcc19b2 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/diagnostic_error_listener.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/diagnostic_error_listener.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. @@ -87,7 +87,6 @@ func (d *DiagnosticErrorListener) getDecisionDescription(recognizer Parser, dfa return strconv.Itoa(decision) + " (" + ruleName + ")" } -// // Computes the set of conflicting or ambiguous alternatives from a // configuration set, if that information was not already provided by the // parser. @@ -97,7 +96,6 @@ func (d *DiagnosticErrorListener) getDecisionDescription(recognizer Parser, dfa // @param configs The conflicting or ambiguous configuration set. // @return Returns {@code ReportedAlts} if it is not {@code nil}, otherwise // returns the set of alternatives represented in {@code configs}. -// func (d *DiagnosticErrorListener) getConflictingAlts(ReportedAlts *BitSet, set ATNConfigSet) *BitSet { if ReportedAlts != nil { return ReportedAlts diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/error_listener.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/error_listener.go similarity index 98% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/error_listener.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/error_listener.go index 028e1a9d7f..f679f0dcd5 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/error_listener.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/error_listener.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. @@ -48,12 +48,9 @@ func NewConsoleErrorListener() *ConsoleErrorListener { return new(ConsoleErrorListener) } -// // Provides a default instance of {@link ConsoleErrorListener}. -// var ConsoleErrorListenerINSTANCE = NewConsoleErrorListener() -// // {@inheritDoc} // //

@@ -64,7 +61,6 @@ var ConsoleErrorListenerINSTANCE = NewConsoleErrorListener() //

 // line line:charPositionInLine msg
 // 
-// func (c *ConsoleErrorListener) SyntaxError(recognizer Recognizer, offendingSymbol interface{}, line, column int, msg string, e RecognitionException) { fmt.Fprintln(os.Stderr, "line "+strconv.Itoa(line)+":"+strconv.Itoa(column)+" "+msg) } diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/error_strategy.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/error_strategy.go similarity index 99% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/error_strategy.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/error_strategy.go index c4080dbfd1..5c0a637ba4 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/error_strategy.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/error_strategy.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. @@ -23,7 +23,6 @@ type ErrorStrategy interface { // This is the default implementation of {@link ANTLRErrorStrategy} used for // error Reporting and recovery in ANTLR parsers. -// type DefaultErrorStrategy struct { errorRecoveryMode bool lastErrorIndex int @@ -61,12 +60,10 @@ func (d *DefaultErrorStrategy) reset(recognizer Parser) { d.endErrorCondition(recognizer) } -// // This method is called to enter error recovery mode when a recognition // exception is Reported. // // @param recognizer the parser instance -// func (d *DefaultErrorStrategy) beginErrorCondition(recognizer Parser) { d.errorRecoveryMode = true } @@ -75,28 +72,23 @@ func (d *DefaultErrorStrategy) InErrorRecoveryMode(recognizer Parser) bool { return d.errorRecoveryMode } -// // This method is called to leave error recovery mode after recovering from // a recognition exception. // // @param recognizer -// func (d *DefaultErrorStrategy) endErrorCondition(recognizer Parser) { d.errorRecoveryMode = false d.lastErrorStates = nil d.lastErrorIndex = -1 } -// // {@inheritDoc} // //

The default implementation simply calls {@link //endErrorCondition}.

-// func (d *DefaultErrorStrategy) ReportMatch(recognizer Parser) { d.endErrorCondition(recognizer) } -// // {@inheritDoc} // //

The default implementation returns immediately if the handler is already @@ -114,7 +106,6 @@ func (d *DefaultErrorStrategy) ReportMatch(recognizer Parser) { //

  • All other types: calls {@link Parser//NotifyErrorListeners} to Report // the exception
  • // -// func (d *DefaultErrorStrategy) ReportError(recognizer Parser, e RecognitionException) { // if we've already Reported an error and have not Matched a token // yet successfully, don't Report any errors. @@ -142,7 +133,6 @@ func (d *DefaultErrorStrategy) ReportError(recognizer Parser, e RecognitionExcep //

    The default implementation reSynchronizes the parser by consuming tokens // until we find one in the reSynchronization set--loosely the set of tokens // that can follow the current rule.

    -// func (d *DefaultErrorStrategy) Recover(recognizer Parser, e RecognitionException) { if d.lastErrorIndex == recognizer.GetInputStream().Index() && @@ -206,7 +196,6 @@ func (d *DefaultErrorStrategy) Recover(recognizer Parser, e RecognitionException // compare token set at the start of the loop and at each iteration. If for // some reason speed is suffering for you, you can turn off d // functionality by simply overriding d method as a blank { }.

    -// func (d *DefaultErrorStrategy) Sync(recognizer Parser) { // If already recovering, don't try to Sync if d.InErrorRecoveryMode(recognizer) { @@ -247,7 +236,6 @@ func (d *DefaultErrorStrategy) Sync(recognizer Parser) { // // @param recognizer the parser instance // @param e the recognition exception -// func (d *DefaultErrorStrategy) ReportNoViableAlternative(recognizer Parser, e *NoViableAltException) { tokens := recognizer.GetTokenStream() var input string @@ -264,7 +252,6 @@ func (d *DefaultErrorStrategy) ReportNoViableAlternative(recognizer Parser, e *N recognizer.NotifyErrorListeners(msg, e.offendingToken, e) } -// // This is called by {@link //ReportError} when the exception is an // {@link InputMisMatchException}. // @@ -272,14 +259,12 @@ func (d *DefaultErrorStrategy) ReportNoViableAlternative(recognizer Parser, e *N // // @param recognizer the parser instance // @param e the recognition exception -// func (this *DefaultErrorStrategy) ReportInputMisMatch(recognizer Parser, e *InputMisMatchException) { msg := "mismatched input " + this.GetTokenErrorDisplay(e.offendingToken) + " expecting " + e.getExpectedTokens().StringVerbose(recognizer.GetLiteralNames(), recognizer.GetSymbolicNames(), false) recognizer.NotifyErrorListeners(msg, e.offendingToken, e) } -// // This is called by {@link //ReportError} when the exception is a // {@link FailedPredicateException}. // @@ -287,7 +272,6 @@ func (this *DefaultErrorStrategy) ReportInputMisMatch(recognizer Parser, e *Inpu // // @param recognizer the parser instance // @param e the recognition exception -// func (d *DefaultErrorStrategy) ReportFailedPredicate(recognizer Parser, e *FailedPredicateException) { ruleName := recognizer.GetRuleNames()[recognizer.GetParserRuleContext().GetRuleIndex()] msg := "rule " + ruleName + " " + e.message @@ -310,7 +294,6 @@ func (d *DefaultErrorStrategy) ReportFailedPredicate(recognizer Parser, e *Faile // {@link Parser//NotifyErrorListeners}.

    // // @param recognizer the parser instance -// func (d *DefaultErrorStrategy) ReportUnwantedToken(recognizer Parser) { if d.InErrorRecoveryMode(recognizer) { return @@ -339,7 +322,6 @@ func (d *DefaultErrorStrategy) ReportUnwantedToken(recognizer Parser) { // {@link Parser//NotifyErrorListeners}.

    // // @param recognizer the parser instance -// func (d *DefaultErrorStrategy) ReportMissingToken(recognizer Parser) { if d.InErrorRecoveryMode(recognizer) { return @@ -392,15 +374,14 @@ func (d *DefaultErrorStrategy) ReportMissingToken(recognizer Parser) { // derivation: // //
    -// => ID '=' '(' INT ')' ('+' atom)* ''
    +// => ID '=' '(' INT ')' ('+' atom)* ”
     // ^
     // 
    // -// The attempt to Match {@code ')'} will fail when it sees {@code ''} and -// call {@link //recoverInline}. To recover, it sees that {@code LA(1)==''} +// The attempt to Match {@code ')'} will fail when it sees {@code ”} and +// call {@link //recoverInline}. To recover, it sees that {@code LA(1)==”} // is in the set of tokens that can follow the {@code ')'} token reference // in rule {@code atom}. It can assume that you forgot the {@code ')'}. -// func (d *DefaultErrorStrategy) RecoverInline(recognizer Parser) Token { // SINGLE TOKEN DELETION MatchedSymbol := d.SingleTokenDeletion(recognizer) @@ -418,7 +399,6 @@ func (d *DefaultErrorStrategy) RecoverInline(recognizer Parser) Token { panic(NewInputMisMatchException(recognizer)) } -// // This method implements the single-token insertion inline error recovery // strategy. It is called by {@link //recoverInline} if the single-token // deletion strategy fails to recover from the mismatched input. If this @@ -434,7 +414,6 @@ func (d *DefaultErrorStrategy) RecoverInline(recognizer Parser) Token { // @param recognizer the parser instance // @return {@code true} if single-token insertion is a viable recovery // strategy for the current mismatched input, otherwise {@code false} -// func (d *DefaultErrorStrategy) SingleTokenInsertion(recognizer Parser) bool { currentSymbolType := recognizer.GetTokenStream().LA(1) // if current token is consistent with what could come after current @@ -469,7 +448,6 @@ func (d *DefaultErrorStrategy) SingleTokenInsertion(recognizer Parser) bool { // @return the successfully Matched {@link Token} instance if single-token // deletion successfully recovers from the mismatched input, otherwise // {@code nil} -// func (d *DefaultErrorStrategy) SingleTokenDeletion(recognizer Parser) Token { NextTokenType := recognizer.GetTokenStream().LA(2) expecting := d.GetExpectedTokens(recognizer) @@ -507,7 +485,6 @@ func (d *DefaultErrorStrategy) SingleTokenDeletion(recognizer Parser) Token { // a CommonToken of the appropriate type. The text will be the token. // If you change what tokens must be created by the lexer, // override d method to create the appropriate tokens. -// func (d *DefaultErrorStrategy) GetMissingSymbol(recognizer Parser) Token { currentSymbol := recognizer.GetCurrentToken() expecting := d.GetExpectedTokens(recognizer) @@ -546,7 +523,6 @@ func (d *DefaultErrorStrategy) GetExpectedTokens(recognizer Parser) *IntervalSet // the token). This is better than forcing you to override a method in // your token objects because you don't have to go modify your lexer // so that it creates a NewJava type. -// func (d *DefaultErrorStrategy) GetTokenErrorDisplay(t Token) string { if t == nil { return "" @@ -578,7 +554,7 @@ func (d *DefaultErrorStrategy) escapeWSAndQuote(s string) string { // from within the rule i.e., the FIRST computation done by // ANTLR stops at the end of a rule. // -// EXAMPLE +// # EXAMPLE // // When you find a "no viable alt exception", the input is not // consistent with any of the alternatives for rule r. The best @@ -597,7 +573,6 @@ func (d *DefaultErrorStrategy) escapeWSAndQuote(s string) string { // c : ID // | INT // -// // At each rule invocation, the set of tokens that could follow // that rule is pushed on a stack. Here are the various // context-sensitive follow sets: @@ -660,7 +635,6 @@ func (d *DefaultErrorStrategy) escapeWSAndQuote(s string) string { // // Like Grosch I implement context-sensitive FOLLOW sets that are combined // at run-time upon error to avoid overhead during parsing. -// func (d *DefaultErrorStrategy) getErrorRecoverySet(recognizer Parser) *IntervalSet { atn := recognizer.GetInterpreter().atn ctx := recognizer.GetParserRuleContext() @@ -733,7 +707,6 @@ func NewBailErrorStrategy() *BailErrorStrategy { // in a {@link ParseCancellationException} so it is not caught by the // rule func catches. Use {@link Exception//getCause()} to get the // original {@link RecognitionException}. -// func (b *BailErrorStrategy) Recover(recognizer Parser, e RecognitionException) { context := recognizer.GetParserRuleContext() for context != nil { @@ -749,7 +722,6 @@ func (b *BailErrorStrategy) Recover(recognizer Parser, e RecognitionException) { // Make sure we don't attempt to recover inline if the parser // successfully recovers, it won't panic an exception. -// func (b *BailErrorStrategy) RecoverInline(recognizer Parser) Token { b.Recover(recognizer, NewInputMisMatchException(recognizer)) diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/errors.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/errors.go new file mode 100644 index 0000000000..3954c13782 --- /dev/null +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/errors.go @@ -0,0 +1,238 @@ +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. +// Use of this file is governed by the BSD 3-clause license that +// can be found in the LICENSE.txt file in the project root. + +package antlr + +// The root of the ANTLR exception hierarchy. In general, ANTLR tracks just +// 3 kinds of errors: prediction errors, failed predicate errors, and +// mismatched input errors. In each case, the parser knows where it is +// in the input, where it is in the ATN, the rule invocation stack, +// and what kind of problem occurred. + +type RecognitionException interface { + GetOffendingToken() Token + GetMessage() string + GetInputStream() IntStream +} + +type BaseRecognitionException struct { + message string + recognizer Recognizer + offendingToken Token + offendingState int + ctx RuleContext + input IntStream +} + +func NewBaseRecognitionException(message string, recognizer Recognizer, input IntStream, ctx RuleContext) *BaseRecognitionException { + + // todo + // Error.call(this) + // + // if (!!Error.captureStackTrace) { + // Error.captureStackTrace(this, RecognitionException) + // } else { + // stack := NewError().stack + // } + // TODO may be able to use - "runtime" func Stack(buf []byte, all bool) int + + t := new(BaseRecognitionException) + + t.message = message + t.recognizer = recognizer + t.input = input + t.ctx = ctx + // The current {@link Token} when an error occurred. Since not all streams + // support accessing symbols by index, we have to track the {@link Token} + // instance itself. + t.offendingToken = nil + // Get the ATN state number the parser was in at the time the error + // occurred. For {@link NoViableAltException} and + // {@link LexerNoViableAltException} exceptions, this is the + // {@link DecisionState} number. For others, it is the state whose outgoing + // edge we couldn't Match. + t.offendingState = -1 + if t.recognizer != nil { + t.offendingState = t.recognizer.GetState() + } + + return t +} + +func (b *BaseRecognitionException) GetMessage() string { + return b.message +} + +func (b *BaseRecognitionException) GetOffendingToken() Token { + return b.offendingToken +} + +func (b *BaseRecognitionException) GetInputStream() IntStream { + return b.input +} + +//

    If the state number is not known, b method returns -1.

    + +// Gets the set of input symbols which could potentially follow the +// previously Matched symbol at the time b exception was panicn. +// +//

    If the set of expected tokens is not known and could not be computed, +// b method returns {@code nil}.

    +// +// @return The set of token types that could potentially follow the current +// state in the ATN, or {@code nil} if the information is not available. +// / +func (b *BaseRecognitionException) getExpectedTokens() *IntervalSet { + if b.recognizer != nil { + return b.recognizer.GetATN().getExpectedTokens(b.offendingState, b.ctx) + } + + return nil +} + +func (b *BaseRecognitionException) String() string { + return b.message +} + +type LexerNoViableAltException struct { + *BaseRecognitionException + + startIndex int + deadEndConfigs ATNConfigSet +} + +func NewLexerNoViableAltException(lexer Lexer, input CharStream, startIndex int, deadEndConfigs ATNConfigSet) *LexerNoViableAltException { + + l := new(LexerNoViableAltException) + + l.BaseRecognitionException = NewBaseRecognitionException("", lexer, input, nil) + + l.startIndex = startIndex + l.deadEndConfigs = deadEndConfigs + + return l +} + +func (l *LexerNoViableAltException) String() string { + symbol := "" + if l.startIndex >= 0 && l.startIndex < l.input.Size() { + symbol = l.input.(CharStream).GetTextFromInterval(NewInterval(l.startIndex, l.startIndex)) + } + return "LexerNoViableAltException" + symbol +} + +type NoViableAltException struct { + *BaseRecognitionException + + startToken Token + offendingToken Token + ctx ParserRuleContext + deadEndConfigs ATNConfigSet +} + +// Indicates that the parser could not decide which of two or more paths +// to take based upon the remaining input. It tracks the starting token +// of the offending input and also knows where the parser was +// in the various paths when the error. Reported by ReportNoViableAlternative() +func NewNoViableAltException(recognizer Parser, input TokenStream, startToken Token, offendingToken Token, deadEndConfigs ATNConfigSet, ctx ParserRuleContext) *NoViableAltException { + + if ctx == nil { + ctx = recognizer.GetParserRuleContext() + } + + if offendingToken == nil { + offendingToken = recognizer.GetCurrentToken() + } + + if startToken == nil { + startToken = recognizer.GetCurrentToken() + } + + if input == nil { + input = recognizer.GetInputStream().(TokenStream) + } + + n := new(NoViableAltException) + n.BaseRecognitionException = NewBaseRecognitionException("", recognizer, input, ctx) + + // Which configurations did we try at input.Index() that couldn't Match + // input.LT(1)?// + n.deadEndConfigs = deadEndConfigs + // The token object at the start index the input stream might + // not be buffering tokens so get a reference to it. (At the + // time the error occurred, of course the stream needs to keep a + // buffer all of the tokens but later we might not have access to those.) + n.startToken = startToken + n.offendingToken = offendingToken + + return n +} + +type InputMisMatchException struct { + *BaseRecognitionException +} + +// This signifies any kind of mismatched input exceptions such as +// when the current input does not Match the expected token. +func NewInputMisMatchException(recognizer Parser) *InputMisMatchException { + + i := new(InputMisMatchException) + i.BaseRecognitionException = NewBaseRecognitionException("", recognizer, recognizer.GetInputStream(), recognizer.GetParserRuleContext()) + + i.offendingToken = recognizer.GetCurrentToken() + + return i + +} + +// A semantic predicate failed during validation. Validation of predicates +// occurs when normally parsing the alternative just like Matching a token. +// Disambiguating predicate evaluation occurs when we test a predicate during +// prediction. + +type FailedPredicateException struct { + *BaseRecognitionException + + ruleIndex int + predicateIndex int + predicate string +} + +func NewFailedPredicateException(recognizer Parser, predicate string, message string) *FailedPredicateException { + + f := new(FailedPredicateException) + + f.BaseRecognitionException = NewBaseRecognitionException(f.formatMessage(predicate, message), recognizer, recognizer.GetInputStream(), recognizer.GetParserRuleContext()) + + s := recognizer.GetInterpreter().atn.states[recognizer.GetState()] + trans := s.GetTransitions()[0] + if trans2, ok := trans.(*PredicateTransition); ok { + f.ruleIndex = trans2.ruleIndex + f.predicateIndex = trans2.predIndex + } else { + f.ruleIndex = 0 + f.predicateIndex = 0 + } + f.predicate = predicate + f.offendingToken = recognizer.GetCurrentToken() + + return f +} + +func (f *FailedPredicateException) formatMessage(predicate, message string) string { + if message != "" { + return message + } + + return "failed predicate: {" + predicate + "}?" +} + +type ParseCancellationException struct { +} + +func NewParseCancellationException() *ParseCancellationException { + // Error.call(this) + // Error.captureStackTrace(this, ParseCancellationException) + return new(ParseCancellationException) +} diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/file_stream.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/file_stream.go similarity index 92% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/file_stream.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/file_stream.go index 842170c086..bd6ad5efe3 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/file_stream.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/file_stream.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/input_stream.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/input_stream.go similarity index 96% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/input_stream.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/input_stream.go index 5ff270f536..a8b889cedb 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/input_stream.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/input_stream.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/int_stream.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/int_stream.go similarity index 82% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/int_stream.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/int_stream.go index 438e0ea6e7..4778878bd0 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/int_stream.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/int_stream.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/interval_set.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/interval_set.go similarity index 98% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/interval_set.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/interval_set.go index 1e9393adb6..c1e155e818 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/interval_set.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/interval_set.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. @@ -223,6 +223,10 @@ func (i *IntervalSet) StringVerbose(literalNames []string, symbolicNames []strin return i.toIndexString() } +func (i *IntervalSet) GetIntervals() []*Interval { + return i.intervals +} + func (i *IntervalSet) toCharString() string { names := make([]string, len(i.intervals)) diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/jcollect.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/jcollect.go new file mode 100644 index 0000000000..e5a74f0c6c --- /dev/null +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/jcollect.go @@ -0,0 +1,198 @@ +package antlr + +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. +// Use of this file is governed by the BSD 3-clause license that +// can be found in the LICENSE.txt file in the project root. + +import ( + "sort" +) + +// Collectable is an interface that a struct should implement if it is to be +// usable as a key in these collections. +type Collectable[T any] interface { + Hash() int + Equals(other Collectable[T]) bool +} + +type Comparator[T any] interface { + Hash1(o T) int + Equals2(T, T) bool +} + +// JStore implements a container that allows the use of a struct to calculate the key +// for a collection of values akin to map. This is not meant to be a full-blown HashMap but just +// serve the needs of the ANTLR Go runtime. +// +// For ease of porting the logic of the runtime from the master target (Java), this collection +// operates in a similar way to Java, in that it can use any struct that supplies a Hash() and Equals() +// function as the key. The values are stored in a standard go map which internally is a form of hashmap +// itself, the key for the go map is the hash supplied by the key object. The collection is able to deal with +// hash conflicts by using a simple slice of values associated with the hash code indexed bucket. That isn't +// particularly efficient, but it is simple, and it works. As this is specifically for the ANTLR runtime, and +// we understand the requirements, then this is fine - this is not a general purpose collection. +type JStore[T any, C Comparator[T]] struct { + store map[int][]T + len int + comparator Comparator[T] +} + +func NewJStore[T any, C Comparator[T]](comparator Comparator[T]) *JStore[T, C] { + + if comparator == nil { + panic("comparator cannot be nil") + } + + s := &JStore[T, C]{ + store: make(map[int][]T, 1), + comparator: comparator, + } + return s +} + +// Put will store given value in the collection. Note that the key for storage is generated from +// the value itself - this is specifically because that is what ANTLR needs - this would not be useful +// as any kind of general collection. +// +// If the key has a hash conflict, then the value will be added to the slice of values associated with the +// hash, unless the value is already in the slice, in which case the existing value is returned. Value equivalence is +// tested by calling the equals() method on the key. +// +// # If the given value is already present in the store, then the existing value is returned as v and exists is set to true +// +// If the given value is not present in the store, then the value is added to the store and returned as v and exists is set to false. +func (s *JStore[T, C]) Put(value T) (v T, exists bool) { //nolint:ireturn + + kh := s.comparator.Hash1(value) + + for _, v1 := range s.store[kh] { + if s.comparator.Equals2(value, v1) { + return v1, true + } + } + s.store[kh] = append(s.store[kh], value) + s.len++ + return value, false +} + +// Get will return the value associated with the key - the type of the key is the same type as the value +// which would not generally be useful, but this is a specific thing for ANTLR where the key is +// generated using the object we are going to store. +func (s *JStore[T, C]) Get(key T) (T, bool) { //nolint:ireturn + + kh := s.comparator.Hash1(key) + + for _, v := range s.store[kh] { + if s.comparator.Equals2(key, v) { + return v, true + } + } + return key, false +} + +// Contains returns true if the given key is present in the store +func (s *JStore[T, C]) Contains(key T) bool { //nolint:ireturn + + _, present := s.Get(key) + return present +} + +func (s *JStore[T, C]) SortedSlice(less func(i, j T) bool) []T { + vs := make([]T, 0, len(s.store)) + for _, v := range s.store { + vs = append(vs, v...) + } + sort.Slice(vs, func(i, j int) bool { + return less(vs[i], vs[j]) + }) + + return vs +} + +func (s *JStore[T, C]) Each(f func(T) bool) { + for _, e := range s.store { + for _, v := range e { + f(v) + } + } +} + +func (s *JStore[T, C]) Len() int { + return s.len +} + +func (s *JStore[T, C]) Values() []T { + vs := make([]T, 0, len(s.store)) + for _, e := range s.store { + for _, v := range e { + vs = append(vs, v) + } + } + return vs +} + +type entry[K, V any] struct { + key K + val V +} + +type JMap[K, V any, C Comparator[K]] struct { + store map[int][]*entry[K, V] + len int + comparator Comparator[K] +} + +func NewJMap[K, V any, C Comparator[K]](comparator Comparator[K]) *JMap[K, V, C] { + return &JMap[K, V, C]{ + store: make(map[int][]*entry[K, V], 1), + comparator: comparator, + } +} + +func (m *JMap[K, V, C]) Put(key K, val V) { + kh := m.comparator.Hash1(key) + + m.store[kh] = append(m.store[kh], &entry[K, V]{key, val}) + m.len++ +} + +func (m *JMap[K, V, C]) Values() []V { + vs := make([]V, 0, len(m.store)) + for _, e := range m.store { + for _, v := range e { + vs = append(vs, v.val) + } + } + return vs +} + +func (m *JMap[K, V, C]) Get(key K) (V, bool) { + + var none V + kh := m.comparator.Hash1(key) + for _, e := range m.store[kh] { + if m.comparator.Equals2(e.key, key) { + return e.val, true + } + } + return none, false +} + +func (m *JMap[K, V, C]) Len() int { + return len(m.store) +} + +func (m *JMap[K, V, C]) Delete(key K) { + kh := m.comparator.Hash1(key) + for i, e := range m.store[kh] { + if m.comparator.Equals2(e.key, key) { + m.store[kh] = append(m.store[kh][:i], m.store[kh][i+1:]...) + m.len-- + return + } + } +} + +func (m *JMap[K, V, C]) Clear() { + m.store = make(map[int][]*entry[K, V]) +} diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/lexer.go similarity index 98% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/lexer.go index b04f04572f..6533f05164 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/lexer.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. @@ -232,8 +232,6 @@ func (b *BaseLexer) NextToken() Token { } return b.token } - - return nil } // Instruct the lexer to Skip creating a token for current lexer rule @@ -342,7 +340,7 @@ func (b *BaseLexer) GetCharIndex() int { } // Return the text Matched so far for the current token or any text override. -//Set the complete text of l token it wipes any previous changes to the text. +// Set the complete text of l token it wipes any previous changes to the text. func (b *BaseLexer) GetText() string { if b.text != "" { return b.text diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer_action.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/lexer_action.go similarity index 91% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer_action.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/lexer_action.go index 5a325be137..111656c295 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer_action.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/lexer_action.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. @@ -21,8 +21,8 @@ type LexerAction interface { getActionType() int getIsPositionDependent() bool execute(lexer Lexer) - hash() int - equals(other LexerAction) bool + Hash() int + Equals(other LexerAction) bool } type BaseLexerAction struct { @@ -51,15 +51,14 @@ func (b *BaseLexerAction) getIsPositionDependent() bool { return b.isPositionDependent } -func (b *BaseLexerAction) hash() int { +func (b *BaseLexerAction) Hash() int { return b.actionType } -func (b *BaseLexerAction) equals(other LexerAction) bool { +func (b *BaseLexerAction) Equals(other LexerAction) bool { return b == other } -// // Implements the {@code Skip} lexer action by calling {@link Lexer//Skip}. // //

    The {@code Skip} command does not have any parameters, so l action is @@ -85,7 +84,8 @@ func (l *LexerSkipAction) String() string { return "skip" } -// Implements the {@code type} lexer action by calling {@link Lexer//setType} +// Implements the {@code type} lexer action by calling {@link Lexer//setType} +// // with the assigned type. type LexerTypeAction struct { *BaseLexerAction @@ -104,14 +104,14 @@ func (l *LexerTypeAction) execute(lexer Lexer) { lexer.SetType(l.thetype) } -func (l *LexerTypeAction) hash() int { +func (l *LexerTypeAction) Hash() int { h := murmurInit(0) h = murmurUpdate(h, l.actionType) h = murmurUpdate(h, l.thetype) return murmurFinish(h, 2) } -func (l *LexerTypeAction) equals(other LexerAction) bool { +func (l *LexerTypeAction) Equals(other LexerAction) bool { if l == other { return true } else if _, ok := other.(*LexerTypeAction); !ok { @@ -148,14 +148,14 @@ func (l *LexerPushModeAction) execute(lexer Lexer) { lexer.PushMode(l.mode) } -func (l *LexerPushModeAction) hash() int { +func (l *LexerPushModeAction) Hash() int { h := murmurInit(0) h = murmurUpdate(h, l.actionType) h = murmurUpdate(h, l.mode) return murmurFinish(h, 2) } -func (l *LexerPushModeAction) equals(other LexerAction) bool { +func (l *LexerPushModeAction) Equals(other LexerAction) bool { if l == other { return true } else if _, ok := other.(*LexerPushModeAction); !ok { @@ -245,14 +245,14 @@ func (l *LexerModeAction) execute(lexer Lexer) { lexer.SetMode(l.mode) } -func (l *LexerModeAction) hash() int { +func (l *LexerModeAction) Hash() int { h := murmurInit(0) h = murmurUpdate(h, l.actionType) h = murmurUpdate(h, l.mode) return murmurFinish(h, 2) } -func (l *LexerModeAction) equals(other LexerAction) bool { +func (l *LexerModeAction) Equals(other LexerAction) bool { if l == other { return true } else if _, ok := other.(*LexerModeAction); !ok { @@ -303,7 +303,7 @@ func (l *LexerCustomAction) execute(lexer Lexer) { lexer.Action(nil, l.ruleIndex, l.actionIndex) } -func (l *LexerCustomAction) hash() int { +func (l *LexerCustomAction) Hash() int { h := murmurInit(0) h = murmurUpdate(h, l.actionType) h = murmurUpdate(h, l.ruleIndex) @@ -311,13 +311,14 @@ func (l *LexerCustomAction) hash() int { return murmurFinish(h, 3) } -func (l *LexerCustomAction) equals(other LexerAction) bool { +func (l *LexerCustomAction) Equals(other LexerAction) bool { if l == other { return true } else if _, ok := other.(*LexerCustomAction); !ok { return false } else { - return l.ruleIndex == other.(*LexerCustomAction).ruleIndex && l.actionIndex == other.(*LexerCustomAction).actionIndex + return l.ruleIndex == other.(*LexerCustomAction).ruleIndex && + l.actionIndex == other.(*LexerCustomAction).actionIndex } } @@ -344,14 +345,14 @@ func (l *LexerChannelAction) execute(lexer Lexer) { lexer.SetChannel(l.channel) } -func (l *LexerChannelAction) hash() int { +func (l *LexerChannelAction) Hash() int { h := murmurInit(0) h = murmurUpdate(h, l.actionType) h = murmurUpdate(h, l.channel) return murmurFinish(h, 2) } -func (l *LexerChannelAction) equals(other LexerAction) bool { +func (l *LexerChannelAction) Equals(other LexerAction) bool { if l == other { return true } else if _, ok := other.(*LexerChannelAction); !ok { @@ -412,10 +413,10 @@ func (l *LexerIndexedCustomAction) execute(lexer Lexer) { l.lexerAction.execute(lexer) } -func (l *LexerIndexedCustomAction) hash() int { +func (l *LexerIndexedCustomAction) Hash() int { h := murmurInit(0) h = murmurUpdate(h, l.offset) - h = murmurUpdate(h, l.lexerAction.hash()) + h = murmurUpdate(h, l.lexerAction.Hash()) return murmurFinish(h, 2) } @@ -425,6 +426,7 @@ func (l *LexerIndexedCustomAction) equals(other LexerAction) bool { } else if _, ok := other.(*LexerIndexedCustomAction); !ok { return false } else { - return l.offset == other.(*LexerIndexedCustomAction).offset && l.lexerAction == other.(*LexerIndexedCustomAction).lexerAction + return l.offset == other.(*LexerIndexedCustomAction).offset && + l.lexerAction.Equals(other.(*LexerIndexedCustomAction).lexerAction) } } diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer_action_executor.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/lexer_action_executor.go similarity index 88% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer_action_executor.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/lexer_action_executor.go index 056941dd6e..be1ba7a7e3 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer_action_executor.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/lexer_action_executor.go @@ -1,9 +1,11 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. package antlr +import "golang.org/x/exp/slices" + // Represents an executor for a sequence of lexer actions which traversed during // the Matching operation of a lexer rule (token). // @@ -12,8 +14,8 @@ package antlr // not cause bloating of the {@link DFA} created for the lexer.

    type LexerActionExecutor struct { - lexerActions []LexerAction - cachedHash int + lexerActions []LexerAction + cachedHash int } func NewLexerActionExecutor(lexerActions []LexerAction) *LexerActionExecutor { @@ -30,7 +32,7 @@ func NewLexerActionExecutor(lexerActions []LexerAction) *LexerActionExecutor { // of the performance-critical {@link LexerATNConfig//hashCode} operation. l.cachedHash = murmurInit(57) for _, a := range lexerActions { - l.cachedHash = murmurUpdate(l.cachedHash, a.hash()) + l.cachedHash = murmurUpdate(l.cachedHash, a.Hash()) } return l @@ -151,14 +153,17 @@ func (l *LexerActionExecutor) execute(lexer Lexer, input CharStream, startIndex } } -func (l *LexerActionExecutor) hash() int { +func (l *LexerActionExecutor) Hash() int { if l == nil { + // TODO: Why is this here? l should not be nil return 61 } + + // TODO: This is created from the action itself when the struct is created - will this be an issue at some point? Java uses the runtime assign hashcode return l.cachedHash } -func (l *LexerActionExecutor) equals(other interface{}) bool { +func (l *LexerActionExecutor) Equals(other interface{}) bool { if l == other { return true } @@ -169,5 +174,13 @@ func (l *LexerActionExecutor) equals(other interface{}) bool { if othert == nil { return false } - return l.cachedHash == othert.cachedHash && &l.lexerActions == &othert.lexerActions + if l.cachedHash != othert.cachedHash { + return false + } + if len(l.lexerActions) != len(othert.lexerActions) { + return false + } + return slices.EqualFunc(l.lexerActions, othert.lexerActions, func(i, j LexerAction) bool { + return i.Equals(j) + }) } diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer_atn_simulator.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/lexer_atn_simulator.go similarity index 98% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer_atn_simulator.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/lexer_atn_simulator.go index dc05153ea4..c573b75210 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/lexer_atn_simulator.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/lexer_atn_simulator.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. @@ -591,19 +591,24 @@ func (l *LexerATNSimulator) addDFAState(configs ATNConfigSet, suppressEdge bool) proposed.lexerActionExecutor = firstConfigWithRuleStopState.(*LexerATNConfig).lexerActionExecutor proposed.setPrediction(l.atn.ruleToTokenType[firstConfigWithRuleStopState.GetState().GetRuleIndex()]) } - hash := proposed.hash() dfa := l.decisionToDFA[l.mode] l.atn.stateMu.Lock() defer l.atn.stateMu.Unlock() - existing, ok := dfa.getState(hash) - if ok { + existing, present := dfa.states.Get(proposed) + if present { + + // This state was already present, so just return it. + // proposed = existing } else { - proposed.stateNumber = dfa.numStates() + + // We need to add the new state + // + proposed.stateNumber = dfa.states.Len() configs.SetReadOnly(true) proposed.configs = configs - dfa.setState(hash, proposed) + dfa.states.Put(proposed) } if !suppressEdge { dfa.setS0(proposed) diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/ll1_analyzer.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/ll1_analyzer.go similarity index 87% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/ll1_analyzer.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/ll1_analyzer.go index 6ffb37de69..76689615a6 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/ll1_analyzer.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/ll1_analyzer.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. @@ -14,14 +14,15 @@ func NewLL1Analyzer(atn *ATN) *LL1Analyzer { return la } -//* Special value added to the lookahead sets to indicate that we hit -// a predicate during analysis if {@code seeThruPreds==false}. -/// +// - Special value added to the lookahead sets to indicate that we hit +// a predicate during analysis if {@code seeThruPreds==false}. +// +// / const ( LL1AnalyzerHitPred = TokenInvalidType ) -//* +// * // Calculates the SLL(1) expected lookahead set for each outgoing transition // of an {@link ATNState}. The returned array has one element for each // outgoing transition in {@code s}. If the closure from transition @@ -38,7 +39,7 @@ func (la *LL1Analyzer) getDecisionLookahead(s ATNState) []*IntervalSet { look := make([]*IntervalSet, count) for alt := 0; alt < count; alt++ { look[alt] = NewIntervalSet() - lookBusy := newArray2DHashSet(nil, nil) + lookBusy := NewJStore[ATNConfig, Comparator[ATNConfig]](aConfEqInst) seeThruPreds := false // fail to get lookahead upon pred la.look1(s.GetTransitions()[alt].getTarget(), nil, BasePredictionContextEMPTY, look[alt], lookBusy, NewBitSet(), seeThruPreds, false) // Wipe out lookahead for la alternative if we found nothing @@ -50,7 +51,7 @@ func (la *LL1Analyzer) getDecisionLookahead(s ATNState) []*IntervalSet { return look } -//* +// * // Compute set of tokens that can follow {@code s} in the ATN in the // specified {@code ctx}. // @@ -67,7 +68,7 @@ func (la *LL1Analyzer) getDecisionLookahead(s ATNState) []*IntervalSet { // // @return The set of tokens that can follow {@code s} in the ATN in the // specified {@code ctx}. -/// +// / func (la *LL1Analyzer) Look(s, stopState ATNState, ctx RuleContext) *IntervalSet { r := NewIntervalSet() seeThruPreds := true // ignore preds get all lookahead @@ -75,7 +76,7 @@ func (la *LL1Analyzer) Look(s, stopState ATNState, ctx RuleContext) *IntervalSet if ctx != nil { lookContext = predictionContextFromRuleContext(s.GetATN(), ctx) } - la.look1(s, stopState, lookContext, r, newArray2DHashSet(nil, nil), NewBitSet(), seeThruPreds, true) + la.look1(s, stopState, lookContext, r, NewJStore[ATNConfig, Comparator[ATNConfig]](aConfEqInst), NewBitSet(), seeThruPreds, true) return r } @@ -109,14 +110,14 @@ func (la *LL1Analyzer) Look(s, stopState ATNState, ctx RuleContext) *IntervalSet // outermost context is reached. This parameter has no effect if {@code ctx} // is {@code nil}. -func (la *LL1Analyzer) look2(s, stopState ATNState, ctx PredictionContext, look *IntervalSet, lookBusy Set, calledRuleStack *BitSet, seeThruPreds, addEOF bool, i int) { +func (la *LL1Analyzer) look2(s, stopState ATNState, ctx PredictionContext, look *IntervalSet, lookBusy *JStore[ATNConfig, Comparator[ATNConfig]], calledRuleStack *BitSet, seeThruPreds, addEOF bool, i int) { returnState := la.atn.states[ctx.getReturnState(i)] la.look1(returnState, stopState, ctx.GetParent(i), look, lookBusy, calledRuleStack, seeThruPreds, addEOF) } -func (la *LL1Analyzer) look1(s, stopState ATNState, ctx PredictionContext, look *IntervalSet, lookBusy Set, calledRuleStack *BitSet, seeThruPreds, addEOF bool) { +func (la *LL1Analyzer) look1(s, stopState ATNState, ctx PredictionContext, look *IntervalSet, lookBusy *JStore[ATNConfig, Comparator[ATNConfig]], calledRuleStack *BitSet, seeThruPreds, addEOF bool) { c := NewBaseATNConfig6(s, 0, ctx) @@ -124,8 +125,11 @@ func (la *LL1Analyzer) look1(s, stopState ATNState, ctx PredictionContext, look return } - lookBusy.Add(c) + _, present := lookBusy.Put(c) + if present { + return + } if s == stopState { if ctx == nil { look.addOne(TokenEpsilon) @@ -198,7 +202,7 @@ func (la *LL1Analyzer) look1(s, stopState ATNState, ctx PredictionContext, look } } -func (la *LL1Analyzer) look3(stopState ATNState, ctx PredictionContext, look *IntervalSet, lookBusy Set, calledRuleStack *BitSet, seeThruPreds, addEOF bool, t1 *RuleTransition) { +func (la *LL1Analyzer) look3(stopState ATNState, ctx PredictionContext, look *IntervalSet, lookBusy *JStore[ATNConfig, Comparator[ATNConfig]], calledRuleStack *BitSet, seeThruPreds, addEOF bool, t1 *RuleTransition) { newContext := SingletonBasePredictionContextCreate(ctx, t1.followState.GetStateNumber()) diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/parser.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/parser.go new file mode 100644 index 0000000000..d26bf06392 --- /dev/null +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/parser.go @@ -0,0 +1,708 @@ +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. +// Use of this file is governed by the BSD 3-clause license that +// can be found in the LICENSE.txt file in the project root. + +package antlr + +import ( + "fmt" + "strconv" +) + +type Parser interface { + Recognizer + + GetInterpreter() *ParserATNSimulator + + GetTokenStream() TokenStream + GetTokenFactory() TokenFactory + GetParserRuleContext() ParserRuleContext + SetParserRuleContext(ParserRuleContext) + Consume() Token + GetParseListeners() []ParseTreeListener + + GetErrorHandler() ErrorStrategy + SetErrorHandler(ErrorStrategy) + GetInputStream() IntStream + GetCurrentToken() Token + GetExpectedTokens() *IntervalSet + NotifyErrorListeners(string, Token, RecognitionException) + IsExpectedToken(int) bool + GetPrecedence() int + GetRuleInvocationStack(ParserRuleContext) []string +} + +type BaseParser struct { + *BaseRecognizer + + Interpreter *ParserATNSimulator + BuildParseTrees bool + + input TokenStream + errHandler ErrorStrategy + precedenceStack IntStack + ctx ParserRuleContext + + tracer *TraceListener + parseListeners []ParseTreeListener + _SyntaxErrors int +} + +// p.is all the parsing support code essentially most of it is error +// recovery stuff.// +func NewBaseParser(input TokenStream) *BaseParser { + + p := new(BaseParser) + + p.BaseRecognizer = NewBaseRecognizer() + + // The input stream. + p.input = nil + // The error handling strategy for the parser. The default value is a new + // instance of {@link DefaultErrorStrategy}. + p.errHandler = NewDefaultErrorStrategy() + p.precedenceStack = make([]int, 0) + p.precedenceStack.Push(0) + // The {@link ParserRuleContext} object for the currently executing rule. + // p.is always non-nil during the parsing process. + p.ctx = nil + // Specifies whether or not the parser should construct a parse tree during + // the parsing process. The default value is {@code true}. + p.BuildParseTrees = true + // When {@link //setTrace}{@code (true)} is called, a reference to the + // {@link TraceListener} is stored here so it can be easily removed in a + // later call to {@link //setTrace}{@code (false)}. The listener itself is + // implemented as a parser listener so p.field is not directly used by + // other parser methods. + p.tracer = nil + // The list of {@link ParseTreeListener} listeners registered to receive + // events during the parse. + p.parseListeners = nil + // The number of syntax errors Reported during parsing. p.value is + // incremented each time {@link //NotifyErrorListeners} is called. + p._SyntaxErrors = 0 + p.SetInputStream(input) + + return p +} + +// p.field maps from the serialized ATN string to the deserialized {@link +// ATN} with +// bypass alternatives. +// +// @see ATNDeserializationOptions//isGenerateRuleBypassTransitions() +var bypassAltsAtnCache = make(map[string]int) + +// reset the parser's state// +func (p *BaseParser) reset() { + if p.input != nil { + p.input.Seek(0) + } + p.errHandler.reset(p) + p.ctx = nil + p._SyntaxErrors = 0 + p.SetTrace(nil) + p.precedenceStack = make([]int, 0) + p.precedenceStack.Push(0) + if p.Interpreter != nil { + p.Interpreter.reset() + } +} + +func (p *BaseParser) GetErrorHandler() ErrorStrategy { + return p.errHandler +} + +func (p *BaseParser) SetErrorHandler(e ErrorStrategy) { + p.errHandler = e +} + +// Match current input symbol against {@code ttype}. If the symbol type +// Matches, {@link ANTLRErrorStrategy//ReportMatch} and {@link //consume} are +// called to complete the Match process. +// +//

    If the symbol type does not Match, +// {@link ANTLRErrorStrategy//recoverInline} is called on the current error +// strategy to attempt recovery. If {@link //getBuildParseTree} is +// {@code true} and the token index of the symbol returned by +// {@link ANTLRErrorStrategy//recoverInline} is -1, the symbol is added to +// the parse tree by calling {@link ParserRuleContext//addErrorNode}.

    +// +// @param ttype the token type to Match +// @return the Matched symbol +// @panics RecognitionException if the current input symbol did not Match +// {@code ttype} and the error strategy could not recover from the +// mismatched symbol + +func (p *BaseParser) Match(ttype int) Token { + + t := p.GetCurrentToken() + + if t.GetTokenType() == ttype { + p.errHandler.ReportMatch(p) + p.Consume() + } else { + t = p.errHandler.RecoverInline(p) + if p.BuildParseTrees && t.GetTokenIndex() == -1 { + // we must have conjured up a Newtoken during single token + // insertion + // if it's not the current symbol + p.ctx.AddErrorNode(t) + } + } + + return t +} + +// Match current input symbol as a wildcard. If the symbol type Matches +// (i.e. has a value greater than 0), {@link ANTLRErrorStrategy//ReportMatch} +// and {@link //consume} are called to complete the Match process. +// +//

    If the symbol type does not Match, +// {@link ANTLRErrorStrategy//recoverInline} is called on the current error +// strategy to attempt recovery. If {@link //getBuildParseTree} is +// {@code true} and the token index of the symbol returned by +// {@link ANTLRErrorStrategy//recoverInline} is -1, the symbol is added to +// the parse tree by calling {@link ParserRuleContext//addErrorNode}.

    +// +// @return the Matched symbol +// @panics RecognitionException if the current input symbol did not Match +// a wildcard and the error strategy could not recover from the mismatched +// symbol + +func (p *BaseParser) MatchWildcard() Token { + t := p.GetCurrentToken() + if t.GetTokenType() > 0 { + p.errHandler.ReportMatch(p) + p.Consume() + } else { + t = p.errHandler.RecoverInline(p) + if p.BuildParseTrees && t.GetTokenIndex() == -1 { + // we must have conjured up a Newtoken during single token + // insertion + // if it's not the current symbol + p.ctx.AddErrorNode(t) + } + } + return t +} + +func (p *BaseParser) GetParserRuleContext() ParserRuleContext { + return p.ctx +} + +func (p *BaseParser) SetParserRuleContext(v ParserRuleContext) { + p.ctx = v +} + +func (p *BaseParser) GetParseListeners() []ParseTreeListener { + if p.parseListeners == nil { + return make([]ParseTreeListener, 0) + } + return p.parseListeners +} + +// Registers {@code listener} to receive events during the parsing process. +// +//

    To support output-preserving grammar transformations (including but not +// limited to left-recursion removal, automated left-factoring, and +// optimized code generation), calls to listener methods during the parse +// may differ substantially from calls made by +// {@link ParseTreeWalker//DEFAULT} used after the parse is complete. In +// particular, rule entry and exit events may occur in a different order +// during the parse than after the parser. In addition, calls to certain +// rule entry methods may be omitted.

    +// +//

    With the following specific exceptions, calls to listener events are +// deterministic, i.e. for identical input the calls to listener +// methods will be the same.

    +// +//
      +//
    • Alterations to the grammar used to generate code may change the +// behavior of the listener calls.
    • +//
    • Alterations to the command line options passed to ANTLR 4 when +// generating the parser may change the behavior of the listener calls.
    • +//
    • Changing the version of the ANTLR Tool used to generate the parser +// may change the behavior of the listener calls.
    • +//
    +// +// @param listener the listener to add +// +// @panics nilPointerException if {@code} listener is {@code nil} +func (p *BaseParser) AddParseListener(listener ParseTreeListener) { + if listener == nil { + panic("listener") + } + if p.parseListeners == nil { + p.parseListeners = make([]ParseTreeListener, 0) + } + p.parseListeners = append(p.parseListeners, listener) +} + +// Remove {@code listener} from the list of parse listeners. +// +//

    If {@code listener} is {@code nil} or has not been added as a parse +// listener, p.method does nothing.

    +// @param listener the listener to remove +func (p *BaseParser) RemoveParseListener(listener ParseTreeListener) { + + if p.parseListeners != nil { + + idx := -1 + for i, v := range p.parseListeners { + if v == listener { + idx = i + break + } + } + + if idx == -1 { + return + } + + // remove the listener from the slice + p.parseListeners = append(p.parseListeners[0:idx], p.parseListeners[idx+1:]...) + + if len(p.parseListeners) == 0 { + p.parseListeners = nil + } + } +} + +// Remove all parse listeners. +func (p *BaseParser) removeParseListeners() { + p.parseListeners = nil +} + +// Notify any parse listeners of an enter rule event. +func (p *BaseParser) TriggerEnterRuleEvent() { + if p.parseListeners != nil { + ctx := p.ctx + for _, listener := range p.parseListeners { + listener.EnterEveryRule(ctx) + ctx.EnterRule(listener) + } + } +} + +// Notify any parse listeners of an exit rule event. +// +// @see //addParseListener +func (p *BaseParser) TriggerExitRuleEvent() { + if p.parseListeners != nil { + // reverse order walk of listeners + ctx := p.ctx + l := len(p.parseListeners) - 1 + + for i := range p.parseListeners { + listener := p.parseListeners[l-i] + ctx.ExitRule(listener) + listener.ExitEveryRule(ctx) + } + } +} + +func (p *BaseParser) GetInterpreter() *ParserATNSimulator { + return p.Interpreter +} + +func (p *BaseParser) GetATN() *ATN { + return p.Interpreter.atn +} + +func (p *BaseParser) GetTokenFactory() TokenFactory { + return p.input.GetTokenSource().GetTokenFactory() +} + +// Tell our token source and error strategy about a Newway to create tokens.// +func (p *BaseParser) setTokenFactory(factory TokenFactory) { + p.input.GetTokenSource().setTokenFactory(factory) +} + +// The ATN with bypass alternatives is expensive to create so we create it +// lazily. +// +// @panics UnsupportedOperationException if the current parser does not +// implement the {@link //getSerializedATN()} method. +func (p *BaseParser) GetATNWithBypassAlts() { + + // TODO + panic("Not implemented!") + + // serializedAtn := p.getSerializedATN() + // if (serializedAtn == nil) { + // panic("The current parser does not support an ATN with bypass alternatives.") + // } + // result := p.bypassAltsAtnCache[serializedAtn] + // if (result == nil) { + // deserializationOptions := NewATNDeserializationOptions(nil) + // deserializationOptions.generateRuleBypassTransitions = true + // result = NewATNDeserializer(deserializationOptions).deserialize(serializedAtn) + // p.bypassAltsAtnCache[serializedAtn] = result + // } + // return result +} + +// The preferred method of getting a tree pattern. For example, here's a +// sample use: +// +//
    +// ParseTree t = parser.expr()
    +// ParseTreePattern p = parser.compileParseTreePattern("<ID>+0",
    +// MyParser.RULE_expr)
    +// ParseTreeMatch m = p.Match(t)
    +// String id = m.Get("ID")
    +// 
    + +func (p *BaseParser) compileParseTreePattern(pattern, patternRuleIndex, lexer Lexer) { + + panic("NewParseTreePatternMatcher not implemented!") + // + // if (lexer == nil) { + // if (p.GetTokenStream() != nil) { + // tokenSource := p.GetTokenStream().GetTokenSource() + // if _, ok := tokenSource.(ILexer); ok { + // lexer = tokenSource + // } + // } + // } + // if (lexer == nil) { + // panic("Parser can't discover a lexer to use") + // } + + // m := NewParseTreePatternMatcher(lexer, p) + // return m.compile(pattern, patternRuleIndex) +} + +func (p *BaseParser) GetInputStream() IntStream { + return p.GetTokenStream() +} + +func (p *BaseParser) SetInputStream(input TokenStream) { + p.SetTokenStream(input) +} + +func (p *BaseParser) GetTokenStream() TokenStream { + return p.input +} + +// Set the token stream and reset the parser.// +func (p *BaseParser) SetTokenStream(input TokenStream) { + p.input = nil + p.reset() + p.input = input +} + +// Match needs to return the current input symbol, which gets put +// into the label for the associated token ref e.g., x=ID. +func (p *BaseParser) GetCurrentToken() Token { + return p.input.LT(1) +} + +func (p *BaseParser) NotifyErrorListeners(msg string, offendingToken Token, err RecognitionException) { + if offendingToken == nil { + offendingToken = p.GetCurrentToken() + } + p._SyntaxErrors++ + line := offendingToken.GetLine() + column := offendingToken.GetColumn() + listener := p.GetErrorListenerDispatch() + listener.SyntaxError(p, offendingToken, line, column, msg, err) +} + +func (p *BaseParser) Consume() Token { + o := p.GetCurrentToken() + if o.GetTokenType() != TokenEOF { + p.GetInputStream().Consume() + } + hasListener := p.parseListeners != nil && len(p.parseListeners) > 0 + if p.BuildParseTrees || hasListener { + if p.errHandler.InErrorRecoveryMode(p) { + node := p.ctx.AddErrorNode(o) + if p.parseListeners != nil { + for _, l := range p.parseListeners { + l.VisitErrorNode(node) + } + } + + } else { + node := p.ctx.AddTokenNode(o) + if p.parseListeners != nil { + for _, l := range p.parseListeners { + l.VisitTerminal(node) + } + } + } + // node.invokingState = p.state + } + + return o +} + +func (p *BaseParser) addContextToParseTree() { + // add current context to parent if we have a parent + if p.ctx.GetParent() != nil { + p.ctx.GetParent().(ParserRuleContext).AddChild(p.ctx) + } +} + +func (p *BaseParser) EnterRule(localctx ParserRuleContext, state, ruleIndex int) { + p.SetState(state) + p.ctx = localctx + p.ctx.SetStart(p.input.LT(1)) + if p.BuildParseTrees { + p.addContextToParseTree() + } + if p.parseListeners != nil { + p.TriggerEnterRuleEvent() + } +} + +func (p *BaseParser) ExitRule() { + p.ctx.SetStop(p.input.LT(-1)) + // trigger event on ctx, before it reverts to parent + if p.parseListeners != nil { + p.TriggerExitRuleEvent() + } + p.SetState(p.ctx.GetInvokingState()) + if p.ctx.GetParent() != nil { + p.ctx = p.ctx.GetParent().(ParserRuleContext) + } else { + p.ctx = nil + } +} + +func (p *BaseParser) EnterOuterAlt(localctx ParserRuleContext, altNum int) { + localctx.SetAltNumber(altNum) + // if we have Newlocalctx, make sure we replace existing ctx + // that is previous child of parse tree + if p.BuildParseTrees && p.ctx != localctx { + if p.ctx.GetParent() != nil { + p.ctx.GetParent().(ParserRuleContext).RemoveLastChild() + p.ctx.GetParent().(ParserRuleContext).AddChild(localctx) + } + } + p.ctx = localctx +} + +// Get the precedence level for the top-most precedence rule. +// +// @return The precedence level for the top-most precedence rule, or -1 if +// the parser context is not nested within a precedence rule. + +func (p *BaseParser) GetPrecedence() int { + if len(p.precedenceStack) == 0 { + return -1 + } + + return p.precedenceStack[len(p.precedenceStack)-1] +} + +func (p *BaseParser) EnterRecursionRule(localctx ParserRuleContext, state, ruleIndex, precedence int) { + p.SetState(state) + p.precedenceStack.Push(precedence) + p.ctx = localctx + p.ctx.SetStart(p.input.LT(1)) + if p.parseListeners != nil { + p.TriggerEnterRuleEvent() // simulates rule entry for + // left-recursive rules + } +} + +// +// Like {@link //EnterRule} but for recursive rules. + +func (p *BaseParser) PushNewRecursionContext(localctx ParserRuleContext, state, ruleIndex int) { + previous := p.ctx + previous.SetParent(localctx) + previous.SetInvokingState(state) + previous.SetStop(p.input.LT(-1)) + + p.ctx = localctx + p.ctx.SetStart(previous.GetStart()) + if p.BuildParseTrees { + p.ctx.AddChild(previous) + } + if p.parseListeners != nil { + p.TriggerEnterRuleEvent() // simulates rule entry for + // left-recursive rules + } +} + +func (p *BaseParser) UnrollRecursionContexts(parentCtx ParserRuleContext) { + p.precedenceStack.Pop() + p.ctx.SetStop(p.input.LT(-1)) + retCtx := p.ctx // save current ctx (return value) + // unroll so ctx is as it was before call to recursive method + if p.parseListeners != nil { + for p.ctx != parentCtx { + p.TriggerExitRuleEvent() + p.ctx = p.ctx.GetParent().(ParserRuleContext) + } + } else { + p.ctx = parentCtx + } + // hook into tree + retCtx.SetParent(parentCtx) + if p.BuildParseTrees && parentCtx != nil { + // add return ctx into invoking rule's tree + parentCtx.AddChild(retCtx) + } +} + +func (p *BaseParser) GetInvokingContext(ruleIndex int) ParserRuleContext { + ctx := p.ctx + for ctx != nil { + if ctx.GetRuleIndex() == ruleIndex { + return ctx + } + ctx = ctx.GetParent().(ParserRuleContext) + } + return nil +} + +func (p *BaseParser) Precpred(localctx RuleContext, precedence int) bool { + return precedence >= p.precedenceStack[len(p.precedenceStack)-1] +} + +func (p *BaseParser) inContext(context ParserRuleContext) bool { + // TODO: useful in parser? + return false +} + +// +// Checks whether or not {@code symbol} can follow the current state in the +// ATN. The behavior of p.method is equivalent to the following, but is +// implemented such that the complete context-sensitive follow set does not +// need to be explicitly constructed. +// +//
    +// return getExpectedTokens().contains(symbol)
    +// 
    +// +// @param symbol the symbol type to check +// @return {@code true} if {@code symbol} can follow the current state in +// the ATN, otherwise {@code false}. + +func (p *BaseParser) IsExpectedToken(symbol int) bool { + atn := p.Interpreter.atn + ctx := p.ctx + s := atn.states[p.state] + following := atn.NextTokens(s, nil) + if following.contains(symbol) { + return true + } + if !following.contains(TokenEpsilon) { + return false + } + for ctx != nil && ctx.GetInvokingState() >= 0 && following.contains(TokenEpsilon) { + invokingState := atn.states[ctx.GetInvokingState()] + rt := invokingState.GetTransitions()[0] + following = atn.NextTokens(rt.(*RuleTransition).followState, nil) + if following.contains(symbol) { + return true + } + ctx = ctx.GetParent().(ParserRuleContext) + } + if following.contains(TokenEpsilon) && symbol == TokenEOF { + return true + } + + return false +} + +// Computes the set of input symbols which could follow the current parser +// state and context, as given by {@link //GetState} and {@link //GetContext}, +// respectively. +// +// @see ATN//getExpectedTokens(int, RuleContext) +func (p *BaseParser) GetExpectedTokens() *IntervalSet { + return p.Interpreter.atn.getExpectedTokens(p.state, p.ctx) +} + +func (p *BaseParser) GetExpectedTokensWithinCurrentRule() *IntervalSet { + atn := p.Interpreter.atn + s := atn.states[p.state] + return atn.NextTokens(s, nil) +} + +// Get a rule's index (i.e., {@code RULE_ruleName} field) or -1 if not found.// +func (p *BaseParser) GetRuleIndex(ruleName string) int { + var ruleIndex, ok = p.GetRuleIndexMap()[ruleName] + if ok { + return ruleIndex + } + + return -1 +} + +// Return List<String> of the rule names in your parser instance +// leading up to a call to the current rule. You could override if +// you want more details such as the file/line info of where +// in the ATN a rule is invoked. +// +// this very useful for error messages. + +func (p *BaseParser) GetRuleInvocationStack(c ParserRuleContext) []string { + if c == nil { + c = p.ctx + } + stack := make([]string, 0) + for c != nil { + // compute what follows who invoked us + ruleIndex := c.GetRuleIndex() + if ruleIndex < 0 { + stack = append(stack, "n/a") + } else { + stack = append(stack, p.GetRuleNames()[ruleIndex]) + } + + vp := c.GetParent() + + if vp == nil { + break + } + + c = vp.(ParserRuleContext) + } + return stack +} + +// For debugging and other purposes.// +func (p *BaseParser) GetDFAStrings() string { + return fmt.Sprint(p.Interpreter.decisionToDFA) +} + +// For debugging and other purposes.// +func (p *BaseParser) DumpDFA() { + seenOne := false + for _, dfa := range p.Interpreter.decisionToDFA { + if dfa.states.Len() > 0 { + if seenOne { + fmt.Println() + } + fmt.Println("Decision " + strconv.Itoa(dfa.decision) + ":") + fmt.Print(dfa.String(p.LiteralNames, p.SymbolicNames)) + seenOne = true + } + } +} + +func (p *BaseParser) GetSourceName() string { + return p.GrammarFileName +} + +// During a parse is sometimes useful to listen in on the rule entry and exit +// events as well as token Matches. p.is for quick and dirty debugging. +func (p *BaseParser) SetTrace(trace *TraceListener) { + if trace == nil { + p.RemoveParseListener(p.tracer) + p.tracer = nil + } else { + if p.tracer != nil { + p.RemoveParseListener(p.tracer) + } + p.tracer = NewTraceListener(p) + p.AddParseListener(p.tracer) + } +} diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/parser_atn_simulator.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/parser_atn_simulator.go similarity index 94% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/parser_atn_simulator.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/parser_atn_simulator.go index 888d512975..8bcc46a0d9 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/parser_atn_simulator.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/parser_atn_simulator.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. @@ -11,11 +11,11 @@ import ( ) var ( - ParserATNSimulatorDebug = false - ParserATNSimulatorListATNDecisions = false - ParserATNSimulatorDFADebug = false - ParserATNSimulatorRetryDebug = false - TurnOffLRLoopEntryBranchOpt = false + ParserATNSimulatorDebug = false + ParserATNSimulatorTraceATNSim = false + ParserATNSimulatorDFADebug = false + ParserATNSimulatorRetryDebug = false + TurnOffLRLoopEntryBranchOpt = false ) type ParserATNSimulator struct { @@ -70,8 +70,8 @@ func (p *ParserATNSimulator) reset() { } func (p *ParserATNSimulator) AdaptivePredict(input TokenStream, decision int, outerContext ParserRuleContext) int { - if ParserATNSimulatorDebug || ParserATNSimulatorListATNDecisions { - fmt.Println("AdaptivePredict decision " + strconv.Itoa(decision) + + if ParserATNSimulatorDebug || ParserATNSimulatorTraceATNSim { + fmt.Println("adaptivePredict decision " + strconv.Itoa(decision) + " exec LA(1)==" + p.getLookaheadName(input) + " line " + strconv.Itoa(input.LT(1).GetLine()) + ":" + strconv.Itoa(input.LT(1).GetColumn())) @@ -111,15 +111,15 @@ func (p *ParserATNSimulator) AdaptivePredict(input TokenStream, decision int, ou if s0 == nil { if outerContext == nil { - outerContext = RuleContextEmpty + outerContext = ParserRuleContextEmpty } - if ParserATNSimulatorDebug || ParserATNSimulatorListATNDecisions { + if ParserATNSimulatorDebug { fmt.Println("predictATN decision " + strconv.Itoa(dfa.decision) + " exec LA(1)==" + p.getLookaheadName(input) + ", outerContext=" + outerContext.String(p.parser.GetRuleNames(), nil)) } fullCtx := false - s0Closure := p.computeStartState(dfa.atnStartState, RuleContextEmpty, fullCtx) + s0Closure := p.computeStartState(dfa.atnStartState, ParserRuleContextEmpty, fullCtx) p.atn.stateMu.Lock() if dfa.getPrecedenceDfa() { @@ -174,17 +174,18 @@ func (p *ParserATNSimulator) AdaptivePredict(input TokenStream, decision int, ou // Reporting insufficient predicates // cover these cases: -// dead end -// single alt -// single alt + preds -// conflict -// conflict + preds // +// dead end +// single alt +// single alt + preds +// conflict +// conflict + preds func (p *ParserATNSimulator) execATN(dfa *DFA, s0 *DFAState, input TokenStream, startIndex int, outerContext ParserRuleContext) int { - if ParserATNSimulatorDebug || ParserATNSimulatorListATNDecisions { + if ParserATNSimulatorDebug || ParserATNSimulatorTraceATNSim { fmt.Println("execATN decision " + strconv.Itoa(dfa.decision) + - " exec LA(1)==" + p.getLookaheadName(input) + + ", DFA state " + s0.String() + + ", LA(1)==" + p.getLookaheadName(input) + " line " + strconv.Itoa(input.LT(1).GetLine()) + ":" + strconv.Itoa(input.LT(1).GetColumn())) } @@ -277,8 +278,6 @@ func (p *ParserATNSimulator) execATN(dfa *DFA, s0 *DFAState, input TokenStream, t = input.LA(1) } } - - panic("Should not have reached p state") } // Get an existing target state for an edge in the DFA. If the target state @@ -384,7 +383,7 @@ func (p *ParserATNSimulator) predicateDFAState(dfaState *DFAState, decisionState // comes back with reach.uniqueAlt set to a valid alt func (p *ParserATNSimulator) execATNWithFullContext(dfa *DFA, D *DFAState, s0 ATNConfigSet, input TokenStream, startIndex int, outerContext ParserRuleContext) int { - if ParserATNSimulatorDebug || ParserATNSimulatorListATNDecisions { + if ParserATNSimulatorDebug || ParserATNSimulatorTraceATNSim { fmt.Println("execATNWithFullContext " + s0.String()) } @@ -492,9 +491,6 @@ func (p *ParserATNSimulator) execATNWithFullContext(dfa *DFA, D *DFAState, s0 AT } func (p *ParserATNSimulator) computeReachSet(closure ATNConfigSet, t int, fullCtx bool) ATNConfigSet { - if ParserATNSimulatorDebug { - fmt.Println("in computeReachSet, starting closure: " + closure.String()) - } if p.mergeCache == nil { p.mergeCache = NewDoubleDict() } @@ -570,7 +566,7 @@ func (p *ParserATNSimulator) computeReachSet(closure ATNConfigSet, t int, fullCt // if reach == nil { reach = NewBaseATNConfigSet(fullCtx) - closureBusy := newArray2DHashSet(nil, nil) + closureBusy := NewJStore[ATNConfig, Comparator[ATNConfig]](aConfEqInst) treatEOFAsEpsilon := t == TokenEOF amount := len(intermediate.configs) for k := 0; k < amount; k++ { @@ -610,6 +606,11 @@ func (p *ParserATNSimulator) computeReachSet(closure ATNConfigSet, t int, fullCt reach.Add(skippedStopStates[l], p.mergeCache) } } + + if ParserATNSimulatorTraceATNSim { + fmt.Println("computeReachSet " + closure.String() + " -> " + reach.String()) + } + if len(reach.GetItems()) == 0 { return nil } @@ -617,7 +618,6 @@ func (p *ParserATNSimulator) computeReachSet(closure ATNConfigSet, t int, fullCt return reach } -// // Return a configuration set containing only the configurations from // {@code configs} which are in a {@link RuleStopState}. If all // configurations in {@code configs} are already in a rule stop state, p @@ -636,7 +636,6 @@ func (p *ParserATNSimulator) computeReachSet(closure ATNConfigSet, t int, fullCt // @return {@code configs} if all configurations in {@code configs} are in a // rule stop state, otherwise return a Newconfiguration set containing only // the configurations from {@code configs} which are in a rule stop state -// func (p *ParserATNSimulator) removeAllConfigsNotInRuleStopState(configs ATNConfigSet, lookToEndOfRule bool) ATNConfigSet { if PredictionModeallConfigsInRuleStopStates(configs) { return configs @@ -662,16 +661,20 @@ func (p *ParserATNSimulator) computeStartState(a ATNState, ctx RuleContext, full // always at least the implicit call to start rule initialContext := predictionContextFromRuleContext(p.atn, ctx) configs := NewBaseATNConfigSet(fullCtx) + if ParserATNSimulatorDebug || ParserATNSimulatorTraceATNSim { + fmt.Println("computeStartState from ATN state " + a.String() + + " initialContext=" + initialContext.String()) + } + for i := 0; i < len(a.GetTransitions()); i++ { target := a.GetTransitions()[i].getTarget() c := NewBaseATNConfig6(target, i+1, initialContext) - closureBusy := newArray2DHashSet(nil, nil) + closureBusy := NewJStore[ATNConfig, Comparator[ATNConfig]](atnConfCompInst) p.closure(c, configs, closureBusy, true, fullCtx, false) } return configs } -// // This method transforms the start state computed by // {@link //computeStartState} to the special start state used by a // precedence DFA for a particular precedence value. The transformation @@ -726,7 +729,6 @@ func (p *ParserATNSimulator) computeStartState(a ATNState, ctx RuleContext, full // @return The transformed configuration set representing the start state // for a precedence DFA at a particular precedence level (determined by // calling {@link Parser//getPrecedence}). -// func (p *ParserATNSimulator) applyPrecedenceFilter(configs ATNConfigSet) ATNConfigSet { statesFromAlt1 := make(map[int]PredictionContext) @@ -760,7 +762,7 @@ func (p *ParserATNSimulator) applyPrecedenceFilter(configs ATNConfigSet) ATNConf // (basically a graph subtraction algorithm). if !config.getPrecedenceFilterSuppressed() { context := statesFromAlt1[config.GetState().GetStateNumber()] - if context != nil && context.equals(config.GetContext()) { + if context != nil && context.Equals(config.GetContext()) { // eliminated continue } @@ -824,7 +826,6 @@ func (p *ParserATNSimulator) getPredicatePredictions(ambigAlts *BitSet, altToPre return pairs } -// // This method is used to improve the localization of error messages by // choosing an alternative rather than panicing a // {@link NoViableAltException} in particular prediction scenarios where the @@ -869,7 +870,6 @@ func (p *ParserATNSimulator) getPredicatePredictions(ambigAlts *BitSet, altToPre // @return The value to return from {@link //AdaptivePredict}, or // {@link ATN//INVALID_ALT_NUMBER} if a suitable alternative was not // identified and {@link //AdaptivePredict} should Report an error instead. -// func (p *ParserATNSimulator) getSynValidOrSemInvalidAltThatFinishedDecisionEntryRule(configs ATNConfigSet, outerContext ParserRuleContext) int { cfgs := p.splitAccordingToSemanticValidity(configs, outerContext) semValidConfigs := cfgs[0] @@ -938,11 +938,11 @@ func (p *ParserATNSimulator) splitAccordingToSemanticValidity(configs ATNConfigS } // Look through a list of predicate/alt pairs, returning alts for the -// pairs that win. A {@code NONE} predicate indicates an alt containing an -// unpredicated config which behaves as "always true." If !complete -// then we stop at the first predicate that evaluates to true. This -// includes pairs with nil predicates. // +// pairs that win. A {@code NONE} predicate indicates an alt containing an +// unpredicated config which behaves as "always true." If !complete +// then we stop at the first predicate that evaluates to true. This +// includes pairs with nil predicates. func (p *ParserATNSimulator) evalSemanticContext(predPredictions []*PredPrediction, outerContext ParserRuleContext, complete bool) *BitSet { predictions := NewBitSet() for i := 0; i < len(predPredictions); i++ { @@ -972,16 +972,16 @@ func (p *ParserATNSimulator) evalSemanticContext(predPredictions []*PredPredicti return predictions } -func (p *ParserATNSimulator) closure(config ATNConfig, configs ATNConfigSet, closureBusy Set, collectPredicates, fullCtx, treatEOFAsEpsilon bool) { +func (p *ParserATNSimulator) closure(config ATNConfig, configs ATNConfigSet, closureBusy *JStore[ATNConfig, Comparator[ATNConfig]], collectPredicates, fullCtx, treatEOFAsEpsilon bool) { initialDepth := 0 p.closureCheckingStopState(config, configs, closureBusy, collectPredicates, fullCtx, initialDepth, treatEOFAsEpsilon) } -func (p *ParserATNSimulator) closureCheckingStopState(config ATNConfig, configs ATNConfigSet, closureBusy Set, collectPredicates, fullCtx bool, depth int, treatEOFAsEpsilon bool) { - if ParserATNSimulatorDebug { +func (p *ParserATNSimulator) closureCheckingStopState(config ATNConfig, configs ATNConfigSet, closureBusy *JStore[ATNConfig, Comparator[ATNConfig]], collectPredicates, fullCtx bool, depth int, treatEOFAsEpsilon bool) { + if ParserATNSimulatorTraceATNSim { fmt.Println("closure(" + config.String() + ")") - fmt.Println("configs(" + configs.String() + ")") + //fmt.Println("configs(" + configs.String() + ")") if config.GetReachesIntoOuterContext() > 50 { panic("problem") } @@ -1031,7 +1031,7 @@ func (p *ParserATNSimulator) closureCheckingStopState(config ATNConfig, configs } // Do the actual work of walking epsilon edges// -func (p *ParserATNSimulator) closureWork(config ATNConfig, configs ATNConfigSet, closureBusy Set, collectPredicates, fullCtx bool, depth int, treatEOFAsEpsilon bool) { +func (p *ParserATNSimulator) closureWork(config ATNConfig, configs ATNConfigSet, closureBusy *JStore[ATNConfig, Comparator[ATNConfig]], collectPredicates, fullCtx bool, depth int, treatEOFAsEpsilon bool) { state := config.GetState() // optimization if !state.GetEpsilonOnlyTransitions() { @@ -1066,7 +1066,8 @@ func (p *ParserATNSimulator) closureWork(config ATNConfig, configs ATNConfigSet, c.SetReachesIntoOuterContext(c.GetReachesIntoOuterContext() + 1) - if closureBusy.Add(c) != c { + _, present := closureBusy.Put(c) + if present { // avoid infinite recursion for right-recursive rules continue } @@ -1077,9 +1078,13 @@ func (p *ParserATNSimulator) closureWork(config ATNConfig, configs ATNConfigSet, fmt.Println("dips into outer ctx: " + c.String()) } } else { - if !t.getIsEpsilon() && closureBusy.Add(c) != c { - // avoid infinite recursion for EOF* and EOF+ - continue + + if !t.getIsEpsilon() { + _, present := closureBusy.Put(c) + if present { + // avoid infinite recursion for EOF* and EOF+ + continue + } } if _, ok := t.(*RuleTransition); ok { // latch when newDepth goes negative - once we step out of the entry context we can't return @@ -1104,7 +1109,16 @@ func (p *ParserATNSimulator) canDropLoopEntryEdgeInLeftRecursiveRule(config ATNC // left-recursion elimination. For efficiency, also check if // the context has an empty stack case. If so, it would mean // global FOLLOW so we can't perform optimization - if startLoop, ok := _p.(StarLoopEntryState); !ok || !startLoop.precedenceRuleDecision || config.GetContext().isEmpty() || config.GetContext().hasEmptyPath() { + if _p.GetStateType() != ATNStateStarLoopEntry { + return false + } + startLoop, ok := _p.(*StarLoopEntryState) + if !ok { + return false + } + if !startLoop.precedenceRuleDecision || + config.GetContext().isEmpty() || + config.GetContext().hasEmptyPath() { return false } @@ -1117,8 +1131,8 @@ func (p *ParserATNSimulator) canDropLoopEntryEdgeInLeftRecursiveRule(config ATNC return false } } - - decisionStartState := _p.(BlockStartState).GetTransitions()[0].getTarget().(BlockStartState) + x := _p.GetTransitions()[0].getTarget() + decisionStartState := x.(BlockStartState) blockEndStateNum := decisionStartState.getEndState().stateNumber blockEndState := p.atn.states[blockEndStateNum].(*BlockEndState) @@ -1355,13 +1369,12 @@ func (p *ParserATNSimulator) GetTokenName(t int) string { return "EOF" } - if p.parser != nil && p.parser.GetLiteralNames() != nil { - if t >= len(p.parser.GetLiteralNames()) { - fmt.Println(strconv.Itoa(t) + " ttype out of range: " + strings.Join(p.parser.GetLiteralNames(), ",")) - // fmt.Println(p.parser.GetInputStream().(TokenStream).GetAllText()) // p seems incorrect - } else { - return p.parser.GetLiteralNames()[t] + "<" + strconv.Itoa(t) + ">" - } + if p.parser != nil && p.parser.GetLiteralNames() != nil && t < len(p.parser.GetLiteralNames()) { + return p.parser.GetLiteralNames()[t] + "<" + strconv.Itoa(t) + ">" + } + + if p.parser != nil && p.parser.GetLiteralNames() != nil && t < len(p.parser.GetSymbolicNames()) { + return p.parser.GetSymbolicNames()[t] + "<" + strconv.Itoa(t) + ">" } return strconv.Itoa(t) @@ -1372,9 +1385,9 @@ func (p *ParserATNSimulator) getLookaheadName(input TokenStream) string { } // Used for debugging in AdaptivePredict around execATN but I cut -// it out for clarity now that alg. works well. We can leave p -// "dead" code for a bit. // +// it out for clarity now that alg. works well. We can leave p +// "dead" code for a bit. func (p *ParserATNSimulator) dumpDeadEndConfigs(nvae *NoViableAltException) { panic("Not implemented") @@ -1421,7 +1434,6 @@ func (p *ParserATNSimulator) getUniqueAlt(configs ATNConfigSet) int { return alt } -// // Add an edge to the DFA, if possible. This method calls // {@link //addDFAState} to ensure the {@code to} state is present in the // DFA. If {@code from} is {@code nil}, or if {@code t} is outside the @@ -1440,7 +1452,6 @@ func (p *ParserATNSimulator) getUniqueAlt(configs ATNConfigSet) int { // @return If {@code to} is {@code nil}, p method returns {@code nil} // otherwise p method returns the result of calling {@link //addDFAState} // on {@code to} -// func (p *ParserATNSimulator) addDFAEdge(dfa *DFA, from *DFAState, t int, to *DFAState) *DFAState { if ParserATNSimulatorDebug { fmt.Println("EDGE " + from.String() + " -> " + to.String() + " upon " + p.GetTokenName(t)) @@ -1472,7 +1483,6 @@ func (p *ParserATNSimulator) addDFAEdge(dfa *DFA, from *DFAState, t int, to *DFA return to } -// // Add state {@code D} to the DFA if it is not already present, and return // the actual instance stored in the DFA. If a state equivalent to {@code D} // is already in the DFA, the existing state is returned. Otherwise p @@ -1486,25 +1496,30 @@ func (p *ParserATNSimulator) addDFAEdge(dfa *DFA, from *DFAState, t int, to *DFA // @return The state stored in the DFA. This will be either the existing // state if {@code D} is already in the DFA, or {@code D} itself if the // state was not already present. -// func (p *ParserATNSimulator) addDFAState(dfa *DFA, d *DFAState) *DFAState { if d == ATNSimulatorError { return d } - hash := d.hash() - existing, ok := dfa.getState(hash) - if ok { + existing, present := dfa.states.Get(d) + if present { + if ParserATNSimulatorTraceATNSim { + fmt.Print("addDFAState " + d.String() + " exists") + } return existing } - d.stateNumber = dfa.numStates() + + // The state was not present, so update it with configs + // + d.stateNumber = dfa.states.Len() if !d.configs.ReadOnly() { d.configs.OptimizeConfigs(p.BaseATNSimulator) d.configs.SetReadOnly(true) } - dfa.setState(hash, d) - if ParserATNSimulatorDebug { - fmt.Println("adding NewDFA state: " + d.String()) + dfa.states.Put(d) + if ParserATNSimulatorTraceATNSim { + fmt.Println("addDFAState new " + d.String()) } + return d } diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/parser_rule_context.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/parser_rule_context.go similarity index 98% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/parser_rule_context.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/parser_rule_context.go index 49cd10c5ff..1c8cee7479 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/parser_rule_context.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/parser_rule_context.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. @@ -340,7 +340,7 @@ func (prc *BaseParserRuleContext) String(ruleNames []string, stop RuleContext) s return s } -var RuleContextEmpty = NewBaseParserRuleContext(nil, -1) +var ParserRuleContextEmpty = NewBaseParserRuleContext(nil, -1) type InterpreterRuleContext interface { ParserRuleContext diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/prediction_context.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/prediction_context.go similarity index 81% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/prediction_context.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/prediction_context.go index 9fdfd52b26..ba62af3610 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/prediction_context.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/prediction_context.go @@ -1,10 +1,12 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. package antlr import ( + "fmt" + "golang.org/x/exp/slices" "strconv" ) @@ -26,10 +28,10 @@ var ( ) type PredictionContext interface { - hash() int + Hash() int + Equals(interface{}) bool GetParent(int) PredictionContext getReturnState(int) int - equals(PredictionContext) bool length() int isEmpty() bool hasEmptyPath() bool @@ -53,7 +55,7 @@ func (b *BasePredictionContext) isEmpty() bool { func calculateHash(parent PredictionContext, returnState int) int { h := murmurInit(1) - h = murmurUpdate(h, parent.hash()) + h = murmurUpdate(h, parent.Hash()) h = murmurUpdate(h, returnState) return murmurFinish(h, 2) } @@ -86,7 +88,6 @@ func NewPredictionContextCache() *PredictionContextCache { // Add a context to the cache and return it. If the context already exists, // return that one instead and do not add a Newcontext to the cache. // Protect shared cache from unsafe thread access. -// func (p *PredictionContextCache) add(ctx PredictionContext) PredictionContext { if ctx == BasePredictionContextEMPTY { return BasePredictionContextEMPTY @@ -160,28 +161,28 @@ func (b *BaseSingletonPredictionContext) hasEmptyPath() bool { return b.returnState == BasePredictionContextEmptyReturnState } -func (b *BaseSingletonPredictionContext) equals(other PredictionContext) bool { +func (b *BaseSingletonPredictionContext) Hash() int { + return b.cachedHash +} + +func (b *BaseSingletonPredictionContext) Equals(other interface{}) bool { if b == other { return true - } else if _, ok := other.(*BaseSingletonPredictionContext); !ok { + } + if _, ok := other.(*BaseSingletonPredictionContext); !ok { return false - } else if b.hash() != other.hash() { - return false // can't be same if hash is different } otherP := other.(*BaseSingletonPredictionContext) - if b.returnState != other.getReturnState(0) { + if b.returnState != otherP.getReturnState(0) { return false - } else if b.parentCtx == nil { + } + if b.parentCtx == nil { return otherP.parentCtx == nil } - return b.parentCtx.equals(otherP.parentCtx) -} - -func (b *BaseSingletonPredictionContext) hash() int { - return b.cachedHash + return b.parentCtx.Equals(otherP.parentCtx) } func (b *BaseSingletonPredictionContext) String() string { @@ -215,7 +216,7 @@ func NewEmptyPredictionContext() *EmptyPredictionContext { p := new(EmptyPredictionContext) p.BaseSingletonPredictionContext = NewBaseSingletonPredictionContext(nil, BasePredictionContextEmptyReturnState) - + p.cachedHash = calculateEmptyHash() return p } @@ -231,7 +232,11 @@ func (e *EmptyPredictionContext) getReturnState(index int) int { return e.returnState } -func (e *EmptyPredictionContext) equals(other PredictionContext) bool { +func (e *EmptyPredictionContext) Hash() int { + return e.cachedHash +} + +func (e *EmptyPredictionContext) Equals(other interface{}) bool { return e == other } @@ -254,7 +259,7 @@ func NewArrayPredictionContext(parents []PredictionContext, returnStates []int) hash := murmurInit(1) for _, parent := range parents { - hash = murmurUpdate(hash, parent.hash()) + hash = murmurUpdate(hash, parent.Hash()) } for _, returnState := range returnStates { @@ -298,18 +303,31 @@ func (a *ArrayPredictionContext) getReturnState(index int) int { return a.returnStates[index] } -func (a *ArrayPredictionContext) equals(other PredictionContext) bool { - if _, ok := other.(*ArrayPredictionContext); !ok { +// Equals is the default comparison function for ArrayPredictionContext when no specialized +// implementation is needed for a collection +func (a *ArrayPredictionContext) Equals(o interface{}) bool { + if a == o { + return true + } + other, ok := o.(*ArrayPredictionContext) + if !ok { return false - } else if a.cachedHash != other.hash() { + } + if a.cachedHash != other.Hash() { return false // can't be same if hash is different - } else { - otherP := other.(*ArrayPredictionContext) - return &a.returnStates == &otherP.returnStates && &a.parents == &otherP.parents } + + // Must compare the actual array elements and not just the array address + // + return slices.Equal(a.returnStates, other.returnStates) && + slices.EqualFunc(a.parents, other.parents, func(x, y PredictionContext) bool { + return x.Equals(y) + }) } -func (a *ArrayPredictionContext) hash() int { +// Hash is the default hash function for ArrayPredictionContext when no specialized +// implementation is needed for a collection +func (a *ArrayPredictionContext) Hash() int { return a.BasePredictionContext.cachedHash } @@ -343,11 +361,11 @@ func (a *ArrayPredictionContext) String() string { // / func predictionContextFromRuleContext(a *ATN, outerContext RuleContext) PredictionContext { if outerContext == nil { - outerContext = RuleContextEmpty + outerContext = ParserRuleContextEmpty } // if we are in RuleContext of start rule, s, then BasePredictionContext // is EMPTY. Nobody called us. (if we are empty, return empty) - if outerContext.GetParent() == nil || outerContext == RuleContextEmpty { + if outerContext.GetParent() == nil || outerContext == ParserRuleContextEmpty { return BasePredictionContextEMPTY } // If we have a parent, convert it to a BasePredictionContext graph @@ -359,11 +377,20 @@ func predictionContextFromRuleContext(a *ATN, outerContext RuleContext) Predicti } func merge(a, b PredictionContext, rootIsWildcard bool, mergeCache *DoubleDict) PredictionContext { - // share same graph if both same - if a == b { + + // Share same graph if both same + // + if a == b || a.Equals(b) { return a } + // In Java, EmptyPredictionContext inherits from SingletonPredictionContext, and so the test + // in java for SingletonPredictionContext will succeed and a new ArrayPredictionContext will be created + // from it. + // In go, EmptyPredictionContext does not equate to SingletonPredictionContext and so that conversion + // will fail. We need to test for both Empty and Singleton and create an ArrayPredictionContext from + // either of them. + ac, ok1 := a.(*BaseSingletonPredictionContext) bc, ok2 := b.(*BaseSingletonPredictionContext) @@ -380,17 +407,32 @@ func merge(a, b PredictionContext, rootIsWildcard bool, mergeCache *DoubleDict) return b } } - // convert singleton so both are arrays to normalize - if _, ok := a.(*BaseSingletonPredictionContext); ok { - a = NewArrayPredictionContext([]PredictionContext{a.GetParent(0)}, []int{a.getReturnState(0)}) + + // Convert Singleton or Empty so both are arrays to normalize - We should not use the existing parameters + // here. + // + // TODO: I think that maybe the Prediction Context structs should be redone as there is a chance we will see this mess again - maybe redo the logic here + + var arp, arb *ArrayPredictionContext + var ok bool + if arp, ok = a.(*ArrayPredictionContext); ok { + } else if _, ok = a.(*BaseSingletonPredictionContext); ok { + arp = NewArrayPredictionContext([]PredictionContext{a.GetParent(0)}, []int{a.getReturnState(0)}) + } else if _, ok = a.(*EmptyPredictionContext); ok { + arp = NewArrayPredictionContext([]PredictionContext{}, []int{}) } - if _, ok := b.(*BaseSingletonPredictionContext); ok { - b = NewArrayPredictionContext([]PredictionContext{b.GetParent(0)}, []int{b.getReturnState(0)}) + + if arb, ok = b.(*ArrayPredictionContext); ok { + } else if _, ok = b.(*BaseSingletonPredictionContext); ok { + arb = NewArrayPredictionContext([]PredictionContext{b.GetParent(0)}, []int{b.getReturnState(0)}) + } else if _, ok = b.(*EmptyPredictionContext); ok { + arb = NewArrayPredictionContext([]PredictionContext{}, []int{}) } - return mergeArrays(a.(*ArrayPredictionContext), b.(*ArrayPredictionContext), rootIsWildcard, mergeCache) + + // Both arp and arb + return mergeArrays(arp, arb, rootIsWildcard, mergeCache) } -// // Merge two {@link SingletonBasePredictionContext} instances. // //

    Stack tops equal, parents merge is same return left graph.
    @@ -423,11 +465,11 @@ func merge(a, b PredictionContext, rootIsWildcard bool, mergeCache *DoubleDict) // / func mergeSingletons(a, b *BaseSingletonPredictionContext, rootIsWildcard bool, mergeCache *DoubleDict) PredictionContext { if mergeCache != nil { - previous := mergeCache.Get(a.hash(), b.hash()) + previous := mergeCache.Get(a.Hash(), b.Hash()) if previous != nil { return previous.(PredictionContext) } - previous = mergeCache.Get(b.hash(), a.hash()) + previous = mergeCache.Get(b.Hash(), a.Hash()) if previous != nil { return previous.(PredictionContext) } @@ -436,7 +478,7 @@ func mergeSingletons(a, b *BaseSingletonPredictionContext, rootIsWildcard bool, rootMerge := mergeRoot(a, b, rootIsWildcard) if rootMerge != nil { if mergeCache != nil { - mergeCache.set(a.hash(), b.hash(), rootMerge) + mergeCache.set(a.Hash(), b.Hash(), rootMerge) } return rootMerge } @@ -456,7 +498,7 @@ func mergeSingletons(a, b *BaseSingletonPredictionContext, rootIsWildcard bool, // Newjoined parent so create Newsingleton pointing to it, a' spc := SingletonBasePredictionContextCreate(parent, a.returnState) if mergeCache != nil { - mergeCache.set(a.hash(), b.hash(), spc) + mergeCache.set(a.Hash(), b.Hash(), spc) } return spc } @@ -478,7 +520,7 @@ func mergeSingletons(a, b *BaseSingletonPredictionContext, rootIsWildcard bool, parents := []PredictionContext{singleParent, singleParent} apc := NewArrayPredictionContext(parents, payloads) if mergeCache != nil { - mergeCache.set(a.hash(), b.hash(), apc) + mergeCache.set(a.Hash(), b.Hash(), apc) } return apc } @@ -494,12 +536,11 @@ func mergeSingletons(a, b *BaseSingletonPredictionContext, rootIsWildcard bool, } apc := NewArrayPredictionContext(parents, payloads) if mergeCache != nil { - mergeCache.set(a.hash(), b.hash(), apc) + mergeCache.set(a.Hash(), b.Hash(), apc) } return apc } -// // Handle case where at least one of {@code a} or {@code b} is // {@link //EMPTY}. In the following diagrams, the symbol {@code $} is used // to represent {@link //EMPTY}. @@ -561,7 +602,6 @@ func mergeRoot(a, b SingletonPredictionContext, rootIsWildcard bool) PredictionC return nil } -// // Merge two {@link ArrayBasePredictionContext} instances. // //

    Different tops, different parents.
    @@ -583,12 +623,18 @@ func mergeRoot(a, b SingletonPredictionContext, rootIsWildcard bool) PredictionC // / func mergeArrays(a, b *ArrayPredictionContext, rootIsWildcard bool, mergeCache *DoubleDict) PredictionContext { if mergeCache != nil { - previous := mergeCache.Get(a.hash(), b.hash()) + previous := mergeCache.Get(a.Hash(), b.Hash()) if previous != nil { + if ParserATNSimulatorTraceATNSim { + fmt.Println("mergeArrays a=" + a.String() + ",b=" + b.String() + " -> previous") + } return previous.(PredictionContext) } - previous = mergeCache.Get(b.hash(), a.hash()) + previous = mergeCache.Get(b.Hash(), a.Hash()) if previous != nil { + if ParserATNSimulatorTraceATNSim { + fmt.Println("mergeArrays a=" + a.String() + ",b=" + b.String() + " -> previous") + } return previous.(PredictionContext) } } @@ -608,7 +654,7 @@ func mergeArrays(a, b *ArrayPredictionContext, rootIsWildcard bool, mergeCache * payload := a.returnStates[i] // $+$ = $ bothDollars := payload == BasePredictionContextEmptyReturnState && aParent == nil && bParent == nil - axAX := (aParent != nil && bParent != nil && aParent == bParent) // ax+ax + axAX := aParent != nil && bParent != nil && aParent == bParent // ax+ax // -> // ax if bothDollars || axAX { @@ -651,7 +697,7 @@ func mergeArrays(a, b *ArrayPredictionContext, rootIsWildcard bool, mergeCache * if k == 1 { // for just one merged element, return singleton top pc := SingletonBasePredictionContextCreate(mergedParents[0], mergedReturnStates[0]) if mergeCache != nil { - mergeCache.set(a.hash(), b.hash(), pc) + mergeCache.set(a.Hash(), b.Hash(), pc) } return pc } @@ -663,27 +709,36 @@ func mergeArrays(a, b *ArrayPredictionContext, rootIsWildcard bool, mergeCache * // if we created same array as a or b, return that instead // TODO: track whether this is possible above during merge sort for speed + // TODO: In go, I do not think we can just do M == xx as M is a brand new allocation. This could be causing allocation problems if M == a { if mergeCache != nil { - mergeCache.set(a.hash(), b.hash(), a) + mergeCache.set(a.Hash(), b.Hash(), a) + } + if ParserATNSimulatorTraceATNSim { + fmt.Println("mergeArrays a=" + a.String() + ",b=" + b.String() + " -> a") } return a } if M == b { if mergeCache != nil { - mergeCache.set(a.hash(), b.hash(), b) + mergeCache.set(a.Hash(), b.Hash(), b) + } + if ParserATNSimulatorTraceATNSim { + fmt.Println("mergeArrays a=" + a.String() + ",b=" + b.String() + " -> b") } return b } combineCommonParents(mergedParents) if mergeCache != nil { - mergeCache.set(a.hash(), b.hash(), M) + mergeCache.set(a.Hash(), b.Hash(), M) + } + if ParserATNSimulatorTraceATNSim { + fmt.Println("mergeArrays a=" + a.String() + ",b=" + b.String() + " -> " + M.String()) } return M } -// // Make pass over all M {@code parents} merge any {@code equals()} // ones. // / diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/prediction_mode.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/prediction_mode.go similarity index 95% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/prediction_mode.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/prediction_mode.go index 15718f912b..7b9b72fab1 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/prediction_mode.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/prediction_mode.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. @@ -70,7 +70,6 @@ const ( PredictionModeLLExactAmbigDetection = 2 ) -// // Computes the SLL prediction termination condition. // //

    @@ -108,9 +107,9 @@ const ( // The single-alt-state thing lets prediction continue upon rules like // (otherwise, it would admit defeat too soon):

    // -//

    {@code [12|1|[], 6|2|[], 12|2|[]]. s : (ID | ID ID?) '' }

    +//

    {@code [12|1|[], 6|2|[], 12|2|[]]. s : (ID | ID ID?) ” }

    // -//

    When the ATN simulation reaches the state before {@code ''}, it has a +//

    When the ATN simulation reaches the state before {@code ”}, it has a // DFA state that looks like: {@code [12|1|[], 6|2|[], 12|2|[]]}. Naturally // {@code 12|1|[]} and {@code 12|2|[]} conflict, but we cannot stop // processing this node because alternative to has another way to continue, @@ -152,16 +151,15 @@ const ( // //

    Before testing these configurations against others, we have to merge // {@code x} and {@code x'} (without modifying the existing configurations). -// For example, we test {@code (x+x')==x''} when looking for conflicts in +// For example, we test {@code (x+x')==x”} when looking for conflicts in // the following configurations.

    // -//

    {@code (s, 1, x, {}), (s, 1, x', {p}), (s, 2, x'', {})}

    +//

    {@code (s, 1, x, {}), (s, 1, x', {p}), (s, 2, x”, {})}

    // //

    If the configuration set has predicates (as indicated by // {@link ATNConfigSet//hasSemanticContext}), this algorithm makes a copy of // the configurations to strip out all of the predicates so that a standard // {@link ATNConfigSet} will merge everything ignoring predicates.

    -// func PredictionModehasSLLConflictTerminatingPrediction(mode int, configs ATNConfigSet) bool { // Configs in rule stop states indicate reaching the end of the decision // rule (local context) or end of start rule (full context). If all @@ -229,7 +227,6 @@ func PredictionModeallConfigsInRuleStopStates(configs ATNConfigSet) bool { return true } -// // Full LL prediction termination. // //

    Can we stop looking ahead during ATN simulation or is there some @@ -334,7 +331,7 @@ func PredictionModeallConfigsInRuleStopStates(configs ATNConfigSet) bool { // // //

  • {@code (s, 1, x)}, {@code (s, 2, x)}, {@code (s', 1, y)}, -// {@code (s', 2, y)}, {@code (s'', 1, z)} yields non-conflicting set +// {@code (s', 2, y)}, {@code (s”, 1, z)} yields non-conflicting set // {@code {1}} U conflicting sets {@code min({1,2})} U {@code min({1,2})} = // {@code {1}} => stop and predict 1
  • // @@ -369,31 +366,26 @@ func PredictionModeallConfigsInRuleStopStates(configs ATNConfigSet) bool { // two or one and three so we keep going. We can only stop prediction when // we need exact ambiguity detection when the sets look like // {@code A={{1,2}}} or {@code {{1,2},{1,2}}}, etc...

    -// func PredictionModeresolvesToJustOneViableAlt(altsets []*BitSet) int { return PredictionModegetSingleViableAlt(altsets) } -// // Determines if every alternative subset in {@code altsets} contains more // than one alternative. // // @param altsets a collection of alternative subsets // @return {@code true} if every {@link BitSet} in {@code altsets} has // {@link BitSet//cardinality cardinality} > 1, otherwise {@code false} -// func PredictionModeallSubsetsConflict(altsets []*BitSet) bool { return !PredictionModehasNonConflictingAltSet(altsets) } -// // Determines if any single alternative subset in {@code altsets} contains // exactly one alternative. // // @param altsets a collection of alternative subsets // @return {@code true} if {@code altsets} contains a {@link BitSet} with // {@link BitSet//cardinality cardinality} 1, otherwise {@code false} -// func PredictionModehasNonConflictingAltSet(altsets []*BitSet) bool { for i := 0; i < len(altsets); i++ { alts := altsets[i] @@ -404,14 +396,12 @@ func PredictionModehasNonConflictingAltSet(altsets []*BitSet) bool { return false } -// // Determines if any single alternative subset in {@code altsets} contains // more than one alternative. // // @param altsets a collection of alternative subsets // @return {@code true} if {@code altsets} contains a {@link BitSet} with // {@link BitSet//cardinality cardinality} > 1, otherwise {@code false} -// func PredictionModehasConflictingAltSet(altsets []*BitSet) bool { for i := 0; i < len(altsets); i++ { alts := altsets[i] @@ -422,13 +412,11 @@ func PredictionModehasConflictingAltSet(altsets []*BitSet) bool { return false } -// // Determines if every alternative subset in {@code altsets} is equivalent. // // @param altsets a collection of alternative subsets // @return {@code true} if every member of {@code altsets} is equal to the // others, otherwise {@code false} -// func PredictionModeallSubsetsEqual(altsets []*BitSet) bool { var first *BitSet @@ -444,13 +432,11 @@ func PredictionModeallSubsetsEqual(altsets []*BitSet) bool { return true } -// // Returns the unique alternative predicted by all alternative subsets in // {@code altsets}. If no such alternative exists, this method returns // {@link ATN//INVALID_ALT_NUMBER}. // // @param altsets a collection of alternative subsets -// func PredictionModegetUniqueAlt(altsets []*BitSet) int { all := PredictionModeGetAlts(altsets) if all.length() == 1 { @@ -466,7 +452,6 @@ func PredictionModegetUniqueAlt(altsets []*BitSet) int { // // @param altsets a collection of alternative subsets // @return the set of represented alternatives in {@code altsets} -// func PredictionModeGetAlts(altsets []*BitSet) *BitSet { all := NewBitSet() for _, alts := range altsets { @@ -475,44 +460,35 @@ func PredictionModeGetAlts(altsets []*BitSet) *BitSet { return all } -// -// This func gets the conflicting alt subsets from a configuration set. +// PredictionModegetConflictingAltSubsets gets the conflicting alt subsets from a configuration set. // For each configuration {@code c} in {@code configs}: // //
     // map[c] U= c.{@link ATNConfig//alt alt} // map hash/equals uses s and x, not
     // alt and not pred
     // 
    -// func PredictionModegetConflictingAltSubsets(configs ATNConfigSet) []*BitSet { - configToAlts := make(map[int]*BitSet) + configToAlts := NewJMap[ATNConfig, *BitSet, *ATNAltConfigComparator[ATNConfig]](atnAltCfgEqInst) for _, c := range configs.GetItems() { - key := 31 * c.GetState().GetStateNumber() + c.GetContext().hash() - alts, ok := configToAlts[key] + alts, ok := configToAlts.Get(c) if !ok { alts = NewBitSet() - configToAlts[key] = alts + configToAlts.Put(c, alts) } alts.add(c.GetAlt()) } - values := make([]*BitSet, 0, 10) - for _, v := range configToAlts { - values = append(values, v) - } - return values + return configToAlts.Values() } -// -// Get a map from state to alt subset from a configuration set. For each +// PredictionModeGetStateToAltMap gets a map from state to alt subset from a configuration set. For each // configuration {@code c} in {@code configs}: // //
     // map[c.{@link ATNConfig//state state}] U= c.{@link ATNConfig//alt alt}
     // 
    -// func PredictionModeGetStateToAltMap(configs ATNConfigSet) *AltDict { m := NewAltDict() diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/recognizer.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/recognizer.go similarity index 92% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/recognizer.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/recognizer.go index 93efcf355d..bfe542d091 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/recognizer.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/recognizer.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. @@ -49,7 +49,7 @@ var tokenTypeMapCache = make(map[string]int) var ruleIndexMapCache = make(map[string]int) func (b *BaseRecognizer) checkVersion(toolVersion string) { - runtimeVersion := "4.10.1" + runtimeVersion := "4.12.0" if runtimeVersion != toolVersion { fmt.Println("ANTLR runtime and generated code versions disagree: " + runtimeVersion + "!=" + toolVersion) } @@ -108,7 +108,6 @@ func (b *BaseRecognizer) SetState(v int) { // Get a map from rule names to rule indexes. // //

    Used for XPath and tree pattern compilation.

    -// func (b *BaseRecognizer) GetRuleIndexMap() map[string]int { panic("Method not defined!") @@ -171,18 +170,18 @@ func (b *BaseRecognizer) GetErrorHeader(e RecognitionException) string { } // How should a token be displayed in an error message? The default -// is to display just the text, but during development you might -// want to have a lot of information spit out. Override in that case -// to use t.String() (which, for CommonToken, dumps everything about -// the token). This is better than forcing you to override a method in -// your token objects because you don't have to go modify your lexer -// so that it creates a NewJava type. +// +// is to display just the text, but during development you might +// want to have a lot of information spit out. Override in that case +// to use t.String() (which, for CommonToken, dumps everything about +// the token). This is better than forcing you to override a method in +// your token objects because you don't have to go modify your lexer +// so that it creates a NewJava type. // // @deprecated This method is not called by the ANTLR 4 Runtime. Specific // implementations of {@link ANTLRErrorStrategy} may provide a similar // feature when necessary. For example, see // {@link DefaultErrorStrategy//GetTokenErrorDisplay}. -// func (b *BaseRecognizer) GetTokenErrorDisplay(t Token) string { if t == nil { return "" diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/rule_context.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/rule_context.go similarity index 97% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/rule_context.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/rule_context.go index 600cf8c062..210699ba23 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/rule_context.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/rule_context.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/semantic_context.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/semantic_context.go similarity index 85% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/semantic_context.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/semantic_context.go index 9ada430779..a702e99def 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/semantic_context.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/semantic_context.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. @@ -18,12 +18,12 @@ import ( // type SemanticContext interface { - comparable + Equals(other Collectable[SemanticContext]) bool + Hash() int evaluate(parser Recognizer, outerContext RuleContext) bool evalPrecedence(parser Recognizer, outerContext RuleContext) SemanticContext - hash() int String() string } @@ -78,7 +78,7 @@ func NewPredicate(ruleIndex, predIndex int, isCtxDependent bool) *Predicate { //The default {@link SemanticContext}, which is semantically equivalent to //a predicate of the form {@code {true}?}. -var SemanticContextNone SemanticContext = NewPredicate(-1, -1, false) +var SemanticContextNone = NewPredicate(-1, -1, false) func (p *Predicate) evalPrecedence(parser Recognizer, outerContext RuleContext) SemanticContext { return p @@ -95,7 +95,7 @@ func (p *Predicate) evaluate(parser Recognizer, outerContext RuleContext) bool { return parser.Sempred(localctx, p.ruleIndex, p.predIndex) } -func (p *Predicate) equals(other interface{}) bool { +func (p *Predicate) Equals(other Collectable[SemanticContext]) bool { if p == other { return true } else if _, ok := other.(*Predicate); !ok { @@ -107,7 +107,7 @@ func (p *Predicate) equals(other interface{}) bool { } } -func (p *Predicate) hash() int { +func (p *Predicate) Hash() int { h := murmurInit(0) h = murmurUpdate(h, p.ruleIndex) h = murmurUpdate(h, p.predIndex) @@ -151,17 +151,22 @@ func (p *PrecedencePredicate) compareTo(other *PrecedencePredicate) int { return p.precedence - other.precedence } -func (p *PrecedencePredicate) equals(other interface{}) bool { - if p == other { - return true - } else if _, ok := other.(*PrecedencePredicate); !ok { +func (p *PrecedencePredicate) Equals(other Collectable[SemanticContext]) bool { + + var op *PrecedencePredicate + var ok bool + if op, ok = other.(*PrecedencePredicate); !ok { return false - } else { - return p.precedence == other.(*PrecedencePredicate).precedence } + + if p == op { + return true + } + + return p.precedence == other.(*PrecedencePredicate).precedence } -func (p *PrecedencePredicate) hash() int { +func (p *PrecedencePredicate) Hash() int { h := uint32(1) h = 31*h + uint32(p.precedence) return int(h) @@ -171,10 +176,10 @@ func (p *PrecedencePredicate) String() string { return "{" + strconv.Itoa(p.precedence) + ">=prec}?" } -func PrecedencePredicatefilterPrecedencePredicates(set Set) []*PrecedencePredicate { +func PrecedencePredicatefilterPrecedencePredicates(set *JStore[SemanticContext, Comparator[SemanticContext]]) []*PrecedencePredicate { result := make([]*PrecedencePredicate, 0) - set.Each(func(v interface{}) bool { + set.Each(func(v SemanticContext) bool { if c2, ok := v.(*PrecedencePredicate); ok { result = append(result, c2) } @@ -193,21 +198,21 @@ type AND struct { func NewAND(a, b SemanticContext) *AND { - operands := newArray2DHashSet(nil, nil) + operands := NewJStore[SemanticContext, Comparator[SemanticContext]](semctxEqInst) if aa, ok := a.(*AND); ok { for _, o := range aa.opnds { - operands.Add(o) + operands.Put(o) } } else { - operands.Add(a) + operands.Put(a) } if ba, ok := b.(*AND); ok { for _, o := range ba.opnds { - operands.Add(o) + operands.Put(o) } } else { - operands.Add(b) + operands.Put(b) } precedencePredicates := PrecedencePredicatefilterPrecedencePredicates(operands) if len(precedencePredicates) > 0 { @@ -220,7 +225,7 @@ func NewAND(a, b SemanticContext) *AND { } } - operands.Add(reduced) + operands.Put(reduced) } vs := operands.Values() @@ -235,14 +240,15 @@ func NewAND(a, b SemanticContext) *AND { return and } -func (a *AND) equals(other interface{}) bool { +func (a *AND) Equals(other Collectable[SemanticContext]) bool { if a == other { return true - } else if _, ok := other.(*AND); !ok { + } + if _, ok := other.(*AND); !ok { return false } else { for i, v := range other.(*AND).opnds { - if !a.opnds[i].equals(v) { + if !a.opnds[i].Equals(v) { return false } } @@ -250,13 +256,11 @@ func (a *AND) equals(other interface{}) bool { } } -// // {@inheritDoc} // //

    // The evaluation of predicates by a context is short-circuiting, but // unordered.

    -// func (a *AND) evaluate(parser Recognizer, outerContext RuleContext) bool { for i := 0; i < len(a.opnds); i++ { if !a.opnds[i].evaluate(parser, outerContext) { @@ -304,18 +308,18 @@ func (a *AND) evalPrecedence(parser Recognizer, outerContext RuleContext) Semant return result } -func (a *AND) hash() int { +func (a *AND) Hash() int { h := murmurInit(37) // Init with a value different from OR for _, op := range a.opnds { - h = murmurUpdate(h, op.hash()) + h = murmurUpdate(h, op.Hash()) } return murmurFinish(h, len(a.opnds)) } -func (a *OR) hash() int { +func (a *OR) Hash() int { h := murmurInit(41) // Init with a value different from AND for _, op := range a.opnds { - h = murmurUpdate(h, op.hash()) + h = murmurUpdate(h, op.Hash()) } return murmurFinish(h, len(a.opnds)) } @@ -345,21 +349,21 @@ type OR struct { func NewOR(a, b SemanticContext) *OR { - operands := newArray2DHashSet(nil, nil) + operands := NewJStore[SemanticContext, Comparator[SemanticContext]](semctxEqInst) if aa, ok := a.(*OR); ok { for _, o := range aa.opnds { - operands.Add(o) + operands.Put(o) } } else { - operands.Add(a) + operands.Put(a) } if ba, ok := b.(*OR); ok { for _, o := range ba.opnds { - operands.Add(o) + operands.Put(o) } } else { - operands.Add(b) + operands.Put(b) } precedencePredicates := PrecedencePredicatefilterPrecedencePredicates(operands) if len(precedencePredicates) > 0 { @@ -372,7 +376,7 @@ func NewOR(a, b SemanticContext) *OR { } } - operands.Add(reduced) + operands.Put(reduced) } vs := operands.Values() @@ -388,14 +392,14 @@ func NewOR(a, b SemanticContext) *OR { return o } -func (o *OR) equals(other interface{}) bool { +func (o *OR) Equals(other Collectable[SemanticContext]) bool { if o == other { return true } else if _, ok := other.(*OR); !ok { return false } else { for i, v := range other.(*OR).opnds { - if !o.opnds[i].equals(v) { + if !o.opnds[i].Equals(v) { return false } } @@ -406,7 +410,6 @@ func (o *OR) equals(other interface{}) bool { //

    // The evaluation of predicates by o context is short-circuiting, but // unordered.

    -// func (o *OR) evaluate(parser Recognizer, outerContext RuleContext) bool { for i := 0; i < len(o.opnds); i++ { if o.opnds[i].evaluate(parser, outerContext) { diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/token.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/token.go new file mode 100644 index 0000000000..f73b06bc6a --- /dev/null +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/token.go @@ -0,0 +1,209 @@ +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. +// Use of this file is governed by the BSD 3-clause license that +// can be found in the LICENSE.txt file in the project root. + +package antlr + +import ( + "strconv" + "strings" +) + +type TokenSourceCharStreamPair struct { + tokenSource TokenSource + charStream CharStream +} + +// A token has properties: text, type, line, character position in the line +// (so we can ignore tabs), token channel, index, and source from which +// we obtained this token. + +type Token interface { + GetSource() *TokenSourceCharStreamPair + GetTokenType() int + GetChannel() int + GetStart() int + GetStop() int + GetLine() int + GetColumn() int + + GetText() string + SetText(s string) + + GetTokenIndex() int + SetTokenIndex(v int) + + GetTokenSource() TokenSource + GetInputStream() CharStream +} + +type BaseToken struct { + source *TokenSourceCharStreamPair + tokenType int // token type of the token + channel int // The parser ignores everything not on DEFAULT_CHANNEL + start int // optional return -1 if not implemented. + stop int // optional return -1 if not implemented. + tokenIndex int // from 0..n-1 of the token object in the input stream + line int // line=1..n of the 1st character + column int // beginning of the line at which it occurs, 0..n-1 + text string // text of the token. + readOnly bool +} + +const ( + TokenInvalidType = 0 + + // During lookahead operations, this "token" signifies we hit rule end ATN state + // and did not follow it despite needing to. + TokenEpsilon = -2 + + TokenMinUserTokenType = 1 + + TokenEOF = -1 + + // All tokens go to the parser (unless Skip() is called in that rule) + // on a particular "channel". The parser tunes to a particular channel + // so that whitespace etc... can go to the parser on a "hidden" channel. + + TokenDefaultChannel = 0 + + // Anything on different channel than DEFAULT_CHANNEL is not parsed + // by parser. + + TokenHiddenChannel = 1 +) + +func (b *BaseToken) GetChannel() int { + return b.channel +} + +func (b *BaseToken) GetStart() int { + return b.start +} + +func (b *BaseToken) GetStop() int { + return b.stop +} + +func (b *BaseToken) GetLine() int { + return b.line +} + +func (b *BaseToken) GetColumn() int { + return b.column +} + +func (b *BaseToken) GetTokenType() int { + return b.tokenType +} + +func (b *BaseToken) GetSource() *TokenSourceCharStreamPair { + return b.source +} + +func (b *BaseToken) GetTokenIndex() int { + return b.tokenIndex +} + +func (b *BaseToken) SetTokenIndex(v int) { + b.tokenIndex = v +} + +func (b *BaseToken) GetTokenSource() TokenSource { + return b.source.tokenSource +} + +func (b *BaseToken) GetInputStream() CharStream { + return b.source.charStream +} + +type CommonToken struct { + *BaseToken +} + +func NewCommonToken(source *TokenSourceCharStreamPair, tokenType, channel, start, stop int) *CommonToken { + + t := new(CommonToken) + + t.BaseToken = new(BaseToken) + + t.source = source + t.tokenType = tokenType + t.channel = channel + t.start = start + t.stop = stop + t.tokenIndex = -1 + if t.source.tokenSource != nil { + t.line = source.tokenSource.GetLine() + t.column = source.tokenSource.GetCharPositionInLine() + } else { + t.column = -1 + } + return t +} + +// An empty {@link Pair} which is used as the default value of +// {@link //source} for tokens that do not have a source. + +//CommonToken.EMPTY_SOURCE = [ nil, nil ] + +// Constructs a New{@link CommonToken} as a copy of another {@link Token}. +// +//

    +// If {@code oldToken} is also a {@link CommonToken} instance, the newly +// constructed token will share a reference to the {@link //text} field and +// the {@link Pair} stored in {@link //source}. Otherwise, {@link //text} will +// be assigned the result of calling {@link //GetText}, and {@link //source} +// will be constructed from the result of {@link Token//GetTokenSource} and +// {@link Token//GetInputStream}.

    +// +// @param oldToken The token to copy. +func (c *CommonToken) clone() *CommonToken { + t := NewCommonToken(c.source, c.tokenType, c.channel, c.start, c.stop) + t.tokenIndex = c.GetTokenIndex() + t.line = c.GetLine() + t.column = c.GetColumn() + t.text = c.GetText() + return t +} + +func (c *CommonToken) GetText() string { + if c.text != "" { + return c.text + } + input := c.GetInputStream() + if input == nil { + return "" + } + n := input.Size() + if c.start < n && c.stop < n { + return input.GetTextFromInterval(NewInterval(c.start, c.stop)) + } + return "" +} + +func (c *CommonToken) SetText(text string) { + c.text = text +} + +func (c *CommonToken) String() string { + txt := c.GetText() + if txt != "" { + txt = strings.Replace(txt, "\n", "\\n", -1) + txt = strings.Replace(txt, "\r", "\\r", -1) + txt = strings.Replace(txt, "\t", "\\t", -1) + } else { + txt = "" + } + + var ch string + if c.channel > 0 { + ch = ",channel=" + strconv.Itoa(c.channel) + } else { + ch = "" + } + + return "[@" + strconv.Itoa(c.tokenIndex) + "," + strconv.Itoa(c.start) + ":" + strconv.Itoa(c.stop) + "='" + + txt + "',<" + strconv.Itoa(c.tokenType) + ">" + + ch + "," + strconv.Itoa(c.line) + ":" + strconv.Itoa(c.column) + "]" +} diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/token_source.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/token_source.go similarity index 85% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/token_source.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/token_source.go index e023978fef..a3f36eaa67 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/token_source.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/token_source.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/token_stream.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/token_stream.go similarity index 87% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/token_stream.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/token_stream.go index df92c81478..1527d43f60 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/token_stream.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/token_stream.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/tokenstream_rewriter.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/tokenstream_rewriter.go new file mode 100644 index 0000000000..b3e38af344 --- /dev/null +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/tokenstream_rewriter.go @@ -0,0 +1,659 @@ +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. +// Use of this file is governed by the BSD 3-clause license that +// can be found in the LICENSE.txt file in the project root. + +package antlr + +import ( + "bytes" + "fmt" +) + +// +// Useful for rewriting out a buffered input token stream after doing some +// augmentation or other manipulations on it. + +//

    +// You can insert stuff, replace, and delete chunks. Note that the operations +// are done lazily--only if you convert the buffer to a {@link String} with +// {@link TokenStream#getText()}. This is very efficient because you are not +// moving data around all the time. As the buffer of tokens is converted to +// strings, the {@link #getText()} method(s) scan the input token stream and +// check to see if there is an operation at the current index. If so, the +// operation is done and then normal {@link String} rendering continues on the +// buffer. This is like having multiple Turing machine instruction streams +// (programs) operating on a single input tape. :)

    +//

    + +// This rewriter makes no modifications to the token stream. It does not ask the +// stream to fill itself up nor does it advance the input cursor. The token +// stream {@link TokenStream#index()} will return the same value before and +// after any {@link #getText()} call.

    + +//

    +// The rewriter only works on tokens that you have in the buffer and ignores the +// current input cursor. If you are buffering tokens on-demand, calling +// {@link #getText()} halfway through the input will only do rewrites for those +// tokens in the first half of the file.

    + +//

    +// Since the operations are done lazily at {@link #getText}-time, operations do +// not screw up the token index values. That is, an insert operation at token +// index {@code i} does not change the index values for tokens +// {@code i}+1..n-1.

    + +//

    +// Because operations never actually alter the buffer, you may always get the +// original token stream back without undoing anything. Since the instructions +// are queued up, you can easily simulate transactions and roll back any changes +// if there is an error just by removing instructions. For example,

    + +//
    +// CharStream input = new ANTLRFileStream("input");
    +// TLexer lex = new TLexer(input);
    +// CommonTokenStream tokens = new CommonTokenStream(lex);
    +// T parser = new T(tokens);
    +// TokenStreamRewriter rewriter = new TokenStreamRewriter(tokens);
    +// parser.startRule();
    +// 
    + +//

    +// Then in the rules, you can execute (assuming rewriter is visible):

    + +//
    +// Token t,u;
    +// ...
    +// rewriter.insertAfter(t, "text to put after t");}
    +// rewriter.insertAfter(u, "text after u");}
    +// System.out.println(rewriter.getText());
    +// 
    + +//

    +// You can also have multiple "instruction streams" and get multiple rewrites +// from a single pass over the input. Just name the instruction streams and use +// that name again when printing the buffer. This could be useful for generating +// a C file and also its header file--all from the same buffer:

    + +//
    +// rewriter.insertAfter("pass1", t, "text to put after t");}
    +// rewriter.insertAfter("pass2", u, "text after u");}
    +// System.out.println(rewriter.getText("pass1"));
    +// System.out.println(rewriter.getText("pass2"));
    +// 
    + +//

    +// If you don't use named rewrite streams, a "default" stream is used as the +// first example shows.

    + +const ( + Default_Program_Name = "default" + Program_Init_Size = 100 + Min_Token_Index = 0 +) + +// Define the rewrite operation hierarchy + +type RewriteOperation interface { + // Execute the rewrite operation by possibly adding to the buffer. + // Return the index of the next token to operate on. + Execute(buffer *bytes.Buffer) int + String() string + GetInstructionIndex() int + GetIndex() int + GetText() string + GetOpName() string + GetTokens() TokenStream + SetInstructionIndex(val int) + SetIndex(int) + SetText(string) + SetOpName(string) + SetTokens(TokenStream) +} + +type BaseRewriteOperation struct { + //Current index of rewrites list + instruction_index int + //Token buffer index + index int + //Substitution text + text string + //Actual operation name + op_name string + //Pointer to token steam + tokens TokenStream +} + +func (op *BaseRewriteOperation) GetInstructionIndex() int { + return op.instruction_index +} + +func (op *BaseRewriteOperation) GetIndex() int { + return op.index +} + +func (op *BaseRewriteOperation) GetText() string { + return op.text +} + +func (op *BaseRewriteOperation) GetOpName() string { + return op.op_name +} + +func (op *BaseRewriteOperation) GetTokens() TokenStream { + return op.tokens +} + +func (op *BaseRewriteOperation) SetInstructionIndex(val int) { + op.instruction_index = val +} + +func (op *BaseRewriteOperation) SetIndex(val int) { + op.index = val +} + +func (op *BaseRewriteOperation) SetText(val string) { + op.text = val +} + +func (op *BaseRewriteOperation) SetOpName(val string) { + op.op_name = val +} + +func (op *BaseRewriteOperation) SetTokens(val TokenStream) { + op.tokens = val +} + +func (op *BaseRewriteOperation) Execute(buffer *bytes.Buffer) int { + return op.index +} + +func (op *BaseRewriteOperation) String() string { + return fmt.Sprintf("<%s@%d:\"%s\">", + op.op_name, + op.tokens.Get(op.GetIndex()), + op.text, + ) + +} + +type InsertBeforeOp struct { + BaseRewriteOperation +} + +func NewInsertBeforeOp(index int, text string, stream TokenStream) *InsertBeforeOp { + return &InsertBeforeOp{BaseRewriteOperation: BaseRewriteOperation{ + index: index, + text: text, + op_name: "InsertBeforeOp", + tokens: stream, + }} +} + +func (op *InsertBeforeOp) Execute(buffer *bytes.Buffer) int { + buffer.WriteString(op.text) + if op.tokens.Get(op.index).GetTokenType() != TokenEOF { + buffer.WriteString(op.tokens.Get(op.index).GetText()) + } + return op.index + 1 +} + +func (op *InsertBeforeOp) String() string { + return op.BaseRewriteOperation.String() +} + +// Distinguish between insert after/before to do the "insert afters" +// first and then the "insert befores" at same index. Implementation +// of "insert after" is "insert before index+1". + +type InsertAfterOp struct { + BaseRewriteOperation +} + +func NewInsertAfterOp(index int, text string, stream TokenStream) *InsertAfterOp { + return &InsertAfterOp{BaseRewriteOperation: BaseRewriteOperation{ + index: index + 1, + text: text, + tokens: stream, + }} +} + +func (op *InsertAfterOp) Execute(buffer *bytes.Buffer) int { + buffer.WriteString(op.text) + if op.tokens.Get(op.index).GetTokenType() != TokenEOF { + buffer.WriteString(op.tokens.Get(op.index).GetText()) + } + return op.index + 1 +} + +func (op *InsertAfterOp) String() string { + return op.BaseRewriteOperation.String() +} + +// I'm going to try replacing range from x..y with (y-x)+1 ReplaceOp +// instructions. +type ReplaceOp struct { + BaseRewriteOperation + LastIndex int +} + +func NewReplaceOp(from, to int, text string, stream TokenStream) *ReplaceOp { + return &ReplaceOp{ + BaseRewriteOperation: BaseRewriteOperation{ + index: from, + text: text, + op_name: "ReplaceOp", + tokens: stream, + }, + LastIndex: to, + } +} + +func (op *ReplaceOp) Execute(buffer *bytes.Buffer) int { + if op.text != "" { + buffer.WriteString(op.text) + } + return op.LastIndex + 1 +} + +func (op *ReplaceOp) String() string { + if op.text == "" { + return fmt.Sprintf("", + op.tokens.Get(op.index), op.tokens.Get(op.LastIndex)) + } + return fmt.Sprintf("", + op.tokens.Get(op.index), op.tokens.Get(op.LastIndex), op.text) +} + +type TokenStreamRewriter struct { + //Our source stream + tokens TokenStream + // You may have multiple, named streams of rewrite operations. + // I'm calling these things "programs." + // Maps String (name) → rewrite (List) + programs map[string][]RewriteOperation + last_rewrite_token_indexes map[string]int +} + +func NewTokenStreamRewriter(tokens TokenStream) *TokenStreamRewriter { + return &TokenStreamRewriter{ + tokens: tokens, + programs: map[string][]RewriteOperation{ + Default_Program_Name: make([]RewriteOperation, 0, Program_Init_Size), + }, + last_rewrite_token_indexes: map[string]int{}, + } +} + +func (tsr *TokenStreamRewriter) GetTokenStream() TokenStream { + return tsr.tokens +} + +// Rollback the instruction stream for a program so that +// the indicated instruction (via instructionIndex) is no +// longer in the stream. UNTESTED! +func (tsr *TokenStreamRewriter) Rollback(program_name string, instruction_index int) { + is, ok := tsr.programs[program_name] + if ok { + tsr.programs[program_name] = is[Min_Token_Index:instruction_index] + } +} + +func (tsr *TokenStreamRewriter) RollbackDefault(instruction_index int) { + tsr.Rollback(Default_Program_Name, instruction_index) +} + +// Reset the program so that no instructions exist +func (tsr *TokenStreamRewriter) DeleteProgram(program_name string) { + tsr.Rollback(program_name, Min_Token_Index) //TODO: double test on that cause lower bound is not included +} + +func (tsr *TokenStreamRewriter) DeleteProgramDefault() { + tsr.DeleteProgram(Default_Program_Name) +} + +func (tsr *TokenStreamRewriter) InsertAfter(program_name string, index int, text string) { + // to insert after, just insert before next index (even if past end) + var op RewriteOperation = NewInsertAfterOp(index, text, tsr.tokens) + rewrites := tsr.GetProgram(program_name) + op.SetInstructionIndex(len(rewrites)) + tsr.AddToProgram(program_name, op) +} + +func (tsr *TokenStreamRewriter) InsertAfterDefault(index int, text string) { + tsr.InsertAfter(Default_Program_Name, index, text) +} + +func (tsr *TokenStreamRewriter) InsertAfterToken(program_name string, token Token, text string) { + tsr.InsertAfter(program_name, token.GetTokenIndex(), text) +} + +func (tsr *TokenStreamRewriter) InsertBefore(program_name string, index int, text string) { + var op RewriteOperation = NewInsertBeforeOp(index, text, tsr.tokens) + rewrites := tsr.GetProgram(program_name) + op.SetInstructionIndex(len(rewrites)) + tsr.AddToProgram(program_name, op) +} + +func (tsr *TokenStreamRewriter) InsertBeforeDefault(index int, text string) { + tsr.InsertBefore(Default_Program_Name, index, text) +} + +func (tsr *TokenStreamRewriter) InsertBeforeToken(program_name string, token Token, text string) { + tsr.InsertBefore(program_name, token.GetTokenIndex(), text) +} + +func (tsr *TokenStreamRewriter) Replace(program_name string, from, to int, text string) { + if from > to || from < 0 || to < 0 || to >= tsr.tokens.Size() { + panic(fmt.Sprintf("replace: range invalid: %d..%d(size=%d)", + from, to, tsr.tokens.Size())) + } + var op RewriteOperation = NewReplaceOp(from, to, text, tsr.tokens) + rewrites := tsr.GetProgram(program_name) + op.SetInstructionIndex(len(rewrites)) + tsr.AddToProgram(program_name, op) +} + +func (tsr *TokenStreamRewriter) ReplaceDefault(from, to int, text string) { + tsr.Replace(Default_Program_Name, from, to, text) +} + +func (tsr *TokenStreamRewriter) ReplaceDefaultPos(index int, text string) { + tsr.ReplaceDefault(index, index, text) +} + +func (tsr *TokenStreamRewriter) ReplaceToken(program_name string, from, to Token, text string) { + tsr.Replace(program_name, from.GetTokenIndex(), to.GetTokenIndex(), text) +} + +func (tsr *TokenStreamRewriter) ReplaceTokenDefault(from, to Token, text string) { + tsr.ReplaceToken(Default_Program_Name, from, to, text) +} + +func (tsr *TokenStreamRewriter) ReplaceTokenDefaultPos(index Token, text string) { + tsr.ReplaceTokenDefault(index, index, text) +} + +func (tsr *TokenStreamRewriter) Delete(program_name string, from, to int) { + tsr.Replace(program_name, from, to, "") +} + +func (tsr *TokenStreamRewriter) DeleteDefault(from, to int) { + tsr.Delete(Default_Program_Name, from, to) +} + +func (tsr *TokenStreamRewriter) DeleteDefaultPos(index int) { + tsr.DeleteDefault(index, index) +} + +func (tsr *TokenStreamRewriter) DeleteToken(program_name string, from, to Token) { + tsr.ReplaceToken(program_name, from, to, "") +} + +func (tsr *TokenStreamRewriter) DeleteTokenDefault(from, to Token) { + tsr.DeleteToken(Default_Program_Name, from, to) +} + +func (tsr *TokenStreamRewriter) GetLastRewriteTokenIndex(program_name string) int { + i, ok := tsr.last_rewrite_token_indexes[program_name] + if !ok { + return -1 + } + return i +} + +func (tsr *TokenStreamRewriter) GetLastRewriteTokenIndexDefault() int { + return tsr.GetLastRewriteTokenIndex(Default_Program_Name) +} + +func (tsr *TokenStreamRewriter) SetLastRewriteTokenIndex(program_name string, i int) { + tsr.last_rewrite_token_indexes[program_name] = i +} + +func (tsr *TokenStreamRewriter) InitializeProgram(name string) []RewriteOperation { + is := make([]RewriteOperation, 0, Program_Init_Size) + tsr.programs[name] = is + return is +} + +func (tsr *TokenStreamRewriter) AddToProgram(name string, op RewriteOperation) { + is := tsr.GetProgram(name) + is = append(is, op) + tsr.programs[name] = is +} + +func (tsr *TokenStreamRewriter) GetProgram(name string) []RewriteOperation { + is, ok := tsr.programs[name] + if !ok { + is = tsr.InitializeProgram(name) + } + return is +} + +// Return the text from the original tokens altered per the +// instructions given to this rewriter. +func (tsr *TokenStreamRewriter) GetTextDefault() string { + return tsr.GetText( + Default_Program_Name, + NewInterval(0, tsr.tokens.Size()-1)) +} + +// Return the text from the original tokens altered per the +// instructions given to this rewriter. +func (tsr *TokenStreamRewriter) GetText(program_name string, interval *Interval) string { + rewrites := tsr.programs[program_name] + start := interval.Start + stop := interval.Stop + // ensure start/end are in range + stop = min(stop, tsr.tokens.Size()-1) + start = max(start, 0) + if rewrites == nil || len(rewrites) == 0 { + return tsr.tokens.GetTextFromInterval(interval) // no instructions to execute + } + buf := bytes.Buffer{} + // First, optimize instruction stream + indexToOp := reduceToSingleOperationPerIndex(rewrites) + // Walk buffer, executing instructions and emitting tokens + for i := start; i <= stop && i < tsr.tokens.Size(); { + op := indexToOp[i] + delete(indexToOp, i) // remove so any left have index size-1 + t := tsr.tokens.Get(i) + if op == nil { + // no operation at that index, just dump token + if t.GetTokenType() != TokenEOF { + buf.WriteString(t.GetText()) + } + i++ // move to next token + } else { + i = op.Execute(&buf) // execute operation and skip + } + } + // include stuff after end if it's last index in buffer + // So, if they did an insertAfter(lastValidIndex, "foo"), include + // foo if end==lastValidIndex. + if stop == tsr.tokens.Size()-1 { + // Scan any remaining operations after last token + // should be included (they will be inserts). + for _, op := range indexToOp { + if op.GetIndex() >= tsr.tokens.Size()-1 { + buf.WriteString(op.GetText()) + } + } + } + return buf.String() +} + +// We need to combine operations and report invalid operations (like +// overlapping replaces that are not completed nested). Inserts to +// same index need to be combined etc... Here are the cases: +// +// I.i.u I.j.v leave alone, nonoverlapping +// I.i.u I.i.v combine: Iivu +// +// R.i-j.u R.x-y.v | i-j in x-y delete first R +// R.i-j.u R.i-j.v delete first R +// R.i-j.u R.x-y.v | x-y in i-j ERROR +// R.i-j.u R.x-y.v | boundaries overlap ERROR +// +// Delete special case of replace (text==null): +// D.i-j.u D.x-y.v | boundaries overlap combine to max(min)..max(right) +// +// I.i.u R.x-y.v | i in (x+1)-y delete I (since insert before +// we're not deleting i) +// I.i.u R.x-y.v | i not in (x+1)-y leave alone, nonoverlapping +// R.x-y.v I.i.u | i in x-y ERROR +// R.x-y.v I.x.u R.x-y.uv (combine, delete I) +// R.x-y.v I.i.u | i not in x-y leave alone, nonoverlapping +// +// I.i.u = insert u before op @ index i +// R.x-y.u = replace x-y indexed tokens with u +// +// First we need to examine replaces. For any replace op: +// +// 1. wipe out any insertions before op within that range. +// 2. Drop any replace op before that is contained completely within +// that range. +// 3. Throw exception upon boundary overlap with any previous replace. +// +// Then we can deal with inserts: +// +// 1. for any inserts to same index, combine even if not adjacent. +// 2. for any prior replace with same left boundary, combine this +// insert with replace and delete this replace. +// 3. throw exception if index in same range as previous replace +// +// Don't actually delete; make op null in list. Easier to walk list. +// Later we can throw as we add to index → op map. +// +// Note that I.2 R.2-2 will wipe out I.2 even though, technically, the +// inserted stuff would be before the replace range. But, if you +// add tokens in front of a method body '{' and then delete the method +// body, I think the stuff before the '{' you added should disappear too. +// +// Return a map from token index to operation. +func reduceToSingleOperationPerIndex(rewrites []RewriteOperation) map[int]RewriteOperation { + // WALK REPLACES + for i := 0; i < len(rewrites); i++ { + op := rewrites[i] + if op == nil { + continue + } + rop, ok := op.(*ReplaceOp) + if !ok { + continue + } + // Wipe prior inserts within range + for j := 0; j < i && j < len(rewrites); j++ { + if iop, ok := rewrites[j].(*InsertBeforeOp); ok { + if iop.index == rop.index { + // E.g., insert before 2, delete 2..2; update replace + // text to include insert before, kill insert + rewrites[iop.instruction_index] = nil + if rop.text != "" { + rop.text = iop.text + rop.text + } else { + rop.text = iop.text + } + } else if iop.index > rop.index && iop.index <= rop.LastIndex { + // delete insert as it's a no-op. + rewrites[iop.instruction_index] = nil + } + } + } + // Drop any prior replaces contained within + for j := 0; j < i && j < len(rewrites); j++ { + if prevop, ok := rewrites[j].(*ReplaceOp); ok { + if prevop.index >= rop.index && prevop.LastIndex <= rop.LastIndex { + // delete replace as it's a no-op. + rewrites[prevop.instruction_index] = nil + continue + } + // throw exception unless disjoint or identical + disjoint := prevop.LastIndex < rop.index || prevop.index > rop.LastIndex + // Delete special case of replace (text==null): + // D.i-j.u D.x-y.v | boundaries overlap combine to max(min)..max(right) + if prevop.text == "" && rop.text == "" && !disjoint { + rewrites[prevop.instruction_index] = nil + rop.index = min(prevop.index, rop.index) + rop.LastIndex = max(prevop.LastIndex, rop.LastIndex) + println("new rop" + rop.String()) //TODO: remove console write, taken from Java version + } else if !disjoint { + panic("replace op boundaries of " + rop.String() + " overlap with previous " + prevop.String()) + } + } + } + } + // WALK INSERTS + for i := 0; i < len(rewrites); i++ { + op := rewrites[i] + if op == nil { + continue + } + //hack to replicate inheritance in composition + _, iok := rewrites[i].(*InsertBeforeOp) + _, aok := rewrites[i].(*InsertAfterOp) + if !iok && !aok { + continue + } + iop := rewrites[i] + // combine current insert with prior if any at same index + // deviating a bit from TokenStreamRewriter.java - hard to incorporate inheritance logic + for j := 0; j < i && j < len(rewrites); j++ { + if nextIop, ok := rewrites[j].(*InsertAfterOp); ok { + if nextIop.index == iop.GetIndex() { + iop.SetText(nextIop.text + iop.GetText()) + rewrites[j] = nil + } + } + if prevIop, ok := rewrites[j].(*InsertBeforeOp); ok { + if prevIop.index == iop.GetIndex() { + iop.SetText(iop.GetText() + prevIop.text) + rewrites[prevIop.instruction_index] = nil + } + } + } + // look for replaces where iop.index is in range; error + for j := 0; j < i && j < len(rewrites); j++ { + if rop, ok := rewrites[j].(*ReplaceOp); ok { + if iop.GetIndex() == rop.index { + rop.text = iop.GetText() + rop.text + rewrites[i] = nil + continue + } + if iop.GetIndex() >= rop.index && iop.GetIndex() <= rop.LastIndex { + panic("insert op " + iop.String() + " within boundaries of previous " + rop.String()) + } + } + } + } + m := map[int]RewriteOperation{} + for i := 0; i < len(rewrites); i++ { + op := rewrites[i] + if op == nil { + continue + } + if _, ok := m[op.GetIndex()]; ok { + panic("should only be one op per index") + } + m[op.GetIndex()] = op + } + return m +} + +/* + Quick fixing Go lack of overloads +*/ + +func max(a, b int) int { + if a > b { + return a + } else { + return b + } +} +func min(a, b int) int { + if a < b { + return a + } else { + return b + } +} diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/trace_listener.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/trace_listener.go similarity index 93% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/trace_listener.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/trace_listener.go index e6fff992ff..7b663bf849 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/trace_listener.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/trace_listener.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/transition.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/transition.go similarity index 99% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/transition.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/transition.go index 53056bd74f..36be4f7331 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/transition.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/transition.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/tree.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/tree.go similarity index 98% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/tree.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/tree.go index 08ce22bba3..85b4f137b5 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/tree.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/tree.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. @@ -234,10 +234,8 @@ func (p *ParseTreeWalker) Walk(listener ParseTreeListener, t Tree) { } } -// // Enters a grammar rule by first triggering the generic event {@link ParseTreeListener//EnterEveryRule} // then by triggering the event specific to the given parse tree node -// func (p *ParseTreeWalker) EnterRule(listener ParseTreeListener, r RuleNode) { ctx := r.GetRuleContext().(ParserRuleContext) listener.EnterEveryRule(ctx) @@ -246,7 +244,6 @@ func (p *ParseTreeWalker) EnterRule(listener ParseTreeListener, r RuleNode) { // Exits a grammar rule by first triggering the event specific to the given parse tree node // then by triggering the generic event {@link ParseTreeListener//ExitEveryRule} -// func (p *ParseTreeWalker) ExitRule(listener ParseTreeListener, r RuleNode) { ctx := r.GetRuleContext().(ParserRuleContext) ctx.ExitRule(listener) diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/trees.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/trees.go similarity index 93% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/trees.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/trees.go index 80144ecade..d7dbb03228 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/trees.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/trees.go @@ -1,4 +1,4 @@ -// Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. // Use of this file is governed by the BSD 3-clause license that // can be found in the LICENSE.txt file in the project root. @@ -9,8 +9,9 @@ import "fmt" /** A set of utility routines useful for all kinds of ANTLR trees. */ // Print out a whole tree in LISP form. {@link //getNodeText} is used on the -// node payloads to get the text for the nodes. Detect -// parse trees and extract data appropriately. +// +// node payloads to get the text for the nodes. Detect +// parse trees and extract data appropriately. func TreesStringTree(tree Tree, ruleNames []string, recog Recognizer) string { if recog != nil { @@ -80,8 +81,8 @@ func TreesGetChildren(t Tree) []Tree { } // Return a list of all ancestors of this node. The first node of -// list is the root and the last is the parent of this node. // +// list is the root and the last is the parent of this node. func TreesgetAncestors(t Tree) []Tree { ancestors := make([]Tree, 0) t = t.GetParent() diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/utils.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/utils.go new file mode 100644 index 0000000000..9fad5d916b --- /dev/null +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/utils.go @@ -0,0 +1,352 @@ +// Copyright (c) 2012-2022 The ANTLR Project. All rights reserved. +// Use of this file is governed by the BSD 3-clause license that +// can be found in the LICENSE.txt file in the project root. + +package antlr + +import ( + "bytes" + "errors" + "fmt" + "math/bits" + "strconv" + "strings" +) + +func intMin(a, b int) int { + if a < b { + return a + } + return b +} + +func intMax(a, b int) int { + if a > b { + return a + } + return b +} + +// A simple integer stack + +type IntStack []int + +var ErrEmptyStack = errors.New("Stack is empty") + +func (s *IntStack) Pop() (int, error) { + l := len(*s) - 1 + if l < 0 { + return 0, ErrEmptyStack + } + v := (*s)[l] + *s = (*s)[0:l] + return v, nil +} + +func (s *IntStack) Push(e int) { + *s = append(*s, e) +} + +type comparable interface { + Equals(other Collectable[any]) bool +} + +func standardEqualsFunction(a Collectable[any], b Collectable[any]) bool { + + return a.Equals(b) +} + +func standardHashFunction(a interface{}) int { + if h, ok := a.(hasher); ok { + return h.Hash() + } + + panic("Not Hasher") +} + +type hasher interface { + Hash() int +} + +const bitsPerWord = 64 + +func indexForBit(bit int) int { + return bit / bitsPerWord +} + +func wordForBit(data []uint64, bit int) uint64 { + idx := indexForBit(bit) + if idx >= len(data) { + return 0 + } + return data[idx] +} + +func maskForBit(bit int) uint64 { + return uint64(1) << (bit % bitsPerWord) +} + +func wordsNeeded(bit int) int { + return indexForBit(bit) + 1 +} + +type BitSet struct { + data []uint64 +} + +func NewBitSet() *BitSet { + return &BitSet{} +} + +func (b *BitSet) add(value int) { + idx := indexForBit(value) + if idx >= len(b.data) { + size := wordsNeeded(value) + data := make([]uint64, size) + copy(data, b.data) + b.data = data + } + b.data[idx] |= maskForBit(value) +} + +func (b *BitSet) clear(index int) { + idx := indexForBit(index) + if idx >= len(b.data) { + return + } + b.data[idx] &= ^maskForBit(index) +} + +func (b *BitSet) or(set *BitSet) { + // Get min size necessary to represent the bits in both sets. + bLen := b.minLen() + setLen := set.minLen() + maxLen := intMax(bLen, setLen) + if maxLen > len(b.data) { + // Increase the size of len(b.data) to repesent the bits in both sets. + data := make([]uint64, maxLen) + copy(data, b.data) + b.data = data + } + // len(b.data) is at least setLen. + for i := 0; i < setLen; i++ { + b.data[i] |= set.data[i] + } +} + +func (b *BitSet) remove(value int) { + b.clear(value) +} + +func (b *BitSet) contains(value int) bool { + idx := indexForBit(value) + if idx >= len(b.data) { + return false + } + return (b.data[idx] & maskForBit(value)) != 0 +} + +func (b *BitSet) minValue() int { + for i, v := range b.data { + if v == 0 { + continue + } + return i*bitsPerWord + bits.TrailingZeros64(v) + } + return 2147483647 +} + +func (b *BitSet) equals(other interface{}) bool { + otherBitSet, ok := other.(*BitSet) + if !ok { + return false + } + + if b == otherBitSet { + return true + } + + // We only compare set bits, so we cannot rely on the two slices having the same size. Its + // possible for two BitSets to have different slice lengths but the same set bits. So we only + // compare the relevant words and ignore the trailing zeros. + bLen := b.minLen() + otherLen := otherBitSet.minLen() + + if bLen != otherLen { + return false + } + + for i := 0; i < bLen; i++ { + if b.data[i] != otherBitSet.data[i] { + return false + } + } + + return true +} + +func (b *BitSet) minLen() int { + for i := len(b.data); i > 0; i-- { + if b.data[i-1] != 0 { + return i + } + } + return 0 +} + +func (b *BitSet) length() int { + cnt := 0 + for _, val := range b.data { + cnt += bits.OnesCount64(val) + } + return cnt +} + +func (b *BitSet) String() string { + vals := make([]string, 0, b.length()) + + for i, v := range b.data { + for v != 0 { + n := bits.TrailingZeros64(v) + vals = append(vals, strconv.Itoa(i*bitsPerWord+n)) + v &= ^(uint64(1) << n) + } + } + + return "{" + strings.Join(vals, ", ") + "}" +} + +type AltDict struct { + data map[string]interface{} +} + +func NewAltDict() *AltDict { + d := new(AltDict) + d.data = make(map[string]interface{}) + return d +} + +func (a *AltDict) Get(key string) interface{} { + key = "k-" + key + return a.data[key] +} + +func (a *AltDict) put(key string, value interface{}) { + key = "k-" + key + a.data[key] = value +} + +func (a *AltDict) values() []interface{} { + vs := make([]interface{}, len(a.data)) + i := 0 + for _, v := range a.data { + vs[i] = v + i++ + } + return vs +} + +type DoubleDict struct { + data map[int]map[int]interface{} +} + +func NewDoubleDict() *DoubleDict { + dd := new(DoubleDict) + dd.data = make(map[int]map[int]interface{}) + return dd +} + +func (d *DoubleDict) Get(a, b int) interface{} { + data := d.data[a] + + if data == nil { + return nil + } + + return data[b] +} + +func (d *DoubleDict) set(a, b int, o interface{}) { + data := d.data[a] + + if data == nil { + data = make(map[int]interface{}) + d.data[a] = data + } + + data[b] = o +} + +func EscapeWhitespace(s string, escapeSpaces bool) string { + + s = strings.Replace(s, "\t", "\\t", -1) + s = strings.Replace(s, "\n", "\\n", -1) + s = strings.Replace(s, "\r", "\\r", -1) + if escapeSpaces { + s = strings.Replace(s, " ", "\u00B7", -1) + } + return s +} + +func TerminalNodeToStringArray(sa []TerminalNode) []string { + st := make([]string, len(sa)) + + for i, s := range sa { + st[i] = fmt.Sprintf("%v", s) + } + + return st +} + +func PrintArrayJavaStyle(sa []string) string { + var buffer bytes.Buffer + + buffer.WriteString("[") + + for i, s := range sa { + buffer.WriteString(s) + if i != len(sa)-1 { + buffer.WriteString(", ") + } + } + + buffer.WriteString("]") + + return buffer.String() +} + +// murmur hash +func murmurInit(seed int) int { + return seed +} + +func murmurUpdate(h int, value int) int { + const c1 uint32 = 0xCC9E2D51 + const c2 uint32 = 0x1B873593 + const r1 uint32 = 15 + const r2 uint32 = 13 + const m uint32 = 5 + const n uint32 = 0xE6546B64 + + k := uint32(value) + k *= c1 + k = (k << r1) | (k >> (32 - r1)) + k *= c2 + + hash := uint32(h) ^ k + hash = (hash << r2) | (hash >> (32 - r2)) + hash = hash*m + n + return int(hash) +} + +func murmurFinish(h int, numberOfWords int) int { + var hash = uint32(h) + hash ^= uint32(numberOfWords) << 2 + hash ^= hash >> 16 + hash *= 0x85ebca6b + hash ^= hash >> 13 + hash *= 0xc2b2ae35 + hash ^= hash >> 16 + + return int(hash) +} diff --git a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/utils_set.go b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/utils_set.go similarity index 80% rename from vendor/github.com/antlr/antlr4/runtime/Go/antlr/utils_set.go rename to vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/utils_set.go index 0d4eac698d..c9bd6751e3 100644 --- a/vendor/github.com/antlr/antlr4/runtime/Go/antlr/utils_set.go +++ b/vendor/github.com/antlr/antlr4/runtime/Go/antlr/v4/utils_set.go @@ -8,8 +8,6 @@ const ( _loadFactor = 0.75 ) -var _ Set = (*array2DHashSet)(nil) - type Set interface { Add(value interface{}) (added interface{}) Len() int @@ -20,9 +18,9 @@ type Set interface { } type array2DHashSet struct { - buckets [][]interface{} + buckets [][]Collectable[any] hashcodeFunction func(interface{}) int - equalsFunction func(interface{}, interface{}) bool + equalsFunction func(Collectable[any], Collectable[any]) bool n int // How many elements in set threshold int // when to expand @@ -61,11 +59,11 @@ func (as *array2DHashSet) Values() []interface{} { return values } -func (as *array2DHashSet) Contains(value interface{}) bool { +func (as *array2DHashSet) Contains(value Collectable[any]) bool { return as.Get(value) != nil } -func (as *array2DHashSet) Add(value interface{}) interface{} { +func (as *array2DHashSet) Add(value Collectable[any]) interface{} { if as.n > as.threshold { as.expand() } @@ -98,7 +96,7 @@ func (as *array2DHashSet) expand() { b := as.getBuckets(o) bucketLength := newBucketLengths[b] - var newBucket []interface{} + var newBucket []Collectable[any] if bucketLength == 0 { // new bucket newBucket = as.createBucket(as.initialBucketCapacity) @@ -107,7 +105,7 @@ func (as *array2DHashSet) expand() { newBucket = newTable[b] if bucketLength == len(newBucket) { // expand - newBucketCopy := make([]interface{}, len(newBucket)<<1) + newBucketCopy := make([]Collectable[any], len(newBucket)<<1) copy(newBucketCopy[:bucketLength], newBucket) newBucket = newBucketCopy newTable[b] = newBucket @@ -124,7 +122,7 @@ func (as *array2DHashSet) Len() int { return as.n } -func (as *array2DHashSet) Get(o interface{}) interface{} { +func (as *array2DHashSet) Get(o Collectable[any]) interface{} { if o == nil { return nil } @@ -147,7 +145,7 @@ func (as *array2DHashSet) Get(o interface{}) interface{} { return nil } -func (as *array2DHashSet) innerAdd(o interface{}) interface{} { +func (as *array2DHashSet) innerAdd(o Collectable[any]) interface{} { b := as.getBuckets(o) bucket := as.buckets[b] @@ -178,7 +176,7 @@ func (as *array2DHashSet) innerAdd(o interface{}) interface{} { // full bucket, expand and add to end oldLength := len(bucket) - bucketCopy := make([]interface{}, oldLength<<1) + bucketCopy := make([]Collectable[any], oldLength<<1) copy(bucketCopy[:oldLength], bucket) bucket = bucketCopy as.buckets[b] = bucket @@ -187,22 +185,22 @@ func (as *array2DHashSet) innerAdd(o interface{}) interface{} { return o } -func (as *array2DHashSet) getBuckets(value interface{}) int { +func (as *array2DHashSet) getBuckets(value Collectable[any]) int { hash := as.hashcodeFunction(value) return hash & (len(as.buckets) - 1) } -func (as *array2DHashSet) createBuckets(cap int) [][]interface{} { - return make([][]interface{}, cap) +func (as *array2DHashSet) createBuckets(cap int) [][]Collectable[any] { + return make([][]Collectable[any], cap) } -func (as *array2DHashSet) createBucket(cap int) []interface{} { - return make([]interface{}, cap) +func (as *array2DHashSet) createBucket(cap int) []Collectable[any] { + return make([]Collectable[any], cap) } func newArray2DHashSetWithCap( hashcodeFunction func(interface{}) int, - equalsFunction func(interface{}, interface{}) bool, + equalsFunction func(Collectable[any], Collectable[any]) bool, initCap int, initBucketCap int, ) *array2DHashSet { @@ -231,7 +229,7 @@ func newArray2DHashSetWithCap( func newArray2DHashSet( hashcodeFunction func(interface{}) int, - equalsFunction func(interface{}, interface{}) bool, + equalsFunction func(Collectable[any], Collectable[any]) bool, ) *array2DHashSet { return newArray2DHashSetWithCap(hashcodeFunction, equalsFunction, _initalCapacity, _initalBucketCapacity) } diff --git a/vendor/github.com/blang/semver/.travis.yml b/vendor/github.com/blang/semver/.travis.yml deleted file mode 100644 index 102fb9a691..0000000000 --- a/vendor/github.com/blang/semver/.travis.yml +++ /dev/null @@ -1,21 +0,0 @@ -language: go -matrix: - include: - - go: 1.4.3 - - go: 1.5.4 - - go: 1.6.3 - - go: 1.7 - - go: tip - allow_failures: - - go: tip -install: -- go get golang.org/x/tools/cmd/cover -- go get github.com/mattn/goveralls -script: -- echo "Test and track coverage" ; $HOME/gopath/bin/goveralls -package "." -service=travis-ci - -repotoken $COVERALLS_TOKEN -- echo "Build examples" ; cd examples && go build -- echo "Check if gofmt'd" ; diff -u <(echo -n) <(gofmt -d -s .) -env: - global: - secure: HroGEAUQpVq9zX1b1VIkraLiywhGbzvNnTZq2TMxgK7JHP8xqNplAeF1izrR2i4QLL9nsY+9WtYss4QuPvEtZcVHUobw6XnL6radF7jS1LgfYZ9Y7oF+zogZ2I5QUMRLGA7rcxQ05s7mKq3XZQfeqaNts4bms/eZRefWuaFZbkw= diff --git a/vendor/github.com/blang/semver/LICENSE b/vendor/github.com/blang/semver/LICENSE deleted file mode 100644 index 5ba5c86fcb..0000000000 --- a/vendor/github.com/blang/semver/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License - -Copyright (c) 2014 Benedikt Lang - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - diff --git a/vendor/github.com/blang/semver/README.md b/vendor/github.com/blang/semver/README.md deleted file mode 100644 index 08b2e4a3d7..0000000000 --- a/vendor/github.com/blang/semver/README.md +++ /dev/null @@ -1,194 +0,0 @@ -semver for golang [![Build Status](https://travis-ci.org/blang/semver.svg?branch=master)](https://travis-ci.org/blang/semver) [![GoDoc](https://godoc.org/github.com/blang/semver?status.png)](https://godoc.org/github.com/blang/semver) [![Coverage Status](https://img.shields.io/coveralls/blang/semver.svg)](https://coveralls.io/r/blang/semver?branch=master) -====== - -semver is a [Semantic Versioning](http://semver.org/) library written in golang. It fully covers spec version `2.0.0`. - -Usage ------ -```bash -$ go get github.com/blang/semver -``` -Note: Always vendor your dependencies or fix on a specific version tag. - -```go -import github.com/blang/semver -v1, err := semver.Make("1.0.0-beta") -v2, err := semver.Make("2.0.0-beta") -v1.Compare(v2) -``` - -Also check the [GoDocs](http://godoc.org/github.com/blang/semver). - -Why should I use this lib? ------ - -- Fully spec compatible -- No reflection -- No regex -- Fully tested (Coverage >99%) -- Readable parsing/validation errors -- Fast (See [Benchmarks](#benchmarks)) -- Only Stdlib -- Uses values instead of pointers -- Many features, see below - - -Features ------ - -- Parsing and validation at all levels -- Comparator-like comparisons -- Compare Helper Methods -- InPlace manipulation -- Ranges `>=1.0.0 <2.0.0 || >=3.0.0 !3.0.1-beta.1` -- Wildcards `>=1.x`, `<=2.5.x` -- Sortable (implements sort.Interface) -- database/sql compatible (sql.Scanner/Valuer) -- encoding/json compatible (json.Marshaler/Unmarshaler) - -Ranges ------- - -A `Range` is a set of conditions which specify which versions satisfy the range. - -A condition is composed of an operator and a version. The supported operators are: - -- `<1.0.0` Less than `1.0.0` -- `<=1.0.0` Less than or equal to `1.0.0` -- `>1.0.0` Greater than `1.0.0` -- `>=1.0.0` Greater than or equal to `1.0.0` -- `1.0.0`, `=1.0.0`, `==1.0.0` Equal to `1.0.0` -- `!1.0.0`, `!=1.0.0` Not equal to `1.0.0`. Excludes version `1.0.0`. - -Note that spaces between the operator and the version will be gracefully tolerated. - -A `Range` can link multiple `Ranges` separated by space: - -Ranges can be linked by logical AND: - - - `>1.0.0 <2.0.0` would match between both ranges, so `1.1.1` and `1.8.7` but not `1.0.0` or `2.0.0` - - `>1.0.0 <3.0.0 !2.0.3-beta.2` would match every version between `1.0.0` and `3.0.0` except `2.0.3-beta.2` - -Ranges can also be linked by logical OR: - - - `<2.0.0 || >=3.0.0` would match `1.x.x` and `3.x.x` but not `2.x.x` - -AND has a higher precedence than OR. It's not possible to use brackets. - -Ranges can be combined by both AND and OR - - - `>1.0.0 <2.0.0 || >3.0.0 !4.2.1` would match `1.2.3`, `1.9.9`, `3.1.1`, but not `4.2.1`, `2.1.1` - -Range usage: - -``` -v, err := semver.Parse("1.2.3") -range, err := semver.ParseRange(">1.0.0 <2.0.0 || >=3.0.0") -if range(v) { - //valid -} - -``` - -Example ------ - -Have a look at full examples in [examples/main.go](examples/main.go) - -```go -import github.com/blang/semver - -v, err := semver.Make("0.0.1-alpha.preview+123.github") -fmt.Printf("Major: %d\n", v.Major) -fmt.Printf("Minor: %d\n", v.Minor) -fmt.Printf("Patch: %d\n", v.Patch) -fmt.Printf("Pre: %s\n", v.Pre) -fmt.Printf("Build: %s\n", v.Build) - -// Prerelease versions array -if len(v.Pre) > 0 { - fmt.Println("Prerelease versions:") - for i, pre := range v.Pre { - fmt.Printf("%d: %q\n", i, pre) - } -} - -// Build meta data array -if len(v.Build) > 0 { - fmt.Println("Build meta data:") - for i, build := range v.Build { - fmt.Printf("%d: %q\n", i, build) - } -} - -v001, err := semver.Make("0.0.1") -// Compare using helpers: v.GT(v2), v.LT, v.GTE, v.LTE -v001.GT(v) == true -v.LT(v001) == true -v.GTE(v) == true -v.LTE(v) == true - -// Or use v.Compare(v2) for comparisons (-1, 0, 1): -v001.Compare(v) == 1 -v.Compare(v001) == -1 -v.Compare(v) == 0 - -// Manipulate Version in place: -v.Pre[0], err = semver.NewPRVersion("beta") -if err != nil { - fmt.Printf("Error parsing pre release version: %q", err) -} - -fmt.Println("\nValidate versions:") -v.Build[0] = "?" - -err = v.Validate() -if err != nil { - fmt.Printf("Validation failed: %s\n", err) -} -``` - - -Benchmarks ------ - - BenchmarkParseSimple-4 5000000 390 ns/op 48 B/op 1 allocs/op - BenchmarkParseComplex-4 1000000 1813 ns/op 256 B/op 7 allocs/op - BenchmarkParseAverage-4 1000000 1171 ns/op 163 B/op 4 allocs/op - BenchmarkStringSimple-4 20000000 119 ns/op 16 B/op 1 allocs/op - BenchmarkStringLarger-4 10000000 206 ns/op 32 B/op 2 allocs/op - BenchmarkStringComplex-4 5000000 324 ns/op 80 B/op 3 allocs/op - BenchmarkStringAverage-4 5000000 273 ns/op 53 B/op 2 allocs/op - BenchmarkValidateSimple-4 200000000 9.33 ns/op 0 B/op 0 allocs/op - BenchmarkValidateComplex-4 3000000 469 ns/op 0 B/op 0 allocs/op - BenchmarkValidateAverage-4 5000000 256 ns/op 0 B/op 0 allocs/op - BenchmarkCompareSimple-4 100000000 11.8 ns/op 0 B/op 0 allocs/op - BenchmarkCompareComplex-4 50000000 30.8 ns/op 0 B/op 0 allocs/op - BenchmarkCompareAverage-4 30000000 41.5 ns/op 0 B/op 0 allocs/op - BenchmarkSort-4 3000000 419 ns/op 256 B/op 2 allocs/op - BenchmarkRangeParseSimple-4 2000000 850 ns/op 192 B/op 5 allocs/op - BenchmarkRangeParseAverage-4 1000000 1677 ns/op 400 B/op 10 allocs/op - BenchmarkRangeParseComplex-4 300000 5214 ns/op 1440 B/op 30 allocs/op - BenchmarkRangeMatchSimple-4 50000000 25.6 ns/op 0 B/op 0 allocs/op - BenchmarkRangeMatchAverage-4 30000000 56.4 ns/op 0 B/op 0 allocs/op - BenchmarkRangeMatchComplex-4 10000000 153 ns/op 0 B/op 0 allocs/op - -See benchmark cases at [semver_test.go](semver_test.go) - - -Motivation ------ - -I simply couldn't find any lib supporting the full spec. Others were just wrong or used reflection and regex which i don't like. - - -Contribution ------ - -Feel free to make a pull request. For bigger changes create a issue first to discuss about it. - - -License ------ - -See [LICENSE](LICENSE) file. diff --git a/vendor/github.com/blang/semver/json.go b/vendor/github.com/blang/semver/json.go deleted file mode 100644 index a74bf7c449..0000000000 --- a/vendor/github.com/blang/semver/json.go +++ /dev/null @@ -1,23 +0,0 @@ -package semver - -import ( - "encoding/json" -) - -// MarshalJSON implements the encoding/json.Marshaler interface. -func (v Version) MarshalJSON() ([]byte, error) { - return json.Marshal(v.String()) -} - -// UnmarshalJSON implements the encoding/json.Unmarshaler interface. -func (v *Version) UnmarshalJSON(data []byte) (err error) { - var versionString string - - if err = json.Unmarshal(data, &versionString); err != nil { - return - } - - *v, err = Parse(versionString) - - return -} diff --git a/vendor/github.com/blang/semver/package.json b/vendor/github.com/blang/semver/package.json deleted file mode 100644 index 1cf8ebdd9c..0000000000 --- a/vendor/github.com/blang/semver/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "author": "blang", - "bugs": { - "URL": "https://github.com/blang/semver/issues", - "url": "https://github.com/blang/semver/issues" - }, - "gx": { - "dvcsimport": "github.com/blang/semver" - }, - "gxVersion": "0.10.0", - "language": "go", - "license": "MIT", - "name": "semver", - "releaseCmd": "git commit -a -m \"gx publish $VERSION\"", - "version": "3.5.1" -} - diff --git a/vendor/github.com/blang/semver/range.go b/vendor/github.com/blang/semver/range.go deleted file mode 100644 index fca406d479..0000000000 --- a/vendor/github.com/blang/semver/range.go +++ /dev/null @@ -1,416 +0,0 @@ -package semver - -import ( - "fmt" - "strconv" - "strings" - "unicode" -) - -type wildcardType int - -const ( - noneWildcard wildcardType = iota - majorWildcard wildcardType = 1 - minorWildcard wildcardType = 2 - patchWildcard wildcardType = 3 -) - -func wildcardTypefromInt(i int) wildcardType { - switch i { - case 1: - return majorWildcard - case 2: - return minorWildcard - case 3: - return patchWildcard - default: - return noneWildcard - } -} - -type comparator func(Version, Version) bool - -var ( - compEQ comparator = func(v1 Version, v2 Version) bool { - return v1.Compare(v2) == 0 - } - compNE = func(v1 Version, v2 Version) bool { - return v1.Compare(v2) != 0 - } - compGT = func(v1 Version, v2 Version) bool { - return v1.Compare(v2) == 1 - } - compGE = func(v1 Version, v2 Version) bool { - return v1.Compare(v2) >= 0 - } - compLT = func(v1 Version, v2 Version) bool { - return v1.Compare(v2) == -1 - } - compLE = func(v1 Version, v2 Version) bool { - return v1.Compare(v2) <= 0 - } -) - -type versionRange struct { - v Version - c comparator -} - -// rangeFunc creates a Range from the given versionRange. -func (vr *versionRange) rangeFunc() Range { - return Range(func(v Version) bool { - return vr.c(v, vr.v) - }) -} - -// Range represents a range of versions. -// A Range can be used to check if a Version satisfies it: -// -// range, err := semver.ParseRange(">1.0.0 <2.0.0") -// range(semver.MustParse("1.1.1") // returns true -type Range func(Version) bool - -// OR combines the existing Range with another Range using logical OR. -func (rf Range) OR(f Range) Range { - return Range(func(v Version) bool { - return rf(v) || f(v) - }) -} - -// AND combines the existing Range with another Range using logical AND. -func (rf Range) AND(f Range) Range { - return Range(func(v Version) bool { - return rf(v) && f(v) - }) -} - -// ParseRange parses a range and returns a Range. -// If the range could not be parsed an error is returned. -// -// Valid ranges are: -// - "<1.0.0" -// - "<=1.0.0" -// - ">1.0.0" -// - ">=1.0.0" -// - "1.0.0", "=1.0.0", "==1.0.0" -// - "!1.0.0", "!=1.0.0" -// -// A Range can consist of multiple ranges separated by space: -// Ranges can be linked by logical AND: -// - ">1.0.0 <2.0.0" would match between both ranges, so "1.1.1" and "1.8.7" but not "1.0.0" or "2.0.0" -// - ">1.0.0 <3.0.0 !2.0.3-beta.2" would match every version between 1.0.0 and 3.0.0 except 2.0.3-beta.2 -// -// Ranges can also be linked by logical OR: -// - "<2.0.0 || >=3.0.0" would match "1.x.x" and "3.x.x" but not "2.x.x" -// -// AND has a higher precedence than OR. It's not possible to use brackets. -// -// Ranges can be combined by both AND and OR -// -// - `>1.0.0 <2.0.0 || >3.0.0 !4.2.1` would match `1.2.3`, `1.9.9`, `3.1.1`, but not `4.2.1`, `2.1.1` -func ParseRange(s string) (Range, error) { - parts := splitAndTrim(s) - orParts, err := splitORParts(parts) - if err != nil { - return nil, err - } - expandedParts, err := expandWildcardVersion(orParts) - if err != nil { - return nil, err - } - var orFn Range - for _, p := range expandedParts { - var andFn Range - for _, ap := range p { - opStr, vStr, err := splitComparatorVersion(ap) - if err != nil { - return nil, err - } - vr, err := buildVersionRange(opStr, vStr) - if err != nil { - return nil, fmt.Errorf("Could not parse Range %q: %s", ap, err) - } - rf := vr.rangeFunc() - - // Set function - if andFn == nil { - andFn = rf - } else { // Combine with existing function - andFn = andFn.AND(rf) - } - } - if orFn == nil { - orFn = andFn - } else { - orFn = orFn.OR(andFn) - } - - } - return orFn, nil -} - -// splitORParts splits the already cleaned parts by '||'. -// Checks for invalid positions of the operator and returns an -// error if found. -func splitORParts(parts []string) ([][]string, error) { - var ORparts [][]string - last := 0 - for i, p := range parts { - if p == "||" { - if i == 0 { - return nil, fmt.Errorf("First element in range is '||'") - } - ORparts = append(ORparts, parts[last:i]) - last = i + 1 - } - } - if last == len(parts) { - return nil, fmt.Errorf("Last element in range is '||'") - } - ORparts = append(ORparts, parts[last:]) - return ORparts, nil -} - -// buildVersionRange takes a slice of 2: operator and version -// and builds a versionRange, otherwise an error. -func buildVersionRange(opStr, vStr string) (*versionRange, error) { - c := parseComparator(opStr) - if c == nil { - return nil, fmt.Errorf("Could not parse comparator %q in %q", opStr, strings.Join([]string{opStr, vStr}, "")) - } - v, err := Parse(vStr) - if err != nil { - return nil, fmt.Errorf("Could not parse version %q in %q: %s", vStr, strings.Join([]string{opStr, vStr}, ""), err) - } - - return &versionRange{ - v: v, - c: c, - }, nil - -} - -// inArray checks if a byte is contained in an array of bytes -func inArray(s byte, list []byte) bool { - for _, el := range list { - if el == s { - return true - } - } - return false -} - -// splitAndTrim splits a range string by spaces and cleans whitespaces -func splitAndTrim(s string) (result []string) { - last := 0 - var lastChar byte - excludeFromSplit := []byte{'>', '<', '='} - for i := 0; i < len(s); i++ { - if s[i] == ' ' && !inArray(lastChar, excludeFromSplit) { - if last < i-1 { - result = append(result, s[last:i]) - } - last = i + 1 - } else if s[i] != ' ' { - lastChar = s[i] - } - } - if last < len(s)-1 { - result = append(result, s[last:]) - } - - for i, v := range result { - result[i] = strings.Replace(v, " ", "", -1) - } - - // parts := strings.Split(s, " ") - // for _, x := range parts { - // if s := strings.TrimSpace(x); len(s) != 0 { - // result = append(result, s) - // } - // } - return -} - -// splitComparatorVersion splits the comparator from the version. -// Input must be free of leading or trailing spaces. -func splitComparatorVersion(s string) (string, string, error) { - i := strings.IndexFunc(s, unicode.IsDigit) - if i == -1 { - return "", "", fmt.Errorf("Could not get version from string: %q", s) - } - return strings.TrimSpace(s[0:i]), s[i:], nil -} - -// getWildcardType will return the type of wildcard that the -// passed version contains -func getWildcardType(vStr string) wildcardType { - parts := strings.Split(vStr, ".") - nparts := len(parts) - wildcard := parts[nparts-1] - - possibleWildcardType := wildcardTypefromInt(nparts) - if wildcard == "x" { - return possibleWildcardType - } - - return noneWildcard -} - -// createVersionFromWildcard will convert a wildcard version -// into a regular version, replacing 'x's with '0's, handling -// special cases like '1.x.x' and '1.x' -func createVersionFromWildcard(vStr string) string { - // handle 1.x.x - vStr2 := strings.Replace(vStr, ".x.x", ".x", 1) - vStr2 = strings.Replace(vStr2, ".x", ".0", 1) - parts := strings.Split(vStr2, ".") - - // handle 1.x - if len(parts) == 2 { - return vStr2 + ".0" - } - - return vStr2 -} - -// incrementMajorVersion will increment the major version -// of the passed version -func incrementMajorVersion(vStr string) (string, error) { - parts := strings.Split(vStr, ".") - i, err := strconv.Atoi(parts[0]) - if err != nil { - return "", err - } - parts[0] = strconv.Itoa(i + 1) - - return strings.Join(parts, "."), nil -} - -// incrementMajorVersion will increment the minor version -// of the passed version -func incrementMinorVersion(vStr string) (string, error) { - parts := strings.Split(vStr, ".") - i, err := strconv.Atoi(parts[1]) - if err != nil { - return "", err - } - parts[1] = strconv.Itoa(i + 1) - - return strings.Join(parts, "."), nil -} - -// expandWildcardVersion will expand wildcards inside versions -// following these rules: -// -// * when dealing with patch wildcards: -// >= 1.2.x will become >= 1.2.0 -// <= 1.2.x will become < 1.3.0 -// > 1.2.x will become >= 1.3.0 -// < 1.2.x will become < 1.2.0 -// != 1.2.x will become < 1.2.0 >= 1.3.0 -// -// * when dealing with minor wildcards: -// >= 1.x will become >= 1.0.0 -// <= 1.x will become < 2.0.0 -// > 1.x will become >= 2.0.0 -// < 1.0 will become < 1.0.0 -// != 1.x will become < 1.0.0 >= 2.0.0 -// -// * when dealing with wildcards without -// version operator: -// 1.2.x will become >= 1.2.0 < 1.3.0 -// 1.x will become >= 1.0.0 < 2.0.0 -func expandWildcardVersion(parts [][]string) ([][]string, error) { - var expandedParts [][]string - for _, p := range parts { - var newParts []string - for _, ap := range p { - if strings.Index(ap, "x") != -1 { - opStr, vStr, err := splitComparatorVersion(ap) - if err != nil { - return nil, err - } - - versionWildcardType := getWildcardType(vStr) - flatVersion := createVersionFromWildcard(vStr) - - var resultOperator string - var shouldIncrementVersion bool - switch opStr { - case ">": - resultOperator = ">=" - shouldIncrementVersion = true - case ">=": - resultOperator = ">=" - case "<": - resultOperator = "<" - case "<=": - resultOperator = "<" - shouldIncrementVersion = true - case "", "=", "==": - newParts = append(newParts, ">="+flatVersion) - resultOperator = "<" - shouldIncrementVersion = true - case "!=", "!": - newParts = append(newParts, "<"+flatVersion) - resultOperator = ">=" - shouldIncrementVersion = true - } - - var resultVersion string - if shouldIncrementVersion { - switch versionWildcardType { - case patchWildcard: - resultVersion, _ = incrementMinorVersion(flatVersion) - case minorWildcard: - resultVersion, _ = incrementMajorVersion(flatVersion) - } - } else { - resultVersion = flatVersion - } - - ap = resultOperator + resultVersion - } - newParts = append(newParts, ap) - } - expandedParts = append(expandedParts, newParts) - } - - return expandedParts, nil -} - -func parseComparator(s string) comparator { - switch s { - case "==": - fallthrough - case "": - fallthrough - case "=": - return compEQ - case ">": - return compGT - case ">=": - return compGE - case "<": - return compLT - case "<=": - return compLE - case "!": - fallthrough - case "!=": - return compNE - } - - return nil -} - -// MustParseRange is like ParseRange but panics if the range cannot be parsed. -func MustParseRange(s string) Range { - r, err := ParseRange(s) - if err != nil { - panic(`semver: ParseRange(` + s + `): ` + err.Error()) - } - return r -} diff --git a/vendor/github.com/blang/semver/semver.go b/vendor/github.com/blang/semver/semver.go deleted file mode 100644 index 8ee0842e6a..0000000000 --- a/vendor/github.com/blang/semver/semver.go +++ /dev/null @@ -1,418 +0,0 @@ -package semver - -import ( - "errors" - "fmt" - "strconv" - "strings" -) - -const ( - numbers string = "0123456789" - alphas = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-" - alphanum = alphas + numbers -) - -// SpecVersion is the latest fully supported spec version of semver -var SpecVersion = Version{ - Major: 2, - Minor: 0, - Patch: 0, -} - -// Version represents a semver compatible version -type Version struct { - Major uint64 - Minor uint64 - Patch uint64 - Pre []PRVersion - Build []string //No Precendence -} - -// Version to string -func (v Version) String() string { - b := make([]byte, 0, 5) - b = strconv.AppendUint(b, v.Major, 10) - b = append(b, '.') - b = strconv.AppendUint(b, v.Minor, 10) - b = append(b, '.') - b = strconv.AppendUint(b, v.Patch, 10) - - if len(v.Pre) > 0 { - b = append(b, '-') - b = append(b, v.Pre[0].String()...) - - for _, pre := range v.Pre[1:] { - b = append(b, '.') - b = append(b, pre.String()...) - } - } - - if len(v.Build) > 0 { - b = append(b, '+') - b = append(b, v.Build[0]...) - - for _, build := range v.Build[1:] { - b = append(b, '.') - b = append(b, build...) - } - } - - return string(b) -} - -// Equals checks if v is equal to o. -func (v Version) Equals(o Version) bool { - return (v.Compare(o) == 0) -} - -// EQ checks if v is equal to o. -func (v Version) EQ(o Version) bool { - return (v.Compare(o) == 0) -} - -// NE checks if v is not equal to o. -func (v Version) NE(o Version) bool { - return (v.Compare(o) != 0) -} - -// GT checks if v is greater than o. -func (v Version) GT(o Version) bool { - return (v.Compare(o) == 1) -} - -// GTE checks if v is greater than or equal to o. -func (v Version) GTE(o Version) bool { - return (v.Compare(o) >= 0) -} - -// GE checks if v is greater than or equal to o. -func (v Version) GE(o Version) bool { - return (v.Compare(o) >= 0) -} - -// LT checks if v is less than o. -func (v Version) LT(o Version) bool { - return (v.Compare(o) == -1) -} - -// LTE checks if v is less than or equal to o. -func (v Version) LTE(o Version) bool { - return (v.Compare(o) <= 0) -} - -// LE checks if v is less than or equal to o. -func (v Version) LE(o Version) bool { - return (v.Compare(o) <= 0) -} - -// Compare compares Versions v to o: -// -1 == v is less than o -// 0 == v is equal to o -// 1 == v is greater than o -func (v Version) Compare(o Version) int { - if v.Major != o.Major { - if v.Major > o.Major { - return 1 - } - return -1 - } - if v.Minor != o.Minor { - if v.Minor > o.Minor { - return 1 - } - return -1 - } - if v.Patch != o.Patch { - if v.Patch > o.Patch { - return 1 - } - return -1 - } - - // Quick comparison if a version has no prerelease versions - if len(v.Pre) == 0 && len(o.Pre) == 0 { - return 0 - } else if len(v.Pre) == 0 && len(o.Pre) > 0 { - return 1 - } else if len(v.Pre) > 0 && len(o.Pre) == 0 { - return -1 - } - - i := 0 - for ; i < len(v.Pre) && i < len(o.Pre); i++ { - if comp := v.Pre[i].Compare(o.Pre[i]); comp == 0 { - continue - } else if comp == 1 { - return 1 - } else { - return -1 - } - } - - // If all pr versions are the equal but one has further prversion, this one greater - if i == len(v.Pre) && i == len(o.Pre) { - return 0 - } else if i == len(v.Pre) && i < len(o.Pre) { - return -1 - } else { - return 1 - } - -} - -// Validate validates v and returns error in case -func (v Version) Validate() error { - // Major, Minor, Patch already validated using uint64 - - for _, pre := range v.Pre { - if !pre.IsNum { //Numeric prerelease versions already uint64 - if len(pre.VersionStr) == 0 { - return fmt.Errorf("Prerelease can not be empty %q", pre.VersionStr) - } - if !containsOnly(pre.VersionStr, alphanum) { - return fmt.Errorf("Invalid character(s) found in prerelease %q", pre.VersionStr) - } - } - } - - for _, build := range v.Build { - if len(build) == 0 { - return fmt.Errorf("Build meta data can not be empty %q", build) - } - if !containsOnly(build, alphanum) { - return fmt.Errorf("Invalid character(s) found in build meta data %q", build) - } - } - - return nil -} - -// New is an alias for Parse and returns a pointer, parses version string and returns a validated Version or error -func New(s string) (vp *Version, err error) { - v, err := Parse(s) - vp = &v - return -} - -// Make is an alias for Parse, parses version string and returns a validated Version or error -func Make(s string) (Version, error) { - return Parse(s) -} - -// ParseTolerant allows for certain version specifications that do not strictly adhere to semver -// specs to be parsed by this library. It does so by normalizing versions before passing them to -// Parse(). It currently trims spaces, removes a "v" prefix, and adds a 0 patch number to versions -// with only major and minor components specified -func ParseTolerant(s string) (Version, error) { - s = strings.TrimSpace(s) - s = strings.TrimPrefix(s, "v") - - // Split into major.minor.(patch+pr+meta) - parts := strings.SplitN(s, ".", 3) - if len(parts) < 3 { - if strings.ContainsAny(parts[len(parts)-1], "+-") { - return Version{}, errors.New("Short version cannot contain PreRelease/Build meta data") - } - for len(parts) < 3 { - parts = append(parts, "0") - } - s = strings.Join(parts, ".") - } - - return Parse(s) -} - -// Parse parses version string and returns a validated Version or error -func Parse(s string) (Version, error) { - if len(s) == 0 { - return Version{}, errors.New("Version string empty") - } - - // Split into major.minor.(patch+pr+meta) - parts := strings.SplitN(s, ".", 3) - if len(parts) != 3 { - return Version{}, errors.New("No Major.Minor.Patch elements found") - } - - // Major - if !containsOnly(parts[0], numbers) { - return Version{}, fmt.Errorf("Invalid character(s) found in major number %q", parts[0]) - } - if hasLeadingZeroes(parts[0]) { - return Version{}, fmt.Errorf("Major number must not contain leading zeroes %q", parts[0]) - } - major, err := strconv.ParseUint(parts[0], 10, 64) - if err != nil { - return Version{}, err - } - - // Minor - if !containsOnly(parts[1], numbers) { - return Version{}, fmt.Errorf("Invalid character(s) found in minor number %q", parts[1]) - } - if hasLeadingZeroes(parts[1]) { - return Version{}, fmt.Errorf("Minor number must not contain leading zeroes %q", parts[1]) - } - minor, err := strconv.ParseUint(parts[1], 10, 64) - if err != nil { - return Version{}, err - } - - v := Version{} - v.Major = major - v.Minor = minor - - var build, prerelease []string - patchStr := parts[2] - - if buildIndex := strings.IndexRune(patchStr, '+'); buildIndex != -1 { - build = strings.Split(patchStr[buildIndex+1:], ".") - patchStr = patchStr[:buildIndex] - } - - if preIndex := strings.IndexRune(patchStr, '-'); preIndex != -1 { - prerelease = strings.Split(patchStr[preIndex+1:], ".") - patchStr = patchStr[:preIndex] - } - - if !containsOnly(patchStr, numbers) { - return Version{}, fmt.Errorf("Invalid character(s) found in patch number %q", patchStr) - } - if hasLeadingZeroes(patchStr) { - return Version{}, fmt.Errorf("Patch number must not contain leading zeroes %q", patchStr) - } - patch, err := strconv.ParseUint(patchStr, 10, 64) - if err != nil { - return Version{}, err - } - - v.Patch = patch - - // Prerelease - for _, prstr := range prerelease { - parsedPR, err := NewPRVersion(prstr) - if err != nil { - return Version{}, err - } - v.Pre = append(v.Pre, parsedPR) - } - - // Build meta data - for _, str := range build { - if len(str) == 0 { - return Version{}, errors.New("Build meta data is empty") - } - if !containsOnly(str, alphanum) { - return Version{}, fmt.Errorf("Invalid character(s) found in build meta data %q", str) - } - v.Build = append(v.Build, str) - } - - return v, nil -} - -// MustParse is like Parse but panics if the version cannot be parsed. -func MustParse(s string) Version { - v, err := Parse(s) - if err != nil { - panic(`semver: Parse(` + s + `): ` + err.Error()) - } - return v -} - -// PRVersion represents a PreRelease Version -type PRVersion struct { - VersionStr string - VersionNum uint64 - IsNum bool -} - -// NewPRVersion creates a new valid prerelease version -func NewPRVersion(s string) (PRVersion, error) { - if len(s) == 0 { - return PRVersion{}, errors.New("Prerelease is empty") - } - v := PRVersion{} - if containsOnly(s, numbers) { - if hasLeadingZeroes(s) { - return PRVersion{}, fmt.Errorf("Numeric PreRelease version must not contain leading zeroes %q", s) - } - num, err := strconv.ParseUint(s, 10, 64) - - // Might never be hit, but just in case - if err != nil { - return PRVersion{}, err - } - v.VersionNum = num - v.IsNum = true - } else if containsOnly(s, alphanum) { - v.VersionStr = s - v.IsNum = false - } else { - return PRVersion{}, fmt.Errorf("Invalid character(s) found in prerelease %q", s) - } - return v, nil -} - -// IsNumeric checks if prerelease-version is numeric -func (v PRVersion) IsNumeric() bool { - return v.IsNum -} - -// Compare compares two PreRelease Versions v and o: -// -1 == v is less than o -// 0 == v is equal to o -// 1 == v is greater than o -func (v PRVersion) Compare(o PRVersion) int { - if v.IsNum && !o.IsNum { - return -1 - } else if !v.IsNum && o.IsNum { - return 1 - } else if v.IsNum && o.IsNum { - if v.VersionNum == o.VersionNum { - return 0 - } else if v.VersionNum > o.VersionNum { - return 1 - } else { - return -1 - } - } else { // both are Alphas - if v.VersionStr == o.VersionStr { - return 0 - } else if v.VersionStr > o.VersionStr { - return 1 - } else { - return -1 - } - } -} - -// PreRelease version to string -func (v PRVersion) String() string { - if v.IsNum { - return strconv.FormatUint(v.VersionNum, 10) - } - return v.VersionStr -} - -func containsOnly(s string, set string) bool { - return strings.IndexFunc(s, func(r rune) bool { - return !strings.ContainsRune(set, r) - }) == -1 -} - -func hasLeadingZeroes(s string) bool { - return len(s) > 1 && s[0] == '0' -} - -// NewBuildVersion creates a new valid build version -func NewBuildVersion(s string) (string, error) { - if len(s) == 0 { - return "", errors.New("Buildversion is empty") - } - if !containsOnly(s, alphanum) { - return "", fmt.Errorf("Invalid character(s) found in build meta data %q", s) - } - return s, nil -} diff --git a/vendor/github.com/blang/semver/sort.go b/vendor/github.com/blang/semver/sort.go deleted file mode 100644 index e18f880826..0000000000 --- a/vendor/github.com/blang/semver/sort.go +++ /dev/null @@ -1,28 +0,0 @@ -package semver - -import ( - "sort" -) - -// Versions represents multiple versions. -type Versions []Version - -// Len returns length of version collection -func (s Versions) Len() int { - return len(s) -} - -// Swap swaps two versions inside the collection by its indices -func (s Versions) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} - -// Less checks if version at index i is less than version at index j -func (s Versions) Less(i, j int) bool { - return s[i].LT(s[j]) -} - -// Sort sorts a slice of versions -func Sort(versions []Version) { - sort.Sort(Versions(versions)) -} diff --git a/vendor/github.com/blang/semver/sql.go b/vendor/github.com/blang/semver/sql.go deleted file mode 100644 index eb4d802666..0000000000 --- a/vendor/github.com/blang/semver/sql.go +++ /dev/null @@ -1,30 +0,0 @@ -package semver - -import ( - "database/sql/driver" - "fmt" -) - -// Scan implements the database/sql.Scanner interface. -func (v *Version) Scan(src interface{}) (err error) { - var str string - switch src := src.(type) { - case string: - str = src - case []byte: - str = string(src) - default: - return fmt.Errorf("Version.Scan: cannot convert %T to string.", src) - } - - if t, err := Parse(str); err == nil { - *v = t - } - - return -} - -// Value implements the database/sql/driver.Valuer interface. -func (v Version) Value() (driver.Value, error) { - return v.String(), nil -} diff --git a/vendor/github.com/cenkalti/backoff/v4/.gitignore b/vendor/github.com/cenkalti/backoff/v4/.gitignore new file mode 100644 index 0000000000..50d95c548b --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/v4/.gitignore @@ -0,0 +1,25 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe + +# IDEs +.idea/ diff --git a/vendor/github.com/cenkalti/backoff/v4/LICENSE b/vendor/github.com/cenkalti/backoff/v4/LICENSE new file mode 100644 index 0000000000..89b8179965 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/v4/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2014 Cenk Altı + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/cenkalti/backoff/v4/README.md b/vendor/github.com/cenkalti/backoff/v4/README.md new file mode 100644 index 0000000000..16abdfc084 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/v4/README.md @@ -0,0 +1,32 @@ +# Exponential Backoff [![GoDoc][godoc image]][godoc] [![Build Status][travis image]][travis] [![Coverage Status][coveralls image]][coveralls] + +This is a Go port of the exponential backoff algorithm from [Google's HTTP Client Library for Java][google-http-java-client]. + +[Exponential backoff][exponential backoff wiki] +is an algorithm that uses feedback to multiplicatively decrease the rate of some process, +in order to gradually find an acceptable rate. +The retries exponentially increase and stop increasing when a certain threshold is met. + +## Usage + +Import path is `github.com/cenkalti/backoff/v4`. Please note the version part at the end. + +Use https://pkg.go.dev/github.com/cenkalti/backoff/v4 to view the documentation. + +## Contributing + +* I would like to keep this library as small as possible. +* Please don't send a PR without opening an issue and discussing it first. +* If proposed change is not a common use case, I will probably not accept it. + +[godoc]: https://pkg.go.dev/github.com/cenkalti/backoff/v4 +[godoc image]: https://godoc.org/github.com/cenkalti/backoff?status.png +[travis]: https://travis-ci.org/cenkalti/backoff +[travis image]: https://travis-ci.org/cenkalti/backoff.png?branch=master +[coveralls]: https://coveralls.io/github/cenkalti/backoff?branch=master +[coveralls image]: https://coveralls.io/repos/github/cenkalti/backoff/badge.svg?branch=master + +[google-http-java-client]: https://github.com/google/google-http-java-client/blob/da1aa993e90285ec18579f1553339b00e19b3ab5/google-http-client/src/main/java/com/google/api/client/util/ExponentialBackOff.java +[exponential backoff wiki]: http://en.wikipedia.org/wiki/Exponential_backoff + +[advanced example]: https://pkg.go.dev/github.com/cenkalti/backoff/v4?tab=doc#pkg-examples diff --git a/vendor/github.com/cenkalti/backoff/v4/backoff.go b/vendor/github.com/cenkalti/backoff/v4/backoff.go new file mode 100644 index 0000000000..3676ee405d --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/v4/backoff.go @@ -0,0 +1,66 @@ +// Package backoff implements backoff algorithms for retrying operations. +// +// Use Retry function for retrying operations that may fail. +// If Retry does not meet your needs, +// copy/paste the function into your project and modify as you wish. +// +// There is also Ticker type similar to time.Ticker. +// You can use it if you need to work with channels. +// +// See Examples section below for usage examples. +package backoff + +import "time" + +// BackOff is a backoff policy for retrying an operation. +type BackOff interface { + // NextBackOff returns the duration to wait before retrying the operation, + // or backoff. Stop to indicate that no more retries should be made. + // + // Example usage: + // + // duration := backoff.NextBackOff(); + // if (duration == backoff.Stop) { + // // Do not retry operation. + // } else { + // // Sleep for duration and retry operation. + // } + // + NextBackOff() time.Duration + + // Reset to initial state. + Reset() +} + +// Stop indicates that no more retries should be made for use in NextBackOff(). +const Stop time.Duration = -1 + +// ZeroBackOff is a fixed backoff policy whose backoff time is always zero, +// meaning that the operation is retried immediately without waiting, indefinitely. +type ZeroBackOff struct{} + +func (b *ZeroBackOff) Reset() {} + +func (b *ZeroBackOff) NextBackOff() time.Duration { return 0 } + +// StopBackOff is a fixed backoff policy that always returns backoff.Stop for +// NextBackOff(), meaning that the operation should never be retried. +type StopBackOff struct{} + +func (b *StopBackOff) Reset() {} + +func (b *StopBackOff) NextBackOff() time.Duration { return Stop } + +// ConstantBackOff is a backoff policy that always returns the same backoff delay. +// This is in contrast to an exponential backoff policy, +// which returns a delay that grows longer as you call NextBackOff() over and over again. +type ConstantBackOff struct { + Interval time.Duration +} + +func (b *ConstantBackOff) Reset() {} +func (b *ConstantBackOff) NextBackOff() time.Duration { return b.Interval } + +func NewConstantBackOff(d time.Duration) *ConstantBackOff { + return &ConstantBackOff{Interval: d} +} diff --git a/vendor/github.com/cenkalti/backoff/v4/context.go b/vendor/github.com/cenkalti/backoff/v4/context.go new file mode 100644 index 0000000000..48482330eb --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/v4/context.go @@ -0,0 +1,62 @@ +package backoff + +import ( + "context" + "time" +) + +// BackOffContext is a backoff policy that stops retrying after the context +// is canceled. +type BackOffContext interface { // nolint: golint + BackOff + Context() context.Context +} + +type backOffContext struct { + BackOff + ctx context.Context +} + +// WithContext returns a BackOffContext with context ctx +// +// ctx must not be nil +func WithContext(b BackOff, ctx context.Context) BackOffContext { // nolint: golint + if ctx == nil { + panic("nil context") + } + + if b, ok := b.(*backOffContext); ok { + return &backOffContext{ + BackOff: b.BackOff, + ctx: ctx, + } + } + + return &backOffContext{ + BackOff: b, + ctx: ctx, + } +} + +func getContext(b BackOff) context.Context { + if cb, ok := b.(BackOffContext); ok { + return cb.Context() + } + if tb, ok := b.(*backOffTries); ok { + return getContext(tb.delegate) + } + return context.Background() +} + +func (b *backOffContext) Context() context.Context { + return b.ctx +} + +func (b *backOffContext) NextBackOff() time.Duration { + select { + case <-b.ctx.Done(): + return Stop + default: + return b.BackOff.NextBackOff() + } +} diff --git a/vendor/github.com/cenkalti/backoff/v4/exponential.go b/vendor/github.com/cenkalti/backoff/v4/exponential.go new file mode 100644 index 0000000000..2c56c1e718 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/v4/exponential.go @@ -0,0 +1,161 @@ +package backoff + +import ( + "math/rand" + "time" +) + +/* +ExponentialBackOff is a backoff implementation that increases the backoff +period for each retry attempt using a randomization function that grows exponentially. + +NextBackOff() is calculated using the following formula: + + randomized interval = + RetryInterval * (random value in range [1 - RandomizationFactor, 1 + RandomizationFactor]) + +In other words NextBackOff() will range between the randomization factor +percentage below and above the retry interval. + +For example, given the following parameters: + + RetryInterval = 2 + RandomizationFactor = 0.5 + Multiplier = 2 + +the actual backoff period used in the next retry attempt will range between 1 and 3 seconds, +multiplied by the exponential, that is, between 2 and 6 seconds. + +Note: MaxInterval caps the RetryInterval and not the randomized interval. + +If the time elapsed since an ExponentialBackOff instance is created goes past the +MaxElapsedTime, then the method NextBackOff() starts returning backoff.Stop. + +The elapsed time can be reset by calling Reset(). + +Example: Given the following default arguments, for 10 tries the sequence will be, +and assuming we go over the MaxElapsedTime on the 10th try: + + Request # RetryInterval (seconds) Randomized Interval (seconds) + + 1 0.5 [0.25, 0.75] + 2 0.75 [0.375, 1.125] + 3 1.125 [0.562, 1.687] + 4 1.687 [0.8435, 2.53] + 5 2.53 [1.265, 3.795] + 6 3.795 [1.897, 5.692] + 7 5.692 [2.846, 8.538] + 8 8.538 [4.269, 12.807] + 9 12.807 [6.403, 19.210] + 10 19.210 backoff.Stop + +Note: Implementation is not thread-safe. +*/ +type ExponentialBackOff struct { + InitialInterval time.Duration + RandomizationFactor float64 + Multiplier float64 + MaxInterval time.Duration + // After MaxElapsedTime the ExponentialBackOff returns Stop. + // It never stops if MaxElapsedTime == 0. + MaxElapsedTime time.Duration + Stop time.Duration + Clock Clock + + currentInterval time.Duration + startTime time.Time +} + +// Clock is an interface that returns current time for BackOff. +type Clock interface { + Now() time.Time +} + +// Default values for ExponentialBackOff. +const ( + DefaultInitialInterval = 500 * time.Millisecond + DefaultRandomizationFactor = 0.5 + DefaultMultiplier = 1.5 + DefaultMaxInterval = 60 * time.Second + DefaultMaxElapsedTime = 15 * time.Minute +) + +// NewExponentialBackOff creates an instance of ExponentialBackOff using default values. +func NewExponentialBackOff() *ExponentialBackOff { + b := &ExponentialBackOff{ + InitialInterval: DefaultInitialInterval, + RandomizationFactor: DefaultRandomizationFactor, + Multiplier: DefaultMultiplier, + MaxInterval: DefaultMaxInterval, + MaxElapsedTime: DefaultMaxElapsedTime, + Stop: Stop, + Clock: SystemClock, + } + b.Reset() + return b +} + +type systemClock struct{} + +func (t systemClock) Now() time.Time { + return time.Now() +} + +// SystemClock implements Clock interface that uses time.Now(). +var SystemClock = systemClock{} + +// Reset the interval back to the initial retry interval and restarts the timer. +// Reset must be called before using b. +func (b *ExponentialBackOff) Reset() { + b.currentInterval = b.InitialInterval + b.startTime = b.Clock.Now() +} + +// NextBackOff calculates the next backoff interval using the formula: +// Randomized interval = RetryInterval * (1 ± RandomizationFactor) +func (b *ExponentialBackOff) NextBackOff() time.Duration { + // Make sure we have not gone over the maximum elapsed time. + elapsed := b.GetElapsedTime() + next := getRandomValueFromInterval(b.RandomizationFactor, rand.Float64(), b.currentInterval) + b.incrementCurrentInterval() + if b.MaxElapsedTime != 0 && elapsed+next > b.MaxElapsedTime { + return b.Stop + } + return next +} + +// GetElapsedTime returns the elapsed time since an ExponentialBackOff instance +// is created and is reset when Reset() is called. +// +// The elapsed time is computed using time.Now().UnixNano(). It is +// safe to call even while the backoff policy is used by a running +// ticker. +func (b *ExponentialBackOff) GetElapsedTime() time.Duration { + return b.Clock.Now().Sub(b.startTime) +} + +// Increments the current interval by multiplying it with the multiplier. +func (b *ExponentialBackOff) incrementCurrentInterval() { + // Check for overflow, if overflow is detected set the current interval to the max interval. + if float64(b.currentInterval) >= float64(b.MaxInterval)/b.Multiplier { + b.currentInterval = b.MaxInterval + } else { + b.currentInterval = time.Duration(float64(b.currentInterval) * b.Multiplier) + } +} + +// Returns a random value from the following interval: +// [currentInterval - randomizationFactor * currentInterval, currentInterval + randomizationFactor * currentInterval]. +func getRandomValueFromInterval(randomizationFactor, random float64, currentInterval time.Duration) time.Duration { + if randomizationFactor == 0 { + return currentInterval // make sure no randomness is used when randomizationFactor is 0. + } + var delta = randomizationFactor * float64(currentInterval) + var minInterval = float64(currentInterval) - delta + var maxInterval = float64(currentInterval) + delta + + // Get a random value from the range [minInterval, maxInterval]. + // The formula used below has a +1 because if the minInterval is 1 and the maxInterval is 3 then + // we want a 33% chance for selecting either 1, 2 or 3. + return time.Duration(minInterval + (random * (maxInterval - minInterval + 1))) +} diff --git a/vendor/github.com/cenkalti/backoff/v4/retry.go b/vendor/github.com/cenkalti/backoff/v4/retry.go new file mode 100644 index 0000000000..b9c0c51cd7 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/v4/retry.go @@ -0,0 +1,146 @@ +package backoff + +import ( + "errors" + "time" +) + +// An OperationWithData is executing by RetryWithData() or RetryNotifyWithData(). +// The operation will be retried using a backoff policy if it returns an error. +type OperationWithData[T any] func() (T, error) + +// An Operation is executing by Retry() or RetryNotify(). +// The operation will be retried using a backoff policy if it returns an error. +type Operation func() error + +func (o Operation) withEmptyData() OperationWithData[struct{}] { + return func() (struct{}, error) { + return struct{}{}, o() + } +} + +// Notify is a notify-on-error function. It receives an operation error and +// backoff delay if the operation failed (with an error). +// +// NOTE that if the backoff policy stated to stop retrying, +// the notify function isn't called. +type Notify func(error, time.Duration) + +// Retry the operation o until it does not return error or BackOff stops. +// o is guaranteed to be run at least once. +// +// If o returns a *PermanentError, the operation is not retried, and the +// wrapped error is returned. +// +// Retry sleeps the goroutine for the duration returned by BackOff after a +// failed operation returns. +func Retry(o Operation, b BackOff) error { + return RetryNotify(o, b, nil) +} + +// RetryWithData is like Retry but returns data in the response too. +func RetryWithData[T any](o OperationWithData[T], b BackOff) (T, error) { + return RetryNotifyWithData(o, b, nil) +} + +// RetryNotify calls notify function with the error and wait duration +// for each failed attempt before sleep. +func RetryNotify(operation Operation, b BackOff, notify Notify) error { + return RetryNotifyWithTimer(operation, b, notify, nil) +} + +// RetryNotifyWithData is like RetryNotify but returns data in the response too. +func RetryNotifyWithData[T any](operation OperationWithData[T], b BackOff, notify Notify) (T, error) { + return doRetryNotify(operation, b, notify, nil) +} + +// RetryNotifyWithTimer calls notify function with the error and wait duration using the given Timer +// for each failed attempt before sleep. +// A default timer that uses system timer is used when nil is passed. +func RetryNotifyWithTimer(operation Operation, b BackOff, notify Notify, t Timer) error { + _, err := doRetryNotify(operation.withEmptyData(), b, notify, t) + return err +} + +// RetryNotifyWithTimerAndData is like RetryNotifyWithTimer but returns data in the response too. +func RetryNotifyWithTimerAndData[T any](operation OperationWithData[T], b BackOff, notify Notify, t Timer) (T, error) { + return doRetryNotify(operation, b, notify, t) +} + +func doRetryNotify[T any](operation OperationWithData[T], b BackOff, notify Notify, t Timer) (T, error) { + var ( + err error + next time.Duration + res T + ) + if t == nil { + t = &defaultTimer{} + } + + defer func() { + t.Stop() + }() + + ctx := getContext(b) + + b.Reset() + for { + res, err = operation() + if err == nil { + return res, nil + } + + var permanent *PermanentError + if errors.As(err, &permanent) { + return res, permanent.Err + } + + if next = b.NextBackOff(); next == Stop { + if cerr := ctx.Err(); cerr != nil { + return res, cerr + } + + return res, err + } + + if notify != nil { + notify(err, next) + } + + t.Start(next) + + select { + case <-ctx.Done(): + return res, ctx.Err() + case <-t.C(): + } + } +} + +// PermanentError signals that the operation should not be retried. +type PermanentError struct { + Err error +} + +func (e *PermanentError) Error() string { + return e.Err.Error() +} + +func (e *PermanentError) Unwrap() error { + return e.Err +} + +func (e *PermanentError) Is(target error) bool { + _, ok := target.(*PermanentError) + return ok +} + +// Permanent wraps the given err in a *PermanentError. +func Permanent(err error) error { + if err == nil { + return nil + } + return &PermanentError{ + Err: err, + } +} diff --git a/vendor/github.com/cenkalti/backoff/v4/ticker.go b/vendor/github.com/cenkalti/backoff/v4/ticker.go new file mode 100644 index 0000000000..df9d68bce5 --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/v4/ticker.go @@ -0,0 +1,97 @@ +package backoff + +import ( + "context" + "sync" + "time" +) + +// Ticker holds a channel that delivers `ticks' of a clock at times reported by a BackOff. +// +// Ticks will continue to arrive when the previous operation is still running, +// so operations that take a while to fail could run in quick succession. +type Ticker struct { + C <-chan time.Time + c chan time.Time + b BackOff + ctx context.Context + timer Timer + stop chan struct{} + stopOnce sync.Once +} + +// NewTicker returns a new Ticker containing a channel that will send +// the time at times specified by the BackOff argument. Ticker is +// guaranteed to tick at least once. The channel is closed when Stop +// method is called or BackOff stops. It is not safe to manipulate the +// provided backoff policy (notably calling NextBackOff or Reset) +// while the ticker is running. +func NewTicker(b BackOff) *Ticker { + return NewTickerWithTimer(b, &defaultTimer{}) +} + +// NewTickerWithTimer returns a new Ticker with a custom timer. +// A default timer that uses system timer is used when nil is passed. +func NewTickerWithTimer(b BackOff, timer Timer) *Ticker { + if timer == nil { + timer = &defaultTimer{} + } + c := make(chan time.Time) + t := &Ticker{ + C: c, + c: c, + b: b, + ctx: getContext(b), + timer: timer, + stop: make(chan struct{}), + } + t.b.Reset() + go t.run() + return t +} + +// Stop turns off a ticker. After Stop, no more ticks will be sent. +func (t *Ticker) Stop() { + t.stopOnce.Do(func() { close(t.stop) }) +} + +func (t *Ticker) run() { + c := t.c + defer close(c) + + // Ticker is guaranteed to tick at least once. + afterC := t.send(time.Now()) + + for { + if afterC == nil { + return + } + + select { + case tick := <-afterC: + afterC = t.send(tick) + case <-t.stop: + t.c = nil // Prevent future ticks from being sent to the channel. + return + case <-t.ctx.Done(): + return + } + } +} + +func (t *Ticker) send(tick time.Time) <-chan time.Time { + select { + case t.c <- tick: + case <-t.stop: + return nil + } + + next := t.b.NextBackOff() + if next == Stop { + t.Stop() + return nil + } + + t.timer.Start(next) + return t.timer.C() +} diff --git a/vendor/github.com/cenkalti/backoff/v4/timer.go b/vendor/github.com/cenkalti/backoff/v4/timer.go new file mode 100644 index 0000000000..8120d0213c --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/v4/timer.go @@ -0,0 +1,35 @@ +package backoff + +import "time" + +type Timer interface { + Start(duration time.Duration) + Stop() + C() <-chan time.Time +} + +// defaultTimer implements Timer interface using time.Timer +type defaultTimer struct { + timer *time.Timer +} + +// C returns the timers channel which receives the current time when the timer fires. +func (t *defaultTimer) C() <-chan time.Time { + return t.timer.C +} + +// Start starts the timer to fire after the given duration +func (t *defaultTimer) Start(duration time.Duration) { + if t.timer == nil { + t.timer = time.NewTimer(duration) + } else { + t.timer.Reset(duration) + } +} + +// Stop is called when the timer is not used anymore and resources may be freed. +func (t *defaultTimer) Stop() { + if t.timer != nil { + t.timer.Stop() + } +} diff --git a/vendor/github.com/cenkalti/backoff/v4/tries.go b/vendor/github.com/cenkalti/backoff/v4/tries.go new file mode 100644 index 0000000000..28d58ca37c --- /dev/null +++ b/vendor/github.com/cenkalti/backoff/v4/tries.go @@ -0,0 +1,38 @@ +package backoff + +import "time" + +/* +WithMaxRetries creates a wrapper around another BackOff, which will +return Stop if NextBackOff() has been called too many times since +the last time Reset() was called + +Note: Implementation is not thread-safe. +*/ +func WithMaxRetries(b BackOff, max uint64) BackOff { + return &backOffTries{delegate: b, maxTries: max} +} + +type backOffTries struct { + delegate BackOff + maxTries uint64 + numTries uint64 +} + +func (b *backOffTries) NextBackOff() time.Duration { + if b.maxTries == 0 { + return Stop + } + if b.maxTries > 0 { + if b.maxTries <= b.numTries { + return Stop + } + b.numTries++ + } + return b.delegate.NextBackOff() +} + +func (b *backOffTries) Reset() { + b.numTries = 0 + b.delegate.Reset() +} diff --git a/vendor/github.com/cespare/xxhash/v2/README.md b/vendor/github.com/cespare/xxhash/v2/README.md index 792b4a60b3..8bf0e5b781 100644 --- a/vendor/github.com/cespare/xxhash/v2/README.md +++ b/vendor/github.com/cespare/xxhash/v2/README.md @@ -3,8 +3,7 @@ [![Go Reference](https://pkg.go.dev/badge/github.com/cespare/xxhash/v2.svg)](https://pkg.go.dev/github.com/cespare/xxhash/v2) [![Test](https://github.com/cespare/xxhash/actions/workflows/test.yml/badge.svg)](https://github.com/cespare/xxhash/actions/workflows/test.yml) -xxhash is a Go implementation of the 64-bit -[xxHash](http://cyan4973.github.io/xxHash/) algorithm, XXH64. This is a +xxhash is a Go implementation of the 64-bit [xxHash] algorithm, XXH64. This is a high-quality hashing algorithm that is much faster than anything in the Go standard library. @@ -25,8 +24,11 @@ func (*Digest) WriteString(string) (int, error) func (*Digest) Sum64() uint64 ``` -This implementation provides a fast pure-Go implementation and an even faster -assembly implementation for amd64. +The package is written with optimized pure Go and also contains even faster +assembly implementations for amd64 and arm64. If desired, the `purego` build tag +opts into using the Go code even on those architectures. + +[xxHash]: http://cyan4973.github.io/xxHash/ ## Compatibility @@ -45,19 +47,20 @@ I recommend using the latest release of Go. Here are some quick benchmarks comparing the pure-Go and assembly implementations of Sum64. -| input size | purego | asm | -| --- | --- | --- | -| 5 B | 979.66 MB/s | 1291.17 MB/s | -| 100 B | 7475.26 MB/s | 7973.40 MB/s | -| 4 KB | 17573.46 MB/s | 17602.65 MB/s | -| 10 MB | 17131.46 MB/s | 17142.16 MB/s | +| input size | purego | asm | +| ---------- | --------- | --------- | +| 4 B | 1.3 GB/s | 1.2 GB/s | +| 16 B | 2.9 GB/s | 3.5 GB/s | +| 100 B | 6.9 GB/s | 8.1 GB/s | +| 4 KB | 11.7 GB/s | 16.7 GB/s | +| 10 MB | 12.0 GB/s | 17.3 GB/s | -These numbers were generated on Ubuntu 18.04 with an Intel i7-8700K CPU using -the following commands under Go 1.11.2: +These numbers were generated on Ubuntu 20.04 with an Intel Xeon Platinum 8252C +CPU using the following commands under Go 1.19.2: ``` -$ go test -tags purego -benchtime 10s -bench '/xxhash,direct,bytes' -$ go test -benchtime 10s -bench '/xxhash,direct,bytes' +benchstat <(go test -tags purego -benchtime 500ms -count 15 -bench 'Sum64$') +benchstat <(go test -benchtime 500ms -count 15 -bench 'Sum64$') ``` ## Projects using this package diff --git a/vendor/github.com/cespare/xxhash/v2/testall.sh b/vendor/github.com/cespare/xxhash/v2/testall.sh new file mode 100644 index 0000000000..94b9c44398 --- /dev/null +++ b/vendor/github.com/cespare/xxhash/v2/testall.sh @@ -0,0 +1,10 @@ +#!/bin/bash +set -eu -o pipefail + +# Small convenience script for running the tests with various combinations of +# arch/tags. This assumes we're running on amd64 and have qemu available. + +go test ./... +go test -tags purego ./... +GOARCH=arm64 go test +GOARCH=arm64 go test -tags purego diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash.go b/vendor/github.com/cespare/xxhash/v2/xxhash.go index 15c835d541..a9e0d45c9d 100644 --- a/vendor/github.com/cespare/xxhash/v2/xxhash.go +++ b/vendor/github.com/cespare/xxhash/v2/xxhash.go @@ -16,19 +16,11 @@ const ( prime5 uint64 = 2870177450012600261 ) -// NOTE(caleb): I'm using both consts and vars of the primes. Using consts where -// possible in the Go code is worth a small (but measurable) performance boost -// by avoiding some MOVQs. Vars are needed for the asm and also are useful for -// convenience in the Go code in a few places where we need to intentionally -// avoid constant arithmetic (e.g., v1 := prime1 + prime2 fails because the -// result overflows a uint64). -var ( - prime1v = prime1 - prime2v = prime2 - prime3v = prime3 - prime4v = prime4 - prime5v = prime5 -) +// Store the primes in an array as well. +// +// The consts are used when possible in Go code to avoid MOVs but we need a +// contiguous array of the assembly code. +var primes = [...]uint64{prime1, prime2, prime3, prime4, prime5} // Digest implements hash.Hash64. type Digest struct { @@ -50,10 +42,10 @@ func New() *Digest { // Reset clears the Digest's state so that it can be reused. func (d *Digest) Reset() { - d.v1 = prime1v + prime2 + d.v1 = primes[0] + prime2 d.v2 = prime2 d.v3 = 0 - d.v4 = -prime1v + d.v4 = -primes[0] d.total = 0 d.n = 0 } @@ -69,21 +61,23 @@ func (d *Digest) Write(b []byte) (n int, err error) { n = len(b) d.total += uint64(n) + memleft := d.mem[d.n&(len(d.mem)-1):] + if d.n+n < 32 { // This new data doesn't even fill the current block. - copy(d.mem[d.n:], b) + copy(memleft, b) d.n += n return } if d.n > 0 { // Finish off the partial block. - copy(d.mem[d.n:], b) + c := copy(memleft, b) d.v1 = round(d.v1, u64(d.mem[0:8])) d.v2 = round(d.v2, u64(d.mem[8:16])) d.v3 = round(d.v3, u64(d.mem[16:24])) d.v4 = round(d.v4, u64(d.mem[24:32])) - b = b[32-d.n:] + b = b[c:] d.n = 0 } @@ -133,21 +127,20 @@ func (d *Digest) Sum64() uint64 { h += d.total - i, end := 0, d.n - for ; i+8 <= end; i += 8 { - k1 := round(0, u64(d.mem[i:i+8])) + b := d.mem[:d.n&(len(d.mem)-1)] + for ; len(b) >= 8; b = b[8:] { + k1 := round(0, u64(b[:8])) h ^= k1 h = rol27(h)*prime1 + prime4 } - if i+4 <= end { - h ^= uint64(u32(d.mem[i:i+4])) * prime1 + if len(b) >= 4 { + h ^= uint64(u32(b[:4])) * prime1 h = rol23(h)*prime2 + prime3 - i += 4 + b = b[4:] } - for i < end { - h ^= uint64(d.mem[i]) * prime5 + for ; len(b) > 0; b = b[1:] { + h ^= uint64(b[0]) * prime5 h = rol11(h) * prime1 - i++ } h ^= h >> 33 diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_amd64.go b/vendor/github.com/cespare/xxhash/v2/xxhash_amd64.go deleted file mode 100644 index ad14b807f4..0000000000 --- a/vendor/github.com/cespare/xxhash/v2/xxhash_amd64.go +++ /dev/null @@ -1,13 +0,0 @@ -// +build !appengine -// +build gc -// +build !purego - -package xxhash - -// Sum64 computes the 64-bit xxHash digest of b. -// -//go:noescape -func Sum64(b []byte) uint64 - -//go:noescape -func writeBlocks(d *Digest, b []byte) int diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_amd64.s b/vendor/github.com/cespare/xxhash/v2/xxhash_amd64.s index be8db5bf79..3e8b132579 100644 --- a/vendor/github.com/cespare/xxhash/v2/xxhash_amd64.s +++ b/vendor/github.com/cespare/xxhash/v2/xxhash_amd64.s @@ -1,215 +1,209 @@ +//go:build !appengine && gc && !purego // +build !appengine // +build gc // +build !purego #include "textflag.h" -// Register allocation: -// AX h -// SI pointer to advance through b -// DX n -// BX loop end -// R8 v1, k1 -// R9 v2 -// R10 v3 -// R11 v4 -// R12 tmp -// R13 prime1v -// R14 prime2v -// DI prime4v - -// round reads from and advances the buffer pointer in SI. -// It assumes that R13 has prime1v and R14 has prime2v. -#define round(r) \ - MOVQ (SI), R12 \ - ADDQ $8, SI \ - IMULQ R14, R12 \ - ADDQ R12, r \ - ROLQ $31, r \ - IMULQ R13, r - -// mergeRound applies a merge round on the two registers acc and val. -// It assumes that R13 has prime1v, R14 has prime2v, and DI has prime4v. -#define mergeRound(acc, val) \ - IMULQ R14, val \ - ROLQ $31, val \ - IMULQ R13, val \ - XORQ val, acc \ - IMULQ R13, acc \ - ADDQ DI, acc +// Registers: +#define h AX +#define d AX +#define p SI // pointer to advance through b +#define n DX +#define end BX // loop end +#define v1 R8 +#define v2 R9 +#define v3 R10 +#define v4 R11 +#define x R12 +#define prime1 R13 +#define prime2 R14 +#define prime4 DI + +#define round(acc, x) \ + IMULQ prime2, x \ + ADDQ x, acc \ + ROLQ $31, acc \ + IMULQ prime1, acc + +// round0 performs the operation x = round(0, x). +#define round0(x) \ + IMULQ prime2, x \ + ROLQ $31, x \ + IMULQ prime1, x + +// mergeRound applies a merge round on the two registers acc and x. +// It assumes that prime1, prime2, and prime4 have been loaded. +#define mergeRound(acc, x) \ + round0(x) \ + XORQ x, acc \ + IMULQ prime1, acc \ + ADDQ prime4, acc + +// blockLoop processes as many 32-byte blocks as possible, +// updating v1, v2, v3, and v4. It assumes that there is at least one block +// to process. +#define blockLoop() \ +loop: \ + MOVQ +0(p), x \ + round(v1, x) \ + MOVQ +8(p), x \ + round(v2, x) \ + MOVQ +16(p), x \ + round(v3, x) \ + MOVQ +24(p), x \ + round(v4, x) \ + ADDQ $32, p \ + CMPQ p, end \ + JLE loop // func Sum64(b []byte) uint64 -TEXT ·Sum64(SB), NOSPLIT, $0-32 +TEXT ·Sum64(SB), NOSPLIT|NOFRAME, $0-32 // Load fixed primes. - MOVQ ·prime1v(SB), R13 - MOVQ ·prime2v(SB), R14 - MOVQ ·prime4v(SB), DI + MOVQ ·primes+0(SB), prime1 + MOVQ ·primes+8(SB), prime2 + MOVQ ·primes+24(SB), prime4 // Load slice. - MOVQ b_base+0(FP), SI - MOVQ b_len+8(FP), DX - LEAQ (SI)(DX*1), BX + MOVQ b_base+0(FP), p + MOVQ b_len+8(FP), n + LEAQ (p)(n*1), end // The first loop limit will be len(b)-32. - SUBQ $32, BX + SUBQ $32, end // Check whether we have at least one block. - CMPQ DX, $32 + CMPQ n, $32 JLT noBlocks // Set up initial state (v1, v2, v3, v4). - MOVQ R13, R8 - ADDQ R14, R8 - MOVQ R14, R9 - XORQ R10, R10 - XORQ R11, R11 - SUBQ R13, R11 - - // Loop until SI > BX. -blockLoop: - round(R8) - round(R9) - round(R10) - round(R11) - - CMPQ SI, BX - JLE blockLoop - - MOVQ R8, AX - ROLQ $1, AX - MOVQ R9, R12 - ROLQ $7, R12 - ADDQ R12, AX - MOVQ R10, R12 - ROLQ $12, R12 - ADDQ R12, AX - MOVQ R11, R12 - ROLQ $18, R12 - ADDQ R12, AX - - mergeRound(AX, R8) - mergeRound(AX, R9) - mergeRound(AX, R10) - mergeRound(AX, R11) + MOVQ prime1, v1 + ADDQ prime2, v1 + MOVQ prime2, v2 + XORQ v3, v3 + XORQ v4, v4 + SUBQ prime1, v4 + + blockLoop() + + MOVQ v1, h + ROLQ $1, h + MOVQ v2, x + ROLQ $7, x + ADDQ x, h + MOVQ v3, x + ROLQ $12, x + ADDQ x, h + MOVQ v4, x + ROLQ $18, x + ADDQ x, h + + mergeRound(h, v1) + mergeRound(h, v2) + mergeRound(h, v3) + mergeRound(h, v4) JMP afterBlocks noBlocks: - MOVQ ·prime5v(SB), AX + MOVQ ·primes+32(SB), h afterBlocks: - ADDQ DX, AX - - // Right now BX has len(b)-32, and we want to loop until SI > len(b)-8. - ADDQ $24, BX - - CMPQ SI, BX - JG fourByte - -wordLoop: - // Calculate k1. - MOVQ (SI), R8 - ADDQ $8, SI - IMULQ R14, R8 - ROLQ $31, R8 - IMULQ R13, R8 - - XORQ R8, AX - ROLQ $27, AX - IMULQ R13, AX - ADDQ DI, AX - - CMPQ SI, BX - JLE wordLoop - -fourByte: - ADDQ $4, BX - CMPQ SI, BX - JG singles - - MOVL (SI), R8 - ADDQ $4, SI - IMULQ R13, R8 - XORQ R8, AX - - ROLQ $23, AX - IMULQ R14, AX - ADDQ ·prime3v(SB), AX - -singles: - ADDQ $4, BX - CMPQ SI, BX + ADDQ n, h + + ADDQ $24, end + CMPQ p, end + JG try4 + +loop8: + MOVQ (p), x + ADDQ $8, p + round0(x) + XORQ x, h + ROLQ $27, h + IMULQ prime1, h + ADDQ prime4, h + + CMPQ p, end + JLE loop8 + +try4: + ADDQ $4, end + CMPQ p, end + JG try1 + + MOVL (p), x + ADDQ $4, p + IMULQ prime1, x + XORQ x, h + + ROLQ $23, h + IMULQ prime2, h + ADDQ ·primes+16(SB), h + +try1: + ADDQ $4, end + CMPQ p, end JGE finalize -singlesLoop: - MOVBQZX (SI), R12 - ADDQ $1, SI - IMULQ ·prime5v(SB), R12 - XORQ R12, AX +loop1: + MOVBQZX (p), x + ADDQ $1, p + IMULQ ·primes+32(SB), x + XORQ x, h + ROLQ $11, h + IMULQ prime1, h - ROLQ $11, AX - IMULQ R13, AX - - CMPQ SI, BX - JL singlesLoop + CMPQ p, end + JL loop1 finalize: - MOVQ AX, R12 - SHRQ $33, R12 - XORQ R12, AX - IMULQ R14, AX - MOVQ AX, R12 - SHRQ $29, R12 - XORQ R12, AX - IMULQ ·prime3v(SB), AX - MOVQ AX, R12 - SHRQ $32, R12 - XORQ R12, AX - - MOVQ AX, ret+24(FP) + MOVQ h, x + SHRQ $33, x + XORQ x, h + IMULQ prime2, h + MOVQ h, x + SHRQ $29, x + XORQ x, h + IMULQ ·primes+16(SB), h + MOVQ h, x + SHRQ $32, x + XORQ x, h + + MOVQ h, ret+24(FP) RET -// writeBlocks uses the same registers as above except that it uses AX to store -// the d pointer. - // func writeBlocks(d *Digest, b []byte) int -TEXT ·writeBlocks(SB), NOSPLIT, $0-40 +TEXT ·writeBlocks(SB), NOSPLIT|NOFRAME, $0-40 // Load fixed primes needed for round. - MOVQ ·prime1v(SB), R13 - MOVQ ·prime2v(SB), R14 + MOVQ ·primes+0(SB), prime1 + MOVQ ·primes+8(SB), prime2 // Load slice. - MOVQ b_base+8(FP), SI - MOVQ b_len+16(FP), DX - LEAQ (SI)(DX*1), BX - SUBQ $32, BX + MOVQ b_base+8(FP), p + MOVQ b_len+16(FP), n + LEAQ (p)(n*1), end + SUBQ $32, end // Load vN from d. - MOVQ d+0(FP), AX - MOVQ 0(AX), R8 // v1 - MOVQ 8(AX), R9 // v2 - MOVQ 16(AX), R10 // v3 - MOVQ 24(AX), R11 // v4 + MOVQ s+0(FP), d + MOVQ 0(d), v1 + MOVQ 8(d), v2 + MOVQ 16(d), v3 + MOVQ 24(d), v4 // We don't need to check the loop condition here; this function is // always called with at least one block of data to process. -blockLoop: - round(R8) - round(R9) - round(R10) - round(R11) - - CMPQ SI, BX - JLE blockLoop + blockLoop() // Copy vN back to d. - MOVQ R8, 0(AX) - MOVQ R9, 8(AX) - MOVQ R10, 16(AX) - MOVQ R11, 24(AX) - - // The number of bytes written is SI minus the old base pointer. - SUBQ b_base+8(FP), SI - MOVQ SI, ret+32(FP) + MOVQ v1, 0(d) + MOVQ v2, 8(d) + MOVQ v3, 16(d) + MOVQ v4, 24(d) + + // The number of bytes written is p minus the old base pointer. + SUBQ b_base+8(FP), p + MOVQ p, ret+32(FP) RET diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_arm64.s b/vendor/github.com/cespare/xxhash/v2/xxhash_arm64.s new file mode 100644 index 0000000000..7e3145a221 --- /dev/null +++ b/vendor/github.com/cespare/xxhash/v2/xxhash_arm64.s @@ -0,0 +1,183 @@ +//go:build !appengine && gc && !purego +// +build !appengine +// +build gc +// +build !purego + +#include "textflag.h" + +// Registers: +#define digest R1 +#define h R2 // return value +#define p R3 // input pointer +#define n R4 // input length +#define nblocks R5 // n / 32 +#define prime1 R7 +#define prime2 R8 +#define prime3 R9 +#define prime4 R10 +#define prime5 R11 +#define v1 R12 +#define v2 R13 +#define v3 R14 +#define v4 R15 +#define x1 R20 +#define x2 R21 +#define x3 R22 +#define x4 R23 + +#define round(acc, x) \ + MADD prime2, acc, x, acc \ + ROR $64-31, acc \ + MUL prime1, acc + +// round0 performs the operation x = round(0, x). +#define round0(x) \ + MUL prime2, x \ + ROR $64-31, x \ + MUL prime1, x + +#define mergeRound(acc, x) \ + round0(x) \ + EOR x, acc \ + MADD acc, prime4, prime1, acc + +// blockLoop processes as many 32-byte blocks as possible, +// updating v1, v2, v3, and v4. It assumes that n >= 32. +#define blockLoop() \ + LSR $5, n, nblocks \ + PCALIGN $16 \ + loop: \ + LDP.P 16(p), (x1, x2) \ + LDP.P 16(p), (x3, x4) \ + round(v1, x1) \ + round(v2, x2) \ + round(v3, x3) \ + round(v4, x4) \ + SUB $1, nblocks \ + CBNZ nblocks, loop + +// func Sum64(b []byte) uint64 +TEXT ·Sum64(SB), NOSPLIT|NOFRAME, $0-32 + LDP b_base+0(FP), (p, n) + + LDP ·primes+0(SB), (prime1, prime2) + LDP ·primes+16(SB), (prime3, prime4) + MOVD ·primes+32(SB), prime5 + + CMP $32, n + CSEL LT, prime5, ZR, h // if n < 32 { h = prime5 } else { h = 0 } + BLT afterLoop + + ADD prime1, prime2, v1 + MOVD prime2, v2 + MOVD $0, v3 + NEG prime1, v4 + + blockLoop() + + ROR $64-1, v1, x1 + ROR $64-7, v2, x2 + ADD x1, x2 + ROR $64-12, v3, x3 + ROR $64-18, v4, x4 + ADD x3, x4 + ADD x2, x4, h + + mergeRound(h, v1) + mergeRound(h, v2) + mergeRound(h, v3) + mergeRound(h, v4) + +afterLoop: + ADD n, h + + TBZ $4, n, try8 + LDP.P 16(p), (x1, x2) + + round0(x1) + + // NOTE: here and below, sequencing the EOR after the ROR (using a + // rotated register) is worth a small but measurable speedup for small + // inputs. + ROR $64-27, h + EOR x1 @> 64-27, h, h + MADD h, prime4, prime1, h + + round0(x2) + ROR $64-27, h + EOR x2 @> 64-27, h, h + MADD h, prime4, prime1, h + +try8: + TBZ $3, n, try4 + MOVD.P 8(p), x1 + + round0(x1) + ROR $64-27, h + EOR x1 @> 64-27, h, h + MADD h, prime4, prime1, h + +try4: + TBZ $2, n, try2 + MOVWU.P 4(p), x2 + + MUL prime1, x2 + ROR $64-23, h + EOR x2 @> 64-23, h, h + MADD h, prime3, prime2, h + +try2: + TBZ $1, n, try1 + MOVHU.P 2(p), x3 + AND $255, x3, x1 + LSR $8, x3, x2 + + MUL prime5, x1 + ROR $64-11, h + EOR x1 @> 64-11, h, h + MUL prime1, h + + MUL prime5, x2 + ROR $64-11, h + EOR x2 @> 64-11, h, h + MUL prime1, h + +try1: + TBZ $0, n, finalize + MOVBU (p), x4 + + MUL prime5, x4 + ROR $64-11, h + EOR x4 @> 64-11, h, h + MUL prime1, h + +finalize: + EOR h >> 33, h + MUL prime2, h + EOR h >> 29, h + MUL prime3, h + EOR h >> 32, h + + MOVD h, ret+24(FP) + RET + +// func writeBlocks(d *Digest, b []byte) int +TEXT ·writeBlocks(SB), NOSPLIT|NOFRAME, $0-40 + LDP ·primes+0(SB), (prime1, prime2) + + // Load state. Assume v[1-4] are stored contiguously. + MOVD d+0(FP), digest + LDP 0(digest), (v1, v2) + LDP 16(digest), (v3, v4) + + LDP b_base+8(FP), (p, n) + + blockLoop() + + // Store updated state. + STP (v1, v2), 0(digest) + STP (v3, v4), 16(digest) + + BIC $31, n + MOVD n, ret+32(FP) + RET diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_asm.go b/vendor/github.com/cespare/xxhash/v2/xxhash_asm.go new file mode 100644 index 0000000000..9216e0a40c --- /dev/null +++ b/vendor/github.com/cespare/xxhash/v2/xxhash_asm.go @@ -0,0 +1,15 @@ +//go:build (amd64 || arm64) && !appengine && gc && !purego +// +build amd64 arm64 +// +build !appengine +// +build gc +// +build !purego + +package xxhash + +// Sum64 computes the 64-bit xxHash digest of b. +// +//go:noescape +func Sum64(b []byte) uint64 + +//go:noescape +func writeBlocks(d *Digest, b []byte) int diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_other.go b/vendor/github.com/cespare/xxhash/v2/xxhash_other.go index 4a5a821603..26df13bba4 100644 --- a/vendor/github.com/cespare/xxhash/v2/xxhash_other.go +++ b/vendor/github.com/cespare/xxhash/v2/xxhash_other.go @@ -1,4 +1,5 @@ -// +build !amd64 appengine !gc purego +//go:build (!amd64 && !arm64) || appengine || !gc || purego +// +build !amd64,!arm64 appengine !gc purego package xxhash @@ -14,10 +15,10 @@ func Sum64(b []byte) uint64 { var h uint64 if n >= 32 { - v1 := prime1v + prime2 + v1 := primes[0] + prime2 v2 := prime2 v3 := uint64(0) - v4 := -prime1v + v4 := -primes[0] for len(b) >= 32 { v1 = round(v1, u64(b[0:8:len(b)])) v2 = round(v2, u64(b[8:16:len(b)])) @@ -36,19 +37,18 @@ func Sum64(b []byte) uint64 { h += uint64(n) - i, end := 0, len(b) - for ; i+8 <= end; i += 8 { - k1 := round(0, u64(b[i:i+8:len(b)])) + for ; len(b) >= 8; b = b[8:] { + k1 := round(0, u64(b[:8])) h ^= k1 h = rol27(h)*prime1 + prime4 } - if i+4 <= end { - h ^= uint64(u32(b[i:i+4:len(b)])) * prime1 + if len(b) >= 4 { + h ^= uint64(u32(b[:4])) * prime1 h = rol23(h)*prime2 + prime3 - i += 4 + b = b[4:] } - for ; i < end; i++ { - h ^= uint64(b[i]) * prime5 + for ; len(b) > 0; b = b[1:] { + h ^= uint64(b[0]) * prime5 h = rol11(h) * prime1 } diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_safe.go b/vendor/github.com/cespare/xxhash/v2/xxhash_safe.go index fc9bea7a31..e86f1b5fd8 100644 --- a/vendor/github.com/cespare/xxhash/v2/xxhash_safe.go +++ b/vendor/github.com/cespare/xxhash/v2/xxhash_safe.go @@ -1,3 +1,4 @@ +//go:build appengine // +build appengine // This file contains the safe implementations of otherwise unsafe-using code. diff --git a/vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go b/vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go index 376e0ca2e4..1c1638fd88 100644 --- a/vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go +++ b/vendor/github.com/cespare/xxhash/v2/xxhash_unsafe.go @@ -1,3 +1,4 @@ +//go:build !appengine // +build !appengine // This file encapsulates usage of unsafe. @@ -11,7 +12,7 @@ import ( // In the future it's possible that compiler optimizations will make these // XxxString functions unnecessary by realizing that calls such as -// Sum64([]byte(s)) don't need to copy s. See https://golang.org/issue/2205. +// Sum64([]byte(s)) don't need to copy s. See https://go.dev/issue/2205. // If that happens, even if we keep these functions they can be replaced with // the trivial safe code. diff --git a/vendor/github.com/chai2010/gettext-go/.travis.yml b/vendor/github.com/chai2010/gettext-go/.travis.yml new file mode 100644 index 0000000000..4eac3982bc --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/.travis.yml @@ -0,0 +1,5 @@ +language: go + +go: + - "1.14" + - tip diff --git a/vendor/github.com/chai2010/gettext-go/README.md b/vendor/github.com/chai2010/gettext-go/README.md new file mode 100644 index 0000000000..9381bd1522 --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/README.md @@ -0,0 +1,191 @@ +- *赞助 BTC: 1Cbd6oGAUUyBi7X7MaR4np4nTmQZXVgkCW* +- *赞助 ETH: 0x623A3C3a72186A6336C79b18Ac1eD36e1c71A8a6* +- *Go语言付费QQ群: 1055927514* + +---- + +# gettext-go: GNU gettext for Go ([Imported By Kubernetes](https://pkg.go.dev/github.com/chai2010/gettext-go@v0.1.0/gettext?tab=importedby)) + +- PkgDoc: [http://godoc.org/github.com/chai2010/gettext-go](http://godoc.org/github.com/chai2010/gettext-go) +- PkgDoc: [http://pkg.go.dev/github.com/chai2010/gettext-go](http://pkg.go.dev/github.com/chai2010/gettext-go) + +## Install + +1. `go get github.com/chai2010/gettext-go` +2. `go run hello.go` + +The godoc.org or go.dev has more information. + +## Examples + +```Go +package main + +import ( + "fmt" + + "github.com/chai2010/gettext-go" +) + +func main() { + gettext := gettext.New("hello", "./examples/locale").SetLanguage("zh_CN") + fmt.Println(gettext.Gettext("Hello, world!")) + + // Output: 你好, 世界! +} +``` + +```Go +package main + +import ( + "fmt" + + "github.com/chai2010/gettext-go" +) + +func main() { + gettext.SetLanguage("zh_CN") + gettext.BindLocale(gettext.New("hello", "locale")) + + // gettext.BindLocale("hello", "locale") // from locale dir + // gettext.BindLocale("hello", "locale.zip") // from locale zip file + // gettext.BindLocale("hello", "locale.zip", zipData) // from embedded zip data + + // translate source text + fmt.Println(gettext.Gettext("Hello, world!")) + // Output: 你好, 世界! + + // if no msgctxt in PO file (only msgid and msgstr), + // specify context as "" by + fmt.Println(gettext.PGettext("", "Hello, world!")) + // Output: 你好, 世界! + + // translate resource + fmt.Println(string(gettext.Getdata("poems.txt")))) + // Output: ... +} +``` + +Go file: [hello.go](https://github.com/chai2010/gettext-go/blob/master/examples/hello.go); PO file: [hello.po](https://github.com/chai2010/gettext-go/blob/master/examples/locale/default/LC_MESSAGES/hello.po); + +---- + +## API Changes (v0.1.0 vs v1.0.0) + +### Renamed package path + +| v0.1.0 (old) | v1.0.0 (new) | +| ----------------------------------------------- | --------------------------------------- | +| `github.com/chai2010/gettext-go/gettext` | `github.com/chai2010/gettext-go` | +| `github.com/chai2010/gettext-go/gettext/po` | `github.com/chai2010/gettext-go/po` | +| `github.com/chai2010/gettext-go/gettext/mo` | `github.com/chai2010/gettext-go/mo` | +| `github.com/chai2010/gettext-go/gettext/plural` | `github.com/chai2010/gettext-go/plural` | + +### Renamed functions + +| v0.1.0 (old) | v1.0.0 (new) | +| ---------------------------------- | --------------------------- | +| `gettext-go/gettext.*` | `gettext-go.*` | +| `gettext-go/gettext.DefaultLocal` | `gettext-go.DefaultLanguage`| +| `gettext-go/gettext.BindTextdomain`| `gettext-go.BindLocale` | +| `gettext-go/gettext.Textdomain` | `gettext-go.SetDomain` | +| `gettext-go/gettext.SetLocale` | `gettext-go.SetLanguage` | +| `gettext-go/gettext/po.Load` | `gettext-go/po.LoadFile` | +| `gettext-go/gettext/po.LoadData` | `gettext-go/po.Load` | +| `gettext-go/gettext/mo.Load` | `gettext-go/mo.LoadFile` | +| `gettext-go/gettext/mo.LoadData` | `gettext-go/mo.Load` | + +### Use empty string as the default context for `gettext.Gettext` + +```go +package main + +// v0.1.0 +// if the **context** missing, use `callerName(2)` as the context: + +// v1.0.0 +// if the **context** missing, use empty string as the context: + +func main() { + gettext.Gettext("hello") + // v0.1.0 => gettext.PGettext("main.main", "hello") + // v1.0.0 => gettext.PGettext("", "hello") + + gettext.DGettext("domain", "hello") + // v0.1.0 => gettext.DPGettext("domain", "main.main", "hello") + // v1.0.0 => gettext.DPGettext("domain", "", "hello") + + gettext.NGettext("domain", "hello", "hello2", n) + // v0.1.0 => gettext.PNGettext("domain", "main.main", "hello", "hello2", n) + // v1.0.0 => gettext.PNGettext("domain", "", "hello", "hello2", n) + + gettext.DNGettext("domain", "hello", "hello2", n) + // v0.1.0 => gettext.DPNGettext("domain", "main.main", "hello", "hello2", n) + // v1.0.0 => gettext.DPNGettext("domain", "", "hello", "hello2", n) +} +``` + +### `BindLocale` support `FileSystem` interface + +```go +// Use FileSystem: +// BindLocale(New("poedit", "name", OS("path/to/dir"))) // bind "poedit" domain +// BindLocale(New("poedit", "name", OS("path/to.zip"))) // bind "poedit" domain +``` + +## New API in v1.0.0 + +`Gettexter` interface: + +```go +type Gettexter interface { + FileSystem() FileSystem + + GetDomain() string + SetDomain(domain string) Gettexter + + GetLanguage() string + SetLanguage(lang string) Gettexter + + Gettext(msgid string) string + PGettext(msgctxt, msgid string) string + + NGettext(msgid, msgidPlural string, n int) string + PNGettext(msgctxt, msgid, msgidPlural string, n int) string + + DGettext(domain, msgid string) string + DPGettext(domain, msgctxt, msgid string) string + DNGettext(domain, msgid, msgidPlural string, n int) string + DPNGettext(domain, msgctxt, msgid, msgidPlural string, n int) string + + Getdata(name string) []byte + DGetdata(domain, name string) []byte +} + +func New(domain, path string, data ...interface{}) Gettexter +``` + +`FileSystem` interface: + +```go +type FileSystem interface { + LocaleList() []string + LoadMessagesFile(domain, lang, ext string) ([]byte, error) + LoadResourceFile(domain, lang, name string) ([]byte, error) + String() string +} + +func NewFS(name string, x interface{}) FileSystem +func OS(root string) FileSystem +func ZipFS(r *zip.Reader, name string) FileSystem +func NilFS(name string) FileSystem +``` + +---- + +## BUGS + +Please report bugs to . + +Thanks! diff --git a/vendor/github.com/chai2010/gettext-go/doc.go b/vendor/github.com/chai2010/gettext-go/doc.go new file mode 100644 index 0000000000..50dfea3305 --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/doc.go @@ -0,0 +1,67 @@ +// Copyright 2013 . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package gettext implements a basic GNU's gettext library. + +Example: + import ( + "github.com/chai2010/gettext-go" + ) + + func main() { + gettext.SetLanguage("zh_CN") + + // gettext.BindLocale(gettext.New("hello", "locale")) // from locale dir + // gettext.BindLocale(gettext.New("hello", "locale.zip")) // from locale zip file + // gettext.BindLocale(gettext.New("hello", "locale.zip", zipData)) // from embedded zip data + + gettext.BindLocale(gettext.New("hello", "locale")) + + // translate source text + fmt.Println(gettext.Gettext("Hello, world!")) + // Output: 你好, 世界! + + // translate resource + fmt.Println(string(gettext.Getdata("poems.txt"))) + // Output: ... + } + +Translate directory struct("./examples/locale.zip"): + + Root: "path" or "file.zip/zipBaseName" + +-default # locale: $(LC_MESSAGES) or $(LANG) or "default" + | +-LC_MESSAGES # just for `gettext.Gettext` + | | +-hello.mo # $(Root)/$(lang)/LC_MESSAGES/$(domain).mo + | | +-hello.po # $(Root)/$(lang)/LC_MESSAGES/$(domain).po + | | \-hello.json # $(Root)/$(lang)/LC_MESSAGES/$(domain).json + | | + | \-LC_RESOURCE # just for `gettext.Getdata` + | +-hello # domain map a dir in resource translate + | +-favicon.ico # $(Root)/$(lang)/LC_RESOURCE/$(domain)/$(filename) + | \-poems.txt + | + \-zh_CN # simple chinese translate + +-LC_MESSAGES + | +-hello.po # try "$(domain).po" first + | +-hello.mo # try "$(domain).mo" second + | \-hello.json # try "$(domain).json" third + | + \-LC_RESOURCE + +-hello + +-favicon.ico # $(lang)/$(domain)/favicon.ico + \-poems.txt # $(lang)/$(domain)/poems.txt + +See: + http://en.wikipedia.org/wiki/Gettext + http://www.gnu.org/software/gettext/manual/html_node + http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html + http://www.gnu.org/software/gettext/manual/html_node/PO-Files.html + http://www.gnu.org/software/gettext/manual/html_node/MO-Files.html + http://www.poedit.net/ + +Please report bugs to . +Thanks! +*/ +package gettext diff --git a/vendor/github.com/chai2010/gettext-go/fs.go b/vendor/github.com/chai2010/gettext-go/fs.go new file mode 100644 index 0000000000..4e66fae7c6 --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/fs.go @@ -0,0 +1,84 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gettext + +import ( + "archive/zip" + "bytes" + "fmt" +) + +type FileSystem interface { + LocaleList() []string + LoadMessagesFile(domain, lang, ext string) ([]byte, error) + LoadResourceFile(domain, lang, name string) ([]byte, error) + String() string +} + +func NewFS(name string, x interface{}) FileSystem { + if x == nil { + if name != "" { + return OS(name) + } + return NilFS(name) + } + + switch x := x.(type) { + case []byte: + if len(x) == 0 { + return OS(name) + } + if r, err := zip.NewReader(bytes.NewReader(x), int64(len(x))); err == nil { + return ZipFS(r, name) + } + if fs, err := newJson(x, name); err == nil { + return fs + } + case string: + if len(x) == 0 { + return OS(name) + } + if r, err := zip.NewReader(bytes.NewReader([]byte(x)), int64(len(x))); err == nil { + return ZipFS(r, name) + } + if fs, err := newJson([]byte(x), name); err == nil { + return fs + } + case FileSystem: + return x + } + + return NilFS(name) +} + +func OS(root string) FileSystem { + return newOsFS(root) +} + +func ZipFS(r *zip.Reader, name string) FileSystem { + return newZipFS(r, name) +} + +func NilFS(name string) FileSystem { + return &nilFS{name} +} + +type nilFS struct { + name string +} + +func (p *nilFS) LocaleList() []string { + return nil +} + +func (p *nilFS) LoadMessagesFile(domain, lang, ext string) ([]byte, error) { + return nil, fmt.Errorf("not found") +} +func (p *nilFS) LoadResourceFile(domain, lang, name string) ([]byte, error) { + return nil, fmt.Errorf("not found") +} +func (p *nilFS) String() string { + return "gettext.nilfs(" + p.name + ")" +} diff --git a/vendor/github.com/chai2010/gettext-go/fs_json.go b/vendor/github.com/chai2010/gettext-go/fs_json.go new file mode 100644 index 0000000000..c7138c9954 --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/fs_json.go @@ -0,0 +1,66 @@ +// Copyright 2020 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gettext + +import ( + "encoding/json" + "fmt" + "sort" +) + +type jsonFS struct { + name string + x map[string]struct { + LC_MESSAGES map[string][]struct { + MsgContext string `json:"msgctxt"` // msgctxt context + MsgId string `json:"msgid"` // msgid untranslated-string + MsgIdPlural string `json:"msgid_plural"` // msgid_plural untranslated-string-plural + MsgStr []string `json:"msgstr"` // msgstr translated-string + } + LC_RESOURCE map[string]map[string]string + } +} + +func isJsonData() bool { + return false +} + +func newJson(jsonData []byte, name string) (*jsonFS, error) { + p := &jsonFS{name: name} + if err := json.Unmarshal(jsonData, &p.x); err != nil { + return nil, err + } + + return p, nil +} + +func (p *jsonFS) LocaleList() []string { + var ss []string + for lang := range p.x { + ss = append(ss, lang) + } + sort.Strings(ss) + return ss +} + +func (p *jsonFS) LoadMessagesFile(domain, lang, ext string) ([]byte, error) { + if v, ok := p.x[lang]; ok { + if v, ok := v.LC_MESSAGES[domain+ext]; ok { + return json.Marshal(v) + } + } + return nil, fmt.Errorf("not found") +} +func (p *jsonFS) LoadResourceFile(domain, lang, name string) ([]byte, error) { + if v, ok := p.x[lang]; ok { + if v, ok := v.LC_RESOURCE[domain]; ok { + return []byte(v[name]), nil + } + } + return nil, fmt.Errorf("not found") +} +func (p *jsonFS) String() string { + return "gettext.nilfs(" + p.name + ")" +} diff --git a/vendor/github.com/chai2010/gettext-go/fs_os.go b/vendor/github.com/chai2010/gettext-go/fs_os.go new file mode 100644 index 0000000000..80d4f51bac --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/fs_os.go @@ -0,0 +1,91 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gettext + +import ( + "archive/zip" + "bytes" + "fmt" + "io/ioutil" + "os" + "sort" + "strings" +) + +type osFS struct { + root string +} + +func newOsFS(root string) FileSystem { + // locale zip file + if fi, err := os.Stat(root); err == nil && !fi.IsDir() { + if strings.HasSuffix(strings.ToLower(root), ".zip") { + if x, err := ioutil.ReadFile(root); err == nil { + if r, err := zip.NewReader(bytes.NewReader(x), int64(len(x))); err == nil { + return ZipFS(r, root) + } + } + } + if strings.HasSuffix(strings.ToLower(root), ".json") { + if x, err := ioutil.ReadFile(root); err == nil { + if fs, err := newJson(x, root); err == nil { + return fs + } + } + } + } + + // locale dir + return &osFS{root: root} +} + +func (p *osFS) LocaleList() []string { + list, err := ioutil.ReadDir(p.root) + if err != nil { + return nil + } + ssMap := make(map[string]bool) + for _, dir := range list { + if dir.IsDir() { + ssMap[dir.Name()] = true + } + } + var locales = make([]string, 0, len(ssMap)) + for s := range ssMap { + locales = append(locales, s) + } + sort.Strings(locales) + return locales +} + +func (p *osFS) LoadMessagesFile(domain, locale, ext string) ([]byte, error) { + trName := p.makeMessagesFileName(domain, locale, ext) + rcData, err := ioutil.ReadFile(trName) + if err != nil { + return nil, err + } + return rcData, nil +} + +func (p *osFS) LoadResourceFile(domain, locale, name string) ([]byte, error) { + rcName := p.makeResourceFileName(domain, locale, name) + rcData, err := ioutil.ReadFile(rcName) + if err != nil { + return nil, err + } + return rcData, nil +} + +func (p *osFS) String() string { + return "gettext.localfs(" + p.root + ")" +} + +func (p *osFS) makeMessagesFileName(domain, lang, ext string) string { + return fmt.Sprintf("%s/%s/LC_MESSAGES/%s%s", p.root, lang, domain, ext) +} + +func (p *osFS) makeResourceFileName(domain, lang, name string) string { + return fmt.Sprintf("%s/%s/LC_RESOURCE/%s/%s", p.root, lang, domain, name) +} diff --git a/vendor/github.com/chai2010/gettext-go/fs_zip.go b/vendor/github.com/chai2010/gettext-go/fs_zip.go new file mode 100644 index 0000000000..61eb8359da --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/fs_zip.go @@ -0,0 +1,142 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gettext + +import ( + "archive/zip" + "fmt" + "io/ioutil" + "sort" + "strings" +) + +type zipFS struct { + root string + name string + r *zip.Reader +} + +func newZipFS(r *zip.Reader, name string) *zipFS { + fs := &zipFS{r: r, name: name} + fs.root = fs.zipRoot() + return fs +} + +func (p *zipFS) zipName() string { + name := p.name + if x := strings.LastIndexAny(name, `\/`); x != -1 { + name = name[x+1:] + } + name = strings.TrimSuffix(name, ".zip") + return name +} + +func (p *zipFS) zipRoot() string { + var somepath string + for _, f := range p.r.File { + if x := strings.Index(f.Name, "LC_MESSAGES"); x != -1 { + somepath = f.Name + } + if x := strings.Index(f.Name, "LC_RESOURCE"); x != -1 { + somepath = f.Name + } + } + if somepath == "" { + return p.zipName() + } + + ss := strings.Split(somepath, "/") + for i, s := range ss { + // $(root)/$(lang)/LC_MESSAGES + // $(root)/$(lang)/LC_RESOURCE + if (s == "LC_MESSAGES" || s == "LC_RESOURCE") && i >= 2 { + return strings.Join(ss[:i-1], "/") + } + } + + return p.zipName() +} + +func (p *zipFS) LocaleList() []string { + var locals []string + for s := range p.lsZip(p.r) { + locals = append(locals, s) + } + sort.Strings(locals) + return locals +} + +func (p *zipFS) LoadMessagesFile(domain, lang, ext string) ([]byte, error) { + trName := p.makeMessagesFileName(domain, lang, ext) + for _, f := range p.r.File { + if f.Name != trName { + continue + } + rc, err := f.Open() + if err != nil { + return nil, err + } + rcData, err := ioutil.ReadAll(rc) + rc.Close() + return rcData, err + } + return nil, fmt.Errorf("not found") +} + +func (p *zipFS) LoadResourceFile(domain, lang, name string) ([]byte, error) { + rcName := p.makeResourceFileName(domain, lang, name) + for _, f := range p.r.File { + if f.Name != rcName { + continue + } + rc, err := f.Open() + if err != nil { + return nil, err + } + rcData, err := ioutil.ReadAll(rc) + rc.Close() + return rcData, err + } + return nil, fmt.Errorf("not found") +} + +func (p *zipFS) String() string { + return "gettext.zipfs(" + p.name + ")" +} + +func (p *zipFS) makeMessagesFileName(domain, lang, ext string) string { + return fmt.Sprintf("%s/%s/LC_MESSAGES/%s%s", p.root, lang, domain, ext) +} + +func (p *zipFS) makeResourceFileName(domain, lang, name string) string { + return fmt.Sprintf("%s/%s/LC_RESOURCE/%s/%s", p.root, lang, domain, name) +} + +func (p *zipFS) lsZip(r *zip.Reader) map[string]bool { + ssMap := make(map[string]bool) + for _, f := range r.File { + if x := strings.Index(f.Name, "LC_MESSAGES"); x != -1 { + s := strings.TrimRight(f.Name[:x], `\/`) + if x = strings.LastIndexAny(s, `\/`); x != -1 { + s = s[x+1:] + } + if s != "" { + ssMap[s] = true + } + continue + } + if x := strings.Index(f.Name, "LC_RESOURCE"); x != -1 { + s := strings.TrimRight(f.Name[:x], `\/`) + if x = strings.LastIndexAny(s, `\/`); x != -1 { + s = s[x+1:] + } + if s != "" { + ssMap[s] = true + } + continue + } + } + return ssMap +} diff --git a/vendor/github.com/chai2010/gettext-go/gettext.go b/vendor/github.com/chai2010/gettext-go/gettext.go new file mode 100644 index 0000000000..7747188ab4 --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/gettext.go @@ -0,0 +1,219 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gettext + +var ( + DefaultLanguage string = getDefaultLanguage() // use $(LC_MESSAGES) or $(LANG) or "default" +) + +type Gettexter interface { + FileSystem() FileSystem + + GetDomain() string + SetDomain(domain string) Gettexter + + GetLanguage() string + SetLanguage(lang string) Gettexter + + Gettext(msgid string) string + PGettext(msgctxt, msgid string) string + + NGettext(msgid, msgidPlural string, n int) string + PNGettext(msgctxt, msgid, msgidPlural string, n int) string + + DGettext(domain, msgid string) string + DPGettext(domain, msgctxt, msgid string) string + DNGettext(domain, msgid, msgidPlural string, n int) string + DPNGettext(domain, msgctxt, msgid, msgidPlural string, n int) string + + Getdata(name string) []byte + DGetdata(domain, name string) []byte +} + +// New create Interface use default language. +func New(domain, path string, data ...interface{}) Gettexter { + return newLocale(domain, path, data...) +} + +var defaultGettexter struct { + lang string + domain string + Gettexter +} + +func init() { + defaultGettexter.lang = getDefaultLanguage() + defaultGettexter.domain = "default" + defaultGettexter.Gettexter = newLocale("", "") +} + +// BindLocale sets and queries program's domains. +// +// Examples: +// BindLocale(New("poedit", "locale")) // bind "poedit" domain +// +// Use zip file: +// BindLocale(New("poedit", "locale.zip")) // bind "poedit" domain +// BindLocale(New("poedit", "locale.zip", zipData)) // bind "poedit" domain +// +// Use FileSystem: +// BindLocale(New("poedit", "name", OS("path/to/dir"))) // bind "poedit" domain +// BindLocale(New("poedit", "name", OS("path/to.zip"))) // bind "poedit" domain +// +func BindLocale(g Gettexter) { + if g != nil { + defaultGettexter.Gettexter = g + defaultGettexter.SetLanguage(defaultGettexter.lang) + } else { + defaultGettexter.Gettexter = newLocale("", "") + defaultGettexter.SetLanguage(defaultGettexter.lang) + } +} + +// SetLanguage sets and queries the program's current lang. +// +// If the lang is not empty string, set the new locale. +// +// If the lang is empty string, don't change anything. +// +// Returns is the current locale. +// +// Examples: +// SetLanguage("") // get locale: return DefaultLocale +// SetLanguage("zh_CN") // set locale: return zh_CN +// SetLanguage("") // get locale: return zh_CN +func SetLanguage(lang string) string { + defaultGettexter.SetLanguage(lang) + return defaultGettexter.GetLanguage() +} + +// SetDomain sets and retrieves the current message domain. +// +// If the domain is not empty string, set the new domains. +// +// If the domain is empty string, don't change anything. +// +// Returns is the all used domains. +// +// Examples: +// SetDomain("poedit") // set domain: poedit +// SetDomain("") // get domain: return poedit +func SetDomain(domain string) string { + defaultGettexter.SetDomain(domain) + return defaultGettexter.GetDomain() +} + +// Gettext attempt to translate a text string into the user's native language, +// by looking up the translation in a message catalog. +// +// It use the caller's function name as the msgctxt. +// +// Examples: +// func Foo() { +// msg := gettext.Gettext("Hello") // msgctxt is "" +// } +func Gettext(msgid string) string { + return defaultGettexter.Gettext(msgid) +} + +// Getdata attempt to translate a resource file into the user's native language, +// by looking up the translation in a message catalog. +// +// Examples: +// func Foo() { +// Textdomain("hello") +// BindLocale("hello", "locale.zip", nilOrZipData) +// poems := gettext.Getdata("poems.txt") +// } +func Getdata(name string) []byte { + return defaultGettexter.Getdata(name) +} + +// NGettext attempt to translate a text string into the user's native language, +// by looking up the appropriate plural form of the translation in a message +// catalog. +// +// It use the caller's function name as the msgctxt. +// +// Examples: +// func Foo() { +// msg := gettext.NGettext("%d people", "%d peoples", 2) +// } +func NGettext(msgid, msgidPlural string, n int) string { + return defaultGettexter.NGettext(msgid, msgidPlural, n) +} + +// PGettext attempt to translate a text string into the user's native language, +// by looking up the translation in a message catalog. +// +// Examples: +// func Foo() { +// msg := gettext.PGettext("gettext-go.example", "Hello") // msgctxt is "gettext-go.example" +// } +func PGettext(msgctxt, msgid string) string { + return defaultGettexter.PGettext(msgctxt, msgid) +} + +// PNGettext attempt to translate a text string into the user's native language, +// by looking up the appropriate plural form of the translation in a message +// catalog. +// +// Examples: +// func Foo() { +// msg := gettext.PNGettext("gettext-go.example", "%d people", "%d peoples", 2) +// } +func PNGettext(msgctxt, msgid, msgidPlural string, n int) string { + return defaultGettexter.PNGettext(msgctxt, msgid, msgidPlural, n) +} + +// DGettext like Gettext(), but looking up the message in the specified domain. +// +// Examples: +// func Foo() { +// msg := gettext.DGettext("poedit", "Hello") +// } +func DGettext(domain, msgid string) string { + return defaultGettexter.DGettext(domain, msgid) +} + +// DNGettext like NGettext(), but looking up the message in the specified domain. +// +// Examples: +// func Foo() { +// msg := gettext.PNGettext("poedit", "gettext-go.example", "%d people", "%d peoples", 2) +// } +func DNGettext(domain, msgid, msgidPlural string, n int) string { + return defaultGettexter.DNGettext(domain, msgid, msgidPlural, n) +} + +// DPGettext like PGettext(), but looking up the message in the specified domain. +// +// Examples: +// func Foo() { +// msg := gettext.DPGettext("poedit", "gettext-go.example", "Hello") +// } +func DPGettext(domain, msgctxt, msgid string) string { + return defaultGettexter.DPGettext(domain, msgctxt, msgid) +} + +// DPNGettext like PNGettext(), but looking up the message in the specified domain. +// +// Examples: +// func Foo() { +// msg := gettext.DPNGettext("poedit", "gettext-go.example", "%d people", "%d peoples", 2) +// } +func DPNGettext(domain, msgctxt, msgid, msgidPlural string, n int) string { + return defaultGettexter.DPNGettext(domain, msgctxt, msgid, msgidPlural, n) +} + +// DGetdata like Getdata(), but looking up the resource in the specified domain. +// +// Examples: +// func Foo() { +// msg := gettext.DGetdata("hello", "poems.txt") +// } +func DGetdata(domain, name string) []byte { + return defaultGettexter.DGetdata(domain, name) +} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/caller.go b/vendor/github.com/chai2010/gettext-go/gettext/caller.go deleted file mode 100644 index e24aab3756..0000000000 --- a/vendor/github.com/chai2010/gettext-go/gettext/caller.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2013 ChaiShushan . All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gettext - -import ( - "regexp" - "runtime" -) - -var ( - reInit = regexp.MustCompile(`init·\d+$`) // main.init·1 - reClosure = regexp.MustCompile(`func·\d+$`) // main.func·001 -) - -// caller types: -// runtime.goexit -// runtime.main -// main.init -// main.main -// main.init·1 -> main.init -// main.func·001 -> main.func -// code.google.com/p/gettext-go/gettext.TestCallerName -// ... -func callerName(skip int) string { - pc, _, _, ok := runtime.Caller(skip) - if !ok { - return "" - } - name := runtime.FuncForPC(pc).Name() - if reInit.MatchString(name) { - return reInit.ReplaceAllString(name, "init") - } - if reClosure.MatchString(name) { - return reClosure.ReplaceAllString(name, "func") - } - return name -} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/doc.go b/vendor/github.com/chai2010/gettext-go/gettext/doc.go deleted file mode 100644 index 422bf2c6d7..0000000000 --- a/vendor/github.com/chai2010/gettext-go/gettext/doc.go +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2013 . All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* -Package gettext implements a basic GNU's gettext library. - -Example: - import ( - "github.com/chai2010/gettext-go/gettext" - ) - - func main() { - gettext.SetLocale("zh_CN") - gettext.Textdomain("hello") - - // gettext.BindTextdomain("hello", "local", nil) // from local dir - // gettext.BindTextdomain("hello", "local.zip", nil) // from local zip file - // gettext.BindTextdomain("hello", "local.zip", zipData) // from embedded zip data - - gettext.BindTextdomain("hello", "local", nil) - - // translate source text - fmt.Println(gettext.Gettext("Hello, world!")) - // Output: 你好, 世界! - - // translate resource - fmt.Println(string(gettext.Getdata("poems.txt"))) - // Output: ... - } - -Translate directory struct("../examples/local.zip"): - - Root: "path" or "file.zip/zipBaseName" - +-default # local: $(LC_MESSAGES) or $(LANG) or "default" - | +-LC_MESSAGES # just for `gettext.Gettext` - | | +-hello.mo # $(Root)/$(local)/LC_MESSAGES/$(domain).mo - | | \-hello.po # $(Root)/$(local)/LC_MESSAGES/$(domain).mo - | | - | \-LC_RESOURCE # just for `gettext.Getdata` - | +-hello # domain map a dir in resource translate - | +-favicon.ico # $(Root)/$(local)/LC_RESOURCE/$(domain)/$(filename) - | \-poems.txt - | - \-zh_CN # simple chinese translate - +-LC_MESSAGES - | +-hello.mo # try "$(domain).mo" first - | \-hello.po # try "$(domain).po" second - | - \-LC_RESOURCE - +-hello - +-favicon.ico # try "$(local)/$(domain)/file" first - \-poems.txt # try "default/$(domain)/file" second - -See: - http://en.wikipedia.org/wiki/Gettext - http://www.gnu.org/software/gettext/manual/html_node - http://www.gnu.org/software/gettext/manual/html_node/Header-Entry.html - http://www.gnu.org/software/gettext/manual/html_node/PO-Files.html - http://www.gnu.org/software/gettext/manual/html_node/MO-Files.html - http://www.poedit.net/ - -Please report bugs to . -Thanks! -*/ -package gettext diff --git a/vendor/github.com/chai2010/gettext-go/gettext/domain.go b/vendor/github.com/chai2010/gettext-go/gettext/domain.go deleted file mode 100644 index f860b27b6b..0000000000 --- a/vendor/github.com/chai2010/gettext-go/gettext/domain.go +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright 2013 ChaiShushan . All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gettext - -import ( - "sync" -) - -type domainManager struct { - mutex sync.Mutex - locale string - domain string - domainMap map[string]*fileSystem - trTextMap map[string]*translator -} - -func newDomainManager() *domainManager { - return &domainManager{ - locale: DefaultLocale, - domainMap: make(map[string]*fileSystem), - trTextMap: make(map[string]*translator), - } -} - -func (p *domainManager) makeTrMapKey(domain, locale string) string { - return domain + "_$$$_" + locale -} - -func (p *domainManager) Bind(domain, path string, data []byte) (domains, paths []string) { - p.mutex.Lock() - defer p.mutex.Unlock() - - switch { - case domain != "" && path != "": // bind new domain - p.bindDomainTranslators(domain, path, data) - case domain != "" && path == "": // delete domain - p.deleteDomain(domain) - } - - // return all bind domain - for k, fs := range p.domainMap { - domains = append(domains, k) - paths = append(paths, fs.FsName) - } - return -} - -func (p *domainManager) SetLocale(locale string) string { - p.mutex.Lock() - defer p.mutex.Unlock() - if locale != "" { - p.locale = locale - } - return p.locale -} - -func (p *domainManager) SetDomain(domain string) string { - p.mutex.Lock() - defer p.mutex.Unlock() - if domain != "" { - p.domain = domain - } - return p.domain -} - -func (p *domainManager) Getdata(name string) []byte { - return p.getdata(p.domain, name) -} - -func (p *domainManager) DGetdata(domain, name string) []byte { - return p.getdata(domain, name) -} - -func (p *domainManager) PNGettext(msgctxt, msgid, msgidPlural string, n int) string { - p.mutex.Lock() - defer p.mutex.Unlock() - return p.gettext(p.domain, msgctxt, msgid, msgidPlural, n) -} - -func (p *domainManager) DPNGettext(domain, msgctxt, msgid, msgidPlural string, n int) string { - p.mutex.Lock() - defer p.mutex.Unlock() - return p.gettext(domain, msgctxt, msgid, msgidPlural, n) -} - -func (p *domainManager) gettext(domain, msgctxt, msgid, msgidPlural string, n int) string { - if p.locale == "" || p.domain == "" { - return msgid - } - if _, ok := p.domainMap[domain]; !ok { - return msgid - } - if f, ok := p.trTextMap[p.makeTrMapKey(domain, p.locale)]; ok { - return f.PNGettext(msgctxt, msgid, msgidPlural, n) - } - return msgid -} - -func (p *domainManager) getdata(domain, name string) []byte { - if p.locale == "" || p.domain == "" { - return nil - } - if _, ok := p.domainMap[domain]; !ok { - return nil - } - if fs, ok := p.domainMap[domain]; ok { - if data, err := fs.LoadResourceFile(domain, p.locale, name); err == nil { - return data - } - if p.locale != "default" { - if data, err := fs.LoadResourceFile(domain, "default", name); err == nil { - return data - } - } - } - return nil -} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/domain_helper.go b/vendor/github.com/chai2010/gettext-go/gettext/domain_helper.go deleted file mode 100644 index 8dce58e655..0000000000 --- a/vendor/github.com/chai2010/gettext-go/gettext/domain_helper.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2013 ChaiShushan . All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gettext - -import ( - "fmt" - "strings" -) - -func (p *domainManager) bindDomainTranslators(domain, path string, data []byte) { - if _, ok := p.domainMap[domain]; ok { - p.deleteDomain(domain) // delete old domain - } - fs := newFileSystem(path, data) - for locale, _ := range fs.LocaleMap { - trMapKey := p.makeTrMapKey(domain, locale) - if data, err := fs.LoadMessagesFile(domain, locale, ".mo"); err == nil { - p.trTextMap[trMapKey], _ = newMoTranslator( - fmt.Sprintf("%s_%s.mo", domain, locale), - data, - ) - continue - } - if data, err := fs.LoadMessagesFile(domain, locale, ".po"); err == nil { - p.trTextMap[trMapKey], _ = newPoTranslator( - fmt.Sprintf("%s_%s.po", domain, locale), - data, - ) - continue - } - p.trTextMap[p.makeTrMapKey(domain, locale)] = nilTranslator - } - p.domainMap[domain] = fs -} - -func (p *domainManager) deleteDomain(domain string) { - if _, ok := p.domainMap[domain]; !ok { - return - } - // delete all mo files - trMapKeyPrefix := p.makeTrMapKey(domain, "") - for k, _ := range p.trTextMap { - if strings.HasPrefix(k, trMapKeyPrefix) { - delete(p.trTextMap, k) - } - } - delete(p.domainMap, domain) -} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/fs.go b/vendor/github.com/chai2010/gettext-go/gettext/fs.go deleted file mode 100644 index 1c2e23c1d0..0000000000 --- a/vendor/github.com/chai2010/gettext-go/gettext/fs.go +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright 2013 ChaiShushan . All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gettext - -import ( - "archive/zip" - "bytes" - "fmt" - "io/ioutil" - "log" - "os" - "strings" -) - -type fileSystem struct { - FsName string - FsRoot string - FsZipData []byte - LocaleMap map[string]bool -} - -func newFileSystem(path string, data []byte) *fileSystem { - fs := &fileSystem{ - FsName: path, - FsZipData: data, - } - if err := fs.init(); err != nil { - log.Printf("gettext-go: invalid domain, err = %v", err) - } - return fs -} - -func (p *fileSystem) init() error { - zipName := func(name string) string { - if x := strings.LastIndexAny(name, `\/`); x != -1 { - name = name[x+1:] - } - name = strings.TrimSuffix(name, ".zip") - return name - } - - // zip data - if len(p.FsZipData) != 0 { - p.FsRoot = zipName(p.FsName) - p.LocaleMap = p.lsZip(p.FsZipData) - return nil - } - - // local dir or zip file - fi, err := os.Stat(p.FsName) - if err != nil { - return err - } - - // local dir - if fi.IsDir() { - p.FsRoot = p.FsName - p.LocaleMap = p.lsDir(p.FsName) - return nil - } - - // local zip file - p.FsZipData, err = ioutil.ReadFile(p.FsName) - if err != nil { - return err - } - p.FsRoot = zipName(p.FsName) - p.LocaleMap = p.lsZip(p.FsZipData) - return nil -} - -func (p *fileSystem) LoadMessagesFile(domain, local, ext string) ([]byte, error) { - if len(p.FsZipData) == 0 { - trName := p.makeMessagesFileName(domain, local, ext) - rcData, err := ioutil.ReadFile(trName) - if err != nil { - return nil, err - } - return rcData, nil - } else { - r, err := zip.NewReader(bytes.NewReader(p.FsZipData), int64(len(p.FsZipData))) - if err != nil { - return nil, err - } - - trName := p.makeMessagesFileName(domain, local, ext) - for _, f := range r.File { - if f.Name != trName { - continue - } - rc, err := f.Open() - if err != nil { - return nil, err - } - rcData, err := ioutil.ReadAll(rc) - rc.Close() - return rcData, err - } - return nil, fmt.Errorf("not found") - } -} - -func (p *fileSystem) LoadResourceFile(domain, local, name string) ([]byte, error) { - if len(p.FsZipData) == 0 { - rcName := p.makeResourceFileName(domain, local, name) - rcData, err := ioutil.ReadFile(rcName) - if err != nil { - return nil, err - } - return rcData, nil - } else { - r, err := zip.NewReader(bytes.NewReader(p.FsZipData), int64(len(p.FsZipData))) - if err != nil { - return nil, err - } - - rcName := p.makeResourceFileName(domain, local, name) - for _, f := range r.File { - if f.Name != rcName { - continue - } - rc, err := f.Open() - if err != nil { - return nil, err - } - rcData, err := ioutil.ReadAll(rc) - rc.Close() - return rcData, err - } - return nil, fmt.Errorf("not found") - } -} - -func (p *fileSystem) makeMessagesFileName(domain, local, ext string) string { - return fmt.Sprintf("%s/%s/LC_MESSAGES/%s%s", p.FsRoot, local, domain, ext) -} - -func (p *fileSystem) makeResourceFileName(domain, local, name string) string { - return fmt.Sprintf("%s/%s/LC_RESOURCE/%s/%s", p.FsRoot, local, domain, name) -} - -func (p *fileSystem) lsZip(data []byte) map[string]bool { - r, err := zip.NewReader(bytes.NewReader(data), int64(len(data))) - if err != nil { - return nil - } - ssMap := make(map[string]bool) - for _, f := range r.File { - if x := strings.Index(f.Name, "LC_MESSAGES"); x != -1 { - s := strings.TrimRight(f.Name[:x], `\/`) - if x = strings.LastIndexAny(s, `\/`); x != -1 { - s = s[x+1:] - } - if s != "" { - ssMap[s] = true - } - continue - } - if x := strings.Index(f.Name, "LC_RESOURCE"); x != -1 { - s := strings.TrimRight(f.Name[:x], `\/`) - if x = strings.LastIndexAny(s, `\/`); x != -1 { - s = s[x+1:] - } - if s != "" { - ssMap[s] = true - } - continue - } - } - return ssMap -} - -func (p *fileSystem) lsDir(path string) map[string]bool { - list, err := ioutil.ReadDir(path) - if err != nil { - return nil - } - ssMap := make(map[string]bool) - for _, dir := range list { - if dir.IsDir() { - ssMap[dir.Name()] = true - } - } - return ssMap -} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/gettext.go b/vendor/github.com/chai2010/gettext-go/gettext/gettext.go deleted file mode 100644 index ca14065b22..0000000000 --- a/vendor/github.com/chai2010/gettext-go/gettext/gettext.go +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright 2013 ChaiShushan . All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gettext - -var ( - defaultManager = newDomainManager() -) - -var ( - DefaultLocale = getDefaultLocale() // use $(LC_MESSAGES) or $(LANG) or "default" -) - -// SetLocale sets and queries the program's current locale. -// -// If the locale is not empty string, set the new local. -// -// If the locale is empty string, don't change anything. -// -// Returns is the current locale. -// -// Examples: -// SetLocale("") // get locale: return DefaultLocale -// SetLocale("zh_CN") // set locale: return zh_CN -// SetLocale("") // get locale: return zh_CN -func SetLocale(locale string) string { - return defaultManager.SetLocale(locale) -} - -// BindTextdomain sets and queries program's domains. -// -// If the domain and path are all not empty string, bind the new domain. -// If the domain already exists, return error. -// -// If the domain is not empty string, but the path is the empty string, -// delete the domain. -// If the domain don't exists, return error. -// -// If the domain and the path are all empty string, don't change anything. -// -// Returns is the all bind domains. -// -// Examples: -// BindTextdomain("poedit", "local", nil) // bind "poedit" domain -// BindTextdomain("", "", nil) // return all domains -// BindTextdomain("poedit", "", nil) // delete "poedit" domain -// BindTextdomain("", "", nil) // return all domains -// -// Use zip file: -// BindTextdomain("poedit", "local.zip", nil) // bind "poedit" domain -// BindTextdomain("poedit", "local.zip", zipData) // bind "poedit" domain -// -func BindTextdomain(domain, path string, zipData []byte) (domains, paths []string) { - return defaultManager.Bind(domain, path, zipData) -} - -// Textdomain sets and retrieves the current message domain. -// -// If the domain is not empty string, set the new domains. -// -// If the domain is empty string, don't change anything. -// -// Returns is the all used domains. -// -// Examples: -// Textdomain("poedit") // set domain: poedit -// Textdomain("") // get domain: return poedit -func Textdomain(domain string) string { - return defaultManager.SetDomain(domain) -} - -// Gettext attempt to translate a text string into the user's native language, -// by looking up the translation in a message catalog. -// -// It use the caller's function name as the msgctxt. -// -// Examples: -// func Foo() { -// msg := gettext.Gettext("Hello") // msgctxt is "some/package/name.Foo" -// } -func Gettext(msgid string) string { - return PGettext(callerName(2), msgid) -} - -// Getdata attempt to translate a resource file into the user's native language, -// by looking up the translation in a message catalog. -// -// Examples: -// func Foo() { -// Textdomain("hello") -// BindTextdomain("hello", "local.zip", nilOrZipData) -// poems := gettext.Getdata("poems.txt") -// } -func Getdata(name string) []byte { - return defaultManager.Getdata(name) -} - -// NGettext attempt to translate a text string into the user's native language, -// by looking up the appropriate plural form of the translation in a message -// catalog. -// -// It use the caller's function name as the msgctxt. -// -// Examples: -// func Foo() { -// msg := gettext.NGettext("%d people", "%d peoples", 2) -// } -func NGettext(msgid, msgidPlural string, n int) string { - return PNGettext(callerName(2), msgid, msgidPlural, n) -} - -// PGettext attempt to translate a text string into the user's native language, -// by looking up the translation in a message catalog. -// -// Examples: -// func Foo() { -// msg := gettext.PGettext("gettext-go.example", "Hello") // msgctxt is "gettext-go.example" -// } -func PGettext(msgctxt, msgid string) string { - return PNGettext(msgctxt, msgid, "", 0) -} - -// PNGettext attempt to translate a text string into the user's native language, -// by looking up the appropriate plural form of the translation in a message -// catalog. -// -// Examples: -// func Foo() { -// msg := gettext.PNGettext("gettext-go.example", "%d people", "%d peoples", 2) -// } -func PNGettext(msgctxt, msgid, msgidPlural string, n int) string { - return defaultManager.PNGettext(msgctxt, msgid, msgidPlural, n) -} - -// DGettext like Gettext(), but looking up the message in the specified domain. -// -// Examples: -// func Foo() { -// msg := gettext.DGettext("poedit", "Hello") -// } -func DGettext(domain, msgid string) string { - return DPGettext(domain, callerName(2), msgid) -} - -// DNGettext like NGettext(), but looking up the message in the specified domain. -// -// Examples: -// func Foo() { -// msg := gettext.PNGettext("poedit", "gettext-go.example", "%d people", "%d peoples", 2) -// } -func DNGettext(domain, msgid, msgidPlural string, n int) string { - return DPNGettext(domain, callerName(2), msgid, msgidPlural, n) -} - -// DPGettext like PGettext(), but looking up the message in the specified domain. -// -// Examples: -// func Foo() { -// msg := gettext.DPGettext("poedit", "gettext-go.example", "Hello") -// } -func DPGettext(domain, msgctxt, msgid string) string { - return DPNGettext(domain, msgctxt, msgid, "", 0) -} - -// DPNGettext like PNGettext(), but looking up the message in the specified domain. -// -// Examples: -// func Foo() { -// msg := gettext.DPNGettext("poedit", "gettext-go.example", "%d people", "%d peoples", 2) -// } -func DPNGettext(domain, msgctxt, msgid, msgidPlural string, n int) string { - return defaultManager.DPNGettext(domain, msgctxt, msgid, msgidPlural, n) -} - -// DGetdata like Getdata(), but looking up the resource in the specified domain. -// -// Examples: -// func Foo() { -// msg := gettext.DGetdata("hello", "poems.txt") -// } -func DGetdata(domain, name string) []byte { - return defaultManager.DGetdata(domain, name) -} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/local.go b/vendor/github.com/chai2010/gettext-go/gettext/local.go deleted file mode 100644 index 179a392fe2..0000000000 --- a/vendor/github.com/chai2010/gettext-go/gettext/local.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2013 ChaiShushan . All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gettext - -import ( - "os" - "strings" -) - -func getDefaultLocale() string { - if v := os.Getenv("LC_MESSAGES"); v != "" { - return simplifiedLocale(v) - } - if v := os.Getenv("LANG"); v != "" { - return simplifiedLocale(v) - } - return "default" -} - -func simplifiedLocale(lang string) string { - // en_US/en_US.UTF-8/zh_CN/zh_TW/el_GR@euro/... - if idx := strings.Index(lang, ":"); idx != -1 { - lang = lang[:idx] - } - if idx := strings.Index(lang, "@"); idx != -1 { - lang = lang[:idx] - } - if idx := strings.Index(lang, "."); idx != -1 { - lang = lang[:idx] - } - return strings.TrimSpace(lang) -} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/mo/doc.go b/vendor/github.com/chai2010/gettext-go/gettext/mo/doc.go deleted file mode 100644 index 9677680631..0000000000 --- a/vendor/github.com/chai2010/gettext-go/gettext/mo/doc.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2013 ChaiShushan . All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* -Package mo provides support for reading and writing GNU MO file. - -Examples: - import ( - "github.com/chai2010/gettext-go/gettext/mo" - ) - - func main() { - moFile, err := mo.Load("test.mo") - if err != nil { - log.Fatal(err) - } - fmt.Printf("%v", moFile) - } - -GNU MO file struct: - - byte - +------------------------------------------+ - 0 | magic number = 0x950412de | - | | - 4 | file format revision = 0 | - | | - 8 | number of strings | == N - | | - 12 | offset of table with original strings | == O - | | - 16 | offset of table with translation strings | == T - | | - 20 | size of hashing table | == S - | | - 24 | offset of hashing table | == H - | | - . . - . (possibly more entries later) . - . . - | | - O | length & offset 0th string ----------------. - O + 8 | length & offset 1st string ------------------. - ... ... | | - O + ((N-1)*8)| length & offset (N-1)th string | | | - | | | | - T | length & offset 0th translation ---------------. - T + 8 | length & offset 1st translation -----------------. - ... ... | | | | - T + ((N-1)*8)| length & offset (N-1)th translation | | | | | - | | | | | | - H | start hash table | | | | | - ... ... | | | | - H + S * 4 | end hash table | | | | | - | | | | | | - | NUL terminated 0th string <----------------' | | | - | | | | | - | NUL terminated 1st string <------------------' | | - | | | | - ... ... | | - | | | | - | NUL terminated 0th translation <---------------' | - | | | - | NUL terminated 1st translation <-----------------' - | | - ... ... - | | - +------------------------------------------+ - -The GNU MO file specification is at -http://www.gnu.org/software/gettext/manual/html_node/MO-Files.html. -*/ -package mo diff --git a/vendor/github.com/chai2010/gettext-go/gettext/mo/encoder.go b/vendor/github.com/chai2010/gettext-go/gettext/mo/encoder.go deleted file mode 100644 index 9b1c240b4f..0000000000 --- a/vendor/github.com/chai2010/gettext-go/gettext/mo/encoder.go +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright 2013 ChaiShushan . All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package mo - -import ( - "bytes" - "encoding/binary" - "sort" - "strings" -) - -type moHeader struct { - MagicNumber uint32 - MajorVersion uint16 - MinorVersion uint16 - MsgIdCount uint32 - MsgIdOffset uint32 - MsgStrOffset uint32 - HashSize uint32 - HashOffset uint32 -} - -type moStrPos struct { - Size uint32 // must keep fields order - Addr uint32 -} - -func encodeFile(f *File) []byte { - hdr := &moHeader{ - MagicNumber: MoMagicLittleEndian, - } - data := encodeData(hdr, f) - data = append(encodeHeader(hdr), data...) - return data -} - -// encode data and init moHeader -func encodeData(hdr *moHeader, f *File) []byte { - msgList := []Message{f.MimeHeader.toMessage()} - for _, v := range f.Messages { - if len(v.MsgId) == 0 { - continue - } - if len(v.MsgStr) == 0 && len(v.MsgStrPlural) == 0 { - continue - } - msgList = append(msgList, v) - } - sort.Sort(byMessages(msgList)) - - var buf bytes.Buffer - var msgIdPosList = make([]moStrPos, len(msgList)) - var msgStrPosList = make([]moStrPos, len(msgList)) - for i, v := range msgList { - // write msgid - msgId := encodeMsgId(v) - msgIdPosList[i].Addr = uint32(buf.Len() + MoHeaderSize) - msgIdPosList[i].Size = uint32(len(msgId)) - buf.WriteString(msgId) - // write msgstr - msgStr := encodeMsgStr(v) - msgStrPosList[i].Addr = uint32(buf.Len() + MoHeaderSize) - msgStrPosList[i].Size = uint32(len(msgStr)) - buf.WriteString(msgStr) - } - - hdr.MsgIdOffset = uint32(buf.Len() + MoHeaderSize) - binary.Write(&buf, binary.LittleEndian, msgIdPosList) - hdr.MsgStrOffset = uint32(buf.Len() + MoHeaderSize) - binary.Write(&buf, binary.LittleEndian, msgStrPosList) - - hdr.MsgIdCount = uint32(len(msgList)) - return buf.Bytes() -} - -// must called after encodeData -func encodeHeader(hdr *moHeader) []byte { - var buf bytes.Buffer - binary.Write(&buf, binary.LittleEndian, hdr) - return buf.Bytes() -} - -func encodeMsgId(v Message) string { - if v.MsgContext != "" && v.MsgIdPlural != "" { - return v.MsgContext + EotSeparator + v.MsgId + NulSeparator + v.MsgIdPlural - } - if v.MsgContext != "" && v.MsgIdPlural == "" { - return v.MsgContext + EotSeparator + v.MsgId - } - if v.MsgContext == "" && v.MsgIdPlural != "" { - return v.MsgId + NulSeparator + v.MsgIdPlural - } - return v.MsgId -} - -func encodeMsgStr(v Message) string { - if v.MsgIdPlural != "" { - return strings.Join(v.MsgStrPlural, NulSeparator) - } - return v.MsgStr -} - -type byMessages []Message - -func (d byMessages) Len() int { - return len(d) -} -func (d byMessages) Less(i, j int) bool { - if a, b := d[i].MsgContext, d[j].MsgContext; a != b { - return a < b - } - if a, b := d[i].MsgId, d[j].MsgId; a != b { - return a < b - } - if a, b := d[i].MsgIdPlural, d[j].MsgIdPlural; a != b { - return a < b - } - return false -} -func (d byMessages) Swap(i, j int) { - d[i], d[j] = d[j], d[i] -} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/mo/file.go b/vendor/github.com/chai2010/gettext-go/gettext/mo/file.go deleted file mode 100644 index b49a77b42a..0000000000 --- a/vendor/github.com/chai2010/gettext-go/gettext/mo/file.go +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright 2013 ChaiShushan . All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package mo - -import ( - "bytes" - "encoding/binary" - "fmt" - "io/ioutil" - "strings" -) - -const ( - MoHeaderSize = 28 - MoMagicLittleEndian = 0x950412de - MoMagicBigEndian = 0xde120495 - - EotSeparator = "\x04" // msgctxt and msgid separator - NulSeparator = "\x00" // msgid and msgstr separator -) - -// File represents an MO File. -// -// See http://www.gnu.org/software/gettext/manual/html_node/MO-Files.html -type File struct { - MagicNumber uint32 - MajorVersion uint16 - MinorVersion uint16 - MsgIdCount uint32 - MsgIdOffset uint32 - MsgStrOffset uint32 - HashSize uint32 - HashOffset uint32 - MimeHeader Header - Messages []Message -} - -// Load loads a named mo file. -func Load(name string) (*File, error) { - data, err := ioutil.ReadFile(name) - if err != nil { - return nil, err - } - return LoadData(data) -} - -// LoadData loads mo file format data. -func LoadData(data []byte) (*File, error) { - r := bytes.NewReader(data) - - var magicNumber uint32 - if err := binary.Read(r, binary.LittleEndian, &magicNumber); err != nil { - return nil, fmt.Errorf("gettext: %v", err) - } - var bo binary.ByteOrder - switch magicNumber { - case MoMagicLittleEndian: - bo = binary.LittleEndian - case MoMagicBigEndian: - bo = binary.BigEndian - default: - return nil, fmt.Errorf("gettext: %v", "invalid magic number") - } - - var header struct { - MajorVersion uint16 - MinorVersion uint16 - MsgIdCount uint32 - MsgIdOffset uint32 - MsgStrOffset uint32 - HashSize uint32 - HashOffset uint32 - } - if err := binary.Read(r, bo, &header); err != nil { - return nil, fmt.Errorf("gettext: %v", err) - } - if v := header.MajorVersion; v != 0 && v != 1 { - return nil, fmt.Errorf("gettext: %v", "invalid version number") - } - if v := header.MinorVersion; v != 0 && v != 1 { - return nil, fmt.Errorf("gettext: %v", "invalid version number") - } - - msgIdStart := make([]uint32, header.MsgIdCount) - msgIdLen := make([]uint32, header.MsgIdCount) - if _, err := r.Seek(int64(header.MsgIdOffset), 0); err != nil { - return nil, fmt.Errorf("gettext: %v", err) - } - for i := 0; i < int(header.MsgIdCount); i++ { - if err := binary.Read(r, bo, &msgIdLen[i]); err != nil { - return nil, fmt.Errorf("gettext: %v", err) - } - if err := binary.Read(r, bo, &msgIdStart[i]); err != nil { - return nil, fmt.Errorf("gettext: %v", err) - } - } - - msgStrStart := make([]int32, header.MsgIdCount) - msgStrLen := make([]int32, header.MsgIdCount) - if _, err := r.Seek(int64(header.MsgStrOffset), 0); err != nil { - return nil, fmt.Errorf("gettext: %v", err) - } - for i := 0; i < int(header.MsgIdCount); i++ { - if err := binary.Read(r, bo, &msgStrLen[i]); err != nil { - return nil, fmt.Errorf("gettext: %v", err) - } - if err := binary.Read(r, bo, &msgStrStart[i]); err != nil { - return nil, fmt.Errorf("gettext: %v", err) - } - } - - file := &File{ - MagicNumber: magicNumber, - MajorVersion: header.MajorVersion, - MinorVersion: header.MinorVersion, - MsgIdCount: header.MsgIdCount, - MsgIdOffset: header.MsgIdOffset, - MsgStrOffset: header.MsgStrOffset, - HashSize: header.HashSize, - HashOffset: header.HashOffset, - } - for i := 0; i < int(header.MsgIdCount); i++ { - if _, err := r.Seek(int64(msgIdStart[i]), 0); err != nil { - return nil, fmt.Errorf("gettext: %v", err) - } - msgIdData := make([]byte, msgIdLen[i]) - if _, err := r.Read(msgIdData); err != nil { - return nil, fmt.Errorf("gettext: %v", err) - } - - if _, err := r.Seek(int64(msgStrStart[i]), 0); err != nil { - return nil, fmt.Errorf("gettext: %v", err) - } - msgStrData := make([]byte, msgStrLen[i]) - if _, err := r.Read(msgStrData); err != nil { - return nil, fmt.Errorf("gettext: %v", err) - } - - if len(msgIdData) == 0 { - var msg = Message{ - MsgId: string(msgIdData), - MsgStr: string(msgStrData), - } - file.MimeHeader.fromMessage(&msg) - } else { - var msg = Message{ - MsgId: string(msgIdData), - MsgStr: string(msgStrData), - } - // Is this a context message? - if idx := strings.Index(msg.MsgId, EotSeparator); idx != -1 { - msg.MsgContext, msg.MsgId = msg.MsgId[:idx], msg.MsgId[idx+1:] - } - // Is this a plural message? - if idx := strings.Index(msg.MsgId, NulSeparator); idx != -1 { - msg.MsgId, msg.MsgIdPlural = msg.MsgId[:idx], msg.MsgId[idx+1:] - msg.MsgStrPlural = strings.Split(msg.MsgStr, NulSeparator) - msg.MsgStr = "" - } - file.Messages = append(file.Messages, msg) - } - } - - return file, nil -} - -// Save saves a mo file. -func (f *File) Save(name string) error { - return ioutil.WriteFile(name, f.Data(), 0666) -} - -// Save returns a mo file format data. -func (f *File) Data() []byte { - return encodeFile(f) -} - -// String returns the po format file string. -func (f *File) String() string { - var buf bytes.Buffer - fmt.Fprintf(&buf, "# version: %d.%d\n", f.MajorVersion, f.MinorVersion) - fmt.Fprintf(&buf, "%s\n", f.MimeHeader.String()) - fmt.Fprintf(&buf, "\n") - - for k, v := range f.Messages { - fmt.Fprintf(&buf, `msgid "%v"`+"\n", k) - fmt.Fprintf(&buf, `msgstr "%s"`+"\n", v.MsgStr) - fmt.Fprintf(&buf, "\n") - } - - return buf.String() -} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/mo/message.go b/vendor/github.com/chai2010/gettext-go/gettext/mo/message.go deleted file mode 100644 index 91ad79bece..0000000000 --- a/vendor/github.com/chai2010/gettext-go/gettext/mo/message.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2013 ChaiShushan . All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package mo - -import ( - "bytes" - "fmt" -) - -// A MO file is made up of many entries, -// each entry holding the relation between an original untranslated string -// and its corresponding translation. -// -// See http://www.gnu.org/software/gettext/manual/html_node/MO-Files.html -type Message struct { - MsgContext string // msgctxt context - MsgId string // msgid untranslated-string - MsgIdPlural string // msgid_plural untranslated-string-plural - MsgStr string // msgstr translated-string - MsgStrPlural []string // msgstr[0] translated-string-case-0 -} - -// String returns the po format entry string. -func (p Message) String() string { - var buf bytes.Buffer - fmt.Fprintf(&buf, "msgid %s", encodePoString(p.MsgId)) - if p.MsgIdPlural != "" { - fmt.Fprintf(&buf, "msgid_plural %s", encodePoString(p.MsgIdPlural)) - } - if p.MsgStr != "" { - fmt.Fprintf(&buf, "msgstr %s", encodePoString(p.MsgStr)) - } - for i := 0; i < len(p.MsgStrPlural); i++ { - fmt.Fprintf(&buf, "msgstr[%d] %s", i, encodePoString(p.MsgStrPlural[i])) - } - return buf.String() -} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/plural/doc.go b/vendor/github.com/chai2010/gettext-go/gettext/plural/doc.go deleted file mode 100644 index 5641e2c3e7..0000000000 --- a/vendor/github.com/chai2010/gettext-go/gettext/plural/doc.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2013 ChaiShushan . All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* -Package plural provides standard plural formulas. - -Examples: - import ( - "code.google.com/p/gettext-go/gettext/plural" - ) - - func main() { - enFormula := plural.Formula("en_US") - xxFormula := plural.Formula("zh_CN") - - fmt.Printf("%s: %d\n", "en", enFormula(0)) - fmt.Printf("%s: %d\n", "en", enFormula(1)) - fmt.Printf("%s: %d\n", "en", enFormula(2)) - fmt.Printf("%s: %d\n", "??", xxFormula(0)) - fmt.Printf("%s: %d\n", "??", xxFormula(1)) - fmt.Printf("%s: %d\n", "??", xxFormula(2)) - fmt.Printf("%s: %d\n", "??", xxFormula(9)) - // Output: - // en: 0 - // en: 0 - // en: 1 - // ??: 0 - // ??: 0 - // ??: 1 - // ??: 8 - } - -See http://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html -*/ -package plural diff --git a/vendor/github.com/chai2010/gettext-go/gettext/po/doc.go b/vendor/github.com/chai2010/gettext-go/gettext/po/doc.go deleted file mode 100644 index 12bac8f2a2..0000000000 --- a/vendor/github.com/chai2010/gettext-go/gettext/po/doc.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2013 ChaiShushan . All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* -Package po provides support for reading and writing GNU PO file. - -Examples: - import ( - "github.com/chai2010/gettext-go/gettext/po" - ) - - func main() { - poFile, err := po.Load("test.po") - if err != nil { - log.Fatal(err) - } - fmt.Printf("%v", poFile) - } - -The GNU PO file specification is at -http://www.gnu.org/software/gettext/manual/html_node/PO-Files.html. -*/ -package po diff --git a/vendor/github.com/chai2010/gettext-go/gettext/po/file.go b/vendor/github.com/chai2010/gettext-go/gettext/po/file.go deleted file mode 100644 index a9b7abf949..0000000000 --- a/vendor/github.com/chai2010/gettext-go/gettext/po/file.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2013 ChaiShushan . All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package po - -import ( - "bytes" - "fmt" - "io" - "io/ioutil" - "sort" -) - -// File represents an PO File. -// -// See http://www.gnu.org/software/gettext/manual/html_node/PO-Files.html -type File struct { - MimeHeader Header - Messages []Message -} - -// Load loads a named po file. -func Load(name string) (*File, error) { - data, err := ioutil.ReadFile(name) - if err != nil { - return nil, err - } - return LoadData(data) -} - -// LoadData loads po file format data. -func LoadData(data []byte) (*File, error) { - r := newLineReader(string(data)) - var file File - for { - var msg Message - if err := msg.readPoEntry(r); err != nil { - if err == io.EOF { - return &file, nil - } - return nil, err - } - if msg.MsgId == "" { - file.MimeHeader.parseHeader(&msg) - continue - } - file.Messages = append(file.Messages, msg) - } -} - -// Save saves a po file. -func (f *File) Save(name string) error { - return ioutil.WriteFile(name, []byte(f.String()), 0666) -} - -// Save returns a po file format data. -func (f *File) Data() []byte { - // sort the massge as ReferenceFile/ReferenceLine field - var messages []Message - messages = append(messages, f.Messages...) - sort.Sort(byMessages(messages)) - - var buf bytes.Buffer - fmt.Fprintf(&buf, "%s\n", f.MimeHeader.String()) - for i := 0; i < len(messages); i++ { - fmt.Fprintf(&buf, "%s\n", messages[i].String()) - } - return buf.Bytes() -} - -// String returns the po format file string. -func (f *File) String() string { - return string(f.Data()) -} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/po/message.go b/vendor/github.com/chai2010/gettext-go/gettext/po/message.go deleted file mode 100644 index a2cf2512c7..0000000000 --- a/vendor/github.com/chai2010/gettext-go/gettext/po/message.go +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright 2013 ChaiShushan . All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package po - -import ( - "bytes" - "fmt" - "io" - "strconv" - "strings" -) - -// A PO file is made up of many entries, -// each entry holding the relation between an original untranslated string -// and its corresponding translation. -// -// See http://www.gnu.org/software/gettext/manual/html_node/PO-Files.html -type Message struct { - Comment // Coments - MsgContext string // msgctxt context - MsgId string // msgid untranslated-string - MsgIdPlural string // msgid_plural untranslated-string-plural - MsgStr string // msgstr translated-string - MsgStrPlural []string // msgstr[0] translated-string-case-0 -} - -type byMessages []Message - -func (d byMessages) Len() int { - return len(d) -} -func (d byMessages) Less(i, j int) bool { - if d[i].Comment.less(&d[j].Comment) { - return true - } - if a, b := d[i].MsgContext, d[j].MsgContext; a != b { - return a < b - } - if a, b := d[i].MsgId, d[j].MsgId; a != b { - return a < b - } - if a, b := d[i].MsgIdPlural, d[j].MsgIdPlural; a != b { - return a < b - } - return false -} -func (d byMessages) Swap(i, j int) { - d[i], d[j] = d[j], d[i] -} - -func (p *Message) readPoEntry(r *lineReader) (err error) { - *p = Message{} - if err = r.skipBlankLine(); err != nil { - return - } - defer func(oldPos int) { - newPos := r.currentPos() - if newPos != oldPos && err == io.EOF { - err = nil - } - }(r.currentPos()) - - if err = p.Comment.readPoComment(r); err != nil { - return - } - for { - var s string - if s, _, err = r.currentLine(); err != nil { - return - } - - if p.isInvalidLine(s) { - err = fmt.Errorf("gettext: line %d, %v", r.currentPos(), "invalid line") - return - } - if reComment.MatchString(s) || reBlankLine.MatchString(s) { - return - } - - if err = p.readMsgContext(r); err != nil { - return - } - if err = p.readMsgId(r); err != nil { - return - } - if err = p.readMsgIdPlural(r); err != nil { - return - } - if err = p.readMsgStrOrPlural(r); err != nil { - return - } - } -} - -func (p *Message) readMsgContext(r *lineReader) (err error) { - var s string - if s, _, err = r.currentLine(); err != nil { - return - } - if !reMsgContext.MatchString(s) { - return - } - p.MsgContext, err = p.readString(r) - return -} - -func (p *Message) readMsgId(r *lineReader) (err error) { - var s string - if s, _, err = r.currentLine(); err != nil { - return - } - if !reMsgId.MatchString(s) { - return - } - p.MsgId, err = p.readString(r) - return -} - -func (p *Message) readMsgIdPlural(r *lineReader) (err error) { - var s string - if s, _, err = r.currentLine(); err != nil { - return - } - if !reMsgIdPlural.MatchString(s) { - return - } - p.MsgIdPlural, err = p.readString(r) - return nil -} - -func (p *Message) readMsgStrOrPlural(r *lineReader) (err error) { - var s string - if s, _, err = r.currentLine(); err != nil { - return - } - if !reMsgStr.MatchString(s) && !reMsgStrPlural.MatchString(s) { - return - } - if reMsgStrPlural.MatchString(s) { - left, right := strings.Index(s, `[`), strings.LastIndex(s, `]`) - idx, _ := strconv.Atoi(s[left+1 : right]) - s, err = p.readString(r) - if n := len(p.MsgStrPlural); (idx + 1) > n { - p.MsgStrPlural = append(p.MsgStrPlural, make([]string, (idx+1)-n)...) - } - p.MsgStrPlural[idx] = s - } else { - p.MsgStr, err = p.readString(r) - } - return nil -} - -func (p *Message) readString(r *lineReader) (msg string, err error) { - var s string - if s, _, err = r.readLine(); err != nil { - return - } - msg += decodePoString(s) - for { - if s, _, err = r.readLine(); err != nil { - return - } - if !reStringLine.MatchString(s) { - r.unreadLine() - break - } - msg += decodePoString(s) - } - return -} - -// String returns the po format entry string. -func (p Message) String() string { - var buf bytes.Buffer - fmt.Fprintf(&buf, "%s", p.Comment.String()) - fmt.Fprintf(&buf, "msgid %s", encodePoString(p.MsgId)) - if p.MsgIdPlural != "" { - fmt.Fprintf(&buf, "msgid_plural %s", encodePoString(p.MsgIdPlural)) - } - if p.MsgStr != "" { - fmt.Fprintf(&buf, "msgstr %s", encodePoString(p.MsgStr)) - } - for i := 0; i < len(p.MsgStrPlural); i++ { - fmt.Fprintf(&buf, "msgstr[%d] %s", i, encodePoString(p.MsgStrPlural[i])) - } - return buf.String() -} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/po/util.go b/vendor/github.com/chai2010/gettext-go/gettext/po/util.go deleted file mode 100644 index 52544832cf..0000000000 --- a/vendor/github.com/chai2010/gettext-go/gettext/po/util.go +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2013 ChaiShushan . All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package po - -import ( - "bytes" - "strings" -) - -func decodePoString(text string) string { - lines := strings.Split(text, "\n") - for i := 0; i < len(lines); i++ { - left := strings.Index(lines[i], `"`) - right := strings.LastIndex(lines[i], `"`) - if left < 0 || right < 0 || left == right { - lines[i] = "" - continue - } - line := lines[i][left+1 : right] - data := make([]byte, 0, len(line)) - for i := 0; i < len(line); i++ { - if line[i] != '\\' { - data = append(data, line[i]) - continue - } - if i+1 >= len(line) { - break - } - switch line[i+1] { - case 'n': // \\n -> \n - data = append(data, '\n') - i++ - case 't': // \\t -> \n - data = append(data, '\t') - i++ - case '\\': // \\\ -> ? - data = append(data, '\\') - i++ - } - } - lines[i] = string(data) - } - return strings.Join(lines, "") -} - -func encodePoString(text string) string { - var buf bytes.Buffer - lines := strings.Split(text, "\n") - for i := 0; i < len(lines); i++ { - if lines[i] == "" { - if i != len(lines)-1 { - buf.WriteString(`"\n"` + "\n") - } - continue - } - buf.WriteRune('"') - for _, r := range lines[i] { - switch r { - case '\\': - buf.WriteString(`\\`) - case '"': - buf.WriteString(`\"`) - case '\n': - buf.WriteString(`\n`) - case '\t': - buf.WriteString(`\t`) - default: - buf.WriteRune(r) - } - } - buf.WriteString(`\n"` + "\n") - } - return buf.String() -} - -func encodeCommentPoString(text string) string { - var buf bytes.Buffer - lines := strings.Split(text, "\n") - if len(lines) > 1 { - buf.WriteString(`""` + "\n") - } - for i := 0; i < len(lines); i++ { - if len(lines) > 0 { - buf.WriteString("#| ") - } - buf.WriteRune('"') - for _, r := range lines[i] { - switch r { - case '\\': - buf.WriteString(`\\`) - case '"': - buf.WriteString(`\"`) - case '\n': - buf.WriteString(`\n`) - case '\t': - buf.WriteString(`\t`) - default: - buf.WriteRune(r) - } - } - if i < len(lines)-1 { - buf.WriteString(`\n"` + "\n") - } else { - buf.WriteString(`"`) - } - } - return buf.String() -} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/tr.go b/vendor/github.com/chai2010/gettext-go/gettext/tr.go deleted file mode 100644 index fedfbc301d..0000000000 --- a/vendor/github.com/chai2010/gettext-go/gettext/tr.go +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright 2013 ChaiShushan . All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package gettext - -import ( - "github.com/chai2010/gettext-go/gettext/mo" - "github.com/chai2010/gettext-go/gettext/plural" - "github.com/chai2010/gettext-go/gettext/po" -) - -var nilTranslator = &translator{ - MessageMap: make(map[string]mo.Message), - PluralFormula: plural.Formula("??"), -} - -type translator struct { - MessageMap map[string]mo.Message - PluralFormula func(n int) int -} - -func newMoTranslator(name string, data []byte) (*translator, error) { - var ( - f *mo.File - err error - ) - if len(data) != 0 { - f, err = mo.LoadData(data) - } else { - f, err = mo.Load(name) - } - if err != nil { - return nil, err - } - var tr = &translator{ - MessageMap: make(map[string]mo.Message), - } - for _, v := range f.Messages { - tr.MessageMap[tr.makeMapKey(v.MsgContext, v.MsgId)] = v - } - if lang := f.MimeHeader.Language; lang != "" { - tr.PluralFormula = plural.Formula(lang) - } else { - tr.PluralFormula = plural.Formula("??") - } - return tr, nil -} - -func newPoTranslator(name string, data []byte) (*translator, error) { - var ( - f *po.File - err error - ) - if len(data) != 0 { - f, err = po.LoadData(data) - } else { - f, err = po.Load(name) - } - if err != nil { - return nil, err - } - var tr = &translator{ - MessageMap: make(map[string]mo.Message), - } - for _, v := range f.Messages { - tr.MessageMap[tr.makeMapKey(v.MsgContext, v.MsgId)] = mo.Message{ - MsgContext: v.MsgContext, - MsgId: v.MsgId, - MsgIdPlural: v.MsgIdPlural, - MsgStr: v.MsgStr, - MsgStrPlural: v.MsgStrPlural, - } - } - if lang := f.MimeHeader.Language; lang != "" { - tr.PluralFormula = plural.Formula(lang) - } else { - tr.PluralFormula = plural.Formula("??") - } - return tr, nil -} - -func (p *translator) PGettext(msgctxt, msgid string) string { - return p.PNGettext(msgctxt, msgid, "", 0) -} - -func (p *translator) PNGettext(msgctxt, msgid, msgidPlural string, n int) string { - n = p.PluralFormula(n) - if ss := p.findMsgStrPlural(msgctxt, msgid, msgidPlural); len(ss) != 0 { - if n >= len(ss) { - n = len(ss) - 1 - } - if ss[n] != "" { - return ss[n] - } - } - if msgidPlural != "" && n > 0 { - return msgidPlural - } - return msgid -} - -func (p *translator) findMsgStrPlural(msgctxt, msgid, msgidPlural string) []string { - key := p.makeMapKey(msgctxt, msgid) - if v, ok := p.MessageMap[key]; ok { - if len(v.MsgIdPlural) != 0 { - if len(v.MsgStrPlural) != 0 { - return v.MsgStrPlural - } else { - return nil - } - } else { - if len(v.MsgStr) != 0 { - return []string{v.MsgStr} - } else { - return nil - } - } - } - return nil -} - -func (p *translator) makeMapKey(msgctxt, msgid string) string { - if msgctxt != "" { - return msgctxt + mo.EotSeparator + msgid - } - return msgid -} diff --git a/vendor/github.com/chai2010/gettext-go/locale.go b/vendor/github.com/chai2010/gettext-go/locale.go new file mode 100644 index 0000000000..e7a2d4b37b --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/locale.go @@ -0,0 +1,205 @@ +// Copyright 2020 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gettext + +import ( + "fmt" + "sync" +) + +type _Locale struct { + mutex sync.Mutex + fs FileSystem + lang string + domain string + trMap map[string]*translator + trCurrent *translator +} + +var _ Gettexter = (*_Locale)(nil) + +func newLocale(domain, path string, data ...interface{}) *_Locale { + if domain == "" { + domain = "default" + } + p := &_Locale{ + lang: DefaultLanguage, + domain: domain, + } + if len(data) > 0 { + p.fs = NewFS(path, data[0]) + } else { + p.fs = NewFS(path, nil) + } + + p.syncTrMap() + return p +} + +func (p *_Locale) makeTrMapKey(domain, _Locale string) string { + return domain + "_$$$_" + _Locale +} + +func (p *_Locale) FileSystem() FileSystem { + return p.fs +} + +func (p *_Locale) GetLanguage() string { + p.mutex.Lock() + defer p.mutex.Unlock() + + return p.lang +} +func (p *_Locale) SetLanguage(lang string) Gettexter { + p.mutex.Lock() + defer p.mutex.Unlock() + + if lang == "" { + lang = DefaultLanguage + } + if lang == p.lang { + return p + } + + p.lang = lang + p.syncTrMap() + return p +} + +func (p *_Locale) GetDomain() string { + p.mutex.Lock() + defer p.mutex.Unlock() + return p.domain +} + +func (p *_Locale) SetDomain(domain string) Gettexter { + p.mutex.Lock() + defer p.mutex.Unlock() + + if domain == "" || domain == p.domain { + return p + } + + p.domain = domain + p.syncTrMap() + return p +} + +func (p *_Locale) syncTrMap() { + p.trMap = make(map[string]*translator) + trMapKey := p.makeTrMapKey(p.domain, p.lang) + + if tr, ok := p.trMap[trMapKey]; ok { + p.trCurrent = tr + return + } + + // try load po file + if data, err := p.fs.LoadMessagesFile(p.domain, p.lang, ".po"); err == nil { + if tr, err := newPoTranslator(fmt.Sprintf("%s_%s.po", p.domain, p.lang), data); err == nil { + p.trMap[trMapKey] = tr + p.trCurrent = tr + return + } + } + + // try load mo file + if data, err := p.fs.LoadMessagesFile(p.domain, p.lang, ".mo"); err == nil { + if tr, err := newMoTranslator(fmt.Sprintf("%s_%s.mo", p.domain, p.lang), data); err == nil { + p.trMap[trMapKey] = tr + p.trCurrent = tr + return + } + } + + // try load json file + if data, err := p.fs.LoadMessagesFile(p.domain, p.lang, ".json"); err == nil { + if tr, err := newJsonTranslator(p.lang, fmt.Sprintf("%s_%s.json", p.domain, p.lang), data); err == nil { + p.trMap[trMapKey] = tr + p.trCurrent = tr + return + } + } + + // no po/mo file + p.trMap[trMapKey] = nilTranslator + p.trCurrent = nilTranslator + return +} + +func (p *_Locale) Gettext(msgid string) string { + p.mutex.Lock() + defer p.mutex.Unlock() + return p.trCurrent.PGettext("", msgid) +} + +func (p *_Locale) PGettext(msgctxt, msgid string) string { + p.mutex.Lock() + defer p.mutex.Unlock() + return p.trCurrent.PGettext(msgctxt, msgid) +} + +func (p *_Locale) NGettext(msgid, msgidPlural string, n int) string { + p.mutex.Lock() + defer p.mutex.Unlock() + return p.trCurrent.PNGettext("", msgid, msgidPlural, n) +} + +func (p *_Locale) PNGettext(msgctxt, msgid, msgidPlural string, n int) string { + p.mutex.Lock() + defer p.mutex.Unlock() + return p.trCurrent.PNGettext(msgctxt, msgid, msgidPlural, n) +} + +func (p *_Locale) DGettext(domain, msgid string) string { + p.mutex.Lock() + defer p.mutex.Unlock() + return p.gettext(domain, "", msgid, "", 0) +} + +func (p *_Locale) DNGettext(domain, msgid, msgidPlural string, n int) string { + p.mutex.Lock() + defer p.mutex.Unlock() + return p.gettext(domain, "", msgid, msgidPlural, n) +} + +func (p *_Locale) DPGettext(domain, msgctxt, msgid string) string { + p.mutex.Lock() + defer p.mutex.Unlock() + return p.gettext(domain, msgctxt, msgid, "", 0) +} + +func (p *_Locale) DPNGettext(domain, msgctxt, msgid, msgidPlural string, n int) string { + p.mutex.Lock() + defer p.mutex.Unlock() + return p.gettext(domain, msgctxt, msgid, msgidPlural, n) +} + +func (p *_Locale) Getdata(name string) []byte { + return p.getdata(p.domain, name) +} + +func (p *_Locale) DGetdata(domain, name string) []byte { + return p.getdata(domain, name) +} + +func (p *_Locale) gettext(domain, msgctxt, msgid, msgidPlural string, n int) string { + if f, ok := p.trMap[p.makeTrMapKey(domain, p.lang)]; ok { + return f.PNGettext(msgctxt, msgid, msgidPlural, n) + } + return msgid +} + +func (p *_Locale) getdata(domain, name string) []byte { + if data, err := p.fs.LoadResourceFile(domain, p.lang, name); err == nil { + return data + } + if p.lang != "default" { + if data, err := p.fs.LoadResourceFile(domain, "default", name); err == nil { + return data + } + } + return nil +} diff --git a/vendor/github.com/chai2010/gettext-go/mo/doc.go b/vendor/github.com/chai2010/gettext-go/mo/doc.go new file mode 100644 index 0000000000..5fefc18930 --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/mo/doc.go @@ -0,0 +1,74 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package mo provides support for reading and writing GNU MO file. + +Examples: + import ( + "github.com/chai2010/gettext-go/mo" + ) + + func main() { + moFile, err := mo.LoadFile("test.mo") + if err != nil { + log.Fatal(err) + } + fmt.Printf("%v", moFile) + } + +GNU MO file struct: + + byte + +------------------------------------------+ + 0 | magic number = 0x950412de | + | | + 4 | file format revision = 0 | + | | + 8 | number of strings | == N + | | + 12 | offset of table with original strings | == O + | | + 16 | offset of table with translation strings | == T + | | + 20 | size of hashing table | == S + | | + 24 | offset of hashing table | == H + | | + . . + . (possibly more entries later) . + . . + | | + O | length & offset 0th string ----------------. + O + 8 | length & offset 1st string ------------------. + ... ... | | + O + ((N-1)*8)| length & offset (N-1)th string | | | + | | | | + T | length & offset 0th translation ---------------. + T + 8 | length & offset 1st translation -----------------. + ... ... | | | | + T + ((N-1)*8)| length & offset (N-1)th translation | | | | | + | | | | | | + H | start hash table | | | | | + ... ... | | | | + H + S * 4 | end hash table | | | | | + | | | | | | + | NUL terminated 0th string <----------------' | | | + | | | | | + | NUL terminated 1st string <------------------' | | + | | | | + ... ... | | + | | | | + | NUL terminated 0th translation <---------------' | + | | | + | NUL terminated 1st translation <-----------------' + | | + ... ... + | | + +------------------------------------------+ + +The GNU MO file specification is at +http://www.gnu.org/software/gettext/manual/html_node/MO-Files.html. +*/ +package mo diff --git a/vendor/github.com/chai2010/gettext-go/mo/encoder.go b/vendor/github.com/chai2010/gettext-go/mo/encoder.go new file mode 100644 index 0000000000..f953fd3cb8 --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/mo/encoder.go @@ -0,0 +1,105 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mo + +import ( + "bytes" + "encoding/binary" + "sort" + "strings" +) + +type moHeader struct { + MagicNumber uint32 + MajorVersion uint16 + MinorVersion uint16 + MsgIdCount uint32 + MsgIdOffset uint32 + MsgStrOffset uint32 + HashSize uint32 + HashOffset uint32 +} + +type moStrPos struct { + Size uint32 // must keep fields order + Addr uint32 +} + +func encodeFile(f *File) []byte { + hdr := &moHeader{ + MagicNumber: MoMagicLittleEndian, + } + data := encodeData(hdr, f) + data = append(encodeHeader(hdr), data...) + return data +} + +// encode data and init moHeader +func encodeData(hdr *moHeader, f *File) []byte { + msgList := []Message{f.MimeHeader.toMessage()} + for _, v := range f.Messages { + if len(v.MsgId) == 0 { + continue + } + if len(v.MsgStr) == 0 && len(v.MsgStrPlural) == 0 { + continue + } + msgList = append(msgList, v) + } + sort.Slice(msgList, func(i, j int) bool { + return msgList[i].less(&msgList[j]) + }) + + var buf bytes.Buffer + var msgIdPosList = make([]moStrPos, len(msgList)) + var msgStrPosList = make([]moStrPos, len(msgList)) + for i, v := range msgList { + // write msgid + msgId := encodeMsgId(v) + msgIdPosList[i].Addr = uint32(buf.Len() + MoHeaderSize) + msgIdPosList[i].Size = uint32(len(msgId)) + buf.WriteString(msgId) + // write msgstr + msgStr := encodeMsgStr(v) + msgStrPosList[i].Addr = uint32(buf.Len() + MoHeaderSize) + msgStrPosList[i].Size = uint32(len(msgStr)) + buf.WriteString(msgStr) + } + + hdr.MsgIdOffset = uint32(buf.Len() + MoHeaderSize) + binary.Write(&buf, binary.LittleEndian, msgIdPosList) + hdr.MsgStrOffset = uint32(buf.Len() + MoHeaderSize) + binary.Write(&buf, binary.LittleEndian, msgStrPosList) + + hdr.MsgIdCount = uint32(len(msgList)) + return buf.Bytes() +} + +// must called after encodeData +func encodeHeader(hdr *moHeader) []byte { + var buf bytes.Buffer + binary.Write(&buf, binary.LittleEndian, hdr) + return buf.Bytes() +} + +func encodeMsgId(v Message) string { + if v.MsgContext != "" && v.MsgIdPlural != "" { + return v.MsgContext + EotSeparator + v.MsgId + NulSeparator + v.MsgIdPlural + } + if v.MsgContext != "" && v.MsgIdPlural == "" { + return v.MsgContext + EotSeparator + v.MsgId + } + if v.MsgContext == "" && v.MsgIdPlural != "" { + return v.MsgId + NulSeparator + v.MsgIdPlural + } + return v.MsgId +} + +func encodeMsgStr(v Message) string { + if v.MsgIdPlural != "" { + return strings.Join(v.MsgStrPlural, NulSeparator) + } + return v.MsgStr +} diff --git a/vendor/github.com/chai2010/gettext-go/mo/file.go b/vendor/github.com/chai2010/gettext-go/mo/file.go new file mode 100644 index 0000000000..6f7ed161c1 --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/mo/file.go @@ -0,0 +1,197 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mo + +import ( + "bytes" + "encoding/binary" + "fmt" + "io/ioutil" + "strings" +) + +const ( + MoHeaderSize = 28 + MoMagicLittleEndian = 0x950412de + MoMagicBigEndian = 0xde120495 + + EotSeparator = "\x04" // msgctxt and msgid separator + NulSeparator = "\x00" // msgid and msgstr separator +) + +// File represents an MO File. +// +// See http://www.gnu.org/software/gettext/manual/html_node/MO-Files.html +type File struct { + MagicNumber uint32 + MajorVersion uint16 + MinorVersion uint16 + MsgIdCount uint32 + MsgIdOffset uint32 + MsgStrOffset uint32 + HashSize uint32 + HashOffset uint32 + MimeHeader Header + Messages []Message +} + +// Load loads mo file format data. +func Load(data []byte) (*File, error) { + return loadData(data) +} + +// Load loads a named mo file. +func LoadFile(path string) (*File, error) { + data, err := ioutil.ReadFile(path) + if err != nil { + return nil, err + } + return loadData(data) +} + +func loadData(data []byte) (*File, error) { + r := bytes.NewReader(data) + + var magicNumber uint32 + if err := binary.Read(r, binary.LittleEndian, &magicNumber); err != nil { + return nil, fmt.Errorf("gettext: %v", err) + } + var bo binary.ByteOrder + switch magicNumber { + case MoMagicLittleEndian: + bo = binary.LittleEndian + case MoMagicBigEndian: + bo = binary.BigEndian + default: + return nil, fmt.Errorf("gettext: %v", "invalid magic number") + } + + var header struct { + MajorVersion uint16 + MinorVersion uint16 + MsgIdCount uint32 + MsgIdOffset uint32 + MsgStrOffset uint32 + HashSize uint32 + HashOffset uint32 + } + if err := binary.Read(r, bo, &header); err != nil { + return nil, fmt.Errorf("gettext: %v", err) + } + if v := header.MajorVersion; v != 0 && v != 1 { + return nil, fmt.Errorf("gettext: %v", "invalid version number") + } + if v := header.MinorVersion; v != 0 && v != 1 { + return nil, fmt.Errorf("gettext: %v", "invalid version number") + } + + msgIdStart := make([]uint32, header.MsgIdCount) + msgIdLen := make([]uint32, header.MsgIdCount) + if _, err := r.Seek(int64(header.MsgIdOffset), 0); err != nil { + return nil, fmt.Errorf("gettext: %v", err) + } + for i := 0; i < int(header.MsgIdCount); i++ { + if err := binary.Read(r, bo, &msgIdLen[i]); err != nil { + return nil, fmt.Errorf("gettext: %v", err) + } + if err := binary.Read(r, bo, &msgIdStart[i]); err != nil { + return nil, fmt.Errorf("gettext: %v", err) + } + } + + msgStrStart := make([]int32, header.MsgIdCount) + msgStrLen := make([]int32, header.MsgIdCount) + if _, err := r.Seek(int64(header.MsgStrOffset), 0); err != nil { + return nil, fmt.Errorf("gettext: %v", err) + } + for i := 0; i < int(header.MsgIdCount); i++ { + if err := binary.Read(r, bo, &msgStrLen[i]); err != nil { + return nil, fmt.Errorf("gettext: %v", err) + } + if err := binary.Read(r, bo, &msgStrStart[i]); err != nil { + return nil, fmt.Errorf("gettext: %v", err) + } + } + + file := &File{ + MagicNumber: magicNumber, + MajorVersion: header.MajorVersion, + MinorVersion: header.MinorVersion, + MsgIdCount: header.MsgIdCount, + MsgIdOffset: header.MsgIdOffset, + MsgStrOffset: header.MsgStrOffset, + HashSize: header.HashSize, + HashOffset: header.HashOffset, + } + for i := 0; i < int(header.MsgIdCount); i++ { + if _, err := r.Seek(int64(msgIdStart[i]), 0); err != nil { + return nil, fmt.Errorf("gettext: %v", err) + } + msgIdData := make([]byte, msgIdLen[i]) + if _, err := r.Read(msgIdData); err != nil { + return nil, fmt.Errorf("gettext: %v", err) + } + + if _, err := r.Seek(int64(msgStrStart[i]), 0); err != nil { + return nil, fmt.Errorf("gettext: %v", err) + } + msgStrData := make([]byte, msgStrLen[i]) + if _, err := r.Read(msgStrData); err != nil { + return nil, fmt.Errorf("gettext: %v", err) + } + + if len(msgIdData) == 0 { + var msg = Message{ + MsgId: string(msgIdData), + MsgStr: string(msgStrData), + } + file.MimeHeader.fromMessage(&msg) + } else { + var msg = Message{ + MsgId: string(msgIdData), + MsgStr: string(msgStrData), + } + // Is this a context message? + if idx := strings.Index(msg.MsgId, EotSeparator); idx != -1 { + msg.MsgContext, msg.MsgId = msg.MsgId[:idx], msg.MsgId[idx+1:] + } + // Is this a plural message? + if idx := strings.Index(msg.MsgId, NulSeparator); idx != -1 { + msg.MsgId, msg.MsgIdPlural = msg.MsgId[:idx], msg.MsgId[idx+1:] + msg.MsgStrPlural = strings.Split(msg.MsgStr, NulSeparator) + msg.MsgStr = "" + } + file.Messages = append(file.Messages, msg) + } + } + + return file, nil +} + +// Save saves a mo file. +func (f *File) Save(name string) error { + return ioutil.WriteFile(name, f.Data(), 0666) +} + +// Save returns a mo file format data. +func (f *File) Data() []byte { + return encodeFile(f) +} + +// String returns the po format file string. +func (f *File) String() string { + var buf bytes.Buffer + fmt.Fprintf(&buf, "# version: %d.%d\n", f.MajorVersion, f.MinorVersion) + fmt.Fprintf(&buf, "%s\n", f.MimeHeader.String()) + fmt.Fprintf(&buf, "\n") + + for k, v := range f.Messages { + fmt.Fprintf(&buf, `msgid "%v"`+"\n", k) + fmt.Fprintf(&buf, `msgstr "%s"`+"\n", v.MsgStr) + fmt.Fprintf(&buf, "\n") + } + + return buf.String() +} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/mo/header.go b/vendor/github.com/chai2010/gettext-go/mo/header.go similarity index 100% rename from vendor/github.com/chai2010/gettext-go/gettext/mo/header.go rename to vendor/github.com/chai2010/gettext-go/mo/header.go diff --git a/vendor/github.com/chai2010/gettext-go/mo/message.go b/vendor/github.com/chai2010/gettext-go/mo/message.go new file mode 100644 index 0000000000..b67bde0b70 --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/mo/message.go @@ -0,0 +1,52 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mo + +import ( + "bytes" + "fmt" +) + +// A MO file is made up of many entries, +// each entry holding the relation between an original untranslated string +// and its corresponding translation. +// +// See http://www.gnu.org/software/gettext/manual/html_node/MO-Files.html +type Message struct { + MsgContext string // msgctxt context + MsgId string // msgid untranslated-string + MsgIdPlural string // msgid_plural untranslated-string-plural + MsgStr string // msgstr translated-string + MsgStrPlural []string // msgstr[0] translated-string-case-0 +} + +// String returns the po format entry string. +func (p Message) String() string { + var buf bytes.Buffer + fmt.Fprintf(&buf, "msgid %s", encodePoString(p.MsgId)) + if p.MsgIdPlural != "" { + fmt.Fprintf(&buf, "msgid_plural %s", encodePoString(p.MsgIdPlural)) + } + if p.MsgStr != "" { + fmt.Fprintf(&buf, "msgstr %s", encodePoString(p.MsgStr)) + } + for i := 0; i < len(p.MsgStrPlural); i++ { + fmt.Fprintf(&buf, "msgstr[%d] %s", i, encodePoString(p.MsgStrPlural[i])) + } + return buf.String() +} + +func (m_i *Message) less(m_j *Message) bool { + if a, b := m_i.MsgContext, m_j.MsgContext; a != b { + return a < b + } + if a, b := m_i.MsgId, m_j.MsgId; a != b { + return a < b + } + if a, b := m_i.MsgIdPlural, m_j.MsgIdPlural; a != b { + return a < b + } + return false +} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/mo/util.go b/vendor/github.com/chai2010/gettext-go/mo/util.go similarity index 100% rename from vendor/github.com/chai2010/gettext-go/gettext/mo/util.go rename to vendor/github.com/chai2010/gettext-go/mo/util.go diff --git a/vendor/github.com/chai2010/gettext-go/plural/doc.go b/vendor/github.com/chai2010/gettext-go/plural/doc.go new file mode 100644 index 0000000000..31cb8fae9f --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/plural/doc.go @@ -0,0 +1,36 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package plural provides standard plural formulas. + +Examples: + import ( + "github.com/chai2010/gettext-go/plural" + ) + + func main() { + enFormula := plural.Formula("en_US") + xxFormula := plural.Formula("zh_CN") + + fmt.Printf("%s: %d\n", "en", enFormula(0)) + fmt.Printf("%s: %d\n", "en", enFormula(1)) + fmt.Printf("%s: %d\n", "en", enFormula(2)) + fmt.Printf("%s: %d\n", "??", xxFormula(0)) + fmt.Printf("%s: %d\n", "??", xxFormula(1)) + fmt.Printf("%s: %d\n", "??", xxFormula(2)) + fmt.Printf("%s: %d\n", "??", xxFormula(9)) + // Output: + // en: 0 + // en: 0 + // en: 1 + // ??: 0 + // ??: 0 + // ??: 1 + // ??: 8 + } + +See http://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html +*/ +package plural diff --git a/vendor/github.com/chai2010/gettext-go/gettext/plural/formula.go b/vendor/github.com/chai2010/gettext-go/plural/formula.go similarity index 100% rename from vendor/github.com/chai2010/gettext-go/gettext/plural/formula.go rename to vendor/github.com/chai2010/gettext-go/plural/formula.go diff --git a/vendor/github.com/chai2010/gettext-go/gettext/plural/table.go b/vendor/github.com/chai2010/gettext-go/plural/table.go similarity index 100% rename from vendor/github.com/chai2010/gettext-go/gettext/plural/table.go rename to vendor/github.com/chai2010/gettext-go/plural/table.go diff --git a/vendor/github.com/chai2010/gettext-go/gettext/po/comment.go b/vendor/github.com/chai2010/gettext-go/po/comment.go similarity index 100% rename from vendor/github.com/chai2010/gettext-go/gettext/po/comment.go rename to vendor/github.com/chai2010/gettext-go/po/comment.go diff --git a/vendor/github.com/chai2010/gettext-go/po/doc.go b/vendor/github.com/chai2010/gettext-go/po/doc.go new file mode 100644 index 0000000000..6cfa2a24be --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/po/doc.go @@ -0,0 +1,24 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package po provides support for reading and writing GNU PO file. + +Examples: + import ( + "github.com/chai2010/gettext-go/po" + ) + + func main() { + poFile, err := po.LoadFile("test.po") + if err != nil { + log.Fatal(err) + } + fmt.Printf("%v", poFile) + } + +The GNU PO file specification is at +http://www.gnu.org/software/gettext/manual/html_node/PO-Files.html. +*/ +package po diff --git a/vendor/github.com/chai2010/gettext-go/po/file.go b/vendor/github.com/chai2010/gettext-go/po/file.go new file mode 100644 index 0000000000..4a122eeb8b --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/po/file.go @@ -0,0 +1,81 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package po + +import ( + "bytes" + "fmt" + "io" + "io/ioutil" + "sort" +) + +// File represents an PO File. +// +// See http://www.gnu.org/software/gettext/manual/html_node/PO-Files.html +type File struct { + MimeHeader Header + Messages []Message +} + +// Load loads po file format data. +func Load(data []byte) (*File, error) { + return loadData(data) +} + +// LoadFile loads a named po file. +func LoadFile(path string) (*File, error) { + data, err := ioutil.ReadFile(path) + if err != nil { + return nil, err + } + return loadData(data) +} + +func loadData(data []byte) (*File, error) { + r := newLineReader(string(data)) + var file File + for { + var msg Message + if err := msg.readPoEntry(r); err != nil { + if err == io.EOF { + return &file, nil + } + return nil, err + } + if msg.MsgId == "" { + file.MimeHeader.parseHeader(&msg) + continue + } + file.Messages = append(file.Messages, msg) + } +} + +// Save saves a po file. +func (f *File) Save(name string) error { + return ioutil.WriteFile(name, []byte(f.String()), 0666) +} + +// Save returns a po file format data. +func (f *File) Data() []byte { + // sort the massge as ReferenceFile/ReferenceLine field + var messages []Message + messages = append(messages, f.Messages...) + sort.Slice(messages, func(i, j int) bool { + return messages[i].less(&messages[j]) + }) + + var buf bytes.Buffer + fmt.Fprintf(&buf, "%s\n", f.MimeHeader.String()) + for i := 0; i < len(messages); i++ { + fmt.Fprintf(&buf, "%s\n", messages[i].String()) + } + return buf.Bytes() +} + +// String returns the po format file string. +func (f *File) String() string { + return string(f.Data()) +} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/po/header.go b/vendor/github.com/chai2010/gettext-go/po/header.go similarity index 100% rename from vendor/github.com/chai2010/gettext-go/gettext/po/header.go rename to vendor/github.com/chai2010/gettext-go/po/header.go diff --git a/vendor/github.com/chai2010/gettext-go/gettext/po/line_reader.go b/vendor/github.com/chai2010/gettext-go/po/line_reader.go similarity index 100% rename from vendor/github.com/chai2010/gettext-go/gettext/po/line_reader.go rename to vendor/github.com/chai2010/gettext-go/po/line_reader.go diff --git a/vendor/github.com/chai2010/gettext-go/po/message.go b/vendor/github.com/chai2010/gettext-go/po/message.go new file mode 100644 index 0000000000..39936dcc7b --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/po/message.go @@ -0,0 +1,193 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package po + +import ( + "bytes" + "fmt" + "io" + "strconv" + "strings" +) + +// A PO file is made up of many entries, +// each entry holding the relation between an original untranslated string +// and its corresponding translation. +// +// See http://www.gnu.org/software/gettext/manual/html_node/PO-Files.html +type Message struct { + Comment // Coments + MsgContext string // msgctxt context + MsgId string // msgid untranslated-string + MsgIdPlural string // msgid_plural untranslated-string-plural + MsgStr string // msgstr translated-string + MsgStrPlural []string // msgstr[0] translated-string-case-0 +} + +func (p *Message) less(q *Message) bool { + if p.Comment.less(&q.Comment) { + return true + } + if a, b := p.MsgContext, q.MsgContext; a != b { + return a < b + } + if a, b := p.MsgId, q.MsgId; a != b { + return a < b + } + if a, b := p.MsgIdPlural, q.MsgIdPlural; a != b { + return a < b + } + return false +} + +func (p *Message) readPoEntry(r *lineReader) (err error) { + *p = Message{} + if err = r.skipBlankLine(); err != nil { + return + } + defer func(oldPos int) { + newPos := r.currentPos() + if newPos != oldPos && err == io.EOF { + err = nil + } + }(r.currentPos()) + + if err = p.Comment.readPoComment(r); err != nil { + return + } + for { + var s string + if s, _, err = r.currentLine(); err != nil { + return + } + + if p.isInvalidLine(s) { + err = fmt.Errorf("gettext: line %d, %v", r.currentPos(), "invalid line") + return + } + if reComment.MatchString(s) || reBlankLine.MatchString(s) { + return + } + + if err = p.readMsgContext(r); err != nil { + return + } + if err = p.readMsgId(r); err != nil { + return + } + if err = p.readMsgIdPlural(r); err != nil { + return + } + if err = p.readMsgStrOrPlural(r); err != nil { + return + } + } +} + +func (p *Message) readMsgContext(r *lineReader) (err error) { + var s string + if s, _, err = r.currentLine(); err != nil { + return + } + if !reMsgContext.MatchString(s) { + return + } + p.MsgContext, err = p.readString(r) + return +} + +func (p *Message) readMsgId(r *lineReader) (err error) { + var s string + if s, _, err = r.currentLine(); err != nil { + return + } + if !reMsgId.MatchString(s) { + return + } + p.MsgId, err = p.readString(r) + return +} + +func (p *Message) readMsgIdPlural(r *lineReader) (err error) { + var s string + if s, _, err = r.currentLine(); err != nil { + return + } + if !reMsgIdPlural.MatchString(s) { + return + } + p.MsgIdPlural, err = p.readString(r) + return nil +} + +func (p *Message) readMsgStrOrPlural(r *lineReader) (err error) { + var s string + if s, _, err = r.currentLine(); err != nil { + return + } + if !reMsgStr.MatchString(s) && !reMsgStrPlural.MatchString(s) { + return + } + if reMsgStrPlural.MatchString(s) { + left, right := strings.Index(s, `[`), strings.LastIndex(s, `]`) + idx, _ := strconv.Atoi(s[left+1 : right]) + s, err = p.readString(r) + if n := len(p.MsgStrPlural); (idx + 1) > n { + p.MsgStrPlural = append(p.MsgStrPlural, make([]string, (idx+1)-n)...) + } + p.MsgStrPlural[idx] = s + } else { + p.MsgStr, err = p.readString(r) + } + return nil +} + +func (p *Message) readString(r *lineReader) (msg string, err error) { + var s string + if s, _, err = r.readLine(); err != nil { + return + } + msg += decodePoString(s) + for { + if s, _, err = r.readLine(); err != nil { + return + } + if !reStringLine.MatchString(s) { + r.unreadLine() + break + } + msg += decodePoString(s) + } + return +} + +// String returns the po format entry string. +func (p Message) String() string { + var buf bytes.Buffer + fmt.Fprintf(&buf, "%s", p.Comment.String()) + if p.MsgContext != "" { + fmt.Fprintf(&buf, "msgctxt %s", encodePoString(p.MsgContext)) + } + fmt.Fprintf(&buf, "msgid %s", encodePoString(p.MsgId)) + if p.MsgIdPlural != "" { + fmt.Fprintf(&buf, "msgid_plural %s", encodePoString(p.MsgIdPlural)) + } + if len(p.MsgStrPlural) == 0 { + if p.MsgStr != "" { + fmt.Fprintf(&buf, "msgstr %s", encodePoString(p.MsgStr)) + } else { + fmt.Fprintf(&buf, "msgstr %s", `""`+"\n") + } + } else { + for i := 0; i < len(p.MsgStrPlural); i++ { + if p.MsgStrPlural[i] != "" { + fmt.Fprintf(&buf, "msgstr[%d] %s", i, encodePoString(p.MsgStrPlural[i])) + } else { + fmt.Fprintf(&buf, "msgstr[%d] %s", i, `""`+"\n") + } + } + } + return buf.String() +} diff --git a/vendor/github.com/chai2010/gettext-go/gettext/po/re.go b/vendor/github.com/chai2010/gettext-go/po/re.go similarity index 100% rename from vendor/github.com/chai2010/gettext-go/gettext/po/re.go rename to vendor/github.com/chai2010/gettext-go/po/re.go diff --git a/vendor/github.com/chai2010/gettext-go/po/util.go b/vendor/github.com/chai2010/gettext-go/po/util.go new file mode 100644 index 0000000000..d8b3b0e254 --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/po/util.go @@ -0,0 +1,114 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package po + +import ( + "bytes" + "strings" +) + +func decodePoString(text string) string { + lines := strings.Split(text, "\n") + for i := 0; i < len(lines); i++ { + left := strings.Index(lines[i], `"`) + right := strings.LastIndex(lines[i], `"`) + if left < 0 || right < 0 || left == right { + lines[i] = "" + continue + } + line := lines[i][left+1 : right] + data := make([]byte, 0, len(line)) + for i := 0; i < len(line); i++ { + if line[i] != '\\' { + data = append(data, line[i]) + continue + } + if i+1 >= len(line) { + break + } + switch line[i+1] { + case 'n': // \\n -> \n + data = append(data, '\n') + i++ + case 't': // \\t -> \n + data = append(data, '\t') + i++ + case '\\': // \\\ -> ? + data = append(data, '\\') + i++ + } + } + lines[i] = string(data) + } + return strings.Join(lines, "") +} + +func encodePoString(text string) string { + var buf bytes.Buffer + lines := strings.Split(text, "\n") + for i := 0; i < len(lines); i++ { + if lines[i] == "" { + if i != len(lines)-1 { + buf.WriteString(`"\n"` + "\n") + } + continue + } + buf.WriteRune('"') + for _, r := range lines[i] { + switch r { + case '\\': + buf.WriteString(`\\`) + case '"': + buf.WriteString(`\"`) + case '\n': + buf.WriteString(`\n`) + case '\t': + buf.WriteString(`\t`) + default: + buf.WriteRune(r) + } + } + if i < len(lines)-1 { + buf.WriteString(`\n"` + "\n") + } else { + buf.WriteString(`"` + "\n") + } + } + return buf.String() +} + +func encodeCommentPoString(text string) string { + var buf bytes.Buffer + lines := strings.Split(text, "\n") + if len(lines) > 1 { + buf.WriteString(`""` + "\n") + } + for i := 0; i < len(lines); i++ { + if len(lines) > 0 { + buf.WriteString("#| ") + } + buf.WriteRune('"') + for _, r := range lines[i] { + switch r { + case '\\': + buf.WriteString(`\\`) + case '"': + buf.WriteString(`\"`) + case '\n': + buf.WriteString(`\n`) + case '\t': + buf.WriteString(`\t`) + default: + buf.WriteRune(r) + } + } + if i < len(lines)-1 { + buf.WriteString(`\n"` + "\n") + } else { + buf.WriteString(`"`) + } + } + return buf.String() +} diff --git a/vendor/github.com/chai2010/gettext-go/tr.go b/vendor/github.com/chai2010/gettext-go/tr.go new file mode 100644 index 0000000000..5b9d08f426 --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/tr.go @@ -0,0 +1,175 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gettext + +import ( + "encoding/json" + + "github.com/chai2010/gettext-go/mo" + "github.com/chai2010/gettext-go/plural" + "github.com/chai2010/gettext-go/po" +) + +var nilTranslator = &translator{ + MessageMap: make(map[string]mo.Message), + PluralFormula: plural.Formula("??"), +} + +type translator struct { + MessageMap map[string]mo.Message + PluralFormula func(n int) int +} + +func newMoTranslator(name string, data []byte) (*translator, error) { + var ( + f *mo.File + err error + ) + if len(data) != 0 { + f, err = mo.Load(data) + } else { + f, err = mo.LoadFile(name) + } + if err != nil { + return nil, err + } + var tr = &translator{ + MessageMap: make(map[string]mo.Message), + } + for _, v := range f.Messages { + tr.MessageMap[tr.makeMapKey(v.MsgContext, v.MsgId)] = v + } + if lang := f.MimeHeader.Language; lang != "" { + tr.PluralFormula = plural.Formula(lang) + } else { + tr.PluralFormula = plural.Formula("??") + } + return tr, nil +} + +func newPoTranslator(name string, data []byte) (*translator, error) { + var ( + f *po.File + err error + ) + if len(data) != 0 { + f, err = po.Load(data) + } else { + f, err = po.LoadFile(name) + } + if err != nil { + return nil, err + } + var tr = &translator{ + MessageMap: make(map[string]mo.Message), + } + for _, v := range f.Messages { + tr.MessageMap[tr.makeMapKey(v.MsgContext, v.MsgId)] = mo.Message{ + MsgContext: v.MsgContext, + MsgId: v.MsgId, + MsgIdPlural: v.MsgIdPlural, + MsgStr: v.MsgStr, + MsgStrPlural: v.MsgStrPlural, + } + } + if lang := f.MimeHeader.Language; lang != "" { + tr.PluralFormula = plural.Formula(lang) + } else { + tr.PluralFormula = plural.Formula("??") + } + return tr, nil +} + +func newJsonTranslator(lang, name string, jsonData []byte) (*translator, error) { + var msgList []struct { + MsgContext string `json:"msgctxt"` // msgctxt context + MsgId string `json:"msgid"` // msgid untranslated-string + MsgIdPlural string `json:"msgid_plural"` // msgid_plural untranslated-string-plural + MsgStr []string `json:"msgstr"` // msgstr translated-string + } + if err := json.Unmarshal(jsonData, &msgList); err != nil { + return nil, err + } + + var tr = &translator{ + MessageMap: make(map[string]mo.Message), + PluralFormula: plural.Formula(lang), + } + + for _, v := range msgList { + var v_MsgStr string + var v_MsgStrPlural = v.MsgStr + + if len(v.MsgStr) != 0 { + v_MsgStr = v.MsgStr[0] + } + + tr.MessageMap[tr.makeMapKey(v.MsgContext, v.MsgId)] = mo.Message{ + MsgContext: v.MsgContext, + MsgId: v.MsgId, + MsgIdPlural: v.MsgIdPlural, + MsgStr: v_MsgStr, + MsgStrPlural: v_MsgStrPlural, + } + } + return tr, nil +} + +func (p *translator) PGettext(msgctxt, msgid string) string { + return p.findMsgStr(msgctxt, msgid) +} + +func (p *translator) PNGettext(msgctxt, msgid, msgidPlural string, n int) string { + n = p.PluralFormula(n) + if ss := p.findMsgStrPlural(msgctxt, msgid, msgidPlural); len(ss) != 0 { + if n >= len(ss) { + n = len(ss) - 1 + } + if ss[n] != "" { + return ss[n] + } + } + if msgidPlural != "" && n > 0 { + return msgidPlural + } + return msgid +} + +func (p *translator) findMsgStr(msgctxt, msgid string) string { + key := p.makeMapKey(msgctxt, msgid) + if v, ok := p.MessageMap[key]; ok { + if v.MsgStr != "" { + return v.MsgStr + } + } + return msgid +} + +func (p *translator) findMsgStrPlural(msgctxt, msgid, msgidPlural string) []string { + key := p.makeMapKey(msgctxt, msgid) + if v, ok := p.MessageMap[key]; ok { + if len(v.MsgIdPlural) != 0 { + if len(v.MsgStrPlural) != 0 { + return v.MsgStrPlural + } else { + return nil + } + } else { + if len(v.MsgStr) != 0 { + return []string{v.MsgStr} + } else { + return nil + } + } + } + return nil +} + +func (p *translator) makeMapKey(msgctxt, msgid string) string { + if msgctxt != "" { + return msgctxt + mo.EotSeparator + msgid + } + return msgid +} diff --git a/vendor/github.com/chai2010/gettext-go/util.go b/vendor/github.com/chai2010/gettext-go/util.go new file mode 100644 index 0000000000..b8269a605c --- /dev/null +++ b/vendor/github.com/chai2010/gettext-go/util.go @@ -0,0 +1,34 @@ +// Copyright 2013 ChaiShushan . All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gettext + +import ( + "os" + "strings" +) + +func getDefaultLanguage() string { + if v := os.Getenv("LC_MESSAGES"); v != "" { + return simplifiedLanguage(v) + } + if v := os.Getenv("LANG"); v != "" { + return simplifiedLanguage(v) + } + return "default" +} + +func simplifiedLanguage(lang string) string { + // en_US/en_US.UTF-8/zh_CN/zh_TW/el_GR@euro/... + if idx := strings.Index(lang, ":"); idx != -1 { + lang = lang[:idx] + } + if idx := strings.Index(lang, "@"); idx != -1 { + lang = lang[:idx] + } + if idx := strings.Index(lang, "."); idx != -1 { + lang = lang[:idx] + } + return strings.TrimSpace(lang) +} diff --git a/vendor/github.com/containerd/containerd/archive/tar.go b/vendor/github.com/containerd/containerd/archive/tar.go index 62341d5e12..44b7949531 100644 --- a/vendor/github.com/containerd/containerd/archive/tar.go +++ b/vendor/github.com/containerd/containerd/archive/tar.go @@ -31,6 +31,7 @@ import ( "time" "github.com/containerd/containerd/log" + "github.com/containerd/containerd/pkg/userns" "github.com/containerd/continuity/fs" ) @@ -119,6 +120,8 @@ const ( whiteoutOpaqueDir = whiteoutMetaPrefix + ".opq" paxSchilyXattr = "SCHILY.xattr." + + userXattrPrefix = "user." ) // Apply applies a tar stream of an OCI style diff tar. @@ -380,6 +383,10 @@ func createTarFile(ctx context.Context, path, extractDir string, hdr *tar.Header // Lchown is not supported on Windows. if runtime.GOOS != "windows" { if err := os.Lchown(path, hdr.Uid, hdr.Gid); err != nil { + err = fmt.Errorf("failed to Lchown %q for UID %d, GID %d: %w", path, hdr.Uid, hdr.Gid, err) + if errors.Is(err, syscall.EINVAL) && userns.RunningInUserNS() { + err = fmt.Errorf("%w (Hint: try increasing the number of subordinate IDs in /etc/subuid and /etc/subgid)", err) + } return err } } @@ -388,11 +395,19 @@ func createTarFile(ctx context.Context, path, extractDir string, hdr *tar.Header if strings.HasPrefix(key, paxSchilyXattr) { key = key[len(paxSchilyXattr):] if err := setxattr(path, key, value); err != nil { + if errors.Is(err, syscall.EPERM) && strings.HasPrefix(key, userXattrPrefix) { + // In the user.* namespace, only regular files and directories can have extended attributes. + // See https://man7.org/linux/man-pages/man7/xattr.7.html for details. + if fi, err := os.Lstat(path); err == nil && (!fi.Mode().IsRegular() && !fi.Mode().IsDir()) { + log.G(ctx).WithError(err).Warnf("ignored xattr %s in archive", key) + continue + } + } if errors.Is(err, syscall.ENOTSUP) { log.G(ctx).WithError(err).Warnf("ignored xattr %s in archive", key) continue } - return err + return fmt.Errorf("failed to setxattr %q for key %q: %w", path, key, err) } } } diff --git a/vendor/github.com/containerd/containerd/archive/tar_unix.go b/vendor/github.com/containerd/containerd/archive/tar_unix.go index 2f3a3a392e..854afcf0ad 100644 --- a/vendor/github.com/containerd/containerd/archive/tar_unix.go +++ b/vendor/github.com/containerd/containerd/archive/tar_unix.go @@ -63,7 +63,7 @@ func setHeaderForSpecialDevice(hdr *tar.Header, name string, fi os.FileInfo) err } // Rdev is int32 on darwin/bsd, int64 on linux/solaris - rdev := uint64(s.Rdev) // nolint: unconvert + rdev := uint64(s.Rdev) //nolint:unconvert // Currently go does not fill in the major/minors if s.Mode&syscall.S_IFBLK != 0 || diff --git a/vendor/github.com/containerd/containerd/content/helpers.go b/vendor/github.com/containerd/containerd/content/helpers.go index 3ec1ffce00..723c313917 100644 --- a/vendor/github.com/containerd/containerd/content/helpers.go +++ b/vendor/github.com/containerd/containerd/content/helpers.go @@ -26,10 +26,16 @@ import ( "time" "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/log" "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) +// maxResets is the no.of times the Copy() method can tolerate a reset of the body +const maxResets = 5 + +var ErrReset = errors.New("writer has been reset") + var bufPool = sync.Pool{ New: func() interface{} { buffer := make([]byte, 1<<20) @@ -80,7 +86,7 @@ func WriteBlob(ctx context.Context, cs Ingester, ref string, r io.Reader, desc o return fmt.Errorf("failed to open writer: %w", err) } - return nil // all ready present + return nil // already present } defer cw.Close() @@ -131,35 +137,63 @@ func OpenWriter(ctx context.Context, cs Ingester, opts ...WriterOpt) (Writer, er // the size or digest is unknown, these values may be empty. // // Copy is buffered, so no need to wrap reader in buffered io. -func Copy(ctx context.Context, cw Writer, r io.Reader, size int64, expected digest.Digest, opts ...Opt) error { +func Copy(ctx context.Context, cw Writer, or io.Reader, size int64, expected digest.Digest, opts ...Opt) error { ws, err := cw.Status() if err != nil { return fmt.Errorf("failed to get status: %w", err) } - + r := or if ws.Offset > 0 { - r, err = seekReader(r, ws.Offset, size) + r, err = seekReader(or, ws.Offset, size) if err != nil { return fmt.Errorf("unable to resume write to %v: %w", ws.Ref, err) } } - copied, err := copyWithBuffer(cw, r) - if err != nil { - return fmt.Errorf("failed to copy: %w", err) - } - if size != 0 && copied < size-ws.Offset { - // Short writes would return its own error, this indicates a read failure - return fmt.Errorf("failed to read expected number of bytes: %w", io.ErrUnexpectedEOF) - } - - if err := cw.Commit(ctx, size, expected, opts...); err != nil { - if !errdefs.IsAlreadyExists(err) { - return fmt.Errorf("failed commit on ref %q: %w", ws.Ref, err) + for i := 0; i < maxResets; i++ { + if i >= 1 { + log.G(ctx).WithField("digest", expected).Debugf("retrying copy due to reset") + } + copied, err := copyWithBuffer(cw, r) + if errors.Is(err, ErrReset) { + ws, err := cw.Status() + if err != nil { + return fmt.Errorf("failed to get status: %w", err) + } + r, err = seekReader(or, ws.Offset, size) + if err != nil { + return fmt.Errorf("unable to resume write to %v: %w", ws.Ref, err) + } + continue + } + if err != nil { + return fmt.Errorf("failed to copy: %w", err) + } + if size != 0 && copied < size-ws.Offset { + // Short writes would return its own error, this indicates a read failure + return fmt.Errorf("failed to read expected number of bytes: %w", io.ErrUnexpectedEOF) + } + if err := cw.Commit(ctx, size, expected, opts...); err != nil { + if errors.Is(err, ErrReset) { + ws, err := cw.Status() + if err != nil { + return fmt.Errorf("failed to get status: %w", err) + } + r, err = seekReader(or, ws.Offset, size) + if err != nil { + return fmt.Errorf("unable to resume write to %v: %w", ws.Ref, err) + } + continue + } + if !errdefs.IsAlreadyExists(err) { + return fmt.Errorf("failed commit on ref %q: %w", ws.Ref, err) + } } + return nil } - return nil + log.G(ctx).WithField("digest", expected).Errorf("failed to copy after %d retries", maxResets) + return fmt.Errorf("failed to copy after %d retries", maxResets) } // CopyReaderAt copies to a writer from a given reader at for the given diff --git a/vendor/github.com/containerd/containerd/content/local/store.go b/vendor/github.com/containerd/containerd/content/local/store.go index 457bbcd0eb..f41a92d04a 100644 --- a/vendor/github.com/containerd/containerd/content/local/store.go +++ b/vendor/github.com/containerd/containerd/content/local/store.go @@ -643,7 +643,6 @@ func (s *store) ingestRoot(ref string) string { // - root: entire ingest directory // - ref: name of the starting ref, must be unique // - data: file where data is written -// func (s *store) ingestPaths(ref string) (string, string, string) { var ( fp = s.ingestRoot(ref) diff --git a/vendor/github.com/containerd/containerd/filters/filter.go b/vendor/github.com/containerd/containerd/filters/filter.go index cf09d8d9e4..e13f2625c7 100644 --- a/vendor/github.com/containerd/containerd/filters/filter.go +++ b/vendor/github.com/containerd/containerd/filters/filter.go @@ -65,7 +65,6 @@ // ``` // name==foo,labels.bar // ``` -// package filters import ( diff --git a/vendor/github.com/containerd/containerd/filters/parser.go b/vendor/github.com/containerd/containerd/filters/parser.go index 49182d7b7b..32767909b1 100644 --- a/vendor/github.com/containerd/containerd/filters/parser.go +++ b/vendor/github.com/containerd/containerd/filters/parser.go @@ -45,7 +45,6 @@ field := quoted | [A-Za-z] [A-Za-z0-9_]+ operator := "==" | "!=" | "~=" value := quoted | [^\s,]+ quoted := - */ func Parse(s string) (Filter, error) { // special case empty to match all diff --git a/vendor/github.com/containerd/containerd/filters/quote.go b/vendor/github.com/containerd/containerd/filters/quote.go index b76aab9b4a..5c800ef846 100644 --- a/vendor/github.com/containerd/containerd/filters/quote.go +++ b/vendor/github.com/containerd/containerd/filters/quote.go @@ -31,10 +31,10 @@ var errQuoteSyntax = errors.New("quote syntax error") // or character literal represented by the string s. // It returns four values: // -// 1) value, the decoded Unicode code point or byte value; -// 2) multibyte, a boolean indicating whether the decoded character requires a multibyte UTF-8 representation; -// 3) tail, the remainder of the string after the character; and -// 4) an error that will be nil if the character is syntactically valid. +// 1. value, the decoded Unicode code point or byte value; +// 2. multibyte, a boolean indicating whether the decoded character requires a multibyte UTF-8 representation; +// 3. tail, the remainder of the string after the character; and +// 4. an error that will be nil if the character is syntactically valid. // // The second argument, quote, specifies the type of literal being parsed // and therefore which escaped quote character is permitted. diff --git a/vendor/github.com/containerd/containerd/leases/lease.go b/vendor/github.com/containerd/containerd/leases/lease.go index 058d065594..fc0ca3491c 100644 --- a/vendor/github.com/containerd/containerd/leases/lease.go +++ b/vendor/github.com/containerd/containerd/leases/lease.go @@ -65,10 +65,15 @@ func SynchronousDelete(ctx context.Context, o *DeleteOptions) error { return nil } -// WithLabels sets labels on a lease +// WithLabels merges labels on a lease func WithLabels(labels map[string]string) Opt { return func(l *Lease) error { - l.Labels = labels + if l.Labels == nil { + l.Labels = map[string]string{} + } + for k, v := range labels { + l.Labels[k] = v + } return nil } } diff --git a/vendor/github.com/containerd/containerd/metadata/buckets.go b/vendor/github.com/containerd/containerd/metadata/buckets.go index d23be84fea..516de1fc7a 100644 --- a/vendor/github.com/containerd/containerd/metadata/buckets.go +++ b/vendor/github.com/containerd/containerd/metadata/buckets.go @@ -26,7 +26,7 @@ // // Generically, we try to do the following: // -// /// -> +// /// -> // // version: Currently, this is "v1". Additions can be made to v1 in a backwards // compatible way. If the layout changes, a new version must be made, along @@ -46,72 +46,73 @@ // the structure is changed in addition to adding a migration and incrementing // the database version. Note that `╘══*...*` refers to maps with arbitrary // keys. -// ├──version : - Latest version, see migrations -// └──v1 - Schema version bucket -// ╘══*namespace* -// ├──labels -// │  ╘══*key* : - Label value -// ├──image -// │  ╘══*image name* -// │   ├──createdat : - Created at -// │   ├──updatedat : - Updated at -// │   ├──target -// │   │  ├──digest : - Descriptor digest -// │   │  ├──mediatype : - Descriptor media type -// │   │  └──size : - Descriptor size -// │   └──labels -// │   ╘══*key* : - Label value -// ├──containers -// │  ╘══*container id* -// │   ├──createdat : - Created at -// │   ├──updatedat : - Updated at -// │   ├──spec : - Proto marshaled spec -// │   ├──image : - Image name -// │   ├──snapshotter : - Snapshotter name -// │   ├──snapshotKey : - Snapshot key -// │   ├──runtime -// │   │  ├──name : - Runtime name -// │   │  ├──extensions -// │   │  │  ╘══*name* : - Proto marshaled extension -// │   │  └──options : - Proto marshaled options -// │   └──labels -// │   ╘══*key* : - Label value -// ├──snapshots -// │  ╘══*snapshotter* -// │   ╘══*snapshot key* -// │    ├──name : - Snapshot name in backend -// │   ├──createdat : - Created at -// │   ├──updatedat : - Updated at -// │    ├──parent : - Parent snapshot name -// │   ├──children -// │   │  ╘══*snapshot key* : - Child snapshot reference -// │   └──labels -// │   ╘══*key* : - Label value -// ├──content -// │  ├──blob -// │  │ ╘══*blob digest* -// │  │ ├──createdat : - Created at -// │  │ ├──updatedat : - Updated at -// │  │   ├──size : - Blob size -// │  │ └──labels -// │  │ ╘══*key* : - Label value -// │  └──ingests -// │   ╘══*ingest reference* -// │    ├──ref : - Ingest reference in backend -// │   ├──expireat : - Time to expire ingest -// │   └──expected : - Expected commit digest -// └──leases -// ╘══*lease id* -//   ├──createdat : - Created at -// ├──labels -// │ ╘══*key* : - Label value -//   ├──snapshots -// │  ╘══*snapshotter* -// │   ╘══*snapshot key* : - Snapshot reference -//   ├──content -// │  ╘══*blob digest* : - Content blob reference -// └──ingests -//   ╘══*ingest reference* : - Content ingest reference +// +// ├──version : - Latest version, see migrations +// └──v1 - Schema version bucket +// ╘══*namespace* +// ├──labels +// │  ╘══*key* : - Label value +// ├──image +// │  ╘══*image name* +// │   ├──createdat : - Created at +// │   ├──updatedat : - Updated at +// │   ├──target +// │   │  ├──digest : - Descriptor digest +// │   │  ├──mediatype : - Descriptor media type +// │   │  └──size : - Descriptor size +// │   └──labels +// │   ╘══*key* : - Label value +// ├──containers +// │  ╘══*container id* +// │   ├──createdat : - Created at +// │   ├──updatedat : - Updated at +// │   ├──spec : - Proto marshaled spec +// │   ├──image : - Image name +// │   ├──snapshotter : - Snapshotter name +// │   ├──snapshotKey : - Snapshot key +// │   ├──runtime +// │   │  ├──name : - Runtime name +// │   │  ├──extensions +// │   │  │  ╘══*name* : - Proto marshaled extension +// │   │  └──options : - Proto marshaled options +// │   └──labels +// │   ╘══*key* : - Label value +// ├──snapshots +// │  ╘══*snapshotter* +// │   ╘══*snapshot key* +// │    ├──name : - Snapshot name in backend +// │   ├──createdat : - Created at +// │   ├──updatedat : - Updated at +// │    ├──parent : - Parent snapshot name +// │   ├──children +// │   │  ╘══*snapshot key* : - Child snapshot reference +// │   └──labels +// │   ╘══*key* : - Label value +// ├──content +// │  ├──blob +// │  │ ╘══*blob digest* +// │  │ ├──createdat : - Created at +// │  │ ├──updatedat : - Updated at +// │  │   ├──size : - Blob size +// │  │ └──labels +// │  │ ╘══*key* : - Label value +// │  └──ingests +// │   ╘══*ingest reference* +// │    ├──ref : - Ingest reference in backend +// │   ├──expireat : - Time to expire ingest +// │   └──expected : - Expected commit digest +// └──leases +// ╘══*lease id* +//   ├──createdat : - Created at +// ├──labels +// │ ╘══*key* : - Label value +//   ├──snapshots +// │  ╘══*snapshotter* +// │   ╘══*snapshot key* : - Snapshot reference +//   ├──content +// │  ╘══*blob digest* : - Content blob reference +// └──ingests +//   ╘══*ingest reference* : - Content ingest reference package metadata import ( diff --git a/vendor/github.com/containerd/containerd/namespaces/store.go b/vendor/github.com/containerd/containerd/namespaces/store.go index 5936772cb4..a1b2571bb1 100644 --- a/vendor/github.com/containerd/containerd/namespaces/store.go +++ b/vendor/github.com/containerd/containerd/namespaces/store.go @@ -24,8 +24,6 @@ import "context" // oriented. A namespace is really just a name and a set of labels. Objects // that belong to a namespace are returned when the namespace is assigned to a // given context. -// -// type Store interface { Create(ctx context.Context, namespace string, labels map[string]string) error Labels(ctx context.Context, namespace string) (map[string]string, error) diff --git a/vendor/github.com/containerd/containerd/platforms/defaults_windows.go b/vendor/github.com/containerd/containerd/platforms/defaults_windows.go index c1aaf72ca8..ff9771a600 100644 --- a/vendor/github.com/containerd/containerd/platforms/defaults_windows.go +++ b/vendor/github.com/containerd/containerd/platforms/defaults_windows.go @@ -46,10 +46,14 @@ type matchComparer struct { // Match matches platform with the same windows major, minor // and build version. -func (m matchComparer) Match(p imagespec.Platform) bool { - if m.defaults.Match(p) { - // TODO(windows): Figure out whether OSVersion is deprecated. - return strings.HasPrefix(p.OSVersion, m.osVersionPrefix) +func (m matchComparer) Match(p specs.Platform) bool { + match := m.defaults.Match(p) + + if match && p.OS == "windows" { + if strings.HasPrefix(p.OSVersion, m.osVersionPrefix) { + return true + } + return p.OSVersion == "" } return false } diff --git a/vendor/github.com/containerd/containerd/platforms/platforms.go b/vendor/github.com/containerd/containerd/platforms/platforms.go index 8f955d036d..2343099418 100644 --- a/vendor/github.com/containerd/containerd/platforms/platforms.go +++ b/vendor/github.com/containerd/containerd/platforms/platforms.go @@ -27,40 +27,40 @@ // The vast majority of use cases should simply use the match function with // user input. The first step is to parse a specifier into a matcher: // -// m, err := Parse("linux") -// if err != nil { ... } +// m, err := Parse("linux") +// if err != nil { ... } // // Once you have a matcher, use it to match against the platform declared by a // component, typically from an image or runtime. Since extracting an images // platform is a little more involved, we'll use an example against the // platform default: // -// if ok := m.Match(Default()); !ok { /* doesn't match */ } +// if ok := m.Match(Default()); !ok { /* doesn't match */ } // // This can be composed in loops for resolving runtimes or used as a filter for // fetch and select images. // // More details of the specifier syntax and platform spec follow. // -// Declaring Platform Support +// # Declaring Platform Support // // Components that have strict platform requirements should use the OCI // platform specification to declare their support. Typically, this will be // images and runtimes that should make these declaring which platform they // support specifically. This looks roughly as follows: // -// type Platform struct { -// Architecture string -// OS string -// Variant string -// } +// type Platform struct { +// Architecture string +// OS string +// Variant string +// } // // Most images and runtimes should at least set Architecture and OS, according // to their GOARCH and GOOS values, respectively (follow the OCI image // specification when in doubt). ARM should set variant under certain // discussions, which are outlined below. // -// Platform Specifiers +// # Platform Specifiers // // While the OCI platform specifications provide a tool for components to // specify structured information, user input typically doesn't need the full @@ -77,7 +77,7 @@ // where the architecture may be known but a runtime may support images from // different operating systems. // -// Normalization +// # Normalization // // Because not all users are familiar with the way the Go runtime represents // platforms, several normalizations have been provided to make this package @@ -85,17 +85,17 @@ // // The following are performed for architectures: // -// Value Normalized -// aarch64 arm64 -// armhf arm -// armel arm/v6 -// i386 386 -// x86_64 amd64 -// x86-64 amd64 +// Value Normalized +// aarch64 arm64 +// armhf arm +// armel arm/v6 +// i386 386 +// x86_64 amd64 +// x86-64 amd64 // // We also normalize the operating system `macos` to `darwin`. // -// ARM Support +// # ARM Support // // To qualify ARM architecture, the Variant field is used to qualify the arm // version. The most common arm version, v7, is represented without the variant diff --git a/vendor/github.com/containerd/containerd/remotes/docker/auth/parse.go b/vendor/github.com/containerd/containerd/remotes/docker/auth/parse.go index 223fa2d052..e4529a7761 100644 --- a/vendor/github.com/containerd/containerd/remotes/docker/auth/parse.go +++ b/vendor/github.com/containerd/containerd/remotes/docker/auth/parse.go @@ -134,9 +134,6 @@ func parseValueAndParams(header string) (value string, params map[string]string) } var pvalue string pvalue, s = expectTokenOrQuoted(s[1:]) - if pvalue == "" { - return - } pkey = strings.ToLower(pkey) params[pkey] = pvalue s = skipSpace(s) diff --git a/vendor/github.com/containerd/containerd/remotes/docker/pusher.go b/vendor/github.com/containerd/containerd/remotes/docker/pusher.go index c786ad2158..bef77fa61d 100644 --- a/vendor/github.com/containerd/containerd/remotes/docker/pusher.go +++ b/vendor/github.com/containerd/containerd/remotes/docker/pusher.go @@ -24,6 +24,7 @@ import ( "net/http" "net/url" "strings" + "sync" "time" "github.com/containerd/containerd/content" @@ -261,27 +262,20 @@ func (p dockerPusher) push(ctx context.Context, desc ocispec.Descriptor, ref str // TODO: Support chunked upload - pr, pw := io.Pipe() - respC := make(chan response, 1) - body := io.NopCloser(pr) + pushw := newPushWriter(p.dockerBase, ref, desc.Digest, p.tracker, isManifest) req.body = func() (io.ReadCloser, error) { - if body == nil { - return nil, errors.New("cannot reuse body, request must be retried") - } - // Only use the body once since pipe cannot be seeked - ob := body - body = nil - return ob, nil + pr, pw := io.Pipe() + pushw.setPipe(pw) + return io.NopCloser(pr), nil } req.size = desc.Size go func() { - defer close(respC) resp, err := req.doWithRetries(ctx, nil) if err != nil { - respC <- response{err: err} - pr.CloseWithError(err) + pushw.setError(err) + pushw.Close() return } @@ -290,20 +284,13 @@ func (p dockerPusher) push(ctx context.Context, desc ocispec.Descriptor, ref str default: err := remoteserrors.NewUnexpectedStatusErr(resp) log.G(ctx).WithField("resp", resp).WithField("body", string(err.(remoteserrors.ErrUnexpectedStatus).Body)).Debug("unexpected response") - pr.CloseWithError(err) + pushw.setError(err) + pushw.Close() } - respC <- response{Response: resp} + pushw.setResponse(resp) }() - return &pushWriter{ - base: p.dockerBase, - ref: ref, - pipe: pw, - responseC: respC, - isManifest: isManifest, - expected: desc.Digest, - tracker: p.tracker, - }, nil + return pushw, nil } func getManifestPath(object string, dgst digest.Digest) []string { @@ -325,29 +312,89 @@ func getManifestPath(object string, dgst digest.Digest) []string { return []string{"manifests", object} } -type response struct { - *http.Response - err error -} - type pushWriter struct { base *dockerBase ref string - pipe *io.PipeWriter - responseC <-chan response + pipe *io.PipeWriter + + pipeC chan *io.PipeWriter + respC chan *http.Response + closeOnce sync.Once + errC chan error + isManifest bool expected digest.Digest tracker StatusTracker } +func newPushWriter(db *dockerBase, ref string, expected digest.Digest, tracker StatusTracker, isManifest bool) *pushWriter { + // Initialize and create response + return &pushWriter{ + base: db, + ref: ref, + expected: expected, + tracker: tracker, + pipeC: make(chan *io.PipeWriter, 1), + respC: make(chan *http.Response, 1), + errC: make(chan error, 1), + isManifest: isManifest, + } +} + +func (pw *pushWriter) setPipe(p *io.PipeWriter) { + pw.pipeC <- p +} + +func (pw *pushWriter) setError(err error) { + pw.errC <- err +} +func (pw *pushWriter) setResponse(resp *http.Response) { + pw.respC <- resp +} + func (pw *pushWriter) Write(p []byte) (n int, err error) { status, err := pw.tracker.GetStatus(pw.ref) if err != nil { return n, err } + + if pw.pipe == nil { + p, ok := <-pw.pipeC + if !ok { + return 0, io.ErrClosedPipe + } + pw.pipe = p + } else { + select { + case p, ok := <-pw.pipeC: + if !ok { + return 0, io.ErrClosedPipe + } + pw.pipe.CloseWithError(content.ErrReset) + pw.pipe = p + + // If content has already been written, the bytes + // cannot be written and the caller must reset + status.Offset = 0 + status.UpdatedAt = time.Now() + pw.tracker.SetStatus(pw.ref, status) + return 0, content.ErrReset + default: + } + } + n, err = pw.pipe.Write(p) + if errors.Is(err, io.ErrClosedPipe) { + // if the pipe is closed, we might have the original error on the error + // channel - so we should try and get it + select { + case err2 := <-pw.errC: + err = err2 + default: + } + } status.Offset += int64(n) status.UpdatedAt = time.Now() pw.tracker.SetStatus(pw.ref, status) @@ -355,13 +402,21 @@ func (pw *pushWriter) Write(p []byte) (n int, err error) { } func (pw *pushWriter) Close() error { - status, err := pw.tracker.GetStatus(pw.ref) - if err == nil && !status.Committed { - // Closing an incomplete writer. Record this as an error so that following write can retry it. - status.ErrClosed = errors.New("closed incomplete writer") - pw.tracker.SetStatus(pw.ref, status) + // Ensure pipeC is closed but handle `Close()` being + // called multiple times without panicking + pw.closeOnce.Do(func() { + close(pw.pipeC) + }) + if pw.pipe != nil { + status, err := pw.tracker.GetStatus(pw.ref) + if err == nil && !status.Committed { + // Closing an incomplete writer. Record this as an error so that following write can retry it. + status.ErrClosed = errors.New("closed incomplete writer") + pw.tracker.SetStatus(pw.ref, status) + } + return pw.pipe.Close() } - return pw.pipe.Close() + return nil } func (pw *pushWriter) Status() (content.Status, error) { @@ -380,7 +435,7 @@ func (pw *pushWriter) Digest() digest.Digest { func (pw *pushWriter) Commit(ctx context.Context, size int64, expected digest.Digest, opts ...content.Opt) error { // Check whether read has already thrown an error - if _, err := pw.pipe.Write([]byte{}); err != nil && err != io.ErrClosedPipe { + if _, err := pw.pipe.Write([]byte{}); err != nil && !errors.Is(err, io.ErrClosedPipe) { return fmt.Errorf("pipe error before commit: %w", err) } @@ -388,18 +443,40 @@ func (pw *pushWriter) Commit(ctx context.Context, size int64, expected digest.Di return err } // TODO: timeout waiting for response - resp := <-pw.responseC - if resp.err != nil { - return resp.err + var resp *http.Response + select { + case err := <-pw.errC: + return err + case resp = <-pw.respC: + defer resp.Body.Close() + case p, ok := <-pw.pipeC: + // check whether the pipe has changed in the commit, because sometimes Write + // can complete successfully, but the pipe may have changed. In that case, the + // content needs to be reset. + if !ok { + return io.ErrClosedPipe + } + pw.pipe.CloseWithError(content.ErrReset) + pw.pipe = p + + // If content has already been written, the bytes + // cannot be written again and the caller must reset + status, err := pw.tracker.GetStatus(pw.ref) + if err != nil { + return err + } + status.Offset = 0 + status.UpdatedAt = time.Now() + pw.tracker.SetStatus(pw.ref, status) + return content.ErrReset } - defer resp.Response.Body.Close() // 201 is specified return status, some registries return // 200, 202 or 204. switch resp.StatusCode { case http.StatusOK, http.StatusCreated, http.StatusNoContent, http.StatusAccepted: default: - return remoteserrors.NewUnexpectedStatusErr(resp.Response) + return remoteserrors.NewUnexpectedStatusErr(resp) } status, err := pw.tracker.GetStatus(pw.ref) diff --git a/vendor/github.com/containerd/containerd/remotes/docker/resolver.go b/vendor/github.com/containerd/containerd/remotes/docker/resolver.go index 9bbbc26222..709fa028de 100644 --- a/vendor/github.com/containerd/containerd/remotes/docker/resolver.go +++ b/vendor/github.com/containerd/containerd/remotes/docker/resolver.go @@ -21,6 +21,7 @@ import ( "errors" "fmt" "io" + "net" "net/http" "net/url" "path" @@ -667,3 +668,17 @@ func responseFields(resp *http.Response) logrus.Fields { return logrus.Fields(fields) } + +// IsLocalhost checks if the registry host is local. +func IsLocalhost(host string) bool { + if h, _, err := net.SplitHostPort(host); err == nil { + host = h + } + + if host == "localhost" { + return true + } + + ip := net.ParseIP(host) + return ip.IsLoopback() +} diff --git a/vendor/github.com/containerd/containerd/remotes/handlers.go b/vendor/github.com/containerd/containerd/remotes/handlers.go index 8bcafb22a0..4d91ed2e54 100644 --- a/vendor/github.com/containerd/containerd/remotes/handlers.go +++ b/vendor/github.com/containerd/containerd/remotes/handlers.go @@ -257,8 +257,8 @@ func PushContent(ctx context.Context, pusher Pusher, desc ocispec.Descriptor, st // An example of this kind of content would be a Windows base layer, which is not supposed to be redistributed. // // This is based on the media type of the content: -// - application/vnd.oci.image.layer.nondistributable -// - application/vnd.docker.image.rootfs.foreign +// - application/vnd.oci.image.layer.nondistributable +// - application/vnd.docker.image.rootfs.foreign func SkipNonDistributableBlobs(f images.HandlerFunc) images.HandlerFunc { return func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) { if images.IsNonDistributable(desc.MediaType) { diff --git a/vendor/github.com/containerd/containerd/snapshots/snapshotter.go b/vendor/github.com/containerd/containerd/snapshots/snapshotter.go index 8b0ea85e65..e144fb1583 100644 --- a/vendor/github.com/containerd/containerd/snapshots/snapshotter.go +++ b/vendor/github.com/containerd/containerd/snapshots/snapshotter.go @@ -153,10 +153,10 @@ type WalkFunc func(context.Context, Info) error // For consistency, we define the following terms to be used throughout this // interface for snapshotter implementations: // -// `ctx` - refers to a context.Context -// `key` - refers to an active snapshot -// `name` - refers to a committed snapshot -// `parent` - refers to the parent in relation +// `ctx` - refers to a context.Context +// `key` - refers to an active snapshot +// `name` - refers to a committed snapshot +// `parent` - refers to the parent in relation // // Most methods take various combinations of these identifiers. Typically, // `name` and `parent` will be used in cases where a method *only* takes @@ -168,7 +168,7 @@ type WalkFunc func(context.Context, Info) error // We cover several examples below to demonstrate the utility of a snapshot // snapshotter. // -// Importing a Layer +// # Importing a Layer // // To import a layer, we simply have the Snapshotter provide a list of // mounts to be applied such that our dst will capture a changeset. We start @@ -185,7 +185,7 @@ type WalkFunc func(context.Context, Info) error // "containerd.io/gc.root": time.Now().UTC().Format(time.RFC3339), // }) // mounts, err := snapshotter.Prepare(ctx, key, "", noGcOpt) -// if err != nil { ... } +// if err != nil { ... } // // We get back a list of mounts from Snapshotter.Prepare, with the key identifying // the active snapshot. Mount this to the temporary location with the @@ -202,8 +202,8 @@ type WalkFunc func(context.Context, Info) error // // layer, err := os.Open(layerPath) // if err != nil { ... } -// digest, err := unpackLayer(tmpLocation, layer) // unpack into layer location -// if err != nil { ... } +// digest, err := unpackLayer(tmpLocation, layer) // unpack into layer location +// if err != nil { ... } // // When the above completes, we should have a filesystem the represents the // contents of the layer. Careful implementations should verify that digest @@ -221,30 +221,30 @@ type WalkFunc func(context.Context, Info) error // Now, we have a layer in the Snapshotter that can be accessed with the digest // provided during commit. // -// Importing the Next Layer +// # Importing the Next Layer // // Making a layer depend on the above is identical to the process described // above except that the parent is provided as parent when calling // Manager.Prepare, assuming a clean, unique key identifier: // -// mounts, err := snapshotter.Prepare(ctx, key, parentDigest, noGcOpt) +// mounts, err := snapshotter.Prepare(ctx, key, parentDigest, noGcOpt) // // We then mount, apply and commit, as we did above. The new snapshot will be // based on the content of the previous one. // -// Running a Container +// # Running a Container // // To run a container, we simply provide Snapshotter.Prepare the committed image // snapshot as the parent. After mounting, the prepared path can // be used directly as the container's filesystem: // -// mounts, err := snapshotter.Prepare(ctx, containerKey, imageRootFSChainID) +// mounts, err := snapshotter.Prepare(ctx, containerKey, imageRootFSChainID) // // The returned mounts can then be passed directly to the container runtime. If // one would like to create a new image from the filesystem, Manager.Commit is // called: // -// if err := snapshotter.Commit(ctx, newImageSnapshot, containerKey); err != nil { ... } +// if err := snapshotter.Commit(ctx, newImageSnapshot, containerKey); err != nil { ... } // // Alternatively, for most container runs, Snapshotter.Remove will be called to // signal the Snapshotter to abandon the changes. diff --git a/vendor/github.com/containerd/containerd/version/version.go b/vendor/github.com/containerd/containerd/version/version.go index 806e3e0d73..ca1b6773ab 100644 --- a/vendor/github.com/containerd/containerd/version/version.go +++ b/vendor/github.com/containerd/containerd/version/version.go @@ -23,7 +23,7 @@ var ( Package = "github.com/containerd/containerd" // Version holds the complete version number. Filled in at linking time. - Version = "1.6.3+unknown" + Version = "1.6.18+unknown" // Revision is filled with the VCS (e.g. git) revision being used to build // the program at linking time. diff --git a/vendor/github.com/containerd/continuity/AUTHORS b/vendor/github.com/containerd/continuity/AUTHORS index deef28c1d7..0b4a03cd45 100644 --- a/vendor/github.com/containerd/continuity/AUTHORS +++ b/vendor/github.com/containerd/continuity/AUTHORS @@ -1,8 +1,6 @@ -Aaron Lehmann +Aaron Lehmann Akash Gupta Akihiro Suda -Akihiro Suda -Akihiro Suda Andrew Pennebaker Brandon Philips Brian Goff @@ -10,9 +8,9 @@ Christopher Jones Daniel, Dao Quang Minh Darren Stahl Derek McGowan -Derek McGowan Edward Pilatowicz Fu Wei +Gabriel Adrian Samfira Hajime Tazaki Ian Campbell Ivan Markin @@ -20,20 +18,18 @@ Jacob Blain Christen Justin Cormack Justin Cummins Kasper Fabæch Brandt +Kazuyoshi Kato Kir Kolyshkin Michael Crosby -Michael Crosby Michael Wan Mike Brown Niels de Vos -Phil Estes Phil Estes -Phil Estes Sam Whited Samuel Karp Sebastiaan van Stijn Shengjing Zhu -Stephen J Day +Stephen J Day Tibor Vass Tobias Klauser Tom Faulhaber diff --git a/vendor/github.com/containerd/continuity/fs/copy.go b/vendor/github.com/containerd/continuity/fs/copy.go index 8e23934e99..6982a761ba 100644 --- a/vendor/github.com/containerd/continuity/fs/copy.go +++ b/vendor/github.com/containerd/continuity/fs/copy.go @@ -22,6 +22,8 @@ import ( "os" "path/filepath" "sync" + + "github.com/sirupsen/logrus" ) var bufferPool = &sync.Pool{ @@ -31,7 +33,7 @@ var bufferPool = &sync.Pool{ }, } -// XAttrErrorHandlers transform a non-nil xattr error. +// XAttrErrorHandler transform a non-nil xattr error. // Return nil to ignore an error. // xattrKey can be empty for listxattr operation. type XAttrErrorHandler func(dst, src, xattrKey string, err error) error @@ -152,13 +154,15 @@ func copyDirectory(dst, src string, inodes map[uint64]string, o *copyDirOpts) er if err := os.Symlink(link, target); err != nil { return fmt.Errorf("failed to create symlink: %s: %w", target, err) } - case (fi.Mode() & os.ModeDevice) == os.ModeDevice: - if err := copyDevice(target, fi); err != nil { - return fmt.Errorf("failed to create device: %w", err) + case (fi.Mode() & os.ModeDevice) == os.ModeDevice, + (fi.Mode() & os.ModeNamedPipe) == os.ModeNamedPipe, + (fi.Mode() & os.ModeSocket) == os.ModeSocket: + if err := copyIrregular(target, fi); err != nil { + return fmt.Errorf("failed to create irregular file: %w", err) } default: - // TODO: Support pipes and sockets - return fmt.Errorf("unsupported mode %s: %w", fi.Mode(), err) + logrus.Warnf("unsupported mode: %s: %s", source, fi.Mode()) + continue } if err := copyFileInfo(fi, source, target); err != nil { diff --git a/vendor/github.com/containerd/continuity/fs/copy_darwin.go b/vendor/github.com/containerd/continuity/fs/copy_darwin.go deleted file mode 100644 index ce55f0aa24..0000000000 --- a/vendor/github.com/containerd/continuity/fs/copy_darwin.go +++ /dev/null @@ -1,36 +0,0 @@ -//go:build darwin -// +build darwin - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package fs - -import ( - "errors" - "os" - "syscall" - - "golang.org/x/sys/unix" -) - -func copyDevice(dst string, fi os.FileInfo) error { - st, ok := fi.Sys().(*syscall.Stat_t) - if !ok { - return errors.New("unsupported stat type") - } - return unix.Mknod(dst, uint32(fi.Mode()), int(st.Rdev)) -} diff --git a/vendor/github.com/containerd/continuity/fs/copy_device_unix.go b/vendor/github.com/containerd/continuity/fs/copy_device_unix.go deleted file mode 100644 index f821890cb7..0000000000 --- a/vendor/github.com/containerd/continuity/fs/copy_device_unix.go +++ /dev/null @@ -1,36 +0,0 @@ -//go:build openbsd || solaris || netbsd -// +build openbsd solaris netbsd - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package fs - -import ( - "errors" - "os" - "syscall" - - "golang.org/x/sys/unix" -) - -func copyDevice(dst string, fi os.FileInfo) error { - st, ok := fi.Sys().(*syscall.Stat_t) - if !ok { - return errors.New("unsupported stat type") - } - return unix.Mknod(dst, uint32(fi.Mode()), int(st.Rdev)) -} diff --git a/vendor/github.com/containerd/continuity/fs/copy_freebsd.go b/vendor/github.com/containerd/continuity/fs/copy_freebsd.go deleted file mode 100644 index 4aaf743e5a..0000000000 --- a/vendor/github.com/containerd/continuity/fs/copy_freebsd.go +++ /dev/null @@ -1,36 +0,0 @@ -//go:build freebsd -// +build freebsd - -/* - Copyright The containerd Authors. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -package fs - -import ( - "errors" - "os" - "syscall" - - "golang.org/x/sys/unix" -) - -func copyDevice(dst string, fi os.FileInfo) error { - st, ok := fi.Sys().(*syscall.Stat_t) - if !ok { - return errors.New("unsupported stat type") - } - return unix.Mknod(dst, uint32(fi.Mode()), st.Rdev) -} diff --git a/vendor/github.com/containerd/continuity/fs/copy_irregular_freebsd.go b/vendor/github.com/containerd/continuity/fs/copy_irregular_freebsd.go new file mode 100644 index 0000000000..cfe9d80204 --- /dev/null +++ b/vendor/github.com/containerd/continuity/fs/copy_irregular_freebsd.go @@ -0,0 +1,36 @@ +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package fs + +import ( + "fmt" + "os" + "syscall" +) + +// copyIrregular covers devices, pipes, and sockets +func copyIrregular(dst string, fi os.FileInfo) error { + st, ok := fi.Sys().(*syscall.Stat_t) // not *unix.Stat_t + if !ok { + return fmt.Errorf("unsupported stat type: %s: %v", dst, fi.Mode()) + } + var rDev uint64 // uint64 on FreeBSD, int on other unixen + if fi.Mode()&os.ModeDevice == os.ModeDevice { + rDev = st.Rdev + } + return syscall.Mknod(dst, uint32(st.Mode), rDev) +} diff --git a/vendor/github.com/containerd/continuity/fs/copy_irregular_unix.go b/vendor/github.com/containerd/continuity/fs/copy_irregular_unix.go new file mode 100644 index 0000000000..99fc8a9651 --- /dev/null +++ b/vendor/github.com/containerd/continuity/fs/copy_irregular_unix.go @@ -0,0 +1,40 @@ +//go:build !windows && !freebsd +// +build !windows,!freebsd + +/* + Copyright The containerd Authors. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package fs + +import ( + "fmt" + "os" + "syscall" +) + +// copyIrregular covers devices, pipes, and sockets +func copyIrregular(dst string, fi os.FileInfo) error { + st, ok := fi.Sys().(*syscall.Stat_t) // not *unix.Stat_t + if !ok { + return fmt.Errorf("unsupported stat type: %s: %v", dst, fi.Mode()) + } + var rDev int + if fi.Mode()&os.ModeDevice == os.ModeDevice { + rDev = int(st.Rdev) + } + //nolint:unconvert + return syscall.Mknod(dst, uint32(st.Mode), rDev) +} diff --git a/vendor/github.com/containerd/continuity/fs/copy_linux.go b/vendor/github.com/containerd/continuity/fs/copy_linux.go index 938407662c..1906e5e011 100644 --- a/vendor/github.com/containerd/continuity/fs/copy_linux.go +++ b/vendor/github.com/containerd/continuity/fs/copy_linux.go @@ -17,7 +17,6 @@ package fs import ( - "errors" "fmt" "io" "os" @@ -144,11 +143,3 @@ func copyXAttrs(dst, src string, excludes map[string]struct{}, errorHandler XAtt return nil } - -func copyDevice(dst string, fi os.FileInfo) error { - st, ok := fi.Sys().(*syscall.Stat_t) - if !ok { - return errors.New("unsupported stat type") - } - return unix.Mknod(dst, uint32(fi.Mode()), int(st.Rdev)) -} diff --git a/vendor/github.com/containerd/continuity/fs/copy_windows.go b/vendor/github.com/containerd/continuity/fs/copy_windows.go index e3f0cdd58d..4dad9441de 100644 --- a/vendor/github.com/containerd/continuity/fs/copy_windows.go +++ b/vendor/github.com/containerd/continuity/fs/copy_windows.go @@ -85,6 +85,6 @@ func copyXAttrs(dst, src string, excludes map[string]struct{}, errorHandler XAtt return nil } -func copyDevice(dst string, fi os.FileInfo) error { - return errors.New("device copy not supported") +func copyIrregular(dst string, fi os.FileInfo) error { + return errors.New("irregular copy not supported") } diff --git a/vendor/github.com/containerd/continuity/fs/diff.go b/vendor/github.com/containerd/continuity/fs/diff.go index e64f9e73d3..3cd4eee6fb 100644 --- a/vendor/github.com/containerd/continuity/fs/diff.go +++ b/vendor/github.com/containerd/continuity/fs/diff.go @@ -22,9 +22,8 @@ import ( "path/filepath" "strings" - "golang.org/x/sync/errgroup" - "github.com/sirupsen/logrus" + "golang.org/x/sync/errgroup" ) // ChangeKind is the type of modification that diff --git a/vendor/github.com/containerd/continuity/fs/dtype_linux.go b/vendor/github.com/containerd/continuity/fs/dtype_linux.go index ddd6c79375..a8eab1db8a 100644 --- a/vendor/github.com/containerd/continuity/fs/dtype_linux.go +++ b/vendor/github.com/containerd/continuity/fs/dtype_linux.go @@ -35,7 +35,7 @@ func locateDummyIfEmpty(path string) (string, error) { if len(children) != 0 { return "", nil } - dummyFile, err := ioutil.TempFile(path, "fsutils-dummy") + dummyFile, err := os.CreateTemp(path, "fsutils-dummy") if err != nil { return "", err } diff --git a/vendor/github.com/containerd/continuity/sysx/generate.sh b/vendor/github.com/containerd/continuity/sysx/generate.sh deleted file mode 100644 index 87d708d7ae..0000000000 --- a/vendor/github.com/containerd/continuity/sysx/generate.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/bin/bash - -# Copyright The containerd Authors. - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -set -e - -mksyscall="$(go env GOROOT)/src/syscall/mksyscall.pl" - -fix() { - sed 's,^package syscall$,package sysx,' \ - | sed 's,^import "unsafe"$,import (\n\t"syscall"\n\t"unsafe"\n),' \ - | gofmt -r='BytePtrFromString -> syscall.BytePtrFromString' \ - | gofmt -r='Syscall6 -> syscall.Syscall6' \ - | gofmt -r='Syscall -> syscall.Syscall' \ - | gofmt -r='SYS_GETXATTR -> syscall.SYS_GETXATTR' \ - | gofmt -r='SYS_LISTXATTR -> syscall.SYS_LISTXATTR' \ - | gofmt -r='SYS_SETXATTR -> syscall.SYS_SETXATTR' \ - | gofmt -r='SYS_REMOVEXATTR -> syscall.SYS_REMOVEXATTR' \ - | gofmt -r='SYS_LGETXATTR -> syscall.SYS_LGETXATTR' \ - | gofmt -r='SYS_LLISTXATTR -> syscall.SYS_LLISTXATTR' \ - | gofmt -r='SYS_LSETXATTR -> syscall.SYS_LSETXATTR' \ - | gofmt -r='SYS_LREMOVEXATTR -> syscall.SYS_LREMOVEXATTR' -} - -if [ "$GOARCH" == "" ] || [ "$GOOS" == "" ]; then - echo "Must specify \$GOARCH and \$GOOS" - exit 1 -fi - -mkargs="" - -if [ "$GOARCH" == "386" ] || [ "$GOARCH" == "arm" ]; then - mkargs="-l32" -fi - -for f in "$@"; do - $mksyscall $mkargs "${f}_${GOOS}.go" | fix > "${f}_${GOOS}_${GOARCH}.go" -done - diff --git a/vendor/github.com/coreos/go-systemd/v22/daemon/watchdog.go b/vendor/github.com/coreos/go-systemd/v22/daemon/watchdog.go index 7a0e0d3a51..25d9c1aa93 100644 --- a/vendor/github.com/coreos/go-systemd/v22/daemon/watchdog.go +++ b/vendor/github.com/coreos/go-systemd/v22/daemon/watchdog.go @@ -30,8 +30,8 @@ import ( // It returns one of the following: // (0, nil) - watchdog isn't enabled or we aren't the watched PID. // (0, err) - an error happened (e.g. error converting time). -// (time, nil) - watchdog is enabled and we can send ping. -// time is delay before inactive service will be killed. +// (time, nil) - watchdog is enabled and we can send ping. time is delay +// before inactive service will be killed. func SdWatchdogEnabled(unsetEnvironment bool) (time.Duration, error) { wusec := os.Getenv("WATCHDOG_USEC") wpid := os.Getenv("WATCHDOG_PID") diff --git a/vendor/github.com/coreos/go-systemd/v22/journal/journal_unix.go b/vendor/github.com/coreos/go-systemd/v22/journal/journal_unix.go index 8d58ca0fbc..439ad28746 100644 --- a/vendor/github.com/coreos/go-systemd/v22/journal/journal_unix.go +++ b/vendor/github.com/coreos/go-systemd/v22/journal/journal_unix.go @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !windows // +build !windows // Package journal provides write bindings to the local systemd journal. @@ -53,15 +54,9 @@ var ( onceConn sync.Once ) -func init() { - onceConn.Do(initConn) -} - // Enabled checks whether the local systemd journal is available for logging. func Enabled() bool { - onceConn.Do(initConn) - - if (*net.UnixConn)(atomic.LoadPointer(&unixConnPtr)) == nil { + if c := getOrInitConn(); c == nil { return false } @@ -82,7 +77,7 @@ func Enabled() bool { // (http://www.freedesktop.org/software/systemd/man/systemd.journal-fields.html) // for more details. vars may be nil. func Send(message string, priority Priority, vars map[string]string) error { - conn := (*net.UnixConn)(atomic.LoadPointer(&unixConnPtr)) + conn := getOrInitConn() if conn == nil { return errors.New("could not initialize socket to journald") } @@ -126,6 +121,16 @@ func Send(message string, priority Priority, vars map[string]string) error { return nil } +// getOrInitConn attempts to get the global `unixConnPtr` socket, initializing if necessary +func getOrInitConn() *net.UnixConn { + conn := (*net.UnixConn)(atomic.LoadPointer(&unixConnPtr)) + if conn != nil { + return conn + } + onceConn.Do(initConn) + return (*net.UnixConn)(atomic.LoadPointer(&unixConnPtr)) +} + func appendVariable(w io.Writer, name, value string) { if err := validVarName(name); err != nil { fmt.Fprintf(os.Stderr, "variable name %s contains invalid character, ignoring\n", name) @@ -194,7 +199,7 @@ func tempFd() (*os.File, error) { } // initConn initializes the global `unixConnPtr` socket. -// It is meant to be called exactly once, at program startup. +// It is automatically called when needed. func initConn() { autobind, err := net.ResolveUnixAddr("unixgram", "") if err != nil { diff --git a/vendor/github.com/docker/cli/cli/config/config.go b/vendor/github.com/docker/cli/cli/config/config.go index 93275f3d98..31ad117d41 100644 --- a/vendor/github.com/docker/cli/cli/config/config.go +++ b/vendor/github.com/docker/cli/cli/config/config.go @@ -104,14 +104,18 @@ func LoadFromReader(configData io.Reader) (*configfile.ConfigFile, error) { return &configFile, err } -// TODO remove this temporary hack, which is used to warn about the deprecated ~/.dockercfg file -var printLegacyFileWarning bool - // Load reads the configuration files in the given directory, and sets up // the auth config information and returns values. // FIXME: use the internal golang config parser func Load(configDir string) (*configfile.ConfigFile, error) { - printLegacyFileWarning = false + cfg, _, err := load(configDir) + return cfg, err +} + +// TODO remove this temporary hack, which is used to warn about the deprecated ~/.dockercfg file +// so we can remove the bool return value and collapse this back into `Load` +func load(configDir string) (*configfile.ConfigFile, bool, error) { + printLegacyFileWarning := false if configDir == "" { configDir = Dir() @@ -127,11 +131,11 @@ func Load(configDir string) (*configfile.ConfigFile, error) { if err != nil { err = errors.Wrap(err, filename) } - return configFile, err + return configFile, printLegacyFileWarning, err } else if !os.IsNotExist(err) { // if file is there but we can't stat it for any reason other // than it doesn't exist then stop - return configFile, errors.Wrap(err, filename) + return configFile, printLegacyFileWarning, errors.Wrap(err, filename) } // Can't find latest config file so check for the old one @@ -140,16 +144,16 @@ func Load(configDir string) (*configfile.ConfigFile, error) { printLegacyFileWarning = true defer file.Close() if err := configFile.LegacyLoadFromReader(file); err != nil { - return configFile, errors.Wrap(err, filename) + return configFile, printLegacyFileWarning, errors.Wrap(err, filename) } } - return configFile, nil + return configFile, printLegacyFileWarning, nil } // LoadDefaultConfigFile attempts to load the default config file and returns // an initialized ConfigFile struct if none is found. func LoadDefaultConfigFile(stderr io.Writer) *configfile.ConfigFile { - configFile, err := Load(Dir()) + configFile, printLegacyFileWarning, err := load(Dir()) if err != nil { fmt.Fprintf(stderr, "WARNING: Error loading config file: %v\n", err) } diff --git a/vendor/github.com/docker/cli/cli/config/configfile/file.go b/vendor/github.com/docker/cli/cli/config/configfile/file.go index dc9f39eb7e..d6f710817a 100644 --- a/vendor/github.com/docker/cli/cli/config/configfile/file.go +++ b/vendor/github.com/docker/cli/cli/config/configfile/file.go @@ -119,7 +119,7 @@ func (configFile *ConfigFile) LegacyLoadFromReader(configData io.Reader) error { // LoadFromReader reads the configuration data given and sets up the auth config // information with given directory and populates the receiver object func (configFile *ConfigFile) LoadFromReader(configData io.Reader) error { - if err := json.NewDecoder(configData).Decode(&configFile); err != nil && !errors.Is(err, io.EOF) { + if err := json.NewDecoder(configData).Decode(configFile); err != nil && !errors.Is(err, io.EOF) { return err } var err error diff --git a/vendor/github.com/docker/cli/cli/config/configfile/file_unix.go b/vendor/github.com/docker/cli/cli/config/configfile/file_unix.go index 3ca65c6140..6af6718126 100644 --- a/vendor/github.com/docker/cli/cli/config/configfile/file_unix.go +++ b/vendor/github.com/docker/cli/cli/config/configfile/file_unix.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows package configfile diff --git a/vendor/github.com/docker/cli/cli/config/credentials/default_store_unsupported.go b/vendor/github.com/docker/cli/cli/config/credentials/default_store_unsupported.go index 3028168ac2..c9630ea51b 100644 --- a/vendor/github.com/docker/cli/cli/config/credentials/default_store_unsupported.go +++ b/vendor/github.com/docker/cli/cli/config/credentials/default_store_unsupported.go @@ -1,3 +1,4 @@ +//go:build !windows && !darwin && !linux // +build !windows,!darwin,!linux package credentials diff --git a/vendor/github.com/docker/cli/cli/config/credentials/native_store.go b/vendor/github.com/docker/cli/cli/config/credentials/native_store.go index afe542cc3c..f9619b0381 100644 --- a/vendor/github.com/docker/cli/cli/config/credentials/native_store.go +++ b/vendor/github.com/docker/cli/cli/config/credentials/native_store.go @@ -7,7 +7,7 @@ import ( ) const ( - remoteCredentialsPrefix = "docker-credential-" + remoteCredentialsPrefix = "docker-credential-" //nolint:gosec // ignore G101: Potential hardcoded credentials tokenUsername = "" ) diff --git a/vendor/github.com/docker/docker-credential-helpers/credentials/credentials.go b/vendor/github.com/docker/docker-credential-helpers/credentials/credentials.go index da8b594e7f..91d9d4bbae 100644 --- a/vendor/github.com/docker/docker-credential-helpers/credentials/credentials.go +++ b/vendor/github.com/docker/docker-credential-helpers/credentials/credentials.go @@ -169,8 +169,8 @@ func Erase(helper Helper, reader io.Reader) error { return helper.Delete(serverURL) } -//List returns all the serverURLs of keys in -//the OS store as a list of strings +// List returns all the serverURLs of keys in +// the OS store as a list of strings func List(helper Helper, writer io.Writer) error { accts, err := helper.List() if err != nil { @@ -179,8 +179,8 @@ func List(helper Helper, writer io.Writer) error { return json.NewEncoder(writer).Encode(accts) } -//PrintVersion outputs the current version. +// PrintVersion outputs the current version. func PrintVersion(writer io.Writer) error { - fmt.Fprintln(writer, Version) + fmt.Fprintf(writer, "%s (%s) %s\n", Name, Package, Version) return nil } diff --git a/vendor/github.com/docker/docker-credential-helpers/credentials/version.go b/vendor/github.com/docker/docker-credential-helpers/credentials/version.go index 185e367961..84377c2630 100644 --- a/vendor/github.com/docker/docker-credential-helpers/credentials/version.go +++ b/vendor/github.com/docker/docker-credential-helpers/credentials/version.go @@ -1,4 +1,16 @@ package credentials -// Version holds a string describing the current version -const Version = "0.6.4" +var ( + // Name is filled at linking time + Name = "" + + // Package is filled at linking time + Package = "github.com/docker/docker-credential-helpers" + + // Version holds the complete version number. Filled in at linking time. + Version = "v0.0.0+unknown" + + // Revision is filled with the VCS (e.g. git) revision being used to build + // the program at linking time. + Revision = "" +) diff --git a/vendor/github.com/docker/docker/api/types/container/hostconfig_unix.go b/vendor/github.com/docker/docker/api/types/container/hostconfig_unix.go index cf6fdf4402..24c4fa8d90 100644 --- a/vendor/github.com/docker/docker/api/types/container/hostconfig_unix.go +++ b/vendor/github.com/docker/docker/api/types/container/hostconfig_unix.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows package container // import "github.com/docker/docker/api/types/container" diff --git a/vendor/github.com/docker/docker/api/types/filters/parse.go b/vendor/github.com/docker/docker/api/types/filters/parse.go index 4bc91cffd6..b4976a3471 100644 --- a/vendor/github.com/docker/docker/api/types/filters/parse.go +++ b/vendor/github.com/docker/docker/api/types/filters/parse.go @@ -1,4 +1,5 @@ -/*Package filters provides tools for encoding a mapping of keys to a set of +/* +Package filters provides tools for encoding a mapping of keys to a set of multiple values. */ package filters // import "github.com/docker/docker/api/types/filters" @@ -48,7 +49,7 @@ func (args Args) Keys() []string { // MarshalJSON returns a JSON byte representation of the Args func (args Args) MarshalJSON() ([]byte, error) { if len(args.fields) == 0 { - return []byte{}, nil + return []byte("{}"), nil } return json.Marshal(args.fields) } @@ -106,9 +107,6 @@ func FromJSON(p string) (Args, error) { // UnmarshalJSON populates the Args from JSON encode bytes func (args Args) UnmarshalJSON(raw []byte) error { - if len(raw) == 0 { - return nil - } return json.Unmarshal(raw, &args.fields) } diff --git a/vendor/github.com/docker/docker/api/types/registry/registry.go b/vendor/github.com/docker/docker/api/types/registry/registry.go index 53e47084c8..62a88f5be8 100644 --- a/vendor/github.com/docker/docker/api/types/registry/registry.go +++ b/vendor/github.com/docker/docker/api/types/registry/registry.go @@ -45,31 +45,32 @@ func (ipnet *NetIPNet) UnmarshalJSON(b []byte) (err error) { // IndexInfo contains information about a registry // // RepositoryInfo Examples: -// { -// "Index" : { -// "Name" : "docker.io", -// "Mirrors" : ["https://registry-2.docker.io/v1/", "https://registry-3.docker.io/v1/"], -// "Secure" : true, -// "Official" : true, -// }, -// "RemoteName" : "library/debian", -// "LocalName" : "debian", -// "CanonicalName" : "docker.io/debian" -// "Official" : true, -// } // -// { -// "Index" : { -// "Name" : "127.0.0.1:5000", -// "Mirrors" : [], -// "Secure" : false, -// "Official" : false, -// }, -// "RemoteName" : "user/repo", -// "LocalName" : "127.0.0.1:5000/user/repo", -// "CanonicalName" : "127.0.0.1:5000/user/repo", -// "Official" : false, -// } +// { +// "Index" : { +// "Name" : "docker.io", +// "Mirrors" : ["https://registry-2.docker.io/v1/", "https://registry-3.docker.io/v1/"], +// "Secure" : true, +// "Official" : true, +// }, +// "RemoteName" : "library/debian", +// "LocalName" : "debian", +// "CanonicalName" : "docker.io/debian" +// "Official" : true, +// } +// +// { +// "Index" : { +// "Name" : "127.0.0.1:5000", +// "Mirrors" : [], +// "Secure" : false, +// "Official" : false, +// }, +// "RemoteName" : "user/repo", +// "LocalName" : "127.0.0.1:5000/user/repo", +// "CanonicalName" : "127.0.0.1:5000/user/repo", +// "Official" : false, +// } type IndexInfo struct { // Name is the name of the registry, such as "docker.io" Name string diff --git a/vendor/github.com/docker/docker/errdefs/http_helpers.go b/vendor/github.com/docker/docker/errdefs/http_helpers.go index 07552f1cc1..5afe486779 100644 --- a/vendor/github.com/docker/docker/errdefs/http_helpers.go +++ b/vendor/github.com/docker/docker/errdefs/http_helpers.go @@ -1,78 +1,11 @@ package errdefs // import "github.com/docker/docker/errdefs" import ( - "fmt" "net/http" - containerderrors "github.com/containerd/containerd/errdefs" - "github.com/docker/distribution/registry/api/errcode" "github.com/sirupsen/logrus" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" ) -// GetHTTPErrorStatusCode retrieves status code from error message. -func GetHTTPErrorStatusCode(err error) int { - if err == nil { - logrus.WithFields(logrus.Fields{"error": err}).Error("unexpected HTTP error handling") - return http.StatusInternalServerError - } - - var statusCode int - - // Stop right there - // Are you sure you should be adding a new error class here? Do one of the existing ones work? - - // Note that the below functions are already checking the error causal chain for matches. - switch { - case IsNotFound(err): - statusCode = http.StatusNotFound - case IsInvalidParameter(err): - statusCode = http.StatusBadRequest - case IsConflict(err): - statusCode = http.StatusConflict - case IsUnauthorized(err): - statusCode = http.StatusUnauthorized - case IsUnavailable(err): - statusCode = http.StatusServiceUnavailable - case IsForbidden(err): - statusCode = http.StatusForbidden - case IsNotModified(err): - statusCode = http.StatusNotModified - case IsNotImplemented(err): - statusCode = http.StatusNotImplemented - case IsSystem(err) || IsUnknown(err) || IsDataLoss(err) || IsDeadline(err) || IsCancelled(err): - statusCode = http.StatusInternalServerError - default: - statusCode = statusCodeFromGRPCError(err) - if statusCode != http.StatusInternalServerError { - return statusCode - } - statusCode = statusCodeFromContainerdError(err) - if statusCode != http.StatusInternalServerError { - return statusCode - } - statusCode = statusCodeFromDistributionError(err) - if statusCode != http.StatusInternalServerError { - return statusCode - } - if e, ok := err.(causer); ok { - return GetHTTPErrorStatusCode(e.Cause()) - } - - logrus.WithFields(logrus.Fields{ - "module": "api", - "error_type": fmt.Sprintf("%T", err), - }).Debugf("FIXME: Got an API for which error does not match any expected type!!!: %+v", err) - } - - if statusCode == 0 { - statusCode = http.StatusInternalServerError - } - - return statusCode -} - // FromStatusCode creates an errdef error, based on the provided HTTP status-code func FromStatusCode(err error, statusCode int) error { if err == nil { @@ -100,10 +33,10 @@ func FromStatusCode(err error, statusCode int) error { err = System(err) } default: - logrus.WithFields(logrus.Fields{ + logrus.WithError(err).WithFields(logrus.Fields{ "module": "api", - "status_code": fmt.Sprintf("%d", statusCode), - }).Debugf("FIXME: Got an status-code for which error does not match any expected type!!!: %d", statusCode) + "status_code": statusCode, + }).Debug("FIXME: Got an status-code for which error does not match any expected type!!!") switch { case statusCode >= 200 && statusCode < 400: @@ -118,74 +51,3 @@ func FromStatusCode(err error, statusCode int) error { } return err } - -// statusCodeFromGRPCError returns status code according to gRPC error -func statusCodeFromGRPCError(err error) int { - switch status.Code(err) { - case codes.InvalidArgument: // code 3 - return http.StatusBadRequest - case codes.NotFound: // code 5 - return http.StatusNotFound - case codes.AlreadyExists: // code 6 - return http.StatusConflict - case codes.PermissionDenied: // code 7 - return http.StatusForbidden - case codes.FailedPrecondition: // code 9 - return http.StatusBadRequest - case codes.Unauthenticated: // code 16 - return http.StatusUnauthorized - case codes.OutOfRange: // code 11 - return http.StatusBadRequest - case codes.Unimplemented: // code 12 - return http.StatusNotImplemented - case codes.Unavailable: // code 14 - return http.StatusServiceUnavailable - default: - // codes.Canceled(1) - // codes.Unknown(2) - // codes.DeadlineExceeded(4) - // codes.ResourceExhausted(8) - // codes.Aborted(10) - // codes.Internal(13) - // codes.DataLoss(15) - return http.StatusInternalServerError - } -} - -// statusCodeFromDistributionError returns status code according to registry errcode -// code is loosely based on errcode.ServeJSON() in docker/distribution -func statusCodeFromDistributionError(err error) int { - switch errs := err.(type) { - case errcode.Errors: - if len(errs) < 1 { - return http.StatusInternalServerError - } - if _, ok := errs[0].(errcode.ErrorCoder); ok { - return statusCodeFromDistributionError(errs[0]) - } - case errcode.ErrorCoder: - return errs.ErrorCode().Descriptor().HTTPStatusCode - } - return http.StatusInternalServerError -} - -// statusCodeFromContainerdError returns status code for containerd errors when -// consumed directly (not through gRPC) -func statusCodeFromContainerdError(err error) int { - switch { - case containerderrors.IsInvalidArgument(err): - return http.StatusBadRequest - case containerderrors.IsNotFound(err): - return http.StatusNotFound - case containerderrors.IsAlreadyExists(err): - return http.StatusConflict - case containerderrors.IsFailedPrecondition(err): - return http.StatusPreconditionFailed - case containerderrors.IsUnavailable(err): - return http.StatusServiceUnavailable - case containerderrors.IsNotImplemented(err): - return http.StatusNotImplemented - default: - return http.StatusInternalServerError - } -} diff --git a/vendor/github.com/docker/docker/pkg/homedir/homedir_others.go b/vendor/github.com/docker/docker/pkg/homedir/homedir_others.go index 67ab9e9b31..fc48e674c1 100644 --- a/vendor/github.com/docker/docker/pkg/homedir/homedir_others.go +++ b/vendor/github.com/docker/docker/pkg/homedir/homedir_others.go @@ -1,3 +1,4 @@ +//go:build !linux // +build !linux package homedir // import "github.com/docker/docker/pkg/homedir" diff --git a/vendor/github.com/docker/docker/pkg/homedir/homedir_unix.go b/vendor/github.com/docker/docker/pkg/homedir/homedir_unix.go index 441bd727b6..d1732dee52 100644 --- a/vendor/github.com/docker/docker/pkg/homedir/homedir_unix.go +++ b/vendor/github.com/docker/docker/pkg/homedir/homedir_unix.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows package homedir // import "github.com/docker/docker/pkg/homedir" diff --git a/vendor/github.com/docker/docker/pkg/ioutils/fswriters.go b/vendor/github.com/docker/docker/pkg/ioutils/fswriters.go index 534d66ac26..82671d8cd5 100644 --- a/vendor/github.com/docker/docker/pkg/ioutils/fswriters.go +++ b/vendor/github.com/docker/docker/pkg/ioutils/fswriters.go @@ -2,7 +2,6 @@ package ioutils // import "github.com/docker/docker/pkg/ioutils" import ( "io" - "io/ioutil" "os" "path/filepath" ) @@ -11,7 +10,7 @@ import ( // temporary file and closing it atomically changes the temporary file to // destination path. Writing and closing concurrently is not allowed. func NewAtomicFileWriter(filename string, perm os.FileMode) (io.WriteCloser, error) { - f, err := ioutil.TempFile(filepath.Dir(filename), ".tmp-"+filepath.Base(filename)) + f, err := os.CreateTemp(filepath.Dir(filename), ".tmp-"+filepath.Base(filename)) if err != nil { return nil, err } @@ -94,7 +93,7 @@ type AtomicWriteSet struct { // commit. If no temporary directory is given the system // default is used. func NewAtomicWriteSet(tmpDir string) (*AtomicWriteSet, error) { - td, err := ioutil.TempDir(tmpDir, "write-set-") + td, err := os.MkdirTemp(tmpDir, "write-set-") if err != nil { return nil, err } diff --git a/vendor/github.com/docker/docker/pkg/ioutils/temp_unix.go b/vendor/github.com/docker/docker/pkg/ioutils/temp_unix.go index dc894f9131..7489122309 100644 --- a/vendor/github.com/docker/docker/pkg/ioutils/temp_unix.go +++ b/vendor/github.com/docker/docker/pkg/ioutils/temp_unix.go @@ -1,10 +1,11 @@ +//go:build !windows // +build !windows package ioutils // import "github.com/docker/docker/pkg/ioutils" -import "io/ioutil" +import "os" -// TempDir on Unix systems is equivalent to ioutil.TempDir. +// TempDir on Unix systems is equivalent to os.MkdirTemp. func TempDir(dir, prefix string) (string, error) { - return ioutil.TempDir(dir, prefix) + return os.MkdirTemp(dir, prefix) } diff --git a/vendor/github.com/docker/docker/pkg/ioutils/temp_windows.go b/vendor/github.com/docker/docker/pkg/ioutils/temp_windows.go index ecaba2e36d..a57fd9af6a 100644 --- a/vendor/github.com/docker/docker/pkg/ioutils/temp_windows.go +++ b/vendor/github.com/docker/docker/pkg/ioutils/temp_windows.go @@ -1,14 +1,14 @@ package ioutils // import "github.com/docker/docker/pkg/ioutils" import ( - "io/ioutil" + "os" "github.com/docker/docker/pkg/longpath" ) -// TempDir is the equivalent of ioutil.TempDir, except that the result is in Windows longpath format. +// TempDir is the equivalent of os.MkdirTemp, except that the result is in Windows longpath format. func TempDir(dir, prefix string) (string, error) { - tempDir, err := ioutil.TempDir(dir, prefix) + tempDir, err := os.MkdirTemp(dir, prefix) if err != nil { return "", err } diff --git a/vendor/github.com/docker/docker/pkg/term/deprecated.go b/vendor/github.com/docker/docker/pkg/term/deprecated.go deleted file mode 100644 index 4d18168fc2..0000000000 --- a/vendor/github.com/docker/docker/pkg/term/deprecated.go +++ /dev/null @@ -1,84 +0,0 @@ -// Package term provides structures and helper functions to work with -// terminal (state, sizes). -// -// Deprecated: use github.com/moby/term instead -package term // import "github.com/docker/docker/pkg/term" - -import ( - "github.com/moby/term" -) - -// EscapeError is special error which returned by a TTY proxy reader's Read() -// method in case its detach escape sequence is read. -// Deprecated: use github.com/moby/term.EscapeError -type EscapeError = term.EscapeError - -// State represents the state of the terminal. -// Deprecated: use github.com/moby/term.State -type State = term.State - -// Winsize represents the size of the terminal window. -// Deprecated: use github.com/moby/term.Winsize -type Winsize = term.Winsize - -var ( - // ASCII list the possible supported ASCII key sequence - ASCII = term.ASCII - - // ToBytes converts a string representing a suite of key-sequence to the corresponding ASCII code. - // Deprecated: use github.com/moby/term.ToBytes - ToBytes = term.ToBytes - - // StdStreams returns the standard streams (stdin, stdout, stderr). - // Deprecated: use github.com/moby/term.StdStreams - StdStreams = term.StdStreams - - // GetFdInfo returns the file descriptor for an os.File and indicates whether the file represents a terminal. - // Deprecated: use github.com/moby/term.GetFdInfo - GetFdInfo = term.GetFdInfo - - // GetWinsize returns the window size based on the specified file descriptor. - // Deprecated: use github.com/moby/term.GetWinsize - GetWinsize = term.GetWinsize - - // IsTerminal returns true if the given file descriptor is a terminal. - // Deprecated: use github.com/moby/term.IsTerminal - IsTerminal = term.IsTerminal - - // RestoreTerminal restores the terminal connected to the given file descriptor - // to a previous state. - // Deprecated: use github.com/moby/term.RestoreTerminal - RestoreTerminal = term.RestoreTerminal - - // SaveState saves the state of the terminal connected to the given file descriptor. - // Deprecated: use github.com/moby/term.SaveState - SaveState = term.SaveState - - // DisableEcho applies the specified state to the terminal connected to the file - // descriptor, with echo disabled. - // Deprecated: use github.com/moby/term.DisableEcho - DisableEcho = term.DisableEcho - - // SetRawTerminal puts the terminal connected to the given file descriptor into - // raw mode and returns the previous state. On UNIX, this puts both the input - // and output into raw mode. On Windows, it only puts the input into raw mode. - // Deprecated: use github.com/moby/term.SetRawTerminal - SetRawTerminal = term.SetRawTerminal - - // SetRawTerminalOutput puts the output of terminal connected to the given file - // descriptor into raw mode. On UNIX, this does nothing and returns nil for the - // state. On Windows, it disables LF -> CRLF translation. - // Deprecated: use github.com/moby/term.SetRawTerminalOutput - SetRawTerminalOutput = term.SetRawTerminalOutput - - // MakeRaw puts the terminal connected to the given file descriptor into raw - // mode and returns the previous state of the terminal so that it can be restored. - // Deprecated: use github.com/moby/term.MakeRaw - MakeRaw = term.MakeRaw - - // NewEscapeProxy returns a new TTY proxy reader which wraps the given reader - // and detects when the specified escape keys are read, in which case the Read - // method will return an error of type EscapeError. - // Deprecated: use github.com/moby/term.NewEscapeProxy - NewEscapeProxy = term.NewEscapeProxy -) diff --git a/vendor/github.com/docker/docker/pkg/term/deprecated_unix.go b/vendor/github.com/docker/docker/pkg/term/deprecated_unix.go deleted file mode 100644 index ed9eb11862..0000000000 --- a/vendor/github.com/docker/docker/pkg/term/deprecated_unix.go +++ /dev/null @@ -1,20 +0,0 @@ -// +build !windows - -package term // import "github.com/docker/docker/pkg/term" - -import ( - "github.com/moby/term" -) - -// Termios is the Unix API for terminal I/O. -// Deprecated: use github.com/moby/term.Termios -type Termios = term.Termios - -var ( - // ErrInvalidState is returned if the state of the terminal is invalid. - ErrInvalidState = term.ErrInvalidState - - // SetWinsize tries to set the specified window size for the specified file descriptor. - // Deprecated: use github.com/moby/term.GetWinsize - SetWinsize = term.SetWinsize -) diff --git a/vendor/github.com/docker/docker/registry/config_unix.go b/vendor/github.com/docker/docker/registry/config_unix.go index 8ee8fedfc1..b5bb31cfa6 100644 --- a/vendor/github.com/docker/docker/registry/config_unix.go +++ b/vendor/github.com/docker/docker/registry/config_unix.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows package registry // import "github.com/docker/docker/registry" diff --git a/vendor/github.com/docker/docker/registry/endpoint_v1.go b/vendor/github.com/docker/docker/registry/endpoint_v1.go index db342d1412..3b5ab2f5ff 100644 --- a/vendor/github.com/docker/docker/registry/endpoint_v1.go +++ b/vendor/github.com/docker/docker/registry/endpoint_v1.go @@ -4,7 +4,7 @@ import ( "crypto/tls" "encoding/json" "fmt" - "io/ioutil" + "io" "net/http" "net/url" "strings" @@ -89,10 +89,7 @@ func trimV1Address(address string) (string, error) { apiVersionStr string ) - if strings.HasSuffix(address, "/") { - address = address[:len(address)-1] - } - + address = strings.TrimSuffix(address, "/") chunks = strings.Split(address, "/") apiVersionStr = chunks[len(chunks)-1] if apiVersionStr == "v1" { @@ -161,7 +158,7 @@ func (e *V1Endpoint) Ping() (PingResult, error) { defer resp.Body.Close() - jsonString, err := ioutil.ReadAll(resp.Body) + jsonString, err := io.ReadAll(resp.Body) if err != nil { return PingResult{Standalone: false}, fmt.Errorf("error while reading the http response: %s", err) } diff --git a/vendor/github.com/docker/docker/registry/registry.go b/vendor/github.com/docker/docker/registry/registry.go index 7a70bf28b5..bcf2509f24 100644 --- a/vendor/github.com/docker/docker/registry/registry.go +++ b/vendor/github.com/docker/docker/registry/registry.go @@ -5,7 +5,6 @@ import ( "crypto/tls" "errors" "fmt" - "io/ioutil" "net" "net/http" "os" @@ -54,7 +53,7 @@ func newTLSConfig(hostname string, isSecure bool) (*tls.Config, error) { return tlsConfig, nil } -func hasFile(files []os.FileInfo, name string) bool { +func hasFile(files []os.DirEntry, name string) bool { for _, f := range files { if f.Name() == name { return true @@ -67,7 +66,7 @@ func hasFile(files []os.FileInfo, name string) bool { // including roots and certificate pairs and updates the // provided TLS configuration. func ReadCertsDirectory(tlsConfig *tls.Config, directory string) error { - fs, err := ioutil.ReadDir(directory) + fs, err := os.ReadDir(directory) if err != nil && !os.IsNotExist(err) { return err } @@ -82,7 +81,7 @@ func ReadCertsDirectory(tlsConfig *tls.Config, directory string) error { tlsConfig.RootCAs = systemPool } logrus.Debugf("crt: %s", filepath.Join(directory, f.Name())) - data, err := ioutil.ReadFile(filepath.Join(directory, f.Name())) + data, err := os.ReadFile(filepath.Join(directory, f.Name())) if err != nil { return err } diff --git a/vendor/github.com/docker/docker/registry/service_v2.go b/vendor/github.com/docker/docker/registry/service_v2.go index 3e3a5b41ff..154ac7c93e 100644 --- a/vendor/github.com/docker/docker/registry/service_v2.go +++ b/vendor/github.com/docker/docker/registry/service_v2.go @@ -9,6 +9,9 @@ import ( func (s *DefaultService) lookupV2Endpoints(hostname string) (endpoints []APIEndpoint, err error) { tlsConfig := tlsconfig.ServerDefault() + + ana := allowNondistributableArtifacts(s.config, hostname) + if hostname == DefaultNamespace || hostname == IndexHostname { for _, mirror := range s.config.Mirrors { if !strings.HasPrefix(mirror, "http://") && !strings.HasPrefix(mirror, "https://") { @@ -36,13 +39,13 @@ func (s *DefaultService) lookupV2Endpoints(hostname string) (endpoints []APIEndp Official: true, TrimHostname: true, TLSConfig: tlsConfig, + + AllowNondistributableArtifacts: ana, }) return endpoints, nil } - ana := allowNondistributableArtifacts(s.config, hostname) - tlsConfig, err = s.tlsConfig(hostname) if err != nil { return nil, err diff --git a/vendor/github.com/docker/go-units/size.go b/vendor/github.com/docker/go-units/size.go index 85f6ab0715..c245a89513 100644 --- a/vendor/github.com/docker/go-units/size.go +++ b/vendor/github.com/docker/go-units/size.go @@ -2,7 +2,6 @@ package units import ( "fmt" - "regexp" "strconv" "strings" ) @@ -26,16 +25,17 @@ const ( PiB = 1024 * TiB ) -type unitMap map[string]int64 +type unitMap map[byte]int64 var ( - decimalMap = unitMap{"k": KB, "m": MB, "g": GB, "t": TB, "p": PB} - binaryMap = unitMap{"k": KiB, "m": MiB, "g": GiB, "t": TiB, "p": PiB} - sizeRegex = regexp.MustCompile(`^(\d+(\.\d+)*) ?([kKmMgGtTpP])?[iI]?[bB]?$`) + decimalMap = unitMap{'k': KB, 'm': MB, 'g': GB, 't': TB, 'p': PB} + binaryMap = unitMap{'k': KiB, 'm': MiB, 'g': GiB, 't': TiB, 'p': PiB} ) -var decimapAbbrs = []string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"} -var binaryAbbrs = []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"} +var ( + decimapAbbrs = []string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"} + binaryAbbrs = []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"} +) func getSizeAndUnit(size float64, base float64, _map []string) (float64, string) { i := 0 @@ -89,20 +89,66 @@ func RAMInBytes(size string) (int64, error) { // Parses the human-readable size string into the amount it represents. func parseSize(sizeStr string, uMap unitMap) (int64, error) { - matches := sizeRegex.FindStringSubmatch(sizeStr) - if len(matches) != 4 { + // TODO: rewrite to use strings.Cut if there's a space + // once Go < 1.18 is deprecated. + sep := strings.LastIndexAny(sizeStr, "01234567890. ") + if sep == -1 { + // There should be at least a digit. return -1, fmt.Errorf("invalid size: '%s'", sizeStr) } + var num, sfx string + if sizeStr[sep] != ' ' { + num = sizeStr[:sep+1] + sfx = sizeStr[sep+1:] + } else { + // Omit the space separator. + num = sizeStr[:sep] + sfx = sizeStr[sep+1:] + } - size, err := strconv.ParseFloat(matches[1], 64) + size, err := strconv.ParseFloat(num, 64) if err != nil { return -1, err } + // Backward compatibility: reject negative sizes. + if size < 0 { + return -1, fmt.Errorf("invalid size: '%s'", sizeStr) + } + + if len(sfx) == 0 { + return int64(size), nil + } - unitPrefix := strings.ToLower(matches[3]) - if mul, ok := uMap[unitPrefix]; ok { + // Process the suffix. + + if len(sfx) > 3 { // Too long. + goto badSuffix + } + sfx = strings.ToLower(sfx) + // Trivial case: b suffix. + if sfx[0] == 'b' { + if len(sfx) > 1 { // no extra characters allowed after b. + goto badSuffix + } + return int64(size), nil + } + // A suffix from the map. + if mul, ok := uMap[sfx[0]]; ok { size *= float64(mul) + } else { + goto badSuffix + } + + // The suffix may have extra "b" or "ib" (e.g. KiB or MB). + switch { + case len(sfx) == 2 && sfx[1] != 'b': + goto badSuffix + case len(sfx) == 3 && sfx[1:] != "ib": + goto badSuffix } return int64(size), nil + +badSuffix: + return -1, fmt.Errorf("invalid suffix: '%s'", sfx) } diff --git a/vendor/github.com/emicklei/go-restful/v3/CHANGES.md b/vendor/github.com/emicklei/go-restful/v3/CHANGES.md index 38169cfd63..74a378157a 100644 --- a/vendor/github.com/emicklei/go-restful/v3/CHANGES.md +++ b/vendor/github.com/emicklei/go-restful/v3/CHANGES.md @@ -1,5 +1,9 @@ # Change history of go-restful +## [v3.9.0] - 20221-07-21 + +- add support for http.Handler implementations to work as FilterFunction, issue #504 (thanks to https://github.com/ggicci) + ## [v3.8.0] - 20221-06-06 - use exact matching of allowed domain entries, issue #489 (#493) diff --git a/vendor/github.com/emicklei/go-restful/v3/README.md b/vendor/github.com/emicklei/go-restful/v3/README.md index 23166d3b47..0625359dc4 100644 --- a/vendor/github.com/emicklei/go-restful/v3/README.md +++ b/vendor/github.com/emicklei/go-restful/v3/README.md @@ -84,6 +84,7 @@ func (u UserResource) findUser(request *restful.Request, response *restful.Respo - Route errors produce HTTP 404/405/406/415 errors, customizable using ServiceErrorHandler(...) - Configurable (trace) logging - Customizable gzip/deflate readers and writers using CompressorProvider registration +- Inject your own http.Handler using the `HttpMiddlewareHandlerToFilter` function ## How to customize There are several hooks to customize the behavior of the go-restful package. @@ -94,7 +95,7 @@ There are several hooks to customize the behavior of the go-restful package. - Trace logging - Compression - Encoders for other serializers -- Use [jsoniter](https://github.com/json-iterator/go) by build this package using a tag, e.g. `go build -tags=jsoniter .` +- Use [jsoniter](https://github.com/json-iterator/go) by building this package using a build tag, e.g. `go build -tags=jsoniter .` ## Resources diff --git a/vendor/github.com/emicklei/go-restful/v3/filter_adapter.go b/vendor/github.com/emicklei/go-restful/v3/filter_adapter.go new file mode 100644 index 0000000000..c246512fc0 --- /dev/null +++ b/vendor/github.com/emicklei/go-restful/v3/filter_adapter.go @@ -0,0 +1,21 @@ +package restful + +import ( + "net/http" +) + +// HttpMiddlewareHandler is a function that takes a http.Handler and returns a http.Handler +type HttpMiddlewareHandler func(http.Handler) http.Handler + +// HttpMiddlewareHandlerToFilter converts a HttpMiddlewareHandler to a FilterFunction. +func HttpMiddlewareHandlerToFilter(middleware HttpMiddlewareHandler) FilterFunction { + return func(req *Request, resp *Response, chain *FilterChain) { + next := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + req.Request = r + resp.ResponseWriter = rw + chain.ProcessFilter(req, resp) + }) + + middleware(next).ServeHTTP(resp.ResponseWriter, req.Request) + } +} diff --git a/vendor/github.com/emicklei/go-restful/v3/parameter.go b/vendor/github.com/emicklei/go-restful/v3/parameter.go index 0e658af5ff..0b851bb437 100644 --- a/vendor/github.com/emicklei/go-restful/v3/parameter.go +++ b/vendor/github.com/emicklei/go-restful/v3/parameter.go @@ -22,6 +22,9 @@ const ( // FormParameterKind = indicator of Request parameter type "form" FormParameterKind + // MultiPartFormParameterKind = indicator of Request parameter type "multipart/form-data" + MultiPartFormParameterKind + // CollectionFormatCSV comma separated values `foo,bar` CollectionFormatCSV = CollectionFormat("csv") @@ -108,6 +111,11 @@ func (p *Parameter) beForm() *Parameter { return p } +func (p *Parameter) beMultiPartForm() *Parameter { + p.data.Kind = MultiPartFormParameterKind + return p +} + // Required sets the required field and returns the receiver func (p *Parameter) Required(required bool) *Parameter { p.data.Required = required diff --git a/vendor/github.com/emicklei/go-restful/v3/web_service.go b/vendor/github.com/emicklei/go-restful/v3/web_service.go index 0bf5d1e5f7..789c4df259 100644 --- a/vendor/github.com/emicklei/go-restful/v3/web_service.go +++ b/vendor/github.com/emicklei/go-restful/v3/web_service.go @@ -165,6 +165,18 @@ func FormParameter(name, description string) *Parameter { return p } +// MultiPartFormParameter creates a new Parameter of kind Form (using multipart/form-data) for documentation purposes. +// It is initialized as required with string as its DataType. +func (w *WebService) MultiPartFormParameter(name, description string) *Parameter { + return MultiPartFormParameter(name, description) +} + +func MultiPartFormParameter(name, description string) *Parameter { + p := &Parameter{&ParameterData{Name: name, Description: description, Required: false, DataType: "string"}} + p.beMultiPartForm() + return p +} + // Route creates a new Route using the RouteBuilder and add to the ordered list of Routes. func (w *WebService) Route(builder *RouteBuilder) *WebService { w.routesLock.Lock() diff --git a/vendor/github.com/evanphx/json-patch/patch.go b/vendor/github.com/evanphx/json-patch/patch.go index dc2b7e51e6..4bce5936d5 100644 --- a/vendor/github.com/evanphx/json-patch/patch.go +++ b/vendor/github.com/evanphx/json-patch/patch.go @@ -568,29 +568,6 @@ func (p Patch) replace(doc *container, op Operation) error { return errors.Wrapf(err, "replace operation failed to decode path") } - if path == "" { - val := op.value() - - if val.which == eRaw { - if !val.tryDoc() { - if !val.tryAry() { - return errors.Wrapf(err, "replace operation value must be object or array") - } - } - } - - switch val.which { - case eAry: - *doc = &val.ary - case eDoc: - *doc = &val.doc - case eRaw: - return errors.Wrapf(err, "replace operation hit impossible case") - } - - return nil - } - con, key := findObject(doc, path) if con == nil { @@ -657,25 +634,6 @@ func (p Patch) test(doc *container, op Operation) error { return errors.Wrapf(err, "test operation failed to decode path") } - if path == "" { - var self lazyNode - - switch sv := (*doc).(type) { - case *partialDoc: - self.doc = *sv - self.which = eDoc - case *partialArray: - self.ary = *sv - self.which = eAry - } - - if self.equal(op.value()) { - return nil - } - - return errors.Wrapf(ErrTestFailed, "testing value %s failed", path) - } - con, key := findObject(doc, path) if con == nil { diff --git a/vendor/github.com/felixge/httpsnoop/README.md b/vendor/github.com/felixge/httpsnoop/README.md index ae44137e9b..ddcecd13e7 100644 --- a/vendor/github.com/felixge/httpsnoop/README.md +++ b/vendor/github.com/felixge/httpsnoop/README.md @@ -65,7 +65,8 @@ being called, or called more than once, as well as concurrent calls to Unfortunately this package is not perfect either. It's possible that it is still missing some interfaces provided by the go core (let me know if you find one), and it won't work for applications adding their own interfaces into the -mix. +mix. You can however use `httpsnoop.Unwrap(w)` to access the underlying +`http.ResponseWriter` and type-assert the result to its other interfaces. However, hopefully the explanation above has sufficiently scared you of rolling your own solution to this problem. httpsnoop may still break your application, diff --git a/vendor/github.com/felixge/httpsnoop/capture_metrics.go b/vendor/github.com/felixge/httpsnoop/capture_metrics.go index 4c45b1a8c1..b77cc7c009 100644 --- a/vendor/github.com/felixge/httpsnoop/capture_metrics.go +++ b/vendor/github.com/felixge/httpsnoop/capture_metrics.go @@ -3,7 +3,6 @@ package httpsnoop import ( "io" "net/http" - "sync" "time" ) @@ -36,17 +35,23 @@ func CaptureMetrics(hnd http.Handler, w http.ResponseWriter, r *http.Request) Me // sugar on top of this func), but is a more usable interface if your // application doesn't use the Go http.Handler interface. func CaptureMetricsFn(w http.ResponseWriter, fn func(http.ResponseWriter)) Metrics { + m := Metrics{Code: http.StatusOK} + m.CaptureMetrics(w, fn) + return m +} + +// CaptureMetrics wraps w and calls fn with the wrapped w and updates +// Metrics m with the resulting metrics. This is similar to CaptureMetricsFn, +// but allows one to customize starting Metrics object. +func (m *Metrics) CaptureMetrics(w http.ResponseWriter, fn func(http.ResponseWriter)) { var ( start = time.Now() - m = Metrics{Code: http.StatusOK} headerWritten bool - lock sync.Mutex hooks = Hooks{ WriteHeader: func(next WriteHeaderFunc) WriteHeaderFunc { return func(code int) { next(code) - lock.Lock() - defer lock.Unlock() + if !headerWritten { m.Code = code headerWritten = true @@ -57,8 +62,7 @@ func CaptureMetricsFn(w http.ResponseWriter, fn func(http.ResponseWriter)) Metri Write: func(next WriteFunc) WriteFunc { return func(p []byte) (int, error) { n, err := next(p) - lock.Lock() - defer lock.Unlock() + m.Written += int64(n) headerWritten = true return n, err @@ -68,8 +72,7 @@ func CaptureMetricsFn(w http.ResponseWriter, fn func(http.ResponseWriter)) Metri ReadFrom: func(next ReadFromFunc) ReadFromFunc { return func(src io.Reader) (int64, error) { n, err := next(src) - lock.Lock() - defer lock.Unlock() + headerWritten = true m.Written += n return n, err @@ -79,6 +82,5 @@ func CaptureMetricsFn(w http.ResponseWriter, fn func(http.ResponseWriter)) Metri ) fn(Wrap(w, hooks)) - m.Duration = time.Since(start) - return m + m.Duration += time.Since(start) } diff --git a/vendor/github.com/felixge/httpsnoop/wrap_generated_gteq_1.8.go b/vendor/github.com/felixge/httpsnoop/wrap_generated_gteq_1.8.go index 41a20da9ea..31cbdfb8ef 100644 --- a/vendor/github.com/felixge/httpsnoop/wrap_generated_gteq_1.8.go +++ b/vendor/github.com/felixge/httpsnoop/wrap_generated_gteq_1.8.go @@ -74,243 +74,275 @@ func Wrap(w http.ResponseWriter, hooks Hooks) http.ResponseWriter { // combination 1/32 case !i0 && !i1 && !i2 && !i3 && !i4: return struct { + Unwrapper http.ResponseWriter - }{rw} + }{rw, rw} // combination 2/32 case !i0 && !i1 && !i2 && !i3 && i4: return struct { + Unwrapper http.ResponseWriter http.Pusher - }{rw, rw} + }{rw, rw, rw} // combination 3/32 case !i0 && !i1 && !i2 && i3 && !i4: return struct { + Unwrapper http.ResponseWriter io.ReaderFrom - }{rw, rw} + }{rw, rw, rw} // combination 4/32 case !i0 && !i1 && !i2 && i3 && i4: return struct { + Unwrapper http.ResponseWriter io.ReaderFrom http.Pusher - }{rw, rw, rw} + }{rw, rw, rw, rw} // combination 5/32 case !i0 && !i1 && i2 && !i3 && !i4: return struct { + Unwrapper http.ResponseWriter http.Hijacker - }{rw, rw} + }{rw, rw, rw} // combination 6/32 case !i0 && !i1 && i2 && !i3 && i4: return struct { + Unwrapper http.ResponseWriter http.Hijacker http.Pusher - }{rw, rw, rw} + }{rw, rw, rw, rw} // combination 7/32 case !i0 && !i1 && i2 && i3 && !i4: return struct { + Unwrapper http.ResponseWriter http.Hijacker io.ReaderFrom - }{rw, rw, rw} + }{rw, rw, rw, rw} // combination 8/32 case !i0 && !i1 && i2 && i3 && i4: return struct { + Unwrapper http.ResponseWriter http.Hijacker io.ReaderFrom http.Pusher - }{rw, rw, rw, rw} + }{rw, rw, rw, rw, rw} // combination 9/32 case !i0 && i1 && !i2 && !i3 && !i4: return struct { + Unwrapper http.ResponseWriter http.CloseNotifier - }{rw, rw} + }{rw, rw, rw} // combination 10/32 case !i0 && i1 && !i2 && !i3 && i4: return struct { + Unwrapper http.ResponseWriter http.CloseNotifier http.Pusher - }{rw, rw, rw} + }{rw, rw, rw, rw} // combination 11/32 case !i0 && i1 && !i2 && i3 && !i4: return struct { + Unwrapper http.ResponseWriter http.CloseNotifier io.ReaderFrom - }{rw, rw, rw} + }{rw, rw, rw, rw} // combination 12/32 case !i0 && i1 && !i2 && i3 && i4: return struct { + Unwrapper http.ResponseWriter http.CloseNotifier io.ReaderFrom http.Pusher - }{rw, rw, rw, rw} + }{rw, rw, rw, rw, rw} // combination 13/32 case !i0 && i1 && i2 && !i3 && !i4: return struct { + Unwrapper http.ResponseWriter http.CloseNotifier http.Hijacker - }{rw, rw, rw} + }{rw, rw, rw, rw} // combination 14/32 case !i0 && i1 && i2 && !i3 && i4: return struct { + Unwrapper http.ResponseWriter http.CloseNotifier http.Hijacker http.Pusher - }{rw, rw, rw, rw} + }{rw, rw, rw, rw, rw} // combination 15/32 case !i0 && i1 && i2 && i3 && !i4: return struct { + Unwrapper http.ResponseWriter http.CloseNotifier http.Hijacker io.ReaderFrom - }{rw, rw, rw, rw} + }{rw, rw, rw, rw, rw} // combination 16/32 case !i0 && i1 && i2 && i3 && i4: return struct { + Unwrapper http.ResponseWriter http.CloseNotifier http.Hijacker io.ReaderFrom http.Pusher - }{rw, rw, rw, rw, rw} + }{rw, rw, rw, rw, rw, rw} // combination 17/32 case i0 && !i1 && !i2 && !i3 && !i4: return struct { + Unwrapper http.ResponseWriter http.Flusher - }{rw, rw} + }{rw, rw, rw} // combination 18/32 case i0 && !i1 && !i2 && !i3 && i4: return struct { + Unwrapper http.ResponseWriter http.Flusher http.Pusher - }{rw, rw, rw} + }{rw, rw, rw, rw} // combination 19/32 case i0 && !i1 && !i2 && i3 && !i4: return struct { + Unwrapper http.ResponseWriter http.Flusher io.ReaderFrom - }{rw, rw, rw} + }{rw, rw, rw, rw} // combination 20/32 case i0 && !i1 && !i2 && i3 && i4: return struct { + Unwrapper http.ResponseWriter http.Flusher io.ReaderFrom http.Pusher - }{rw, rw, rw, rw} + }{rw, rw, rw, rw, rw} // combination 21/32 case i0 && !i1 && i2 && !i3 && !i4: return struct { + Unwrapper http.ResponseWriter http.Flusher http.Hijacker - }{rw, rw, rw} + }{rw, rw, rw, rw} // combination 22/32 case i0 && !i1 && i2 && !i3 && i4: return struct { + Unwrapper http.ResponseWriter http.Flusher http.Hijacker http.Pusher - }{rw, rw, rw, rw} + }{rw, rw, rw, rw, rw} // combination 23/32 case i0 && !i1 && i2 && i3 && !i4: return struct { + Unwrapper http.ResponseWriter http.Flusher http.Hijacker io.ReaderFrom - }{rw, rw, rw, rw} + }{rw, rw, rw, rw, rw} // combination 24/32 case i0 && !i1 && i2 && i3 && i4: return struct { + Unwrapper http.ResponseWriter http.Flusher http.Hijacker io.ReaderFrom http.Pusher - }{rw, rw, rw, rw, rw} + }{rw, rw, rw, rw, rw, rw} // combination 25/32 case i0 && i1 && !i2 && !i3 && !i4: return struct { + Unwrapper http.ResponseWriter http.Flusher http.CloseNotifier - }{rw, rw, rw} + }{rw, rw, rw, rw} // combination 26/32 case i0 && i1 && !i2 && !i3 && i4: return struct { + Unwrapper http.ResponseWriter http.Flusher http.CloseNotifier http.Pusher - }{rw, rw, rw, rw} + }{rw, rw, rw, rw, rw} // combination 27/32 case i0 && i1 && !i2 && i3 && !i4: return struct { + Unwrapper http.ResponseWriter http.Flusher http.CloseNotifier io.ReaderFrom - }{rw, rw, rw, rw} + }{rw, rw, rw, rw, rw} // combination 28/32 case i0 && i1 && !i2 && i3 && i4: return struct { + Unwrapper http.ResponseWriter http.Flusher http.CloseNotifier io.ReaderFrom http.Pusher - }{rw, rw, rw, rw, rw} + }{rw, rw, rw, rw, rw, rw} // combination 29/32 case i0 && i1 && i2 && !i3 && !i4: return struct { + Unwrapper http.ResponseWriter http.Flusher http.CloseNotifier http.Hijacker - }{rw, rw, rw, rw} + }{rw, rw, rw, rw, rw} // combination 30/32 case i0 && i1 && i2 && !i3 && i4: return struct { + Unwrapper http.ResponseWriter http.Flusher http.CloseNotifier http.Hijacker http.Pusher - }{rw, rw, rw, rw, rw} + }{rw, rw, rw, rw, rw, rw} // combination 31/32 case i0 && i1 && i2 && i3 && !i4: return struct { + Unwrapper http.ResponseWriter http.Flusher http.CloseNotifier http.Hijacker io.ReaderFrom - }{rw, rw, rw, rw, rw} + }{rw, rw, rw, rw, rw, rw} // combination 32/32 case i0 && i1 && i2 && i3 && i4: return struct { + Unwrapper http.ResponseWriter http.Flusher http.CloseNotifier http.Hijacker io.ReaderFrom http.Pusher - }{rw, rw, rw, rw, rw, rw} + }{rw, rw, rw, rw, rw, rw, rw} } panic("unreachable") } @@ -320,6 +352,10 @@ type rw struct { h Hooks } +func (w *rw) Unwrap() http.ResponseWriter { + return w.w +} + func (w *rw) Header() http.Header { f := w.w.(http.ResponseWriter).Header if w.h.Header != nil { @@ -383,3 +419,18 @@ func (w *rw) Push(target string, opts *http.PushOptions) error { } return f(target, opts) } + +type Unwrapper interface { + Unwrap() http.ResponseWriter +} + +// Unwrap returns the underlying http.ResponseWriter from within zero or more +// layers of httpsnoop wrappers. +func Unwrap(w http.ResponseWriter) http.ResponseWriter { + if rw, ok := w.(Unwrapper); ok { + // recurse until rw.Unwrap() returns a non-Unwrapper + return Unwrap(rw.Unwrap()) + } else { + return w + } +} diff --git a/vendor/github.com/felixge/httpsnoop/wrap_generated_lt_1.8.go b/vendor/github.com/felixge/httpsnoop/wrap_generated_lt_1.8.go index 36bb59b837..ab99c07c7a 100644 --- a/vendor/github.com/felixge/httpsnoop/wrap_generated_lt_1.8.go +++ b/vendor/github.com/felixge/httpsnoop/wrap_generated_lt_1.8.go @@ -68,115 +68,131 @@ func Wrap(w http.ResponseWriter, hooks Hooks) http.ResponseWriter { // combination 1/16 case !i0 && !i1 && !i2 && !i3: return struct { + Unwrapper http.ResponseWriter - }{rw} + }{rw, rw} // combination 2/16 case !i0 && !i1 && !i2 && i3: return struct { + Unwrapper http.ResponseWriter io.ReaderFrom - }{rw, rw} + }{rw, rw, rw} // combination 3/16 case !i0 && !i1 && i2 && !i3: return struct { + Unwrapper http.ResponseWriter http.Hijacker - }{rw, rw} + }{rw, rw, rw} // combination 4/16 case !i0 && !i1 && i2 && i3: return struct { + Unwrapper http.ResponseWriter http.Hijacker io.ReaderFrom - }{rw, rw, rw} + }{rw, rw, rw, rw} // combination 5/16 case !i0 && i1 && !i2 && !i3: return struct { + Unwrapper http.ResponseWriter http.CloseNotifier - }{rw, rw} + }{rw, rw, rw} // combination 6/16 case !i0 && i1 && !i2 && i3: return struct { + Unwrapper http.ResponseWriter http.CloseNotifier io.ReaderFrom - }{rw, rw, rw} + }{rw, rw, rw, rw} // combination 7/16 case !i0 && i1 && i2 && !i3: return struct { + Unwrapper http.ResponseWriter http.CloseNotifier http.Hijacker - }{rw, rw, rw} + }{rw, rw, rw, rw} // combination 8/16 case !i0 && i1 && i2 && i3: return struct { + Unwrapper http.ResponseWriter http.CloseNotifier http.Hijacker io.ReaderFrom - }{rw, rw, rw, rw} + }{rw, rw, rw, rw, rw} // combination 9/16 case i0 && !i1 && !i2 && !i3: return struct { + Unwrapper http.ResponseWriter http.Flusher - }{rw, rw} + }{rw, rw, rw} // combination 10/16 case i0 && !i1 && !i2 && i3: return struct { + Unwrapper http.ResponseWriter http.Flusher io.ReaderFrom - }{rw, rw, rw} + }{rw, rw, rw, rw} // combination 11/16 case i0 && !i1 && i2 && !i3: return struct { + Unwrapper http.ResponseWriter http.Flusher http.Hijacker - }{rw, rw, rw} + }{rw, rw, rw, rw} // combination 12/16 case i0 && !i1 && i2 && i3: return struct { + Unwrapper http.ResponseWriter http.Flusher http.Hijacker io.ReaderFrom - }{rw, rw, rw, rw} + }{rw, rw, rw, rw, rw} // combination 13/16 case i0 && i1 && !i2 && !i3: return struct { + Unwrapper http.ResponseWriter http.Flusher http.CloseNotifier - }{rw, rw, rw} + }{rw, rw, rw, rw} // combination 14/16 case i0 && i1 && !i2 && i3: return struct { + Unwrapper http.ResponseWriter http.Flusher http.CloseNotifier io.ReaderFrom - }{rw, rw, rw, rw} + }{rw, rw, rw, rw, rw} // combination 15/16 case i0 && i1 && i2 && !i3: return struct { + Unwrapper http.ResponseWriter http.Flusher http.CloseNotifier http.Hijacker - }{rw, rw, rw, rw} + }{rw, rw, rw, rw, rw} // combination 16/16 case i0 && i1 && i2 && i3: return struct { + Unwrapper http.ResponseWriter http.Flusher http.CloseNotifier http.Hijacker io.ReaderFrom - }{rw, rw, rw, rw, rw} + }{rw, rw, rw, rw, rw, rw} } panic("unreachable") } @@ -186,6 +202,10 @@ type rw struct { h Hooks } +func (w *rw) Unwrap() http.ResponseWriter { + return w.w +} + func (w *rw) Header() http.Header { f := w.w.(http.ResponseWriter).Header if w.h.Header != nil { @@ -241,3 +261,18 @@ func (w *rw) ReadFrom(src io.Reader) (int64, error) { } return f(src) } + +type Unwrapper interface { + Unwrap() http.ResponseWriter +} + +// Unwrap returns the underlying http.ResponseWriter from within zero or more +// layers of httpsnoop wrappers. +func Unwrap(w http.ResponseWriter) http.ResponseWriter { + if rw, ok := w.(Unwrapper); ok { + // recurse until rw.Unwrap() returns a non-Unwrapper + return Unwrap(rw.Unwrap()) + } else { + return w + } +} diff --git a/vendor/github.com/fsnotify/fsnotify/.gitignore b/vendor/github.com/fsnotify/fsnotify/.gitignore index 4cd0cbaf43..1d89d85ce4 100644 --- a/vendor/github.com/fsnotify/fsnotify/.gitignore +++ b/vendor/github.com/fsnotify/fsnotify/.gitignore @@ -1,6 +1,6 @@ -# Setup a Global .gitignore for OS and editor generated files: -# https://help.github.com/articles/ignoring-files -# git config --global core.excludesfile ~/.gitignore_global +# go test -c output +*.test +*.test.exe -.vagrant -*.sublime-project +# Output of go build ./cmd/fsnotify +/fsnotify diff --git a/vendor/github.com/fsnotify/fsnotify/AUTHORS b/vendor/github.com/fsnotify/fsnotify/AUTHORS deleted file mode 100644 index 6cbabe5ef5..0000000000 --- a/vendor/github.com/fsnotify/fsnotify/AUTHORS +++ /dev/null @@ -1,62 +0,0 @@ -# Names should be added to this file as -# Name or Organization -# The email address is not required for organizations. - -# You can update this list using the following command: -# -# $ (head -n10 AUTHORS && git shortlog -se | sed -E 's/^\s+[0-9]+\t//') | tee AUTHORS - -# Please keep the list sorted. - -Aaron L -Adrien Bustany -Alexey Kazakov -Amit Krishnan -Anmol Sethi -Bjørn Erik Pedersen -Brian Goff -Bruno Bigras -Caleb Spare -Case Nelson -Chris Howey -Christoffer Buchholz -Daniel Wagner-Hall -Dave Cheney -Eric Lin -Evan Phoenix -Francisco Souza -Gautam Dey -Hari haran -Ichinose Shogo -Johannes Ebke -John C Barstow -Kelvin Fo -Ken-ichirou MATSUZAWA -Matt Layher -Matthias Stone -Nathan Youngman -Nickolai Zeldovich -Oliver Bristow -Patrick -Paul Hammond -Pawel Knap -Pieter Droogendijk -Pratik Shinde -Pursuit92 -Riku Voipio -Rob Figueiredo -Rodrigo Chiossi -Slawek Ligus -Soge Zhang -Tiffany Jernigan -Tilak Sharma -Tobias Klauser -Tom Payne -Travis Cline -Tudor Golubenco -Vahe Khachikyan -Yukang -bronze1man -debrando -henrikedwards -铁哥 diff --git a/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md b/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md index cc01c08f56..77f9593bd5 100644 --- a/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md +++ b/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md @@ -7,6 +7,95 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +Nothing yet. + +## [1.6.0] - 2022-10-13 + +This version of fsnotify needs Go 1.16 (this was already the case since 1.5.1, +but not documented). It also increases the minimum Linux version to 2.6.32. + +### Additions + +- all: add `Event.Has()` and `Op.Has()` ([#477]) + + This makes checking events a lot easier; for example: + + if event.Op&Write == Write && !(event.Op&Remove == Remove) { + } + + Becomes: + + if event.Has(Write) && !event.Has(Remove) { + } + +- all: add cmd/fsnotify ([#463]) + + A command-line utility for testing and some examples. + +### Changes and fixes + +- inotify: don't ignore events for files that don't exist ([#260], [#470]) + + Previously the inotify watcher would call `os.Lstat()` to check if a file + still exists before emitting events. + + This was inconsistent with other platforms and resulted in inconsistent event + reporting (e.g. when a file is quickly removed and re-created), and generally + a source of confusion. It was added in 2013 to fix a memory leak that no + longer exists. + +- all: return `ErrNonExistentWatch` when `Remove()` is called on a path that's + not watched ([#460]) + +- inotify: replace epoll() with non-blocking inotify ([#434]) + + Non-blocking inotify was not generally available at the time this library was + written in 2014, but now it is. As a result, the minimum Linux version is + bumped from 2.6.27 to 2.6.32. This hugely simplifies the code and is faster. + +- kqueue: don't check for events every 100ms ([#480]) + + The watcher would wake up every 100ms, even when there was nothing to do. Now + it waits until there is something to do. + +- macos: retry opening files on EINTR ([#475]) + +- kqueue: skip unreadable files ([#479]) + + kqueue requires a file descriptor for every file in a directory; this would + fail if a file was unreadable by the current user. Now these files are simply + skipped. + +- windows: fix renaming a watched directory if the parent is also watched ([#370]) + +- windows: increase buffer size from 4K to 64K ([#485]) + +- windows: close file handle on Remove() ([#288]) + +- kqueue: put pathname in the error if watching a file fails ([#471]) + +- inotify, windows: calling Close() more than once could race ([#465]) + +- kqueue: improve Close() performance ([#233]) + +- all: various documentation additions and clarifications. + +[#233]: https://github.com/fsnotify/fsnotify/pull/233 +[#260]: https://github.com/fsnotify/fsnotify/pull/260 +[#288]: https://github.com/fsnotify/fsnotify/pull/288 +[#370]: https://github.com/fsnotify/fsnotify/pull/370 +[#434]: https://github.com/fsnotify/fsnotify/pull/434 +[#460]: https://github.com/fsnotify/fsnotify/pull/460 +[#463]: https://github.com/fsnotify/fsnotify/pull/463 +[#465]: https://github.com/fsnotify/fsnotify/pull/465 +[#470]: https://github.com/fsnotify/fsnotify/pull/470 +[#471]: https://github.com/fsnotify/fsnotify/pull/471 +[#475]: https://github.com/fsnotify/fsnotify/pull/475 +[#477]: https://github.com/fsnotify/fsnotify/pull/477 +[#479]: https://github.com/fsnotify/fsnotify/pull/479 +[#480]: https://github.com/fsnotify/fsnotify/pull/480 +[#485]: https://github.com/fsnotify/fsnotify/pull/485 + ## [1.5.4] - 2022-04-25 * Windows: add missing defer to `Watcher.WatchList` [#447](https://github.com/fsnotify/fsnotify/pull/447) @@ -40,6 +129,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [#385](https://github.com/fsnotify/fsnotify/pull/385) * Go 1.14+: Fix unsafe pointer conversion [#325](https://github.com/fsnotify/fsnotify/pull/325) +## [1.4.9] - 2020-03-11 + +* Move example usage to the readme #329. This may resolve #328. + +## [1.4.8] - 2020-03-10 + +* CI: test more go versions (@nathany 1d13583d846ea9d66dcabbfefbfb9d8e6fb05216) +* Tests: Queued inotify events could have been read by the test before max_queued_events was hit (@matthias-stone #265) +* Tests: t.Fatalf -> t.Errorf in go routines (@gdey #266) +* CI: Less verbosity (@nathany #267) +* Tests: Darwin: Exchangedata is deprecated on 10.13 (@nathany #267) +* Tests: Check if channels are closed in the example (@alexeykazakov #244) +* CI: Only run golint on latest version of go and fix issues (@cpuguy83 #284) +* CI: Add windows to travis matrix (@cpuguy83 #284) +* Docs: Remover appveyor badge (@nathany 11844c0959f6fff69ba325d097fce35bd85a8e93) +* Linux: create epoll and pipe fds with close-on-exec (@JohannesEbke #219) +* Linux: open files with close-on-exec (@linxiulei #273) +* Docs: Plan to support fanotify (@nathany ab058b44498e8b7566a799372a39d150d9ea0119 ) +* Project: Add go.mod (@nathany #309) +* Project: Revise editor config (@nathany #309) +* Project: Update copyright for 2019 (@nathany #309) +* CI: Drop go1.8 from CI matrix (@nathany #309) +* Docs: Updating the FAQ section for supportability with NFS & FUSE filesystems (@Pratik32 4bf2d1fec78374803a39307bfb8d340688f4f28e ) + ## [1.4.7] - 2018-01-09 * BSD/macOS: Fix possible deadlock on closing the watcher on kqueue (thanks @nhooyr and @glycerine) diff --git a/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md b/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md index 8a642563d7..ea379759d5 100644 --- a/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md +++ b/vendor/github.com/fsnotify/fsnotify/CONTRIBUTING.md @@ -1,60 +1,26 @@ -# Contributing +Thank you for your interest in contributing to fsnotify! We try to review and +merge PRs in a reasonable timeframe, but please be aware that: -## Issues +- To avoid "wasted" work, please discus changes on the issue tracker first. You + can just send PRs, but they may end up being rejected for one reason or the + other. -* Request features and report bugs using the [GitHub Issue Tracker](https://github.com/fsnotify/fsnotify/issues). -* Please indicate the platform you are using fsnotify on. -* A code example to reproduce the problem is appreciated. +- fsnotify is a cross-platform library, and changes must work reasonably well on + all supported platforms. -## Pull Requests +- Changes will need to be compatible; old code should still compile, and the + runtime behaviour can't change in ways that are likely to lead to problems for + users. -### Contributor License Agreement +Testing +------- +Just `go test ./...` runs all the tests; the CI runs this on all supported +platforms. Testing different platforms locally can be done with something like +[goon] or [Vagrant], but this isn't super-easy to set up at the moment. -fsnotify is derived from code in the [golang.org/x/exp](https://godoc.org/golang.org/x/exp) package and it may be included [in the standard library](https://github.com/fsnotify/fsnotify/issues/1) in the future. Therefore fsnotify carries the same [LICENSE](https://github.com/fsnotify/fsnotify/blob/master/LICENSE) as Go. Contributors retain their copyright, so you need to fill out a short form before we can accept your contribution: [Google Individual Contributor License Agreement](https://developers.google.com/open-source/cla/individual). +Use the `-short` flag to make the "stress test" run faster. -Please indicate that you have signed the CLA in your pull request. -### How fsnotify is Developed - -* Development is done on feature branches. -* Tests are run on BSD, Linux, macOS and Windows. -* Pull requests are reviewed and [applied to master][am] using [hub][]. - * Maintainers may modify or squash commits rather than asking contributors to. -* To issue a new release, the maintainers will: - * Update the CHANGELOG - * Tag a version, which will become available through gopkg.in. - -### How to Fork - -For smooth sailing, always use the original import path. Installing with `go get` makes this easy. - -1. Install from GitHub (`go get -u github.com/fsnotify/fsnotify`) -2. Create your feature branch (`git checkout -b my-new-feature`) -3. Ensure everything works and the tests pass (see below) -4. Commit your changes (`git commit -am 'Add some feature'`) - -Contribute upstream: - -1. Fork fsnotify on GitHub -2. Add your remote (`git remote add fork git@github.com:mycompany/repo.git`) -3. Push to the branch (`git push fork my-new-feature`) -4. Create a new Pull Request on GitHub - -This workflow is [thoroughly explained by Katrina Owen](https://splice.com/blog/contributing-open-source-git-repositories-go/). - -### Testing - -fsnotify uses build tags to compile different code on Linux, BSD, macOS, and Windows. - -Before doing a pull request, please do your best to test your changes on multiple platforms, and list which platforms you were able/unable to test on. - -### Maintainers - -Help maintaining fsnotify is welcome. To be a maintainer: - -* Submit a pull request and sign the CLA as above. -* You must be able to run the test suite on Mac, Windows, Linux and BSD. - -All code changes should be internal pull requests. - -Releases are tagged using [Semantic Versioning](http://semver.org/). +[goon]: https://github.com/arp242/goon +[Vagrant]: https://www.vagrantup.com/ +[integration_test.go]: /integration_test.go diff --git a/vendor/github.com/fsnotify/fsnotify/LICENSE b/vendor/github.com/fsnotify/fsnotify/LICENSE index e180c8fb05..fb03ade750 100644 --- a/vendor/github.com/fsnotify/fsnotify/LICENSE +++ b/vendor/github.com/fsnotify/fsnotify/LICENSE @@ -1,28 +1,25 @@ -Copyright (c) 2012 The Go Authors. All rights reserved. -Copyright (c) 2012-2019 fsnotify Authors. All rights reserved. +Copyright © 2012 The Go Authors. All rights reserved. +Copyright © fsnotify Authors. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. +* Neither the name of Google Inc. nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/fsnotify/fsnotify/README.md b/vendor/github.com/fsnotify/fsnotify/README.md index 0731c5ef8a..d4e6080feb 100644 --- a/vendor/github.com/fsnotify/fsnotify/README.md +++ b/vendor/github.com/fsnotify/fsnotify/README.md @@ -1,120 +1,161 @@ -# File system notifications for Go +fsnotify is a Go library to provide cross-platform filesystem notifications on +Windows, Linux, macOS, and BSD systems. -[![Go Reference](https://pkg.go.dev/badge/github.com/fsnotify/fsnotify.svg)](https://pkg.go.dev/github.com/fsnotify/fsnotify) [![Go Report Card](https://goreportcard.com/badge/github.com/fsnotify/fsnotify)](https://goreportcard.com/report/github.com/fsnotify/fsnotify) [![Maintainers Wanted](https://img.shields.io/badge/maintainers-wanted-red.svg)](https://github.com/fsnotify/fsnotify/issues/413) +Go 1.16 or newer is required; the full documentation is at +https://pkg.go.dev/github.com/fsnotify/fsnotify -fsnotify utilizes [`golang.org/x/sys`](https://pkg.go.dev/golang.org/x/sys) rather than [`syscall`](https://pkg.go.dev/syscall) from the standard library. +**It's best to read the documentation at pkg.go.dev, as it's pinned to the last +released version, whereas this README is for the last development version which +may include additions/changes.** -Cross platform: Windows, Linux, BSD and macOS. +--- -| Adapter | OS | Status | -| --------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | -| inotify | Linux 2.6.27 or later, Android\* | Supported | -| kqueue | BSD, macOS, iOS\* | Supported | -| ReadDirectoryChangesW | Windows | Supported | -| FSEvents | macOS | [Planned](https://github.com/fsnotify/fsnotify/issues/11) | -| FEN | Solaris 11 | [In Progress](https://github.com/fsnotify/fsnotify/pull/371) | -| fanotify | Linux 2.6.37+ | [Maybe](https://github.com/fsnotify/fsnotify/issues/114) | -| USN Journals | Windows | [Maybe](https://github.com/fsnotify/fsnotify/issues/53) | -| Polling | *All* | [Maybe](https://github.com/fsnotify/fsnotify/issues/9) | +Platform support: -\* Android and iOS are untested. +| Adapter | OS | Status | +| --------------------- | ---------------| -------------------------------------------------------------| +| inotify | Linux 2.6.32+ | Supported | +| kqueue | BSD, macOS | Supported | +| ReadDirectoryChangesW | Windows | Supported | +| FSEvents | macOS | [Planned](https://github.com/fsnotify/fsnotify/issues/11) | +| FEN | Solaris 11 | [In Progress](https://github.com/fsnotify/fsnotify/pull/371) | +| fanotify | Linux 5.9+ | [Maybe](https://github.com/fsnotify/fsnotify/issues/114) | +| USN Journals | Windows | [Maybe](https://github.com/fsnotify/fsnotify/issues/53) | +| Polling | *All* | [Maybe](https://github.com/fsnotify/fsnotify/issues/9) | -Please see [the documentation](https://pkg.go.dev/github.com/fsnotify/fsnotify) and consult the [FAQ](#faq) for usage information. +Linux and macOS should include Android and iOS, but these are currently untested. -## API stability - -fsnotify is a fork of [howeyc/fsnotify](https://github.com/howeyc/fsnotify) with a new API as of v1.0. The API is based on [this design document](http://goo.gl/MrYxyA). - -All [releases](https://github.com/fsnotify/fsnotify/releases) are tagged based on [Semantic Versioning](http://semver.org/). - -## Usage +Usage +----- +A basic example: ```go package main import ( - "log" + "log" - "github.com/fsnotify/fsnotify" + "github.com/fsnotify/fsnotify" ) func main() { - watcher, err := fsnotify.NewWatcher() - if err != nil { - log.Fatal(err) - } - defer watcher.Close() - - done := make(chan bool) - go func() { - for { - select { - case event, ok := <-watcher.Events: - if !ok { - return - } - log.Println("event:", event) - if event.Op&fsnotify.Write == fsnotify.Write { - log.Println("modified file:", event.Name) - } - case err, ok := <-watcher.Errors: - if !ok { - return - } - log.Println("error:", err) - } - } - }() - - err = watcher.Add("/tmp/foo") - if err != nil { - log.Fatal(err) - } - <-done + // Create new watcher. + watcher, err := fsnotify.NewWatcher() + if err != nil { + log.Fatal(err) + } + defer watcher.Close() + + // Start listening for events. + go func() { + for { + select { + case event, ok := <-watcher.Events: + if !ok { + return + } + log.Println("event:", event) + if event.Has(fsnotify.Write) { + log.Println("modified file:", event.Name) + } + case err, ok := <-watcher.Errors: + if !ok { + return + } + log.Println("error:", err) + } + } + }() + + // Add a path. + err = watcher.Add("/tmp") + if err != nil { + log.Fatal(err) + } + + // Block main goroutine forever. + <-make(chan struct{}) } ``` -## Contributing +Some more examples can be found in [cmd/fsnotify](cmd/fsnotify), which can be +run with: -Please refer to [CONTRIBUTING][] before opening an issue or pull request. + % go run ./cmd/fsnotify -## FAQ +FAQ +--- +### Will a file still be watched when it's moved to another directory? +No, not unless you are watching the location it was moved to. -**When a file is moved to another directory is it still being watched?** +### Are subdirectories watched too? +No, you must add watches for any directory you want to watch (a recursive +watcher is on the roadmap: [#18]). -No (it shouldn't be, unless you are watching where it was moved to). +[#18]: https://github.com/fsnotify/fsnotify/issues/18 -**When I watch a directory, are all subdirectories watched as well?** +### Do I have to watch the Error and Event channels in a goroutine? +As of now, yes (you can read both channels in the same goroutine using `select`, +you don't need a separate goroutine for both channels; see the example). -No, you must add watches for any directory you want to watch (a recursive watcher is on the roadmap [#18][]). +### Why don't notifications work with NFS, SMB, FUSE, /proc, or /sys? +fsnotify requires support from underlying OS to work. The current NFS and SMB +protocols does not provide network level support for file notifications, and +neither do the /proc and /sys virtual filesystems. -**Do I have to watch the Error and Event channels in a separate goroutine?** +This could be fixed with a polling watcher ([#9]), but it's not yet implemented. -As of now, yes. Looking into making this single-thread friendly (see [howeyc #7][#7]) +[#9]: https://github.com/fsnotify/fsnotify/issues/9 -**Why am I receiving multiple events for the same file on OS X?** +Platform-specific notes +----------------------- +### Linux +When a file is removed a REMOVE event won't be emitted until all file +descriptors are closed; it will emit a CHMOD instead: -Spotlight indexing on OS X can result in multiple events (see [howeyc #62][#62]). A temporary workaround is to add your folder(s) to the *Spotlight Privacy settings* until we have a native FSEvents implementation (see [#11][]). + fp := os.Open("file") + os.Remove("file") // CHMOD + fp.Close() // REMOVE -**How many files can be watched at once?** +This is the event that inotify sends, so not much can be changed about this. -There are OS-specific limits as to how many watches can be created: -* Linux: /proc/sys/fs/inotify/max_user_watches contains the limit, reaching this limit results in a "no space left on device" error. -* BSD / OSX: sysctl variables "kern.maxfiles" and "kern.maxfilesperproc", reaching these limits results in a "too many open files" error. +The `fs.inotify.max_user_watches` sysctl variable specifies the upper limit for +the number of watches per user, and `fs.inotify.max_user_instances` specifies +the maximum number of inotify instances per user. Every Watcher you create is an +"instance", and every path you add is a "watch". -**Why don't notifications work with NFS filesystems or filesystem in userspace (FUSE)?** +These are also exposed in `/proc` as `/proc/sys/fs/inotify/max_user_watches` and +`/proc/sys/fs/inotify/max_user_instances` -fsnotify requires support from underlying OS to work. The current NFS protocol does not provide network level support for file notifications. +To increase them you can use `sysctl` or write the value to proc file: -[#62]: https://github.com/howeyc/fsnotify/issues/62 -[#18]: https://github.com/fsnotify/fsnotify/issues/18 -[#11]: https://github.com/fsnotify/fsnotify/issues/11 -[#7]: https://github.com/howeyc/fsnotify/issues/7 + # The default values on Linux 5.18 + sysctl fs.inotify.max_user_watches=124983 + sysctl fs.inotify.max_user_instances=128 + +To make the changes persist on reboot edit `/etc/sysctl.conf` or +`/usr/lib/sysctl.d/50-default.conf` (details differ per Linux distro; check your +distro's documentation): + + fs.inotify.max_user_watches=124983 + fs.inotify.max_user_instances=128 -[contributing]: https://github.com/fsnotify/fsnotify/blob/master/CONTRIBUTING.md +Reaching the limit will result in a "no space left on device" or "too many open +files" error. -## Related Projects +### kqueue (macOS, all BSD systems) +kqueue requires opening a file descriptor for every file that's being watched; +so if you're watching a directory with five files then that's six file +descriptors. You will run in to your system's "max open files" limit faster on +these platforms. -* [notify](https://github.com/rjeczalik/notify) -* [fsevents](https://github.com/fsnotify/fsevents) +The sysctl variables `kern.maxfiles` and `kern.maxfilesperproc` can be used to +control the maximum number of open files. +### macOS +Spotlight indexing on macOS can result in multiple events (see [#15]). A temporary +workaround is to add your folder(s) to the *Spotlight Privacy settings* until we +have a native FSEvents implementation (see [#11]). + +[#11]: https://github.com/fsnotify/fsnotify/issues/11 +[#15]: https://github.com/fsnotify/fsnotify/issues/15 diff --git a/vendor/github.com/fsnotify/fsnotify/backend_fen.go b/vendor/github.com/fsnotify/fsnotify/backend_fen.go new file mode 100644 index 0000000000..1a95ad8e7c --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/backend_fen.go @@ -0,0 +1,162 @@ +//go:build solaris +// +build solaris + +package fsnotify + +import ( + "errors" +) + +// Watcher watches a set of paths, delivering events on a channel. +// +// A watcher should not be copied (e.g. pass it by pointer, rather than by +// value). +// +// # Linux notes +// +// When a file is removed a Remove event won't be emitted until all file +// descriptors are closed, and deletes will always emit a Chmod. For example: +// +// fp := os.Open("file") +// os.Remove("file") // Triggers Chmod +// fp.Close() // Triggers Remove +// +// This is the event that inotify sends, so not much can be changed about this. +// +// The fs.inotify.max_user_watches sysctl variable specifies the upper limit +// for the number of watches per user, and fs.inotify.max_user_instances +// specifies the maximum number of inotify instances per user. Every Watcher you +// create is an "instance", and every path you add is a "watch". +// +// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and +// /proc/sys/fs/inotify/max_user_instances +// +// To increase them you can use sysctl or write the value to the /proc file: +// +// # Default values on Linux 5.18 +// sysctl fs.inotify.max_user_watches=124983 +// sysctl fs.inotify.max_user_instances=128 +// +// To make the changes persist on reboot edit /etc/sysctl.conf or +// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check +// your distro's documentation): +// +// fs.inotify.max_user_watches=124983 +// fs.inotify.max_user_instances=128 +// +// Reaching the limit will result in a "no space left on device" or "too many open +// files" error. +// +// # kqueue notes (macOS, BSD) +// +// kqueue requires opening a file descriptor for every file that's being watched; +// so if you're watching a directory with five files then that's six file +// descriptors. You will run in to your system's "max open files" limit faster on +// these platforms. +// +// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to +// control the maximum number of open files, as well as /etc/login.conf on BSD +// systems. +// +// # macOS notes +// +// Spotlight indexing on macOS can result in multiple events (see [#15]). A +// temporary workaround is to add your folder(s) to the "Spotlight Privacy +// Settings" until we have a native FSEvents implementation (see [#11]). +// +// [#11]: https://github.com/fsnotify/fsnotify/issues/11 +// [#15]: https://github.com/fsnotify/fsnotify/issues/15 +type Watcher struct { + // Events sends the filesystem change events. + // + // fsnotify can send the following events; a "path" here can refer to a + // file, directory, symbolic link, or special file like a FIFO. + // + // fsnotify.Create A new path was created; this may be followed by one + // or more Write events if data also gets written to a + // file. + // + // fsnotify.Remove A path was removed. + // + // fsnotify.Rename A path was renamed. A rename is always sent with the + // old path as Event.Name, and a Create event will be + // sent with the new name. Renames are only sent for + // paths that are currently watched; e.g. moving an + // unmonitored file into a monitored directory will + // show up as just a Create. Similarly, renaming a file + // to outside a monitored directory will show up as + // only a Rename. + // + // fsnotify.Write A file or named pipe was written to. A Truncate will + // also trigger a Write. A single "write action" + // initiated by the user may show up as one or multiple + // writes, depending on when the system syncs things to + // disk. For example when compiling a large Go program + // you may get hundreds of Write events, so you + // probably want to wait until you've stopped receiving + // them (see the dedup example in cmd/fsnotify). + // + // fsnotify.Chmod Attributes were changed. On Linux this is also sent + // when a file is removed (or more accurately, when a + // link to an inode is removed). On kqueue it's sent + // and on kqueue when a file is truncated. On Windows + // it's never sent. + Events chan Event + + // Errors sends any errors. + Errors chan error +} + +// NewWatcher creates a new Watcher. +func NewWatcher() (*Watcher, error) { + return nil, errors.New("FEN based watcher not yet supported for fsnotify\n") +} + +// Close removes all watches and closes the events channel. +func (w *Watcher) Close() error { + return nil +} + +// Add starts monitoring the path for changes. +// +// A path can only be watched once; attempting to watch it more than once will +// return an error. Paths that do not yet exist on the filesystem cannot be +// added. A watch will be automatically removed if the path is deleted. +// +// A path will remain watched if it gets renamed to somewhere else on the same +// filesystem, but the monitor will get removed if the path gets deleted and +// re-created, or if it's moved to a different filesystem. +// +// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special +// filesystems (/proc, /sys, etc.) generally don't work. +// +// # Watching directories +// +// All files in a directory are monitored, including new files that are created +// after the watcher is started. Subdirectories are not watched (i.e. it's +// non-recursive). +// +// # Watching files +// +// Watching individual files (rather than directories) is generally not +// recommended as many tools update files atomically. Instead of "just" writing +// to the file a temporary file will be written to first, and if successful the +// temporary file is moved to to destination removing the original, or some +// variant thereof. The watcher on the original file is now lost, as it no +// longer exists. +// +// Instead, watch the parent directory and use Event.Name to filter out files +// you're not interested in. There is an example of this in [cmd/fsnotify/file.go]. +func (w *Watcher) Add(name string) error { + return nil +} + +// Remove stops monitoring the path for changes. +// +// Directories are always removed non-recursively. For example, if you added +// /tmp/dir and /tmp/dir/subdir then you will need to remove both. +// +// Removing a path that has not yet been added returns [ErrNonExistentWatch]. +func (w *Watcher) Remove(name string) error { + return nil +} diff --git a/vendor/github.com/fsnotify/fsnotify/backend_inotify.go b/vendor/github.com/fsnotify/fsnotify/backend_inotify.go new file mode 100644 index 0000000000..54c77fbb0e --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/backend_inotify.go @@ -0,0 +1,459 @@ +//go:build linux +// +build linux + +package fsnotify + +import ( + "errors" + "fmt" + "io" + "os" + "path/filepath" + "strings" + "sync" + "unsafe" + + "golang.org/x/sys/unix" +) + +// Watcher watches a set of paths, delivering events on a channel. +// +// A watcher should not be copied (e.g. pass it by pointer, rather than by +// value). +// +// # Linux notes +// +// When a file is removed a Remove event won't be emitted until all file +// descriptors are closed, and deletes will always emit a Chmod. For example: +// +// fp := os.Open("file") +// os.Remove("file") // Triggers Chmod +// fp.Close() // Triggers Remove +// +// This is the event that inotify sends, so not much can be changed about this. +// +// The fs.inotify.max_user_watches sysctl variable specifies the upper limit +// for the number of watches per user, and fs.inotify.max_user_instances +// specifies the maximum number of inotify instances per user. Every Watcher you +// create is an "instance", and every path you add is a "watch". +// +// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and +// /proc/sys/fs/inotify/max_user_instances +// +// To increase them you can use sysctl or write the value to the /proc file: +// +// # Default values on Linux 5.18 +// sysctl fs.inotify.max_user_watches=124983 +// sysctl fs.inotify.max_user_instances=128 +// +// To make the changes persist on reboot edit /etc/sysctl.conf or +// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check +// your distro's documentation): +// +// fs.inotify.max_user_watches=124983 +// fs.inotify.max_user_instances=128 +// +// Reaching the limit will result in a "no space left on device" or "too many open +// files" error. +// +// # kqueue notes (macOS, BSD) +// +// kqueue requires opening a file descriptor for every file that's being watched; +// so if you're watching a directory with five files then that's six file +// descriptors. You will run in to your system's "max open files" limit faster on +// these platforms. +// +// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to +// control the maximum number of open files, as well as /etc/login.conf on BSD +// systems. +// +// # macOS notes +// +// Spotlight indexing on macOS can result in multiple events (see [#15]). A +// temporary workaround is to add your folder(s) to the "Spotlight Privacy +// Settings" until we have a native FSEvents implementation (see [#11]). +// +// [#11]: https://github.com/fsnotify/fsnotify/issues/11 +// [#15]: https://github.com/fsnotify/fsnotify/issues/15 +type Watcher struct { + // Events sends the filesystem change events. + // + // fsnotify can send the following events; a "path" here can refer to a + // file, directory, symbolic link, or special file like a FIFO. + // + // fsnotify.Create A new path was created; this may be followed by one + // or more Write events if data also gets written to a + // file. + // + // fsnotify.Remove A path was removed. + // + // fsnotify.Rename A path was renamed. A rename is always sent with the + // old path as Event.Name, and a Create event will be + // sent with the new name. Renames are only sent for + // paths that are currently watched; e.g. moving an + // unmonitored file into a monitored directory will + // show up as just a Create. Similarly, renaming a file + // to outside a monitored directory will show up as + // only a Rename. + // + // fsnotify.Write A file or named pipe was written to. A Truncate will + // also trigger a Write. A single "write action" + // initiated by the user may show up as one or multiple + // writes, depending on when the system syncs things to + // disk. For example when compiling a large Go program + // you may get hundreds of Write events, so you + // probably want to wait until you've stopped receiving + // them (see the dedup example in cmd/fsnotify). + // + // fsnotify.Chmod Attributes were changed. On Linux this is also sent + // when a file is removed (or more accurately, when a + // link to an inode is removed). On kqueue it's sent + // and on kqueue when a file is truncated. On Windows + // it's never sent. + Events chan Event + + // Errors sends any errors. + Errors chan error + + // Store fd here as os.File.Read() will no longer return on close after + // calling Fd(). See: https://github.com/golang/go/issues/26439 + fd int + mu sync.Mutex // Map access + inotifyFile *os.File + watches map[string]*watch // Map of inotify watches (key: path) + paths map[int]string // Map of watched paths (key: watch descriptor) + done chan struct{} // Channel for sending a "quit message" to the reader goroutine + doneResp chan struct{} // Channel to respond to Close +} + +// NewWatcher creates a new Watcher. +func NewWatcher() (*Watcher, error) { + // Create inotify fd + // Need to set the FD to nonblocking mode in order for SetDeadline methods to work + // Otherwise, blocking i/o operations won't terminate on close + fd, errno := unix.InotifyInit1(unix.IN_CLOEXEC | unix.IN_NONBLOCK) + if fd == -1 { + return nil, errno + } + + w := &Watcher{ + fd: fd, + inotifyFile: os.NewFile(uintptr(fd), ""), + watches: make(map[string]*watch), + paths: make(map[int]string), + Events: make(chan Event), + Errors: make(chan error), + done: make(chan struct{}), + doneResp: make(chan struct{}), + } + + go w.readEvents() + return w, nil +} + +// Returns true if the event was sent, or false if watcher is closed. +func (w *Watcher) sendEvent(e Event) bool { + select { + case w.Events <- e: + return true + case <-w.done: + } + return false +} + +// Returns true if the error was sent, or false if watcher is closed. +func (w *Watcher) sendError(err error) bool { + select { + case w.Errors <- err: + return true + case <-w.done: + return false + } +} + +func (w *Watcher) isClosed() bool { + select { + case <-w.done: + return true + default: + return false + } +} + +// Close removes all watches and closes the events channel. +func (w *Watcher) Close() error { + w.mu.Lock() + if w.isClosed() { + w.mu.Unlock() + return nil + } + + // Send 'close' signal to goroutine, and set the Watcher to closed. + close(w.done) + w.mu.Unlock() + + // Causes any blocking reads to return with an error, provided the file + // still supports deadline operations. + err := w.inotifyFile.Close() + if err != nil { + return err + } + + // Wait for goroutine to close + <-w.doneResp + + return nil +} + +// Add starts monitoring the path for changes. +// +// A path can only be watched once; attempting to watch it more than once will +// return an error. Paths that do not yet exist on the filesystem cannot be +// added. A watch will be automatically removed if the path is deleted. +// +// A path will remain watched if it gets renamed to somewhere else on the same +// filesystem, but the monitor will get removed if the path gets deleted and +// re-created, or if it's moved to a different filesystem. +// +// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special +// filesystems (/proc, /sys, etc.) generally don't work. +// +// # Watching directories +// +// All files in a directory are monitored, including new files that are created +// after the watcher is started. Subdirectories are not watched (i.e. it's +// non-recursive). +// +// # Watching files +// +// Watching individual files (rather than directories) is generally not +// recommended as many tools update files atomically. Instead of "just" writing +// to the file a temporary file will be written to first, and if successful the +// temporary file is moved to to destination removing the original, or some +// variant thereof. The watcher on the original file is now lost, as it no +// longer exists. +// +// Instead, watch the parent directory and use Event.Name to filter out files +// you're not interested in. There is an example of this in [cmd/fsnotify/file.go]. +func (w *Watcher) Add(name string) error { + name = filepath.Clean(name) + if w.isClosed() { + return errors.New("inotify instance already closed") + } + + var flags uint32 = unix.IN_MOVED_TO | unix.IN_MOVED_FROM | + unix.IN_CREATE | unix.IN_ATTRIB | unix.IN_MODIFY | + unix.IN_MOVE_SELF | unix.IN_DELETE | unix.IN_DELETE_SELF + + w.mu.Lock() + defer w.mu.Unlock() + watchEntry := w.watches[name] + if watchEntry != nil { + flags |= watchEntry.flags | unix.IN_MASK_ADD + } + wd, errno := unix.InotifyAddWatch(w.fd, name, flags) + if wd == -1 { + return errno + } + + if watchEntry == nil { + w.watches[name] = &watch{wd: uint32(wd), flags: flags} + w.paths[wd] = name + } else { + watchEntry.wd = uint32(wd) + watchEntry.flags = flags + } + + return nil +} + +// Remove stops monitoring the path for changes. +// +// Directories are always removed non-recursively. For example, if you added +// /tmp/dir and /tmp/dir/subdir then you will need to remove both. +// +// Removing a path that has not yet been added returns [ErrNonExistentWatch]. +func (w *Watcher) Remove(name string) error { + name = filepath.Clean(name) + + // Fetch the watch. + w.mu.Lock() + defer w.mu.Unlock() + watch, ok := w.watches[name] + + // Remove it from inotify. + if !ok { + return fmt.Errorf("%w: %s", ErrNonExistentWatch, name) + } + + // We successfully removed the watch if InotifyRmWatch doesn't return an + // error, we need to clean up our internal state to ensure it matches + // inotify's kernel state. + delete(w.paths, int(watch.wd)) + delete(w.watches, name) + + // inotify_rm_watch will return EINVAL if the file has been deleted; + // the inotify will already have been removed. + // watches and pathes are deleted in ignoreLinux() implicitly and asynchronously + // by calling inotify_rm_watch() below. e.g. readEvents() goroutine receives IN_IGNORE + // so that EINVAL means that the wd is being rm_watch()ed or its file removed + // by another thread and we have not received IN_IGNORE event. + success, errno := unix.InotifyRmWatch(w.fd, watch.wd) + if success == -1 { + // TODO: Perhaps it's not helpful to return an error here in every case; + // The only two possible errors are: + // + // - EBADF, which happens when w.fd is not a valid file descriptor + // of any kind. + // - EINVAL, which is when fd is not an inotify descriptor or wd + // is not a valid watch descriptor. Watch descriptors are + // invalidated when they are removed explicitly or implicitly; + // explicitly by inotify_rm_watch, implicitly when the file they + // are watching is deleted. + return errno + } + + return nil +} + +// WatchList returns all paths added with [Add] (and are not yet removed). +func (w *Watcher) WatchList() []string { + w.mu.Lock() + defer w.mu.Unlock() + + entries := make([]string, 0, len(w.watches)) + for pathname := range w.watches { + entries = append(entries, pathname) + } + + return entries +} + +type watch struct { + wd uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall) + flags uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags) +} + +// readEvents reads from the inotify file descriptor, converts the +// received events into Event objects and sends them via the Events channel +func (w *Watcher) readEvents() { + defer func() { + close(w.doneResp) + close(w.Errors) + close(w.Events) + }() + + var ( + buf [unix.SizeofInotifyEvent * 4096]byte // Buffer for a maximum of 4096 raw events + errno error // Syscall errno + ) + for { + // See if we have been closed. + if w.isClosed() { + return + } + + n, err := w.inotifyFile.Read(buf[:]) + switch { + case errors.Unwrap(err) == os.ErrClosed: + return + case err != nil: + if !w.sendError(err) { + return + } + continue + } + + if n < unix.SizeofInotifyEvent { + var err error + if n == 0 { + // If EOF is received. This should really never happen. + err = io.EOF + } else if n < 0 { + // If an error occurred while reading. + err = errno + } else { + // Read was too short. + err = errors.New("notify: short read in readEvents()") + } + if !w.sendError(err) { + return + } + continue + } + + var offset uint32 + // We don't know how many events we just read into the buffer + // While the offset points to at least one whole event... + for offset <= uint32(n-unix.SizeofInotifyEvent) { + var ( + // Point "raw" to the event in the buffer + raw = (*unix.InotifyEvent)(unsafe.Pointer(&buf[offset])) + mask = uint32(raw.Mask) + nameLen = uint32(raw.Len) + ) + + if mask&unix.IN_Q_OVERFLOW != 0 { + if !w.sendError(ErrEventOverflow) { + return + } + } + + // If the event happened to the watched directory or the watched file, the kernel + // doesn't append the filename to the event, but we would like to always fill the + // the "Name" field with a valid filename. We retrieve the path of the watch from + // the "paths" map. + w.mu.Lock() + name, ok := w.paths[int(raw.Wd)] + // IN_DELETE_SELF occurs when the file/directory being watched is removed. + // This is a sign to clean up the maps, otherwise we are no longer in sync + // with the inotify kernel state which has already deleted the watch + // automatically. + if ok && mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF { + delete(w.paths, int(raw.Wd)) + delete(w.watches, name) + } + w.mu.Unlock() + + if nameLen > 0 { + // Point "bytes" at the first byte of the filename + bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&buf[offset+unix.SizeofInotifyEvent]))[:nameLen:nameLen] + // The filename is padded with NULL bytes. TrimRight() gets rid of those. + name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000") + } + + event := w.newEvent(name, mask) + + // Send the events that are not ignored on the events channel + if mask&unix.IN_IGNORED == 0 { + if !w.sendEvent(event) { + return + } + } + + // Move to the next event in the buffer + offset += unix.SizeofInotifyEvent + nameLen + } + } +} + +// newEvent returns an platform-independent Event based on an inotify mask. +func (w *Watcher) newEvent(name string, mask uint32) Event { + e := Event{Name: name} + if mask&unix.IN_CREATE == unix.IN_CREATE || mask&unix.IN_MOVED_TO == unix.IN_MOVED_TO { + e.Op |= Create + } + if mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF || mask&unix.IN_DELETE == unix.IN_DELETE { + e.Op |= Remove + } + if mask&unix.IN_MODIFY == unix.IN_MODIFY { + e.Op |= Write + } + if mask&unix.IN_MOVE_SELF == unix.IN_MOVE_SELF || mask&unix.IN_MOVED_FROM == unix.IN_MOVED_FROM { + e.Op |= Rename + } + if mask&unix.IN_ATTRIB == unix.IN_ATTRIB { + e.Op |= Chmod + } + return e +} diff --git a/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go b/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go new file mode 100644 index 0000000000..29087469bf --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/backend_kqueue.go @@ -0,0 +1,707 @@ +//go:build freebsd || openbsd || netbsd || dragonfly || darwin +// +build freebsd openbsd netbsd dragonfly darwin + +package fsnotify + +import ( + "errors" + "fmt" + "io/ioutil" + "os" + "path/filepath" + "sync" + + "golang.org/x/sys/unix" +) + +// Watcher watches a set of paths, delivering events on a channel. +// +// A watcher should not be copied (e.g. pass it by pointer, rather than by +// value). +// +// # Linux notes +// +// When a file is removed a Remove event won't be emitted until all file +// descriptors are closed, and deletes will always emit a Chmod. For example: +// +// fp := os.Open("file") +// os.Remove("file") // Triggers Chmod +// fp.Close() // Triggers Remove +// +// This is the event that inotify sends, so not much can be changed about this. +// +// The fs.inotify.max_user_watches sysctl variable specifies the upper limit +// for the number of watches per user, and fs.inotify.max_user_instances +// specifies the maximum number of inotify instances per user. Every Watcher you +// create is an "instance", and every path you add is a "watch". +// +// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and +// /proc/sys/fs/inotify/max_user_instances +// +// To increase them you can use sysctl or write the value to the /proc file: +// +// # Default values on Linux 5.18 +// sysctl fs.inotify.max_user_watches=124983 +// sysctl fs.inotify.max_user_instances=128 +// +// To make the changes persist on reboot edit /etc/sysctl.conf or +// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check +// your distro's documentation): +// +// fs.inotify.max_user_watches=124983 +// fs.inotify.max_user_instances=128 +// +// Reaching the limit will result in a "no space left on device" or "too many open +// files" error. +// +// # kqueue notes (macOS, BSD) +// +// kqueue requires opening a file descriptor for every file that's being watched; +// so if you're watching a directory with five files then that's six file +// descriptors. You will run in to your system's "max open files" limit faster on +// these platforms. +// +// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to +// control the maximum number of open files, as well as /etc/login.conf on BSD +// systems. +// +// # macOS notes +// +// Spotlight indexing on macOS can result in multiple events (see [#15]). A +// temporary workaround is to add your folder(s) to the "Spotlight Privacy +// Settings" until we have a native FSEvents implementation (see [#11]). +// +// [#11]: https://github.com/fsnotify/fsnotify/issues/11 +// [#15]: https://github.com/fsnotify/fsnotify/issues/15 +type Watcher struct { + // Events sends the filesystem change events. + // + // fsnotify can send the following events; a "path" here can refer to a + // file, directory, symbolic link, or special file like a FIFO. + // + // fsnotify.Create A new path was created; this may be followed by one + // or more Write events if data also gets written to a + // file. + // + // fsnotify.Remove A path was removed. + // + // fsnotify.Rename A path was renamed. A rename is always sent with the + // old path as Event.Name, and a Create event will be + // sent with the new name. Renames are only sent for + // paths that are currently watched; e.g. moving an + // unmonitored file into a monitored directory will + // show up as just a Create. Similarly, renaming a file + // to outside a monitored directory will show up as + // only a Rename. + // + // fsnotify.Write A file or named pipe was written to. A Truncate will + // also trigger a Write. A single "write action" + // initiated by the user may show up as one or multiple + // writes, depending on when the system syncs things to + // disk. For example when compiling a large Go program + // you may get hundreds of Write events, so you + // probably want to wait until you've stopped receiving + // them (see the dedup example in cmd/fsnotify). + // + // fsnotify.Chmod Attributes were changed. On Linux this is also sent + // when a file is removed (or more accurately, when a + // link to an inode is removed). On kqueue it's sent + // and on kqueue when a file is truncated. On Windows + // it's never sent. + Events chan Event + + // Errors sends any errors. + Errors chan error + + done chan struct{} + kq int // File descriptor (as returned by the kqueue() syscall). + closepipe [2]int // Pipe used for closing. + mu sync.Mutex // Protects access to watcher data + watches map[string]int // Watched file descriptors (key: path). + watchesByDir map[string]map[int]struct{} // Watched file descriptors indexed by the parent directory (key: dirname(path)). + userWatches map[string]struct{} // Watches added with Watcher.Add() + dirFlags map[string]uint32 // Watched directories to fflags used in kqueue. + paths map[int]pathInfo // File descriptors to path names for processing kqueue events. + fileExists map[string]struct{} // Keep track of if we know this file exists (to stop duplicate create events). + isClosed bool // Set to true when Close() is first called +} + +type pathInfo struct { + name string + isDir bool +} + +// NewWatcher creates a new Watcher. +func NewWatcher() (*Watcher, error) { + kq, closepipe, err := newKqueue() + if err != nil { + return nil, err + } + + w := &Watcher{ + kq: kq, + closepipe: closepipe, + watches: make(map[string]int), + watchesByDir: make(map[string]map[int]struct{}), + dirFlags: make(map[string]uint32), + paths: make(map[int]pathInfo), + fileExists: make(map[string]struct{}), + userWatches: make(map[string]struct{}), + Events: make(chan Event), + Errors: make(chan error), + done: make(chan struct{}), + } + + go w.readEvents() + return w, nil +} + +// newKqueue creates a new kernel event queue and returns a descriptor. +// +// This registers a new event on closepipe, which will trigger an event when +// it's closed. This way we can use kevent() without timeout/polling; without +// the closepipe, it would block forever and we wouldn't be able to stop it at +// all. +func newKqueue() (kq int, closepipe [2]int, err error) { + kq, err = unix.Kqueue() + if kq == -1 { + return kq, closepipe, err + } + + // Register the close pipe. + err = unix.Pipe(closepipe[:]) + if err != nil { + unix.Close(kq) + return kq, closepipe, err + } + + // Register changes to listen on the closepipe. + changes := make([]unix.Kevent_t, 1) + // SetKevent converts int to the platform-specific types. + unix.SetKevent(&changes[0], closepipe[0], unix.EVFILT_READ, + unix.EV_ADD|unix.EV_ENABLE|unix.EV_ONESHOT) + + ok, err := unix.Kevent(kq, changes, nil, nil) + if ok == -1 { + unix.Close(kq) + unix.Close(closepipe[0]) + unix.Close(closepipe[1]) + return kq, closepipe, err + } + return kq, closepipe, nil +} + +// Returns true if the event was sent, or false if watcher is closed. +func (w *Watcher) sendEvent(e Event) bool { + select { + case w.Events <- e: + return true + case <-w.done: + } + return false +} + +// Returns true if the error was sent, or false if watcher is closed. +func (w *Watcher) sendError(err error) bool { + select { + case w.Errors <- err: + return true + case <-w.done: + } + return false +} + +// Close removes all watches and closes the events channel. +func (w *Watcher) Close() error { + w.mu.Lock() + if w.isClosed { + w.mu.Unlock() + return nil + } + w.isClosed = true + + // copy paths to remove while locked + pathsToRemove := make([]string, 0, len(w.watches)) + for name := range w.watches { + pathsToRemove = append(pathsToRemove, name) + } + w.mu.Unlock() // Unlock before calling Remove, which also locks + for _, name := range pathsToRemove { + w.Remove(name) + } + + // Send "quit" message to the reader goroutine. + unix.Close(w.closepipe[1]) + close(w.done) + + return nil +} + +// Add starts monitoring the path for changes. +// +// A path can only be watched once; attempting to watch it more than once will +// return an error. Paths that do not yet exist on the filesystem cannot be +// added. A watch will be automatically removed if the path is deleted. +// +// A path will remain watched if it gets renamed to somewhere else on the same +// filesystem, but the monitor will get removed if the path gets deleted and +// re-created, or if it's moved to a different filesystem. +// +// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special +// filesystems (/proc, /sys, etc.) generally don't work. +// +// # Watching directories +// +// All files in a directory are monitored, including new files that are created +// after the watcher is started. Subdirectories are not watched (i.e. it's +// non-recursive). +// +// # Watching files +// +// Watching individual files (rather than directories) is generally not +// recommended as many tools update files atomically. Instead of "just" writing +// to the file a temporary file will be written to first, and if successful the +// temporary file is moved to to destination removing the original, or some +// variant thereof. The watcher on the original file is now lost, as it no +// longer exists. +// +// Instead, watch the parent directory and use Event.Name to filter out files +// you're not interested in. There is an example of this in [cmd/fsnotify/file.go]. +func (w *Watcher) Add(name string) error { + w.mu.Lock() + w.userWatches[name] = struct{}{} + w.mu.Unlock() + _, err := w.addWatch(name, noteAllEvents) + return err +} + +// Remove stops monitoring the path for changes. +// +// Directories are always removed non-recursively. For example, if you added +// /tmp/dir and /tmp/dir/subdir then you will need to remove both. +// +// Removing a path that has not yet been added returns [ErrNonExistentWatch]. +func (w *Watcher) Remove(name string) error { + name = filepath.Clean(name) + w.mu.Lock() + watchfd, ok := w.watches[name] + w.mu.Unlock() + if !ok { + return fmt.Errorf("%w: %s", ErrNonExistentWatch, name) + } + + err := w.register([]int{watchfd}, unix.EV_DELETE, 0) + if err != nil { + return err + } + + unix.Close(watchfd) + + w.mu.Lock() + isDir := w.paths[watchfd].isDir + delete(w.watches, name) + delete(w.userWatches, name) + + parentName := filepath.Dir(name) + delete(w.watchesByDir[parentName], watchfd) + + if len(w.watchesByDir[parentName]) == 0 { + delete(w.watchesByDir, parentName) + } + + delete(w.paths, watchfd) + delete(w.dirFlags, name) + delete(w.fileExists, name) + w.mu.Unlock() + + // Find all watched paths that are in this directory that are not external. + if isDir { + var pathsToRemove []string + w.mu.Lock() + for fd := range w.watchesByDir[name] { + path := w.paths[fd] + if _, ok := w.userWatches[path.name]; !ok { + pathsToRemove = append(pathsToRemove, path.name) + } + } + w.mu.Unlock() + for _, name := range pathsToRemove { + // Since these are internal, not much sense in propagating error + // to the user, as that will just confuse them with an error about + // a path they did not explicitly watch themselves. + w.Remove(name) + } + } + + return nil +} + +// WatchList returns all paths added with [Add] (and are not yet removed). +func (w *Watcher) WatchList() []string { + w.mu.Lock() + defer w.mu.Unlock() + + entries := make([]string, 0, len(w.userWatches)) + for pathname := range w.userWatches { + entries = append(entries, pathname) + } + + return entries +} + +// Watch all events (except NOTE_EXTEND, NOTE_LINK, NOTE_REVOKE) +const noteAllEvents = unix.NOTE_DELETE | unix.NOTE_WRITE | unix.NOTE_ATTRIB | unix.NOTE_RENAME + +// addWatch adds name to the watched file set. +// The flags are interpreted as described in kevent(2). +// Returns the real path to the file which was added, if any, which may be different from the one passed in the case of symlinks. +func (w *Watcher) addWatch(name string, flags uint32) (string, error) { + var isDir bool + // Make ./name and name equivalent + name = filepath.Clean(name) + + w.mu.Lock() + if w.isClosed { + w.mu.Unlock() + return "", errors.New("kevent instance already closed") + } + watchfd, alreadyWatching := w.watches[name] + // We already have a watch, but we can still override flags. + if alreadyWatching { + isDir = w.paths[watchfd].isDir + } + w.mu.Unlock() + + if !alreadyWatching { + fi, err := os.Lstat(name) + if err != nil { + return "", err + } + + // Don't watch sockets or named pipes + if (fi.Mode()&os.ModeSocket == os.ModeSocket) || (fi.Mode()&os.ModeNamedPipe == os.ModeNamedPipe) { + return "", nil + } + + // Follow Symlinks + // + // Linux can add unresolvable symlinks to the watch list without issue, + // and Windows can't do symlinks period. To maintain consistency, we + // will act like everything is fine if the link can't be resolved. + // There will simply be no file events for broken symlinks. Hence the + // returns of nil on errors. + if fi.Mode()&os.ModeSymlink == os.ModeSymlink { + name, err = filepath.EvalSymlinks(name) + if err != nil { + return "", nil + } + + w.mu.Lock() + _, alreadyWatching = w.watches[name] + w.mu.Unlock() + + if alreadyWatching { + return name, nil + } + + fi, err = os.Lstat(name) + if err != nil { + return "", nil + } + } + + // Retry on EINTR; open() can return EINTR in practice on macOS. + // See #354, and go issues 11180 and 39237. + for { + watchfd, err = unix.Open(name, openMode, 0) + if err == nil { + break + } + if errors.Is(err, unix.EINTR) { + continue + } + + return "", err + } + + isDir = fi.IsDir() + } + + err := w.register([]int{watchfd}, unix.EV_ADD|unix.EV_CLEAR|unix.EV_ENABLE, flags) + if err != nil { + unix.Close(watchfd) + return "", err + } + + if !alreadyWatching { + w.mu.Lock() + parentName := filepath.Dir(name) + w.watches[name] = watchfd + + watchesByDir, ok := w.watchesByDir[parentName] + if !ok { + watchesByDir = make(map[int]struct{}, 1) + w.watchesByDir[parentName] = watchesByDir + } + watchesByDir[watchfd] = struct{}{} + + w.paths[watchfd] = pathInfo{name: name, isDir: isDir} + w.mu.Unlock() + } + + if isDir { + // Watch the directory if it has not been watched before, + // or if it was watched before, but perhaps only a NOTE_DELETE (watchDirectoryFiles) + w.mu.Lock() + + watchDir := (flags&unix.NOTE_WRITE) == unix.NOTE_WRITE && + (!alreadyWatching || (w.dirFlags[name]&unix.NOTE_WRITE) != unix.NOTE_WRITE) + // Store flags so this watch can be updated later + w.dirFlags[name] = flags + w.mu.Unlock() + + if watchDir { + if err := w.watchDirectoryFiles(name); err != nil { + return "", err + } + } + } + return name, nil +} + +// readEvents reads from kqueue and converts the received kevents into +// Event values that it sends down the Events channel. +func (w *Watcher) readEvents() { + defer func() { + err := unix.Close(w.kq) + if err != nil { + w.Errors <- err + } + unix.Close(w.closepipe[0]) + close(w.Events) + close(w.Errors) + }() + + eventBuffer := make([]unix.Kevent_t, 10) + for closed := false; !closed; { + kevents, err := w.read(eventBuffer) + // EINTR is okay, the syscall was interrupted before timeout expired. + if err != nil && err != unix.EINTR { + if !w.sendError(fmt.Errorf("fsnotify.readEvents: %w", err)) { + closed = true + } + continue + } + + // Flush the events we received to the Events channel + for _, kevent := range kevents { + var ( + watchfd = int(kevent.Ident) + mask = uint32(kevent.Fflags) + ) + + // Shut down the loop when the pipe is closed, but only after all + // other events have been processed. + if watchfd == w.closepipe[0] { + closed = true + continue + } + + w.mu.Lock() + path := w.paths[watchfd] + w.mu.Unlock() + + event := w.newEvent(path.name, mask) + + if path.isDir && !event.Has(Remove) { + // Double check to make sure the directory exists. This can + // happen when we do a rm -fr on a recursively watched folders + // and we receive a modification event first but the folder has + // been deleted and later receive the delete event. + if _, err := os.Lstat(event.Name); os.IsNotExist(err) { + event.Op |= Remove + } + } + + if event.Has(Rename) || event.Has(Remove) { + w.Remove(event.Name) + w.mu.Lock() + delete(w.fileExists, event.Name) + w.mu.Unlock() + } + + if path.isDir && event.Has(Write) && !event.Has(Remove) { + w.sendDirectoryChangeEvents(event.Name) + } else { + if !w.sendEvent(event) { + closed = true + continue + } + } + + if event.Has(Remove) { + // Look for a file that may have overwritten this. + // For example, mv f1 f2 will delete f2, then create f2. + if path.isDir { + fileDir := filepath.Clean(event.Name) + w.mu.Lock() + _, found := w.watches[fileDir] + w.mu.Unlock() + if found { + // make sure the directory exists before we watch for changes. When we + // do a recursive watch and perform rm -fr, the parent directory might + // have gone missing, ignore the missing directory and let the + // upcoming delete event remove the watch from the parent directory. + if _, err := os.Lstat(fileDir); err == nil { + w.sendDirectoryChangeEvents(fileDir) + } + } + } else { + filePath := filepath.Clean(event.Name) + if fileInfo, err := os.Lstat(filePath); err == nil { + w.sendFileCreatedEventIfNew(filePath, fileInfo) + } + } + } + } + } +} + +// newEvent returns an platform-independent Event based on kqueue Fflags. +func (w *Watcher) newEvent(name string, mask uint32) Event { + e := Event{Name: name} + if mask&unix.NOTE_DELETE == unix.NOTE_DELETE { + e.Op |= Remove + } + if mask&unix.NOTE_WRITE == unix.NOTE_WRITE { + e.Op |= Write + } + if mask&unix.NOTE_RENAME == unix.NOTE_RENAME { + e.Op |= Rename + } + if mask&unix.NOTE_ATTRIB == unix.NOTE_ATTRIB { + e.Op |= Chmod + } + return e +} + +// watchDirectoryFiles to mimic inotify when adding a watch on a directory +func (w *Watcher) watchDirectoryFiles(dirPath string) error { + // Get all files + files, err := ioutil.ReadDir(dirPath) + if err != nil { + return err + } + + for _, fileInfo := range files { + path := filepath.Join(dirPath, fileInfo.Name()) + + cleanPath, err := w.internalWatch(path, fileInfo) + if err != nil { + // No permission to read the file; that's not a problem: just skip. + // But do add it to w.fileExists to prevent it from being picked up + // as a "new" file later (it still shows up in the directory + // listing). + switch { + case errors.Is(err, unix.EACCES) || errors.Is(err, unix.EPERM): + cleanPath = filepath.Clean(path) + default: + return fmt.Errorf("%q: %w", filepath.Join(dirPath, fileInfo.Name()), err) + } + } + + w.mu.Lock() + w.fileExists[cleanPath] = struct{}{} + w.mu.Unlock() + } + + return nil +} + +// Search the directory for new files and send an event for them. +// +// This functionality is to have the BSD watcher match the inotify, which sends +// a create event for files created in a watched directory. +func (w *Watcher) sendDirectoryChangeEvents(dir string) { + // Get all files + files, err := ioutil.ReadDir(dir) + if err != nil { + if !w.sendError(fmt.Errorf("fsnotify.sendDirectoryChangeEvents: %w", err)) { + return + } + } + + // Search for new files + for _, fi := range files { + err := w.sendFileCreatedEventIfNew(filepath.Join(dir, fi.Name()), fi) + if err != nil { + return + } + } +} + +// sendFileCreatedEvent sends a create event if the file isn't already being tracked. +func (w *Watcher) sendFileCreatedEventIfNew(filePath string, fileInfo os.FileInfo) (err error) { + w.mu.Lock() + _, doesExist := w.fileExists[filePath] + w.mu.Unlock() + if !doesExist { + if !w.sendEvent(Event{Name: filePath, Op: Create}) { + return + } + } + + // like watchDirectoryFiles (but without doing another ReadDir) + filePath, err = w.internalWatch(filePath, fileInfo) + if err != nil { + return err + } + + w.mu.Lock() + w.fileExists[filePath] = struct{}{} + w.mu.Unlock() + + return nil +} + +func (w *Watcher) internalWatch(name string, fileInfo os.FileInfo) (string, error) { + if fileInfo.IsDir() { + // mimic Linux providing delete events for subdirectories + // but preserve the flags used if currently watching subdirectory + w.mu.Lock() + flags := w.dirFlags[name] + w.mu.Unlock() + + flags |= unix.NOTE_DELETE | unix.NOTE_RENAME + return w.addWatch(name, flags) + } + + // watch file to mimic Linux inotify + return w.addWatch(name, noteAllEvents) +} + +// Register events with the queue. +func (w *Watcher) register(fds []int, flags int, fflags uint32) error { + changes := make([]unix.Kevent_t, len(fds)) + for i, fd := range fds { + // SetKevent converts int to the platform-specific types. + unix.SetKevent(&changes[i], fd, unix.EVFILT_VNODE, flags) + changes[i].Fflags = fflags + } + + // Register the events. + success, err := unix.Kevent(w.kq, changes, nil, nil) + if success == -1 { + return err + } + return nil +} + +// read retrieves pending events, or waits until an event occurs. +func (w *Watcher) read(events []unix.Kevent_t) ([]unix.Kevent_t, error) { + n, err := unix.Kevent(w.kq, nil, events, nil) + if err != nil { + return nil, err + } + return events[0:n], nil +} diff --git a/vendor/github.com/fsnotify/fsnotify/backend_other.go b/vendor/github.com/fsnotify/fsnotify/backend_other.go new file mode 100644 index 0000000000..a9bb1c3c4d --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/backend_other.go @@ -0,0 +1,66 @@ +//go:build !darwin && !dragonfly && !freebsd && !openbsd && !linux && !netbsd && !solaris && !windows +// +build !darwin,!dragonfly,!freebsd,!openbsd,!linux,!netbsd,!solaris,!windows + +package fsnotify + +import ( + "fmt" + "runtime" +) + +// Watcher watches a set of files, delivering events to a channel. +type Watcher struct{} + +// NewWatcher creates a new Watcher. +func NewWatcher() (*Watcher, error) { + return nil, fmt.Errorf("fsnotify not supported on %s", runtime.GOOS) +} + +// Close removes all watches and closes the events channel. +func (w *Watcher) Close() error { + return nil +} + +// Add starts monitoring the path for changes. +// +// A path can only be watched once; attempting to watch it more than once will +// return an error. Paths that do not yet exist on the filesystem cannot be +// added. A watch will be automatically removed if the path is deleted. +// +// A path will remain watched if it gets renamed to somewhere else on the same +// filesystem, but the monitor will get removed if the path gets deleted and +// re-created, or if it's moved to a different filesystem. +// +// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special +// filesystems (/proc, /sys, etc.) generally don't work. +// +// # Watching directories +// +// All files in a directory are monitored, including new files that are created +// after the watcher is started. Subdirectories are not watched (i.e. it's +// non-recursive). +// +// # Watching files +// +// Watching individual files (rather than directories) is generally not +// recommended as many tools update files atomically. Instead of "just" writing +// to the file a temporary file will be written to first, and if successful the +// temporary file is moved to to destination removing the original, or some +// variant thereof. The watcher on the original file is now lost, as it no +// longer exists. +// +// Instead, watch the parent directory and use Event.Name to filter out files +// you're not interested in. There is an example of this in [cmd/fsnotify/file.go]. +func (w *Watcher) Add(name string) error { + return nil +} + +// Remove stops monitoring the path for changes. +// +// Directories are always removed non-recursively. For example, if you added +// /tmp/dir and /tmp/dir/subdir then you will need to remove both. +// +// Removing a path that has not yet been added returns [ErrNonExistentWatch]. +func (w *Watcher) Remove(name string) error { + return nil +} diff --git a/vendor/github.com/fsnotify/fsnotify/backend_windows.go b/vendor/github.com/fsnotify/fsnotify/backend_windows.go new file mode 100644 index 0000000000..ae392867c0 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/backend_windows.go @@ -0,0 +1,746 @@ +//go:build windows +// +build windows + +package fsnotify + +import ( + "errors" + "fmt" + "os" + "path/filepath" + "reflect" + "runtime" + "strings" + "sync" + "unsafe" + + "golang.org/x/sys/windows" +) + +// Watcher watches a set of paths, delivering events on a channel. +// +// A watcher should not be copied (e.g. pass it by pointer, rather than by +// value). +// +// # Linux notes +// +// When a file is removed a Remove event won't be emitted until all file +// descriptors are closed, and deletes will always emit a Chmod. For example: +// +// fp := os.Open("file") +// os.Remove("file") // Triggers Chmod +// fp.Close() // Triggers Remove +// +// This is the event that inotify sends, so not much can be changed about this. +// +// The fs.inotify.max_user_watches sysctl variable specifies the upper limit +// for the number of watches per user, and fs.inotify.max_user_instances +// specifies the maximum number of inotify instances per user. Every Watcher you +// create is an "instance", and every path you add is a "watch". +// +// These are also exposed in /proc as /proc/sys/fs/inotify/max_user_watches and +// /proc/sys/fs/inotify/max_user_instances +// +// To increase them you can use sysctl or write the value to the /proc file: +// +// # Default values on Linux 5.18 +// sysctl fs.inotify.max_user_watches=124983 +// sysctl fs.inotify.max_user_instances=128 +// +// To make the changes persist on reboot edit /etc/sysctl.conf or +// /usr/lib/sysctl.d/50-default.conf (details differ per Linux distro; check +// your distro's documentation): +// +// fs.inotify.max_user_watches=124983 +// fs.inotify.max_user_instances=128 +// +// Reaching the limit will result in a "no space left on device" or "too many open +// files" error. +// +// # kqueue notes (macOS, BSD) +// +// kqueue requires opening a file descriptor for every file that's being watched; +// so if you're watching a directory with five files then that's six file +// descriptors. You will run in to your system's "max open files" limit faster on +// these platforms. +// +// The sysctl variables kern.maxfiles and kern.maxfilesperproc can be used to +// control the maximum number of open files, as well as /etc/login.conf on BSD +// systems. +// +// # macOS notes +// +// Spotlight indexing on macOS can result in multiple events (see [#15]). A +// temporary workaround is to add your folder(s) to the "Spotlight Privacy +// Settings" until we have a native FSEvents implementation (see [#11]). +// +// [#11]: https://github.com/fsnotify/fsnotify/issues/11 +// [#15]: https://github.com/fsnotify/fsnotify/issues/15 +type Watcher struct { + // Events sends the filesystem change events. + // + // fsnotify can send the following events; a "path" here can refer to a + // file, directory, symbolic link, or special file like a FIFO. + // + // fsnotify.Create A new path was created; this may be followed by one + // or more Write events if data also gets written to a + // file. + // + // fsnotify.Remove A path was removed. + // + // fsnotify.Rename A path was renamed. A rename is always sent with the + // old path as Event.Name, and a Create event will be + // sent with the new name. Renames are only sent for + // paths that are currently watched; e.g. moving an + // unmonitored file into a monitored directory will + // show up as just a Create. Similarly, renaming a file + // to outside a monitored directory will show up as + // only a Rename. + // + // fsnotify.Write A file or named pipe was written to. A Truncate will + // also trigger a Write. A single "write action" + // initiated by the user may show up as one or multiple + // writes, depending on when the system syncs things to + // disk. For example when compiling a large Go program + // you may get hundreds of Write events, so you + // probably want to wait until you've stopped receiving + // them (see the dedup example in cmd/fsnotify). + // + // fsnotify.Chmod Attributes were changed. On Linux this is also sent + // when a file is removed (or more accurately, when a + // link to an inode is removed). On kqueue it's sent + // and on kqueue when a file is truncated. On Windows + // it's never sent. + Events chan Event + + // Errors sends any errors. + Errors chan error + + port windows.Handle // Handle to completion port + input chan *input // Inputs to the reader are sent on this channel + quit chan chan<- error + + mu sync.Mutex // Protects access to watches, isClosed + watches watchMap // Map of watches (key: i-number) + isClosed bool // Set to true when Close() is first called +} + +// NewWatcher creates a new Watcher. +func NewWatcher() (*Watcher, error) { + port, err := windows.CreateIoCompletionPort(windows.InvalidHandle, 0, 0, 0) + if err != nil { + return nil, os.NewSyscallError("CreateIoCompletionPort", err) + } + w := &Watcher{ + port: port, + watches: make(watchMap), + input: make(chan *input, 1), + Events: make(chan Event, 50), + Errors: make(chan error), + quit: make(chan chan<- error, 1), + } + go w.readEvents() + return w, nil +} + +func (w *Watcher) sendEvent(name string, mask uint64) bool { + if mask == 0 { + return false + } + + event := w.newEvent(name, uint32(mask)) + select { + case ch := <-w.quit: + w.quit <- ch + case w.Events <- event: + } + return true +} + +// Returns true if the error was sent, or false if watcher is closed. +func (w *Watcher) sendError(err error) bool { + select { + case w.Errors <- err: + return true + case <-w.quit: + } + return false +} + +// Close removes all watches and closes the events channel. +func (w *Watcher) Close() error { + w.mu.Lock() + if w.isClosed { + w.mu.Unlock() + return nil + } + w.isClosed = true + w.mu.Unlock() + + // Send "quit" message to the reader goroutine + ch := make(chan error) + w.quit <- ch + if err := w.wakeupReader(); err != nil { + return err + } + return <-ch +} + +// Add starts monitoring the path for changes. +// +// A path can only be watched once; attempting to watch it more than once will +// return an error. Paths that do not yet exist on the filesystem cannot be +// added. A watch will be automatically removed if the path is deleted. +// +// A path will remain watched if it gets renamed to somewhere else on the same +// filesystem, but the monitor will get removed if the path gets deleted and +// re-created, or if it's moved to a different filesystem. +// +// Notifications on network filesystems (NFS, SMB, FUSE, etc.) or special +// filesystems (/proc, /sys, etc.) generally don't work. +// +// # Watching directories +// +// All files in a directory are monitored, including new files that are created +// after the watcher is started. Subdirectories are not watched (i.e. it's +// non-recursive). +// +// # Watching files +// +// Watching individual files (rather than directories) is generally not +// recommended as many tools update files atomically. Instead of "just" writing +// to the file a temporary file will be written to first, and if successful the +// temporary file is moved to to destination removing the original, or some +// variant thereof. The watcher on the original file is now lost, as it no +// longer exists. +// +// Instead, watch the parent directory and use Event.Name to filter out files +// you're not interested in. There is an example of this in [cmd/fsnotify/file.go]. +func (w *Watcher) Add(name string) error { + w.mu.Lock() + if w.isClosed { + w.mu.Unlock() + return errors.New("watcher already closed") + } + w.mu.Unlock() + + in := &input{ + op: opAddWatch, + path: filepath.Clean(name), + flags: sysFSALLEVENTS, + reply: make(chan error), + } + w.input <- in + if err := w.wakeupReader(); err != nil { + return err + } + return <-in.reply +} + +// Remove stops monitoring the path for changes. +// +// Directories are always removed non-recursively. For example, if you added +// /tmp/dir and /tmp/dir/subdir then you will need to remove both. +// +// Removing a path that has not yet been added returns [ErrNonExistentWatch]. +func (w *Watcher) Remove(name string) error { + in := &input{ + op: opRemoveWatch, + path: filepath.Clean(name), + reply: make(chan error), + } + w.input <- in + if err := w.wakeupReader(); err != nil { + return err + } + return <-in.reply +} + +// WatchList returns all paths added with [Add] (and are not yet removed). +func (w *Watcher) WatchList() []string { + w.mu.Lock() + defer w.mu.Unlock() + + entries := make([]string, 0, len(w.watches)) + for _, entry := range w.watches { + for _, watchEntry := range entry { + entries = append(entries, watchEntry.path) + } + } + + return entries +} + +// These options are from the old golang.org/x/exp/winfsnotify, where you could +// add various options to the watch. This has long since been removed. +// +// The "sys" in the name is misleading as they're not part of any "system". +// +// This should all be removed at some point, and just use windows.FILE_NOTIFY_* +const ( + sysFSALLEVENTS = 0xfff + sysFSATTRIB = 0x4 + sysFSCREATE = 0x100 + sysFSDELETE = 0x200 + sysFSDELETESELF = 0x400 + sysFSMODIFY = 0x2 + sysFSMOVE = 0xc0 + sysFSMOVEDFROM = 0x40 + sysFSMOVEDTO = 0x80 + sysFSMOVESELF = 0x800 + sysFSIGNORED = 0x8000 +) + +func (w *Watcher) newEvent(name string, mask uint32) Event { + e := Event{Name: name} + if mask&sysFSCREATE == sysFSCREATE || mask&sysFSMOVEDTO == sysFSMOVEDTO { + e.Op |= Create + } + if mask&sysFSDELETE == sysFSDELETE || mask&sysFSDELETESELF == sysFSDELETESELF { + e.Op |= Remove + } + if mask&sysFSMODIFY == sysFSMODIFY { + e.Op |= Write + } + if mask&sysFSMOVE == sysFSMOVE || mask&sysFSMOVESELF == sysFSMOVESELF || mask&sysFSMOVEDFROM == sysFSMOVEDFROM { + e.Op |= Rename + } + if mask&sysFSATTRIB == sysFSATTRIB { + e.Op |= Chmod + } + return e +} + +const ( + opAddWatch = iota + opRemoveWatch +) + +const ( + provisional uint64 = 1 << (32 + iota) +) + +type input struct { + op int + path string + flags uint32 + reply chan error +} + +type inode struct { + handle windows.Handle + volume uint32 + index uint64 +} + +type watch struct { + ov windows.Overlapped + ino *inode // i-number + path string // Directory path + mask uint64 // Directory itself is being watched with these notify flags + names map[string]uint64 // Map of names being watched and their notify flags + rename string // Remembers the old name while renaming a file + buf [65536]byte // 64K buffer +} + +type ( + indexMap map[uint64]*watch + watchMap map[uint32]indexMap +) + +func (w *Watcher) wakeupReader() error { + err := windows.PostQueuedCompletionStatus(w.port, 0, 0, nil) + if err != nil { + return os.NewSyscallError("PostQueuedCompletionStatus", err) + } + return nil +} + +func (w *Watcher) getDir(pathname string) (dir string, err error) { + attr, err := windows.GetFileAttributes(windows.StringToUTF16Ptr(pathname)) + if err != nil { + return "", os.NewSyscallError("GetFileAttributes", err) + } + if attr&windows.FILE_ATTRIBUTE_DIRECTORY != 0 { + dir = pathname + } else { + dir, _ = filepath.Split(pathname) + dir = filepath.Clean(dir) + } + return +} + +func (w *Watcher) getIno(path string) (ino *inode, err error) { + h, err := windows.CreateFile(windows.StringToUTF16Ptr(path), + windows.FILE_LIST_DIRECTORY, + windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE|windows.FILE_SHARE_DELETE, + nil, windows.OPEN_EXISTING, + windows.FILE_FLAG_BACKUP_SEMANTICS|windows.FILE_FLAG_OVERLAPPED, 0) + if err != nil { + return nil, os.NewSyscallError("CreateFile", err) + } + + var fi windows.ByHandleFileInformation + err = windows.GetFileInformationByHandle(h, &fi) + if err != nil { + windows.CloseHandle(h) + return nil, os.NewSyscallError("GetFileInformationByHandle", err) + } + ino = &inode{ + handle: h, + volume: fi.VolumeSerialNumber, + index: uint64(fi.FileIndexHigh)<<32 | uint64(fi.FileIndexLow), + } + return ino, nil +} + +// Must run within the I/O thread. +func (m watchMap) get(ino *inode) *watch { + if i := m[ino.volume]; i != nil { + return i[ino.index] + } + return nil +} + +// Must run within the I/O thread. +func (m watchMap) set(ino *inode, watch *watch) { + i := m[ino.volume] + if i == nil { + i = make(indexMap) + m[ino.volume] = i + } + i[ino.index] = watch +} + +// Must run within the I/O thread. +func (w *Watcher) addWatch(pathname string, flags uint64) error { + dir, err := w.getDir(pathname) + if err != nil { + return err + } + + ino, err := w.getIno(dir) + if err != nil { + return err + } + w.mu.Lock() + watchEntry := w.watches.get(ino) + w.mu.Unlock() + if watchEntry == nil { + _, err := windows.CreateIoCompletionPort(ino.handle, w.port, 0, 0) + if err != nil { + windows.CloseHandle(ino.handle) + return os.NewSyscallError("CreateIoCompletionPort", err) + } + watchEntry = &watch{ + ino: ino, + path: dir, + names: make(map[string]uint64), + } + w.mu.Lock() + w.watches.set(ino, watchEntry) + w.mu.Unlock() + flags |= provisional + } else { + windows.CloseHandle(ino.handle) + } + if pathname == dir { + watchEntry.mask |= flags + } else { + watchEntry.names[filepath.Base(pathname)] |= flags + } + + err = w.startRead(watchEntry) + if err != nil { + return err + } + + if pathname == dir { + watchEntry.mask &= ^provisional + } else { + watchEntry.names[filepath.Base(pathname)] &= ^provisional + } + return nil +} + +// Must run within the I/O thread. +func (w *Watcher) remWatch(pathname string) error { + dir, err := w.getDir(pathname) + if err != nil { + return err + } + ino, err := w.getIno(dir) + if err != nil { + return err + } + + w.mu.Lock() + watch := w.watches.get(ino) + w.mu.Unlock() + + err = windows.CloseHandle(ino.handle) + if err != nil { + w.sendError(os.NewSyscallError("CloseHandle", err)) + } + if watch == nil { + return fmt.Errorf("%w: %s", ErrNonExistentWatch, pathname) + } + if pathname == dir { + w.sendEvent(watch.path, watch.mask&sysFSIGNORED) + watch.mask = 0 + } else { + name := filepath.Base(pathname) + w.sendEvent(filepath.Join(watch.path, name), watch.names[name]&sysFSIGNORED) + delete(watch.names, name) + } + + return w.startRead(watch) +} + +// Must run within the I/O thread. +func (w *Watcher) deleteWatch(watch *watch) { + for name, mask := range watch.names { + if mask&provisional == 0 { + w.sendEvent(filepath.Join(watch.path, name), mask&sysFSIGNORED) + } + delete(watch.names, name) + } + if watch.mask != 0 { + if watch.mask&provisional == 0 { + w.sendEvent(watch.path, watch.mask&sysFSIGNORED) + } + watch.mask = 0 + } +} + +// Must run within the I/O thread. +func (w *Watcher) startRead(watch *watch) error { + err := windows.CancelIo(watch.ino.handle) + if err != nil { + w.sendError(os.NewSyscallError("CancelIo", err)) + w.deleteWatch(watch) + } + mask := w.toWindowsFlags(watch.mask) + for _, m := range watch.names { + mask |= w.toWindowsFlags(m) + } + if mask == 0 { + err := windows.CloseHandle(watch.ino.handle) + if err != nil { + w.sendError(os.NewSyscallError("CloseHandle", err)) + } + w.mu.Lock() + delete(w.watches[watch.ino.volume], watch.ino.index) + w.mu.Unlock() + return nil + } + + rdErr := windows.ReadDirectoryChanges(watch.ino.handle, &watch.buf[0], + uint32(unsafe.Sizeof(watch.buf)), false, mask, nil, &watch.ov, 0) + if rdErr != nil { + err := os.NewSyscallError("ReadDirectoryChanges", rdErr) + if rdErr == windows.ERROR_ACCESS_DENIED && watch.mask&provisional == 0 { + // Watched directory was probably removed + w.sendEvent(watch.path, watch.mask&sysFSDELETESELF) + err = nil + } + w.deleteWatch(watch) + w.startRead(watch) + return err + } + return nil +} + +// readEvents reads from the I/O completion port, converts the +// received events into Event objects and sends them via the Events channel. +// Entry point to the I/O thread. +func (w *Watcher) readEvents() { + var ( + n uint32 + key uintptr + ov *windows.Overlapped + ) + runtime.LockOSThread() + + for { + qErr := windows.GetQueuedCompletionStatus(w.port, &n, &key, &ov, windows.INFINITE) + // This error is handled after the watch == nil check below. NOTE: this + // seems odd, note sure if it's correct. + + watch := (*watch)(unsafe.Pointer(ov)) + if watch == nil { + select { + case ch := <-w.quit: + w.mu.Lock() + var indexes []indexMap + for _, index := range w.watches { + indexes = append(indexes, index) + } + w.mu.Unlock() + for _, index := range indexes { + for _, watch := range index { + w.deleteWatch(watch) + w.startRead(watch) + } + } + + err := windows.CloseHandle(w.port) + if err != nil { + err = os.NewSyscallError("CloseHandle", err) + } + close(w.Events) + close(w.Errors) + ch <- err + return + case in := <-w.input: + switch in.op { + case opAddWatch: + in.reply <- w.addWatch(in.path, uint64(in.flags)) + case opRemoveWatch: + in.reply <- w.remWatch(in.path) + } + default: + } + continue + } + + switch qErr { + case windows.ERROR_MORE_DATA: + if watch == nil { + w.sendError(errors.New("ERROR_MORE_DATA has unexpectedly null lpOverlapped buffer")) + } else { + // The i/o succeeded but the buffer is full. + // In theory we should be building up a full packet. + // In practice we can get away with just carrying on. + n = uint32(unsafe.Sizeof(watch.buf)) + } + case windows.ERROR_ACCESS_DENIED: + // Watched directory was probably removed + w.sendEvent(watch.path, watch.mask&sysFSDELETESELF) + w.deleteWatch(watch) + w.startRead(watch) + continue + case windows.ERROR_OPERATION_ABORTED: + // CancelIo was called on this handle + continue + default: + w.sendError(os.NewSyscallError("GetQueuedCompletionPort", qErr)) + continue + case nil: + } + + var offset uint32 + for { + if n == 0 { + w.sendError(errors.New("short read in readEvents()")) + break + } + + // Point "raw" to the event in the buffer + raw := (*windows.FileNotifyInformation)(unsafe.Pointer(&watch.buf[offset])) + + // Create a buf that is the size of the path name + size := int(raw.FileNameLength / 2) + var buf []uint16 + // TODO: Use unsafe.Slice in Go 1.17; https://stackoverflow.com/questions/51187973 + sh := (*reflect.SliceHeader)(unsafe.Pointer(&buf)) + sh.Data = uintptr(unsafe.Pointer(&raw.FileName)) + sh.Len = size + sh.Cap = size + name := windows.UTF16ToString(buf) + fullname := filepath.Join(watch.path, name) + + var mask uint64 + switch raw.Action { + case windows.FILE_ACTION_REMOVED: + mask = sysFSDELETESELF + case windows.FILE_ACTION_MODIFIED: + mask = sysFSMODIFY + case windows.FILE_ACTION_RENAMED_OLD_NAME: + watch.rename = name + case windows.FILE_ACTION_RENAMED_NEW_NAME: + // Update saved path of all sub-watches. + old := filepath.Join(watch.path, watch.rename) + w.mu.Lock() + for _, watchMap := range w.watches { + for _, ww := range watchMap { + if strings.HasPrefix(ww.path, old) { + ww.path = filepath.Join(fullname, strings.TrimPrefix(ww.path, old)) + } + } + } + w.mu.Unlock() + + if watch.names[watch.rename] != 0 { + watch.names[name] |= watch.names[watch.rename] + delete(watch.names, watch.rename) + mask = sysFSMOVESELF + } + } + + sendNameEvent := func() { + w.sendEvent(fullname, watch.names[name]&mask) + } + if raw.Action != windows.FILE_ACTION_RENAMED_NEW_NAME { + sendNameEvent() + } + if raw.Action == windows.FILE_ACTION_REMOVED { + w.sendEvent(fullname, watch.names[name]&sysFSIGNORED) + delete(watch.names, name) + } + + w.sendEvent(fullname, watch.mask&w.toFSnotifyFlags(raw.Action)) + if raw.Action == windows.FILE_ACTION_RENAMED_NEW_NAME { + fullname = filepath.Join(watch.path, watch.rename) + sendNameEvent() + } + + // Move to the next event in the buffer + if raw.NextEntryOffset == 0 { + break + } + offset += raw.NextEntryOffset + + // Error! + if offset >= n { + w.sendError(errors.New( + "Windows system assumed buffer larger than it is, events have likely been missed.")) + break + } + } + + if err := w.startRead(watch); err != nil { + w.sendError(err) + } + } +} + +func (w *Watcher) toWindowsFlags(mask uint64) uint32 { + var m uint32 + if mask&sysFSMODIFY != 0 { + m |= windows.FILE_NOTIFY_CHANGE_LAST_WRITE + } + if mask&sysFSATTRIB != 0 { + m |= windows.FILE_NOTIFY_CHANGE_ATTRIBUTES + } + if mask&(sysFSMOVE|sysFSCREATE|sysFSDELETE) != 0 { + m |= windows.FILE_NOTIFY_CHANGE_FILE_NAME | windows.FILE_NOTIFY_CHANGE_DIR_NAME + } + return m +} + +func (w *Watcher) toFSnotifyFlags(action uint32) uint64 { + switch action { + case windows.FILE_ACTION_ADDED: + return sysFSCREATE + case windows.FILE_ACTION_REMOVED: + return sysFSDELETE + case windows.FILE_ACTION_MODIFIED: + return sysFSMODIFY + case windows.FILE_ACTION_RENAMED_OLD_NAME: + return sysFSMOVEDFROM + case windows.FILE_ACTION_RENAMED_NEW_NAME: + return sysFSMOVEDTO + } + return 0 +} diff --git a/vendor/github.com/fsnotify/fsnotify/fen.go b/vendor/github.com/fsnotify/fsnotify/fen.go deleted file mode 100644 index b3ac3d8f55..0000000000 --- a/vendor/github.com/fsnotify/fsnotify/fen.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build solaris -// +build solaris - -package fsnotify - -import ( - "errors" -) - -// Watcher watches a set of files, delivering events to a channel. -type Watcher struct { - Events chan Event - Errors chan error -} - -// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events. -func NewWatcher() (*Watcher, error) { - return nil, errors.New("FEN based watcher not yet supported for fsnotify\n") -} - -// Close removes all watches and closes the events channel. -func (w *Watcher) Close() error { - return nil -} - -// Add starts watching the named file or directory (non-recursively). -func (w *Watcher) Add(name string) error { - return nil -} - -// Remove stops watching the the named file or directory (non-recursively). -func (w *Watcher) Remove(name string) error { - return nil -} diff --git a/vendor/github.com/fsnotify/fsnotify/fsnotify.go b/vendor/github.com/fsnotify/fsnotify/fsnotify.go index 0f4ee52e8a..30a5bf0f07 100644 --- a/vendor/github.com/fsnotify/fsnotify/fsnotify.go +++ b/vendor/github.com/fsnotify/fsnotify/fsnotify.go @@ -1,29 +1,37 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - //go:build !plan9 // +build !plan9 -// Package fsnotify provides a platform-independent interface for file system notifications. +// Package fsnotify provides a cross-platform interface for file system +// notifications. package fsnotify import ( - "bytes" "errors" "fmt" + "strings" ) -// Event represents a single file system notification. +// Event represents a file system notification. type Event struct { - Name string // Relative path to the file or directory. - Op Op // File operation that triggered the event. + // Path to the file or directory. + // + // Paths are relative to the input; for example with Add("dir") the Name + // will be set to "dir/file" if you create that file, but if you use + // Add("/path/to/dir") it will be "/path/to/dir/file". + Name string + + // File operation that triggered the event. + // + // This is a bitmask and some systems may send multiple operations at once. + // Use the Event.Has() method instead of comparing with ==. + Op Op } // Op describes a set of file operations. type Op uint32 -// These are the generalized file operations that can trigger a notification. +// The operations fsnotify can trigger; see the documentation on [Watcher] for a +// full description, and check them with [Event.Has]. const ( Create Op = 1 << iota Write @@ -32,38 +40,42 @@ const ( Chmod ) -func (op Op) String() string { - // Use a buffer for efficient string concatenation - var buffer bytes.Buffer +// Common errors that can be reported by a watcher +var ( + ErrNonExistentWatch = errors.New("can't remove non-existent watcher") + ErrEventOverflow = errors.New("fsnotify queue overflow") +) - if op&Create == Create { - buffer.WriteString("|CREATE") +func (op Op) String() string { + var b strings.Builder + if op.Has(Create) { + b.WriteString("|CREATE") } - if op&Remove == Remove { - buffer.WriteString("|REMOVE") + if op.Has(Remove) { + b.WriteString("|REMOVE") } - if op&Write == Write { - buffer.WriteString("|WRITE") + if op.Has(Write) { + b.WriteString("|WRITE") } - if op&Rename == Rename { - buffer.WriteString("|RENAME") + if op.Has(Rename) { + b.WriteString("|RENAME") } - if op&Chmod == Chmod { - buffer.WriteString("|CHMOD") + if op.Has(Chmod) { + b.WriteString("|CHMOD") } - if buffer.Len() == 0 { - return "" + if b.Len() == 0 { + return "[no events]" } - return buffer.String()[1:] // Strip leading pipe + return b.String()[1:] } -// String returns a string representation of the event in the form -// "file: REMOVE|WRITE|..." +// Has reports if this operation has the given operation. +func (o Op) Has(h Op) bool { return o&h == h } + +// Has reports if this event has the given operation. +func (e Event) Has(op Op) bool { return e.Op.Has(op) } + +// String returns a string representation of the event with their path. func (e Event) String() string { - return fmt.Sprintf("%q: %s", e.Name, e.Op.String()) + return fmt.Sprintf("%-13s %q", e.Op.String(), e.Name) } - -// Common errors that can be reported by a watcher -var ( - ErrEventOverflow = errors.New("fsnotify queue overflow") -) diff --git a/vendor/github.com/fsnotify/fsnotify/fsnotify_unsupported.go b/vendor/github.com/fsnotify/fsnotify/fsnotify_unsupported.go deleted file mode 100644 index 5968855983..0000000000 --- a/vendor/github.com/fsnotify/fsnotify/fsnotify_unsupported.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !darwin && !dragonfly && !freebsd && !openbsd && !linux && !netbsd && !solaris && !windows -// +build !darwin,!dragonfly,!freebsd,!openbsd,!linux,!netbsd,!solaris,!windows - -package fsnotify - -import ( - "fmt" - "runtime" -) - -// Watcher watches a set of files, delivering events to a channel. -type Watcher struct{} - -// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events. -func NewWatcher() (*Watcher, error) { - return nil, fmt.Errorf("fsnotify not supported on %s", runtime.GOOS) -} - -// Close removes all watches and closes the events channel. -func (w *Watcher) Close() error { - return nil -} - -// Add starts watching the named file or directory (non-recursively). -func (w *Watcher) Add(name string) error { - return nil -} - -// Remove stops watching the the named file or directory (non-recursively). -func (w *Watcher) Remove(name string) error { - return nil -} diff --git a/vendor/github.com/fsnotify/fsnotify/inotify.go b/vendor/github.com/fsnotify/fsnotify/inotify.go deleted file mode 100644 index a6d0e0ec8c..0000000000 --- a/vendor/github.com/fsnotify/fsnotify/inotify.go +++ /dev/null @@ -1,351 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build linux -// +build linux - -package fsnotify - -import ( - "errors" - "fmt" - "io" - "os" - "path/filepath" - "strings" - "sync" - "unsafe" - - "golang.org/x/sys/unix" -) - -// Watcher watches a set of files, delivering events to a channel. -type Watcher struct { - Events chan Event - Errors chan error - mu sync.Mutex // Map access - fd int - poller *fdPoller - watches map[string]*watch // Map of inotify watches (key: path) - paths map[int]string // Map of watched paths (key: watch descriptor) - done chan struct{} // Channel for sending a "quit message" to the reader goroutine - doneResp chan struct{} // Channel to respond to Close -} - -// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events. -func NewWatcher() (*Watcher, error) { - // Create inotify fd - fd, errno := unix.InotifyInit1(unix.IN_CLOEXEC) - if fd == -1 { - return nil, errno - } - // Create epoll - poller, err := newFdPoller(fd) - if err != nil { - unix.Close(fd) - return nil, err - } - w := &Watcher{ - fd: fd, - poller: poller, - watches: make(map[string]*watch), - paths: make(map[int]string), - Events: make(chan Event), - Errors: make(chan error), - done: make(chan struct{}), - doneResp: make(chan struct{}), - } - - go w.readEvents() - return w, nil -} - -func (w *Watcher) isClosed() bool { - select { - case <-w.done: - return true - default: - return false - } -} - -// Close removes all watches and closes the events channel. -func (w *Watcher) Close() error { - if w.isClosed() { - return nil - } - - // Send 'close' signal to goroutine, and set the Watcher to closed. - close(w.done) - - // Wake up goroutine - w.poller.wake() - - // Wait for goroutine to close - <-w.doneResp - - return nil -} - -// Add starts watching the named file or directory (non-recursively). -func (w *Watcher) Add(name string) error { - name = filepath.Clean(name) - if w.isClosed() { - return errors.New("inotify instance already closed") - } - - const agnosticEvents = unix.IN_MOVED_TO | unix.IN_MOVED_FROM | - unix.IN_CREATE | unix.IN_ATTRIB | unix.IN_MODIFY | - unix.IN_MOVE_SELF | unix.IN_DELETE | unix.IN_DELETE_SELF - - var flags uint32 = agnosticEvents - - w.mu.Lock() - defer w.mu.Unlock() - watchEntry := w.watches[name] - if watchEntry != nil { - flags |= watchEntry.flags | unix.IN_MASK_ADD - } - wd, errno := unix.InotifyAddWatch(w.fd, name, flags) - if wd == -1 { - return errno - } - - if watchEntry == nil { - w.watches[name] = &watch{wd: uint32(wd), flags: flags} - w.paths[wd] = name - } else { - watchEntry.wd = uint32(wd) - watchEntry.flags = flags - } - - return nil -} - -// Remove stops watching the named file or directory (non-recursively). -func (w *Watcher) Remove(name string) error { - name = filepath.Clean(name) - - // Fetch the watch. - w.mu.Lock() - defer w.mu.Unlock() - watch, ok := w.watches[name] - - // Remove it from inotify. - if !ok { - return fmt.Errorf("can't remove non-existent inotify watch for: %s", name) - } - - // We successfully removed the watch if InotifyRmWatch doesn't return an - // error, we need to clean up our internal state to ensure it matches - // inotify's kernel state. - delete(w.paths, int(watch.wd)) - delete(w.watches, name) - - // inotify_rm_watch will return EINVAL if the file has been deleted; - // the inotify will already have been removed. - // watches and pathes are deleted in ignoreLinux() implicitly and asynchronously - // by calling inotify_rm_watch() below. e.g. readEvents() goroutine receives IN_IGNORE - // so that EINVAL means that the wd is being rm_watch()ed or its file removed - // by another thread and we have not received IN_IGNORE event. - success, errno := unix.InotifyRmWatch(w.fd, watch.wd) - if success == -1 { - // TODO: Perhaps it's not helpful to return an error here in every case. - // the only two possible errors are: - // EBADF, which happens when w.fd is not a valid file descriptor of any kind. - // EINVAL, which is when fd is not an inotify descriptor or wd is not a valid watch descriptor. - // Watch descriptors are invalidated when they are removed explicitly or implicitly; - // explicitly by inotify_rm_watch, implicitly when the file they are watching is deleted. - return errno - } - - return nil -} - -// WatchList returns the directories and files that are being monitered. -func (w *Watcher) WatchList() []string { - w.mu.Lock() - defer w.mu.Unlock() - - entries := make([]string, 0, len(w.watches)) - for pathname := range w.watches { - entries = append(entries, pathname) - } - - return entries -} - -type watch struct { - wd uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall) - flags uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags) -} - -// readEvents reads from the inotify file descriptor, converts the -// received events into Event objects and sends them via the Events channel -func (w *Watcher) readEvents() { - var ( - buf [unix.SizeofInotifyEvent * 4096]byte // Buffer for a maximum of 4096 raw events - n int // Number of bytes read with read() - errno error // Syscall errno - ok bool // For poller.wait - ) - - defer close(w.doneResp) - defer close(w.Errors) - defer close(w.Events) - defer unix.Close(w.fd) - defer w.poller.close() - - for { - // See if we have been closed. - if w.isClosed() { - return - } - - ok, errno = w.poller.wait() - if errno != nil { - select { - case w.Errors <- errno: - case <-w.done: - return - } - continue - } - - if !ok { - continue - } - - n, errno = unix.Read(w.fd, buf[:]) - // If a signal interrupted execution, see if we've been asked to close, and try again. - // http://man7.org/linux/man-pages/man7/signal.7.html : - // "Before Linux 3.8, reads from an inotify(7) file descriptor were not restartable" - if errno == unix.EINTR { - continue - } - - // unix.Read might have been woken up by Close. If so, we're done. - if w.isClosed() { - return - } - - if n < unix.SizeofInotifyEvent { - var err error - if n == 0 { - // If EOF is received. This should really never happen. - err = io.EOF - } else if n < 0 { - // If an error occurred while reading. - err = errno - } else { - // Read was too short. - err = errors.New("notify: short read in readEvents()") - } - select { - case w.Errors <- err: - case <-w.done: - return - } - continue - } - - var offset uint32 - // We don't know how many events we just read into the buffer - // While the offset points to at least one whole event... - for offset <= uint32(n-unix.SizeofInotifyEvent) { - // Point "raw" to the event in the buffer - raw := (*unix.InotifyEvent)(unsafe.Pointer(&buf[offset])) - - mask := uint32(raw.Mask) - nameLen := uint32(raw.Len) - - if mask&unix.IN_Q_OVERFLOW != 0 { - select { - case w.Errors <- ErrEventOverflow: - case <-w.done: - return - } - } - - // If the event happened to the watched directory or the watched file, the kernel - // doesn't append the filename to the event, but we would like to always fill the - // the "Name" field with a valid filename. We retrieve the path of the watch from - // the "paths" map. - w.mu.Lock() - name, ok := w.paths[int(raw.Wd)] - // IN_DELETE_SELF occurs when the file/directory being watched is removed. - // This is a sign to clean up the maps, otherwise we are no longer in sync - // with the inotify kernel state which has already deleted the watch - // automatically. - if ok && mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF { - delete(w.paths, int(raw.Wd)) - delete(w.watches, name) - } - w.mu.Unlock() - - if nameLen > 0 { - // Point "bytes" at the first byte of the filename - bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&buf[offset+unix.SizeofInotifyEvent]))[:nameLen:nameLen] - // The filename is padded with NULL bytes. TrimRight() gets rid of those. - name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000") - } - - event := newEvent(name, mask) - - // Send the events that are not ignored on the events channel - if !event.ignoreLinux(mask) { - select { - case w.Events <- event: - case <-w.done: - return - } - } - - // Move to the next event in the buffer - offset += unix.SizeofInotifyEvent + nameLen - } - } -} - -// Certain types of events can be "ignored" and not sent over the Events -// channel. Such as events marked ignore by the kernel, or MODIFY events -// against files that do not exist. -func (e *Event) ignoreLinux(mask uint32) bool { - // Ignore anything the inotify API says to ignore - if mask&unix.IN_IGNORED == unix.IN_IGNORED { - return true - } - - // If the event is not a DELETE or RENAME, the file must exist. - // Otherwise the event is ignored. - // *Note*: this was put in place because it was seen that a MODIFY - // event was sent after the DELETE. This ignores that MODIFY and - // assumes a DELETE will come or has come if the file doesn't exist. - if !(e.Op&Remove == Remove || e.Op&Rename == Rename) { - _, statErr := os.Lstat(e.Name) - return os.IsNotExist(statErr) - } - return false -} - -// newEvent returns an platform-independent Event based on an inotify mask. -func newEvent(name string, mask uint32) Event { - e := Event{Name: name} - if mask&unix.IN_CREATE == unix.IN_CREATE || mask&unix.IN_MOVED_TO == unix.IN_MOVED_TO { - e.Op |= Create - } - if mask&unix.IN_DELETE_SELF == unix.IN_DELETE_SELF || mask&unix.IN_DELETE == unix.IN_DELETE { - e.Op |= Remove - } - if mask&unix.IN_MODIFY == unix.IN_MODIFY { - e.Op |= Write - } - if mask&unix.IN_MOVE_SELF == unix.IN_MOVE_SELF || mask&unix.IN_MOVED_FROM == unix.IN_MOVED_FROM { - e.Op |= Rename - } - if mask&unix.IN_ATTRIB == unix.IN_ATTRIB { - e.Op |= Chmod - } - return e -} diff --git a/vendor/github.com/fsnotify/fsnotify/inotify_poller.go b/vendor/github.com/fsnotify/fsnotify/inotify_poller.go deleted file mode 100644 index b572a37c3f..0000000000 --- a/vendor/github.com/fsnotify/fsnotify/inotify_poller.go +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build linux -// +build linux - -package fsnotify - -import ( - "errors" - - "golang.org/x/sys/unix" -) - -type fdPoller struct { - fd int // File descriptor (as returned by the inotify_init() syscall) - epfd int // Epoll file descriptor - pipe [2]int // Pipe for waking up -} - -func emptyPoller(fd int) *fdPoller { - poller := new(fdPoller) - poller.fd = fd - poller.epfd = -1 - poller.pipe[0] = -1 - poller.pipe[1] = -1 - return poller -} - -// Create a new inotify poller. -// This creates an inotify handler, and an epoll handler. -func newFdPoller(fd int) (*fdPoller, error) { - var errno error - poller := emptyPoller(fd) - defer func() { - if errno != nil { - poller.close() - } - }() - - // Create epoll fd - poller.epfd, errno = unix.EpollCreate1(unix.EPOLL_CLOEXEC) - if poller.epfd == -1 { - return nil, errno - } - // Create pipe; pipe[0] is the read end, pipe[1] the write end. - errno = unix.Pipe2(poller.pipe[:], unix.O_NONBLOCK|unix.O_CLOEXEC) - if errno != nil { - return nil, errno - } - - // Register inotify fd with epoll - event := unix.EpollEvent{ - Fd: int32(poller.fd), - Events: unix.EPOLLIN, - } - errno = unix.EpollCtl(poller.epfd, unix.EPOLL_CTL_ADD, poller.fd, &event) - if errno != nil { - return nil, errno - } - - // Register pipe fd with epoll - event = unix.EpollEvent{ - Fd: int32(poller.pipe[0]), - Events: unix.EPOLLIN, - } - errno = unix.EpollCtl(poller.epfd, unix.EPOLL_CTL_ADD, poller.pipe[0], &event) - if errno != nil { - return nil, errno - } - - return poller, nil -} - -// Wait using epoll. -// Returns true if something is ready to be read, -// false if there is not. -func (poller *fdPoller) wait() (bool, error) { - // 3 possible events per fd, and 2 fds, makes a maximum of 6 events. - // I don't know whether epoll_wait returns the number of events returned, - // or the total number of events ready. - // I decided to catch both by making the buffer one larger than the maximum. - events := make([]unix.EpollEvent, 7) - for { - n, errno := unix.EpollWait(poller.epfd, events, -1) - if n == -1 { - if errno == unix.EINTR { - continue - } - return false, errno - } - if n == 0 { - // If there are no events, try again. - continue - } - if n > 6 { - // This should never happen. More events were returned than should be possible. - return false, errors.New("epoll_wait returned more events than I know what to do with") - } - ready := events[:n] - epollhup := false - epollerr := false - epollin := false - for _, event := range ready { - if event.Fd == int32(poller.fd) { - if event.Events&unix.EPOLLHUP != 0 { - // This should not happen, but if it does, treat it as a wakeup. - epollhup = true - } - if event.Events&unix.EPOLLERR != 0 { - // If an error is waiting on the file descriptor, we should pretend - // something is ready to read, and let unix.Read pick up the error. - epollerr = true - } - if event.Events&unix.EPOLLIN != 0 { - // There is data to read. - epollin = true - } - } - if event.Fd == int32(poller.pipe[0]) { - if event.Events&unix.EPOLLHUP != 0 { - // Write pipe descriptor was closed, by us. This means we're closing down the - // watcher, and we should wake up. - } - if event.Events&unix.EPOLLERR != 0 { - // If an error is waiting on the pipe file descriptor. - // This is an absolute mystery, and should never ever happen. - return false, errors.New("Error on the pipe descriptor.") - } - if event.Events&unix.EPOLLIN != 0 { - // This is a regular wakeup, so we have to clear the buffer. - err := poller.clearWake() - if err != nil { - return false, err - } - } - } - } - - if epollhup || epollerr || epollin { - return true, nil - } - return false, nil - } -} - -// Close the write end of the poller. -func (poller *fdPoller) wake() error { - buf := make([]byte, 1) - n, errno := unix.Write(poller.pipe[1], buf) - if n == -1 { - if errno == unix.EAGAIN { - // Buffer is full, poller will wake. - return nil - } - return errno - } - return nil -} - -func (poller *fdPoller) clearWake() error { - // You have to be woken up a LOT in order to get to 100! - buf := make([]byte, 100) - n, errno := unix.Read(poller.pipe[0], buf) - if n == -1 { - if errno == unix.EAGAIN { - // Buffer is empty, someone else cleared our wake. - return nil - } - return errno - } - return nil -} - -// Close all poller file descriptors, but not the one passed to it. -func (poller *fdPoller) close() { - if poller.pipe[1] != -1 { - unix.Close(poller.pipe[1]) - } - if poller.pipe[0] != -1 { - unix.Close(poller.pipe[0]) - } - if poller.epfd != -1 { - unix.Close(poller.epfd) - } -} diff --git a/vendor/github.com/fsnotify/fsnotify/kqueue.go b/vendor/github.com/fsnotify/fsnotify/kqueue.go deleted file mode 100644 index 6fb8d8532e..0000000000 --- a/vendor/github.com/fsnotify/fsnotify/kqueue.go +++ /dev/null @@ -1,535 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build freebsd || openbsd || netbsd || dragonfly || darwin -// +build freebsd openbsd netbsd dragonfly darwin - -package fsnotify - -import ( - "errors" - "fmt" - "io/ioutil" - "os" - "path/filepath" - "sync" - "time" - - "golang.org/x/sys/unix" -) - -// Watcher watches a set of files, delivering events to a channel. -type Watcher struct { - Events chan Event - Errors chan error - done chan struct{} // Channel for sending a "quit message" to the reader goroutine - - kq int // File descriptor (as returned by the kqueue() syscall). - - mu sync.Mutex // Protects access to watcher data - watches map[string]int // Map of watched file descriptors (key: path). - externalWatches map[string]bool // Map of watches added by user of the library. - dirFlags map[string]uint32 // Map of watched directories to fflags used in kqueue. - paths map[int]pathInfo // Map file descriptors to path names for processing kqueue events. - fileExists map[string]bool // Keep track of if we know this file exists (to stop duplicate create events). - isClosed bool // Set to true when Close() is first called -} - -type pathInfo struct { - name string - isDir bool -} - -// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events. -func NewWatcher() (*Watcher, error) { - kq, err := kqueue() - if err != nil { - return nil, err - } - - w := &Watcher{ - kq: kq, - watches: make(map[string]int), - dirFlags: make(map[string]uint32), - paths: make(map[int]pathInfo), - fileExists: make(map[string]bool), - externalWatches: make(map[string]bool), - Events: make(chan Event), - Errors: make(chan error), - done: make(chan struct{}), - } - - go w.readEvents() - return w, nil -} - -// Close removes all watches and closes the events channel. -func (w *Watcher) Close() error { - w.mu.Lock() - if w.isClosed { - w.mu.Unlock() - return nil - } - w.isClosed = true - - // copy paths to remove while locked - var pathsToRemove = make([]string, 0, len(w.watches)) - for name := range w.watches { - pathsToRemove = append(pathsToRemove, name) - } - w.mu.Unlock() - // unlock before calling Remove, which also locks - - for _, name := range pathsToRemove { - w.Remove(name) - } - - // send a "quit" message to the reader goroutine - close(w.done) - - return nil -} - -// Add starts watching the named file or directory (non-recursively). -func (w *Watcher) Add(name string) error { - w.mu.Lock() - w.externalWatches[name] = true - w.mu.Unlock() - _, err := w.addWatch(name, noteAllEvents) - return err -} - -// Remove stops watching the the named file or directory (non-recursively). -func (w *Watcher) Remove(name string) error { - name = filepath.Clean(name) - w.mu.Lock() - watchfd, ok := w.watches[name] - w.mu.Unlock() - if !ok { - return fmt.Errorf("can't remove non-existent kevent watch for: %s", name) - } - - const registerRemove = unix.EV_DELETE - if err := register(w.kq, []int{watchfd}, registerRemove, 0); err != nil { - return err - } - - unix.Close(watchfd) - - w.mu.Lock() - isDir := w.paths[watchfd].isDir - delete(w.watches, name) - delete(w.paths, watchfd) - delete(w.dirFlags, name) - w.mu.Unlock() - - // Find all watched paths that are in this directory that are not external. - if isDir { - var pathsToRemove []string - w.mu.Lock() - for _, path := range w.paths { - wdir, _ := filepath.Split(path.name) - if filepath.Clean(wdir) == name { - if !w.externalWatches[path.name] { - pathsToRemove = append(pathsToRemove, path.name) - } - } - } - w.mu.Unlock() - for _, name := range pathsToRemove { - // Since these are internal, not much sense in propagating error - // to the user, as that will just confuse them with an error about - // a path they did not explicitly watch themselves. - w.Remove(name) - } - } - - return nil -} - -// WatchList returns the directories and files that are being monitered. -func (w *Watcher) WatchList() []string { - w.mu.Lock() - defer w.mu.Unlock() - - entries := make([]string, 0, len(w.watches)) - for pathname := range w.watches { - entries = append(entries, pathname) - } - - return entries -} - -// Watch all events (except NOTE_EXTEND, NOTE_LINK, NOTE_REVOKE) -const noteAllEvents = unix.NOTE_DELETE | unix.NOTE_WRITE | unix.NOTE_ATTRIB | unix.NOTE_RENAME - -// keventWaitTime to block on each read from kevent -var keventWaitTime = durationToTimespec(100 * time.Millisecond) - -// addWatch adds name to the watched file set. -// The flags are interpreted as described in kevent(2). -// Returns the real path to the file which was added, if any, which may be different from the one passed in the case of symlinks. -func (w *Watcher) addWatch(name string, flags uint32) (string, error) { - var isDir bool - // Make ./name and name equivalent - name = filepath.Clean(name) - - w.mu.Lock() - if w.isClosed { - w.mu.Unlock() - return "", errors.New("kevent instance already closed") - } - watchfd, alreadyWatching := w.watches[name] - // We already have a watch, but we can still override flags. - if alreadyWatching { - isDir = w.paths[watchfd].isDir - } - w.mu.Unlock() - - if !alreadyWatching { - fi, err := os.Lstat(name) - if err != nil { - return "", err - } - - // Don't watch sockets. - if fi.Mode()&os.ModeSocket == os.ModeSocket { - return "", nil - } - - // Don't watch named pipes. - if fi.Mode()&os.ModeNamedPipe == os.ModeNamedPipe { - return "", nil - } - - // Follow Symlinks - // Unfortunately, Linux can add bogus symlinks to watch list without - // issue, and Windows can't do symlinks period (AFAIK). To maintain - // consistency, we will act like everything is fine. There will simply - // be no file events for broken symlinks. - // Hence the returns of nil on errors. - if fi.Mode()&os.ModeSymlink == os.ModeSymlink { - name, err = filepath.EvalSymlinks(name) - if err != nil { - return "", nil - } - - w.mu.Lock() - _, alreadyWatching = w.watches[name] - w.mu.Unlock() - - if alreadyWatching { - return name, nil - } - - fi, err = os.Lstat(name) - if err != nil { - return "", nil - } - } - - watchfd, err = unix.Open(name, openMode, 0700) - if watchfd == -1 { - return "", err - } - - isDir = fi.IsDir() - } - - const registerAdd = unix.EV_ADD | unix.EV_CLEAR | unix.EV_ENABLE - if err := register(w.kq, []int{watchfd}, registerAdd, flags); err != nil { - unix.Close(watchfd) - return "", err - } - - if !alreadyWatching { - w.mu.Lock() - w.watches[name] = watchfd - w.paths[watchfd] = pathInfo{name: name, isDir: isDir} - w.mu.Unlock() - } - - if isDir { - // Watch the directory if it has not been watched before, - // or if it was watched before, but perhaps only a NOTE_DELETE (watchDirectoryFiles) - w.mu.Lock() - - watchDir := (flags&unix.NOTE_WRITE) == unix.NOTE_WRITE && - (!alreadyWatching || (w.dirFlags[name]&unix.NOTE_WRITE) != unix.NOTE_WRITE) - // Store flags so this watch can be updated later - w.dirFlags[name] = flags - w.mu.Unlock() - - if watchDir { - if err := w.watchDirectoryFiles(name); err != nil { - return "", err - } - } - } - return name, nil -} - -// readEvents reads from kqueue and converts the received kevents into -// Event values that it sends down the Events channel. -func (w *Watcher) readEvents() { - eventBuffer := make([]unix.Kevent_t, 10) - -loop: - for { - // See if there is a message on the "done" channel - select { - case <-w.done: - break loop - default: - } - - // Get new events - kevents, err := read(w.kq, eventBuffer, &keventWaitTime) - // EINTR is okay, the syscall was interrupted before timeout expired. - if err != nil && err != unix.EINTR { - select { - case w.Errors <- err: - case <-w.done: - break loop - } - continue - } - - // Flush the events we received to the Events channel - for len(kevents) > 0 { - kevent := &kevents[0] - watchfd := int(kevent.Ident) - mask := uint32(kevent.Fflags) - w.mu.Lock() - path := w.paths[watchfd] - w.mu.Unlock() - event := newEvent(path.name, mask) - - if path.isDir && !(event.Op&Remove == Remove) { - // Double check to make sure the directory exists. This can happen when - // we do a rm -fr on a recursively watched folders and we receive a - // modification event first but the folder has been deleted and later - // receive the delete event - if _, err := os.Lstat(event.Name); os.IsNotExist(err) { - // mark is as delete event - event.Op |= Remove - } - } - - if event.Op&Rename == Rename || event.Op&Remove == Remove { - w.Remove(event.Name) - w.mu.Lock() - delete(w.fileExists, event.Name) - w.mu.Unlock() - } - - if path.isDir && event.Op&Write == Write && !(event.Op&Remove == Remove) { - w.sendDirectoryChangeEvents(event.Name) - } else { - // Send the event on the Events channel. - select { - case w.Events <- event: - case <-w.done: - break loop - } - } - - if event.Op&Remove == Remove { - // Look for a file that may have overwritten this. - // For example, mv f1 f2 will delete f2, then create f2. - if path.isDir { - fileDir := filepath.Clean(event.Name) - w.mu.Lock() - _, found := w.watches[fileDir] - w.mu.Unlock() - if found { - // make sure the directory exists before we watch for changes. When we - // do a recursive watch and perform rm -fr, the parent directory might - // have gone missing, ignore the missing directory and let the - // upcoming delete event remove the watch from the parent directory. - if _, err := os.Lstat(fileDir); err == nil { - w.sendDirectoryChangeEvents(fileDir) - } - } - } else { - filePath := filepath.Clean(event.Name) - if fileInfo, err := os.Lstat(filePath); err == nil { - w.sendFileCreatedEventIfNew(filePath, fileInfo) - } - } - } - - // Move to next event - kevents = kevents[1:] - } - } - - // cleanup - err := unix.Close(w.kq) - if err != nil { - // only way the previous loop breaks is if w.done was closed so we need to async send to w.Errors. - select { - case w.Errors <- err: - default: - } - } - close(w.Events) - close(w.Errors) -} - -// newEvent returns an platform-independent Event based on kqueue Fflags. -func newEvent(name string, mask uint32) Event { - e := Event{Name: name} - if mask&unix.NOTE_DELETE == unix.NOTE_DELETE { - e.Op |= Remove - } - if mask&unix.NOTE_WRITE == unix.NOTE_WRITE { - e.Op |= Write - } - if mask&unix.NOTE_RENAME == unix.NOTE_RENAME { - e.Op |= Rename - } - if mask&unix.NOTE_ATTRIB == unix.NOTE_ATTRIB { - e.Op |= Chmod - } - return e -} - -func newCreateEvent(name string) Event { - return Event{Name: name, Op: Create} -} - -// watchDirectoryFiles to mimic inotify when adding a watch on a directory -func (w *Watcher) watchDirectoryFiles(dirPath string) error { - // Get all files - files, err := ioutil.ReadDir(dirPath) - if err != nil { - return err - } - - for _, fileInfo := range files { - filePath := filepath.Join(dirPath, fileInfo.Name()) - filePath, err = w.internalWatch(filePath, fileInfo) - if err != nil { - return err - } - - w.mu.Lock() - w.fileExists[filePath] = true - w.mu.Unlock() - } - - return nil -} - -// sendDirectoryEvents searches the directory for newly created files -// and sends them over the event channel. This functionality is to have -// the BSD version of fsnotify match Linux inotify which provides a -// create event for files created in a watched directory. -func (w *Watcher) sendDirectoryChangeEvents(dirPath string) { - // Get all files - files, err := ioutil.ReadDir(dirPath) - if err != nil { - select { - case w.Errors <- err: - case <-w.done: - return - } - } - - // Search for new files - for _, fileInfo := range files { - filePath := filepath.Join(dirPath, fileInfo.Name()) - err := w.sendFileCreatedEventIfNew(filePath, fileInfo) - - if err != nil { - return - } - } -} - -// sendFileCreatedEvent sends a create event if the file isn't already being tracked. -func (w *Watcher) sendFileCreatedEventIfNew(filePath string, fileInfo os.FileInfo) (err error) { - w.mu.Lock() - _, doesExist := w.fileExists[filePath] - w.mu.Unlock() - if !doesExist { - // Send create event - select { - case w.Events <- newCreateEvent(filePath): - case <-w.done: - return - } - } - - // like watchDirectoryFiles (but without doing another ReadDir) - filePath, err = w.internalWatch(filePath, fileInfo) - if err != nil { - return err - } - - w.mu.Lock() - w.fileExists[filePath] = true - w.mu.Unlock() - - return nil -} - -func (w *Watcher) internalWatch(name string, fileInfo os.FileInfo) (string, error) { - if fileInfo.IsDir() { - // mimic Linux providing delete events for subdirectories - // but preserve the flags used if currently watching subdirectory - w.mu.Lock() - flags := w.dirFlags[name] - w.mu.Unlock() - - flags |= unix.NOTE_DELETE | unix.NOTE_RENAME - return w.addWatch(name, flags) - } - - // watch file to mimic Linux inotify - return w.addWatch(name, noteAllEvents) -} - -// kqueue creates a new kernel event queue and returns a descriptor. -func kqueue() (kq int, err error) { - kq, err = unix.Kqueue() - if kq == -1 { - return kq, err - } - return kq, nil -} - -// register events with the queue -func register(kq int, fds []int, flags int, fflags uint32) error { - changes := make([]unix.Kevent_t, len(fds)) - - for i, fd := range fds { - // SetKevent converts int to the platform-specific types: - unix.SetKevent(&changes[i], fd, unix.EVFILT_VNODE, flags) - changes[i].Fflags = fflags - } - - // register the events - success, err := unix.Kevent(kq, changes, nil, nil) - if success == -1 { - return err - } - return nil -} - -// read retrieves pending events, or waits until an event occurs. -// A timeout of nil blocks indefinitely, while 0 polls the queue. -func read(kq int, events []unix.Kevent_t, timeout *unix.Timespec) ([]unix.Kevent_t, error) { - n, err := unix.Kevent(kq, nil, events, timeout) - if err != nil { - return nil, err - } - return events[0:n], nil -} - -// durationToTimespec prepares a timeout value -func durationToTimespec(d time.Duration) unix.Timespec { - return unix.NsecToTimespec(d.Nanoseconds()) -} diff --git a/vendor/github.com/fsnotify/fsnotify/mkdoc.zsh b/vendor/github.com/fsnotify/fsnotify/mkdoc.zsh new file mode 100644 index 0000000000..b09ef76834 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/mkdoc.zsh @@ -0,0 +1,208 @@ +#!/usr/bin/env zsh +[ "${ZSH_VERSION:-}" = "" ] && echo >&2 "Only works with zsh" && exit 1 +setopt err_exit no_unset pipefail extended_glob + +# Simple script to update the godoc comments on all watchers. Probably took me +# more time to write this than doing it manually, but ah well 🙃 + +watcher=$(</tmp/x + print -r -- $cmt >>/tmp/x + tail -n+$(( end + 1 )) $file >>/tmp/x + mv /tmp/x $file + done +} + +set-cmt '^type Watcher struct ' $watcher +set-cmt '^func NewWatcher(' $new +set-cmt '^func (w \*Watcher) Add(' $add +set-cmt '^func (w \*Watcher) Remove(' $remove +set-cmt '^func (w \*Watcher) Close(' $close +set-cmt '^func (w \*Watcher) WatchList(' $watchlist +set-cmt '^[[:space:]]*Events *chan Event$' $events +set-cmt '^[[:space:]]*Errors *chan error$' $errors diff --git a/vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go b/vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go deleted file mode 100644 index 36cc3845b6..0000000000 --- a/vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build freebsd || openbsd || netbsd || dragonfly -// +build freebsd openbsd netbsd dragonfly - -package fsnotify - -import "golang.org/x/sys/unix" - -const openMode = unix.O_NONBLOCK | unix.O_RDONLY | unix.O_CLOEXEC diff --git a/vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go b/vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go deleted file mode 100644 index 98cd8476ff..0000000000 --- a/vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build darwin -// +build darwin - -package fsnotify - -import "golang.org/x/sys/unix" - -// note: this constant is not defined on BSD -const openMode = unix.O_EVTONLY | unix.O_CLOEXEC diff --git a/vendor/github.com/fsnotify/fsnotify/system_bsd.go b/vendor/github.com/fsnotify/fsnotify/system_bsd.go new file mode 100644 index 0000000000..4322b0b885 --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/system_bsd.go @@ -0,0 +1,8 @@ +//go:build freebsd || openbsd || netbsd || dragonfly +// +build freebsd openbsd netbsd dragonfly + +package fsnotify + +import "golang.org/x/sys/unix" + +const openMode = unix.O_NONBLOCK | unix.O_RDONLY | unix.O_CLOEXEC diff --git a/vendor/github.com/fsnotify/fsnotify/system_darwin.go b/vendor/github.com/fsnotify/fsnotify/system_darwin.go new file mode 100644 index 0000000000..5da5ffa78f --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/system_darwin.go @@ -0,0 +1,9 @@ +//go:build darwin +// +build darwin + +package fsnotify + +import "golang.org/x/sys/unix" + +// note: this constant is not defined on BSD +const openMode = unix.O_EVTONLY | unix.O_CLOEXEC diff --git a/vendor/github.com/fsnotify/fsnotify/windows.go b/vendor/github.com/fsnotify/fsnotify/windows.go deleted file mode 100644 index 02ce7deb0b..0000000000 --- a/vendor/github.com/fsnotify/fsnotify/windows.go +++ /dev/null @@ -1,586 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build windows -// +build windows - -package fsnotify - -import ( - "errors" - "fmt" - "os" - "path/filepath" - "reflect" - "runtime" - "sync" - "syscall" - "unsafe" -) - -// Watcher watches a set of files, delivering events to a channel. -type Watcher struct { - Events chan Event - Errors chan error - isClosed bool // Set to true when Close() is first called - mu sync.Mutex // Map access - port syscall.Handle // Handle to completion port - watches watchMap // Map of watches (key: i-number) - input chan *input // Inputs to the reader are sent on this channel - quit chan chan<- error -} - -// NewWatcher establishes a new watcher with the underlying OS and begins waiting for events. -func NewWatcher() (*Watcher, error) { - port, e := syscall.CreateIoCompletionPort(syscall.InvalidHandle, 0, 0, 0) - if e != nil { - return nil, os.NewSyscallError("CreateIoCompletionPort", e) - } - w := &Watcher{ - port: port, - watches: make(watchMap), - input: make(chan *input, 1), - Events: make(chan Event, 50), - Errors: make(chan error), - quit: make(chan chan<- error, 1), - } - go w.readEvents() - return w, nil -} - -// Close removes all watches and closes the events channel. -func (w *Watcher) Close() error { - if w.isClosed { - return nil - } - w.isClosed = true - - // Send "quit" message to the reader goroutine - ch := make(chan error) - w.quit <- ch - if err := w.wakeupReader(); err != nil { - return err - } - return <-ch -} - -// Add starts watching the named file or directory (non-recursively). -func (w *Watcher) Add(name string) error { - if w.isClosed { - return errors.New("watcher already closed") - } - in := &input{ - op: opAddWatch, - path: filepath.Clean(name), - flags: sysFSALLEVENTS, - reply: make(chan error), - } - w.input <- in - if err := w.wakeupReader(); err != nil { - return err - } - return <-in.reply -} - -// Remove stops watching the the named file or directory (non-recursively). -func (w *Watcher) Remove(name string) error { - in := &input{ - op: opRemoveWatch, - path: filepath.Clean(name), - reply: make(chan error), - } - w.input <- in - if err := w.wakeupReader(); err != nil { - return err - } - return <-in.reply -} - -// WatchList returns the directories and files that are being monitered. -func (w *Watcher) WatchList() []string { - w.mu.Lock() - defer w.mu.Unlock() - - entries := make([]string, 0, len(w.watches)) - for _, entry := range w.watches { - for _, watchEntry := range entry { - entries = append(entries, watchEntry.path) - } - } - - return entries -} - -const ( - // Options for AddWatch - sysFSONESHOT = 0x80000000 - sysFSONLYDIR = 0x1000000 - - // Events - sysFSACCESS = 0x1 - sysFSALLEVENTS = 0xfff - sysFSATTRIB = 0x4 - sysFSCLOSE = 0x18 - sysFSCREATE = 0x100 - sysFSDELETE = 0x200 - sysFSDELETESELF = 0x400 - sysFSMODIFY = 0x2 - sysFSMOVE = 0xc0 - sysFSMOVEDFROM = 0x40 - sysFSMOVEDTO = 0x80 - sysFSMOVESELF = 0x800 - - // Special events - sysFSIGNORED = 0x8000 - sysFSQOVERFLOW = 0x4000 -) - -func newEvent(name string, mask uint32) Event { - e := Event{Name: name} - if mask&sysFSCREATE == sysFSCREATE || mask&sysFSMOVEDTO == sysFSMOVEDTO { - e.Op |= Create - } - if mask&sysFSDELETE == sysFSDELETE || mask&sysFSDELETESELF == sysFSDELETESELF { - e.Op |= Remove - } - if mask&sysFSMODIFY == sysFSMODIFY { - e.Op |= Write - } - if mask&sysFSMOVE == sysFSMOVE || mask&sysFSMOVESELF == sysFSMOVESELF || mask&sysFSMOVEDFROM == sysFSMOVEDFROM { - e.Op |= Rename - } - if mask&sysFSATTRIB == sysFSATTRIB { - e.Op |= Chmod - } - return e -} - -const ( - opAddWatch = iota - opRemoveWatch -) - -const ( - provisional uint64 = 1 << (32 + iota) -) - -type input struct { - op int - path string - flags uint32 - reply chan error -} - -type inode struct { - handle syscall.Handle - volume uint32 - index uint64 -} - -type watch struct { - ov syscall.Overlapped - ino *inode // i-number - path string // Directory path - mask uint64 // Directory itself is being watched with these notify flags - names map[string]uint64 // Map of names being watched and their notify flags - rename string // Remembers the old name while renaming a file - buf [4096]byte -} - -type indexMap map[uint64]*watch -type watchMap map[uint32]indexMap - -func (w *Watcher) wakeupReader() error { - e := syscall.PostQueuedCompletionStatus(w.port, 0, 0, nil) - if e != nil { - return os.NewSyscallError("PostQueuedCompletionStatus", e) - } - return nil -} - -func getDir(pathname string) (dir string, err error) { - attr, e := syscall.GetFileAttributes(syscall.StringToUTF16Ptr(pathname)) - if e != nil { - return "", os.NewSyscallError("GetFileAttributes", e) - } - if attr&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 { - dir = pathname - } else { - dir, _ = filepath.Split(pathname) - dir = filepath.Clean(dir) - } - return -} - -func getIno(path string) (ino *inode, err error) { - h, e := syscall.CreateFile(syscall.StringToUTF16Ptr(path), - syscall.FILE_LIST_DIRECTORY, - syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE, - nil, syscall.OPEN_EXISTING, - syscall.FILE_FLAG_BACKUP_SEMANTICS|syscall.FILE_FLAG_OVERLAPPED, 0) - if e != nil { - return nil, os.NewSyscallError("CreateFile", e) - } - var fi syscall.ByHandleFileInformation - if e = syscall.GetFileInformationByHandle(h, &fi); e != nil { - syscall.CloseHandle(h) - return nil, os.NewSyscallError("GetFileInformationByHandle", e) - } - ino = &inode{ - handle: h, - volume: fi.VolumeSerialNumber, - index: uint64(fi.FileIndexHigh)<<32 | uint64(fi.FileIndexLow), - } - return ino, nil -} - -// Must run within the I/O thread. -func (m watchMap) get(ino *inode) *watch { - if i := m[ino.volume]; i != nil { - return i[ino.index] - } - return nil -} - -// Must run within the I/O thread. -func (m watchMap) set(ino *inode, watch *watch) { - i := m[ino.volume] - if i == nil { - i = make(indexMap) - m[ino.volume] = i - } - i[ino.index] = watch -} - -// Must run within the I/O thread. -func (w *Watcher) addWatch(pathname string, flags uint64) error { - dir, err := getDir(pathname) - if err != nil { - return err - } - if flags&sysFSONLYDIR != 0 && pathname != dir { - return nil - } - ino, err := getIno(dir) - if err != nil { - return err - } - w.mu.Lock() - watchEntry := w.watches.get(ino) - w.mu.Unlock() - if watchEntry == nil { - if _, e := syscall.CreateIoCompletionPort(ino.handle, w.port, 0, 0); e != nil { - syscall.CloseHandle(ino.handle) - return os.NewSyscallError("CreateIoCompletionPort", e) - } - watchEntry = &watch{ - ino: ino, - path: dir, - names: make(map[string]uint64), - } - w.mu.Lock() - w.watches.set(ino, watchEntry) - w.mu.Unlock() - flags |= provisional - } else { - syscall.CloseHandle(ino.handle) - } - if pathname == dir { - watchEntry.mask |= flags - } else { - watchEntry.names[filepath.Base(pathname)] |= flags - } - if err = w.startRead(watchEntry); err != nil { - return err - } - if pathname == dir { - watchEntry.mask &= ^provisional - } else { - watchEntry.names[filepath.Base(pathname)] &= ^provisional - } - return nil -} - -// Must run within the I/O thread. -func (w *Watcher) remWatch(pathname string) error { - dir, err := getDir(pathname) - if err != nil { - return err - } - ino, err := getIno(dir) - if err != nil { - return err - } - w.mu.Lock() - watch := w.watches.get(ino) - w.mu.Unlock() - if watch == nil { - return fmt.Errorf("can't remove non-existent watch for: %s", pathname) - } - if pathname == dir { - w.sendEvent(watch.path, watch.mask&sysFSIGNORED) - watch.mask = 0 - } else { - name := filepath.Base(pathname) - w.sendEvent(filepath.Join(watch.path, name), watch.names[name]&sysFSIGNORED) - delete(watch.names, name) - } - return w.startRead(watch) -} - -// Must run within the I/O thread. -func (w *Watcher) deleteWatch(watch *watch) { - for name, mask := range watch.names { - if mask&provisional == 0 { - w.sendEvent(filepath.Join(watch.path, name), mask&sysFSIGNORED) - } - delete(watch.names, name) - } - if watch.mask != 0 { - if watch.mask&provisional == 0 { - w.sendEvent(watch.path, watch.mask&sysFSIGNORED) - } - watch.mask = 0 - } -} - -// Must run within the I/O thread. -func (w *Watcher) startRead(watch *watch) error { - if e := syscall.CancelIo(watch.ino.handle); e != nil { - w.Errors <- os.NewSyscallError("CancelIo", e) - w.deleteWatch(watch) - } - mask := toWindowsFlags(watch.mask) - for _, m := range watch.names { - mask |= toWindowsFlags(m) - } - if mask == 0 { - if e := syscall.CloseHandle(watch.ino.handle); e != nil { - w.Errors <- os.NewSyscallError("CloseHandle", e) - } - w.mu.Lock() - delete(w.watches[watch.ino.volume], watch.ino.index) - w.mu.Unlock() - return nil - } - e := syscall.ReadDirectoryChanges(watch.ino.handle, &watch.buf[0], - uint32(unsafe.Sizeof(watch.buf)), false, mask, nil, &watch.ov, 0) - if e != nil { - err := os.NewSyscallError("ReadDirectoryChanges", e) - if e == syscall.ERROR_ACCESS_DENIED && watch.mask&provisional == 0 { - // Watched directory was probably removed - if w.sendEvent(watch.path, watch.mask&sysFSDELETESELF) { - if watch.mask&sysFSONESHOT != 0 { - watch.mask = 0 - } - } - err = nil - } - w.deleteWatch(watch) - w.startRead(watch) - return err - } - return nil -} - -// readEvents reads from the I/O completion port, converts the -// received events into Event objects and sends them via the Events channel. -// Entry point to the I/O thread. -func (w *Watcher) readEvents() { - var ( - n, key uint32 - ov *syscall.Overlapped - ) - runtime.LockOSThread() - - for { - e := syscall.GetQueuedCompletionStatus(w.port, &n, &key, &ov, syscall.INFINITE) - watch := (*watch)(unsafe.Pointer(ov)) - - if watch == nil { - select { - case ch := <-w.quit: - w.mu.Lock() - var indexes []indexMap - for _, index := range w.watches { - indexes = append(indexes, index) - } - w.mu.Unlock() - for _, index := range indexes { - for _, watch := range index { - w.deleteWatch(watch) - w.startRead(watch) - } - } - var err error - if e := syscall.CloseHandle(w.port); e != nil { - err = os.NewSyscallError("CloseHandle", e) - } - close(w.Events) - close(w.Errors) - ch <- err - return - case in := <-w.input: - switch in.op { - case opAddWatch: - in.reply <- w.addWatch(in.path, uint64(in.flags)) - case opRemoveWatch: - in.reply <- w.remWatch(in.path) - } - default: - } - continue - } - - switch e { - case syscall.ERROR_MORE_DATA: - if watch == nil { - w.Errors <- errors.New("ERROR_MORE_DATA has unexpectedly null lpOverlapped buffer") - } else { - // The i/o succeeded but the buffer is full. - // In theory we should be building up a full packet. - // In practice we can get away with just carrying on. - n = uint32(unsafe.Sizeof(watch.buf)) - } - case syscall.ERROR_ACCESS_DENIED: - // Watched directory was probably removed - w.sendEvent(watch.path, watch.mask&sysFSDELETESELF) - w.deleteWatch(watch) - w.startRead(watch) - continue - case syscall.ERROR_OPERATION_ABORTED: - // CancelIo was called on this handle - continue - default: - w.Errors <- os.NewSyscallError("GetQueuedCompletionPort", e) - continue - case nil: - } - - var offset uint32 - for { - if n == 0 { - w.Events <- newEvent("", sysFSQOVERFLOW) - w.Errors <- errors.New("short read in readEvents()") - break - } - - // Point "raw" to the event in the buffer - raw := (*syscall.FileNotifyInformation)(unsafe.Pointer(&watch.buf[offset])) - // TODO: Consider using unsafe.Slice that is available from go1.17 - // https://stackoverflow.com/questions/51187973/how-to-create-an-array-or-a-slice-from-an-array-unsafe-pointer-in-golang - // instead of using a fixed syscall.MAX_PATH buf, we create a buf that is the size of the path name - size := int(raw.FileNameLength / 2) - var buf []uint16 - sh := (*reflect.SliceHeader)(unsafe.Pointer(&buf)) - sh.Data = uintptr(unsafe.Pointer(&raw.FileName)) - sh.Len = size - sh.Cap = size - name := syscall.UTF16ToString(buf) - fullname := filepath.Join(watch.path, name) - - var mask uint64 - switch raw.Action { - case syscall.FILE_ACTION_REMOVED: - mask = sysFSDELETESELF - case syscall.FILE_ACTION_MODIFIED: - mask = sysFSMODIFY - case syscall.FILE_ACTION_RENAMED_OLD_NAME: - watch.rename = name - case syscall.FILE_ACTION_RENAMED_NEW_NAME: - if watch.names[watch.rename] != 0 { - watch.names[name] |= watch.names[watch.rename] - delete(watch.names, watch.rename) - mask = sysFSMOVESELF - } - } - - sendNameEvent := func() { - if w.sendEvent(fullname, watch.names[name]&mask) { - if watch.names[name]&sysFSONESHOT != 0 { - delete(watch.names, name) - } - } - } - if raw.Action != syscall.FILE_ACTION_RENAMED_NEW_NAME { - sendNameEvent() - } - if raw.Action == syscall.FILE_ACTION_REMOVED { - w.sendEvent(fullname, watch.names[name]&sysFSIGNORED) - delete(watch.names, name) - } - if w.sendEvent(fullname, watch.mask&toFSnotifyFlags(raw.Action)) { - if watch.mask&sysFSONESHOT != 0 { - watch.mask = 0 - } - } - if raw.Action == syscall.FILE_ACTION_RENAMED_NEW_NAME { - fullname = filepath.Join(watch.path, watch.rename) - sendNameEvent() - } - - // Move to the next event in the buffer - if raw.NextEntryOffset == 0 { - break - } - offset += raw.NextEntryOffset - - // Error! - if offset >= n { - w.Errors <- errors.New("Windows system assumed buffer larger than it is, events have likely been missed.") - break - } - } - - if err := w.startRead(watch); err != nil { - w.Errors <- err - } - } -} - -func (w *Watcher) sendEvent(name string, mask uint64) bool { - if mask == 0 { - return false - } - event := newEvent(name, uint32(mask)) - select { - case ch := <-w.quit: - w.quit <- ch - case w.Events <- event: - } - return true -} - -func toWindowsFlags(mask uint64) uint32 { - var m uint32 - if mask&sysFSACCESS != 0 { - m |= syscall.FILE_NOTIFY_CHANGE_LAST_ACCESS - } - if mask&sysFSMODIFY != 0 { - m |= syscall.FILE_NOTIFY_CHANGE_LAST_WRITE - } - if mask&sysFSATTRIB != 0 { - m |= syscall.FILE_NOTIFY_CHANGE_ATTRIBUTES - } - if mask&(sysFSMOVE|sysFSCREATE|sysFSDELETE) != 0 { - m |= syscall.FILE_NOTIFY_CHANGE_FILE_NAME | syscall.FILE_NOTIFY_CHANGE_DIR_NAME - } - return m -} - -func toFSnotifyFlags(action uint32) uint64 { - switch action { - case syscall.FILE_ACTION_ADDED: - return sysFSCREATE - case syscall.FILE_ACTION_REMOVED: - return sysFSDELETE - case syscall.FILE_ACTION_MODIFIED: - return sysFSMODIFY - case syscall.FILE_ACTION_RENAMED_OLD_NAME: - return sysFSMOVEDFROM - case syscall.FILE_ACTION_RENAMED_NEW_NAME: - return sysFSMOVEDTO - } - return 0 -} diff --git a/vendor/github.com/fvbommel/sortorder/.gitignore b/vendor/github.com/fvbommel/sortorder/.gitignore new file mode 100644 index 0000000000..c021733e25 --- /dev/null +++ b/vendor/github.com/fvbommel/sortorder/.gitignore @@ -0,0 +1,19 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so +# Folders +_obj +_test +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* +_testmain.go +*.exe +*.test +*.prof diff --git a/vendor/github.com/fvbommel/sortorder/LICENSE b/vendor/github.com/fvbommel/sortorder/LICENSE new file mode 100644 index 0000000000..5c695fb590 --- /dev/null +++ b/vendor/github.com/fvbommel/sortorder/LICENSE @@ -0,0 +1,17 @@ +The MIT License (MIT) +Copyright (c) 2015 Frits van Bommel +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/fvbommel/sortorder/README.md b/vendor/github.com/fvbommel/sortorder/README.md new file mode 100644 index 0000000000..7ebcab1d16 --- /dev/null +++ b/vendor/github.com/fvbommel/sortorder/README.md @@ -0,0 +1,5 @@ +# sortorder [![PkgGoDev](https://pkg.go.dev/badge/github.com/fvbommel/sortorder)](https://pkg.go.dev/github.com/fvbommel/sortorder) + + import "github.com/fvbommel/sortorder" + +Sort orders and comparison functions. diff --git a/vendor/github.com/fvbommel/sortorder/doc.go b/vendor/github.com/fvbommel/sortorder/doc.go new file mode 100644 index 0000000000..75d5a2928f --- /dev/null +++ b/vendor/github.com/fvbommel/sortorder/doc.go @@ -0,0 +1,5 @@ +// Package sortorder implements sort orders and comparison functions. +// +// Currently, it only implements so-called "natural order", where integers +// embedded in strings are compared by value. +package sortorder diff --git a/vendor/github.com/fvbommel/sortorder/natsort.go b/vendor/github.com/fvbommel/sortorder/natsort.go new file mode 100644 index 0000000000..66a52c7125 --- /dev/null +++ b/vendor/github.com/fvbommel/sortorder/natsort.go @@ -0,0 +1,76 @@ +package sortorder + +// Natural implements sort.Interface to sort strings in natural order. This +// means that e.g. "abc2" < "abc12". +// +// Non-digit sequences and numbers are compared separately. The former are +// compared bytewise, while the latter are compared numerically (except that +// the number of leading zeros is used as a tie-breaker, so e.g. "2" < "02") +// +// Limitation: only ASCII digits (0-9) are considered. +type Natural []string + +func (n Natural) Len() int { return len(n) } +func (n Natural) Swap(i, j int) { n[i], n[j] = n[j], n[i] } +func (n Natural) Less(i, j int) bool { return NaturalLess(n[i], n[j]) } + +func isdigit(b byte) bool { return '0' <= b && b <= '9' } + +// NaturalLess compares two strings using natural ordering. This means that e.g. +// "abc2" < "abc12". +// +// Non-digit sequences and numbers are compared separately. The former are +// compared bytewise, while the latter are compared numerically (except that +// the number of leading zeros is used as a tie-breaker, so e.g. "2" < "02") +// +// Limitation: only ASCII digits (0-9) are considered. +func NaturalLess(str1, str2 string) bool { + idx1, idx2 := 0, 0 + for idx1 < len(str1) && idx2 < len(str2) { + c1, c2 := str1[idx1], str2[idx2] + dig1, dig2 := isdigit(c1), isdigit(c2) + switch { + case dig1 != dig2: // Digits before other characters. + return dig1 // True if LHS is a digit, false if the RHS is one. + case !dig1: // && !dig2, because dig1 == dig2 + // UTF-8 compares bytewise-lexicographically, no need to decode + // codepoints. + if c1 != c2 { + return c1 < c2 + } + idx1++ + idx2++ + default: // Digits + // Eat zeros. + for ; idx1 < len(str1) && str1[idx1] == '0'; idx1++ { + } + for ; idx2 < len(str2) && str2[idx2] == '0'; idx2++ { + } + // Eat all digits. + nonZero1, nonZero2 := idx1, idx2 + for ; idx1 < len(str1) && isdigit(str1[idx1]); idx1++ { + } + for ; idx2 < len(str2) && isdigit(str2[idx2]); idx2++ { + } + // If lengths of numbers with non-zero prefix differ, the shorter + // one is less. + if len1, len2 := idx1-nonZero1, idx2-nonZero2; len1 != len2 { + return len1 < len2 + } + // If they're equal, string comparison is correct. + if nr1, nr2 := str1[nonZero1:idx1], str2[nonZero2:idx2]; nr1 != nr2 { + return nr1 < nr2 + } + // Otherwise, the one with less zeros is less. + // Because everything up to the number is equal, comparing the index + // after the zeros is sufficient. + if nonZero1 != nonZero2 { + return nonZero1 < nonZero2 + } + } + // They're identical so far, so continue comparing. + } + // So far they are identical. At least one is ended. If the other continues, + // it sorts last. + return len(str1) < len(str2) +} diff --git a/vendor/github.com/go-errors/errors/.travis.yml b/vendor/github.com/go-errors/errors/.travis.yml index 9d00fdd5d6..77a6bccf77 100644 --- a/vendor/github.com/go-errors/errors/.travis.yml +++ b/vendor/github.com/go-errors/errors/.travis.yml @@ -3,3 +3,6 @@ language: go go: - "1.8.x" - "1.10.x" + - "1.13.x" + - "1.14.x" + - "1.16.x" diff --git a/vendor/github.com/go-errors/errors/README.md b/vendor/github.com/go-errors/errors/README.md index 5d4f1873dd..3d78525940 100644 --- a/vendor/github.com/go-errors/errors/README.md +++ b/vendor/github.com/go-errors/errors/README.md @@ -64,3 +64,19 @@ packages by Facebook and Dropbox, it was moved to one canonical location so everyone can benefit. This package is licensed under the MIT license, see LICENSE.MIT for details. + + +## Changelog +* v1.1.0 updated to use go1.13's standard-library errors.Is method instead of == in errors.Is +* v1.2.0 added `errors.As` from the standard library. +* v1.3.0 *BREAKING* updated error methods to return `error` instead of `*Error`. +> Code that needs access to the underlying `*Error` can use the new errors.AsError(e) +> ``` +> // before +> errors.New(err).ErrorStack() +> // after +>. errors.AsError(errors.Wrap(err)).ErrorStack() +> ``` +* v1.4.0 *BREAKING* v1.4.0 reverted all changes from v1.3.0 and is identical to v1.2.0 +* v1.4.1 no code change, but now without an unnecessary cover.out file. +* v1.4.2 performance improvement to ErrorStack() to avoid unnecessary work https://github.com/go-errors/errors/pull/40 diff --git a/vendor/github.com/go-errors/errors/cover.out b/vendor/github.com/go-errors/errors/cover.out deleted file mode 100644 index ab18b0519f..0000000000 --- a/vendor/github.com/go-errors/errors/cover.out +++ /dev/null @@ -1,89 +0,0 @@ -mode: set -github.com/go-errors/errors/stackframe.go:27.51,30.25 2 1 -github.com/go-errors/errors/stackframe.go:33.2,38.8 3 1 -github.com/go-errors/errors/stackframe.go:30.25,32.3 1 0 -github.com/go-errors/errors/stackframe.go:43.47,44.31 1 1 -github.com/go-errors/errors/stackframe.go:47.2,47.48 1 1 -github.com/go-errors/errors/stackframe.go:44.31,46.3 1 1 -github.com/go-errors/errors/stackframe.go:52.42,56.16 3 1 -github.com/go-errors/errors/stackframe.go:60.2,60.60 1 1 -github.com/go-errors/errors/stackframe.go:56.16,58.3 1 0 -github.com/go-errors/errors/stackframe.go:64.55,67.16 2 1 -github.com/go-errors/errors/stackframe.go:71.2,72.61 2 1 -github.com/go-errors/errors/stackframe.go:76.2,76.66 1 1 -github.com/go-errors/errors/stackframe.go:67.16,69.3 1 0 -github.com/go-errors/errors/stackframe.go:72.61,74.3 1 0 -github.com/go-errors/errors/stackframe.go:79.56,91.63 3 1 -github.com/go-errors/errors/stackframe.go:95.2,95.53 1 1 -github.com/go-errors/errors/stackframe.go:100.2,101.18 2 1 -github.com/go-errors/errors/stackframe.go:91.63,94.3 2 1 -github.com/go-errors/errors/stackframe.go:95.53,98.3 2 1 -github.com/go-errors/errors/error.go:70.32,73.23 2 1 -github.com/go-errors/errors/error.go:80.2,85.3 3 1 -github.com/go-errors/errors/error.go:74.2,75.10 1 1 -github.com/go-errors/errors/error.go:76.2,77.28 1 1 -github.com/go-errors/errors/error.go:92.43,95.23 2 1 -github.com/go-errors/errors/error.go:104.2,109.3 3 1 -github.com/go-errors/errors/error.go:96.2,97.11 1 1 -github.com/go-errors/errors/error.go:98.2,99.10 1 1 -github.com/go-errors/errors/error.go:100.2,101.28 1 1 -github.com/go-errors/errors/error.go:115.39,117.19 1 1 -github.com/go-errors/errors/error.go:121.2,121.29 1 1 -github.com/go-errors/errors/error.go:125.2,125.43 1 1 -github.com/go-errors/errors/error.go:129.2,129.14 1 1 -github.com/go-errors/errors/error.go:117.19,119.3 1 1 -github.com/go-errors/errors/error.go:121.29,123.3 1 1 -github.com/go-errors/errors/error.go:125.43,127.3 1 1 -github.com/go-errors/errors/error.go:135.53,137.2 1 1 -github.com/go-errors/errors/error.go:140.34,142.2 1 1 -github.com/go-errors/errors/error.go:146.34,149.42 2 1 -github.com/go-errors/errors/error.go:153.2,153.20 1 1 -github.com/go-errors/errors/error.go:149.42,151.3 1 1 -github.com/go-errors/errors/error.go:158.39,160.2 1 1 -github.com/go-errors/errors/error.go:164.46,165.23 1 1 -github.com/go-errors/errors/error.go:173.2,173.19 1 1 -github.com/go-errors/errors/error.go:165.23,168.32 2 1 -github.com/go-errors/errors/error.go:168.32,170.4 1 1 -github.com/go-errors/errors/error.go:177.37,178.42 1 1 -github.com/go-errors/errors/error.go:181.2,181.41 1 1 -github.com/go-errors/errors/error.go:178.42,180.3 1 1 -github.com/go-errors/errors/parse_panic.go:10.39,12.2 1 1 -github.com/go-errors/errors/parse_panic.go:16.46,24.34 5 1 -github.com/go-errors/errors/parse_panic.go:70.2,70.43 1 1 -github.com/go-errors/errors/parse_panic.go:73.2,73.55 1 0 -github.com/go-errors/errors/parse_panic.go:24.34,27.23 2 1 -github.com/go-errors/errors/parse_panic.go:27.23,28.42 1 1 -github.com/go-errors/errors/parse_panic.go:28.42,31.5 2 1 -github.com/go-errors/errors/parse_panic.go:31.6,33.5 1 0 -github.com/go-errors/errors/parse_panic.go:35.5,35.29 1 1 -github.com/go-errors/errors/parse_panic.go:35.29,36.86 1 1 -github.com/go-errors/errors/parse_panic.go:36.86,38.5 1 1 -github.com/go-errors/errors/parse_panic.go:40.5,40.32 1 1 -github.com/go-errors/errors/parse_panic.go:40.32,41.18 1 1 -github.com/go-errors/errors/parse_panic.go:45.4,46.46 2 1 -github.com/go-errors/errors/parse_panic.go:51.4,53.23 2 1 -github.com/go-errors/errors/parse_panic.go:57.4,58.18 2 1 -github.com/go-errors/errors/parse_panic.go:62.4,63.17 2 1 -github.com/go-errors/errors/parse_panic.go:41.18,43.10 2 1 -github.com/go-errors/errors/parse_panic.go:46.46,49.5 2 1 -github.com/go-errors/errors/parse_panic.go:53.23,55.5 1 0 -github.com/go-errors/errors/parse_panic.go:58.18,60.5 1 0 -github.com/go-errors/errors/parse_panic.go:63.17,65.10 2 1 -github.com/go-errors/errors/parse_panic.go:70.43,72.3 1 1 -github.com/go-errors/errors/parse_panic.go:80.85,82.29 2 1 -github.com/go-errors/errors/parse_panic.go:85.2,85.15 1 1 -github.com/go-errors/errors/parse_panic.go:88.2,90.63 2 1 -github.com/go-errors/errors/parse_panic.go:94.2,94.53 1 1 -github.com/go-errors/errors/parse_panic.go:99.2,101.36 2 1 -github.com/go-errors/errors/parse_panic.go:105.2,106.15 2 1 -github.com/go-errors/errors/parse_panic.go:109.2,112.49 3 1 -github.com/go-errors/errors/parse_panic.go:116.2,117.16 2 1 -github.com/go-errors/errors/parse_panic.go:121.2,126.8 1 1 -github.com/go-errors/errors/parse_panic.go:82.29,84.3 1 0 -github.com/go-errors/errors/parse_panic.go:85.15,87.3 1 1 -github.com/go-errors/errors/parse_panic.go:90.63,93.3 2 1 -github.com/go-errors/errors/parse_panic.go:94.53,97.3 2 1 -github.com/go-errors/errors/parse_panic.go:101.36,103.3 1 0 -github.com/go-errors/errors/parse_panic.go:106.15,108.3 1 0 -github.com/go-errors/errors/parse_panic.go:112.49,114.3 1 1 -github.com/go-errors/errors/parse_panic.go:117.16,119.3 1 0 diff --git a/vendor/github.com/go-errors/errors/error.go b/vendor/github.com/go-errors/errors/error.go index 60062a4372..ccbc2e4272 100644 --- a/vendor/github.com/go-errors/errors/error.go +++ b/vendor/github.com/go-errors/errors/error.go @@ -91,6 +91,10 @@ func New(e interface{}) *Error { // fmt.Errorf("%v"). The skip parameter indicates how far up the stack // to start the stacktrace. 0 is from the current call, 1 from its caller, etc. func Wrap(e interface{}, skip int) *Error { + if e == nil { + return nil + } + var err error switch e := e.(type) { @@ -117,6 +121,9 @@ func Wrap(e interface{}, skip int) *Error { // up the stack to start the stacktrace. 0 is from the current call, // 1 from its caller, etc. func WrapPrefix(e interface{}, prefix string, skip int) *Error { + if e == nil { + return nil + } err := Wrap(e, 1+skip) @@ -132,26 +139,6 @@ func WrapPrefix(e interface{}, prefix string, skip int) *Error { } -// Is detects whether the error is equal to a given error. Errors -// are considered equal by this function if they are the same object, -// or if they both contain the same error inside an errors.Error. -func Is(e error, original error) bool { - - if e == original { - return true - } - - if e, ok := e.(*Error); ok { - return Is(e.Err, original) - } - - if original, ok := original.(*Error); ok { - return Is(e, original.Err) - } - - return false -} - // Errorf creates a new error with the given message. You can use it // as a drop-in replacement for fmt.Errorf() to provide descriptive // errors in return values. @@ -215,3 +202,8 @@ func (err *Error) TypeName() string { } return reflect.TypeOf(err.Err).String() } + +// Return the wrapped error (implements api for As function). +func (err *Error) Unwrap() error { + return err.Err +} diff --git a/vendor/github.com/go-errors/errors/error_1_13.go b/vendor/github.com/go-errors/errors/error_1_13.go new file mode 100644 index 0000000000..0af2fc8065 --- /dev/null +++ b/vendor/github.com/go-errors/errors/error_1_13.go @@ -0,0 +1,31 @@ +// +build go1.13 + +package errors + +import ( + baseErrors "errors" +) + +// find error in any wrapped error +func As(err error, target interface{}) bool { + return baseErrors.As(err, target) +} + +// Is detects whether the error is equal to a given error. Errors +// are considered equal by this function if they are matched by errors.Is +// or if their contained errors are matched through errors.Is +func Is(e error, original error) bool { + if baseErrors.Is(e, original) { + return true + } + + if e, ok := e.(*Error); ok { + return Is(e.Err, original) + } + + if original, ok := original.(*Error); ok { + return Is(e, original.Err) + } + + return false +} diff --git a/vendor/github.com/go-errors/errors/error_backward.go b/vendor/github.com/go-errors/errors/error_backward.go new file mode 100644 index 0000000000..80b0695e7e --- /dev/null +++ b/vendor/github.com/go-errors/errors/error_backward.go @@ -0,0 +1,57 @@ +// +build !go1.13 + +package errors + +import ( + "reflect" +) + +type unwrapper interface { + Unwrap() error +} + +// As assigns error or any wrapped error to the value target points +// to. If there is no value of the target type of target As returns +// false. +func As(err error, target interface{}) bool { + targetType := reflect.TypeOf(target) + + for { + errType := reflect.TypeOf(err) + + if errType == nil { + return false + } + + if reflect.PtrTo(errType) == targetType { + reflect.ValueOf(target).Elem().Set(reflect.ValueOf(err)) + return true + } + + wrapped, ok := err.(unwrapper) + if ok { + err = wrapped.Unwrap() + } else { + return false + } + } +} + +// Is detects whether the error is equal to a given error. Errors +// are considered equal by this function if they are the same object, +// or if they both contain the same error inside an errors.Error. +func Is(e error, original error) bool { + if e == original { + return true + } + + if e, ok := e.(*Error); ok { + return Is(e.Err, original) + } + + if original, ok := original.(*Error); ok { + return Is(e, original.Err) + } + + return false +} diff --git a/vendor/github.com/go-errors/errors/stackframe.go b/vendor/github.com/go-errors/errors/stackframe.go index 750ab9a521..ef4a8b3f3b 100644 --- a/vendor/github.com/go-errors/errors/stackframe.go +++ b/vendor/github.com/go-errors/errors/stackframe.go @@ -1,9 +1,10 @@ package errors import ( + "bufio" "bytes" "fmt" - "io/ioutil" + "os" "runtime" "strings" ) @@ -52,7 +53,7 @@ func (frame *StackFrame) Func() *runtime.Func { func (frame *StackFrame) String() string { str := fmt.Sprintf("%s:%d (0x%x)\n", frame.File, frame.LineNumber, frame.ProgramCounter) - source, err := frame.SourceLine() + source, err := frame.sourceLine() if err != nil { return str } @@ -62,18 +63,37 @@ func (frame *StackFrame) String() string { // SourceLine gets the line of code (from File and Line) of the original source if possible. func (frame *StackFrame) SourceLine() (string, error) { - data, err := ioutil.ReadFile(frame.File) - + source, err := frame.sourceLine() if err != nil { - return "", New(err) + return source, New(err) } + return source, err +} - lines := bytes.Split(data, []byte{'\n'}) - if frame.LineNumber <= 0 || frame.LineNumber >= len(lines) { +func (frame *StackFrame) sourceLine() (string, error) { + if frame.LineNumber <= 0 { return "???", nil } - // -1 because line-numbers are 1 based, but our array is 0 based - return string(bytes.Trim(lines[frame.LineNumber-1], " \t")), nil + + file, err := os.Open(frame.File) + if err != nil { + return "", err + } + defer file.Close() + + scanner := bufio.NewScanner(file) + currentLine := 1 + for scanner.Scan() { + if currentLine == frame.LineNumber { + return string(bytes.Trim(scanner.Bytes(), " \t")), nil + } + currentLine++ + } + if err := scanner.Err(); err != nil { + return "", err + } + + return "???", nil } func packageAndName(fn *runtime.Func) (string, string) { diff --git a/vendor/github.com/go-logr/logr/.golangci.yaml b/vendor/github.com/go-logr/logr/.golangci.yaml index 94ff801df1..0cffafa7bf 100644 --- a/vendor/github.com/go-logr/logr/.golangci.yaml +++ b/vendor/github.com/go-logr/logr/.golangci.yaml @@ -6,7 +6,6 @@ linters: disable-all: true enable: - asciicheck - - deadcode - errcheck - forcetypeassert - gocritic @@ -18,10 +17,8 @@ linters: - misspell - revive - staticcheck - - structcheck - typecheck - unused - - varcheck issues: exclude-use-default: false diff --git a/vendor/github.com/go-logr/logr/discard.go b/vendor/github.com/go-logr/logr/discard.go index 9d92a38f1d..99fe8be93c 100644 --- a/vendor/github.com/go-logr/logr/discard.go +++ b/vendor/github.com/go-logr/logr/discard.go @@ -20,35 +20,5 @@ package logr // used whenever the caller is not interested in the logs. Logger instances // produced by this function always compare as equal. func Discard() Logger { - return Logger{ - level: 0, - sink: discardLogSink{}, - } -} - -// discardLogSink is a LogSink that discards all messages. -type discardLogSink struct{} - -// Verify that it actually implements the interface -var _ LogSink = discardLogSink{} - -func (l discardLogSink) Init(RuntimeInfo) { -} - -func (l discardLogSink) Enabled(int) bool { - return false -} - -func (l discardLogSink) Info(int, string, ...interface{}) { -} - -func (l discardLogSink) Error(error, string, ...interface{}) { -} - -func (l discardLogSink) WithValues(...interface{}) LogSink { - return l -} - -func (l discardLogSink) WithName(string) LogSink { - return l + return New(nil) } diff --git a/vendor/github.com/go-logr/logr/funcr/funcr.go b/vendor/github.com/go-logr/logr/funcr/funcr.go new file mode 100644 index 0000000000..e52f0cd01e --- /dev/null +++ b/vendor/github.com/go-logr/logr/funcr/funcr.go @@ -0,0 +1,804 @@ +/* +Copyright 2021 The logr Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package funcr implements formatting of structured log messages and +// optionally captures the call site and timestamp. +// +// The simplest way to use it is via its implementation of a +// github.com/go-logr/logr.LogSink with output through an arbitrary +// "write" function. See New and NewJSON for details. +// +// # Custom LogSinks +// +// For users who need more control, a funcr.Formatter can be embedded inside +// your own custom LogSink implementation. This is useful when the LogSink +// needs to implement additional methods, for example. +// +// # Formatting +// +// This will respect logr.Marshaler, fmt.Stringer, and error interfaces for +// values which are being logged. When rendering a struct, funcr will use Go's +// standard JSON tags (all except "string"). +package funcr + +import ( + "bytes" + "encoding" + "encoding/json" + "fmt" + "path/filepath" + "reflect" + "runtime" + "strconv" + "strings" + "time" + + "github.com/go-logr/logr" +) + +// New returns a logr.Logger which is implemented by an arbitrary function. +func New(fn func(prefix, args string), opts Options) logr.Logger { + return logr.New(newSink(fn, NewFormatter(opts))) +} + +// NewJSON returns a logr.Logger which is implemented by an arbitrary function +// and produces JSON output. +func NewJSON(fn func(obj string), opts Options) logr.Logger { + fnWrapper := func(_, obj string) { + fn(obj) + } + return logr.New(newSink(fnWrapper, NewFormatterJSON(opts))) +} + +// Underlier exposes access to the underlying logging function. Since +// callers only have a logr.Logger, they have to know which +// implementation is in use, so this interface is less of an +// abstraction and more of a way to test type conversion. +type Underlier interface { + GetUnderlying() func(prefix, args string) +} + +func newSink(fn func(prefix, args string), formatter Formatter) logr.LogSink { + l := &fnlogger{ + Formatter: formatter, + write: fn, + } + // For skipping fnlogger.Info and fnlogger.Error. + l.Formatter.AddCallDepth(1) + return l +} + +// Options carries parameters which influence the way logs are generated. +type Options struct { + // LogCaller tells funcr to add a "caller" key to some or all log lines. + // This has some overhead, so some users might not want it. + LogCaller MessageClass + + // LogCallerFunc tells funcr to also log the calling function name. This + // has no effect if caller logging is not enabled (see Options.LogCaller). + LogCallerFunc bool + + // LogTimestamp tells funcr to add a "ts" key to log lines. This has some + // overhead, so some users might not want it. + LogTimestamp bool + + // TimestampFormat tells funcr how to render timestamps when LogTimestamp + // is enabled. If not specified, a default format will be used. For more + // details, see docs for Go's time.Layout. + TimestampFormat string + + // Verbosity tells funcr which V logs to produce. Higher values enable + // more logs. Info logs at or below this level will be written, while logs + // above this level will be discarded. + Verbosity int + + // RenderBuiltinsHook allows users to mutate the list of key-value pairs + // while a log line is being rendered. The kvList argument follows logr + // conventions - each pair of slice elements is comprised of a string key + // and an arbitrary value (verified and sanitized before calling this + // hook). The value returned must follow the same conventions. This hook + // can be used to audit or modify logged data. For example, you might want + // to prefix all of funcr's built-in keys with some string. This hook is + // only called for built-in (provided by funcr itself) key-value pairs. + // Equivalent hooks are offered for key-value pairs saved via + // logr.Logger.WithValues or Formatter.AddValues (see RenderValuesHook) and + // for user-provided pairs (see RenderArgsHook). + RenderBuiltinsHook func(kvList []interface{}) []interface{} + + // RenderValuesHook is the same as RenderBuiltinsHook, except that it is + // only called for key-value pairs saved via logr.Logger.WithValues. See + // RenderBuiltinsHook for more details. + RenderValuesHook func(kvList []interface{}) []interface{} + + // RenderArgsHook is the same as RenderBuiltinsHook, except that it is only + // called for key-value pairs passed directly to Info and Error. See + // RenderBuiltinsHook for more details. + RenderArgsHook func(kvList []interface{}) []interface{} + + // MaxLogDepth tells funcr how many levels of nested fields (e.g. a struct + // that contains a struct, etc.) it may log. Every time it finds a struct, + // slice, array, or map the depth is increased by one. When the maximum is + // reached, the value will be converted to a string indicating that the max + // depth has been exceeded. If this field is not specified, a default + // value will be used. + MaxLogDepth int +} + +// MessageClass indicates which category or categories of messages to consider. +type MessageClass int + +const ( + // None ignores all message classes. + None MessageClass = iota + // All considers all message classes. + All + // Info only considers info messages. + Info + // Error only considers error messages. + Error +) + +// fnlogger inherits some of its LogSink implementation from Formatter +// and just needs to add some glue code. +type fnlogger struct { + Formatter + write func(prefix, args string) +} + +func (l fnlogger) WithName(name string) logr.LogSink { + l.Formatter.AddName(name) + return &l +} + +func (l fnlogger) WithValues(kvList ...interface{}) logr.LogSink { + l.Formatter.AddValues(kvList) + return &l +} + +func (l fnlogger) WithCallDepth(depth int) logr.LogSink { + l.Formatter.AddCallDepth(depth) + return &l +} + +func (l fnlogger) Info(level int, msg string, kvList ...interface{}) { + prefix, args := l.FormatInfo(level, msg, kvList) + l.write(prefix, args) +} + +func (l fnlogger) Error(err error, msg string, kvList ...interface{}) { + prefix, args := l.FormatError(err, msg, kvList) + l.write(prefix, args) +} + +func (l fnlogger) GetUnderlying() func(prefix, args string) { + return l.write +} + +// Assert conformance to the interfaces. +var _ logr.LogSink = &fnlogger{} +var _ logr.CallDepthLogSink = &fnlogger{} +var _ Underlier = &fnlogger{} + +// NewFormatter constructs a Formatter which emits a JSON-like key=value format. +func NewFormatter(opts Options) Formatter { + return newFormatter(opts, outputKeyValue) +} + +// NewFormatterJSON constructs a Formatter which emits strict JSON. +func NewFormatterJSON(opts Options) Formatter { + return newFormatter(opts, outputJSON) +} + +// Defaults for Options. +const defaultTimestampFormat = "2006-01-02 15:04:05.000000" +const defaultMaxLogDepth = 16 + +func newFormatter(opts Options, outfmt outputFormat) Formatter { + if opts.TimestampFormat == "" { + opts.TimestampFormat = defaultTimestampFormat + } + if opts.MaxLogDepth == 0 { + opts.MaxLogDepth = defaultMaxLogDepth + } + f := Formatter{ + outputFormat: outfmt, + prefix: "", + values: nil, + depth: 0, + opts: &opts, + } + return f +} + +// Formatter is an opaque struct which can be embedded in a LogSink +// implementation. It should be constructed with NewFormatter. Some of +// its methods directly implement logr.LogSink. +type Formatter struct { + outputFormat outputFormat + prefix string + values []interface{} + valuesStr string + depth int + opts *Options +} + +// outputFormat indicates which outputFormat to use. +type outputFormat int + +const ( + // outputKeyValue emits a JSON-like key=value format, but not strict JSON. + outputKeyValue outputFormat = iota + // outputJSON emits strict JSON. + outputJSON +) + +// PseudoStruct is a list of key-value pairs that gets logged as a struct. +type PseudoStruct []interface{} + +// render produces a log line, ready to use. +func (f Formatter) render(builtins, args []interface{}) string { + // Empirically bytes.Buffer is faster than strings.Builder for this. + buf := bytes.NewBuffer(make([]byte, 0, 1024)) + if f.outputFormat == outputJSON { + buf.WriteByte('{') + } + vals := builtins + if hook := f.opts.RenderBuiltinsHook; hook != nil { + vals = hook(f.sanitize(vals)) + } + f.flatten(buf, vals, false, false) // keys are ours, no need to escape + continuing := len(builtins) > 0 + if len(f.valuesStr) > 0 { + if continuing { + if f.outputFormat == outputJSON { + buf.WriteByte(',') + } else { + buf.WriteByte(' ') + } + } + continuing = true + buf.WriteString(f.valuesStr) + } + vals = args + if hook := f.opts.RenderArgsHook; hook != nil { + vals = hook(f.sanitize(vals)) + } + f.flatten(buf, vals, continuing, true) // escape user-provided keys + if f.outputFormat == outputJSON { + buf.WriteByte('}') + } + return buf.String() +} + +// flatten renders a list of key-value pairs into a buffer. If continuing is +// true, it assumes that the buffer has previous values and will emit a +// separator (which depends on the output format) before the first pair it +// writes. If escapeKeys is true, the keys are assumed to have +// non-JSON-compatible characters in them and must be evaluated for escapes. +// +// This function returns a potentially modified version of kvList, which +// ensures that there is a value for every key (adding a value if needed) and +// that each key is a string (substituting a key if needed). +func (f Formatter) flatten(buf *bytes.Buffer, kvList []interface{}, continuing bool, escapeKeys bool) []interface{} { + // This logic overlaps with sanitize() but saves one type-cast per key, + // which can be measurable. + if len(kvList)%2 != 0 { + kvList = append(kvList, noValue) + } + for i := 0; i < len(kvList); i += 2 { + k, ok := kvList[i].(string) + if !ok { + k = f.nonStringKey(kvList[i]) + kvList[i] = k + } + v := kvList[i+1] + + if i > 0 || continuing { + if f.outputFormat == outputJSON { + buf.WriteByte(',') + } else { + // In theory the format could be something we don't understand. In + // practice, we control it, so it won't be. + buf.WriteByte(' ') + } + } + + if escapeKeys { + buf.WriteString(prettyString(k)) + } else { + // this is faster + buf.WriteByte('"') + buf.WriteString(k) + buf.WriteByte('"') + } + if f.outputFormat == outputJSON { + buf.WriteByte(':') + } else { + buf.WriteByte('=') + } + buf.WriteString(f.pretty(v)) + } + return kvList +} + +func (f Formatter) pretty(value interface{}) string { + return f.prettyWithFlags(value, 0, 0) +} + +const ( + flagRawStruct = 0x1 // do not print braces on structs +) + +// TODO: This is not fast. Most of the overhead goes here. +func (f Formatter) prettyWithFlags(value interface{}, flags uint32, depth int) string { + if depth > f.opts.MaxLogDepth { + return `""` + } + + // Handle types that take full control of logging. + if v, ok := value.(logr.Marshaler); ok { + // Replace the value with what the type wants to get logged. + // That then gets handled below via reflection. + value = invokeMarshaler(v) + } + + // Handle types that want to format themselves. + switch v := value.(type) { + case fmt.Stringer: + value = invokeStringer(v) + case error: + value = invokeError(v) + } + + // Handling the most common types without reflect is a small perf win. + switch v := value.(type) { + case bool: + return strconv.FormatBool(v) + case string: + return prettyString(v) + case int: + return strconv.FormatInt(int64(v), 10) + case int8: + return strconv.FormatInt(int64(v), 10) + case int16: + return strconv.FormatInt(int64(v), 10) + case int32: + return strconv.FormatInt(int64(v), 10) + case int64: + return strconv.FormatInt(int64(v), 10) + case uint: + return strconv.FormatUint(uint64(v), 10) + case uint8: + return strconv.FormatUint(uint64(v), 10) + case uint16: + return strconv.FormatUint(uint64(v), 10) + case uint32: + return strconv.FormatUint(uint64(v), 10) + case uint64: + return strconv.FormatUint(v, 10) + case uintptr: + return strconv.FormatUint(uint64(v), 10) + case float32: + return strconv.FormatFloat(float64(v), 'f', -1, 32) + case float64: + return strconv.FormatFloat(v, 'f', -1, 64) + case complex64: + return `"` + strconv.FormatComplex(complex128(v), 'f', -1, 64) + `"` + case complex128: + return `"` + strconv.FormatComplex(v, 'f', -1, 128) + `"` + case PseudoStruct: + buf := bytes.NewBuffer(make([]byte, 0, 1024)) + v = f.sanitize(v) + if flags&flagRawStruct == 0 { + buf.WriteByte('{') + } + for i := 0; i < len(v); i += 2 { + if i > 0 { + buf.WriteByte(',') + } + k, _ := v[i].(string) // sanitize() above means no need to check success + // arbitrary keys might need escaping + buf.WriteString(prettyString(k)) + buf.WriteByte(':') + buf.WriteString(f.prettyWithFlags(v[i+1], 0, depth+1)) + } + if flags&flagRawStruct == 0 { + buf.WriteByte('}') + } + return buf.String() + } + + buf := bytes.NewBuffer(make([]byte, 0, 256)) + t := reflect.TypeOf(value) + if t == nil { + return "null" + } + v := reflect.ValueOf(value) + switch t.Kind() { + case reflect.Bool: + return strconv.FormatBool(v.Bool()) + case reflect.String: + return prettyString(v.String()) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return strconv.FormatInt(int64(v.Int()), 10) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return strconv.FormatUint(uint64(v.Uint()), 10) + case reflect.Float32: + return strconv.FormatFloat(float64(v.Float()), 'f', -1, 32) + case reflect.Float64: + return strconv.FormatFloat(v.Float(), 'f', -1, 64) + case reflect.Complex64: + return `"` + strconv.FormatComplex(complex128(v.Complex()), 'f', -1, 64) + `"` + case reflect.Complex128: + return `"` + strconv.FormatComplex(v.Complex(), 'f', -1, 128) + `"` + case reflect.Struct: + if flags&flagRawStruct == 0 { + buf.WriteByte('{') + } + printComma := false // testing i>0 is not enough because of JSON omitted fields + for i := 0; i < t.NumField(); i++ { + fld := t.Field(i) + if fld.PkgPath != "" { + // reflect says this field is only defined for non-exported fields. + continue + } + if !v.Field(i).CanInterface() { + // reflect isn't clear exactly what this means, but we can't use it. + continue + } + name := "" + omitempty := false + if tag, found := fld.Tag.Lookup("json"); found { + if tag == "-" { + continue + } + if comma := strings.Index(tag, ","); comma != -1 { + if n := tag[:comma]; n != "" { + name = n + } + rest := tag[comma:] + if strings.Contains(rest, ",omitempty,") || strings.HasSuffix(rest, ",omitempty") { + omitempty = true + } + } else { + name = tag + } + } + if omitempty && isEmpty(v.Field(i)) { + continue + } + if printComma { + buf.WriteByte(',') + } + printComma = true // if we got here, we are rendering a field + if fld.Anonymous && fld.Type.Kind() == reflect.Struct && name == "" { + buf.WriteString(f.prettyWithFlags(v.Field(i).Interface(), flags|flagRawStruct, depth+1)) + continue + } + if name == "" { + name = fld.Name + } + // field names can't contain characters which need escaping + buf.WriteByte('"') + buf.WriteString(name) + buf.WriteByte('"') + buf.WriteByte(':') + buf.WriteString(f.prettyWithFlags(v.Field(i).Interface(), 0, depth+1)) + } + if flags&flagRawStruct == 0 { + buf.WriteByte('}') + } + return buf.String() + case reflect.Slice, reflect.Array: + // If this is outputing as JSON make sure this isn't really a json.RawMessage. + // If so just emit "as-is" and don't pretty it as that will just print + // it as [X,Y,Z,...] which isn't terribly useful vs the string form you really want. + if f.outputFormat == outputJSON { + if rm, ok := value.(json.RawMessage); ok { + // If it's empty make sure we emit an empty value as the array style would below. + if len(rm) > 0 { + buf.Write(rm) + } else { + buf.WriteString("null") + } + return buf.String() + } + } + buf.WriteByte('[') + for i := 0; i < v.Len(); i++ { + if i > 0 { + buf.WriteByte(',') + } + e := v.Index(i) + buf.WriteString(f.prettyWithFlags(e.Interface(), 0, depth+1)) + } + buf.WriteByte(']') + return buf.String() + case reflect.Map: + buf.WriteByte('{') + // This does not sort the map keys, for best perf. + it := v.MapRange() + i := 0 + for it.Next() { + if i > 0 { + buf.WriteByte(',') + } + // If a map key supports TextMarshaler, use it. + keystr := "" + if m, ok := it.Key().Interface().(encoding.TextMarshaler); ok { + txt, err := m.MarshalText() + if err != nil { + keystr = fmt.Sprintf("", err.Error()) + } else { + keystr = string(txt) + } + keystr = prettyString(keystr) + } else { + // prettyWithFlags will produce already-escaped values + keystr = f.prettyWithFlags(it.Key().Interface(), 0, depth+1) + if t.Key().Kind() != reflect.String { + // JSON only does string keys. Unlike Go's standard JSON, we'll + // convert just about anything to a string. + keystr = prettyString(keystr) + } + } + buf.WriteString(keystr) + buf.WriteByte(':') + buf.WriteString(f.prettyWithFlags(it.Value().Interface(), 0, depth+1)) + i++ + } + buf.WriteByte('}') + return buf.String() + case reflect.Ptr, reflect.Interface: + if v.IsNil() { + return "null" + } + return f.prettyWithFlags(v.Elem().Interface(), 0, depth) + } + return fmt.Sprintf(`""`, t.Kind().String()) +} + +func prettyString(s string) string { + // Avoid escaping (which does allocations) if we can. + if needsEscape(s) { + return strconv.Quote(s) + } + b := bytes.NewBuffer(make([]byte, 0, 1024)) + b.WriteByte('"') + b.WriteString(s) + b.WriteByte('"') + return b.String() +} + +// needsEscape determines whether the input string needs to be escaped or not, +// without doing any allocations. +func needsEscape(s string) bool { + for _, r := range s { + if !strconv.IsPrint(r) || r == '\\' || r == '"' { + return true + } + } + return false +} + +func isEmpty(v reflect.Value) bool { + switch v.Kind() { + case reflect.Array, reflect.Map, reflect.Slice, reflect.String: + return v.Len() == 0 + case reflect.Bool: + return !v.Bool() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v.Int() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return v.Uint() == 0 + case reflect.Float32, reflect.Float64: + return v.Float() == 0 + case reflect.Complex64, reflect.Complex128: + return v.Complex() == 0 + case reflect.Interface, reflect.Ptr: + return v.IsNil() + } + return false +} + +func invokeMarshaler(m logr.Marshaler) (ret interface{}) { + defer func() { + if r := recover(); r != nil { + ret = fmt.Sprintf("", r) + } + }() + return m.MarshalLog() +} + +func invokeStringer(s fmt.Stringer) (ret string) { + defer func() { + if r := recover(); r != nil { + ret = fmt.Sprintf("", r) + } + }() + return s.String() +} + +func invokeError(e error) (ret string) { + defer func() { + if r := recover(); r != nil { + ret = fmt.Sprintf("", r) + } + }() + return e.Error() +} + +// Caller represents the original call site for a log line, after considering +// logr.Logger.WithCallDepth and logr.Logger.WithCallStackHelper. The File and +// Line fields will always be provided, while the Func field is optional. +// Users can set the render hook fields in Options to examine logged key-value +// pairs, one of which will be {"caller", Caller} if the Options.LogCaller +// field is enabled for the given MessageClass. +type Caller struct { + // File is the basename of the file for this call site. + File string `json:"file"` + // Line is the line number in the file for this call site. + Line int `json:"line"` + // Func is the function name for this call site, or empty if + // Options.LogCallerFunc is not enabled. + Func string `json:"function,omitempty"` +} + +func (f Formatter) caller() Caller { + // +1 for this frame, +1 for Info/Error. + pc, file, line, ok := runtime.Caller(f.depth + 2) + if !ok { + return Caller{"", 0, ""} + } + fn := "" + if f.opts.LogCallerFunc { + if fp := runtime.FuncForPC(pc); fp != nil { + fn = fp.Name() + } + } + + return Caller{filepath.Base(file), line, fn} +} + +const noValue = "" + +func (f Formatter) nonStringKey(v interface{}) string { + return fmt.Sprintf("", f.snippet(v)) +} + +// snippet produces a short snippet string of an arbitrary value. +func (f Formatter) snippet(v interface{}) string { + const snipLen = 16 + + snip := f.pretty(v) + if len(snip) > snipLen { + snip = snip[:snipLen] + } + return snip +} + +// sanitize ensures that a list of key-value pairs has a value for every key +// (adding a value if needed) and that each key is a string (substituting a key +// if needed). +func (f Formatter) sanitize(kvList []interface{}) []interface{} { + if len(kvList)%2 != 0 { + kvList = append(kvList, noValue) + } + for i := 0; i < len(kvList); i += 2 { + _, ok := kvList[i].(string) + if !ok { + kvList[i] = f.nonStringKey(kvList[i]) + } + } + return kvList +} + +// Init configures this Formatter from runtime info, such as the call depth +// imposed by logr itself. +// Note that this receiver is a pointer, so depth can be saved. +func (f *Formatter) Init(info logr.RuntimeInfo) { + f.depth += info.CallDepth +} + +// Enabled checks whether an info message at the given level should be logged. +func (f Formatter) Enabled(level int) bool { + return level <= f.opts.Verbosity +} + +// GetDepth returns the current depth of this Formatter. This is useful for +// implementations which do their own caller attribution. +func (f Formatter) GetDepth() int { + return f.depth +} + +// FormatInfo renders an Info log message into strings. The prefix will be +// empty when no names were set (via AddNames), or when the output is +// configured for JSON. +func (f Formatter) FormatInfo(level int, msg string, kvList []interface{}) (prefix, argsStr string) { + args := make([]interface{}, 0, 64) // using a constant here impacts perf + prefix = f.prefix + if f.outputFormat == outputJSON { + args = append(args, "logger", prefix) + prefix = "" + } + if f.opts.LogTimestamp { + args = append(args, "ts", time.Now().Format(f.opts.TimestampFormat)) + } + if policy := f.opts.LogCaller; policy == All || policy == Info { + args = append(args, "caller", f.caller()) + } + args = append(args, "level", level, "msg", msg) + return prefix, f.render(args, kvList) +} + +// FormatError renders an Error log message into strings. The prefix will be +// empty when no names were set (via AddNames), or when the output is +// configured for JSON. +func (f Formatter) FormatError(err error, msg string, kvList []interface{}) (prefix, argsStr string) { + args := make([]interface{}, 0, 64) // using a constant here impacts perf + prefix = f.prefix + if f.outputFormat == outputJSON { + args = append(args, "logger", prefix) + prefix = "" + } + if f.opts.LogTimestamp { + args = append(args, "ts", time.Now().Format(f.opts.TimestampFormat)) + } + if policy := f.opts.LogCaller; policy == All || policy == Error { + args = append(args, "caller", f.caller()) + } + args = append(args, "msg", msg) + var loggableErr interface{} + if err != nil { + loggableErr = err.Error() + } + args = append(args, "error", loggableErr) + return f.prefix, f.render(args, kvList) +} + +// AddName appends the specified name. funcr uses '/' characters to separate +// name elements. Callers should not pass '/' in the provided name string, but +// this library does not actually enforce that. +func (f *Formatter) AddName(name string) { + if len(f.prefix) > 0 { + f.prefix += "/" + } + f.prefix += name +} + +// AddValues adds key-value pairs to the set of saved values to be logged with +// each log line. +func (f *Formatter) AddValues(kvList []interface{}) { + // Three slice args forces a copy. + n := len(f.values) + f.values = append(f.values[:n:n], kvList...) + + vals := f.values + if hook := f.opts.RenderValuesHook; hook != nil { + vals = hook(f.sanitize(vals)) + } + + // Pre-render values, so we don't have to do it on each Info/Error call. + buf := bytes.NewBuffer(make([]byte, 0, 1024)) + f.flatten(buf, vals, false, true) // escape user-provided keys + f.valuesStr = buf.String() +} + +// AddCallDepth increases the number of stack-frames to skip when attributing +// the log line to a file and line. +func (f *Formatter) AddCallDepth(depth int) { + f.depth += depth +} diff --git a/vendor/github.com/go-logr/logr/logr.go b/vendor/github.com/go-logr/logr/logr.go index c3b56b3d2c..e027aea3fd 100644 --- a/vendor/github.com/go-logr/logr/logr.go +++ b/vendor/github.com/go-logr/logr/logr.go @@ -21,7 +21,7 @@ limitations under the License. // to back that API. Packages in the Go ecosystem can depend on this package, // while callers can implement logging with whatever backend is appropriate. // -// Usage +// # Usage // // Logging is done using a Logger instance. Logger is a concrete type with // methods, which defers the actual logging to a LogSink interface. The main @@ -30,16 +30,20 @@ limitations under the License. // "structured logging". // // With Go's standard log package, we might write: -// log.Printf("setting target value %s", targetValue) +// +// log.Printf("setting target value %s", targetValue) // // With logr's structured logging, we'd write: -// logger.Info("setting target", "value", targetValue) +// +// logger.Info("setting target", "value", targetValue) // // Errors are much the same. Instead of: -// log.Printf("failed to open the pod bay door for user %s: %v", user, err) +// +// log.Printf("failed to open the pod bay door for user %s: %v", user, err) // // We'd write: -// logger.Error(err, "failed to open the pod bay door", "user", user) +// +// logger.Error(err, "failed to open the pod bay door", "user", user) // // Info() and Error() are very similar, but they are separate methods so that // LogSink implementations can choose to do things like attach additional @@ -47,7 +51,7 @@ limitations under the License. // always logged, regardless of the current verbosity. If there is no error // instance available, passing nil is valid. // -// Verbosity +// # Verbosity // // Often we want to log information only when the application in "verbose // mode". To write log lines that are more verbose, Logger has a V() method. @@ -58,20 +62,22 @@ limitations under the License. // Error messages do not have a verbosity level and are always logged. // // Where we might have written: -// if flVerbose >= 2 { -// log.Printf("an unusual thing happened") -// } +// +// if flVerbose >= 2 { +// log.Printf("an unusual thing happened") +// } // // We can write: -// logger.V(2).Info("an unusual thing happened") // -// Logger Names +// logger.V(2).Info("an unusual thing happened") +// +// # Logger Names // // Logger instances can have name strings so that all messages logged through // that instance have additional context. For example, you might want to add // a subsystem name: // -// logger.WithName("compactor").Info("started", "time", time.Now()) +// logger.WithName("compactor").Info("started", "time", time.Now()) // // The WithName() method returns a new Logger, which can be passed to // constructors or other functions for further use. Repeated use of WithName() @@ -82,25 +88,27 @@ limitations under the License. // joining operation (e.g. whitespace, commas, periods, slashes, brackets, // quotes, etc). // -// Saved Values +// # Saved Values // // Logger instances can store any number of key/value pairs, which will be // logged alongside all messages logged through that instance. For example, // you might want to create a Logger instance per managed object: // // With the standard log package, we might write: -// log.Printf("decided to set field foo to value %q for object %s/%s", -// targetValue, object.Namespace, object.Name) +// +// log.Printf("decided to set field foo to value %q for object %s/%s", +// targetValue, object.Namespace, object.Name) // // With logr we'd write: -// // Elsewhere: set up the logger to log the object name. -// obj.logger = mainLogger.WithValues( -// "name", obj.name, "namespace", obj.namespace) // -// // later on... -// obj.logger.Info("setting foo", "value", targetValue) +// // Elsewhere: set up the logger to log the object name. +// obj.logger = mainLogger.WithValues( +// "name", obj.name, "namespace", obj.namespace) +// +// // later on... +// obj.logger.Info("setting foo", "value", targetValue) // -// Best Practices +// # Best Practices // // Logger has very few hard rules, with the goal that LogSink implementations // might have a lot of freedom to differentiate. There are, however, some @@ -124,15 +132,15 @@ limitations under the License. // around. For cases where passing a logger is optional, a pointer to Logger // should be used. // -// Key Naming Conventions +// # Key Naming Conventions // // Keys are not strictly required to conform to any specification or regex, but // it is recommended that they: -// * be human-readable and meaningful (not auto-generated or simple ordinals) -// * be constant (not dependent on input data) -// * contain only printable characters -// * not contain whitespace or punctuation -// * use lower case for simple keys and lowerCamelCase for more complex ones +// - be human-readable and meaningful (not auto-generated or simple ordinals) +// - be constant (not dependent on input data) +// - contain only printable characters +// - not contain whitespace or punctuation +// - use lower case for simple keys and lowerCamelCase for more complex ones // // These guidelines help ensure that log data is processed properly regardless // of the log implementation. For example, log implementations will try to @@ -141,51 +149,54 @@ limitations under the License. // While users are generally free to use key names of their choice, it's // generally best to avoid using the following keys, as they're frequently used // by implementations: -// * "caller": the calling information (file/line) of a particular log line -// * "error": the underlying error value in the `Error` method -// * "level": the log level -// * "logger": the name of the associated logger -// * "msg": the log message -// * "stacktrace": the stack trace associated with a particular log line or -// error (often from the `Error` message) -// * "ts": the timestamp for a log line +// - "caller": the calling information (file/line) of a particular log line +// - "error": the underlying error value in the `Error` method +// - "level": the log level +// - "logger": the name of the associated logger +// - "msg": the log message +// - "stacktrace": the stack trace associated with a particular log line or +// error (often from the `Error` message) +// - "ts": the timestamp for a log line // // Implementations are encouraged to make use of these keys to represent the // above concepts, when necessary (for example, in a pure-JSON output form, it // would be necessary to represent at least message and timestamp as ordinary // named values). // -// Break Glass +// # Break Glass // // Implementations may choose to give callers access to the underlying // logging implementation. The recommended pattern for this is: -// // Underlier exposes access to the underlying logging implementation. -// // Since callers only have a logr.Logger, they have to know which -// // implementation is in use, so this interface is less of an abstraction -// // and more of way to test type conversion. -// type Underlier interface { -// GetUnderlying() -// } +// +// // Underlier exposes access to the underlying logging implementation. +// // Since callers only have a logr.Logger, they have to know which +// // implementation is in use, so this interface is less of an abstraction +// // and more of way to test type conversion. +// type Underlier interface { +// GetUnderlying() +// } // // Logger grants access to the sink to enable type assertions like this: -// func DoSomethingWithImpl(log logr.Logger) { -// if underlier, ok := log.GetSink()(impl.Underlier) { -// implLogger := underlier.GetUnderlying() -// ... -// } -// } +// +// func DoSomethingWithImpl(log logr.Logger) { +// if underlier, ok := log.GetSink().(impl.Underlier); ok { +// implLogger := underlier.GetUnderlying() +// ... +// } +// } // // Custom `With*` functions can be implemented by copying the complete // Logger struct and replacing the sink in the copy: -// // WithFooBar changes the foobar parameter in the log sink and returns a -// // new logger with that modified sink. It does nothing for loggers where -// // the sink doesn't support that parameter. -// func WithFoobar(log logr.Logger, foobar int) logr.Logger { -// if foobarLogSink, ok := log.GetSink()(FoobarSink); ok { -// log = log.WithSink(foobarLogSink.WithFooBar(foobar)) -// } -// return log -// } +// +// // WithFooBar changes the foobar parameter in the log sink and returns a +// // new logger with that modified sink. It does nothing for loggers where +// // the sink doesn't support that parameter. +// func WithFoobar(log logr.Logger, foobar int) logr.Logger { +// if foobarLogSink, ok := log.GetSink().(FoobarSink); ok { +// log = log.WithSink(foobarLogSink.WithFooBar(foobar)) +// } +// return log +// } // // Don't use New to construct a new Logger with a LogSink retrieved from an // existing Logger. Source code attribution might not work correctly and @@ -201,11 +212,14 @@ import ( ) // New returns a new Logger instance. This is primarily used by libraries -// implementing LogSink, rather than end users. +// implementing LogSink, rather than end users. Passing a nil sink will create +// a Logger which discards all log lines. func New(sink LogSink) Logger { logger := Logger{} logger.setSink(sink) - sink.Init(runtimeInfo) + if sink != nil { + sink.Init(runtimeInfo) + } return logger } @@ -244,7 +258,7 @@ type Logger struct { // Enabled tests whether this Logger is enabled. For example, commandline // flags might be used to set the logging verbosity and disable some info logs. func (l Logger) Enabled() bool { - return l.sink.Enabled(l.level) + return l.sink != nil && l.sink.Enabled(l.level) } // Info logs a non-error message with the given key/value pairs as context. @@ -254,6 +268,9 @@ func (l Logger) Enabled() bool { // information. The key/value pairs must alternate string keys and arbitrary // values. func (l Logger) Info(msg string, keysAndValues ...interface{}) { + if l.sink == nil { + return + } if l.Enabled() { if withHelper, ok := l.sink.(CallStackHelperLogSink); ok { withHelper.GetCallStackHelper()() @@ -273,6 +290,9 @@ func (l Logger) Info(msg string, keysAndValues ...interface{}) { // triggered this log line, if present. The err parameter is optional // and nil may be passed instead of an error instance. func (l Logger) Error(err error, msg string, keysAndValues ...interface{}) { + if l.sink == nil { + return + } if withHelper, ok := l.sink.(CallStackHelperLogSink); ok { withHelper.GetCallStackHelper()() } @@ -284,6 +304,9 @@ func (l Logger) Error(err error, msg string, keysAndValues ...interface{}) { // level means a log message is less important. Negative V-levels are treated // as 0. func (l Logger) V(level int) Logger { + if l.sink == nil { + return l + } if level < 0 { level = 0 } @@ -294,6 +317,9 @@ func (l Logger) V(level int) Logger { // WithValues returns a new Logger instance with additional key/value pairs. // See Info for documentation on how key/value pairs work. func (l Logger) WithValues(keysAndValues ...interface{}) Logger { + if l.sink == nil { + return l + } l.setSink(l.sink.WithValues(keysAndValues...)) return l } @@ -304,6 +330,9 @@ func (l Logger) WithValues(keysAndValues ...interface{}) Logger { // contain only letters, digits, and hyphens (see the package documentation for // more information). func (l Logger) WithName(name string) Logger { + if l.sink == nil { + return l + } l.setSink(l.sink.WithName(name)) return l } @@ -324,6 +353,9 @@ func (l Logger) WithName(name string) Logger { // WithCallDepth(1) because it works with implementions that support the // CallDepthLogSink and/or CallStackHelperLogSink interfaces. func (l Logger) WithCallDepth(depth int) Logger { + if l.sink == nil { + return l + } if withCallDepth, ok := l.sink.(CallDepthLogSink); ok { l.setSink(withCallDepth.WithCallDepth(depth)) } @@ -345,6 +377,9 @@ func (l Logger) WithCallDepth(depth int) Logger { // implementation does not support either of these, the original Logger will be // returned. func (l Logger) WithCallStackHelper() (func(), Logger) { + if l.sink == nil { + return func() {}, l + } var helper func() if withCallDepth, ok := l.sink.(CallDepthLogSink); ok { l.setSink(withCallDepth.WithCallDepth(1)) @@ -357,6 +392,11 @@ func (l Logger) WithCallStackHelper() (func(), Logger) { return helper, l } +// IsZero returns true if this logger is an uninitialized zero value +func (l Logger) IsZero() bool { + return l.sink == nil +} + // contextKey is how we find Loggers in a context.Context. type contextKey struct{} @@ -442,7 +482,7 @@ type LogSink interface { WithName(name string) LogSink } -// CallDepthLogSink represents a Logger that knows how to climb the call stack +// CallDepthLogSink represents a LogSink that knows how to climb the call stack // to identify the original call site and can offset the depth by a specified // number of frames. This is useful for users who have helper functions // between the "real" call site and the actual calls to Logger methods. @@ -467,7 +507,7 @@ type CallDepthLogSink interface { WithCallDepth(depth int) LogSink } -// CallStackHelperLogSink represents a Logger that knows how to climb +// CallStackHelperLogSink represents a LogSink that knows how to climb // the call stack to identify the original call site and can skip // intermediate helper functions if they mark themselves as // helper. Go's testing package uses that approach. diff --git a/vendor/go.opentelemetry.io/contrib/LICENSE b/vendor/github.com/go-logr/stdr/LICENSE similarity index 100% rename from vendor/go.opentelemetry.io/contrib/LICENSE rename to vendor/github.com/go-logr/stdr/LICENSE diff --git a/vendor/github.com/go-logr/stdr/README.md b/vendor/github.com/go-logr/stdr/README.md new file mode 100644 index 0000000000..5158667890 --- /dev/null +++ b/vendor/github.com/go-logr/stdr/README.md @@ -0,0 +1,6 @@ +# Minimal Go logging using logr and Go's standard library + +[![Go Reference](https://pkg.go.dev/badge/github.com/go-logr/stdr.svg)](https://pkg.go.dev/github.com/go-logr/stdr) + +This package implements the [logr interface](https://github.com/go-logr/logr) +in terms of Go's standard log package(https://pkg.go.dev/log). diff --git a/vendor/github.com/go-logr/stdr/stdr.go b/vendor/github.com/go-logr/stdr/stdr.go new file mode 100644 index 0000000000..93a8aab51b --- /dev/null +++ b/vendor/github.com/go-logr/stdr/stdr.go @@ -0,0 +1,170 @@ +/* +Copyright 2019 The logr Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package stdr implements github.com/go-logr/logr.Logger in terms of +// Go's standard log package. +package stdr + +import ( + "log" + "os" + + "github.com/go-logr/logr" + "github.com/go-logr/logr/funcr" +) + +// The global verbosity level. See SetVerbosity(). +var globalVerbosity int + +// SetVerbosity sets the global level against which all info logs will be +// compared. If this is greater than or equal to the "V" of the logger, the +// message will be logged. A higher value here means more logs will be written. +// The previous verbosity value is returned. This is not concurrent-safe - +// callers must be sure to call it from only one goroutine. +func SetVerbosity(v int) int { + old := globalVerbosity + globalVerbosity = v + return old +} + +// New returns a logr.Logger which is implemented by Go's standard log package, +// or something like it. If std is nil, this will use a default logger +// instead. +// +// Example: stdr.New(log.New(os.Stderr, "", log.LstdFlags|log.Lshortfile))) +func New(std StdLogger) logr.Logger { + return NewWithOptions(std, Options{}) +} + +// NewWithOptions returns a logr.Logger which is implemented by Go's standard +// log package, or something like it. See New for details. +func NewWithOptions(std StdLogger, opts Options) logr.Logger { + if std == nil { + // Go's log.Default() is only available in 1.16 and higher. + std = log.New(os.Stderr, "", log.LstdFlags) + } + + if opts.Depth < 0 { + opts.Depth = 0 + } + + fopts := funcr.Options{ + LogCaller: funcr.MessageClass(opts.LogCaller), + } + + sl := &logger{ + Formatter: funcr.NewFormatter(fopts), + std: std, + } + + // For skipping our own logger.Info/Error. + sl.Formatter.AddCallDepth(1 + opts.Depth) + + return logr.New(sl) +} + +// Options carries parameters which influence the way logs are generated. +type Options struct { + // Depth biases the assumed number of call frames to the "true" caller. + // This is useful when the calling code calls a function which then calls + // stdr (e.g. a logging shim to another API). Values less than zero will + // be treated as zero. + Depth int + + // LogCaller tells stdr to add a "caller" key to some or all log lines. + // Go's log package has options to log this natively, too. + LogCaller MessageClass + + // TODO: add an option to log the date/time +} + +// MessageClass indicates which category or categories of messages to consider. +type MessageClass int + +const ( + // None ignores all message classes. + None MessageClass = iota + // All considers all message classes. + All + // Info only considers info messages. + Info + // Error only considers error messages. + Error +) + +// StdLogger is the subset of the Go stdlib log.Logger API that is needed for +// this adapter. +type StdLogger interface { + // Output is the same as log.Output and log.Logger.Output. + Output(calldepth int, logline string) error +} + +type logger struct { + funcr.Formatter + std StdLogger +} + +var _ logr.LogSink = &logger{} +var _ logr.CallDepthLogSink = &logger{} + +func (l logger) Enabled(level int) bool { + return globalVerbosity >= level +} + +func (l logger) Info(level int, msg string, kvList ...interface{}) { + prefix, args := l.FormatInfo(level, msg, kvList) + if prefix != "" { + args = prefix + ": " + args + } + _ = l.std.Output(l.Formatter.GetDepth()+1, args) +} + +func (l logger) Error(err error, msg string, kvList ...interface{}) { + prefix, args := l.FormatError(err, msg, kvList) + if prefix != "" { + args = prefix + ": " + args + } + _ = l.std.Output(l.Formatter.GetDepth()+1, args) +} + +func (l logger) WithName(name string) logr.LogSink { + l.Formatter.AddName(name) + return &l +} + +func (l logger) WithValues(kvList ...interface{}) logr.LogSink { + l.Formatter.AddValues(kvList) + return &l +} + +func (l logger) WithCallDepth(depth int) logr.LogSink { + l.Formatter.AddCallDepth(depth) + return &l +} + +// Underlier exposes access to the underlying logging implementation. Since +// callers only have a logr.Logger, they have to know which implementation is +// in use, so this interface is less of an abstraction and more of way to test +// type conversion. +type Underlier interface { + GetUnderlying() StdLogger +} + +// GetUnderlying returns the StdLogger underneath this logger. Since StdLogger +// is itself an interface, the result may or may not be a Go log.Logger. +func (l logger) GetUnderlying() StdLogger { + return l.std +} diff --git a/vendor/github.com/go-openapi/jsonpointer/.travis.yml b/vendor/github.com/go-openapi/jsonpointer/.travis.yml deleted file mode 100644 index 03a22fe06f..0000000000 --- a/vendor/github.com/go-openapi/jsonpointer/.travis.yml +++ /dev/null @@ -1,15 +0,0 @@ -after_success: -- bash <(curl -s https://codecov.io/bash) -go: -- 1.14.x -- 1.15.x -install: -- GO111MODULE=off go get -u gotest.tools/gotestsum -env: -- GO111MODULE=on -language: go -notifications: - slack: - secure: a5VgoiwB1G/AZqzmephPZIhEB9avMlsWSlVnM1dSAtYAwdrQHGTQxAmpOxYIoSPDhWNN5bfZmjd29++UlTwLcHSR+e0kJhH6IfDlsHj/HplNCJ9tyI0zYc7XchtdKgeMxMzBKCzgwFXGSbQGydXTliDNBo0HOzmY3cou/daMFTP60K+offcjS+3LRAYb1EroSRXZqrk1nuF/xDL3792DZUdPMiFR/L/Df6y74D6/QP4sTkTDFQitz4Wy/7jbsfj8dG6qK2zivgV6/l+w4OVjFkxVpPXogDWY10vVXNVynqxfJ7to2d1I9lNCHE2ilBCkWMIPdyJF7hjF8pKW+82yP4EzRh0vu8Xn0HT5MZpQxdRY/YMxNrWaG7SxsoEaO4q5uhgdzAqLYY3TRa7MjIK+7Ur+aqOeTXn6OKwVi0CjvZ6mIU3WUKSwiwkFZMbjRAkSb5CYwMEfGFO/z964xz83qGt6WAtBXNotqCQpTIiKtDHQeLOMfksHImCg6JLhQcWBVxamVgu0G3Pdh8Y6DyPnxraXY95+QDavbjqv7TeYT9T/FNnrkXaTTK0s4iWE5H4ACU0Qvz0wUYgfQrZv0/Hp7V17+rabUwnzYySHCy9SWX/7OV9Cfh31iMp9ZIffr76xmmThtOEqs8TrTtU6BWI3rWwvA9cXQipZTVtL0oswrGw= -script: -- gotestsum -f short-verbose -- -race -coverprofile=coverage.txt -covermode=atomic ./... diff --git a/vendor/github.com/go-openapi/jsonreference/.golangci.yml b/vendor/github.com/go-openapi/jsonreference/.golangci.yml index f9381aee54..013fc1943a 100644 --- a/vendor/github.com/go-openapi/jsonreference/.golangci.yml +++ b/vendor/github.com/go-openapi/jsonreference/.golangci.yml @@ -1,8 +1,6 @@ linters-settings: govet: check-shadowing: true - golint: - min-confidence: 0 gocyclo: min-complexity: 30 maligned: @@ -12,6 +10,8 @@ linters-settings: goconst: min-len: 2 min-occurrences: 4 + paralleltest: + ignore-missing: true linters: enable-all: true disable: @@ -39,3 +39,12 @@ linters: - nestif - godot - errorlint + - varcheck + - interfacer + - deadcode + - golint + - ifshort + - structcheck + - nosnakecase + - varnamelen + - exhaustruct diff --git a/vendor/github.com/go-openapi/jsonreference/.travis.yml b/vendor/github.com/go-openapi/jsonreference/.travis.yml deleted file mode 100644 index 05482f4b90..0000000000 --- a/vendor/github.com/go-openapi/jsonreference/.travis.yml +++ /dev/null @@ -1,24 +0,0 @@ -after_success: -- bash <(curl -s https://codecov.io/bash) -go: -- 1.14.x -- 1.x -install: -- go get gotest.tools/gotestsum -jobs: - include: - # include linting job, but only for latest go version and amd64 arch - - go: 1.x - arch: amd64 - install: - go get github.com/golangci/golangci-lint/cmd/golangci-lint - script: - - golangci-lint run --new-from-rev master -env: -- GO111MODULE=on -language: go -notifications: - slack: - secure: OpQG/36F7DSF00HLm9WZMhyqFCYYyYTsVDObW226cWiR8PWYiNfLZiSEvIzT1Gx4dDjhigKTIqcLhG34CkL5iNXDjm9Yyo2RYhQPlK8NErNqUEXuBqn4RqYHW48VGhEhOyDd4Ei0E2FN5ZbgpvHgtpkdZ6XDi64r3Ac89isP9aPHXQTuv2Jog6b4/OKKiUTftLcTIst0p4Cp3gqOJWf1wnoj+IadWiECNVQT6zb47IYjtyw6+uV8iUjTzdKcRB6Zc6b4Dq7JAg1Zd7Jfxkql3hlKp4PNlRf9Cy7y5iA3G7MLyg3FcPX5z2kmcyPt2jOTRMBWUJ5zIQpOxizAcN8WsT3WWBL5KbuYK6k0PzujrIDLqdxGpNmjkkMfDBT9cKmZpm2FdW+oZgPFJP+oKmAo4u4KJz/vjiPTXgQlN5bmrLuRMCp+AwC5wkIohTqWZVPE2TK6ZSnMYcg/W39s+RP/9mJoyryAvPSpBOLTI+biCgaUCTOAZxNTWpMFc3tPYntc41WWkdKcooZ9JA5DwfcaVFyTGQ3YXz+HvX6G1z/gW0Q/A4dBi9mj2iE1xm7tRTT+4VQ2AXFvSEI1HJpfPgYnwAtwOD1v3Qm2EUHk9sCdtEDR4wVGEPIVn44GnwFMnGKx9JWppMPYwFu3SVDdHt+E+LOlhZUply11Aa+IVrT2KUQ= -script: -- gotestsum -f short-verbose -- -race -coverprofile=coverage.txt -covermode=atomic ./... diff --git a/vendor/github.com/go-openapi/jsonreference/internal/normalize_url.go b/vendor/github.com/go-openapi/jsonreference/internal/normalize_url.go new file mode 100644 index 0000000000..fb376fce2d --- /dev/null +++ b/vendor/github.com/go-openapi/jsonreference/internal/normalize_url.go @@ -0,0 +1,64 @@ +package internal + +import ( + "net/url" + "regexp" + "strings" +) + +const ( + defaultHTTPPort = ":80" + defaultHTTPSPort = ":443" +) + +// Regular expressions used by the normalizations +var rxPort = regexp.MustCompile(`(:\d+)/?$`) +var rxDupSlashes = regexp.MustCompile(`/{2,}`) + +// NormalizeURL will normalize the specified URL +// This was added to replace a previous call to the no longer maintained purell library: +// The call that was used looked like the following: +// +// url.Parse(purell.NormalizeURL(parsed, purell.FlagsSafe|purell.FlagRemoveDuplicateSlashes)) +// +// To explain all that was included in the call above, purell.FlagsSafe was really just the following: +// - FlagLowercaseScheme +// - FlagLowercaseHost +// - FlagRemoveDefaultPort +// - FlagRemoveDuplicateSlashes (and this was mixed in with the |) +func NormalizeURL(u *url.URL) { + lowercaseScheme(u) + lowercaseHost(u) + removeDefaultPort(u) + removeDuplicateSlashes(u) +} + +func lowercaseScheme(u *url.URL) { + if len(u.Scheme) > 0 { + u.Scheme = strings.ToLower(u.Scheme) + } +} + +func lowercaseHost(u *url.URL) { + if len(u.Host) > 0 { + u.Host = strings.ToLower(u.Host) + } +} + +func removeDefaultPort(u *url.URL) { + if len(u.Host) > 0 { + scheme := strings.ToLower(u.Scheme) + u.Host = rxPort.ReplaceAllStringFunc(u.Host, func(val string) string { + if (scheme == "http" && val == defaultHTTPPort) || (scheme == "https" && val == defaultHTTPSPort) { + return "" + } + return val + }) + } +} + +func removeDuplicateSlashes(u *url.URL) { + if len(u.Path) > 0 { + u.Path = rxDupSlashes.ReplaceAllString(u.Path, "/") + } +} diff --git a/vendor/github.com/go-openapi/jsonreference/reference.go b/vendor/github.com/go-openapi/jsonreference/reference.go index 3bc0a6e26f..cfdef03e5d 100644 --- a/vendor/github.com/go-openapi/jsonreference/reference.go +++ b/vendor/github.com/go-openapi/jsonreference/reference.go @@ -30,8 +30,8 @@ import ( "net/url" "strings" - "github.com/PuerkitoBio/purell" "github.com/go-openapi/jsonpointer" + "github.com/go-openapi/jsonreference/internal" ) const ( @@ -114,7 +114,9 @@ func (r *Ref) parse(jsonReferenceString string) error { return err } - r.referenceURL, _ = url.Parse(purell.NormalizeURL(parsed, purell.FlagsSafe|purell.FlagRemoveDuplicateSlashes)) + internal.NormalizeURL(parsed) + + r.referenceURL = parsed refURL := r.referenceURL if refURL.Scheme != "" && refURL.Host != "" { diff --git a/vendor/github.com/go-openapi/swag/.gitattributes b/vendor/github.com/go-openapi/swag/.gitattributes new file mode 100644 index 0000000000..49ad52766a --- /dev/null +++ b/vendor/github.com/go-openapi/swag/.gitattributes @@ -0,0 +1,2 @@ +# gofmt always uses LF, whereas Git uses CRLF on Windows. +*.go text eol=lf diff --git a/vendor/github.com/go-openapi/swag/.golangci.yml b/vendor/github.com/go-openapi/swag/.golangci.yml index 813c47aa64..bf503e4000 100644 --- a/vendor/github.com/go-openapi/swag/.golangci.yml +++ b/vendor/github.com/go-openapi/swag/.golangci.yml @@ -37,3 +37,18 @@ linters: - gci - gocognit - paralleltest + - thelper + - ifshort + - gomoddirectives + - cyclop + - forcetypeassert + - ireturn + - tagliatelle + - varnamelen + - goimports + - tenv + - golint + - exhaustruct + - nilnil + - nonamedreturns + - nosnakecase diff --git a/vendor/github.com/go-openapi/swag/.travis.yml b/vendor/github.com/go-openapi/swag/.travis.yml deleted file mode 100644 index fc25a88728..0000000000 --- a/vendor/github.com/go-openapi/swag/.travis.yml +++ /dev/null @@ -1,37 +0,0 @@ -after_success: -- bash <(curl -s https://codecov.io/bash) -go: -- 1.14.x -- 1.x -arch: -- amd64 -jobs: - include: - # include arch ppc, but only for latest go version - skip testing for race - - go: 1.x - arch: ppc64le - install: ~ - script: - - go test -v - - #- go: 1.x - # arch: arm - # install: ~ - # script: - # - go test -v - - # include linting job, but only for latest go version and amd64 arch - - go: 1.x - arch: amd64 - install: - go get github.com/golangci/golangci-lint/cmd/golangci-lint - script: - - golangci-lint run --new-from-rev master -install: -- GO111MODULE=off go get -u gotest.tools/gotestsum -language: go -notifications: - slack: - secure: QUWvCkBBK09GF7YtEvHHVt70JOkdlNBG0nIKu/5qc4/nW5HP8I2w0SEf/XR2je0eED1Qe3L/AfMCWwrEj+IUZc3l4v+ju8X8R3Lomhme0Eb0jd1MTMCuPcBT47YCj0M7RON7vXtbFfm1hFJ/jLe5+9FXz0hpXsR24PJc5ZIi/ogNwkaPqG4BmndzecpSh0vc2FJPZUD9LT0I09REY/vXR0oQAalLkW0asGD5taHZTUZq/kBpsNxaAFrLM23i4mUcf33M5fjLpvx5LRICrX/57XpBrDh2TooBU6Qj3CgoY0uPRYUmSNxbVx1czNzl2JtEpb5yjoxfVPQeg0BvQM00G8LJINISR+ohrjhkZmAqchDupAX+yFrxTtORa78CtnIL6z/aTNlgwwVD8kvL/1pFA/JWYmKDmz93mV/+6wubGzNSQCstzjkFA4/iZEKewKUoRIAi/fxyscP6L/rCpmY/4llZZvrnyTqVbt6URWpopUpH4rwYqreXAtJxJsfBJIeSmUIiDIOMGkCTvyTEW3fWGmGoqWtSHLoaWDyAIGb7azb+KvfpWtEcoPFWfSWU+LGee0A/YsUhBl7ADB9A0CJEuR8q4BPpKpfLwPKSiKSAXL7zDkyjExyhtgqbSl2jS+rKIHOZNL8JkCcTP2MKMVd563C5rC5FMKqu3S9m2b6380E= -script: -- gotestsum -f short-verbose -- -race -coverprofile=coverage.txt -covermode=atomic ./... diff --git a/vendor/github.com/go-openapi/swag/doc.go b/vendor/github.com/go-openapi/swag/doc.go index 8d2c8c5014..55094cb74c 100644 --- a/vendor/github.com/go-openapi/swag/doc.go +++ b/vendor/github.com/go-openapi/swag/doc.go @@ -17,16 +17,15 @@ Package swag contains a bunch of helper functions for go-openapi and go-swagger You may also use it standalone for your projects. - * convert between value and pointers for builtin types - * convert from string to builtin types (wraps strconv) - * fast json concatenation - * search in path - * load from file or http - * name mangling - + - convert between value and pointers for builtin types + - convert from string to builtin types (wraps strconv) + - fast json concatenation + - search in path + - load from file or http + - name mangling This repo has only few dependencies outside of the standard library: - * YAML utilities depend on gopkg.in/yaml.v2 + - YAML utilities depend on gopkg.in/yaml.v2 */ package swag diff --git a/vendor/github.com/go-openapi/swag/file.go b/vendor/github.com/go-openapi/swag/file.go new file mode 100644 index 0000000000..16accc55f8 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/file.go @@ -0,0 +1,33 @@ +// Copyright 2015 go-swagger maintainers +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package swag + +import "mime/multipart" + +// File represents an uploaded file. +type File struct { + Data multipart.File + Header *multipart.FileHeader +} + +// Read bytes from the file +func (f *File) Read(p []byte) (n int, err error) { + return f.Data.Read(p) +} + +// Close the file +func (f *File) Close() error { + return f.Data.Close() +} diff --git a/vendor/github.com/go-openapi/swag/loading.go b/vendor/github.com/go-openapi/swag/loading.go index 9a60409725..00038c3773 100644 --- a/vendor/github.com/go-openapi/swag/loading.go +++ b/vendor/github.com/go-openapi/swag/loading.go @@ -16,10 +16,11 @@ package swag import ( "fmt" - "io/ioutil" + "io" "log" "net/http" "net/url" + "os" "path/filepath" "runtime" "strings" @@ -40,13 +41,13 @@ var LoadHTTPCustomHeaders = map[string]string{} // LoadFromFileOrHTTP loads the bytes from a file or a remote http server based on the path passed in func LoadFromFileOrHTTP(path string) ([]byte, error) { - return LoadStrategy(path, ioutil.ReadFile, loadHTTPBytes(LoadHTTPTimeout))(path) + return LoadStrategy(path, os.ReadFile, loadHTTPBytes(LoadHTTPTimeout))(path) } // LoadFromFileOrHTTPWithTimeout loads the bytes from a file or a remote http server based on the path passed in // timeout arg allows for per request overriding of the request timeout func LoadFromFileOrHTTPWithTimeout(path string, timeout time.Duration) ([]byte, error) { - return LoadStrategy(path, ioutil.ReadFile, loadHTTPBytes(timeout))(path) + return LoadStrategy(path, os.ReadFile, loadHTTPBytes(timeout))(path) } // LoadStrategy returns a loader function for a given path or uri @@ -86,7 +87,7 @@ func LoadStrategy(path string, local, remote func(string) ([]byte, error)) func( func loadHTTPBytes(timeout time.Duration) func(path string) ([]byte, error) { return func(path string) ([]byte, error) { client := &http.Client{Timeout: timeout} - req, err := http.NewRequest("GET", path, nil) // nolint: noctx + req, err := http.NewRequest(http.MethodGet, path, nil) //nolint:noctx if err != nil { return nil, err } @@ -115,6 +116,6 @@ func loadHTTPBytes(timeout time.Duration) func(path string) ([]byte, error) { return nil, fmt.Errorf("could not access document at %q [%s] ", path, resp.Status) } - return ioutil.ReadAll(resp.Body) + return io.ReadAll(resp.Body) } } diff --git a/vendor/github.com/go-openapi/swag/post_go18.go b/vendor/github.com/go-openapi/swag/post_go18.go index c2e686d313..f5228b82c0 100644 --- a/vendor/github.com/go-openapi/swag/post_go18.go +++ b/vendor/github.com/go-openapi/swag/post_go18.go @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build go1.8 // +build go1.8 package swag diff --git a/vendor/github.com/go-openapi/swag/post_go19.go b/vendor/github.com/go-openapi/swag/post_go19.go index eb2f2d8bc7..7c7da9c088 100644 --- a/vendor/github.com/go-openapi/swag/post_go19.go +++ b/vendor/github.com/go-openapi/swag/post_go19.go @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build go1.9 // +build go1.9 package swag diff --git a/vendor/github.com/go-openapi/swag/pre_go18.go b/vendor/github.com/go-openapi/swag/pre_go18.go index 6607f33935..2757d9b95f 100644 --- a/vendor/github.com/go-openapi/swag/pre_go18.go +++ b/vendor/github.com/go-openapi/swag/pre_go18.go @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !go1.8 // +build !go1.8 package swag diff --git a/vendor/github.com/go-openapi/swag/pre_go19.go b/vendor/github.com/go-openapi/swag/pre_go19.go index 4bae187d1e..0565db377b 100644 --- a/vendor/github.com/go-openapi/swag/pre_go19.go +++ b/vendor/github.com/go-openapi/swag/pre_go19.go @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !go1.9 // +build !go1.9 package swag diff --git a/vendor/github.com/go-openapi/swag/util.go b/vendor/github.com/go-openapi/swag/util.go index 193702f2ce..f78ab684a0 100644 --- a/vendor/github.com/go-openapi/swag/util.go +++ b/vendor/github.com/go-openapi/swag/util.go @@ -99,10 +99,11 @@ const ( ) // JoinByFormat joins a string array by a known format (e.g. swagger's collectionFormat attribute): -// ssv: space separated value -// tsv: tab separated value -// pipes: pipe (|) separated value -// csv: comma separated value (default) +// +// ssv: space separated value +// tsv: tab separated value +// pipes: pipe (|) separated value +// csv: comma separated value (default) func JoinByFormat(data []string, format string) []string { if len(data) == 0 { return data @@ -124,11 +125,11 @@ func JoinByFormat(data []string, format string) []string { } // SplitByFormat splits a string by a known format: -// ssv: space separated value -// tsv: tab separated value -// pipes: pipe (|) separated value -// csv: comma separated value (default) // +// ssv: space separated value +// tsv: tab separated value +// pipes: pipe (|) separated value +// csv: comma separated value (default) func SplitByFormat(data, format string) []string { if data == "" { return nil diff --git a/vendor/github.com/go-openapi/swag/yaml.go b/vendor/github.com/go-openapi/swag/yaml.go index ec96914405..f09ee609f3 100644 --- a/vendor/github.com/go-openapi/swag/yaml.go +++ b/vendor/github.com/go-openapi/swag/yaml.go @@ -22,7 +22,7 @@ import ( "github.com/mailru/easyjson/jlexer" "github.com/mailru/easyjson/jwriter" - yaml "gopkg.in/yaml.v2" + yaml "gopkg.in/yaml.v3" ) // YAMLMatcher matches yaml @@ -43,16 +43,126 @@ func YAMLToJSON(data interface{}) (json.RawMessage, error) { // BytesToYAMLDoc converts a byte slice into a YAML document func BytesToYAMLDoc(data []byte) (interface{}, error) { - var canary map[interface{}]interface{} // validate this is an object and not a different type - if err := yaml.Unmarshal(data, &canary); err != nil { + var document yaml.Node // preserve order that is present in the document + if err := yaml.Unmarshal(data, &document); err != nil { return nil, err } + if document.Kind != yaml.DocumentNode || len(document.Content) != 1 || document.Content[0].Kind != yaml.MappingNode { + return nil, fmt.Errorf("only YAML documents that are objects are supported") + } + return &document, nil +} - var document yaml.MapSlice // preserve order that is present in the document - if err := yaml.Unmarshal(data, &document); err != nil { - return nil, err +func yamlNode(root *yaml.Node) (interface{}, error) { + switch root.Kind { + case yaml.DocumentNode: + return yamlDocument(root) + case yaml.SequenceNode: + return yamlSequence(root) + case yaml.MappingNode: + return yamlMapping(root) + case yaml.ScalarNode: + return yamlScalar(root) + case yaml.AliasNode: + return yamlNode(root.Alias) + default: + return nil, fmt.Errorf("unsupported YAML node type: %v", root.Kind) + } +} + +func yamlDocument(node *yaml.Node) (interface{}, error) { + if len(node.Content) != 1 { + return nil, fmt.Errorf("unexpected YAML Document node content length: %d", len(node.Content)) + } + return yamlNode(node.Content[0]) +} + +func yamlMapping(node *yaml.Node) (interface{}, error) { + m := make(JSONMapSlice, len(node.Content)/2) + + var j int + for i := 0; i < len(node.Content); i += 2 { + var nmi JSONMapItem + k, err := yamlStringScalarC(node.Content[i]) + if err != nil { + return nil, fmt.Errorf("unable to decode YAML map key: %w", err) + } + nmi.Key = k + v, err := yamlNode(node.Content[i+1]) + if err != nil { + return nil, fmt.Errorf("unable to process YAML map value for key %q: %w", k, err) + } + nmi.Value = v + m[j] = nmi + j++ + } + return m, nil +} + +func yamlSequence(node *yaml.Node) (interface{}, error) { + s := make([]interface{}, 0) + + for i := 0; i < len(node.Content); i++ { + + v, err := yamlNode(node.Content[i]) + if err != nil { + return nil, fmt.Errorf("unable to decode YAML sequence value: %w", err) + } + s = append(s, v) + } + return s, nil +} + +const ( // See https://yaml.org/type/ + yamlStringScalar = "tag:yaml.org,2002:str" + yamlIntScalar = "tag:yaml.org,2002:int" + yamlBoolScalar = "tag:yaml.org,2002:bool" + yamlFloatScalar = "tag:yaml.org,2002:float" + yamlTimestamp = "tag:yaml.org,2002:timestamp" + yamlNull = "tag:yaml.org,2002:null" +) + +func yamlScalar(node *yaml.Node) (interface{}, error) { + switch node.LongTag() { + case yamlStringScalar: + return node.Value, nil + case yamlBoolScalar: + b, err := strconv.ParseBool(node.Value) + if err != nil { + return nil, fmt.Errorf("unable to process scalar node. Got %q. Expecting bool content: %w", node.Value, err) + } + return b, nil + case yamlIntScalar: + i, err := strconv.ParseInt(node.Value, 10, 64) + if err != nil { + return nil, fmt.Errorf("unable to process scalar node. Got %q. Expecting integer content: %w", node.Value, err) + } + return i, nil + case yamlFloatScalar: + f, err := strconv.ParseFloat(node.Value, 64) + if err != nil { + return nil, fmt.Errorf("unable to process scalar node. Got %q. Expecting float content: %w", node.Value, err) + } + return f, nil + case yamlTimestamp: + return node.Value, nil + case yamlNull: + return nil, nil + default: + return nil, fmt.Errorf("YAML tag %q is not supported", node.LongTag()) + } +} + +func yamlStringScalarC(node *yaml.Node) (string, error) { + if node.Kind != yaml.ScalarNode { + return "", fmt.Errorf("expecting a string scalar but got %q", node.Kind) + } + switch node.LongTag() { + case yamlStringScalar, yamlIntScalar, yamlFloatScalar: + return node.Value, nil + default: + return "", fmt.Errorf("YAML tag %q is not supported as map key", node.LongTag()) } - return document, nil } // JSONMapSlice represent a JSON object, with the order of keys maintained @@ -105,6 +215,113 @@ func (s *JSONMapSlice) UnmarshalEasyJSON(in *jlexer.Lexer) { *s = result } +func (s JSONMapSlice) MarshalYAML() (interface{}, error) { + var n yaml.Node + n.Kind = yaml.DocumentNode + var nodes []*yaml.Node + for _, item := range s { + nn, err := json2yaml(item.Value) + if err != nil { + return nil, err + } + ns := []*yaml.Node{ + { + Kind: yaml.ScalarNode, + Tag: yamlStringScalar, + Value: item.Key, + }, + nn, + } + nodes = append(nodes, ns...) + } + + n.Content = []*yaml.Node{ + { + Kind: yaml.MappingNode, + Content: nodes, + }, + } + + return yaml.Marshal(&n) +} + +func json2yaml(item interface{}) (*yaml.Node, error) { + switch val := item.(type) { + case JSONMapSlice: + var n yaml.Node + n.Kind = yaml.MappingNode + for i := range val { + childNode, err := json2yaml(&val[i].Value) + if err != nil { + return nil, err + } + n.Content = append(n.Content, &yaml.Node{ + Kind: yaml.ScalarNode, + Tag: yamlStringScalar, + Value: val[i].Key, + }, childNode) + } + return &n, nil + case map[string]interface{}: + var n yaml.Node + n.Kind = yaml.MappingNode + for k, v := range val { + childNode, err := json2yaml(v) + if err != nil { + return nil, err + } + n.Content = append(n.Content, &yaml.Node{ + Kind: yaml.ScalarNode, + Tag: yamlStringScalar, + Value: k, + }, childNode) + } + return &n, nil + case []interface{}: + var n yaml.Node + n.Kind = yaml.SequenceNode + for i := range val { + childNode, err := json2yaml(val[i]) + if err != nil { + return nil, err + } + n.Content = append(n.Content, childNode) + } + return &n, nil + case string: + return &yaml.Node{ + Kind: yaml.ScalarNode, + Tag: yamlStringScalar, + Value: val, + }, nil + case float64: + return &yaml.Node{ + Kind: yaml.ScalarNode, + Tag: yamlFloatScalar, + Value: strconv.FormatFloat(val, 'f', -1, 64), + }, nil + case int64: + return &yaml.Node{ + Kind: yaml.ScalarNode, + Tag: yamlIntScalar, + Value: strconv.FormatInt(val, 10), + }, nil + case uint64: + return &yaml.Node{ + Kind: yaml.ScalarNode, + Tag: yamlIntScalar, + Value: strconv.FormatUint(val, 10), + }, nil + case bool: + return &yaml.Node{ + Kind: yaml.ScalarNode, + Tag: yamlBoolScalar, + Value: strconv.FormatBool(val), + }, nil + } + return nil, nil +} + // JSONMapItem represents the value of a key in a JSON object held by JSONMapSlice type JSONMapItem struct { Key string @@ -173,23 +390,10 @@ func transformData(input interface{}) (out interface{}, err error) { } switch in := input.(type) { - case yaml.MapSlice: - - o := make(JSONMapSlice, len(in)) - for i, mi := range in { - var nmi JSONMapItem - if nmi.Key, err = format(mi.Key); err != nil { - return nil, err - } - - v, ert := transformData(mi.Value) - if ert != nil { - return nil, ert - } - nmi.Value = v - o[i] = nmi - } - return o, nil + case yaml.Node: + return yamlNode(&in) + case *yaml.Node: + return yamlNode(in) case map[interface{}]interface{}: o := make(JSONMapSlice, 0, len(in)) for ke, va := range in { diff --git a/vendor/github.com/golang-jwt/jwt/v4/.gitignore b/vendor/github.com/golang-jwt/jwt/v4/.gitignore deleted file mode 100644 index 09573e0169..0000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -.DS_Store -bin -.idea/ - diff --git a/vendor/github.com/golang-jwt/jwt/v4/LICENSE b/vendor/github.com/golang-jwt/jwt/v4/LICENSE deleted file mode 100644 index 35dbc25204..0000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/LICENSE +++ /dev/null @@ -1,9 +0,0 @@ -Copyright (c) 2012 Dave Grijalva -Copyright (c) 2021 golang-jwt maintainers - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - diff --git a/vendor/github.com/golang-jwt/jwt/v4/MIGRATION_GUIDE.md b/vendor/github.com/golang-jwt/jwt/v4/MIGRATION_GUIDE.md deleted file mode 100644 index 32966f5981..0000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/MIGRATION_GUIDE.md +++ /dev/null @@ -1,22 +0,0 @@ -## Migration Guide (v4.0.0) - -Starting from [v4.0.0](https://github.com/golang-jwt/jwt/releases/tag/v4.0.0), the import path will be: - - "github.com/golang-jwt/jwt/v4" - -The `/v4` version will be backwards compatible with existing `v3.x.y` tags in this repo, as well as -`github.com/dgrijalva/jwt-go`. For most users this should be a drop-in replacement, if you're having -troubles migrating, please open an issue. - -You can replace all occurrences of `github.com/dgrijalva/jwt-go` or `github.com/golang-jwt/jwt` with `github.com/golang-jwt/jwt/v4`, either manually or by using tools such as `sed` or `gofmt`. - -And then you'd typically run: - -``` -go get github.com/golang-jwt/jwt/v4 -go mod tidy -``` - -## Older releases (before v3.2.0) - -The original migration guide for older releases can be found at https://github.com/dgrijalva/jwt-go/blob/master/MIGRATION_GUIDE.md. diff --git a/vendor/github.com/golang-jwt/jwt/v4/README.md b/vendor/github.com/golang-jwt/jwt/v4/README.md deleted file mode 100644 index 3072d24a9d..0000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/README.md +++ /dev/null @@ -1,114 +0,0 @@ -# jwt-go - -[![build](https://github.com/golang-jwt/jwt/actions/workflows/build.yml/badge.svg)](https://github.com/golang-jwt/jwt/actions/workflows/build.yml) -[![Go Reference](https://pkg.go.dev/badge/github.com/golang-jwt/jwt/v4.svg)](https://pkg.go.dev/github.com/golang-jwt/jwt/v4) - -A [go](http://www.golang.org) (or 'golang' for search engine friendliness) implementation of [JSON Web Tokens](https://datatracker.ietf.org/doc/html/rfc7519). - -Starting with [v4.0.0](https://github.com/golang-jwt/jwt/releases/tag/v4.0.0) this project adds Go module support, but maintains backwards compatibility with older `v3.x.y` tags and upstream `github.com/dgrijalva/jwt-go`. -See the [`MIGRATION_GUIDE.md`](./MIGRATION_GUIDE.md) for more information. - -> After the original author of the library suggested migrating the maintenance of `jwt-go`, a dedicated team of open source maintainers decided to clone the existing library into this repository. See [dgrijalva/jwt-go#462](https://github.com/dgrijalva/jwt-go/issues/462) for a detailed discussion on this topic. - - -**SECURITY NOTICE:** Some older versions of Go have a security issue in the crypto/elliptic. Recommendation is to upgrade to at least 1.15 See issue [dgrijalva/jwt-go#216](https://github.com/dgrijalva/jwt-go/issues/216) for more detail. - -**SECURITY NOTICE:** It's important that you [validate the `alg` presented is what you expect](https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/). This library attempts to make it easy to do the right thing by requiring key types match the expected alg, but you should take the extra step to verify it in your usage. See the examples provided. - -### Supported Go versions - -Our support of Go versions is aligned with Go's [version release policy](https://golang.org/doc/devel/release#policy). -So we will support a major version of Go until there are two newer major releases. -We no longer support building jwt-go with unsupported Go versions, as these contain security vulnerabilities -which will not be fixed. - -## What the heck is a JWT? - -JWT.io has [a great introduction](https://jwt.io/introduction) to JSON Web Tokens. - -In short, it's a signed JSON object that does something useful (for example, authentication). It's commonly used for `Bearer` tokens in Oauth 2. A token is made of three parts, separated by `.`'s. The first two parts are JSON objects, that have been [base64url](https://datatracker.ietf.org/doc/html/rfc4648) encoded. The last part is the signature, encoded the same way. - -The first part is called the header. It contains the necessary information for verifying the last part, the signature. For example, which encryption method was used for signing and what key was used. - -The part in the middle is the interesting bit. It's called the Claims and contains the actual stuff you care about. Refer to [RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519) for information about reserved keys and the proper way to add your own. - -## What's in the box? - -This library supports the parsing and verification as well as the generation and signing of JWTs. Current supported signing algorithms are HMAC SHA, RSA, RSA-PSS, and ECDSA, though hooks are present for adding your own. - -## Examples - -See [the project documentation](https://pkg.go.dev/github.com/golang-jwt/jwt) for examples of usage: - -* [Simple example of parsing and validating a token](https://pkg.go.dev/github.com/golang-jwt/jwt#example-Parse-Hmac) -* [Simple example of building and signing a token](https://pkg.go.dev/github.com/golang-jwt/jwt#example-New-Hmac) -* [Directory of Examples](https://pkg.go.dev/github.com/golang-jwt/jwt#pkg-examples) - -## Extensions - -This library publishes all the necessary components for adding your own signing methods. Simply implement the `SigningMethod` interface and register a factory method using `RegisterSigningMethod`. - -Here's an example of an extension that integrates with multiple Google Cloud Platform signing tools (AppEngine, IAM API, Cloud KMS): https://github.com/someone1/gcp-jwt-go - -## Compliance - -This library was last reviewed to comply with [RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519) dated May 2015 with a few notable differences: - -* In order to protect against accidental use of [Unsecured JWTs](https://datatracker.ietf.org/doc/html/rfc7519#section-6), tokens using `alg=none` will only be accepted if the constant `jwt.UnsafeAllowNoneSignatureType` is provided as the key. - -## Project Status & Versioning - -This library is considered production ready. Feedback and feature requests are appreciated. The API should be considered stable. There should be very few backwards-incompatible changes outside of major version updates (and only with good reason). - -This project uses [Semantic Versioning 2.0.0](http://semver.org). Accepted pull requests will land on `main`. Periodically, versions will be tagged from `main`. You can find all the releases on [the project releases page](https://github.com/golang-jwt/jwt/releases). - -**BREAKING CHANGES:*** -A full list of breaking changes is available in `VERSION_HISTORY.md`. See `MIGRATION_GUIDE.md` for more information on updating your code. - -## Usage Tips - -### Signing vs Encryption - -A token is simply a JSON object that is signed by its author. this tells you exactly two things about the data: - -* The author of the token was in the possession of the signing secret -* The data has not been modified since it was signed - -It's important to know that JWT does not provide encryption, which means anyone who has access to the token can read its contents. If you need to protect (encrypt) the data, there is a companion spec, `JWE`, that provides this functionality. JWE is currently outside the scope of this library. - -### Choosing a Signing Method - -There are several signing methods available, and you should probably take the time to learn about the various options before choosing one. The principal design decision is most likely going to be symmetric vs asymmetric. - -Symmetric signing methods, such as HSA, use only a single secret. This is probably the simplest signing method to use since any `[]byte` can be used as a valid secret. They are also slightly computationally faster to use, though this rarely is enough to matter. Symmetric signing methods work the best when both producers and consumers of tokens are trusted, or even the same system. Since the same secret is used to both sign and validate tokens, you can't easily distribute the key for validation. - -Asymmetric signing methods, such as RSA, use different keys for signing and verifying tokens. This makes it possible to produce tokens with a private key, and allow any consumer to access the public key for verification. - -### Signing Methods and Key Types - -Each signing method expects a different object type for its signing keys. See the package documentation for details. Here are the most common ones: - -* The [HMAC signing method](https://pkg.go.dev/github.com/golang-jwt/jwt#SigningMethodHMAC) (`HS256`,`HS384`,`HS512`) expect `[]byte` values for signing and validation -* The [RSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt#SigningMethodRSA) (`RS256`,`RS384`,`RS512`) expect `*rsa.PrivateKey` for signing and `*rsa.PublicKey` for validation -* The [ECDSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt#SigningMethodECDSA) (`ES256`,`ES384`,`ES512`) expect `*ecdsa.PrivateKey` for signing and `*ecdsa.PublicKey` for validation -* The [EdDSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt#SigningMethodEd25519) (`Ed25519`) expect `ed25519.PrivateKey` for signing and `ed25519.PublicKey` for validation - -### JWT and OAuth - -It's worth mentioning that OAuth and JWT are not the same thing. A JWT token is simply a signed JSON object. It can be used anywhere such a thing is useful. There is some confusion, though, as JWT is the most common type of bearer token used in OAuth2 authentication. - -Without going too far down the rabbit hole, here's a description of the interaction of these technologies: - -* OAuth is a protocol for allowing an identity provider to be separate from the service a user is logging in to. For example, whenever you use Facebook to log into a different service (Yelp, Spotify, etc), you are using OAuth. -* OAuth defines several options for passing around authentication data. One popular method is called a "bearer token". A bearer token is simply a string that _should_ only be held by an authenticated user. Thus, simply presenting this token proves your identity. You can probably derive from here why a JWT might make a good bearer token. -* Because bearer tokens are used for authentication, it's important they're kept secret. This is why transactions that use bearer tokens typically happen over SSL. - -### Troubleshooting - -This library uses descriptive error messages whenever possible. If you are not getting the expected result, have a look at the errors. The most common place people get stuck is providing the correct type of key to the parser. See the above section on signing methods and key types. - -## More - -Documentation can be found [on pkg.go.dev](https://pkg.go.dev/github.com/golang-jwt/jwt). - -The command line utility included in this project (cmd/jwt) provides a straightforward example of token creation and parsing as well as a useful tool for debugging your own integration. You'll also find several implementation examples in the documentation. diff --git a/vendor/github.com/golang-jwt/jwt/v4/VERSION_HISTORY.md b/vendor/github.com/golang-jwt/jwt/v4/VERSION_HISTORY.md deleted file mode 100644 index afbfc4e408..0000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/VERSION_HISTORY.md +++ /dev/null @@ -1,135 +0,0 @@ -## `jwt-go` Version History - -#### 4.0.0 - -* Introduces support for Go modules. The `v4` version will be backwards compatible with `v3.x.y`. - -#### 3.2.2 - -* Starting from this release, we are adopting the policy to support the most 2 recent versions of Go currently available. By the time of this release, this is Go 1.15 and 1.16 ([#28](https://github.com/golang-jwt/jwt/pull/28)). -* Fixed a potential issue that could occur when the verification of `exp`, `iat` or `nbf` was not required and contained invalid contents, i.e. non-numeric/date. Thanks for @thaJeztah for making us aware of that and @giorgos-f3 for originally reporting it to the formtech fork ([#40](https://github.com/golang-jwt/jwt/pull/40)). -* Added support for EdDSA / ED25519 ([#36](https://github.com/golang-jwt/jwt/pull/36)). -* Optimized allocations ([#33](https://github.com/golang-jwt/jwt/pull/33)). - -#### 3.2.1 - -* **Import Path Change**: See MIGRATION_GUIDE.md for tips on updating your code - * Changed the import path from `github.com/dgrijalva/jwt-go` to `github.com/golang-jwt/jwt` -* Fixed type confusing issue between `string` and `[]string` in `VerifyAudience` ([#12](https://github.com/golang-jwt/jwt/pull/12)). This fixes CVE-2020-26160 - -#### 3.2.0 - -* Added method `ParseUnverified` to allow users to split up the tasks of parsing and validation -* HMAC signing method returns `ErrInvalidKeyType` instead of `ErrInvalidKey` where appropriate -* Added options to `request.ParseFromRequest`, which allows for an arbitrary list of modifiers to parsing behavior. Initial set include `WithClaims` and `WithParser`. Existing usage of this function will continue to work as before. -* Deprecated `ParseFromRequestWithClaims` to simplify API in the future. - -#### 3.1.0 - -* Improvements to `jwt` command line tool -* Added `SkipClaimsValidation` option to `Parser` -* Documentation updates - -#### 3.0.0 - -* **Compatibility Breaking Changes**: See MIGRATION_GUIDE.md for tips on updating your code - * Dropped support for `[]byte` keys when using RSA signing methods. This convenience feature could contribute to security vulnerabilities involving mismatched key types with signing methods. - * `ParseFromRequest` has been moved to `request` subpackage and usage has changed - * The `Claims` property on `Token` is now type `Claims` instead of `map[string]interface{}`. The default value is type `MapClaims`, which is an alias to `map[string]interface{}`. This makes it possible to use a custom type when decoding claims. -* Other Additions and Changes - * Added `Claims` interface type to allow users to decode the claims into a custom type - * Added `ParseWithClaims`, which takes a third argument of type `Claims`. Use this function instead of `Parse` if you have a custom type you'd like to decode into. - * Dramatically improved the functionality and flexibility of `ParseFromRequest`, which is now in the `request` subpackage - * Added `ParseFromRequestWithClaims` which is the `FromRequest` equivalent of `ParseWithClaims` - * Added new interface type `Extractor`, which is used for extracting JWT strings from http requests. Used with `ParseFromRequest` and `ParseFromRequestWithClaims`. - * Added several new, more specific, validation errors to error type bitmask - * Moved examples from README to executable example files - * Signing method registry is now thread safe - * Added new property to `ValidationError`, which contains the raw error returned by calls made by parse/verify (such as those returned by keyfunc or json parser) - -#### 2.7.0 - -This will likely be the last backwards compatible release before 3.0.0, excluding essential bug fixes. - -* Added new option `-show` to the `jwt` command that will just output the decoded token without verifying -* Error text for expired tokens includes how long it's been expired -* Fixed incorrect error returned from `ParseRSAPublicKeyFromPEM` -* Documentation updates - -#### 2.6.0 - -* Exposed inner error within ValidationError -* Fixed validation errors when using UseJSONNumber flag -* Added several unit tests - -#### 2.5.0 - -* Added support for signing method none. You shouldn't use this. The API tries to make this clear. -* Updated/fixed some documentation -* Added more helpful error message when trying to parse tokens that begin with `BEARER ` - -#### 2.4.0 - -* Added new type, Parser, to allow for configuration of various parsing parameters - * You can now specify a list of valid signing methods. Anything outside this set will be rejected. - * You can now opt to use the `json.Number` type instead of `float64` when parsing token JSON -* Added support for [Travis CI](https://travis-ci.org/dgrijalva/jwt-go) -* Fixed some bugs with ECDSA parsing - -#### 2.3.0 - -* Added support for ECDSA signing methods -* Added support for RSA PSS signing methods (requires go v1.4) - -#### 2.2.0 - -* Gracefully handle a `nil` `Keyfunc` being passed to `Parse`. Result will now be the parsed token and an error, instead of a panic. - -#### 2.1.0 - -Backwards compatible API change that was missed in 2.0.0. - -* The `SignedString` method on `Token` now takes `interface{}` instead of `[]byte` - -#### 2.0.0 - -There were two major reasons for breaking backwards compatibility with this update. The first was a refactor required to expand the width of the RSA and HMAC-SHA signing implementations. There will likely be no required code changes to support this change. - -The second update, while unfortunately requiring a small change in integration, is required to open up this library to other signing methods. Not all keys used for all signing methods have a single standard on-disk representation. Requiring `[]byte` as the type for all keys proved too limiting. Additionally, this implementation allows for pre-parsed tokens to be reused, which might matter in an application that parses a high volume of tokens with a small set of keys. Backwards compatibilty has been maintained for passing `[]byte` to the RSA signing methods, but they will also accept `*rsa.PublicKey` and `*rsa.PrivateKey`. - -It is likely the only integration change required here will be to change `func(t *jwt.Token) ([]byte, error)` to `func(t *jwt.Token) (interface{}, error)` when calling `Parse`. - -* **Compatibility Breaking Changes** - * `SigningMethodHS256` is now `*SigningMethodHMAC` instead of `type struct` - * `SigningMethodRS256` is now `*SigningMethodRSA` instead of `type struct` - * `KeyFunc` now returns `interface{}` instead of `[]byte` - * `SigningMethod.Sign` now takes `interface{}` instead of `[]byte` for the key - * `SigningMethod.Verify` now takes `interface{}` instead of `[]byte` for the key -* Renamed type `SigningMethodHS256` to `SigningMethodHMAC`. Specific sizes are now just instances of this type. - * Added public package global `SigningMethodHS256` - * Added public package global `SigningMethodHS384` - * Added public package global `SigningMethodHS512` -* Renamed type `SigningMethodRS256` to `SigningMethodRSA`. Specific sizes are now just instances of this type. - * Added public package global `SigningMethodRS256` - * Added public package global `SigningMethodRS384` - * Added public package global `SigningMethodRS512` -* Moved sample private key for HMAC tests from an inline value to a file on disk. Value is unchanged. -* Refactored the RSA implementation to be easier to read -* Exposed helper methods `ParseRSAPrivateKeyFromPEM` and `ParseRSAPublicKeyFromPEM` - -#### 1.0.2 - -* Fixed bug in parsing public keys from certificates -* Added more tests around the parsing of keys for RS256 -* Code refactoring in RS256 implementation. No functional changes - -#### 1.0.1 - -* Fixed panic if RS256 signing method was passed an invalid key - -#### 1.0.0 - -* First versioned release -* API stabilized -* Supports creating, signing, parsing, and validating JWT tokens -* Supports RS256 and HS256 signing methods diff --git a/vendor/github.com/golang-jwt/jwt/v4/claims.go b/vendor/github.com/golang-jwt/jwt/v4/claims.go deleted file mode 100644 index 41cc826563..0000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/claims.go +++ /dev/null @@ -1,273 +0,0 @@ -package jwt - -import ( - "crypto/subtle" - "fmt" - "time" -) - -// Claims must just have a Valid method that determines -// if the token is invalid for any supported reason -type Claims interface { - Valid() error -} - -// RegisteredClaims are a structured version of the JWT Claims Set, -// restricted to Registered Claim Names, as referenced at -// https://datatracker.ietf.org/doc/html/rfc7519#section-4.1 -// -// This type can be used on its own, but then additional private and -// public claims embedded in the JWT will not be parsed. The typical usecase -// therefore is to embedded this in a user-defined claim type. -// -// See examples for how to use this with your own claim types. -type RegisteredClaims struct { - // the `iss` (Issuer) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.1 - Issuer string `json:"iss,omitempty"` - - // the `sub` (Subject) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.2 - Subject string `json:"sub,omitempty"` - - // the `aud` (Audience) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.3 - Audience ClaimStrings `json:"aud,omitempty"` - - // the `exp` (Expiration Time) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4 - ExpiresAt *NumericDate `json:"exp,omitempty"` - - // the `nbf` (Not Before) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.5 - NotBefore *NumericDate `json:"nbf,omitempty"` - - // the `iat` (Issued At) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.6 - IssuedAt *NumericDate `json:"iat,omitempty"` - - // the `jti` (JWT ID) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.7 - ID string `json:"jti,omitempty"` -} - -// Valid validates time based claims "exp, iat, nbf". -// There is no accounting for clock skew. -// As well, if any of the above claims are not in the token, it will still -// be considered a valid claim. -func (c RegisteredClaims) Valid() error { - vErr := new(ValidationError) - now := TimeFunc() - - // The claims below are optional, by default, so if they are set to the - // default value in Go, let's not fail the verification for them. - if !c.VerifyExpiresAt(now, false) { - delta := now.Sub(c.ExpiresAt.Time) - vErr.Inner = fmt.Errorf("token is expired by %v", delta) - vErr.Errors |= ValidationErrorExpired - } - - if !c.VerifyIssuedAt(now, false) { - vErr.Inner = fmt.Errorf("token used before issued") - vErr.Errors |= ValidationErrorIssuedAt - } - - if !c.VerifyNotBefore(now, false) { - vErr.Inner = fmt.Errorf("token is not valid yet") - vErr.Errors |= ValidationErrorNotValidYet - } - - if vErr.valid() { - return nil - } - - return vErr -} - -// VerifyAudience compares the aud claim against cmp. -// If required is false, this method will return true if the value matches or is unset -func (c *RegisteredClaims) VerifyAudience(cmp string, req bool) bool { - return verifyAud(c.Audience, cmp, req) -} - -// VerifyExpiresAt compares the exp claim against cmp (cmp < exp). -// If req is false, it will return true, if exp is unset. -func (c *RegisteredClaims) VerifyExpiresAt(cmp time.Time, req bool) bool { - if c.ExpiresAt == nil { - return verifyExp(nil, cmp, req) - } - - return verifyExp(&c.ExpiresAt.Time, cmp, req) -} - -// VerifyIssuedAt compares the iat claim against cmp (cmp >= iat). -// If req is false, it will return true, if iat is unset. -func (c *RegisteredClaims) VerifyIssuedAt(cmp time.Time, req bool) bool { - if c.IssuedAt == nil { - return verifyIat(nil, cmp, req) - } - - return verifyIat(&c.IssuedAt.Time, cmp, req) -} - -// VerifyNotBefore compares the nbf claim against cmp (cmp >= nbf). -// If req is false, it will return true, if nbf is unset. -func (c *RegisteredClaims) VerifyNotBefore(cmp time.Time, req bool) bool { - if c.NotBefore == nil { - return verifyNbf(nil, cmp, req) - } - - return verifyNbf(&c.NotBefore.Time, cmp, req) -} - -// VerifyIssuer compares the iss claim against cmp. -// If required is false, this method will return true if the value matches or is unset -func (c *RegisteredClaims) VerifyIssuer(cmp string, req bool) bool { - return verifyIss(c.Issuer, cmp, req) -} - -// StandardClaims are a structured version of the JWT Claims Set, as referenced at -// https://datatracker.ietf.org/doc/html/rfc7519#section-4. They do not follow the -// specification exactly, since they were based on an earlier draft of the -// specification and not updated. The main difference is that they only -// support integer-based date fields and singular audiences. This might lead to -// incompatibilities with other JWT implementations. The use of this is discouraged, instead -// the newer RegisteredClaims struct should be used. -// -// Deprecated: Use RegisteredClaims instead for a forward-compatible way to access registered claims in a struct. -type StandardClaims struct { - Audience string `json:"aud,omitempty"` - ExpiresAt int64 `json:"exp,omitempty"` - Id string `json:"jti,omitempty"` - IssuedAt int64 `json:"iat,omitempty"` - Issuer string `json:"iss,omitempty"` - NotBefore int64 `json:"nbf,omitempty"` - Subject string `json:"sub,omitempty"` -} - -// Valid validates time based claims "exp, iat, nbf". There is no accounting for clock skew. -// As well, if any of the above claims are not in the token, it will still -// be considered a valid claim. -func (c StandardClaims) Valid() error { - vErr := new(ValidationError) - now := TimeFunc().Unix() - - // The claims below are optional, by default, so if they are set to the - // default value in Go, let's not fail the verification for them. - if !c.VerifyExpiresAt(now, false) { - delta := time.Unix(now, 0).Sub(time.Unix(c.ExpiresAt, 0)) - vErr.Inner = fmt.Errorf("token is expired by %v", delta) - vErr.Errors |= ValidationErrorExpired - } - - if !c.VerifyIssuedAt(now, false) { - vErr.Inner = fmt.Errorf("token used before issued") - vErr.Errors |= ValidationErrorIssuedAt - } - - if !c.VerifyNotBefore(now, false) { - vErr.Inner = fmt.Errorf("token is not valid yet") - vErr.Errors |= ValidationErrorNotValidYet - } - - if vErr.valid() { - return nil - } - - return vErr -} - -// VerifyAudience compares the aud claim against cmp. -// If required is false, this method will return true if the value matches or is unset -func (c *StandardClaims) VerifyAudience(cmp string, req bool) bool { - return verifyAud([]string{c.Audience}, cmp, req) -} - -// VerifyExpiresAt compares the exp claim against cmp (cmp < exp). -// If req is false, it will return true, if exp is unset. -func (c *StandardClaims) VerifyExpiresAt(cmp int64, req bool) bool { - if c.ExpiresAt == 0 { - return verifyExp(nil, time.Unix(cmp, 0), req) - } - - t := time.Unix(c.ExpiresAt, 0) - return verifyExp(&t, time.Unix(cmp, 0), req) -} - -// VerifyIssuedAt compares the iat claim against cmp (cmp >= iat). -// If req is false, it will return true, if iat is unset. -func (c *StandardClaims) VerifyIssuedAt(cmp int64, req bool) bool { - if c.IssuedAt == 0 { - return verifyIat(nil, time.Unix(cmp, 0), req) - } - - t := time.Unix(c.IssuedAt, 0) - return verifyIat(&t, time.Unix(cmp, 0), req) -} - -// VerifyNotBefore compares the nbf claim against cmp (cmp >= nbf). -// If req is false, it will return true, if nbf is unset. -func (c *StandardClaims) VerifyNotBefore(cmp int64, req bool) bool { - if c.NotBefore == 0 { - return verifyNbf(nil, time.Unix(cmp, 0), req) - } - - t := time.Unix(c.NotBefore, 0) - return verifyNbf(&t, time.Unix(cmp, 0), req) -} - -// VerifyIssuer compares the iss claim against cmp. -// If required is false, this method will return true if the value matches or is unset -func (c *StandardClaims) VerifyIssuer(cmp string, req bool) bool { - return verifyIss(c.Issuer, cmp, req) -} - -// ----- helpers - -func verifyAud(aud []string, cmp string, required bool) bool { - if len(aud) == 0 { - return !required - } - // use a var here to keep constant time compare when looping over a number of claims - result := false - - var stringClaims string - for _, a := range aud { - if subtle.ConstantTimeCompare([]byte(a), []byte(cmp)) != 0 { - result = true - } - stringClaims = stringClaims + a - } - - // case where "" is sent in one or many aud claims - if len(stringClaims) == 0 { - return !required - } - - return result -} - -func verifyExp(exp *time.Time, now time.Time, required bool) bool { - if exp == nil { - return !required - } - return now.Before(*exp) -} - -func verifyIat(iat *time.Time, now time.Time, required bool) bool { - if iat == nil { - return !required - } - return now.After(*iat) || now.Equal(*iat) -} - -func verifyNbf(nbf *time.Time, now time.Time, required bool) bool { - if nbf == nil { - return !required - } - return now.After(*nbf) || now.Equal(*nbf) -} - -func verifyIss(iss string, cmp string, required bool) bool { - if iss == "" { - return !required - } - if subtle.ConstantTimeCompare([]byte(iss), []byte(cmp)) != 0 { - return true - } else { - return false - } -} diff --git a/vendor/github.com/golang-jwt/jwt/v4/doc.go b/vendor/github.com/golang-jwt/jwt/v4/doc.go deleted file mode 100644 index a86dc1a3b3..0000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/doc.go +++ /dev/null @@ -1,4 +0,0 @@ -// Package jwt is a Go implementation of JSON Web Tokens: http://self-issued.info/docs/draft-jones-json-web-token.html -// -// See README.md for more info. -package jwt diff --git a/vendor/github.com/golang-jwt/jwt/v4/ecdsa.go b/vendor/github.com/golang-jwt/jwt/v4/ecdsa.go deleted file mode 100644 index eac023fc6c..0000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/ecdsa.go +++ /dev/null @@ -1,142 +0,0 @@ -package jwt - -import ( - "crypto" - "crypto/ecdsa" - "crypto/rand" - "errors" - "math/big" -) - -var ( - // Sadly this is missing from crypto/ecdsa compared to crypto/rsa - ErrECDSAVerification = errors.New("crypto/ecdsa: verification error") -) - -// SigningMethodECDSA implements the ECDSA family of signing methods. -// Expects *ecdsa.PrivateKey for signing and *ecdsa.PublicKey for verification -type SigningMethodECDSA struct { - Name string - Hash crypto.Hash - KeySize int - CurveBits int -} - -// Specific instances for EC256 and company -var ( - SigningMethodES256 *SigningMethodECDSA - SigningMethodES384 *SigningMethodECDSA - SigningMethodES512 *SigningMethodECDSA -) - -func init() { - // ES256 - SigningMethodES256 = &SigningMethodECDSA{"ES256", crypto.SHA256, 32, 256} - RegisterSigningMethod(SigningMethodES256.Alg(), func() SigningMethod { - return SigningMethodES256 - }) - - // ES384 - SigningMethodES384 = &SigningMethodECDSA{"ES384", crypto.SHA384, 48, 384} - RegisterSigningMethod(SigningMethodES384.Alg(), func() SigningMethod { - return SigningMethodES384 - }) - - // ES512 - SigningMethodES512 = &SigningMethodECDSA{"ES512", crypto.SHA512, 66, 521} - RegisterSigningMethod(SigningMethodES512.Alg(), func() SigningMethod { - return SigningMethodES512 - }) -} - -func (m *SigningMethodECDSA) Alg() string { - return m.Name -} - -// Verify implements token verification for the SigningMethod. -// For this verify method, key must be an ecdsa.PublicKey struct -func (m *SigningMethodECDSA) Verify(signingString, signature string, key interface{}) error { - var err error - - // Decode the signature - var sig []byte - if sig, err = DecodeSegment(signature); err != nil { - return err - } - - // Get the key - var ecdsaKey *ecdsa.PublicKey - switch k := key.(type) { - case *ecdsa.PublicKey: - ecdsaKey = k - default: - return ErrInvalidKeyType - } - - if len(sig) != 2*m.KeySize { - return ErrECDSAVerification - } - - r := big.NewInt(0).SetBytes(sig[:m.KeySize]) - s := big.NewInt(0).SetBytes(sig[m.KeySize:]) - - // Create hasher - if !m.Hash.Available() { - return ErrHashUnavailable - } - hasher := m.Hash.New() - hasher.Write([]byte(signingString)) - - // Verify the signature - if verifystatus := ecdsa.Verify(ecdsaKey, hasher.Sum(nil), r, s); verifystatus { - return nil - } - - return ErrECDSAVerification -} - -// Sign implements token signing for the SigningMethod. -// For this signing method, key must be an ecdsa.PrivateKey struct -func (m *SigningMethodECDSA) Sign(signingString string, key interface{}) (string, error) { - // Get the key - var ecdsaKey *ecdsa.PrivateKey - switch k := key.(type) { - case *ecdsa.PrivateKey: - ecdsaKey = k - default: - return "", ErrInvalidKeyType - } - - // Create the hasher - if !m.Hash.Available() { - return "", ErrHashUnavailable - } - - hasher := m.Hash.New() - hasher.Write([]byte(signingString)) - - // Sign the string and return r, s - if r, s, err := ecdsa.Sign(rand.Reader, ecdsaKey, hasher.Sum(nil)); err == nil { - curveBits := ecdsaKey.Curve.Params().BitSize - - if m.CurveBits != curveBits { - return "", ErrInvalidKey - } - - keyBytes := curveBits / 8 - if curveBits%8 > 0 { - keyBytes += 1 - } - - // We serialize the outputs (r and s) into big-endian byte arrays - // padded with zeros on the left to make sure the sizes work out. - // Output must be 2*keyBytes long. - out := make([]byte, 2*keyBytes) - r.FillBytes(out[0:keyBytes]) // r is assigned to the first half of output. - s.FillBytes(out[keyBytes:]) // s is assigned to the second half of output. - - return EncodeSegment(out), nil - } else { - return "", err - } -} diff --git a/vendor/github.com/golang-jwt/jwt/v4/ecdsa_utils.go b/vendor/github.com/golang-jwt/jwt/v4/ecdsa_utils.go deleted file mode 100644 index 5700636d35..0000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/ecdsa_utils.go +++ /dev/null @@ -1,69 +0,0 @@ -package jwt - -import ( - "crypto/ecdsa" - "crypto/x509" - "encoding/pem" - "errors" -) - -var ( - ErrNotECPublicKey = errors.New("key is not a valid ECDSA public key") - ErrNotECPrivateKey = errors.New("key is not a valid ECDSA private key") -) - -// ParseECPrivateKeyFromPEM parses a PEM encoded Elliptic Curve Private Key Structure -func ParseECPrivateKeyFromPEM(key []byte) (*ecdsa.PrivateKey, error) { - var err error - - // Parse PEM block - var block *pem.Block - if block, _ = pem.Decode(key); block == nil { - return nil, ErrKeyMustBePEMEncoded - } - - // Parse the key - var parsedKey interface{} - if parsedKey, err = x509.ParseECPrivateKey(block.Bytes); err != nil { - if parsedKey, err = x509.ParsePKCS8PrivateKey(block.Bytes); err != nil { - return nil, err - } - } - - var pkey *ecdsa.PrivateKey - var ok bool - if pkey, ok = parsedKey.(*ecdsa.PrivateKey); !ok { - return nil, ErrNotECPrivateKey - } - - return pkey, nil -} - -// ParseECPublicKeyFromPEM parses a PEM encoded PKCS1 or PKCS8 public key -func ParseECPublicKeyFromPEM(key []byte) (*ecdsa.PublicKey, error) { - var err error - - // Parse PEM block - var block *pem.Block - if block, _ = pem.Decode(key); block == nil { - return nil, ErrKeyMustBePEMEncoded - } - - // Parse the key - var parsedKey interface{} - if parsedKey, err = x509.ParsePKIXPublicKey(block.Bytes); err != nil { - if cert, err := x509.ParseCertificate(block.Bytes); err == nil { - parsedKey = cert.PublicKey - } else { - return nil, err - } - } - - var pkey *ecdsa.PublicKey - var ok bool - if pkey, ok = parsedKey.(*ecdsa.PublicKey); !ok { - return nil, ErrNotECPublicKey - } - - return pkey, nil -} diff --git a/vendor/github.com/golang-jwt/jwt/v4/ed25519.go b/vendor/github.com/golang-jwt/jwt/v4/ed25519.go deleted file mode 100644 index 07d3aacd63..0000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/ed25519.go +++ /dev/null @@ -1,85 +0,0 @@ -package jwt - -import ( - "errors" - - "crypto" - "crypto/ed25519" - "crypto/rand" -) - -var ( - ErrEd25519Verification = errors.New("ed25519: verification error") -) - -// SigningMethodEd25519 implements the EdDSA family. -// Expects ed25519.PrivateKey for signing and ed25519.PublicKey for verification -type SigningMethodEd25519 struct{} - -// Specific instance for EdDSA -var ( - SigningMethodEdDSA *SigningMethodEd25519 -) - -func init() { - SigningMethodEdDSA = &SigningMethodEd25519{} - RegisterSigningMethod(SigningMethodEdDSA.Alg(), func() SigningMethod { - return SigningMethodEdDSA - }) -} - -func (m *SigningMethodEd25519) Alg() string { - return "EdDSA" -} - -// Verify implements token verification for the SigningMethod. -// For this verify method, key must be an ed25519.PublicKey -func (m *SigningMethodEd25519) Verify(signingString, signature string, key interface{}) error { - var err error - var ed25519Key ed25519.PublicKey - var ok bool - - if ed25519Key, ok = key.(ed25519.PublicKey); !ok { - return ErrInvalidKeyType - } - - if len(ed25519Key) != ed25519.PublicKeySize { - return ErrInvalidKey - } - - // Decode the signature - var sig []byte - if sig, err = DecodeSegment(signature); err != nil { - return err - } - - // Verify the signature - if !ed25519.Verify(ed25519Key, []byte(signingString), sig) { - return ErrEd25519Verification - } - - return nil -} - -// Sign implements token signing for the SigningMethod. -// For this signing method, key must be an ed25519.PrivateKey -func (m *SigningMethodEd25519) Sign(signingString string, key interface{}) (string, error) { - var ed25519Key crypto.Signer - var ok bool - - if ed25519Key, ok = key.(crypto.Signer); !ok { - return "", ErrInvalidKeyType - } - - if _, ok := ed25519Key.Public().(ed25519.PublicKey); !ok { - return "", ErrInvalidKey - } - - // Sign the string and return the encoded result - // ed25519 performs a two-pass hash as part of its algorithm. Therefore, we need to pass a non-prehashed message into the Sign function, as indicated by crypto.Hash(0) - sig, err := ed25519Key.Sign(rand.Reader, []byte(signingString), crypto.Hash(0)) - if err != nil { - return "", err - } - return EncodeSegment(sig), nil -} diff --git a/vendor/github.com/golang-jwt/jwt/v4/ed25519_utils.go b/vendor/github.com/golang-jwt/jwt/v4/ed25519_utils.go deleted file mode 100644 index cdb5e68e87..0000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/ed25519_utils.go +++ /dev/null @@ -1,64 +0,0 @@ -package jwt - -import ( - "crypto" - "crypto/ed25519" - "crypto/x509" - "encoding/pem" - "errors" -) - -var ( - ErrNotEdPrivateKey = errors.New("key is not a valid Ed25519 private key") - ErrNotEdPublicKey = errors.New("key is not a valid Ed25519 public key") -) - -// ParseEdPrivateKeyFromPEM parses a PEM-encoded Edwards curve private key -func ParseEdPrivateKeyFromPEM(key []byte) (crypto.PrivateKey, error) { - var err error - - // Parse PEM block - var block *pem.Block - if block, _ = pem.Decode(key); block == nil { - return nil, ErrKeyMustBePEMEncoded - } - - // Parse the key - var parsedKey interface{} - if parsedKey, err = x509.ParsePKCS8PrivateKey(block.Bytes); err != nil { - return nil, err - } - - var pkey ed25519.PrivateKey - var ok bool - if pkey, ok = parsedKey.(ed25519.PrivateKey); !ok { - return nil, ErrNotEdPrivateKey - } - - return pkey, nil -} - -// ParseEdPublicKeyFromPEM parses a PEM-encoded Edwards curve public key -func ParseEdPublicKeyFromPEM(key []byte) (crypto.PublicKey, error) { - var err error - - // Parse PEM block - var block *pem.Block - if block, _ = pem.Decode(key); block == nil { - return nil, ErrKeyMustBePEMEncoded - } - - // Parse the key - var parsedKey interface{} - if parsedKey, err = x509.ParsePKIXPublicKey(block.Bytes); err != nil { - return nil, err - } - - var pkey ed25519.PublicKey - var ok bool - if pkey, ok = parsedKey.(ed25519.PublicKey); !ok { - return nil, ErrNotEdPublicKey - } - - return pkey, nil -} diff --git a/vendor/github.com/golang-jwt/jwt/v4/errors.go b/vendor/github.com/golang-jwt/jwt/v4/errors.go deleted file mode 100644 index b9d18e498e..0000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/errors.go +++ /dev/null @@ -1,64 +0,0 @@ -package jwt - -import ( - "errors" -) - -// Error constants -var ( - ErrInvalidKey = errors.New("key is invalid") - ErrInvalidKeyType = errors.New("key is of invalid type") - ErrHashUnavailable = errors.New("the requested hash function is unavailable") -) - -// The errors that might occur when parsing and validating a token -const ( - ValidationErrorMalformed uint32 = 1 << iota // Token is malformed - ValidationErrorUnverifiable // Token could not be verified because of signing problems - ValidationErrorSignatureInvalid // Signature validation failed - - // Standard Claim validation errors - ValidationErrorAudience // AUD validation failed - ValidationErrorExpired // EXP validation failed - ValidationErrorIssuedAt // IAT validation failed - ValidationErrorIssuer // ISS validation failed - ValidationErrorNotValidYet // NBF validation failed - ValidationErrorId // JTI validation failed - ValidationErrorClaimsInvalid // Generic claims validation error -) - -// NewValidationError is a helper for constructing a ValidationError with a string error message -func NewValidationError(errorText string, errorFlags uint32) *ValidationError { - return &ValidationError{ - text: errorText, - Errors: errorFlags, - } -} - -// ValidationError represents an error from Parse if token is not valid -type ValidationError struct { - Inner error // stores the error returned by external dependencies, i.e.: KeyFunc - Errors uint32 // bitfield. see ValidationError... constants - text string // errors that do not have a valid error just have text -} - -// Error is the implementation of the err interface. -func (e ValidationError) Error() string { - if e.Inner != nil { - return e.Inner.Error() - } else if e.text != "" { - return e.text - } else { - return "token is invalid" - } -} - -// Unwrap gives errors.Is and errors.As access to the inner error. -func (e *ValidationError) Unwrap() error { - return e.Inner -} - -// No errors -func (e *ValidationError) valid() bool { - return e.Errors == 0 -} diff --git a/vendor/github.com/golang-jwt/jwt/v4/hmac.go b/vendor/github.com/golang-jwt/jwt/v4/hmac.go deleted file mode 100644 index 011f68a274..0000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/hmac.go +++ /dev/null @@ -1,95 +0,0 @@ -package jwt - -import ( - "crypto" - "crypto/hmac" - "errors" -) - -// SigningMethodHMAC implements the HMAC-SHA family of signing methods. -// Expects key type of []byte for both signing and validation -type SigningMethodHMAC struct { - Name string - Hash crypto.Hash -} - -// Specific instances for HS256 and company -var ( - SigningMethodHS256 *SigningMethodHMAC - SigningMethodHS384 *SigningMethodHMAC - SigningMethodHS512 *SigningMethodHMAC - ErrSignatureInvalid = errors.New("signature is invalid") -) - -func init() { - // HS256 - SigningMethodHS256 = &SigningMethodHMAC{"HS256", crypto.SHA256} - RegisterSigningMethod(SigningMethodHS256.Alg(), func() SigningMethod { - return SigningMethodHS256 - }) - - // HS384 - SigningMethodHS384 = &SigningMethodHMAC{"HS384", crypto.SHA384} - RegisterSigningMethod(SigningMethodHS384.Alg(), func() SigningMethod { - return SigningMethodHS384 - }) - - // HS512 - SigningMethodHS512 = &SigningMethodHMAC{"HS512", crypto.SHA512} - RegisterSigningMethod(SigningMethodHS512.Alg(), func() SigningMethod { - return SigningMethodHS512 - }) -} - -func (m *SigningMethodHMAC) Alg() string { - return m.Name -} - -// Verify implements token verification for the SigningMethod. Returns nil if the signature is valid. -func (m *SigningMethodHMAC) Verify(signingString, signature string, key interface{}) error { - // Verify the key is the right type - keyBytes, ok := key.([]byte) - if !ok { - return ErrInvalidKeyType - } - - // Decode signature, for comparison - sig, err := DecodeSegment(signature) - if err != nil { - return err - } - - // Can we use the specified hashing method? - if !m.Hash.Available() { - return ErrHashUnavailable - } - - // This signing method is symmetric, so we validate the signature - // by reproducing the signature from the signing string and key, then - // comparing that against the provided signature. - hasher := hmac.New(m.Hash.New, keyBytes) - hasher.Write([]byte(signingString)) - if !hmac.Equal(sig, hasher.Sum(nil)) { - return ErrSignatureInvalid - } - - // No validation errors. Signature is good. - return nil -} - -// Sign implements token signing for the SigningMethod. -// Key must be []byte -func (m *SigningMethodHMAC) Sign(signingString string, key interface{}) (string, error) { - if keyBytes, ok := key.([]byte); ok { - if !m.Hash.Available() { - return "", ErrHashUnavailable - } - - hasher := hmac.New(m.Hash.New, keyBytes) - hasher.Write([]byte(signingString)) - - return EncodeSegment(hasher.Sum(nil)), nil - } - - return "", ErrInvalidKeyType -} diff --git a/vendor/github.com/golang-jwt/jwt/v4/map_claims.go b/vendor/github.com/golang-jwt/jwt/v4/map_claims.go deleted file mode 100644 index e7da633b93..0000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/map_claims.go +++ /dev/null @@ -1,148 +0,0 @@ -package jwt - -import ( - "encoding/json" - "errors" - "time" - // "fmt" -) - -// MapClaims is a claims type that uses the map[string]interface{} for JSON decoding. -// This is the default claims type if you don't supply one -type MapClaims map[string]interface{} - -// VerifyAudience Compares the aud claim against cmp. -// If required is false, this method will return true if the value matches or is unset -func (m MapClaims) VerifyAudience(cmp string, req bool) bool { - var aud []string - switch v := m["aud"].(type) { - case string: - aud = append(aud, v) - case []string: - aud = v - case []interface{}: - for _, a := range v { - vs, ok := a.(string) - if !ok { - return false - } - aud = append(aud, vs) - } - } - return verifyAud(aud, cmp, req) -} - -// VerifyExpiresAt compares the exp claim against cmp (cmp <= exp). -// If req is false, it will return true, if exp is unset. -func (m MapClaims) VerifyExpiresAt(cmp int64, req bool) bool { - cmpTime := time.Unix(cmp, 0) - - v, ok := m["exp"] - if !ok { - return !req - } - - switch exp := v.(type) { - case float64: - if exp == 0 { - return verifyExp(nil, cmpTime, req) - } - - return verifyExp(&newNumericDateFromSeconds(exp).Time, cmpTime, req) - case json.Number: - v, _ := exp.Float64() - - return verifyExp(&newNumericDateFromSeconds(v).Time, cmpTime, req) - } - - return false -} - -// VerifyIssuedAt compares the exp claim against cmp (cmp >= iat). -// If req is false, it will return true, if iat is unset. -func (m MapClaims) VerifyIssuedAt(cmp int64, req bool) bool { - cmpTime := time.Unix(cmp, 0) - - v, ok := m["iat"] - if !ok { - return !req - } - - switch iat := v.(type) { - case float64: - if iat == 0 { - return verifyIat(nil, cmpTime, req) - } - - return verifyIat(&newNumericDateFromSeconds(iat).Time, cmpTime, req) - case json.Number: - v, _ := iat.Float64() - - return verifyIat(&newNumericDateFromSeconds(v).Time, cmpTime, req) - } - - return false -} - -// VerifyNotBefore compares the nbf claim against cmp (cmp >= nbf). -// If req is false, it will return true, if nbf is unset. -func (m MapClaims) VerifyNotBefore(cmp int64, req bool) bool { - cmpTime := time.Unix(cmp, 0) - - v, ok := m["nbf"] - if !ok { - return !req - } - - switch nbf := v.(type) { - case float64: - if nbf == 0 { - return verifyNbf(nil, cmpTime, req) - } - - return verifyNbf(&newNumericDateFromSeconds(nbf).Time, cmpTime, req) - case json.Number: - v, _ := nbf.Float64() - - return verifyNbf(&newNumericDateFromSeconds(v).Time, cmpTime, req) - } - - return false -} - -// VerifyIssuer compares the iss claim against cmp. -// If required is false, this method will return true if the value matches or is unset -func (m MapClaims) VerifyIssuer(cmp string, req bool) bool { - iss, _ := m["iss"].(string) - return verifyIss(iss, cmp, req) -} - -// Valid validates time based claims "exp, iat, nbf". -// There is no accounting for clock skew. -// As well, if any of the above claims are not in the token, it will still -// be considered a valid claim. -func (m MapClaims) Valid() error { - vErr := new(ValidationError) - now := TimeFunc().Unix() - - if !m.VerifyExpiresAt(now, false) { - vErr.Inner = errors.New("Token is expired") - vErr.Errors |= ValidationErrorExpired - } - - if !m.VerifyIssuedAt(now, false) { - vErr.Inner = errors.New("Token used before issued") - vErr.Errors |= ValidationErrorIssuedAt - } - - if !m.VerifyNotBefore(now, false) { - vErr.Inner = errors.New("Token is not valid yet") - vErr.Errors |= ValidationErrorNotValidYet - } - - if vErr.valid() { - return nil - } - - return vErr -} diff --git a/vendor/github.com/golang-jwt/jwt/v4/none.go b/vendor/github.com/golang-jwt/jwt/v4/none.go deleted file mode 100644 index f19835d207..0000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/none.go +++ /dev/null @@ -1,52 +0,0 @@ -package jwt - -// SigningMethodNone implements the none signing method. This is required by the spec -// but you probably should never use it. -var SigningMethodNone *signingMethodNone - -const UnsafeAllowNoneSignatureType unsafeNoneMagicConstant = "none signing method allowed" - -var NoneSignatureTypeDisallowedError error - -type signingMethodNone struct{} -type unsafeNoneMagicConstant string - -func init() { - SigningMethodNone = &signingMethodNone{} - NoneSignatureTypeDisallowedError = NewValidationError("'none' signature type is not allowed", ValidationErrorSignatureInvalid) - - RegisterSigningMethod(SigningMethodNone.Alg(), func() SigningMethod { - return SigningMethodNone - }) -} - -func (m *signingMethodNone) Alg() string { - return "none" -} - -// Only allow 'none' alg type if UnsafeAllowNoneSignatureType is specified as the key -func (m *signingMethodNone) Verify(signingString, signature string, key interface{}) (err error) { - // Key must be UnsafeAllowNoneSignatureType to prevent accidentally - // accepting 'none' signing method - if _, ok := key.(unsafeNoneMagicConstant); !ok { - return NoneSignatureTypeDisallowedError - } - // If signing method is none, signature must be an empty string - if signature != "" { - return NewValidationError( - "'none' signing method with non-empty signature", - ValidationErrorSignatureInvalid, - ) - } - - // Accept 'none' signing method. - return nil -} - -// Only allow 'none' signing if UnsafeAllowNoneSignatureType is specified as the key -func (m *signingMethodNone) Sign(signingString string, key interface{}) (string, error) { - if _, ok := key.(unsafeNoneMagicConstant); ok { - return "", nil - } - return "", NoneSignatureTypeDisallowedError -} diff --git a/vendor/github.com/golang-jwt/jwt/v4/parser.go b/vendor/github.com/golang-jwt/jwt/v4/parser.go deleted file mode 100644 index 2f61a69d7f..0000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/parser.go +++ /dev/null @@ -1,170 +0,0 @@ -package jwt - -import ( - "bytes" - "encoding/json" - "fmt" - "strings" -) - -type Parser struct { - // If populated, only these methods will be considered valid. - // - // Deprecated: In future releases, this field will not be exported anymore and should be set with an option to NewParser instead. - ValidMethods []string - - // Use JSON Number format in JSON decoder. - // - // Deprecated: In future releases, this field will not be exported anymore and should be set with an option to NewParser instead. - UseJSONNumber bool - - // Skip claims validation during token parsing. - // - // Deprecated: In future releases, this field will not be exported anymore and should be set with an option to NewParser instead. - SkipClaimsValidation bool -} - -// NewParser creates a new Parser with the specified options -func NewParser(options ...ParserOption) *Parser { - p := &Parser{} - - // loop through our parsing options and apply them - for _, option := range options { - option(p) - } - - return p -} - -// Parse parses, validates, verifies the signature and returns the parsed token. -// keyFunc will receive the parsed token and should return the key for validating. -func (p *Parser) Parse(tokenString string, keyFunc Keyfunc) (*Token, error) { - return p.ParseWithClaims(tokenString, MapClaims{}, keyFunc) -} - -func (p *Parser) ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token, error) { - token, parts, err := p.ParseUnverified(tokenString, claims) - if err != nil { - return token, err - } - - // Verify signing method is in the required set - if p.ValidMethods != nil { - var signingMethodValid = false - var alg = token.Method.Alg() - for _, m := range p.ValidMethods { - if m == alg { - signingMethodValid = true - break - } - } - if !signingMethodValid { - // signing method is not in the listed set - return token, NewValidationError(fmt.Sprintf("signing method %v is invalid", alg), ValidationErrorSignatureInvalid) - } - } - - // Lookup key - var key interface{} - if keyFunc == nil { - // keyFunc was not provided. short circuiting validation - return token, NewValidationError("no Keyfunc was provided.", ValidationErrorUnverifiable) - } - if key, err = keyFunc(token); err != nil { - // keyFunc returned an error - if ve, ok := err.(*ValidationError); ok { - return token, ve - } - return token, &ValidationError{Inner: err, Errors: ValidationErrorUnverifiable} - } - - vErr := &ValidationError{} - - // Validate Claims - if !p.SkipClaimsValidation { - if err := token.Claims.Valid(); err != nil { - - // If the Claims Valid returned an error, check if it is a validation error, - // If it was another error type, create a ValidationError with a generic ClaimsInvalid flag set - if e, ok := err.(*ValidationError); !ok { - vErr = &ValidationError{Inner: err, Errors: ValidationErrorClaimsInvalid} - } else { - vErr = e - } - } - } - - // Perform validation - token.Signature = parts[2] - if err = token.Method.Verify(strings.Join(parts[0:2], "."), token.Signature, key); err != nil { - vErr.Inner = err - vErr.Errors |= ValidationErrorSignatureInvalid - } - - if vErr.valid() { - token.Valid = true - return token, nil - } - - return token, vErr -} - -// ParseUnverified parses the token but doesn't validate the signature. -// -// WARNING: Don't use this method unless you know what you're doing. -// -// It's only ever useful in cases where you know the signature is valid (because it has -// been checked previously in the stack) and you want to extract values from it. -func (p *Parser) ParseUnverified(tokenString string, claims Claims) (token *Token, parts []string, err error) { - parts = strings.Split(tokenString, ".") - if len(parts) != 3 { - return nil, parts, NewValidationError("token contains an invalid number of segments", ValidationErrorMalformed) - } - - token = &Token{Raw: tokenString} - - // parse Header - var headerBytes []byte - if headerBytes, err = DecodeSegment(parts[0]); err != nil { - if strings.HasPrefix(strings.ToLower(tokenString), "bearer ") { - return token, parts, NewValidationError("tokenstring should not contain 'bearer '", ValidationErrorMalformed) - } - return token, parts, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} - } - if err = json.Unmarshal(headerBytes, &token.Header); err != nil { - return token, parts, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} - } - - // parse Claims - var claimBytes []byte - token.Claims = claims - - if claimBytes, err = DecodeSegment(parts[1]); err != nil { - return token, parts, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} - } - dec := json.NewDecoder(bytes.NewBuffer(claimBytes)) - if p.UseJSONNumber { - dec.UseNumber() - } - // JSON Decode. Special case for map type to avoid weird pointer behavior - if c, ok := token.Claims.(MapClaims); ok { - err = dec.Decode(&c) - } else { - err = dec.Decode(&claims) - } - // Handle decode error - if err != nil { - return token, parts, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} - } - - // Lookup signature method - if method, ok := token.Header["alg"].(string); ok { - if token.Method = GetSigningMethod(method); token.Method == nil { - return token, parts, NewValidationError("signing method (alg) is unavailable.", ValidationErrorUnverifiable) - } - } else { - return token, parts, NewValidationError("signing method (alg) is unspecified.", ValidationErrorUnverifiable) - } - - return token, parts, nil -} diff --git a/vendor/github.com/golang-jwt/jwt/v4/parser_option.go b/vendor/github.com/golang-jwt/jwt/v4/parser_option.go deleted file mode 100644 index 0fede4f15c..0000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/parser_option.go +++ /dev/null @@ -1,29 +0,0 @@ -package jwt - -// ParserOption is used to implement functional-style options that modify the behaviour of the parser. To add -// new options, just create a function (ideally beginning with With or Without) that returns an anonymous function that -// takes a *Parser type as input and manipulates its configuration accordingly. -type ParserOption func(*Parser) - -// WithValidMethods is an option to supply algorithm methods that the parser will check. Only those methods will be considered valid. -// It is heavily encouraged to use this option in order to prevent attacks such as https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/. -func WithValidMethods(methods []string) ParserOption { - return func(p *Parser) { - p.ValidMethods = methods - } -} - -// WithJSONNumber is an option to configure the underyling JSON parser with UseNumber -func WithJSONNumber() ParserOption { - return func(p *Parser) { - p.UseJSONNumber = true - } -} - -// WithoutClaimsValidation is an option to disable claims validation. This option should only be used if you exactly know -// what you are doing. -func WithoutClaimsValidation() ParserOption { - return func(p *Parser) { - p.SkipClaimsValidation = true - } -} diff --git a/vendor/github.com/golang-jwt/jwt/v4/rsa.go b/vendor/github.com/golang-jwt/jwt/v4/rsa.go deleted file mode 100644 index b910b19c0b..0000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/rsa.go +++ /dev/null @@ -1,101 +0,0 @@ -package jwt - -import ( - "crypto" - "crypto/rand" - "crypto/rsa" -) - -// SigningMethodRSA implements the RSA family of signing methods. -// Expects *rsa.PrivateKey for signing and *rsa.PublicKey for validation -type SigningMethodRSA struct { - Name string - Hash crypto.Hash -} - -// Specific instances for RS256 and company -var ( - SigningMethodRS256 *SigningMethodRSA - SigningMethodRS384 *SigningMethodRSA - SigningMethodRS512 *SigningMethodRSA -) - -func init() { - // RS256 - SigningMethodRS256 = &SigningMethodRSA{"RS256", crypto.SHA256} - RegisterSigningMethod(SigningMethodRS256.Alg(), func() SigningMethod { - return SigningMethodRS256 - }) - - // RS384 - SigningMethodRS384 = &SigningMethodRSA{"RS384", crypto.SHA384} - RegisterSigningMethod(SigningMethodRS384.Alg(), func() SigningMethod { - return SigningMethodRS384 - }) - - // RS512 - SigningMethodRS512 = &SigningMethodRSA{"RS512", crypto.SHA512} - RegisterSigningMethod(SigningMethodRS512.Alg(), func() SigningMethod { - return SigningMethodRS512 - }) -} - -func (m *SigningMethodRSA) Alg() string { - return m.Name -} - -// Verify implements token verification for the SigningMethod -// For this signing method, must be an *rsa.PublicKey structure. -func (m *SigningMethodRSA) Verify(signingString, signature string, key interface{}) error { - var err error - - // Decode the signature - var sig []byte - if sig, err = DecodeSegment(signature); err != nil { - return err - } - - var rsaKey *rsa.PublicKey - var ok bool - - if rsaKey, ok = key.(*rsa.PublicKey); !ok { - return ErrInvalidKeyType - } - - // Create hasher - if !m.Hash.Available() { - return ErrHashUnavailable - } - hasher := m.Hash.New() - hasher.Write([]byte(signingString)) - - // Verify the signature - return rsa.VerifyPKCS1v15(rsaKey, m.Hash, hasher.Sum(nil), sig) -} - -// Sign implements token signing for the SigningMethod -// For this signing method, must be an *rsa.PrivateKey structure. -func (m *SigningMethodRSA) Sign(signingString string, key interface{}) (string, error) { - var rsaKey *rsa.PrivateKey - var ok bool - - // Validate type of key - if rsaKey, ok = key.(*rsa.PrivateKey); !ok { - return "", ErrInvalidKey - } - - // Create the hasher - if !m.Hash.Available() { - return "", ErrHashUnavailable - } - - hasher := m.Hash.New() - hasher.Write([]byte(signingString)) - - // Sign the string and return the encoded bytes - if sigBytes, err := rsa.SignPKCS1v15(rand.Reader, rsaKey, m.Hash, hasher.Sum(nil)); err == nil { - return EncodeSegment(sigBytes), nil - } else { - return "", err - } -} diff --git a/vendor/github.com/golang-jwt/jwt/v4/rsa_pss.go b/vendor/github.com/golang-jwt/jwt/v4/rsa_pss.go deleted file mode 100644 index 5a8502feb3..0000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/rsa_pss.go +++ /dev/null @@ -1,142 +0,0 @@ -// +build go1.4 - -package jwt - -import ( - "crypto" - "crypto/rand" - "crypto/rsa" -) - -// SigningMethodRSAPSS implements the RSAPSS family of signing methods signing methods -type SigningMethodRSAPSS struct { - *SigningMethodRSA - Options *rsa.PSSOptions - // VerifyOptions is optional. If set overrides Options for rsa.VerifyPPS. - // Used to accept tokens signed with rsa.PSSSaltLengthAuto, what doesn't follow - // https://tools.ietf.org/html/rfc7518#section-3.5 but was used previously. - // See https://github.com/dgrijalva/jwt-go/issues/285#issuecomment-437451244 for details. - VerifyOptions *rsa.PSSOptions -} - -// Specific instances for RS/PS and company. -var ( - SigningMethodPS256 *SigningMethodRSAPSS - SigningMethodPS384 *SigningMethodRSAPSS - SigningMethodPS512 *SigningMethodRSAPSS -) - -func init() { - // PS256 - SigningMethodPS256 = &SigningMethodRSAPSS{ - SigningMethodRSA: &SigningMethodRSA{ - Name: "PS256", - Hash: crypto.SHA256, - }, - Options: &rsa.PSSOptions{ - SaltLength: rsa.PSSSaltLengthEqualsHash, - }, - VerifyOptions: &rsa.PSSOptions{ - SaltLength: rsa.PSSSaltLengthAuto, - }, - } - RegisterSigningMethod(SigningMethodPS256.Alg(), func() SigningMethod { - return SigningMethodPS256 - }) - - // PS384 - SigningMethodPS384 = &SigningMethodRSAPSS{ - SigningMethodRSA: &SigningMethodRSA{ - Name: "PS384", - Hash: crypto.SHA384, - }, - Options: &rsa.PSSOptions{ - SaltLength: rsa.PSSSaltLengthEqualsHash, - }, - VerifyOptions: &rsa.PSSOptions{ - SaltLength: rsa.PSSSaltLengthAuto, - }, - } - RegisterSigningMethod(SigningMethodPS384.Alg(), func() SigningMethod { - return SigningMethodPS384 - }) - - // PS512 - SigningMethodPS512 = &SigningMethodRSAPSS{ - SigningMethodRSA: &SigningMethodRSA{ - Name: "PS512", - Hash: crypto.SHA512, - }, - Options: &rsa.PSSOptions{ - SaltLength: rsa.PSSSaltLengthEqualsHash, - }, - VerifyOptions: &rsa.PSSOptions{ - SaltLength: rsa.PSSSaltLengthAuto, - }, - } - RegisterSigningMethod(SigningMethodPS512.Alg(), func() SigningMethod { - return SigningMethodPS512 - }) -} - -// Verify implements token verification for the SigningMethod. -// For this verify method, key must be an rsa.PublicKey struct -func (m *SigningMethodRSAPSS) Verify(signingString, signature string, key interface{}) error { - var err error - - // Decode the signature - var sig []byte - if sig, err = DecodeSegment(signature); err != nil { - return err - } - - var rsaKey *rsa.PublicKey - switch k := key.(type) { - case *rsa.PublicKey: - rsaKey = k - default: - return ErrInvalidKey - } - - // Create hasher - if !m.Hash.Available() { - return ErrHashUnavailable - } - hasher := m.Hash.New() - hasher.Write([]byte(signingString)) - - opts := m.Options - if m.VerifyOptions != nil { - opts = m.VerifyOptions - } - - return rsa.VerifyPSS(rsaKey, m.Hash, hasher.Sum(nil), sig, opts) -} - -// Sign implements token signing for the SigningMethod. -// For this signing method, key must be an rsa.PrivateKey struct -func (m *SigningMethodRSAPSS) Sign(signingString string, key interface{}) (string, error) { - var rsaKey *rsa.PrivateKey - - switch k := key.(type) { - case *rsa.PrivateKey: - rsaKey = k - default: - return "", ErrInvalidKeyType - } - - // Create the hasher - if !m.Hash.Available() { - return "", ErrHashUnavailable - } - - hasher := m.Hash.New() - hasher.Write([]byte(signingString)) - - // Sign the string and return the encoded bytes - if sigBytes, err := rsa.SignPSS(rand.Reader, rsaKey, m.Hash, hasher.Sum(nil), m.Options); err == nil { - return EncodeSegment(sigBytes), nil - } else { - return "", err - } -} diff --git a/vendor/github.com/golang-jwt/jwt/v4/rsa_utils.go b/vendor/github.com/golang-jwt/jwt/v4/rsa_utils.go deleted file mode 100644 index 1966c450bf..0000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/rsa_utils.go +++ /dev/null @@ -1,105 +0,0 @@ -package jwt - -import ( - "crypto/rsa" - "crypto/x509" - "encoding/pem" - "errors" -) - -var ( - ErrKeyMustBePEMEncoded = errors.New("invalid key: Key must be a PEM encoded PKCS1 or PKCS8 key") - ErrNotRSAPrivateKey = errors.New("key is not a valid RSA private key") - ErrNotRSAPublicKey = errors.New("key is not a valid RSA public key") -) - -// ParseRSAPrivateKeyFromPEM parses a PEM encoded PKCS1 or PKCS8 private key -func ParseRSAPrivateKeyFromPEM(key []byte) (*rsa.PrivateKey, error) { - var err error - - // Parse PEM block - var block *pem.Block - if block, _ = pem.Decode(key); block == nil { - return nil, ErrKeyMustBePEMEncoded - } - - var parsedKey interface{} - if parsedKey, err = x509.ParsePKCS1PrivateKey(block.Bytes); err != nil { - if parsedKey, err = x509.ParsePKCS8PrivateKey(block.Bytes); err != nil { - return nil, err - } - } - - var pkey *rsa.PrivateKey - var ok bool - if pkey, ok = parsedKey.(*rsa.PrivateKey); !ok { - return nil, ErrNotRSAPrivateKey - } - - return pkey, nil -} - -// ParseRSAPrivateKeyFromPEMWithPassword parses a PEM encoded PKCS1 or PKCS8 private key protected with password -// -// Deprecated: This function is deprecated and should not be used anymore. It uses the deprecated x509.DecryptPEMBlock -// function, which was deprecated since RFC 1423 is regarded insecure by design. Unfortunately, there is no alternative -// in the Go standard library for now. See https://github.com/golang/go/issues/8860. -func ParseRSAPrivateKeyFromPEMWithPassword(key []byte, password string) (*rsa.PrivateKey, error) { - var err error - - // Parse PEM block - var block *pem.Block - if block, _ = pem.Decode(key); block == nil { - return nil, ErrKeyMustBePEMEncoded - } - - var parsedKey interface{} - - var blockDecrypted []byte - if blockDecrypted, err = x509.DecryptPEMBlock(block, []byte(password)); err != nil { - return nil, err - } - - if parsedKey, err = x509.ParsePKCS1PrivateKey(blockDecrypted); err != nil { - if parsedKey, err = x509.ParsePKCS8PrivateKey(blockDecrypted); err != nil { - return nil, err - } - } - - var pkey *rsa.PrivateKey - var ok bool - if pkey, ok = parsedKey.(*rsa.PrivateKey); !ok { - return nil, ErrNotRSAPrivateKey - } - - return pkey, nil -} - -// ParseRSAPublicKeyFromPEM parses a PEM encoded PKCS1 or PKCS8 public key -func ParseRSAPublicKeyFromPEM(key []byte) (*rsa.PublicKey, error) { - var err error - - // Parse PEM block - var block *pem.Block - if block, _ = pem.Decode(key); block == nil { - return nil, ErrKeyMustBePEMEncoded - } - - // Parse the key - var parsedKey interface{} - if parsedKey, err = x509.ParsePKIXPublicKey(block.Bytes); err != nil { - if cert, err := x509.ParseCertificate(block.Bytes); err == nil { - parsedKey = cert.PublicKey - } else { - return nil, err - } - } - - var pkey *rsa.PublicKey - var ok bool - if pkey, ok = parsedKey.(*rsa.PublicKey); !ok { - return nil, ErrNotRSAPublicKey - } - - return pkey, nil -} diff --git a/vendor/github.com/golang-jwt/jwt/v4/signing_method.go b/vendor/github.com/golang-jwt/jwt/v4/signing_method.go deleted file mode 100644 index 241ae9c60d..0000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/signing_method.go +++ /dev/null @@ -1,46 +0,0 @@ -package jwt - -import ( - "sync" -) - -var signingMethods = map[string]func() SigningMethod{} -var signingMethodLock = new(sync.RWMutex) - -// SigningMethod can be used add new methods for signing or verifying tokens. -type SigningMethod interface { - Verify(signingString, signature string, key interface{}) error // Returns nil if signature is valid - Sign(signingString string, key interface{}) (string, error) // Returns encoded signature or error - Alg() string // returns the alg identifier for this method (example: 'HS256') -} - -// RegisterSigningMethod registers the "alg" name and a factory function for signing method. -// This is typically done during init() in the method's implementation -func RegisterSigningMethod(alg string, f func() SigningMethod) { - signingMethodLock.Lock() - defer signingMethodLock.Unlock() - - signingMethods[alg] = f -} - -// GetSigningMethod retrieves a signing method from an "alg" string -func GetSigningMethod(alg string) (method SigningMethod) { - signingMethodLock.RLock() - defer signingMethodLock.RUnlock() - - if methodF, ok := signingMethods[alg]; ok { - method = methodF() - } - return -} - -// GetAlgorithms returns a list of registered "alg" names -func GetAlgorithms() (algs []string) { - signingMethodLock.RLock() - defer signingMethodLock.RUnlock() - - for alg := range signingMethods { - algs = append(algs, alg) - } - return -} diff --git a/vendor/github.com/golang-jwt/jwt/v4/staticcheck.conf b/vendor/github.com/golang-jwt/jwt/v4/staticcheck.conf deleted file mode 100644 index 53745d51d7..0000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/staticcheck.conf +++ /dev/null @@ -1 +0,0 @@ -checks = ["all", "-ST1000", "-ST1003", "-ST1016", "-ST1023"] diff --git a/vendor/github.com/golang-jwt/jwt/v4/token.go b/vendor/github.com/golang-jwt/jwt/v4/token.go deleted file mode 100644 index 12344138be..0000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/token.go +++ /dev/null @@ -1,131 +0,0 @@ -package jwt - -import ( - "encoding/base64" - "encoding/json" - "strings" - "time" -) - - -// DecodePaddingAllowed will switch the codec used for decoding JWTs respectively. Note that the JWS RFC7515 -// states that the tokens will utilize a Base64url encoding with no padding. Unfortunately, some implementations -// of JWT are producing non-standard tokens, and thus require support for decoding. Note that this is a global -// variable, and updating it will change the behavior on a package level, and is also NOT go-routine safe. -// To use the non-recommended decoding, set this boolean to `true` prior to using this package. -var DecodePaddingAllowed bool - -// TimeFunc provides the current time when parsing token to validate "exp" claim (expiration time). -// You can override it to use another time value. This is useful for testing or if your -// server uses a different time zone than your tokens. -var TimeFunc = time.Now - -// Keyfunc will be used by the Parse methods as a callback function to supply -// the key for verification. The function receives the parsed, -// but unverified Token. This allows you to use properties in the -// Header of the token (such as `kid`) to identify which key to use. -type Keyfunc func(*Token) (interface{}, error) - -// Token represents a JWT Token. Different fields will be used depending on whether you're -// creating or parsing/verifying a token. -type Token struct { - Raw string // The raw token. Populated when you Parse a token - Method SigningMethod // The signing method used or to be used - Header map[string]interface{} // The first segment of the token - Claims Claims // The second segment of the token - Signature string // The third segment of the token. Populated when you Parse a token - Valid bool // Is the token valid? Populated when you Parse/Verify a token -} - -// New creates a new Token with the specified signing method and an empty map of claims. -func New(method SigningMethod) *Token { - return NewWithClaims(method, MapClaims{}) -} - -// NewWithClaims creates a new Token with the specified signing method and claims. -func NewWithClaims(method SigningMethod, claims Claims) *Token { - return &Token{ - Header: map[string]interface{}{ - "typ": "JWT", - "alg": method.Alg(), - }, - Claims: claims, - Method: method, - } -} - -// SignedString creates and returns a complete, signed JWT. -// The token is signed using the SigningMethod specified in the token. -func (t *Token) SignedString(key interface{}) (string, error) { - var sig, sstr string - var err error - if sstr, err = t.SigningString(); err != nil { - return "", err - } - if sig, err = t.Method.Sign(sstr, key); err != nil { - return "", err - } - return strings.Join([]string{sstr, sig}, "."), nil -} - -// SigningString generates the signing string. This is the -// most expensive part of the whole deal. Unless you -// need this for something special, just go straight for -// the SignedString. -func (t *Token) SigningString() (string, error) { - var err error - parts := make([]string, 2) - for i := range parts { - var jsonValue []byte - if i == 0 { - if jsonValue, err = json.Marshal(t.Header); err != nil { - return "", err - } - } else { - if jsonValue, err = json.Marshal(t.Claims); err != nil { - return "", err - } - } - - parts[i] = EncodeSegment(jsonValue) - } - return strings.Join(parts, "."), nil -} - -// Parse parses, validates, verifies the signature and returns the parsed token. -// keyFunc will receive the parsed token and should return the cryptographic key -// for verifying the signature. -// The caller is strongly encouraged to set the WithValidMethods option to -// validate the 'alg' claim in the token matches the expected algorithm. -// For more details about the importance of validating the 'alg' claim, -// see https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/ -func Parse(tokenString string, keyFunc Keyfunc, options ...ParserOption) (*Token, error) { - return NewParser(options...).Parse(tokenString, keyFunc) -} - -func ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc, options ...ParserOption) (*Token, error) { - return NewParser(options...).ParseWithClaims(tokenString, claims, keyFunc) -} - -// EncodeSegment encodes a JWT specific base64url encoding with padding stripped -// -// Deprecated: In a future release, we will demote this function to a non-exported function, since it -// should only be used internally -func EncodeSegment(seg []byte) string { - return base64.RawURLEncoding.EncodeToString(seg) -} - -// DecodeSegment decodes a JWT specific base64url encoding with padding stripped -// -// Deprecated: In a future release, we will demote this function to a non-exported function, since it -// should only be used internally -func DecodeSegment(seg string) ([]byte, error) { - if DecodePaddingAllowed { - if l := len(seg) % 4; l > 0 { - seg += strings.Repeat("=", 4-l) - } - return base64.URLEncoding.DecodeString(seg) - } - - return base64.RawURLEncoding.DecodeString(seg) -} diff --git a/vendor/github.com/golang-jwt/jwt/v4/types.go b/vendor/github.com/golang-jwt/jwt/v4/types.go deleted file mode 100644 index 80b1b96948..0000000000 --- a/vendor/github.com/golang-jwt/jwt/v4/types.go +++ /dev/null @@ -1,127 +0,0 @@ -package jwt - -import ( - "encoding/json" - "fmt" - "math" - "reflect" - "strconv" - "time" -) - -// TimePrecision sets the precision of times and dates within this library. -// This has an influence on the precision of times when comparing expiry or -// other related time fields. Furthermore, it is also the precision of times -// when serializing. -// -// For backwards compatibility the default precision is set to seconds, so that -// no fractional timestamps are generated. -var TimePrecision = time.Second - -// MarshalSingleStringAsArray modifies the behaviour of the ClaimStrings type, especially -// its MarshalJSON function. -// -// If it is set to true (the default), it will always serialize the type as an -// array of strings, even if it just contains one element, defaulting to the behaviour -// of the underlying []string. If it is set to false, it will serialize to a single -// string, if it contains one element. Otherwise, it will serialize to an array of strings. -var MarshalSingleStringAsArray = true - -// NumericDate represents a JSON numeric date value, as referenced at -// https://datatracker.ietf.org/doc/html/rfc7519#section-2. -type NumericDate struct { - time.Time -} - -// NewNumericDate constructs a new *NumericDate from a standard library time.Time struct. -// It will truncate the timestamp according to the precision specified in TimePrecision. -func NewNumericDate(t time.Time) *NumericDate { - return &NumericDate{t.Truncate(TimePrecision)} -} - -// newNumericDateFromSeconds creates a new *NumericDate out of a float64 representing a -// UNIX epoch with the float fraction representing non-integer seconds. -func newNumericDateFromSeconds(f float64) *NumericDate { - round, frac := math.Modf(f) - return NewNumericDate(time.Unix(int64(round), int64(frac*1e9))) -} - -// MarshalJSON is an implementation of the json.RawMessage interface and serializes the UNIX epoch -// represented in NumericDate to a byte array, using the precision specified in TimePrecision. -func (date NumericDate) MarshalJSON() (b []byte, err error) { - f := float64(date.Truncate(TimePrecision).UnixNano()) / float64(time.Second) - - return []byte(strconv.FormatFloat(f, 'f', -1, 64)), nil -} - -// UnmarshalJSON is an implementation of the json.RawMessage interface and deserializses a -// NumericDate from a JSON representation, i.e. a json.Number. This number represents an UNIX epoch -// with either integer or non-integer seconds. -func (date *NumericDate) UnmarshalJSON(b []byte) (err error) { - var ( - number json.Number - f float64 - ) - - if err = json.Unmarshal(b, &number); err != nil { - return fmt.Errorf("could not parse NumericData: %w", err) - } - - if f, err = number.Float64(); err != nil { - return fmt.Errorf("could not convert json number value to float: %w", err) - } - - n := newNumericDateFromSeconds(f) - *date = *n - - return nil -} - -// ClaimStrings is basically just a slice of strings, but it can be either serialized from a string array or just a string. -// This type is necessary, since the "aud" claim can either be a single string or an array. -type ClaimStrings []string - -func (s *ClaimStrings) UnmarshalJSON(data []byte) (err error) { - var value interface{} - - if err = json.Unmarshal(data, &value); err != nil { - return err - } - - var aud []string - - switch v := value.(type) { - case string: - aud = append(aud, v) - case []string: - aud = ClaimStrings(v) - case []interface{}: - for _, vv := range v { - vs, ok := vv.(string) - if !ok { - return &json.UnsupportedTypeError{Type: reflect.TypeOf(vv)} - } - aud = append(aud, vs) - } - case nil: - return nil - default: - return &json.UnsupportedTypeError{Type: reflect.TypeOf(v)} - } - - *s = aud - - return -} - -func (s ClaimStrings) MarshalJSON() (b []byte, err error) { - // This handles a special case in the JWT RFC. If the string array, e.g. used by the "aud" field, - // only contains one element, it MAY be serialized as a single string. This may or may not be - // desired based on the ecosystem of other JWT library used, so we make it configurable by the - // variable MarshalSingleStringAsArray. - if len(s) == 1 && !MarshalSingleStringAsArray { - return json.Marshal(s[0]) - } - - return json.Marshal([]string(s)) -} diff --git a/vendor/github.com/golang-migrate/migrate/v4/source/driver.go b/vendor/github.com/golang-migrate/migrate/v4/source/driver.go index 05f97adabf..396eabfae7 100644 --- a/vendor/github.com/golang-migrate/migrate/v4/source/driver.go +++ b/vendor/github.com/golang-migrate/migrate/v4/source/driver.go @@ -17,23 +17,23 @@ var drivers = make(map[string]Driver) // Driver is the interface every source driver must implement. // // How to implement a source driver? -// 1. Implement this interface. -// 2. Optionally, add a function named `WithInstance`. -// This function should accept an existing source instance and a Config{} struct -// and return a driver instance. -// 3. Add a test that calls source/testing.go:Test() -// 4. Add own tests for Open(), WithInstance() (when provided) and Close(). -// All other functions are tested by tests in source/testing. -// Saves you some time and makes sure all source drivers behave the same way. -// 5. Call Register in init(). +// 1. Implement this interface. +// 2. Optionally, add a function named `WithInstance`. +// This function should accept an existing source instance and a Config{} struct +// and return a driver instance. +// 3. Add a test that calls source/testing.go:Test() +// 4. Add own tests for Open(), WithInstance() (when provided) and Close(). +// All other functions are tested by tests in source/testing. +// Saves you some time and makes sure all source drivers behave the same way. +// 5. Call Register in init(). // // Guidelines: -// * All configuration input must come from the URL string in func Open() +// - All configuration input must come from the URL string in func Open() // or the Config{} struct in WithInstance. Don't os.Getenv(). -// * Drivers are supposed to be read only. -// * Ideally don't load any contents (into memory) in Open or WithInstance. +// - Drivers are supposed to be read only. +// - Ideally don't load any contents (into memory) in Open or WithInstance. type Driver interface { - // Open returns a a new driver instance configured with parameters + // Open returns a new driver instance configured with parameters // coming from the URL string. Migrate will call this function // only once per instance. Open(url string) (Driver, error) @@ -87,7 +87,7 @@ func Open(url string) (Driver, error) { d, ok := drivers[u.Scheme] driversMu.RUnlock() if !ok { - return nil, fmt.Errorf("source driver: unknown driver %v (forgotten import?)", u.Scheme) + return nil, fmt.Errorf("source driver: unknown driver '%s' (forgotten import?)", u.Scheme) } return d.Open(url) diff --git a/vendor/github.com/golang-migrate/migrate/v4/source/errors.go b/vendor/github.com/golang-migrate/migrate/v4/source/errors.go new file mode 100644 index 0000000000..93d66e0d4b --- /dev/null +++ b/vendor/github.com/golang-migrate/migrate/v4/source/errors.go @@ -0,0 +1,15 @@ +package source + +import "os" + +// ErrDuplicateMigration is an error type for reporting duplicate migration +// files. +type ErrDuplicateMigration struct { + Migration + os.FileInfo +} + +// Error implements error interface. +func (e ErrDuplicateMigration) Error() string { + return "duplicate migration file: " + e.Name() +} diff --git a/vendor/github.com/golang-migrate/migrate/v4/source/file/file.go b/vendor/github.com/golang-migrate/migrate/v4/source/file/file.go index a0c6419318..d8b21dffb2 100644 --- a/vendor/github.com/golang-migrate/migrate/v4/source/file/file.go +++ b/vendor/github.com/golang-migrate/migrate/v4/source/file/file.go @@ -1,15 +1,12 @@ package file import ( - "fmt" - "io" - "io/ioutil" nurl "net/url" "os" - "path" "path/filepath" "github.com/golang-migrate/migrate/v4/source" + "github.com/golang-migrate/migrate/v4/source/iofs" ) func init() { @@ -17,17 +14,31 @@ func init() { } type File struct { - url string - path string - migrations *source.Migrations + iofs.PartialDriver + url string + path string } func (f *File) Open(url string) (source.Driver, error) { - u, err := nurl.Parse(url) + p, err := parseURL(url) if err != nil { return nil, err } + nf := &File{ + url: url, + path: p, + } + if err := nf.Init(os.DirFS(p), "."); err != nil { + return nil, err + } + return nf, nil +} +func parseURL(url string) (string, error) { + u, err := nurl.Parse(url) + if err != nil { + return "", err + } // concat host and path to restore full path // host might be `.` p := u.Opaque @@ -39,7 +50,7 @@ func (f *File) Open(url string) (source.Driver, error) { // default to current directory if no path wd, err := os.Getwd() if err != nil { - return nil, err + return "", err } p = wd @@ -47,81 +58,9 @@ func (f *File) Open(url string) (source.Driver, error) { // make path absolute if relative abs, err := filepath.Abs(p) if err != nil { - return nil, err + return "", err } p = abs } - - // scan directory - files, err := ioutil.ReadDir(p) - if err != nil { - return nil, err - } - - nf := &File{ - url: url, - path: p, - migrations: source.NewMigrations(), - } - - for _, fi := range files { - if !fi.IsDir() { - m, err := source.DefaultParse(fi.Name()) - if err != nil { - continue // ignore files that we can't parse - } - if !nf.migrations.Append(m) { - return nil, fmt.Errorf("unable to parse file %v", fi.Name()) - } - } - } - return nf, nil -} - -func (f *File) Close() error { - // nothing do to here - return nil -} - -func (f *File) First() (version uint, err error) { - if v, ok := f.migrations.First(); ok { - return v, nil - } - return 0, &os.PathError{Op: "first", Path: f.path, Err: os.ErrNotExist} -} - -func (f *File) Prev(version uint) (prevVersion uint, err error) { - if v, ok := f.migrations.Prev(version); ok { - return v, nil - } - return 0, &os.PathError{Op: fmt.Sprintf("prev for version %v", version), Path: f.path, Err: os.ErrNotExist} -} - -func (f *File) Next(version uint) (nextVersion uint, err error) { - if v, ok := f.migrations.Next(version); ok { - return v, nil - } - return 0, &os.PathError{Op: fmt.Sprintf("next for version %v", version), Path: f.path, Err: os.ErrNotExist} -} - -func (f *File) ReadUp(version uint) (r io.ReadCloser, identifier string, err error) { - if m, ok := f.migrations.Up(version); ok { - r, err := os.Open(path.Join(f.path, m.Raw)) - if err != nil { - return nil, "", err - } - return r, m.Identifier, nil - } - return nil, "", &os.PathError{Op: fmt.Sprintf("read version %v", version), Path: f.path, Err: os.ErrNotExist} -} - -func (f *File) ReadDown(version uint) (r io.ReadCloser, identifier string, err error) { - if m, ok := f.migrations.Down(version); ok { - r, err := os.Open(path.Join(f.path, m.Raw)) - if err != nil { - return nil, "", err - } - return r, m.Identifier, nil - } - return nil, "", &os.PathError{Op: fmt.Sprintf("read version %v", version), Path: f.path, Err: os.ErrNotExist} + return p, nil } diff --git a/vendor/github.com/golang-migrate/migrate/v4/source/iofs/README.md b/vendor/github.com/golang-migrate/migrate/v4/source/iofs/README.md new file mode 100644 index 0000000000..d75b328b95 --- /dev/null +++ b/vendor/github.com/golang-migrate/migrate/v4/source/iofs/README.md @@ -0,0 +1,3 @@ +# iofs + +https://pkg.go.dev/github.com/golang-migrate/migrate/v4/source/iofs diff --git a/vendor/github.com/golang-migrate/migrate/v4/source/iofs/doc.go b/vendor/github.com/golang-migrate/migrate/v4/source/iofs/doc.go new file mode 100644 index 0000000000..6b2c862e0f --- /dev/null +++ b/vendor/github.com/golang-migrate/migrate/v4/source/iofs/doc.go @@ -0,0 +1,10 @@ +/* +Package iofs provides the Go 1.16+ io/fs#FS driver. + +It can accept various file systems (like embed.FS, archive/zip#Reader) implementing io/fs#FS. + +This driver cannot be used with Go versions 1.15 and below. + +Also, Opening with a URL scheme is not supported. +*/ +package iofs diff --git a/vendor/github.com/golang-migrate/migrate/v4/source/iofs/iofs.go b/vendor/github.com/golang-migrate/migrate/v4/source/iofs/iofs.go new file mode 100644 index 0000000000..dc934a5fe2 --- /dev/null +++ b/vendor/github.com/golang-migrate/migrate/v4/source/iofs/iofs.go @@ -0,0 +1,176 @@ +//go:build go1.16 +// +build go1.16 + +package iofs + +import ( + "errors" + "fmt" + "io" + "io/fs" + "path" + "strconv" + + "github.com/golang-migrate/migrate/v4/source" +) + +type driver struct { + PartialDriver +} + +// New returns a new Driver from io/fs#FS and a relative path. +func New(fsys fs.FS, path string) (source.Driver, error) { + var i driver + if err := i.Init(fsys, path); err != nil { + return nil, fmt.Errorf("failed to init driver with path %s: %w", path, err) + } + return &i, nil +} + +// Open is part of source.Driver interface implementation. +// Open cannot be called on the iofs passthrough driver. +func (d *driver) Open(url string) (source.Driver, error) { + return nil, errors.New("Open() cannot be called on the iofs passthrough driver") +} + +// PartialDriver is a helper service for creating new source drivers working with +// io/fs.FS instances. It implements all source.Driver interface methods +// except for Open(). New driver could embed this struct and add missing Open() +// method. +// +// To prepare PartialDriver for use Init() function. +type PartialDriver struct { + migrations *source.Migrations + fsys fs.FS + path string +} + +// Init prepares not initialized IoFS instance to read migrations from a +// io/fs#FS instance and a relative path. +func (d *PartialDriver) Init(fsys fs.FS, path string) error { + entries, err := fs.ReadDir(fsys, path) + if err != nil { + return err + } + + ms := source.NewMigrations() + for _, e := range entries { + if e.IsDir() { + continue + } + m, err := source.DefaultParse(e.Name()) + if err != nil { + continue + } + file, err := e.Info() + if err != nil { + return err + } + if !ms.Append(m) { + return source.ErrDuplicateMigration{ + Migration: *m, + FileInfo: file, + } + } + } + + d.fsys = fsys + d.path = path + d.migrations = ms + return nil +} + +// Close is part of source.Driver interface implementation. +// Closes the file system if possible. +func (d *PartialDriver) Close() error { + c, ok := d.fsys.(io.Closer) + if !ok { + return nil + } + return c.Close() +} + +// First is part of source.Driver interface implementation. +func (d *PartialDriver) First() (version uint, err error) { + if version, ok := d.migrations.First(); ok { + return version, nil + } + return 0, &fs.PathError{ + Op: "first", + Path: d.path, + Err: fs.ErrNotExist, + } +} + +// Prev is part of source.Driver interface implementation. +func (d *PartialDriver) Prev(version uint) (prevVersion uint, err error) { + if version, ok := d.migrations.Prev(version); ok { + return version, nil + } + return 0, &fs.PathError{ + Op: "prev for version " + strconv.FormatUint(uint64(version), 10), + Path: d.path, + Err: fs.ErrNotExist, + } +} + +// Next is part of source.Driver interface implementation. +func (d *PartialDriver) Next(version uint) (nextVersion uint, err error) { + if version, ok := d.migrations.Next(version); ok { + return version, nil + } + return 0, &fs.PathError{ + Op: "next for version " + strconv.FormatUint(uint64(version), 10), + Path: d.path, + Err: fs.ErrNotExist, + } +} + +// ReadUp is part of source.Driver interface implementation. +func (d *PartialDriver) ReadUp(version uint) (r io.ReadCloser, identifier string, err error) { + if m, ok := d.migrations.Up(version); ok { + body, err := d.open(path.Join(d.path, m.Raw)) + if err != nil { + return nil, "", err + } + return body, m.Identifier, nil + } + return nil, "", &fs.PathError{ + Op: "read up for version " + strconv.FormatUint(uint64(version), 10), + Path: d.path, + Err: fs.ErrNotExist, + } +} + +// ReadDown is part of source.Driver interface implementation. +func (d *PartialDriver) ReadDown(version uint) (r io.ReadCloser, identifier string, err error) { + if m, ok := d.migrations.Down(version); ok { + body, err := d.open(path.Join(d.path, m.Raw)) + if err != nil { + return nil, "", err + } + return body, m.Identifier, nil + } + return nil, "", &fs.PathError{ + Op: "read down for version " + strconv.FormatUint(uint64(version), 10), + Path: d.path, + Err: fs.ErrNotExist, + } +} + +func (d *PartialDriver) open(path string) (fs.File, error) { + f, err := d.fsys.Open(path) + if err == nil { + return f, nil + } + // Some non-standard file systems may return errors that don't include the path, that + // makes debugging harder. + if !errors.As(err, new(*fs.PathError)) { + err = &fs.PathError{ + Op: "open", + Path: path, + Err: err, + } + } + return nil, err +} diff --git a/vendor/github.com/golang-migrate/migrate/v4/source/iofs/testdata/migrations/1_foobar.down.sql b/vendor/github.com/golang-migrate/migrate/v4/source/iofs/testdata/migrations/1_foobar.down.sql new file mode 100644 index 0000000000..4267951a5b --- /dev/null +++ b/vendor/github.com/golang-migrate/migrate/v4/source/iofs/testdata/migrations/1_foobar.down.sql @@ -0,0 +1 @@ +1 down diff --git a/vendor/github.com/golang-migrate/migrate/v4/source/iofs/testdata/migrations/1_foobar.up.sql b/vendor/github.com/golang-migrate/migrate/v4/source/iofs/testdata/migrations/1_foobar.up.sql new file mode 100644 index 0000000000..046fd5a5dc --- /dev/null +++ b/vendor/github.com/golang-migrate/migrate/v4/source/iofs/testdata/migrations/1_foobar.up.sql @@ -0,0 +1 @@ +1 up diff --git a/vendor/github.com/golang-migrate/migrate/v4/source/iofs/testdata/migrations/3_foobar.up.sql b/vendor/github.com/golang-migrate/migrate/v4/source/iofs/testdata/migrations/3_foobar.up.sql new file mode 100644 index 0000000000..77c1b77dcb --- /dev/null +++ b/vendor/github.com/golang-migrate/migrate/v4/source/iofs/testdata/migrations/3_foobar.up.sql @@ -0,0 +1 @@ +3 up diff --git a/vendor/github.com/golang-migrate/migrate/v4/source/iofs/testdata/migrations/4_foobar.down.sql b/vendor/github.com/golang-migrate/migrate/v4/source/iofs/testdata/migrations/4_foobar.down.sql new file mode 100644 index 0000000000..b405d8bd02 --- /dev/null +++ b/vendor/github.com/golang-migrate/migrate/v4/source/iofs/testdata/migrations/4_foobar.down.sql @@ -0,0 +1 @@ +4 down diff --git a/vendor/github.com/golang-migrate/migrate/v4/source/iofs/testdata/migrations/4_foobar.up.sql b/vendor/github.com/golang-migrate/migrate/v4/source/iofs/testdata/migrations/4_foobar.up.sql new file mode 100644 index 0000000000..eba61bb94e --- /dev/null +++ b/vendor/github.com/golang-migrate/migrate/v4/source/iofs/testdata/migrations/4_foobar.up.sql @@ -0,0 +1 @@ +4 up diff --git a/vendor/github.com/golang-migrate/migrate/v4/source/iofs/testdata/migrations/5_foobar.down.sql b/vendor/github.com/golang-migrate/migrate/v4/source/iofs/testdata/migrations/5_foobar.down.sql new file mode 100644 index 0000000000..6dc96e2068 --- /dev/null +++ b/vendor/github.com/golang-migrate/migrate/v4/source/iofs/testdata/migrations/5_foobar.down.sql @@ -0,0 +1 @@ +5 down diff --git a/vendor/github.com/golang-migrate/migrate/v4/source/iofs/testdata/migrations/7_foobar.down.sql b/vendor/github.com/golang-migrate/migrate/v4/source/iofs/testdata/migrations/7_foobar.down.sql new file mode 100644 index 0000000000..46636016b3 --- /dev/null +++ b/vendor/github.com/golang-migrate/migrate/v4/source/iofs/testdata/migrations/7_foobar.down.sql @@ -0,0 +1 @@ +7 down diff --git a/vendor/github.com/golang-migrate/migrate/v4/source/iofs/testdata/migrations/7_foobar.up.sql b/vendor/github.com/golang-migrate/migrate/v4/source/iofs/testdata/migrations/7_foobar.up.sql new file mode 100644 index 0000000000..cdbc410ee9 --- /dev/null +++ b/vendor/github.com/golang-migrate/migrate/v4/source/iofs/testdata/migrations/7_foobar.up.sql @@ -0,0 +1 @@ +7 up diff --git a/vendor/github.com/golang-migrate/migrate/v4/source/migration.go b/vendor/github.com/golang-migrate/migrate/v4/source/migration.go index b8bb79020b..74f6523cb7 100644 --- a/vendor/github.com/golang-migrate/migrate/v4/source/migration.go +++ b/vendor/github.com/golang-migrate/migrate/v4/source/migration.go @@ -66,11 +66,13 @@ func (i *Migrations) Append(m *Migration) (ok bool) { } func (i *Migrations) buildIndex() { - i.index = make(uintSlice, 0) + i.index = make(uintSlice, 0, len(i.migrations)) for version := range i.migrations { i.index = append(i.index, version) } - sort.Sort(i.index) + sort.Slice(i.index, func(x, y int) bool { + return i.index[x] < i.index[y] + }) } func (i *Migrations) First() (version uint, ok bool) { @@ -126,18 +128,6 @@ func (i *Migrations) findPos(version uint) int { type uintSlice []uint -func (s uintSlice) Len() int { - return len(s) -} - -func (s uintSlice) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} - -func (s uintSlice) Less(i, j int) bool { - return s[i] < s[j] -} - func (s uintSlice) Search(x uint) int { return sort.Search(len(s), func(i int) bool { return s[i] >= x }) } diff --git a/vendor/github.com/golang-migrate/migrate/v4/source/parse.go b/vendor/github.com/golang-migrate/migrate/v4/source/parse.go index 2f888fe753..df085ae299 100644 --- a/vendor/github.com/golang-migrate/migrate/v4/source/parse.go +++ b/vendor/github.com/golang-migrate/migrate/v4/source/parse.go @@ -16,8 +16,9 @@ var ( ) // Regex matches the following pattern: -// 123_name.up.ext -// 123_name.down.ext +// +// 123_name.up.ext +// 123_name.down.ext var Regex = regexp.MustCompile(`^([0-9]+)_(.*)\.(` + string(Down) + `|` + string(Up) + `)\.(.*)$`) // Parse returns Migration for matching Regex pattern. diff --git a/vendor/github.com/golang/protobuf/descriptor/descriptor.go b/vendor/github.com/golang/protobuf/descriptor/descriptor.go deleted file mode 100644 index ffde8a6508..0000000000 --- a/vendor/github.com/golang/protobuf/descriptor/descriptor.go +++ /dev/null @@ -1,180 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package descriptor provides functions for obtaining the protocol buffer -// descriptors of generated Go types. -// -// Deprecated: See the "google.golang.org/protobuf/reflect/protoreflect" package -// for how to obtain an EnumDescriptor or MessageDescriptor in order to -// programatically interact with the protobuf type system. -package descriptor - -import ( - "bytes" - "compress/gzip" - "io/ioutil" - "sync" - - "github.com/golang/protobuf/proto" - "google.golang.org/protobuf/reflect/protodesc" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/runtime/protoimpl" - - descriptorpb "github.com/golang/protobuf/protoc-gen-go/descriptor" -) - -// Message is proto.Message with a method to return its descriptor. -// -// Deprecated: The Descriptor method may not be generated by future -// versions of protoc-gen-go, meaning that this interface may not -// be implemented by many concrete message types. -type Message interface { - proto.Message - Descriptor() ([]byte, []int) -} - -// ForMessage returns the file descriptor proto containing -// the message and the message descriptor proto for the message itself. -// The returned proto messages must not be mutated. -// -// Deprecated: Not all concrete message types satisfy the Message interface. -// Use MessageDescriptorProto instead. If possible, the calling code should -// be rewritten to use protobuf reflection instead. -// See package "google.golang.org/protobuf/reflect/protoreflect" for details. -func ForMessage(m Message) (*descriptorpb.FileDescriptorProto, *descriptorpb.DescriptorProto) { - return MessageDescriptorProto(m) -} - -type rawDesc struct { - fileDesc []byte - indexes []int -} - -var rawDescCache sync.Map // map[protoreflect.Descriptor]*rawDesc - -func deriveRawDescriptor(d protoreflect.Descriptor) ([]byte, []int) { - // Fast-path: check whether raw descriptors are already cached. - origDesc := d - if v, ok := rawDescCache.Load(origDesc); ok { - return v.(*rawDesc).fileDesc, v.(*rawDesc).indexes - } - - // Slow-path: derive the raw descriptor from the v2 descriptor. - - // Start with the leaf (a given enum or message declaration) and - // ascend upwards until we hit the parent file descriptor. - var idxs []int - for { - idxs = append(idxs, d.Index()) - d = d.Parent() - if d == nil { - // TODO: We could construct a FileDescriptor stub for standalone - // descriptors to satisfy the API. - return nil, nil - } - if _, ok := d.(protoreflect.FileDescriptor); ok { - break - } - } - - // Obtain the raw file descriptor. - fd := d.(protoreflect.FileDescriptor) - b, _ := proto.Marshal(protodesc.ToFileDescriptorProto(fd)) - file := protoimpl.X.CompressGZIP(b) - - // Reverse the indexes, since we populated it in reverse. - for i, j := 0, len(idxs)-1; i < j; i, j = i+1, j-1 { - idxs[i], idxs[j] = idxs[j], idxs[i] - } - - if v, ok := rawDescCache.LoadOrStore(origDesc, &rawDesc{file, idxs}); ok { - return v.(*rawDesc).fileDesc, v.(*rawDesc).indexes - } - return file, idxs -} - -// EnumRawDescriptor returns the GZIP'd raw file descriptor representing -// the enum and the index path to reach the enum declaration. -// The returned slices must not be mutated. -func EnumRawDescriptor(e proto.GeneratedEnum) ([]byte, []int) { - if ev, ok := e.(interface{ EnumDescriptor() ([]byte, []int) }); ok { - return ev.EnumDescriptor() - } - ed := protoimpl.X.EnumTypeOf(e) - return deriveRawDescriptor(ed.Descriptor()) -} - -// MessageRawDescriptor returns the GZIP'd raw file descriptor representing -// the message and the index path to reach the message declaration. -// The returned slices must not be mutated. -func MessageRawDescriptor(m proto.GeneratedMessage) ([]byte, []int) { - if mv, ok := m.(interface{ Descriptor() ([]byte, []int) }); ok { - return mv.Descriptor() - } - md := protoimpl.X.MessageTypeOf(m) - return deriveRawDescriptor(md.Descriptor()) -} - -var fileDescCache sync.Map // map[*byte]*descriptorpb.FileDescriptorProto - -func deriveFileDescriptor(rawDesc []byte) *descriptorpb.FileDescriptorProto { - // Fast-path: check whether descriptor protos are already cached. - if v, ok := fileDescCache.Load(&rawDesc[0]); ok { - return v.(*descriptorpb.FileDescriptorProto) - } - - // Slow-path: derive the descriptor proto from the GZIP'd message. - zr, err := gzip.NewReader(bytes.NewReader(rawDesc)) - if err != nil { - panic(err) - } - b, err := ioutil.ReadAll(zr) - if err != nil { - panic(err) - } - fd := new(descriptorpb.FileDescriptorProto) - if err := proto.Unmarshal(b, fd); err != nil { - panic(err) - } - if v, ok := fileDescCache.LoadOrStore(&rawDesc[0], fd); ok { - return v.(*descriptorpb.FileDescriptorProto) - } - return fd -} - -// EnumDescriptorProto returns the file descriptor proto representing -// the enum and the enum descriptor proto for the enum itself. -// The returned proto messages must not be mutated. -func EnumDescriptorProto(e proto.GeneratedEnum) (*descriptorpb.FileDescriptorProto, *descriptorpb.EnumDescriptorProto) { - rawDesc, idxs := EnumRawDescriptor(e) - if rawDesc == nil || idxs == nil { - return nil, nil - } - fd := deriveFileDescriptor(rawDesc) - if len(idxs) == 1 { - return fd, fd.EnumType[idxs[0]] - } - md := fd.MessageType[idxs[0]] - for _, i := range idxs[1 : len(idxs)-1] { - md = md.NestedType[i] - } - ed := md.EnumType[idxs[len(idxs)-1]] - return fd, ed -} - -// MessageDescriptorProto returns the file descriptor proto representing -// the message and the message descriptor proto for the message itself. -// The returned proto messages must not be mutated. -func MessageDescriptorProto(m proto.GeneratedMessage) (*descriptorpb.FileDescriptorProto, *descriptorpb.DescriptorProto) { - rawDesc, idxs := MessageRawDescriptor(m) - if rawDesc == nil || idxs == nil { - return nil, nil - } - fd := deriveFileDescriptor(rawDesc) - md := fd.MessageType[idxs[0]] - for _, i := range idxs[1:] { - md = md.NestedType[i] - } - return fd, md -} diff --git a/vendor/github.com/golang/protobuf/jsonpb/decode.go b/vendor/github.com/golang/protobuf/jsonpb/decode.go deleted file mode 100644 index 60e82caa9a..0000000000 --- a/vendor/github.com/golang/protobuf/jsonpb/decode.go +++ /dev/null @@ -1,524 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package jsonpb - -import ( - "encoding/json" - "errors" - "fmt" - "io" - "math" - "reflect" - "strconv" - "strings" - "time" - - "github.com/golang/protobuf/proto" - "google.golang.org/protobuf/encoding/protojson" - protoV2 "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/reflect/protoregistry" -) - -const wrapJSONUnmarshalV2 = false - -// UnmarshalNext unmarshals the next JSON object from d into m. -func UnmarshalNext(d *json.Decoder, m proto.Message) error { - return new(Unmarshaler).UnmarshalNext(d, m) -} - -// Unmarshal unmarshals a JSON object from r into m. -func Unmarshal(r io.Reader, m proto.Message) error { - return new(Unmarshaler).Unmarshal(r, m) -} - -// UnmarshalString unmarshals a JSON object from s into m. -func UnmarshalString(s string, m proto.Message) error { - return new(Unmarshaler).Unmarshal(strings.NewReader(s), m) -} - -// Unmarshaler is a configurable object for converting from a JSON -// representation to a protocol buffer object. -type Unmarshaler struct { - // AllowUnknownFields specifies whether to allow messages to contain - // unknown JSON fields, as opposed to failing to unmarshal. - AllowUnknownFields bool - - // AnyResolver is used to resolve the google.protobuf.Any well-known type. - // If unset, the global registry is used by default. - AnyResolver AnyResolver -} - -// JSONPBUnmarshaler is implemented by protobuf messages that customize the way -// they are unmarshaled from JSON. Messages that implement this should also -// implement JSONPBMarshaler so that the custom format can be produced. -// -// The JSON unmarshaling must follow the JSON to proto specification: -// https://developers.google.com/protocol-buffers/docs/proto3#json -// -// Deprecated: Custom types should implement protobuf reflection instead. -type JSONPBUnmarshaler interface { - UnmarshalJSONPB(*Unmarshaler, []byte) error -} - -// Unmarshal unmarshals a JSON object from r into m. -func (u *Unmarshaler) Unmarshal(r io.Reader, m proto.Message) error { - return u.UnmarshalNext(json.NewDecoder(r), m) -} - -// UnmarshalNext unmarshals the next JSON object from d into m. -func (u *Unmarshaler) UnmarshalNext(d *json.Decoder, m proto.Message) error { - if m == nil { - return errors.New("invalid nil message") - } - - // Parse the next JSON object from the stream. - raw := json.RawMessage{} - if err := d.Decode(&raw); err != nil { - return err - } - - // Check for custom unmarshalers first since they may not properly - // implement protobuf reflection that the logic below relies on. - if jsu, ok := m.(JSONPBUnmarshaler); ok { - return jsu.UnmarshalJSONPB(u, raw) - } - - mr := proto.MessageReflect(m) - - // NOTE: For historical reasons, a top-level null is treated as a noop. - // This is incorrect, but kept for compatibility. - if string(raw) == "null" && mr.Descriptor().FullName() != "google.protobuf.Value" { - return nil - } - - if wrapJSONUnmarshalV2 { - // NOTE: If input message is non-empty, we need to preserve merge semantics - // of the old jsonpb implementation. These semantics are not supported by - // the protobuf JSON specification. - isEmpty := true - mr.Range(func(protoreflect.FieldDescriptor, protoreflect.Value) bool { - isEmpty = false // at least one iteration implies non-empty - return false - }) - if !isEmpty { - // Perform unmarshaling into a newly allocated, empty message. - mr = mr.New() - - // Use a defer to copy all unmarshaled fields into the original message. - dst := proto.MessageReflect(m) - defer mr.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { - dst.Set(fd, v) - return true - }) - } - - // Unmarshal using the v2 JSON unmarshaler. - opts := protojson.UnmarshalOptions{ - DiscardUnknown: u.AllowUnknownFields, - } - if u.AnyResolver != nil { - opts.Resolver = anyResolver{u.AnyResolver} - } - return opts.Unmarshal(raw, mr.Interface()) - } else { - if err := u.unmarshalMessage(mr, raw); err != nil { - return err - } - return protoV2.CheckInitialized(mr.Interface()) - } -} - -func (u *Unmarshaler) unmarshalMessage(m protoreflect.Message, in []byte) error { - md := m.Descriptor() - fds := md.Fields() - - if jsu, ok := proto.MessageV1(m.Interface()).(JSONPBUnmarshaler); ok { - return jsu.UnmarshalJSONPB(u, in) - } - - if string(in) == "null" && md.FullName() != "google.protobuf.Value" { - return nil - } - - switch wellKnownType(md.FullName()) { - case "Any": - var jsonObject map[string]json.RawMessage - if err := json.Unmarshal(in, &jsonObject); err != nil { - return err - } - - rawTypeURL, ok := jsonObject["@type"] - if !ok { - return errors.New("Any JSON doesn't have '@type'") - } - typeURL, err := unquoteString(string(rawTypeURL)) - if err != nil { - return fmt.Errorf("can't unmarshal Any's '@type': %q", rawTypeURL) - } - m.Set(fds.ByNumber(1), protoreflect.ValueOfString(typeURL)) - - var m2 protoreflect.Message - if u.AnyResolver != nil { - mi, err := u.AnyResolver.Resolve(typeURL) - if err != nil { - return err - } - m2 = proto.MessageReflect(mi) - } else { - mt, err := protoregistry.GlobalTypes.FindMessageByURL(typeURL) - if err != nil { - if err == protoregistry.NotFound { - return fmt.Errorf("could not resolve Any message type: %v", typeURL) - } - return err - } - m2 = mt.New() - } - - if wellKnownType(m2.Descriptor().FullName()) != "" { - rawValue, ok := jsonObject["value"] - if !ok { - return errors.New("Any JSON doesn't have 'value'") - } - if err := u.unmarshalMessage(m2, rawValue); err != nil { - return fmt.Errorf("can't unmarshal Any nested proto %v: %v", typeURL, err) - } - } else { - delete(jsonObject, "@type") - rawJSON, err := json.Marshal(jsonObject) - if err != nil { - return fmt.Errorf("can't generate JSON for Any's nested proto to be unmarshaled: %v", err) - } - if err = u.unmarshalMessage(m2, rawJSON); err != nil { - return fmt.Errorf("can't unmarshal Any nested proto %v: %v", typeURL, err) - } - } - - rawWire, err := protoV2.Marshal(m2.Interface()) - if err != nil { - return fmt.Errorf("can't marshal proto %v into Any.Value: %v", typeURL, err) - } - m.Set(fds.ByNumber(2), protoreflect.ValueOfBytes(rawWire)) - return nil - case "BoolValue", "BytesValue", "StringValue", - "Int32Value", "UInt32Value", "FloatValue", - "Int64Value", "UInt64Value", "DoubleValue": - fd := fds.ByNumber(1) - v, err := u.unmarshalValue(m.NewField(fd), in, fd) - if err != nil { - return err - } - m.Set(fd, v) - return nil - case "Duration": - v, err := unquoteString(string(in)) - if err != nil { - return err - } - d, err := time.ParseDuration(v) - if err != nil { - return fmt.Errorf("bad Duration: %v", err) - } - - sec := d.Nanoseconds() / 1e9 - nsec := d.Nanoseconds() % 1e9 - m.Set(fds.ByNumber(1), protoreflect.ValueOfInt64(int64(sec))) - m.Set(fds.ByNumber(2), protoreflect.ValueOfInt32(int32(nsec))) - return nil - case "Timestamp": - v, err := unquoteString(string(in)) - if err != nil { - return err - } - t, err := time.Parse(time.RFC3339Nano, v) - if err != nil { - return fmt.Errorf("bad Timestamp: %v", err) - } - - sec := t.Unix() - nsec := t.Nanosecond() - m.Set(fds.ByNumber(1), protoreflect.ValueOfInt64(int64(sec))) - m.Set(fds.ByNumber(2), protoreflect.ValueOfInt32(int32(nsec))) - return nil - case "Value": - switch { - case string(in) == "null": - m.Set(fds.ByNumber(1), protoreflect.ValueOfEnum(0)) - case string(in) == "true": - m.Set(fds.ByNumber(4), protoreflect.ValueOfBool(true)) - case string(in) == "false": - m.Set(fds.ByNumber(4), protoreflect.ValueOfBool(false)) - case hasPrefixAndSuffix('"', in, '"'): - s, err := unquoteString(string(in)) - if err != nil { - return fmt.Errorf("unrecognized type for Value %q", in) - } - m.Set(fds.ByNumber(3), protoreflect.ValueOfString(s)) - case hasPrefixAndSuffix('[', in, ']'): - v := m.Mutable(fds.ByNumber(6)) - return u.unmarshalMessage(v.Message(), in) - case hasPrefixAndSuffix('{', in, '}'): - v := m.Mutable(fds.ByNumber(5)) - return u.unmarshalMessage(v.Message(), in) - default: - f, err := strconv.ParseFloat(string(in), 0) - if err != nil { - return fmt.Errorf("unrecognized type for Value %q", in) - } - m.Set(fds.ByNumber(2), protoreflect.ValueOfFloat64(f)) - } - return nil - case "ListValue": - var jsonArray []json.RawMessage - if err := json.Unmarshal(in, &jsonArray); err != nil { - return fmt.Errorf("bad ListValue: %v", err) - } - - lv := m.Mutable(fds.ByNumber(1)).List() - for _, raw := range jsonArray { - ve := lv.NewElement() - if err := u.unmarshalMessage(ve.Message(), raw); err != nil { - return err - } - lv.Append(ve) - } - return nil - case "Struct": - var jsonObject map[string]json.RawMessage - if err := json.Unmarshal(in, &jsonObject); err != nil { - return fmt.Errorf("bad StructValue: %v", err) - } - - mv := m.Mutable(fds.ByNumber(1)).Map() - for key, raw := range jsonObject { - kv := protoreflect.ValueOf(key).MapKey() - vv := mv.NewValue() - if err := u.unmarshalMessage(vv.Message(), raw); err != nil { - return fmt.Errorf("bad value in StructValue for key %q: %v", key, err) - } - mv.Set(kv, vv) - } - return nil - } - - var jsonObject map[string]json.RawMessage - if err := json.Unmarshal(in, &jsonObject); err != nil { - return err - } - - // Handle known fields. - for i := 0; i < fds.Len(); i++ { - fd := fds.Get(i) - if fd.IsWeak() && fd.Message().IsPlaceholder() { - continue // weak reference is not linked in - } - - // Search for any raw JSON value associated with this field. - var raw json.RawMessage - name := string(fd.Name()) - if fd.Kind() == protoreflect.GroupKind { - name = string(fd.Message().Name()) - } - if v, ok := jsonObject[name]; ok { - delete(jsonObject, name) - raw = v - } - name = string(fd.JSONName()) - if v, ok := jsonObject[name]; ok { - delete(jsonObject, name) - raw = v - } - - field := m.NewField(fd) - // Unmarshal the field value. - if raw == nil || (string(raw) == "null" && !isSingularWellKnownValue(fd) && !isSingularJSONPBUnmarshaler(field, fd)) { - continue - } - v, err := u.unmarshalValue(field, raw, fd) - if err != nil { - return err - } - m.Set(fd, v) - } - - // Handle extension fields. - for name, raw := range jsonObject { - if !strings.HasPrefix(name, "[") || !strings.HasSuffix(name, "]") { - continue - } - - // Resolve the extension field by name. - xname := protoreflect.FullName(name[len("[") : len(name)-len("]")]) - xt, _ := protoregistry.GlobalTypes.FindExtensionByName(xname) - if xt == nil && isMessageSet(md) { - xt, _ = protoregistry.GlobalTypes.FindExtensionByName(xname.Append("message_set_extension")) - } - if xt == nil { - continue - } - delete(jsonObject, name) - fd := xt.TypeDescriptor() - if fd.ContainingMessage().FullName() != m.Descriptor().FullName() { - return fmt.Errorf("extension field %q does not extend message %q", xname, m.Descriptor().FullName()) - } - - field := m.NewField(fd) - // Unmarshal the field value. - if raw == nil || (string(raw) == "null" && !isSingularWellKnownValue(fd) && !isSingularJSONPBUnmarshaler(field, fd)) { - continue - } - v, err := u.unmarshalValue(field, raw, fd) - if err != nil { - return err - } - m.Set(fd, v) - } - - if !u.AllowUnknownFields && len(jsonObject) > 0 { - for name := range jsonObject { - return fmt.Errorf("unknown field %q in %v", name, md.FullName()) - } - } - return nil -} - -func isSingularWellKnownValue(fd protoreflect.FieldDescriptor) bool { - if md := fd.Message(); md != nil { - return md.FullName() == "google.protobuf.Value" && fd.Cardinality() != protoreflect.Repeated - } - return false -} - -func isSingularJSONPBUnmarshaler(v protoreflect.Value, fd protoreflect.FieldDescriptor) bool { - if fd.Message() != nil && fd.Cardinality() != protoreflect.Repeated { - _, ok := proto.MessageV1(v.Interface()).(JSONPBUnmarshaler) - return ok - } - return false -} - -func (u *Unmarshaler) unmarshalValue(v protoreflect.Value, in []byte, fd protoreflect.FieldDescriptor) (protoreflect.Value, error) { - switch { - case fd.IsList(): - var jsonArray []json.RawMessage - if err := json.Unmarshal(in, &jsonArray); err != nil { - return v, err - } - lv := v.List() - for _, raw := range jsonArray { - ve, err := u.unmarshalSingularValue(lv.NewElement(), raw, fd) - if err != nil { - return v, err - } - lv.Append(ve) - } - return v, nil - case fd.IsMap(): - var jsonObject map[string]json.RawMessage - if err := json.Unmarshal(in, &jsonObject); err != nil { - return v, err - } - kfd := fd.MapKey() - vfd := fd.MapValue() - mv := v.Map() - for key, raw := range jsonObject { - var kv protoreflect.MapKey - if kfd.Kind() == protoreflect.StringKind { - kv = protoreflect.ValueOf(key).MapKey() - } else { - v, err := u.unmarshalSingularValue(kfd.Default(), []byte(key), kfd) - if err != nil { - return v, err - } - kv = v.MapKey() - } - - vv, err := u.unmarshalSingularValue(mv.NewValue(), raw, vfd) - if err != nil { - return v, err - } - mv.Set(kv, vv) - } - return v, nil - default: - return u.unmarshalSingularValue(v, in, fd) - } -} - -var nonFinite = map[string]float64{ - `"NaN"`: math.NaN(), - `"Infinity"`: math.Inf(+1), - `"-Infinity"`: math.Inf(-1), -} - -func (u *Unmarshaler) unmarshalSingularValue(v protoreflect.Value, in []byte, fd protoreflect.FieldDescriptor) (protoreflect.Value, error) { - switch fd.Kind() { - case protoreflect.BoolKind: - return unmarshalValue(in, new(bool)) - case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind: - return unmarshalValue(trimQuote(in), new(int32)) - case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: - return unmarshalValue(trimQuote(in), new(int64)) - case protoreflect.Uint32Kind, protoreflect.Fixed32Kind: - return unmarshalValue(trimQuote(in), new(uint32)) - case protoreflect.Uint64Kind, protoreflect.Fixed64Kind: - return unmarshalValue(trimQuote(in), new(uint64)) - case protoreflect.FloatKind: - if f, ok := nonFinite[string(in)]; ok { - return protoreflect.ValueOfFloat32(float32(f)), nil - } - return unmarshalValue(trimQuote(in), new(float32)) - case protoreflect.DoubleKind: - if f, ok := nonFinite[string(in)]; ok { - return protoreflect.ValueOfFloat64(float64(f)), nil - } - return unmarshalValue(trimQuote(in), new(float64)) - case protoreflect.StringKind: - return unmarshalValue(in, new(string)) - case protoreflect.BytesKind: - return unmarshalValue(in, new([]byte)) - case protoreflect.EnumKind: - if hasPrefixAndSuffix('"', in, '"') { - vd := fd.Enum().Values().ByName(protoreflect.Name(trimQuote(in))) - if vd == nil { - return v, fmt.Errorf("unknown value %q for enum %s", in, fd.Enum().FullName()) - } - return protoreflect.ValueOfEnum(vd.Number()), nil - } - return unmarshalValue(in, new(protoreflect.EnumNumber)) - case protoreflect.MessageKind, protoreflect.GroupKind: - err := u.unmarshalMessage(v.Message(), in) - return v, err - default: - panic(fmt.Sprintf("invalid kind %v", fd.Kind())) - } -} - -func unmarshalValue(in []byte, v interface{}) (protoreflect.Value, error) { - err := json.Unmarshal(in, v) - return protoreflect.ValueOf(reflect.ValueOf(v).Elem().Interface()), err -} - -func unquoteString(in string) (out string, err error) { - err = json.Unmarshal([]byte(in), &out) - return out, err -} - -func hasPrefixAndSuffix(prefix byte, in []byte, suffix byte) bool { - if len(in) >= 2 && in[0] == prefix && in[len(in)-1] == suffix { - return true - } - return false -} - -// trimQuote is like unquoteString but simply strips surrounding quotes. -// This is incorrect, but is behavior done by the legacy implementation. -func trimQuote(in []byte) []byte { - if len(in) >= 2 && in[0] == '"' && in[len(in)-1] == '"' { - in = in[1 : len(in)-1] - } - return in -} diff --git a/vendor/github.com/golang/protobuf/jsonpb/encode.go b/vendor/github.com/golang/protobuf/jsonpb/encode.go deleted file mode 100644 index 685c80a62b..0000000000 --- a/vendor/github.com/golang/protobuf/jsonpb/encode.go +++ /dev/null @@ -1,559 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package jsonpb - -import ( - "encoding/json" - "errors" - "fmt" - "io" - "math" - "reflect" - "sort" - "strconv" - "strings" - "time" - - "github.com/golang/protobuf/proto" - "google.golang.org/protobuf/encoding/protojson" - protoV2 "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/reflect/protoregistry" -) - -const wrapJSONMarshalV2 = false - -// Marshaler is a configurable object for marshaling protocol buffer messages -// to the specified JSON representation. -type Marshaler struct { - // OrigName specifies whether to use the original protobuf name for fields. - OrigName bool - - // EnumsAsInts specifies whether to render enum values as integers, - // as opposed to string values. - EnumsAsInts bool - - // EmitDefaults specifies whether to render fields with zero values. - EmitDefaults bool - - // Indent controls whether the output is compact or not. - // If empty, the output is compact JSON. Otherwise, every JSON object - // entry and JSON array value will be on its own line. - // Each line will be preceded by repeated copies of Indent, where the - // number of copies is the current indentation depth. - Indent string - - // AnyResolver is used to resolve the google.protobuf.Any well-known type. - // If unset, the global registry is used by default. - AnyResolver AnyResolver -} - -// JSONPBMarshaler is implemented by protobuf messages that customize the -// way they are marshaled to JSON. Messages that implement this should also -// implement JSONPBUnmarshaler so that the custom format can be parsed. -// -// The JSON marshaling must follow the proto to JSON specification: -// https://developers.google.com/protocol-buffers/docs/proto3#json -// -// Deprecated: Custom types should implement protobuf reflection instead. -type JSONPBMarshaler interface { - MarshalJSONPB(*Marshaler) ([]byte, error) -} - -// Marshal serializes a protobuf message as JSON into w. -func (jm *Marshaler) Marshal(w io.Writer, m proto.Message) error { - b, err := jm.marshal(m) - if len(b) > 0 { - if _, err := w.Write(b); err != nil { - return err - } - } - return err -} - -// MarshalToString serializes a protobuf message as JSON in string form. -func (jm *Marshaler) MarshalToString(m proto.Message) (string, error) { - b, err := jm.marshal(m) - if err != nil { - return "", err - } - return string(b), nil -} - -func (jm *Marshaler) marshal(m proto.Message) ([]byte, error) { - v := reflect.ValueOf(m) - if m == nil || (v.Kind() == reflect.Ptr && v.IsNil()) { - return nil, errors.New("Marshal called with nil") - } - - // Check for custom marshalers first since they may not properly - // implement protobuf reflection that the logic below relies on. - if jsm, ok := m.(JSONPBMarshaler); ok { - return jsm.MarshalJSONPB(jm) - } - - if wrapJSONMarshalV2 { - opts := protojson.MarshalOptions{ - UseProtoNames: jm.OrigName, - UseEnumNumbers: jm.EnumsAsInts, - EmitUnpopulated: jm.EmitDefaults, - Indent: jm.Indent, - } - if jm.AnyResolver != nil { - opts.Resolver = anyResolver{jm.AnyResolver} - } - return opts.Marshal(proto.MessageReflect(m).Interface()) - } else { - // Check for unpopulated required fields first. - m2 := proto.MessageReflect(m) - if err := protoV2.CheckInitialized(m2.Interface()); err != nil { - return nil, err - } - - w := jsonWriter{Marshaler: jm} - err := w.marshalMessage(m2, "", "") - return w.buf, err - } -} - -type jsonWriter struct { - *Marshaler - buf []byte -} - -func (w *jsonWriter) write(s string) { - w.buf = append(w.buf, s...) -} - -func (w *jsonWriter) marshalMessage(m protoreflect.Message, indent, typeURL string) error { - if jsm, ok := proto.MessageV1(m.Interface()).(JSONPBMarshaler); ok { - b, err := jsm.MarshalJSONPB(w.Marshaler) - if err != nil { - return err - } - if typeURL != "" { - // we are marshaling this object to an Any type - var js map[string]*json.RawMessage - if err = json.Unmarshal(b, &js); err != nil { - return fmt.Errorf("type %T produced invalid JSON: %v", m.Interface(), err) - } - turl, err := json.Marshal(typeURL) - if err != nil { - return fmt.Errorf("failed to marshal type URL %q to JSON: %v", typeURL, err) - } - js["@type"] = (*json.RawMessage)(&turl) - if b, err = json.Marshal(js); err != nil { - return err - } - } - w.write(string(b)) - return nil - } - - md := m.Descriptor() - fds := md.Fields() - - // Handle well-known types. - const secondInNanos = int64(time.Second / time.Nanosecond) - switch wellKnownType(md.FullName()) { - case "Any": - return w.marshalAny(m, indent) - case "BoolValue", "BytesValue", "StringValue", - "Int32Value", "UInt32Value", "FloatValue", - "Int64Value", "UInt64Value", "DoubleValue": - fd := fds.ByNumber(1) - return w.marshalValue(fd, m.Get(fd), indent) - case "Duration": - const maxSecondsInDuration = 315576000000 - // "Generated output always contains 0, 3, 6, or 9 fractional digits, - // depending on required precision." - s := m.Get(fds.ByNumber(1)).Int() - ns := m.Get(fds.ByNumber(2)).Int() - if s < -maxSecondsInDuration || s > maxSecondsInDuration { - return fmt.Errorf("seconds out of range %v", s) - } - if ns <= -secondInNanos || ns >= secondInNanos { - return fmt.Errorf("ns out of range (%v, %v)", -secondInNanos, secondInNanos) - } - if (s > 0 && ns < 0) || (s < 0 && ns > 0) { - return errors.New("signs of seconds and nanos do not match") - } - var sign string - if s < 0 || ns < 0 { - sign, s, ns = "-", -1*s, -1*ns - } - x := fmt.Sprintf("%s%d.%09d", sign, s, ns) - x = strings.TrimSuffix(x, "000") - x = strings.TrimSuffix(x, "000") - x = strings.TrimSuffix(x, ".000") - w.write(fmt.Sprintf(`"%vs"`, x)) - return nil - case "Timestamp": - // "RFC 3339, where generated output will always be Z-normalized - // and uses 0, 3, 6 or 9 fractional digits." - s := m.Get(fds.ByNumber(1)).Int() - ns := m.Get(fds.ByNumber(2)).Int() - if ns < 0 || ns >= secondInNanos { - return fmt.Errorf("ns out of range [0, %v)", secondInNanos) - } - t := time.Unix(s, ns).UTC() - // time.RFC3339Nano isn't exactly right (we need to get 3/6/9 fractional digits). - x := t.Format("2006-01-02T15:04:05.000000000") - x = strings.TrimSuffix(x, "000") - x = strings.TrimSuffix(x, "000") - x = strings.TrimSuffix(x, ".000") - w.write(fmt.Sprintf(`"%vZ"`, x)) - return nil - case "Value": - // JSON value; which is a null, number, string, bool, object, or array. - od := md.Oneofs().Get(0) - fd := m.WhichOneof(od) - if fd == nil { - return errors.New("nil Value") - } - return w.marshalValue(fd, m.Get(fd), indent) - case "Struct", "ListValue": - // JSON object or array. - fd := fds.ByNumber(1) - return w.marshalValue(fd, m.Get(fd), indent) - } - - w.write("{") - if w.Indent != "" { - w.write("\n") - } - - firstField := true - if typeURL != "" { - if err := w.marshalTypeURL(indent, typeURL); err != nil { - return err - } - firstField = false - } - - for i := 0; i < fds.Len(); { - fd := fds.Get(i) - if od := fd.ContainingOneof(); od != nil { - fd = m.WhichOneof(od) - i += od.Fields().Len() - if fd == nil { - continue - } - } else { - i++ - } - - v := m.Get(fd) - - if !m.Has(fd) { - if !w.EmitDefaults || fd.ContainingOneof() != nil { - continue - } - if fd.Cardinality() != protoreflect.Repeated && (fd.Message() != nil || fd.Syntax() == protoreflect.Proto2) { - v = protoreflect.Value{} // use "null" for singular messages or proto2 scalars - } - } - - if !firstField { - w.writeComma() - } - if err := w.marshalField(fd, v, indent); err != nil { - return err - } - firstField = false - } - - // Handle proto2 extensions. - if md.ExtensionRanges().Len() > 0 { - // Collect a sorted list of all extension descriptor and values. - type ext struct { - desc protoreflect.FieldDescriptor - val protoreflect.Value - } - var exts []ext - m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { - if fd.IsExtension() { - exts = append(exts, ext{fd, v}) - } - return true - }) - sort.Slice(exts, func(i, j int) bool { - return exts[i].desc.Number() < exts[j].desc.Number() - }) - - for _, ext := range exts { - if !firstField { - w.writeComma() - } - if err := w.marshalField(ext.desc, ext.val, indent); err != nil { - return err - } - firstField = false - } - } - - if w.Indent != "" { - w.write("\n") - w.write(indent) - } - w.write("}") - return nil -} - -func (w *jsonWriter) writeComma() { - if w.Indent != "" { - w.write(",\n") - } else { - w.write(",") - } -} - -func (w *jsonWriter) marshalAny(m protoreflect.Message, indent string) error { - // "If the Any contains a value that has a special JSON mapping, - // it will be converted as follows: {"@type": xxx, "value": yyy}. - // Otherwise, the value will be converted into a JSON object, - // and the "@type" field will be inserted to indicate the actual data type." - md := m.Descriptor() - typeURL := m.Get(md.Fields().ByNumber(1)).String() - rawVal := m.Get(md.Fields().ByNumber(2)).Bytes() - - var m2 protoreflect.Message - if w.AnyResolver != nil { - mi, err := w.AnyResolver.Resolve(typeURL) - if err != nil { - return err - } - m2 = proto.MessageReflect(mi) - } else { - mt, err := protoregistry.GlobalTypes.FindMessageByURL(typeURL) - if err != nil { - return err - } - m2 = mt.New() - } - - if err := protoV2.Unmarshal(rawVal, m2.Interface()); err != nil { - return err - } - - if wellKnownType(m2.Descriptor().FullName()) == "" { - return w.marshalMessage(m2, indent, typeURL) - } - - w.write("{") - if w.Indent != "" { - w.write("\n") - } - if err := w.marshalTypeURL(indent, typeURL); err != nil { - return err - } - w.writeComma() - if w.Indent != "" { - w.write(indent) - w.write(w.Indent) - w.write(`"value": `) - } else { - w.write(`"value":`) - } - if err := w.marshalMessage(m2, indent+w.Indent, ""); err != nil { - return err - } - if w.Indent != "" { - w.write("\n") - w.write(indent) - } - w.write("}") - return nil -} - -func (w *jsonWriter) marshalTypeURL(indent, typeURL string) error { - if w.Indent != "" { - w.write(indent) - w.write(w.Indent) - } - w.write(`"@type":`) - if w.Indent != "" { - w.write(" ") - } - b, err := json.Marshal(typeURL) - if err != nil { - return err - } - w.write(string(b)) - return nil -} - -// marshalField writes field description and value to the Writer. -func (w *jsonWriter) marshalField(fd protoreflect.FieldDescriptor, v protoreflect.Value, indent string) error { - if w.Indent != "" { - w.write(indent) - w.write(w.Indent) - } - w.write(`"`) - switch { - case fd.IsExtension(): - // For message set, use the fname of the message as the extension name. - name := string(fd.FullName()) - if isMessageSet(fd.ContainingMessage()) { - name = strings.TrimSuffix(name, ".message_set_extension") - } - - w.write("[" + name + "]") - case w.OrigName: - name := string(fd.Name()) - if fd.Kind() == protoreflect.GroupKind { - name = string(fd.Message().Name()) - } - w.write(name) - default: - w.write(string(fd.JSONName())) - } - w.write(`":`) - if w.Indent != "" { - w.write(" ") - } - return w.marshalValue(fd, v, indent) -} - -func (w *jsonWriter) marshalValue(fd protoreflect.FieldDescriptor, v protoreflect.Value, indent string) error { - switch { - case fd.IsList(): - w.write("[") - comma := "" - lv := v.List() - for i := 0; i < lv.Len(); i++ { - w.write(comma) - if w.Indent != "" { - w.write("\n") - w.write(indent) - w.write(w.Indent) - w.write(w.Indent) - } - if err := w.marshalSingularValue(fd, lv.Get(i), indent+w.Indent); err != nil { - return err - } - comma = "," - } - if w.Indent != "" { - w.write("\n") - w.write(indent) - w.write(w.Indent) - } - w.write("]") - return nil - case fd.IsMap(): - kfd := fd.MapKey() - vfd := fd.MapValue() - mv := v.Map() - - // Collect a sorted list of all map keys and values. - type entry struct{ key, val protoreflect.Value } - var entries []entry - mv.Range(func(k protoreflect.MapKey, v protoreflect.Value) bool { - entries = append(entries, entry{k.Value(), v}) - return true - }) - sort.Slice(entries, func(i, j int) bool { - switch kfd.Kind() { - case protoreflect.BoolKind: - return !entries[i].key.Bool() && entries[j].key.Bool() - case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind, protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: - return entries[i].key.Int() < entries[j].key.Int() - case protoreflect.Uint32Kind, protoreflect.Fixed32Kind, protoreflect.Uint64Kind, protoreflect.Fixed64Kind: - return entries[i].key.Uint() < entries[j].key.Uint() - case protoreflect.StringKind: - return entries[i].key.String() < entries[j].key.String() - default: - panic("invalid kind") - } - }) - - w.write(`{`) - comma := "" - for _, entry := range entries { - w.write(comma) - if w.Indent != "" { - w.write("\n") - w.write(indent) - w.write(w.Indent) - w.write(w.Indent) - } - - s := fmt.Sprint(entry.key.Interface()) - b, err := json.Marshal(s) - if err != nil { - return err - } - w.write(string(b)) - - w.write(`:`) - if w.Indent != "" { - w.write(` `) - } - - if err := w.marshalSingularValue(vfd, entry.val, indent+w.Indent); err != nil { - return err - } - comma = "," - } - if w.Indent != "" { - w.write("\n") - w.write(indent) - w.write(w.Indent) - } - w.write(`}`) - return nil - default: - return w.marshalSingularValue(fd, v, indent) - } -} - -func (w *jsonWriter) marshalSingularValue(fd protoreflect.FieldDescriptor, v protoreflect.Value, indent string) error { - switch { - case !v.IsValid(): - w.write("null") - return nil - case fd.Message() != nil: - return w.marshalMessage(v.Message(), indent+w.Indent, "") - case fd.Enum() != nil: - if fd.Enum().FullName() == "google.protobuf.NullValue" { - w.write("null") - return nil - } - - vd := fd.Enum().Values().ByNumber(v.Enum()) - if vd == nil || w.EnumsAsInts { - w.write(strconv.Itoa(int(v.Enum()))) - } else { - w.write(`"` + string(vd.Name()) + `"`) - } - return nil - default: - switch v.Interface().(type) { - case float32, float64: - switch { - case math.IsInf(v.Float(), +1): - w.write(`"Infinity"`) - return nil - case math.IsInf(v.Float(), -1): - w.write(`"-Infinity"`) - return nil - case math.IsNaN(v.Float()): - w.write(`"NaN"`) - return nil - } - case int64, uint64: - w.write(fmt.Sprintf(`"%d"`, v.Interface())) - return nil - } - - b, err := json.Marshal(v.Interface()) - if err != nil { - return err - } - w.write(string(b)) - return nil - } -} diff --git a/vendor/github.com/golang/protobuf/jsonpb/json.go b/vendor/github.com/golang/protobuf/jsonpb/json.go deleted file mode 100644 index 480e2448de..0000000000 --- a/vendor/github.com/golang/protobuf/jsonpb/json.go +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package jsonpb provides functionality to marshal and unmarshal between a -// protocol buffer message and JSON. It follows the specification at -// https://developers.google.com/protocol-buffers/docs/proto3#json. -// -// Do not rely on the default behavior of the standard encoding/json package -// when called on generated message types as it does not operate correctly. -// -// Deprecated: Use the "google.golang.org/protobuf/encoding/protojson" -// package instead. -package jsonpb - -import ( - "github.com/golang/protobuf/proto" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/reflect/protoregistry" - "google.golang.org/protobuf/runtime/protoimpl" -) - -// AnyResolver takes a type URL, present in an Any message, -// and resolves it into an instance of the associated message. -type AnyResolver interface { - Resolve(typeURL string) (proto.Message, error) -} - -type anyResolver struct{ AnyResolver } - -func (r anyResolver) FindMessageByName(message protoreflect.FullName) (protoreflect.MessageType, error) { - return r.FindMessageByURL(string(message)) -} - -func (r anyResolver) FindMessageByURL(url string) (protoreflect.MessageType, error) { - m, err := r.Resolve(url) - if err != nil { - return nil, err - } - return protoimpl.X.MessageTypeOf(m), nil -} - -func (r anyResolver) FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) { - return protoregistry.GlobalTypes.FindExtensionByName(field) -} - -func (r anyResolver) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) { - return protoregistry.GlobalTypes.FindExtensionByNumber(message, field) -} - -func wellKnownType(s protoreflect.FullName) string { - if s.Parent() == "google.protobuf" { - switch s.Name() { - case "Empty", "Any", - "BoolValue", "BytesValue", "StringValue", - "Int32Value", "UInt32Value", "FloatValue", - "Int64Value", "UInt64Value", "DoubleValue", - "Duration", "Timestamp", - "NullValue", "Struct", "Value", "ListValue": - return string(s.Name()) - } - } - return "" -} - -func isMessageSet(md protoreflect.MessageDescriptor) bool { - ms, ok := md.(interface{ IsMessageSet() bool }) - return ok && ms.IsMessageSet() -} diff --git a/vendor/github.com/golang/protobuf/ptypes/wrappers/wrappers.pb.go b/vendor/github.com/golang/protobuf/ptypes/wrappers/wrappers.pb.go deleted file mode 100644 index cc40f27ad3..0000000000 --- a/vendor/github.com/golang/protobuf/ptypes/wrappers/wrappers.pb.go +++ /dev/null @@ -1,71 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: github.com/golang/protobuf/ptypes/wrappers/wrappers.proto - -package wrappers - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" - reflect "reflect" -) - -// Symbols defined in public import of google/protobuf/wrappers.proto. - -type DoubleValue = wrapperspb.DoubleValue -type FloatValue = wrapperspb.FloatValue -type Int64Value = wrapperspb.Int64Value -type UInt64Value = wrapperspb.UInt64Value -type Int32Value = wrapperspb.Int32Value -type UInt32Value = wrapperspb.UInt32Value -type BoolValue = wrapperspb.BoolValue -type StringValue = wrapperspb.StringValue -type BytesValue = wrapperspb.BytesValue - -var File_github_com_golang_protobuf_ptypes_wrappers_wrappers_proto protoreflect.FileDescriptor - -var file_github_com_golang_protobuf_ptypes_wrappers_wrappers_proto_rawDesc = []byte{ - 0x0a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, - 0x61, 0x6e, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2f, 0x77, 0x72, 0x61, - 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, - 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x42, 0x35, 0x5a, 0x33, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x3b, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, - 0x72, 0x73, 0x50, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var file_github_com_golang_protobuf_ptypes_wrappers_wrappers_proto_goTypes = []interface{}{} -var file_github_com_golang_protobuf_ptypes_wrappers_wrappers_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_github_com_golang_protobuf_ptypes_wrappers_wrappers_proto_init() } -func file_github_com_golang_protobuf_ptypes_wrappers_wrappers_proto_init() { - if File_github_com_golang_protobuf_ptypes_wrappers_wrappers_proto != nil { - return - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_github_com_golang_protobuf_ptypes_wrappers_wrappers_proto_rawDesc, - NumEnums: 0, - NumMessages: 0, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_github_com_golang_protobuf_ptypes_wrappers_wrappers_proto_goTypes, - DependencyIndexes: file_github_com_golang_protobuf_ptypes_wrappers_wrappers_proto_depIdxs, - }.Build() - File_github_com_golang_protobuf_ptypes_wrappers_wrappers_proto = out.File - file_github_com_golang_protobuf_ptypes_wrappers_wrappers_proto_rawDesc = nil - file_github_com_golang_protobuf_ptypes_wrappers_wrappers_proto_goTypes = nil - file_github_com_golang_protobuf_ptypes_wrappers_wrappers_proto_depIdxs = nil -} diff --git a/vendor/github.com/google/cel-go/cel/BUILD.bazel b/vendor/github.com/google/cel-go/cel/BUILD.bazel index e973abfc54..ddddbd2804 100644 --- a/vendor/github.com/google/cel-go/cel/BUILD.bazel +++ b/vendor/github.com/google/cel-go/cel/BUILD.bazel @@ -23,6 +23,7 @@ go_library( "//checker/decls:go_default_library", "//common:go_default_library", "//common/containers:go_default_library", + "//common/operators:go_default_library", "//common/overloads:go_default_library", "//common/types:go_default_library", "//common/types/pb:go_default_library", diff --git a/vendor/github.com/google/cel-go/cel/decls.go b/vendor/github.com/google/cel-go/cel/decls.go index f2df721d07..c0624d1e59 100644 --- a/vendor/github.com/google/cel-go/cel/decls.go +++ b/vendor/github.com/google/cel-go/cel/decls.go @@ -139,7 +139,7 @@ var ( kind: TypeKind, runtimeType: types.TypeType, } - //UintType represents a uint type. + // UintType represents a uint type. UintType = &Type{ kind: UintKind, runtimeType: types.UintType, @@ -222,7 +222,8 @@ func (t *Type) equals(other *Type) bool { // - The from types are the same instance // - The target type is dynamic // - The fromType has the same kind and type name as the target type, and all parameters of the target type -// are IsAssignableType() from the parameters of the fromType. +// +// are IsAssignableType() from the parameters of the fromType. func (t *Type) defaultIsAssignableType(fromType *Type) bool { if t == fromType || t.isDyn() { return true @@ -312,6 +313,11 @@ func NullableType(wrapped *Type) *Type { } } +// OptionalType creates an abstract parameterized type instance corresponding to CEL's notion of optional. +func OptionalType(param *Type) *Type { + return OpaqueType("optional", param) +} + // OpaqueType creates an abstract parameterized type with a given name. func OpaqueType(name string, params ...*Type) *Type { return &Type{ @@ -365,7 +371,9 @@ func Variable(name string, t *Type) EnvOption { // // - Overloads are searched in the order they are declared // - Dynamic dispatch for lists and maps is limited by inspection of the list and map contents -// at runtime. Empty lists and maps will result in a 'default dispatch' +// +// at runtime. Empty lists and maps will result in a 'default dispatch' +// // - In the event that a default dispatch occurs, the first overload provided is the one invoked // // If you intend to use overloads which differentiate based on the key or element type of a list or @@ -405,7 +413,7 @@ func Function(name string, opts ...FunctionOpt) EnvOption { // FunctionOpt defines a functional option for configuring a function declaration. type FunctionOpt func(*functionDecl) (*functionDecl, error) -// SingletonUnaryBinding creates a singleton function defintion to be used for all function overloads. +// SingletonUnaryBinding creates a singleton function definition to be used for all function overloads. // // Note, this approach works well if operand is expected to have a specific trait which it implements, // e.g. traits.ContainerType. Otherwise, prefer per-overload function bindings. @@ -431,7 +439,17 @@ func SingletonUnaryBinding(fn functions.UnaryOp, traits ...int) FunctionOpt { // // Note, this approach works well if operand is expected to have a specific trait which it implements, // e.g. traits.ContainerType. Otherwise, prefer per-overload function bindings. +// +// Deprecated: use SingletonBinaryBinding func SingletonBinaryImpl(fn functions.BinaryOp, traits ...int) FunctionOpt { + return SingletonBinaryBinding(fn, traits...) +} + +// SingletonBinaryBinding creates a singleton function definition to be used with all function overloads. +// +// Note, this approach works well if operand is expected to have a specific trait which it implements, +// e.g. traits.ContainerType. Otherwise, prefer per-overload function bindings. +func SingletonBinaryBinding(fn functions.BinaryOp, traits ...int) FunctionOpt { trait := 0 for _, t := range traits { trait = trait | t @@ -453,7 +471,17 @@ func SingletonBinaryImpl(fn functions.BinaryOp, traits ...int) FunctionOpt { // // Note, this approach works well if operand is expected to have a specific trait which it implements, // e.g. traits.ContainerType. Otherwise, prefer per-overload function bindings. +// +// Deprecated: use SingletonFunctionBinding func SingletonFunctionImpl(fn functions.FunctionOp, traits ...int) FunctionOpt { + return SingletonFunctionBinding(fn, traits...) +} + +// SingletonFunctionBinding creates a singleton function definition to be used with all function overloads. +// +// Note, this approach works well if operand is expected to have a specific trait which it implements, +// e.g. traits.ContainerType. Otherwise, prefer per-overload function bindings. +func SingletonFunctionBinding(fn functions.FunctionOp, traits ...int) FunctionOpt { trait := 0 for _, t := range traits { trait = trait | t @@ -720,9 +748,8 @@ func (f *functionDecl) addOverload(overload *overloadDecl) error { // Allow redefinition of an overload implementation so long as the signatures match. f.overloads[index] = overload return nil - } else { - return fmt.Errorf("overload redefinition in function. %s: %s has multiple definitions", f.name, o.id) } + return fmt.Errorf("overload redefinition in function. %s: %s has multiple definitions", f.name, o.id) } } f.overloads = append(f.overloads, overload) @@ -1177,3 +1204,43 @@ func collectParamNames(paramNames map[string]struct{}, arg *Type) { collectParamNames(paramNames, param) } } + +func typeValueToKind(tv *types.TypeValue) (Kind, error) { + switch tv { + case types.BoolType: + return BoolKind, nil + case types.DoubleType: + return DoubleKind, nil + case types.IntType: + return IntKind, nil + case types.UintType: + return UintKind, nil + case types.ListType: + return ListKind, nil + case types.MapType: + return MapKind, nil + case types.StringType: + return StringKind, nil + case types.BytesType: + return BytesKind, nil + case types.DurationType: + return DurationKind, nil + case types.TimestampType: + return TimestampKind, nil + case types.NullType: + return NullTypeKind, nil + case types.TypeType: + return TypeKind, nil + default: + switch tv.TypeName() { + case "dyn": + return DynKind, nil + case "google.protobuf.Any": + return AnyKind, nil + case "optional": + return OpaqueKind, nil + default: + return 0, fmt.Errorf("no known conversion for type of %s", tv.TypeName()) + } + } +} diff --git a/vendor/github.com/google/cel-go/cel/env.go b/vendor/github.com/google/cel-go/cel/env.go index 4e9ecdd648..9dc0ff5bb1 100644 --- a/vendor/github.com/google/cel-go/cel/env.go +++ b/vendor/github.com/google/cel-go/cel/env.go @@ -102,15 +102,18 @@ type Env struct { provider ref.TypeProvider features map[int]bool appliedFeatures map[int]bool + libraries map[string]bool // Internal parser representation - prsr *parser.Parser + prsr *parser.Parser + prsrOpts []parser.Option // Internal checker representation - chk *checker.Env - chkErr error - chkOnce sync.Once - chkOpts []checker.Option + chkMutex sync.Mutex + chk *checker.Env + chkErr error + chkOnce sync.Once + chkOpts []checker.Option // Program options tied to the environment progOpts []ProgramOption @@ -159,6 +162,7 @@ func NewCustomEnv(opts ...EnvOption) (*Env, error) { provider: registry, features: map[int]bool{}, appliedFeatures: map[int]bool{}, + libraries: map[string]bool{}, progOpts: []ProgramOption{}, }).configure(opts) } @@ -175,14 +179,14 @@ func (e *Env) Check(ast *Ast) (*Ast, *Issues) { pe, _ := AstToParsedExpr(ast) // Construct the internal checker env, erroring if there is an issue adding the declarations. - err := e.initChecker() + chk, err := e.initChecker() if err != nil { errs := common.NewErrors(ast.Source()) - errs.ReportError(common.NoLocation, e.chkErr.Error()) + errs.ReportError(common.NoLocation, err.Error()) return nil, NewIssues(errs) } - res, errs := checker.Check(pe, ast.Source(), e.chk) + res, errs := checker.Check(pe, ast.Source(), chk) if len(errs.GetErrors()) > 0 { return nil, NewIssues(errs) } @@ -236,10 +240,14 @@ func (e *Env) CompileSource(src Source) (*Ast, *Issues) { // TypeProvider are immutable, or that their underlying implementations are based on the // ref.TypeRegistry which provides a Copy method which will be invoked by this method. func (e *Env) Extend(opts ...EnvOption) (*Env, error) { - if e.chkErr != nil { - return nil, e.chkErr + chk, chkErr := e.getCheckerOrError() + if chkErr != nil { + return nil, chkErr } + prsrOptsCopy := make([]parser.Option, len(e.prsrOpts)) + copy(prsrOptsCopy, e.prsrOpts) + // The type-checker is configured with Declarations. The declarations may either be provided // as options which have not yet been validated, or may come from a previous checker instance // whose types have already been validated. @@ -248,10 +256,10 @@ func (e *Env) Extend(opts ...EnvOption) (*Env, error) { // Copy the declarations if needed. decsCopy := []*exprpb.Decl{} - if e.chk != nil { + if chk != nil { // If the type-checker has already been instantiated, then the e.declarations have been - // valdiated within the chk instance. - chkOptsCopy = append(chkOptsCopy, checker.ValidatedDeclarations(e.chk)) + // validated within the chk instance. + chkOptsCopy = append(chkOptsCopy, checker.ValidatedDeclarations(chk)) } else { // If the type-checker has not been instantiated, ensure the unvalidated declarations are // provided to the extended Env instance. @@ -304,8 +312,11 @@ func (e *Env) Extend(opts ...EnvOption) (*Env, error) { for k, v := range e.functions { funcsCopy[k] = v } + libsCopy := make(map[string]bool, len(e.libraries)) + for k, v := range e.libraries { + libsCopy[k] = v + } - // TODO: functions copy needs to happen here. ext := &Env{ Container: e.Container, declarations: decsCopy, @@ -315,8 +326,10 @@ func (e *Env) Extend(opts ...EnvOption) (*Env, error) { adapter: adapter, features: featuresCopy, appliedFeatures: appliedFeaturesCopy, + libraries: libsCopy, provider: provider, chkOpts: chkOptsCopy, + prsrOpts: prsrOptsCopy, } return ext.configure(opts) } @@ -328,6 +341,12 @@ func (e *Env) HasFeature(flag int) bool { return has && enabled } +// HasLibrary returns whether a specific SingletonLibrary has been configured in the environment. +func (e *Env) HasLibrary(libName string) bool { + configured, exists := e.libraries[libName] + return exists && configured +} + // Parse parses the input expression value `txt` to a Ast and/or a set of Issues. // // This form of Parse creates a Source value for the input `txt` and forwards to the @@ -422,8 +441,8 @@ func (e *Env) UnknownVars() interpreter.PartialActivation { // TODO: Consider adding an option to generate a Program.Residual to avoid round-tripping to an // Ast format and then Program again. func (e *Env) ResidualAst(a *Ast, details *EvalDetails) (*Ast, error) { - pruned := interpreter.PruneAst(a.Expr(), details.State()) - expr, err := AstToString(ParsedExprToAst(&exprpb.ParsedExpr{Expr: pruned})) + pruned := interpreter.PruneAst(a.Expr(), a.SourceInfo().GetMacroCalls(), details.State()) + expr, err := AstToString(ParsedExprToAst(pruned)) if err != nil { return nil, err } @@ -464,17 +483,9 @@ func (e *Env) configure(opts []EnvOption) (*Env, error) { } // If the default UTC timezone fix has been enabled, make sure the library is configured - if e.HasFeature(featureDefaultUTCTimeZone) { - if _, found := e.appliedFeatures[featureDefaultUTCTimeZone]; !found { - e, err = Lib(timeUTCLibrary{})(e) - if err != nil { - return nil, err - } - // record that the feature has been applied since it will generate declarations - // and functions which will be propagated on Extend() calls and which should only - // be registered once. - e.appliedFeatures[featureDefaultUTCTimeZone] = true - } + e, err = e.maybeApplyFeature(featureDefaultUTCTimeZone, Lib(timeUTCLibrary{})) + if err != nil { + return nil, err } // Initialize all of the functions configured within the environment. @@ -486,7 +497,10 @@ func (e *Env) configure(opts []EnvOption) (*Env, error) { } // Configure the parser. - prsrOpts := []parser.Option{parser.Macros(e.macros...)} + prsrOpts := []parser.Option{} + prsrOpts = append(prsrOpts, e.prsrOpts...) + prsrOpts = append(prsrOpts, parser.Macros(e.macros...)) + if e.HasFeature(featureEnableMacroCallTracking) { prsrOpts = append(prsrOpts, parser.PopulateMacroCalls(true)) } @@ -497,7 +511,7 @@ func (e *Env) configure(opts []EnvOption) (*Env, error) { // Ensure that the checker init happens eagerly rather than lazily. if e.HasFeature(featureEagerlyValidateDeclarations) { - err := e.initChecker() + _, err := e.initChecker() if err != nil { return nil, err } @@ -506,7 +520,7 @@ func (e *Env) configure(opts []EnvOption) (*Env, error) { return e, nil } -func (e *Env) initChecker() error { +func (e *Env) initChecker() (*checker.Env, error) { e.chkOnce.Do(func() { chkOpts := []checker.Option{} chkOpts = append(chkOpts, e.chkOpts...) @@ -518,32 +532,68 @@ func (e *Env) initChecker() error { ce, err := checker.NewEnv(e.Container, e.provider, chkOpts...) if err != nil { - e.chkErr = err + e.setCheckerOrError(nil, err) return } // Add the statically configured declarations. err = ce.Add(e.declarations...) if err != nil { - e.chkErr = err + e.setCheckerOrError(nil, err) return } // Add the function declarations which are derived from the FunctionDecl instances. for _, fn := range e.functions { fnDecl, err := functionDeclToExprDecl(fn) if err != nil { - e.chkErr = err + e.setCheckerOrError(nil, err) return } err = ce.Add(fnDecl) if err != nil { - e.chkErr = err + e.setCheckerOrError(nil, err) return } } // Add function declarations here separately. - e.chk = ce + e.setCheckerOrError(ce, nil) }) - return e.chkErr + return e.getCheckerOrError() +} + +// setCheckerOrError sets the checker.Env or error state in a concurrency-safe manner +func (e *Env) setCheckerOrError(chk *checker.Env, chkErr error) { + e.chkMutex.Lock() + e.chk = chk + e.chkErr = chkErr + e.chkMutex.Unlock() +} + +// getCheckerOrError gets the checker.Env or error state in a concurrency-safe manner +func (e *Env) getCheckerOrError() (*checker.Env, error) { + e.chkMutex.Lock() + defer e.chkMutex.Unlock() + return e.chk, e.chkErr +} + +// maybeApplyFeature determines whether the feature-guarded option is enabled, and if so applies +// the feature if it has not already been enabled. +func (e *Env) maybeApplyFeature(feature int, option EnvOption) (*Env, error) { + if !e.HasFeature(feature) { + return e, nil + } + _, applied := e.appliedFeatures[feature] + if applied { + return e, nil + } + e, err := option(e) + if err != nil { + return nil, err + } + // record that the feature has been applied since it will generate declarations + // and functions which will be propagated on Extend() calls and which should only + // be registered once. + e.appliedFeatures[feature] = true + return e, nil } // Issues defines methods for inspecting the error details of parse and check calls. diff --git a/vendor/github.com/google/cel-go/cel/io.go b/vendor/github.com/google/cel-go/cel/io.go index e721c97f66..93ded3cf1b 100644 --- a/vendor/github.com/google/cel-go/cel/io.go +++ b/vendor/github.com/google/cel-go/cel/io.go @@ -19,14 +19,14 @@ import ( "fmt" "reflect" + "google.golang.org/protobuf/proto" + "github.com/google/cel-go/common" "github.com/google/cel-go/common/types" "github.com/google/cel-go/common/types/ref" "github.com/google/cel-go/common/types/traits" "github.com/google/cel-go/parser" - "google.golang.org/protobuf/proto" - exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1" anypb "google.golang.org/protobuf/types/known/anypb" ) diff --git a/vendor/github.com/google/cel-go/cel/library.go b/vendor/github.com/google/cel-go/cel/library.go index 5ca528459a..072cec30e6 100644 --- a/vendor/github.com/google/cel-go/cel/library.go +++ b/vendor/github.com/google/cel-go/cel/library.go @@ -20,10 +20,14 @@ import ( "time" "github.com/google/cel-go/checker" + "github.com/google/cel-go/common/operators" "github.com/google/cel-go/common/overloads" "github.com/google/cel-go/common/types" "github.com/google/cel-go/common/types/ref" + "github.com/google/cel-go/common/types/traits" + "github.com/google/cel-go/interpreter" "github.com/google/cel-go/interpreter/functions" + "github.com/google/cel-go/parser" ) // Library provides a collection of EnvOption and ProgramOption values used to configure a CEL @@ -42,10 +46,27 @@ type Library interface { ProgramOptions() []ProgramOption } +// SingletonLibrary refines the Library interface to ensure that libraries in this format are only +// configured once within the environment. +type SingletonLibrary interface { + Library + + // LibraryName provides a namespaced name which is used to check whether the library has already + // been configured in the environment. + LibraryName() string +} + // Lib creates an EnvOption out of a Library, allowing libraries to be provided as functional args, // and to be linked to each other. func Lib(l Library) EnvOption { + singleton, isSingleton := l.(SingletonLibrary) return func(e *Env) (*Env, error) { + if isSingleton { + if e.HasLibrary(singleton.LibraryName()) { + return e, nil + } + e.libraries[singleton.LibraryName()] = true + } var err error for _, opt := range l.CompileOptions() { e, err = opt(e) @@ -67,6 +88,11 @@ func StdLib() EnvOption { // features documented in the specification. type stdLibrary struct{} +// LibraryName implements the SingletonLibrary interface method. +func (stdLibrary) LibraryName() string { + return "cel.lib.std" +} + // EnvOptions returns options for the standard CEL function declarations and macros. func (stdLibrary) CompileOptions() []EnvOption { return []EnvOption{ @@ -82,6 +108,191 @@ func (stdLibrary) ProgramOptions() []ProgramOption { } } +type optionalLibrary struct{} + +// LibraryName implements the SingletonLibrary interface method. +func (optionalLibrary) LibraryName() string { + return "cel.lib.optional" +} + +// CompileOptions implements the Library interface method. +func (optionalLibrary) CompileOptions() []EnvOption { + paramTypeK := TypeParamType("K") + paramTypeV := TypeParamType("V") + optionalTypeV := OptionalType(paramTypeV) + listTypeV := ListType(paramTypeV) + mapTypeKV := MapType(paramTypeK, paramTypeV) + + return []EnvOption{ + // Enable the optional syntax in the parser. + enableOptionalSyntax(), + + // Introduce the optional type. + Types(types.OptionalType), + + // Global and member functions for working with optional values. + Function("optional.of", + Overload("optional_of", []*Type{paramTypeV}, optionalTypeV, + UnaryBinding(func(value ref.Val) ref.Val { + return types.OptionalOf(value) + }))), + Function("optional.ofNonZeroValue", + Overload("optional_ofNonZeroValue", []*Type{paramTypeV}, optionalTypeV, + UnaryBinding(func(value ref.Val) ref.Val { + v, isZeroer := value.(traits.Zeroer) + if !isZeroer || !v.IsZeroValue() { + return types.OptionalOf(value) + } + return types.OptionalNone + }))), + Function("optional.none", + Overload("optional_none", []*Type{}, optionalTypeV, + FunctionBinding(func(values ...ref.Val) ref.Val { + return types.OptionalNone + }))), + Function("value", + MemberOverload("optional_value", []*Type{optionalTypeV}, paramTypeV, + UnaryBinding(func(value ref.Val) ref.Val { + opt := value.(*types.Optional) + return opt.GetValue() + }))), + Function("hasValue", + MemberOverload("optional_hasValue", []*Type{optionalTypeV}, BoolType, + UnaryBinding(func(value ref.Val) ref.Val { + opt := value.(*types.Optional) + return types.Bool(opt.HasValue()) + }))), + + // Implementation of 'or' and 'orValue' are special-cased to support short-circuiting in the + // evaluation chain. + Function("or", + MemberOverload("optional_or_optional", []*Type{optionalTypeV, optionalTypeV}, optionalTypeV)), + Function("orValue", + MemberOverload("optional_orValue_value", []*Type{optionalTypeV, paramTypeV}, paramTypeV)), + + // OptSelect is handled specially by the type-checker, so the receiver's field type is used to determine the + // optput type. + Function(operators.OptSelect, + Overload("select_optional_field", []*Type{DynType, StringType}, optionalTypeV)), + + // OptIndex is handled mostly like any other indexing operation on a list or map, so the type-checker can use + // these signatures to determine type-agreement without any special handling. + Function(operators.OptIndex, + Overload("list_optindex_optional_int", []*Type{listTypeV, IntType}, optionalTypeV), + Overload("optional_list_optindex_optional_int", []*Type{OptionalType(listTypeV), IntType}, optionalTypeV), + Overload("map_optindex_optional_value", []*Type{mapTypeKV, paramTypeK}, optionalTypeV), + Overload("optional_map_optindex_optional_value", []*Type{OptionalType(mapTypeKV), paramTypeK}, optionalTypeV)), + + // Index overloads to accommodate using an optional value as the operand. + Function(operators.Index, + Overload("optional_list_index_int", []*Type{OptionalType(listTypeV), IntType}, optionalTypeV), + Overload("optional_map_index_optional_value", []*Type{OptionalType(mapTypeKV), paramTypeK}, optionalTypeV)), + } +} + +// ProgramOptions implements the Library interface method. +func (optionalLibrary) ProgramOptions() []ProgramOption { + return []ProgramOption{ + CustomDecorator(decorateOptionalOr), + } +} + +func enableOptionalSyntax() EnvOption { + return func(e *Env) (*Env, error) { + e.prsrOpts = append(e.prsrOpts, parser.EnableOptionalSyntax(true)) + return e, nil + } +} + +func decorateOptionalOr(i interpreter.Interpretable) (interpreter.Interpretable, error) { + call, ok := i.(interpreter.InterpretableCall) + if !ok { + return i, nil + } + args := call.Args() + if len(args) != 2 { + return i, nil + } + switch call.Function() { + case "or": + if call.OverloadID() != "" && call.OverloadID() != "optional_or_optional" { + return i, nil + } + return &evalOptionalOr{ + id: call.ID(), + lhs: args[0], + rhs: args[1], + }, nil + case "orValue": + if call.OverloadID() != "" && call.OverloadID() != "optional_orValue_value" { + return i, nil + } + return &evalOptionalOrValue{ + id: call.ID(), + lhs: args[0], + rhs: args[1], + }, nil + default: + return i, nil + } +} + +// evalOptionalOr selects between two optional values, either the first if it has a value, or +// the second optional expression is evaluated and returned. +type evalOptionalOr struct { + id int64 + lhs interpreter.Interpretable + rhs interpreter.Interpretable +} + +// ID implements the Interpretable interface method. +func (opt *evalOptionalOr) ID() int64 { + return opt.id +} + +// Eval evaluates the left-hand side optional to determine whether it contains a value, else +// proceeds with the right-hand side evaluation. +func (opt *evalOptionalOr) Eval(ctx interpreter.Activation) ref.Val { + // short-circuit lhs. + optLHS := opt.lhs.Eval(ctx) + optVal, ok := optLHS.(*types.Optional) + if !ok { + return optLHS + } + if optVal.HasValue() { + return optVal + } + return opt.rhs.Eval(ctx) +} + +// evalOptionalOrValue selects between an optional or a concrete value. If the optional has a value, +// its value is returned, otherwise the alternative value expression is evaluated and returned. +type evalOptionalOrValue struct { + id int64 + lhs interpreter.Interpretable + rhs interpreter.Interpretable +} + +// ID implements the Interpretable interface method. +func (opt *evalOptionalOrValue) ID() int64 { + return opt.id +} + +// Eval evaluates the left-hand side optional to determine whether it contains a value, else +// proceeds with the right-hand side evaluation. +func (opt *evalOptionalOrValue) Eval(ctx interpreter.Activation) ref.Val { + // short-circuit lhs. + optLHS := opt.lhs.Eval(ctx) + optVal, ok := optLHS.(*types.Optional) + if !ok { + return optLHS + } + if optVal.HasValue() { + return optVal.GetValue() + } + return opt.rhs.Eval(ctx) +} + type timeUTCLibrary struct{} func (timeUTCLibrary) CompileOptions() []EnvOption { diff --git a/vendor/github.com/google/cel-go/cel/macro.go b/vendor/github.com/google/cel-go/cel/macro.go index e43cb4eeea..e48c5bf8ee 100644 --- a/vendor/github.com/google/cel-go/cel/macro.go +++ b/vendor/github.com/google/cel-go/cel/macro.go @@ -17,6 +17,7 @@ package cel import ( "github.com/google/cel-go/common" "github.com/google/cel-go/parser" + exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1" ) @@ -26,8 +27,11 @@ import ( // a Macro should be created per arg-count or as a var arg macro. type Macro = parser.Macro -// MacroExpander converts a call and its associated arguments into a new CEL abstract syntax tree, or an error -// if the input arguments are not suitable for the expansion requirements for the macro in question. +// MacroExpander converts a call and its associated arguments into a new CEL abstract syntax tree. +// +// If the MacroExpander determines within the implementation that an expansion is not needed it may return +// a nil Expr value to indicate a non-match. However, if an expansion is to be performed, but the arguments +// are not well-formed, the result of the expansion will be an error. // // The MacroExpander accepts as arguments a MacroExprHelper as well as the arguments used in the function call // and produces as output an Expr ast node. @@ -81,8 +85,10 @@ func ExistsOneMacroExpander(meh MacroExprHelper, target *exprpb.Expr, args []*ex // input to produce an output list. // // There are two call patterns supported by map: -// .map(, ) -// .map(, , ) +// +// .map(, ) +// .map(, , ) +// // In the second form only iterVar values which return true when provided to the predicate expression // are transformed. func MapMacroExpander(meh MacroExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *common.Error) { diff --git a/vendor/github.com/google/cel-go/cel/options.go b/vendor/github.com/google/cel-go/cel/options.go index 21c7570106..63321b5481 100644 --- a/vendor/github.com/google/cel-go/cel/options.go +++ b/vendor/github.com/google/cel-go/cel/options.go @@ -29,6 +29,7 @@ import ( "github.com/google/cel-go/common/types/ref" "github.com/google/cel-go/interpreter" "github.com/google/cel-go/interpreter/functions" + "github.com/google/cel-go/parser" exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1" descpb "google.golang.org/protobuf/types/descriptorpb" @@ -61,6 +62,10 @@ const ( // on a CEL timestamp operation. This fixes the scenario where the input time // is not already in UTC. featureDefaultUTCTimeZone + + // Enable the use of optional types in the syntax, type-system, type-checking, + // and runtime. + featureOptionalTypes ) // EnvOption is a functional interface for configuring the environment. @@ -163,19 +168,19 @@ func Container(name string) EnvOption { // Abbreviations can be useful when working with variables, functions, and especially types from // multiple namespaces: // -// // CEL object construction -// qual.pkg.version.ObjTypeName{ -// field: alt.container.ver.FieldTypeName{value: ...} -// } +// // CEL object construction +// qual.pkg.version.ObjTypeName{ +// field: alt.container.ver.FieldTypeName{value: ...} +// } // // Only one the qualified names above may be used as the CEL container, so at least one of these // references must be a long qualified name within an otherwise short CEL program. Using the // following abbreviations, the program becomes much simpler: // -// // CEL Go option -// Abbrevs("qual.pkg.version.ObjTypeName", "alt.container.ver.FieldTypeName") -// // Simplified Object construction -// ObjTypeName{field: FieldTypeName{value: ...}} +// // CEL Go option +// Abbrevs("qual.pkg.version.ObjTypeName", "alt.container.ver.FieldTypeName") +// // Simplified Object construction +// ObjTypeName{field: FieldTypeName{value: ...}} // // There are a few rules for the qualified names and the simple abbreviations generated from them: // - Qualified names must be dot-delimited, e.g. `package.subpkg.name`. @@ -188,9 +193,12 @@ func Container(name string) EnvOption { // - Expanded abbreviations do not participate in namespace resolution. // - Abbreviation expansion is done instead of the container search for a matching identifier. // - Containers follow C++ namespace resolution rules with searches from the most qualified name -// to the least qualified name. +// +// to the least qualified name. +// // - Container references within the CEL program may be relative, and are resolved to fully -// qualified names at either type-check time or program plan time, whichever comes first. +// +// qualified names at either type-check time or program plan time, whichever comes first. // // If there is ever a case where an identifier could be in both the container and as an // abbreviation, the abbreviation wins as this will ensure that the meaning of a program is @@ -216,7 +224,7 @@ func Abbrevs(qualifiedNames ...string) EnvOption { // environment by default. // // Note: This option must be specified after the CustomTypeProvider option when used together. -func Types(addTypes ...interface{}) EnvOption { +func Types(addTypes ...any) EnvOption { return func(e *Env) (*Env, error) { reg, isReg := e.provider.(ref.TypeRegistry) if !isReg { @@ -253,7 +261,7 @@ func Types(addTypes ...interface{}) EnvOption { // // TypeDescs are hermetic to a single Env object, but may be copied to other Env values via // extension or by re-using the same EnvOption with another NewEnv() call. -func TypeDescs(descs ...interface{}) EnvOption { +func TypeDescs(descs ...any) EnvOption { return func(e *Env) (*Env, error) { reg, isReg := e.provider.(ref.TypeRegistry) if !isReg { @@ -350,8 +358,8 @@ func Functions(funcs ...*functions.Overload) ProgramOption { // variables with the same name provided to the Eval() call. If Globals is used in a Library with // a Lib EnvOption, vars may shadow variables provided by previously added libraries. // -// The vars value may either be an `interpreter.Activation` instance or a `map[string]interface{}`. -func Globals(vars interface{}) ProgramOption { +// The vars value may either be an `interpreter.Activation` instance or a `map[string]any`. +func Globals(vars any) ProgramOption { return func(p *prog) (*prog, error) { defaultVars, err := interpreter.NewActivation(vars) if err != nil { @@ -404,6 +412,9 @@ const ( // OptTrackCost enables the runtime cost calculation while validation and return cost within evalDetails // cost calculation is available via func ActualCost() OptTrackCost EvalOption = 1 << iota + + // OptCheckStringFormat enables compile-time checking of string.format calls for syntax/cardinality. + OptCheckStringFormat EvalOption = 1 << iota ) // EvalOptions sets one or more evaluation options which may affect the evaluation or Result. @@ -534,6 +545,13 @@ func DefaultUTCTimeZone(enabled bool) EnvOption { return features(featureDefaultUTCTimeZone, enabled) } +// OptionalTypes enable support for optional syntax and types in CEL. The optional value type makes +// it possible to express whether variables have been provided, whether a result has been computed, +// and in the future whether an object field path, map key value, or list index has a value. +func OptionalTypes() EnvOption { + return Lib(optionalLibrary{}) +} + // features sets the given feature flags. See list of Feature constants above. func features(flag int, enabled bool) EnvOption { return func(e *Env) (*Env, error) { @@ -541,3 +559,12 @@ func features(flag int, enabled bool) EnvOption { return e, nil } } + +// ParserRecursionLimit adjusts the AST depth the parser will tolerate. +// Defaults defined in the parser package. +func ParserRecursionLimit(limit int) EnvOption { + return func(e *Env) (*Env, error) { + e.prsrOpts = append(e.prsrOpts, parser.MaxRecursionDepth(limit)) + return e, nil + } +} diff --git a/vendor/github.com/google/cel-go/cel/program.go b/vendor/github.com/google/cel-go/cel/program.go index 672c83ef71..a630f5bfa1 100644 --- a/vendor/github.com/google/cel-go/cel/program.go +++ b/vendor/github.com/google/cel-go/cel/program.go @@ -17,21 +17,20 @@ package cel import ( "context" "fmt" - "math" "sync" - exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1" - "github.com/google/cel-go/common/types" "github.com/google/cel-go/common/types/ref" "github.com/google/cel-go/interpreter" + + exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1" ) // Program is an evaluable view of an Ast. type Program interface { // Eval returns the result of an evaluation of the Ast and environment against the input vars. // - // The vars value may either be an `interpreter.Activation` or a `map[string]interface{}`. + // The vars value may either be an `interpreter.Activation` or a `map[string]any`. // // If the `OptTrackState`, `OptTrackCost` or `OptExhaustiveEval` flags are used, the `details` response will // be non-nil. Given this caveat on `details`, the return state from evaluation will be: @@ -43,16 +42,16 @@ type Program interface { // An unsuccessful evaluation is typically the result of a series of incompatible `EnvOption` // or `ProgramOption` values used in the creation of the evaluation environment or executable // program. - Eval(interface{}) (ref.Val, *EvalDetails, error) + Eval(any) (ref.Val, *EvalDetails, error) // ContextEval evaluates the program with a set of input variables and a context object in order // to support cancellation and timeouts. This method must be used in conjunction with the // InterruptCheckFrequency() option for cancellation interrupts to be impact evaluation. // - // The vars value may either be an `interpreter.Activation` or `map[string]interface{}`. + // The vars value may either be an `interpreter.Activation` or `map[string]any`. // // The output contract for `ContextEval` is otherwise identical to the `Eval` method. - ContextEval(context.Context, interface{}) (ref.Val, *EvalDetails, error) + ContextEval(context.Context, any) (ref.Val, *EvalDetails, error) } // NoVars returns an empty Activation. @@ -65,7 +64,7 @@ func NoVars() interpreter.Activation { // // The `vars` value may either be an interpreter.Activation or any valid input to the // interpreter.NewActivation call. -func PartialVars(vars interface{}, +func PartialVars(vars any, unknowns ...*interpreter.AttributePattern) (interpreter.PartialActivation, error) { return interpreter.NewPartialActivation(vars, unknowns...) } @@ -207,13 +206,47 @@ func newProgram(e *Env, ast *Ast, opts []ProgramOption) (Program, error) { if len(p.regexOptimizations) > 0 { decorators = append(decorators, interpreter.CompileRegexConstants(p.regexOptimizations...)) } + // Enable compile-time checking of syntax/cardinality for string.format calls. + if p.evalOpts&OptCheckStringFormat == OptCheckStringFormat { + var isValidType func(id int64, validTypes ...*types.TypeValue) (bool, error) + if ast.IsChecked() { + isValidType = func(id int64, validTypes ...*types.TypeValue) (bool, error) { + t, err := ExprTypeToType(ast.typeMap[id]) + if err != nil { + return false, err + } + if t.kind == DynKind { + return true, nil + } + for _, vt := range validTypes { + k, err := typeValueToKind(vt) + if err != nil { + return false, err + } + if k == t.kind { + return true, nil + } + } + return false, nil + } + } else { + // if the AST isn't type-checked, short-circuit validation + isValidType = func(id int64, validTypes ...*types.TypeValue) (bool, error) { + return true, nil + } + } + decorators = append(decorators, interpreter.InterpolateFormattedString(isValidType)) + } // Enable exhaustive eval, state tracking and cost tracking last since they require a factory. if p.evalOpts&(OptExhaustiveEval|OptTrackState|OptTrackCost) != 0 { factory := func(state interpreter.EvalState, costTracker *interpreter.CostTracker) (Program, error) { costTracker.Estimator = p.callCostEstimator costTracker.Limit = p.costLimit - decs := decorators + // Limit capacity to guarantee a reallocation when calling 'append(decs, ...)' below. This + // prevents the underlying memory from being shared between factory function calls causing + // undesired mutations. + decs := decorators[:len(decorators):len(decorators)] var observers []interpreter.EvalObserver if p.evalOpts&(OptExhaustiveEval|OptTrackState) != 0 { @@ -265,7 +298,7 @@ func (p *prog) initInterpretable(ast *Ast, decs []interpreter.InterpretableDecor } // Eval implements the Program interface method. -func (p *prog) Eval(input interface{}) (v ref.Val, det *EvalDetails, err error) { +func (p *prog) Eval(input any) (v ref.Val, det *EvalDetails, err error) { // Configure error recovery for unexpected panics during evaluation. Note, the use of named // return values makes it possible to modify the error response during the recovery // function. @@ -284,11 +317,11 @@ func (p *prog) Eval(input interface{}) (v ref.Val, det *EvalDetails, err error) switch v := input.(type) { case interpreter.Activation: vars = v - case map[string]interface{}: + case map[string]any: vars = activationPool.Setup(v) defer activationPool.Put(vars) default: - return nil, nil, fmt.Errorf("invalid input, wanted Activation or map[string]interface{}, got: (%T)%v", input, input) + return nil, nil, fmt.Errorf("invalid input, wanted Activation or map[string]any, got: (%T)%v", input, input) } if p.defaultVars != nil { vars = interpreter.NewHierarchicalActivation(p.defaultVars, vars) @@ -304,7 +337,7 @@ func (p *prog) Eval(input interface{}) (v ref.Val, det *EvalDetails, err error) } // ContextEval implements the Program interface. -func (p *prog) ContextEval(ctx context.Context, input interface{}) (ref.Val, *EvalDetails, error) { +func (p *prog) ContextEval(ctx context.Context, input any) (ref.Val, *EvalDetails, error) { if ctx == nil { return nil, nil, fmt.Errorf("context can not be nil") } @@ -315,22 +348,17 @@ func (p *prog) ContextEval(ctx context.Context, input interface{}) (ref.Val, *Ev case interpreter.Activation: vars = ctxActivationPool.Setup(v, ctx.Done(), p.interruptCheckFrequency) defer ctxActivationPool.Put(vars) - case map[string]interface{}: + case map[string]any: rawVars := activationPool.Setup(v) defer activationPool.Put(rawVars) vars = ctxActivationPool.Setup(rawVars, ctx.Done(), p.interruptCheckFrequency) defer ctxActivationPool.Put(vars) default: - return nil, nil, fmt.Errorf("invalid input, wanted Activation or map[string]interface{}, got: (%T)%v", input, input) + return nil, nil, fmt.Errorf("invalid input, wanted Activation or map[string]any, got: (%T)%v", input, input) } return p.Eval(vars) } -// Cost implements the Coster interface method. -func (p *prog) Cost() (min, max int64) { - return estimateCost(p.interpretable) -} - // progFactory is a helper alias for marking a program creation factory function. type progFactory func(interpreter.EvalState, *interpreter.CostTracker) (Program, error) @@ -351,7 +379,7 @@ func newProgGen(factory progFactory) (Program, error) { } // Eval implements the Program interface method. -func (gen *progGen) Eval(input interface{}) (ref.Val, *EvalDetails, error) { +func (gen *progGen) Eval(input any) (ref.Val, *EvalDetails, error) { // The factory based Eval() differs from the standard evaluation model in that it generates a // new EvalState instance for each call to ensure that unique evaluations yield unique stateful // results. @@ -376,7 +404,7 @@ func (gen *progGen) Eval(input interface{}) (ref.Val, *EvalDetails, error) { } // ContextEval implements the Program interface method. -func (gen *progGen) ContextEval(ctx context.Context, input interface{}) (ref.Val, *EvalDetails, error) { +func (gen *progGen) ContextEval(ctx context.Context, input any) (ref.Val, *EvalDetails, error) { if ctx == nil { return nil, nil, fmt.Errorf("context can not be nil") } @@ -403,29 +431,6 @@ func (gen *progGen) ContextEval(ctx context.Context, input interface{}) (ref.Val return v, det, nil } -// Cost implements the Coster interface method. -func (gen *progGen) Cost() (min, max int64) { - // Use an empty state value since no evaluation is performed. - p, err := gen.factory(emptyEvalState, nil) - if err != nil { - return 0, math.MaxInt64 - } - return estimateCost(p) -} - -// EstimateCost returns the heuristic cost interval for the program. -func EstimateCost(p Program) (min, max int64) { - return estimateCost(p) -} - -func estimateCost(i interface{}) (min, max int64) { - c, ok := i.(interpreter.Coster) - if !ok { - return 0, math.MaxInt64 - } - return c.Cost() -} - type ctxEvalActivation struct { parent interpreter.Activation interrupt <-chan struct{} @@ -435,7 +440,7 @@ type ctxEvalActivation struct { // ResolveName implements the Activation interface method, but adds a special #interrupted variable // which is capable of testing whether a 'done' signal is provided from a context.Context channel. -func (a *ctxEvalActivation) ResolveName(name string) (interface{}, bool) { +func (a *ctxEvalActivation) ResolveName(name string) (any, bool) { if name == "#interrupted" { a.interruptCheckCount++ if a.interruptCheckCount%a.interruptCheckFrequency == 0 { @@ -458,7 +463,7 @@ func (a *ctxEvalActivation) Parent() interpreter.Activation { func newCtxEvalActivationPool() *ctxEvalActivationPool { return &ctxEvalActivationPool{ Pool: sync.Pool{ - New: func() interface{} { + New: func() any { return &ctxEvalActivation{} }, }, @@ -480,21 +485,21 @@ func (p *ctxEvalActivationPool) Setup(vars interpreter.Activation, done <-chan s } type evalActivation struct { - vars map[string]interface{} - lazyVars map[string]interface{} + vars map[string]any + lazyVars map[string]any } // ResolveName looks up the value of the input variable name, if found. // // Lazy bindings may be supplied within the map-based input in either of the following forms: -// - func() interface{} +// - func() any // - func() ref.Val // // The lazy binding will only be invoked once per evaluation. // // Values which are not represented as ref.Val types on input may be adapted to a ref.Val using // the ref.TypeAdapter configured in the environment. -func (a *evalActivation) ResolveName(name string) (interface{}, bool) { +func (a *evalActivation) ResolveName(name string) (any, bool) { v, found := a.vars[name] if !found { return nil, false @@ -507,7 +512,7 @@ func (a *evalActivation) ResolveName(name string) (interface{}, bool) { lazy := obj() a.lazyVars[name] = lazy return lazy, true - case func() interface{}: + case func() any: if resolved, found := a.lazyVars[name]; found { return resolved, true } @@ -527,8 +532,8 @@ func (a *evalActivation) Parent() interpreter.Activation { func newEvalActivationPool() *evalActivationPool { return &evalActivationPool{ Pool: sync.Pool{ - New: func() interface{} { - return &evalActivation{lazyVars: make(map[string]interface{})} + New: func() any { + return &evalActivation{lazyVars: make(map[string]any)} }, }, } @@ -539,13 +544,13 @@ type evalActivationPool struct { } // Setup initializes a pooled Activation object with the map input. -func (p *evalActivationPool) Setup(vars map[string]interface{}) *evalActivation { +func (p *evalActivationPool) Setup(vars map[string]any) *evalActivation { a := p.Pool.Get().(*evalActivation) a.vars = vars return a } -func (p *evalActivationPool) Put(value interface{}) { +func (p *evalActivationPool) Put(value any) { a := value.(*evalActivation) for k := range a.lazyVars { delete(a.lazyVars, k) @@ -556,7 +561,7 @@ func (p *evalActivationPool) Put(value interface{}) { var ( emptyEvalState = interpreter.NewEvalState() - // activationPool is an internally managed pool of Activation values that wrap map[string]interface{} inputs + // activationPool is an internally managed pool of Activation values that wrap map[string]any inputs activationPool = newEvalActivationPool() // ctxActivationPool is an internally managed pool of Activation values that expose a special #interrupted variable diff --git a/vendor/github.com/google/cel-go/checker/BUILD.bazel b/vendor/github.com/google/cel-go/checker/BUILD.bazel index bec40b6e69..ac2417b89d 100644 --- a/vendor/github.com/google/cel-go/checker/BUILD.bazel +++ b/vendor/github.com/google/cel-go/checker/BUILD.bazel @@ -54,7 +54,7 @@ go_test( "//test:go_default_library", "//test/proto2pb:go_default_library", "//test/proto3pb:go_default_library", - "@com_github_antlr_antlr4_runtime_go_antlr//:go_default_library", + "@com_github_antlr_antlr4_runtime_go_antlr_v4//:go_default_library", "@org_golang_google_protobuf//proto:go_default_library", ], ) diff --git a/vendor/github.com/google/cel-go/checker/checker.go b/vendor/github.com/google/cel-go/checker/checker.go index fcddb1b2c2..257cffecf6 100644 --- a/vendor/github.com/google/cel-go/checker/checker.go +++ b/vendor/github.com/google/cel-go/checker/checker.go @@ -23,6 +23,7 @@ import ( "github.com/google/cel-go/checker/decls" "github.com/google/cel-go/common" "github.com/google/cel-go/common/containers" + "github.com/google/cel-go/common/operators" "github.com/google/cel-go/common/types/ref" "google.golang.org/protobuf/proto" @@ -173,8 +174,8 @@ func (c *checker) checkSelect(e *exprpb.Expr) { // Rewrite the node to be a variable reference to the resolved fully-qualified // variable name. - c.setType(e, ident.GetIdent().Type) - c.setReference(e, newIdentReference(ident.GetName(), ident.GetIdent().Value)) + c.setType(e, ident.GetIdent().GetType()) + c.setReference(e, newIdentReference(ident.GetName(), ident.GetIdent().GetValue())) identName := ident.GetName() e.ExprKind = &exprpb.Expr_IdentExpr{ IdentExpr: &exprpb.Expr_Ident{ @@ -185,9 +186,37 @@ func (c *checker) checkSelect(e *exprpb.Expr) { } } + resultType := c.checkSelectField(e, sel.GetOperand(), sel.GetField(), false) + if sel.TestOnly { + resultType = decls.Bool + } + c.setType(e, substitute(c.mappings, resultType, false)) +} + +func (c *checker) checkOptSelect(e *exprpb.Expr) { + // Collect metadata related to the opt select call packaged by the parser. + call := e.GetCallExpr() + operand := call.GetArgs()[0] + field := call.GetArgs()[1] + fieldName, isString := maybeUnwrapString(field) + if !isString { + c.errors.ReportError(c.location(field), "unsupported optional field selection: %v", field) + return + } + + // Perform type-checking using the field selection logic. + resultType := c.checkSelectField(e, operand, fieldName, true) + c.setType(e, substitute(c.mappings, resultType, false)) +} + +func (c *checker) checkSelectField(e, operand *exprpb.Expr, field string, optional bool) *exprpb.Type { // Interpret as field selection, first traversing down the operand. - c.check(sel.GetOperand()) - targetType := substitute(c.mappings, c.getType(sel.GetOperand()), false) + c.check(operand) + operandType := substitute(c.mappings, c.getType(operand), false) + + // If the target type is 'optional', unwrap it for the sake of this check. + targetType, isOpt := maybeUnwrapOptional(operandType) + // Assume error type by default as most types do not support field selection. resultType := decls.Error switch kindOf(targetType) { @@ -199,7 +228,7 @@ func (c *checker) checkSelect(e *exprpb.Expr) { // Objects yield their field type declaration as the selection result type, but only if // the field is defined. messageType := targetType - if fieldType, found := c.lookupFieldType(c.location(e), messageType.GetMessageType(), sel.GetField()); found { + if fieldType, found := c.lookupFieldType(c.location(e), messageType.GetMessageType(), field); found { resultType = fieldType.Type } case kindTypeParam: @@ -212,16 +241,17 @@ func (c *checker) checkSelect(e *exprpb.Expr) { default: // Dynamic / error values are treated as DYN type. Errors are handled this way as well // in order to allow forward progress on the check. - if isDynOrError(targetType) { - resultType = decls.Dyn - } else { + if !isDynOrError(targetType) { c.errors.typeDoesNotSupportFieldSelection(c.location(e), targetType) } + resultType = decls.Dyn } - if sel.TestOnly { - resultType = decls.Bool + + // If the target type was optional coming in, then the result must be optional going out. + if isOpt || optional { + return decls.NewOptionalType(resultType) } - c.setType(e, substitute(c.mappings, resultType, false)) + return resultType } func (c *checker) checkCall(e *exprpb.Expr) { @@ -229,15 +259,19 @@ func (c *checker) checkCall(e *exprpb.Expr) { // please consider the impact on planner.go and consolidate implementations or mirror code // as appropriate. call := e.GetCallExpr() - target := call.GetTarget() - args := call.GetArgs() fnName := call.GetFunction() + if fnName == operators.OptSelect { + c.checkOptSelect(e) + return + } + args := call.GetArgs() // Traverse arguments. for _, arg := range args { c.check(arg) } + target := call.GetTarget() // Regular static call with simple name. if target == nil { // Check for the existence of the function. @@ -359,6 +393,9 @@ func (c *checker) resolveOverload( } if resultType == nil { + for i, arg := range argTypes { + argTypes[i] = substitute(c.mappings, arg, true) + } c.errors.noMatchingOverload(loc, fn.GetName(), argTypes, target != nil) resultType = decls.Error return nil @@ -369,16 +406,29 @@ func (c *checker) resolveOverload( func (c *checker) checkCreateList(e *exprpb.Expr) { create := e.GetListExpr() - var elemType *exprpb.Type - for _, e := range create.GetElements() { + var elemsType *exprpb.Type + optionalIndices := create.GetOptionalIndices() + optionals := make(map[int32]bool, len(optionalIndices)) + for _, optInd := range optionalIndices { + optionals[optInd] = true + } + for i, e := range create.GetElements() { c.check(e) - elemType = c.joinTypes(c.location(e), elemType, c.getType(e)) + elemType := c.getType(e) + if optionals[int32(i)] { + var isOptional bool + elemType, isOptional = maybeUnwrapOptional(elemType) + if !isOptional && !isDyn(elemType) { + c.errors.typeMismatch(c.location(e), decls.NewOptionalType(elemType), elemType) + } + } + elemsType = c.joinTypes(c.location(e), elemsType, elemType) } - if elemType == nil { + if elemsType == nil { // If the list is empty, assign free type var to elem type. - elemType = c.newTypeVar() + elemsType = c.newTypeVar() } - c.setType(e, decls.NewListType(elemType)) + c.setType(e, decls.NewListType(elemsType)) } func (c *checker) checkCreateStruct(e *exprpb.Expr) { @@ -392,22 +442,31 @@ func (c *checker) checkCreateStruct(e *exprpb.Expr) { func (c *checker) checkCreateMap(e *exprpb.Expr) { mapVal := e.GetStructExpr() - var keyType *exprpb.Type - var valueType *exprpb.Type + var mapKeyType *exprpb.Type + var mapValueType *exprpb.Type for _, ent := range mapVal.GetEntries() { key := ent.GetMapKey() c.check(key) - keyType = c.joinTypes(c.location(key), keyType, c.getType(key)) - - c.check(ent.Value) - valueType = c.joinTypes(c.location(ent.Value), valueType, c.getType(ent.Value)) + mapKeyType = c.joinTypes(c.location(key), mapKeyType, c.getType(key)) + + val := ent.GetValue() + c.check(val) + valType := c.getType(val) + if ent.GetOptionalEntry() { + var isOptional bool + valType, isOptional = maybeUnwrapOptional(valType) + if !isOptional && !isDyn(valType) { + c.errors.typeMismatch(c.location(val), decls.NewOptionalType(valType), valType) + } + } + mapValueType = c.joinTypes(c.location(val), mapValueType, valType) } - if keyType == nil { + if mapKeyType == nil { // If the map is empty, assign free type variables to typeKey and value type. - keyType = c.newTypeVar() - valueType = c.newTypeVar() + mapKeyType = c.newTypeVar() + mapValueType = c.newTypeVar() } - c.setType(e, decls.NewMapType(keyType, valueType)) + c.setType(e, decls.NewMapType(mapKeyType, mapValueType)) } func (c *checker) checkCreateMessage(e *exprpb.Expr) { @@ -449,15 +508,21 @@ func (c *checker) checkCreateMessage(e *exprpb.Expr) { c.check(value) fieldType := decls.Error - if t, found := c.lookupFieldType( - c.locationByID(ent.GetId()), - messageType.GetMessageType(), - field); found { - fieldType = t.Type + ft, found := c.lookupFieldType(c.locationByID(ent.GetId()), messageType.GetMessageType(), field) + if found { + fieldType = ft.Type + } + + valType := c.getType(value) + if ent.GetOptionalEntry() { + var isOptional bool + valType, isOptional = maybeUnwrapOptional(valType) + if !isOptional && !isDyn(valType) { + c.errors.typeMismatch(c.location(value), decls.NewOptionalType(valType), valType) + } } - if !c.isAssignable(fieldType, c.getType(value)) { - c.errors.fieldTypeMismatch( - c.locationByID(ent.Id), field, fieldType, c.getType(value)) + if !c.isAssignable(fieldType, valType) { + c.errors.fieldTypeMismatch(c.locationByID(ent.Id), field, fieldType, valType) } } } diff --git a/vendor/github.com/google/cel-go/checker/cost.go b/vendor/github.com/google/cel-go/checker/cost.go index 7312d1fe2f..f1102686f6 100644 --- a/vendor/github.com/google/cel-go/checker/cost.go +++ b/vendor/github.com/google/cel-go/checker/cost.go @@ -92,7 +92,10 @@ func (e astNode) ComputedSize() *SizeEstimate { case *exprpb.Expr_ConstExpr: switch ck := ek.ConstExpr.GetConstantKind().(type) { case *exprpb.Constant_StringValue: - v = uint64(len(ck.StringValue)) + // converting to runes here is an O(n) operation, but + // this is consistent with how size is computed at runtime, + // and how the language definition defines string size + v = uint64(len([]rune(ck.StringValue))) case *exprpb.Constant_BytesValue: v = uint64(len(ck.BytesValue)) case *exprpb.Constant_BoolValue, *exprpb.Constant_DoubleValue, *exprpb.Constant_DurationValue, @@ -340,6 +343,12 @@ func (c *coster) costSelect(e *exprpb.Expr) CostEstimate { sel := e.GetSelectExpr() var sum CostEstimate if sel.GetTestOnly() { + // recurse, but do not add any cost + // this is equivalent to how evalTestOnly increments the runtime cost counter + // but does not add any additional cost for the qualifier, except here we do + // the reverse (ident adds cost) + sum = sum.Add(selectAndIdentCost) + sum = sum.Add(c.cost(sel.GetOperand())) return sum } sum = sum.Add(c.cost(sel.GetOperand())) @@ -503,7 +512,10 @@ func (c *coster) functionCost(function, overloadID string, target *AstNode, args } switch overloadID { // O(n) functions - case overloads.StartsWithString, overloads.EndsWithString, overloads.StringToBytes, overloads.BytesToString: + case overloads.StartsWithString, overloads.EndsWithString, overloads.StringToBytes, overloads.BytesToString, overloads.ExtQuoteString, overloads.ExtFormatString: + if overloadID == overloads.ExtFormatString { + return CallEstimate{CostEstimate: c.sizeEstimate(*target).MultiplyByCostFactor(common.StringTraversalCostFactor).Add(argCostSum())} + } if len(args) == 1 { return CallEstimate{CostEstimate: c.sizeEstimate(args[0]).MultiplyByCostFactor(common.StringTraversalCostFactor).Add(argCostSum())} } diff --git a/vendor/github.com/google/cel-go/checker/decls/decls.go b/vendor/github.com/google/cel-go/checker/decls/decls.go index 88a99282d9..0d91bef514 100644 --- a/vendor/github.com/google/cel-go/checker/decls/decls.go +++ b/vendor/github.com/google/cel-go/checker/decls/decls.go @@ -16,9 +16,9 @@ package decls import ( + exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1" emptypb "google.golang.org/protobuf/types/known/emptypb" structpb "google.golang.org/protobuf/types/known/structpb" - exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1" ) var ( @@ -64,6 +64,12 @@ func NewAbstractType(name string, paramTypes ...*exprpb.Type) *exprpb.Type { ParameterTypes: paramTypes}}} } +// NewOptionalType constructs an abstract type indicating that the parameterized type +// may be contained within the object. +func NewOptionalType(paramType *exprpb.Type) *exprpb.Type { + return NewAbstractType("optional", paramType) +} + // NewFunctionType creates a function invocation contract, typically only used // by type-checking steps after overload resolution. func NewFunctionType(resultType *exprpb.Type, diff --git a/vendor/github.com/google/cel-go/checker/printer.go b/vendor/github.com/google/cel-go/checker/printer.go index e2ed35be83..0cecc5210d 100644 --- a/vendor/github.com/google/cel-go/checker/printer.go +++ b/vendor/github.com/google/cel-go/checker/printer.go @@ -26,7 +26,7 @@ type semanticAdorner struct { var _ debug.Adorner = &semanticAdorner{} -func (a *semanticAdorner) GetMetadata(elem interface{}) string { +func (a *semanticAdorner) GetMetadata(elem any) string { result := "" e, isExpr := elem.(*exprpb.Expr) if !isExpr { diff --git a/vendor/github.com/google/cel-go/checker/standard.go b/vendor/github.com/google/cel-go/checker/standard.go index 5b48a9046a..e64337ba44 100644 --- a/vendor/github.com/google/cel-go/checker/standard.go +++ b/vendor/github.com/google/cel-go/checker/standard.go @@ -287,6 +287,8 @@ func init() { decls.NewInstanceOverload(overloads.EndsWithString, []*exprpb.Type{decls.String, decls.String}, decls.Bool)), decls.NewFunction(overloads.Matches, + decls.NewOverload(overloads.Matches, + []*exprpb.Type{decls.String, decls.String}, decls.Bool), decls.NewInstanceOverload(overloads.MatchesString, []*exprpb.Type{decls.String, decls.String}, decls.Bool)), decls.NewFunction(overloads.StartsWith, diff --git a/vendor/github.com/google/cel-go/checker/types.go b/vendor/github.com/google/cel-go/checker/types.go index 8683797d5b..28d21c9d92 100644 --- a/vendor/github.com/google/cel-go/checker/types.go +++ b/vendor/github.com/google/cel-go/checker/types.go @@ -90,6 +90,14 @@ func FormatCheckedType(t *exprpb.Type) string { return "!error!" case kindTypeParam: return t.GetTypeParam() + case kindAbstract: + at := t.GetAbstractType() + params := at.GetParameterTypes() + paramStrs := make([]string, len(params)) + for i, p := range params { + paramStrs[i] = FormatCheckedType(p) + } + return fmt.Sprintf("%s(%s)", at.GetName(), strings.Join(paramStrs, ", ")) } return t.String() } @@ -110,12 +118,39 @@ func isDyn(t *exprpb.Type) bool { // isDynOrError returns true if the input is either an Error, DYN, or well-known ANY message. func isDynOrError(t *exprpb.Type) bool { - switch kindOf(t) { - case kindError: - return true - default: - return isDyn(t) + return isError(t) || isDyn(t) +} + +func isError(t *exprpb.Type) bool { + return kindOf(t) == kindError +} + +func isOptional(t *exprpb.Type) bool { + if kindOf(t) == kindAbstract { + at := t.GetAbstractType() + return at.GetName() == "optional" + } + return false +} + +func maybeUnwrapOptional(t *exprpb.Type) (*exprpb.Type, bool) { + if isOptional(t) { + at := t.GetAbstractType() + return at.GetParameterTypes()[0], true + } + return t, false +} + +func maybeUnwrapString(e *exprpb.Expr) (string, bool) { + switch e.GetExprKind().(type) { + case *exprpb.Expr_ConstExpr: + literal := e.GetConstExpr() + switch literal.GetConstantKind().(type) { + case *exprpb.Constant_StringValue: + return literal.GetStringValue(), true + } } + return "", false } // isEqualOrLessSpecific checks whether one type is equal or less specific than the other one. @@ -236,7 +271,7 @@ func internalIsAssignable(m *mapping, t1 *exprpb.Type, t2 *exprpb.Type) bool { // substitution for t1, and whether t2 has a type substitution in mapping m. // // The type t2 is a valid substitution for t1 if any of the following statements is true -// - t2 has a type substitition (t2sub) equal to t1 +// - t2 has a type substitution (t2sub) equal to t1 // - t2 has a type substitution (t2sub) assignable to t1 // - t2 does not occur within t1. func isValidTypeSubstitution(m *mapping, t1, t2 *exprpb.Type) (valid, hasSub bool) { diff --git a/vendor/github.com/google/cel-go/common/debug/debug.go b/vendor/github.com/google/cel-go/common/debug/debug.go index bec885424b..5dab156ef3 100644 --- a/vendor/github.com/google/cel-go/common/debug/debug.go +++ b/vendor/github.com/google/cel-go/common/debug/debug.go @@ -29,7 +29,7 @@ import ( // representation of an expression. type Adorner interface { // GetMetadata for the input context. - GetMetadata(ctx interface{}) string + GetMetadata(ctx any) string } // Writer manages writing expressions to an internal string. @@ -46,7 +46,7 @@ type emptyDebugAdorner struct { var emptyAdorner Adorner = &emptyDebugAdorner{} -func (a *emptyDebugAdorner) GetMetadata(e interface{}) string { +func (a *emptyDebugAdorner) GetMetadata(e any) string { return "" } @@ -170,6 +170,9 @@ func (w *debugWriter) appendObject(obj *exprpb.Expr_CreateStruct) { w.append(",") w.appendLine() } + if entry.GetOptionalEntry() { + w.append("?") + } w.append(entry.GetFieldKey()) w.append(":") w.Buffer(entry.GetValue()) @@ -191,6 +194,9 @@ func (w *debugWriter) appendMap(obj *exprpb.Expr_CreateStruct) { w.append(",") w.appendLine() } + if entry.GetOptionalEntry() { + w.append("?") + } w.Buffer(entry.GetMapKey()) w.append(":") w.Buffer(entry.GetValue()) @@ -269,7 +275,7 @@ func (w *debugWriter) append(s string) { w.buffer.WriteString(s) } -func (w *debugWriter) appendFormat(f string, args ...interface{}) { +func (w *debugWriter) appendFormat(f string, args ...any) { w.append(fmt.Sprintf(f, args...)) } @@ -280,7 +286,7 @@ func (w *debugWriter) doIndent() { } } -func (w *debugWriter) adorn(e interface{}) { +func (w *debugWriter) adorn(e any) { w.append(w.adorner.GetMetadata(e)) } diff --git a/vendor/github.com/google/cel-go/common/errors.go b/vendor/github.com/google/cel-go/common/errors.go index daebba8609..1565085ab9 100644 --- a/vendor/github.com/google/cel-go/common/errors.go +++ b/vendor/github.com/google/cel-go/common/errors.go @@ -38,7 +38,7 @@ func NewErrors(source Source) *Errors { } // ReportError records an error at a source location. -func (e *Errors) ReportError(l Location, format string, args ...interface{}) { +func (e *Errors) ReportError(l Location, format string, args ...any) { e.numErrors++ if e.numErrors > e.maxErrorsToReport { return diff --git a/vendor/github.com/google/cel-go/common/operators/operators.go b/vendor/github.com/google/cel-go/common/operators/operators.go index fa25dfb7f0..f9b39bda3f 100644 --- a/vendor/github.com/google/cel-go/common/operators/operators.go +++ b/vendor/github.com/google/cel-go/common/operators/operators.go @@ -37,6 +37,8 @@ const ( Modulo = "_%_" Negate = "-_" Index = "_[_]" + OptIndex = "_[?_]" + OptSelect = "_?._" // Macros, must have a valid identifier. Has = "has" @@ -99,6 +101,8 @@ var ( LogicalNot: {displayName: "!", precedence: 2, arity: 1}, Negate: {displayName: "-", precedence: 2, arity: 1}, Index: {displayName: "", precedence: 1, arity: 2}, + OptIndex: {displayName: "", precedence: 1, arity: 2}, + OptSelect: {displayName: "", precedence: 1, arity: 2}, } ) diff --git a/vendor/github.com/google/cel-go/common/overloads/overloads.go b/vendor/github.com/google/cel-go/common/overloads/overloads.go index 9ebaf6fabf..9d50f4367b 100644 --- a/vendor/github.com/google/cel-go/common/overloads/overloads.go +++ b/vendor/github.com/google/cel-go/common/overloads/overloads.go @@ -148,6 +148,11 @@ const ( StartsWith = "startsWith" ) +// Extension function overloads with complex behaviors that need to be referenced in runtime and static analysis cost computations. +const ( + ExtQuoteString = "strings_quote" +) + // String function overload names. const ( ContainsString = "contains_string" @@ -156,6 +161,11 @@ const ( StartsWithString = "starts_with_string" ) +// Extension function overloads with complex behaviors that need to be referenced in runtime and static analysis cost computations. +const ( + ExtFormatString = "string_format" +) + // Time-based functions. const ( TimeGetFullYear = "getFullYear" diff --git a/vendor/github.com/google/cel-go/common/types/BUILD.bazel b/vendor/github.com/google/cel-go/common/types/BUILD.bazel index 5f1b1cd1fd..f56700de5d 100644 --- a/vendor/github.com/google/cel-go/common/types/BUILD.bazel +++ b/vendor/github.com/google/cel-go/common/types/BUILD.bazel @@ -22,6 +22,7 @@ go_library( "map.go", "null.go", "object.go", + "optional.go", "overflow.go", "provider.go", "string.go", @@ -40,8 +41,6 @@ go_library( "@com_github_stoewer_go_strcase//:go_default_library", "@org_golang_google_genproto//googleapis/api/expr/v1alpha1:go_default_library", "@org_golang_google_genproto//googleapis/rpc/status:go_default_library", - "@org_golang_google_grpc//codes:go_default_library", - "@org_golang_google_grpc//status:go_default_library", "@org_golang_google_protobuf//encoding/protojson:go_default_library", "@org_golang_google_protobuf//proto:go_default_library", "@org_golang_google_protobuf//reflect/protoreflect:go_default_library", @@ -68,6 +67,7 @@ go_test( "map_test.go", "null_test.go", "object_test.go", + "optional_test.go", "provider_test.go", "string_test.go", "timestamp_test.go", diff --git a/vendor/github.com/google/cel-go/common/types/bool.go b/vendor/github.com/google/cel-go/common/types/bool.go index 1b55ba9529..a634ecc287 100644 --- a/vendor/github.com/google/cel-go/common/types/bool.go +++ b/vendor/github.com/google/cel-go/common/types/bool.go @@ -62,7 +62,7 @@ func (b Bool) Compare(other ref.Val) ref.Val { } // ConvertToNative implements the ref.Val interface method. -func (b Bool) ConvertToNative(typeDesc reflect.Type) (interface{}, error) { +func (b Bool) ConvertToNative(typeDesc reflect.Type) (any, error) { switch typeDesc.Kind() { case reflect.Bool: return reflect.ValueOf(b).Convert(typeDesc).Interface(), nil @@ -114,6 +114,11 @@ func (b Bool) Equal(other ref.Val) ref.Val { return Bool(ok && b == otherBool) } +// IsZeroValue returns true if the boolean value is false. +func (b Bool) IsZeroValue() bool { + return b == False +} + // Negate implements the traits.Negater interface method. func (b Bool) Negate() ref.Val { return !b @@ -125,7 +130,7 @@ func (b Bool) Type() ref.Type { } // Value implements the ref.Val interface method. -func (b Bool) Value() interface{} { +func (b Bool) Value() any { return bool(b) } diff --git a/vendor/github.com/google/cel-go/common/types/bytes.go b/vendor/github.com/google/cel-go/common/types/bytes.go index 3575717ec7..bef190759f 100644 --- a/vendor/github.com/google/cel-go/common/types/bytes.go +++ b/vendor/github.com/google/cel-go/common/types/bytes.go @@ -63,7 +63,7 @@ func (b Bytes) Compare(other ref.Val) ref.Val { } // ConvertToNative implements the ref.Val interface method. -func (b Bytes) ConvertToNative(typeDesc reflect.Type) (interface{}, error) { +func (b Bytes) ConvertToNative(typeDesc reflect.Type) (any, error) { switch typeDesc.Kind() { case reflect.Array, reflect.Slice: return reflect.ValueOf(b).Convert(typeDesc).Interface(), nil @@ -116,6 +116,11 @@ func (b Bytes) Equal(other ref.Val) ref.Val { return Bool(ok && bytes.Equal(b, otherBytes)) } +// IsZeroValue returns true if the byte array is empty. +func (b Bytes) IsZeroValue() bool { + return len(b) == 0 +} + // Size implements the traits.Sizer interface method. func (b Bytes) Size() ref.Val { return Int(len(b)) @@ -127,6 +132,6 @@ func (b Bytes) Type() ref.Type { } // Value implements the ref.Val interface method. -func (b Bytes) Value() interface{} { +func (b Bytes) Value() any { return []byte(b) } diff --git a/vendor/github.com/google/cel-go/common/types/double.go b/vendor/github.com/google/cel-go/common/types/double.go index a6ec52a0f9..bda9f31a6b 100644 --- a/vendor/github.com/google/cel-go/common/types/double.go +++ b/vendor/github.com/google/cel-go/common/types/double.go @@ -78,7 +78,7 @@ func (d Double) Compare(other ref.Val) ref.Val { } // ConvertToNative implements ref.Val.ConvertToNative. -func (d Double) ConvertToNative(typeDesc reflect.Type) (interface{}, error) { +func (d Double) ConvertToNative(typeDesc reflect.Type) (any, error) { switch typeDesc.Kind() { case reflect.Float32: v := float32(d) @@ -134,13 +134,13 @@ func (d Double) ConvertToType(typeVal ref.Type) ref.Val { case IntType: i, err := doubleToInt64Checked(float64(d)) if err != nil { - return wrapErr(err) + return WrapErr(err) } return Int(i) case UintType: i, err := doubleToUint64Checked(float64(d)) if err != nil { - return wrapErr(err) + return WrapErr(err) } return Uint(i) case DoubleType: @@ -182,6 +182,11 @@ func (d Double) Equal(other ref.Val) ref.Val { } } +// IsZeroValue returns true if double value is 0.0 +func (d Double) IsZeroValue() bool { + return float64(d) == 0.0 +} + // Multiply implements traits.Multiplier.Multiply. func (d Double) Multiply(other ref.Val) ref.Val { otherDouble, ok := other.(Double) @@ -211,6 +216,6 @@ func (d Double) Type() ref.Type { } // Value implements ref.Val.Value. -func (d Double) Value() interface{} { +func (d Double) Value() any { return float64(d) } diff --git a/vendor/github.com/google/cel-go/common/types/duration.go b/vendor/github.com/google/cel-go/common/types/duration.go index 418349fa6c..c90ac1bee9 100644 --- a/vendor/github.com/google/cel-go/common/types/duration.go +++ b/vendor/github.com/google/cel-go/common/types/duration.go @@ -57,14 +57,14 @@ func (d Duration) Add(other ref.Val) ref.Val { dur2 := other.(Duration) val, err := addDurationChecked(d.Duration, dur2.Duration) if err != nil { - return wrapErr(err) + return WrapErr(err) } return durationOf(val) case TimestampType: ts := other.(Timestamp).Time val, err := addTimeDurationChecked(ts, d.Duration) if err != nil { - return wrapErr(err) + return WrapErr(err) } return timestampOf(val) } @@ -90,7 +90,7 @@ func (d Duration) Compare(other ref.Val) ref.Val { } // ConvertToNative implements ref.Val.ConvertToNative. -func (d Duration) ConvertToNative(typeDesc reflect.Type) (interface{}, error) { +func (d Duration) ConvertToNative(typeDesc reflect.Type) (any, error) { // If the duration is already assignable to the desired type return it. if reflect.TypeOf(d.Duration).AssignableTo(typeDesc) { return d.Duration, nil @@ -138,11 +138,16 @@ func (d Duration) Equal(other ref.Val) ref.Val { return Bool(ok && d.Duration == otherDur.Duration) } +// IsZeroValue returns true if the duration value is zero +func (d Duration) IsZeroValue() bool { + return d.Duration == 0 +} + // Negate implements traits.Negater.Negate. func (d Duration) Negate() ref.Val { val, err := negateDurationChecked(d.Duration) if err != nil { - return wrapErr(err) + return WrapErr(err) } return durationOf(val) } @@ -165,7 +170,7 @@ func (d Duration) Subtract(subtrahend ref.Val) ref.Val { } val, err := subtractDurationChecked(d.Duration, subtraDur.Duration) if err != nil { - return wrapErr(err) + return WrapErr(err) } return durationOf(val) } @@ -176,7 +181,7 @@ func (d Duration) Type() ref.Type { } // Value implements ref.Val.Value. -func (d Duration) Value() interface{} { +func (d Duration) Value() any { return d.Duration } diff --git a/vendor/github.com/google/cel-go/common/types/err.go b/vendor/github.com/google/cel-go/common/types/err.go index 93d79cdcbc..b4874d9d4d 100644 --- a/vendor/github.com/google/cel-go/common/types/err.go +++ b/vendor/github.com/google/cel-go/common/types/err.go @@ -22,6 +22,12 @@ import ( "github.com/google/cel-go/common/types/ref" ) +// Error interface which allows types types.Err values to be treated as error values. +type Error interface { + error + ref.Val +} + // Err type which extends the built-in go error and implements ref.Val. type Err struct { error @@ -51,7 +57,7 @@ var ( // NewErr creates a new Err described by the format string and args. // TODO: Audit the use of this function and standardize the error messages and codes. -func NewErr(format string, args ...interface{}) ref.Val { +func NewErr(format string, args ...any) ref.Val { return &Err{fmt.Errorf(format, args...)} } @@ -62,7 +68,7 @@ func NoSuchOverloadErr() ref.Val { // UnsupportedRefValConversionErr returns a types.NewErr instance with a no such conversion // message that indicates that the native value could not be converted to a CEL ref.Val. -func UnsupportedRefValConversionErr(val interface{}) ref.Val { +func UnsupportedRefValConversionErr(val any) ref.Val { return NewErr("unsupported conversion to ref.Val: (%T)%v", val, val) } @@ -74,20 +80,20 @@ func MaybeNoSuchOverloadErr(val ref.Val) ref.Val { // ValOrErr either returns the existing error or creates a new one. // TODO: Audit the use of this function and standardize the error messages and codes. -func ValOrErr(val ref.Val, format string, args ...interface{}) ref.Val { +func ValOrErr(val ref.Val, format string, args ...any) ref.Val { if val == nil || !IsUnknownOrError(val) { return NewErr(format, args...) } return val } -// wrapErr wraps an existing Go error value into a CEL Err value. -func wrapErr(err error) ref.Val { +// WrapErr wraps an existing Go error value into a CEL Err value. +func WrapErr(err error) ref.Val { return &Err{error: err} } // ConvertToNative implements ref.Val.ConvertToNative. -func (e *Err) ConvertToNative(typeDesc reflect.Type) (interface{}, error) { +func (e *Err) ConvertToNative(typeDesc reflect.Type) (any, error) { return nil, e.error } @@ -114,10 +120,15 @@ func (e *Err) Type() ref.Type { } // Value implements ref.Val.Value. -func (e *Err) Value() interface{} { +func (e *Err) Value() any { return e.error } +// Is implements errors.Is. +func (e *Err) Is(target error) bool { + return e.error.Error() == target.Error() +} + // IsError returns whether the input element ref.Type or ref.Val is equal to // the ErrType singleton. func IsError(val ref.Val) bool { diff --git a/vendor/github.com/google/cel-go/common/types/int.go b/vendor/github.com/google/cel-go/common/types/int.go index 95f25dcd80..f5a9511c8d 100644 --- a/vendor/github.com/google/cel-go/common/types/int.go +++ b/vendor/github.com/google/cel-go/common/types/int.go @@ -66,7 +66,7 @@ func (i Int) Add(other ref.Val) ref.Val { } val, err := addInt64Checked(int64(i), int64(otherInt)) if err != nil { - return wrapErr(err) + return WrapErr(err) } return Int(val) } @@ -89,7 +89,7 @@ func (i Int) Compare(other ref.Val) ref.Val { } // ConvertToNative implements ref.Val.ConvertToNative. -func (i Int) ConvertToNative(typeDesc reflect.Type) (interface{}, error) { +func (i Int) ConvertToNative(typeDesc reflect.Type) (any, error) { switch typeDesc.Kind() { case reflect.Int, reflect.Int32: // Enums are also mapped as int32 derivations. @@ -176,7 +176,7 @@ func (i Int) ConvertToType(typeVal ref.Type) ref.Val { case UintType: u, err := int64ToUint64Checked(int64(i)) if err != nil { - return wrapErr(err) + return WrapErr(err) } return Uint(u) case DoubleType: @@ -204,7 +204,7 @@ func (i Int) Divide(other ref.Val) ref.Val { } val, err := divideInt64Checked(int64(i), int64(otherInt)) if err != nil { - return wrapErr(err) + return WrapErr(err) } return Int(val) } @@ -226,6 +226,11 @@ func (i Int) Equal(other ref.Val) ref.Val { } } +// IsZeroValue returns true if integer is equal to 0 +func (i Int) IsZeroValue() bool { + return i == IntZero +} + // Modulo implements traits.Modder.Modulo. func (i Int) Modulo(other ref.Val) ref.Val { otherInt, ok := other.(Int) @@ -234,7 +239,7 @@ func (i Int) Modulo(other ref.Val) ref.Val { } val, err := moduloInt64Checked(int64(i), int64(otherInt)) if err != nil { - return wrapErr(err) + return WrapErr(err) } return Int(val) } @@ -247,7 +252,7 @@ func (i Int) Multiply(other ref.Val) ref.Val { } val, err := multiplyInt64Checked(int64(i), int64(otherInt)) if err != nil { - return wrapErr(err) + return WrapErr(err) } return Int(val) } @@ -256,7 +261,7 @@ func (i Int) Multiply(other ref.Val) ref.Val { func (i Int) Negate() ref.Val { val, err := negateInt64Checked(int64(i)) if err != nil { - return wrapErr(err) + return WrapErr(err) } return Int(val) } @@ -269,7 +274,7 @@ func (i Int) Subtract(subtrahend ref.Val) ref.Val { } val, err := subtractInt64Checked(int64(i), int64(subtraInt)) if err != nil { - return wrapErr(err) + return WrapErr(err) } return Int(val) } @@ -280,7 +285,7 @@ func (i Int) Type() ref.Type { } // Value implements ref.Val.Value. -func (i Int) Value() interface{} { +func (i Int) Value() any { return int64(i) } diff --git a/vendor/github.com/google/cel-go/common/types/iterator.go b/vendor/github.com/google/cel-go/common/types/iterator.go index 4906627783..9f224ad4ff 100644 --- a/vendor/github.com/google/cel-go/common/types/iterator.go +++ b/vendor/github.com/google/cel-go/common/types/iterator.go @@ -34,7 +34,7 @@ var ( // interpreter. type baseIterator struct{} -func (*baseIterator) ConvertToNative(typeDesc reflect.Type) (interface{}, error) { +func (*baseIterator) ConvertToNative(typeDesc reflect.Type) (any, error) { return nil, fmt.Errorf("type conversion on iterators not supported") } @@ -50,6 +50,6 @@ func (*baseIterator) Type() ref.Type { return IteratorType } -func (*baseIterator) Value() interface{} { +func (*baseIterator) Value() any { return nil } diff --git a/vendor/github.com/google/cel-go/common/types/json_value.go b/vendor/github.com/google/cel-go/common/types/json_value.go index cd63b51944..13a4efe7ad 100644 --- a/vendor/github.com/google/cel-go/common/types/json_value.go +++ b/vendor/github.com/google/cel-go/common/types/json_value.go @@ -25,4 +25,5 @@ var ( jsonValueType = reflect.TypeOf(&structpb.Value{}) jsonListValueType = reflect.TypeOf(&structpb.ListValue{}) jsonStructType = reflect.TypeOf(&structpb.Struct{}) + jsonNullType = reflect.TypeOf(structpb.NullValue_NULL_VALUE) ) diff --git a/vendor/github.com/google/cel-go/common/types/list.go b/vendor/github.com/google/cel-go/common/types/list.go index 7230f7ea12..de5f2099bf 100644 --- a/vendor/github.com/google/cel-go/common/types/list.go +++ b/vendor/github.com/google/cel-go/common/types/list.go @@ -17,12 +17,14 @@ package types import ( "fmt" "reflect" + "strings" - "github.com/google/cel-go/common/types/ref" - "github.com/google/cel-go/common/types/traits" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" + "github.com/google/cel-go/common/types/ref" + "github.com/google/cel-go/common/types/traits" + anypb "google.golang.org/protobuf/types/known/anypb" structpb "google.golang.org/protobuf/types/known/structpb" ) @@ -40,13 +42,13 @@ var ( // NewDynamicList returns a traits.Lister with heterogenous elements. // value should be an array of "native" types, i.e. any type that // NativeToValue() can convert to a ref.Val. -func NewDynamicList(adapter ref.TypeAdapter, value interface{}) traits.Lister { +func NewDynamicList(adapter ref.TypeAdapter, value any) traits.Lister { refValue := reflect.ValueOf(value) return &baseList{ TypeAdapter: adapter, value: value, size: refValue.Len(), - get: func(i int) interface{} { + get: func(i int) any { return refValue.Index(i).Interface() }, } @@ -58,7 +60,7 @@ func NewStringList(adapter ref.TypeAdapter, elems []string) traits.Lister { TypeAdapter: adapter, value: elems, size: len(elems), - get: func(i int) interface{} { return elems[i] }, + get: func(i int) any { return elems[i] }, } } @@ -70,7 +72,7 @@ func NewRefValList(adapter ref.TypeAdapter, elems []ref.Val) traits.Lister { TypeAdapter: adapter, value: elems, size: len(elems), - get: func(i int) interface{} { return elems[i] }, + get: func(i int) any { return elems[i] }, } } @@ -80,7 +82,7 @@ func NewProtoList(adapter ref.TypeAdapter, list protoreflect.List) traits.Lister TypeAdapter: adapter, value: list, size: list.Len(), - get: func(i int) interface{} { return list.Get(i).Interface() }, + get: func(i int) any { return list.Get(i).Interface() }, } } @@ -91,22 +93,25 @@ func NewJSONList(adapter ref.TypeAdapter, l *structpb.ListValue) traits.Lister { TypeAdapter: adapter, value: l, size: len(vals), - get: func(i int) interface{} { return vals[i] }, + get: func(i int) any { return vals[i] }, } } // NewMutableList creates a new mutable list whose internal state can be modified. func NewMutableList(adapter ref.TypeAdapter) traits.MutableLister { var mutableValues []ref.Val - return &mutableList{ + l := &mutableList{ baseList: &baseList{ TypeAdapter: adapter, value: mutableValues, size: 0, - get: func(i int) interface{} { return mutableValues[i] }, }, mutableValues: mutableValues, } + l.get = func(i int) any { + return l.mutableValues[i] + } + return l } // baseList points to a list containing elements of any type. @@ -114,7 +119,7 @@ func NewMutableList(adapter ref.TypeAdapter) traits.MutableLister { // The `ref.TypeAdapter` enables native type to CEL type conversions. type baseList struct { ref.TypeAdapter - value interface{} + value any // size indicates the number of elements within the list. // Since objects are immutable the size of a list is static. @@ -122,7 +127,7 @@ type baseList struct { // get returns a value at the specified integer index. // The index is guaranteed to be checked against the list index range. - get func(int) interface{} + get func(int) any } // Add implements the traits.Adder interface method. @@ -157,7 +162,7 @@ func (l *baseList) Contains(elem ref.Val) ref.Val { } // ConvertToNative implements the ref.Val interface method. -func (l *baseList) ConvertToNative(typeDesc reflect.Type) (interface{}, error) { +func (l *baseList) ConvertToNative(typeDesc reflect.Type) (any, error) { // If the underlying list value is assignable to the reflected type return it. if reflect.TypeOf(l.value).AssignableTo(typeDesc) { return l.value, nil @@ -240,7 +245,7 @@ func (l *baseList) Equal(other ref.Val) ref.Val { // Get implements the traits.Indexer interface method. func (l *baseList) Get(index ref.Val) ref.Val { - ind, err := indexOrError(index) + ind, err := IndexOrError(index) if err != nil { return ValOrErr(index, err.Error()) } @@ -250,6 +255,11 @@ func (l *baseList) Get(index ref.Val) ref.Val { return l.NativeToValue(l.get(ind)) } +// IsZeroValue returns true if the list is empty. +func (l *baseList) IsZeroValue() bool { + return l.size == 0 +} + // Iterator implements the traits.Iterable interface method. func (l *baseList) Iterator() traits.Iterator { return newListIterator(l) @@ -266,10 +276,24 @@ func (l *baseList) Type() ref.Type { } // Value implements the ref.Val interface method. -func (l *baseList) Value() interface{} { +func (l *baseList) Value() any { return l.value } +// String converts the list to a human readable string form. +func (l *baseList) String() string { + var sb strings.Builder + sb.WriteString("[") + for i := 0; i < l.size; i++ { + sb.WriteString(fmt.Sprintf("%v", l.get(i))) + if i != l.size-1 { + sb.WriteString(", ") + } + } + sb.WriteString("]") + return sb.String() +} + // mutableList aggregates values into its internal storage. For use with internal CEL variables only. type mutableList struct { *baseList @@ -305,7 +329,7 @@ func (l *mutableList) ToImmutableList() traits.Lister { // The `ref.TypeAdapter` enables native type to CEL type conversions. type concatList struct { ref.TypeAdapter - value interface{} + value any prevList traits.Lister nextList traits.Lister } @@ -351,8 +375,8 @@ func (l *concatList) Contains(elem ref.Val) ref.Val { } // ConvertToNative implements the ref.Val interface method. -func (l *concatList) ConvertToNative(typeDesc reflect.Type) (interface{}, error) { - combined := NewDynamicList(l.TypeAdapter, l.Value().([]interface{})) +func (l *concatList) ConvertToNative(typeDesc reflect.Type) (any, error) { + combined := NewDynamicList(l.TypeAdapter, l.Value().([]any)) return combined.ConvertToNative(typeDesc) } @@ -396,7 +420,7 @@ func (l *concatList) Equal(other ref.Val) ref.Val { // Get implements the traits.Indexer interface method. func (l *concatList) Get(index ref.Val) ref.Val { - ind, err := indexOrError(index) + ind, err := IndexOrError(index) if err != nil { return ValOrErr(index, err.Error()) } @@ -408,6 +432,11 @@ func (l *concatList) Get(index ref.Val) ref.Val { return l.nextList.Get(offset) } +// IsZeroValue returns true if the list is empty. +func (l *concatList) IsZeroValue() bool { + return l.Size().(Int) == 0 +} + // Iterator implements the traits.Iterable interface method. func (l *concatList) Iterator() traits.Iterator { return newListIterator(l) @@ -418,15 +447,29 @@ func (l *concatList) Size() ref.Val { return l.prevList.Size().(Int).Add(l.nextList.Size()) } +// String converts the concatenated list to a human-readable string. +func (l *concatList) String() string { + var sb strings.Builder + sb.WriteString("[") + for i := Int(0); i < l.Size().(Int); i++ { + sb.WriteString(fmt.Sprintf("%v", l.Get(i))) + if i != l.Size().(Int)-1 { + sb.WriteString(", ") + } + } + sb.WriteString("]") + return sb.String() +} + // Type implements the ref.Val interface method. func (l *concatList) Type() ref.Type { return ListType } // Value implements the ref.Val interface method. -func (l *concatList) Value() interface{} { +func (l *concatList) Value() any { if l.value == nil { - merged := make([]interface{}, l.Size().(Int)) + merged := make([]any, l.Size().(Int)) prevLen := l.prevList.Size().(Int) for i := Int(0); i < prevLen; i++ { merged[i] = l.prevList.Get(i).Value() @@ -469,7 +512,8 @@ func (it *listIterator) Next() ref.Val { return nil } -func indexOrError(index ref.Val) (int, error) { +// IndexOrError converts an input index value into either a lossless integer index or an error. +func IndexOrError(index ref.Val) (int, error) { switch iv := index.(type) { case Int: return int(iv), nil diff --git a/vendor/github.com/google/cel-go/common/types/map.go b/vendor/github.com/google/cel-go/common/types/map.go index 5865594024..213be4ac9e 100644 --- a/vendor/github.com/google/cel-go/common/types/map.go +++ b/vendor/github.com/google/cel-go/common/types/map.go @@ -17,20 +17,22 @@ package types import ( "fmt" "reflect" + "strings" - "github.com/google/cel-go/common/types/pb" - "github.com/google/cel-go/common/types/ref" - "github.com/google/cel-go/common/types/traits" "github.com/stoewer/go-strcase" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" + "github.com/google/cel-go/common/types/pb" + "github.com/google/cel-go/common/types/ref" + "github.com/google/cel-go/common/types/traits" + anypb "google.golang.org/protobuf/types/known/anypb" structpb "google.golang.org/protobuf/types/known/structpb" ) // NewDynamicMap returns a traits.Mapper value with dynamic key, value pairs. -func NewDynamicMap(adapter ref.TypeAdapter, value interface{}) traits.Mapper { +func NewDynamicMap(adapter ref.TypeAdapter, value any) traits.Mapper { refValue := reflect.ValueOf(value) return &baseMap{ TypeAdapter: adapter, @@ -65,7 +67,7 @@ func NewRefValMap(adapter ref.TypeAdapter, value map[ref.Val]ref.Val) traits.Map } // NewStringInterfaceMap returns a specialized traits.Mapper with string keys and interface values. -func NewStringInterfaceMap(adapter ref.TypeAdapter, value map[string]interface{}) traits.Mapper { +func NewStringInterfaceMap(adapter ref.TypeAdapter, value map[string]any) traits.Mapper { return &baseMap{ TypeAdapter: adapter, mapAccessor: newStringIfaceMapAccessor(adapter, value), @@ -125,7 +127,7 @@ type baseMap struct { mapAccessor // value is the native Go value upon which the map type operators. - value interface{} + value any // size is the number of entries in the map. size int @@ -138,7 +140,7 @@ func (m *baseMap) Contains(index ref.Val) ref.Val { } // ConvertToNative implements the ref.Val interface method. -func (m *baseMap) ConvertToNative(typeDesc reflect.Type) (interface{}, error) { +func (m *baseMap) ConvertToNative(typeDesc reflect.Type) (any, error) { // If the map is already assignable to the desired type return it, e.g. interfaces and // maps with the same key value types. if reflect.TypeOf(m.value).AssignableTo(typeDesc) { @@ -275,18 +277,42 @@ func (m *baseMap) Get(key ref.Val) ref.Val { return v } +// IsZeroValue returns true if the map is empty. +func (m *baseMap) IsZeroValue() bool { + return m.size == 0 +} + // Size implements the traits.Sizer interface method. func (m *baseMap) Size() ref.Val { return Int(m.size) } +// String converts the map into a human-readable string. +func (m *baseMap) String() string { + var sb strings.Builder + sb.WriteString("{") + it := m.Iterator() + i := 0 + for it.HasNext() == True { + k := it.Next() + v, _ := m.Find(k) + sb.WriteString(fmt.Sprintf("%v: %v", k, v)) + if i != m.size-1 { + sb.WriteString(", ") + } + i++ + } + sb.WriteString("}") + return sb.String() +} + // Type implements the ref.Val interface method. func (m *baseMap) Type() ref.Type { return MapType } // Value implements the ref.Val interface method. -func (m *baseMap) Value() interface{} { +func (m *baseMap) Value() any { return m.value } @@ -498,7 +524,7 @@ func (a *stringMapAccessor) Iterator() traits.Iterator { } } -func newStringIfaceMapAccessor(adapter ref.TypeAdapter, mapVal map[string]interface{}) mapAccessor { +func newStringIfaceMapAccessor(adapter ref.TypeAdapter, mapVal map[string]any) mapAccessor { return &stringIfaceMapAccessor{ TypeAdapter: adapter, mapVal: mapVal, @@ -507,7 +533,7 @@ func newStringIfaceMapAccessor(adapter ref.TypeAdapter, mapVal map[string]interf type stringIfaceMapAccessor struct { ref.TypeAdapter - mapVal map[string]interface{} + mapVal map[string]any } // Find uses native map accesses to find the key, returning (value, true) if present. @@ -556,7 +582,7 @@ func (m *protoMap) Contains(key ref.Val) ref.Val { // ConvertToNative implements the ref.Val interface method. // // Note, assignment to Golang struct types is not yet supported. -func (m *protoMap) ConvertToNative(typeDesc reflect.Type) (interface{}, error) { +func (m *protoMap) ConvertToNative(typeDesc reflect.Type) (any, error) { // If the map is already assignable to the desired type return it, e.g. interfaces and // maps with the same key value types. switch typeDesc { @@ -601,9 +627,9 @@ func (m *protoMap) ConvertToNative(typeDesc reflect.Type) (interface{}, error) { m.value.Range(func(key protoreflect.MapKey, val protoreflect.Value) bool { ntvKey := key.Interface() ntvVal := val.Interface() - switch ntvVal.(type) { + switch pv := ntvVal.(type) { case protoreflect.Message: - ntvVal = ntvVal.(protoreflect.Message).Interface() + ntvVal = pv.Interface() } if keyType == otherKeyType && valType == otherValType { mapVal.SetMapIndex(reflect.ValueOf(ntvKey), reflect.ValueOf(ntvVal)) @@ -732,6 +758,11 @@ func (m *protoMap) Get(key ref.Val) ref.Val { return v } +// IsZeroValue returns true if the map is empty. +func (m *protoMap) IsZeroValue() bool { + return m.value.Len() == 0 +} + // Iterator implements the traits.Iterable interface method. func (m *protoMap) Iterator() traits.Iterator { // Copy the keys to make their order stable. @@ -758,7 +789,7 @@ func (m *protoMap) Type() ref.Type { } // Value implements the ref.Val interface method. -func (m *protoMap) Value() interface{} { +func (m *protoMap) Value() any { return m.value } diff --git a/vendor/github.com/google/cel-go/common/types/null.go b/vendor/github.com/google/cel-go/common/types/null.go index 3d3503c275..38927a112c 100644 --- a/vendor/github.com/google/cel-go/common/types/null.go +++ b/vendor/github.com/google/cel-go/common/types/null.go @@ -18,9 +18,10 @@ import ( "fmt" "reflect" - "github.com/google/cel-go/common/types/ref" "google.golang.org/protobuf/proto" + "github.com/google/cel-go/common/types/ref" + anypb "google.golang.org/protobuf/types/known/anypb" structpb "google.golang.org/protobuf/types/known/structpb" ) @@ -34,14 +35,20 @@ var ( // NullValue singleton. NullValue = Null(structpb.NullValue_NULL_VALUE) - jsonNullType = reflect.TypeOf(structpb.NullValue_NULL_VALUE) + // golang reflect type for Null values. + nullReflectType = reflect.TypeOf(NullValue) ) // ConvertToNative implements ref.Val.ConvertToNative. -func (n Null) ConvertToNative(typeDesc reflect.Type) (interface{}, error) { +func (n Null) ConvertToNative(typeDesc reflect.Type) (any, error) { switch typeDesc.Kind() { case reflect.Int32: - return reflect.ValueOf(n).Convert(typeDesc).Interface(), nil + switch typeDesc { + case jsonNullType: + return structpb.NullValue_NULL_VALUE, nil + case nullReflectType: + return n, nil + } case reflect.Ptr: switch typeDesc { case anyValueType: @@ -54,6 +61,10 @@ func (n Null) ConvertToNative(typeDesc reflect.Type) (interface{}, error) { return anypb.New(pb.(proto.Message)) case jsonValueType: return structpb.NewNullValue(), nil + case boolWrapperType, byteWrapperType, doubleWrapperType, floatWrapperType, + int32WrapperType, int64WrapperType, stringWrapperType, uint32WrapperType, + uint64WrapperType: + return nil, nil } case reflect.Interface: nv := n.Value() @@ -86,12 +97,17 @@ func (n Null) Equal(other ref.Val) ref.Val { return Bool(NullType == other.Type()) } +// IsZeroValue returns true as null always represents an absent value. +func (n Null) IsZeroValue() bool { + return true +} + // Type implements ref.Val.Type. func (n Null) Type() ref.Type { return NullType } // Value implements ref.Val.Value. -func (n Null) Value() interface{} { +func (n Null) Value() any { return structpb.NullValue_NULL_VALUE } diff --git a/vendor/github.com/google/cel-go/common/types/object.go b/vendor/github.com/google/cel-go/common/types/object.go index 5faf855110..9955e2dce5 100644 --- a/vendor/github.com/google/cel-go/common/types/object.go +++ b/vendor/github.com/google/cel-go/common/types/object.go @@ -18,11 +18,12 @@ import ( "fmt" "reflect" - "github.com/google/cel-go/common/types/pb" - "github.com/google/cel-go/common/types/ref" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" + "github.com/google/cel-go/common/types/pb" + "github.com/google/cel-go/common/types/ref" + anypb "google.golang.org/protobuf/types/known/anypb" structpb "google.golang.org/protobuf/types/known/structpb" ) @@ -52,7 +53,7 @@ func NewObject(adapter ref.TypeAdapter, typeValue: typeValue} } -func (o *protoObj) ConvertToNative(typeDesc reflect.Type) (interface{}, error) { +func (o *protoObj) ConvertToNative(typeDesc reflect.Type) (any, error) { srcPB := o.value if reflect.TypeOf(srcPB).AssignableTo(typeDesc) { return srcPB, nil @@ -133,6 +134,11 @@ func (o *protoObj) IsSet(field ref.Val) ref.Val { return False } +// IsZeroValue returns true if the protobuf object is empty. +func (o *protoObj) IsZeroValue() bool { + return proto.Equal(o.value, o.typeDesc.Zero()) +} + func (o *protoObj) Get(index ref.Val) ref.Val { protoFieldName, ok := index.(String) if !ok { @@ -154,6 +160,6 @@ func (o *protoObj) Type() ref.Type { return o.typeValue } -func (o *protoObj) Value() interface{} { +func (o *protoObj) Value() any { return o.value } diff --git a/vendor/github.com/google/cel-go/common/types/optional.go b/vendor/github.com/google/cel-go/common/types/optional.go new file mode 100644 index 0000000000..54cb35b1ab --- /dev/null +++ b/vendor/github.com/google/cel-go/common/types/optional.go @@ -0,0 +1,108 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "errors" + "fmt" + "reflect" + + "github.com/google/cel-go/common/types/ref" +) + +var ( + // OptionalType indicates the runtime type of an optional value. + OptionalType = NewTypeValue("optional") + + // OptionalNone is a sentinel value which is used to indicate an empty optional value. + OptionalNone = &Optional{} +) + +// OptionalOf returns an optional value which wraps a concrete CEL value. +func OptionalOf(value ref.Val) *Optional { + return &Optional{value: value} +} + +// Optional value which points to a value if non-empty. +type Optional struct { + value ref.Val +} + +// HasValue returns true if the optional has a value. +func (o *Optional) HasValue() bool { + return o.value != nil +} + +// GetValue returns the wrapped value contained in the optional. +func (o *Optional) GetValue() ref.Val { + if !o.HasValue() { + return NewErr("optional.none() dereference") + } + return o.value +} + +// ConvertToNative implements the ref.Val interface method. +func (o *Optional) ConvertToNative(typeDesc reflect.Type) (any, error) { + if !o.HasValue() { + return nil, errors.New("optional.none() dereference") + } + return o.value.ConvertToNative(typeDesc) +} + +// ConvertToType implements the ref.Val interface method. +func (o *Optional) ConvertToType(typeVal ref.Type) ref.Val { + switch typeVal { + case OptionalType: + return o + case TypeType: + return OptionalType + } + return NewErr("type conversion error from '%s' to '%s'", OptionalType, typeVal) +} + +// Equal determines whether the values contained by two optional values are equal. +func (o *Optional) Equal(other ref.Val) ref.Val { + otherOpt, isOpt := other.(*Optional) + if !isOpt { + return False + } + if !o.HasValue() { + return Bool(!otherOpt.HasValue()) + } + if !otherOpt.HasValue() { + return False + } + return o.value.Equal(otherOpt.value) +} + +func (o *Optional) String() string { + if o.HasValue() { + return fmt.Sprintf("optional(%v)", o.GetValue()) + } + return "optional.none()" +} + +// Type implements the ref.Val interface method. +func (o *Optional) Type() ref.Type { + return OptionalType +} + +// Value returns the underlying 'Value()' of the wrapped value, if present. +func (o *Optional) Value() any { + if o.value == nil { + return nil + } + return o.value.Value() +} diff --git a/vendor/github.com/google/cel-go/common/types/pb/enum.go b/vendor/github.com/google/cel-go/common/types/pb/enum.go index 4a26b5c7c3..09a1546308 100644 --- a/vendor/github.com/google/cel-go/common/types/pb/enum.go +++ b/vendor/github.com/google/cel-go/common/types/pb/enum.go @@ -18,9 +18,9 @@ import ( "google.golang.org/protobuf/reflect/protoreflect" ) -// NewEnumValueDescription produces an enum value description with the fully qualified enum value +// newEnumValueDescription produces an enum value description with the fully qualified enum value // name and the enum value descriptor. -func NewEnumValueDescription(name string, desc protoreflect.EnumValueDescriptor) *EnumValueDescription { +func newEnumValueDescription(name string, desc protoreflect.EnumValueDescriptor) *EnumValueDescription { return &EnumValueDescription{ enumValueName: name, desc: desc, diff --git a/vendor/github.com/google/cel-go/common/types/pb/file.go b/vendor/github.com/google/cel-go/common/types/pb/file.go index 0bcade75f9..e323afb1df 100644 --- a/vendor/github.com/google/cel-go/common/types/pb/file.go +++ b/vendor/github.com/google/cel-go/common/types/pb/file.go @@ -18,32 +18,66 @@ import ( "fmt" "google.golang.org/protobuf/reflect/protoreflect" + + dynamicpb "google.golang.org/protobuf/types/dynamicpb" ) -// NewFileDescription returns a FileDescription instance with a complete listing of all the message -// types and enum values declared within any scope in the file. -func NewFileDescription(fileDesc protoreflect.FileDescriptor, pbdb *Db) *FileDescription { +// newFileDescription returns a FileDescription instance with a complete listing of all the message +// types and enum values, as well as a map of extensions declared within any scope in the file. +func newFileDescription(fileDesc protoreflect.FileDescriptor, pbdb *Db) (*FileDescription, extensionMap) { metadata := collectFileMetadata(fileDesc) enums := make(map[string]*EnumValueDescription) for name, enumVal := range metadata.enumValues { - enums[name] = NewEnumValueDescription(name, enumVal) + enums[name] = newEnumValueDescription(name, enumVal) } types := make(map[string]*TypeDescription) for name, msgType := range metadata.msgTypes { - types[name] = NewTypeDescription(name, msgType) + types[name] = newTypeDescription(name, msgType, pbdb.extensions) + } + fileExtMap := make(extensionMap) + for typeName, extensions := range metadata.msgExtensionMap { + messageExtMap, found := fileExtMap[typeName] + if !found { + messageExtMap = make(map[string]*FieldDescription) + } + for _, ext := range extensions { + extDesc := dynamicpb.NewExtensionType(ext).TypeDescriptor() + messageExtMap[string(ext.FullName())] = newFieldDescription(extDesc) + } + fileExtMap[typeName] = messageExtMap } return &FileDescription{ + name: fileDesc.Path(), types: types, enums: enums, - } + }, fileExtMap } // FileDescription holds a map of all types and enum values declared within a proto file. type FileDescription struct { + name string types map[string]*TypeDescription enums map[string]*EnumValueDescription } +// Copy creates a copy of the FileDescription with updated Db references within its types. +func (fd *FileDescription) Copy(pbdb *Db) *FileDescription { + typesCopy := make(map[string]*TypeDescription, len(fd.types)) + for k, v := range fd.types { + typesCopy[k] = v.Copy(pbdb) + } + return &FileDescription{ + name: fd.name, + types: typesCopy, + enums: fd.enums, + } +} + +// GetName returns the fully qualified file path for the file. +func (fd *FileDescription) GetName() string { + return fd.name +} + // GetEnumDescription returns an EnumDescription for a qualified enum value // name declared within the .proto file. func (fd *FileDescription) GetEnumDescription(enumName string) (*EnumValueDescription, bool) { @@ -94,6 +128,10 @@ type fileMetadata struct { msgTypes map[string]protoreflect.MessageDescriptor // enumValues maps from fully-qualified enum value to enum value descriptor. enumValues map[string]protoreflect.EnumValueDescriptor + // msgExtensionMap maps from the protobuf message name being extended to a set of extensions + // for the type. + msgExtensionMap map[string][]protoreflect.ExtensionDescriptor + // TODO: support enum type definitions for use in future type-check enhancements. } @@ -102,28 +140,38 @@ type fileMetadata struct { func collectFileMetadata(fileDesc protoreflect.FileDescriptor) *fileMetadata { msgTypes := make(map[string]protoreflect.MessageDescriptor) enumValues := make(map[string]protoreflect.EnumValueDescriptor) - collectMsgTypes(fileDesc.Messages(), msgTypes, enumValues) + msgExtensionMap := make(map[string][]protoreflect.ExtensionDescriptor) + collectMsgTypes(fileDesc.Messages(), msgTypes, enumValues, msgExtensionMap) collectEnumValues(fileDesc.Enums(), enumValues) + collectExtensions(fileDesc.Extensions(), msgExtensionMap) return &fileMetadata{ - msgTypes: msgTypes, - enumValues: enumValues, + msgTypes: msgTypes, + enumValues: enumValues, + msgExtensionMap: msgExtensionMap, } } // collectMsgTypes recursively collects messages, nested messages, and nested enums into a map of // fully qualified protobuf names to descriptors. -func collectMsgTypes(msgTypes protoreflect.MessageDescriptors, msgTypeMap map[string]protoreflect.MessageDescriptor, enumValueMap map[string]protoreflect.EnumValueDescriptor) { +func collectMsgTypes(msgTypes protoreflect.MessageDescriptors, + msgTypeMap map[string]protoreflect.MessageDescriptor, + enumValueMap map[string]protoreflect.EnumValueDescriptor, + msgExtensionMap map[string][]protoreflect.ExtensionDescriptor) { for i := 0; i < msgTypes.Len(); i++ { msgType := msgTypes.Get(i) msgTypeMap[string(msgType.FullName())] = msgType nestedMsgTypes := msgType.Messages() if nestedMsgTypes.Len() != 0 { - collectMsgTypes(nestedMsgTypes, msgTypeMap, enumValueMap) + collectMsgTypes(nestedMsgTypes, msgTypeMap, enumValueMap, msgExtensionMap) } nestedEnumTypes := msgType.Enums() if nestedEnumTypes.Len() != 0 { collectEnumValues(nestedEnumTypes, enumValueMap) } + nestedExtensions := msgType.Extensions() + if nestedExtensions.Len() != 0 { + collectExtensions(nestedExtensions, msgExtensionMap) + } } } @@ -139,3 +187,16 @@ func collectEnumValues(enumTypes protoreflect.EnumDescriptors, enumValueMap map[ } } } + +func collectExtensions(extensions protoreflect.ExtensionDescriptors, msgExtensionMap map[string][]protoreflect.ExtensionDescriptor) { + for i := 0; i < extensions.Len(); i++ { + ext := extensions.Get(i) + extendsMsg := string(ext.ContainingMessage().FullName()) + msgExts, found := msgExtensionMap[extendsMsg] + if !found { + msgExts = []protoreflect.ExtensionDescriptor{} + } + msgExts = append(msgExts, ext) + msgExtensionMap[extendsMsg] = msgExts + } +} diff --git a/vendor/github.com/google/cel-go/common/types/pb/pb.go b/vendor/github.com/google/cel-go/common/types/pb/pb.go index 457b47ceee..eadebcb04e 100644 --- a/vendor/github.com/google/cel-go/common/types/pb/pb.go +++ b/vendor/github.com/google/cel-go/common/types/pb/pb.go @@ -40,13 +40,19 @@ type Db struct { revFileDescriptorMap map[string]*FileDescription // files contains the deduped set of FileDescriptions whose types are contained in the pb.Db. files []*FileDescription + // extensions contains the mapping between a given type name, extension name and its FieldDescription + extensions map[string]map[string]*FieldDescription } +// extensionsMap is a type alias to a map[typeName]map[extensionName]*FieldDescription +type extensionMap = map[string]map[string]*FieldDescription + var ( // DefaultDb used at evaluation time or unless overridden at check time. DefaultDb = &Db{ revFileDescriptorMap: make(map[string]*FileDescription), files: []*FileDescription{}, + extensions: make(extensionMap), } ) @@ -80,6 +86,7 @@ func NewDb() *Db { pbdb := &Db{ revFileDescriptorMap: make(map[string]*FileDescription), files: []*FileDescription{}, + extensions: make(extensionMap), } // The FileDescription objects in the default db contain lazily initialized TypeDescription // values which may point to the state contained in the DefaultDb irrespective of this shallow @@ -96,19 +103,34 @@ func NewDb() *Db { // Copy creates a copy of the current database with its own internal descriptor mapping. func (pbdb *Db) Copy() *Db { copy := NewDb() - for k, v := range pbdb.revFileDescriptorMap { - copy.revFileDescriptorMap[k] = v - } - for _, f := range pbdb.files { + for _, fd := range pbdb.files { hasFile := false - for _, f2 := range copy.files { - if f2 == f { + for _, fd2 := range copy.files { + if fd2 == fd { hasFile = true } } if !hasFile { - copy.files = append(copy.files, f) + fd = fd.Copy(copy) + copy.files = append(copy.files, fd) + } + for _, enumValName := range fd.GetEnumNames() { + copy.revFileDescriptorMap[enumValName] = fd + } + for _, msgTypeName := range fd.GetTypeNames() { + copy.revFileDescriptorMap[msgTypeName] = fd + } + copy.revFileDescriptorMap[fd.GetName()] = fd + } + for typeName, extFieldMap := range pbdb.extensions { + copyExtFieldMap, found := copy.extensions[typeName] + if !found { + copyExtFieldMap = make(map[string]*FieldDescription, len(extFieldMap)) } + for extFieldName, fd := range extFieldMap { + copyExtFieldMap[extFieldName] = fd + } + copy.extensions[typeName] = copyExtFieldMap } return copy } @@ -137,17 +159,30 @@ func (pbdb *Db) RegisterDescriptor(fileDesc protoreflect.FileDescriptor) (*FileD if err == nil { fileDesc = globalFD } - fd = NewFileDescription(fileDesc, pbdb) + var fileExtMap extensionMap + fd, fileExtMap = newFileDescription(fileDesc, pbdb) for _, enumValName := range fd.GetEnumNames() { pbdb.revFileDescriptorMap[enumValName] = fd } for _, msgTypeName := range fd.GetTypeNames() { pbdb.revFileDescriptorMap[msgTypeName] = fd } - pbdb.revFileDescriptorMap[fileDesc.Path()] = fd + pbdb.revFileDescriptorMap[fd.GetName()] = fd // Return the specific file descriptor registered. pbdb.files = append(pbdb.files, fd) + + // Index the protobuf message extensions from the file into the pbdb + for typeName, extMap := range fileExtMap { + typeExtMap, found := pbdb.extensions[typeName] + if !found { + pbdb.extensions[typeName] = extMap + continue + } + for extName, field := range extMap { + typeExtMap[extName] = field + } + } return fd, nil } diff --git a/vendor/github.com/google/cel-go/common/types/pb/type.go b/vendor/github.com/google/cel-go/common/types/pb/type.go index 912076fa48..df9532156a 100644 --- a/vendor/github.com/google/cel-go/common/types/pb/type.go +++ b/vendor/github.com/google/cel-go/common/types/pb/type.go @@ -38,22 +38,23 @@ type description interface { Zero() proto.Message } -// NewTypeDescription produces a TypeDescription value for the fully-qualified proto type name +// newTypeDescription produces a TypeDescription value for the fully-qualified proto type name // with a given descriptor. -func NewTypeDescription(typeName string, desc protoreflect.MessageDescriptor) *TypeDescription { +func newTypeDescription(typeName string, desc protoreflect.MessageDescriptor, extensions extensionMap) *TypeDescription { msgType := dynamicpb.NewMessageType(desc) msgZero := dynamicpb.NewMessage(desc) fieldMap := map[string]*FieldDescription{} fields := desc.Fields() for i := 0; i < fields.Len(); i++ { f := fields.Get(i) - fieldMap[string(f.Name())] = NewFieldDescription(f) + fieldMap[string(f.Name())] = newFieldDescription(f) } return &TypeDescription{ typeName: typeName, desc: desc, msgType: msgType, fieldMap: fieldMap, + extensions: extensions, reflectType: reflectTypeOf(msgZero), zeroMsg: zeroValueOf(msgZero), } @@ -66,10 +67,24 @@ type TypeDescription struct { desc protoreflect.MessageDescriptor msgType protoreflect.MessageType fieldMap map[string]*FieldDescription + extensions extensionMap reflectType reflect.Type zeroMsg proto.Message } +// Copy copies the type description with updated references to the Db. +func (td *TypeDescription) Copy(pbdb *Db) *TypeDescription { + return &TypeDescription{ + typeName: td.typeName, + desc: td.desc, + msgType: td.msgType, + fieldMap: td.fieldMap, + extensions: pbdb.extensions, + reflectType: td.reflectType, + zeroMsg: td.zeroMsg, + } +} + // FieldMap returns a string field name to FieldDescription map. func (td *TypeDescription) FieldMap() map[string]*FieldDescription { return td.fieldMap @@ -78,16 +93,21 @@ func (td *TypeDescription) FieldMap() map[string]*FieldDescription { // FieldByName returns (FieldDescription, true) if the field name is declared within the type. func (td *TypeDescription) FieldByName(name string) (*FieldDescription, bool) { fd, found := td.fieldMap[name] + if found { + return fd, true + } + extFieldMap, found := td.extensions[td.typeName] if !found { return nil, false } - return fd, true + fd, found = extFieldMap[name] + return fd, found } // MaybeUnwrap accepts a proto message as input and unwraps it to a primitive CEL type if possible. // // This method returns the unwrapped value and 'true', else the original value and 'false'. -func (td *TypeDescription) MaybeUnwrap(msg proto.Message) (interface{}, bool, error) { +func (td *TypeDescription) MaybeUnwrap(msg proto.Message) (any, bool, error) { return unwrap(td, msg) } @@ -111,8 +131,8 @@ func (td *TypeDescription) Zero() proto.Message { return td.zeroMsg } -// NewFieldDescription creates a new field description from a protoreflect.FieldDescriptor. -func NewFieldDescription(fieldDesc protoreflect.FieldDescriptor) *FieldDescription { +// newFieldDescription creates a new field description from a protoreflect.FieldDescriptor. +func newFieldDescription(fieldDesc protoreflect.FieldDescriptor) *FieldDescription { var reflectType reflect.Type var zeroMsg proto.Message switch fieldDesc.Kind() { @@ -124,9 +144,17 @@ func NewFieldDescription(fieldDesc protoreflect.FieldDescriptor) *FieldDescripti default: reflectType = reflectTypeOf(fieldDesc.Default().Interface()) if fieldDesc.IsList() { - parentMsg := dynamicpb.NewMessage(fieldDesc.ContainingMessage()) - listField := parentMsg.NewField(fieldDesc).List() - elem := listField.NewElement().Interface() + var elemValue protoreflect.Value + if fieldDesc.IsExtension() { + et := dynamicpb.NewExtensionType(fieldDesc) + elemValue = et.New().List().NewElement() + } else { + parentMsgType := fieldDesc.ContainingMessage() + parentMsg := dynamicpb.NewMessage(parentMsgType) + listField := parentMsg.NewField(fieldDesc).List() + elemValue = listField.NewElement() + } + elem := elemValue.Interface() switch elemType := elem.(type) { case protoreflect.Message: elem = elemType.Interface() @@ -140,8 +168,8 @@ func NewFieldDescription(fieldDesc protoreflect.FieldDescriptor) *FieldDescripti } var keyType, valType *FieldDescription if fieldDesc.IsMap() { - keyType = NewFieldDescription(fieldDesc.MapKey()) - valType = NewFieldDescription(fieldDesc.MapValue()) + keyType = newFieldDescription(fieldDesc.MapKey()) + valType = newFieldDescription(fieldDesc.MapValue()) } return &FieldDescription{ desc: fieldDesc, @@ -195,7 +223,7 @@ func (fd *FieldDescription) Descriptor() protoreflect.FieldDescriptor { // // This function implements the FieldType.IsSet function contract which can be used to operate on // more than just protobuf field accesses; however, the target here must be a protobuf.Message. -func (fd *FieldDescription) IsSet(target interface{}) bool { +func (fd *FieldDescription) IsSet(target any) bool { switch v := target.(type) { case proto.Message: pbRef := v.ProtoReflect() @@ -219,14 +247,14 @@ func (fd *FieldDescription) IsSet(target interface{}) bool { // // This function implements the FieldType.GetFrom function contract which can be used to operate // on more than just protobuf field accesses; however, the target here must be a protobuf.Message. -func (fd *FieldDescription) GetFrom(target interface{}) (interface{}, error) { +func (fd *FieldDescription) GetFrom(target any) (any, error) { v, ok := target.(proto.Message) if !ok { return nil, fmt.Errorf("unsupported field selection target: (%T)%v", target, target) } pbRef := v.ProtoReflect() pbDesc := pbRef.Descriptor() - var fieldVal interface{} + var fieldVal any if pbDesc == fd.desc.ContainingMessage() { // When the target protobuf shares the same message descriptor instance as the field // descriptor, use the cached field descriptor value. @@ -289,7 +317,7 @@ func (fd *FieldDescription) IsList() bool { // // This function returns the unwrapped value and 'true' on success, or the original value // and 'false' otherwise. -func (fd *FieldDescription) MaybeUnwrapDynamic(msg protoreflect.Message) (interface{}, bool, error) { +func (fd *FieldDescription) MaybeUnwrapDynamic(msg protoreflect.Message) (any, bool, error) { return unwrapDynamic(fd, msg) } @@ -362,7 +390,7 @@ func checkedWrap(t *exprpb.Type) *exprpb.Type { // input message is a *dynamicpb.Message which obscures the typing information from Go. // // Returns the unwrapped value and 'true' if unwrapped, otherwise the input value and 'false'. -func unwrap(desc description, msg proto.Message) (interface{}, bool, error) { +func unwrap(desc description, msg proto.Message) (any, bool, error) { switch v := msg.(type) { case *anypb.Any: dynMsg, err := v.UnmarshalNew() @@ -418,7 +446,7 @@ func unwrap(desc description, msg proto.Message) (interface{}, bool, error) { // unwrapDynamic unwraps a reflected protobuf Message value. // // Returns the unwrapped value and 'true' if unwrapped, otherwise the input value and 'false'. -func unwrapDynamic(desc description, refMsg protoreflect.Message) (interface{}, bool, error) { +func unwrapDynamic(desc description, refMsg protoreflect.Message) (any, bool, error) { msg := refMsg.Interface() if !refMsg.IsValid() { msg = desc.Zero() @@ -508,7 +536,7 @@ func unwrapDynamic(desc description, refMsg protoreflect.Message) (interface{}, // reflectTypeOf intercepts the reflect.Type call to ensure that dynamicpb.Message types preserve // well-known protobuf reflected types expected by the CEL type system. -func reflectTypeOf(val interface{}) reflect.Type { +func reflectTypeOf(val any) reflect.Type { switch v := val.(type) { case proto.Message: return reflect.TypeOf(zeroValueOf(v)) diff --git a/vendor/github.com/google/cel-go/common/types/provider.go b/vendor/github.com/google/cel-go/common/types/provider.go index 02087d14e3..e66951f5b2 100644 --- a/vendor/github.com/google/cel-go/common/types/provider.go +++ b/vendor/github.com/google/cel-go/common/types/provider.go @@ -19,11 +19,12 @@ import ( "reflect" "time" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + "github.com/google/cel-go/common/types/pb" "github.com/google/cel-go/common/types/ref" "github.com/google/cel-go/common/types/traits" - "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/reflect/protoreflect" exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1" anypb "google.golang.org/protobuf/types/known/anypb" @@ -195,7 +196,7 @@ func (p *protoTypeRegistry) RegisterType(types ...ref.Type) error { // providing support for custom proto-based types. // // This method should be the inverse of ref.Val.ConvertToNative. -func (p *protoTypeRegistry) NativeToValue(value interface{}) ref.Val { +func (p *protoTypeRegistry) NativeToValue(value any) ref.Val { if val, found := nativeToValue(p, value); found { return val } @@ -249,7 +250,7 @@ var ( ) // NativeToValue implements the ref.TypeAdapter interface. -func (a *defaultTypeAdapter) NativeToValue(value interface{}) ref.Val { +func (a *defaultTypeAdapter) NativeToValue(value any) ref.Val { if val, found := nativeToValue(a, value); found { return val } @@ -258,7 +259,7 @@ func (a *defaultTypeAdapter) NativeToValue(value interface{}) ref.Val { // nativeToValue returns the converted (ref.Val, true) of a conversion is found, // otherwise (nil, false) -func nativeToValue(a ref.TypeAdapter, value interface{}) (ref.Val, bool) { +func nativeToValue(a ref.TypeAdapter, value any) (ref.Val, bool) { switch v := value.(type) { case nil: return NullValue, true @@ -364,7 +365,7 @@ func nativeToValue(a ref.TypeAdapter, value interface{}) (ref.Val, bool) { // specializations for common map types. case map[string]string: return NewStringStringMap(a, v), true - case map[string]interface{}: + case map[string]any: return NewStringInterfaceMap(a, v), true case map[ref.Val]ref.Val: return NewRefValMap(a, v), true @@ -479,9 +480,12 @@ func msgSetField(target protoreflect.Message, field *pb.FieldDescription, val re if err != nil { return fieldTypeConversionError(field, err) } - switch v.(type) { + if v == nil { + return nil + } + switch pv := v.(type) { case proto.Message: - v = v.(proto.Message).ProtoReflect() + v = pv.ProtoReflect() } target.Set(field.Descriptor(), protoreflect.ValueOf(v)) return nil @@ -495,6 +499,9 @@ func msgSetListField(target protoreflect.List, listField *pb.FieldDescription, l if err != nil { return fieldTypeConversionError(listField, err) } + if elemVal == nil { + continue + } switch ev := elemVal.(type) { case proto.Message: elemVal = ev.ProtoReflect() @@ -519,9 +526,12 @@ func msgSetMapField(target protoreflect.Map, mapField *pb.FieldDescription, mapV if err != nil { return fieldTypeConversionError(mapField, err) } - switch v.(type) { + if v == nil { + continue + } + switch pv := v.(type) { case proto.Message: - v = v.(proto.Message).ProtoReflect() + v = pv.ProtoReflect() } target.Set(protoreflect.ValueOf(k).MapKey(), protoreflect.ValueOf(v)) } diff --git a/vendor/github.com/google/cel-go/common/types/ref/provider.go b/vendor/github.com/google/cel-go/common/types/ref/provider.go index 91a711fa70..7eabbb9ca3 100644 --- a/vendor/github.com/google/cel-go/common/types/ref/provider.go +++ b/vendor/github.com/google/cel-go/common/types/ref/provider.go @@ -39,8 +39,6 @@ type TypeProvider interface { // FieldFieldType returns the field type for a checked type value. Returns // false if the field could not be found. - // - // Used during type-checking only. FindFieldType(messageType string, fieldName string) (*FieldType, bool) // NewValue creates a new type value from a qualified name and map of field @@ -55,7 +53,7 @@ type TypeProvider interface { // TypeAdapter converts native Go values of varying type and complexity to equivalent CEL values. type TypeAdapter interface { // NativeToValue converts the input `value` to a CEL `ref.Val`. - NativeToValue(value interface{}) Val + NativeToValue(value any) Val } // TypeRegistry allows third-parties to add custom types to CEL. Not all `TypeProvider` @@ -97,7 +95,7 @@ type FieldType struct { } // FieldTester is used to test field presence on an input object. -type FieldTester func(target interface{}) bool +type FieldTester func(target any) bool // FieldGetter is used to get the field value from an input object, if set. -type FieldGetter func(target interface{}) (interface{}, error) +type FieldGetter func(target any) (any, error) diff --git a/vendor/github.com/google/cel-go/common/types/ref/reference.go b/vendor/github.com/google/cel-go/common/types/ref/reference.go index 3098580c91..e0d58145cd 100644 --- a/vendor/github.com/google/cel-go/common/types/ref/reference.go +++ b/vendor/github.com/google/cel-go/common/types/ref/reference.go @@ -37,9 +37,18 @@ type Type interface { type Val interface { // ConvertToNative converts the Value to a native Go struct according to the // reflected type description, or error if the conversion is not feasible. - ConvertToNative(typeDesc reflect.Type) (interface{}, error) + // + // The ConvertToNative method is intended to be used to support conversion between CEL types + // and native types during object creation expressions or by clients who need to adapt the, + // returned CEL value into an equivalent Go value instance. + // + // When implementing or using ConvertToNative, the following guidelines apply: + // - Use ConvertToNative when marshalling CEL evaluation results to native types. + // - Do not use ConvertToNative within CEL extension functions. + // - Document whether your implementation supports non-CEL field types, such as Go or Protobuf. + ConvertToNative(typeDesc reflect.Type) (any, error) - // ConvertToType supports type conversions between value types supported by the expression language. + // ConvertToType supports type conversions between CEL value types supported by the expression language. ConvertToType(typeValue Type) Val // Equal returns true if the `other` value has the same type and content as the implementing struct. @@ -50,5 +59,5 @@ type Val interface { // Value returns the raw value of the instance which may not be directly compatible with the expression // language types. - Value() interface{} + Value() any } diff --git a/vendor/github.com/google/cel-go/common/types/string.go b/vendor/github.com/google/cel-go/common/types/string.go index b6d665683c..a65cc14e4c 100644 --- a/vendor/github.com/google/cel-go/common/types/string.go +++ b/vendor/github.com/google/cel-go/common/types/string.go @@ -72,7 +72,7 @@ func (s String) Compare(other ref.Val) ref.Val { } // ConvertToNative implements ref.Val.ConvertToNative. -func (s String) ConvertToNative(typeDesc reflect.Type) (interface{}, error) { +func (s String) ConvertToNative(typeDesc reflect.Type) (any, error) { switch typeDesc.Kind() { case reflect.String: if reflect.TypeOf(s).AssignableTo(typeDesc) { @@ -154,6 +154,11 @@ func (s String) Equal(other ref.Val) ref.Val { return Bool(ok && s == otherString) } +// IsZeroValue returns true if the string is empty. +func (s String) IsZeroValue() bool { + return len(s) == 0 +} + // Match implements traits.Matcher.Match. func (s String) Match(pattern ref.Val) ref.Val { pat, ok := pattern.(String) @@ -189,7 +194,7 @@ func (s String) Type() ref.Type { } // Value implements ref.Val.Value. -func (s String) Value() interface{} { +func (s String) Value() any { return string(s) } diff --git a/vendor/github.com/google/cel-go/common/types/timestamp.go b/vendor/github.com/google/cel-go/common/types/timestamp.go index 7513a1b210..c784f2e54b 100644 --- a/vendor/github.com/google/cel-go/common/types/timestamp.go +++ b/vendor/github.com/google/cel-go/common/types/timestamp.go @@ -89,7 +89,7 @@ func (t Timestamp) Compare(other ref.Val) ref.Val { } // ConvertToNative implements ref.Val.ConvertToNative. -func (t Timestamp) ConvertToNative(typeDesc reflect.Type) (interface{}, error) { +func (t Timestamp) ConvertToNative(typeDesc reflect.Type) (any, error) { // If the timestamp is already assignable to the desired type return it. if reflect.TypeOf(t.Time).AssignableTo(typeDesc) { return t.Time, nil @@ -138,6 +138,11 @@ func (t Timestamp) Equal(other ref.Val) ref.Val { return Bool(ok && t.Time.Equal(otherTime.Time)) } +// IsZeroValue returns true if the timestamp is epoch 0. +func (t Timestamp) IsZeroValue() bool { + return t.IsZero() +} + // Receive implements traits.Receiver.Receive. func (t Timestamp) Receive(function string, overload string, args []ref.Val) ref.Val { switch len(args) { @@ -160,14 +165,14 @@ func (t Timestamp) Subtract(subtrahend ref.Val) ref.Val { dur := subtrahend.(Duration) val, err := subtractTimeDurationChecked(t.Time, dur.Duration) if err != nil { - return wrapErr(err) + return WrapErr(err) } return timestampOf(val) case TimestampType: t2 := subtrahend.(Timestamp).Time val, err := subtractTimeChecked(t.Time, t2) if err != nil { - return wrapErr(err) + return WrapErr(err) } return durationOf(val) } @@ -180,7 +185,7 @@ func (t Timestamp) Type() ref.Type { } // Value implements ref.Val.Value. -func (t Timestamp) Value() interface{} { +func (t Timestamp) Value() any { return t.Time } @@ -288,7 +293,7 @@ func timeZone(tz ref.Val, visitor timestampVisitor) timestampVisitor { if ind == -1 { loc, err := time.LoadLocation(val) if err != nil { - return wrapErr(err) + return WrapErr(err) } return visitor(t.In(loc)) } @@ -297,11 +302,11 @@ func timeZone(tz ref.Val, visitor timestampVisitor) timestampVisitor { // in the format ^(+|-)(0[0-9]|1[0-4]):[0-5][0-9]$. The numerical input is parsed in terms of hours and minutes. hr, err := strconv.Atoi(string(val[0:ind])) if err != nil { - return wrapErr(err) + return WrapErr(err) } min, err := strconv.Atoi(string(val[ind+1:])) if err != nil { - return wrapErr(err) + return WrapErr(err) } var offset int if string(val[0]) == "-" { diff --git a/vendor/github.com/google/cel-go/common/types/traits/BUILD.bazel b/vendor/github.com/google/cel-go/common/types/traits/BUILD.bazel index 86e54af61a..b19eb8301e 100644 --- a/vendor/github.com/google/cel-go/common/types/traits/BUILD.bazel +++ b/vendor/github.com/google/cel-go/common/types/traits/BUILD.bazel @@ -20,6 +20,7 @@ go_library( "receiver.go", "sizer.go", "traits.go", + "zeroer.go", ], importpath = "github.com/google/cel-go/common/types/traits", deps = [ diff --git a/vendor/github.com/google/cel-go/common/types/traits/zeroer.go b/vendor/github.com/google/cel-go/common/types/traits/zeroer.go new file mode 100644 index 0000000000..0b7c830a24 --- /dev/null +++ b/vendor/github.com/google/cel-go/common/types/traits/zeroer.go @@ -0,0 +1,21 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package traits + +// Zeroer interface for testing whether a CEL value is a zero value for its type. +type Zeroer interface { + // IsZeroValue indicates whether the object is the zero value for the type. + IsZeroValue() bool +} diff --git a/vendor/github.com/google/cel-go/common/types/type.go b/vendor/github.com/google/cel-go/common/types/type.go index 21160974bb..164a460503 100644 --- a/vendor/github.com/google/cel-go/common/types/type.go +++ b/vendor/github.com/google/cel-go/common/types/type.go @@ -53,7 +53,7 @@ func NewObjectTypeValue(name string) *TypeValue { } // ConvertToNative implements ref.Val.ConvertToNative. -func (t *TypeValue) ConvertToNative(typeDesc reflect.Type) (interface{}, error) { +func (t *TypeValue) ConvertToNative(typeDesc reflect.Type) (any, error) { // TODO: replace the internal type representation with a proto-value. return nil, fmt.Errorf("type conversion not supported for 'type'") } @@ -97,6 +97,6 @@ func (t *TypeValue) TypeName() string { } // Value implements ref.Val.Value. -func (t *TypeValue) Value() interface{} { +func (t *TypeValue) Value() any { return t.name } diff --git a/vendor/github.com/google/cel-go/common/types/uint.go b/vendor/github.com/google/cel-go/common/types/uint.go index ca266e0457..615c7ec523 100644 --- a/vendor/github.com/google/cel-go/common/types/uint.go +++ b/vendor/github.com/google/cel-go/common/types/uint.go @@ -59,7 +59,7 @@ func (i Uint) Add(other ref.Val) ref.Val { } val, err := addUint64Checked(uint64(i), uint64(otherUint)) if err != nil { - return wrapErr(err) + return WrapErr(err) } return Uint(val) } @@ -82,7 +82,7 @@ func (i Uint) Compare(other ref.Val) ref.Val { } // ConvertToNative implements ref.Val.ConvertToNative. -func (i Uint) ConvertToNative(typeDesc reflect.Type) (interface{}, error) { +func (i Uint) ConvertToNative(typeDesc reflect.Type) (any, error) { switch typeDesc.Kind() { case reflect.Uint, reflect.Uint32: v, err := uint64ToUint32Checked(uint64(i)) @@ -149,7 +149,7 @@ func (i Uint) ConvertToType(typeVal ref.Type) ref.Val { case IntType: v, err := uint64ToInt64Checked(uint64(i)) if err != nil { - return wrapErr(err) + return WrapErr(err) } return Int(v) case UintType: @@ -172,7 +172,7 @@ func (i Uint) Divide(other ref.Val) ref.Val { } div, err := divideUint64Checked(uint64(i), uint64(otherUint)) if err != nil { - return wrapErr(err) + return WrapErr(err) } return Uint(div) } @@ -194,6 +194,11 @@ func (i Uint) Equal(other ref.Val) ref.Val { } } +// IsZeroValue returns true if the uint is zero. +func (i Uint) IsZeroValue() bool { + return i == 0 +} + // Modulo implements traits.Modder.Modulo. func (i Uint) Modulo(other ref.Val) ref.Val { otherUint, ok := other.(Uint) @@ -202,7 +207,7 @@ func (i Uint) Modulo(other ref.Val) ref.Val { } mod, err := moduloUint64Checked(uint64(i), uint64(otherUint)) if err != nil { - return wrapErr(err) + return WrapErr(err) } return Uint(mod) } @@ -215,7 +220,7 @@ func (i Uint) Multiply(other ref.Val) ref.Val { } val, err := multiplyUint64Checked(uint64(i), uint64(otherUint)) if err != nil { - return wrapErr(err) + return WrapErr(err) } return Uint(val) } @@ -228,7 +233,7 @@ func (i Uint) Subtract(subtrahend ref.Val) ref.Val { } val, err := subtractUint64Checked(uint64(i), uint64(subtraUint)) if err != nil { - return wrapErr(err) + return WrapErr(err) } return Uint(val) } @@ -239,7 +244,7 @@ func (i Uint) Type() ref.Type { } // Value implements ref.Val.Value. -func (i Uint) Value() interface{} { +func (i Uint) Value() any { return uint64(i) } diff --git a/vendor/github.com/google/cel-go/common/types/unknown.go b/vendor/github.com/google/cel-go/common/types/unknown.go index 95b47426fd..bc411c15b9 100644 --- a/vendor/github.com/google/cel-go/common/types/unknown.go +++ b/vendor/github.com/google/cel-go/common/types/unknown.go @@ -30,7 +30,7 @@ var ( ) // ConvertToNative implements ref.Val.ConvertToNative. -func (u Unknown) ConvertToNative(typeDesc reflect.Type) (interface{}, error) { +func (u Unknown) ConvertToNative(typeDesc reflect.Type) (any, error) { return u.Value(), nil } @@ -50,7 +50,7 @@ func (u Unknown) Type() ref.Type { } // Value implements ref.Val.Value. -func (u Unknown) Value() interface{} { +func (u Unknown) Value() any { return []int64(u) } diff --git a/vendor/github.com/google/cel-go/ext/BUILD.bazel b/vendor/github.com/google/cel-go/ext/BUILD.bazel index 9c2520b408..7dfbc6f67d 100644 --- a/vendor/github.com/google/cel-go/ext/BUILD.bazel +++ b/vendor/github.com/google/cel-go/ext/BUILD.bazel @@ -9,14 +9,30 @@ go_library( srcs = [ "encoders.go", "guards.go", + "math.go", + "native.go", + "protos.go", + "sets.go", "strings.go", ], importpath = "github.com/google/cel-go/ext", visibility = ["//visibility:public"], deps = [ "//cel:go_default_library", + "//checker/decls:go_default_library", + "//common:go_default_library", + "//common/overloads:go_default_library", "//common/types:go_default_library", + "//common/types/pb:go_default_library", "//common/types/ref:go_default_library", + "//common/types/traits:go_default_library", + "//interpreter:go_default_library", + "@org_golang_google_genproto//googleapis/api/expr/v1alpha1:go_default_library", + "@org_golang_google_protobuf//proto:go_default_library", + "@org_golang_google_protobuf//reflect/protoreflect:go_default_library", + "@org_golang_google_protobuf//types/known/structpb", + "@org_golang_x_text//language:go_default_library", + "@org_golang_x_text//message:go_default_library", ], ) @@ -25,6 +41,10 @@ go_test( size = "small", srcs = [ "encoders_test.go", + "math_test.go", + "native_test.go", + "protos_test.go", + "sets_test.go", "strings_test.go", ], embed = [ @@ -32,5 +52,17 @@ go_test( ], deps = [ "//cel:go_default_library", + "//checker:go_default_library", + "//common:go_default_library", + "//common/types:go_default_library", + "//common/types/ref:go_default_library", + "//common/types/traits:go_default_library", + "//test:go_default_library", + "//test/proto2pb:go_default_library", + "//test/proto3pb:go_default_library", + "@org_golang_google_genproto//googleapis/api/expr/v1alpha1:go_default_library", + "@org_golang_google_protobuf//proto:go_default_library", + "@org_golang_google_protobuf//types/known/wrapperspb:go_default_library", + "@org_golang_google_protobuf//encoding/protojson:go_default_library", ], ) diff --git a/vendor/github.com/google/cel-go/ext/README.md b/vendor/github.com/google/cel-go/ext/README.md index 5ddcc41510..ef0eb2ab7f 100644 --- a/vendor/github.com/google/cel-go/ext/README.md +++ b/vendor/github.com/google/cel-go/ext/README.md @@ -3,6 +3,30 @@ CEL extensions are a related set of constants, functions, macros, or other features which may not be covered by the core CEL spec. +## Bindings + +Returns a cel.EnvOption to configure support for local variable bindings +in expressions. + +# Cel.Bind + +Binds a simple identifier to an initialization expression which may be used +in a subsequenct result expression. Bindings may also be nested within each +other. + + cel.bind(, , ) + +Examples: + + cel.bind(a, 'hello', + cel.bind(b, 'world', a + b + b + a)) // "helloworldworldhello" + + // Avoid a list allocation within the exists comprehension. + cel.bind(valid_values, [a, b, c], + [d, e, f].exists(elem, elem in valid_values)) + +Local bindings are not guaranteed to be evaluated before use. + ## Encoders Encoding utilies for marshalling data into standardized representations. @@ -31,6 +55,156 @@ Example: base64.encode(b'hello') // return 'aGVsbG8=' +## Math + +Math helper macros and functions. + +Note, all macros use the 'math' namespace; however, at the time of macro +expansion the namespace looks just like any other identifier. If you are +currently using a variable named 'math', the macro will likely work just as +intended; however, there is some chance for collision. + +### Math.Greatest + +Returns the greatest valued number present in the arguments to the macro. + +Greatest is a variable argument count macro which must take at least one +argument. Simple numeric and list literals are supported as valid argument +types; however, other literals will be flagged as errors during macro +expansion. If the argument expression does not resolve to a numeric or +list(numeric) type during type-checking, or during runtime then an error +will be produced. If a list argument is empty, this too will produce an +error. + + math.greatest(, ...) -> + +Examples: + + math.greatest(1) // 1 + math.greatest(1u, 2u) // 2u + math.greatest(-42.0, -21.5, -100.0) // -21.5 + math.greatest([-42.0, -21.5, -100.0]) // -21.5 + math.greatest(numbers) // numbers must be list(numeric) + + math.greatest() // parse error + math.greatest('string') // parse error + math.greatest(a, b) // check-time error if a or b is non-numeric + math.greatest(dyn('string')) // runtime error + +### Math.Least + +Returns the least valued number present in the arguments to the macro. + +Least is a variable argument count macro which must take at least one +argument. Simple numeric and list literals are supported as valid argument +types; however, other literals will be flagged as errors during macro +expansion. If the argument expression does not resolve to a numeric or +list(numeric) type during type-checking, or during runtime then an error +will be produced. If a list argument is empty, this too will produce an error. + + math.least(, ...) -> + +Examples: + + math.least(1) // 1 + math.least(1u, 2u) // 1u + math.least(-42.0, -21.5, -100.0) // -100.0 + math.least([-42.0, -21.5, -100.0]) // -100.0 + math.least(numbers) // numbers must be list(numeric) + + math.least() // parse error + math.least('string') // parse error + math.least(a, b) // check-time error if a or b is non-numeric + math.least(dyn('string')) // runtime error + +## Protos + +Protos configure extended macros and functions for proto manipulation. + +Note, all macros use the 'proto' namespace; however, at the time of macro +expansion the namespace looks just like any other identifier. If you are +currently using a variable named 'proto', the macro will likely work just as +you intend; however, there is some chance for collision. + +### Protos.GetExt + +Macro which generates a select expression that retrieves an extension field +from the input proto2 syntax message. If the field is not set, the default +value forthe extension field is returned according to safe-traversal semantics. + + proto.getExt(, ) -> + +Example: + + proto.getExt(msg, google.expr.proto2.test.int32_ext) // returns int value + +### Protos.HasExt + +Macro which generates a test-only select expression that determines whether +an extension field is set on a proto2 syntax message. + + proto.hasExt(, ) -> + +Example: + + proto.hasExt(msg, google.expr.proto2.test.int32_ext) // returns true || false + +## Sets + +Sets provides set relationship tests. + +There is no set type within CEL, and while one may be introduced in the +future, there are cases where a `list` type is known to behave like a set. +For such cases, this library provides some basic functionality for +determining set containment, equivalence, and intersection. + +### Sets.Contains + +Returns whether the first list argument contains all elements in the second +list argument. The list may contain elements of any type and standard CEL +equality is used to determine whether a value exists in both lists. If the +second list is empty, the result will always return true. + + sets.contains(list(T), list(T)) -> bool + +Examples: + + sets.contains([], []) // true + sets.contains([], [1]) // false + sets.contains([1, 2, 3, 4], [2, 3]) // true + sets.contains([1, 2.0, 3u], [1.0, 2u, 3]) // true + +### Sets.Equivalent + +Returns whether the first and second list are set equivalent. Lists are set +equivalent if for every item in the first list, there is an element in the +second which is equal. The lists may not be of the same size as they do not +guarantee the elements within them are unique, so size does not factor into +the computation. + + sets.equivalent(list(T), list(T)) -> bool + +Examples: + + sets.equivalent([], []) // true + sets.equivalent([1], [1, 1]) // true + sets.equivalent([1], [1u, 1.0]) // true + sets.equivalent([1, 2, 3], [3u, 2.0, 1]) // true + +### Sets.Intersects + +Returns whether the first list has at least one element whose value is equal +to an element in the second list. If either list is empty, the result will +be false. + + sets.intersects(list(T), list(T)) -> bool + +Examples: + + sets.intersects([1], []) // false + sets.intersects([1], [1, 2]) // true + sets.intersects([[1], [2, 3]], [[1, 2], [2, 3.0]]) // true + ## Strings Extended functions for string manipulation. As a general note, all indices are @@ -70,6 +244,23 @@ Examples: 'hello mellow'.indexOf('ello', 2) // returns 7 'hello mellow'.indexOf('ello', 20) // error +### Join + +Returns a new string where the elements of string list are concatenated. + +The function also accepts an optional separator which is placed between +elements in the resulting string. + + >.join() -> + >.join() -> + +Examples: + + ['hello', 'mellow'].join() // returns 'hellomellow' + ['hello', 'mellow'].join(' ') // returns 'hello mellow' + [].join() // returns '' + [].join('/') // returns '' + ### LastIndexOf Returns the integer index of the last occurrence of the search string. If the @@ -105,6 +296,20 @@ Examples: 'TacoCat'.lowerAscii() // returns 'tacocat' 'TacoCÆt Xii'.lowerAscii() // returns 'tacocÆt xii' +### Quote + +**Introduced in version 1** + +Takes the given string and makes it safe to print (without any formatting due to escape sequences). +If any invalid UTF-8 characters are encountered, they are replaced with \uFFFD. + + strings.quote() + +Examples: + + strings.quote('single-quote with "double quote"') // returns '"single-quote with \"double quote\""' + strings.quote("two escape sequences \a\n") // returns '"two escape sequences \\a\\n"' + ### Replace Returns a new string based on the target, which replaces the occurrences of a diff --git a/vendor/github.com/google/cel-go/ext/bindings.go b/vendor/github.com/google/cel-go/ext/bindings.go new file mode 100644 index 0000000000..9cc3c3efe5 --- /dev/null +++ b/vendor/github.com/google/cel-go/ext/bindings.go @@ -0,0 +1,100 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ext + +import ( + "github.com/google/cel-go/cel" + "github.com/google/cel-go/common" + + exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1" +) + +// Bindings returns a cel.EnvOption to configure support for local variable +// bindings in expressions. +// +// # Cel.Bind +// +// Binds a simple identifier to an initialization expression which may be used +// in a subsequenct result expression. Bindings may also be nested within each +// other. +// +// cel.bind(, , ) +// +// Examples: +// +// cel.bind(a, 'hello', +// cel.bind(b, 'world', a + b + b + a)) // "helloworldworldhello" +// +// // Avoid a list allocation within the exists comprehension. +// cel.bind(valid_values, [a, b, c], +// [d, e, f].exists(elem, elem in valid_values)) +// +// Local bindings are not guaranteed to be evaluated before use. +func Bindings() cel.EnvOption { + return cel.Lib(celBindings{}) +} + +const ( + celNamespace = "cel" + bindMacro = "bind" + unusedIterVar = "#unused" +) + +type celBindings struct{} + +func (celBindings) LibraryName() string { + return "cel.lib.ext.cel.bindings" +} + +func (celBindings) CompileOptions() []cel.EnvOption { + return []cel.EnvOption{ + cel.Macros( + // cel.bind(var, , ) + cel.NewReceiverMacro(bindMacro, 3, celBind), + ), + } +} + +func (celBindings) ProgramOptions() []cel.ProgramOption { + return []cel.ProgramOption{} +} + +func celBind(meh cel.MacroExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *common.Error) { + if !macroTargetMatchesNamespace(celNamespace, target) { + return nil, nil + } + varIdent := args[0] + varName := "" + switch varIdent.GetExprKind().(type) { + case *exprpb.Expr_IdentExpr: + varName = varIdent.GetIdentExpr().GetName() + default: + return nil, &common.Error{ + Message: "cel.bind() variable names must be simple identifers", + Location: meh.OffsetLocation(varIdent.GetId()), + } + } + varInit := args[1] + resultExpr := args[2] + return meh.Fold( + unusedIterVar, + meh.NewList(), + varName, + varInit, + meh.LiteralBool(false), + meh.Ident(varName), + resultExpr, + ), nil +} diff --git a/vendor/github.com/google/cel-go/ext/encoders.go b/vendor/github.com/google/cel-go/ext/encoders.go index 22e38c39f9..d9f9cb5152 100644 --- a/vendor/github.com/google/cel-go/ext/encoders.go +++ b/vendor/github.com/google/cel-go/ext/encoders.go @@ -26,34 +26,38 @@ import ( // Encoders returns a cel.EnvOption to configure extended functions for string, byte, and object // encodings. // -// Base64.Decode +// # Base64.Decode // // Decodes base64-encoded string to bytes. // // This function will return an error if the string input is not base64-encoded. // -// base64.decode() -> +// base64.decode() -> // // Examples: // -// base64.decode('aGVsbG8=') // return b'hello' -// base64.decode('aGVsbG8') // error +// base64.decode('aGVsbG8=') // return b'hello' +// base64.decode('aGVsbG8') // error // -// Base64.Encode +// # Base64.Encode // // Encodes bytes to a base64-encoded string. // -// base64.encode() -> +// base64.encode() -> // // Examples: // -// base64.encode(b'hello') // return b'aGVsbG8=' +// base64.encode(b'hello') // return b'aGVsbG8=' func Encoders() cel.EnvOption { return cel.Lib(encoderLib{}) } type encoderLib struct{} +func (encoderLib) LibraryName() string { + return "cel.lib.ext.encoders" +} + func (encoderLib) CompileOptions() []cel.EnvOption { return []cel.EnvOption{ cel.Function("base64.decode", diff --git a/vendor/github.com/google/cel-go/ext/guards.go b/vendor/github.com/google/cel-go/ext/guards.go index 0794f859b5..4c7786a690 100644 --- a/vendor/github.com/google/cel-go/ext/guards.go +++ b/vendor/github.com/google/cel-go/ext/guards.go @@ -17,6 +17,7 @@ package ext import ( "github.com/google/cel-go/common/types" "github.com/google/cel-go/common/types/ref" + exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1" ) // function invocation guards for common call signatures within extension functions. @@ -48,3 +49,15 @@ func listStringOrError(strs []string, err error) ref.Val { } return types.DefaultTypeAdapter.NativeToValue(strs) } + +func macroTargetMatchesNamespace(ns string, target *exprpb.Expr) bool { + switch target.GetExprKind().(type) { + case *exprpb.Expr_IdentExpr: + if target.GetIdentExpr().GetName() != ns { + return false + } + return true + default: + return false + } +} diff --git a/vendor/github.com/google/cel-go/ext/math.go b/vendor/github.com/google/cel-go/ext/math.go new file mode 100644 index 0000000000..1c8ad585a1 --- /dev/null +++ b/vendor/github.com/google/cel-go/ext/math.go @@ -0,0 +1,388 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ext + +import ( + "fmt" + "strings" + + "github.com/google/cel-go/cel" + "github.com/google/cel-go/common" + "github.com/google/cel-go/common/types" + "github.com/google/cel-go/common/types/ref" + "github.com/google/cel-go/common/types/traits" + exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1" +) + +// Math returns a cel.EnvOption to configure namespaced math helper macros and +// functions. +// +// Note, all macros use the 'math' namespace; however, at the time of macro +// expansion the namespace looks just like any other identifier. If you are +// currently using a variable named 'math', the macro will likely work just as +// intended; however, there is some chance for collision. +// +// # Math.Greatest +// +// Returns the greatest valued number present in the arguments to the macro. +// +// Greatest is a variable argument count macro which must take at least one +// argument. Simple numeric and list literals are supported as valid argument +// types; however, other literals will be flagged as errors during macro +// expansion. If the argument expression does not resolve to a numeric or +// list(numeric) type during type-checking, or during runtime then an error +// will be produced. If a list argument is empty, this too will produce an +// error. +// +// math.greatest(, ...) -> +// +// Examples: +// +// math.greatest(1) // 1 +// math.greatest(1u, 2u) // 2u +// math.greatest(-42.0, -21.5, -100.0) // -21.5 +// math.greatest([-42.0, -21.5, -100.0]) // -21.5 +// math.greatest(numbers) // numbers must be list(numeric) +// +// math.greatest() // parse error +// math.greatest('string') // parse error +// math.greatest(a, b) // check-time error if a or b is non-numeric +// math.greatest(dyn('string')) // runtime error +// +// # Math.Least +// +// Returns the least valued number present in the arguments to the macro. +// +// Least is a variable argument count macro which must take at least one +// argument. Simple numeric and list literals are supported as valid argument +// types; however, other literals will be flagged as errors during macro +// expansion. If the argument expression does not resolve to a numeric or +// list(numeric) type during type-checking, or during runtime then an error +// will be produced. If a list argument is empty, this too will produce an +// error. +// +// math.least(, ...) -> +// +// Examples: +// +// math.least(1) // 1 +// math.least(1u, 2u) // 1u +// math.least(-42.0, -21.5, -100.0) // -100.0 +// math.least([-42.0, -21.5, -100.0]) // -100.0 +// math.least(numbers) // numbers must be list(numeric) +// +// math.least() // parse error +// math.least('string') // parse error +// math.least(a, b) // check-time error if a or b is non-numeric +// math.least(dyn('string')) // runtime error +func Math() cel.EnvOption { + return cel.Lib(mathLib{}) +} + +const ( + mathNamespace = "math" + leastMacro = "least" + greatestMacro = "greatest" + minFunc = "math.@min" + maxFunc = "math.@max" +) + +type mathLib struct{} + +// LibraryName implements the SingletonLibrary interface method. +func (mathLib) LibraryName() string { + return "cel.lib.ext.math" +} + +// CompileOptions implements the Library interface method. +func (mathLib) CompileOptions() []cel.EnvOption { + return []cel.EnvOption{ + cel.Macros( + // math.least(num, ...) + cel.NewReceiverVarArgMacro(leastMacro, mathLeast), + // math.greatest(num, ...) + cel.NewReceiverVarArgMacro(greatestMacro, mathGreatest), + ), + cel.Function(minFunc, + cel.Overload("math_@min_double", []*cel.Type{cel.DoubleType}, cel.DoubleType, + cel.UnaryBinding(identity)), + cel.Overload("math_@min_int", []*cel.Type{cel.IntType}, cel.IntType, + cel.UnaryBinding(identity)), + cel.Overload("math_@min_uint", []*cel.Type{cel.UintType}, cel.UintType, + cel.UnaryBinding(identity)), + cel.Overload("math_@min_double_double", []*cel.Type{cel.DoubleType, cel.DoubleType}, cel.DoubleType, + cel.BinaryBinding(minPair)), + cel.Overload("math_@min_int_int", []*cel.Type{cel.IntType, cel.IntType}, cel.IntType, + cel.BinaryBinding(minPair)), + cel.Overload("math_@min_uint_uint", []*cel.Type{cel.UintType, cel.UintType}, cel.UintType, + cel.BinaryBinding(minPair)), + cel.Overload("math_@min_int_uint", []*cel.Type{cel.IntType, cel.UintType}, cel.DynType, + cel.BinaryBinding(minPair)), + cel.Overload("math_@min_int_double", []*cel.Type{cel.IntType, cel.DoubleType}, cel.DynType, + cel.BinaryBinding(minPair)), + cel.Overload("math_@min_double_int", []*cel.Type{cel.DoubleType, cel.IntType}, cel.DynType, + cel.BinaryBinding(minPair)), + cel.Overload("math_@min_double_uint", []*cel.Type{cel.DoubleType, cel.UintType}, cel.DynType, + cel.BinaryBinding(minPair)), + cel.Overload("math_@min_uint_int", []*cel.Type{cel.UintType, cel.IntType}, cel.DynType, + cel.BinaryBinding(minPair)), + cel.Overload("math_@min_uint_double", []*cel.Type{cel.UintType, cel.DoubleType}, cel.DynType, + cel.BinaryBinding(minPair)), + cel.Overload("math_@min_list_double", []*cel.Type{cel.ListType(cel.DoubleType)}, cel.DoubleType, + cel.UnaryBinding(minList)), + cel.Overload("math_@min_list_int", []*cel.Type{cel.ListType(cel.IntType)}, cel.IntType, + cel.UnaryBinding(minList)), + cel.Overload("math_@min_list_uint", []*cel.Type{cel.ListType(cel.UintType)}, cel.UintType, + cel.UnaryBinding(minList)), + ), + cel.Function(maxFunc, + cel.Overload("math_@max_double", []*cel.Type{cel.DoubleType}, cel.DoubleType, + cel.UnaryBinding(identity)), + cel.Overload("math_@max_int", []*cel.Type{cel.IntType}, cel.IntType, + cel.UnaryBinding(identity)), + cel.Overload("math_@max_uint", []*cel.Type{cel.UintType}, cel.UintType, + cel.UnaryBinding(identity)), + cel.Overload("math_@max_double_double", []*cel.Type{cel.DoubleType, cel.DoubleType}, cel.DoubleType, + cel.BinaryBinding(maxPair)), + cel.Overload("math_@max_int_int", []*cel.Type{cel.IntType, cel.IntType}, cel.IntType, + cel.BinaryBinding(maxPair)), + cel.Overload("math_@max_uint_uint", []*cel.Type{cel.UintType, cel.UintType}, cel.UintType, + cel.BinaryBinding(maxPair)), + cel.Overload("math_@max_int_uint", []*cel.Type{cel.IntType, cel.UintType}, cel.DynType, + cel.BinaryBinding(maxPair)), + cel.Overload("math_@max_int_double", []*cel.Type{cel.IntType, cel.DoubleType}, cel.DynType, + cel.BinaryBinding(maxPair)), + cel.Overload("math_@max_double_int", []*cel.Type{cel.DoubleType, cel.IntType}, cel.DynType, + cel.BinaryBinding(maxPair)), + cel.Overload("math_@max_double_uint", []*cel.Type{cel.DoubleType, cel.UintType}, cel.DynType, + cel.BinaryBinding(maxPair)), + cel.Overload("math_@max_uint_int", []*cel.Type{cel.UintType, cel.IntType}, cel.DynType, + cel.BinaryBinding(maxPair)), + cel.Overload("math_@max_uint_double", []*cel.Type{cel.UintType, cel.DoubleType}, cel.DynType, + cel.BinaryBinding(maxPair)), + cel.Overload("math_@max_list_double", []*cel.Type{cel.ListType(cel.DoubleType)}, cel.DoubleType, + cel.UnaryBinding(maxList)), + cel.Overload("math_@max_list_int", []*cel.Type{cel.ListType(cel.IntType)}, cel.IntType, + cel.UnaryBinding(maxList)), + cel.Overload("math_@max_list_uint", []*cel.Type{cel.ListType(cel.UintType)}, cel.UintType, + cel.UnaryBinding(maxList)), + ), + } +} + +// ProgramOptions implements the Library interface method. +func (mathLib) ProgramOptions() []cel.ProgramOption { + return []cel.ProgramOption{} +} + +func mathLeast(meh cel.MacroExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *common.Error) { + if !macroTargetMatchesNamespace(mathNamespace, target) { + return nil, nil + } + switch len(args) { + case 0: + return nil, &common.Error{ + Message: "math.least() requires at least one argument", + Location: meh.OffsetLocation(target.GetId()), + } + case 1: + if isListLiteralWithValidArgs(args[0]) || isValidArgType(args[0]) { + return meh.GlobalCall(minFunc, args[0]), nil + } + return nil, &common.Error{ + Message: "math.least() invalid single argument value", + Location: meh.OffsetLocation(args[0].GetId()), + } + case 2: + err := checkInvalidArgs(meh, "math.least()", args) + if err != nil { + return nil, err + } + return meh.GlobalCall(minFunc, args...), nil + default: + err := checkInvalidArgs(meh, "math.least()", args) + if err != nil { + return nil, err + } + return meh.GlobalCall(minFunc, meh.NewList(args...)), nil + } +} + +func mathGreatest(meh cel.MacroExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *common.Error) { + if !macroTargetMatchesNamespace(mathNamespace, target) { + return nil, nil + } + switch len(args) { + case 0: + return nil, &common.Error{ + Message: "math.greatest() requires at least one argument", + Location: meh.OffsetLocation(target.GetId()), + } + case 1: + if isListLiteralWithValidArgs(args[0]) || isValidArgType(args[0]) { + return meh.GlobalCall(maxFunc, args[0]), nil + } + return nil, &common.Error{ + Message: "math.greatest() invalid single argument value", + Location: meh.OffsetLocation(args[0].GetId()), + } + case 2: + err := checkInvalidArgs(meh, "math.greatest()", args) + if err != nil { + return nil, err + } + return meh.GlobalCall(maxFunc, args...), nil + default: + err := checkInvalidArgs(meh, "math.greatest()", args) + if err != nil { + return nil, err + } + return meh.GlobalCall(maxFunc, meh.NewList(args...)), nil + } +} + +func identity(val ref.Val) ref.Val { + return val +} + +func minPair(first, second ref.Val) ref.Val { + cmp, ok := first.(traits.Comparer) + if !ok { + return types.MaybeNoSuchOverloadErr(first) + } + out := cmp.Compare(second) + if types.IsUnknownOrError(out) { + return maybeSuffixError(out, "math.@min") + } + if out == types.IntOne { + return second + } + return first +} + +func minList(numList ref.Val) ref.Val { + l := numList.(traits.Lister) + size := l.Size().(types.Int) + if size == types.IntZero { + return types.NewErr("math.@min(list) argument must not be empty") + } + min := l.Get(types.IntZero) + for i := types.IntOne; i < size; i++ { + min = minPair(min, l.Get(i)) + } + switch min.Type() { + case types.IntType, types.DoubleType, types.UintType, types.UnknownType: + return min + default: + return types.NewErr("no such overload: math.@min") + } +} + +func maxPair(first, second ref.Val) ref.Val { + cmp, ok := first.(traits.Comparer) + if !ok { + return types.MaybeNoSuchOverloadErr(first) + } + out := cmp.Compare(second) + if types.IsUnknownOrError(out) { + return maybeSuffixError(out, "math.@max") + } + if out == types.IntNegOne { + return second + } + return first +} + +func maxList(numList ref.Val) ref.Val { + l := numList.(traits.Lister) + size := l.Size().(types.Int) + if size == types.IntZero { + return types.NewErr("math.@max(list) argument must not be empty") + } + max := l.Get(types.IntZero) + for i := types.IntOne; i < size; i++ { + max = maxPair(max, l.Get(i)) + } + switch max.Type() { + case types.IntType, types.DoubleType, types.UintType, types.UnknownType: + return max + default: + return types.NewErr("no such overload: math.@max") + } +} + +func checkInvalidArgs(meh cel.MacroExprHelper, funcName string, args []*exprpb.Expr) *common.Error { + for _, arg := range args { + err := checkInvalidArgLiteral(funcName, arg) + if err != nil { + return &common.Error{ + Message: err.Error(), + Location: meh.OffsetLocation(arg.GetId()), + } + } + } + return nil +} + +func checkInvalidArgLiteral(funcName string, arg *exprpb.Expr) error { + if !isValidArgType(arg) { + return fmt.Errorf("%s simple literal arguments must be numeric", funcName) + } + return nil +} + +func isValidArgType(arg *exprpb.Expr) bool { + switch arg.GetExprKind().(type) { + case *exprpb.Expr_ConstExpr: + c := arg.GetConstExpr() + switch c.GetConstantKind().(type) { + case *exprpb.Constant_DoubleValue, *exprpb.Constant_Int64Value, *exprpb.Constant_Uint64Value: + return true + default: + return false + } + case *exprpb.Expr_ListExpr, *exprpb.Expr_StructExpr: + return false + default: + return true + } +} + +func isListLiteralWithValidArgs(arg *exprpb.Expr) bool { + switch arg.GetExprKind().(type) { + case *exprpb.Expr_ListExpr: + list := arg.GetListExpr() + if len(list.GetElements()) == 0 { + return false + } + for _, e := range list.GetElements() { + if !isValidArgType(e) { + return false + } + } + return true + } + return false +} + +func maybeSuffixError(val ref.Val, suffix string) ref.Val { + if types.IsError(val) { + msg := val.(*types.Err).String() + if !strings.Contains(msg, suffix) { + return types.NewErr("%s: %s", msg, suffix) + } + } + return val +} diff --git a/vendor/github.com/google/cel-go/ext/native.go b/vendor/github.com/google/cel-go/ext/native.go new file mode 100644 index 0000000000..acbc44b6d5 --- /dev/null +++ b/vendor/github.com/google/cel-go/ext/native.go @@ -0,0 +1,574 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ext + +import ( + "fmt" + "reflect" + "strings" + "time" + + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + + "github.com/google/cel-go/cel" + "github.com/google/cel-go/checker/decls" + "github.com/google/cel-go/common/types" + "github.com/google/cel-go/common/types/pb" + "github.com/google/cel-go/common/types/ref" + "github.com/google/cel-go/common/types/traits" + + exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1" + structpb "google.golang.org/protobuf/types/known/structpb" +) + +var ( + nativeObjTraitMask = traits.FieldTesterType | traits.IndexerType + jsonValueType = reflect.TypeOf(&structpb.Value{}) + jsonStructType = reflect.TypeOf(&structpb.Struct{}) +) + +// NativeTypes creates a type provider which uses reflect.Type and reflect.Value instances +// to produce type definitions that can be used within CEL. +// +// All struct types in Go are exposed to CEL via their simple package name and struct type name: +// +// ```go +// package identity +// +// type Account struct { +// ID int +// } +// +// ``` +// +// The type `identity.Account` would be exported to CEL using the same qualified name, e.g. +// `identity.Account{ID: 1234}` would create a new `Account` instance with the `ID` field +// populated. +// +// Only exported fields are exposed via NativeTypes, and the type-mapping between Go and CEL +// is as follows: +// +// | Go type | CEL type | +// |-------------------------------------|-----------| +// | bool | bool | +// | []byte | bytes | +// | float32, float64 | double | +// | int, int8, int16, int32, int64 | int | +// | string | string | +// | uint, uint8, uint16, uint32, uint64 | uint | +// | time.Duration | duration | +// | time.Time | timestamp | +// | array, slice | list | +// | map | map | +// +// Please note, if you intend to configure support for proto messages in addition to native +// types, you will need to provide the protobuf types before the golang native types. The +// same advice holds if you are using custom type adapters and type providers. The native type +// provider composes over whichever type adapter and provider is configured in the cel.Env at +// the time that it is invoked. +func NativeTypes(refTypes ...any) cel.EnvOption { + return func(env *cel.Env) (*cel.Env, error) { + tp, err := newNativeTypeProvider(env.TypeAdapter(), env.TypeProvider(), refTypes...) + if err != nil { + return nil, err + } + env, err = cel.CustomTypeAdapter(tp)(env) + if err != nil { + return nil, err + } + return cel.CustomTypeProvider(tp)(env) + } +} + +func newNativeTypeProvider(adapter ref.TypeAdapter, provider ref.TypeProvider, refTypes ...any) (*nativeTypeProvider, error) { + nativeTypes := make(map[string]*nativeType, len(refTypes)) + for _, refType := range refTypes { + switch rt := refType.(type) { + case reflect.Type: + t, err := newNativeType(rt) + if err != nil { + return nil, err + } + nativeTypes[t.TypeName()] = t + case reflect.Value: + t, err := newNativeType(rt.Type()) + if err != nil { + return nil, err + } + nativeTypes[t.TypeName()] = t + default: + return nil, fmt.Errorf("unsupported native type: %v (%T) must be reflect.Type or reflect.Value", rt, rt) + } + } + return &nativeTypeProvider{ + nativeTypes: nativeTypes, + baseAdapter: adapter, + baseProvider: provider, + }, nil +} + +type nativeTypeProvider struct { + nativeTypes map[string]*nativeType + baseAdapter ref.TypeAdapter + baseProvider ref.TypeProvider +} + +// EnumValue proxies to the ref.TypeProvider configured at the times the NativeTypes +// option was configured. +func (tp *nativeTypeProvider) EnumValue(enumName string) ref.Val { + return tp.baseProvider.EnumValue(enumName) +} + +// FindIdent looks up natives type instances by qualified identifier, and if not found +// proxies to the composed ref.TypeProvider. +func (tp *nativeTypeProvider) FindIdent(typeName string) (ref.Val, bool) { + if t, found := tp.nativeTypes[typeName]; found { + return t, true + } + return tp.baseProvider.FindIdent(typeName) +} + +// FindType looks up CEL type-checker type definition by qualified identifier, and if not found +// proxies to the composed ref.TypeProvider. +func (tp *nativeTypeProvider) FindType(typeName string) (*exprpb.Type, bool) { + if _, found := tp.nativeTypes[typeName]; found { + return decls.NewTypeType(decls.NewObjectType(typeName)), true + } + return tp.baseProvider.FindType(typeName) +} + +// FindFieldType looks up a native type's field definition, and if the type name is not a native +// type then proxies to the composed ref.TypeProvider +func (tp *nativeTypeProvider) FindFieldType(typeName, fieldName string) (*ref.FieldType, bool) { + t, found := tp.nativeTypes[typeName] + if !found { + return tp.baseProvider.FindFieldType(typeName, fieldName) + } + refField, isDefined := t.hasField(fieldName) + if !found || !isDefined { + return nil, false + } + exprType, ok := convertToExprType(refField.Type) + if !ok { + return nil, false + } + return &ref.FieldType{ + Type: exprType, + IsSet: func(obj any) bool { + refVal := reflect.Indirect(reflect.ValueOf(obj)) + refField := refVal.FieldByName(fieldName) + return !refField.IsZero() + }, + GetFrom: func(obj any) (any, error) { + refVal := reflect.Indirect(reflect.ValueOf(obj)) + refField := refVal.FieldByName(fieldName) + return getFieldValue(tp, refField), nil + }, + }, true +} + +// NewValue implements the ref.TypeProvider interface method. +func (tp *nativeTypeProvider) NewValue(typeName string, fields map[string]ref.Val) ref.Val { + t, found := tp.nativeTypes[typeName] + if !found { + return tp.baseProvider.NewValue(typeName, fields) + } + refPtr := reflect.New(t.refType) + refVal := refPtr.Elem() + for fieldName, val := range fields { + refFieldDef, isDefined := t.hasField(fieldName) + if !isDefined { + return types.NewErr("no such field: %s", fieldName) + } + fieldVal, err := val.ConvertToNative(refFieldDef.Type) + if err != nil { + return types.NewErr(err.Error()) + } + refField := refVal.FieldByIndex(refFieldDef.Index) + refFieldVal := reflect.ValueOf(fieldVal) + refField.Set(refFieldVal) + } + return tp.NativeToValue(refPtr.Interface()) +} + +// NewValue adapts native values to CEL values and will proxy to the composed type adapter +// for non-native types. +func (tp *nativeTypeProvider) NativeToValue(val any) ref.Val { + if val == nil { + return types.NullValue + } + if v, ok := val.(ref.Val); ok { + return v + } + rawVal := reflect.ValueOf(val) + refVal := rawVal + if refVal.Kind() == reflect.Ptr { + refVal = reflect.Indirect(refVal) + } + // This isn't quite right if you're also supporting proto, + // but maybe an acceptable limitation. + switch refVal.Kind() { + case reflect.Array, reflect.Slice: + switch val := val.(type) { + case []byte: + return tp.baseAdapter.NativeToValue(val) + default: + return types.NewDynamicList(tp, val) + } + case reflect.Map: + return types.NewDynamicMap(tp, val) + case reflect.Struct: + switch val := val.(type) { + case proto.Message, *pb.Map, protoreflect.List, protoreflect.Message, protoreflect.Value, + time.Time: + return tp.baseAdapter.NativeToValue(val) + default: + return newNativeObject(tp, val, rawVal) + } + default: + return tp.baseAdapter.NativeToValue(val) + } +} + +// convertToExprType converts the Golang reflect.Type to a protobuf exprpb.Type. +func convertToExprType(refType reflect.Type) (*exprpb.Type, bool) { + switch refType.Kind() { + case reflect.Bool: + return decls.Bool, true + case reflect.Float32, reflect.Float64: + return decls.Double, true + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + if refType == durationType { + return decls.Duration, true + } + return decls.Int, true + case reflect.String: + return decls.String, true + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return decls.Uint, true + case reflect.Array, reflect.Slice: + refElem := refType.Elem() + if refElem == reflect.TypeOf(byte(0)) { + return decls.Bytes, true + } + elemType, ok := convertToExprType(refElem) + if !ok { + return nil, false + } + return decls.NewListType(elemType), true + case reflect.Map: + keyType, ok := convertToExprType(refType.Key()) + if !ok { + return nil, false + } + // Ensure the key type is a int, bool, uint, string + elemType, ok := convertToExprType(refType.Elem()) + if !ok { + return nil, false + } + return decls.NewMapType(keyType, elemType), true + case reflect.Struct: + if refType == timestampType { + return decls.Timestamp, true + } + return decls.NewObjectType( + fmt.Sprintf("%s.%s", simplePkgAlias(refType.PkgPath()), refType.Name()), + ), true + case reflect.Pointer: + if refType.Implements(pbMsgInterfaceType) { + pbMsg := reflect.New(refType.Elem()).Interface().(protoreflect.ProtoMessage) + return decls.NewObjectType(string(pbMsg.ProtoReflect().Descriptor().FullName())), true + } + return convertToExprType(refType.Elem()) + } + return nil, false +} + +func newNativeObject(adapter ref.TypeAdapter, val any, refValue reflect.Value) ref.Val { + valType, err := newNativeType(refValue.Type()) + if err != nil { + return types.NewErr(err.Error()) + } + return &nativeObj{ + TypeAdapter: adapter, + val: val, + valType: valType, + refValue: refValue, + } +} + +type nativeObj struct { + ref.TypeAdapter + val any + valType *nativeType + refValue reflect.Value +} + +// ConvertToNative implements the ref.Val interface method. +// +// CEL does not have a notion of pointers, so whether a field is a pointer or value +// is handled as part of this conversion step. +func (o *nativeObj) ConvertToNative(typeDesc reflect.Type) (any, error) { + if o.refValue.Type() == typeDesc { + return o.val, nil + } + if o.refValue.Kind() == reflect.Pointer && o.refValue.Type().Elem() == typeDesc { + return o.refValue.Elem().Interface(), nil + } + if typeDesc.Kind() == reflect.Pointer && o.refValue.Type() == typeDesc.Elem() { + ptr := reflect.New(typeDesc.Elem()) + ptr.Elem().Set(o.refValue) + return ptr.Interface(), nil + } + switch typeDesc { + case jsonValueType: + jsonStruct, err := o.ConvertToNative(jsonStructType) + if err != nil { + return nil, err + } + return structpb.NewStructValue(jsonStruct.(*structpb.Struct)), nil + case jsonStructType: + refVal := reflect.Indirect(o.refValue) + refType := refVal.Type() + fields := make(map[string]*structpb.Value, refVal.NumField()) + for i := 0; i < refVal.NumField(); i++ { + fieldType := refType.Field(i) + fieldValue := refVal.Field(i) + if !fieldValue.IsValid() || fieldValue.IsZero() { + continue + } + fieldCELVal := o.NativeToValue(fieldValue.Interface()) + fieldJSONVal, err := fieldCELVal.ConvertToNative(jsonValueType) + if err != nil { + return nil, err + } + fields[fieldType.Name] = fieldJSONVal.(*structpb.Value) + } + return &structpb.Struct{Fields: fields}, nil + } + return nil, fmt.Errorf("type conversion error from '%v' to '%v'", o.Type(), typeDesc) +} + +// ConvertToType implements the ref.Val interface method. +func (o *nativeObj) ConvertToType(typeVal ref.Type) ref.Val { + switch typeVal { + case types.TypeType: + return o.valType + default: + if typeVal.TypeName() == o.valType.typeName { + return o + } + } + return types.NewErr("type conversion error from '%s' to '%s'", o.Type(), typeVal) +} + +// Equal implements the ref.Val interface method. +// +// Note, that in Golang a pointer to a value is not equal to the value it contains. +// In CEL pointers and values to which they point are equal. +func (o *nativeObj) Equal(other ref.Val) ref.Val { + otherNtv, ok := other.(*nativeObj) + if !ok { + return types.False + } + val := o.val + otherVal := otherNtv.val + refVal := o.refValue + otherRefVal := otherNtv.refValue + if refVal.Kind() != otherRefVal.Kind() { + if refVal.Kind() == reflect.Pointer { + val = refVal.Elem().Interface() + } else if otherRefVal.Kind() == reflect.Pointer { + otherVal = otherRefVal.Elem().Interface() + } + } + return types.Bool(reflect.DeepEqual(val, otherVal)) +} + +// IsZeroValue indicates whether the contained Golang value is a zero value. +// +// Golang largely follows proto3 semantics for zero values. +func (o *nativeObj) IsZeroValue() bool { + return reflect.Indirect(o.refValue).IsZero() +} + +// IsSet tests whether a field which is defined is set to a non-default value. +func (o *nativeObj) IsSet(field ref.Val) ref.Val { + refField, refErr := o.getReflectedField(field) + if refErr != nil { + return refErr + } + return types.Bool(!refField.IsZero()) +} + +// Get returns the value fo a field name. +func (o *nativeObj) Get(field ref.Val) ref.Val { + refField, refErr := o.getReflectedField(field) + if refErr != nil { + return refErr + } + return adaptFieldValue(o, refField) +} + +func (o *nativeObj) getReflectedField(field ref.Val) (reflect.Value, ref.Val) { + fieldName, ok := field.(types.String) + if !ok { + return reflect.Value{}, types.MaybeNoSuchOverloadErr(field) + } + fieldNameStr := string(fieldName) + refField, isDefined := o.valType.hasField(fieldNameStr) + if !isDefined { + return reflect.Value{}, types.NewErr("no such field: %s", fieldName) + } + refVal := reflect.Indirect(o.refValue) + return refVal.FieldByIndex(refField.Index), nil +} + +// Type implements the ref.Val interface method. +func (o *nativeObj) Type() ref.Type { + return o.valType +} + +// Value implements the ref.Val interface method. +func (o *nativeObj) Value() any { + return o.val +} + +func newNativeType(rawType reflect.Type) (*nativeType, error) { + refType := rawType + if refType.Kind() == reflect.Pointer { + refType = refType.Elem() + } + if !isValidObjectType(refType) { + return nil, fmt.Errorf("unsupported reflect.Type %v, must be reflect.Struct", rawType) + } + return &nativeType{ + typeName: fmt.Sprintf("%s.%s", simplePkgAlias(refType.PkgPath()), refType.Name()), + refType: refType, + }, nil +} + +type nativeType struct { + typeName string + refType reflect.Type +} + +// ConvertToNative implements ref.Val.ConvertToNative. +func (t *nativeType) ConvertToNative(typeDesc reflect.Type) (any, error) { + return nil, fmt.Errorf("type conversion error for type to '%v'", typeDesc) +} + +// ConvertToType implements ref.Val.ConvertToType. +func (t *nativeType) ConvertToType(typeVal ref.Type) ref.Val { + switch typeVal { + case types.TypeType: + return types.TypeType + } + return types.NewErr("type conversion error from '%s' to '%s'", types.TypeType, typeVal) +} + +// Equal returns true of both type names are equal to each other. +func (t *nativeType) Equal(other ref.Val) ref.Val { + otherType, ok := other.(ref.Type) + return types.Bool(ok && t.TypeName() == otherType.TypeName()) +} + +// HasTrait implements the ref.Type interface method. +func (t *nativeType) HasTrait(trait int) bool { + return nativeObjTraitMask&trait == trait +} + +// String implements the strings.Stringer interface method. +func (t *nativeType) String() string { + return t.typeName +} + +// Type implements the ref.Val interface method. +func (t *nativeType) Type() ref.Type { + return types.TypeType +} + +// TypeName implements the ref.Type interface method. +func (t *nativeType) TypeName() string { + return t.typeName +} + +// Value implements the ref.Val interface method. +func (t *nativeType) Value() any { + return t.typeName +} + +// hasField returns whether a field name has a corresponding Golang reflect.StructField +func (t *nativeType) hasField(fieldName string) (reflect.StructField, bool) { + f, found := t.refType.FieldByName(fieldName) + if !found || !f.IsExported() || !isSupportedType(f.Type) { + return reflect.StructField{}, false + } + return f, true +} + +func adaptFieldValue(adapter ref.TypeAdapter, refField reflect.Value) ref.Val { + return adapter.NativeToValue(getFieldValue(adapter, refField)) +} + +func getFieldValue(adapter ref.TypeAdapter, refField reflect.Value) any { + if refField.IsZero() { + switch refField.Kind() { + case reflect.Array, reflect.Slice: + return types.NewDynamicList(adapter, []ref.Val{}) + case reflect.Map: + return types.NewDynamicMap(adapter, map[ref.Val]ref.Val{}) + case reflect.Struct: + if refField.Type() == timestampType { + return types.Timestamp{Time: time.Unix(0, 0)} + } + return reflect.New(refField.Type()).Elem().Interface() + case reflect.Pointer: + return reflect.New(refField.Type().Elem()).Interface() + } + } + return refField.Interface() +} + +func simplePkgAlias(pkgPath string) string { + paths := strings.Split(pkgPath, "/") + if len(paths) == 0 { + return "" + } + return paths[len(paths)-1] +} + +func isValidObjectType(refType reflect.Type) bool { + return refType.Kind() == reflect.Struct +} + +func isSupportedType(refType reflect.Type) bool { + switch refType.Kind() { + case reflect.Chan, reflect.Complex64, reflect.Complex128, reflect.Func, reflect.UnsafePointer, reflect.Uintptr: + return false + case reflect.Array, reflect.Slice: + return isSupportedType(refType.Elem()) + case reflect.Map: + return isSupportedType(refType.Key()) && isSupportedType(refType.Elem()) + } + return true +} + +var ( + pbMsgInterfaceType = reflect.TypeOf((*protoreflect.ProtoMessage)(nil)).Elem() + timestampType = reflect.TypeOf(time.Now()) + durationType = reflect.TypeOf(time.Nanosecond) +) diff --git a/vendor/github.com/google/cel-go/ext/protos.go b/vendor/github.com/google/cel-go/ext/protos.go new file mode 100644 index 0000000000..b905e710c1 --- /dev/null +++ b/vendor/github.com/google/cel-go/ext/protos.go @@ -0,0 +1,145 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ext + +import ( + "github.com/google/cel-go/cel" + "github.com/google/cel-go/common" + + exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1" +) + +// Protos returns a cel.EnvOption to configure extended macros and functions for +// proto manipulation. +// +// Note, all macros use the 'proto' namespace; however, at the time of macro +// expansion the namespace looks just like any other identifier. If you are +// currently using a variable named 'proto', the macro will likely work just as +// intended; however, there is some chance for collision. +// +// # Protos.GetExt +// +// Macro which generates a select expression that retrieves an extension field +// from the input proto2 syntax message. If the field is not set, the default +// value forthe extension field is returned according to safe-traversal semantics. +// +// proto.getExt(, ) -> +// +// Examples: +// +// proto.getExt(msg, google.expr.proto2.test.int32_ext) // returns int value +// +// # Protos.HasExt +// +// Macro which generates a test-only select expression that determines whether +// an extension field is set on a proto2 syntax message. +// +// proto.hasExt(, ) -> +// +// Examples: +// +// proto.hasExt(msg, google.expr.proto2.test.int32_ext) // returns true || false +func Protos() cel.EnvOption { + return cel.Lib(protoLib{}) +} + +var ( + protoNamespace = "proto" + hasExtension = "hasExt" + getExtension = "getExt" +) + +type protoLib struct{} + +// LibraryName implements the SingletonLibrary interface method. +func (protoLib) LibraryName() string { + return "cel.lib.ext.protos" +} + +// CompileOptions implements the Library interface method. +func (protoLib) CompileOptions() []cel.EnvOption { + return []cel.EnvOption{ + cel.Macros( + // proto.getExt(msg, select_expression) + cel.NewReceiverMacro(getExtension, 2, getProtoExt), + // proto.hasExt(msg, select_expression) + cel.NewReceiverMacro(hasExtension, 2, hasProtoExt), + ), + } +} + +// ProgramOptions implements the Library interface method. +func (protoLib) ProgramOptions() []cel.ProgramOption { + return []cel.ProgramOption{} +} + +// hasProtoExt generates a test-only select expression for a fully-qualified extension name on a protobuf message. +func hasProtoExt(meh cel.MacroExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *common.Error) { + if !macroTargetMatchesNamespace(protoNamespace, target) { + return nil, nil + } + extensionField, err := getExtFieldName(meh, args[1]) + if err != nil { + return nil, err + } + return meh.PresenceTest(args[0], extensionField), nil +} + +// getProtoExt generates a select expression for a fully-qualified extension name on a protobuf message. +func getProtoExt(meh cel.MacroExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *common.Error) { + if !macroTargetMatchesNamespace(protoNamespace, target) { + return nil, nil + } + extFieldName, err := getExtFieldName(meh, args[1]) + if err != nil { + return nil, err + } + return meh.Select(args[0], extFieldName), nil +} + +func getExtFieldName(meh cel.MacroExprHelper, expr *exprpb.Expr) (string, *common.Error) { + isValid := false + extensionField := "" + switch expr.GetExprKind().(type) { + case *exprpb.Expr_SelectExpr: + extensionField, isValid = validateIdentifier(expr) + } + if !isValid { + return "", &common.Error{ + Message: "invalid extension field", + Location: meh.OffsetLocation(expr.GetId()), + } + } + return extensionField, nil +} + +func validateIdentifier(expr *exprpb.Expr) (string, bool) { + switch expr.GetExprKind().(type) { + case *exprpb.Expr_IdentExpr: + return expr.GetIdentExpr().GetName(), true + case *exprpb.Expr_SelectExpr: + sel := expr.GetSelectExpr() + if sel.GetTestOnly() { + return "", false + } + opStr, isIdent := validateIdentifier(sel.GetOperand()) + if !isIdent { + return "", false + } + return opStr + "." + sel.GetField(), true + default: + return "", false + } +} diff --git a/vendor/github.com/google/cel-go/ext/sets.go b/vendor/github.com/google/cel-go/ext/sets.go new file mode 100644 index 0000000000..4820d6199e --- /dev/null +++ b/vendor/github.com/google/cel-go/ext/sets.go @@ -0,0 +1,138 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ext + +import ( + "github.com/google/cel-go/cel" + "github.com/google/cel-go/common/types" + "github.com/google/cel-go/common/types/ref" + "github.com/google/cel-go/common/types/traits" +) + +// Sets returns a cel.EnvOption to configure namespaced set relationship +// functions. +// +// There is no set type within CEL, and while one may be introduced in the +// future, there are cases where a `list` type is known to behave like a set. +// For such cases, this library provides some basic functionality for +// determining set containment, equivalence, and intersection. +// +// # Sets.Contains +// +// Returns whether the first list argument contains all elements in the second +// list argument. The list may contain elements of any type and standard CEL +// equality is used to determine whether a value exists in both lists. If the +// second list is empty, the result will always return true. +// +// sets.contains(list(T), list(T)) -> bool +// +// Examples: +// +// sets.contains([], []) // true +// sets.contains([], [1]) // false +// sets.contains([1, 2, 3, 4], [2, 3]) // true +// sets.contains([1, 2.0, 3u], [1.0, 2u, 3]) // true +// +// # Sets.Equivalent +// +// Returns whether the first and second list are set equivalent. Lists are set +// equivalent if for every item in the first list, there is an element in the +// second which is equal. The lists may not be of the same size as they do not +// guarantee the elements within them are unique, so size does not factor into +// the computation. +// +// Examples: +// +// sets.equivalent([], []) // true +// sets.equivalent([1], [1, 1]) // true +// sets.equivalent([1], [1u, 1.0]) // true +// sets.equivalent([1, 2, 3], [3u, 2.0, 1]) // true +// +// # Sets.Intersects +// +// Returns whether the first list has at least one element whose value is equal +// to an element in the second list. If either list is empty, the result will +// be false. +// +// Examples: +// +// sets.intersects([1], []) // false +// sets.intersects([1], [1, 2]) // true +// sets.intersects([[1], [2, 3]], [[1, 2], [2, 3.0]]) // true +func Sets() cel.EnvOption { + return cel.Lib(setsLib{}) +} + +type setsLib struct{} + +// LibraryName implements the SingletonLibrary interface method. +func (setsLib) LibraryName() string { + return "cel.lib.ext.sets" +} + +// CompileOptions implements the Library interface method. +func (setsLib) CompileOptions() []cel.EnvOption { + listType := cel.ListType(cel.TypeParamType("T")) + return []cel.EnvOption{ + cel.Function("sets.contains", + cel.Overload("list_sets_contains_list", []*cel.Type{listType, listType}, cel.BoolType, + cel.BinaryBinding(setsContains))), + cel.Function("sets.equivalent", + cel.Overload("list_sets_equivalent_list", []*cel.Type{listType, listType}, cel.BoolType, + cel.BinaryBinding(setsEquivalent))), + cel.Function("sets.intersects", + cel.Overload("list_sets_intersects_list", []*cel.Type{listType, listType}, cel.BoolType, + cel.BinaryBinding(setsIntersects))), + } +} + +// ProgramOptions implements the Library interface method. +func (setsLib) ProgramOptions() []cel.ProgramOption { + return []cel.ProgramOption{} +} + +func setsIntersects(listA, listB ref.Val) ref.Val { + lA := listA.(traits.Lister) + lB := listB.(traits.Lister) + it := lA.Iterator() + for it.HasNext() == types.True { + exists := lB.Contains(it.Next()) + if exists == types.True { + return types.True + } + } + return types.False +} + +func setsContains(list, sublist ref.Val) ref.Val { + l := list.(traits.Lister) + sub := sublist.(traits.Lister) + it := sub.Iterator() + for it.HasNext() == types.True { + exists := l.Contains(it.Next()) + if exists != types.True { + return exists + } + } + return types.True +} + +func setsEquivalent(listA, listB ref.Val) ref.Val { + aContainsB := setsContains(listA, listB) + if aContainsB != types.True { + return aContainsB + } + return setsContains(listB, listA) +} diff --git a/vendor/github.com/google/cel-go/ext/strings.go b/vendor/github.com/google/cel-go/ext/strings.go index 6ce239ac2b..8455d58290 100644 --- a/vendor/github.com/google/cel-go/ext/strings.go +++ b/vendor/github.com/google/cel-go/ext/strings.go @@ -19,32 +19,92 @@ package ext import ( "fmt" + "math" "reflect" + "sort" "strings" "unicode" + "unicode/utf8" + + "golang.org/x/text/language" + "golang.org/x/text/message" "github.com/google/cel-go/cel" "github.com/google/cel-go/common/types" "github.com/google/cel-go/common/types/ref" + "github.com/google/cel-go/common/types/traits" + "github.com/google/cel-go/interpreter" +) + +const ( + defaultLocale = "en-US" + defaultPrecision = 6 ) // Strings returns a cel.EnvOption to configure extended functions for string manipulation. // As a general note, all indices are zero-based. // -// CharAt +// # CharAt // // Returns the character at the given position. If the position is negative, or greater than // the length of the string, the function will produce an error: // -// .charAt() -> +// .charAt() -> // // Examples: // -// 'hello'.charAt(4) // return 'o' -// 'hello'.charAt(5) // return '' -// 'hello'.charAt(-1) // error +// 'hello'.charAt(4) // return 'o' +// 'hello'.charAt(5) // return '' +// 'hello'.charAt(-1) // error +// +// # Format +// +// Introduced at version: 1 +// +// Returns a new string with substitutions being performed, printf-style. +// The valid formatting clauses are: +// +// `%s` - substitutes a string. This can also be used on bools, lists, maps, bytes, +// Duration and Timestamp, in addition to all numerical types (int, uint, and double). +// Note that the dot/period decimal separator will always be used when printing a list +// or map that contains a double, and that null can be passed (which results in the +// string "null") in addition to types. +// `%d` - substitutes an integer. +// `%f` - substitutes a double with fixed-point precision. The default precision is 6, but +// this can be adjusted. The strings `Infinity`, `-Infinity`, and `NaN` are also valid input +// for this clause. +// `%e` - substitutes a double in scientific notation. The default precision is 6, but this +// can be adjusted. +// `%b` - substitutes an integer with its equivalent binary string. Can also be used on bools. +// `%x` - substitutes an integer with its equivalent in hexadecimal, or if given a string or +// bytes, will output each character's equivalent in hexadecimal. +// `%X` - same as above, but with A-F capitalized. +// `%o` - substitutes an integer with its equivalent in octal. +// +// .format() -> +// +// Examples: // -// IndexOf +// "this is a string: %s\nand an integer: %d".format(["str", 42]) // returns "this is a string: str\nand an integer: 42" +// "a double substituted with %%s: %s".format([64.2]) // returns "a double substituted with %s: 64.2" +// "string type: %s".format([type(string)]) // returns "string type: string" +// "timestamp: %s".format([timestamp("2023-02-03T23:31:20+00:00")]) // returns "timestamp: 2023-02-03T23:31:20Z" +// "duration: %s".format([duration("1h45m47s")]) // returns "duration: 6347s" +// "%f".format([3.14]) // returns "3.140000" +// "scientific notation: %e".format([2.71828]) // returns "scientific notation: 2.718280\u202f\u00d7\u202f10\u2070\u2070" +// "5 in binary: %b".format([5]), // returns "5 in binary; 101" +// "26 in hex: %x".format([26]), // returns "26 in hex: 1a" +// "26 in hex (uppercase): %X".format([26]) // returns "26 in hex (uppercase): 1A" +// "30 in octal: %o".format([30]) // returns "30 in octal: 36" +// "a map inside a list: %s".format([[1, 2, 3, {"a": "x", "b": "y", "c": "z"}]]) // returns "a map inside a list: [1, 2, 3, {"a":"x", "b":"y", "c":"d"}]" +// "true bool: %s - false bool: %s\nbinary bool: %b".format([true, false, true]) // returns "true bool: true - false bool: false\nbinary bool: 1" +// +// Passing an incorrect type (an integer to `%s`) is considered an error, as well as attempting +// to use more formatting clauses than there are arguments (`%d %d %d` while passing two ints, for instance). +// If compile-time checking is enabled, and the formatting string is a constant, and the argument list is a literal, +// then letting any arguments go unused/unformatted is also considered an error. +// +// # IndexOf // // Returns the integer index of the first occurrence of the search string. If the search string is // not found the function returns -1. @@ -52,19 +112,19 @@ import ( // The function also accepts an optional position from which to begin the substring search. If the // substring is the empty string, the index where the search starts is returned (zero or custom). // -// .indexOf() -> -// .indexOf(, ) -> +// .indexOf() -> +// .indexOf(, ) -> // // Examples: // -// 'hello mellow'.indexOf('') // returns 0 -// 'hello mellow'.indexOf('ello') // returns 1 -// 'hello mellow'.indexOf('jello') // returns -1 -// 'hello mellow'.indexOf('', 2) // returns 2 -// 'hello mellow'.indexOf('ello', 2) // returns 7 -// 'hello mellow'.indexOf('ello', 20) // error +// 'hello mellow'.indexOf('') // returns 0 +// 'hello mellow'.indexOf('ello') // returns 1 +// 'hello mellow'.indexOf('jello') // returns -1 +// 'hello mellow'.indexOf('', 2) // returns 2 +// 'hello mellow'.indexOf('ello', 2) // returns 7 +// 'hello mellow'.indexOf('ello', 20) // error // -// Join +// # Join // // Returns a new string where the elements of string list are concatenated. // @@ -75,12 +135,12 @@ import ( // // Examples: // -// ['hello', 'mellow'].join() // returns 'hellomellow' -// ['hello', 'mellow'].join(' ') // returns 'hello mellow' -// [].join() // returns '' -// [].join('/') // returns '' +// ['hello', 'mellow'].join() // returns 'hellomellow' +// ['hello', 'mellow'].join(' ') // returns 'hello mellow' +// [].join() // returns '' +// [].join('/') // returns '' // -// LastIndexOf +// # LastIndexOf // // Returns the integer index at the start of the last occurrence of the search string. If the // search string is not found the function returns -1. @@ -89,31 +149,45 @@ import ( // considered as the beginning of the substring match. If the substring is the empty string, // the index where the search starts is returned (string length or custom). // -// .lastIndexOf() -> -// .lastIndexOf(, ) -> +// .lastIndexOf() -> +// .lastIndexOf(, ) -> // // Examples: // -// 'hello mellow'.lastIndexOf('') // returns 12 -// 'hello mellow'.lastIndexOf('ello') // returns 7 -// 'hello mellow'.lastIndexOf('jello') // returns -1 -// 'hello mellow'.lastIndexOf('ello', 6) // returns 1 -// 'hello mellow'.lastIndexOf('ello', -1) // error +// 'hello mellow'.lastIndexOf('') // returns 12 +// 'hello mellow'.lastIndexOf('ello') // returns 7 +// 'hello mellow'.lastIndexOf('jello') // returns -1 +// 'hello mellow'.lastIndexOf('ello', 6) // returns 1 +// 'hello mellow'.lastIndexOf('ello', -1) // error // -// LowerAscii +// # LowerAscii // // Returns a new string where all ASCII characters are lower-cased. // // This function does not perform Unicode case-mapping for characters outside the ASCII range. // -// .lowerAscii() -> +// .lowerAscii() -> +// +// Examples: +// +// 'TacoCat'.lowerAscii() // returns 'tacocat' +// 'TacoCÆt Xii'.lowerAscii() // returns 'tacocÆt xii' +// +// # Quote +// +// Introduced in version: 1 +// +// Takes the given string and makes it safe to print (without any formatting due to escape sequences). +// If any invalid UTF-8 characters are encountered, they are replaced with \uFFFD. +// +// strings.quote() // // Examples: // -// 'TacoCat'.lowerAscii() // returns 'tacocat' -// 'TacoCÆt Xii'.lowerAscii() // returns 'tacocÆt xii' +// strings.quote('single-quote with "double quote"') // returns '"single-quote with \"double quote\""' +// strings.quote("two escape sequences \a\n") // returns '"two escape sequences \\a\\n"' // -// Replace +// # Replace // // Returns a new string based on the target, which replaces the occurrences of a search string // with a replacement string if present. The function accepts an optional limit on the number of @@ -122,17 +196,17 @@ import ( // When the replacement limit is 0, the result is the original string. When the limit is a negative // number, the function behaves the same as replace all. // -// .replace(, ) -> -// .replace(, , ) -> +// .replace(, ) -> +// .replace(, , ) -> // // Examples: // -// 'hello hello'.replace('he', 'we') // returns 'wello wello' -// 'hello hello'.replace('he', 'we', -1) // returns 'wello wello' -// 'hello hello'.replace('he', 'we', 1) // returns 'wello hello' -// 'hello hello'.replace('he', 'we', 0) // returns 'hello hello' +// 'hello hello'.replace('he', 'we') // returns 'wello wello' +// 'hello hello'.replace('he', 'we', -1) // returns 'wello wello' +// 'hello hello'.replace('he', 'we', 1) // returns 'wello hello' +// 'hello hello'.replace('he', 'we', 0) // returns 'hello hello' // -// Split +// # Split // // Returns a list of strings split from the input by the given separator. The function accepts // an optional argument specifying a limit on the number of substrings produced by the split. @@ -141,18 +215,18 @@ import ( // target string to split. When the limit is a negative number, the function behaves the same as // split all. // -// .split() -> > -// .split(, ) -> > +// .split() -> > +// .split(, ) -> > // // Examples: // -// 'hello hello hello'.split(' ') // returns ['hello', 'hello', 'hello'] -// 'hello hello hello'.split(' ', 0) // returns [] -// 'hello hello hello'.split(' ', 1) // returns ['hello hello hello'] -// 'hello hello hello'.split(' ', 2) // returns ['hello', 'hello hello'] -// 'hello hello hello'.split(' ', -1) // returns ['hello', 'hello', 'hello'] +// 'hello hello hello'.split(' ') // returns ['hello', 'hello', 'hello'] +// 'hello hello hello'.split(' ', 0) // returns [] +// 'hello hello hello'.split(' ', 1) // returns ['hello hello hello'] +// 'hello hello hello'.split(' ', 2) // returns ['hello', 'hello hello'] +// 'hello hello hello'.split(' ', -1) // returns ['hello', 'hello', 'hello'] // -// Substring +// # Substring // // Returns the substring given a numeric range corresponding to character positions. Optionally // may omit the trailing range for a substring from a given character position until the end of @@ -162,48 +236,102 @@ import ( // error to specify an end range that is lower than the start range, or for either the start or end // index to be negative or exceed the string length. // -// .substring() -> -// .substring(, ) -> +// .substring() -> +// .substring(, ) -> // // Examples: // -// 'tacocat'.substring(4) // returns 'cat' -// 'tacocat'.substring(0, 4) // returns 'taco' -// 'tacocat'.substring(-1) // error -// 'tacocat'.substring(2, 1) // error +// 'tacocat'.substring(4) // returns 'cat' +// 'tacocat'.substring(0, 4) // returns 'taco' +// 'tacocat'.substring(-1) // error +// 'tacocat'.substring(2, 1) // error // -// Trim +// # Trim // // Returns a new string which removes the leading and trailing whitespace in the target string. // The trim function uses the Unicode definition of whitespace which does not include the // zero-width spaces. See: https://en.wikipedia.org/wiki/Whitespace_character#Unicode // -// .trim() -> +// .trim() -> // // Examples: // -// ' \ttrim\n '.trim() // returns 'trim' +// ' \ttrim\n '.trim() // returns 'trim' // -// UpperAscii +// # UpperAscii // // Returns a new string where all ASCII characters are upper-cased. // // This function does not perform Unicode case-mapping for characters outside the ASCII range. // -// .upperAscii() -> +// .upperAscii() -> // // Examples: // -// 'TacoCat'.upperAscii() // returns 'TACOCAT' -// 'TacoCÆt Xii'.upperAscii() // returns 'TACOCÆT XII' -func Strings() cel.EnvOption { - return cel.Lib(stringLib{}) +// 'TacoCat'.upperAscii() // returns 'TACOCAT' +// 'TacoCÆt Xii'.upperAscii() // returns 'TACOCÆT XII' +func Strings(options ...StringsOption) cel.EnvOption { + s := &stringLib{version: math.MaxUint32} + for _, o := range options { + s = o(s) + } + return cel.Lib(s) +} + +type stringLib struct { + locale string + version uint32 +} + +// LibraryName implements the SingletonLibrary interface method. +func (*stringLib) LibraryName() string { + return "cel.lib.ext.strings" } -type stringLib struct{} +// StringsOption is a functional interface for configuring the strings library. +type StringsOption func(*stringLib) *stringLib -func (stringLib) CompileOptions() []cel.EnvOption { - return []cel.EnvOption{ +// StringsLocale configures the library with the given locale. The locale tag will +// be checked for validity at the time that EnvOptions are configured. If this option +// is not passed, string.format will behave as if en_US was passed as the locale. +func StringsLocale(locale string) StringsOption { + return func(sl *stringLib) *stringLib { + sl.locale = locale + return sl + } +} + +// StringsVersion configures the version of the string library. The version limits which +// functions are available. Only functions introduced below or equal to the given +// version included in the library. See the library documentation to determine +// which version a function was introduced at. If the documentation does not +// state which version a function was introduced at, it can be assumed to be +// introduced at version 0, when the library was first created. +// If this option is not set, all functions are available. +func StringsVersion(version uint32) func(lib *stringLib) *stringLib { + return func(sl *stringLib) *stringLib { + sl.version = version + return sl + } +} + +// CompileOptions implements the Library interface method. +func (sl *stringLib) CompileOptions() []cel.EnvOption { + formatLocale := "en_US" + if sl.locale != "" { + // ensure locale is properly-formed if set + _, err := language.Parse(sl.locale) + if err != nil { + return []cel.EnvOption{ + func(e *cel.Env) (*cel.Env, error) { + return nil, fmt.Errorf("failed to parse locale: %w", err) + }, + } + } + formatLocale = sl.locale + } + + opts := []cel.EnvOption{ cel.Function("charAt", cel.MemberOverload("string_char_at_int", []*cel.Type{cel.StringType, cel.IntType}, cel.StringType, cel.BinaryBinding(func(str, ind ref.Val) ref.Val { @@ -303,28 +431,64 @@ func (stringLib) CompileOptions() []cel.EnvOption { s := str.(types.String) return stringOrError(upperASCII(string(s))) }))), - cel.Function("join", - cel.MemberOverload("list_join", []*cel.Type{cel.ListType(cel.StringType)}, cel.StringType, - cel.UnaryBinding(func(list ref.Val) ref.Val { - l, err := list.ConvertToNative(stringListType) - if err != nil { - return types.NewErr(err.Error()) - } - return stringOrError(join(l.([]string))) - })), - cel.MemberOverload("list_join_string", []*cel.Type{cel.ListType(cel.StringType), cel.StringType}, cel.StringType, - cel.BinaryBinding(func(list, delim ref.Val) ref.Val { - l, err := list.ConvertToNative(stringListType) - if err != nil { - return types.NewErr(err.Error()) - } - d := delim.(types.String) - return stringOrError(joinSeparator(l.([]string), string(d))) + } + if sl.version >= 1 { + opts = append(opts, cel.Function("format", + cel.MemberOverload("string_format", []*cel.Type{cel.StringType, cel.ListType(cel.DynType)}, cel.StringType, + cel.FunctionBinding(func(args ...ref.Val) ref.Val { + s := string(args[0].(types.String)) + formatArgs := args[1].(traits.Lister) + return stringOrError(interpreter.ParseFormatString(s, &stringFormatter{}, &stringArgList{formatArgs}, formatLocale)) }))), + cel.Function("strings.quote", cel.Overload("strings_quote", []*cel.Type{cel.StringType}, cel.StringType, + cel.UnaryBinding(func(str ref.Val) ref.Val { + s := str.(types.String) + return stringOrError(quote(string(s))) + })))) + + } + if sl.version >= 2 { + opts = append(opts, + cel.Function("join", + cel.MemberOverload("list_join", []*cel.Type{cel.ListType(cel.StringType)}, cel.StringType, + cel.UnaryBinding(func(list ref.Val) ref.Val { + l := list.(traits.Lister) + return stringOrError(joinValSeparator(l, "")) + })), + cel.MemberOverload("list_join_string", []*cel.Type{cel.ListType(cel.StringType), cel.StringType}, cel.StringType, + cel.BinaryBinding(func(list, delim ref.Val) ref.Val { + l := list.(traits.Lister) + d := delim.(types.String) + return stringOrError(joinValSeparator(l, string(d))) + }))), + ) + } else { + opts = append(opts, + cel.Function("join", + cel.MemberOverload("list_join", []*cel.Type{cel.ListType(cel.StringType)}, cel.StringType, + cel.UnaryBinding(func(list ref.Val) ref.Val { + l, err := list.ConvertToNative(stringListType) + if err != nil { + return types.NewErr(err.Error()) + } + return stringOrError(join(l.([]string))) + })), + cel.MemberOverload("list_join_string", []*cel.Type{cel.ListType(cel.StringType), cel.StringType}, cel.StringType, + cel.BinaryBinding(func(list, delim ref.Val) ref.Val { + l, err := list.ConvertToNative(stringListType) + if err != nil { + return types.NewErr(err.Error()) + } + d := delim.(types.String) + return stringOrError(joinSeparator(l.([]string), string(d))) + }))), + ) } + return opts } -func (stringLib) ProgramOptions() []cel.ProgramOption { +// ProgramOptions implements the Library interface method. +func (*stringLib) ProgramOptions() []cel.ProgramOption { return []cel.ProgramOption{} } @@ -478,6 +642,452 @@ func join(strs []string) (string, error) { return strings.Join(strs, ""), nil } +func joinValSeparator(strs traits.Lister, separator string) (string, error) { + sz := strs.Size().(types.Int) + var sb strings.Builder + for i := types.Int(0); i < sz; i++ { + if i != 0 { + sb.WriteString(separator) + } + elem := strs.Get(i) + str, ok := elem.(types.String) + if !ok { + return "", fmt.Errorf("join: invalid input: %v", elem) + } + sb.WriteString(string(str)) + } + return sb.String(), nil +} + +type clauseImpl func(ref.Val, string) (string, error) + +func clauseForType(argType ref.Type) (clauseImpl, error) { + switch argType { + case types.IntType, types.UintType: + return formatDecimal, nil + case types.StringType, types.BytesType, types.BoolType, types.NullType, types.TypeType: + return FormatString, nil + case types.TimestampType, types.DurationType: + // special case to ensure timestamps/durations get printed as CEL literals + return func(arg ref.Val, locale string) (string, error) { + argStrVal := arg.ConvertToType(types.StringType) + argStr := argStrVal.Value().(string) + if arg.Type() == types.TimestampType { + return fmt.Sprintf("timestamp(%q)", argStr), nil + } + if arg.Type() == types.DurationType { + return fmt.Sprintf("duration(%q)", argStr), nil + } + return "", fmt.Errorf("cannot convert argument of type %s to timestamp/duration", arg.Type().TypeName()) + }, nil + case types.ListType: + return formatList, nil + case types.MapType: + return formatMap, nil + case types.DoubleType: + // avoid formatFixed so we can output a period as the decimal separator in order + // to always be a valid CEL literal + return func(arg ref.Val, locale string) (string, error) { + argDouble, ok := arg.Value().(float64) + if !ok { + return "", fmt.Errorf("couldn't convert %s to float64", arg.Type().TypeName()) + } + fmtStr := fmt.Sprintf("%%.%df", defaultPrecision) + return fmt.Sprintf(fmtStr, argDouble), nil + }, nil + case types.TypeType: + return func(arg ref.Val, locale string) (string, error) { + return fmt.Sprintf("type(%s)", arg.Value().(string)), nil + }, nil + default: + return nil, fmt.Errorf("no formatting function for %s", argType.TypeName()) + } +} + +func formatList(arg ref.Val, locale string) (string, error) { + argList := arg.(traits.Lister) + argIterator := argList.Iterator() + var listStrBuilder strings.Builder + _, err := listStrBuilder.WriteRune('[') + if err != nil { + return "", fmt.Errorf("error writing to list string: %w", err) + } + for argIterator.HasNext() == types.True { + member := argIterator.Next() + memberFormat, err := clauseForType(member.Type()) + if err != nil { + return "", err + } + unquotedStr, err := memberFormat(member, locale) + if err != nil { + return "", err + } + str := quoteForCEL(member, unquotedStr) + _, err = listStrBuilder.WriteString(str) + if err != nil { + return "", fmt.Errorf("error writing to list string: %w", err) + } + if argIterator.HasNext() == types.True { + _, err = listStrBuilder.WriteString(", ") + if err != nil { + return "", fmt.Errorf("error writing to list string: %w", err) + } + } + } + _, err = listStrBuilder.WriteRune(']') + if err != nil { + return "", fmt.Errorf("error writing to list string: %w", err) + } + return listStrBuilder.String(), nil +} + +func formatMap(arg ref.Val, locale string) (string, error) { + argMap := arg.(traits.Mapper) + argIterator := argMap.Iterator() + type mapPair struct { + key string + value string + } + argPairs := make([]mapPair, argMap.Size().Value().(int64)) + i := 0 + for argIterator.HasNext() == types.True { + key := argIterator.Next() + var keyFormat clauseImpl + switch key.Type() { + case types.StringType, types.BoolType: + keyFormat = FormatString + case types.IntType, types.UintType: + keyFormat = formatDecimal + default: + return "", fmt.Errorf("no formatting function for map key of type %s", key.Type().TypeName()) + } + unquotedKeyStr, err := keyFormat(key, locale) + if err != nil { + return "", err + } + keyStr := quoteForCEL(key, unquotedKeyStr) + value, found := argMap.Find(key) + if !found { + return "", fmt.Errorf("could not find key: %q", key) + } + valueFormat, err := clauseForType(value.Type()) + if err != nil { + return "", err + } + unquotedValueStr, err := valueFormat(value, locale) + if err != nil { + return "", err + } + valueStr := quoteForCEL(value, unquotedValueStr) + argPairs[i] = mapPair{keyStr, valueStr} + i++ + } + sort.SliceStable(argPairs, func(x, y int) bool { + return argPairs[x].key < argPairs[y].key + }) + var mapStrBuilder strings.Builder + _, err := mapStrBuilder.WriteRune('{') + if err != nil { + return "", fmt.Errorf("error writing to map string: %w", err) + } + for i, entry := range argPairs { + _, err = mapStrBuilder.WriteString(fmt.Sprintf("%s:%s", entry.key, entry.value)) + if err != nil { + return "", fmt.Errorf("error writing to map string: %w", err) + } + if i < len(argPairs)-1 { + _, err = mapStrBuilder.WriteString(", ") + if err != nil { + return "", fmt.Errorf("error writing to map string: %w", err) + } + } + } + _, err = mapStrBuilder.WriteRune('}') + if err != nil { + return "", fmt.Errorf("error writing to map string: %w", err) + } + return mapStrBuilder.String(), nil +} + +// quoteForCEL takes a formatted, unquoted value and quotes it in a manner +// suitable for embedding directly in CEL. +func quoteForCEL(refVal ref.Val, unquotedValue string) string { + switch refVal.Type() { + case types.StringType: + return fmt.Sprintf("%q", unquotedValue) + case types.BytesType: + return fmt.Sprintf("b%q", unquotedValue) + case types.DoubleType: + // special case to handle infinity/NaN + num := refVal.Value().(float64) + if math.IsInf(num, 1) || math.IsInf(num, -1) || math.IsNaN(num) { + return fmt.Sprintf("%q", unquotedValue) + } + return unquotedValue + default: + return unquotedValue + } +} + +// FormatString returns the string representation of a CEL value. +// It is used to implement the %s specifier in the (string).format() extension +// function. +func FormatString(arg ref.Val, locale string) (string, error) { + switch arg.Type() { + case types.ListType: + return formatList(arg, locale) + case types.MapType: + return formatMap(arg, locale) + case types.IntType, types.UintType, types.DoubleType, + types.BoolType, types.StringType, types.TimestampType, types.BytesType, types.DurationType, types.TypeType: + argStrVal := arg.ConvertToType(types.StringType) + argStr, ok := argStrVal.Value().(string) + if !ok { + return "", fmt.Errorf("could not convert argument %q to string", argStrVal) + } + return argStr, nil + case types.NullType: + return "null", nil + default: + return "", fmt.Errorf("string clause can only be used on strings, bools, bytes, ints, doubles, maps, lists, types, durations, and timestamps, was given %s", arg.Type().TypeName()) + } +} + +func formatDecimal(arg ref.Val, locale string) (string, error) { + switch arg.Type() { + case types.IntType: + argInt, ok := arg.ConvertToType(types.IntType).Value().(int64) + if !ok { + return "", fmt.Errorf("could not convert \"%s\" to int64", arg.Value()) + } + return fmt.Sprintf("%d", argInt), nil + case types.UintType: + argInt, ok := arg.ConvertToType(types.UintType).Value().(uint64) + if !ok { + return "", fmt.Errorf("could not convert \"%s\" to uint64", arg.Value()) + } + return fmt.Sprintf("%d", argInt), nil + default: + return "", fmt.Errorf("decimal clause can only be used on integers, was given %s", arg.Type().TypeName()) + } +} + +func matchLanguage(locale string) (language.Tag, error) { + matcher, err := makeMatcher(locale) + if err != nil { + return language.Und, err + } + tag, _ := language.MatchStrings(matcher, locale) + return tag, nil +} + +func makeMatcher(locale string) (language.Matcher, error) { + tags := make([]language.Tag, 0) + tag, err := language.Parse(locale) + if err != nil { + return nil, err + } + tags = append(tags, tag) + return language.NewMatcher(tags), nil +} + +// quote implements a string quoting function. The string will be wrapped in +// double quotes, and all valid CEL escape sequences will be escaped to show up +// literally if printed. If the input contains any invalid UTF-8, the invalid runes +// will be replaced with utf8.RuneError. +func quote(s string) (string, error) { + var quotedStrBuilder strings.Builder + for _, c := range sanitize(s) { + switch c { + case '\a': + quotedStrBuilder.WriteString("\\a") + case '\b': + quotedStrBuilder.WriteString("\\b") + case '\f': + quotedStrBuilder.WriteString("\\f") + case '\n': + quotedStrBuilder.WriteString("\\n") + case '\r': + quotedStrBuilder.WriteString("\\r") + case '\t': + quotedStrBuilder.WriteString("\\t") + case '\v': + quotedStrBuilder.WriteString("\\v") + case '\\': + quotedStrBuilder.WriteString("\\\\") + case '"': + quotedStrBuilder.WriteString("\\\"") + default: + quotedStrBuilder.WriteRune(c) + } + } + escapedStr := quotedStrBuilder.String() + return "\"" + escapedStr + "\"", nil +} + +// sanitize replaces all invalid runes in the given string with utf8.RuneError. +func sanitize(s string) string { + var sanitizedStringBuilder strings.Builder + for _, r := range s { + if !utf8.ValidRune(r) { + sanitizedStringBuilder.WriteRune(utf8.RuneError) + } else { + sanitizedStringBuilder.WriteRune(r) + } + } + return sanitizedStringBuilder.String() +} + +type stringFormatter struct{} + +func (c *stringFormatter) String(arg ref.Val, locale string) (string, error) { + return FormatString(arg, locale) +} + +func (c *stringFormatter) Decimal(arg ref.Val, locale string) (string, error) { + return formatDecimal(arg, locale) +} + +func (c *stringFormatter) Fixed(precision *int) func(ref.Val, string) (string, error) { + if precision == nil { + precision = new(int) + *precision = defaultPrecision + } + return func(arg ref.Val, locale string) (string, error) { + strException := false + if arg.Type() == types.StringType { + argStr := arg.Value().(string) + if argStr == "NaN" || argStr == "Infinity" || argStr == "-Infinity" { + strException = true + } + } + if arg.Type() != types.DoubleType && !strException { + return "", fmt.Errorf("fixed-point clause can only be used on doubles, was given %s", arg.Type().TypeName()) + } + argFloatVal := arg.ConvertToType(types.DoubleType) + argFloat, ok := argFloatVal.Value().(float64) + if !ok { + return "", fmt.Errorf("could not convert \"%s\" to float64", argFloatVal.Value()) + } + fmtStr := fmt.Sprintf("%%.%df", *precision) + + matchedLocale, err := matchLanguage(locale) + if err != nil { + return "", fmt.Errorf("error matching locale: %w", err) + } + return message.NewPrinter(matchedLocale).Sprintf(fmtStr, argFloat), nil + } +} + +func (c *stringFormatter) Scientific(precision *int) func(ref.Val, string) (string, error) { + if precision == nil { + precision = new(int) + *precision = defaultPrecision + } + return func(arg ref.Val, locale string) (string, error) { + strException := false + if arg.Type() == types.StringType { + argStr := arg.Value().(string) + if argStr == "NaN" || argStr == "Infinity" || argStr == "-Infinity" { + strException = true + } + } + if arg.Type() != types.DoubleType && !strException { + return "", fmt.Errorf("scientific clause can only be used on doubles, was given %s", arg.Type().TypeName()) + } + argFloatVal := arg.ConvertToType(types.DoubleType) + argFloat, ok := argFloatVal.Value().(float64) + if !ok { + return "", fmt.Errorf("could not convert \"%s\" to float64", argFloatVal.Value()) + } + matchedLocale, err := matchLanguage(locale) + if err != nil { + return "", fmt.Errorf("error matching locale: %w", err) + } + fmtStr := fmt.Sprintf("%%%de", *precision) + return message.NewPrinter(matchedLocale).Sprintf(fmtStr, argFloat), nil + } +} + +func (c *stringFormatter) Binary(arg ref.Val, locale string) (string, error) { + switch arg.Type() { + case types.IntType: + argInt := arg.Value().(int64) + // locale is intentionally unused as integers formatted as binary + // strings are locale-independent + return fmt.Sprintf("%b", argInt), nil + case types.UintType: + argInt := arg.Value().(uint64) + return fmt.Sprintf("%b", argInt), nil + case types.BoolType: + argBool := arg.Value().(bool) + if argBool { + return "1", nil + } + return "0", nil + default: + return "", fmt.Errorf("only integers and bools can be formatted as binary, was given %s", arg.Type().TypeName()) + } +} + +func (c *stringFormatter) Hex(useUpper bool) func(ref.Val, string) (string, error) { + return func(arg ref.Val, locale string) (string, error) { + fmtStr := "%x" + if useUpper { + fmtStr = "%X" + } + switch arg.Type() { + case types.StringType, types.BytesType: + if arg.Type() == types.BytesType { + return fmt.Sprintf(fmtStr, arg.Value().([]byte)), nil + } + return fmt.Sprintf(fmtStr, arg.Value().(string)), nil + case types.IntType: + argInt, ok := arg.Value().(int64) + if !ok { + return "", fmt.Errorf("could not convert \"%s\" to int64", arg.Value()) + } + return fmt.Sprintf(fmtStr, argInt), nil + case types.UintType: + argInt, ok := arg.Value().(uint64) + if !ok { + return "", fmt.Errorf("could not convert \"%s\" to uint64", arg.Value()) + } + return fmt.Sprintf(fmtStr, argInt), nil + default: + return "", fmt.Errorf("only integers, byte buffers, and strings can be formatted as hex, was given %s", arg.Type().TypeName()) + } + } +} + +func (c *stringFormatter) Octal(arg ref.Val, locale string) (string, error) { + switch arg.Type() { + case types.IntType: + argInt := arg.Value().(int64) + return fmt.Sprintf("%o", argInt), nil + case types.UintType: + argInt := arg.Value().(uint64) + return fmt.Sprintf("%o", argInt), nil + default: + return "", fmt.Errorf("octal clause can only be used on integers, was given %s", arg.Type().TypeName()) + } +} + +type stringArgList struct { + args traits.Lister +} + +func (c *stringArgList) Arg(index int64) (ref.Val, error) { + if index >= c.args.Size().Value().(int64) { + return nil, fmt.Errorf("index %d out of range", index) + } + return c.args.Get(types.Int(index)), nil +} + +func (c *stringArgList) ArgSize() int64 { + return c.args.Size().Value().(int64) +} + var ( stringListType = reflect.TypeOf([]string{}) ) diff --git a/vendor/github.com/google/cel-go/interpreter/BUILD.bazel b/vendor/github.com/google/cel-go/interpreter/BUILD.bazel index 04a3ec7441..1e50caf091 100644 --- a/vendor/github.com/google/cel-go/interpreter/BUILD.bazel +++ b/vendor/github.com/google/cel-go/interpreter/BUILD.bazel @@ -11,10 +11,10 @@ go_library( "activation.go", "attribute_patterns.go", "attributes.go", - "coster.go", "decorators.go", "dispatcher.go", "evalstate.go", + "formatting.go", "interpretable.go", "interpreter.go", "optimizations.go", @@ -49,6 +49,7 @@ go_test( "attributes_test.go", "interpreter_test.go", "prune_test.go", + "runtimecost_test.go", ], embed = [ ":go_default_library", diff --git a/vendor/github.com/google/cel-go/interpreter/activation.go b/vendor/github.com/google/cel-go/interpreter/activation.go index 8686d4f04f..f82e4e9038 100644 --- a/vendor/github.com/google/cel-go/interpreter/activation.go +++ b/vendor/github.com/google/cel-go/interpreter/activation.go @@ -28,7 +28,7 @@ import ( type Activation interface { // ResolveName returns a value from the activation by qualified name, or false if the name // could not be found. - ResolveName(name string) (interface{}, bool) + ResolveName(name string) (any, bool) // Parent returns the parent of the current activation, may be nil. // If non-nil, the parent will be searched during resolve calls. @@ -43,23 +43,23 @@ func EmptyActivation() Activation { // emptyActivation is a variable-free activation. type emptyActivation struct{} -func (emptyActivation) ResolveName(string) (interface{}, bool) { return nil, false } -func (emptyActivation) Parent() Activation { return nil } +func (emptyActivation) ResolveName(string) (any, bool) { return nil, false } +func (emptyActivation) Parent() Activation { return nil } // NewActivation returns an activation based on a map-based binding where the map keys are // expected to be qualified names used with ResolveName calls. // -// The input `bindings` may either be of type `Activation` or `map[string]interface{}`. +// The input `bindings` may either be of type `Activation` or `map[string]any`. // // Lazy bindings may be supplied within the map-based input in either of the following forms: -// - func() interface{} +// - func() any // - func() ref.Val // // The output of the lazy binding will overwrite the variable reference in the internal map. // // Values which are not represented as ref.Val types on input may be adapted to a ref.Val using // the ref.TypeAdapter configured in the environment. -func NewActivation(bindings interface{}) (Activation, error) { +func NewActivation(bindings any) (Activation, error) { if bindings == nil { return nil, errors.New("bindings must be non-nil") } @@ -67,7 +67,7 @@ func NewActivation(bindings interface{}) (Activation, error) { if isActivation { return a, nil } - m, isMap := bindings.(map[string]interface{}) + m, isMap := bindings.(map[string]any) if !isMap { return nil, fmt.Errorf( "activation input must be an activation or map[string]interface: got %T", @@ -81,7 +81,7 @@ func NewActivation(bindings interface{}) (Activation, error) { // Named bindings may lazily supply values by providing a function which accepts no arguments and // produces an interface value. type mapActivation struct { - bindings map[string]interface{} + bindings map[string]any } // Parent implements the Activation interface method. @@ -90,7 +90,7 @@ func (a *mapActivation) Parent() Activation { } // ResolveName implements the Activation interface method. -func (a *mapActivation) ResolveName(name string) (interface{}, bool) { +func (a *mapActivation) ResolveName(name string) (any, bool) { obj, found := a.bindings[name] if !found { return nil, false @@ -100,7 +100,7 @@ func (a *mapActivation) ResolveName(name string) (interface{}, bool) { obj = fn() a.bindings[name] = obj } - fnRaw, isLazy := obj.(func() interface{}) + fnRaw, isLazy := obj.(func() any) if isLazy { obj = fnRaw() a.bindings[name] = obj @@ -121,7 +121,7 @@ func (a *hierarchicalActivation) Parent() Activation { } // ResolveName implements the Activation interface method. -func (a *hierarchicalActivation) ResolveName(name string) (interface{}, bool) { +func (a *hierarchicalActivation) ResolveName(name string) (any, bool) { if object, found := a.child.ResolveName(name); found { return object, found } @@ -138,8 +138,8 @@ func NewHierarchicalActivation(parent Activation, child Activation) Activation { // representing field and index operations that should result in a 'types.Unknown' result. // // The `bindings` value may be any value type supported by the interpreter.NewActivation call, -// but is typically either an existing Activation or map[string]interface{}. -func NewPartialActivation(bindings interface{}, +// but is typically either an existing Activation or map[string]any. +func NewPartialActivation(bindings any, unknowns ...*AttributePattern) (PartialActivation, error) { a, err := NewActivation(bindings) if err != nil { @@ -184,7 +184,7 @@ func (v *varActivation) Parent() Activation { } // ResolveName implements the Activation interface method. -func (v *varActivation) ResolveName(name string) (interface{}, bool) { +func (v *varActivation) ResolveName(name string) (any, bool) { if name == v.name { return v.val, true } @@ -194,7 +194,7 @@ func (v *varActivation) ResolveName(name string) (interface{}, bool) { var ( // pool of var activations to reduce allocations during folds. varActivationPool = &sync.Pool{ - New: func() interface{} { + New: func() any { return &varActivation{} }, } diff --git a/vendor/github.com/google/cel-go/interpreter/attribute_patterns.go b/vendor/github.com/google/cel-go/interpreter/attribute_patterns.go index b33f7f7fd9..afb7c8d5bf 100644 --- a/vendor/github.com/google/cel-go/interpreter/attribute_patterns.go +++ b/vendor/github.com/google/cel-go/interpreter/attribute_patterns.go @@ -15,8 +15,6 @@ package interpreter import ( - "fmt" - "github.com/google/cel-go/common/containers" "github.com/google/cel-go/common/types" "github.com/google/cel-go/common/types/ref" @@ -36,9 +34,9 @@ import ( // // Examples: // -// 1. ns.myvar["complex-value"] -// 2. ns.myvar["complex-value"][0] -// 3. ns.myvar["complex-value"].*.name +// 1. ns.myvar["complex-value"] +// 2. ns.myvar["complex-value"][0] +// 3. ns.myvar["complex-value"].*.name // // The first example is simple: match an attribute where the variable is 'ns.myvar' with a // field access on 'complex-value'. The second example expands the match to indicate that only @@ -108,7 +106,7 @@ func (apat *AttributePattern) QualifierPatterns() []*AttributeQualifierPattern { // AttributeQualifierPattern holds a wildcard or valued qualifier pattern. type AttributeQualifierPattern struct { wildcard bool - value interface{} + value any } // Matches returns true if the qualifier pattern is a wildcard, or the Qualifier implements the @@ -134,44 +132,44 @@ func (qpat *AttributeQualifierPattern) Matches(q Qualifier) bool { type qualifierValueEquator interface { // QualifierValueEquals returns true if the input value is equal to the value held in the // Qualifier. - QualifierValueEquals(value interface{}) bool + QualifierValueEquals(value any) bool } // QualifierValueEquals implementation for boolean qualifiers. -func (q *boolQualifier) QualifierValueEquals(value interface{}) bool { +func (q *boolQualifier) QualifierValueEquals(value any) bool { bval, ok := value.(bool) return ok && q.value == bval } // QualifierValueEquals implementation for field qualifiers. -func (q *fieldQualifier) QualifierValueEquals(value interface{}) bool { +func (q *fieldQualifier) QualifierValueEquals(value any) bool { sval, ok := value.(string) return ok && q.Name == sval } // QualifierValueEquals implementation for string qualifiers. -func (q *stringQualifier) QualifierValueEquals(value interface{}) bool { +func (q *stringQualifier) QualifierValueEquals(value any) bool { sval, ok := value.(string) return ok && q.value == sval } // QualifierValueEquals implementation for int qualifiers. -func (q *intQualifier) QualifierValueEquals(value interface{}) bool { +func (q *intQualifier) QualifierValueEquals(value any) bool { return numericValueEquals(value, q.celValue) } // QualifierValueEquals implementation for uint qualifiers. -func (q *uintQualifier) QualifierValueEquals(value interface{}) bool { +func (q *uintQualifier) QualifierValueEquals(value any) bool { return numericValueEquals(value, q.celValue) } // QualifierValueEquals implementation for double qualifiers. -func (q *doubleQualifier) QualifierValueEquals(value interface{}) bool { +func (q *doubleQualifier) QualifierValueEquals(value any) bool { return numericValueEquals(value, q.celValue) } // numericValueEquals uses CEL equality to determine whether two number values are -func numericValueEquals(value interface{}, celValue ref.Val) bool { +func numericValueEquals(value any, celValue ref.Val) bool { val := types.DefaultTypeAdapter.NativeToValue(value) return celValue.Equal(val) == types.True } @@ -272,13 +270,9 @@ func (fac *partialAttributeFactory) matchesUnknownPatterns( if err != nil { return nil, err } - unk, isUnk := val.(types.Unknown) - if isUnk { - return unk, nil - } // If this resolution behavior ever changes, new implementations of the // qualifierValueEquator may be required to handle proper resolution. - qual, err = fac.NewQualifier(nil, qual.ID(), val) + qual, err = fac.NewQualifier(nil, qual.ID(), val, attr.IsOptional()) if err != nil { return nil, err } @@ -338,24 +332,10 @@ func (m *attributeMatcher) AddQualifier(qual Qualifier) (Attribute, error) { return m, nil } -// Resolve is an implementation of the Attribute interface method which uses the -// attributeMatcher TryResolve implementation rather than the embedded NamespacedAttribute -// Resolve implementation. -func (m *attributeMatcher) Resolve(vars Activation) (interface{}, error) { - obj, found, err := m.TryResolve(vars) - if err != nil { - return nil, err - } - if !found { - return nil, fmt.Errorf("no such attribute: %v", m.NamespacedAttribute) - } - return obj, nil -} - -// TryResolve is an implementation of the NamespacedAttribute interface method which tests +// Resolve is an implementation of the NamespacedAttribute interface method which tests // for matching unknown attribute patterns and returns types.Unknown if present. Otherwise, // the standard Resolve logic applies. -func (m *attributeMatcher) TryResolve(vars Activation) (interface{}, bool, error) { +func (m *attributeMatcher) Resolve(vars Activation) (any, error) { id := m.NamespacedAttribute.ID() // Bug in how partial activation is resolved, should search parents as well. partial, isPartial := toPartialActivation(vars) @@ -366,30 +346,23 @@ func (m *attributeMatcher) TryResolve(vars Activation) (interface{}, bool, error m.CandidateVariableNames(), m.qualifiers) if err != nil { - return nil, true, err + return nil, err } if unk != nil { - return unk, true, nil + return unk, nil } } - return m.NamespacedAttribute.TryResolve(vars) + return m.NamespacedAttribute.Resolve(vars) } // Qualify is an implementation of the Qualifier interface method. -func (m *attributeMatcher) Qualify(vars Activation, obj interface{}) (interface{}, error) { - val, err := m.Resolve(vars) - if err != nil { - return nil, err - } - unk, isUnk := val.(types.Unknown) - if isUnk { - return unk, nil - } - qual, err := m.fac.NewQualifier(nil, m.ID(), val) - if err != nil { - return nil, err - } - return qual.Qualify(vars, obj) +func (m *attributeMatcher) Qualify(vars Activation, obj any) (any, error) { + return attrQualify(m.fac, vars, obj, m) +} + +// QualifyIfPresent is an implementation of the Qualifier interface method. +func (m *attributeMatcher) QualifyIfPresent(vars Activation, obj any, presenceOnly bool) (any, bool, error) { + return attrQualifyIfPresent(m.fac, vars, obj, m, presenceOnly) } func toPartialActivation(vars Activation) (PartialActivation, bool) { diff --git a/vendor/github.com/google/cel-go/interpreter/attributes.go b/vendor/github.com/google/cel-go/interpreter/attributes.go index 4f1772ea39..1b19dc2b57 100644 --- a/vendor/github.com/google/cel-go/interpreter/attributes.go +++ b/vendor/github.com/google/cel-go/interpreter/attributes.go @@ -16,7 +16,7 @@ package interpreter import ( "fmt" - "math" + "strings" "github.com/google/cel-go/common/containers" "github.com/google/cel-go/common/types" @@ -61,7 +61,7 @@ type AttributeFactory interface { // The qualifier may consider the object type being qualified, if present. If absent, the // qualification should be considered dynamic and the qualification should still work, though // it may be sub-optimal. - NewQualifier(objType *exprpb.Type, qualID int64, val interface{}) (Qualifier, error) + NewQualifier(objType *exprpb.Type, qualID int64, val any, opt bool) (Qualifier, error) } // Qualifier marker interface for designating different qualifier values and where they appear @@ -70,9 +70,21 @@ type Qualifier interface { // ID where the qualifier appears within an expression. ID() int64 + // IsOptional specifies whether the qualifier is optional. + // Instead of a direct qualification, an optional qualifier will be resolved via QualifyIfPresent + // rather than Qualify. A non-optional qualifier may also be resolved through QualifyIfPresent if + // the object to qualify is itself optional. + IsOptional() bool + // Qualify performs a qualification, e.g. field selection, on the input object and returns - // the value or error that results. - Qualify(vars Activation, obj interface{}) (interface{}, error) + // the value of the access and whether the value was set. A non-nil value with a false presence + // test result indicates that the value being returned is the default value. + Qualify(vars Activation, obj any) (any, error) + + // QualifyIfPresent qualifies the object if the qualifier is declared or defined on the object. + // The 'presenceOnly' flag indicates that the value is not necessary, just a boolean status as + // to whether the qualifier is present. + QualifyIfPresent(vars Activation, obj any, presenceOnly bool) (any, bool, error) } // ConstantQualifier interface embeds the Qualifier interface and provides an option to inspect the @@ -82,6 +94,7 @@ type Qualifier interface { type ConstantQualifier interface { Qualifier + // Value returns the constant value associated with the qualifier. Value() ref.Val } @@ -90,12 +103,16 @@ type ConstantQualifier interface { type Attribute interface { Qualifier - // AddQualifier adds a qualifier on the Attribute or error if the qualification is not a valid - // qualifier type. + // AddQualifier adds a qualifier on the Attribute or error if the qualification is not a valid qualifier type. AddQualifier(Qualifier) (Attribute, error) - // Resolve returns the value of the Attribute given the current Activation. - Resolve(Activation) (interface{}, error) + // Resolve returns the value of the Attribute and whether it was present given an Activation. + // For objects which support safe traversal, the value may be non-nil and the presence flag be false. + // + // If an error is encountered during attribute resolution, it will be returned immediately. + // If the attribute cannot be resolved within the Activation, the result must be: `nil`, `error` + // with the error indicating which variable was missing. + Resolve(Activation) (any, error) } // NamespacedAttribute values are a variable within a namespace, and an optional set of qualifiers @@ -107,22 +124,14 @@ type NamespacedAttribute interface { // the CEL namespace resolution order. CandidateVariableNames() []string - // Qualifiers returns the list of qualifiers associated with the Attribute.s + // Qualifiers returns the list of qualifiers associated with the Attribute. Qualifiers() []Qualifier - - // TryResolve attempts to return the value of the attribute given the current Activation. - // If an error is encountered during attribute resolution, it will be returned immediately. - // If the attribute cannot be resolved within the Activation, the result must be: `nil`, - // `false`, `nil`. - TryResolve(Activation) (interface{}, bool, error) } // NewAttributeFactory returns a default AttributeFactory which is produces Attribute values // capable of resolving types by simple names and qualify the values using the supported qualifier // types: bool, int, string, and uint. -func NewAttributeFactory(cont *containers.Container, - a ref.TypeAdapter, - p ref.TypeProvider) AttributeFactory { +func NewAttributeFactory(cont *containers.Container, a ref.TypeAdapter, p ref.TypeProvider) AttributeFactory { return &attrFactory{ container: cont, adapter: a, @@ -190,9 +199,7 @@ func (r *attrFactory) RelativeAttribute(id int64, operand Interpretable) Attribu } // NewQualifier is an implementation of the AttributeFactory interface. -func (r *attrFactory) NewQualifier(objType *exprpb.Type, - qualID int64, - val interface{}) (Qualifier, error) { +func (r *attrFactory) NewQualifier(objType *exprpb.Type, qualID int64, val any, opt bool) (Qualifier, error) { // Before creating a new qualifier check to see if this is a protobuf message field access. // If so, use the precomputed GetFrom qualification method rather than the standard // stringQualifier. @@ -205,10 +212,11 @@ func (r *attrFactory) NewQualifier(objType *exprpb.Type, Name: str, FieldType: ft, adapter: r.adapter, + optional: opt, }, nil } } - return newQualifier(r.adapter, qualID, val) + return newQualifier(r.adapter, qualID, val, opt) } type absoluteAttribute struct { @@ -224,19 +232,18 @@ type absoluteAttribute struct { // ID implements the Attribute interface method. func (a *absoluteAttribute) ID() int64 { - return a.id + qualCount := len(a.qualifiers) + if qualCount == 0 { + return a.id + } + return a.qualifiers[qualCount-1].ID() } -// Cost implements the Coster interface method. -func (a *absoluteAttribute) Cost() (min, max int64) { - for _, q := range a.qualifiers { - minQ, maxQ := estimateCost(q) - min += minQ - max += maxQ - } - min++ // For object retrieval. - max++ - return +// IsOptional returns trivially false for an attribute as the attribute represents a fully +// qualified variable name. If the attribute is used in an optional manner, then an attrQualifier +// is created and marks the attribute as optional. +func (a *absoluteAttribute) IsOptional() bool { + return false } // AddQualifier implements the Attribute interface method. @@ -256,33 +263,13 @@ func (a *absoluteAttribute) Qualifiers() []Qualifier { } // Qualify is an implementation of the Qualifier interface method. -func (a *absoluteAttribute) Qualify(vars Activation, obj interface{}) (interface{}, error) { - val, err := a.Resolve(vars) - if err != nil { - return nil, err - } - unk, isUnk := val.(types.Unknown) - if isUnk { - return unk, nil - } - qual, err := a.fac.NewQualifier(nil, a.id, val) - if err != nil { - return nil, err - } - return qual.Qualify(vars, obj) +func (a *absoluteAttribute) Qualify(vars Activation, obj any) (any, error) { + return attrQualify(a.fac, vars, obj, a) } -// Resolve returns the resolved Attribute value given the Activation, or error if the Attribute -// variable is not found, or if its Qualifiers cannot be applied successfully. -func (a *absoluteAttribute) Resolve(vars Activation) (interface{}, error) { - obj, found, err := a.TryResolve(vars) - if err != nil { - return nil, err - } - if found { - return obj, nil - } - return nil, fmt.Errorf("no such attribute: %v", a) +// QualifyIfPresent is an implementation of the Qualifier interface method. +func (a *absoluteAttribute) QualifyIfPresent(vars Activation, obj any, presenceOnly bool) (any, bool, error) { + return attrQualifyIfPresent(a.fac, vars, obj, a, presenceOnly) } // String implements the Stringer interface method. @@ -290,36 +277,47 @@ func (a *absoluteAttribute) String() string { return fmt.Sprintf("id: %v, names: %v", a.id, a.namespaceNames) } -// TryResolve iterates through the namespaced variable names until one is found within the -// Activation or TypeProvider. +// Resolve returns the resolved Attribute value given the Activation, or error if the Attribute +// variable is not found, or if its Qualifiers cannot be applied successfully. // // If the variable name cannot be found as an Activation variable or in the TypeProvider as -// a type, then the result is `nil`, `false`, `nil` per the interface requirement. -func (a *absoluteAttribute) TryResolve(vars Activation) (interface{}, bool, error) { +// a type, then the result is `nil`, `error` with the error indicating the name of the first +// variable searched as missing. +func (a *absoluteAttribute) Resolve(vars Activation) (any, error) { for _, nm := range a.namespaceNames { // If the variable is found, process it. Otherwise, wait until the checks to // determine whether the type is unknown before returning. - op, found := vars.ResolveName(nm) + obj, found := vars.ResolveName(nm) if found { - var err error - for _, qual := range a.qualifiers { - op, err = qual.Qualify(vars, op) - if err != nil { - return nil, true, err + obj, isOpt, err := applyQualifiers(vars, obj, a.qualifiers) + if err != nil { + return nil, err + } + if isOpt { + val := a.adapter.NativeToValue(obj) + if types.IsUnknown(val) { + return val, nil } + return types.OptionalOf(val), nil } - return op, true, nil + return obj, nil } // Attempt to resolve the qualified type name if the name is not a variable identifier. typ, found := a.provider.FindIdent(nm) if found { if len(a.qualifiers) == 0 { - return typ, true, nil + return typ, nil } - return nil, true, fmt.Errorf("no such attribute: %v", typ) } } - return nil, false, nil + var attrNames strings.Builder + for i, nm := range a.namespaceNames { + if i != 0 { + attrNames.WriteString(", ") + } + attrNames.WriteString(nm) + } + return nil, missingAttribute(attrNames.String()) } type conditionalAttribute struct { @@ -333,17 +331,19 @@ type conditionalAttribute struct { // ID is an implementation of the Attribute interface method. func (a *conditionalAttribute) ID() int64 { + // There's a field access after the conditional. + if a.truthy.ID() == a.falsy.ID() { + return a.truthy.ID() + } + // Otherwise return the conditional id as the consistent id being tracked. return a.id } -// Cost provides the heuristic cost of a ternary operation ? : . -// The cost is computed as cost(expr) plus the min/max costs of evaluating either -// `t` or `f`. -func (a *conditionalAttribute) Cost() (min, max int64) { - tMin, tMax := estimateCost(a.truthy) - fMin, fMax := estimateCost(a.falsy) - eMin, eMax := estimateCost(a.expr) - return eMin + findMin(tMin, fMin), eMax + findMax(tMax, fMax) +// IsOptional returns trivially false for an attribute as the attribute represents a fully +// qualified variable name. If the attribute is used in an optional manner, then an attrQualifier +// is created and marks the attribute as optional. +func (a *conditionalAttribute) IsOptional() bool { + return false } // AddQualifier appends the same qualifier to both sides of the conditional, in effect managing @@ -361,28 +361,18 @@ func (a *conditionalAttribute) AddQualifier(qual Qualifier) (Attribute, error) { } // Qualify is an implementation of the Qualifier interface method. -func (a *conditionalAttribute) Qualify(vars Activation, obj interface{}) (interface{}, error) { - val, err := a.Resolve(vars) - if err != nil { - return nil, err - } - unk, isUnk := val.(types.Unknown) - if isUnk { - return unk, nil - } - qual, err := a.fac.NewQualifier(nil, a.id, val) - if err != nil { - return nil, err - } - return qual.Qualify(vars, obj) +func (a *conditionalAttribute) Qualify(vars Activation, obj any) (any, error) { + return attrQualify(a.fac, vars, obj, a) +} + +// QualifyIfPresent is an implementation of the Qualifier interface method. +func (a *conditionalAttribute) QualifyIfPresent(vars Activation, obj any, presenceOnly bool) (any, bool, error) { + return attrQualifyIfPresent(a.fac, vars, obj, a, presenceOnly) } // Resolve evaluates the condition, and then resolves the truthy or falsy branch accordingly. -func (a *conditionalAttribute) Resolve(vars Activation) (interface{}, error) { +func (a *conditionalAttribute) Resolve(vars Activation) (any, error) { val := a.expr.Eval(vars) - if types.IsError(val) { - return nil, val.(*types.Err) - } if val == types.True { return a.truthy.Resolve(vars) } @@ -410,33 +400,14 @@ type maybeAttribute struct { // ID is an implementation of the Attribute interface method. func (a *maybeAttribute) ID() int64 { - return a.id + return a.attrs[0].ID() } -// Cost implements the Coster interface method. The min cost is computed as the minimal cost among -// all the possible attributes, the max cost ditto. -func (a *maybeAttribute) Cost() (min, max int64) { - min, max = math.MaxInt64, 0 - for _, a := range a.attrs { - minA, maxA := estimateCost(a) - min = findMin(min, minA) - max = findMax(max, maxA) - } - return -} - -func findMin(x, y int64) int64 { - if x < y { - return x - } - return y -} - -func findMax(x, y int64) int64 { - if x > y { - return x - } - return y +// IsOptional returns trivially false for an attribute as the attribute represents a fully +// qualified variable name. If the attribute is used in an optional manner, then an attrQualifier +// is created and marks the attribute as optional. +func (a *maybeAttribute) IsOptional() bool { + return false } // AddQualifier adds a qualifier to each possible attribute variant, and also creates @@ -446,21 +417,21 @@ func findMax(x, y int64) int64 { // // 1. Create a maybe attribute from a simple identifier when it occurs in a parsed-only expression // -// mb = MaybeAttribute(, "a") +// mb = MaybeAttribute(, "a") // -// Initializing the maybe attribute creates an absolute attribute internally which includes the -// possible namespaced names of the attribute. In this example, let's assume we are in namespace -// 'ns', then the maybe is either one of the following variable names: +// Initializing the maybe attribute creates an absolute attribute internally which includes the +// possible namespaced names of the attribute. In this example, let's assume we are in namespace +// 'ns', then the maybe is either one of the following variable names: // -// possible variables names -- ns.a, a +// possible variables names -- ns.a, a // // 2. Adding a qualifier to the maybe means that the variable name could be a longer qualified -// name, or a field selection on one of the possible variable names produced earlier: +// name, or a field selection on one of the possible variable names produced earlier: // -// mb.AddQualifier("b") +// mb.AddQualifier("b") // -// possible variables names -- ns.a.b, a.b -// possible field selection -- ns.a['b'], a['b'] +// possible variables names -- ns.a.b, a.b +// possible field selection -- ns.a['b'], a['b'] // // If none of the attributes within the maybe resolves a value, the result is an error. func (a *maybeAttribute) AddQualifier(qual Qualifier) (Attribute, error) { @@ -486,43 +457,49 @@ func (a *maybeAttribute) AddQualifier(qual Qualifier) (Attribute, error) { } } // Next, ensure the most specific variable / type reference is searched first. - a.attrs = append([]NamespacedAttribute{a.fac.AbsoluteAttribute(qual.ID(), augmentedNames...)}, a.attrs...) + if len(augmentedNames) != 0 { + a.attrs = append([]NamespacedAttribute{a.fac.AbsoluteAttribute(qual.ID(), augmentedNames...)}, a.attrs...) + } return a, nil } // Qualify is an implementation of the Qualifier interface method. -func (a *maybeAttribute) Qualify(vars Activation, obj interface{}) (interface{}, error) { - val, err := a.Resolve(vars) - if err != nil { - return nil, err - } - unk, isUnk := val.(types.Unknown) - if isUnk { - return unk, nil - } - qual, err := a.fac.NewQualifier(nil, a.id, val) - if err != nil { - return nil, err - } - return qual.Qualify(vars, obj) +func (a *maybeAttribute) Qualify(vars Activation, obj any) (any, error) { + return attrQualify(a.fac, vars, obj, a) +} + +// QualifyIfPresent is an implementation of the Qualifier interface method. +func (a *maybeAttribute) QualifyIfPresent(vars Activation, obj any, presenceOnly bool) (any, bool, error) { + return attrQualifyIfPresent(a.fac, vars, obj, a, presenceOnly) } // Resolve follows the variable resolution rules to determine whether the attribute is a variable // or a field selection. -func (a *maybeAttribute) Resolve(vars Activation) (interface{}, error) { +func (a *maybeAttribute) Resolve(vars Activation) (any, error) { + var maybeErr error for _, attr := range a.attrs { - obj, found, err := attr.TryResolve(vars) + obj, err := attr.Resolve(vars) // Return an error if one is encountered. if err != nil { - return nil, err - } - // If the object was found, return it. - if found { - return obj, nil + resErr, ok := err.(*resolutionError) + if !ok { + return nil, err + } + // If this was not a missing variable error, return it. + if !resErr.isMissingAttribute() { + return nil, err + } + // When the variable is missing in a maybe attribute we defer erroring. + if maybeErr == nil { + maybeErr = resErr + } + // Continue attempting to resolve possible variables. + continue } + return obj, nil } // Else, produce a no such attribute error. - return nil, fmt.Errorf("no such attribute: %v", a) + return nil, maybeErr } // String is an implementation of the Stringer interface method. @@ -540,18 +517,18 @@ type relativeAttribute struct { // ID is an implementation of the Attribute interface method. func (a *relativeAttribute) ID() int64 { - return a.id + qualCount := len(a.qualifiers) + if qualCount == 0 { + return a.id + } + return a.qualifiers[qualCount-1].ID() } -// Cost implements the Coster interface method. -func (a *relativeAttribute) Cost() (min, max int64) { - min, max = estimateCost(a.operand) - for _, qual := range a.qualifiers { - minQ, maxQ := estimateCost(qual) - min += minQ - max += maxQ - } - return +// IsOptional returns trivially false for an attribute as the attribute represents a fully +// qualified variable name. If the attribute is used in an optional manner, then an attrQualifier +// is created and marks the attribute as optional. +func (a *relativeAttribute) IsOptional() bool { + return false } // AddQualifier implements the Attribute interface method. @@ -561,24 +538,17 @@ func (a *relativeAttribute) AddQualifier(qual Qualifier) (Attribute, error) { } // Qualify is an implementation of the Qualifier interface method. -func (a *relativeAttribute) Qualify(vars Activation, obj interface{}) (interface{}, error) { - val, err := a.Resolve(vars) - if err != nil { - return nil, err - } - unk, isUnk := val.(types.Unknown) - if isUnk { - return unk, nil - } - qual, err := a.fac.NewQualifier(nil, a.id, val) - if err != nil { - return nil, err - } - return qual.Qualify(vars, obj) +func (a *relativeAttribute) Qualify(vars Activation, obj any) (any, error) { + return attrQualify(a.fac, vars, obj, a) +} + +// QualifyIfPresent is an implementation of the Qualifier interface method. +func (a *relativeAttribute) QualifyIfPresent(vars Activation, obj any, presenceOnly bool) (any, bool, error) { + return attrQualifyIfPresent(a.fac, vars, obj, a, presenceOnly) } // Resolve expression value and qualifier relative to the expression result. -func (a *relativeAttribute) Resolve(vars Activation) (interface{}, error) { +func (a *relativeAttribute) Resolve(vars Activation) (any, error) { // First, evaluate the operand. v := a.operand.Eval(vars) if types.IsError(v) { @@ -587,14 +557,16 @@ func (a *relativeAttribute) Resolve(vars Activation) (interface{}, error) { if types.IsUnknown(v) { return v, nil } - // Next, qualify it. Qualification handles unknowns as well, so there's no need to recheck. - var err error - var obj interface{} = v - for _, qual := range a.qualifiers { - obj, err = qual.Qualify(vars, obj) - if err != nil { - return nil, err + obj, isOpt, err := applyQualifiers(vars, v, a.qualifiers) + if err != nil { + return nil, err + } + if isOpt { + val := a.adapter.NativeToValue(obj) + if types.IsUnknown(val) { + return val, nil } + return types.OptionalOf(val), nil } return obj, nil } @@ -604,42 +576,93 @@ func (a *relativeAttribute) String() string { return fmt.Sprintf("id: %v, operand: %v", a.id, a.operand) } -func newQualifier(adapter ref.TypeAdapter, id int64, v interface{}) (Qualifier, error) { +func newQualifier(adapter ref.TypeAdapter, id int64, v any, opt bool) (Qualifier, error) { var qual Qualifier switch val := v.(type) { case Attribute: - return &attrQualifier{id: id, Attribute: val}, nil + // Note, attributes are initially identified as non-optional since they represent a top-level + // field access; however, when used as a relative qualifier, e.g. a[?b.c], then an attrQualifier + // is created which intercepts the IsOptional check for the attribute in order to return the + // correct result. + return &attrQualifier{ + id: id, + Attribute: val, + optional: opt, + }, nil case string: - qual = &stringQualifier{id: id, value: val, celValue: types.String(val), adapter: adapter} + qual = &stringQualifier{ + id: id, + value: val, + celValue: types.String(val), + adapter: adapter, + optional: opt, + } case int: - qual = &intQualifier{id: id, value: int64(val), celValue: types.Int(val), adapter: adapter} + qual = &intQualifier{ + id: id, value: int64(val), celValue: types.Int(val), adapter: adapter, optional: opt, + } case int32: - qual = &intQualifier{id: id, value: int64(val), celValue: types.Int(val), adapter: adapter} + qual = &intQualifier{ + id: id, value: int64(val), celValue: types.Int(val), adapter: adapter, optional: opt, + } case int64: - qual = &intQualifier{id: id, value: val, celValue: types.Int(val), adapter: adapter} + qual = &intQualifier{ + id: id, value: val, celValue: types.Int(val), adapter: adapter, optional: opt, + } case uint: - qual = &uintQualifier{id: id, value: uint64(val), celValue: types.Uint(val), adapter: adapter} + qual = &uintQualifier{ + id: id, value: uint64(val), celValue: types.Uint(val), adapter: adapter, optional: opt, + } case uint32: - qual = &uintQualifier{id: id, value: uint64(val), celValue: types.Uint(val), adapter: adapter} + qual = &uintQualifier{ + id: id, value: uint64(val), celValue: types.Uint(val), adapter: adapter, optional: opt, + } case uint64: - qual = &uintQualifier{id: id, value: val, celValue: types.Uint(val), adapter: adapter} + qual = &uintQualifier{ + id: id, value: val, celValue: types.Uint(val), adapter: adapter, optional: opt, + } case bool: - qual = &boolQualifier{id: id, value: val, celValue: types.Bool(val), adapter: adapter} + qual = &boolQualifier{ + id: id, value: val, celValue: types.Bool(val), adapter: adapter, optional: opt, + } case float32: - qual = &doubleQualifier{id: id, value: float64(val), celValue: types.Double(val), adapter: adapter} + qual = &doubleQualifier{ + id: id, + value: float64(val), + celValue: types.Double(val), + adapter: adapter, + optional: opt, + } case float64: - qual = &doubleQualifier{id: id, value: val, celValue: types.Double(val), adapter: adapter} + qual = &doubleQualifier{ + id: id, value: val, celValue: types.Double(val), adapter: adapter, optional: opt, + } case types.String: - qual = &stringQualifier{id: id, value: string(val), celValue: val, adapter: adapter} + qual = &stringQualifier{ + id: id, value: string(val), celValue: val, adapter: adapter, optional: opt, + } case types.Int: - qual = &intQualifier{id: id, value: int64(val), celValue: val, adapter: adapter} + qual = &intQualifier{ + id: id, value: int64(val), celValue: val, adapter: adapter, optional: opt, + } case types.Uint: - qual = &uintQualifier{id: id, value: uint64(val), celValue: val, adapter: adapter} + qual = &uintQualifier{ + id: id, value: uint64(val), celValue: val, adapter: adapter, optional: opt, + } case types.Bool: - qual = &boolQualifier{id: id, value: bool(val), celValue: val, adapter: adapter} + qual = &boolQualifier{ + id: id, value: bool(val), celValue: val, adapter: adapter, optional: opt, + } case types.Double: - qual = &doubleQualifier{id: id, value: float64(val), celValue: val, adapter: adapter} + qual = &doubleQualifier{ + id: id, value: float64(val), celValue: val, adapter: adapter, optional: opt, + } + case types.Unknown: + qual = &unknownQualifier{id: id, value: val} default: + if q, ok := v.(Qualifier); ok { + return q, nil + } return nil, fmt.Errorf("invalid qualifier type: %T", v) } return qual, nil @@ -648,15 +671,18 @@ func newQualifier(adapter ref.TypeAdapter, id int64, v interface{}) (Qualifier, type attrQualifier struct { id int64 Attribute + optional bool } +// ID implements the Qualifier interface method and returns the qualification instruction id +// rather than the attribute id. func (q *attrQualifier) ID() int64 { return q.id } -// Cost returns zero for constant field qualifiers -func (q *attrQualifier) Cost() (min, max int64) { - return estimateCost(q.Attribute) +// IsOptional implements the Qualifier interface method. +func (q *attrQualifier) IsOptional() bool { + return q.optional } type stringQualifier struct { @@ -664,6 +690,7 @@ type stringQualifier struct { value string celValue ref.Val adapter ref.TypeAdapter + optional bool } // ID is an implementation of the Qualifier interface method. @@ -671,58 +698,87 @@ func (q *stringQualifier) ID() int64 { return q.id } +// IsOptional implements the Qualifier interface method. +func (q *stringQualifier) IsOptional() bool { + return q.optional +} + // Qualify implements the Qualifier interface method. -func (q *stringQualifier) Qualify(vars Activation, obj interface{}) (interface{}, error) { +func (q *stringQualifier) Qualify(vars Activation, obj any) (any, error) { + val, _, err := q.qualifyInternal(vars, obj, false, false) + return val, err +} + +// QualifyIfPresent is an implementation of the Qualifier interface method. +func (q *stringQualifier) QualifyIfPresent(vars Activation, obj any, presenceOnly bool) (any, bool, error) { + return q.qualifyInternal(vars, obj, true, presenceOnly) +} + +func (q *stringQualifier) qualifyInternal(vars Activation, obj any, presenceTest, presenceOnly bool) (any, bool, error) { s := q.value - isMap := false - isKey := false switch o := obj.(type) { - case map[string]interface{}: - isMap = true - obj, isKey = o[s] + case map[string]any: + obj, isKey := o[s] + if isKey { + return obj, true, nil + } case map[string]string: - isMap = true - obj, isKey = o[s] + obj, isKey := o[s] + if isKey { + return obj, true, nil + } case map[string]int: - isMap = true - obj, isKey = o[s] + obj, isKey := o[s] + if isKey { + return obj, true, nil + } case map[string]int32: - isMap = true - obj, isKey = o[s] + obj, isKey := o[s] + if isKey { + return obj, true, nil + } case map[string]int64: - isMap = true - obj, isKey = o[s] + obj, isKey := o[s] + if isKey { + return obj, true, nil + } case map[string]uint: - isMap = true - obj, isKey = o[s] + obj, isKey := o[s] + if isKey { + return obj, true, nil + } case map[string]uint32: - isMap = true - obj, isKey = o[s] + obj, isKey := o[s] + if isKey { + return obj, true, nil + } case map[string]uint64: - isMap = true - obj, isKey = o[s] + obj, isKey := o[s] + if isKey { + return obj, true, nil + } case map[string]float32: - isMap = true - obj, isKey = o[s] + obj, isKey := o[s] + if isKey { + return obj, true, nil + } case map[string]float64: - isMap = true - obj, isKey = o[s] + obj, isKey := o[s] + if isKey { + return obj, true, nil + } case map[string]bool: - isMap = true - obj, isKey = o[s] - case types.Unknown: - return o, nil - default: - elem, err := refResolve(q.adapter, q.celValue, obj) - if err != nil { - return nil, err + obj, isKey := o[s] + if isKey { + return obj, true, nil } - return elem, nil + default: + return refQualify(q.adapter, obj, q.celValue, presenceTest, presenceOnly) } - if isMap && !isKey { - return nil, fmt.Errorf("no such key: %v", s) + if presenceTest { + return nil, false, nil } - return obj, nil + return nil, false, missingKey(q.celValue) } // Value implements the ConstantQualifier interface @@ -730,16 +786,12 @@ func (q *stringQualifier) Value() ref.Val { return q.celValue } -// Cost returns zero for constant field qualifiers -func (q *stringQualifier) Cost() (min, max int64) { - return 0, 0 -} - type intQualifier struct { id int64 value int64 celValue ref.Val adapter ref.TypeAdapter + optional bool } // ID is an implementation of the Qualifier interface method. @@ -747,97 +799,113 @@ func (q *intQualifier) ID() int64 { return q.id } +// IsOptional implements the Qualifier interface method. +func (q *intQualifier) IsOptional() bool { + return q.optional +} + // Qualify implements the Qualifier interface method. -func (q *intQualifier) Qualify(vars Activation, obj interface{}) (interface{}, error) { +func (q *intQualifier) Qualify(vars Activation, obj any) (any, error) { + val, _, err := q.qualifyInternal(vars, obj, false, false) + return val, err +} + +// QualifyIfPresent is an implementation of the Qualifier interface method. +func (q *intQualifier) QualifyIfPresent(vars Activation, obj any, presenceOnly bool) (any, bool, error) { + return q.qualifyInternal(vars, obj, true, presenceOnly) +} + +func (q *intQualifier) qualifyInternal(vars Activation, obj any, presenceTest, presenceOnly bool) (any, bool, error) { i := q.value - isMap := false - isKey := false - isIndex := false + var isMap bool switch o := obj.(type) { // The specialized map types supported by an int qualifier are considerably fewer than the set // of specialized map types supported by string qualifiers since they are less frequently used // than string-based map keys. Additional specializations may be added in the future if // desired. - case map[int]interface{}: + case map[int]any: isMap = true - obj, isKey = o[int(i)] - case map[int32]interface{}: + obj, isKey := o[int(i)] + if isKey { + return obj, true, nil + } + case map[int32]any: isMap = true - obj, isKey = o[int32(i)] - case map[int64]interface{}: + obj, isKey := o[int32(i)] + if isKey { + return obj, true, nil + } + case map[int64]any: isMap = true - obj, isKey = o[i] - case []interface{}: - isIndex = i >= 0 && i < int64(len(o)) + obj, isKey := o[i] + if isKey { + return obj, true, nil + } + case []any: + isIndex := i >= 0 && i < int64(len(o)) if isIndex { - obj = o[i] + return o[i], true, nil } case []string: - isIndex = i >= 0 && i < int64(len(o)) + isIndex := i >= 0 && i < int64(len(o)) if isIndex { - obj = o[i] + return o[i], true, nil } case []int: - isIndex = i >= 0 && i < int64(len(o)) + isIndex := i >= 0 && i < int64(len(o)) if isIndex { - obj = o[i] + return o[i], true, nil } case []int32: - isIndex = i >= 0 && i < int64(len(o)) + isIndex := i >= 0 && i < int64(len(o)) if isIndex { - obj = o[i] + return o[i], true, nil } case []int64: - isIndex = i >= 0 && i < int64(len(o)) + isIndex := i >= 0 && i < int64(len(o)) if isIndex { - obj = o[i] + return o[i], true, nil } case []uint: - isIndex = i >= 0 && i < int64(len(o)) + isIndex := i >= 0 && i < int64(len(o)) if isIndex { - obj = o[i] + return o[i], true, nil } case []uint32: - isIndex = i >= 0 && i < int64(len(o)) + isIndex := i >= 0 && i < int64(len(o)) if isIndex { - obj = o[i] + return o[i], true, nil } case []uint64: - isIndex = i >= 0 && i < int64(len(o)) + isIndex := i >= 0 && i < int64(len(o)) if isIndex { - obj = o[i] + return o[i], true, nil } case []float32: - isIndex = i >= 0 && i < int64(len(o)) + isIndex := i >= 0 && i < int64(len(o)) if isIndex { - obj = o[i] + return o[i], true, nil } case []float64: - isIndex = i >= 0 && i < int64(len(o)) + isIndex := i >= 0 && i < int64(len(o)) if isIndex { - obj = o[i] + return o[i], true, nil } case []bool: - isIndex = i >= 0 && i < int64(len(o)) + isIndex := i >= 0 && i < int64(len(o)) if isIndex { - obj = o[i] + return o[i], true, nil } - case types.Unknown: - return o, nil default: - elem, err := refResolve(q.adapter, q.celValue, obj) - if err != nil { - return nil, err - } - return elem, nil + return refQualify(q.adapter, obj, q.celValue, presenceTest, presenceOnly) } - if isMap && !isKey { - return nil, fmt.Errorf("no such key: %v", i) + if presenceTest { + return nil, false, nil } - if !isMap && !isIndex { - return nil, fmt.Errorf("index out of bounds: %v", i) + if isMap { + return nil, false, missingKey(q.celValue) } - return obj, nil + return nil, false, missingIndex(q.celValue) } // Value implements the ConstantQualifier interface @@ -845,16 +913,12 @@ func (q *intQualifier) Value() ref.Val { return q.celValue } -// Cost returns zero for constant field qualifiers -func (q *intQualifier) Cost() (min, max int64) { - return 0, 0 -} - type uintQualifier struct { id int64 value uint64 celValue ref.Val adapter ref.TypeAdapter + optional bool } // ID is an implementation of the Qualifier interface method. @@ -862,38 +926,51 @@ func (q *uintQualifier) ID() int64 { return q.id } +// IsOptional implements the Qualifier interface method. +func (q *uintQualifier) IsOptional() bool { + return q.optional +} + // Qualify implements the Qualifier interface method. -func (q *uintQualifier) Qualify(vars Activation, obj interface{}) (interface{}, error) { +func (q *uintQualifier) Qualify(vars Activation, obj any) (any, error) { + val, _, err := q.qualifyInternal(vars, obj, false, false) + return val, err +} + +// QualifyIfPresent is an implementation of the Qualifier interface method. +func (q *uintQualifier) QualifyIfPresent(vars Activation, obj any, presenceOnly bool) (any, bool, error) { + return q.qualifyInternal(vars, obj, true, presenceOnly) +} + +func (q *uintQualifier) qualifyInternal(vars Activation, obj any, presenceTest, presenceOnly bool) (any, bool, error) { u := q.value - isMap := false - isKey := false switch o := obj.(type) { // The specialized map types supported by a uint qualifier are considerably fewer than the set // of specialized map types supported by string qualifiers since they are less frequently used // than string-based map keys. Additional specializations may be added in the future if // desired. - case map[uint]interface{}: - isMap = true - obj, isKey = o[uint(u)] - case map[uint32]interface{}: - isMap = true - obj, isKey = o[uint32(u)] - case map[uint64]interface{}: - isMap = true - obj, isKey = o[u] - case types.Unknown: - return o, nil - default: - elem, err := refResolve(q.adapter, q.celValue, obj) - if err != nil { - return nil, err + case map[uint]any: + obj, isKey := o[uint(u)] + if isKey { + return obj, true, nil + } + case map[uint32]any: + obj, isKey := o[uint32(u)] + if isKey { + return obj, true, nil } - return elem, nil + case map[uint64]any: + obj, isKey := o[u] + if isKey { + return obj, true, nil + } + default: + return refQualify(q.adapter, obj, q.celValue, presenceTest, presenceOnly) } - if isMap && !isKey { - return nil, fmt.Errorf("no such key: %v", u) + if presenceTest { + return nil, false, nil } - return obj, nil + return nil, false, missingKey(q.celValue) } // Value implements the ConstantQualifier interface @@ -901,16 +978,12 @@ func (q *uintQualifier) Value() ref.Val { return q.celValue } -// Cost returns zero for constant field qualifiers -func (q *uintQualifier) Cost() (min, max int64) { - return 0, 0 -} - type boolQualifier struct { id int64 value bool celValue ref.Val adapter ref.TypeAdapter + optional bool } // ID is an implementation of the Qualifier interface method. @@ -918,30 +991,37 @@ func (q *boolQualifier) ID() int64 { return q.id } +// IsOptional implements the Qualifier interface method. +func (q *boolQualifier) IsOptional() bool { + return q.optional +} + // Qualify implements the Qualifier interface method. -func (q *boolQualifier) Qualify(vars Activation, obj interface{}) (interface{}, error) { +func (q *boolQualifier) Qualify(vars Activation, obj any) (any, error) { + val, _, err := q.qualifyInternal(vars, obj, false, false) + return val, err +} + +// QualifyIfPresent is an implementation of the Qualifier interface method. +func (q *boolQualifier) QualifyIfPresent(vars Activation, obj any, presenceOnly bool) (any, bool, error) { + return q.qualifyInternal(vars, obj, true, presenceOnly) +} + +func (q *boolQualifier) qualifyInternal(vars Activation, obj any, presenceTest, presenceOnly bool) (any, bool, error) { b := q.value - isKey := false switch o := obj.(type) { - // The specialized map types supported by a bool qualifier are considerably fewer than the set - // of specialized map types supported by string qualifiers since they are less frequently used - // than string-based map keys. Additional specializations may be added in the future if - // desired. - case map[bool]interface{}: - obj, isKey = o[b] - case types.Unknown: - return o, nil - default: - elem, err := refResolve(q.adapter, q.celValue, obj) - if err != nil { - return nil, err + case map[bool]any: + obj, isKey := o[b] + if isKey { + return obj, true, nil } - return elem, nil + default: + return refQualify(q.adapter, obj, q.celValue, presenceTest, presenceOnly) } - if !isKey { - return nil, fmt.Errorf("no such key: %v", b) + if presenceTest { + return nil, false, nil } - return obj, nil + return nil, false, missingKey(q.celValue) } // Value implements the ConstantQualifier interface @@ -949,11 +1029,6 @@ func (q *boolQualifier) Value() ref.Val { return q.celValue } -// Cost returns zero for constant field qualifiers -func (q *boolQualifier) Cost() (min, max int64) { - return 0, 0 -} - // fieldQualifier indicates that the qualification is a well-defined field with a known // field type. When the field type is known this can be used to improve the speed and // efficiency of field resolution. @@ -962,6 +1037,7 @@ type fieldQualifier struct { Name string FieldType *ref.FieldType adapter ref.TypeAdapter + optional bool } // ID is an implementation of the Qualifier interface method. @@ -969,12 +1045,39 @@ func (q *fieldQualifier) ID() int64 { return q.id } +// IsOptional implements the Qualifier interface method. +func (q *fieldQualifier) IsOptional() bool { + return q.optional +} + // Qualify implements the Qualifier interface method. -func (q *fieldQualifier) Qualify(vars Activation, obj interface{}) (interface{}, error) { +func (q *fieldQualifier) Qualify(vars Activation, obj any) (any, error) { if rv, ok := obj.(ref.Val); ok { obj = rv.Value() } - return q.FieldType.GetFrom(obj) + val, err := q.FieldType.GetFrom(obj) + if err != nil { + return nil, err + } + return val, nil +} + +// QualifyIfPresent is an implementation of the Qualifier interface method. +func (q *fieldQualifier) QualifyIfPresent(vars Activation, obj any, presenceOnly bool) (any, bool, error) { + if rv, ok := obj.(ref.Val); ok { + obj = rv.Value() + } + if !q.FieldType.IsSet(obj) { + return nil, false, nil + } + if presenceOnly { + return nil, true, nil + } + val, err := q.FieldType.GetFrom(obj) + if err != nil { + return nil, false, err + } + return val, true, nil } // Value implements the ConstantQualifier interface @@ -982,11 +1085,6 @@ func (q *fieldQualifier) Value() ref.Val { return types.String(q.Name) } -// Cost returns zero for constant field qualifiers -func (q *fieldQualifier) Cost() (min, max int64) { - return 0, 0 -} - // doubleQualifier qualifies a CEL object, map, or list using a double value. // // This qualifier is used for working with dynamic data like JSON or protobuf.Any where the value @@ -997,6 +1095,7 @@ type doubleQualifier struct { value float64 celValue ref.Val adapter ref.TypeAdapter + optional bool } // ID is an implementation of the Qualifier interface method. @@ -1004,48 +1103,237 @@ func (q *doubleQualifier) ID() int64 { return q.id } +// IsOptional implements the Qualifier interface method. +func (q *doubleQualifier) IsOptional() bool { + return q.optional +} + // Qualify implements the Qualifier interface method. -func (q *doubleQualifier) Qualify(vars Activation, obj interface{}) (interface{}, error) { - switch o := obj.(type) { - case types.Unknown: - return o, nil - default: - elem, err := refResolve(q.adapter, q.celValue, obj) - if err != nil { - return nil, err +func (q *doubleQualifier) Qualify(vars Activation, obj any) (any, error) { + val, _, err := q.qualifyInternal(vars, obj, false, false) + return val, err +} + +func (q *doubleQualifier) QualifyIfPresent(vars Activation, obj any, presenceOnly bool) (any, bool, error) { + return q.qualifyInternal(vars, obj, true, presenceOnly) +} + +func (q *doubleQualifier) qualifyInternal(vars Activation, obj any, presenceTest, presenceOnly bool) (any, bool, error) { + return refQualify(q.adapter, obj, q.celValue, presenceTest, presenceOnly) +} + +// Value implements the ConstantQualifier interface +func (q *doubleQualifier) Value() ref.Val { + return q.celValue +} + +// unknownQualifier is a simple qualifier which always returns a preconfigured set of unknown values +// for any value subject to qualification. This is consistent with CEL's unknown handling elsewhere. +type unknownQualifier struct { + id int64 + value types.Unknown +} + +// ID is an implementation of the Qualifier interface method. +func (q *unknownQualifier) ID() int64 { + return q.id +} + +// IsOptional returns trivially false as an the unknown value is always returned. +func (q *unknownQualifier) IsOptional() bool { + return false +} + +// Qualify returns the unknown value associated with this qualifier. +func (q *unknownQualifier) Qualify(vars Activation, obj any) (any, error) { + return q.value, nil +} + +// QualifyIfPresent is an implementation of the Qualifier interface method. +func (q *unknownQualifier) QualifyIfPresent(vars Activation, obj any, presenceOnly bool) (any, bool, error) { + return q.value, true, nil +} + +// Value implements the ConstantQualifier interface +func (q *unknownQualifier) Value() ref.Val { + return q.value +} + +func applyQualifiers(vars Activation, obj any, qualifiers []Qualifier) (any, bool, error) { + optObj, isOpt := obj.(*types.Optional) + if isOpt { + if !optObj.HasValue() { + return optObj, false, nil } - return elem, nil + obj = optObj.GetValue().Value() } + + var err error + for _, qual := range qualifiers { + var qualObj any + isOpt = isOpt || qual.IsOptional() + if isOpt { + var present bool + qualObj, present, err = qual.QualifyIfPresent(vars, obj, false) + if err != nil { + return nil, false, err + } + if !present { + // We return optional none here with a presence of 'false' as the layers + // above will attempt to call types.OptionalOf() on a present value if any + // of the qualifiers is optional. + return types.OptionalNone, false, nil + } + } else { + qualObj, err = qual.Qualify(vars, obj) + if err != nil { + return nil, false, err + } + } + obj = qualObj + } + return obj, isOpt, nil +} + +// attrQualify performs a qualification using the result of an attribute evaluation. +func attrQualify(fac AttributeFactory, vars Activation, obj any, qualAttr Attribute) (any, error) { + val, err := qualAttr.Resolve(vars) + if err != nil { + return nil, err + } + qual, err := fac.NewQualifier(nil, qualAttr.ID(), val, qualAttr.IsOptional()) + if err != nil { + return nil, err + } + return qual.Qualify(vars, obj) } -// refResolve attempts to convert the value to a CEL value and then uses reflection methods -// to try and resolve the qualifier. -func refResolve(adapter ref.TypeAdapter, idx ref.Val, obj interface{}) (ref.Val, error) { +// attrQualifyIfPresent conditionally performs the qualification of the result of attribute is present +// on the target object. +func attrQualifyIfPresent(fac AttributeFactory, vars Activation, obj any, qualAttr Attribute, + presenceOnly bool) (any, bool, error) { + val, err := qualAttr.Resolve(vars) + if err != nil { + return nil, false, err + } + qual, err := fac.NewQualifier(nil, qualAttr.ID(), val, qualAttr.IsOptional()) + if err != nil { + return nil, false, err + } + return qual.QualifyIfPresent(vars, obj, presenceOnly) +} + +// refQualify attempts to convert the value to a CEL value and then uses reflection methods to try and +// apply the qualifier with the option to presence test field accesses before retrieving field values. +func refQualify(adapter ref.TypeAdapter, obj any, idx ref.Val, presenceTest, presenceOnly bool) (ref.Val, bool, error) { celVal := adapter.NativeToValue(obj) - mapper, isMapper := celVal.(traits.Mapper) - if isMapper { - elem, found := mapper.Find(idx) - if !found { - return nil, fmt.Errorf("no such key: %v", idx) + switch v := celVal.(type) { + case types.Unknown: + return v, true, nil + case *types.Err: + return nil, false, v + case traits.Mapper: + val, found := v.Find(idx) + // If the index is of the wrong type for the map, then it is possible + // for the Find call to produce an error. + if types.IsError(val) { + return nil, false, val.(*types.Err) } - return elem, nil - } - indexer, isIndexer := celVal.(traits.Indexer) - if isIndexer { - elem := indexer.Get(idx) - if types.IsError(elem) { - return nil, elem.(*types.Err) + if found { + return val, true, nil + } + if presenceTest { + return nil, false, nil + } + return nil, false, missingKey(idx) + case traits.Lister: + // If the index argument is not a valid numeric type, then it is possible + // for the index operation to produce an error. + i, err := types.IndexOrError(idx) + if err != nil { + return nil, false, err + } + celIndex := types.Int(i) + if i >= 0 && celIndex < v.Size().(types.Int) { + return v.Get(idx), true, nil + } + if presenceTest { + return nil, false, nil + } + return nil, false, missingIndex(idx) + case traits.Indexer: + if presenceTest { + ft, ok := v.(traits.FieldTester) + if ok { + presence := ft.IsSet(idx) + if types.IsError(presence) { + return nil, false, presence.(*types.Err) + } + // If not found or presence only test, then return. + // Otherwise, if found, obtain the value later on. + if presenceOnly || presence == types.False { + return nil, presence == types.True, nil + } + } + } + val := v.Get(idx) + if types.IsError(val) { + return nil, false, val.(*types.Err) + } + return val, true, nil + default: + if presenceTest { + return nil, false, nil } - return elem, nil + return nil, false, missingKey(idx) } - if types.IsUnknown(celVal) { - return celVal, nil +} + +// resolutionError is a custom error type which encodes the different error states which may +// occur during attribute resolution. +type resolutionError struct { + missingAttribute string + missingIndex ref.Val + missingKey ref.Val +} + +func (e *resolutionError) isMissingAttribute() bool { + return e.missingAttribute != "" +} + +func missingIndex(missing ref.Val) *resolutionError { + return &resolutionError{ + missingIndex: missing, + } +} + +func missingKey(missing ref.Val) *resolutionError { + return &resolutionError{ + missingKey: missing, } - // TODO: If the types.Err value contains more than just an error message at some point in the - // future, then it would be reasonable to return error values as ref.Val types rather than - // simple go error types. - if types.IsError(celVal) { - return nil, celVal.(*types.Err) +} + +func missingAttribute(attr string) *resolutionError { + return &resolutionError{ + missingAttribute: attr, + } +} + +// Error implements the error interface method. +func (e *resolutionError) Error() string { + if e.missingKey != nil { + return fmt.Sprintf("no such key: %v", e.missingKey) } - return nil, fmt.Errorf("no such key: %v", idx) + if e.missingIndex != nil { + return fmt.Sprintf("index out of bounds: %v", e.missingIndex) + } + if e.missingAttribute != "" { + return fmt.Sprintf("no such attribute(s): %s", e.missingAttribute) + } + return "invalid attribute" +} + +// Is implements the errors.Is() method used by more recent versions of Go. +func (e *resolutionError) Is(err error) bool { + return err.Error() == e.Error() } diff --git a/vendor/github.com/google/cel-go/interpreter/coster.go b/vendor/github.com/google/cel-go/interpreter/coster.go deleted file mode 100644 index ac573d5745..0000000000 --- a/vendor/github.com/google/cel-go/interpreter/coster.go +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2020 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package interpreter - -import "math" - -// TODO: remove Coster. - -// Coster calculates the heuristic cost incurred during evaluation. -// Deprecated: Please migrate cel.EstimateCost, it supports length estimates for input data and cost estimates for -// extension functions. -type Coster interface { - Cost() (min, max int64) -} - -// estimateCost returns the heuristic cost interval for the program. -func estimateCost(i interface{}) (min, max int64) { - c, ok := i.(Coster) - if !ok { - return 0, math.MaxInt64 - } - return c.Cost() -} diff --git a/vendor/github.com/google/cel-go/interpreter/decorators.go b/vendor/github.com/google/cel-go/interpreter/decorators.go index bdbbad43e2..208487b7d3 100644 --- a/vendor/github.com/google/cel-go/interpreter/decorators.go +++ b/vendor/github.com/google/cel-go/interpreter/decorators.go @@ -29,7 +29,7 @@ type InterpretableDecorator func(Interpretable) (Interpretable, error) func decObserveEval(observer EvalObserver) InterpretableDecorator { return func(i Interpretable) (Interpretable, error) { switch inst := i.(type) { - case *evalWatch, *evalWatchAttr, *evalWatchConst: + case *evalWatch, *evalWatchAttr, *evalWatchConst, *evalWatchConstructor: // these instruction are already watching, return straight-away. return i, nil case InterpretableAttribute: @@ -42,6 +42,11 @@ func decObserveEval(observer EvalObserver) InterpretableDecorator { InterpretableConst: inst, observer: observer, }, nil + case InterpretableConstructor: + return &evalWatchConstructor{ + constructor: inst, + observer: observer, + }, nil default: return &evalWatch{ Interpretable: i, @@ -224,8 +229,8 @@ func maybeOptimizeSetMembership(i Interpretable, inlist InterpretableCall) (Inte valueSet := make(map[ref.Val]ref.Val) for it.HasNext() == types.True { elem := it.Next() - if !types.IsPrimitiveType(elem) { - // Note, non-primitive type are not yet supported. + if !types.IsPrimitiveType(elem) || elem.Type() == types.BytesType { + // Note, non-primitive type are not yet supported, and []byte isn't hashable. return i, nil } valueSet[elem] = types.True diff --git a/vendor/github.com/google/cel-go/interpreter/formatting.go b/vendor/github.com/google/cel-go/interpreter/formatting.go new file mode 100644 index 0000000000..6a98f6fa56 --- /dev/null +++ b/vendor/github.com/google/cel-go/interpreter/formatting.go @@ -0,0 +1,383 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package interpreter + +import ( + "errors" + "fmt" + "strconv" + "strings" + "unicode" + + "github.com/google/cel-go/common/types" + "github.com/google/cel-go/common/types/ref" +) + +type typeVerifier func(int64, ...*types.TypeValue) (bool, error) + +// InterpolateFormattedString checks the syntax and cardinality of any string.format calls present in the expression and reports +// any errors at compile time. +func InterpolateFormattedString(verifier typeVerifier) InterpretableDecorator { + return func(inter Interpretable) (Interpretable, error) { + call, ok := inter.(InterpretableCall) + if !ok { + return inter, nil + } + if call.OverloadID() != "string_format" { + return inter, nil + } + args := call.Args() + if len(args) != 2 { + return nil, fmt.Errorf("wrong number of arguments to string.format (expected 2, got %d)", len(args)) + } + fmtStrInter, ok := args[0].(InterpretableConst) + if !ok { + return inter, nil + } + var fmtArgsInter InterpretableConstructor + fmtArgsInter, ok = args[1].(InterpretableConstructor) + if !ok { + return inter, nil + } + if fmtArgsInter.Type() != types.ListType { + // don't necessarily return an error since the list may be DynType + return inter, nil + } + formatStr := fmtStrInter.Value().Value().(string) + initVals := fmtArgsInter.InitVals() + + formatCheck := &formatCheck{ + args: initVals, + verifier: verifier, + } + // use a placeholder locale, since locale doesn't affect syntax + _, err := ParseFormatString(formatStr, formatCheck, formatCheck, "en_US") + if err != nil { + return nil, err + } + seenArgs := formatCheck.argsRequested + if len(initVals) > seenArgs { + return nil, fmt.Errorf("too many arguments supplied to string.format (expected %d, got %d)", seenArgs, len(initVals)) + } + return inter, nil + } +} + +type formatCheck struct { + args []Interpretable + argsRequested int + curArgIndex int64 + enableCheckArgTypes bool + verifier typeVerifier +} + +func (c *formatCheck) String(arg ref.Val, locale string) (string, error) { + valid, err := verifyString(c.args[c.curArgIndex], c.verifier) + if err != nil { + return "", err + } + if !valid { + return "", errors.New("string clause can only be used on strings, bools, bytes, ints, doubles, maps, lists, types, durations, and timestamps") + } + return "", nil +} + +func (c *formatCheck) Decimal(arg ref.Val, locale string) (string, error) { + id := c.args[c.curArgIndex].ID() + valid, err := c.verifier(id, types.IntType, types.UintType) + if err != nil { + return "", err + } + if !valid { + return "", errors.New("integer clause can only be used on integers") + } + return "", nil +} + +func (c *formatCheck) Fixed(precision *int) func(ref.Val, string) (string, error) { + return func(arg ref.Val, locale string) (string, error) { + id := c.args[c.curArgIndex].ID() + // we allow StringType since "NaN", "Infinity", and "-Infinity" are also valid values + valid, err := c.verifier(id, types.DoubleType, types.StringType) + if err != nil { + return "", err + } + if !valid { + return "", errors.New("fixed-point clause can only be used on doubles") + } + return "", nil + } +} + +func (c *formatCheck) Scientific(precision *int) func(ref.Val, string) (string, error) { + return func(arg ref.Val, locale string) (string, error) { + id := c.args[c.curArgIndex].ID() + valid, err := c.verifier(id, types.DoubleType, types.StringType) + if err != nil { + return "", err + } + if !valid { + return "", errors.New("scientific clause can only be used on doubles") + } + return "", nil + } +} + +func (c *formatCheck) Binary(arg ref.Val, locale string) (string, error) { + id := c.args[c.curArgIndex].ID() + valid, err := c.verifier(id, types.IntType, types.UintType, types.BoolType) + if err != nil { + return "", err + } + if !valid { + return "", errors.New("only integers and bools can be formatted as binary") + } + return "", nil +} + +func (c *formatCheck) Hex(useUpper bool) func(ref.Val, string) (string, error) { + return func(arg ref.Val, locale string) (string, error) { + id := c.args[c.curArgIndex].ID() + valid, err := c.verifier(id, types.IntType, types.UintType, types.StringType, types.BytesType) + if err != nil { + return "", err + } + if !valid { + return "", errors.New("only integers, byte buffers, and strings can be formatted as hex") + } + return "", nil + } +} + +func (c *formatCheck) Octal(arg ref.Val, locale string) (string, error) { + id := c.args[c.curArgIndex].ID() + valid, err := c.verifier(id, types.IntType, types.UintType) + if err != nil { + return "", err + } + if !valid { + return "", errors.New("octal clause can only be used on integers") + } + return "", nil +} + +func (c *formatCheck) Arg(index int64) (ref.Val, error) { + c.argsRequested++ + c.curArgIndex = index + // return a dummy value - this is immediately passed to back to us + // through one of the FormatCallback functions, so anything will do + return types.Int(0), nil +} + +func (c *formatCheck) ArgSize() int64 { + return int64(len(c.args)) +} + +func verifyString(sub Interpretable, verifier typeVerifier) (bool, error) { + subVerified, err := verifier(sub.ID(), + types.ListType, types.MapType, types.IntType, types.UintType, types.DoubleType, + types.BoolType, types.StringType, types.TimestampType, types.BytesType, types.DurationType, types.TypeType, types.NullType) + if err != nil { + return false, err + } + if !subVerified { + return false, nil + } + con, ok := sub.(InterpretableConstructor) + if ok { + members := con.InitVals() + for _, m := range members { + // recursively verify if we're dealing with a list/map + verified, err := verifyString(m, verifier) + if err != nil { + return false, err + } + if !verified { + return false, nil + } + } + } + return true, nil + +} + +// FormatStringInterpolator is an interface that allows user-defined behavior +// for formatting clause implementations, as well as argument retrieval. +// Each function is expected to support the appropriate types as laid out in +// the string.format documentation, and to return an error if given an inappropriate type. +type FormatStringInterpolator interface { + // String takes a ref.Val and a string representing the current locale identifier + // and returns the Val formatted as a string, or an error if one occurred. + String(ref.Val, string) (string, error) + + // Decimal takes a ref.Val and a string representing the current locale identifier + // and returns the Val formatted as a decimal integer, or an error if one occurred. + Decimal(ref.Val, string) (string, error) + + // Fixed takes an int pointer representing precision (or nil if none was given) and + // returns a function operating in a similar manner to String and Decimal, taking a + // ref.Val and locale and returning the appropriate string. A closure is returned + // so precision can be set without needing an additional function call/configuration. + Fixed(*int) func(ref.Val, string) (string, error) + + // Scientific functions identically to Fixed, except the string returned from the closure + // is expected to be in scientific notation. + Scientific(*int) func(ref.Val, string) (string, error) + + // Binary takes a ref.Val and a string representing the current locale identifier + // and returns the Val formatted as a binary integer, or an error if one occurred. + Binary(ref.Val, string) (string, error) + + // Hex takes a boolean that, if true, indicates the hex string output by the returned + // closure should use uppercase letters for A-F. + Hex(bool) func(ref.Val, string) (string, error) + + // Octal takes a ref.Val and a string representing the current locale identifier and + // returns the Val formatted in octal, or an error if one occurred. + Octal(ref.Val, string) (string, error) +} + +// FormatList is an interface that allows user-defined list-like datatypes to be used +// for formatting clause implementations. +type FormatList interface { + // Arg returns the ref.Val at the given index, or an error if one occurred. + Arg(int64) (ref.Val, error) + // ArgSize returns the length of the argument list. + ArgSize() int64 +} + +type clauseImpl func(ref.Val, string) (string, error) + +// ParseFormatString formats a string according to the string.format syntax, taking the clause implementations +// from the provided FormatCallback and the args from the given FormatList. +func ParseFormatString(formatStr string, callback FormatStringInterpolator, list FormatList, locale string) (string, error) { + i := 0 + argIndex := 0 + var builtStr strings.Builder + for i < len(formatStr) { + if formatStr[i] == '%' { + if i+1 < len(formatStr) && formatStr[i+1] == '%' { + err := builtStr.WriteByte('%') + if err != nil { + return "", fmt.Errorf("error writing format string: %w", err) + } + i += 2 + continue + } else { + argAny, err := list.Arg(int64(argIndex)) + if err != nil { + return "", err + } + if i+1 >= len(formatStr) { + return "", errors.New("unexpected end of string") + } + if int64(argIndex) >= list.ArgSize() { + return "", fmt.Errorf("index %d out of range", argIndex) + } + numRead, val, refErr := parseAndFormatClause(formatStr[i:], argAny, callback, list, locale) + if refErr != nil { + return "", refErr + } + _, err = builtStr.WriteString(val) + if err != nil { + return "", fmt.Errorf("error writing format string: %w", err) + } + i += numRead + argIndex++ + } + } else { + err := builtStr.WriteByte(formatStr[i]) + if err != nil { + return "", fmt.Errorf("error writing format string: %w", err) + } + i++ + } + } + return builtStr.String(), nil +} + +// parseAndFormatClause parses the format clause at the start of the given string with val, and returns +// how many characters were consumed and the substituted string form of val, or an error if one occurred. +func parseAndFormatClause(formatStr string, val ref.Val, callback FormatStringInterpolator, list FormatList, locale string) (int, string, error) { + i := 1 + read, formatter, err := parseFormattingClause(formatStr[i:], callback) + i += read + if err != nil { + return -1, "", fmt.Errorf("could not parse formatting clause: %s", err) + } + + valStr, err := formatter(val, locale) + if err != nil { + return -1, "", fmt.Errorf("error during formatting: %s", err) + } + return i, valStr, nil +} + +func parseFormattingClause(formatStr string, callback FormatStringInterpolator) (int, clauseImpl, error) { + i := 0 + read, precision, err := parsePrecision(formatStr[i:]) + i += read + if err != nil { + return -1, nil, fmt.Errorf("error while parsing precision: %w", err) + } + r := rune(formatStr[i]) + i++ + switch r { + case 's': + return i, callback.String, nil + case 'd': + return i, callback.Decimal, nil + case 'f': + return i, callback.Fixed(precision), nil + case 'e': + return i, callback.Scientific(precision), nil + case 'b': + return i, callback.Binary, nil + case 'x', 'X': + return i, callback.Hex(unicode.IsUpper(r)), nil + case 'o': + return i, callback.Octal, nil + default: + return -1, nil, fmt.Errorf("unrecognized formatting clause \"%c\"", r) + } +} + +func parsePrecision(formatStr string) (int, *int, error) { + i := 0 + if formatStr[i] != '.' { + return i, nil, nil + } + i++ + var buffer strings.Builder + for { + if i >= len(formatStr) { + return -1, nil, errors.New("could not find end of precision specifier") + } + if !isASCIIDigit(rune(formatStr[i])) { + break + } + buffer.WriteByte(formatStr[i]) + i++ + } + precision, err := strconv.Atoi(buffer.String()) + if err != nil { + return -1, nil, fmt.Errorf("error while converting precision to integer: %w", err) + } + return i, &precision, nil +} + +func isASCIIDigit(r rune) bool { + return r <= unicode.MaxASCII && unicode.IsDigit(r) +} diff --git a/vendor/github.com/google/cel-go/interpreter/functions/functions.go b/vendor/github.com/google/cel-go/interpreter/functions/functions.go index dd1e9ddd5f..9816017522 100644 --- a/vendor/github.com/google/cel-go/interpreter/functions/functions.go +++ b/vendor/github.com/google/cel-go/interpreter/functions/functions.go @@ -58,5 +58,5 @@ type UnaryOp func(value ref.Val) ref.Val type BinaryOp func(lhs ref.Val, rhs ref.Val) ref.Val // FunctionOp is a function with accepts zero or more arguments and produces -// an value (as interface{}) or error as a result. +// a value or error as a result. type FunctionOp func(values ...ref.Val) ref.Val diff --git a/vendor/github.com/google/cel-go/interpreter/interpretable.go b/vendor/github.com/google/cel-go/interpreter/interpretable.go index 4fdd12028b..7d67a92b67 100644 --- a/vendor/github.com/google/cel-go/interpreter/interpretable.go +++ b/vendor/github.com/google/cel-go/interpreter/interpretable.go @@ -15,7 +15,7 @@ package interpreter import ( - "math" + "fmt" "github.com/google/cel-go/common/operators" "github.com/google/cel-go/common/overloads" @@ -64,10 +64,18 @@ type InterpretableAttribute interface { // Qualify replicates the Attribute.Qualify method to permit extension and interception // of object qualification. - Qualify(vars Activation, obj interface{}) (interface{}, error) + Qualify(vars Activation, obj any) (any, error) + + // QualifyIfPresent qualifies the object if the qualifier is declared or defined on the object. + // The 'presenceOnly' flag indicates that the value is not necessary, just a boolean status as + // to whether the qualifier is present. + QualifyIfPresent(vars Activation, obj any, presenceOnly bool) (any, bool, error) + + // IsOptional indicates whether the resulting value is an optional type. + IsOptional() bool // Resolve returns the value of the Attribute given the current Activation. - Resolve(Activation) (interface{}, error) + Resolve(Activation) (any, error) } // InterpretableCall interface for inspecting Interpretable instructions related to function calls. @@ -103,10 +111,8 @@ type InterpretableConstructor interface { // Core Interpretable implementations used during the program planning phase. type evalTestOnly struct { - id int64 - op Interpretable - field types.String - fieldType *ref.FieldType + id int64 + InterpretableAttribute } // ID implements the Interpretable interface method. @@ -116,44 +122,58 @@ func (test *evalTestOnly) ID() int64 { // Eval implements the Interpretable interface method. func (test *evalTestOnly) Eval(ctx Activation) ref.Val { - // Handle field selection on a proto in the most efficient way possible. - if test.fieldType != nil { - opAttr, ok := test.op.(InterpretableAttribute) - if ok { - opVal, err := opAttr.Resolve(ctx) - if err != nil { - return types.NewErr(err.Error()) - } - refVal, ok := opVal.(ref.Val) - if ok { - opVal = refVal.Value() - } - if test.fieldType.IsSet(opVal) { - return types.True - } - return types.False - } + val, err := test.Resolve(ctx) + // Return an error if the resolve step fails + if err != nil { + return types.WrapErr(err) } + if optVal, isOpt := val.(*types.Optional); isOpt { + return types.Bool(optVal.HasValue()) + } + return test.Adapter().NativeToValue(val) +} + +// AddQualifier appends a qualifier that will always and only perform a presence test. +func (test *evalTestOnly) AddQualifier(q Qualifier) (Attribute, error) { + cq, ok := q.(ConstantQualifier) + if !ok { + return nil, fmt.Errorf("test only expressions must have constant qualifiers: %v", q) + } + return test.InterpretableAttribute.AddQualifier(&testOnlyQualifier{ConstantQualifier: cq}) +} + +type testOnlyQualifier struct { + ConstantQualifier +} - obj := test.op.Eval(ctx) - tester, ok := obj.(traits.FieldTester) - if ok { - return tester.IsSet(test.field) +// Qualify determines whether the test-only qualifier is present on the input object. +func (q *testOnlyQualifier) Qualify(vars Activation, obj any) (any, error) { + out, present, err := q.ConstantQualifier.QualifyIfPresent(vars, obj, true) + if err != nil { + return nil, err + } + if unk, isUnk := out.(types.Unknown); isUnk { + return unk, nil } - container, ok := obj.(traits.Container) - if ok { - return container.Contains(test.field) + if opt, isOpt := out.(types.Optional); isOpt { + return opt.HasValue(), nil } - return types.ValOrErr(obj, "invalid type for field selection.") + return present, nil +} + +// QualifyIfPresent returns whether the target field in the test-only expression is present. +// +// This method should never be called as the has() macro and optional syntax are incompatible +// when used on the same field. +func (q *testOnlyQualifier) QualifyIfPresent(vars Activation, obj any, presenceOnly bool) (any, bool, error) { + // Only ever test for presence. + return q.ConstantQualifier.QualifyIfPresent(vars, obj, true) } -// Cost provides the heuristic cost of a `has(field)` macro. The cost has at least 1 for determining -// if the field exists, apart from the cost of accessing the field. -func (test *evalTestOnly) Cost() (min, max int64) { - min, max = estimateCost(test.op) - min++ - max++ - return +// QualifierValueEquals determines whether the test-only constant qualifier equals the input value. +func (q *testOnlyQualifier) QualifierValueEquals(value any) bool { + // The input qualifier will always be of type string + return q.ConstantQualifier.Value().Value() == value } // NewConstValue creates a new constant valued Interpretable. @@ -179,11 +199,6 @@ func (cons *evalConst) Eval(ctx Activation) ref.Val { return cons.val } -// Cost returns zero for a constant valued Interpretable. -func (cons *evalConst) Cost() (min, max int64) { - return 0, 0 -} - // Value implements the InterpretableConst interface method. func (cons *evalConst) Value() ref.Val { return cons.val @@ -233,12 +248,6 @@ func (or *evalOr) Eval(ctx Activation) ref.Val { return types.ValOrErr(rVal, "no such overload") } -// Cost implements the Coster interface method. The minimum possible cost incurs when the left-hand -// side expr is sufficient in determining the evaluation result. -func (or *evalOr) Cost() (min, max int64) { - return calShortCircuitBinaryOpsCost(or.lhs, or.rhs) -} - type evalAnd struct { id int64 lhs Interpretable @@ -283,18 +292,6 @@ func (and *evalAnd) Eval(ctx Activation) ref.Val { return types.ValOrErr(rVal, "no such overload") } -// Cost implements the Coster interface method. The minimum possible cost incurs when the left-hand -// side expr is sufficient in determining the evaluation result. -func (and *evalAnd) Cost() (min, max int64) { - return calShortCircuitBinaryOpsCost(and.lhs, and.rhs) -} - -func calShortCircuitBinaryOpsCost(lhs, rhs Interpretable) (min, max int64) { - lMin, lMax := estimateCost(lhs) - _, rMax := estimateCost(rhs) - return lMin, lMax + rMax + 1 -} - type evalEq struct { id int64 lhs Interpretable @@ -319,11 +316,6 @@ func (eq *evalEq) Eval(ctx Activation) ref.Val { return types.Equal(lVal, rVal) } -// Cost implements the Coster interface method. -func (eq *evalEq) Cost() (min, max int64) { - return calExhaustiveBinaryOpsCost(eq.lhs, eq.rhs) -} - // Function implements the InterpretableCall interface method. func (*evalEq) Function() string { return operators.Equals @@ -363,11 +355,6 @@ func (ne *evalNe) Eval(ctx Activation) ref.Val { return types.Bool(types.Equal(lVal, rVal) != types.True) } -// Cost implements the Coster interface method. -func (ne *evalNe) Cost() (min, max int64) { - return calExhaustiveBinaryOpsCost(ne.lhs, ne.rhs) -} - // Function implements the InterpretableCall interface method. func (*evalNe) Function() string { return operators.NotEquals @@ -400,11 +387,6 @@ func (zero *evalZeroArity) Eval(ctx Activation) ref.Val { return zero.impl() } -// Cost returns 1 representing the heuristic cost of the function. -func (zero *evalZeroArity) Cost() (min, max int64) { - return 1, 1 -} - // Function implements the InterpretableCall interface method. func (zero *evalZeroArity) Function() string { return zero.function @@ -456,14 +438,6 @@ func (un *evalUnary) Eval(ctx Activation) ref.Val { return types.NewErr("no such overload: %s", un.function) } -// Cost implements the Coster interface method. -func (un *evalUnary) Cost() (min, max int64) { - min, max = estimateCost(un.arg) - min++ // add cost for function - max++ - return -} - // Function implements the InterpretableCall interface method. func (un *evalUnary) Function() string { return un.function @@ -522,11 +496,6 @@ func (bin *evalBinary) Eval(ctx Activation) ref.Val { return types.NewErr("no such overload: %s", bin.function) } -// Cost implements the Coster interface method. -func (bin *evalBinary) Cost() (min, max int64) { - return calExhaustiveBinaryOpsCost(bin.lhs, bin.rhs) -} - // Function implements the InterpretableCall interface method. func (bin *evalBinary) Function() string { return bin.function @@ -593,14 +562,6 @@ func (fn *evalVarArgs) Eval(ctx Activation) ref.Val { return types.NewErr("no such overload: %s", fn.function) } -// Cost implements the Coster interface method. -func (fn *evalVarArgs) Cost() (min, max int64) { - min, max = sumOfCost(fn.args) - min++ // add cost for function - max++ - return -} - // Function implements the InterpretableCall interface method. func (fn *evalVarArgs) Function() string { return fn.function @@ -617,9 +578,11 @@ func (fn *evalVarArgs) Args() []Interpretable { } type evalList struct { - id int64 - elems []Interpretable - adapter ref.TypeAdapter + id int64 + elems []Interpretable + optionals []bool + hasOptionals bool + adapter ref.TypeAdapter } // ID implements the Interpretable interface method. @@ -629,14 +592,24 @@ func (l *evalList) ID() int64 { // Eval implements the Interpretable interface method. func (l *evalList) Eval(ctx Activation) ref.Val { - elemVals := make([]ref.Val, len(l.elems)) + elemVals := make([]ref.Val, 0, len(l.elems)) // If any argument is unknown or error early terminate. for i, elem := range l.elems { elemVal := elem.Eval(ctx) if types.IsUnknownOrError(elemVal) { return elemVal } - elemVals[i] = elemVal + if l.hasOptionals && l.optionals[i] { + optVal, ok := elemVal.(*types.Optional) + if !ok { + return invalidOptionalElementInit(elemVal) + } + if !optVal.HasValue() { + continue + } + elemVal = optVal.GetValue() + } + elemVals = append(elemVals, elemVal) } return l.adapter.NativeToValue(elemVals) } @@ -649,16 +622,13 @@ func (l *evalList) Type() ref.Type { return types.ListType } -// Cost implements the Coster interface method. -func (l *evalList) Cost() (min, max int64) { - return sumOfCost(l.elems) -} - type evalMap struct { - id int64 - keys []Interpretable - vals []Interpretable - adapter ref.TypeAdapter + id int64 + keys []Interpretable + vals []Interpretable + optionals []bool + hasOptionals bool + adapter ref.TypeAdapter } // ID implements the Interpretable interface method. @@ -679,6 +649,17 @@ func (m *evalMap) Eval(ctx Activation) ref.Val { if types.IsUnknownOrError(valVal) { return valVal } + if m.hasOptionals && m.optionals[i] { + optVal, ok := valVal.(*types.Optional) + if !ok { + return invalidOptionalEntryInit(keyVal, valVal) + } + if !optVal.HasValue() { + delete(entries, keyVal) + continue + } + valVal = optVal.GetValue() + } entries[keyVal] = valVal } return m.adapter.NativeToValue(entries) @@ -704,19 +685,14 @@ func (m *evalMap) Type() ref.Type { return types.MapType } -// Cost implements the Coster interface method. -func (m *evalMap) Cost() (min, max int64) { - kMin, kMax := sumOfCost(m.keys) - vMin, vMax := sumOfCost(m.vals) - return kMin + vMin, kMax + vMax -} - type evalObj struct { - id int64 - typeName string - fields []string - vals []Interpretable - provider ref.TypeProvider + id int64 + typeName string + fields []string + vals []Interpretable + optionals []bool + hasOptionals bool + provider ref.TypeProvider } // ID implements the Interpretable interface method. @@ -733,6 +709,17 @@ func (o *evalObj) Eval(ctx Activation) ref.Val { if types.IsUnknownOrError(val) { return val } + if o.hasOptionals && o.optionals[i] { + optVal, ok := val.(*types.Optional) + if !ok { + return invalidOptionalEntryInit(field, val) + } + if !optVal.HasValue() { + delete(fieldVals, field) + continue + } + val = optVal.GetValue() + } fieldVals[field] = val } return o.provider.NewValue(o.typeName, fieldVals) @@ -746,21 +733,6 @@ func (o *evalObj) Type() ref.Type { return types.NewObjectTypeValue(o.typeName) } -// Cost implements the Coster interface method. -func (o *evalObj) Cost() (min, max int64) { - return sumOfCost(o.vals) -} - -func sumOfCost(interps []Interpretable) (min, max int64) { - min, max = 0, 0 - for _, in := range interps { - minT, maxT := estimateCost(in) - min += minT - max += maxT - } - return -} - type evalFold struct { id int64 accuVar string @@ -842,38 +814,6 @@ func (fold *evalFold) Eval(ctx Activation) ref.Val { return res } -// Cost implements the Coster interface method. -func (fold *evalFold) Cost() (min, max int64) { - // Compute the cost for evaluating iterRange. - iMin, iMax := estimateCost(fold.iterRange) - - // Compute the size of iterRange. If the size depends on the input, return the maximum possible - // cost range. - foldRange := fold.iterRange.Eval(EmptyActivation()) - if !foldRange.Type().HasTrait(traits.IterableType) { - return 0, math.MaxInt64 - } - var rangeCnt int64 - it := foldRange.(traits.Iterable).Iterator() - for it.HasNext() == types.True { - it.Next() - rangeCnt++ - } - aMin, aMax := estimateCost(fold.accu) - cMin, cMax := estimateCost(fold.cond) - sMin, sMax := estimateCost(fold.step) - rMin, rMax := estimateCost(fold.result) - if fold.exhaustive { - cMin = cMin * rangeCnt - sMin = sMin * rangeCnt - } - - // The cond and step costs are multiplied by size(iterRange). The minimum possible cost incurs - // when the evaluation result can be determined by the first iteration. - return iMin + aMin + cMin + sMin + rMin, - iMax + aMax + cMax*rangeCnt + sMax*rangeCnt + rMax -} - // Optional Interpretable implementations that specialize, subsume, or extend the core evaluation // plan via decorators. @@ -893,17 +833,15 @@ func (e *evalSetMembership) ID() int64 { // Eval implements the Interpretable interface method. func (e *evalSetMembership) Eval(ctx Activation) ref.Val { val := e.arg.Eval(ctx) + if types.IsUnknownOrError(val) { + return val + } if ret, found := e.valueSet[val]; found { return ret } return types.False } -// Cost implements the Coster interface method. -func (e *evalSetMembership) Cost() (min, max int64) { - return estimateCost(e.arg) -} - // evalWatch is an Interpretable implementation that wraps the execution of a given // expression so that it may observe the computed value and send it to an observer. type evalWatch struct { @@ -918,15 +856,10 @@ func (e *evalWatch) Eval(ctx Activation) ref.Val { return val } -// Cost implements the Coster interface method. -func (e *evalWatch) Cost() (min, max int64) { - return estimateCost(e.Interpretable) -} - -// evalWatchAttr describes a watcher of an instAttr Interpretable. +// evalWatchAttr describes a watcher of an InterpretableAttribute Interpretable. // // Since the watcher may be selected against at a later stage in program planning, the watcher -// must implement the instAttr interface by proxy. +// must implement the InterpretableAttribute interface by proxy. type evalWatchAttr struct { InterpretableAttribute observer EvalObserver @@ -953,11 +886,6 @@ func (e *evalWatchAttr) AddQualifier(q Qualifier) (Attribute, error) { return e, err } -// Cost implements the Coster interface method. -func (e *evalWatchAttr) Cost() (min, max int64) { - return estimateCost(e.InterpretableAttribute) -} - // Eval implements the Interpretable interface method. func (e *evalWatchAttr) Eval(vars Activation) ref.Val { val := e.InterpretableAttribute.Eval(vars) @@ -973,17 +901,12 @@ type evalWatchConstQual struct { adapter ref.TypeAdapter } -// Cost implements the Coster interface method. -func (e *evalWatchConstQual) Cost() (min, max int64) { - return estimateCost(e.ConstantQualifier) -} - // Qualify observes the qualification of a object via a constant boolean, int, string, or uint. -func (e *evalWatchConstQual) Qualify(vars Activation, obj interface{}) (interface{}, error) { +func (e *evalWatchConstQual) Qualify(vars Activation, obj any) (any, error) { out, err := e.ConstantQualifier.Qualify(vars, obj) var val ref.Val if err != nil { - val = types.NewErr(err.Error()) + val = types.WrapErr(err) } else { val = e.adapter.NativeToValue(out) } @@ -991,8 +914,25 @@ func (e *evalWatchConstQual) Qualify(vars Activation, obj interface{}) (interfac return out, err } +// QualifyIfPresent conditionally qualifies the variable and only records a value if one is present. +func (e *evalWatchConstQual) QualifyIfPresent(vars Activation, obj any, presenceOnly bool) (any, bool, error) { + out, present, err := e.ConstantQualifier.QualifyIfPresent(vars, obj, presenceOnly) + var val ref.Val + if err != nil { + val = types.WrapErr(err) + } else if out != nil { + val = e.adapter.NativeToValue(out) + } else if out == nil && presenceOnly { + val = types.Bool(present) + } + if present || presenceOnly { + e.observer(e.ID(), e.ConstantQualifier, val) + } + return out, present, err +} + // QualifierValueEquals tests whether the incoming value is equal to the qualifying constant. -func (e *evalWatchConstQual) QualifierValueEquals(value interface{}) bool { +func (e *evalWatchConstQual) QualifierValueEquals(value any) bool { qve, ok := e.ConstantQualifier.(qualifierValueEquator) return ok && qve.QualifierValueEquals(value) } @@ -1004,17 +944,12 @@ type evalWatchQual struct { adapter ref.TypeAdapter } -// Cost implements the Coster interface method. -func (e *evalWatchQual) Cost() (min, max int64) { - return estimateCost(e.Qualifier) -} - // Qualify observes the qualification of a object via a value computed at runtime. -func (e *evalWatchQual) Qualify(vars Activation, obj interface{}) (interface{}, error) { +func (e *evalWatchQual) Qualify(vars Activation, obj any) (any, error) { out, err := e.Qualifier.Qualify(vars, obj) var val ref.Val if err != nil { - val = types.NewErr(err.Error()) + val = types.WrapErr(err) } else { val = e.adapter.NativeToValue(out) } @@ -1022,6 +957,23 @@ func (e *evalWatchQual) Qualify(vars Activation, obj interface{}) (interface{}, return out, err } +// QualifyIfPresent conditionally qualifies the variable and only records a value if one is present. +func (e *evalWatchQual) QualifyIfPresent(vars Activation, obj any, presenceOnly bool) (any, bool, error) { + out, present, err := e.Qualifier.QualifyIfPresent(vars, obj, presenceOnly) + var val ref.Val + if err != nil { + val = types.WrapErr(err) + } else if out != nil { + val = e.adapter.NativeToValue(out) + } else if out == nil && presenceOnly { + val = types.Bool(present) + } + if present || presenceOnly { + e.observer(e.ID(), e.Qualifier, val) + } + return out, present, err +} + // evalWatchConst describes a watcher of an instConst Interpretable. type evalWatchConst struct { InterpretableConst @@ -1035,11 +987,6 @@ func (e *evalWatchConst) Eval(vars Activation) ref.Val { return val } -// Cost implements the Coster interface method. -func (e *evalWatchConst) Cost() (min, max int64) { - return estimateCost(e.InterpretableConst) -} - // evalExhaustiveOr is just like evalOr, but does not short-circuit argument evaluation. type evalExhaustiveOr struct { id int64 @@ -1078,12 +1025,7 @@ func (or *evalExhaustiveOr) Eval(ctx Activation) ref.Val { if types.IsError(lVal) { return lVal } - return types.ValOrErr(rVal, "no such overload") -} - -// Cost implements the Coster interface method. -func (or *evalExhaustiveOr) Cost() (min, max int64) { - return calExhaustiveBinaryOpsCost(or.lhs, or.rhs) + return types.MaybeNoSuchOverloadErr(rVal) } // evalExhaustiveAnd is just like evalAnd, but does not short-circuit argument evaluation. @@ -1124,18 +1066,7 @@ func (and *evalExhaustiveAnd) Eval(ctx Activation) ref.Val { if types.IsError(lVal) { return lVal } - return types.ValOrErr(rVal, "no such overload") -} - -// Cost implements the Coster interface method. -func (and *evalExhaustiveAnd) Cost() (min, max int64) { - return calExhaustiveBinaryOpsCost(and.lhs, and.rhs) -} - -func calExhaustiveBinaryOpsCost(lhs, rhs Interpretable) (min, max int64) { - lMin, lMax := estimateCost(lhs) - rMin, rMax := estimateCost(rhs) - return lMin + rMin + 1, lMax + rMax + 1 + return types.MaybeNoSuchOverloadErr(rVal) } // evalExhaustiveConditional is like evalConditional, but does not short-circuit argument @@ -1154,77 +1085,114 @@ func (cond *evalExhaustiveConditional) ID() int64 { // Eval implements the Interpretable interface method. func (cond *evalExhaustiveConditional) Eval(ctx Activation) ref.Val { cVal := cond.attr.expr.Eval(ctx) - tVal, err := cond.attr.truthy.Resolve(ctx) - if err != nil { - return types.NewErr(err.Error()) - } - fVal, err := cond.attr.falsy.Resolve(ctx) - if err != nil { - return types.NewErr(err.Error()) - } + tVal, tErr := cond.attr.truthy.Resolve(ctx) + fVal, fErr := cond.attr.falsy.Resolve(ctx) cBool, ok := cVal.(types.Bool) if !ok { return types.ValOrErr(cVal, "no such overload") } if cBool { + if tErr != nil { + return types.WrapErr(tErr) + } return cond.adapter.NativeToValue(tVal) } + if fErr != nil { + return types.WrapErr(fErr) + } return cond.adapter.NativeToValue(fVal) } -// Cost implements the Coster interface method. -func (cond *evalExhaustiveConditional) Cost() (min, max int64) { - return cond.attr.Cost() -} - // evalAttr evaluates an Attribute value. type evalAttr struct { - adapter ref.TypeAdapter - attr Attribute + adapter ref.TypeAdapter + attr Attribute + optional bool } +var _ InterpretableAttribute = &evalAttr{} + // ID of the attribute instruction. func (a *evalAttr) ID() int64 { return a.attr.ID() } -// AddQualifier implements the instAttr interface method. +// AddQualifier implements the InterpretableAttribute interface method. func (a *evalAttr) AddQualifier(qual Qualifier) (Attribute, error) { attr, err := a.attr.AddQualifier(qual) a.attr = attr return attr, err } -// Attr implements the instAttr interface method. +// Attr implements the InterpretableAttribute interface method. func (a *evalAttr) Attr() Attribute { return a.attr } -// Adapter implements the instAttr interface method. +// Adapter implements the InterpretableAttribute interface method. func (a *evalAttr) Adapter() ref.TypeAdapter { return a.adapter } -// Cost implements the Coster interface method. -func (a *evalAttr) Cost() (min, max int64) { - return estimateCost(a.attr) -} - // Eval implements the Interpretable interface method. func (a *evalAttr) Eval(ctx Activation) ref.Val { v, err := a.attr.Resolve(ctx) if err != nil { - return types.NewErr(err.Error()) + return types.WrapErr(err) } return a.adapter.NativeToValue(v) } // Qualify proxies to the Attribute's Qualify method. -func (a *evalAttr) Qualify(ctx Activation, obj interface{}) (interface{}, error) { +func (a *evalAttr) Qualify(ctx Activation, obj any) (any, error) { return a.attr.Qualify(ctx, obj) } +// QualifyIfPresent proxies to the Attribute's QualifyIfPresent method. +func (a *evalAttr) QualifyIfPresent(ctx Activation, obj any, presenceOnly bool) (any, bool, error) { + return a.attr.QualifyIfPresent(ctx, obj, presenceOnly) +} + +func (a *evalAttr) IsOptional() bool { + return a.optional +} + // Resolve proxies to the Attribute's Resolve method. -func (a *evalAttr) Resolve(ctx Activation) (interface{}, error) { +func (a *evalAttr) Resolve(ctx Activation) (any, error) { return a.attr.Resolve(ctx) } + +type evalWatchConstructor struct { + constructor InterpretableConstructor + observer EvalObserver +} + +// InitVals implements the InterpretableConstructor InitVals function. +func (c *evalWatchConstructor) InitVals() []Interpretable { + return c.constructor.InitVals() +} + +// Type implements the InterpretableConstructor Type function. +func (c *evalWatchConstructor) Type() ref.Type { + return c.constructor.Type() +} + +// ID implements the Interpretable ID function. +func (c *evalWatchConstructor) ID() int64 { + return c.constructor.ID() +} + +// Eval implements the Interpretable Eval function. +func (c *evalWatchConstructor) Eval(ctx Activation) ref.Val { + val := c.constructor.Eval(ctx) + c.observer(c.ID(), c.constructor, val) + return val +} + +func invalidOptionalEntryInit(field any, value ref.Val) ref.Val { + return types.NewErr("cannot initialize optional entry '%v' from non-optional value %v", field, value) +} + +func invalidOptionalElementInit(value ref.Val) ref.Val { + return types.NewErr("cannot initialize optional list element from non-optional value %v", value) +} diff --git a/vendor/github.com/google/cel-go/interpreter/interpreter.go b/vendor/github.com/google/cel-go/interpreter/interpreter.go index b3fd14f8b3..707a6105a1 100644 --- a/vendor/github.com/google/cel-go/interpreter/interpreter.go +++ b/vendor/github.com/google/cel-go/interpreter/interpreter.go @@ -29,19 +29,17 @@ import ( type Interpreter interface { // NewInterpretable creates an Interpretable from a checked expression and an // optional list of InterpretableDecorator values. - NewInterpretable(checked *exprpb.CheckedExpr, - decorators ...InterpretableDecorator) (Interpretable, error) + NewInterpretable(checked *exprpb.CheckedExpr, decorators ...InterpretableDecorator) (Interpretable, error) // NewUncheckedInterpretable returns an Interpretable from a parsed expression // and an optional list of InterpretableDecorator values. - NewUncheckedInterpretable(expr *exprpb.Expr, - decorators ...InterpretableDecorator) (Interpretable, error) + NewUncheckedInterpretable(expr *exprpb.Expr, decorators ...InterpretableDecorator) (Interpretable, error) } // EvalObserver is a functional interface that accepts an expression id and an observed value. // The id identifies the expression that was evaluated, the programStep is the Interpretable or Qualifier that // was evaluated and value is the result of the evaluation. -type EvalObserver func(id int64, programStep interface{}, value ref.Val) +type EvalObserver func(id int64, programStep any, value ref.Val) // Observe constructs a decorator that calls all the provided observers in order after evaluating each Interpretable // or Qualifier during program evaluation. @@ -49,7 +47,7 @@ func Observe(observers ...EvalObserver) InterpretableDecorator { if len(observers) == 1 { return decObserveEval(observers[0]) } - observeFn := func(id int64, programStep interface{}, val ref.Val) { + observeFn := func(id int64, programStep any, val ref.Val) { for _, observer := range observers { observer(id, programStep, val) } @@ -96,7 +94,7 @@ func TrackState(state EvalState) InterpretableDecorator { // This decorator is not thread-safe, and the EvalState must be reset between Eval() // calls. func EvalStateObserver(state EvalState) EvalObserver { - return func(id int64, programStep interface{}, val ref.Val) { + return func(id int64, programStep any, val ref.Val) { state.SetValue(id, val) } } diff --git a/vendor/github.com/google/cel-go/interpreter/planner.go b/vendor/github.com/google/cel-go/interpreter/planner.go index 882e0419a5..0b65d0fa90 100644 --- a/vendor/github.com/google/cel-go/interpreter/planner.go +++ b/vendor/github.com/google/cel-go/interpreter/planner.go @@ -20,7 +20,6 @@ import ( "github.com/google/cel-go/common/containers" "github.com/google/cel-go/common/operators" - "github.com/google/cel-go/common/types" "github.com/google/cel-go/common/types/ref" "github.com/google/cel-go/interpreter/functions" @@ -189,16 +188,7 @@ func (p *planner) planSelect(expr *exprpb.Expr) (Interpretable, error) { if err != nil { return nil, err } - - // Determine the field type if this is a proto message type. - var fieldType *ref.FieldType opType := p.typeMap[sel.GetOperand().GetId()] - if opType.GetMessageType() != "" { - ft, found := p.provider.FindFieldType(opType.GetMessageType(), sel.GetField()) - if found && ft.IsSet != nil && ft.GetFrom != nil { - fieldType = ft - } - } // If the Select was marked TestOnly, this is a presence test. // @@ -211,37 +201,31 @@ func (p *planner) planSelect(expr *exprpb.Expr) (Interpretable, error) { // If a string named 'a.b.c' is declared in the environment and referenced within `has(a.b.c)`, // it is not clear whether has should error or follow the convention defined for structured // values. - if sel.TestOnly { - // Return the test only eval expression. - return &evalTestOnly{ - id: expr.GetId(), - field: types.String(sel.GetField()), - fieldType: fieldType, - op: op, - }, nil - } - // Build a qualifier. - qual, err := p.attrFactory.NewQualifier( - opType, expr.GetId(), sel.GetField()) - if err != nil { - return nil, err - } - // Lastly, create a field selection Interpretable. + + // Establish the attribute reference. attr, isAttr := op.(InterpretableAttribute) - if isAttr { - _, err = attr.AddQualifier(qual) - return attr, err + if !isAttr { + attr, err = p.relativeAttr(op.ID(), op, false) + if err != nil { + return nil, err + } } - relAttr, err := p.relativeAttr(op.ID(), op) + // Build a qualifier for the attribute. + qual, err := p.attrFactory.NewQualifier(opType, expr.GetId(), sel.GetField(), false) if err != nil { return nil, err } - _, err = relAttr.AddQualifier(qual) - if err != nil { - return nil, err + // Modify the attribute to be test-only. + if sel.GetTestOnly() { + attr = &evalTestOnly{ + id: expr.GetId(), + InterpretableAttribute: attr, + } } - return relAttr, nil + // Append the qualifier on the attribute. + _, err = attr.AddQualifier(qual) + return attr, err } // planCall creates a callable Interpretable while specializing for common functions and invocation @@ -286,7 +270,9 @@ func (p *planner) planCall(expr *exprpb.Expr) (Interpretable, error) { case operators.NotEquals: return p.planCallNotEqual(expr, args) case operators.Index: - return p.planCallIndex(expr, args) + return p.planCallIndex(expr, args, false) + case operators.OptSelect, operators.OptIndex: + return p.planCallIndex(expr, args, true) } // Otherwise, generate Interpretable calls specialized by argument count. @@ -423,8 +409,7 @@ func (p *planner) planCallVarArgs(expr *exprpb.Expr, } // planCallEqual generates an equals (==) Interpretable. -func (p *planner) planCallEqual(expr *exprpb.Expr, - args []Interpretable) (Interpretable, error) { +func (p *planner) planCallEqual(expr *exprpb.Expr, args []Interpretable) (Interpretable, error) { return &evalEq{ id: expr.GetId(), lhs: args[0], @@ -433,8 +418,7 @@ func (p *planner) planCallEqual(expr *exprpb.Expr, } // planCallNotEqual generates a not equals (!=) Interpretable. -func (p *planner) planCallNotEqual(expr *exprpb.Expr, - args []Interpretable) (Interpretable, error) { +func (p *planner) planCallNotEqual(expr *exprpb.Expr, args []Interpretable) (Interpretable, error) { return &evalNe{ id: expr.GetId(), lhs: args[0], @@ -443,8 +427,7 @@ func (p *planner) planCallNotEqual(expr *exprpb.Expr, } // planCallLogicalAnd generates a logical and (&&) Interpretable. -func (p *planner) planCallLogicalAnd(expr *exprpb.Expr, - args []Interpretable) (Interpretable, error) { +func (p *planner) planCallLogicalAnd(expr *exprpb.Expr, args []Interpretable) (Interpretable, error) { return &evalAnd{ id: expr.GetId(), lhs: args[0], @@ -453,8 +436,7 @@ func (p *planner) planCallLogicalAnd(expr *exprpb.Expr, } // planCallLogicalOr generates a logical or (||) Interpretable. -func (p *planner) planCallLogicalOr(expr *exprpb.Expr, - args []Interpretable) (Interpretable, error) { +func (p *planner) planCallLogicalOr(expr *exprpb.Expr, args []Interpretable) (Interpretable, error) { return &evalOr{ id: expr.GetId(), lhs: args[0], @@ -463,10 +445,8 @@ func (p *planner) planCallLogicalOr(expr *exprpb.Expr, } // planCallConditional generates a conditional / ternary (c ? t : f) Interpretable. -func (p *planner) planCallConditional(expr *exprpb.Expr, - args []Interpretable) (Interpretable, error) { +func (p *planner) planCallConditional(expr *exprpb.Expr, args []Interpretable) (Interpretable, error) { cond := args[0] - t := args[1] var tAttr Attribute truthyAttr, isTruthyAttr := t.(InterpretableAttribute) @@ -493,48 +473,54 @@ func (p *planner) planCallConditional(expr *exprpb.Expr, // planCallIndex either extends an attribute with the argument to the index operation, or creates // a relative attribute based on the return of a function call or operation. -func (p *planner) planCallIndex(expr *exprpb.Expr, - args []Interpretable) (Interpretable, error) { +func (p *planner) planCallIndex(expr *exprpb.Expr, args []Interpretable, optional bool) (Interpretable, error) { op := args[0] ind := args[1] - opAttr, err := p.relativeAttr(op.ID(), op) - if err != nil { - return nil, err - } opType := p.typeMap[expr.GetCallExpr().GetTarget().GetId()] - indConst, isIndConst := ind.(InterpretableConst) - if isIndConst { - qual, err := p.attrFactory.NewQualifier( - opType, expr.GetId(), indConst.Value()) + + // Establish the attribute reference. + var err error + attr, isAttr := op.(InterpretableAttribute) + if !isAttr { + attr, err = p.relativeAttr(op.ID(), op, false) if err != nil { return nil, err } - _, err = opAttr.AddQualifier(qual) - return opAttr, err } - indAttr, isIndAttr := ind.(InterpretableAttribute) - if isIndAttr { - qual, err := p.attrFactory.NewQualifier( - opType, expr.GetId(), indAttr) - if err != nil { - return nil, err - } - _, err = opAttr.AddQualifier(qual) - return opAttr, err + + // Construct the qualifier type. + var qual Qualifier + switch ind := ind.(type) { + case InterpretableConst: + qual, err = p.attrFactory.NewQualifier(opType, expr.GetId(), ind.Value(), optional) + case InterpretableAttribute: + qual, err = p.attrFactory.NewQualifier(opType, expr.GetId(), ind, optional) + default: + qual, err = p.relativeAttr(expr.GetId(), ind, optional) } - indQual, err := p.relativeAttr(expr.GetId(), ind) if err != nil { return nil, err } - _, err = opAttr.AddQualifier(indQual) - return opAttr, err + + // Add the qualifier to the attribute + _, err = attr.AddQualifier(qual) + return attr, err } // planCreateList generates a list construction Interpretable. func (p *planner) planCreateList(expr *exprpb.Expr) (Interpretable, error) { list := expr.GetListExpr() - elems := make([]Interpretable, len(list.GetElements())) - for i, elem := range list.GetElements() { + optionalIndices := list.GetOptionalIndices() + elements := list.GetElements() + optionals := make([]bool, len(elements)) + for _, index := range optionalIndices { + if index < 0 || index >= int32(len(elements)) { + return nil, fmt.Errorf("optional index %d out of element bounds [0, %d]", index, len(elements)) + } + optionals[index] = true + } + elems := make([]Interpretable, len(elements)) + for i, elem := range elements { elemVal, err := p.Plan(elem) if err != nil { return nil, err @@ -542,9 +528,11 @@ func (p *planner) planCreateList(expr *exprpb.Expr) (Interpretable, error) { elems[i] = elemVal } return &evalList{ - id: expr.GetId(), - elems: elems, - adapter: p.adapter, + id: expr.GetId(), + elems: elems, + optionals: optionals, + hasOptionals: len(optionals) != 0, + adapter: p.adapter, }, nil } @@ -555,6 +543,7 @@ func (p *planner) planCreateStruct(expr *exprpb.Expr) (Interpretable, error) { return p.planCreateObj(expr) } entries := str.GetEntries() + optionals := make([]bool, len(entries)) keys := make([]Interpretable, len(entries)) vals := make([]Interpretable, len(entries)) for i, entry := range entries { @@ -569,23 +558,27 @@ func (p *planner) planCreateStruct(expr *exprpb.Expr) (Interpretable, error) { return nil, err } vals[i] = valVal + optionals[i] = entry.GetOptionalEntry() } return &evalMap{ - id: expr.GetId(), - keys: keys, - vals: vals, - adapter: p.adapter, + id: expr.GetId(), + keys: keys, + vals: vals, + optionals: optionals, + hasOptionals: len(optionals) != 0, + adapter: p.adapter, }, nil } // planCreateObj generates an object construction Interpretable. func (p *planner) planCreateObj(expr *exprpb.Expr) (Interpretable, error) { obj := expr.GetStructExpr() - typeName, defined := p.resolveTypeName(obj.MessageName) + typeName, defined := p.resolveTypeName(obj.GetMessageName()) if !defined { - return nil, fmt.Errorf("unknown type: %s", typeName) + return nil, fmt.Errorf("unknown type: %s", obj.GetMessageName()) } entries := obj.GetEntries() + optionals := make([]bool, len(entries)) fields := make([]string, len(entries)) vals := make([]Interpretable, len(entries)) for i, entry := range entries { @@ -595,13 +588,16 @@ func (p *planner) planCreateObj(expr *exprpb.Expr) (Interpretable, error) { return nil, err } vals[i] = val + optionals[i] = entry.GetOptionalEntry() } return &evalObj{ - id: expr.GetId(), - typeName: typeName, - fields: fields, - vals: vals, - provider: p.provider, + id: expr.GetId(), + typeName: typeName, + fields: fields, + vals: vals, + optionals: optionals, + hasOptionals: len(optionals) != 0, + provider: p.provider, }, nil } @@ -753,14 +749,18 @@ func (p *planner) resolveFunction(expr *exprpb.Expr) (*exprpb.Expr, string, stri return target, fnName, "" } -func (p *planner) relativeAttr(id int64, eval Interpretable) (InterpretableAttribute, error) { +// relativeAttr indicates that the attribute in this case acts as a qualifier and as such needs to +// be observed to ensure that it's evaluation value is properly recorded for state tracking. +func (p *planner) relativeAttr(id int64, eval Interpretable, opt bool) (InterpretableAttribute, error) { eAttr, ok := eval.(InterpretableAttribute) if !ok { eAttr = &evalAttr{ - adapter: p.adapter, - attr: p.attrFactory.RelativeAttribute(id, eval), + adapter: p.adapter, + attr: p.attrFactory.RelativeAttribute(id, eval), + optional: opt, } } + // This looks like it should either decorate the new evalAttr node, or early return the InterpretableAttribute decAttr, err := p.decorate(eAttr, nil) if err != nil { return nil, err diff --git a/vendor/github.com/google/cel-go/interpreter/prune.go b/vendor/github.com/google/cel-go/interpreter/prune.go index eab46e0c06..d1b5d6bd6b 100644 --- a/vendor/github.com/google/cel-go/interpreter/prune.go +++ b/vendor/github.com/google/cel-go/interpreter/prune.go @@ -16,6 +16,7 @@ package interpreter import ( "github.com/google/cel-go/common/operators" + "github.com/google/cel-go/common/overloads" "github.com/google/cel-go/common/types" "github.com/google/cel-go/common/types/ref" "github.com/google/cel-go/common/types/traits" @@ -26,6 +27,7 @@ import ( type astPruner struct { expr *exprpb.Expr + macroCalls map[int64]*exprpb.Expr state EvalState nextExprID int64 } @@ -65,13 +67,22 @@ type astPruner struct { // compiled and constant folded expressions, but is not willing to constant // fold(and thus cache results of) some external calls, then they can prepare // the overloads accordingly. -func PruneAst(expr *exprpb.Expr, state EvalState) *exprpb.Expr { +func PruneAst(expr *exprpb.Expr, macroCalls map[int64]*exprpb.Expr, state EvalState) *exprpb.ParsedExpr { + pruneState := NewEvalState() + for _, id := range state.IDs() { + v, _ := state.Value(id) + pruneState.SetValue(id, v) + } pruner := &astPruner{ expr: expr, - state: state, - nextExprID: 1} - newExpr, _ := pruner.prune(expr) - return newExpr + macroCalls: macroCalls, + state: pruneState, + nextExprID: getMaxID(expr)} + newExpr, _ := pruner.maybePrune(expr) + return &exprpb.ParsedExpr{ + Expr: newExpr, + SourceInfo: &exprpb.SourceInfo{MacroCalls: pruner.macroCalls}, + } } func (p *astPruner) createLiteral(id int64, val *exprpb.Constant) *exprpb.Expr { @@ -84,28 +95,50 @@ func (p *astPruner) createLiteral(id int64, val *exprpb.Constant) *exprpb.Expr { } func (p *astPruner) maybeCreateLiteral(id int64, val ref.Val) (*exprpb.Expr, bool) { - switch val.Type() { - case types.BoolType: + switch v := val.(type) { + case types.Bool: + p.state.SetValue(id, val) return p.createLiteral(id, - &exprpb.Constant{ConstantKind: &exprpb.Constant_BoolValue{BoolValue: val.Value().(bool)}}), true - case types.IntType: + &exprpb.Constant{ConstantKind: &exprpb.Constant_BoolValue{BoolValue: bool(v)}}), true + case types.Bytes: + p.state.SetValue(id, val) return p.createLiteral(id, - &exprpb.Constant{ConstantKind: &exprpb.Constant_Int64Value{Int64Value: val.Value().(int64)}}), true - case types.UintType: + &exprpb.Constant{ConstantKind: &exprpb.Constant_BytesValue{BytesValue: []byte(v)}}), true + case types.Double: + p.state.SetValue(id, val) return p.createLiteral(id, - &exprpb.Constant{ConstantKind: &exprpb.Constant_Uint64Value{Uint64Value: val.Value().(uint64)}}), true - case types.StringType: + &exprpb.Constant{ConstantKind: &exprpb.Constant_DoubleValue{DoubleValue: float64(v)}}), true + case types.Duration: + p.state.SetValue(id, val) + durationString := string(v.ConvertToType(types.StringType).(types.String)) + return &exprpb.Expr{ + Id: id, + ExprKind: &exprpb.Expr_CallExpr{ + CallExpr: &exprpb.Expr_Call{ + Function: overloads.TypeConvertDuration, + Args: []*exprpb.Expr{ + p.createLiteral(p.nextID(), + &exprpb.Constant{ConstantKind: &exprpb.Constant_StringValue{StringValue: durationString}}), + }, + }, + }, + }, true + case types.Int: + p.state.SetValue(id, val) return p.createLiteral(id, - &exprpb.Constant{ConstantKind: &exprpb.Constant_StringValue{StringValue: val.Value().(string)}}), true - case types.DoubleType: + &exprpb.Constant{ConstantKind: &exprpb.Constant_Int64Value{Int64Value: int64(v)}}), true + case types.Uint: + p.state.SetValue(id, val) return p.createLiteral(id, - &exprpb.Constant{ConstantKind: &exprpb.Constant_DoubleValue{DoubleValue: val.Value().(float64)}}), true - case types.BytesType: + &exprpb.Constant{ConstantKind: &exprpb.Constant_Uint64Value{Uint64Value: uint64(v)}}), true + case types.String: + p.state.SetValue(id, val) return p.createLiteral(id, - &exprpb.Constant{ConstantKind: &exprpb.Constant_BytesValue{BytesValue: val.Value().([]byte)}}), true - case types.NullType: + &exprpb.Constant{ConstantKind: &exprpb.Constant_StringValue{StringValue: string(v)}}), true + case types.Null: + p.state.SetValue(id, val) return p.createLiteral(id, - &exprpb.Constant{ConstantKind: &exprpb.Constant_NullValue{NullValue: val.Value().(structpb.NullValue)}}), true + &exprpb.Constant{ConstantKind: &exprpb.Constant_NullValue{NullValue: v.Value().(structpb.NullValue)}}), true } // Attempt to build a list literal. @@ -123,6 +156,7 @@ func (p *astPruner) maybeCreateLiteral(id int64, val ref.Val) (*exprpb.Expr, boo } elemExprs[i] = elemExpr } + p.state.SetValue(id, val) return &exprpb.Expr{ Id: id, ExprKind: &exprpb.Expr_ListExpr{ @@ -162,6 +196,7 @@ func (p *astPruner) maybeCreateLiteral(id int64, val ref.Val) (*exprpb.Expr, boo entries[i] = entry i++ } + p.state.SetValue(id, val) return &exprpb.Expr{ Id: id, ExprKind: &exprpb.Expr_StructExpr{ @@ -177,70 +212,147 @@ func (p *astPruner) maybeCreateLiteral(id int64, val ref.Val) (*exprpb.Expr, boo return nil, false } -func (p *astPruner) maybePruneAndOr(node *exprpb.Expr) (*exprpb.Expr, bool) { - if !p.existsWithUnknownValue(node.GetId()) { +func (p *astPruner) maybePruneOptional(elem *exprpb.Expr) (*exprpb.Expr, bool) { + elemVal, found := p.value(elem.GetId()) + if found && elemVal.Type() == types.OptionalType { + opt := elemVal.(*types.Optional) + if !opt.HasValue() { + return nil, true + } + if newElem, pruned := p.maybeCreateLiteral(elem.GetId(), opt.GetValue()); pruned { + return newElem, true + } + } + return elem, false +} + +func (p *astPruner) maybePruneIn(node *exprpb.Expr) (*exprpb.Expr, bool) { + // elem in list + call := node.GetCallExpr() + val, exists := p.maybeValue(call.GetArgs()[1].GetId()) + if !exists { return nil, false } + if sz, ok := val.(traits.Sizer); ok && sz.Size() == types.IntZero { + return p.maybeCreateLiteral(node.GetId(), types.False) + } + return nil, false +} +func (p *astPruner) maybePruneLogicalNot(node *exprpb.Expr) (*exprpb.Expr, bool) { + call := node.GetCallExpr() + arg := call.GetArgs()[0] + val, exists := p.maybeValue(arg.GetId()) + if !exists { + return nil, false + } + if b, ok := val.(types.Bool); ok { + return p.maybeCreateLiteral(node.GetId(), !b) + } + return nil, false +} + +func (p *astPruner) maybePruneOr(node *exprpb.Expr) (*exprpb.Expr, bool) { call := node.GetCallExpr() // We know result is unknown, so we have at least one unknown arg // and if one side is a known value, we know we can ignore it. - if p.existsWithKnownValue(call.Args[0].GetId()) { - return call.Args[1], true + if v, exists := p.maybeValue(call.GetArgs()[0].GetId()); exists { + if v == types.True { + return p.maybeCreateLiteral(node.GetId(), types.True) + } + return call.GetArgs()[1], true } - if p.existsWithKnownValue(call.Args[1].GetId()) { - return call.Args[0], true + if v, exists := p.maybeValue(call.GetArgs()[1].GetId()); exists { + if v == types.True { + return p.maybeCreateLiteral(node.GetId(), types.True) + } + return call.GetArgs()[0], true } return nil, false } -func (p *astPruner) maybePruneConditional(node *exprpb.Expr) (*exprpb.Expr, bool) { - if !p.existsWithUnknownValue(node.GetId()) { - return nil, false +func (p *astPruner) maybePruneAnd(node *exprpb.Expr) (*exprpb.Expr, bool) { + call := node.GetCallExpr() + // We know result is unknown, so we have at least one unknown arg + // and if one side is a known value, we know we can ignore it. + if v, exists := p.maybeValue(call.GetArgs()[0].GetId()); exists { + if v == types.False { + return p.maybeCreateLiteral(node.GetId(), types.False) + } + return call.GetArgs()[1], true + } + if v, exists := p.maybeValue(call.GetArgs()[1].GetId()); exists { + if v == types.False { + return p.maybeCreateLiteral(node.GetId(), types.False) + } + return call.GetArgs()[0], true } + return nil, false +} +func (p *astPruner) maybePruneConditional(node *exprpb.Expr) (*exprpb.Expr, bool) { call := node.GetCallExpr() - condVal, condValueExists := p.value(call.Args[0].GetId()) - if !condValueExists || types.IsUnknownOrError(condVal) { + cond, exists := p.maybeValue(call.GetArgs()[0].GetId()) + if !exists { return nil, false } - - if condVal.Value().(bool) { - return call.Args[1], true + if cond.Value().(bool) { + return call.GetArgs()[1], true } - return call.Args[2], true + return call.GetArgs()[2], true } func (p *astPruner) maybePruneFunction(node *exprpb.Expr) (*exprpb.Expr, bool) { + if _, exists := p.value(node.GetId()); !exists { + return nil, false + } call := node.GetCallExpr() - if call.Function == operators.LogicalOr || call.Function == operators.LogicalAnd { - return p.maybePruneAndOr(node) + if call.Function == operators.LogicalOr { + return p.maybePruneOr(node) + } + if call.Function == operators.LogicalAnd { + return p.maybePruneAnd(node) } if call.Function == operators.Conditional { return p.maybePruneConditional(node) } - + if call.Function == operators.In { + return p.maybePruneIn(node) + } + if call.Function == operators.LogicalNot { + return p.maybePruneLogicalNot(node) + } return nil, false } +func (p *astPruner) maybePrune(node *exprpb.Expr) (*exprpb.Expr, bool) { + return p.prune(node) +} + func (p *astPruner) prune(node *exprpb.Expr) (*exprpb.Expr, bool) { if node == nil { return node, false } - val, valueExists := p.value(node.GetId()) - if valueExists && !types.IsUnknownOrError(val) { + val, valueExists := p.maybeValue(node.GetId()) + if valueExists { if newNode, ok := p.maybeCreateLiteral(node.GetId(), val); ok { + delete(p.macroCalls, node.GetId()) return newNode, true } } + if macro, found := p.macroCalls[node.GetId()]; found { + // prune the expression in terms of the macro call instead of the expanded form. + if newMacro, pruned := p.prune(macro); pruned { + p.macroCalls[node.GetId()] = newMacro + } + } // We have either an unknown/error value, or something we don't want to // transform, or expression was not evaluated. If possible, drill down // more. - switch node.GetExprKind().(type) { case *exprpb.Expr_SelectExpr: - if operand, pruned := p.prune(node.GetSelectExpr().GetOperand()); pruned { + if operand, pruned := p.maybePrune(node.GetSelectExpr().GetOperand()); pruned { return &exprpb.Expr{ Id: node.GetId(), ExprKind: &exprpb.Expr_SelectExpr{ @@ -253,10 +365,6 @@ func (p *astPruner) prune(node *exprpb.Expr) (*exprpb.Expr, bool) { }, true } case *exprpb.Expr_CallExpr: - if newExpr, pruned := p.maybePruneFunction(node); pruned { - newExpr, _ = p.prune(newExpr) - return newExpr, true - } var prunedCall bool call := node.GetCallExpr() args := call.GetArgs() @@ -268,40 +376,75 @@ func (p *astPruner) prune(node *exprpb.Expr) (*exprpb.Expr, bool) { } for i, arg := range args { newArgs[i] = arg - if newArg, prunedArg := p.prune(arg); prunedArg { + if newArg, prunedArg := p.maybePrune(arg); prunedArg { prunedCall = true newArgs[i] = newArg } } - if newTarget, prunedTarget := p.prune(call.GetTarget()); prunedTarget { + if newTarget, prunedTarget := p.maybePrune(call.GetTarget()); prunedTarget { prunedCall = true newCall.Target = newTarget } + newNode := &exprpb.Expr{ + Id: node.GetId(), + ExprKind: &exprpb.Expr_CallExpr{ + CallExpr: newCall, + }, + } + if newExpr, pruned := p.maybePruneFunction(newNode); pruned { + newExpr, _ = p.maybePrune(newExpr) + return newExpr, true + } if prunedCall { - return &exprpb.Expr{ - Id: node.GetId(), - ExprKind: &exprpb.Expr_CallExpr{ - CallExpr: newCall, - }, - }, true + return newNode, true } case *exprpb.Expr_ListExpr: elems := node.GetListExpr().GetElements() - newElems := make([]*exprpb.Expr, len(elems)) + optIndices := node.GetListExpr().GetOptionalIndices() + optIndexMap := map[int32]bool{} + for _, i := range optIndices { + optIndexMap[i] = true + } + newOptIndexMap := make(map[int32]bool, len(optIndexMap)) + newElems := make([]*exprpb.Expr, 0, len(elems)) var prunedList bool + + prunedIdx := 0 for i, elem := range elems { - newElems[i] = elem - if newElem, prunedElem := p.prune(elem); prunedElem { - newElems[i] = newElem + _, isOpt := optIndexMap[int32(i)] + if isOpt { + newElem, pruned := p.maybePruneOptional(elem) + if pruned { + prunedList = true + if newElem != nil { + newElems = append(newElems, newElem) + prunedIdx++ + } + continue + } + newOptIndexMap[int32(prunedIdx)] = true + } + if newElem, prunedElem := p.maybePrune(elem); prunedElem { + newElems = append(newElems, newElem) prunedList = true + } else { + newElems = append(newElems, elem) } + prunedIdx++ + } + optIndices = make([]int32, len(newOptIndexMap)) + idx := 0 + for i := range newOptIndexMap { + optIndices[idx] = i + idx++ } if prunedList { return &exprpb.Expr{ Id: node.GetId(), ExprKind: &exprpb.Expr_ListExpr{ ListExpr: &exprpb.Expr_CreateList{ - Elements: newElems, + Elements: newElems, + OptionalIndices: optIndices, }, }, }, true @@ -313,8 +456,8 @@ func (p *astPruner) prune(node *exprpb.Expr) (*exprpb.Expr, bool) { newEntries := make([]*exprpb.Expr_CreateStruct_Entry, len(entries)) for i, entry := range entries { newEntries[i] = entry - newKey, prunedKey := p.prune(entry.GetMapKey()) - newValue, prunedValue := p.prune(entry.GetValue()) + newKey, prunedKey := p.maybePrune(entry.GetMapKey()) + newValue, prunedValue := p.maybePrune(entry.GetValue()) if !prunedKey && !prunedValue { continue } @@ -331,6 +474,7 @@ func (p *astPruner) prune(node *exprpb.Expr) (*exprpb.Expr, bool) { MapKey: newKey, } } + newEntry.OptionalEntry = entry.GetOptionalEntry() newEntries[i] = newEntry } if prunedStruct { @@ -344,27 +488,6 @@ func (p *astPruner) prune(node *exprpb.Expr) (*exprpb.Expr, bool) { }, }, true } - case *exprpb.Expr_ComprehensionExpr: - compre := node.GetComprehensionExpr() - // Only the range of the comprehension is pruned since the state tracking only records - // the last iteration of the comprehension and not each step in the evaluation which - // means that the any residuals computed in between might be inaccurate. - if newRange, pruned := p.prune(compre.GetIterRange()); pruned { - return &exprpb.Expr{ - Id: node.GetId(), - ExprKind: &exprpb.Expr_ComprehensionExpr{ - ComprehensionExpr: &exprpb.Expr_Comprehension{ - IterVar: compre.GetIterVar(), - IterRange: newRange, - AccuVar: compre.GetAccuVar(), - AccuInit: compre.GetAccuInit(), - LoopCondition: compre.GetLoopCondition(), - LoopStep: compre.GetLoopStep(), - Result: compre.GetResult(), - }, - }, - }, true - } } return node, false } @@ -374,24 +497,82 @@ func (p *astPruner) value(id int64) (ref.Val, bool) { return val, (found && val != nil) } -func (p *astPruner) existsWithUnknownValue(id int64) bool { - val, valueExists := p.value(id) - return valueExists && types.IsUnknown(val) +func (p *astPruner) maybeValue(id int64) (ref.Val, bool) { + val, found := p.value(id) + if !found || types.IsUnknownOrError(val) { + return nil, false + } + return val, true } -func (p *astPruner) existsWithKnownValue(id int64) bool { - val, valueExists := p.value(id) - return valueExists && !types.IsUnknown(val) +func (p *astPruner) nextID() int64 { + next := p.nextExprID + p.nextExprID++ + return next } -func (p *astPruner) nextID() int64 { - for { - _, found := p.state.Value(p.nextExprID) - if !found { - next := p.nextExprID - p.nextExprID++ - return next +type astVisitor struct { + // visitEntry is called on every expr node, including those within a map/struct entry. + visitExpr func(expr *exprpb.Expr) + // visitEntry is called before entering the key, value of a map/struct entry. + visitEntry func(entry *exprpb.Expr_CreateStruct_Entry) +} + +func getMaxID(expr *exprpb.Expr) int64 { + maxID := int64(1) + visit(expr, maxIDVisitor(&maxID)) + return maxID +} + +func maxIDVisitor(maxID *int64) astVisitor { + return astVisitor{ + visitExpr: func(e *exprpb.Expr) { + if e.GetId() >= *maxID { + *maxID = e.GetId() + 1 + } + }, + visitEntry: func(e *exprpb.Expr_CreateStruct_Entry) { + if e.GetId() >= *maxID { + *maxID = e.GetId() + 1 + } + }, + } +} + +func visit(expr *exprpb.Expr, visitor astVisitor) { + exprs := []*exprpb.Expr{expr} + for len(exprs) != 0 { + e := exprs[0] + visitor.visitExpr(e) + exprs = exprs[1:] + switch e.GetExprKind().(type) { + case *exprpb.Expr_SelectExpr: + exprs = append(exprs, e.GetSelectExpr().GetOperand()) + case *exprpb.Expr_CallExpr: + call := e.GetCallExpr() + if call.GetTarget() != nil { + exprs = append(exprs, call.GetTarget()) + } + exprs = append(exprs, call.GetArgs()...) + case *exprpb.Expr_ComprehensionExpr: + compre := e.GetComprehensionExpr() + exprs = append(exprs, + compre.GetIterRange(), + compre.GetAccuInit(), + compre.GetLoopCondition(), + compre.GetLoopStep(), + compre.GetResult()) + case *exprpb.Expr_ListExpr: + list := e.GetListExpr() + exprs = append(exprs, list.GetElements()...) + case *exprpb.Expr_StructExpr: + for _, entry := range e.GetStructExpr().GetEntries() { + visitor.visitEntry(entry) + if entry.GetMapKey() != nil { + exprs = append(exprs, entry.GetMapKey()) + } + exprs = append(exprs, entry.GetValue()) + } } - p.nextExprID++ } } diff --git a/vendor/github.com/google/cel-go/interpreter/runtimecost.go b/vendor/github.com/google/cel-go/interpreter/runtimecost.go index 06b6b27ef1..a47ed59bfb 100644 --- a/vendor/github.com/google/cel-go/interpreter/runtimecost.go +++ b/vendor/github.com/google/cel-go/interpreter/runtimecost.go @@ -36,7 +36,7 @@ type ActualCostEstimator interface { // CostObserver provides an observer that tracks runtime cost. func CostObserver(tracker *CostTracker) EvalObserver { - observer := func(id int64, programStep interface{}, val ref.Val) { + observer := func(id int64, programStep any, val ref.Val) { switch t := programStep.(type) { case ConstantQualifier: // TODO: Push identifiers on to the stack before observing constant qualifiers that apply to them @@ -122,7 +122,7 @@ func (c CostTracker) costCall(call InterpretableCall, argValues []ref.Val, resul // if user has their own implementation of ActualCostEstimator, make sure to cover the mapping between overloadId and cost calculation switch call.OverloadID() { // O(n) functions - case overloads.StartsWithString, overloads.EndsWithString, overloads.StringToBytes, overloads.BytesToString: + case overloads.StartsWithString, overloads.EndsWithString, overloads.StringToBytes, overloads.BytesToString, overloads.ExtQuoteString, overloads.ExtFormatString: cost += uint64(math.Ceil(float64(c.actualSize(argValues[0])) * common.StringTraversalCostFactor)) case overloads.InList: // If a list is composed entirely of constant values this is O(1), but we don't account for that here. diff --git a/vendor/github.com/google/cel-go/parser/BUILD.bazel b/vendor/github.com/google/cel-go/parser/BUILD.bazel index b76e6e4844..c904ae311c 100644 --- a/vendor/github.com/google/cel-go/parser/BUILD.bazel +++ b/vendor/github.com/google/cel-go/parser/BUILD.bazel @@ -23,7 +23,7 @@ go_library( "//common/operators:go_default_library", "//common/runes:go_default_library", "//parser/gen:go_default_library", - "@com_github_antlr_antlr4_runtime_go_antlr//:go_default_library", + "@com_github_antlr_antlr4_runtime_go_antlr_v4//:go_default_library", "@org_golang_google_genproto//googleapis/api/expr/v1alpha1:go_default_library", "@org_golang_google_protobuf//proto:go_default_library", "@org_golang_google_protobuf//types/known/structpb:go_default_library", @@ -34,6 +34,7 @@ go_test( name = "go_default_test", size = "small", srcs = [ + "helper_test.go", "parser_test.go", "unescape_test.go", "unparser_test.go", @@ -45,7 +46,8 @@ go_test( "//common/debug:go_default_library", "//parser/gen:go_default_library", "//test:go_default_library", - "@com_github_antlr_antlr4_runtime_go_antlr//:go_default_library", + "@com_github_antlr_antlr4_runtime_go_antlr_v4//:go_default_library", "@org_golang_google_protobuf//proto:go_default_library", + "@org_golang_google_protobuf//testing/protocmp:go_default_library", ], ) diff --git a/vendor/github.com/google/cel-go/parser/gen/BUILD.bazel b/vendor/github.com/google/cel-go/parser/gen/BUILD.bazel index 22711310ce..654d1de7aa 100644 --- a/vendor/github.com/google/cel-go/parser/gen/BUILD.bazel +++ b/vendor/github.com/google/cel-go/parser/gen/BUILD.bazel @@ -21,6 +21,6 @@ go_library( ], importpath = "github.com/google/cel-go/parser/gen", deps = [ - "@com_github_antlr_antlr4_runtime_go_antlr//:go_default_library", + "@com_github_antlr_antlr4_runtime_go_antlr_v4//:go_default_library", ], ) diff --git a/vendor/github.com/google/cel-go/parser/gen/CEL.g4 b/vendor/github.com/google/cel-go/parser/gen/CEL.g4 index 11145ec374..b011da803c 100644 --- a/vendor/github.com/google/cel-go/parser/gen/CEL.g4 +++ b/vendor/github.com/google/cel-go/parser/gen/CEL.g4 @@ -52,16 +52,18 @@ unary member : primary # PrimaryExpr - | member op='.' id=IDENTIFIER (open='(' args=exprList? ')')? # SelectOrCall - | member op='[' index=expr ']' # Index - | member op='{' entries=fieldInitializerList? ','? '}' # CreateMessage + | member op='.' (opt='?')? id=IDENTIFIER # Select + | member op='.' id=IDENTIFIER open='(' args=exprList? ')' # MemberCall + | member op='[' (opt='?')? index=expr ']' # Index ; primary : leadingDot='.'? id=IDENTIFIER (op='(' args=exprList? ')')? # IdentOrGlobalCall | '(' e=expr ')' # Nested - | op='[' elems=exprList? ','? ']' # CreateList + | op='[' elems=listInit? ','? ']' # CreateList | op='{' entries=mapInitializerList? ','? '}' # CreateStruct + | leadingDot='.'? ids+=IDENTIFIER (ops+='.' ids+=IDENTIFIER)* + op='{' entries=fieldInitializerList? ','? '}' # CreateMessage | literal # ConstantLiteral ; @@ -69,23 +71,35 @@ exprList : e+=expr (',' e+=expr)* ; +listInit + : elems+=optExpr (',' elems+=optExpr)* + ; + fieldInitializerList - : fields+=IDENTIFIER cols+=':' values+=expr (',' fields+=IDENTIFIER cols+=':' values+=expr)* + : fields+=optField cols+=':' values+=expr (',' fields+=optField cols+=':' values+=expr)* + ; + +optField + : (opt='?')? IDENTIFIER ; mapInitializerList - : keys+=expr cols+=':' values+=expr (',' keys+=expr cols+=':' values+=expr)* + : keys+=optExpr cols+=':' values+=expr (',' keys+=optExpr cols+=':' values+=expr)* + ; + +optExpr + : (opt='?')? e=expr ; literal : sign=MINUS? tok=NUM_INT # Int - | tok=NUM_UINT # Uint + | tok=NUM_UINT # Uint | sign=MINUS? tok=NUM_FLOAT # Double - | tok=STRING # String - | tok=BYTES # Bytes - | tok=CEL_TRUE # BoolTrue - | tok=CEL_FALSE # BoolFalse - | tok=NUL # Null + | tok=STRING # String + | tok=BYTES # Bytes + | tok=CEL_TRUE # BoolTrue + | tok=CEL_FALSE # BoolFalse + | tok=NUL # Null ; // Lexer Rules diff --git a/vendor/github.com/google/cel-go/parser/gen/CEL.interp b/vendor/github.com/google/cel-go/parser/gen/CEL.interp index 13e3a10d17..75b8bb3e20 100644 --- a/vendor/github.com/google/cel-go/parser/gen/CEL.interp +++ b/vendor/github.com/google/cel-go/parser/gen/CEL.interp @@ -87,10 +87,13 @@ unary member primary exprList +listInit fieldInitializerList +optField mapInitializerList +optExpr literal atn: -[4, 1, 36, 209, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 36, 8, 1, 1, 2, 1, 2, 1, 2, 5, 2, 41, 8, 2, 10, 2, 12, 2, 44, 9, 2, 1, 3, 1, 3, 1, 3, 5, 3, 49, 8, 3, 10, 3, 12, 3, 52, 9, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 5, 4, 60, 8, 4, 10, 4, 12, 4, 63, 9, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 5, 5, 74, 8, 5, 10, 5, 12, 5, 77, 9, 5, 1, 6, 1, 6, 4, 6, 81, 8, 6, 11, 6, 12, 6, 82, 1, 6, 1, 6, 4, 6, 87, 8, 6, 11, 6, 12, 6, 88, 1, 6, 3, 6, 92, 8, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 3, 7, 102, 8, 7, 1, 7, 3, 7, 105, 8, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 3, 7, 115, 8, 7, 1, 7, 3, 7, 118, 8, 7, 1, 7, 5, 7, 121, 8, 7, 10, 7, 12, 7, 124, 9, 7, 1, 8, 3, 8, 127, 8, 8, 1, 8, 1, 8, 1, 8, 3, 8, 132, 8, 8, 1, 8, 3, 8, 135, 8, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 3, 8, 143, 8, 8, 1, 8, 3, 8, 146, 8, 8, 1, 8, 1, 8, 1, 8, 3, 8, 151, 8, 8, 1, 8, 3, 8, 154, 8, 8, 1, 8, 1, 8, 3, 8, 158, 8, 8, 1, 9, 1, 9, 1, 9, 5, 9, 163, 8, 9, 10, 9, 12, 9, 166, 9, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 5, 10, 175, 8, 10, 10, 10, 12, 10, 178, 9, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 5, 11, 188, 8, 11, 10, 11, 12, 11, 191, 9, 11, 1, 12, 3, 12, 194, 8, 12, 1, 12, 1, 12, 1, 12, 3, 12, 199, 8, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 3, 12, 207, 8, 12, 1, 12, 0, 3, 8, 10, 14, 13, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 0, 3, 1, 0, 1, 7, 1, 0, 23, 25, 2, 0, 18, 18, 22, 22, 235, 0, 26, 1, 0, 0, 0, 2, 29, 1, 0, 0, 0, 4, 37, 1, 0, 0, 0, 6, 45, 1, 0, 0, 0, 8, 53, 1, 0, 0, 0, 10, 64, 1, 0, 0, 0, 12, 91, 1, 0, 0, 0, 14, 93, 1, 0, 0, 0, 16, 157, 1, 0, 0, 0, 18, 159, 1, 0, 0, 0, 20, 167, 1, 0, 0, 0, 22, 179, 1, 0, 0, 0, 24, 206, 1, 0, 0, 0, 26, 27, 3, 2, 1, 0, 27, 28, 5, 0, 0, 1, 28, 1, 1, 0, 0, 0, 29, 35, 3, 4, 2, 0, 30, 31, 5, 20, 0, 0, 31, 32, 3, 4, 2, 0, 32, 33, 5, 21, 0, 0, 33, 34, 3, 2, 1, 0, 34, 36, 1, 0, 0, 0, 35, 30, 1, 0, 0, 0, 35, 36, 1, 0, 0, 0, 36, 3, 1, 0, 0, 0, 37, 42, 3, 6, 3, 0, 38, 39, 5, 9, 0, 0, 39, 41, 3, 6, 3, 0, 40, 38, 1, 0, 0, 0, 41, 44, 1, 0, 0, 0, 42, 40, 1, 0, 0, 0, 42, 43, 1, 0, 0, 0, 43, 5, 1, 0, 0, 0, 44, 42, 1, 0, 0, 0, 45, 50, 3, 8, 4, 0, 46, 47, 5, 8, 0, 0, 47, 49, 3, 8, 4, 0, 48, 46, 1, 0, 0, 0, 49, 52, 1, 0, 0, 0, 50, 48, 1, 0, 0, 0, 50, 51, 1, 0, 0, 0, 51, 7, 1, 0, 0, 0, 52, 50, 1, 0, 0, 0, 53, 54, 6, 4, -1, 0, 54, 55, 3, 10, 5, 0, 55, 61, 1, 0, 0, 0, 56, 57, 10, 1, 0, 0, 57, 58, 7, 0, 0, 0, 58, 60, 3, 8, 4, 2, 59, 56, 1, 0, 0, 0, 60, 63, 1, 0, 0, 0, 61, 59, 1, 0, 0, 0, 61, 62, 1, 0, 0, 0, 62, 9, 1, 0, 0, 0, 63, 61, 1, 0, 0, 0, 64, 65, 6, 5, -1, 0, 65, 66, 3, 12, 6, 0, 66, 75, 1, 0, 0, 0, 67, 68, 10, 2, 0, 0, 68, 69, 7, 1, 0, 0, 69, 74, 3, 10, 5, 3, 70, 71, 10, 1, 0, 0, 71, 72, 7, 2, 0, 0, 72, 74, 3, 10, 5, 2, 73, 67, 1, 0, 0, 0, 73, 70, 1, 0, 0, 0, 74, 77, 1, 0, 0, 0, 75, 73, 1, 0, 0, 0, 75, 76, 1, 0, 0, 0, 76, 11, 1, 0, 0, 0, 77, 75, 1, 0, 0, 0, 78, 92, 3, 14, 7, 0, 79, 81, 5, 19, 0, 0, 80, 79, 1, 0, 0, 0, 81, 82, 1, 0, 0, 0, 82, 80, 1, 0, 0, 0, 82, 83, 1, 0, 0, 0, 83, 84, 1, 0, 0, 0, 84, 92, 3, 14, 7, 0, 85, 87, 5, 18, 0, 0, 86, 85, 1, 0, 0, 0, 87, 88, 1, 0, 0, 0, 88, 86, 1, 0, 0, 0, 88, 89, 1, 0, 0, 0, 89, 90, 1, 0, 0, 0, 90, 92, 3, 14, 7, 0, 91, 78, 1, 0, 0, 0, 91, 80, 1, 0, 0, 0, 91, 86, 1, 0, 0, 0, 92, 13, 1, 0, 0, 0, 93, 94, 6, 7, -1, 0, 94, 95, 3, 16, 8, 0, 95, 122, 1, 0, 0, 0, 96, 97, 10, 3, 0, 0, 97, 98, 5, 16, 0, 0, 98, 104, 5, 36, 0, 0, 99, 101, 5, 14, 0, 0, 100, 102, 3, 18, 9, 0, 101, 100, 1, 0, 0, 0, 101, 102, 1, 0, 0, 0, 102, 103, 1, 0, 0, 0, 103, 105, 5, 15, 0, 0, 104, 99, 1, 0, 0, 0, 104, 105, 1, 0, 0, 0, 105, 121, 1, 0, 0, 0, 106, 107, 10, 2, 0, 0, 107, 108, 5, 10, 0, 0, 108, 109, 3, 2, 1, 0, 109, 110, 5, 11, 0, 0, 110, 121, 1, 0, 0, 0, 111, 112, 10, 1, 0, 0, 112, 114, 5, 12, 0, 0, 113, 115, 3, 20, 10, 0, 114, 113, 1, 0, 0, 0, 114, 115, 1, 0, 0, 0, 115, 117, 1, 0, 0, 0, 116, 118, 5, 17, 0, 0, 117, 116, 1, 0, 0, 0, 117, 118, 1, 0, 0, 0, 118, 119, 1, 0, 0, 0, 119, 121, 5, 13, 0, 0, 120, 96, 1, 0, 0, 0, 120, 106, 1, 0, 0, 0, 120, 111, 1, 0, 0, 0, 121, 124, 1, 0, 0, 0, 122, 120, 1, 0, 0, 0, 122, 123, 1, 0, 0, 0, 123, 15, 1, 0, 0, 0, 124, 122, 1, 0, 0, 0, 125, 127, 5, 16, 0, 0, 126, 125, 1, 0, 0, 0, 126, 127, 1, 0, 0, 0, 127, 128, 1, 0, 0, 0, 128, 134, 5, 36, 0, 0, 129, 131, 5, 14, 0, 0, 130, 132, 3, 18, 9, 0, 131, 130, 1, 0, 0, 0, 131, 132, 1, 0, 0, 0, 132, 133, 1, 0, 0, 0, 133, 135, 5, 15, 0, 0, 134, 129, 1, 0, 0, 0, 134, 135, 1, 0, 0, 0, 135, 158, 1, 0, 0, 0, 136, 137, 5, 14, 0, 0, 137, 138, 3, 2, 1, 0, 138, 139, 5, 15, 0, 0, 139, 158, 1, 0, 0, 0, 140, 142, 5, 10, 0, 0, 141, 143, 3, 18, 9, 0, 142, 141, 1, 0, 0, 0, 142, 143, 1, 0, 0, 0, 143, 145, 1, 0, 0, 0, 144, 146, 5, 17, 0, 0, 145, 144, 1, 0, 0, 0, 145, 146, 1, 0, 0, 0, 146, 147, 1, 0, 0, 0, 147, 158, 5, 11, 0, 0, 148, 150, 5, 12, 0, 0, 149, 151, 3, 22, 11, 0, 150, 149, 1, 0, 0, 0, 150, 151, 1, 0, 0, 0, 151, 153, 1, 0, 0, 0, 152, 154, 5, 17, 0, 0, 153, 152, 1, 0, 0, 0, 153, 154, 1, 0, 0, 0, 154, 155, 1, 0, 0, 0, 155, 158, 5, 13, 0, 0, 156, 158, 3, 24, 12, 0, 157, 126, 1, 0, 0, 0, 157, 136, 1, 0, 0, 0, 157, 140, 1, 0, 0, 0, 157, 148, 1, 0, 0, 0, 157, 156, 1, 0, 0, 0, 158, 17, 1, 0, 0, 0, 159, 164, 3, 2, 1, 0, 160, 161, 5, 17, 0, 0, 161, 163, 3, 2, 1, 0, 162, 160, 1, 0, 0, 0, 163, 166, 1, 0, 0, 0, 164, 162, 1, 0, 0, 0, 164, 165, 1, 0, 0, 0, 165, 19, 1, 0, 0, 0, 166, 164, 1, 0, 0, 0, 167, 168, 5, 36, 0, 0, 168, 169, 5, 21, 0, 0, 169, 176, 3, 2, 1, 0, 170, 171, 5, 17, 0, 0, 171, 172, 5, 36, 0, 0, 172, 173, 5, 21, 0, 0, 173, 175, 3, 2, 1, 0, 174, 170, 1, 0, 0, 0, 175, 178, 1, 0, 0, 0, 176, 174, 1, 0, 0, 0, 176, 177, 1, 0, 0, 0, 177, 21, 1, 0, 0, 0, 178, 176, 1, 0, 0, 0, 179, 180, 3, 2, 1, 0, 180, 181, 5, 21, 0, 0, 181, 189, 3, 2, 1, 0, 182, 183, 5, 17, 0, 0, 183, 184, 3, 2, 1, 0, 184, 185, 5, 21, 0, 0, 185, 186, 3, 2, 1, 0, 186, 188, 1, 0, 0, 0, 187, 182, 1, 0, 0, 0, 188, 191, 1, 0, 0, 0, 189, 187, 1, 0, 0, 0, 189, 190, 1, 0, 0, 0, 190, 23, 1, 0, 0, 0, 191, 189, 1, 0, 0, 0, 192, 194, 5, 18, 0, 0, 193, 192, 1, 0, 0, 0, 193, 194, 1, 0, 0, 0, 194, 195, 1, 0, 0, 0, 195, 207, 5, 32, 0, 0, 196, 207, 5, 33, 0, 0, 197, 199, 5, 18, 0, 0, 198, 197, 1, 0, 0, 0, 198, 199, 1, 0, 0, 0, 199, 200, 1, 0, 0, 0, 200, 207, 5, 31, 0, 0, 201, 207, 5, 34, 0, 0, 202, 207, 5, 35, 0, 0, 203, 207, 5, 26, 0, 0, 204, 207, 5, 27, 0, 0, 205, 207, 5, 28, 0, 0, 206, 193, 1, 0, 0, 0, 206, 196, 1, 0, 0, 0, 206, 198, 1, 0, 0, 0, 206, 201, 1, 0, 0, 0, 206, 202, 1, 0, 0, 0, 206, 203, 1, 0, 0, 0, 206, 204, 1, 0, 0, 0, 206, 205, 1, 0, 0, 0, 207, 25, 1, 0, 0, 0, 29, 35, 42, 50, 61, 73, 75, 82, 88, 91, 101, 104, 114, 117, 120, 122, 126, 131, 134, 142, 145, 150, 153, 157, 164, 176, 189, 193, 198, 206] \ No newline at end of file +[4, 1, 36, 251, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 42, 8, 1, 1, 2, 1, 2, 1, 2, 5, 2, 47, 8, 2, 10, 2, 12, 2, 50, 9, 2, 1, 3, 1, 3, 1, 3, 5, 3, 55, 8, 3, 10, 3, 12, 3, 58, 9, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 5, 4, 66, 8, 4, 10, 4, 12, 4, 69, 9, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 5, 5, 80, 8, 5, 10, 5, 12, 5, 83, 9, 5, 1, 6, 1, 6, 4, 6, 87, 8, 6, 11, 6, 12, 6, 88, 1, 6, 1, 6, 4, 6, 93, 8, 6, 11, 6, 12, 6, 94, 1, 6, 3, 6, 98, 8, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 3, 7, 106, 8, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 3, 7, 114, 8, 7, 1, 7, 1, 7, 1, 7, 1, 7, 3, 7, 120, 8, 7, 1, 7, 1, 7, 1, 7, 5, 7, 125, 8, 7, 10, 7, 12, 7, 128, 9, 7, 1, 8, 3, 8, 131, 8, 8, 1, 8, 1, 8, 1, 8, 3, 8, 136, 8, 8, 1, 8, 3, 8, 139, 8, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 3, 8, 147, 8, 8, 1, 8, 3, 8, 150, 8, 8, 1, 8, 1, 8, 1, 8, 3, 8, 155, 8, 8, 1, 8, 3, 8, 158, 8, 8, 1, 8, 1, 8, 3, 8, 162, 8, 8, 1, 8, 1, 8, 1, 8, 5, 8, 167, 8, 8, 10, 8, 12, 8, 170, 9, 8, 1, 8, 1, 8, 3, 8, 174, 8, 8, 1, 8, 3, 8, 177, 8, 8, 1, 8, 1, 8, 3, 8, 181, 8, 8, 1, 9, 1, 9, 1, 9, 5, 9, 186, 8, 9, 10, 9, 12, 9, 189, 9, 9, 1, 10, 1, 10, 1, 10, 5, 10, 194, 8, 10, 10, 10, 12, 10, 197, 9, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 5, 11, 207, 8, 11, 10, 11, 12, 11, 210, 9, 11, 1, 12, 3, 12, 213, 8, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 5, 13, 225, 8, 13, 10, 13, 12, 13, 228, 9, 13, 1, 14, 3, 14, 231, 8, 14, 1, 14, 1, 14, 1, 15, 3, 15, 236, 8, 15, 1, 15, 1, 15, 1, 15, 3, 15, 241, 8, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 3, 15, 249, 8, 15, 1, 15, 0, 3, 8, 10, 14, 16, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 0, 3, 1, 0, 1, 7, 1, 0, 23, 25, 2, 0, 18, 18, 22, 22, 281, 0, 32, 1, 0, 0, 0, 2, 35, 1, 0, 0, 0, 4, 43, 1, 0, 0, 0, 6, 51, 1, 0, 0, 0, 8, 59, 1, 0, 0, 0, 10, 70, 1, 0, 0, 0, 12, 97, 1, 0, 0, 0, 14, 99, 1, 0, 0, 0, 16, 180, 1, 0, 0, 0, 18, 182, 1, 0, 0, 0, 20, 190, 1, 0, 0, 0, 22, 198, 1, 0, 0, 0, 24, 212, 1, 0, 0, 0, 26, 216, 1, 0, 0, 0, 28, 230, 1, 0, 0, 0, 30, 248, 1, 0, 0, 0, 32, 33, 3, 2, 1, 0, 33, 34, 5, 0, 0, 1, 34, 1, 1, 0, 0, 0, 35, 41, 3, 4, 2, 0, 36, 37, 5, 20, 0, 0, 37, 38, 3, 4, 2, 0, 38, 39, 5, 21, 0, 0, 39, 40, 3, 2, 1, 0, 40, 42, 1, 0, 0, 0, 41, 36, 1, 0, 0, 0, 41, 42, 1, 0, 0, 0, 42, 3, 1, 0, 0, 0, 43, 48, 3, 6, 3, 0, 44, 45, 5, 9, 0, 0, 45, 47, 3, 6, 3, 0, 46, 44, 1, 0, 0, 0, 47, 50, 1, 0, 0, 0, 48, 46, 1, 0, 0, 0, 48, 49, 1, 0, 0, 0, 49, 5, 1, 0, 0, 0, 50, 48, 1, 0, 0, 0, 51, 56, 3, 8, 4, 0, 52, 53, 5, 8, 0, 0, 53, 55, 3, 8, 4, 0, 54, 52, 1, 0, 0, 0, 55, 58, 1, 0, 0, 0, 56, 54, 1, 0, 0, 0, 56, 57, 1, 0, 0, 0, 57, 7, 1, 0, 0, 0, 58, 56, 1, 0, 0, 0, 59, 60, 6, 4, -1, 0, 60, 61, 3, 10, 5, 0, 61, 67, 1, 0, 0, 0, 62, 63, 10, 1, 0, 0, 63, 64, 7, 0, 0, 0, 64, 66, 3, 8, 4, 2, 65, 62, 1, 0, 0, 0, 66, 69, 1, 0, 0, 0, 67, 65, 1, 0, 0, 0, 67, 68, 1, 0, 0, 0, 68, 9, 1, 0, 0, 0, 69, 67, 1, 0, 0, 0, 70, 71, 6, 5, -1, 0, 71, 72, 3, 12, 6, 0, 72, 81, 1, 0, 0, 0, 73, 74, 10, 2, 0, 0, 74, 75, 7, 1, 0, 0, 75, 80, 3, 10, 5, 3, 76, 77, 10, 1, 0, 0, 77, 78, 7, 2, 0, 0, 78, 80, 3, 10, 5, 2, 79, 73, 1, 0, 0, 0, 79, 76, 1, 0, 0, 0, 80, 83, 1, 0, 0, 0, 81, 79, 1, 0, 0, 0, 81, 82, 1, 0, 0, 0, 82, 11, 1, 0, 0, 0, 83, 81, 1, 0, 0, 0, 84, 98, 3, 14, 7, 0, 85, 87, 5, 19, 0, 0, 86, 85, 1, 0, 0, 0, 87, 88, 1, 0, 0, 0, 88, 86, 1, 0, 0, 0, 88, 89, 1, 0, 0, 0, 89, 90, 1, 0, 0, 0, 90, 98, 3, 14, 7, 0, 91, 93, 5, 18, 0, 0, 92, 91, 1, 0, 0, 0, 93, 94, 1, 0, 0, 0, 94, 92, 1, 0, 0, 0, 94, 95, 1, 0, 0, 0, 95, 96, 1, 0, 0, 0, 96, 98, 3, 14, 7, 0, 97, 84, 1, 0, 0, 0, 97, 86, 1, 0, 0, 0, 97, 92, 1, 0, 0, 0, 98, 13, 1, 0, 0, 0, 99, 100, 6, 7, -1, 0, 100, 101, 3, 16, 8, 0, 101, 126, 1, 0, 0, 0, 102, 103, 10, 3, 0, 0, 103, 105, 5, 16, 0, 0, 104, 106, 5, 20, 0, 0, 105, 104, 1, 0, 0, 0, 105, 106, 1, 0, 0, 0, 106, 107, 1, 0, 0, 0, 107, 125, 5, 36, 0, 0, 108, 109, 10, 2, 0, 0, 109, 110, 5, 16, 0, 0, 110, 111, 5, 36, 0, 0, 111, 113, 5, 14, 0, 0, 112, 114, 3, 18, 9, 0, 113, 112, 1, 0, 0, 0, 113, 114, 1, 0, 0, 0, 114, 115, 1, 0, 0, 0, 115, 125, 5, 15, 0, 0, 116, 117, 10, 1, 0, 0, 117, 119, 5, 10, 0, 0, 118, 120, 5, 20, 0, 0, 119, 118, 1, 0, 0, 0, 119, 120, 1, 0, 0, 0, 120, 121, 1, 0, 0, 0, 121, 122, 3, 2, 1, 0, 122, 123, 5, 11, 0, 0, 123, 125, 1, 0, 0, 0, 124, 102, 1, 0, 0, 0, 124, 108, 1, 0, 0, 0, 124, 116, 1, 0, 0, 0, 125, 128, 1, 0, 0, 0, 126, 124, 1, 0, 0, 0, 126, 127, 1, 0, 0, 0, 127, 15, 1, 0, 0, 0, 128, 126, 1, 0, 0, 0, 129, 131, 5, 16, 0, 0, 130, 129, 1, 0, 0, 0, 130, 131, 1, 0, 0, 0, 131, 132, 1, 0, 0, 0, 132, 138, 5, 36, 0, 0, 133, 135, 5, 14, 0, 0, 134, 136, 3, 18, 9, 0, 135, 134, 1, 0, 0, 0, 135, 136, 1, 0, 0, 0, 136, 137, 1, 0, 0, 0, 137, 139, 5, 15, 0, 0, 138, 133, 1, 0, 0, 0, 138, 139, 1, 0, 0, 0, 139, 181, 1, 0, 0, 0, 140, 141, 5, 14, 0, 0, 141, 142, 3, 2, 1, 0, 142, 143, 5, 15, 0, 0, 143, 181, 1, 0, 0, 0, 144, 146, 5, 10, 0, 0, 145, 147, 3, 20, 10, 0, 146, 145, 1, 0, 0, 0, 146, 147, 1, 0, 0, 0, 147, 149, 1, 0, 0, 0, 148, 150, 5, 17, 0, 0, 149, 148, 1, 0, 0, 0, 149, 150, 1, 0, 0, 0, 150, 151, 1, 0, 0, 0, 151, 181, 5, 11, 0, 0, 152, 154, 5, 12, 0, 0, 153, 155, 3, 26, 13, 0, 154, 153, 1, 0, 0, 0, 154, 155, 1, 0, 0, 0, 155, 157, 1, 0, 0, 0, 156, 158, 5, 17, 0, 0, 157, 156, 1, 0, 0, 0, 157, 158, 1, 0, 0, 0, 158, 159, 1, 0, 0, 0, 159, 181, 5, 13, 0, 0, 160, 162, 5, 16, 0, 0, 161, 160, 1, 0, 0, 0, 161, 162, 1, 0, 0, 0, 162, 163, 1, 0, 0, 0, 163, 168, 5, 36, 0, 0, 164, 165, 5, 16, 0, 0, 165, 167, 5, 36, 0, 0, 166, 164, 1, 0, 0, 0, 167, 170, 1, 0, 0, 0, 168, 166, 1, 0, 0, 0, 168, 169, 1, 0, 0, 0, 169, 171, 1, 0, 0, 0, 170, 168, 1, 0, 0, 0, 171, 173, 5, 12, 0, 0, 172, 174, 3, 22, 11, 0, 173, 172, 1, 0, 0, 0, 173, 174, 1, 0, 0, 0, 174, 176, 1, 0, 0, 0, 175, 177, 5, 17, 0, 0, 176, 175, 1, 0, 0, 0, 176, 177, 1, 0, 0, 0, 177, 178, 1, 0, 0, 0, 178, 181, 5, 13, 0, 0, 179, 181, 3, 30, 15, 0, 180, 130, 1, 0, 0, 0, 180, 140, 1, 0, 0, 0, 180, 144, 1, 0, 0, 0, 180, 152, 1, 0, 0, 0, 180, 161, 1, 0, 0, 0, 180, 179, 1, 0, 0, 0, 181, 17, 1, 0, 0, 0, 182, 187, 3, 2, 1, 0, 183, 184, 5, 17, 0, 0, 184, 186, 3, 2, 1, 0, 185, 183, 1, 0, 0, 0, 186, 189, 1, 0, 0, 0, 187, 185, 1, 0, 0, 0, 187, 188, 1, 0, 0, 0, 188, 19, 1, 0, 0, 0, 189, 187, 1, 0, 0, 0, 190, 195, 3, 28, 14, 0, 191, 192, 5, 17, 0, 0, 192, 194, 3, 28, 14, 0, 193, 191, 1, 0, 0, 0, 194, 197, 1, 0, 0, 0, 195, 193, 1, 0, 0, 0, 195, 196, 1, 0, 0, 0, 196, 21, 1, 0, 0, 0, 197, 195, 1, 0, 0, 0, 198, 199, 3, 24, 12, 0, 199, 200, 5, 21, 0, 0, 200, 208, 3, 2, 1, 0, 201, 202, 5, 17, 0, 0, 202, 203, 3, 24, 12, 0, 203, 204, 5, 21, 0, 0, 204, 205, 3, 2, 1, 0, 205, 207, 1, 0, 0, 0, 206, 201, 1, 0, 0, 0, 207, 210, 1, 0, 0, 0, 208, 206, 1, 0, 0, 0, 208, 209, 1, 0, 0, 0, 209, 23, 1, 0, 0, 0, 210, 208, 1, 0, 0, 0, 211, 213, 5, 20, 0, 0, 212, 211, 1, 0, 0, 0, 212, 213, 1, 0, 0, 0, 213, 214, 1, 0, 0, 0, 214, 215, 5, 36, 0, 0, 215, 25, 1, 0, 0, 0, 216, 217, 3, 28, 14, 0, 217, 218, 5, 21, 0, 0, 218, 226, 3, 2, 1, 0, 219, 220, 5, 17, 0, 0, 220, 221, 3, 28, 14, 0, 221, 222, 5, 21, 0, 0, 222, 223, 3, 2, 1, 0, 223, 225, 1, 0, 0, 0, 224, 219, 1, 0, 0, 0, 225, 228, 1, 0, 0, 0, 226, 224, 1, 0, 0, 0, 226, 227, 1, 0, 0, 0, 227, 27, 1, 0, 0, 0, 228, 226, 1, 0, 0, 0, 229, 231, 5, 20, 0, 0, 230, 229, 1, 0, 0, 0, 230, 231, 1, 0, 0, 0, 231, 232, 1, 0, 0, 0, 232, 233, 3, 2, 1, 0, 233, 29, 1, 0, 0, 0, 234, 236, 5, 18, 0, 0, 235, 234, 1, 0, 0, 0, 235, 236, 1, 0, 0, 0, 236, 237, 1, 0, 0, 0, 237, 249, 5, 32, 0, 0, 238, 249, 5, 33, 0, 0, 239, 241, 5, 18, 0, 0, 240, 239, 1, 0, 0, 0, 240, 241, 1, 0, 0, 0, 241, 242, 1, 0, 0, 0, 242, 249, 5, 31, 0, 0, 243, 249, 5, 34, 0, 0, 244, 249, 5, 35, 0, 0, 245, 249, 5, 26, 0, 0, 246, 249, 5, 27, 0, 0, 247, 249, 5, 28, 0, 0, 248, 235, 1, 0, 0, 0, 248, 238, 1, 0, 0, 0, 248, 240, 1, 0, 0, 0, 248, 243, 1, 0, 0, 0, 248, 244, 1, 0, 0, 0, 248, 245, 1, 0, 0, 0, 248, 246, 1, 0, 0, 0, 248, 247, 1, 0, 0, 0, 249, 31, 1, 0, 0, 0, 35, 41, 48, 56, 67, 79, 81, 88, 94, 97, 105, 113, 119, 124, 126, 130, 135, 138, 146, 149, 154, 157, 161, 168, 173, 176, 180, 187, 195, 208, 212, 226, 230, 235, 240, 248] \ No newline at end of file diff --git a/vendor/github.com/google/cel-go/parser/gen/cel_base_listener.go b/vendor/github.com/google/cel-go/parser/gen/cel_base_listener.go index 969a598618..0247f470a7 100644 --- a/vendor/github.com/google/cel-go/parser/gen/cel_base_listener.go +++ b/vendor/github.com/google/cel-go/parser/gen/cel_base_listener.go @@ -1,7 +1,7 @@ -// Code generated from /Users/tswadell/go/src/github.com/google/cel-go/parser/gen/CEL.g4 by ANTLR 4.10.1. DO NOT EDIT. +// Code generated from /Users/tswadell/go/src/github.com/google/cel-go/parser/gen/CEL.g4 by ANTLR 4.12.0. DO NOT EDIT. package gen // CEL -import "github.com/antlr/antlr4/runtime/Go/antlr" +import "github.com/antlr/antlr4/runtime/Go/antlr/v4" // BaseCELListener is a complete listener for a parse tree produced by CELParser. type BaseCELListener struct{} @@ -74,11 +74,17 @@ func (s *BaseCELListener) EnterNegate(ctx *NegateContext) {} // ExitNegate is called when production Negate is exited. func (s *BaseCELListener) ExitNegate(ctx *NegateContext) {} -// EnterSelectOrCall is called when production SelectOrCall is entered. -func (s *BaseCELListener) EnterSelectOrCall(ctx *SelectOrCallContext) {} +// EnterMemberCall is called when production MemberCall is entered. +func (s *BaseCELListener) EnterMemberCall(ctx *MemberCallContext) {} -// ExitSelectOrCall is called when production SelectOrCall is exited. -func (s *BaseCELListener) ExitSelectOrCall(ctx *SelectOrCallContext) {} +// ExitMemberCall is called when production MemberCall is exited. +func (s *BaseCELListener) ExitMemberCall(ctx *MemberCallContext) {} + +// EnterSelect is called when production Select is entered. +func (s *BaseCELListener) EnterSelect(ctx *SelectContext) {} + +// ExitSelect is called when production Select is exited. +func (s *BaseCELListener) ExitSelect(ctx *SelectContext) {} // EnterPrimaryExpr is called when production PrimaryExpr is entered. func (s *BaseCELListener) EnterPrimaryExpr(ctx *PrimaryExprContext) {} @@ -92,12 +98,6 @@ func (s *BaseCELListener) EnterIndex(ctx *IndexContext) {} // ExitIndex is called when production Index is exited. func (s *BaseCELListener) ExitIndex(ctx *IndexContext) {} -// EnterCreateMessage is called when production CreateMessage is entered. -func (s *BaseCELListener) EnterCreateMessage(ctx *CreateMessageContext) {} - -// ExitCreateMessage is called when production CreateMessage is exited. -func (s *BaseCELListener) ExitCreateMessage(ctx *CreateMessageContext) {} - // EnterIdentOrGlobalCall is called when production IdentOrGlobalCall is entered. func (s *BaseCELListener) EnterIdentOrGlobalCall(ctx *IdentOrGlobalCallContext) {} @@ -122,6 +122,12 @@ func (s *BaseCELListener) EnterCreateStruct(ctx *CreateStructContext) {} // ExitCreateStruct is called when production CreateStruct is exited. func (s *BaseCELListener) ExitCreateStruct(ctx *CreateStructContext) {} +// EnterCreateMessage is called when production CreateMessage is entered. +func (s *BaseCELListener) EnterCreateMessage(ctx *CreateMessageContext) {} + +// ExitCreateMessage is called when production CreateMessage is exited. +func (s *BaseCELListener) ExitCreateMessage(ctx *CreateMessageContext) {} + // EnterConstantLiteral is called when production ConstantLiteral is entered. func (s *BaseCELListener) EnterConstantLiteral(ctx *ConstantLiteralContext) {} @@ -134,18 +140,36 @@ func (s *BaseCELListener) EnterExprList(ctx *ExprListContext) {} // ExitExprList is called when production exprList is exited. func (s *BaseCELListener) ExitExprList(ctx *ExprListContext) {} +// EnterListInit is called when production listInit is entered. +func (s *BaseCELListener) EnterListInit(ctx *ListInitContext) {} + +// ExitListInit is called when production listInit is exited. +func (s *BaseCELListener) ExitListInit(ctx *ListInitContext) {} + // EnterFieldInitializerList is called when production fieldInitializerList is entered. func (s *BaseCELListener) EnterFieldInitializerList(ctx *FieldInitializerListContext) {} // ExitFieldInitializerList is called when production fieldInitializerList is exited. func (s *BaseCELListener) ExitFieldInitializerList(ctx *FieldInitializerListContext) {} +// EnterOptField is called when production optField is entered. +func (s *BaseCELListener) EnterOptField(ctx *OptFieldContext) {} + +// ExitOptField is called when production optField is exited. +func (s *BaseCELListener) ExitOptField(ctx *OptFieldContext) {} + // EnterMapInitializerList is called when production mapInitializerList is entered. func (s *BaseCELListener) EnterMapInitializerList(ctx *MapInitializerListContext) {} // ExitMapInitializerList is called when production mapInitializerList is exited. func (s *BaseCELListener) ExitMapInitializerList(ctx *MapInitializerListContext) {} +// EnterOptExpr is called when production optExpr is entered. +func (s *BaseCELListener) EnterOptExpr(ctx *OptExprContext) {} + +// ExitOptExpr is called when production optExpr is exited. +func (s *BaseCELListener) ExitOptExpr(ctx *OptExprContext) {} + // EnterInt is called when production Int is entered. func (s *BaseCELListener) EnterInt(ctx *IntContext) {} diff --git a/vendor/github.com/google/cel-go/parser/gen/cel_base_visitor.go b/vendor/github.com/google/cel-go/parser/gen/cel_base_visitor.go index 8e84579ed1..52a7f4dc57 100644 --- a/vendor/github.com/google/cel-go/parser/gen/cel_base_visitor.go +++ b/vendor/github.com/google/cel-go/parser/gen/cel_base_visitor.go @@ -1,7 +1,7 @@ -// Code generated from /Users/tswadell/go/src/github.com/google/cel-go/parser/gen/CEL.g4 by ANTLR 4.10.1. DO NOT EDIT. +// Code generated from /Users/tswadell/go/src/github.com/google/cel-go/parser/gen/CEL.g4 by ANTLR 4.12.0. DO NOT EDIT. package gen // CEL -import "github.com/antlr/antlr4/runtime/Go/antlr" +import "github.com/antlr/antlr4/runtime/Go/antlr/v4" type BaseCELVisitor struct { *antlr.BaseParseTreeVisitor @@ -43,19 +43,19 @@ func (v *BaseCELVisitor) VisitNegate(ctx *NegateContext) interface{} { return v.VisitChildren(ctx) } -func (v *BaseCELVisitor) VisitSelectOrCall(ctx *SelectOrCallContext) interface{} { +func (v *BaseCELVisitor) VisitMemberCall(ctx *MemberCallContext) interface{} { return v.VisitChildren(ctx) } -func (v *BaseCELVisitor) VisitPrimaryExpr(ctx *PrimaryExprContext) interface{} { +func (v *BaseCELVisitor) VisitSelect(ctx *SelectContext) interface{} { return v.VisitChildren(ctx) } -func (v *BaseCELVisitor) VisitIndex(ctx *IndexContext) interface{} { +func (v *BaseCELVisitor) VisitPrimaryExpr(ctx *PrimaryExprContext) interface{} { return v.VisitChildren(ctx) } -func (v *BaseCELVisitor) VisitCreateMessage(ctx *CreateMessageContext) interface{} { +func (v *BaseCELVisitor) VisitIndex(ctx *IndexContext) interface{} { return v.VisitChildren(ctx) } @@ -75,6 +75,10 @@ func (v *BaseCELVisitor) VisitCreateStruct(ctx *CreateStructContext) interface{} return v.VisitChildren(ctx) } +func (v *BaseCELVisitor) VisitCreateMessage(ctx *CreateMessageContext) interface{} { + return v.VisitChildren(ctx) +} + func (v *BaseCELVisitor) VisitConstantLiteral(ctx *ConstantLiteralContext) interface{} { return v.VisitChildren(ctx) } @@ -83,14 +87,26 @@ func (v *BaseCELVisitor) VisitExprList(ctx *ExprListContext) interface{} { return v.VisitChildren(ctx) } +func (v *BaseCELVisitor) VisitListInit(ctx *ListInitContext) interface{} { + return v.VisitChildren(ctx) +} + func (v *BaseCELVisitor) VisitFieldInitializerList(ctx *FieldInitializerListContext) interface{} { return v.VisitChildren(ctx) } +func (v *BaseCELVisitor) VisitOptField(ctx *OptFieldContext) interface{} { + return v.VisitChildren(ctx) +} + func (v *BaseCELVisitor) VisitMapInitializerList(ctx *MapInitializerListContext) interface{} { return v.VisitChildren(ctx) } +func (v *BaseCELVisitor) VisitOptExpr(ctx *OptExprContext) interface{} { + return v.VisitChildren(ctx) +} + func (v *BaseCELVisitor) VisitInt(ctx *IntContext) interface{} { return v.VisitChildren(ctx) } diff --git a/vendor/github.com/google/cel-go/parser/gen/cel_lexer.go b/vendor/github.com/google/cel-go/parser/gen/cel_lexer.go index 7b4cca62e6..98ddc06d0b 100644 --- a/vendor/github.com/google/cel-go/parser/gen/cel_lexer.go +++ b/vendor/github.com/google/cel-go/parser/gen/cel_lexer.go @@ -1,4 +1,4 @@ -// Code generated from /Users/tswadell/go/src/github.com/google/cel-go/parser/gen/CEL.g4 by ANTLR 4.10.1. DO NOT EDIT. +// Code generated from /Users/tswadell/go/src/github.com/google/cel-go/parser/gen/CEL.g4 by ANTLR 4.12.0. DO NOT EDIT. package gen @@ -7,7 +7,7 @@ import ( "sync" "unicode" - "github.com/antlr/antlr4/runtime/Go/antlr" + "github.com/antlr/antlr4/runtime/Go/antlr/v4" ) // Suppress unused import error diff --git a/vendor/github.com/google/cel-go/parser/gen/cel_listener.go b/vendor/github.com/google/cel-go/parser/gen/cel_listener.go index 1b631b6e1b..73b7f1d39f 100644 --- a/vendor/github.com/google/cel-go/parser/gen/cel_listener.go +++ b/vendor/github.com/google/cel-go/parser/gen/cel_listener.go @@ -1,7 +1,7 @@ -// Code generated from /Users/tswadell/go/src/github.com/google/cel-go/parser/gen/CEL.g4 by ANTLR 4.10.1. DO NOT EDIT. +// Code generated from /Users/tswadell/go/src/github.com/google/cel-go/parser/gen/CEL.g4 by ANTLR 4.12.0. DO NOT EDIT. package gen // CEL -import "github.com/antlr/antlr4/runtime/Go/antlr" +import "github.com/antlr/antlr4/runtime/Go/antlr/v4" // CELListener is a complete listener for a parse tree produced by CELParser. type CELListener interface { @@ -34,8 +34,11 @@ type CELListener interface { // EnterNegate is called when entering the Negate production. EnterNegate(c *NegateContext) - // EnterSelectOrCall is called when entering the SelectOrCall production. - EnterSelectOrCall(c *SelectOrCallContext) + // EnterMemberCall is called when entering the MemberCall production. + EnterMemberCall(c *MemberCallContext) + + // EnterSelect is called when entering the Select production. + EnterSelect(c *SelectContext) // EnterPrimaryExpr is called when entering the PrimaryExpr production. EnterPrimaryExpr(c *PrimaryExprContext) @@ -43,9 +46,6 @@ type CELListener interface { // EnterIndex is called when entering the Index production. EnterIndex(c *IndexContext) - // EnterCreateMessage is called when entering the CreateMessage production. - EnterCreateMessage(c *CreateMessageContext) - // EnterIdentOrGlobalCall is called when entering the IdentOrGlobalCall production. EnterIdentOrGlobalCall(c *IdentOrGlobalCallContext) @@ -58,18 +58,30 @@ type CELListener interface { // EnterCreateStruct is called when entering the CreateStruct production. EnterCreateStruct(c *CreateStructContext) + // EnterCreateMessage is called when entering the CreateMessage production. + EnterCreateMessage(c *CreateMessageContext) + // EnterConstantLiteral is called when entering the ConstantLiteral production. EnterConstantLiteral(c *ConstantLiteralContext) // EnterExprList is called when entering the exprList production. EnterExprList(c *ExprListContext) + // EnterListInit is called when entering the listInit production. + EnterListInit(c *ListInitContext) + // EnterFieldInitializerList is called when entering the fieldInitializerList production. EnterFieldInitializerList(c *FieldInitializerListContext) + // EnterOptField is called when entering the optField production. + EnterOptField(c *OptFieldContext) + // EnterMapInitializerList is called when entering the mapInitializerList production. EnterMapInitializerList(c *MapInitializerListContext) + // EnterOptExpr is called when entering the optExpr production. + EnterOptExpr(c *OptExprContext) + // EnterInt is called when entering the Int production. EnterInt(c *IntContext) @@ -121,8 +133,11 @@ type CELListener interface { // ExitNegate is called when exiting the Negate production. ExitNegate(c *NegateContext) - // ExitSelectOrCall is called when exiting the SelectOrCall production. - ExitSelectOrCall(c *SelectOrCallContext) + // ExitMemberCall is called when exiting the MemberCall production. + ExitMemberCall(c *MemberCallContext) + + // ExitSelect is called when exiting the Select production. + ExitSelect(c *SelectContext) // ExitPrimaryExpr is called when exiting the PrimaryExpr production. ExitPrimaryExpr(c *PrimaryExprContext) @@ -130,9 +145,6 @@ type CELListener interface { // ExitIndex is called when exiting the Index production. ExitIndex(c *IndexContext) - // ExitCreateMessage is called when exiting the CreateMessage production. - ExitCreateMessage(c *CreateMessageContext) - // ExitIdentOrGlobalCall is called when exiting the IdentOrGlobalCall production. ExitIdentOrGlobalCall(c *IdentOrGlobalCallContext) @@ -145,18 +157,30 @@ type CELListener interface { // ExitCreateStruct is called when exiting the CreateStruct production. ExitCreateStruct(c *CreateStructContext) + // ExitCreateMessage is called when exiting the CreateMessage production. + ExitCreateMessage(c *CreateMessageContext) + // ExitConstantLiteral is called when exiting the ConstantLiteral production. ExitConstantLiteral(c *ConstantLiteralContext) // ExitExprList is called when exiting the exprList production. ExitExprList(c *ExprListContext) + // ExitListInit is called when exiting the listInit production. + ExitListInit(c *ListInitContext) + // ExitFieldInitializerList is called when exiting the fieldInitializerList production. ExitFieldInitializerList(c *FieldInitializerListContext) + // ExitOptField is called when exiting the optField production. + ExitOptField(c *OptFieldContext) + // ExitMapInitializerList is called when exiting the mapInitializerList production. ExitMapInitializerList(c *MapInitializerListContext) + // ExitOptExpr is called when exiting the optExpr production. + ExitOptExpr(c *OptExprContext) + // ExitInt is called when exiting the Int production. ExitInt(c *IntContext) diff --git a/vendor/github.com/google/cel-go/parser/gen/cel_parser.go b/vendor/github.com/google/cel-go/parser/gen/cel_parser.go index afb3fe0d1c..0cb6c8eae8 100644 --- a/vendor/github.com/google/cel-go/parser/gen/cel_parser.go +++ b/vendor/github.com/google/cel-go/parser/gen/cel_parser.go @@ -1,4 +1,4 @@ -// Code generated from /Users/tswadell/go/src/github.com/google/cel-go/parser/gen/CEL.g4 by ANTLR 4.10.1. DO NOT EDIT. +// Code generated from /Users/tswadell/go/src/github.com/google/cel-go/parser/gen/CEL.g4 by ANTLR 4.12.0. DO NOT EDIT. package gen // CEL import ( @@ -6,7 +6,7 @@ import ( "strconv" "sync" - "github.com/antlr/antlr4/runtime/Go/antlr" + "github.com/antlr/antlr4/runtime/Go/antlr/v4" ) // Suppress unused import errors @@ -46,106 +46,125 @@ func celParserInit() { } staticData.ruleNames = []string{ "start", "expr", "conditionalOr", "conditionalAnd", "relation", "calc", - "unary", "member", "primary", "exprList", "fieldInitializerList", "mapInitializerList", - "literal", + "unary", "member", "primary", "exprList", "listInit", "fieldInitializerList", + "optField", "mapInitializerList", "optExpr", "literal", } staticData.predictionContextCache = antlr.NewPredictionContextCache() staticData.serializedATN = []int32{ - 4, 1, 36, 209, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, + 4, 1, 36, 251, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, - 10, 2, 11, 7, 11, 2, 12, 7, 12, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 3, 1, 36, 8, 1, 1, 2, 1, 2, 1, 2, 5, 2, 41, 8, 2, 10, 2, - 12, 2, 44, 9, 2, 1, 3, 1, 3, 1, 3, 5, 3, 49, 8, 3, 10, 3, 12, 3, 52, 9, - 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 5, 4, 60, 8, 4, 10, 4, 12, 4, 63, - 9, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 5, 5, 74, 8, - 5, 10, 5, 12, 5, 77, 9, 5, 1, 6, 1, 6, 4, 6, 81, 8, 6, 11, 6, 12, 6, 82, - 1, 6, 1, 6, 4, 6, 87, 8, 6, 11, 6, 12, 6, 88, 1, 6, 3, 6, 92, 8, 6, 1, - 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 3, 7, 102, 8, 7, 1, 7, 3, - 7, 105, 8, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 3, 7, 115, - 8, 7, 1, 7, 3, 7, 118, 8, 7, 1, 7, 5, 7, 121, 8, 7, 10, 7, 12, 7, 124, - 9, 7, 1, 8, 3, 8, 127, 8, 8, 1, 8, 1, 8, 1, 8, 3, 8, 132, 8, 8, 1, 8, 3, - 8, 135, 8, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 3, 8, 143, 8, 8, 1, 8, - 3, 8, 146, 8, 8, 1, 8, 1, 8, 1, 8, 3, 8, 151, 8, 8, 1, 8, 3, 8, 154, 8, - 8, 1, 8, 1, 8, 3, 8, 158, 8, 8, 1, 9, 1, 9, 1, 9, 5, 9, 163, 8, 9, 10, - 9, 12, 9, 166, 9, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 5, - 10, 175, 8, 10, 10, 10, 12, 10, 178, 9, 10, 1, 11, 1, 11, 1, 11, 1, 11, - 1, 11, 1, 11, 1, 11, 1, 11, 5, 11, 188, 8, 11, 10, 11, 12, 11, 191, 9, - 11, 1, 12, 3, 12, 194, 8, 12, 1, 12, 1, 12, 1, 12, 3, 12, 199, 8, 12, 1, - 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 3, 12, 207, 8, 12, 1, 12, 0, 3, - 8, 10, 14, 13, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 0, 3, 1, - 0, 1, 7, 1, 0, 23, 25, 2, 0, 18, 18, 22, 22, 235, 0, 26, 1, 0, 0, 0, 2, - 29, 1, 0, 0, 0, 4, 37, 1, 0, 0, 0, 6, 45, 1, 0, 0, 0, 8, 53, 1, 0, 0, 0, - 10, 64, 1, 0, 0, 0, 12, 91, 1, 0, 0, 0, 14, 93, 1, 0, 0, 0, 16, 157, 1, - 0, 0, 0, 18, 159, 1, 0, 0, 0, 20, 167, 1, 0, 0, 0, 22, 179, 1, 0, 0, 0, - 24, 206, 1, 0, 0, 0, 26, 27, 3, 2, 1, 0, 27, 28, 5, 0, 0, 1, 28, 1, 1, - 0, 0, 0, 29, 35, 3, 4, 2, 0, 30, 31, 5, 20, 0, 0, 31, 32, 3, 4, 2, 0, 32, - 33, 5, 21, 0, 0, 33, 34, 3, 2, 1, 0, 34, 36, 1, 0, 0, 0, 35, 30, 1, 0, - 0, 0, 35, 36, 1, 0, 0, 0, 36, 3, 1, 0, 0, 0, 37, 42, 3, 6, 3, 0, 38, 39, - 5, 9, 0, 0, 39, 41, 3, 6, 3, 0, 40, 38, 1, 0, 0, 0, 41, 44, 1, 0, 0, 0, - 42, 40, 1, 0, 0, 0, 42, 43, 1, 0, 0, 0, 43, 5, 1, 0, 0, 0, 44, 42, 1, 0, - 0, 0, 45, 50, 3, 8, 4, 0, 46, 47, 5, 8, 0, 0, 47, 49, 3, 8, 4, 0, 48, 46, - 1, 0, 0, 0, 49, 52, 1, 0, 0, 0, 50, 48, 1, 0, 0, 0, 50, 51, 1, 0, 0, 0, - 51, 7, 1, 0, 0, 0, 52, 50, 1, 0, 0, 0, 53, 54, 6, 4, -1, 0, 54, 55, 3, - 10, 5, 0, 55, 61, 1, 0, 0, 0, 56, 57, 10, 1, 0, 0, 57, 58, 7, 0, 0, 0, - 58, 60, 3, 8, 4, 2, 59, 56, 1, 0, 0, 0, 60, 63, 1, 0, 0, 0, 61, 59, 1, - 0, 0, 0, 61, 62, 1, 0, 0, 0, 62, 9, 1, 0, 0, 0, 63, 61, 1, 0, 0, 0, 64, - 65, 6, 5, -1, 0, 65, 66, 3, 12, 6, 0, 66, 75, 1, 0, 0, 0, 67, 68, 10, 2, - 0, 0, 68, 69, 7, 1, 0, 0, 69, 74, 3, 10, 5, 3, 70, 71, 10, 1, 0, 0, 71, - 72, 7, 2, 0, 0, 72, 74, 3, 10, 5, 2, 73, 67, 1, 0, 0, 0, 73, 70, 1, 0, - 0, 0, 74, 77, 1, 0, 0, 0, 75, 73, 1, 0, 0, 0, 75, 76, 1, 0, 0, 0, 76, 11, - 1, 0, 0, 0, 77, 75, 1, 0, 0, 0, 78, 92, 3, 14, 7, 0, 79, 81, 5, 19, 0, - 0, 80, 79, 1, 0, 0, 0, 81, 82, 1, 0, 0, 0, 82, 80, 1, 0, 0, 0, 82, 83, - 1, 0, 0, 0, 83, 84, 1, 0, 0, 0, 84, 92, 3, 14, 7, 0, 85, 87, 5, 18, 0, - 0, 86, 85, 1, 0, 0, 0, 87, 88, 1, 0, 0, 0, 88, 86, 1, 0, 0, 0, 88, 89, - 1, 0, 0, 0, 89, 90, 1, 0, 0, 0, 90, 92, 3, 14, 7, 0, 91, 78, 1, 0, 0, 0, - 91, 80, 1, 0, 0, 0, 91, 86, 1, 0, 0, 0, 92, 13, 1, 0, 0, 0, 93, 94, 6, - 7, -1, 0, 94, 95, 3, 16, 8, 0, 95, 122, 1, 0, 0, 0, 96, 97, 10, 3, 0, 0, - 97, 98, 5, 16, 0, 0, 98, 104, 5, 36, 0, 0, 99, 101, 5, 14, 0, 0, 100, 102, - 3, 18, 9, 0, 101, 100, 1, 0, 0, 0, 101, 102, 1, 0, 0, 0, 102, 103, 1, 0, - 0, 0, 103, 105, 5, 15, 0, 0, 104, 99, 1, 0, 0, 0, 104, 105, 1, 0, 0, 0, - 105, 121, 1, 0, 0, 0, 106, 107, 10, 2, 0, 0, 107, 108, 5, 10, 0, 0, 108, - 109, 3, 2, 1, 0, 109, 110, 5, 11, 0, 0, 110, 121, 1, 0, 0, 0, 111, 112, - 10, 1, 0, 0, 112, 114, 5, 12, 0, 0, 113, 115, 3, 20, 10, 0, 114, 113, 1, - 0, 0, 0, 114, 115, 1, 0, 0, 0, 115, 117, 1, 0, 0, 0, 116, 118, 5, 17, 0, - 0, 117, 116, 1, 0, 0, 0, 117, 118, 1, 0, 0, 0, 118, 119, 1, 0, 0, 0, 119, - 121, 5, 13, 0, 0, 120, 96, 1, 0, 0, 0, 120, 106, 1, 0, 0, 0, 120, 111, - 1, 0, 0, 0, 121, 124, 1, 0, 0, 0, 122, 120, 1, 0, 0, 0, 122, 123, 1, 0, - 0, 0, 123, 15, 1, 0, 0, 0, 124, 122, 1, 0, 0, 0, 125, 127, 5, 16, 0, 0, - 126, 125, 1, 0, 0, 0, 126, 127, 1, 0, 0, 0, 127, 128, 1, 0, 0, 0, 128, - 134, 5, 36, 0, 0, 129, 131, 5, 14, 0, 0, 130, 132, 3, 18, 9, 0, 131, 130, - 1, 0, 0, 0, 131, 132, 1, 0, 0, 0, 132, 133, 1, 0, 0, 0, 133, 135, 5, 15, - 0, 0, 134, 129, 1, 0, 0, 0, 134, 135, 1, 0, 0, 0, 135, 158, 1, 0, 0, 0, - 136, 137, 5, 14, 0, 0, 137, 138, 3, 2, 1, 0, 138, 139, 5, 15, 0, 0, 139, - 158, 1, 0, 0, 0, 140, 142, 5, 10, 0, 0, 141, 143, 3, 18, 9, 0, 142, 141, - 1, 0, 0, 0, 142, 143, 1, 0, 0, 0, 143, 145, 1, 0, 0, 0, 144, 146, 5, 17, - 0, 0, 145, 144, 1, 0, 0, 0, 145, 146, 1, 0, 0, 0, 146, 147, 1, 0, 0, 0, - 147, 158, 5, 11, 0, 0, 148, 150, 5, 12, 0, 0, 149, 151, 3, 22, 11, 0, 150, - 149, 1, 0, 0, 0, 150, 151, 1, 0, 0, 0, 151, 153, 1, 0, 0, 0, 152, 154, - 5, 17, 0, 0, 153, 152, 1, 0, 0, 0, 153, 154, 1, 0, 0, 0, 154, 155, 1, 0, - 0, 0, 155, 158, 5, 13, 0, 0, 156, 158, 3, 24, 12, 0, 157, 126, 1, 0, 0, - 0, 157, 136, 1, 0, 0, 0, 157, 140, 1, 0, 0, 0, 157, 148, 1, 0, 0, 0, 157, - 156, 1, 0, 0, 0, 158, 17, 1, 0, 0, 0, 159, 164, 3, 2, 1, 0, 160, 161, 5, - 17, 0, 0, 161, 163, 3, 2, 1, 0, 162, 160, 1, 0, 0, 0, 163, 166, 1, 0, 0, - 0, 164, 162, 1, 0, 0, 0, 164, 165, 1, 0, 0, 0, 165, 19, 1, 0, 0, 0, 166, - 164, 1, 0, 0, 0, 167, 168, 5, 36, 0, 0, 168, 169, 5, 21, 0, 0, 169, 176, - 3, 2, 1, 0, 170, 171, 5, 17, 0, 0, 171, 172, 5, 36, 0, 0, 172, 173, 5, - 21, 0, 0, 173, 175, 3, 2, 1, 0, 174, 170, 1, 0, 0, 0, 175, 178, 1, 0, 0, - 0, 176, 174, 1, 0, 0, 0, 176, 177, 1, 0, 0, 0, 177, 21, 1, 0, 0, 0, 178, - 176, 1, 0, 0, 0, 179, 180, 3, 2, 1, 0, 180, 181, 5, 21, 0, 0, 181, 189, - 3, 2, 1, 0, 182, 183, 5, 17, 0, 0, 183, 184, 3, 2, 1, 0, 184, 185, 5, 21, - 0, 0, 185, 186, 3, 2, 1, 0, 186, 188, 1, 0, 0, 0, 187, 182, 1, 0, 0, 0, - 188, 191, 1, 0, 0, 0, 189, 187, 1, 0, 0, 0, 189, 190, 1, 0, 0, 0, 190, - 23, 1, 0, 0, 0, 191, 189, 1, 0, 0, 0, 192, 194, 5, 18, 0, 0, 193, 192, - 1, 0, 0, 0, 193, 194, 1, 0, 0, 0, 194, 195, 1, 0, 0, 0, 195, 207, 5, 32, - 0, 0, 196, 207, 5, 33, 0, 0, 197, 199, 5, 18, 0, 0, 198, 197, 1, 0, 0, - 0, 198, 199, 1, 0, 0, 0, 199, 200, 1, 0, 0, 0, 200, 207, 5, 31, 0, 0, 201, - 207, 5, 34, 0, 0, 202, 207, 5, 35, 0, 0, 203, 207, 5, 26, 0, 0, 204, 207, - 5, 27, 0, 0, 205, 207, 5, 28, 0, 0, 206, 193, 1, 0, 0, 0, 206, 196, 1, - 0, 0, 0, 206, 198, 1, 0, 0, 0, 206, 201, 1, 0, 0, 0, 206, 202, 1, 0, 0, - 0, 206, 203, 1, 0, 0, 0, 206, 204, 1, 0, 0, 0, 206, 205, 1, 0, 0, 0, 207, - 25, 1, 0, 0, 0, 29, 35, 42, 50, 61, 73, 75, 82, 88, 91, 101, 104, 114, - 117, 120, 122, 126, 131, 134, 142, 145, 150, 153, 157, 164, 176, 189, 193, - 198, 206, + 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, + 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 42, 8, 1, 1, + 2, 1, 2, 1, 2, 5, 2, 47, 8, 2, 10, 2, 12, 2, 50, 9, 2, 1, 3, 1, 3, 1, 3, + 5, 3, 55, 8, 3, 10, 3, 12, 3, 58, 9, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, + 4, 5, 4, 66, 8, 4, 10, 4, 12, 4, 69, 9, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, + 1, 5, 1, 5, 1, 5, 1, 5, 5, 5, 80, 8, 5, 10, 5, 12, 5, 83, 9, 5, 1, 6, 1, + 6, 4, 6, 87, 8, 6, 11, 6, 12, 6, 88, 1, 6, 1, 6, 4, 6, 93, 8, 6, 11, 6, + 12, 6, 94, 1, 6, 3, 6, 98, 8, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 3, + 7, 106, 8, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 3, 7, 114, 8, 7, 1, 7, + 1, 7, 1, 7, 1, 7, 3, 7, 120, 8, 7, 1, 7, 1, 7, 1, 7, 5, 7, 125, 8, 7, 10, + 7, 12, 7, 128, 9, 7, 1, 8, 3, 8, 131, 8, 8, 1, 8, 1, 8, 1, 8, 3, 8, 136, + 8, 8, 1, 8, 3, 8, 139, 8, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 3, 8, + 147, 8, 8, 1, 8, 3, 8, 150, 8, 8, 1, 8, 1, 8, 1, 8, 3, 8, 155, 8, 8, 1, + 8, 3, 8, 158, 8, 8, 1, 8, 1, 8, 3, 8, 162, 8, 8, 1, 8, 1, 8, 1, 8, 5, 8, + 167, 8, 8, 10, 8, 12, 8, 170, 9, 8, 1, 8, 1, 8, 3, 8, 174, 8, 8, 1, 8, + 3, 8, 177, 8, 8, 1, 8, 1, 8, 3, 8, 181, 8, 8, 1, 9, 1, 9, 1, 9, 5, 9, 186, + 8, 9, 10, 9, 12, 9, 189, 9, 9, 1, 10, 1, 10, 1, 10, 5, 10, 194, 8, 10, + 10, 10, 12, 10, 197, 9, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, + 11, 1, 11, 5, 11, 207, 8, 11, 10, 11, 12, 11, 210, 9, 11, 1, 12, 3, 12, + 213, 8, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, + 13, 1, 13, 5, 13, 225, 8, 13, 10, 13, 12, 13, 228, 9, 13, 1, 14, 3, 14, + 231, 8, 14, 1, 14, 1, 14, 1, 15, 3, 15, 236, 8, 15, 1, 15, 1, 15, 1, 15, + 3, 15, 241, 8, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 3, 15, 249, + 8, 15, 1, 15, 0, 3, 8, 10, 14, 16, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, + 22, 24, 26, 28, 30, 0, 3, 1, 0, 1, 7, 1, 0, 23, 25, 2, 0, 18, 18, 22, 22, + 281, 0, 32, 1, 0, 0, 0, 2, 35, 1, 0, 0, 0, 4, 43, 1, 0, 0, 0, 6, 51, 1, + 0, 0, 0, 8, 59, 1, 0, 0, 0, 10, 70, 1, 0, 0, 0, 12, 97, 1, 0, 0, 0, 14, + 99, 1, 0, 0, 0, 16, 180, 1, 0, 0, 0, 18, 182, 1, 0, 0, 0, 20, 190, 1, 0, + 0, 0, 22, 198, 1, 0, 0, 0, 24, 212, 1, 0, 0, 0, 26, 216, 1, 0, 0, 0, 28, + 230, 1, 0, 0, 0, 30, 248, 1, 0, 0, 0, 32, 33, 3, 2, 1, 0, 33, 34, 5, 0, + 0, 1, 34, 1, 1, 0, 0, 0, 35, 41, 3, 4, 2, 0, 36, 37, 5, 20, 0, 0, 37, 38, + 3, 4, 2, 0, 38, 39, 5, 21, 0, 0, 39, 40, 3, 2, 1, 0, 40, 42, 1, 0, 0, 0, + 41, 36, 1, 0, 0, 0, 41, 42, 1, 0, 0, 0, 42, 3, 1, 0, 0, 0, 43, 48, 3, 6, + 3, 0, 44, 45, 5, 9, 0, 0, 45, 47, 3, 6, 3, 0, 46, 44, 1, 0, 0, 0, 47, 50, + 1, 0, 0, 0, 48, 46, 1, 0, 0, 0, 48, 49, 1, 0, 0, 0, 49, 5, 1, 0, 0, 0, + 50, 48, 1, 0, 0, 0, 51, 56, 3, 8, 4, 0, 52, 53, 5, 8, 0, 0, 53, 55, 3, + 8, 4, 0, 54, 52, 1, 0, 0, 0, 55, 58, 1, 0, 0, 0, 56, 54, 1, 0, 0, 0, 56, + 57, 1, 0, 0, 0, 57, 7, 1, 0, 0, 0, 58, 56, 1, 0, 0, 0, 59, 60, 6, 4, -1, + 0, 60, 61, 3, 10, 5, 0, 61, 67, 1, 0, 0, 0, 62, 63, 10, 1, 0, 0, 63, 64, + 7, 0, 0, 0, 64, 66, 3, 8, 4, 2, 65, 62, 1, 0, 0, 0, 66, 69, 1, 0, 0, 0, + 67, 65, 1, 0, 0, 0, 67, 68, 1, 0, 0, 0, 68, 9, 1, 0, 0, 0, 69, 67, 1, 0, + 0, 0, 70, 71, 6, 5, -1, 0, 71, 72, 3, 12, 6, 0, 72, 81, 1, 0, 0, 0, 73, + 74, 10, 2, 0, 0, 74, 75, 7, 1, 0, 0, 75, 80, 3, 10, 5, 3, 76, 77, 10, 1, + 0, 0, 77, 78, 7, 2, 0, 0, 78, 80, 3, 10, 5, 2, 79, 73, 1, 0, 0, 0, 79, + 76, 1, 0, 0, 0, 80, 83, 1, 0, 0, 0, 81, 79, 1, 0, 0, 0, 81, 82, 1, 0, 0, + 0, 82, 11, 1, 0, 0, 0, 83, 81, 1, 0, 0, 0, 84, 98, 3, 14, 7, 0, 85, 87, + 5, 19, 0, 0, 86, 85, 1, 0, 0, 0, 87, 88, 1, 0, 0, 0, 88, 86, 1, 0, 0, 0, + 88, 89, 1, 0, 0, 0, 89, 90, 1, 0, 0, 0, 90, 98, 3, 14, 7, 0, 91, 93, 5, + 18, 0, 0, 92, 91, 1, 0, 0, 0, 93, 94, 1, 0, 0, 0, 94, 92, 1, 0, 0, 0, 94, + 95, 1, 0, 0, 0, 95, 96, 1, 0, 0, 0, 96, 98, 3, 14, 7, 0, 97, 84, 1, 0, + 0, 0, 97, 86, 1, 0, 0, 0, 97, 92, 1, 0, 0, 0, 98, 13, 1, 0, 0, 0, 99, 100, + 6, 7, -1, 0, 100, 101, 3, 16, 8, 0, 101, 126, 1, 0, 0, 0, 102, 103, 10, + 3, 0, 0, 103, 105, 5, 16, 0, 0, 104, 106, 5, 20, 0, 0, 105, 104, 1, 0, + 0, 0, 105, 106, 1, 0, 0, 0, 106, 107, 1, 0, 0, 0, 107, 125, 5, 36, 0, 0, + 108, 109, 10, 2, 0, 0, 109, 110, 5, 16, 0, 0, 110, 111, 5, 36, 0, 0, 111, + 113, 5, 14, 0, 0, 112, 114, 3, 18, 9, 0, 113, 112, 1, 0, 0, 0, 113, 114, + 1, 0, 0, 0, 114, 115, 1, 0, 0, 0, 115, 125, 5, 15, 0, 0, 116, 117, 10, + 1, 0, 0, 117, 119, 5, 10, 0, 0, 118, 120, 5, 20, 0, 0, 119, 118, 1, 0, + 0, 0, 119, 120, 1, 0, 0, 0, 120, 121, 1, 0, 0, 0, 121, 122, 3, 2, 1, 0, + 122, 123, 5, 11, 0, 0, 123, 125, 1, 0, 0, 0, 124, 102, 1, 0, 0, 0, 124, + 108, 1, 0, 0, 0, 124, 116, 1, 0, 0, 0, 125, 128, 1, 0, 0, 0, 126, 124, + 1, 0, 0, 0, 126, 127, 1, 0, 0, 0, 127, 15, 1, 0, 0, 0, 128, 126, 1, 0, + 0, 0, 129, 131, 5, 16, 0, 0, 130, 129, 1, 0, 0, 0, 130, 131, 1, 0, 0, 0, + 131, 132, 1, 0, 0, 0, 132, 138, 5, 36, 0, 0, 133, 135, 5, 14, 0, 0, 134, + 136, 3, 18, 9, 0, 135, 134, 1, 0, 0, 0, 135, 136, 1, 0, 0, 0, 136, 137, + 1, 0, 0, 0, 137, 139, 5, 15, 0, 0, 138, 133, 1, 0, 0, 0, 138, 139, 1, 0, + 0, 0, 139, 181, 1, 0, 0, 0, 140, 141, 5, 14, 0, 0, 141, 142, 3, 2, 1, 0, + 142, 143, 5, 15, 0, 0, 143, 181, 1, 0, 0, 0, 144, 146, 5, 10, 0, 0, 145, + 147, 3, 20, 10, 0, 146, 145, 1, 0, 0, 0, 146, 147, 1, 0, 0, 0, 147, 149, + 1, 0, 0, 0, 148, 150, 5, 17, 0, 0, 149, 148, 1, 0, 0, 0, 149, 150, 1, 0, + 0, 0, 150, 151, 1, 0, 0, 0, 151, 181, 5, 11, 0, 0, 152, 154, 5, 12, 0, + 0, 153, 155, 3, 26, 13, 0, 154, 153, 1, 0, 0, 0, 154, 155, 1, 0, 0, 0, + 155, 157, 1, 0, 0, 0, 156, 158, 5, 17, 0, 0, 157, 156, 1, 0, 0, 0, 157, + 158, 1, 0, 0, 0, 158, 159, 1, 0, 0, 0, 159, 181, 5, 13, 0, 0, 160, 162, + 5, 16, 0, 0, 161, 160, 1, 0, 0, 0, 161, 162, 1, 0, 0, 0, 162, 163, 1, 0, + 0, 0, 163, 168, 5, 36, 0, 0, 164, 165, 5, 16, 0, 0, 165, 167, 5, 36, 0, + 0, 166, 164, 1, 0, 0, 0, 167, 170, 1, 0, 0, 0, 168, 166, 1, 0, 0, 0, 168, + 169, 1, 0, 0, 0, 169, 171, 1, 0, 0, 0, 170, 168, 1, 0, 0, 0, 171, 173, + 5, 12, 0, 0, 172, 174, 3, 22, 11, 0, 173, 172, 1, 0, 0, 0, 173, 174, 1, + 0, 0, 0, 174, 176, 1, 0, 0, 0, 175, 177, 5, 17, 0, 0, 176, 175, 1, 0, 0, + 0, 176, 177, 1, 0, 0, 0, 177, 178, 1, 0, 0, 0, 178, 181, 5, 13, 0, 0, 179, + 181, 3, 30, 15, 0, 180, 130, 1, 0, 0, 0, 180, 140, 1, 0, 0, 0, 180, 144, + 1, 0, 0, 0, 180, 152, 1, 0, 0, 0, 180, 161, 1, 0, 0, 0, 180, 179, 1, 0, + 0, 0, 181, 17, 1, 0, 0, 0, 182, 187, 3, 2, 1, 0, 183, 184, 5, 17, 0, 0, + 184, 186, 3, 2, 1, 0, 185, 183, 1, 0, 0, 0, 186, 189, 1, 0, 0, 0, 187, + 185, 1, 0, 0, 0, 187, 188, 1, 0, 0, 0, 188, 19, 1, 0, 0, 0, 189, 187, 1, + 0, 0, 0, 190, 195, 3, 28, 14, 0, 191, 192, 5, 17, 0, 0, 192, 194, 3, 28, + 14, 0, 193, 191, 1, 0, 0, 0, 194, 197, 1, 0, 0, 0, 195, 193, 1, 0, 0, 0, + 195, 196, 1, 0, 0, 0, 196, 21, 1, 0, 0, 0, 197, 195, 1, 0, 0, 0, 198, 199, + 3, 24, 12, 0, 199, 200, 5, 21, 0, 0, 200, 208, 3, 2, 1, 0, 201, 202, 5, + 17, 0, 0, 202, 203, 3, 24, 12, 0, 203, 204, 5, 21, 0, 0, 204, 205, 3, 2, + 1, 0, 205, 207, 1, 0, 0, 0, 206, 201, 1, 0, 0, 0, 207, 210, 1, 0, 0, 0, + 208, 206, 1, 0, 0, 0, 208, 209, 1, 0, 0, 0, 209, 23, 1, 0, 0, 0, 210, 208, + 1, 0, 0, 0, 211, 213, 5, 20, 0, 0, 212, 211, 1, 0, 0, 0, 212, 213, 1, 0, + 0, 0, 213, 214, 1, 0, 0, 0, 214, 215, 5, 36, 0, 0, 215, 25, 1, 0, 0, 0, + 216, 217, 3, 28, 14, 0, 217, 218, 5, 21, 0, 0, 218, 226, 3, 2, 1, 0, 219, + 220, 5, 17, 0, 0, 220, 221, 3, 28, 14, 0, 221, 222, 5, 21, 0, 0, 222, 223, + 3, 2, 1, 0, 223, 225, 1, 0, 0, 0, 224, 219, 1, 0, 0, 0, 225, 228, 1, 0, + 0, 0, 226, 224, 1, 0, 0, 0, 226, 227, 1, 0, 0, 0, 227, 27, 1, 0, 0, 0, + 228, 226, 1, 0, 0, 0, 229, 231, 5, 20, 0, 0, 230, 229, 1, 0, 0, 0, 230, + 231, 1, 0, 0, 0, 231, 232, 1, 0, 0, 0, 232, 233, 3, 2, 1, 0, 233, 29, 1, + 0, 0, 0, 234, 236, 5, 18, 0, 0, 235, 234, 1, 0, 0, 0, 235, 236, 1, 0, 0, + 0, 236, 237, 1, 0, 0, 0, 237, 249, 5, 32, 0, 0, 238, 249, 5, 33, 0, 0, + 239, 241, 5, 18, 0, 0, 240, 239, 1, 0, 0, 0, 240, 241, 1, 0, 0, 0, 241, + 242, 1, 0, 0, 0, 242, 249, 5, 31, 0, 0, 243, 249, 5, 34, 0, 0, 244, 249, + 5, 35, 0, 0, 245, 249, 5, 26, 0, 0, 246, 249, 5, 27, 0, 0, 247, 249, 5, + 28, 0, 0, 248, 235, 1, 0, 0, 0, 248, 238, 1, 0, 0, 0, 248, 240, 1, 0, 0, + 0, 248, 243, 1, 0, 0, 0, 248, 244, 1, 0, 0, 0, 248, 245, 1, 0, 0, 0, 248, + 246, 1, 0, 0, 0, 248, 247, 1, 0, 0, 0, 249, 31, 1, 0, 0, 0, 35, 41, 48, + 56, 67, 79, 81, 88, 94, 97, 105, 113, 119, 124, 126, 130, 135, 138, 146, + 149, 154, 157, 161, 168, 173, 176, 180, 187, 195, 208, 212, 226, 230, 235, + 240, 248, } deserializer := antlr.NewATNDeserializer(nil) staticData.atn = deserializer.Deserialize(staticData.serializedATN) @@ -234,9 +253,12 @@ const ( CELParserRULE_member = 7 CELParserRULE_primary = 8 CELParserRULE_exprList = 9 - CELParserRULE_fieldInitializerList = 10 - CELParserRULE_mapInitializerList = 11 - CELParserRULE_literal = 12 + CELParserRULE_listInit = 10 + CELParserRULE_fieldInitializerList = 11 + CELParserRULE_optField = 12 + CELParserRULE_mapInitializerList = 13 + CELParserRULE_optExpr = 14 + CELParserRULE_literal = 15 ) // IStartContext is an interface to support dynamic dispatch. @@ -252,6 +274,10 @@ type IStartContext interface { // SetE sets the e rule contexts. SetE(IExprContext) + // Getter signatures + EOF() antlr.TerminalNode + Expr() IExprContext + // IsStartContext differentiates from other interfaces. IsStartContext() } @@ -363,14 +389,14 @@ func (p *CELParser) Start() (localctx IStartContext) { p.EnterOuterAlt(localctx, 1) { - p.SetState(26) + p.SetState(32) var _x = p.Expr() localctx.(*StartContext).e = _x } { - p.SetState(27) + p.SetState(33) p.Match(CELParserEOF) } @@ -408,6 +434,13 @@ type IExprContext interface { // SetE2 sets the e2 rule contexts. SetE2(IExprContext) + // Getter signatures + AllConditionalOr() []IConditionalOrContext + ConditionalOr(i int) IConditionalOrContext + COLON() antlr.TerminalNode + QUESTIONMARK() antlr.TerminalNode + Expr() IExprContext + // IsExprContext differentiates from other interfaces. IsExprContext() } @@ -580,37 +613,37 @@ func (p *CELParser) Expr() (localctx IExprContext) { p.EnterOuterAlt(localctx, 1) { - p.SetState(29) + p.SetState(35) var _x = p.ConditionalOr() localctx.(*ExprContext).e = _x } - p.SetState(35) + p.SetState(41) p.GetErrorHandler().Sync(p) _la = p.GetTokenStream().LA(1) if _la == CELParserQUESTIONMARK { { - p.SetState(30) + p.SetState(36) var _m = p.Match(CELParserQUESTIONMARK) localctx.(*ExprContext).op = _m } { - p.SetState(31) + p.SetState(37) var _x = p.ConditionalOr() localctx.(*ExprContext).e1 = _x } { - p.SetState(32) + p.SetState(38) p.Match(CELParserCOLON) } { - p.SetState(33) + p.SetState(39) var _x = p.Expr() @@ -659,6 +692,12 @@ type IConditionalOrContext interface { // SetE1 sets the e1 rule context list. SetE1([]IConditionalAndContext) + // Getter signatures + AllConditionalAnd() []IConditionalAndContext + ConditionalAnd(i int) IConditionalAndContext + AllLOGICAL_OR() []antlr.TerminalNode + LOGICAL_OR(i int) antlr.TerminalNode + // IsConditionalOrContext differentiates from other interfaces. IsConditionalOrContext() } @@ -820,19 +859,19 @@ func (p *CELParser) ConditionalOr() (localctx IConditionalOrContext) { p.EnterOuterAlt(localctx, 1) { - p.SetState(37) + p.SetState(43) var _x = p.ConditionalAnd() localctx.(*ConditionalOrContext).e = _x } - p.SetState(42) + p.SetState(48) p.GetErrorHandler().Sync(p) _la = p.GetTokenStream().LA(1) for _la == CELParserLOGICAL_OR { { - p.SetState(38) + p.SetState(44) var _m = p.Match(CELParserLOGICAL_OR) @@ -840,7 +879,7 @@ func (p *CELParser) ConditionalOr() (localctx IConditionalOrContext) { } localctx.(*ConditionalOrContext).ops = append(localctx.(*ConditionalOrContext).ops, localctx.(*ConditionalOrContext).s9) { - p.SetState(39) + p.SetState(45) var _x = p.ConditionalAnd() @@ -848,7 +887,7 @@ func (p *CELParser) ConditionalOr() (localctx IConditionalOrContext) { } localctx.(*ConditionalOrContext).e1 = append(localctx.(*ConditionalOrContext).e1, localctx.(*ConditionalOrContext)._conditionalAnd) - p.SetState(44) + p.SetState(50) p.GetErrorHandler().Sync(p) _la = p.GetTokenStream().LA(1) } @@ -893,6 +932,12 @@ type IConditionalAndContext interface { // SetE1 sets the e1 rule context list. SetE1([]IRelationContext) + // Getter signatures + AllRelation() []IRelationContext + Relation(i int) IRelationContext + AllLOGICAL_AND() []antlr.TerminalNode + LOGICAL_AND(i int) antlr.TerminalNode + // IsConditionalAndContext differentiates from other interfaces. IsConditionalAndContext() } @@ -1054,19 +1099,19 @@ func (p *CELParser) ConditionalAnd() (localctx IConditionalAndContext) { p.EnterOuterAlt(localctx, 1) { - p.SetState(45) + p.SetState(51) var _x = p.relation(0) localctx.(*ConditionalAndContext).e = _x } - p.SetState(50) + p.SetState(56) p.GetErrorHandler().Sync(p) _la = p.GetTokenStream().LA(1) for _la == CELParserLOGICAL_AND { { - p.SetState(46) + p.SetState(52) var _m = p.Match(CELParserLOGICAL_AND) @@ -1074,7 +1119,7 @@ func (p *CELParser) ConditionalAnd() (localctx IConditionalAndContext) { } localctx.(*ConditionalAndContext).ops = append(localctx.(*ConditionalAndContext).ops, localctx.(*ConditionalAndContext).s8) { - p.SetState(47) + p.SetState(53) var _x = p.relation(0) @@ -1082,7 +1127,7 @@ func (p *CELParser) ConditionalAnd() (localctx IConditionalAndContext) { } localctx.(*ConditionalAndContext).e1 = append(localctx.(*ConditionalAndContext).e1, localctx.(*ConditionalAndContext)._relation) - p.SetState(52) + p.SetState(58) p.GetErrorHandler().Sync(p) _la = p.GetTokenStream().LA(1) } @@ -1103,6 +1148,18 @@ type IRelationContext interface { // SetOp sets the op token. SetOp(antlr.Token) + // Getter signatures + Calc() ICalcContext + AllRelation() []IRelationContext + Relation(i int) IRelationContext + LESS() antlr.TerminalNode + LESS_EQUALS() antlr.TerminalNode + GREATER_EQUALS() antlr.TerminalNode + GREATER() antlr.TerminalNode + EQUALS() antlr.TerminalNode + NOT_EQUALS() antlr.TerminalNode + IN() antlr.TerminalNode + // IsRelationContext differentiates from other interfaces. IsRelationContext() } @@ -1291,12 +1348,12 @@ func (p *CELParser) relation(_p int) (localctx IRelationContext) { p.EnterOuterAlt(localctx, 1) { - p.SetState(54) + p.SetState(60) p.calc(0) } p.GetParserRuleContext().SetStop(p.GetTokenStream().LT(-1)) - p.SetState(61) + p.SetState(67) p.GetErrorHandler().Sync(p) _alt = p.GetInterpreter().AdaptivePredict(p.GetTokenStream(), 3, p.GetParserRuleContext()) @@ -1308,13 +1365,13 @@ func (p *CELParser) relation(_p int) (localctx IRelationContext) { _prevctx = localctx localctx = NewRelationContext(p, _parentctx, _parentState) p.PushNewRecursionContext(localctx, _startState, CELParserRULE_relation) - p.SetState(56) + p.SetState(62) if !(p.Precpred(p.GetParserRuleContext(), 1)) { panic(antlr.NewFailedPredicateException(p, "p.Precpred(p.GetParserRuleContext(), 1)", "")) } { - p.SetState(57) + p.SetState(63) var _lt = p.GetTokenStream().LT(1) @@ -1322,7 +1379,7 @@ func (p *CELParser) relation(_p int) (localctx IRelationContext) { _la = p.GetTokenStream().LA(1) - if !(((_la)&-(0x1f+1)) == 0 && ((1<.map(, ) -// .map(, , ) +// +// .map(, ) +// .map(, , ) +// // In the second form only iterVar values which return true when provided to the predicate expression // are transformed. func MakeMap(eh ExprHelper, target *exprpb.Expr, args []*exprpb.Expr) (*exprpb.Expr, *common.Error) { diff --git a/vendor/github.com/google/cel-go/parser/options.go b/vendor/github.com/google/cel-go/parser/options.go index b50686a912..674c697c5c 100644 --- a/vendor/github.com/google/cel-go/parser/options.go +++ b/vendor/github.com/google/cel-go/parser/options.go @@ -18,11 +18,13 @@ import "fmt" type options struct { maxRecursionDepth int + errorReportingLimit int errorRecoveryTokenLookaheadLimit int errorRecoveryLimit int expressionSizeCodePointLimit int macros map[string]Macro populateMacroCalls bool + enableOptionalSyntax bool } // Option configures the behavior of the parser. @@ -45,7 +47,7 @@ func MaxRecursionDepth(limit int) Option { // successfully resume. In some pathological cases, the parser can look through quite a large set of input which // in turn generates a lot of back-tracking and performance degredation. // -// The limit must be > 1, and is recommended to be less than the default of 256. +// The limit must be >= 1, and is recommended to be less than the default of 256. func ErrorRecoveryLookaheadTokenLimit(limit int) Option { return func(opts *options) error { if limit < 1 { @@ -67,6 +69,19 @@ func ErrorRecoveryLimit(limit int) Option { } } +// ErrorReportingLimit limits the number of syntax error reports before terminating parsing. +// +// The limit must be at least 1. If unset, the limit will be 100. +func ErrorReportingLimit(limit int) Option { + return func(opts *options) error { + if limit < 1 { + return fmt.Errorf("error reporting limit must be at least 1: %d", limit) + } + opts.errorReportingLimit = limit + return nil + } +} + // ExpressionSizeCodePointLimit is an option which limits the maximum code point count of an // expression. func ExpressionSizeCodePointLimit(expressionSizeCodePointLimit int) Option { @@ -102,3 +117,11 @@ func PopulateMacroCalls(populateMacroCalls bool) Option { return nil } } + +// EnableOptionalSyntax enables syntax for optional field and index selection. +func EnableOptionalSyntax(optionalSyntax bool) Option { + return func(opts *options) error { + opts.enableOptionalSyntax = optionalSyntax + return nil + } +} diff --git a/vendor/github.com/google/cel-go/parser/parser.go b/vendor/github.com/google/cel-go/parser/parser.go index 072f624574..e6f70f9060 100644 --- a/vendor/github.com/google/cel-go/parser/parser.go +++ b/vendor/github.com/google/cel-go/parser/parser.go @@ -18,11 +18,13 @@ package parser import ( "fmt" + "regexp" "strconv" "strings" "sync" - "github.com/antlr/antlr4/runtime/Go/antlr" + antlr "github.com/antlr/antlr4/runtime/Go/antlr/v4" + "github.com/google/cel-go/common" "github.com/google/cel-go/common/operators" "github.com/google/cel-go/common/runes" @@ -45,6 +47,9 @@ func NewParser(opts ...Option) (*Parser, error) { return nil, err } } + if p.errorReportingLimit == 0 { + p.errorReportingLimit = 100 + } if p.maxRecursionDepth == 0 { p.maxRecursionDepth = 250 } @@ -89,9 +94,11 @@ func (p *Parser) Parse(source common.Source) (*exprpb.ParsedExpr, *common.Errors helper: newParserHelper(source), macros: p.macros, maxRecursionDepth: p.maxRecursionDepth, + errorReportingLimit: p.errorReportingLimit, errorRecoveryLimit: p.errorRecoveryLimit, errorRecoveryLookaheadTokenLimit: p.errorRecoveryTokenLookaheadLimit, populateMacroCalls: p.populateMacroCalls, + enableOptionalSyntax: p.enableOptionalSyntax, } buf, ok := source.(runes.Buffer) if !ok { @@ -178,7 +185,7 @@ func (rl *recursionListener) EnterEveryRule(ctx antlr.ParserRuleContext) { } else { *depth++ } - if *depth >= rl.maxDepth { + if *depth > rl.maxDepth { panic(&recursionError{ message: fmt.Sprintf("expression recursion limit exceeded: %d", rl.maxDepth), }) @@ -197,6 +204,16 @@ func (rl *recursionListener) ExitEveryRule(ctx antlr.ParserRuleContext) { var _ antlr.ParseTreeListener = &recursionListener{} +type tooManyErrors struct { + errorReportingLimit int +} + +func (t *tooManyErrors) Error() string { + return fmt.Sprintf("More than %d syntax errors", t.errorReportingLimit) +} + +var _ error = &tooManyErrors{} + type recoveryLimitError struct { message string } @@ -271,17 +288,20 @@ type parser struct { helper *parserHelper macros map[string]Macro recursionDepth int + errorReports int maxRecursionDepth int + errorReportingLimit int errorRecoveryLimit int errorRecoveryLookaheadTokenLimit int populateMacroCalls bool + enableOptionalSyntax bool } var ( _ gen.CELVisitor = (*parser)(nil) lexerPool *sync.Pool = &sync.Pool{ - New: func() interface{} { + New: func() any { l := gen.NewCELLexer(nil) l.RemoveErrorListeners() return l @@ -289,7 +309,7 @@ var ( } parserPool *sync.Pool = &sync.Pool{ - New: func() interface{} { + New: func() any { p := gen.NewCELParser(nil) p.RemoveErrorListeners() return p @@ -302,14 +322,14 @@ func (p *parser) parse(expr runes.Buffer, desc string) *exprpb.Expr { lexer := lexerPool.Get().(*gen.CELLexer) prsr := parserPool.Get().(*gen.CELParser) - // Unfortunately ANTLR Go runtime is missing (*antlr.BaseParser).RemoveParseListeners, so this is - // good enough until that is exported. prsrListener := &recursionListener{ maxDepth: p.maxRecursionDepth, ruleTypeDepth: map[int]*int{}, } defer func() { + // Unfortunately ANTLR Go runtime is missing (*antlr.BaseParser).RemoveParseListeners, + // so this is good enough until that is exported. // Reset the lexer and parser before putting them back in the pool. lexer.RemoveErrorListeners() prsr.RemoveParseListener(prsrListener) @@ -340,6 +360,8 @@ func (p *parser) parse(expr runes.Buffer, desc string) *exprpb.Expr { p.errors.ReportError(common.NoLocation, err.Error()) case *recursionError: p.errors.ReportError(common.NoLocation, err.Error()) + case *tooManyErrors: + // do nothing case *recoveryLimitError: // do nothing, listeners already notified and error reported. default: @@ -352,57 +374,85 @@ func (p *parser) parse(expr runes.Buffer, desc string) *exprpb.Expr { } // Visitor implementations. -func (p *parser) Visit(tree antlr.ParseTree) interface{} { - p.recursionDepth++ - if p.recursionDepth > p.maxRecursionDepth { - panic(&recursionError{message: "max recursion depth exceeded"}) - } - defer func() { - p.recursionDepth-- - }() - switch tree.(type) { +func (p *parser) Visit(tree antlr.ParseTree) any { + t := unnest(tree) + switch tree := t.(type) { case *gen.StartContext: - return p.VisitStart(tree.(*gen.StartContext)) + return p.VisitStart(tree) case *gen.ExprContext: - return p.VisitExpr(tree.(*gen.ExprContext)) + p.checkAndIncrementRecursionDepth() + out := p.VisitExpr(tree) + p.decrementRecursionDepth() + return out case *gen.ConditionalAndContext: - return p.VisitConditionalAnd(tree.(*gen.ConditionalAndContext)) + return p.VisitConditionalAnd(tree) case *gen.ConditionalOrContext: - return p.VisitConditionalOr(tree.(*gen.ConditionalOrContext)) + return p.VisitConditionalOr(tree) case *gen.RelationContext: - return p.VisitRelation(tree.(*gen.RelationContext)) + p.checkAndIncrementRecursionDepth() + out := p.VisitRelation(tree) + p.decrementRecursionDepth() + return out case *gen.CalcContext: - return p.VisitCalc(tree.(*gen.CalcContext)) + p.checkAndIncrementRecursionDepth() + out := p.VisitCalc(tree) + p.decrementRecursionDepth() + return out case *gen.LogicalNotContext: - return p.VisitLogicalNot(tree.(*gen.LogicalNotContext)) - case *gen.MemberExprContext: - return p.VisitMemberExpr(tree.(*gen.MemberExprContext)) - case *gen.PrimaryExprContext: - return p.VisitPrimaryExpr(tree.(*gen.PrimaryExprContext)) - case *gen.SelectOrCallContext: - return p.VisitSelectOrCall(tree.(*gen.SelectOrCallContext)) + return p.VisitLogicalNot(tree) + case *gen.IdentOrGlobalCallContext: + return p.VisitIdentOrGlobalCall(tree) + case *gen.SelectContext: + p.checkAndIncrementRecursionDepth() + out := p.VisitSelect(tree) + p.decrementRecursionDepth() + return out + case *gen.MemberCallContext: + p.checkAndIncrementRecursionDepth() + out := p.VisitMemberCall(tree) + p.decrementRecursionDepth() + return out case *gen.MapInitializerListContext: - return p.VisitMapInitializerList(tree.(*gen.MapInitializerListContext)) + return p.VisitMapInitializerList(tree) case *gen.NegateContext: - return p.VisitNegate(tree.(*gen.NegateContext)) + return p.VisitNegate(tree) case *gen.IndexContext: - return p.VisitIndex(tree.(*gen.IndexContext)) + p.checkAndIncrementRecursionDepth() + out := p.VisitIndex(tree) + p.decrementRecursionDepth() + return out case *gen.UnaryContext: - return p.VisitUnary(tree.(*gen.UnaryContext)) + return p.VisitUnary(tree) case *gen.CreateListContext: - return p.VisitCreateList(tree.(*gen.CreateListContext)) + return p.VisitCreateList(tree) case *gen.CreateMessageContext: - return p.VisitCreateMessage(tree.(*gen.CreateMessageContext)) + return p.VisitCreateMessage(tree) case *gen.CreateStructContext: - return p.VisitCreateStruct(tree.(*gen.CreateStructContext)) + return p.VisitCreateStruct(tree) + case *gen.IntContext: + return p.VisitInt(tree) + case *gen.UintContext: + return p.VisitUint(tree) + case *gen.DoubleContext: + return p.VisitDouble(tree) + case *gen.StringContext: + return p.VisitString(tree) + case *gen.BytesContext: + return p.VisitBytes(tree) + case *gen.BoolFalseContext: + return p.VisitBoolFalse(tree) + case *gen.BoolTrueContext: + return p.VisitBoolTrue(tree) + case *gen.NullContext: + return p.VisitNull(tree) } // Report at least one error if the parser reaches an unknown parse element. // Typically, this happens if the parser has already encountered a syntax error elsewhere. if len(p.errors.GetErrors()) == 0 { txt := "<>" - if tree != nil { - txt = fmt.Sprintf("<<%T>>", tree) + if t != nil { + txt = fmt.Sprintf("<<%T>>", t) } return p.reportError(common.NoLocation, "unknown parse element encountered: %s", txt) } @@ -411,12 +461,12 @@ func (p *parser) Visit(tree antlr.ParseTree) interface{} { } // Visit a parse tree produced by CELParser#start. -func (p *parser) VisitStart(ctx *gen.StartContext) interface{} { +func (p *parser) VisitStart(ctx *gen.StartContext) any { return p.Visit(ctx.Expr()) } // Visit a parse tree produced by CELParser#expr. -func (p *parser) VisitExpr(ctx *gen.ExprContext) interface{} { +func (p *parser) VisitExpr(ctx *gen.ExprContext) any { result := p.Visit(ctx.GetE()).(*exprpb.Expr) if ctx.GetOp() == nil { return result @@ -428,11 +478,8 @@ func (p *parser) VisitExpr(ctx *gen.ExprContext) interface{} { } // Visit a parse tree produced by CELParser#conditionalOr. -func (p *parser) VisitConditionalOr(ctx *gen.ConditionalOrContext) interface{} { +func (p *parser) VisitConditionalOr(ctx *gen.ConditionalOrContext) any { result := p.Visit(ctx.GetE()).(*exprpb.Expr) - if ctx.GetOps() == nil { - return result - } b := newBalancer(p.helper, operators.LogicalOr, result) rest := ctx.GetE1() for i, op := range ctx.GetOps() { @@ -447,11 +494,8 @@ func (p *parser) VisitConditionalOr(ctx *gen.ConditionalOrContext) interface{} { } // Visit a parse tree produced by CELParser#conditionalAnd. -func (p *parser) VisitConditionalAnd(ctx *gen.ConditionalAndContext) interface{} { +func (p *parser) VisitConditionalAnd(ctx *gen.ConditionalAndContext) any { result := p.Visit(ctx.GetE()).(*exprpb.Expr) - if ctx.GetOps() == nil { - return result - } b := newBalancer(p.helper, operators.LogicalAnd, result) rest := ctx.GetE1() for i, op := range ctx.GetOps() { @@ -466,10 +510,7 @@ func (p *parser) VisitConditionalAnd(ctx *gen.ConditionalAndContext) interface{} } // Visit a parse tree produced by CELParser#relation. -func (p *parser) VisitRelation(ctx *gen.RelationContext) interface{} { - if ctx.Calc() != nil { - return p.Visit(ctx.Calc()) - } +func (p *parser) VisitRelation(ctx *gen.RelationContext) any { opText := "" if ctx.GetOp() != nil { opText = ctx.GetOp().GetText() @@ -484,10 +525,7 @@ func (p *parser) VisitRelation(ctx *gen.RelationContext) interface{} { } // Visit a parse tree produced by CELParser#calc. -func (p *parser) VisitCalc(ctx *gen.CalcContext) interface{} { - if ctx.Unary() != nil { - return p.Visit(ctx.Unary()) - } +func (p *parser) VisitCalc(ctx *gen.CalcContext) any { opText := "" if ctx.GetOp() != nil { opText = ctx.GetOp().GetText() @@ -501,27 +539,12 @@ func (p *parser) VisitCalc(ctx *gen.CalcContext) interface{} { return p.reportError(ctx, "operator not found") } -func (p *parser) VisitUnary(ctx *gen.UnaryContext) interface{} { +func (p *parser) VisitUnary(ctx *gen.UnaryContext) any { return p.helper.newLiteralString(ctx, "<>") } -// Visit a parse tree produced by CELParser#MemberExpr. -func (p *parser) VisitMemberExpr(ctx *gen.MemberExprContext) interface{} { - switch ctx.Member().(type) { - case *gen.PrimaryExprContext: - return p.VisitPrimaryExpr(ctx.Member().(*gen.PrimaryExprContext)) - case *gen.SelectOrCallContext: - return p.VisitSelectOrCall(ctx.Member().(*gen.SelectOrCallContext)) - case *gen.IndexContext: - return p.VisitIndex(ctx.Member().(*gen.IndexContext)) - case *gen.CreateMessageContext: - return p.VisitCreateMessage(ctx.Member().(*gen.CreateMessageContext)) - } - return p.reportError(ctx, "unsupported simple expression") -} - // Visit a parse tree produced by CELParser#LogicalNot. -func (p *parser) VisitLogicalNot(ctx *gen.LogicalNotContext) interface{} { +func (p *parser) VisitLogicalNot(ctx *gen.LogicalNotContext) any { if len(ctx.GetOps())%2 == 0 { return p.Visit(ctx.Member()) } @@ -530,7 +553,7 @@ func (p *parser) VisitLogicalNot(ctx *gen.LogicalNotContext) interface{} { return p.globalCallOrMacro(opID, operators.LogicalNot, target) } -func (p *parser) VisitNegate(ctx *gen.NegateContext) interface{} { +func (p *parser) VisitNegate(ctx *gen.NegateContext) any { if len(ctx.GetOps())%2 == 0 { return p.Visit(ctx.Member()) } @@ -539,60 +562,77 @@ func (p *parser) VisitNegate(ctx *gen.NegateContext) interface{} { return p.globalCallOrMacro(opID, operators.Negate, target) } -// Visit a parse tree produced by CELParser#SelectOrCall. -func (p *parser) VisitSelectOrCall(ctx *gen.SelectOrCallContext) interface{} { +// VisitSelect visits a parse tree produced by CELParser#Select. +func (p *parser) VisitSelect(ctx *gen.SelectContext) any { operand := p.Visit(ctx.Member()).(*exprpb.Expr) // Handle the error case where no valid identifier is specified. - if ctx.GetId() == nil { + if ctx.GetId() == nil || ctx.GetOp() == nil { return p.helper.newExpr(ctx) } id := ctx.GetId().GetText() - if ctx.GetOpen() != nil { - opID := p.helper.id(ctx.GetOpen()) - return p.receiverCallOrMacro(opID, id, operand, p.visitList(ctx.GetArgs())...) + if ctx.GetOpt() != nil { + if !p.enableOptionalSyntax { + return p.reportError(ctx.GetOp(), "unsupported syntax '.?'") + } + return p.helper.newGlobalCall( + ctx.GetOp(), + operators.OptSelect, + operand, + p.helper.newLiteralString(ctx.GetId(), id)) } return p.helper.newSelect(ctx.GetOp(), operand, id) } -// Visit a parse tree produced by CELParser#PrimaryExpr. -func (p *parser) VisitPrimaryExpr(ctx *gen.PrimaryExprContext) interface{} { - switch ctx.Primary().(type) { - case *gen.NestedContext: - return p.VisitNested(ctx.Primary().(*gen.NestedContext)) - case *gen.IdentOrGlobalCallContext: - return p.VisitIdentOrGlobalCall(ctx.Primary().(*gen.IdentOrGlobalCallContext)) - case *gen.CreateListContext: - return p.VisitCreateList(ctx.Primary().(*gen.CreateListContext)) - case *gen.CreateStructContext: - return p.VisitCreateStruct(ctx.Primary().(*gen.CreateStructContext)) - case *gen.ConstantLiteralContext: - return p.VisitConstantLiteral(ctx.Primary().(*gen.ConstantLiteralContext)) +// VisitMemberCall visits a parse tree produced by CELParser#MemberCall. +func (p *parser) VisitMemberCall(ctx *gen.MemberCallContext) any { + operand := p.Visit(ctx.Member()).(*exprpb.Expr) + // Handle the error case where no valid identifier is specified. + if ctx.GetId() == nil { + return p.helper.newExpr(ctx) } - - return p.reportError(ctx, "invalid primary expression") + id := ctx.GetId().GetText() + opID := p.helper.id(ctx.GetOpen()) + return p.receiverCallOrMacro(opID, id, operand, p.visitExprList(ctx.GetArgs())...) } // Visit a parse tree produced by CELParser#Index. -func (p *parser) VisitIndex(ctx *gen.IndexContext) interface{} { +func (p *parser) VisitIndex(ctx *gen.IndexContext) any { target := p.Visit(ctx.Member()).(*exprpb.Expr) + // Handle the error case where no valid identifier is specified. + if ctx.GetOp() == nil { + return p.helper.newExpr(ctx) + } opID := p.helper.id(ctx.GetOp()) index := p.Visit(ctx.GetIndex()).(*exprpb.Expr) - return p.globalCallOrMacro(opID, operators.Index, target, index) + operator := operators.Index + if ctx.GetOpt() != nil { + if !p.enableOptionalSyntax { + return p.reportError(ctx.GetOp(), "unsupported syntax '[?'") + } + operator = operators.OptIndex + } + return p.globalCallOrMacro(opID, operator, target, index) } // Visit a parse tree produced by CELParser#CreateMessage. -func (p *parser) VisitCreateMessage(ctx *gen.CreateMessageContext) interface{} { - target := p.Visit(ctx.Member()).(*exprpb.Expr) - objID := p.helper.id(ctx.GetOp()) - if messageName, found := p.extractQualifiedName(target); found { - entries := p.VisitIFieldInitializerList(ctx.GetEntries()).([]*exprpb.Expr_CreateStruct_Entry) - return p.helper.newObject(objID, messageName, entries...) +func (p *parser) VisitCreateMessage(ctx *gen.CreateMessageContext) any { + messageName := "" + for _, id := range ctx.GetIds() { + if len(messageName) != 0 { + messageName += "." + } + messageName += id.GetText() + } + if ctx.GetLeadingDot() != nil { + messageName = "." + messageName } - return p.helper.newExpr(objID) + objID := p.helper.id(ctx.GetOp()) + entries := p.VisitIFieldInitializerList(ctx.GetEntries()).([]*exprpb.Expr_CreateStruct_Entry) + return p.helper.newObject(objID, messageName, entries...) } // Visit a parse tree of field initializers. -func (p *parser) VisitIFieldInitializerList(ctx gen.IFieldInitializerListContext) interface{} { +func (p *parser) VisitIFieldInitializerList(ctx gen.IFieldInitializerListContext) any { if ctx == nil || ctx.GetFields() == nil { // This is the result of a syntax error handled elswhere, return empty. return []*exprpb.Expr_CreateStruct_Entry{} @@ -607,15 +647,27 @@ func (p *parser) VisitIFieldInitializerList(ctx gen.IFieldInitializerListContext return []*exprpb.Expr_CreateStruct_Entry{} } initID := p.helper.id(cols[i]) + optField := f.(*gen.OptFieldContext) + optional := optField.GetOpt() != nil + if !p.enableOptionalSyntax && optional { + p.reportError(optField, "unsupported syntax '?'") + continue + } + // The field may be empty due to a prior error. + id := optField.IDENTIFIER() + if id == nil { + return []*exprpb.Expr_CreateStruct_Entry{} + } + fieldName := id.GetText() value := p.Visit(vals[i]).(*exprpb.Expr) - field := p.helper.newObjectField(initID, f.GetText(), value) + field := p.helper.newObjectField(initID, fieldName, value, optional) result[i] = field } return result } // Visit a parse tree produced by CELParser#IdentOrGlobalCall. -func (p *parser) VisitIdentOrGlobalCall(ctx *gen.IdentOrGlobalCallContext) interface{} { +func (p *parser) VisitIdentOrGlobalCall(ctx *gen.IdentOrGlobalCallContext) any { identName := "" if ctx.GetLeadingDot() != nil { identName = "." @@ -632,24 +684,20 @@ func (p *parser) VisitIdentOrGlobalCall(ctx *gen.IdentOrGlobalCallContext) inter identName += id if ctx.GetOp() != nil { opID := p.helper.id(ctx.GetOp()) - return p.globalCallOrMacro(opID, identName, p.visitList(ctx.GetArgs())...) + return p.globalCallOrMacro(opID, identName, p.visitExprList(ctx.GetArgs())...) } return p.helper.newIdent(ctx.GetId(), identName) } -// Visit a parse tree produced by CELParser#Nested. -func (p *parser) VisitNested(ctx *gen.NestedContext) interface{} { - return p.Visit(ctx.GetE()) -} - // Visit a parse tree produced by CELParser#CreateList. -func (p *parser) VisitCreateList(ctx *gen.CreateListContext) interface{} { +func (p *parser) VisitCreateList(ctx *gen.CreateListContext) any { listID := p.helper.id(ctx.GetOp()) - return p.helper.newList(listID, p.visitList(ctx.GetElems())...) + elems, optionals := p.visitListInit(ctx.GetElems()) + return p.helper.newList(listID, elems, optionals...) } // Visit a parse tree produced by CELParser#CreateStruct. -func (p *parser) VisitCreateStruct(ctx *gen.CreateStructContext) interface{} { +func (p *parser) VisitCreateStruct(ctx *gen.CreateStructContext) any { structID := p.helper.id(ctx.GetOp()) entries := []*exprpb.Expr_CreateStruct_Entry{} if ctx.GetEntries() != nil { @@ -658,31 +706,8 @@ func (p *parser) VisitCreateStruct(ctx *gen.CreateStructContext) interface{} { return p.helper.newMap(structID, entries...) } -// Visit a parse tree produced by CELParser#ConstantLiteral. -func (p *parser) VisitConstantLiteral(ctx *gen.ConstantLiteralContext) interface{} { - switch ctx.Literal().(type) { - case *gen.IntContext: - return p.VisitInt(ctx.Literal().(*gen.IntContext)) - case *gen.UintContext: - return p.VisitUint(ctx.Literal().(*gen.UintContext)) - case *gen.DoubleContext: - return p.VisitDouble(ctx.Literal().(*gen.DoubleContext)) - case *gen.StringContext: - return p.VisitString(ctx.Literal().(*gen.StringContext)) - case *gen.BytesContext: - return p.VisitBytes(ctx.Literal().(*gen.BytesContext)) - case *gen.BoolFalseContext: - return p.VisitBoolFalse(ctx.Literal().(*gen.BoolFalseContext)) - case *gen.BoolTrueContext: - return p.VisitBoolTrue(ctx.Literal().(*gen.BoolTrueContext)) - case *gen.NullContext: - return p.VisitNull(ctx.Literal().(*gen.NullContext)) - } - return p.reportError(ctx, "invalid literal") -} - // Visit a parse tree produced by CELParser#mapInitializerList. -func (p *parser) VisitMapInitializerList(ctx *gen.MapInitializerListContext) interface{} { +func (p *parser) VisitMapInitializerList(ctx *gen.MapInitializerListContext) any { if ctx == nil || ctx.GetKeys() == nil { // This is the result of a syntax error handled elswhere, return empty. return []*exprpb.Expr_CreateStruct_Entry{} @@ -697,16 +722,22 @@ func (p *parser) VisitMapInitializerList(ctx *gen.MapInitializerListContext) int // This is the result of a syntax error detected elsewhere. return []*exprpb.Expr_CreateStruct_Entry{} } - key := p.Visit(keys[i]).(*exprpb.Expr) + optKey := keys[i] + optional := optKey.GetOpt() != nil + if !p.enableOptionalSyntax && optional { + p.reportError(optKey, "unsupported syntax '?'") + continue + } + key := p.Visit(optKey.GetE()).(*exprpb.Expr) value := p.Visit(vals[i]).(*exprpb.Expr) - entry := p.helper.newMapEntry(colID, key, value) + entry := p.helper.newMapEntry(colID, key, value, optional) result[i] = entry } return result } // Visit a parse tree produced by CELParser#Int. -func (p *parser) VisitInt(ctx *gen.IntContext) interface{} { +func (p *parser) VisitInt(ctx *gen.IntContext) any { text := ctx.GetTok().GetText() base := 10 if strings.HasPrefix(text, "0x") { @@ -724,7 +755,7 @@ func (p *parser) VisitInt(ctx *gen.IntContext) interface{} { } // Visit a parse tree produced by CELParser#Uint. -func (p *parser) VisitUint(ctx *gen.UintContext) interface{} { +func (p *parser) VisitUint(ctx *gen.UintContext) any { text := ctx.GetTok().GetText() // trim the 'u' designator included in the uint literal. text = text[:len(text)-1] @@ -741,7 +772,7 @@ func (p *parser) VisitUint(ctx *gen.UintContext) interface{} { } // Visit a parse tree produced by CELParser#Double. -func (p *parser) VisitDouble(ctx *gen.DoubleContext) interface{} { +func (p *parser) VisitDouble(ctx *gen.DoubleContext) any { txt := ctx.GetTok().GetText() if ctx.GetSign() != nil { txt = ctx.GetSign().GetText() + txt @@ -755,42 +786,66 @@ func (p *parser) VisitDouble(ctx *gen.DoubleContext) interface{} { } // Visit a parse tree produced by CELParser#String. -func (p *parser) VisitString(ctx *gen.StringContext) interface{} { +func (p *parser) VisitString(ctx *gen.StringContext) any { s := p.unquote(ctx, ctx.GetText(), false) return p.helper.newLiteralString(ctx, s) } // Visit a parse tree produced by CELParser#Bytes. -func (p *parser) VisitBytes(ctx *gen.BytesContext) interface{} { +func (p *parser) VisitBytes(ctx *gen.BytesContext) any { b := []byte(p.unquote(ctx, ctx.GetTok().GetText()[1:], true)) return p.helper.newLiteralBytes(ctx, b) } // Visit a parse tree produced by CELParser#BoolTrue. -func (p *parser) VisitBoolTrue(ctx *gen.BoolTrueContext) interface{} { +func (p *parser) VisitBoolTrue(ctx *gen.BoolTrueContext) any { return p.helper.newLiteralBool(ctx, true) } // Visit a parse tree produced by CELParser#BoolFalse. -func (p *parser) VisitBoolFalse(ctx *gen.BoolFalseContext) interface{} { +func (p *parser) VisitBoolFalse(ctx *gen.BoolFalseContext) any { return p.helper.newLiteralBool(ctx, false) } // Visit a parse tree produced by CELParser#Null. -func (p *parser) VisitNull(ctx *gen.NullContext) interface{} { +func (p *parser) VisitNull(ctx *gen.NullContext) any { return p.helper.newLiteral(ctx, &exprpb.Constant{ ConstantKind: &exprpb.Constant_NullValue{ NullValue: structpb.NullValue_NULL_VALUE}}) } -func (p *parser) visitList(ctx gen.IExprListContext) []*exprpb.Expr { +func (p *parser) visitExprList(ctx gen.IExprListContext) []*exprpb.Expr { if ctx == nil { return []*exprpb.Expr{} } return p.visitSlice(ctx.GetE()) } +func (p *parser) visitListInit(ctx gen.IListInitContext) ([]*exprpb.Expr, []int32) { + if ctx == nil { + return []*exprpb.Expr{}, []int32{} + } + elements := ctx.GetElems() + result := make([]*exprpb.Expr, len(elements)) + optionals := []int32{} + for i, e := range elements { + ex := p.Visit(e.GetE()).(*exprpb.Expr) + if ex == nil { + return []*exprpb.Expr{}, []int32{} + } + result[i] = ex + if e.GetOpt() != nil { + if !p.enableOptionalSyntax { + p.reportError(e.GetOpt(), "unsupported syntax '?'") + continue + } + optionals = append(optionals, int32(i)) + } + } + return result, optionals +} + func (p *parser) visitSlice(expressions []gen.IExprContext) []*exprpb.Expr { if expressions == nil { return []*exprpb.Expr{} @@ -803,26 +858,7 @@ func (p *parser) visitSlice(expressions []gen.IExprContext) []*exprpb.Expr { return result } -func (p *parser) extractQualifiedName(e *exprpb.Expr) (string, bool) { - if e == nil { - return "", false - } - switch e.GetExprKind().(type) { - case *exprpb.Expr_IdentExpr: - return e.GetIdentExpr().GetName(), true - case *exprpb.Expr_SelectExpr: - s := e.GetSelectExpr() - if prefix, found := p.extractQualifiedName(s.GetOperand()); found { - return prefix + "." + s.GetField(), true - } - } - // TODO: Add a method to Source to get location from character offset. - location := p.helper.getLocation(e.GetId()) - p.reportError(location, "expected a qualified name") - return "", false -} - -func (p *parser) unquote(ctx interface{}, value string, isBytes bool) string { +func (p *parser) unquote(ctx any, value string, isBytes bool) string { text, err := unescape(value, isBytes) if err != nil { p.reportError(ctx, "%s", err.Error()) @@ -831,7 +867,7 @@ func (p *parser) unquote(ctx interface{}, value string, isBytes bool) string { return text } -func (p *parser) reportError(ctx interface{}, format string, args ...interface{}) *exprpb.Expr { +func (p *parser) reportError(ctx any, format string, args ...any) *exprpb.Expr { var location common.Location switch ctx.(type) { case common.Location: @@ -847,10 +883,24 @@ func (p *parser) reportError(ctx interface{}, format string, args ...interface{} } // ANTLR Parse listener implementations -func (p *parser) SyntaxError(recognizer antlr.Recognizer, offendingSymbol interface{}, line, column int, msg string, e antlr.RecognitionException) { - // TODO: Snippet +func (p *parser) SyntaxError(recognizer antlr.Recognizer, offendingSymbol any, line, column int, msg string, e antlr.RecognitionException) { l := p.helper.source.NewLocation(line, column) - p.errors.syntaxError(l, msg) + // Hack to keep existing error messages consistent with previous versions of CEL when a reserved word + // is used as an identifier. This behavior needs to be overhauled to provide consistent, normalized error + // messages out of ANTLR to prevent future breaking changes related to error message content. + if strings.Contains(msg, "no viable alternative") { + msg = reservedIdentifier.ReplaceAllString(msg, mismatchedReservedIdentifier) + } + // Ensure that no more than 100 syntax errors are reported as this will halt attempts to recover from a + // seriously broken expression. + if p.errorReports < p.errorReportingLimit { + p.errorReports++ + p.errors.syntaxError(l, msg) + } else { + tme := &tooManyErrors{errorReportingLimit: p.errorReportingLimit} + p.errors.syntaxError(l, tme.Error()) + panic(tme) + } } func (p *parser) ReportAmbiguity(recognizer antlr.Parser, dfa *antlr.DFA, startIndex, stopIndex int, exact bool, ambigAlts *antlr.BitSet, configs antlr.ATNConfigSet) { @@ -892,14 +942,95 @@ func (p *parser) expandMacro(exprID int64, function string, target *exprpb.Expr, eh.parserHelper = p.helper eh.id = exprID expr, err := macro.Expander()(eh, target, args) + // An error indicates that the macro was matched, but the arguments were not well-formed. if err != nil { if err.Location != nil { return p.reportError(err.Location, err.Message), true } return p.reportError(p.helper.getLocation(exprID), err.Message), true } + // A nil value from the macro indicates that the macro implementation decided that + // an expansion should not be performed. + if expr == nil { + return nil, false + } if p.populateMacroCalls { p.helper.addMacroCall(expr.GetId(), function, target, args...) } return expr, true } + +func (p *parser) checkAndIncrementRecursionDepth() { + p.recursionDepth++ + if p.recursionDepth > p.maxRecursionDepth { + panic(&recursionError{message: "max recursion depth exceeded"}) + } +} + +func (p *parser) decrementRecursionDepth() { + p.recursionDepth-- +} + +// unnest traverses down the left-hand side of the parse graph until it encounters the first compound +// parse node or the first leaf in the parse graph. +func unnest(tree antlr.ParseTree) antlr.ParseTree { + for tree != nil { + switch t := tree.(type) { + case *gen.ExprContext: + // conditionalOr op='?' conditionalOr : expr + if t.GetOp() != nil { + return t + } + // conditionalOr + tree = t.GetE() + case *gen.ConditionalOrContext: + // conditionalAnd (ops=|| conditionalAnd)* + if t.GetOps() != nil && len(t.GetOps()) > 0 { + return t + } + // conditionalAnd + tree = t.GetE() + case *gen.ConditionalAndContext: + // relation (ops=&& relation)* + if t.GetOps() != nil && len(t.GetOps()) > 0 { + return t + } + // relation + tree = t.GetE() + case *gen.RelationContext: + // relation op relation + if t.GetOp() != nil { + return t + } + // calc + tree = t.Calc() + case *gen.CalcContext: + // calc op calc + if t.GetOp() != nil { + return t + } + // unary + tree = t.Unary() + case *gen.MemberExprContext: + // member expands to one of: primary, select, index, or create message + tree = t.Member() + case *gen.PrimaryExprContext: + // primary expands to one of identifier, nested, create list, create struct, literal + tree = t.Primary() + case *gen.NestedContext: + // contains a nested 'expr' + tree = t.GetE() + case *gen.ConstantLiteralContext: + // expands to a primitive literal + tree = t.Literal() + default: + return t + } + } + return tree +} + +var ( + reservedIdentifier = regexp.MustCompile("no viable alternative at input '.(true|false|null)'") + mismatchedReservedIdentifier = "mismatched input '$1' expecting IDENTIFIER" +) diff --git a/vendor/github.com/google/cel-go/parser/unparser.go b/vendor/github.com/google/cel-go/parser/unparser.go index a459bb4a98..c3c40a0dd3 100644 --- a/vendor/github.com/google/cel-go/parser/unparser.go +++ b/vendor/github.com/google/cel-go/parser/unparser.go @@ -106,9 +106,15 @@ func (un *unparser) visitCall(expr *exprpb.Expr) error { // ternary operator case operators.Conditional: return un.visitCallConditional(expr) + // optional select operator + case operators.OptSelect: + return un.visitOptSelect(expr) // index operator case operators.Index: return un.visitCallIndex(expr) + // optional index operator + case operators.OptIndex: + return un.visitCallOptIndex(expr) // unary operators case operators.LogicalNot, operators.Negate: return un.visitCallUnary(expr) @@ -218,6 +224,14 @@ func (un *unparser) visitCallFunc(expr *exprpb.Expr) error { } func (un *unparser) visitCallIndex(expr *exprpb.Expr) error { + return un.visitCallIndexInternal(expr, "[") +} + +func (un *unparser) visitCallOptIndex(expr *exprpb.Expr) error { + return un.visitCallIndexInternal(expr, "[?") +} + +func (un *unparser) visitCallIndexInternal(expr *exprpb.Expr, op string) error { c := expr.GetCallExpr() args := c.GetArgs() nested := isBinaryOrTernaryOperator(args[0]) @@ -225,7 +239,7 @@ func (un *unparser) visitCallIndex(expr *exprpb.Expr) error { if err != nil { return err } - un.str.WriteString("[") + un.str.WriteString(op) err = un.visit(args[1]) if err != nil { return err @@ -262,6 +276,9 @@ func (un *unparser) visitConst(expr *exprpb.Expr) error { // represent the float using the minimum required digits d := strconv.FormatFloat(c.GetDoubleValue(), 'g', -1, 64) un.str.WriteString(d) + if !strings.Contains(d, ".") { + un.str.WriteString(".0") + } case *exprpb.Constant_Int64Value: i := strconv.FormatInt(c.GetInt64Value(), 10) un.str.WriteString(i) @@ -289,8 +306,15 @@ func (un *unparser) visitIdent(expr *exprpb.Expr) error { func (un *unparser) visitList(expr *exprpb.Expr) error { l := expr.GetListExpr() elems := l.GetElements() + optIndices := make(map[int]bool, len(elems)) + for _, idx := range l.GetOptionalIndices() { + optIndices[int(idx)] = true + } un.str.WriteString("[") for i, elem := range elems { + if optIndices[i] { + un.str.WriteString("?") + } err := un.visit(elem) if err != nil { return err @@ -303,20 +327,32 @@ func (un *unparser) visitList(expr *exprpb.Expr) error { return nil } +func (un *unparser) visitOptSelect(expr *exprpb.Expr) error { + c := expr.GetCallExpr() + args := c.GetArgs() + operand := args[0] + field := args[1].GetConstExpr().GetStringValue() + return un.visitSelectInternal(operand, false, ".?", field) +} + func (un *unparser) visitSelect(expr *exprpb.Expr) error { sel := expr.GetSelectExpr() + return un.visitSelectInternal(sel.GetOperand(), sel.GetTestOnly(), ".", sel.GetField()) +} + +func (un *unparser) visitSelectInternal(operand *exprpb.Expr, testOnly bool, op string, field string) error { // handle the case when the select expression was generated by the has() macro. - if sel.GetTestOnly() { + if testOnly { un.str.WriteString("has(") } - nested := !sel.GetTestOnly() && isBinaryOrTernaryOperator(sel.GetOperand()) - err := un.visitMaybeNested(sel.GetOperand(), nested) + nested := !testOnly && isBinaryOrTernaryOperator(operand) + err := un.visitMaybeNested(operand, nested) if err != nil { return err } - un.str.WriteString(".") - un.str.WriteString(sel.GetField()) - if sel.GetTestOnly() { + un.str.WriteString(op) + un.str.WriteString(field) + if testOnly { un.str.WriteString(")") } return nil @@ -339,6 +375,9 @@ func (un *unparser) visitStructMsg(expr *exprpb.Expr) error { un.str.WriteString("{") for i, entry := range entries { f := entry.GetFieldKey() + if entry.GetOptionalEntry() { + un.str.WriteString("?") + } un.str.WriteString(f) un.str.WriteString(": ") v := entry.GetValue() @@ -360,6 +399,9 @@ func (un *unparser) visitStructMap(expr *exprpb.Expr) error { un.str.WriteString("{") for i, entry := range entries { k := entry.GetMapKey() + if entry.GetOptionalEntry() { + un.str.WriteString("?") + } err := un.visit(k) if err != nil { return err @@ -492,11 +534,10 @@ func (un *unparser) writeOperatorWithWrapping(fun string, unmangled string) bool un.str.WriteString(" ") } return true - } else { - un.str.WriteString(" ") - un.str.WriteString(unmangled) - un.str.WriteString(" ") } + un.str.WriteString(" ") + un.str.WriteString(unmangled) + un.str.WriteString(" ") return false } diff --git a/vendor/github.com/google/go-cmp/cmp/compare.go b/vendor/github.com/google/go-cmp/cmp/compare.go index fd2b3a42b2..087320da7f 100644 --- a/vendor/github.com/google/go-cmp/cmp/compare.go +++ b/vendor/github.com/google/go-cmp/cmp/compare.go @@ -13,21 +13,21 @@ // // The primary features of cmp are: // -// • When the default behavior of equality does not suit the needs of the test, -// custom equality functions can override the equality operation. -// For example, an equality function may report floats as equal so long as they -// are within some tolerance of each other. +// - When the default behavior of equality does not suit the test's needs, +// custom equality functions can override the equality operation. +// For example, an equality function may report floats as equal so long as +// they are within some tolerance of each other. // -// • Types that have an Equal method may use that method to determine equality. -// This allows package authors to determine the equality operation for the types -// that they define. +// - Types with an Equal method may use that method to determine equality. +// This allows package authors to determine the equality operation +// for the types that they define. // -// • If no custom equality functions are used and no Equal method is defined, -// equality is determined by recursively comparing the primitive kinds on both -// values, much like reflect.DeepEqual. Unlike reflect.DeepEqual, unexported -// fields are not compared by default; they result in panics unless suppressed -// by using an Ignore option (see cmpopts.IgnoreUnexported) or explicitly -// compared using the Exporter option. +// - If no custom equality functions are used and no Equal method is defined, +// equality is determined by recursively comparing the primitive kinds on +// both values, much like reflect.DeepEqual. Unlike reflect.DeepEqual, +// unexported fields are not compared by default; they result in panics +// unless suppressed by using an Ignore option (see cmpopts.IgnoreUnexported) +// or explicitly compared using the Exporter option. package cmp import ( @@ -45,25 +45,25 @@ import ( // Equal reports whether x and y are equal by recursively applying the // following rules in the given order to x and y and all of their sub-values: // -// • Let S be the set of all Ignore, Transformer, and Comparer options that -// remain after applying all path filters, value filters, and type filters. -// If at least one Ignore exists in S, then the comparison is ignored. -// If the number of Transformer and Comparer options in S is greater than one, -// then Equal panics because it is ambiguous which option to use. -// If S contains a single Transformer, then use that to transform the current -// values and recursively call Equal on the output values. -// If S contains a single Comparer, then use that to compare the current values. -// Otherwise, evaluation proceeds to the next rule. +// - Let S be the set of all Ignore, Transformer, and Comparer options that +// remain after applying all path filters, value filters, and type filters. +// If at least one Ignore exists in S, then the comparison is ignored. +// If the number of Transformer and Comparer options in S is non-zero, +// then Equal panics because it is ambiguous which option to use. +// If S contains a single Transformer, then use that to transform +// the current values and recursively call Equal on the output values. +// If S contains a single Comparer, then use that to compare the current values. +// Otherwise, evaluation proceeds to the next rule. // -// • If the values have an Equal method of the form "(T) Equal(T) bool" or -// "(T) Equal(I) bool" where T is assignable to I, then use the result of -// x.Equal(y) even if x or y is nil. Otherwise, no such method exists and -// evaluation proceeds to the next rule. +// - If the values have an Equal method of the form "(T) Equal(T) bool" or +// "(T) Equal(I) bool" where T is assignable to I, then use the result of +// x.Equal(y) even if x or y is nil. Otherwise, no such method exists and +// evaluation proceeds to the next rule. // -// • Lastly, try to compare x and y based on their basic kinds. -// Simple kinds like booleans, integers, floats, complex numbers, strings, and -// channels are compared using the equivalent of the == operator in Go. -// Functions are only equal if they are both nil, otherwise they are unequal. +// - Lastly, try to compare x and y based on their basic kinds. +// Simple kinds like booleans, integers, floats, complex numbers, strings, +// and channels are compared using the equivalent of the == operator in Go. +// Functions are only equal if they are both nil, otherwise they are unequal. // // Structs are equal if recursively calling Equal on all fields report equal. // If a struct contains unexported fields, Equal panics unless an Ignore option @@ -144,7 +144,7 @@ func rootStep(x, y interface{}) PathStep { // so that they have the same parent type. var t reflect.Type if !vx.IsValid() || !vy.IsValid() || vx.Type() != vy.Type() { - t = reflect.TypeOf((*interface{})(nil)).Elem() + t = anyType if vx.IsValid() { vvx := reflect.New(t).Elem() vvx.Set(vx) @@ -639,7 +639,9 @@ type dynChecker struct{ curr, next int } // Next increments the state and reports whether a check should be performed. // // Checks occur every Nth function call, where N is a triangular number: +// // 0 1 3 6 10 15 21 28 36 45 55 66 78 91 105 120 136 153 171 190 ... +// // See https://en.wikipedia.org/wiki/Triangular_number // // This sequence ensures that the cost of checks drops significantly as diff --git a/vendor/github.com/google/go-cmp/cmp/internal/diff/diff.go b/vendor/github.com/google/go-cmp/cmp/internal/diff/diff.go index bc196b16cf..a248e5436d 100644 --- a/vendor/github.com/google/go-cmp/cmp/internal/diff/diff.go +++ b/vendor/github.com/google/go-cmp/cmp/internal/diff/diff.go @@ -127,9 +127,9 @@ var randBool = rand.New(rand.NewSource(time.Now().Unix())).Intn(2) == 0 // This function returns an edit-script, which is a sequence of operations // needed to convert one list into the other. The following invariants for // the edit-script are maintained: -// • eq == (es.Dist()==0) -// • nx == es.LenX() -// • ny == es.LenY() +// - eq == (es.Dist()==0) +// - nx == es.LenX() +// - ny == es.LenY() // // This algorithm is not guaranteed to be an optimal solution (i.e., one that // produces an edit-script with a minimal Levenshtein distance). This algorithm @@ -169,12 +169,13 @@ func Difference(nx, ny int, f EqualFunc) (es EditScript) { // A diagonal edge is equivalent to a matching symbol between both X and Y. // Invariants: - // • 0 ≤ fwdPath.X ≤ (fwdFrontier.X, revFrontier.X) ≤ revPath.X ≤ nx - // • 0 ≤ fwdPath.Y ≤ (fwdFrontier.Y, revFrontier.Y) ≤ revPath.Y ≤ ny + // - 0 ≤ fwdPath.X ≤ (fwdFrontier.X, revFrontier.X) ≤ revPath.X ≤ nx + // - 0 ≤ fwdPath.Y ≤ (fwdFrontier.Y, revFrontier.Y) ≤ revPath.Y ≤ ny // // In general: - // • fwdFrontier.X < revFrontier.X - // • fwdFrontier.Y < revFrontier.Y + // - fwdFrontier.X < revFrontier.X + // - fwdFrontier.Y < revFrontier.Y + // // Unless, it is time for the algorithm to terminate. fwdPath := path{+1, point{0, 0}, make(EditScript, 0, (nx+ny)/2)} revPath := path{-1, point{nx, ny}, make(EditScript, 0)} @@ -195,19 +196,21 @@ func Difference(nx, ny int, f EqualFunc) (es EditScript) { // computing sub-optimal edit-scripts between two lists. // // The algorithm is approximately as follows: - // • Searching for differences switches back-and-forth between - // a search that starts at the beginning (the top-left corner), and - // a search that starts at the end (the bottom-right corner). The goal of - // the search is connect with the search from the opposite corner. - // • As we search, we build a path in a greedy manner, where the first - // match seen is added to the path (this is sub-optimal, but provides a - // decent result in practice). When matches are found, we try the next pair - // of symbols in the lists and follow all matches as far as possible. - // • When searching for matches, we search along a diagonal going through - // through the "frontier" point. If no matches are found, we advance the - // frontier towards the opposite corner. - // • This algorithm terminates when either the X coordinates or the - // Y coordinates of the forward and reverse frontier points ever intersect. + // - Searching for differences switches back-and-forth between + // a search that starts at the beginning (the top-left corner), and + // a search that starts at the end (the bottom-right corner). + // The goal of the search is connect with the search + // from the opposite corner. + // - As we search, we build a path in a greedy manner, + // where the first match seen is added to the path (this is sub-optimal, + // but provides a decent result in practice). When matches are found, + // we try the next pair of symbols in the lists and follow all matches + // as far as possible. + // - When searching for matches, we search along a diagonal going through + // through the "frontier" point. If no matches are found, + // we advance the frontier towards the opposite corner. + // - This algorithm terminates when either the X coordinates or the + // Y coordinates of the forward and reverse frontier points ever intersect. // This algorithm is correct even if searching only in the forward direction // or in the reverse direction. We do both because it is commonly observed @@ -389,6 +392,7 @@ type point struct{ X, Y int } func (p *point) add(dx, dy int) { p.X += dx; p.Y += dy } // zigzag maps a consecutive sequence of integers to a zig-zag sequence. +// // [0 1 2 3 4 5 ...] => [0 -1 +1 -2 +2 ...] func zigzag(x int) int { if x&1 != 0 { diff --git a/vendor/github.com/google/go-cmp/cmp/internal/value/zero.go b/vendor/github.com/google/go-cmp/cmp/internal/value/zero.go deleted file mode 100644 index 9147a29973..0000000000 --- a/vendor/github.com/google/go-cmp/cmp/internal/value/zero.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2017, The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package value - -import ( - "math" - "reflect" -) - -// IsZero reports whether v is the zero value. -// This does not rely on Interface and so can be used on unexported fields. -func IsZero(v reflect.Value) bool { - switch v.Kind() { - case reflect.Bool: - return v.Bool() == false - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return v.Int() == 0 - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return v.Uint() == 0 - case reflect.Float32, reflect.Float64: - return math.Float64bits(v.Float()) == 0 - case reflect.Complex64, reflect.Complex128: - return math.Float64bits(real(v.Complex())) == 0 && math.Float64bits(imag(v.Complex())) == 0 - case reflect.String: - return v.String() == "" - case reflect.UnsafePointer: - return v.Pointer() == 0 - case reflect.Chan, reflect.Func, reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice: - return v.IsNil() - case reflect.Array: - for i := 0; i < v.Len(); i++ { - if !IsZero(v.Index(i)) { - return false - } - } - return true - case reflect.Struct: - for i := 0; i < v.NumField(); i++ { - if !IsZero(v.Field(i)) { - return false - } - } - return true - } - return false -} diff --git a/vendor/github.com/google/go-cmp/cmp/options.go b/vendor/github.com/google/go-cmp/cmp/options.go index e57b9eb539..1f9ca9c489 100644 --- a/vendor/github.com/google/go-cmp/cmp/options.go +++ b/vendor/github.com/google/go-cmp/cmp/options.go @@ -33,6 +33,7 @@ type Option interface { } // applicableOption represents the following types: +// // Fundamental: ignore | validator | *comparer | *transformer // Grouping: Options type applicableOption interface { @@ -43,6 +44,7 @@ type applicableOption interface { } // coreOption represents the following types: +// // Fundamental: ignore | validator | *comparer | *transformer // Filters: *pathFilter | *valuesFilter type coreOption interface { @@ -336,9 +338,9 @@ func (tr transformer) String() string { // both implement T. // // The equality function must be: -// • Symmetric: equal(x, y) == equal(y, x) -// • Deterministic: equal(x, y) == equal(x, y) -// • Pure: equal(x, y) does not modify x or y +// - Symmetric: equal(x, y) == equal(y, x) +// - Deterministic: equal(x, y) == equal(x, y) +// - Pure: equal(x, y) does not modify x or y func Comparer(f interface{}) Option { v := reflect.ValueOf(f) if !function.IsType(v.Type(), function.Equal) || v.IsNil() { @@ -430,7 +432,7 @@ func AllowUnexported(types ...interface{}) Option { } // Result represents the comparison result for a single node and -// is provided by cmp when calling Result (see Reporter). +// is provided by cmp when calling Report (see Reporter). type Result struct { _ [0]func() // Make Result incomparable flags resultFlags diff --git a/vendor/github.com/google/go-cmp/cmp/path.go b/vendor/github.com/google/go-cmp/cmp/path.go index c710034632..a0a588502e 100644 --- a/vendor/github.com/google/go-cmp/cmp/path.go +++ b/vendor/github.com/google/go-cmp/cmp/path.go @@ -41,13 +41,13 @@ type PathStep interface { // The type of each valid value is guaranteed to be identical to Type. // // In some cases, one or both may be invalid or have restrictions: - // • For StructField, both are not interface-able if the current field - // is unexported and the struct type is not explicitly permitted by - // an Exporter to traverse unexported fields. - // • For SliceIndex, one may be invalid if an element is missing from - // either the x or y slice. - // • For MapIndex, one may be invalid if an entry is missing from - // either the x or y map. + // - For StructField, both are not interface-able if the current field + // is unexported and the struct type is not explicitly permitted by + // an Exporter to traverse unexported fields. + // - For SliceIndex, one may be invalid if an element is missing from + // either the x or y slice. + // - For MapIndex, one may be invalid if an entry is missing from + // either the x or y map. // // The provided values must not be mutated. Values() (vx, vy reflect.Value) @@ -94,6 +94,7 @@ func (pa Path) Index(i int) PathStep { // The simplified path only contains struct field accesses. // // For example: +// // MyMap.MySlices.MyField func (pa Path) String() string { var ss []string @@ -108,6 +109,7 @@ func (pa Path) String() string { // GoString returns the path to a specific node using Go syntax. // // For example: +// // (*root.MyMap["key"].(*mypkg.MyStruct).MySlices)[2][3].MyField func (pa Path) GoString() string { var ssPre, ssPost []string @@ -159,7 +161,7 @@ func (ps pathStep) String() string { if ps.typ == nil { return "" } - s := ps.typ.String() + s := value.TypeString(ps.typ, false) if s == "" || strings.ContainsAny(s, "{}\n") { return "root" // Type too simple or complex to print } @@ -282,7 +284,7 @@ type typeAssertion struct { func (ta TypeAssertion) Type() reflect.Type { return ta.typ } func (ta TypeAssertion) Values() (vx, vy reflect.Value) { return ta.vx, ta.vy } -func (ta TypeAssertion) String() string { return fmt.Sprintf(".(%v)", ta.typ) } +func (ta TypeAssertion) String() string { return fmt.Sprintf(".(%v)", value.TypeString(ta.typ, false)) } // Transform is a transformation from the parent type to the current type. type Transform struct{ *transform } diff --git a/vendor/github.com/google/go-cmp/cmp/report_compare.go b/vendor/github.com/google/go-cmp/cmp/report_compare.go index 1ef65ac1db..2050bf6b46 100644 --- a/vendor/github.com/google/go-cmp/cmp/report_compare.go +++ b/vendor/github.com/google/go-cmp/cmp/report_compare.go @@ -7,8 +7,6 @@ package cmp import ( "fmt" "reflect" - - "github.com/google/go-cmp/cmp/internal/value" ) // numContextRecords is the number of surrounding equal records to print. @@ -117,7 +115,7 @@ func (opts formatOptions) FormatDiff(v *valueNode, ptrs *pointerReferences) (out // For leaf nodes, format the value based on the reflect.Values alone. // As a special case, treat equal []byte as a leaf nodes. - isBytes := v.Type.Kind() == reflect.Slice && v.Type.Elem() == reflect.TypeOf(byte(0)) + isBytes := v.Type.Kind() == reflect.Slice && v.Type.Elem() == byteType isEqualBytes := isBytes && v.NumDiff+v.NumIgnored+v.NumTransformed == 0 if v.MaxDepth == 0 || isEqualBytes { switch opts.DiffMode { @@ -248,11 +246,11 @@ func (opts formatOptions) formatDiffList(recs []reportRecord, k reflect.Kind, pt var isZero bool switch opts.DiffMode { case diffIdentical: - isZero = value.IsZero(r.Value.ValueX) || value.IsZero(r.Value.ValueY) + isZero = r.Value.ValueX.IsZero() || r.Value.ValueY.IsZero() case diffRemoved: - isZero = value.IsZero(r.Value.ValueX) + isZero = r.Value.ValueX.IsZero() case diffInserted: - isZero = value.IsZero(r.Value.ValueY) + isZero = r.Value.ValueY.IsZero() } if isZero { continue diff --git a/vendor/github.com/google/go-cmp/cmp/report_reflect.go b/vendor/github.com/google/go-cmp/cmp/report_reflect.go index 287b893588..2ab41fad3f 100644 --- a/vendor/github.com/google/go-cmp/cmp/report_reflect.go +++ b/vendor/github.com/google/go-cmp/cmp/report_reflect.go @@ -16,6 +16,13 @@ import ( "github.com/google/go-cmp/cmp/internal/value" ) +var ( + anyType = reflect.TypeOf((*interface{})(nil)).Elem() + stringType = reflect.TypeOf((*string)(nil)).Elem() + bytesType = reflect.TypeOf((*[]byte)(nil)).Elem() + byteType = reflect.TypeOf((*byte)(nil)).Elem() +) + type formatValueOptions struct { // AvoidStringer controls whether to avoid calling custom stringer // methods like error.Error or fmt.Stringer.String. @@ -184,7 +191,7 @@ func (opts formatOptions) FormatValue(v reflect.Value, parentKind reflect.Kind, } for i := 0; i < v.NumField(); i++ { vv := v.Field(i) - if value.IsZero(vv) { + if vv.IsZero() { continue // Elide fields with zero values } if len(list) == maxLen { @@ -205,7 +212,7 @@ func (opts formatOptions) FormatValue(v reflect.Value, parentKind reflect.Kind, } // Check whether this is a []byte of text data. - if t.Elem() == reflect.TypeOf(byte(0)) { + if t.Elem() == byteType { b := v.Bytes() isPrintSpace := func(r rune) bool { return unicode.IsPrint(r) || unicode.IsSpace(r) } if len(b) > 0 && utf8.Valid(b) && len(bytes.TrimFunc(b, isPrintSpace)) == 0 { diff --git a/vendor/github.com/google/go-cmp/cmp/report_slices.go b/vendor/github.com/google/go-cmp/cmp/report_slices.go index 68b5c1ae16..23e444f62f 100644 --- a/vendor/github.com/google/go-cmp/cmp/report_slices.go +++ b/vendor/github.com/google/go-cmp/cmp/report_slices.go @@ -104,7 +104,7 @@ func (opts formatOptions) FormatDiffSlice(v *valueNode) textNode { case t.Kind() == reflect.String: sx, sy = vx.String(), vy.String() isString = true - case t.Kind() == reflect.Slice && t.Elem() == reflect.TypeOf(byte(0)): + case t.Kind() == reflect.Slice && t.Elem() == byteType: sx, sy = string(vx.Bytes()), string(vy.Bytes()) isString = true case t.Kind() == reflect.Array: @@ -147,7 +147,10 @@ func (opts formatOptions) FormatDiffSlice(v *valueNode) textNode { }) efficiencyLines := float64(esLines.Dist()) / float64(len(esLines)) efficiencyBytes := float64(esBytes.Dist()) / float64(len(esBytes)) - isPureLinedText = efficiencyLines < 4*efficiencyBytes + quotedLength := len(strconv.Quote(sx + sy)) + unquotedLength := len(sx) + len(sy) + escapeExpansionRatio := float64(quotedLength) / float64(unquotedLength) + isPureLinedText = efficiencyLines < 4*efficiencyBytes || escapeExpansionRatio > 1.1 } } @@ -171,12 +174,13 @@ func (opts formatOptions) FormatDiffSlice(v *valueNode) textNode { // differences in a string literal. This format is more readable, // but has edge-cases where differences are visually indistinguishable. // This format is avoided under the following conditions: - // • A line starts with `"""` - // • A line starts with "..." - // • A line contains non-printable characters - // • Adjacent different lines differ only by whitespace + // - A line starts with `"""` + // - A line starts with "..." + // - A line contains non-printable characters + // - Adjacent different lines differ only by whitespace // // For example: + // // """ // ... // 3 identical lines // foo @@ -231,7 +235,7 @@ func (opts formatOptions) FormatDiffSlice(v *valueNode) textNode { var out textNode = &textWrap{Prefix: "(", Value: list2, Suffix: ")"} switch t.Kind() { case reflect.String: - if t != reflect.TypeOf(string("")) { + if t != stringType { out = opts.FormatType(t, out) } case reflect.Slice: @@ -326,12 +330,12 @@ func (opts formatOptions) FormatDiffSlice(v *valueNode) textNode { switch t.Kind() { case reflect.String: out = &textWrap{Prefix: "strings.Join(", Value: out, Suffix: fmt.Sprintf(", %q)", delim)} - if t != reflect.TypeOf(string("")) { + if t != stringType { out = opts.FormatType(t, out) } case reflect.Slice: out = &textWrap{Prefix: "bytes.Join(", Value: out, Suffix: fmt.Sprintf(", %q)", delim)} - if t != reflect.TypeOf([]byte(nil)) { + if t != bytesType { out = opts.FormatType(t, out) } } @@ -446,7 +450,6 @@ func (opts formatOptions) formatDiffSlice( // {NumIdentical: 3}, // {NumInserted: 1}, // ] -// func coalesceAdjacentEdits(name string, es diff.EditScript) (groups []diffStats) { var prevMode byte lastStats := func(mode byte) *diffStats { @@ -503,7 +506,6 @@ func coalesceAdjacentEdits(name string, es diff.EditScript) (groups []diffStats) // {NumIdentical: 8, NumRemoved: 12, NumInserted: 3}, // {NumIdentical: 63}, // ] -// func coalesceInterveningIdentical(groups []diffStats, windowSize int) []diffStats { groups, groupsOrig := groups[:0], groups for i, ds := range groupsOrig { @@ -548,7 +550,6 @@ func coalesceInterveningIdentical(groups []diffStats, windowSize int) []diffStat // {NumRemoved: 9}, // {NumIdentical: 64}, // incremented by 10 // ] -// func cleanupSurroundingIdentical(groups []diffStats, eq func(i, j int) bool) []diffStats { var ix, iy int // indexes into sequence x and y for i, ds := range groups { diff --git a/vendor/github.com/google/go-cmp/cmp/report_text.go b/vendor/github.com/google/go-cmp/cmp/report_text.go index 0fd46d7ffb..388fcf5712 100644 --- a/vendor/github.com/google/go-cmp/cmp/report_text.go +++ b/vendor/github.com/google/go-cmp/cmp/report_text.go @@ -393,6 +393,7 @@ func (s diffStats) Append(ds diffStats) diffStats { // String prints a humanly-readable summary of coalesced records. // // Example: +// // diffStats{Name: "Field", NumIgnored: 5}.String() => "5 ignored fields" func (s diffStats) String() string { var ss []string diff --git a/vendor/github.com/google/uuid/null.go b/vendor/github.com/google/uuid/null.go new file mode 100644 index 0000000000..d7fcbf2865 --- /dev/null +++ b/vendor/github.com/google/uuid/null.go @@ -0,0 +1,118 @@ +// Copyright 2021 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "bytes" + "database/sql/driver" + "encoding/json" + "fmt" +) + +var jsonNull = []byte("null") + +// NullUUID represents a UUID that may be null. +// NullUUID implements the SQL driver.Scanner interface so +// it can be used as a scan destination: +// +// var u uuid.NullUUID +// err := db.QueryRow("SELECT name FROM foo WHERE id=?", id).Scan(&u) +// ... +// if u.Valid { +// // use u.UUID +// } else { +// // NULL value +// } +// +type NullUUID struct { + UUID UUID + Valid bool // Valid is true if UUID is not NULL +} + +// Scan implements the SQL driver.Scanner interface. +func (nu *NullUUID) Scan(value interface{}) error { + if value == nil { + nu.UUID, nu.Valid = Nil, false + return nil + } + + err := nu.UUID.Scan(value) + if err != nil { + nu.Valid = false + return err + } + + nu.Valid = true + return nil +} + +// Value implements the driver Valuer interface. +func (nu NullUUID) Value() (driver.Value, error) { + if !nu.Valid { + return nil, nil + } + // Delegate to UUID Value function + return nu.UUID.Value() +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (nu NullUUID) MarshalBinary() ([]byte, error) { + if nu.Valid { + return nu.UUID[:], nil + } + + return []byte(nil), nil +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (nu *NullUUID) UnmarshalBinary(data []byte) error { + if len(data) != 16 { + return fmt.Errorf("invalid UUID (got %d bytes)", len(data)) + } + copy(nu.UUID[:], data) + nu.Valid = true + return nil +} + +// MarshalText implements encoding.TextMarshaler. +func (nu NullUUID) MarshalText() ([]byte, error) { + if nu.Valid { + return nu.UUID.MarshalText() + } + + return jsonNull, nil +} + +// UnmarshalText implements encoding.TextUnmarshaler. +func (nu *NullUUID) UnmarshalText(data []byte) error { + id, err := ParseBytes(data) + if err != nil { + nu.Valid = false + return err + } + nu.UUID = id + nu.Valid = true + return nil +} + +// MarshalJSON implements json.Marshaler. +func (nu NullUUID) MarshalJSON() ([]byte, error) { + if nu.Valid { + return json.Marshal(nu.UUID) + } + + return jsonNull, nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (nu *NullUUID) UnmarshalJSON(data []byte) error { + if bytes.Equal(data, jsonNull) { + *nu = NullUUID{} + return nil // valid null UUID + } + err := json.Unmarshal(data, &nu.UUID) + nu.Valid = err == nil + return err +} diff --git a/vendor/github.com/google/uuid/uuid.go b/vendor/github.com/google/uuid/uuid.go index 60d26bb50c..a57207aeb6 100644 --- a/vendor/github.com/google/uuid/uuid.go +++ b/vendor/github.com/google/uuid/uuid.go @@ -12,6 +12,7 @@ import ( "fmt" "io" "strings" + "sync" ) // A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC @@ -33,7 +34,15 @@ const ( Future // Reserved for future definition. ) -var rander = rand.Reader // random function +const randPoolSize = 16 * 16 + +var ( + rander = rand.Reader // random function + poolEnabled = false + poolMu sync.Mutex + poolPos = randPoolSize // protected with poolMu + pool [randPoolSize]byte // protected with poolMu +) type invalidLengthError struct{ len int } @@ -41,6 +50,12 @@ func (err invalidLengthError) Error() string { return fmt.Sprintf("invalid UUID length: %d", err.len) } +// IsInvalidLengthError is matcher function for custom error invalidLengthError +func IsInvalidLengthError(err error) bool { + _, ok := err.(invalidLengthError) + return ok +} + // Parse decodes s into a UUID or returns an error. Both the standard UUID // forms of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded as well as the @@ -249,3 +264,31 @@ func SetRand(r io.Reader) { } rander = r } + +// EnableRandPool enables internal randomness pool used for Random +// (Version 4) UUID generation. The pool contains random bytes read from +// the random number generator on demand in batches. Enabling the pool +// may improve the UUID generation throughput significantly. +// +// Since the pool is stored on the Go heap, this feature may be a bad fit +// for security sensitive applications. +// +// Both EnableRandPool and DisableRandPool are not thread-safe and should +// only be called when there is no possibility that New or any other +// UUID Version 4 generation function will be called concurrently. +func EnableRandPool() { + poolEnabled = true +} + +// DisableRandPool disables the randomness pool if it was previously +// enabled with EnableRandPool. +// +// Both EnableRandPool and DisableRandPool are not thread-safe and should +// only be called when there is no possibility that New or any other +// UUID Version 4 generation function will be called concurrently. +func DisableRandPool() { + poolEnabled = false + defer poolMu.Unlock() + poolMu.Lock() + poolPos = randPoolSize +} diff --git a/vendor/github.com/google/uuid/version4.go b/vendor/github.com/google/uuid/version4.go index 86160fbd07..7697802e4d 100644 --- a/vendor/github.com/google/uuid/version4.go +++ b/vendor/github.com/google/uuid/version4.go @@ -27,6 +27,8 @@ func NewString() string { // The strength of the UUIDs is based on the strength of the crypto/rand // package. // +// Uses the randomness pool if it was enabled with EnableRandPool. +// // A note about uniqueness derived from the UUID Wikipedia entry: // // Randomly generated UUIDs have 122 random bits. One's annual risk of being @@ -35,7 +37,10 @@ func NewString() string { // equivalent to the odds of creating a few tens of trillions of UUIDs in a // year and having one duplicate. func NewRandom() (UUID, error) { - return NewRandomFromReader(rander) + if !poolEnabled { + return NewRandomFromReader(rander) + } + return newRandomFromPool() } // NewRandomFromReader returns a UUID based on bytes read from a given io.Reader. @@ -49,3 +54,23 @@ func NewRandomFromReader(r io.Reader) (UUID, error) { uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10 return uuid, nil } + +func newRandomFromPool() (UUID, error) { + var uuid UUID + poolMu.Lock() + if poolPos == randPoolSize { + _, err := io.ReadFull(rander, pool[:]) + if err != nil { + poolMu.Unlock() + return Nil, err + } + poolPos = 0 + } + copy(uuid[:], pool[poolPos:(poolPos+16)]) + poolPos += 16 + poolMu.Unlock() + + uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4 + uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10 + return uuid, nil +} diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/internal/BUILD.bazel b/vendor/github.com/grpc-ecosystem/grpc-gateway/internal/BUILD.bazel deleted file mode 100644 index 5242751fb2..0000000000 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/internal/BUILD.bazel +++ /dev/null @@ -1,23 +0,0 @@ -load("@rules_proto//proto:defs.bzl", "proto_library") -load("@io_bazel_rules_go//go:def.bzl", "go_library") -load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") - -package(default_visibility = ["//visibility:public"]) - -proto_library( - name = "internal_proto", - srcs = ["errors.proto"], - deps = ["@com_google_protobuf//:any_proto"], -) - -go_proto_library( - name = "internal_go_proto", - importpath = "github.com/grpc-ecosystem/grpc-gateway/internal", - proto = ":internal_proto", -) - -go_library( - name = "go_default_library", - embed = [":internal_go_proto"], - importpath = "github.com/grpc-ecosystem/grpc-gateway/internal", -) diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/internal/errors.pb.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/internal/errors.pb.go deleted file mode 100644 index 61101d7177..0000000000 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/internal/errors.pb.go +++ /dev/null @@ -1,189 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: internal/errors.proto - -package internal - -import ( - fmt "fmt" - proto "github.com/golang/protobuf/proto" - any "github.com/golang/protobuf/ptypes/any" - math "math" -) - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package - -// Error is the generic error returned from unary RPCs. -type Error struct { - Error string `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` - // This is to make the error more compatible with users that expect errors to be Status objects: - // https://github.com/grpc/grpc/blob/master/src/proto/grpc/status/status.proto - // It should be the exact same message as the Error field. - Code int32 `protobuf:"varint,2,opt,name=code,proto3" json:"code,omitempty"` - Message string `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"` - Details []*any.Any `protobuf:"bytes,4,rep,name=details,proto3" json:"details,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Error) Reset() { *m = Error{} } -func (m *Error) String() string { return proto.CompactTextString(m) } -func (*Error) ProtoMessage() {} -func (*Error) Descriptor() ([]byte, []int) { - return fileDescriptor_9b093362ca6d1e03, []int{0} -} - -func (m *Error) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Error.Unmarshal(m, b) -} -func (m *Error) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Error.Marshal(b, m, deterministic) -} -func (m *Error) XXX_Merge(src proto.Message) { - xxx_messageInfo_Error.Merge(m, src) -} -func (m *Error) XXX_Size() int { - return xxx_messageInfo_Error.Size(m) -} -func (m *Error) XXX_DiscardUnknown() { - xxx_messageInfo_Error.DiscardUnknown(m) -} - -var xxx_messageInfo_Error proto.InternalMessageInfo - -func (m *Error) GetError() string { - if m != nil { - return m.Error - } - return "" -} - -func (m *Error) GetCode() int32 { - if m != nil { - return m.Code - } - return 0 -} - -func (m *Error) GetMessage() string { - if m != nil { - return m.Message - } - return "" -} - -func (m *Error) GetDetails() []*any.Any { - if m != nil { - return m.Details - } - return nil -} - -// StreamError is a response type which is returned when -// streaming rpc returns an error. -type StreamError struct { - GrpcCode int32 `protobuf:"varint,1,opt,name=grpc_code,json=grpcCode,proto3" json:"grpc_code,omitempty"` - HttpCode int32 `protobuf:"varint,2,opt,name=http_code,json=httpCode,proto3" json:"http_code,omitempty"` - Message string `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"` - HttpStatus string `protobuf:"bytes,4,opt,name=http_status,json=httpStatus,proto3" json:"http_status,omitempty"` - Details []*any.Any `protobuf:"bytes,5,rep,name=details,proto3" json:"details,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *StreamError) Reset() { *m = StreamError{} } -func (m *StreamError) String() string { return proto.CompactTextString(m) } -func (*StreamError) ProtoMessage() {} -func (*StreamError) Descriptor() ([]byte, []int) { - return fileDescriptor_9b093362ca6d1e03, []int{1} -} - -func (m *StreamError) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_StreamError.Unmarshal(m, b) -} -func (m *StreamError) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_StreamError.Marshal(b, m, deterministic) -} -func (m *StreamError) XXX_Merge(src proto.Message) { - xxx_messageInfo_StreamError.Merge(m, src) -} -func (m *StreamError) XXX_Size() int { - return xxx_messageInfo_StreamError.Size(m) -} -func (m *StreamError) XXX_DiscardUnknown() { - xxx_messageInfo_StreamError.DiscardUnknown(m) -} - -var xxx_messageInfo_StreamError proto.InternalMessageInfo - -func (m *StreamError) GetGrpcCode() int32 { - if m != nil { - return m.GrpcCode - } - return 0 -} - -func (m *StreamError) GetHttpCode() int32 { - if m != nil { - return m.HttpCode - } - return 0 -} - -func (m *StreamError) GetMessage() string { - if m != nil { - return m.Message - } - return "" -} - -func (m *StreamError) GetHttpStatus() string { - if m != nil { - return m.HttpStatus - } - return "" -} - -func (m *StreamError) GetDetails() []*any.Any { - if m != nil { - return m.Details - } - return nil -} - -func init() { - proto.RegisterType((*Error)(nil), "grpc.gateway.runtime.Error") - proto.RegisterType((*StreamError)(nil), "grpc.gateway.runtime.StreamError") -} - -func init() { proto.RegisterFile("internal/errors.proto", fileDescriptor_9b093362ca6d1e03) } - -var fileDescriptor_9b093362ca6d1e03 = []byte{ - // 252 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x90, 0xc1, 0x4a, 0xc4, 0x30, - 0x10, 0x86, 0x89, 0xbb, 0x75, 0xdb, 0xe9, 0x2d, 0x54, 0x88, 0xee, 0xc1, 0xb2, 0xa7, 0x9e, 0x52, - 0xd0, 0x27, 0xd0, 0xc5, 0x17, 0xe8, 0xde, 0xbc, 0x2c, 0xd9, 0xdd, 0x31, 0x16, 0xda, 0xa4, 0x24, - 0x53, 0xa4, 0xf8, 0x56, 0x3e, 0xa1, 0x24, 0xa5, 0xb0, 0x27, 0xf1, 0xd6, 0xf9, 0xfb, 0xcf, 0x7c, - 0x1f, 0x81, 0xbb, 0xd6, 0x10, 0x3a, 0xa3, 0xba, 0x1a, 0x9d, 0xb3, 0xce, 0xcb, 0xc1, 0x59, 0xb2, - 0xbc, 0xd0, 0x6e, 0x38, 0x4b, 0xad, 0x08, 0xbf, 0xd4, 0x24, 0xdd, 0x68, 0xa8, 0xed, 0xf1, 0xe1, - 0x5e, 0x5b, 0xab, 0x3b, 0xac, 0x63, 0xe7, 0x34, 0x7e, 0xd4, 0xca, 0x4c, 0xf3, 0xc2, 0xee, 0x1b, - 0x92, 0xb7, 0x70, 0x80, 0x17, 0x90, 0xc4, 0x4b, 0x82, 0x95, 0xac, 0xca, 0x9a, 0x79, 0xe0, 0x1c, - 0xd6, 0x67, 0x7b, 0x41, 0x71, 0x53, 0xb2, 0x2a, 0x69, 0xe2, 0x37, 0x17, 0xb0, 0xe9, 0xd1, 0x7b, - 0xa5, 0x51, 0xac, 0x62, 0x77, 0x19, 0xb9, 0x84, 0xcd, 0x05, 0x49, 0xb5, 0x9d, 0x17, 0xeb, 0x72, - 0x55, 0xe5, 0x4f, 0x85, 0x9c, 0xc9, 0x72, 0x21, 0xcb, 0x17, 0x33, 0x35, 0x4b, 0x69, 0xf7, 0xc3, - 0x20, 0x3f, 0x90, 0x43, 0xd5, 0xcf, 0x0e, 0x5b, 0xc8, 0x82, 0xff, 0x31, 0x22, 0x59, 0x44, 0xa6, - 0x21, 0xd8, 0x07, 0xec, 0x16, 0xb2, 0x4f, 0xa2, 0xe1, 0x78, 0xe5, 0x93, 0x86, 0x60, 0xff, 0xb7, - 0xd3, 0x23, 0xe4, 0x71, 0xcd, 0x93, 0xa2, 0x31, 0x78, 0x85, 0xbf, 0x10, 0xa2, 0x43, 0x4c, 0xae, - 0xa5, 0x93, 0x7f, 0x48, 0xbf, 0xc2, 0x7b, 0xba, 0xbc, 0xfd, 0xe9, 0x36, 0x56, 0x9e, 0x7f, 0x03, - 0x00, 0x00, 0xff, 0xff, 0xde, 0x72, 0x6b, 0x83, 0x8e, 0x01, 0x00, 0x00, -} diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/internal/errors.proto b/vendor/github.com/grpc-ecosystem/grpc-gateway/internal/errors.proto deleted file mode 100644 index 4fb212c6b6..0000000000 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/internal/errors.proto +++ /dev/null @@ -1,26 +0,0 @@ -syntax = "proto3"; -package grpc.gateway.runtime; -option go_package = "internal"; - -import "google/protobuf/any.proto"; - -// Error is the generic error returned from unary RPCs. -message Error { - string error = 1; - // This is to make the error more compatible with users that expect errors to be Status objects: - // https://github.com/grpc/grpc/blob/master/src/proto/grpc/status/status.proto - // It should be the exact same message as the Error field. - int32 code = 2; - string message = 3; - repeated google.protobuf.Any details = 4; -} - -// StreamError is a response type which is returned when -// streaming rpc returns an error. -message StreamError { - int32 grpc_code = 1; - int32 http_code = 2; - string message = 3; - string http_status = 4; - repeated google.protobuf.Any details = 5; -} diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/BUILD.bazel b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/BUILD.bazel deleted file mode 100644 index 58b72b9cf7..0000000000 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/BUILD.bazel +++ /dev/null @@ -1,85 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") - -package(default_visibility = ["//visibility:public"]) - -go_library( - name = "go_default_library", - srcs = [ - "context.go", - "convert.go", - "doc.go", - "errors.go", - "fieldmask.go", - "handler.go", - "marshal_httpbodyproto.go", - "marshal_json.go", - "marshal_jsonpb.go", - "marshal_proto.go", - "marshaler.go", - "marshaler_registry.go", - "mux.go", - "pattern.go", - "proto2_convert.go", - "proto_errors.go", - "query.go", - ], - importpath = "github.com/grpc-ecosystem/grpc-gateway/runtime", - deps = [ - "//internal:go_default_library", - "//utilities:go_default_library", - "@com_github_golang_protobuf//descriptor:go_default_library_gen", - "@com_github_golang_protobuf//jsonpb:go_default_library_gen", - "@com_github_golang_protobuf//proto:go_default_library", - "@go_googleapis//google/api:httpbody_go_proto", - "@io_bazel_rules_go//proto/wkt:any_go_proto", - "@io_bazel_rules_go//proto/wkt:descriptor_go_proto", - "@io_bazel_rules_go//proto/wkt:duration_go_proto", - "@io_bazel_rules_go//proto/wkt:field_mask_go_proto", - "@io_bazel_rules_go//proto/wkt:timestamp_go_proto", - "@io_bazel_rules_go//proto/wkt:wrappers_go_proto", - "@org_golang_google_grpc//codes:go_default_library", - "@org_golang_google_grpc//grpclog:go_default_library", - "@org_golang_google_grpc//metadata:go_default_library", - "@org_golang_google_grpc//status:go_default_library", - ], -) - -go_test( - name = "go_default_test", - size = "small", - srcs = [ - "context_test.go", - "convert_test.go", - "errors_test.go", - "fieldmask_test.go", - "handler_test.go", - "marshal_httpbodyproto_test.go", - "marshal_json_test.go", - "marshal_jsonpb_test.go", - "marshal_proto_test.go", - "marshaler_registry_test.go", - "mux_test.go", - "pattern_test.go", - "query_test.go", - ], - embed = [":go_default_library"], - deps = [ - "//internal:go_default_library", - "//runtime/internal/examplepb:go_default_library", - "//utilities:go_default_library", - "@com_github_golang_protobuf//jsonpb:go_default_library_gen", - "@com_github_golang_protobuf//proto:go_default_library", - "@com_github_golang_protobuf//ptypes:go_default_library_gen", - "@go_googleapis//google/api:httpbody_go_proto", - "@go_googleapis//google/rpc:errdetails_go_proto", - "@io_bazel_rules_go//proto/wkt:duration_go_proto", - "@io_bazel_rules_go//proto/wkt:empty_go_proto", - "@io_bazel_rules_go//proto/wkt:field_mask_go_proto", - "@io_bazel_rules_go//proto/wkt:struct_go_proto", - "@io_bazel_rules_go//proto/wkt:timestamp_go_proto", - "@io_bazel_rules_go//proto/wkt:wrappers_go_proto", - "@org_golang_google_grpc//codes:go_default_library", - "@org_golang_google_grpc//metadata:go_default_library", - "@org_golang_google_grpc//status:go_default_library", - ], -) diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/context.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/context.go deleted file mode 100644 index d8cbd4cc96..0000000000 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/context.go +++ /dev/null @@ -1,291 +0,0 @@ -package runtime - -import ( - "context" - "encoding/base64" - "fmt" - "net" - "net/http" - "net/textproto" - "strconv" - "strings" - "sync" - "time" - - "google.golang.org/grpc/codes" - "google.golang.org/grpc/metadata" - "google.golang.org/grpc/status" -) - -// MetadataHeaderPrefix is the http prefix that represents custom metadata -// parameters to or from a gRPC call. -const MetadataHeaderPrefix = "Grpc-Metadata-" - -// MetadataPrefix is prepended to permanent HTTP header keys (as specified -// by the IANA) when added to the gRPC context. -const MetadataPrefix = "grpcgateway-" - -// MetadataTrailerPrefix is prepended to gRPC metadata as it is converted to -// HTTP headers in a response handled by grpc-gateway -const MetadataTrailerPrefix = "Grpc-Trailer-" - -const metadataGrpcTimeout = "Grpc-Timeout" -const metadataHeaderBinarySuffix = "-Bin" - -const xForwardedFor = "X-Forwarded-For" -const xForwardedHost = "X-Forwarded-Host" - -var ( - // DefaultContextTimeout is used for gRPC call context.WithTimeout whenever a Grpc-Timeout inbound - // header isn't present. If the value is 0 the sent `context` will not have a timeout. - DefaultContextTimeout = 0 * time.Second -) - -func decodeBinHeader(v string) ([]byte, error) { - if len(v)%4 == 0 { - // Input was padded, or padding was not necessary. - return base64.StdEncoding.DecodeString(v) - } - return base64.RawStdEncoding.DecodeString(v) -} - -/* -AnnotateContext adds context information such as metadata from the request. - -At a minimum, the RemoteAddr is included in the fashion of "X-Forwarded-For", -except that the forwarded destination is not another HTTP service but rather -a gRPC service. -*/ -func AnnotateContext(ctx context.Context, mux *ServeMux, req *http.Request) (context.Context, error) { - ctx, md, err := annotateContext(ctx, mux, req) - if err != nil { - return nil, err - } - if md == nil { - return ctx, nil - } - - return metadata.NewOutgoingContext(ctx, md), nil -} - -// AnnotateIncomingContext adds context information such as metadata from the request. -// Attach metadata as incoming context. -func AnnotateIncomingContext(ctx context.Context, mux *ServeMux, req *http.Request) (context.Context, error) { - ctx, md, err := annotateContext(ctx, mux, req) - if err != nil { - return nil, err - } - if md == nil { - return ctx, nil - } - - return metadata.NewIncomingContext(ctx, md), nil -} - -func annotateContext(ctx context.Context, mux *ServeMux, req *http.Request) (context.Context, metadata.MD, error) { - var pairs []string - timeout := DefaultContextTimeout - if tm := req.Header.Get(metadataGrpcTimeout); tm != "" { - var err error - timeout, err = timeoutDecode(tm) - if err != nil { - return nil, nil, status.Errorf(codes.InvalidArgument, "invalid grpc-timeout: %s", tm) - } - } - - for key, vals := range req.Header { - key = textproto.CanonicalMIMEHeaderKey(key) - for _, val := range vals { - // For backwards-compatibility, pass through 'authorization' header with no prefix. - if key == "Authorization" { - pairs = append(pairs, "authorization", val) - } - if h, ok := mux.incomingHeaderMatcher(key); ok { - // Handles "-bin" metadata in grpc, since grpc will do another base64 - // encode before sending to server, we need to decode it first. - if strings.HasSuffix(key, metadataHeaderBinarySuffix) { - b, err := decodeBinHeader(val) - if err != nil { - return nil, nil, status.Errorf(codes.InvalidArgument, "invalid binary header %s: %s", key, err) - } - - val = string(b) - } - pairs = append(pairs, h, val) - } - } - } - if host := req.Header.Get(xForwardedHost); host != "" { - pairs = append(pairs, strings.ToLower(xForwardedHost), host) - } else if req.Host != "" { - pairs = append(pairs, strings.ToLower(xForwardedHost), req.Host) - } - - if addr := req.RemoteAddr; addr != "" { - if remoteIP, _, err := net.SplitHostPort(addr); err == nil { - if fwd := req.Header.Get(xForwardedFor); fwd == "" { - pairs = append(pairs, strings.ToLower(xForwardedFor), remoteIP) - } else { - pairs = append(pairs, strings.ToLower(xForwardedFor), fmt.Sprintf("%s, %s", fwd, remoteIP)) - } - } - } - - if timeout != 0 { - ctx, _ = context.WithTimeout(ctx, timeout) - } - if len(pairs) == 0 { - return ctx, nil, nil - } - md := metadata.Pairs(pairs...) - for _, mda := range mux.metadataAnnotators { - md = metadata.Join(md, mda(ctx, req)) - } - return ctx, md, nil -} - -// ServerMetadata consists of metadata sent from gRPC server. -type ServerMetadata struct { - HeaderMD metadata.MD - TrailerMD metadata.MD -} - -type serverMetadataKey struct{} - -// NewServerMetadataContext creates a new context with ServerMetadata -func NewServerMetadataContext(ctx context.Context, md ServerMetadata) context.Context { - return context.WithValue(ctx, serverMetadataKey{}, md) -} - -// ServerMetadataFromContext returns the ServerMetadata in ctx -func ServerMetadataFromContext(ctx context.Context) (md ServerMetadata, ok bool) { - md, ok = ctx.Value(serverMetadataKey{}).(ServerMetadata) - return -} - -// ServerTransportStream implements grpc.ServerTransportStream. -// It should only be used by the generated files to support grpc.SendHeader -// outside of gRPC server use. -type ServerTransportStream struct { - mu sync.Mutex - header metadata.MD - trailer metadata.MD -} - -// Method returns the method for the stream. -func (s *ServerTransportStream) Method() string { - return "" -} - -// Header returns the header metadata of the stream. -func (s *ServerTransportStream) Header() metadata.MD { - s.mu.Lock() - defer s.mu.Unlock() - return s.header.Copy() -} - -// SetHeader sets the header metadata. -func (s *ServerTransportStream) SetHeader(md metadata.MD) error { - if md.Len() == 0 { - return nil - } - - s.mu.Lock() - s.header = metadata.Join(s.header, md) - s.mu.Unlock() - return nil -} - -// SendHeader sets the header metadata. -func (s *ServerTransportStream) SendHeader(md metadata.MD) error { - return s.SetHeader(md) -} - -// Trailer returns the cached trailer metadata. -func (s *ServerTransportStream) Trailer() metadata.MD { - s.mu.Lock() - defer s.mu.Unlock() - return s.trailer.Copy() -} - -// SetTrailer sets the trailer metadata. -func (s *ServerTransportStream) SetTrailer(md metadata.MD) error { - if md.Len() == 0 { - return nil - } - - s.mu.Lock() - s.trailer = metadata.Join(s.trailer, md) - s.mu.Unlock() - return nil -} - -func timeoutDecode(s string) (time.Duration, error) { - size := len(s) - if size < 2 { - return 0, fmt.Errorf("timeout string is too short: %q", s) - } - d, ok := timeoutUnitToDuration(s[size-1]) - if !ok { - return 0, fmt.Errorf("timeout unit is not recognized: %q", s) - } - t, err := strconv.ParseInt(s[:size-1], 10, 64) - if err != nil { - return 0, err - } - return d * time.Duration(t), nil -} - -func timeoutUnitToDuration(u uint8) (d time.Duration, ok bool) { - switch u { - case 'H': - return time.Hour, true - case 'M': - return time.Minute, true - case 'S': - return time.Second, true - case 'm': - return time.Millisecond, true - case 'u': - return time.Microsecond, true - case 'n': - return time.Nanosecond, true - default: - } - return -} - -// isPermanentHTTPHeader checks whether hdr belongs to the list of -// permanent request headers maintained by IANA. -// http://www.iana.org/assignments/message-headers/message-headers.xml -func isPermanentHTTPHeader(hdr string) bool { - switch hdr { - case - "Accept", - "Accept-Charset", - "Accept-Language", - "Accept-Ranges", - "Authorization", - "Cache-Control", - "Content-Type", - "Cookie", - "Date", - "Expect", - "From", - "Host", - "If-Match", - "If-Modified-Since", - "If-None-Match", - "If-Schedule-Tag-Match", - "If-Unmodified-Since", - "Max-Forwards", - "Origin", - "Pragma", - "Referer", - "User-Agent", - "Via", - "Warning": - return true - } - return false -} diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/errors.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/errors.go deleted file mode 100644 index b2ce743bdd..0000000000 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/errors.go +++ /dev/null @@ -1,186 +0,0 @@ -package runtime - -import ( - "context" - "io" - "net/http" - "strings" - - "github.com/grpc-ecosystem/grpc-gateway/internal" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/grpclog" - "google.golang.org/grpc/status" -) - -// HTTPStatusFromCode converts a gRPC error code into the corresponding HTTP response status. -// See: https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto -func HTTPStatusFromCode(code codes.Code) int { - switch code { - case codes.OK: - return http.StatusOK - case codes.Canceled: - return http.StatusRequestTimeout - case codes.Unknown: - return http.StatusInternalServerError - case codes.InvalidArgument: - return http.StatusBadRequest - case codes.DeadlineExceeded: - return http.StatusGatewayTimeout - case codes.NotFound: - return http.StatusNotFound - case codes.AlreadyExists: - return http.StatusConflict - case codes.PermissionDenied: - return http.StatusForbidden - case codes.Unauthenticated: - return http.StatusUnauthorized - case codes.ResourceExhausted: - return http.StatusTooManyRequests - case codes.FailedPrecondition: - // Note, this deliberately doesn't translate to the similarly named '412 Precondition Failed' HTTP response status. - return http.StatusBadRequest - case codes.Aborted: - return http.StatusConflict - case codes.OutOfRange: - return http.StatusBadRequest - case codes.Unimplemented: - return http.StatusNotImplemented - case codes.Internal: - return http.StatusInternalServerError - case codes.Unavailable: - return http.StatusServiceUnavailable - case codes.DataLoss: - return http.StatusInternalServerError - } - - grpclog.Infof("Unknown gRPC error code: %v", code) - return http.StatusInternalServerError -} - -var ( - // HTTPError replies to the request with an error. - // - // HTTPError is called: - // - From generated per-endpoint gateway handler code, when calling the backend results in an error. - // - From gateway runtime code, when forwarding the response message results in an error. - // - // The default value for HTTPError calls the custom error handler configured on the ServeMux via the - // WithProtoErrorHandler serve option if that option was used, calling GlobalHTTPErrorHandler otherwise. - // - // To customize the error handling of a particular ServeMux instance, use the WithProtoErrorHandler - // serve option. - // - // To customize the error format for all ServeMux instances not using the WithProtoErrorHandler serve - // option, set GlobalHTTPErrorHandler to a custom function. - // - // Setting this variable directly to customize error format is deprecated. - HTTPError = MuxOrGlobalHTTPError - - // GlobalHTTPErrorHandler is the HTTPError handler for all ServeMux instances not using the - // WithProtoErrorHandler serve option. - // - // You can set a custom function to this variable to customize error format. - GlobalHTTPErrorHandler = DefaultHTTPError - - // OtherErrorHandler handles gateway errors from parsing and routing client requests for all - // ServeMux instances not using the WithProtoErrorHandler serve option. - // - // It returns the following error codes: StatusMethodNotAllowed StatusNotFound StatusBadRequest - // - // To customize parsing and routing error handling of a particular ServeMux instance, use the - // WithProtoErrorHandler serve option. - // - // To customize parsing and routing error handling of all ServeMux instances not using the - // WithProtoErrorHandler serve option, set a custom function to this variable. - OtherErrorHandler = DefaultOtherErrorHandler -) - -// MuxOrGlobalHTTPError uses the mux-configured error handler, falling back to GlobalErrorHandler. -func MuxOrGlobalHTTPError(ctx context.Context, mux *ServeMux, marshaler Marshaler, w http.ResponseWriter, r *http.Request, err error) { - if mux.protoErrorHandler != nil { - mux.protoErrorHandler(ctx, mux, marshaler, w, r, err) - } else { - GlobalHTTPErrorHandler(ctx, mux, marshaler, w, r, err) - } -} - -// DefaultHTTPError is the default implementation of HTTPError. -// If "err" is an error from gRPC system, the function replies with the status code mapped by HTTPStatusFromCode. -// If otherwise, it replies with http.StatusInternalServerError. -// -// The response body returned by this function is a JSON object, -// which contains a member whose key is "error" and whose value is err.Error(). -func DefaultHTTPError(ctx context.Context, mux *ServeMux, marshaler Marshaler, w http.ResponseWriter, r *http.Request, err error) { - const fallback = `{"error": "failed to marshal error message"}` - - s, ok := status.FromError(err) - if !ok { - s = status.New(codes.Unknown, err.Error()) - } - - w.Header().Del("Trailer") - w.Header().Del("Transfer-Encoding") - - contentType := marshaler.ContentType() - // Check marshaler on run time in order to keep backwards compatibility - // An interface param needs to be added to the ContentType() function on - // the Marshal interface to be able to remove this check - if typeMarshaler, ok := marshaler.(contentTypeMarshaler); ok { - pb := s.Proto() - contentType = typeMarshaler.ContentTypeFromMessage(pb) - } - w.Header().Set("Content-Type", contentType) - - body := &internal.Error{ - Error: s.Message(), - Message: s.Message(), - Code: int32(s.Code()), - Details: s.Proto().GetDetails(), - } - - buf, merr := marshaler.Marshal(body) - if merr != nil { - grpclog.Infof("Failed to marshal error message %q: %v", body, merr) - w.WriteHeader(http.StatusInternalServerError) - if _, err := io.WriteString(w, fallback); err != nil { - grpclog.Infof("Failed to write response: %v", err) - } - return - } - - md, ok := ServerMetadataFromContext(ctx) - if !ok { - grpclog.Infof("Failed to extract ServerMetadata from context") - } - - handleForwardResponseServerMetadata(w, mux, md) - - // RFC 7230 https://tools.ietf.org/html/rfc7230#section-4.1.2 - // Unless the request includes a TE header field indicating "trailers" - // is acceptable, as described in Section 4.3, a server SHOULD NOT - // generate trailer fields that it believes are necessary for the user - // agent to receive. - var wantsTrailers bool - - if te := r.Header.Get("TE"); strings.Contains(strings.ToLower(te), "trailers") { - wantsTrailers = true - handleForwardResponseTrailerHeader(w, md) - w.Header().Set("Transfer-Encoding", "chunked") - } - - st := HTTPStatusFromCode(s.Code()) - w.WriteHeader(st) - if _, err := w.Write(buf); err != nil { - grpclog.Infof("Failed to write response: %v", err) - } - - if wantsTrailers { - handleForwardResponseTrailer(w, md) - } -} - -// DefaultOtherErrorHandler is the default implementation of OtherErrorHandler. -// It simply writes a string representation of the given error into "w". -func DefaultOtherErrorHandler(w http.ResponseWriter, _ *http.Request, msg string, code int) { - http.Error(w, msg, code) -} diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/fieldmask.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/fieldmask.go deleted file mode 100644 index aef645e40b..0000000000 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/fieldmask.go +++ /dev/null @@ -1,89 +0,0 @@ -package runtime - -import ( - "encoding/json" - "io" - "strings" - - descriptor2 "github.com/golang/protobuf/descriptor" - "github.com/golang/protobuf/protoc-gen-go/descriptor" - "google.golang.org/genproto/protobuf/field_mask" -) - -func translateName(name string, md *descriptor.DescriptorProto) (string, *descriptor.DescriptorProto) { - // TODO - should really gate this with a test that the marshaller has used json names - if md != nil { - for _, f := range md.Field { - if f.JsonName != nil && f.Name != nil && *f.JsonName == name { - var subType *descriptor.DescriptorProto - - // If the field has a TypeName then we retrieve the nested type for translating the embedded message names. - if f.TypeName != nil { - typeSplit := strings.Split(*f.TypeName, ".") - typeName := typeSplit[len(typeSplit)-1] - for _, t := range md.NestedType { - if typeName == *t.Name { - subType = t - } - } - } - return *f.Name, subType - } - } - } - return name, nil -} - -// FieldMaskFromRequestBody creates a FieldMask printing all complete paths from the JSON body. -func FieldMaskFromRequestBody(r io.Reader, md *descriptor.DescriptorProto) (*field_mask.FieldMask, error) { - fm := &field_mask.FieldMask{} - var root interface{} - if err := json.NewDecoder(r).Decode(&root); err != nil { - if err == io.EOF { - return fm, nil - } - return nil, err - } - - queue := []fieldMaskPathItem{{node: root, md: md}} - for len(queue) > 0 { - // dequeue an item - item := queue[0] - queue = queue[1:] - - if m, ok := item.node.(map[string]interface{}); ok { - // if the item is an object, then enqueue all of its children - for k, v := range m { - protoName, subMd := translateName(k, item.md) - if subMsg, ok := v.(descriptor2.Message); ok { - _, subMd = descriptor2.ForMessage(subMsg) - } - - var path string - if item.path == "" { - path = protoName - } else { - path = item.path + "." + protoName - } - queue = append(queue, fieldMaskPathItem{path: path, node: v, md: subMd}) - } - } else if len(item.path) > 0 { - // otherwise, it's a leaf node so print its path - fm.Paths = append(fm.Paths, item.path) - } - } - - return fm, nil -} - -// fieldMaskPathItem stores a in-progress deconstruction of a path for a fieldmask -type fieldMaskPathItem struct { - // the list of prior fields leading up to node connected by dots - path string - - // a generic decoded json object the current item to inspect for further path extraction - node interface{} - - // descriptor for parent message - md *descriptor.DescriptorProto -} diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/handler.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/handler.go deleted file mode 100644 index e6e8f286e1..0000000000 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/handler.go +++ /dev/null @@ -1,212 +0,0 @@ -package runtime - -import ( - "context" - "errors" - "fmt" - "io" - "net/http" - "net/textproto" - - "github.com/golang/protobuf/proto" - "github.com/grpc-ecosystem/grpc-gateway/internal" - "google.golang.org/grpc/grpclog" -) - -var errEmptyResponse = errors.New("empty response") - -// ForwardResponseStream forwards the stream from gRPC server to REST client. -func ForwardResponseStream(ctx context.Context, mux *ServeMux, marshaler Marshaler, w http.ResponseWriter, req *http.Request, recv func() (proto.Message, error), opts ...func(context.Context, http.ResponseWriter, proto.Message) error) { - f, ok := w.(http.Flusher) - if !ok { - grpclog.Infof("Flush not supported in %T", w) - http.Error(w, "unexpected type of web server", http.StatusInternalServerError) - return - } - - md, ok := ServerMetadataFromContext(ctx) - if !ok { - grpclog.Infof("Failed to extract ServerMetadata from context") - http.Error(w, "unexpected error", http.StatusInternalServerError) - return - } - handleForwardResponseServerMetadata(w, mux, md) - - w.Header().Set("Transfer-Encoding", "chunked") - w.Header().Set("Content-Type", marshaler.ContentType()) - if err := handleForwardResponseOptions(ctx, w, nil, opts); err != nil { - HTTPError(ctx, mux, marshaler, w, req, err) - return - } - - var delimiter []byte - if d, ok := marshaler.(Delimited); ok { - delimiter = d.Delimiter() - } else { - delimiter = []byte("\n") - } - - var wroteHeader bool - for { - resp, err := recv() - if err == io.EOF { - return - } - if err != nil { - handleForwardResponseStreamError(ctx, wroteHeader, marshaler, w, req, mux, err) - return - } - if err := handleForwardResponseOptions(ctx, w, resp, opts); err != nil { - handleForwardResponseStreamError(ctx, wroteHeader, marshaler, w, req, mux, err) - return - } - - var buf []byte - switch { - case resp == nil: - buf, err = marshaler.Marshal(errorChunk(streamError(ctx, mux.streamErrorHandler, errEmptyResponse))) - default: - result := map[string]interface{}{"result": resp} - if rb, ok := resp.(responseBody); ok { - result["result"] = rb.XXX_ResponseBody() - } - - buf, err = marshaler.Marshal(result) - } - - if err != nil { - grpclog.Infof("Failed to marshal response chunk: %v", err) - handleForwardResponseStreamError(ctx, wroteHeader, marshaler, w, req, mux, err) - return - } - if _, err = w.Write(buf); err != nil { - grpclog.Infof("Failed to send response chunk: %v", err) - return - } - wroteHeader = true - if _, err = w.Write(delimiter); err != nil { - grpclog.Infof("Failed to send delimiter chunk: %v", err) - return - } - f.Flush() - } -} - -func handleForwardResponseServerMetadata(w http.ResponseWriter, mux *ServeMux, md ServerMetadata) { - for k, vs := range md.HeaderMD { - if h, ok := mux.outgoingHeaderMatcher(k); ok { - for _, v := range vs { - w.Header().Add(h, v) - } - } - } -} - -func handleForwardResponseTrailerHeader(w http.ResponseWriter, md ServerMetadata) { - for k := range md.TrailerMD { - tKey := textproto.CanonicalMIMEHeaderKey(fmt.Sprintf("%s%s", MetadataTrailerPrefix, k)) - w.Header().Add("Trailer", tKey) - } -} - -func handleForwardResponseTrailer(w http.ResponseWriter, md ServerMetadata) { - for k, vs := range md.TrailerMD { - tKey := fmt.Sprintf("%s%s", MetadataTrailerPrefix, k) - for _, v := range vs { - w.Header().Add(tKey, v) - } - } -} - -// responseBody interface contains method for getting field for marshaling to the response body -// this method is generated for response struct from the value of `response_body` in the `google.api.HttpRule` -type responseBody interface { - XXX_ResponseBody() interface{} -} - -// ForwardResponseMessage forwards the message "resp" from gRPC server to REST client. -func ForwardResponseMessage(ctx context.Context, mux *ServeMux, marshaler Marshaler, w http.ResponseWriter, req *http.Request, resp proto.Message, opts ...func(context.Context, http.ResponseWriter, proto.Message) error) { - md, ok := ServerMetadataFromContext(ctx) - if !ok { - grpclog.Infof("Failed to extract ServerMetadata from context") - } - - handleForwardResponseServerMetadata(w, mux, md) - handleForwardResponseTrailerHeader(w, md) - - contentType := marshaler.ContentType() - // Check marshaler on run time in order to keep backwards compatibility - // An interface param needs to be added to the ContentType() function on - // the Marshal interface to be able to remove this check - if typeMarshaler, ok := marshaler.(contentTypeMarshaler); ok { - contentType = typeMarshaler.ContentTypeFromMessage(resp) - } - w.Header().Set("Content-Type", contentType) - - if err := handleForwardResponseOptions(ctx, w, resp, opts); err != nil { - HTTPError(ctx, mux, marshaler, w, req, err) - return - } - var buf []byte - var err error - if rb, ok := resp.(responseBody); ok { - buf, err = marshaler.Marshal(rb.XXX_ResponseBody()) - } else { - buf, err = marshaler.Marshal(resp) - } - if err != nil { - grpclog.Infof("Marshal error: %v", err) - HTTPError(ctx, mux, marshaler, w, req, err) - return - } - - if _, err = w.Write(buf); err != nil { - grpclog.Infof("Failed to write response: %v", err) - } - - handleForwardResponseTrailer(w, md) -} - -func handleForwardResponseOptions(ctx context.Context, w http.ResponseWriter, resp proto.Message, opts []func(context.Context, http.ResponseWriter, proto.Message) error) error { - if len(opts) == 0 { - return nil - } - for _, opt := range opts { - if err := opt(ctx, w, resp); err != nil { - grpclog.Infof("Error handling ForwardResponseOptions: %v", err) - return err - } - } - return nil -} - -func handleForwardResponseStreamError(ctx context.Context, wroteHeader bool, marshaler Marshaler, w http.ResponseWriter, req *http.Request, mux *ServeMux, err error) { - serr := streamError(ctx, mux.streamErrorHandler, err) - if !wroteHeader { - w.WriteHeader(int(serr.HttpCode)) - } - buf, merr := marshaler.Marshal(errorChunk(serr)) - if merr != nil { - grpclog.Infof("Failed to marshal an error: %v", merr) - return - } - if _, werr := w.Write(buf); werr != nil { - grpclog.Infof("Failed to notify error to client: %v", werr) - return - } -} - -// streamError returns the payload for the final message in a response stream -// that represents the given err. -func streamError(ctx context.Context, errHandler StreamErrorHandlerFunc, err error) *StreamError { - serr := errHandler(ctx, err) - if serr != nil { - return serr - } - // TODO: log about misbehaving stream error handler? - return DefaultHTTPStreamErrorHandler(ctx, err) -} - -func errorChunk(err *StreamError) map[string]proto.Message { - return map[string]proto.Message{"error": (*internal.StreamError)(err)} -} diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshal_httpbodyproto.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshal_httpbodyproto.go deleted file mode 100644 index 525b0338c7..0000000000 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshal_httpbodyproto.go +++ /dev/null @@ -1,43 +0,0 @@ -package runtime - -import ( - "google.golang.org/genproto/googleapis/api/httpbody" -) - -// SetHTTPBodyMarshaler overwrite the default marshaler with the HTTPBodyMarshaler -func SetHTTPBodyMarshaler(serveMux *ServeMux) { - serveMux.marshalers.mimeMap[MIMEWildcard] = &HTTPBodyMarshaler{ - Marshaler: &JSONPb{OrigName: true}, - } -} - -// HTTPBodyMarshaler is a Marshaler which supports marshaling of a -// google.api.HttpBody message as the full response body if it is -// the actual message used as the response. If not, then this will -// simply fallback to the Marshaler specified as its default Marshaler. -type HTTPBodyMarshaler struct { - Marshaler -} - -// ContentType implementation to keep backwards compatibility with marshal interface -func (h *HTTPBodyMarshaler) ContentType() string { - return h.ContentTypeFromMessage(nil) -} - -// ContentTypeFromMessage in case v is a google.api.HttpBody message it returns -// its specified content type otherwise fall back to the default Marshaler. -func (h *HTTPBodyMarshaler) ContentTypeFromMessage(v interface{}) string { - if httpBody, ok := v.(*httpbody.HttpBody); ok { - return httpBody.GetContentType() - } - return h.Marshaler.ContentType() -} - -// Marshal marshals "v" by returning the body bytes if v is a -// google.api.HttpBody message, otherwise it falls back to the default Marshaler. -func (h *HTTPBodyMarshaler) Marshal(v interface{}) ([]byte, error) { - if httpBody, ok := v.(*httpbody.HttpBody); ok { - return httpBody.Data, nil - } - return h.Marshaler.Marshal(v) -} diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshal_jsonpb.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshal_jsonpb.go deleted file mode 100644 index f0de351b21..0000000000 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshal_jsonpb.go +++ /dev/null @@ -1,262 +0,0 @@ -package runtime - -import ( - "bytes" - "encoding/json" - "fmt" - "io" - "reflect" - - "github.com/golang/protobuf/jsonpb" - "github.com/golang/protobuf/proto" -) - -// JSONPb is a Marshaler which marshals/unmarshals into/from JSON -// with the "github.com/golang/protobuf/jsonpb". -// It supports fully functionality of protobuf unlike JSONBuiltin. -// -// The NewDecoder method returns a DecoderWrapper, so the underlying -// *json.Decoder methods can be used. -type JSONPb jsonpb.Marshaler - -// ContentType always returns "application/json". -func (*JSONPb) ContentType() string { - return "application/json" -} - -// Marshal marshals "v" into JSON. -func (j *JSONPb) Marshal(v interface{}) ([]byte, error) { - if _, ok := v.(proto.Message); !ok { - return j.marshalNonProtoField(v) - } - - var buf bytes.Buffer - if err := j.marshalTo(&buf, v); err != nil { - return nil, err - } - return buf.Bytes(), nil -} - -func (j *JSONPb) marshalTo(w io.Writer, v interface{}) error { - p, ok := v.(proto.Message) - if !ok { - buf, err := j.marshalNonProtoField(v) - if err != nil { - return err - } - _, err = w.Write(buf) - return err - } - return (*jsonpb.Marshaler)(j).Marshal(w, p) -} - -var ( - // protoMessageType is stored to prevent constant lookup of the same type at runtime. - protoMessageType = reflect.TypeOf((*proto.Message)(nil)).Elem() -) - -// marshalNonProto marshals a non-message field of a protobuf message. -// This function does not correctly marshals arbitrary data structure into JSON, -// but it is only capable of marshaling non-message field values of protobuf, -// i.e. primitive types, enums; pointers to primitives or enums; maps from -// integer/string types to primitives/enums/pointers to messages. -func (j *JSONPb) marshalNonProtoField(v interface{}) ([]byte, error) { - if v == nil { - return []byte("null"), nil - } - rv := reflect.ValueOf(v) - for rv.Kind() == reflect.Ptr { - if rv.IsNil() { - return []byte("null"), nil - } - rv = rv.Elem() - } - - if rv.Kind() == reflect.Slice { - if rv.IsNil() { - if j.EmitDefaults { - return []byte("[]"), nil - } - return []byte("null"), nil - } - - if rv.Type().Elem().Implements(protoMessageType) { - var buf bytes.Buffer - err := buf.WriteByte('[') - if err != nil { - return nil, err - } - for i := 0; i < rv.Len(); i++ { - if i != 0 { - err = buf.WriteByte(',') - if err != nil { - return nil, err - } - } - if err = (*jsonpb.Marshaler)(j).Marshal(&buf, rv.Index(i).Interface().(proto.Message)); err != nil { - return nil, err - } - } - err = buf.WriteByte(']') - if err != nil { - return nil, err - } - - return buf.Bytes(), nil - } - } - - if rv.Kind() == reflect.Map { - m := make(map[string]*json.RawMessage) - for _, k := range rv.MapKeys() { - buf, err := j.Marshal(rv.MapIndex(k).Interface()) - if err != nil { - return nil, err - } - m[fmt.Sprintf("%v", k.Interface())] = (*json.RawMessage)(&buf) - } - if j.Indent != "" { - return json.MarshalIndent(m, "", j.Indent) - } - return json.Marshal(m) - } - if enum, ok := rv.Interface().(protoEnum); ok && !j.EnumsAsInts { - return json.Marshal(enum.String()) - } - return json.Marshal(rv.Interface()) -} - -// Unmarshal unmarshals JSON "data" into "v" -func (j *JSONPb) Unmarshal(data []byte, v interface{}) error { - return unmarshalJSONPb(data, v) -} - -// NewDecoder returns a Decoder which reads JSON stream from "r". -func (j *JSONPb) NewDecoder(r io.Reader) Decoder { - d := json.NewDecoder(r) - return DecoderWrapper{Decoder: d} -} - -// DecoderWrapper is a wrapper around a *json.Decoder that adds -// support for protos to the Decode method. -type DecoderWrapper struct { - *json.Decoder -} - -// Decode wraps the embedded decoder's Decode method to support -// protos using a jsonpb.Unmarshaler. -func (d DecoderWrapper) Decode(v interface{}) error { - return decodeJSONPb(d.Decoder, v) -} - -// NewEncoder returns an Encoder which writes JSON stream into "w". -func (j *JSONPb) NewEncoder(w io.Writer) Encoder { - return EncoderFunc(func(v interface{}) error { - if err := j.marshalTo(w, v); err != nil { - return err - } - // mimic json.Encoder by adding a newline (makes output - // easier to read when it contains multiple encoded items) - _, err := w.Write(j.Delimiter()) - return err - }) -} - -func unmarshalJSONPb(data []byte, v interface{}) error { - d := json.NewDecoder(bytes.NewReader(data)) - return decodeJSONPb(d, v) -} - -func decodeJSONPb(d *json.Decoder, v interface{}) error { - p, ok := v.(proto.Message) - if !ok { - return decodeNonProtoField(d, v) - } - unmarshaler := &jsonpb.Unmarshaler{AllowUnknownFields: allowUnknownFields} - return unmarshaler.UnmarshalNext(d, p) -} - -func decodeNonProtoField(d *json.Decoder, v interface{}) error { - rv := reflect.ValueOf(v) - if rv.Kind() != reflect.Ptr { - return fmt.Errorf("%T is not a pointer", v) - } - for rv.Kind() == reflect.Ptr { - if rv.IsNil() { - rv.Set(reflect.New(rv.Type().Elem())) - } - if rv.Type().ConvertibleTo(typeProtoMessage) { - unmarshaler := &jsonpb.Unmarshaler{AllowUnknownFields: allowUnknownFields} - return unmarshaler.UnmarshalNext(d, rv.Interface().(proto.Message)) - } - rv = rv.Elem() - } - if rv.Kind() == reflect.Map { - if rv.IsNil() { - rv.Set(reflect.MakeMap(rv.Type())) - } - conv, ok := convFromType[rv.Type().Key().Kind()] - if !ok { - return fmt.Errorf("unsupported type of map field key: %v", rv.Type().Key()) - } - - m := make(map[string]*json.RawMessage) - if err := d.Decode(&m); err != nil { - return err - } - for k, v := range m { - result := conv.Call([]reflect.Value{reflect.ValueOf(k)}) - if err := result[1].Interface(); err != nil { - return err.(error) - } - bk := result[0] - bv := reflect.New(rv.Type().Elem()) - if err := unmarshalJSONPb([]byte(*v), bv.Interface()); err != nil { - return err - } - rv.SetMapIndex(bk, bv.Elem()) - } - return nil - } - if _, ok := rv.Interface().(protoEnum); ok { - var repr interface{} - if err := d.Decode(&repr); err != nil { - return err - } - switch repr.(type) { - case string: - // TODO(yugui) Should use proto.StructProperties? - return fmt.Errorf("unmarshaling of symbolic enum %q not supported: %T", repr, rv.Interface()) - case float64: - rv.Set(reflect.ValueOf(int32(repr.(float64))).Convert(rv.Type())) - return nil - default: - return fmt.Errorf("cannot assign %#v into Go type %T", repr, rv.Interface()) - } - } - return d.Decode(v) -} - -type protoEnum interface { - fmt.Stringer - EnumDescriptor() ([]byte, []int) -} - -var typeProtoMessage = reflect.TypeOf((*proto.Message)(nil)).Elem() - -// Delimiter for newline encoded JSON streams. -func (j *JSONPb) Delimiter() []byte { - return []byte("\n") -} - -// allowUnknownFields helps not to return an error when the destination -// is a struct and the input contains object keys which do not match any -// non-ignored, exported fields in the destination. -var allowUnknownFields = true - -// DisallowUnknownFields enables option in decoder (unmarshaller) to -// return an error when it finds an unknown field. This function must be -// called before using the JSON marshaller. -func DisallowUnknownFields() { - allowUnknownFields = false -} diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/mux.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/mux.go deleted file mode 100644 index 523a9cb43c..0000000000 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/mux.go +++ /dev/null @@ -1,300 +0,0 @@ -package runtime - -import ( - "context" - "fmt" - "net/http" - "net/textproto" - "strings" - - "github.com/golang/protobuf/proto" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/metadata" - "google.golang.org/grpc/status" -) - -// A HandlerFunc handles a specific pair of path pattern and HTTP method. -type HandlerFunc func(w http.ResponseWriter, r *http.Request, pathParams map[string]string) - -// ErrUnknownURI is the error supplied to a custom ProtoErrorHandlerFunc when -// a request is received with a URI path that does not match any registered -// service method. -// -// Since gRPC servers return an "Unimplemented" code for requests with an -// unrecognized URI path, this error also has a gRPC "Unimplemented" code. -var ErrUnknownURI = status.Error(codes.Unimplemented, http.StatusText(http.StatusNotImplemented)) - -// ServeMux is a request multiplexer for grpc-gateway. -// It matches http requests to patterns and invokes the corresponding handler. -type ServeMux struct { - // handlers maps HTTP method to a list of handlers. - handlers map[string][]handler - forwardResponseOptions []func(context.Context, http.ResponseWriter, proto.Message) error - marshalers marshalerRegistry - incomingHeaderMatcher HeaderMatcherFunc - outgoingHeaderMatcher HeaderMatcherFunc - metadataAnnotators []func(context.Context, *http.Request) metadata.MD - streamErrorHandler StreamErrorHandlerFunc - protoErrorHandler ProtoErrorHandlerFunc - disablePathLengthFallback bool - lastMatchWins bool -} - -// ServeMuxOption is an option that can be given to a ServeMux on construction. -type ServeMuxOption func(*ServeMux) - -// WithForwardResponseOption returns a ServeMuxOption representing the forwardResponseOption. -// -// forwardResponseOption is an option that will be called on the relevant context.Context, -// http.ResponseWriter, and proto.Message before every forwarded response. -// -// The message may be nil in the case where just a header is being sent. -func WithForwardResponseOption(forwardResponseOption func(context.Context, http.ResponseWriter, proto.Message) error) ServeMuxOption { - return func(serveMux *ServeMux) { - serveMux.forwardResponseOptions = append(serveMux.forwardResponseOptions, forwardResponseOption) - } -} - -// SetQueryParameterParser sets the query parameter parser, used to populate message from query parameters. -// Configuring this will mean the generated swagger output is no longer correct, and it should be -// done with careful consideration. -func SetQueryParameterParser(queryParameterParser QueryParameterParser) ServeMuxOption { - return func(serveMux *ServeMux) { - currentQueryParser = queryParameterParser - } -} - -// HeaderMatcherFunc checks whether a header key should be forwarded to/from gRPC context. -type HeaderMatcherFunc func(string) (string, bool) - -// DefaultHeaderMatcher is used to pass http request headers to/from gRPC context. This adds permanent HTTP header -// keys (as specified by the IANA) to gRPC context with grpcgateway- prefix. HTTP headers that start with -// 'Grpc-Metadata-' are mapped to gRPC metadata after removing prefix 'Grpc-Metadata-'. -func DefaultHeaderMatcher(key string) (string, bool) { - key = textproto.CanonicalMIMEHeaderKey(key) - if isPermanentHTTPHeader(key) { - return MetadataPrefix + key, true - } else if strings.HasPrefix(key, MetadataHeaderPrefix) { - return key[len(MetadataHeaderPrefix):], true - } - return "", false -} - -// WithIncomingHeaderMatcher returns a ServeMuxOption representing a headerMatcher for incoming request to gateway. -// -// This matcher will be called with each header in http.Request. If matcher returns true, that header will be -// passed to gRPC context. To transform the header before passing to gRPC context, matcher should return modified header. -func WithIncomingHeaderMatcher(fn HeaderMatcherFunc) ServeMuxOption { - return func(mux *ServeMux) { - mux.incomingHeaderMatcher = fn - } -} - -// WithOutgoingHeaderMatcher returns a ServeMuxOption representing a headerMatcher for outgoing response from gateway. -// -// This matcher will be called with each header in response header metadata. If matcher returns true, that header will be -// passed to http response returned from gateway. To transform the header before passing to response, -// matcher should return modified header. -func WithOutgoingHeaderMatcher(fn HeaderMatcherFunc) ServeMuxOption { - return func(mux *ServeMux) { - mux.outgoingHeaderMatcher = fn - } -} - -// WithMetadata returns a ServeMuxOption for passing metadata to a gRPC context. -// -// This can be used by services that need to read from http.Request and modify gRPC context. A common use case -// is reading token from cookie and adding it in gRPC context. -func WithMetadata(annotator func(context.Context, *http.Request) metadata.MD) ServeMuxOption { - return func(serveMux *ServeMux) { - serveMux.metadataAnnotators = append(serveMux.metadataAnnotators, annotator) - } -} - -// WithProtoErrorHandler returns a ServeMuxOption for configuring a custom error handler. -// -// This can be used to handle an error as general proto message defined by gRPC. -// When this option is used, the mux uses the configured error handler instead of HTTPError and -// OtherErrorHandler. -func WithProtoErrorHandler(fn ProtoErrorHandlerFunc) ServeMuxOption { - return func(serveMux *ServeMux) { - serveMux.protoErrorHandler = fn - } -} - -// WithDisablePathLengthFallback returns a ServeMuxOption for disable path length fallback. -func WithDisablePathLengthFallback() ServeMuxOption { - return func(serveMux *ServeMux) { - serveMux.disablePathLengthFallback = true - } -} - -// WithStreamErrorHandler returns a ServeMuxOption that will use the given custom stream -// error handler, which allows for customizing the error trailer for server-streaming -// calls. -// -// For stream errors that occur before any response has been written, the mux's -// ProtoErrorHandler will be invoked. However, once data has been written, the errors must -// be handled differently: they must be included in the response body. The response body's -// final message will include the error details returned by the stream error handler. -func WithStreamErrorHandler(fn StreamErrorHandlerFunc) ServeMuxOption { - return func(serveMux *ServeMux) { - serveMux.streamErrorHandler = fn - } -} - -// WithLastMatchWins returns a ServeMuxOption that will enable "last -// match wins" behavior, where if multiple path patterns match a -// request path, the last one defined in the .proto file will be used. -func WithLastMatchWins() ServeMuxOption { - return func(serveMux *ServeMux) { - serveMux.lastMatchWins = true - } -} - -// NewServeMux returns a new ServeMux whose internal mapping is empty. -func NewServeMux(opts ...ServeMuxOption) *ServeMux { - serveMux := &ServeMux{ - handlers: make(map[string][]handler), - forwardResponseOptions: make([]func(context.Context, http.ResponseWriter, proto.Message) error, 0), - marshalers: makeMarshalerMIMERegistry(), - streamErrorHandler: DefaultHTTPStreamErrorHandler, - } - - for _, opt := range opts { - opt(serveMux) - } - - if serveMux.incomingHeaderMatcher == nil { - serveMux.incomingHeaderMatcher = DefaultHeaderMatcher - } - - if serveMux.outgoingHeaderMatcher == nil { - serveMux.outgoingHeaderMatcher = func(key string) (string, bool) { - return fmt.Sprintf("%s%s", MetadataHeaderPrefix, key), true - } - } - - return serveMux -} - -// Handle associates "h" to the pair of HTTP method and path pattern. -func (s *ServeMux) Handle(meth string, pat Pattern, h HandlerFunc) { - if s.lastMatchWins { - s.handlers[meth] = append([]handler{handler{pat: pat, h: h}}, s.handlers[meth]...) - } else { - s.handlers[meth] = append(s.handlers[meth], handler{pat: pat, h: h}) - } -} - -// ServeHTTP dispatches the request to the first handler whose pattern matches to r.Method and r.Path. -func (s *ServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) { - ctx := r.Context() - - path := r.URL.Path - if !strings.HasPrefix(path, "/") { - if s.protoErrorHandler != nil { - _, outboundMarshaler := MarshalerForRequest(s, r) - sterr := status.Error(codes.InvalidArgument, http.StatusText(http.StatusBadRequest)) - s.protoErrorHandler(ctx, s, outboundMarshaler, w, r, sterr) - } else { - OtherErrorHandler(w, r, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) - } - return - } - - components := strings.Split(path[1:], "/") - l := len(components) - var verb string - if idx := strings.LastIndex(components[l-1], ":"); idx == 0 { - if s.protoErrorHandler != nil { - _, outboundMarshaler := MarshalerForRequest(s, r) - s.protoErrorHandler(ctx, s, outboundMarshaler, w, r, ErrUnknownURI) - } else { - OtherErrorHandler(w, r, http.StatusText(http.StatusNotFound), http.StatusNotFound) - } - return - } else if idx > 0 { - c := components[l-1] - components[l-1], verb = c[:idx], c[idx+1:] - } - - if override := r.Header.Get("X-HTTP-Method-Override"); override != "" && s.isPathLengthFallback(r) { - r.Method = strings.ToUpper(override) - if err := r.ParseForm(); err != nil { - if s.protoErrorHandler != nil { - _, outboundMarshaler := MarshalerForRequest(s, r) - sterr := status.Error(codes.InvalidArgument, err.Error()) - s.protoErrorHandler(ctx, s, outboundMarshaler, w, r, sterr) - } else { - OtherErrorHandler(w, r, err.Error(), http.StatusBadRequest) - } - return - } - } - for _, h := range s.handlers[r.Method] { - pathParams, err := h.pat.Match(components, verb) - if err != nil { - continue - } - h.h(w, r, pathParams) - return - } - - // lookup other methods to handle fallback from GET to POST and - // to determine if it is MethodNotAllowed or NotFound. - for m, handlers := range s.handlers { - if m == r.Method { - continue - } - for _, h := range handlers { - pathParams, err := h.pat.Match(components, verb) - if err != nil { - continue - } - // X-HTTP-Method-Override is optional. Always allow fallback to POST. - if s.isPathLengthFallback(r) { - if err := r.ParseForm(); err != nil { - if s.protoErrorHandler != nil { - _, outboundMarshaler := MarshalerForRequest(s, r) - sterr := status.Error(codes.InvalidArgument, err.Error()) - s.protoErrorHandler(ctx, s, outboundMarshaler, w, r, sterr) - } else { - OtherErrorHandler(w, r, err.Error(), http.StatusBadRequest) - } - return - } - h.h(w, r, pathParams) - return - } - if s.protoErrorHandler != nil { - _, outboundMarshaler := MarshalerForRequest(s, r) - s.protoErrorHandler(ctx, s, outboundMarshaler, w, r, ErrUnknownURI) - } else { - OtherErrorHandler(w, r, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) - } - return - } - } - - if s.protoErrorHandler != nil { - _, outboundMarshaler := MarshalerForRequest(s, r) - s.protoErrorHandler(ctx, s, outboundMarshaler, w, r, ErrUnknownURI) - } else { - OtherErrorHandler(w, r, http.StatusText(http.StatusNotFound), http.StatusNotFound) - } -} - -// GetForwardResponseOptions returns the ForwardResponseOptions associated with this ServeMux. -func (s *ServeMux) GetForwardResponseOptions() []func(context.Context, http.ResponseWriter, proto.Message) error { - return s.forwardResponseOptions -} - -func (s *ServeMux) isPathLengthFallback(r *http.Request) bool { - return !s.disablePathLengthFallback && r.Method == "POST" && r.Header.Get("Content-Type") == "application/x-www-form-urlencoded" -} - -type handler struct { - pat Pattern - h HandlerFunc -} diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/pattern.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/pattern.go deleted file mode 100644 index 09053695da..0000000000 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/pattern.go +++ /dev/null @@ -1,262 +0,0 @@ -package runtime - -import ( - "errors" - "fmt" - "strings" - - "github.com/grpc-ecosystem/grpc-gateway/utilities" - "google.golang.org/grpc/grpclog" -) - -var ( - // ErrNotMatch indicates that the given HTTP request path does not match to the pattern. - ErrNotMatch = errors.New("not match to the path pattern") - // ErrInvalidPattern indicates that the given definition of Pattern is not valid. - ErrInvalidPattern = errors.New("invalid pattern") -) - -type op struct { - code utilities.OpCode - operand int -} - -// Pattern is a template pattern of http request paths defined in github.com/googleapis/googleapis/google/api/http.proto. -type Pattern struct { - // ops is a list of operations - ops []op - // pool is a constant pool indexed by the operands or vars. - pool []string - // vars is a list of variables names to be bound by this pattern - vars []string - // stacksize is the max depth of the stack - stacksize int - // tailLen is the length of the fixed-size segments after a deep wildcard - tailLen int - // verb is the VERB part of the path pattern. It is empty if the pattern does not have VERB part. - verb string - // assumeColonVerb indicates whether a path suffix after a final - // colon may only be interpreted as a verb. - assumeColonVerb bool -} - -type patternOptions struct { - assumeColonVerb bool -} - -// PatternOpt is an option for creating Patterns. -type PatternOpt func(*patternOptions) - -// NewPattern returns a new Pattern from the given definition values. -// "ops" is a sequence of op codes. "pool" is a constant pool. -// "verb" is the verb part of the pattern. It is empty if the pattern does not have the part. -// "version" must be 1 for now. -// It returns an error if the given definition is invalid. -func NewPattern(version int, ops []int, pool []string, verb string, opts ...PatternOpt) (Pattern, error) { - options := patternOptions{ - assumeColonVerb: true, - } - for _, o := range opts { - o(&options) - } - - if version != 1 { - grpclog.Infof("unsupported version: %d", version) - return Pattern{}, ErrInvalidPattern - } - - l := len(ops) - if l%2 != 0 { - grpclog.Infof("odd number of ops codes: %d", l) - return Pattern{}, ErrInvalidPattern - } - - var ( - typedOps []op - stack, maxstack int - tailLen int - pushMSeen bool - vars []string - ) - for i := 0; i < l; i += 2 { - op := op{code: utilities.OpCode(ops[i]), operand: ops[i+1]} - switch op.code { - case utilities.OpNop: - continue - case utilities.OpPush: - if pushMSeen { - tailLen++ - } - stack++ - case utilities.OpPushM: - if pushMSeen { - grpclog.Infof("pushM appears twice") - return Pattern{}, ErrInvalidPattern - } - pushMSeen = true - stack++ - case utilities.OpLitPush: - if op.operand < 0 || len(pool) <= op.operand { - grpclog.Infof("negative literal index: %d", op.operand) - return Pattern{}, ErrInvalidPattern - } - if pushMSeen { - tailLen++ - } - stack++ - case utilities.OpConcatN: - if op.operand <= 0 { - grpclog.Infof("negative concat size: %d", op.operand) - return Pattern{}, ErrInvalidPattern - } - stack -= op.operand - if stack < 0 { - grpclog.Print("stack underflow") - return Pattern{}, ErrInvalidPattern - } - stack++ - case utilities.OpCapture: - if op.operand < 0 || len(pool) <= op.operand { - grpclog.Infof("variable name index out of bound: %d", op.operand) - return Pattern{}, ErrInvalidPattern - } - v := pool[op.operand] - op.operand = len(vars) - vars = append(vars, v) - stack-- - if stack < 0 { - grpclog.Infof("stack underflow") - return Pattern{}, ErrInvalidPattern - } - default: - grpclog.Infof("invalid opcode: %d", op.code) - return Pattern{}, ErrInvalidPattern - } - - if maxstack < stack { - maxstack = stack - } - typedOps = append(typedOps, op) - } - return Pattern{ - ops: typedOps, - pool: pool, - vars: vars, - stacksize: maxstack, - tailLen: tailLen, - verb: verb, - assumeColonVerb: options.assumeColonVerb, - }, nil -} - -// MustPattern is a helper function which makes it easier to call NewPattern in variable initialization. -func MustPattern(p Pattern, err error) Pattern { - if err != nil { - grpclog.Fatalf("Pattern initialization failed: %v", err) - } - return p -} - -// Match examines components if it matches to the Pattern. -// If it matches, the function returns a mapping from field paths to their captured values. -// If otherwise, the function returns an error. -func (p Pattern) Match(components []string, verb string) (map[string]string, error) { - if p.verb != verb { - if p.assumeColonVerb || p.verb != "" { - return nil, ErrNotMatch - } - if len(components) == 0 { - components = []string{":" + verb} - } else { - components = append([]string{}, components...) - components[len(components)-1] += ":" + verb - } - verb = "" - } - - var pos int - stack := make([]string, 0, p.stacksize) - captured := make([]string, len(p.vars)) - l := len(components) - for _, op := range p.ops { - switch op.code { - case utilities.OpNop: - continue - case utilities.OpPush, utilities.OpLitPush: - if pos >= l { - return nil, ErrNotMatch - } - c := components[pos] - if op.code == utilities.OpLitPush { - if lit := p.pool[op.operand]; c != lit { - return nil, ErrNotMatch - } - } - stack = append(stack, c) - pos++ - case utilities.OpPushM: - end := len(components) - if end < pos+p.tailLen { - return nil, ErrNotMatch - } - end -= p.tailLen - stack = append(stack, strings.Join(components[pos:end], "/")) - pos = end - case utilities.OpConcatN: - n := op.operand - l := len(stack) - n - stack = append(stack[:l], strings.Join(stack[l:], "/")) - case utilities.OpCapture: - n := len(stack) - 1 - captured[op.operand] = stack[n] - stack = stack[:n] - } - } - if pos < l { - return nil, ErrNotMatch - } - bindings := make(map[string]string) - for i, val := range captured { - bindings[p.vars[i]] = val - } - return bindings, nil -} - -// Verb returns the verb part of the Pattern. -func (p Pattern) Verb() string { return p.verb } - -func (p Pattern) String() string { - var stack []string - for _, op := range p.ops { - switch op.code { - case utilities.OpNop: - continue - case utilities.OpPush: - stack = append(stack, "*") - case utilities.OpLitPush: - stack = append(stack, p.pool[op.operand]) - case utilities.OpPushM: - stack = append(stack, "**") - case utilities.OpConcatN: - n := op.operand - l := len(stack) - n - stack = append(stack[:l], strings.Join(stack[l:], "/")) - case utilities.OpCapture: - n := len(stack) - 1 - stack[n] = fmt.Sprintf("{%s=%s}", p.vars[op.operand], stack[n]) - } - } - segs := strings.Join(stack, "/") - if p.verb != "" { - return fmt.Sprintf("/%s:%s", segs, p.verb) - } - return "/" + segs -} - -// AssumeColonVerbOpt indicates whether a path suffix after a final -// colon may only be interpreted as a verb. -func AssumeColonVerbOpt(val bool) PatternOpt { - return PatternOpt(func(o *patternOptions) { - o.assumeColonVerb = val - }) -} diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/proto_errors.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/proto_errors.go deleted file mode 100644 index 3fd30da22a..0000000000 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/proto_errors.go +++ /dev/null @@ -1,106 +0,0 @@ -package runtime - -import ( - "context" - "io" - "net/http" - - "github.com/golang/protobuf/ptypes/any" - "github.com/grpc-ecosystem/grpc-gateway/internal" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/grpclog" - "google.golang.org/grpc/status" -) - -// StreamErrorHandlerFunc accepts an error as a gRPC error generated via status package and translates it into a -// a proto struct used to represent error at the end of a stream. -type StreamErrorHandlerFunc func(context.Context, error) *StreamError - -// StreamError is the payload for the final message in a server stream in the event that the server returns an -// error after a response message has already been sent. -type StreamError internal.StreamError - -// ProtoErrorHandlerFunc handles the error as a gRPC error generated via status package and replies to the request. -type ProtoErrorHandlerFunc func(context.Context, *ServeMux, Marshaler, http.ResponseWriter, *http.Request, error) - -var _ ProtoErrorHandlerFunc = DefaultHTTPProtoErrorHandler - -// DefaultHTTPProtoErrorHandler is an implementation of HTTPError. -// If "err" is an error from gRPC system, the function replies with the status code mapped by HTTPStatusFromCode. -// If otherwise, it replies with http.StatusInternalServerError. -// -// The response body returned by this function is a Status message marshaled by a Marshaler. -// -// Do not set this function to HTTPError variable directly, use WithProtoErrorHandler option instead. -func DefaultHTTPProtoErrorHandler(ctx context.Context, mux *ServeMux, marshaler Marshaler, w http.ResponseWriter, _ *http.Request, err error) { - // return Internal when Marshal failed - const fallback = `{"code": 13, "message": "failed to marshal error message"}` - - s, ok := status.FromError(err) - if !ok { - s = status.New(codes.Unknown, err.Error()) - } - - w.Header().Del("Trailer") - - contentType := marshaler.ContentType() - // Check marshaler on run time in order to keep backwards compatibility - // An interface param needs to be added to the ContentType() function on - // the Marshal interface to be able to remove this check - if typeMarshaler, ok := marshaler.(contentTypeMarshaler); ok { - pb := s.Proto() - contentType = typeMarshaler.ContentTypeFromMessage(pb) - } - w.Header().Set("Content-Type", contentType) - - buf, merr := marshaler.Marshal(s.Proto()) - if merr != nil { - grpclog.Infof("Failed to marshal error message %q: %v", s.Proto(), merr) - w.WriteHeader(http.StatusInternalServerError) - if _, err := io.WriteString(w, fallback); err != nil { - grpclog.Infof("Failed to write response: %v", err) - } - return - } - - md, ok := ServerMetadataFromContext(ctx) - if !ok { - grpclog.Infof("Failed to extract ServerMetadata from context") - } - - handleForwardResponseServerMetadata(w, mux, md) - handleForwardResponseTrailerHeader(w, md) - st := HTTPStatusFromCode(s.Code()) - w.WriteHeader(st) - if _, err := w.Write(buf); err != nil { - grpclog.Infof("Failed to write response: %v", err) - } - - handleForwardResponseTrailer(w, md) -} - -// DefaultHTTPStreamErrorHandler converts the given err into a *StreamError via -// default logic. -// -// It extracts the gRPC status from err if possible. The fields of the status are -// used to populate the returned StreamError, and the HTTP status code is derived -// from the gRPC code via HTTPStatusFromCode. If the given err does not contain a -// gRPC status, an "Unknown" gRPC code is used and "Internal Server Error" HTTP code. -func DefaultHTTPStreamErrorHandler(_ context.Context, err error) *StreamError { - grpcCode := codes.Unknown - grpcMessage := err.Error() - var grpcDetails []*any.Any - if s, ok := status.FromError(err); ok { - grpcCode = s.Code() - grpcMessage = s.Message() - grpcDetails = s.Proto().GetDetails() - } - httpCode := HTTPStatusFromCode(grpcCode) - return &StreamError{ - GrpcCode: int32(grpcCode), - HttpCode: int32(httpCode), - Message: grpcMessage, - HttpStatus: http.StatusText(httpCode), - Details: grpcDetails, - } -} diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/query.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/query.go deleted file mode 100644 index ba66842c33..0000000000 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/query.go +++ /dev/null @@ -1,406 +0,0 @@ -package runtime - -import ( - "encoding/base64" - "fmt" - "net/url" - "reflect" - "regexp" - "strconv" - "strings" - "time" - - "github.com/golang/protobuf/proto" - "github.com/grpc-ecosystem/grpc-gateway/utilities" - "google.golang.org/grpc/grpclog" -) - -var valuesKeyRegexp = regexp.MustCompile("^(.*)\\[(.*)\\]$") - -var currentQueryParser QueryParameterParser = &defaultQueryParser{} - -// QueryParameterParser defines interface for all query parameter parsers -type QueryParameterParser interface { - Parse(msg proto.Message, values url.Values, filter *utilities.DoubleArray) error -} - -// PopulateQueryParameters parses query parameters -// into "msg" using current query parser -func PopulateQueryParameters(msg proto.Message, values url.Values, filter *utilities.DoubleArray) error { - return currentQueryParser.Parse(msg, values, filter) -} - -type defaultQueryParser struct{} - -// Parse populates "values" into "msg". -// A value is ignored if its key starts with one of the elements in "filter". -func (*defaultQueryParser) Parse(msg proto.Message, values url.Values, filter *utilities.DoubleArray) error { - for key, values := range values { - match := valuesKeyRegexp.FindStringSubmatch(key) - if len(match) == 3 { - key = match[1] - values = append([]string{match[2]}, values...) - } - fieldPath := strings.Split(key, ".") - if filter.HasCommonPrefix(fieldPath) { - continue - } - if err := populateFieldValueFromPath(msg, fieldPath, values); err != nil { - return err - } - } - return nil -} - -// PopulateFieldFromPath sets a value in a nested Protobuf structure. -// It instantiates missing protobuf fields as it goes. -func PopulateFieldFromPath(msg proto.Message, fieldPathString string, value string) error { - fieldPath := strings.Split(fieldPathString, ".") - return populateFieldValueFromPath(msg, fieldPath, []string{value}) -} - -func populateFieldValueFromPath(msg proto.Message, fieldPath []string, values []string) error { - m := reflect.ValueOf(msg) - if m.Kind() != reflect.Ptr { - return fmt.Errorf("unexpected type %T: %v", msg, msg) - } - var props *proto.Properties - m = m.Elem() - for i, fieldName := range fieldPath { - isLast := i == len(fieldPath)-1 - if !isLast && m.Kind() != reflect.Struct { - return fmt.Errorf("non-aggregate type in the mid of path: %s", strings.Join(fieldPath, ".")) - } - var f reflect.Value - var err error - f, props, err = fieldByProtoName(m, fieldName) - if err != nil { - return err - } else if !f.IsValid() { - grpclog.Infof("field not found in %T: %s", msg, strings.Join(fieldPath, ".")) - return nil - } - - switch f.Kind() { - case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64, reflect.String, reflect.Uint32, reflect.Uint64: - if !isLast { - return fmt.Errorf("unexpected nested field %s in %s", fieldPath[i+1], strings.Join(fieldPath[:i+1], ".")) - } - m = f - case reflect.Slice: - if !isLast { - return fmt.Errorf("unexpected repeated field in %s", strings.Join(fieldPath, ".")) - } - // Handle []byte - if f.Type().Elem().Kind() == reflect.Uint8 { - m = f - break - } - return populateRepeatedField(f, values, props) - case reflect.Ptr: - if f.IsNil() { - m = reflect.New(f.Type().Elem()) - f.Set(m.Convert(f.Type())) - } - m = f.Elem() - continue - case reflect.Struct: - m = f - continue - case reflect.Map: - if !isLast { - return fmt.Errorf("unexpected nested field %s in %s", fieldPath[i+1], strings.Join(fieldPath[:i+1], ".")) - } - return populateMapField(f, values, props) - default: - return fmt.Errorf("unexpected type %s in %T", f.Type(), msg) - } - } - switch len(values) { - case 0: - return fmt.Errorf("no value of field: %s", strings.Join(fieldPath, ".")) - case 1: - default: - grpclog.Infof("too many field values: %s", strings.Join(fieldPath, ".")) - } - return populateField(m, values[0], props) -} - -// fieldByProtoName looks up a field whose corresponding protobuf field name is "name". -// "m" must be a struct value. It returns zero reflect.Value if no such field found. -func fieldByProtoName(m reflect.Value, name string) (reflect.Value, *proto.Properties, error) { - props := proto.GetProperties(m.Type()) - - // look up field name in oneof map - for _, op := range props.OneofTypes { - if name == op.Prop.OrigName || name == op.Prop.JSONName { - v := reflect.New(op.Type.Elem()) - field := m.Field(op.Field) - if !field.IsNil() { - return reflect.Value{}, nil, fmt.Errorf("field already set for %s oneof", props.Prop[op.Field].OrigName) - } - field.Set(v) - return v.Elem().Field(0), op.Prop, nil - } - } - - for _, p := range props.Prop { - if p.OrigName == name { - return m.FieldByName(p.Name), p, nil - } - if p.JSONName == name { - return m.FieldByName(p.Name), p, nil - } - } - return reflect.Value{}, nil, nil -} - -func populateMapField(f reflect.Value, values []string, props *proto.Properties) error { - if len(values) != 2 { - return fmt.Errorf("more than one value provided for key %s in map %s", values[0], props.Name) - } - - key, value := values[0], values[1] - keyType := f.Type().Key() - valueType := f.Type().Elem() - if f.IsNil() { - f.Set(reflect.MakeMap(f.Type())) - } - - keyConv, ok := convFromType[keyType.Kind()] - if !ok { - return fmt.Errorf("unsupported key type %s in map %s", keyType, props.Name) - } - valueConv, ok := convFromType[valueType.Kind()] - if !ok { - return fmt.Errorf("unsupported value type %s in map %s", valueType, props.Name) - } - - keyV := keyConv.Call([]reflect.Value{reflect.ValueOf(key)}) - if err := keyV[1].Interface(); err != nil { - return err.(error) - } - valueV := valueConv.Call([]reflect.Value{reflect.ValueOf(value)}) - if err := valueV[1].Interface(); err != nil { - return err.(error) - } - - f.SetMapIndex(keyV[0].Convert(keyType), valueV[0].Convert(valueType)) - - return nil -} - -func populateRepeatedField(f reflect.Value, values []string, props *proto.Properties) error { - elemType := f.Type().Elem() - - // is the destination field a slice of an enumeration type? - if enumValMap := proto.EnumValueMap(props.Enum); enumValMap != nil { - return populateFieldEnumRepeated(f, values, enumValMap) - } - - conv, ok := convFromType[elemType.Kind()] - if !ok { - return fmt.Errorf("unsupported field type %s", elemType) - } - f.Set(reflect.MakeSlice(f.Type(), len(values), len(values)).Convert(f.Type())) - for i, v := range values { - result := conv.Call([]reflect.Value{reflect.ValueOf(v)}) - if err := result[1].Interface(); err != nil { - return err.(error) - } - f.Index(i).Set(result[0].Convert(f.Index(i).Type())) - } - return nil -} - -func populateField(f reflect.Value, value string, props *proto.Properties) error { - i := f.Addr().Interface() - - // Handle protobuf well known types - var name string - switch m := i.(type) { - case interface{ XXX_WellKnownType() string }: - name = m.XXX_WellKnownType() - case proto.Message: - const wktPrefix = "google.protobuf." - if fullName := proto.MessageName(m); strings.HasPrefix(fullName, wktPrefix) { - name = fullName[len(wktPrefix):] - } - } - switch name { - case "Timestamp": - if value == "null" { - f.FieldByName("Seconds").SetInt(0) - f.FieldByName("Nanos").SetInt(0) - return nil - } - - t, err := time.Parse(time.RFC3339Nano, value) - if err != nil { - return fmt.Errorf("bad Timestamp: %v", err) - } - f.FieldByName("Seconds").SetInt(int64(t.Unix())) - f.FieldByName("Nanos").SetInt(int64(t.Nanosecond())) - return nil - case "Duration": - if value == "null" { - f.FieldByName("Seconds").SetInt(0) - f.FieldByName("Nanos").SetInt(0) - return nil - } - d, err := time.ParseDuration(value) - if err != nil { - return fmt.Errorf("bad Duration: %v", err) - } - - ns := d.Nanoseconds() - s := ns / 1e9 - ns %= 1e9 - f.FieldByName("Seconds").SetInt(s) - f.FieldByName("Nanos").SetInt(ns) - return nil - case "DoubleValue": - fallthrough - case "FloatValue": - float64Val, err := strconv.ParseFloat(value, 64) - if err != nil { - return fmt.Errorf("bad DoubleValue: %s", value) - } - f.FieldByName("Value").SetFloat(float64Val) - return nil - case "Int64Value": - fallthrough - case "Int32Value": - int64Val, err := strconv.ParseInt(value, 10, 64) - if err != nil { - return fmt.Errorf("bad DoubleValue: %s", value) - } - f.FieldByName("Value").SetInt(int64Val) - return nil - case "UInt64Value": - fallthrough - case "UInt32Value": - uint64Val, err := strconv.ParseUint(value, 10, 64) - if err != nil { - return fmt.Errorf("bad DoubleValue: %s", value) - } - f.FieldByName("Value").SetUint(uint64Val) - return nil - case "BoolValue": - if value == "true" { - f.FieldByName("Value").SetBool(true) - } else if value == "false" { - f.FieldByName("Value").SetBool(false) - } else { - return fmt.Errorf("bad BoolValue: %s", value) - } - return nil - case "StringValue": - f.FieldByName("Value").SetString(value) - return nil - case "BytesValue": - bytesVal, err := base64.StdEncoding.DecodeString(value) - if err != nil { - return fmt.Errorf("bad BytesValue: %s", value) - } - f.FieldByName("Value").SetBytes(bytesVal) - return nil - case "FieldMask": - p := f.FieldByName("Paths") - for _, v := range strings.Split(value, ",") { - if v != "" { - p.Set(reflect.Append(p, reflect.ValueOf(v))) - } - } - return nil - } - - // Handle Time and Duration stdlib types - switch t := i.(type) { - case *time.Time: - pt, err := time.Parse(time.RFC3339Nano, value) - if err != nil { - return fmt.Errorf("bad Timestamp: %v", err) - } - *t = pt - return nil - case *time.Duration: - d, err := time.ParseDuration(value) - if err != nil { - return fmt.Errorf("bad Duration: %v", err) - } - *t = d - return nil - } - - // is the destination field an enumeration type? - if enumValMap := proto.EnumValueMap(props.Enum); enumValMap != nil { - return populateFieldEnum(f, value, enumValMap) - } - - conv, ok := convFromType[f.Kind()] - if !ok { - return fmt.Errorf("field type %T is not supported in query parameters", i) - } - result := conv.Call([]reflect.Value{reflect.ValueOf(value)}) - if err := result[1].Interface(); err != nil { - return err.(error) - } - f.Set(result[0].Convert(f.Type())) - return nil -} - -func convertEnum(value string, t reflect.Type, enumValMap map[string]int32) (reflect.Value, error) { - // see if it's an enumeration string - if enumVal, ok := enumValMap[value]; ok { - return reflect.ValueOf(enumVal).Convert(t), nil - } - - // check for an integer that matches an enumeration value - eVal, err := strconv.Atoi(value) - if err != nil { - return reflect.Value{}, fmt.Errorf("%s is not a valid %s", value, t) - } - for _, v := range enumValMap { - if v == int32(eVal) { - return reflect.ValueOf(eVal).Convert(t), nil - } - } - return reflect.Value{}, fmt.Errorf("%s is not a valid %s", value, t) -} - -func populateFieldEnum(f reflect.Value, value string, enumValMap map[string]int32) error { - cval, err := convertEnum(value, f.Type(), enumValMap) - if err != nil { - return err - } - f.Set(cval) - return nil -} - -func populateFieldEnumRepeated(f reflect.Value, values []string, enumValMap map[string]int32) error { - elemType := f.Type().Elem() - f.Set(reflect.MakeSlice(f.Type(), len(values), len(values)).Convert(f.Type())) - for i, v := range values { - result, err := convertEnum(v, elemType, enumValMap) - if err != nil { - return err - } - f.Index(i).Set(result) - } - return nil -} - -var ( - convFromType = map[reflect.Kind]reflect.Value{ - reflect.String: reflect.ValueOf(String), - reflect.Bool: reflect.ValueOf(Bool), - reflect.Float64: reflect.ValueOf(Float64), - reflect.Float32: reflect.ValueOf(Float32), - reflect.Int64: reflect.ValueOf(Int64), - reflect.Int32: reflect.ValueOf(Int32), - reflect.Uint64: reflect.ValueOf(Uint64), - reflect.Uint32: reflect.ValueOf(Uint32), - reflect.Slice: reflect.ValueOf(Bytes), - } -) diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/utilities/BUILD.bazel b/vendor/github.com/grpc-ecosystem/grpc-gateway/utilities/BUILD.bazel deleted file mode 100644 index 7109d79323..0000000000 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/utilities/BUILD.bazel +++ /dev/null @@ -1,21 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") - -package(default_visibility = ["//visibility:public"]) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "pattern.go", - "readerfactory.go", - "trie.go", - ], - importpath = "github.com/grpc-ecosystem/grpc-gateway/utilities", -) - -go_test( - name = "go_default_test", - size = "small", - srcs = ["trie_test.go"], - embed = [":go_default_library"], -) diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/LICENSE.txt b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/LICENSE.txt similarity index 100% rename from vendor/github.com/grpc-ecosystem/grpc-gateway/LICENSE.txt rename to vendor/github.com/grpc-ecosystem/grpc-gateway/v2/LICENSE.txt diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule/BUILD.bazel b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule/BUILD.bazel new file mode 100644 index 0000000000..f694f3c0d0 --- /dev/null +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule/BUILD.bazel @@ -0,0 +1,35 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +package(default_visibility = ["//visibility:public"]) + +go_library( + name = "httprule", + srcs = [ + "compile.go", + "parse.go", + "types.go", + ], + importpath = "github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule", + deps = ["//utilities"], +) + +go_test( + name = "httprule_test", + size = "small", + srcs = [ + "compile_test.go", + "parse_test.go", + "types_test.go", + ], + embed = [":httprule"], + deps = [ + "//utilities", + "@com_github_golang_glog//:glog", + ], +) + +alias( + name = "go_default_library", + actual = ":httprule", + visibility = ["//:__subpackages__"], +) diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule/compile.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule/compile.go new file mode 100644 index 0000000000..3cd9372959 --- /dev/null +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule/compile.go @@ -0,0 +1,121 @@ +package httprule + +import ( + "github.com/grpc-ecosystem/grpc-gateway/v2/utilities" +) + +const ( + opcodeVersion = 1 +) + +// Template is a compiled representation of path templates. +type Template struct { + // Version is the version number of the format. + Version int + // OpCodes is a sequence of operations. + OpCodes []int + // Pool is a constant pool + Pool []string + // Verb is a VERB part in the template. + Verb string + // Fields is a list of field paths bound in this template. + Fields []string + // Original template (example: /v1/a_bit_of_everything) + Template string +} + +// Compiler compiles utilities representation of path templates into marshallable operations. +// They can be unmarshalled by runtime.NewPattern. +type Compiler interface { + Compile() Template +} + +type op struct { + // code is the opcode of the operation + code utilities.OpCode + + // str is a string operand of the code. + // num is ignored if str is not empty. + str string + + // num is a numeric operand of the code. + num int +} + +func (w wildcard) compile() []op { + return []op{ + {code: utilities.OpPush}, + } +} + +func (w deepWildcard) compile() []op { + return []op{ + {code: utilities.OpPushM}, + } +} + +func (l literal) compile() []op { + return []op{ + { + code: utilities.OpLitPush, + str: string(l), + }, + } +} + +func (v variable) compile() []op { + var ops []op + for _, s := range v.segments { + ops = append(ops, s.compile()...) + } + ops = append(ops, op{ + code: utilities.OpConcatN, + num: len(v.segments), + }, op{ + code: utilities.OpCapture, + str: v.path, + }) + + return ops +} + +func (t template) Compile() Template { + var rawOps []op + for _, s := range t.segments { + rawOps = append(rawOps, s.compile()...) + } + + var ( + ops []int + pool []string + fields []string + ) + consts := make(map[string]int) + for _, op := range rawOps { + ops = append(ops, int(op.code)) + if op.str == "" { + ops = append(ops, op.num) + } else { + // eof segment literal represents the "/" path pattern + if op.str == eof { + op.str = "" + } + if _, ok := consts[op.str]; !ok { + consts[op.str] = len(pool) + pool = append(pool, op.str) + } + ops = append(ops, consts[op.str]) + } + if op.code == utilities.OpCapture { + fields = append(fields, op.str) + } + } + return Template{ + Version: opcodeVersion, + OpCodes: ops, + Pool: pool, + Verb: t.verb, + Fields: fields, + Template: t.template, + } +} diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule/fuzz.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule/fuzz.go new file mode 100644 index 0000000000..138f7c12f0 --- /dev/null +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule/fuzz.go @@ -0,0 +1,11 @@ +// +build gofuzz + +package httprule + +func Fuzz(data []byte) int { + _, err := Parse(string(data)) + if err != nil { + return 0 + } + return 0 +} diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule/parse.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule/parse.go new file mode 100644 index 0000000000..5edd784e62 --- /dev/null +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule/parse.go @@ -0,0 +1,368 @@ +package httprule + +import ( + "fmt" + "strings" +) + +// InvalidTemplateError indicates that the path template is not valid. +type InvalidTemplateError struct { + tmpl string + msg string +} + +func (e InvalidTemplateError) Error() string { + return fmt.Sprintf("%s: %s", e.msg, e.tmpl) +} + +// Parse parses the string representation of path template +func Parse(tmpl string) (Compiler, error) { + if !strings.HasPrefix(tmpl, "/") { + return template{}, InvalidTemplateError{tmpl: tmpl, msg: "no leading /"} + } + tokens, verb := tokenize(tmpl[1:]) + + p := parser{tokens: tokens} + segs, err := p.topLevelSegments() + if err != nil { + return template{}, InvalidTemplateError{tmpl: tmpl, msg: err.Error()} + } + + return template{ + segments: segs, + verb: verb, + template: tmpl, + }, nil +} + +func tokenize(path string) (tokens []string, verb string) { + if path == "" { + return []string{eof}, "" + } + + const ( + init = iota + field + nested + ) + st := init + for path != "" { + var idx int + switch st { + case init: + idx = strings.IndexAny(path, "/{") + case field: + idx = strings.IndexAny(path, ".=}") + case nested: + idx = strings.IndexAny(path, "/}") + } + if idx < 0 { + tokens = append(tokens, path) + break + } + switch r := path[idx]; r { + case '/', '.': + case '{': + st = field + case '=': + st = nested + case '}': + st = init + } + if idx == 0 { + tokens = append(tokens, path[idx:idx+1]) + } else { + tokens = append(tokens, path[:idx], path[idx:idx+1]) + } + path = path[idx+1:] + } + + l := len(tokens) + // See + // https://github.com/grpc-ecosystem/grpc-gateway/pull/1947#issuecomment-774523693 ; + // although normal and backwards-compat logic here is to use the last index + // of a colon, if the final segment is a variable followed by a colon, the + // part following the colon must be a verb. Hence if the previous token is + // an end var marker, we switch the index we're looking for to Index instead + // of LastIndex, so that we correctly grab the remaining part of the path as + // the verb. + var penultimateTokenIsEndVar bool + switch l { + case 0, 1: + // Not enough to be variable so skip this logic and don't result in an + // invalid index + default: + penultimateTokenIsEndVar = tokens[l-2] == "}" + } + t := tokens[l-1] + var idx int + if penultimateTokenIsEndVar { + idx = strings.Index(t, ":") + } else { + idx = strings.LastIndex(t, ":") + } + if idx == 0 { + tokens, verb = tokens[:l-1], t[1:] + } else if idx > 0 { + tokens[l-1], verb = t[:idx], t[idx+1:] + } + tokens = append(tokens, eof) + return tokens, verb +} + +// parser is a parser of the template syntax defined in github.com/googleapis/googleapis/google/api/http.proto. +type parser struct { + tokens []string + accepted []string +} + +// topLevelSegments is the target of this parser. +func (p *parser) topLevelSegments() ([]segment, error) { + if _, err := p.accept(typeEOF); err == nil { + p.tokens = p.tokens[:0] + return []segment{literal(eof)}, nil + } + segs, err := p.segments() + if err != nil { + return nil, err + } + if _, err := p.accept(typeEOF); err != nil { + return nil, fmt.Errorf("unexpected token %q after segments %q", p.tokens[0], strings.Join(p.accepted, "")) + } + return segs, nil +} + +func (p *parser) segments() ([]segment, error) { + s, err := p.segment() + if err != nil { + return nil, err + } + + segs := []segment{s} + for { + if _, err := p.accept("/"); err != nil { + return segs, nil + } + s, err := p.segment() + if err != nil { + return segs, err + } + segs = append(segs, s) + } +} + +func (p *parser) segment() (segment, error) { + if _, err := p.accept("*"); err == nil { + return wildcard{}, nil + } + if _, err := p.accept("**"); err == nil { + return deepWildcard{}, nil + } + if l, err := p.literal(); err == nil { + return l, nil + } + + v, err := p.variable() + if err != nil { + return nil, fmt.Errorf("segment neither wildcards, literal or variable: %v", err) + } + return v, err +} + +func (p *parser) literal() (segment, error) { + lit, err := p.accept(typeLiteral) + if err != nil { + return nil, err + } + return literal(lit), nil +} + +func (p *parser) variable() (segment, error) { + if _, err := p.accept("{"); err != nil { + return nil, err + } + + path, err := p.fieldPath() + if err != nil { + return nil, err + } + + var segs []segment + if _, err := p.accept("="); err == nil { + segs, err = p.segments() + if err != nil { + return nil, fmt.Errorf("invalid segment in variable %q: %v", path, err) + } + } else { + segs = []segment{wildcard{}} + } + + if _, err := p.accept("}"); err != nil { + return nil, fmt.Errorf("unterminated variable segment: %s", path) + } + return variable{ + path: path, + segments: segs, + }, nil +} + +func (p *parser) fieldPath() (string, error) { + c, err := p.accept(typeIdent) + if err != nil { + return "", err + } + components := []string{c} + for { + if _, err = p.accept("."); err != nil { + return strings.Join(components, "."), nil + } + c, err := p.accept(typeIdent) + if err != nil { + return "", fmt.Errorf("invalid field path component: %v", err) + } + components = append(components, c) + } +} + +// A termType is a type of terminal symbols. +type termType string + +// These constants define some of valid values of termType. +// They improve readability of parse functions. +// +// You can also use "/", "*", "**", "." or "=" as valid values. +const ( + typeIdent = termType("ident") + typeLiteral = termType("literal") + typeEOF = termType("$") +) + +const ( + // eof is the terminal symbol which always appears at the end of token sequence. + eof = "\u0000" +) + +// accept tries to accept a token in "p". +// This function consumes a token and returns it if it matches to the specified "term". +// If it doesn't match, the function does not consume any tokens and return an error. +func (p *parser) accept(term termType) (string, error) { + t := p.tokens[0] + switch term { + case "/", "*", "**", ".", "=", "{", "}": + if t != string(term) && t != "/" { + return "", fmt.Errorf("expected %q but got %q", term, t) + } + case typeEOF: + if t != eof { + return "", fmt.Errorf("expected EOF but got %q", t) + } + case typeIdent: + if err := expectIdent(t); err != nil { + return "", err + } + case typeLiteral: + if err := expectPChars(t); err != nil { + return "", err + } + default: + return "", fmt.Errorf("unknown termType %q", term) + } + p.tokens = p.tokens[1:] + p.accepted = append(p.accepted, t) + return t, nil +} + +// expectPChars determines if "t" consists of only pchars defined in RFC3986. +// +// https://www.ietf.org/rfc/rfc3986.txt, P.49 +// pchar = unreserved / pct-encoded / sub-delims / ":" / "@" +// unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" +// sub-delims = "!" / "$" / "&" / "'" / "(" / ")" +// / "*" / "+" / "," / ";" / "=" +// pct-encoded = "%" HEXDIG HEXDIG +func expectPChars(t string) error { + const ( + init = iota + pct1 + pct2 + ) + st := init + for _, r := range t { + if st != init { + if !isHexDigit(r) { + return fmt.Errorf("invalid hexdigit: %c(%U)", r, r) + } + switch st { + case pct1: + st = pct2 + case pct2: + st = init + } + continue + } + + // unreserved + switch { + case 'A' <= r && r <= 'Z': + continue + case 'a' <= r && r <= 'z': + continue + case '0' <= r && r <= '9': + continue + } + switch r { + case '-', '.', '_', '~': + // unreserved + case '!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '=': + // sub-delims + case ':', '@': + // rest of pchar + case '%': + // pct-encoded + st = pct1 + default: + return fmt.Errorf("invalid character in path segment: %q(%U)", r, r) + } + } + if st != init { + return fmt.Errorf("invalid percent-encoding in %q", t) + } + return nil +} + +// expectIdent determines if "ident" is a valid identifier in .proto schema ([[:alpha:]_][[:alphanum:]_]*). +func expectIdent(ident string) error { + if ident == "" { + return fmt.Errorf("empty identifier") + } + for pos, r := range ident { + switch { + case '0' <= r && r <= '9': + if pos == 0 { + return fmt.Errorf("identifier starting with digit: %s", ident) + } + continue + case 'A' <= r && r <= 'Z': + continue + case 'a' <= r && r <= 'z': + continue + case r == '_': + continue + default: + return fmt.Errorf("invalid character %q(%U) in identifier: %s", r, r, ident) + } + } + return nil +} + +func isHexDigit(r rune) bool { + switch { + case '0' <= r && r <= '9': + return true + case 'A' <= r && r <= 'F': + return true + case 'a' <= r && r <= 'f': + return true + } + return false +} diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule/types.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule/types.go new file mode 100644 index 0000000000..5a814a0004 --- /dev/null +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule/types.go @@ -0,0 +1,60 @@ +package httprule + +import ( + "fmt" + "strings" +) + +type template struct { + segments []segment + verb string + template string +} + +type segment interface { + fmt.Stringer + compile() (ops []op) +} + +type wildcard struct{} + +type deepWildcard struct{} + +type literal string + +type variable struct { + path string + segments []segment +} + +func (wildcard) String() string { + return "*" +} + +func (deepWildcard) String() string { + return "**" +} + +func (l literal) String() string { + return string(l) +} + +func (v variable) String() string { + var segs []string + for _, s := range v.segments { + segs = append(segs, s.String()) + } + return fmt.Sprintf("{%s=%s}", v.path, strings.Join(segs, "/")) +} + +func (t template) String() string { + var segs []string + for _, s := range t.segments { + segs = append(segs, s.String()) + } + str := strings.Join(segs, "/") + if t.verb != "" { + str = fmt.Sprintf("%s:%s", str, t.verb) + } + return "/" + str +} diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/BUILD.bazel b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/BUILD.bazel new file mode 100644 index 0000000000..95f867a528 --- /dev/null +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/BUILD.bazel @@ -0,0 +1,91 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +package(default_visibility = ["//visibility:public"]) + +go_library( + name = "runtime", + srcs = [ + "context.go", + "convert.go", + "doc.go", + "errors.go", + "fieldmask.go", + "handler.go", + "marshal_httpbodyproto.go", + "marshal_json.go", + "marshal_jsonpb.go", + "marshal_proto.go", + "marshaler.go", + "marshaler_registry.go", + "mux.go", + "pattern.go", + "proto2_convert.go", + "query.go", + ], + importpath = "github.com/grpc-ecosystem/grpc-gateway/v2/runtime", + deps = [ + "//internal/httprule", + "//utilities", + "@go_googleapis//google/api:httpbody_go_proto", + "@io_bazel_rules_go//proto/wkt:field_mask_go_proto", + "@org_golang_google_grpc//codes", + "@org_golang_google_grpc//grpclog", + "@org_golang_google_grpc//metadata", + "@org_golang_google_grpc//status", + "@org_golang_google_protobuf//encoding/protojson", + "@org_golang_google_protobuf//proto", + "@org_golang_google_protobuf//reflect/protoreflect", + "@org_golang_google_protobuf//reflect/protoregistry", + "@org_golang_google_protobuf//types/known/durationpb", + "@org_golang_google_protobuf//types/known/timestamppb", + "@org_golang_google_protobuf//types/known/wrapperspb", + ], +) + +go_test( + name = "runtime_test", + size = "small", + srcs = [ + "context_test.go", + "convert_test.go", + "errors_test.go", + "fieldmask_test.go", + "handler_test.go", + "marshal_httpbodyproto_test.go", + "marshal_json_test.go", + "marshal_jsonpb_test.go", + "marshal_proto_test.go", + "marshaler_registry_test.go", + "mux_test.go", + "pattern_test.go", + "query_test.go", + ], + embed = [":runtime"], + deps = [ + "//runtime/internal/examplepb", + "//utilities", + "@com_github_google_go_cmp//cmp", + "@com_github_google_go_cmp//cmp/cmpopts", + "@go_googleapis//google/api:httpbody_go_proto", + "@go_googleapis//google/rpc:errdetails_go_proto", + "@go_googleapis//google/rpc:status_go_proto", + "@io_bazel_rules_go//proto/wkt:field_mask_go_proto", + "@org_golang_google_grpc//codes", + "@org_golang_google_grpc//metadata", + "@org_golang_google_grpc//status", + "@org_golang_google_protobuf//encoding/protojson", + "@org_golang_google_protobuf//proto", + "@org_golang_google_protobuf//testing/protocmp", + "@org_golang_google_protobuf//types/known/durationpb", + "@org_golang_google_protobuf//types/known/emptypb", + "@org_golang_google_protobuf//types/known/structpb", + "@org_golang_google_protobuf//types/known/timestamppb", + "@org_golang_google_protobuf//types/known/wrapperspb", + ], +) + +alias( + name = "go_default_library", + actual = ":runtime", + visibility = ["//visibility:public"], +) diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/context.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/context.go new file mode 100644 index 0000000000..fb57b9366e --- /dev/null +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/context.go @@ -0,0 +1,345 @@ +package runtime + +import ( + "context" + "encoding/base64" + "fmt" + "net" + "net/http" + "net/textproto" + "strconv" + "strings" + "sync" + "time" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" +) + +// MetadataHeaderPrefix is the http prefix that represents custom metadata +// parameters to or from a gRPC call. +const MetadataHeaderPrefix = "Grpc-Metadata-" + +// MetadataPrefix is prepended to permanent HTTP header keys (as specified +// by the IANA) when added to the gRPC context. +const MetadataPrefix = "grpcgateway-" + +// MetadataTrailerPrefix is prepended to gRPC metadata as it is converted to +// HTTP headers in a response handled by grpc-gateway +const MetadataTrailerPrefix = "Grpc-Trailer-" + +const metadataGrpcTimeout = "Grpc-Timeout" +const metadataHeaderBinarySuffix = "-Bin" + +const xForwardedFor = "X-Forwarded-For" +const xForwardedHost = "X-Forwarded-Host" + +var ( + // DefaultContextTimeout is used for gRPC call context.WithTimeout whenever a Grpc-Timeout inbound + // header isn't present. If the value is 0 the sent `context` will not have a timeout. + DefaultContextTimeout = 0 * time.Second +) + +type ( + rpcMethodKey struct{} + httpPathPatternKey struct{} + + AnnotateContextOption func(ctx context.Context) context.Context +) + +func WithHTTPPathPattern(pattern string) AnnotateContextOption { + return func(ctx context.Context) context.Context { + return withHTTPPathPattern(ctx, pattern) + } +} + +func decodeBinHeader(v string) ([]byte, error) { + if len(v)%4 == 0 { + // Input was padded, or padding was not necessary. + return base64.StdEncoding.DecodeString(v) + } + return base64.RawStdEncoding.DecodeString(v) +} + +/* +AnnotateContext adds context information such as metadata from the request. + +At a minimum, the RemoteAddr is included in the fashion of "X-Forwarded-For", +except that the forwarded destination is not another HTTP service but rather +a gRPC service. +*/ +func AnnotateContext(ctx context.Context, mux *ServeMux, req *http.Request, rpcMethodName string, options ...AnnotateContextOption) (context.Context, error) { + ctx, md, err := annotateContext(ctx, mux, req, rpcMethodName, options...) + if err != nil { + return nil, err + } + if md == nil { + return ctx, nil + } + + return metadata.NewOutgoingContext(ctx, md), nil +} + +// AnnotateIncomingContext adds context information such as metadata from the request. +// Attach metadata as incoming context. +func AnnotateIncomingContext(ctx context.Context, mux *ServeMux, req *http.Request, rpcMethodName string, options ...AnnotateContextOption) (context.Context, error) { + ctx, md, err := annotateContext(ctx, mux, req, rpcMethodName, options...) + if err != nil { + return nil, err + } + if md == nil { + return ctx, nil + } + + return metadata.NewIncomingContext(ctx, md), nil +} + +func annotateContext(ctx context.Context, mux *ServeMux, req *http.Request, rpcMethodName string, options ...AnnotateContextOption) (context.Context, metadata.MD, error) { + ctx = withRPCMethod(ctx, rpcMethodName) + for _, o := range options { + ctx = o(ctx) + } + var pairs []string + timeout := DefaultContextTimeout + if tm := req.Header.Get(metadataGrpcTimeout); tm != "" { + var err error + timeout, err = timeoutDecode(tm) + if err != nil { + return nil, nil, status.Errorf(codes.InvalidArgument, "invalid grpc-timeout: %s", tm) + } + } + + for key, vals := range req.Header { + key = textproto.CanonicalMIMEHeaderKey(key) + for _, val := range vals { + // For backwards-compatibility, pass through 'authorization' header with no prefix. + if key == "Authorization" { + pairs = append(pairs, "authorization", val) + } + if h, ok := mux.incomingHeaderMatcher(key); ok { + // Handles "-bin" metadata in grpc, since grpc will do another base64 + // encode before sending to server, we need to decode it first. + if strings.HasSuffix(key, metadataHeaderBinarySuffix) { + b, err := decodeBinHeader(val) + if err != nil { + return nil, nil, status.Errorf(codes.InvalidArgument, "invalid binary header %s: %s", key, err) + } + + val = string(b) + } + pairs = append(pairs, h, val) + } + } + } + if host := req.Header.Get(xForwardedHost); host != "" { + pairs = append(pairs, strings.ToLower(xForwardedHost), host) + } else if req.Host != "" { + pairs = append(pairs, strings.ToLower(xForwardedHost), req.Host) + } + + if addr := req.RemoteAddr; addr != "" { + if remoteIP, _, err := net.SplitHostPort(addr); err == nil { + if fwd := req.Header.Get(xForwardedFor); fwd == "" { + pairs = append(pairs, strings.ToLower(xForwardedFor), remoteIP) + } else { + pairs = append(pairs, strings.ToLower(xForwardedFor), fmt.Sprintf("%s, %s", fwd, remoteIP)) + } + } + } + + if timeout != 0 { + //nolint:govet // The context outlives this function + ctx, _ = context.WithTimeout(ctx, timeout) + } + if len(pairs) == 0 { + return ctx, nil, nil + } + md := metadata.Pairs(pairs...) + for _, mda := range mux.metadataAnnotators { + md = metadata.Join(md, mda(ctx, req)) + } + return ctx, md, nil +} + +// ServerMetadata consists of metadata sent from gRPC server. +type ServerMetadata struct { + HeaderMD metadata.MD + TrailerMD metadata.MD +} + +type serverMetadataKey struct{} + +// NewServerMetadataContext creates a new context with ServerMetadata +func NewServerMetadataContext(ctx context.Context, md ServerMetadata) context.Context { + return context.WithValue(ctx, serverMetadataKey{}, md) +} + +// ServerMetadataFromContext returns the ServerMetadata in ctx +func ServerMetadataFromContext(ctx context.Context) (md ServerMetadata, ok bool) { + md, ok = ctx.Value(serverMetadataKey{}).(ServerMetadata) + return +} + +// ServerTransportStream implements grpc.ServerTransportStream. +// It should only be used by the generated files to support grpc.SendHeader +// outside of gRPC server use. +type ServerTransportStream struct { + mu sync.Mutex + header metadata.MD + trailer metadata.MD +} + +// Method returns the method for the stream. +func (s *ServerTransportStream) Method() string { + return "" +} + +// Header returns the header metadata of the stream. +func (s *ServerTransportStream) Header() metadata.MD { + s.mu.Lock() + defer s.mu.Unlock() + return s.header.Copy() +} + +// SetHeader sets the header metadata. +func (s *ServerTransportStream) SetHeader(md metadata.MD) error { + if md.Len() == 0 { + return nil + } + + s.mu.Lock() + s.header = metadata.Join(s.header, md) + s.mu.Unlock() + return nil +} + +// SendHeader sets the header metadata. +func (s *ServerTransportStream) SendHeader(md metadata.MD) error { + return s.SetHeader(md) +} + +// Trailer returns the cached trailer metadata. +func (s *ServerTransportStream) Trailer() metadata.MD { + s.mu.Lock() + defer s.mu.Unlock() + return s.trailer.Copy() +} + +// SetTrailer sets the trailer metadata. +func (s *ServerTransportStream) SetTrailer(md metadata.MD) error { + if md.Len() == 0 { + return nil + } + + s.mu.Lock() + s.trailer = metadata.Join(s.trailer, md) + s.mu.Unlock() + return nil +} + +func timeoutDecode(s string) (time.Duration, error) { + size := len(s) + if size < 2 { + return 0, fmt.Errorf("timeout string is too short: %q", s) + } + d, ok := timeoutUnitToDuration(s[size-1]) + if !ok { + return 0, fmt.Errorf("timeout unit is not recognized: %q", s) + } + t, err := strconv.ParseInt(s[:size-1], 10, 64) + if err != nil { + return 0, err + } + return d * time.Duration(t), nil +} + +func timeoutUnitToDuration(u uint8) (d time.Duration, ok bool) { + switch u { + case 'H': + return time.Hour, true + case 'M': + return time.Minute, true + case 'S': + return time.Second, true + case 'm': + return time.Millisecond, true + case 'u': + return time.Microsecond, true + case 'n': + return time.Nanosecond, true + default: + } + return +} + +// isPermanentHTTPHeader checks whether hdr belongs to the list of +// permanent request headers maintained by IANA. +// http://www.iana.org/assignments/message-headers/message-headers.xml +func isPermanentHTTPHeader(hdr string) bool { + switch hdr { + case + "Accept", + "Accept-Charset", + "Accept-Language", + "Accept-Ranges", + "Authorization", + "Cache-Control", + "Content-Type", + "Cookie", + "Date", + "Expect", + "From", + "Host", + "If-Match", + "If-Modified-Since", + "If-None-Match", + "If-Schedule-Tag-Match", + "If-Unmodified-Since", + "Max-Forwards", + "Origin", + "Pragma", + "Referer", + "User-Agent", + "Via", + "Warning": + return true + } + return false +} + +// RPCMethod returns the method string for the server context. The returned +// string is in the format of "/package.service/method". +func RPCMethod(ctx context.Context) (string, bool) { + m := ctx.Value(rpcMethodKey{}) + if m == nil { + return "", false + } + ms, ok := m.(string) + if !ok { + return "", false + } + return ms, true +} + +func withRPCMethod(ctx context.Context, rpcMethodName string) context.Context { + return context.WithValue(ctx, rpcMethodKey{}, rpcMethodName) +} + +// HTTPPathPattern returns the HTTP path pattern string relating to the HTTP handler, if one exists. +// The format of the returned string is defined by the google.api.http path template type. +func HTTPPathPattern(ctx context.Context) (string, bool) { + m := ctx.Value(httpPathPatternKey{}) + if m == nil { + return "", false + } + ms, ok := m.(string) + if !ok { + return "", false + } + return ms, true +} + +func withHTTPPathPattern(ctx context.Context, httpPathPattern string) context.Context { + return context.WithValue(ctx, httpPathPatternKey{}, httpPathPattern) +} diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/convert.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/convert.go similarity index 80% rename from vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/convert.go rename to vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/convert.go index 2c279344dc..e6bc4e6cee 100644 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/convert.go +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/convert.go @@ -6,10 +6,10 @@ import ( "strconv" "strings" - "github.com/golang/protobuf/jsonpb" - "github.com/golang/protobuf/ptypes/duration" - "github.com/golang/protobuf/ptypes/timestamp" - "github.com/golang/protobuf/ptypes/wrappers" + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/types/known/durationpb" + "google.golang.org/protobuf/types/known/timestamppb" + "google.golang.org/protobuf/types/known/wrapperspb" ) // String just returns the given string. @@ -205,9 +205,11 @@ func BytesSlice(val, sep string) ([][]byte, error) { } // Timestamp converts the given RFC3339 formatted string into a timestamp.Timestamp. -func Timestamp(val string) (*timestamp.Timestamp, error) { - var r timestamp.Timestamp - err := jsonpb.UnmarshalString(val, &r) +func Timestamp(val string) (*timestamppb.Timestamp, error) { + var r timestamppb.Timestamp + val = strconv.Quote(strings.Trim(val, `"`)) + unmarshaler := &protojson.UnmarshalOptions{} + err := unmarshaler.Unmarshal([]byte(val), &r) if err != nil { return nil, err } @@ -215,9 +217,11 @@ func Timestamp(val string) (*timestamp.Timestamp, error) { } // Duration converts the given string into a timestamp.Duration. -func Duration(val string) (*duration.Duration, error) { - var r duration.Duration - err := jsonpb.UnmarshalString(val, &r) +func Duration(val string) (*durationpb.Duration, error) { + var r durationpb.Duration + val = strconv.Quote(strings.Trim(val, `"`)) + unmarshaler := &protojson.UnmarshalOptions{} + err := unmarshaler.Unmarshal([]byte(val), &r) if err != nil { return nil, err } @@ -265,54 +269,54 @@ func EnumSlice(val, sep string, enumValMap map[string]int32) ([]int32, error) { */ // StringValue well-known type support as wrapper around string type -func StringValue(val string) (*wrappers.StringValue, error) { - return &wrappers.StringValue{Value: val}, nil +func StringValue(val string) (*wrapperspb.StringValue, error) { + return &wrapperspb.StringValue{Value: val}, nil } // FloatValue well-known type support as wrapper around float32 type -func FloatValue(val string) (*wrappers.FloatValue, error) { +func FloatValue(val string) (*wrapperspb.FloatValue, error) { parsedVal, err := Float32(val) - return &wrappers.FloatValue{Value: parsedVal}, err + return &wrapperspb.FloatValue{Value: parsedVal}, err } // DoubleValue well-known type support as wrapper around float64 type -func DoubleValue(val string) (*wrappers.DoubleValue, error) { +func DoubleValue(val string) (*wrapperspb.DoubleValue, error) { parsedVal, err := Float64(val) - return &wrappers.DoubleValue{Value: parsedVal}, err + return &wrapperspb.DoubleValue{Value: parsedVal}, err } // BoolValue well-known type support as wrapper around bool type -func BoolValue(val string) (*wrappers.BoolValue, error) { +func BoolValue(val string) (*wrapperspb.BoolValue, error) { parsedVal, err := Bool(val) - return &wrappers.BoolValue{Value: parsedVal}, err + return &wrapperspb.BoolValue{Value: parsedVal}, err } // Int32Value well-known type support as wrapper around int32 type -func Int32Value(val string) (*wrappers.Int32Value, error) { +func Int32Value(val string) (*wrapperspb.Int32Value, error) { parsedVal, err := Int32(val) - return &wrappers.Int32Value{Value: parsedVal}, err + return &wrapperspb.Int32Value{Value: parsedVal}, err } // UInt32Value well-known type support as wrapper around uint32 type -func UInt32Value(val string) (*wrappers.UInt32Value, error) { +func UInt32Value(val string) (*wrapperspb.UInt32Value, error) { parsedVal, err := Uint32(val) - return &wrappers.UInt32Value{Value: parsedVal}, err + return &wrapperspb.UInt32Value{Value: parsedVal}, err } // Int64Value well-known type support as wrapper around int64 type -func Int64Value(val string) (*wrappers.Int64Value, error) { +func Int64Value(val string) (*wrapperspb.Int64Value, error) { parsedVal, err := Int64(val) - return &wrappers.Int64Value{Value: parsedVal}, err + return &wrapperspb.Int64Value{Value: parsedVal}, err } // UInt64Value well-known type support as wrapper around uint64 type -func UInt64Value(val string) (*wrappers.UInt64Value, error) { +func UInt64Value(val string) (*wrapperspb.UInt64Value, error) { parsedVal, err := Uint64(val) - return &wrappers.UInt64Value{Value: parsedVal}, err + return &wrapperspb.UInt64Value{Value: parsedVal}, err } // BytesValue well-known type support as wrapper around bytes[] type -func BytesValue(val string) (*wrappers.BytesValue, error) { +func BytesValue(val string) (*wrapperspb.BytesValue, error) { parsedVal, err := Bytes(val) - return &wrappers.BytesValue{Value: parsedVal}, err + return &wrapperspb.BytesValue{Value: parsedVal}, err } diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/doc.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/doc.go similarity index 100% rename from vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/doc.go rename to vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/doc.go diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/errors.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/errors.go new file mode 100644 index 0000000000..d9e0013c43 --- /dev/null +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/errors.go @@ -0,0 +1,180 @@ +package runtime + +import ( + "context" + "errors" + "io" + "net/http" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/status" +) + +// ErrorHandlerFunc is the signature used to configure error handling. +type ErrorHandlerFunc func(context.Context, *ServeMux, Marshaler, http.ResponseWriter, *http.Request, error) + +// StreamErrorHandlerFunc is the signature used to configure stream error handling. +type StreamErrorHandlerFunc func(context.Context, error) *status.Status + +// RoutingErrorHandlerFunc is the signature used to configure error handling for routing errors. +type RoutingErrorHandlerFunc func(context.Context, *ServeMux, Marshaler, http.ResponseWriter, *http.Request, int) + +// HTTPStatusError is the error to use when needing to provide a different HTTP status code for an error +// passed to the DefaultRoutingErrorHandler. +type HTTPStatusError struct { + HTTPStatus int + Err error +} + +func (e *HTTPStatusError) Error() string { + return e.Err.Error() +} + +// HTTPStatusFromCode converts a gRPC error code into the corresponding HTTP response status. +// See: https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto +func HTTPStatusFromCode(code codes.Code) int { + switch code { + case codes.OK: + return http.StatusOK + case codes.Canceled: + return http.StatusRequestTimeout + case codes.Unknown: + return http.StatusInternalServerError + case codes.InvalidArgument: + return http.StatusBadRequest + case codes.DeadlineExceeded: + return http.StatusGatewayTimeout + case codes.NotFound: + return http.StatusNotFound + case codes.AlreadyExists: + return http.StatusConflict + case codes.PermissionDenied: + return http.StatusForbidden + case codes.Unauthenticated: + return http.StatusUnauthorized + case codes.ResourceExhausted: + return http.StatusTooManyRequests + case codes.FailedPrecondition: + // Note, this deliberately doesn't translate to the similarly named '412 Precondition Failed' HTTP response status. + return http.StatusBadRequest + case codes.Aborted: + return http.StatusConflict + case codes.OutOfRange: + return http.StatusBadRequest + case codes.Unimplemented: + return http.StatusNotImplemented + case codes.Internal: + return http.StatusInternalServerError + case codes.Unavailable: + return http.StatusServiceUnavailable + case codes.DataLoss: + return http.StatusInternalServerError + } + + grpclog.Infof("Unknown gRPC error code: %v", code) + return http.StatusInternalServerError +} + +// HTTPError uses the mux-configured error handler. +func HTTPError(ctx context.Context, mux *ServeMux, marshaler Marshaler, w http.ResponseWriter, r *http.Request, err error) { + mux.errorHandler(ctx, mux, marshaler, w, r, err) +} + +// DefaultHTTPErrorHandler is the default error handler. +// If "err" is a gRPC Status, the function replies with the status code mapped by HTTPStatusFromCode. +// If "err" is a HTTPStatusError, the function replies with the status code provide by that struct. This is +// intended to allow passing through of specific statuses via the function set via WithRoutingErrorHandler +// for the ServeMux constructor to handle edge cases which the standard mappings in HTTPStatusFromCode +// are insufficient for. +// If otherwise, it replies with http.StatusInternalServerError. +// +// The response body written by this function is a Status message marshaled by the Marshaler. +func DefaultHTTPErrorHandler(ctx context.Context, mux *ServeMux, marshaler Marshaler, w http.ResponseWriter, r *http.Request, err error) { + // return Internal when Marshal failed + const fallback = `{"code": 13, "message": "failed to marshal error message"}` + + var customStatus *HTTPStatusError + if errors.As(err, &customStatus) { + err = customStatus.Err + } + + s := status.Convert(err) + pb := s.Proto() + + w.Header().Del("Trailer") + w.Header().Del("Transfer-Encoding") + + contentType := marshaler.ContentType(pb) + w.Header().Set("Content-Type", contentType) + + if s.Code() == codes.Unauthenticated { + w.Header().Set("WWW-Authenticate", s.Message()) + } + + buf, merr := marshaler.Marshal(pb) + if merr != nil { + grpclog.Infof("Failed to marshal error message %q: %v", s, merr) + w.WriteHeader(http.StatusInternalServerError) + if _, err := io.WriteString(w, fallback); err != nil { + grpclog.Infof("Failed to write response: %v", err) + } + return + } + + md, ok := ServerMetadataFromContext(ctx) + if !ok { + grpclog.Infof("Failed to extract ServerMetadata from context") + } + + handleForwardResponseServerMetadata(w, mux, md) + + // RFC 7230 https://tools.ietf.org/html/rfc7230#section-4.1.2 + // Unless the request includes a TE header field indicating "trailers" + // is acceptable, as described in Section 4.3, a server SHOULD NOT + // generate trailer fields that it believes are necessary for the user + // agent to receive. + doForwardTrailers := requestAcceptsTrailers(r) + + if doForwardTrailers { + handleForwardResponseTrailerHeader(w, md) + w.Header().Set("Transfer-Encoding", "chunked") + } + + st := HTTPStatusFromCode(s.Code()) + if customStatus != nil { + st = customStatus.HTTPStatus + } + + w.WriteHeader(st) + if _, err := w.Write(buf); err != nil { + grpclog.Infof("Failed to write response: %v", err) + } + + if doForwardTrailers { + handleForwardResponseTrailer(w, md) + } +} + +func DefaultStreamErrorHandler(_ context.Context, err error) *status.Status { + return status.Convert(err) +} + +// DefaultRoutingErrorHandler is our default handler for routing errors. +// By default http error codes mapped on the following error codes: +// NotFound -> grpc.NotFound +// StatusBadRequest -> grpc.InvalidArgument +// MethodNotAllowed -> grpc.Unimplemented +// Other -> grpc.Internal, method is not expecting to be called for anything else +func DefaultRoutingErrorHandler(ctx context.Context, mux *ServeMux, marshaler Marshaler, w http.ResponseWriter, r *http.Request, httpStatus int) { + sterr := status.Error(codes.Internal, "Unexpected routing error") + switch httpStatus { + case http.StatusBadRequest: + sterr = status.Error(codes.InvalidArgument, http.StatusText(httpStatus)) + case http.StatusMethodNotAllowed: + sterr = status.Error(codes.Unimplemented, http.StatusText(httpStatus)) + case http.StatusNotFound: + sterr = status.Error(codes.NotFound, http.StatusText(httpStatus)) + } + mux.errorHandler(ctx, mux, marshaler, w, r, sterr) +} diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/fieldmask.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/fieldmask.go new file mode 100644 index 0000000000..0138ed2f76 --- /dev/null +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/fieldmask.go @@ -0,0 +1,165 @@ +package runtime + +import ( + "encoding/json" + "fmt" + "io" + "sort" + + "google.golang.org/genproto/protobuf/field_mask" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" +) + +func getFieldByName(fields protoreflect.FieldDescriptors, name string) protoreflect.FieldDescriptor { + fd := fields.ByName(protoreflect.Name(name)) + if fd != nil { + return fd + } + + return fields.ByJSONName(name) +} + +// FieldMaskFromRequestBody creates a FieldMask printing all complete paths from the JSON body. +func FieldMaskFromRequestBody(r io.Reader, msg proto.Message) (*field_mask.FieldMask, error) { + fm := &field_mask.FieldMask{} + var root interface{} + + if err := json.NewDecoder(r).Decode(&root); err != nil { + if err == io.EOF { + return fm, nil + } + return nil, err + } + + queue := []fieldMaskPathItem{{node: root, msg: msg.ProtoReflect()}} + for len(queue) > 0 { + // dequeue an item + item := queue[0] + queue = queue[1:] + + m, ok := item.node.(map[string]interface{}) + switch { + case ok: + // if the item is an object, then enqueue all of its children + for k, v := range m { + if item.msg == nil { + return nil, fmt.Errorf("JSON structure did not match request type") + } + + fd := getFieldByName(item.msg.Descriptor().Fields(), k) + if fd == nil { + return nil, fmt.Errorf("could not find field %q in %q", k, item.msg.Descriptor().FullName()) + } + + if isDynamicProtoMessage(fd.Message()) { + for _, p := range buildPathsBlindly(k, v) { + newPath := p + if item.path != "" { + newPath = item.path + "." + newPath + } + queue = append(queue, fieldMaskPathItem{path: newPath}) + } + continue + } + + if isProtobufAnyMessage(fd.Message()) { + _, hasTypeField := v.(map[string]interface{})["@type"] + if hasTypeField { + queue = append(queue, fieldMaskPathItem{path: k}) + continue + } else { + return nil, fmt.Errorf("could not find field @type in %q in message %q", k, item.msg.Descriptor().FullName()) + } + + } + + child := fieldMaskPathItem{ + node: v, + } + if item.path == "" { + child.path = string(fd.FullName().Name()) + } else { + child.path = item.path + "." + string(fd.FullName().Name()) + } + + switch { + case fd.IsList(), fd.IsMap(): + // As per: https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/field_mask.proto#L85-L86 + // Do not recurse into repeated fields. The repeated field goes on the end of the path and we stop. + fm.Paths = append(fm.Paths, child.path) + case fd.Message() != nil: + child.msg = item.msg.Get(fd).Message() + fallthrough + default: + queue = append(queue, child) + } + } + case len(item.path) > 0: + // otherwise, it's a leaf node so print its path + fm.Paths = append(fm.Paths, item.path) + } + } + + // Sort for deterministic output in the presence + // of repeated fields. + sort.Strings(fm.Paths) + + return fm, nil +} + +func isProtobufAnyMessage(md protoreflect.MessageDescriptor) bool { + return md != nil && (md.FullName() == "google.protobuf.Any") +} + +func isDynamicProtoMessage(md protoreflect.MessageDescriptor) bool { + return md != nil && (md.FullName() == "google.protobuf.Struct" || md.FullName() == "google.protobuf.Value") +} + +// buildPathsBlindly does not attempt to match proto field names to the +// json value keys. Instead it relies completely on the structure of +// the unmarshalled json contained within in. +// Returns a slice containing all subpaths with the root at the +// passed in name and json value. +func buildPathsBlindly(name string, in interface{}) []string { + m, ok := in.(map[string]interface{}) + if !ok { + return []string{name} + } + + var paths []string + queue := []fieldMaskPathItem{{path: name, node: m}} + for len(queue) > 0 { + cur := queue[0] + queue = queue[1:] + + m, ok := cur.node.(map[string]interface{}) + if !ok { + // This should never happen since we should always check that we only add + // nodes of type map[string]interface{} to the queue. + continue + } + for k, v := range m { + if mi, ok := v.(map[string]interface{}); ok { + queue = append(queue, fieldMaskPathItem{path: cur.path + "." + k, node: mi}) + } else { + // This is not a struct, so there are no more levels to descend. + curPath := cur.path + "." + k + paths = append(paths, curPath) + } + } + } + return paths +} + +// fieldMaskPathItem stores a in-progress deconstruction of a path for a fieldmask +type fieldMaskPathItem struct { + // the list of prior fields leading up to node connected by dots + path string + + // a generic decoded json object the current item to inspect for further path extraction + node interface{} + + // parent message + msg protoreflect.Message +} diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/handler.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/handler.go new file mode 100644 index 0000000000..d1e21df481 --- /dev/null +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/handler.go @@ -0,0 +1,223 @@ +package runtime + +import ( + "context" + "fmt" + "io" + "net/http" + "net/textproto" + "strings" + + "google.golang.org/genproto/googleapis/api/httpbody" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" +) + +// ForwardResponseStream forwards the stream from gRPC server to REST client. +func ForwardResponseStream(ctx context.Context, mux *ServeMux, marshaler Marshaler, w http.ResponseWriter, req *http.Request, recv func() (proto.Message, error), opts ...func(context.Context, http.ResponseWriter, proto.Message) error) { + f, ok := w.(http.Flusher) + if !ok { + grpclog.Infof("Flush not supported in %T", w) + http.Error(w, "unexpected type of web server", http.StatusInternalServerError) + return + } + + md, ok := ServerMetadataFromContext(ctx) + if !ok { + grpclog.Infof("Failed to extract ServerMetadata from context") + http.Error(w, "unexpected error", http.StatusInternalServerError) + return + } + handleForwardResponseServerMetadata(w, mux, md) + + w.Header().Set("Transfer-Encoding", "chunked") + if err := handleForwardResponseOptions(ctx, w, nil, opts); err != nil { + HTTPError(ctx, mux, marshaler, w, req, err) + return + } + + var delimiter []byte + if d, ok := marshaler.(Delimited); ok { + delimiter = d.Delimiter() + } else { + delimiter = []byte("\n") + } + + var wroteHeader bool + for { + resp, err := recv() + if err == io.EOF { + return + } + if err != nil { + handleForwardResponseStreamError(ctx, wroteHeader, marshaler, w, req, mux, err) + return + } + if err := handleForwardResponseOptions(ctx, w, resp, opts); err != nil { + handleForwardResponseStreamError(ctx, wroteHeader, marshaler, w, req, mux, err) + return + } + + if !wroteHeader { + w.Header().Set("Content-Type", marshaler.ContentType(resp)) + } + + var buf []byte + httpBody, isHTTPBody := resp.(*httpbody.HttpBody) + switch { + case resp == nil: + buf, err = marshaler.Marshal(errorChunk(status.New(codes.Internal, "empty response"))) + case isHTTPBody: + buf = httpBody.GetData() + default: + result := map[string]interface{}{"result": resp} + if rb, ok := resp.(responseBody); ok { + result["result"] = rb.XXX_ResponseBody() + } + + buf, err = marshaler.Marshal(result) + } + + if err != nil { + grpclog.Infof("Failed to marshal response chunk: %v", err) + handleForwardResponseStreamError(ctx, wroteHeader, marshaler, w, req, mux, err) + return + } + if _, err = w.Write(buf); err != nil { + grpclog.Infof("Failed to send response chunk: %v", err) + return + } + wroteHeader = true + if _, err = w.Write(delimiter); err != nil { + grpclog.Infof("Failed to send delimiter chunk: %v", err) + return + } + f.Flush() + } +} + +func handleForwardResponseServerMetadata(w http.ResponseWriter, mux *ServeMux, md ServerMetadata) { + for k, vs := range md.HeaderMD { + if h, ok := mux.outgoingHeaderMatcher(k); ok { + for _, v := range vs { + w.Header().Add(h, v) + } + } + } +} + +func handleForwardResponseTrailerHeader(w http.ResponseWriter, md ServerMetadata) { + for k := range md.TrailerMD { + tKey := textproto.CanonicalMIMEHeaderKey(fmt.Sprintf("%s%s", MetadataTrailerPrefix, k)) + w.Header().Add("Trailer", tKey) + } +} + +func handleForwardResponseTrailer(w http.ResponseWriter, md ServerMetadata) { + for k, vs := range md.TrailerMD { + tKey := fmt.Sprintf("%s%s", MetadataTrailerPrefix, k) + for _, v := range vs { + w.Header().Add(tKey, v) + } + } +} + +// responseBody interface contains method for getting field for marshaling to the response body +// this method is generated for response struct from the value of `response_body` in the `google.api.HttpRule` +type responseBody interface { + XXX_ResponseBody() interface{} +} + +// ForwardResponseMessage forwards the message "resp" from gRPC server to REST client. +func ForwardResponseMessage(ctx context.Context, mux *ServeMux, marshaler Marshaler, w http.ResponseWriter, req *http.Request, resp proto.Message, opts ...func(context.Context, http.ResponseWriter, proto.Message) error) { + md, ok := ServerMetadataFromContext(ctx) + if !ok { + grpclog.Infof("Failed to extract ServerMetadata from context") + } + + handleForwardResponseServerMetadata(w, mux, md) + + // RFC 7230 https://tools.ietf.org/html/rfc7230#section-4.1.2 + // Unless the request includes a TE header field indicating "trailers" + // is acceptable, as described in Section 4.3, a server SHOULD NOT + // generate trailer fields that it believes are necessary for the user + // agent to receive. + doForwardTrailers := requestAcceptsTrailers(req) + + if doForwardTrailers { + handleForwardResponseTrailerHeader(w, md) + w.Header().Set("Transfer-Encoding", "chunked") + } + + handleForwardResponseTrailerHeader(w, md) + + contentType := marshaler.ContentType(resp) + w.Header().Set("Content-Type", contentType) + + if err := handleForwardResponseOptions(ctx, w, resp, opts); err != nil { + HTTPError(ctx, mux, marshaler, w, req, err) + return + } + var buf []byte + var err error + if rb, ok := resp.(responseBody); ok { + buf, err = marshaler.Marshal(rb.XXX_ResponseBody()) + } else { + buf, err = marshaler.Marshal(resp) + } + if err != nil { + grpclog.Infof("Marshal error: %v", err) + HTTPError(ctx, mux, marshaler, w, req, err) + return + } + + if _, err = w.Write(buf); err != nil { + grpclog.Infof("Failed to write response: %v", err) + } + + if doForwardTrailers { + handleForwardResponseTrailer(w, md) + } +} + +func requestAcceptsTrailers(req *http.Request) bool { + te := req.Header.Get("TE") + return strings.Contains(strings.ToLower(te), "trailers") +} + +func handleForwardResponseOptions(ctx context.Context, w http.ResponseWriter, resp proto.Message, opts []func(context.Context, http.ResponseWriter, proto.Message) error) error { + if len(opts) == 0 { + return nil + } + for _, opt := range opts { + if err := opt(ctx, w, resp); err != nil { + grpclog.Infof("Error handling ForwardResponseOptions: %v", err) + return err + } + } + return nil +} + +func handleForwardResponseStreamError(ctx context.Context, wroteHeader bool, marshaler Marshaler, w http.ResponseWriter, req *http.Request, mux *ServeMux, err error) { + st := mux.streamErrorHandler(ctx, err) + msg := errorChunk(st) + if !wroteHeader { + w.Header().Set("Content-Type", marshaler.ContentType(msg)) + w.WriteHeader(HTTPStatusFromCode(st.Code())) + } + buf, merr := marshaler.Marshal(msg) + if merr != nil { + grpclog.Infof("Failed to marshal an error: %v", merr) + return + } + if _, werr := w.Write(buf); werr != nil { + grpclog.Infof("Failed to notify error to client: %v", werr) + return + } +} + +func errorChunk(st *status.Status) map[string]proto.Message { + return map[string]proto.Message{"error": st.Proto()} +} diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_httpbodyproto.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_httpbodyproto.go new file mode 100644 index 0000000000..b86135c889 --- /dev/null +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_httpbodyproto.go @@ -0,0 +1,32 @@ +package runtime + +import ( + "google.golang.org/genproto/googleapis/api/httpbody" +) + +// HTTPBodyMarshaler is a Marshaler which supports marshaling of a +// google.api.HttpBody message as the full response body if it is +// the actual message used as the response. If not, then this will +// simply fallback to the Marshaler specified as its default Marshaler. +type HTTPBodyMarshaler struct { + Marshaler +} + +// ContentType returns its specified content type in case v is a +// google.api.HttpBody message, otherwise it will fall back to the default Marshalers +// content type. +func (h *HTTPBodyMarshaler) ContentType(v interface{}) string { + if httpBody, ok := v.(*httpbody.HttpBody); ok { + return httpBody.GetContentType() + } + return h.Marshaler.ContentType(v) +} + +// Marshal marshals "v" by returning the body bytes if v is a +// google.api.HttpBody message, otherwise it falls back to the default Marshaler. +func (h *HTTPBodyMarshaler) Marshal(v interface{}) ([]byte, error) { + if httpBody, ok := v.(*httpbody.HttpBody); ok { + return httpBody.Data, nil + } + return h.Marshaler.Marshal(v) +} diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshal_json.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_json.go similarity index 95% rename from vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshal_json.go rename to vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_json.go index f9d3a585a4..d6aa825783 100644 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshal_json.go +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_json.go @@ -15,7 +15,7 @@ import ( type JSONBuiltin struct{} // ContentType always Returns "application/json". -func (*JSONBuiltin) ContentType() string { +func (*JSONBuiltin) ContentType(_ interface{}) string { return "application/json" } diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_jsonpb.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_jsonpb.go new file mode 100644 index 0000000000..7387c8e397 --- /dev/null +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_jsonpb.go @@ -0,0 +1,344 @@ +package runtime + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "reflect" + "strconv" + + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/proto" +) + +// JSONPb is a Marshaler which marshals/unmarshals into/from JSON +// with the "google.golang.org/protobuf/encoding/protojson" marshaler. +// It supports the full functionality of protobuf unlike JSONBuiltin. +// +// The NewDecoder method returns a DecoderWrapper, so the underlying +// *json.Decoder methods can be used. +type JSONPb struct { + protojson.MarshalOptions + protojson.UnmarshalOptions +} + +// ContentType always returns "application/json". +func (*JSONPb) ContentType(_ interface{}) string { + return "application/json" +} + +// Marshal marshals "v" into JSON. +func (j *JSONPb) Marshal(v interface{}) ([]byte, error) { + if _, ok := v.(proto.Message); !ok { + return j.marshalNonProtoField(v) + } + + var buf bytes.Buffer + if err := j.marshalTo(&buf, v); err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +func (j *JSONPb) marshalTo(w io.Writer, v interface{}) error { + p, ok := v.(proto.Message) + if !ok { + buf, err := j.marshalNonProtoField(v) + if err != nil { + return err + } + _, err = w.Write(buf) + return err + } + b, err := j.MarshalOptions.Marshal(p) + if err != nil { + return err + } + + _, err = w.Write(b) + return err +} + +var ( + // protoMessageType is stored to prevent constant lookup of the same type at runtime. + protoMessageType = reflect.TypeOf((*proto.Message)(nil)).Elem() +) + +// marshalNonProto marshals a non-message field of a protobuf message. +// This function does not correctly marshal arbitrary data structures into JSON, +// it is only capable of marshaling non-message field values of protobuf, +// i.e. primitive types, enums; pointers to primitives or enums; maps from +// integer/string types to primitives/enums/pointers to messages. +func (j *JSONPb) marshalNonProtoField(v interface{}) ([]byte, error) { + if v == nil { + return []byte("null"), nil + } + rv := reflect.ValueOf(v) + for rv.Kind() == reflect.Ptr { + if rv.IsNil() { + return []byte("null"), nil + } + rv = rv.Elem() + } + + if rv.Kind() == reflect.Slice { + if rv.IsNil() { + if j.EmitUnpopulated { + return []byte("[]"), nil + } + return []byte("null"), nil + } + + if rv.Type().Elem().Implements(protoMessageType) { + var buf bytes.Buffer + err := buf.WriteByte('[') + if err != nil { + return nil, err + } + for i := 0; i < rv.Len(); i++ { + if i != 0 { + err = buf.WriteByte(',') + if err != nil { + return nil, err + } + } + if err = j.marshalTo(&buf, rv.Index(i).Interface().(proto.Message)); err != nil { + return nil, err + } + } + err = buf.WriteByte(']') + if err != nil { + return nil, err + } + + return buf.Bytes(), nil + } + + if rv.Type().Elem().Implements(typeProtoEnum) { + var buf bytes.Buffer + err := buf.WriteByte('[') + if err != nil { + return nil, err + } + for i := 0; i < rv.Len(); i++ { + if i != 0 { + err = buf.WriteByte(',') + if err != nil { + return nil, err + } + } + if j.UseEnumNumbers { + _, err = buf.WriteString(strconv.FormatInt(rv.Index(i).Int(), 10)) + } else { + _, err = buf.WriteString("\"" + rv.Index(i).Interface().(protoEnum).String() + "\"") + } + if err != nil { + return nil, err + } + } + err = buf.WriteByte(']') + if err != nil { + return nil, err + } + + return buf.Bytes(), nil + } + } + + if rv.Kind() == reflect.Map { + m := make(map[string]*json.RawMessage) + for _, k := range rv.MapKeys() { + buf, err := j.Marshal(rv.MapIndex(k).Interface()) + if err != nil { + return nil, err + } + m[fmt.Sprintf("%v", k.Interface())] = (*json.RawMessage)(&buf) + } + if j.Indent != "" { + return json.MarshalIndent(m, "", j.Indent) + } + return json.Marshal(m) + } + if enum, ok := rv.Interface().(protoEnum); ok && !j.UseEnumNumbers { + return json.Marshal(enum.String()) + } + return json.Marshal(rv.Interface()) +} + +// Unmarshal unmarshals JSON "data" into "v" +func (j *JSONPb) Unmarshal(data []byte, v interface{}) error { + return unmarshalJSONPb(data, j.UnmarshalOptions, v) +} + +// NewDecoder returns a Decoder which reads JSON stream from "r". +func (j *JSONPb) NewDecoder(r io.Reader) Decoder { + d := json.NewDecoder(r) + return DecoderWrapper{ + Decoder: d, + UnmarshalOptions: j.UnmarshalOptions, + } +} + +// DecoderWrapper is a wrapper around a *json.Decoder that adds +// support for protos to the Decode method. +type DecoderWrapper struct { + *json.Decoder + protojson.UnmarshalOptions +} + +// Decode wraps the embedded decoder's Decode method to support +// protos using a jsonpb.Unmarshaler. +func (d DecoderWrapper) Decode(v interface{}) error { + return decodeJSONPb(d.Decoder, d.UnmarshalOptions, v) +} + +// NewEncoder returns an Encoder which writes JSON stream into "w". +func (j *JSONPb) NewEncoder(w io.Writer) Encoder { + return EncoderFunc(func(v interface{}) error { + if err := j.marshalTo(w, v); err != nil { + return err + } + // mimic json.Encoder by adding a newline (makes output + // easier to read when it contains multiple encoded items) + _, err := w.Write(j.Delimiter()) + return err + }) +} + +func unmarshalJSONPb(data []byte, unmarshaler protojson.UnmarshalOptions, v interface{}) error { + d := json.NewDecoder(bytes.NewReader(data)) + return decodeJSONPb(d, unmarshaler, v) +} + +func decodeJSONPb(d *json.Decoder, unmarshaler protojson.UnmarshalOptions, v interface{}) error { + p, ok := v.(proto.Message) + if !ok { + return decodeNonProtoField(d, unmarshaler, v) + } + + // Decode into bytes for marshalling + var b json.RawMessage + err := d.Decode(&b) + if err != nil { + return err + } + + return unmarshaler.Unmarshal([]byte(b), p) +} + +func decodeNonProtoField(d *json.Decoder, unmarshaler protojson.UnmarshalOptions, v interface{}) error { + rv := reflect.ValueOf(v) + if rv.Kind() != reflect.Ptr { + return fmt.Errorf("%T is not a pointer", v) + } + for rv.Kind() == reflect.Ptr { + if rv.IsNil() { + rv.Set(reflect.New(rv.Type().Elem())) + } + if rv.Type().ConvertibleTo(typeProtoMessage) { + // Decode into bytes for marshalling + var b json.RawMessage + err := d.Decode(&b) + if err != nil { + return err + } + + return unmarshaler.Unmarshal([]byte(b), rv.Interface().(proto.Message)) + } + rv = rv.Elem() + } + if rv.Kind() == reflect.Map { + if rv.IsNil() { + rv.Set(reflect.MakeMap(rv.Type())) + } + conv, ok := convFromType[rv.Type().Key().Kind()] + if !ok { + return fmt.Errorf("unsupported type of map field key: %v", rv.Type().Key()) + } + + m := make(map[string]*json.RawMessage) + if err := d.Decode(&m); err != nil { + return err + } + for k, v := range m { + result := conv.Call([]reflect.Value{reflect.ValueOf(k)}) + if err := result[1].Interface(); err != nil { + return err.(error) + } + bk := result[0] + bv := reflect.New(rv.Type().Elem()) + if v == nil { + null := json.RawMessage("null") + v = &null + } + if err := unmarshalJSONPb([]byte(*v), unmarshaler, bv.Interface()); err != nil { + return err + } + rv.SetMapIndex(bk, bv.Elem()) + } + return nil + } + if rv.Kind() == reflect.Slice { + var sl []json.RawMessage + if err := d.Decode(&sl); err != nil { + return err + } + if sl != nil { + rv.Set(reflect.MakeSlice(rv.Type(), 0, 0)) + } + for _, item := range sl { + bv := reflect.New(rv.Type().Elem()) + if err := unmarshalJSONPb([]byte(item), unmarshaler, bv.Interface()); err != nil { + return err + } + rv.Set(reflect.Append(rv, bv.Elem())) + } + return nil + } + if _, ok := rv.Interface().(protoEnum); ok { + var repr interface{} + if err := d.Decode(&repr); err != nil { + return err + } + switch v := repr.(type) { + case string: + // TODO(yugui) Should use proto.StructProperties? + return fmt.Errorf("unmarshaling of symbolic enum %q not supported: %T", repr, rv.Interface()) + case float64: + rv.Set(reflect.ValueOf(int32(v)).Convert(rv.Type())) + return nil + default: + return fmt.Errorf("cannot assign %#v into Go type %T", repr, rv.Interface()) + } + } + return d.Decode(v) +} + +type protoEnum interface { + fmt.Stringer + EnumDescriptor() ([]byte, []int) +} + +var typeProtoEnum = reflect.TypeOf((*protoEnum)(nil)).Elem() + +var typeProtoMessage = reflect.TypeOf((*proto.Message)(nil)).Elem() + +// Delimiter for newline encoded JSON streams. +func (j *JSONPb) Delimiter() []byte { + return []byte("\n") +} + +var ( + convFromType = map[reflect.Kind]reflect.Value{ + reflect.String: reflect.ValueOf(String), + reflect.Bool: reflect.ValueOf(Bool), + reflect.Float64: reflect.ValueOf(Float64), + reflect.Float32: reflect.ValueOf(Float32), + reflect.Int64: reflect.ValueOf(Int64), + reflect.Int32: reflect.ValueOf(Int32), + reflect.Uint64: reflect.ValueOf(Uint64), + reflect.Uint32: reflect.ValueOf(Uint32), + reflect.Slice: reflect.ValueOf(Bytes), + } +) diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshal_proto.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_proto.go similarity index 93% rename from vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshal_proto.go rename to vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_proto.go index f65d1a2676..007f8f1a2c 100644 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshal_proto.go +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_proto.go @@ -4,15 +4,16 @@ import ( "io" "errors" - "github.com/golang/protobuf/proto" "io/ioutil" + + "google.golang.org/protobuf/proto" ) // ProtoMarshaller is a Marshaller which marshals/unmarshals into/from serialize proto bytes type ProtoMarshaller struct{} // ContentType always returns "application/octet-stream". -func (*ProtoMarshaller) ContentType() string { +func (*ProtoMarshaller) ContentType(_ interface{}) string { return "application/octet-stream" } diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshaler.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshaler.go similarity index 80% rename from vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshaler.go rename to vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshaler.go index 4615329421..2c0d25ff49 100644 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshaler.go +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshaler.go @@ -16,14 +16,9 @@ type Marshaler interface { // NewEncoder returns an Encoder which writes bytes sequence into "w". NewEncoder(w io.Writer) Encoder // ContentType returns the Content-Type which this marshaler is responsible for. - ContentType() string -} - -// Marshalers that implement contentTypeMarshaler will have their ContentTypeFromMessage method called -// to set the Content-Type header on the response -type contentTypeMarshaler interface { - // ContentTypeFromMessage returns the Content-Type this marshaler produces from the provided message - ContentTypeFromMessage(v interface{}) string + // The parameter describes the type which is being marshalled, which can sometimes + // affect the content type returned. + ContentType(v interface{}) string } // Decoder decodes a byte sequence diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshaler_registry.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshaler_registry.go similarity index 91% rename from vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshaler_registry.go rename to vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshaler_registry.go index 8dd5c24db4..a714de0240 100644 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshaler_registry.go +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshaler_registry.go @@ -6,6 +6,7 @@ import ( "net/http" "google.golang.org/grpc/grpclog" + "google.golang.org/protobuf/encoding/protojson" ) // MIMEWildcard is the fallback MIME type used for requests which do not match @@ -16,7 +17,16 @@ var ( acceptHeader = http.CanonicalHeaderKey("Accept") contentTypeHeader = http.CanonicalHeaderKey("Content-Type") - defaultMarshaler = &JSONPb{OrigName: true} + defaultMarshaler = &HTTPBodyMarshaler{ + Marshaler: &JSONPb{ + MarshalOptions: protojson.MarshalOptions{ + EmitUnpopulated: true, + }, + UnmarshalOptions: protojson.UnmarshalOptions{ + DiscardUnknown: true, + }, + }, + } ) // MarshalerForRequest returns the inbound/outbound marshalers for this request. diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/mux.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/mux.go new file mode 100644 index 0000000000..46a4aabaf9 --- /dev/null +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/mux.go @@ -0,0 +1,356 @@ +package runtime + +import ( + "context" + "errors" + "fmt" + "net/http" + "net/textproto" + "strings" + + "github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" +) + +// UnescapingMode defines the behavior of ServeMux when unescaping path parameters. +type UnescapingMode int + +const ( + // UnescapingModeLegacy is the default V2 behavior, which escapes the entire + // path string before doing any routing. + UnescapingModeLegacy UnescapingMode = iota + + // EscapingTypeExceptReserved unescapes all path parameters except RFC 6570 + // reserved characters. + UnescapingModeAllExceptReserved + + // EscapingTypeExceptSlash unescapes URL path parameters except path + // seperators, which will be left as "%2F". + UnescapingModeAllExceptSlash + + // URL path parameters will be fully decoded. + UnescapingModeAllCharacters + + // UnescapingModeDefault is the default escaping type. + // TODO(v3): default this to UnescapingModeAllExceptReserved per grpc-httpjson-transcoding's + // reference implementation + UnescapingModeDefault = UnescapingModeLegacy +) + +// A HandlerFunc handles a specific pair of path pattern and HTTP method. +type HandlerFunc func(w http.ResponseWriter, r *http.Request, pathParams map[string]string) + +// ServeMux is a request multiplexer for grpc-gateway. +// It matches http requests to patterns and invokes the corresponding handler. +type ServeMux struct { + // handlers maps HTTP method to a list of handlers. + handlers map[string][]handler + forwardResponseOptions []func(context.Context, http.ResponseWriter, proto.Message) error + marshalers marshalerRegistry + incomingHeaderMatcher HeaderMatcherFunc + outgoingHeaderMatcher HeaderMatcherFunc + metadataAnnotators []func(context.Context, *http.Request) metadata.MD + errorHandler ErrorHandlerFunc + streamErrorHandler StreamErrorHandlerFunc + routingErrorHandler RoutingErrorHandlerFunc + disablePathLengthFallback bool + unescapingMode UnescapingMode +} + +// ServeMuxOption is an option that can be given to a ServeMux on construction. +type ServeMuxOption func(*ServeMux) + +// WithForwardResponseOption returns a ServeMuxOption representing the forwardResponseOption. +// +// forwardResponseOption is an option that will be called on the relevant context.Context, +// http.ResponseWriter, and proto.Message before every forwarded response. +// +// The message may be nil in the case where just a header is being sent. +func WithForwardResponseOption(forwardResponseOption func(context.Context, http.ResponseWriter, proto.Message) error) ServeMuxOption { + return func(serveMux *ServeMux) { + serveMux.forwardResponseOptions = append(serveMux.forwardResponseOptions, forwardResponseOption) + } +} + +// WithEscapingType sets the escaping type. See the definitions of UnescapingMode +// for more information. +func WithUnescapingMode(mode UnescapingMode) ServeMuxOption { + return func(serveMux *ServeMux) { + serveMux.unescapingMode = mode + } +} + +// SetQueryParameterParser sets the query parameter parser, used to populate message from query parameters. +// Configuring this will mean the generated OpenAPI output is no longer correct, and it should be +// done with careful consideration. +func SetQueryParameterParser(queryParameterParser QueryParameterParser) ServeMuxOption { + return func(serveMux *ServeMux) { + currentQueryParser = queryParameterParser + } +} + +// HeaderMatcherFunc checks whether a header key should be forwarded to/from gRPC context. +type HeaderMatcherFunc func(string) (string, bool) + +// DefaultHeaderMatcher is used to pass http request headers to/from gRPC context. This adds permanent HTTP header +// keys (as specified by the IANA) to gRPC context with grpcgateway- prefix. HTTP headers that start with +// 'Grpc-Metadata-' are mapped to gRPC metadata after removing prefix 'Grpc-Metadata-'. +func DefaultHeaderMatcher(key string) (string, bool) { + key = textproto.CanonicalMIMEHeaderKey(key) + if isPermanentHTTPHeader(key) { + return MetadataPrefix + key, true + } else if strings.HasPrefix(key, MetadataHeaderPrefix) { + return key[len(MetadataHeaderPrefix):], true + } + return "", false +} + +// WithIncomingHeaderMatcher returns a ServeMuxOption representing a headerMatcher for incoming request to gateway. +// +// This matcher will be called with each header in http.Request. If matcher returns true, that header will be +// passed to gRPC context. To transform the header before passing to gRPC context, matcher should return modified header. +func WithIncomingHeaderMatcher(fn HeaderMatcherFunc) ServeMuxOption { + return func(mux *ServeMux) { + mux.incomingHeaderMatcher = fn + } +} + +// WithOutgoingHeaderMatcher returns a ServeMuxOption representing a headerMatcher for outgoing response from gateway. +// +// This matcher will be called with each header in response header metadata. If matcher returns true, that header will be +// passed to http response returned from gateway. To transform the header before passing to response, +// matcher should return modified header. +func WithOutgoingHeaderMatcher(fn HeaderMatcherFunc) ServeMuxOption { + return func(mux *ServeMux) { + mux.outgoingHeaderMatcher = fn + } +} + +// WithMetadata returns a ServeMuxOption for passing metadata to a gRPC context. +// +// This can be used by services that need to read from http.Request and modify gRPC context. A common use case +// is reading token from cookie and adding it in gRPC context. +func WithMetadata(annotator func(context.Context, *http.Request) metadata.MD) ServeMuxOption { + return func(serveMux *ServeMux) { + serveMux.metadataAnnotators = append(serveMux.metadataAnnotators, annotator) + } +} + +// WithErrorHandler returns a ServeMuxOption for configuring a custom error handler. +// +// This can be used to configure a custom error response. +func WithErrorHandler(fn ErrorHandlerFunc) ServeMuxOption { + return func(serveMux *ServeMux) { + serveMux.errorHandler = fn + } +} + +// WithStreamErrorHandler returns a ServeMuxOption that will use the given custom stream +// error handler, which allows for customizing the error trailer for server-streaming +// calls. +// +// For stream errors that occur before any response has been written, the mux's +// ErrorHandler will be invoked. However, once data has been written, the errors must +// be handled differently: they must be included in the response body. The response body's +// final message will include the error details returned by the stream error handler. +func WithStreamErrorHandler(fn StreamErrorHandlerFunc) ServeMuxOption { + return func(serveMux *ServeMux) { + serveMux.streamErrorHandler = fn + } +} + +// WithRoutingErrorHandler returns a ServeMuxOption for configuring a custom error handler to handle http routing errors. +// +// Method called for errors which can happen before gRPC route selected or executed. +// The following error codes: StatusMethodNotAllowed StatusNotFound StatusBadRequest +func WithRoutingErrorHandler(fn RoutingErrorHandlerFunc) ServeMuxOption { + return func(serveMux *ServeMux) { + serveMux.routingErrorHandler = fn + } +} + +// WithDisablePathLengthFallback returns a ServeMuxOption for disable path length fallback. +func WithDisablePathLengthFallback() ServeMuxOption { + return func(serveMux *ServeMux) { + serveMux.disablePathLengthFallback = true + } +} + +// NewServeMux returns a new ServeMux whose internal mapping is empty. +func NewServeMux(opts ...ServeMuxOption) *ServeMux { + serveMux := &ServeMux{ + handlers: make(map[string][]handler), + forwardResponseOptions: make([]func(context.Context, http.ResponseWriter, proto.Message) error, 0), + marshalers: makeMarshalerMIMERegistry(), + errorHandler: DefaultHTTPErrorHandler, + streamErrorHandler: DefaultStreamErrorHandler, + routingErrorHandler: DefaultRoutingErrorHandler, + unescapingMode: UnescapingModeDefault, + } + + for _, opt := range opts { + opt(serveMux) + } + + if serveMux.incomingHeaderMatcher == nil { + serveMux.incomingHeaderMatcher = DefaultHeaderMatcher + } + + if serveMux.outgoingHeaderMatcher == nil { + serveMux.outgoingHeaderMatcher = func(key string) (string, bool) { + return fmt.Sprintf("%s%s", MetadataHeaderPrefix, key), true + } + } + + return serveMux +} + +// Handle associates "h" to the pair of HTTP method and path pattern. +func (s *ServeMux) Handle(meth string, pat Pattern, h HandlerFunc) { + s.handlers[meth] = append([]handler{{pat: pat, h: h}}, s.handlers[meth]...) +} + +// HandlePath allows users to configure custom path handlers. +// refer: https://grpc-ecosystem.github.io/grpc-gateway/docs/operations/inject_router/ +func (s *ServeMux) HandlePath(meth string, pathPattern string, h HandlerFunc) error { + compiler, err := httprule.Parse(pathPattern) + if err != nil { + return fmt.Errorf("parsing path pattern: %w", err) + } + tp := compiler.Compile() + pattern, err := NewPattern(tp.Version, tp.OpCodes, tp.Pool, tp.Verb) + if err != nil { + return fmt.Errorf("creating new pattern: %w", err) + } + s.Handle(meth, pattern, h) + return nil +} + +// ServeHTTP dispatches the request to the first handler whose pattern matches to r.Method and r.Path. +func (s *ServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + + path := r.URL.Path + if !strings.HasPrefix(path, "/") { + _, outboundMarshaler := MarshalerForRequest(s, r) + s.routingErrorHandler(ctx, s, outboundMarshaler, w, r, http.StatusBadRequest) + return + } + + // TODO(v3): remove UnescapingModeLegacy + if s.unescapingMode != UnescapingModeLegacy && r.URL.RawPath != "" { + path = r.URL.RawPath + } + + components := strings.Split(path[1:], "/") + + if override := r.Header.Get("X-HTTP-Method-Override"); override != "" && s.isPathLengthFallback(r) { + r.Method = strings.ToUpper(override) + if err := r.ParseForm(); err != nil { + _, outboundMarshaler := MarshalerForRequest(s, r) + sterr := status.Error(codes.InvalidArgument, err.Error()) + s.errorHandler(ctx, s, outboundMarshaler, w, r, sterr) + return + } + } + + // Verb out here is to memoize for the fallback case below + var verb string + + for _, h := range s.handlers[r.Method] { + // If the pattern has a verb, explicitly look for a suffix in the last + // component that matches a colon plus the verb. This allows us to + // handle some cases that otherwise can't be correctly handled by the + // former LastIndex case, such as when the verb literal itself contains + // a colon. This should work for all cases that have run through the + // parser because we know what verb we're looking for, however, there + // are still some cases that the parser itself cannot disambiguate. See + // the comment there if interested. + patVerb := h.pat.Verb() + l := len(components) + lastComponent := components[l-1] + var idx int = -1 + if patVerb != "" && strings.HasSuffix(lastComponent, ":"+patVerb) { + idx = len(lastComponent) - len(patVerb) - 1 + } + if idx == 0 { + _, outboundMarshaler := MarshalerForRequest(s, r) + s.routingErrorHandler(ctx, s, outboundMarshaler, w, r, http.StatusNotFound) + return + } + if idx > 0 { + components[l-1], verb = lastComponent[:idx], lastComponent[idx+1:] + } + + pathParams, err := h.pat.MatchAndEscape(components, verb, s.unescapingMode) + if err != nil { + var mse MalformedSequenceError + if ok := errors.As(err, &mse); ok { + _, outboundMarshaler := MarshalerForRequest(s, r) + s.errorHandler(ctx, s, outboundMarshaler, w, r, &HTTPStatusError{ + HTTPStatus: http.StatusBadRequest, + Err: mse, + }) + } + continue + } + h.h(w, r, pathParams) + return + } + + // lookup other methods to handle fallback from GET to POST and + // to determine if it is NotImplemented or NotFound. + for m, handlers := range s.handlers { + if m == r.Method { + continue + } + for _, h := range handlers { + pathParams, err := h.pat.MatchAndEscape(components, verb, s.unescapingMode) + if err != nil { + var mse MalformedSequenceError + if ok := errors.As(err, &mse); ok { + _, outboundMarshaler := MarshalerForRequest(s, r) + s.errorHandler(ctx, s, outboundMarshaler, w, r, &HTTPStatusError{ + HTTPStatus: http.StatusBadRequest, + Err: mse, + }) + } + continue + } + // X-HTTP-Method-Override is optional. Always allow fallback to POST. + if s.isPathLengthFallback(r) { + if err := r.ParseForm(); err != nil { + _, outboundMarshaler := MarshalerForRequest(s, r) + sterr := status.Error(codes.InvalidArgument, err.Error()) + s.errorHandler(ctx, s, outboundMarshaler, w, r, sterr) + return + } + h.h(w, r, pathParams) + return + } + _, outboundMarshaler := MarshalerForRequest(s, r) + s.routingErrorHandler(ctx, s, outboundMarshaler, w, r, http.StatusMethodNotAllowed) + return + } + } + + _, outboundMarshaler := MarshalerForRequest(s, r) + s.routingErrorHandler(ctx, s, outboundMarshaler, w, r, http.StatusNotFound) +} + +// GetForwardResponseOptions returns the ForwardResponseOptions associated with this ServeMux. +func (s *ServeMux) GetForwardResponseOptions() []func(context.Context, http.ResponseWriter, proto.Message) error { + return s.forwardResponseOptions +} + +func (s *ServeMux) isPathLengthFallback(r *http.Request) bool { + return !s.disablePathLengthFallback && r.Method == "POST" && r.Header.Get("Content-Type") == "application/x-www-form-urlencoded" +} + +type handler struct { + pat Pattern + h HandlerFunc +} diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/pattern.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/pattern.go new file mode 100644 index 0000000000..df7cb81426 --- /dev/null +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/pattern.go @@ -0,0 +1,383 @@ +package runtime + +import ( + "errors" + "fmt" + "strconv" + "strings" + + "github.com/grpc-ecosystem/grpc-gateway/v2/utilities" + "google.golang.org/grpc/grpclog" +) + +var ( + // ErrNotMatch indicates that the given HTTP request path does not match to the pattern. + ErrNotMatch = errors.New("not match to the path pattern") + // ErrInvalidPattern indicates that the given definition of Pattern is not valid. + ErrInvalidPattern = errors.New("invalid pattern") + // ErrMalformedSequence indicates that an escape sequence was malformed. + ErrMalformedSequence = errors.New("malformed escape sequence") +) + +type MalformedSequenceError string + +func (e MalformedSequenceError) Error() string { + return "malformed path escape " + strconv.Quote(string(e)) +} + +type op struct { + code utilities.OpCode + operand int +} + +// Pattern is a template pattern of http request paths defined in +// https://github.com/googleapis/googleapis/blob/master/google/api/http.proto +type Pattern struct { + // ops is a list of operations + ops []op + // pool is a constant pool indexed by the operands or vars. + pool []string + // vars is a list of variables names to be bound by this pattern + vars []string + // stacksize is the max depth of the stack + stacksize int + // tailLen is the length of the fixed-size segments after a deep wildcard + tailLen int + // verb is the VERB part of the path pattern. It is empty if the pattern does not have VERB part. + verb string +} + +// NewPattern returns a new Pattern from the given definition values. +// "ops" is a sequence of op codes. "pool" is a constant pool. +// "verb" is the verb part of the pattern. It is empty if the pattern does not have the part. +// "version" must be 1 for now. +// It returns an error if the given definition is invalid. +func NewPattern(version int, ops []int, pool []string, verb string) (Pattern, error) { + if version != 1 { + grpclog.Infof("unsupported version: %d", version) + return Pattern{}, ErrInvalidPattern + } + + l := len(ops) + if l%2 != 0 { + grpclog.Infof("odd number of ops codes: %d", l) + return Pattern{}, ErrInvalidPattern + } + + var ( + typedOps []op + stack, maxstack int + tailLen int + pushMSeen bool + vars []string + ) + for i := 0; i < l; i += 2 { + op := op{code: utilities.OpCode(ops[i]), operand: ops[i+1]} + switch op.code { + case utilities.OpNop: + continue + case utilities.OpPush: + if pushMSeen { + tailLen++ + } + stack++ + case utilities.OpPushM: + if pushMSeen { + grpclog.Infof("pushM appears twice") + return Pattern{}, ErrInvalidPattern + } + pushMSeen = true + stack++ + case utilities.OpLitPush: + if op.operand < 0 || len(pool) <= op.operand { + grpclog.Infof("negative literal index: %d", op.operand) + return Pattern{}, ErrInvalidPattern + } + if pushMSeen { + tailLen++ + } + stack++ + case utilities.OpConcatN: + if op.operand <= 0 { + grpclog.Infof("negative concat size: %d", op.operand) + return Pattern{}, ErrInvalidPattern + } + stack -= op.operand + if stack < 0 { + grpclog.Info("stack underflow") + return Pattern{}, ErrInvalidPattern + } + stack++ + case utilities.OpCapture: + if op.operand < 0 || len(pool) <= op.operand { + grpclog.Infof("variable name index out of bound: %d", op.operand) + return Pattern{}, ErrInvalidPattern + } + v := pool[op.operand] + op.operand = len(vars) + vars = append(vars, v) + stack-- + if stack < 0 { + grpclog.Infof("stack underflow") + return Pattern{}, ErrInvalidPattern + } + default: + grpclog.Infof("invalid opcode: %d", op.code) + return Pattern{}, ErrInvalidPattern + } + + if maxstack < stack { + maxstack = stack + } + typedOps = append(typedOps, op) + } + return Pattern{ + ops: typedOps, + pool: pool, + vars: vars, + stacksize: maxstack, + tailLen: tailLen, + verb: verb, + }, nil +} + +// MustPattern is a helper function which makes it easier to call NewPattern in variable initialization. +func MustPattern(p Pattern, err error) Pattern { + if err != nil { + grpclog.Fatalf("Pattern initialization failed: %v", err) + } + return p +} + +// MatchAndEscape examines components to determine if they match to a Pattern. +// MatchAndEscape will return an error if no Patterns matched or if a pattern +// matched but contained malformed escape sequences. If successful, the function +// returns a mapping from field paths to their captured values. +func (p Pattern) MatchAndEscape(components []string, verb string, unescapingMode UnescapingMode) (map[string]string, error) { + if p.verb != verb { + if p.verb != "" { + return nil, ErrNotMatch + } + if len(components) == 0 { + components = []string{":" + verb} + } else { + components = append([]string{}, components...) + components[len(components)-1] += ":" + verb + } + } + + var pos int + stack := make([]string, 0, p.stacksize) + captured := make([]string, len(p.vars)) + l := len(components) + for _, op := range p.ops { + var err error + + switch op.code { + case utilities.OpNop: + continue + case utilities.OpPush, utilities.OpLitPush: + if pos >= l { + return nil, ErrNotMatch + } + c := components[pos] + if op.code == utilities.OpLitPush { + if lit := p.pool[op.operand]; c != lit { + return nil, ErrNotMatch + } + } else if op.code == utilities.OpPush { + if c, err = unescape(c, unescapingMode, false); err != nil { + return nil, err + } + } + stack = append(stack, c) + pos++ + case utilities.OpPushM: + end := len(components) + if end < pos+p.tailLen { + return nil, ErrNotMatch + } + end -= p.tailLen + c := strings.Join(components[pos:end], "/") + if c, err = unescape(c, unescapingMode, true); err != nil { + return nil, err + } + stack = append(stack, c) + pos = end + case utilities.OpConcatN: + n := op.operand + l := len(stack) - n + stack = append(stack[:l], strings.Join(stack[l:], "/")) + case utilities.OpCapture: + n := len(stack) - 1 + captured[op.operand] = stack[n] + stack = stack[:n] + } + } + if pos < l { + return nil, ErrNotMatch + } + bindings := make(map[string]string) + for i, val := range captured { + bindings[p.vars[i]] = val + } + return bindings, nil +} + +// MatchAndEscape examines components to determine if they match to a Pattern. +// It will never perform per-component unescaping (see: UnescapingModeLegacy). +// MatchAndEscape will return an error if no Patterns matched. If successful, +// the function returns a mapping from field paths to their captured values. +// +// Deprecated: Use MatchAndEscape. +func (p Pattern) Match(components []string, verb string) (map[string]string, error) { + return p.MatchAndEscape(components, verb, UnescapingModeDefault) +} + +// Verb returns the verb part of the Pattern. +func (p Pattern) Verb() string { return p.verb } + +func (p Pattern) String() string { + var stack []string + for _, op := range p.ops { + switch op.code { + case utilities.OpNop: + continue + case utilities.OpPush: + stack = append(stack, "*") + case utilities.OpLitPush: + stack = append(stack, p.pool[op.operand]) + case utilities.OpPushM: + stack = append(stack, "**") + case utilities.OpConcatN: + n := op.operand + l := len(stack) - n + stack = append(stack[:l], strings.Join(stack[l:], "/")) + case utilities.OpCapture: + n := len(stack) - 1 + stack[n] = fmt.Sprintf("{%s=%s}", p.vars[op.operand], stack[n]) + } + } + segs := strings.Join(stack, "/") + if p.verb != "" { + return fmt.Sprintf("/%s:%s", segs, p.verb) + } + return "/" + segs +} + +/* + * The following code is adopted and modified from Go's standard library + * and carries the attached license. + * + * Copyright 2009 The Go Authors. All rights reserved. + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file. + */ + +// ishex returns whether or not the given byte is a valid hex character +func ishex(c byte) bool { + switch { + case '0' <= c && c <= '9': + return true + case 'a' <= c && c <= 'f': + return true + case 'A' <= c && c <= 'F': + return true + } + return false +} + +func isRFC6570Reserved(c byte) bool { + switch c { + case '!', '#', '$', '&', '\'', '(', ')', '*', + '+', ',', '/', ':', ';', '=', '?', '@', '[', ']': + return true + default: + return false + } +} + +// unhex converts a hex point to the bit representation +func unhex(c byte) byte { + switch { + case '0' <= c && c <= '9': + return c - '0' + case 'a' <= c && c <= 'f': + return c - 'a' + 10 + case 'A' <= c && c <= 'F': + return c - 'A' + 10 + } + return 0 +} + +// shouldUnescapeWithMode returns true if the character is escapable with the +// given mode +func shouldUnescapeWithMode(c byte, mode UnescapingMode) bool { + switch mode { + case UnescapingModeAllExceptReserved: + if isRFC6570Reserved(c) { + return false + } + case UnescapingModeAllExceptSlash: + if c == '/' { + return false + } + case UnescapingModeAllCharacters: + return true + } + return true +} + +// unescape unescapes a path string using the provided mode +func unescape(s string, mode UnescapingMode, multisegment bool) (string, error) { + // TODO(v3): remove UnescapingModeLegacy + if mode == UnescapingModeLegacy { + return s, nil + } + + if !multisegment { + mode = UnescapingModeAllCharacters + } + + // Count %, check that they're well-formed. + n := 0 + for i := 0; i < len(s); { + if s[i] == '%' { + n++ + if i+2 >= len(s) || !ishex(s[i+1]) || !ishex(s[i+2]) { + s = s[i:] + if len(s) > 3 { + s = s[:3] + } + + return "", MalformedSequenceError(s) + } + i += 3 + } else { + i++ + } + } + + if n == 0 { + return s, nil + } + + var t strings.Builder + t.Grow(len(s)) + for i := 0; i < len(s); i++ { + switch s[i] { + case '%': + c := unhex(s[i+1])<<4 | unhex(s[i+2]) + if shouldUnescapeWithMode(c, mode) { + t.WriteByte(c) + i += 2 + continue + } + fallthrough + default: + t.WriteByte(s[i]) + } + } + + return t.String(), nil +} diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/proto2_convert.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/proto2_convert.go similarity index 98% rename from vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/proto2_convert.go rename to vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/proto2_convert.go index a3151e2a55..d549407f20 100644 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/proto2_convert.go +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/proto2_convert.go @@ -1,7 +1,7 @@ package runtime import ( - "github.com/golang/protobuf/proto" + "google.golang.org/protobuf/proto" ) // StringP returns a pointer to a string whose pointee is same as the given string value. diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/query.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/query.go new file mode 100644 index 0000000000..fb0c84ef0c --- /dev/null +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/query.go @@ -0,0 +1,329 @@ +package runtime + +import ( + "encoding/base64" + "errors" + "fmt" + "net/url" + "regexp" + "strconv" + "strings" + "time" + + "github.com/grpc-ecosystem/grpc-gateway/v2/utilities" + "google.golang.org/genproto/protobuf/field_mask" + "google.golang.org/grpc/grpclog" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/reflect/protoregistry" + "google.golang.org/protobuf/types/known/durationpb" + "google.golang.org/protobuf/types/known/timestamppb" + "google.golang.org/protobuf/types/known/wrapperspb" +) + +var valuesKeyRegexp = regexp.MustCompile(`^(.*)\[(.*)\]$`) + +var currentQueryParser QueryParameterParser = &defaultQueryParser{} + +// QueryParameterParser defines interface for all query parameter parsers +type QueryParameterParser interface { + Parse(msg proto.Message, values url.Values, filter *utilities.DoubleArray) error +} + +// PopulateQueryParameters parses query parameters +// into "msg" using current query parser +func PopulateQueryParameters(msg proto.Message, values url.Values, filter *utilities.DoubleArray) error { + return currentQueryParser.Parse(msg, values, filter) +} + +type defaultQueryParser struct{} + +// Parse populates "values" into "msg". +// A value is ignored if its key starts with one of the elements in "filter". +func (*defaultQueryParser) Parse(msg proto.Message, values url.Values, filter *utilities.DoubleArray) error { + for key, values := range values { + match := valuesKeyRegexp.FindStringSubmatch(key) + if len(match) == 3 { + key = match[1] + values = append([]string{match[2]}, values...) + } + fieldPath := strings.Split(key, ".") + if filter.HasCommonPrefix(fieldPath) { + continue + } + if err := populateFieldValueFromPath(msg.ProtoReflect(), fieldPath, values); err != nil { + return err + } + } + return nil +} + +// PopulateFieldFromPath sets a value in a nested Protobuf structure. +func PopulateFieldFromPath(msg proto.Message, fieldPathString string, value string) error { + fieldPath := strings.Split(fieldPathString, ".") + return populateFieldValueFromPath(msg.ProtoReflect(), fieldPath, []string{value}) +} + +func populateFieldValueFromPath(msgValue protoreflect.Message, fieldPath []string, values []string) error { + if len(fieldPath) < 1 { + return errors.New("no field path") + } + if len(values) < 1 { + return errors.New("no value provided") + } + + var fieldDescriptor protoreflect.FieldDescriptor + for i, fieldName := range fieldPath { + fields := msgValue.Descriptor().Fields() + + // Get field by name + fieldDescriptor = fields.ByName(protoreflect.Name(fieldName)) + if fieldDescriptor == nil { + fieldDescriptor = fields.ByJSONName(fieldName) + if fieldDescriptor == nil { + // We're not returning an error here because this could just be + // an extra query parameter that isn't part of the request. + grpclog.Infof("field not found in %q: %q", msgValue.Descriptor().FullName(), strings.Join(fieldPath, ".")) + return nil + } + } + + // If this is the last element, we're done + if i == len(fieldPath)-1 { + break + } + + // Only singular message fields are allowed + if fieldDescriptor.Message() == nil || fieldDescriptor.Cardinality() == protoreflect.Repeated { + return fmt.Errorf("invalid path: %q is not a message", fieldName) + } + + // Get the nested message + msgValue = msgValue.Mutable(fieldDescriptor).Message() + } + + // Check if oneof already set + if of := fieldDescriptor.ContainingOneof(); of != nil { + if f := msgValue.WhichOneof(of); f != nil { + return fmt.Errorf("field already set for oneof %q", of.FullName().Name()) + } + } + + switch { + case fieldDescriptor.IsList(): + return populateRepeatedField(fieldDescriptor, msgValue.Mutable(fieldDescriptor).List(), values) + case fieldDescriptor.IsMap(): + return populateMapField(fieldDescriptor, msgValue.Mutable(fieldDescriptor).Map(), values) + } + + if len(values) > 1 { + return fmt.Errorf("too many values for field %q: %s", fieldDescriptor.FullName().Name(), strings.Join(values, ", ")) + } + + return populateField(fieldDescriptor, msgValue, values[0]) +} + +func populateField(fieldDescriptor protoreflect.FieldDescriptor, msgValue protoreflect.Message, value string) error { + v, err := parseField(fieldDescriptor, value) + if err != nil { + return fmt.Errorf("parsing field %q: %w", fieldDescriptor.FullName().Name(), err) + } + + msgValue.Set(fieldDescriptor, v) + return nil +} + +func populateRepeatedField(fieldDescriptor protoreflect.FieldDescriptor, list protoreflect.List, values []string) error { + for _, value := range values { + v, err := parseField(fieldDescriptor, value) + if err != nil { + return fmt.Errorf("parsing list %q: %w", fieldDescriptor.FullName().Name(), err) + } + list.Append(v) + } + + return nil +} + +func populateMapField(fieldDescriptor protoreflect.FieldDescriptor, mp protoreflect.Map, values []string) error { + if len(values) != 2 { + return fmt.Errorf("more than one value provided for key %q in map %q", values[0], fieldDescriptor.FullName()) + } + + key, err := parseField(fieldDescriptor.MapKey(), values[0]) + if err != nil { + return fmt.Errorf("parsing map key %q: %w", fieldDescriptor.FullName().Name(), err) + } + + value, err := parseField(fieldDescriptor.MapValue(), values[1]) + if err != nil { + return fmt.Errorf("parsing map value %q: %w", fieldDescriptor.FullName().Name(), err) + } + + mp.Set(key.MapKey(), value) + + return nil +} + +func parseField(fieldDescriptor protoreflect.FieldDescriptor, value string) (protoreflect.Value, error) { + switch fieldDescriptor.Kind() { + case protoreflect.BoolKind: + v, err := strconv.ParseBool(value) + if err != nil { + return protoreflect.Value{}, err + } + return protoreflect.ValueOfBool(v), nil + case protoreflect.EnumKind: + enum, err := protoregistry.GlobalTypes.FindEnumByName(fieldDescriptor.Enum().FullName()) + switch { + case errors.Is(err, protoregistry.NotFound): + return protoreflect.Value{}, fmt.Errorf("enum %q is not registered", fieldDescriptor.Enum().FullName()) + case err != nil: + return protoreflect.Value{}, fmt.Errorf("failed to look up enum: %w", err) + } + // Look for enum by name + v := enum.Descriptor().Values().ByName(protoreflect.Name(value)) + if v == nil { + i, err := strconv.Atoi(value) + if err != nil { + return protoreflect.Value{}, fmt.Errorf("%q is not a valid value", value) + } + // Look for enum by number + v = enum.Descriptor().Values().ByNumber(protoreflect.EnumNumber(i)) + if v == nil { + return protoreflect.Value{}, fmt.Errorf("%q is not a valid value", value) + } + } + return protoreflect.ValueOfEnum(v.Number()), nil + case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind: + v, err := strconv.ParseInt(value, 10, 32) + if err != nil { + return protoreflect.Value{}, err + } + return protoreflect.ValueOfInt32(int32(v)), nil + case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: + v, err := strconv.ParseInt(value, 10, 64) + if err != nil { + return protoreflect.Value{}, err + } + return protoreflect.ValueOfInt64(v), nil + case protoreflect.Uint32Kind, protoreflect.Fixed32Kind: + v, err := strconv.ParseUint(value, 10, 32) + if err != nil { + return protoreflect.Value{}, err + } + return protoreflect.ValueOfUint32(uint32(v)), nil + case protoreflect.Uint64Kind, protoreflect.Fixed64Kind: + v, err := strconv.ParseUint(value, 10, 64) + if err != nil { + return protoreflect.Value{}, err + } + return protoreflect.ValueOfUint64(v), nil + case protoreflect.FloatKind: + v, err := strconv.ParseFloat(value, 32) + if err != nil { + return protoreflect.Value{}, err + } + return protoreflect.ValueOfFloat32(float32(v)), nil + case protoreflect.DoubleKind: + v, err := strconv.ParseFloat(value, 64) + if err != nil { + return protoreflect.Value{}, err + } + return protoreflect.ValueOfFloat64(v), nil + case protoreflect.StringKind: + return protoreflect.ValueOfString(value), nil + case protoreflect.BytesKind: + v, err := base64.URLEncoding.DecodeString(value) + if err != nil { + return protoreflect.Value{}, err + } + return protoreflect.ValueOfBytes(v), nil + case protoreflect.MessageKind, protoreflect.GroupKind: + return parseMessage(fieldDescriptor.Message(), value) + default: + panic(fmt.Sprintf("unknown field kind: %v", fieldDescriptor.Kind())) + } +} + +func parseMessage(msgDescriptor protoreflect.MessageDescriptor, value string) (protoreflect.Value, error) { + var msg proto.Message + switch msgDescriptor.FullName() { + case "google.protobuf.Timestamp": + if value == "null" { + break + } + t, err := time.Parse(time.RFC3339Nano, value) + if err != nil { + return protoreflect.Value{}, err + } + msg = timestamppb.New(t) + case "google.protobuf.Duration": + if value == "null" { + break + } + d, err := time.ParseDuration(value) + if err != nil { + return protoreflect.Value{}, err + } + msg = durationpb.New(d) + case "google.protobuf.DoubleValue": + v, err := strconv.ParseFloat(value, 64) + if err != nil { + return protoreflect.Value{}, err + } + msg = &wrapperspb.DoubleValue{Value: v} + case "google.protobuf.FloatValue": + v, err := strconv.ParseFloat(value, 32) + if err != nil { + return protoreflect.Value{}, err + } + msg = &wrapperspb.FloatValue{Value: float32(v)} + case "google.protobuf.Int64Value": + v, err := strconv.ParseInt(value, 10, 64) + if err != nil { + return protoreflect.Value{}, err + } + msg = &wrapperspb.Int64Value{Value: v} + case "google.protobuf.Int32Value": + v, err := strconv.ParseInt(value, 10, 32) + if err != nil { + return protoreflect.Value{}, err + } + msg = &wrapperspb.Int32Value{Value: int32(v)} + case "google.protobuf.UInt64Value": + v, err := strconv.ParseUint(value, 10, 64) + if err != nil { + return protoreflect.Value{}, err + } + msg = &wrapperspb.UInt64Value{Value: v} + case "google.protobuf.UInt32Value": + v, err := strconv.ParseUint(value, 10, 32) + if err != nil { + return protoreflect.Value{}, err + } + msg = &wrapperspb.UInt32Value{Value: uint32(v)} + case "google.protobuf.BoolValue": + v, err := strconv.ParseBool(value) + if err != nil { + return protoreflect.Value{}, err + } + msg = &wrapperspb.BoolValue{Value: v} + case "google.protobuf.StringValue": + msg = &wrapperspb.StringValue{Value: value} + case "google.protobuf.BytesValue": + v, err := base64.URLEncoding.DecodeString(value) + if err != nil { + return protoreflect.Value{}, err + } + msg = &wrapperspb.BytesValue{Value: v} + case "google.protobuf.FieldMask": + fm := &field_mask.FieldMask{} + fm.Paths = append(fm.Paths, strings.Split(value, ",")...) + msg = fm + default: + return protoreflect.Value{}, fmt.Errorf("unsupported message type: %q", string(msgDescriptor.FullName())) + } + + return protoreflect.ValueOfMessage(msg.ProtoReflect()), nil +} diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/utilities/BUILD.bazel b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/utilities/BUILD.bazel new file mode 100644 index 0000000000..5d8d12bc42 --- /dev/null +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/utilities/BUILD.bazel @@ -0,0 +1,27 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +package(default_visibility = ["//visibility:public"]) + +go_library( + name = "utilities", + srcs = [ + "doc.go", + "pattern.go", + "readerfactory.go", + "trie.go", + ], + importpath = "github.com/grpc-ecosystem/grpc-gateway/v2/utilities", +) + +go_test( + name = "utilities_test", + size = "small", + srcs = ["trie_test.go"], + deps = [":utilities"], +) + +alias( + name = "go_default_library", + actual = ":utilities", + visibility = ["//visibility:public"], +) diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/utilities/doc.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/utilities/doc.go similarity index 100% rename from vendor/github.com/grpc-ecosystem/grpc-gateway/utilities/doc.go rename to vendor/github.com/grpc-ecosystem/grpc-gateway/v2/utilities/doc.go diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/utilities/pattern.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/utilities/pattern.go similarity index 100% rename from vendor/github.com/grpc-ecosystem/grpc-gateway/utilities/pattern.go rename to vendor/github.com/grpc-ecosystem/grpc-gateway/v2/utilities/pattern.go diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/utilities/readerfactory.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/utilities/readerfactory.go similarity index 100% rename from vendor/github.com/grpc-ecosystem/grpc-gateway/utilities/readerfactory.go rename to vendor/github.com/grpc-ecosystem/grpc-gateway/v2/utilities/readerfactory.go diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/utilities/trie.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/utilities/trie.go similarity index 98% rename from vendor/github.com/grpc-ecosystem/grpc-gateway/utilities/trie.go rename to vendor/github.com/grpc-ecosystem/grpc-gateway/v2/utilities/trie.go index c2b7b30dd9..af3b703d50 100644 --- a/vendor/github.com/grpc-ecosystem/grpc-gateway/utilities/trie.go +++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/utilities/trie.go @@ -145,10 +145,7 @@ func (l byLex) Less(i, j int) bool { return false } } - if k < len(sj) { - return true - } - return false + return k < len(sj) } // HasCommonPrefix determines if any sequence in the DoubleArray is a prefix of the given sequence. diff --git a/vendor/github.com/huandu/xstrings/.travis.yml b/vendor/github.com/huandu/xstrings/.travis.yml deleted file mode 100644 index d6460be411..0000000000 --- a/vendor/github.com/huandu/xstrings/.travis.yml +++ /dev/null @@ -1,7 +0,0 @@ -language: go -install: - - go get golang.org/x/tools/cmd/cover - - go get github.com/mattn/goveralls -script: - - go test -v -covermode=count -coverprofile=coverage.out - - 'if [ "$TRAVIS_PULL_REQUEST" = "false" ] && [ ! -z "$COVERALLS_TOKEN" ]; then $HOME/gopath/bin/goveralls -coverprofile=coverage.out -service=travis-ci -repotoken $COVERALLS_TOKEN; fi' diff --git a/vendor/github.com/huandu/xstrings/README.md b/vendor/github.com/huandu/xstrings/README.md index 292bf2f39e..750c3c7eb6 100644 --- a/vendor/github.com/huandu/xstrings/README.md +++ b/vendor/github.com/huandu/xstrings/README.md @@ -1,7 +1,7 @@ -# xstrings # +# xstrings -[![Build Status](https://travis-ci.org/huandu/xstrings.svg?branch=master)](https://travis-ci.org/huandu/xstrings) -[![GoDoc](https://godoc.org/github.com/huandu/xstrings?status.svg)](https://godoc.org/github.com/huandu/xstrings) +[![Build Status](https://github.com/huandu/xstrings/workflows/Go/badge.svg)](https://github.com/huandu/xstrings/actions) +[![Go Doc](https://godoc.org/github.com/huandu/xstrings?status.svg)](https://pkg.go.dev/github.com/huandu/xstrings) [![Go Report](https://goreportcard.com/badge/github.com/huandu/xstrings)](https://goreportcard.com/report/github.com/huandu/xstrings) [![Coverage Status](https://coveralls.io/repos/github/huandu/xstrings/badge.svg?branch=master)](https://coveralls.io/github/huandu/xstrings?branch=master) @@ -9,109 +9,109 @@ Go package [xstrings](https://godoc.org/github.com/huandu/xstrings) is a collect All functions are well tested and carefully tuned for performance. -## Propose a new function ## +## Propose a new function Please review [contributing guideline](CONTRIBUTING.md) and [create new issue](https://github.com/huandu/xstrings/issues) to state why it should be included. -## Install ## +## Install Use `go get` to install this library. go get github.com/huandu/xstrings -## API document ## +## API document See [GoDoc](https://godoc.org/github.com/huandu/xstrings) for full document. -## Function list ## +## Function list Go functions have a unique naming style. One, who has experience in other language but new in Go, may have difficulties to find out right string function to use. Here is a list of functions in [strings](http://golang.org/pkg/strings) and [xstrings](https://godoc.org/github.com/huandu/xstrings) with enough extra information about how to map these functions to their friends in other languages. Hope this list could be helpful for fresh gophers. -### Package `xstrings` functions ### - -*Keep this table sorted by Function in ascending order.* - -| Function | Friends | # | -| -------- | ------- | --- | -| [Center](https://godoc.org/github.com/huandu/xstrings#Center) | `str.center` in Python; `String#center` in Ruby | [#30](https://github.com/huandu/xstrings/issues/30) | -| [Count](https://godoc.org/github.com/huandu/xstrings#Count) | `String#count` in Ruby | [#16](https://github.com/huandu/xstrings/issues/16) | -| [Delete](https://godoc.org/github.com/huandu/xstrings#Delete) | `String#delete` in Ruby | [#17](https://github.com/huandu/xstrings/issues/17) | -| [ExpandTabs](https://godoc.org/github.com/huandu/xstrings#ExpandTabs) | `str.expandtabs` in Python | [#27](https://github.com/huandu/xstrings/issues/27) | -| [FirstRuneToLower](https://godoc.org/github.com/huandu/xstrings#FirstRuneToLower) | `lcfirst` in PHP or Perl | [#15](https://github.com/huandu/xstrings/issues/15) | -| [FirstRuneToUpper](https://godoc.org/github.com/huandu/xstrings#FirstRuneToUpper) | `String#capitalize` in Ruby; `ucfirst` in PHP or Perl | [#15](https://github.com/huandu/xstrings/issues/15) | -| [Insert](https://godoc.org/github.com/huandu/xstrings#Insert) | `String#insert` in Ruby | [#18](https://github.com/huandu/xstrings/issues/18) | -| [LastPartition](https://godoc.org/github.com/huandu/xstrings#LastPartition) | `str.rpartition` in Python; `String#rpartition` in Ruby | [#19](https://github.com/huandu/xstrings/issues/19) | -| [LeftJustify](https://godoc.org/github.com/huandu/xstrings#LeftJustify) | `str.ljust` in Python; `String#ljust` in Ruby | [#28](https://github.com/huandu/xstrings/issues/28) | -| [Len](https://godoc.org/github.com/huandu/xstrings#Len) | `mb_strlen` in PHP | [#23](https://github.com/huandu/xstrings/issues/23) | -| [Partition](https://godoc.org/github.com/huandu/xstrings#Partition) | `str.partition` in Python; `String#partition` in Ruby | [#10](https://github.com/huandu/xstrings/issues/10) | -| [Reverse](https://godoc.org/github.com/huandu/xstrings#Reverse) | `String#reverse` in Ruby; `strrev` in PHP; `reverse` in Perl | [#7](https://github.com/huandu/xstrings/issues/7) | -| [RightJustify](https://godoc.org/github.com/huandu/xstrings#RightJustify) | `str.rjust` in Python; `String#rjust` in Ruby | [#29](https://github.com/huandu/xstrings/issues/29) | -| [RuneWidth](https://godoc.org/github.com/huandu/xstrings#RuneWidth) | - | [#27](https://github.com/huandu/xstrings/issues/27) | -| [Scrub](https://godoc.org/github.com/huandu/xstrings#Scrub) | `String#scrub` in Ruby | [#20](https://github.com/huandu/xstrings/issues/20) | -| [Shuffle](https://godoc.org/github.com/huandu/xstrings#Shuffle) | `str_shuffle` in PHP | [#13](https://github.com/huandu/xstrings/issues/13) | -| [ShuffleSource](https://godoc.org/github.com/huandu/xstrings#ShuffleSource) | `str_shuffle` in PHP | [#13](https://github.com/huandu/xstrings/issues/13) | -| [Slice](https://godoc.org/github.com/huandu/xstrings#Slice) | `mb_substr` in PHP | [#9](https://github.com/huandu/xstrings/issues/9) | -| [Squeeze](https://godoc.org/github.com/huandu/xstrings#Squeeze) | `String#squeeze` in Ruby | [#11](https://github.com/huandu/xstrings/issues/11) | -| [Successor](https://godoc.org/github.com/huandu/xstrings#Successor) | `String#succ` or `String#next` in Ruby | [#22](https://github.com/huandu/xstrings/issues/22) | -| [SwapCase](https://godoc.org/github.com/huandu/xstrings#SwapCase) | `str.swapcase` in Python; `String#swapcase` in Ruby | [#12](https://github.com/huandu/xstrings/issues/12) | -| [ToCamelCase](https://godoc.org/github.com/huandu/xstrings#ToCamelCase) | `String#camelize` in RoR | [#1](https://github.com/huandu/xstrings/issues/1) | -| [ToKebab](https://godoc.org/github.com/huandu/xstrings#ToKebabCase) | - | [#41](https://github.com/huandu/xstrings/issues/41) | -| [ToSnakeCase](https://godoc.org/github.com/huandu/xstrings#ToSnakeCase) | `String#underscore` in RoR | [#1](https://github.com/huandu/xstrings/issues/1) | -| [Translate](https://godoc.org/github.com/huandu/xstrings#Translate) | `str.translate` in Python; `String#tr` in Ruby; `strtr` in PHP; `tr///` in Perl | [#21](https://github.com/huandu/xstrings/issues/21) | -| [Width](https://godoc.org/github.com/huandu/xstrings#Width) | `mb_strwidth` in PHP | [#26](https://github.com/huandu/xstrings/issues/26) | -| [WordCount](https://godoc.org/github.com/huandu/xstrings#WordCount) | `str_word_count` in PHP | [#14](https://github.com/huandu/xstrings/issues/14) | -| [WordSplit](https://godoc.org/github.com/huandu/xstrings#WordSplit) | - | [#14](https://github.com/huandu/xstrings/issues/14) | - -### Package `strings` functions ### - -*Keep this table sorted by Function in ascending order.* - -| Function | Friends | -| -------- | ------- | -| [Contains](http://golang.org/pkg/strings/#Contains) | `String#include?` in Ruby | -| [ContainsAny](http://golang.org/pkg/strings/#ContainsAny) | - | -| [ContainsRune](http://golang.org/pkg/strings/#ContainsRune) | - | -| [Count](http://golang.org/pkg/strings/#Count) | `str.count` in Python; `substr_count` in PHP | -| [EqualFold](http://golang.org/pkg/strings/#EqualFold) | `stricmp` in PHP; `String#casecmp` in Ruby | -| [Fields](http://golang.org/pkg/strings/#Fields) | `str.split` in Python; `split` in Perl; `String#split` in Ruby | -| [FieldsFunc](http://golang.org/pkg/strings/#FieldsFunc) | - | -| [HasPrefix](http://golang.org/pkg/strings/#HasPrefix) | `str.startswith` in Python; `String#start_with?` in Ruby | -| [HasSuffix](http://golang.org/pkg/strings/#HasSuffix) | `str.endswith` in Python; `String#end_with?` in Ruby | -| [Index](http://golang.org/pkg/strings/#Index) | `str.index` in Python; `String#index` in Ruby; `strpos` in PHP; `index` in Perl | -| [IndexAny](http://golang.org/pkg/strings/#IndexAny) | - | -| [IndexByte](http://golang.org/pkg/strings/#IndexByte) | - | -| [IndexFunc](http://golang.org/pkg/strings/#IndexFunc) | - | -| [IndexRune](http://golang.org/pkg/strings/#IndexRune) | - | -| [Join](http://golang.org/pkg/strings/#Join) | `str.join` in Python; `Array#join` in Ruby; `implode` in PHP; `join` in Perl | -| [LastIndex](http://golang.org/pkg/strings/#LastIndex) | `str.rindex` in Python; `String#rindex`; `strrpos` in PHP; `rindex` in Perl | -| [LastIndexAny](http://golang.org/pkg/strings/#LastIndexAny) | - | -| [LastIndexFunc](http://golang.org/pkg/strings/#LastIndexFunc) | - | -| [Map](http://golang.org/pkg/strings/#Map) | `String#each_codepoint` in Ruby | -| [Repeat](http://golang.org/pkg/strings/#Repeat) | operator `*` in Python and Ruby; `str_repeat` in PHP | -| [Replace](http://golang.org/pkg/strings/#Replace) | `str.replace` in Python; `String#sub` in Ruby; `str_replace` in PHP | -| [Split](http://golang.org/pkg/strings/#Split) | `str.split` in Python; `String#split` in Ruby; `explode` in PHP; `split` in Perl | -| [SplitAfter](http://golang.org/pkg/strings/#SplitAfter) | - | -| [SplitAfterN](http://golang.org/pkg/strings/#SplitAfterN) | - | -| [SplitN](http://golang.org/pkg/strings/#SplitN) | `str.split` in Python; `String#split` in Ruby; `explode` in PHP; `split` in Perl | -| [Title](http://golang.org/pkg/strings/#Title) | `str.title` in Python | -| [ToLower](http://golang.org/pkg/strings/#ToLower) | `str.lower` in Python; `String#downcase` in Ruby; `strtolower` in PHP; `lc` in Perl | -| [ToLowerSpecial](http://golang.org/pkg/strings/#ToLowerSpecial) | - | -| [ToTitle](http://golang.org/pkg/strings/#ToTitle) | - | -| [ToTitleSpecial](http://golang.org/pkg/strings/#ToTitleSpecial) | - | -| [ToUpper](http://golang.org/pkg/strings/#ToUpper) | `str.upper` in Python; `String#upcase` in Ruby; `strtoupper` in PHP; `uc` in Perl | -| [ToUpperSpecial](http://golang.org/pkg/strings/#ToUpperSpecial) | - | -| [Trim](http://golang.org/pkg/strings/#Trim) | `str.strip` in Python; `String#strip` in Ruby; `trim` in PHP | -| [TrimFunc](http://golang.org/pkg/strings/#TrimFunc) | - | -| [TrimLeft](http://golang.org/pkg/strings/#TrimLeft) | `str.lstrip` in Python; `String#lstrip` in Ruby; `ltrim` in PHP | -| [TrimLeftFunc](http://golang.org/pkg/strings/#TrimLeftFunc) | - | -| [TrimPrefix](http://golang.org/pkg/strings/#TrimPrefix) | - | -| [TrimRight](http://golang.org/pkg/strings/#TrimRight) | `str.rstrip` in Python; `String#rstrip` in Ruby; `rtrim` in PHP | -| [TrimRightFunc](http://golang.org/pkg/strings/#TrimRightFunc) | - | -| [TrimSpace](http://golang.org/pkg/strings/#TrimSpace) | `str.strip` in Python; `String#strip` in Ruby; `trim` in PHP | -| [TrimSuffix](http://golang.org/pkg/strings/#TrimSuffix) | `String#chomp` in Ruby; `chomp` in Perl | - -## License ## +### Package `xstrings` functions + +_Keep this table sorted by Function in ascending order._ + +| Function | Friends | # | +| --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | --------------------------------------------------- | +| [Center](https://godoc.org/github.com/huandu/xstrings#Center) | `str.center` in Python; `String#center` in Ruby | [#30](https://github.com/huandu/xstrings/issues/30) | +| [Count](https://godoc.org/github.com/huandu/xstrings#Count) | `String#count` in Ruby | [#16](https://github.com/huandu/xstrings/issues/16) | +| [Delete](https://godoc.org/github.com/huandu/xstrings#Delete) | `String#delete` in Ruby | [#17](https://github.com/huandu/xstrings/issues/17) | +| [ExpandTabs](https://godoc.org/github.com/huandu/xstrings#ExpandTabs) | `str.expandtabs` in Python | [#27](https://github.com/huandu/xstrings/issues/27) | +| [FirstRuneToLower](https://godoc.org/github.com/huandu/xstrings#FirstRuneToLower) | `lcfirst` in PHP or Perl | [#15](https://github.com/huandu/xstrings/issues/15) | +| [FirstRuneToUpper](https://godoc.org/github.com/huandu/xstrings#FirstRuneToUpper) | `String#capitalize` in Ruby; `ucfirst` in PHP or Perl | [#15](https://github.com/huandu/xstrings/issues/15) | +| [Insert](https://godoc.org/github.com/huandu/xstrings#Insert) | `String#insert` in Ruby | [#18](https://github.com/huandu/xstrings/issues/18) | +| [LastPartition](https://godoc.org/github.com/huandu/xstrings#LastPartition) | `str.rpartition` in Python; `String#rpartition` in Ruby | [#19](https://github.com/huandu/xstrings/issues/19) | +| [LeftJustify](https://godoc.org/github.com/huandu/xstrings#LeftJustify) | `str.ljust` in Python; `String#ljust` in Ruby | [#28](https://github.com/huandu/xstrings/issues/28) | +| [Len](https://godoc.org/github.com/huandu/xstrings#Len) | `mb_strlen` in PHP | [#23](https://github.com/huandu/xstrings/issues/23) | +| [Partition](https://godoc.org/github.com/huandu/xstrings#Partition) | `str.partition` in Python; `String#partition` in Ruby | [#10](https://github.com/huandu/xstrings/issues/10) | +| [Reverse](https://godoc.org/github.com/huandu/xstrings#Reverse) | `String#reverse` in Ruby; `strrev` in PHP; `reverse` in Perl | [#7](https://github.com/huandu/xstrings/issues/7) | +| [RightJustify](https://godoc.org/github.com/huandu/xstrings#RightJustify) | `str.rjust` in Python; `String#rjust` in Ruby | [#29](https://github.com/huandu/xstrings/issues/29) | +| [RuneWidth](https://godoc.org/github.com/huandu/xstrings#RuneWidth) | - | [#27](https://github.com/huandu/xstrings/issues/27) | +| [Scrub](https://godoc.org/github.com/huandu/xstrings#Scrub) | `String#scrub` in Ruby | [#20](https://github.com/huandu/xstrings/issues/20) | +| [Shuffle](https://godoc.org/github.com/huandu/xstrings#Shuffle) | `str_shuffle` in PHP | [#13](https://github.com/huandu/xstrings/issues/13) | +| [ShuffleSource](https://godoc.org/github.com/huandu/xstrings#ShuffleSource) | `str_shuffle` in PHP | [#13](https://github.com/huandu/xstrings/issues/13) | +| [Slice](https://godoc.org/github.com/huandu/xstrings#Slice) | `mb_substr` in PHP | [#9](https://github.com/huandu/xstrings/issues/9) | +| [Squeeze](https://godoc.org/github.com/huandu/xstrings#Squeeze) | `String#squeeze` in Ruby | [#11](https://github.com/huandu/xstrings/issues/11) | +| [Successor](https://godoc.org/github.com/huandu/xstrings#Successor) | `String#succ` or `String#next` in Ruby | [#22](https://github.com/huandu/xstrings/issues/22) | +| [SwapCase](https://godoc.org/github.com/huandu/xstrings#SwapCase) | `str.swapcase` in Python; `String#swapcase` in Ruby | [#12](https://github.com/huandu/xstrings/issues/12) | +| [ToCamelCase](https://godoc.org/github.com/huandu/xstrings#ToCamelCase) | `String#camelize` in RoR | [#1](https://github.com/huandu/xstrings/issues/1) | +| [ToKebab](https://godoc.org/github.com/huandu/xstrings#ToKebabCase) | - | [#41](https://github.com/huandu/xstrings/issues/41) | +| [ToSnakeCase](https://godoc.org/github.com/huandu/xstrings#ToSnakeCase) | `String#underscore` in RoR | [#1](https://github.com/huandu/xstrings/issues/1) | +| [Translate](https://godoc.org/github.com/huandu/xstrings#Translate) | `str.translate` in Python; `String#tr` in Ruby; `strtr` in PHP; `tr///` in Perl | [#21](https://github.com/huandu/xstrings/issues/21) | +| [Width](https://godoc.org/github.com/huandu/xstrings#Width) | `mb_strwidth` in PHP | [#26](https://github.com/huandu/xstrings/issues/26) | +| [WordCount](https://godoc.org/github.com/huandu/xstrings#WordCount) | `str_word_count` in PHP | [#14](https://github.com/huandu/xstrings/issues/14) | +| [WordSplit](https://godoc.org/github.com/huandu/xstrings#WordSplit) | - | [#14](https://github.com/huandu/xstrings/issues/14) | + +### Package `strings` functions + +_Keep this table sorted by Function in ascending order._ + +| Function | Friends | +| --------------------------------------------------------------- | ----------------------------------------------------------------------------------- | +| [Contains](http://golang.org/pkg/strings/#Contains) | `String#include?` in Ruby | +| [ContainsAny](http://golang.org/pkg/strings/#ContainsAny) | - | +| [ContainsRune](http://golang.org/pkg/strings/#ContainsRune) | - | +| [Count](http://golang.org/pkg/strings/#Count) | `str.count` in Python; `substr_count` in PHP | +| [EqualFold](http://golang.org/pkg/strings/#EqualFold) | `stricmp` in PHP; `String#casecmp` in Ruby | +| [Fields](http://golang.org/pkg/strings/#Fields) | `str.split` in Python; `split` in Perl; `String#split` in Ruby | +| [FieldsFunc](http://golang.org/pkg/strings/#FieldsFunc) | - | +| [HasPrefix](http://golang.org/pkg/strings/#HasPrefix) | `str.startswith` in Python; `String#start_with?` in Ruby | +| [HasSuffix](http://golang.org/pkg/strings/#HasSuffix) | `str.endswith` in Python; `String#end_with?` in Ruby | +| [Index](http://golang.org/pkg/strings/#Index) | `str.index` in Python; `String#index` in Ruby; `strpos` in PHP; `index` in Perl | +| [IndexAny](http://golang.org/pkg/strings/#IndexAny) | - | +| [IndexByte](http://golang.org/pkg/strings/#IndexByte) | - | +| [IndexFunc](http://golang.org/pkg/strings/#IndexFunc) | - | +| [IndexRune](http://golang.org/pkg/strings/#IndexRune) | - | +| [Join](http://golang.org/pkg/strings/#Join) | `str.join` in Python; `Array#join` in Ruby; `implode` in PHP; `join` in Perl | +| [LastIndex](http://golang.org/pkg/strings/#LastIndex) | `str.rindex` in Python; `String#rindex`; `strrpos` in PHP; `rindex` in Perl | +| [LastIndexAny](http://golang.org/pkg/strings/#LastIndexAny) | - | +| [LastIndexFunc](http://golang.org/pkg/strings/#LastIndexFunc) | - | +| [Map](http://golang.org/pkg/strings/#Map) | `String#each_codepoint` in Ruby | +| [Repeat](http://golang.org/pkg/strings/#Repeat) | operator `*` in Python and Ruby; `str_repeat` in PHP | +| [Replace](http://golang.org/pkg/strings/#Replace) | `str.replace` in Python; `String#sub` in Ruby; `str_replace` in PHP | +| [Split](http://golang.org/pkg/strings/#Split) | `str.split` in Python; `String#split` in Ruby; `explode` in PHP; `split` in Perl | +| [SplitAfter](http://golang.org/pkg/strings/#SplitAfter) | - | +| [SplitAfterN](http://golang.org/pkg/strings/#SplitAfterN) | - | +| [SplitN](http://golang.org/pkg/strings/#SplitN) | `str.split` in Python; `String#split` in Ruby; `explode` in PHP; `split` in Perl | +| [Title](http://golang.org/pkg/strings/#Title) | `str.title` in Python | +| [ToLower](http://golang.org/pkg/strings/#ToLower) | `str.lower` in Python; `String#downcase` in Ruby; `strtolower` in PHP; `lc` in Perl | +| [ToLowerSpecial](http://golang.org/pkg/strings/#ToLowerSpecial) | - | +| [ToTitle](http://golang.org/pkg/strings/#ToTitle) | - | +| [ToTitleSpecial](http://golang.org/pkg/strings/#ToTitleSpecial) | - | +| [ToUpper](http://golang.org/pkg/strings/#ToUpper) | `str.upper` in Python; `String#upcase` in Ruby; `strtoupper` in PHP; `uc` in Perl | +| [ToUpperSpecial](http://golang.org/pkg/strings/#ToUpperSpecial) | - | +| [Trim](http://golang.org/pkg/strings/#Trim) | `str.strip` in Python; `String#strip` in Ruby; `trim` in PHP | +| [TrimFunc](http://golang.org/pkg/strings/#TrimFunc) | - | +| [TrimLeft](http://golang.org/pkg/strings/#TrimLeft) | `str.lstrip` in Python; `String#lstrip` in Ruby; `ltrim` in PHP | +| [TrimLeftFunc](http://golang.org/pkg/strings/#TrimLeftFunc) | - | +| [TrimPrefix](http://golang.org/pkg/strings/#TrimPrefix) | - | +| [TrimRight](http://golang.org/pkg/strings/#TrimRight) | `str.rstrip` in Python; `String#rstrip` in Ruby; `rtrim` in PHP | +| [TrimRightFunc](http://golang.org/pkg/strings/#TrimRightFunc) | - | +| [TrimSpace](http://golang.org/pkg/strings/#TrimSpace) | `str.strip` in Python; `String#strip` in Ruby; `trim` in PHP | +| [TrimSuffix](http://golang.org/pkg/strings/#TrimSuffix) | `String#chomp` in Ruby; `chomp` in Perl | + +## License This library is licensed under MIT license. See LICENSE for details. diff --git a/vendor/github.com/huandu/xstrings/convert.go b/vendor/github.com/huandu/xstrings/convert.go index 3d5a34950b..151c3151d9 100644 --- a/vendor/github.com/huandu/xstrings/convert.go +++ b/vendor/github.com/huandu/xstrings/convert.go @@ -130,7 +130,7 @@ func camelCaseToLowerCase(str string, connector rune) string { wt, word, remaining = nextWord(remaining) } - if wt != invalidWord && wt != punctWord { + if wt != invalidWord && wt != punctWord && wt != connectorWord { buf.WriteRune(connector) } diff --git a/vendor/github.com/inconshreveable/mousetrap/LICENSE b/vendor/github.com/inconshreveable/mousetrap/LICENSE index 5f0d1fb6a7..5f920e9732 100644 --- a/vendor/github.com/inconshreveable/mousetrap/LICENSE +++ b/vendor/github.com/inconshreveable/mousetrap/LICENSE @@ -1,13 +1,201 @@ -Copyright 2014 Alan Shreve + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - http://www.apache.org/licenses/LICENSE-2.0 + 1. Definitions. -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2022 Alan Shreve (@inconshreveable) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/inconshreveable/mousetrap/trap_others.go b/vendor/github.com/inconshreveable/mousetrap/trap_others.go index 9d2d8a4bab..06a91f0868 100644 --- a/vendor/github.com/inconshreveable/mousetrap/trap_others.go +++ b/vendor/github.com/inconshreveable/mousetrap/trap_others.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows package mousetrap diff --git a/vendor/github.com/inconshreveable/mousetrap/trap_windows.go b/vendor/github.com/inconshreveable/mousetrap/trap_windows.go index 336142a5e3..0c56880216 100644 --- a/vendor/github.com/inconshreveable/mousetrap/trap_windows.go +++ b/vendor/github.com/inconshreveable/mousetrap/trap_windows.go @@ -1,81 +1,32 @@ -// +build windows -// +build !go1.4 - package mousetrap import ( - "fmt" - "os" "syscall" "unsafe" ) -const ( - // defined by the Win32 API - th32cs_snapprocess uintptr = 0x2 -) - -var ( - kernel = syscall.MustLoadDLL("kernel32.dll") - CreateToolhelp32Snapshot = kernel.MustFindProc("CreateToolhelp32Snapshot") - Process32First = kernel.MustFindProc("Process32FirstW") - Process32Next = kernel.MustFindProc("Process32NextW") -) - -// ProcessEntry32 structure defined by the Win32 API -type processEntry32 struct { - dwSize uint32 - cntUsage uint32 - th32ProcessID uint32 - th32DefaultHeapID int - th32ModuleID uint32 - cntThreads uint32 - th32ParentProcessID uint32 - pcPriClassBase int32 - dwFlags uint32 - szExeFile [syscall.MAX_PATH]uint16 -} - -func getProcessEntry(pid int) (pe *processEntry32, err error) { - snapshot, _, e1 := CreateToolhelp32Snapshot.Call(th32cs_snapprocess, uintptr(0)) - if snapshot == uintptr(syscall.InvalidHandle) { - err = fmt.Errorf("CreateToolhelp32Snapshot: %v", e1) - return +func getProcessEntry(pid int) (*syscall.ProcessEntry32, error) { + snapshot, err := syscall.CreateToolhelp32Snapshot(syscall.TH32CS_SNAPPROCESS, 0) + if err != nil { + return nil, err } - defer syscall.CloseHandle(syscall.Handle(snapshot)) - - var processEntry processEntry32 - processEntry.dwSize = uint32(unsafe.Sizeof(processEntry)) - ok, _, e1 := Process32First.Call(snapshot, uintptr(unsafe.Pointer(&processEntry))) - if ok == 0 { - err = fmt.Errorf("Process32First: %v", e1) - return + defer syscall.CloseHandle(snapshot) + var procEntry syscall.ProcessEntry32 + procEntry.Size = uint32(unsafe.Sizeof(procEntry)) + if err = syscall.Process32First(snapshot, &procEntry); err != nil { + return nil, err } - for { - if processEntry.th32ProcessID == uint32(pid) { - pe = &processEntry - return + if procEntry.ProcessID == uint32(pid) { + return &procEntry, nil } - - ok, _, e1 = Process32Next.Call(snapshot, uintptr(unsafe.Pointer(&processEntry))) - if ok == 0 { - err = fmt.Errorf("Process32Next: %v", e1) - return + err = syscall.Process32Next(snapshot, &procEntry) + if err != nil { + return nil, err } } } -func getppid() (pid int, err error) { - pe, err := getProcessEntry(os.Getpid()) - if err != nil { - return - } - - pid = int(pe.th32ParentProcessID) - return -} - // StartedByExplorer returns true if the program was invoked by the user double-clicking // on the executable from explorer.exe // @@ -83,16 +34,9 @@ func getppid() (pid int, err error) { // It does not guarantee that the program was run from a terminal. It only can tell you // whether it was launched from explorer.exe func StartedByExplorer() bool { - ppid, err := getppid() + pe, err := getProcessEntry(syscall.Getppid()) if err != nil { return false } - - pe, err := getProcessEntry(ppid) - if err != nil { - return false - } - - name := syscall.UTF16ToString(pe.szExeFile[:]) - return name == "explorer.exe" + return "explorer.exe" == syscall.UTF16ToString(pe.ExeFile[:]) } diff --git a/vendor/github.com/inconshreveable/mousetrap/trap_windows_1.4.go b/vendor/github.com/inconshreveable/mousetrap/trap_windows_1.4.go deleted file mode 100644 index 9a28e57c3c..0000000000 --- a/vendor/github.com/inconshreveable/mousetrap/trap_windows_1.4.go +++ /dev/null @@ -1,46 +0,0 @@ -// +build windows -// +build go1.4 - -package mousetrap - -import ( - "os" - "syscall" - "unsafe" -) - -func getProcessEntry(pid int) (*syscall.ProcessEntry32, error) { - snapshot, err := syscall.CreateToolhelp32Snapshot(syscall.TH32CS_SNAPPROCESS, 0) - if err != nil { - return nil, err - } - defer syscall.CloseHandle(snapshot) - var procEntry syscall.ProcessEntry32 - procEntry.Size = uint32(unsafe.Sizeof(procEntry)) - if err = syscall.Process32First(snapshot, &procEntry); err != nil { - return nil, err - } - for { - if procEntry.ProcessID == uint32(pid) { - return &procEntry, nil - } - err = syscall.Process32Next(snapshot, &procEntry) - if err != nil { - return nil, err - } - } -} - -// StartedByExplorer returns true if the program was invoked by the user double-clicking -// on the executable from explorer.exe -// -// It is conservative and returns false if any of the internal calls fail. -// It does not guarantee that the program was run from a terminal. It only can tell you -// whether it was launched from explorer.exe -func StartedByExplorer() bool { - pe, err := getProcessEntry(os.Getppid()) - if err != nil { - return false - } - return "explorer.exe" == syscall.UTF16ToString(pe.ExeFile[:]) -} diff --git a/vendor/github.com/jmoiron/sqlx/sqlx.go b/vendor/github.com/jmoiron/sqlx/sqlx.go index 112ef70e9c..f7b2876834 100644 --- a/vendor/github.com/jmoiron/sqlx/sqlx.go +++ b/vendor/github.com/jmoiron/sqlx/sqlx.go @@ -878,9 +878,10 @@ func structOnlyError(t reflect.Type) error { } // scanAll scans all rows into a destination, which must be a slice of any -// type. If the destination slice type is a Struct, then StructScan will be -// used on each row. If the destination is some other kind of base type, then -// each row must only have one column which can scan into that type. This +// type. It resets the slice length to zero before appending each element to +// the slice. If the destination slice type is a Struct, then StructScan will +// be used on each row. If the destination is some other kind of base type, +// then each row must only have one column which can scan into that type. This // allows you to do something like: // // rows, _ := db.Query("select id from people;") @@ -910,6 +911,7 @@ func scanAll(rows rowsi, dest interface{}, structOnly bool) error { if err != nil { return err } + direct.SetLen(0) isPtr := slice.Elem().Kind() == reflect.Ptr base := reflectx.Deref(slice.Elem()) diff --git a/vendor/github.com/lib/pq/conn.go b/vendor/github.com/lib/pq/conn.go index e050d53586..e70b386ff0 100644 --- a/vendor/github.com/lib/pq/conn.go +++ b/vendor/github.com/lib/pq/conn.go @@ -31,8 +31,10 @@ var ( ErrNotSupported = errors.New("pq: Unsupported command") ErrInFailedTransaction = errors.New("pq: Could not complete operation in a failed transaction") ErrSSLNotSupported = errors.New("pq: SSL is not enabled on the server") - ErrSSLKeyHasWorldPermissions = errors.New("pq: Private key file has group or world access. Permissions should be u=rw (0600) or less") - ErrCouldNotDetectUsername = errors.New("pq: Could not detect default username. Please provide one explicitly") + ErrSSLKeyUnknownOwnership = errors.New("pq: Could not get owner information for private key, may not be properly protected") + ErrSSLKeyHasWorldPermissions = errors.New("pq: Private key has world access. Permissions should be u=rw,g=r (0640) if owned by root, or u=rw (0600), or less") + + ErrCouldNotDetectUsername = errors.New("pq: Could not detect default username. Please provide one explicitly") errUnexpectedReady = errors.New("unexpected ReadyForQuery") errNoRowsAffected = errors.New("no RowsAffected available after the empty statement") @@ -322,7 +324,7 @@ func DialOpen(d Dialer, dsn string) (_ driver.Conn, err error) { if err != nil { return nil, err } - c.dialer = d + c.Dialer(d) return c.open(context.Background()) } @@ -1125,7 +1127,7 @@ func isDriverSetting(key string) bool { return true case "password": return true - case "sslmode", "sslcert", "sslkey", "sslrootcert", "sslinline": + case "sslmode", "sslcert", "sslkey", "sslrootcert", "sslinline", "sslsni": return true case "fallback_application_name": return true @@ -2018,6 +2020,8 @@ func parseEnviron(env []string) (out map[string]string) { accrue("sslkey") case "PGSSLROOTCERT": accrue("sslrootcert") + case "PGSSLSNI": + accrue("sslsni") case "PGREQUIRESSL", "PGSSLCRL": unsupported() case "PGREQUIREPEER": diff --git a/vendor/github.com/lib/pq/connector.go b/vendor/github.com/lib/pq/connector.go index d7d4726156..1145e12257 100644 --- a/vendor/github.com/lib/pq/connector.go +++ b/vendor/github.com/lib/pq/connector.go @@ -27,6 +27,11 @@ func (c *Connector) Connect(ctx context.Context) (driver.Conn, error) { return c.open(ctx) } +// Dialer allows change the dialer used to open connections. +func (c *Connector) Dialer(dialer Dialer) { + c.dialer = dialer +} + // Driver returns the underlying driver of this Connector. func (c *Connector) Driver() driver.Driver { return &Driver{} diff --git a/vendor/github.com/lib/pq/copy.go b/vendor/github.com/lib/pq/copy.go index c072bc3bc4..2f5c1ec8a6 100644 --- a/vendor/github.com/lib/pq/copy.go +++ b/vendor/github.com/lib/pq/copy.go @@ -1,6 +1,7 @@ package pq import ( + "context" "database/sql/driver" "encoding/binary" "errors" @@ -273,6 +274,43 @@ func (ci *copyin) Exec(v []driver.Value) (r driver.Result, err error) { return driver.RowsAffected(0), nil } +// CopyData inserts a raw string into the COPY stream. The insert is +// asynchronous and CopyData can return errors from previous CopyData calls to +// the same COPY stmt. +// +// You need to call Exec(nil) to sync the COPY stream and to get any +// errors from pending data, since Stmt.Close() doesn't return errors +// to the user. +func (ci *copyin) CopyData(ctx context.Context, line string) (r driver.Result, err error) { + if ci.closed { + return nil, errCopyInClosed + } + + if finish := ci.cn.watchCancel(ctx); finish != nil { + defer finish() + } + + if err := ci.getBad(); err != nil { + return nil, err + } + defer ci.cn.errRecover(&err) + + if err := ci.err(); err != nil { + return nil, err + } + + ci.buffer = append(ci.buffer, []byte(line)...) + ci.buffer = append(ci.buffer, '\n') + + if len(ci.buffer) > ciBufferFlushSize { + ci.flush(ci.buffer) + // reset buffer, keep bytes for message identifier and length + ci.buffer = ci.buffer[:5] + } + + return driver.RowsAffected(0), nil +} + func (ci *copyin) Close() (err error) { if ci.closed { // Don't do anything, we're already closed return nil diff --git a/vendor/github.com/lib/pq/encode.go b/vendor/github.com/lib/pq/encode.go index 210b1ec347..bffe6096af 100644 --- a/vendor/github.com/lib/pq/encode.go +++ b/vendor/github.com/lib/pq/encode.go @@ -422,7 +422,7 @@ func ParseTimestamp(currentLocation *time.Location, str string) (time.Time, erro if remainderIdx < len(str) && str[remainderIdx] == '.' { fracStart := remainderIdx + 1 - fracOff := strings.IndexAny(str[fracStart:], "-+ ") + fracOff := strings.IndexAny(str[fracStart:], "-+Z ") if fracOff < 0 { fracOff = len(str) - fracStart } @@ -432,7 +432,7 @@ func ParseTimestamp(currentLocation *time.Location, str string) (time.Time, erro remainderIdx += fracOff + 1 } if tzStart := remainderIdx; tzStart < len(str) && (str[tzStart] == '-' || str[tzStart] == '+') { - // time zone separator is always '-' or '+' (UTC is +00) + // time zone separator is always '-' or '+' or 'Z' (UTC is +00) var tzSign int switch c := str[tzStart]; c { case '-': @@ -454,7 +454,11 @@ func ParseTimestamp(currentLocation *time.Location, str string) (time.Time, erro remainderIdx += 3 } tzOff = tzSign * ((tzHours * 60 * 60) + (tzMin * 60) + tzSec) + } else if tzStart < len(str) && str[tzStart] == 'Z' { + // time zone Z separator indicates UTC is +00 + remainderIdx += 1 } + var isoYear int if isBC { diff --git a/vendor/github.com/lib/pq/error.go b/vendor/github.com/lib/pq/error.go index 5cfe9c6e9f..f67c5a5fa6 100644 --- a/vendor/github.com/lib/pq/error.go +++ b/vendor/github.com/lib/pq/error.go @@ -402,6 +402,11 @@ func (err *Error) Fatal() bool { return err.Severity == Efatal } +// SQLState returns the SQLState of the error. +func (err *Error) SQLState() string { + return string(err.Code) +} + // Get implements the legacy PGError interface. New code should use the fields // of the Error struct directly. func (err *Error) Get(k byte) (v string) { @@ -444,7 +449,7 @@ func (err *Error) Get(k byte) (v string) { return "" } -func (err Error) Error() string { +func (err *Error) Error() string { return "pq: " + err.Message } diff --git a/vendor/github.com/lib/pq/ssl.go b/vendor/github.com/lib/pq/ssl.go index e5eb928954..36b61ba45b 100644 --- a/vendor/github.com/lib/pq/ssl.go +++ b/vendor/github.com/lib/pq/ssl.go @@ -8,6 +8,7 @@ import ( "os" "os/user" "path/filepath" + "strings" ) // ssl generates a function to upgrade a net.Conn based on the "sslmode" and @@ -50,6 +51,16 @@ func ssl(o values) (func(net.Conn) (net.Conn, error), error) { return nil, fmterrorf(`unsupported sslmode %q; only "require" (default), "verify-full", "verify-ca", and "disable" supported`, mode) } + // Set Server Name Indication (SNI), if enabled by connection parameters. + // By default SNI is on, any value which is not starting with "1" disables + // SNI -- that is the same check vanilla libpq uses. + if sslsni := o["sslsni"]; sslsni == "" || strings.HasPrefix(sslsni, "1") { + // RFC 6066 asks to not set SNI if the host is a literal IP address (IPv4 + // or IPv6). This check is coded already crypto.tls.hostnameInSNI, so + // just always set ServerName here and let crypto/tls do the filtering. + tlsConf.ServerName = o["host"] + } + err := sslClientCertificates(&tlsConf, o) if err != nil { return nil, err diff --git a/vendor/github.com/lib/pq/ssl_permissions.go b/vendor/github.com/lib/pq/ssl_permissions.go index 014af6a169..d587f102ed 100644 --- a/vendor/github.com/lib/pq/ssl_permissions.go +++ b/vendor/github.com/lib/pq/ssl_permissions.go @@ -3,7 +3,28 @@ package pq -import "os" +import ( + "errors" + "os" + "syscall" +) + +const ( + rootUserID = uint32(0) + + // The maximum permissions that a private key file owned by a regular user + // is allowed to have. This translates to u=rw. + maxUserOwnedKeyPermissions os.FileMode = 0600 + + // The maximum permissions that a private key file owned by root is allowed + // to have. This translates to u=rw,g=r. + maxRootOwnedKeyPermissions os.FileMode = 0640 +) + +var ( + errSSLKeyHasUnacceptableUserPermissions = errors.New("permissions for files not owned by root should be u=rw (0600) or less") + errSSLKeyHasUnacceptableRootPermissions = errors.New("permissions for root owned files should be u=rw,g=r (0640) or less") +) // sslKeyPermissions checks the permissions on user-supplied ssl key files. // The key file should have very little access. @@ -14,8 +35,59 @@ func sslKeyPermissions(sslkey string) error { if err != nil { return err } - if info.Mode().Perm()&0077 != 0 { - return ErrSSLKeyHasWorldPermissions + + err = hasCorrectPermissions(info) + + // return ErrSSLKeyHasWorldPermissions for backwards compatability with + // existing code. + if err == errSSLKeyHasUnacceptableUserPermissions || err == errSSLKeyHasUnacceptableRootPermissions { + err = ErrSSLKeyHasWorldPermissions } - return nil + return err +} + +// hasCorrectPermissions checks the file info (and the unix-specific stat_t +// output) to verify that the permissions on the file are correct. +// +// If the file is owned by the same user the process is running as, +// the file should only have 0600 (u=rw). If the file is owned by root, +// and the group matches the group that the process is running in, the +// permissions cannot be more than 0640 (u=rw,g=r). The file should +// never have world permissions. +// +// Returns an error when the permission check fails. +func hasCorrectPermissions(info os.FileInfo) error { + // if file's permission matches 0600, allow access. + userPermissionMask := (os.FileMode(0777) ^ maxUserOwnedKeyPermissions) + + // regardless of if we're running as root or not, 0600 is acceptable, + // so we return if we match the regular user permission mask. + if info.Mode().Perm()&userPermissionMask == 0 { + return nil + } + + // We need to pull the Unix file information to get the file's owner. + // If we can't access it, there's some sort of operating system level error + // and we should fail rather than attempting to use faulty information. + sysInfo := info.Sys() + if sysInfo == nil { + return ErrSSLKeyUnknownOwnership + } + + unixStat, ok := sysInfo.(*syscall.Stat_t) + if !ok { + return ErrSSLKeyUnknownOwnership + } + + // if the file is owned by root, we allow 0640 (u=rw,g=r) to match what + // Postgres does. + if unixStat.Uid == rootUserID { + rootPermissionMask := (os.FileMode(0777) ^ maxRootOwnedKeyPermissions) + if info.Mode().Perm()&rootPermissionMask != 0 { + return errSSLKeyHasUnacceptableRootPermissions + } + return nil + } + + return errSSLKeyHasUnacceptableUserPermissions } diff --git a/vendor/github.com/mailru/easyjson/jlexer/lexer.go b/vendor/github.com/mailru/easyjson/jlexer/lexer.go index a42e9d65ad..b5f5e26132 100644 --- a/vendor/github.com/mailru/easyjson/jlexer/lexer.go +++ b/vendor/github.com/mailru/easyjson/jlexer/lexer.go @@ -401,6 +401,7 @@ func (r *Lexer) scanToken() { // consume resets the current token to allow scanning the next one. func (r *Lexer) consume() { r.token.kind = tokenUndef + r.token.byteValueCloned = false r.token.delimValue = 0 } @@ -528,6 +529,7 @@ func (r *Lexer) Skip() { func (r *Lexer) SkipRecursive() { r.scanToken() var start, end byte + startPos := r.start switch r.token.delimValue { case '{': @@ -553,6 +555,14 @@ func (r *Lexer) SkipRecursive() { level-- if level == 0 { r.pos += i + 1 + if !json.Valid(r.Data[startPos:r.pos]) { + r.pos = len(r.Data) + r.fatalError = &LexerError{ + Reason: "skipped array/object json value is invalid", + Offset: r.pos, + Data: string(r.Data[r.pos:]), + } + } return } case c == '\\' && inQuotes: @@ -702,6 +712,10 @@ func (r *Lexer) Bytes() []byte { r.errInvalidToken("string") return nil } + if err := r.unescapeStringToken(); err != nil { + r.errInvalidToken("string") + return nil + } ret := make([]byte, base64.StdEncoding.DecodedLen(len(r.token.byteValue))) n, err := base64.StdEncoding.Decode(ret, r.token.byteValue) if err != nil { diff --git a/vendor/github.com/mattn/go-sqlite3/README.md b/vendor/github.com/mattn/go-sqlite3/README.md index e455133fc9..931b02e3e2 100644 --- a/vendor/github.com/mattn/go-sqlite3/README.md +++ b/vendor/github.com/mattn/go-sqlite3/README.md @@ -1,7 +1,7 @@ go-sqlite3 ========== -[![GoDoc Reference](https://godoc.org/github.com/mattn/go-sqlite3?status.svg)](http://godoc.org/github.com/mattn/go-sqlite3) +[![Go Reference](https://pkg.go.dev/badge/github.com/mattn/go-sqlite3.svg)](https://pkg.go.dev/github.com/mattn/go-sqlite3) [![GitHub Actions](https://github.com/mattn/go-sqlite3/workflows/Go/badge.svg)](https://github.com/mattn/go-sqlite3/actions?query=workflow%3AGo) [![Financial Contributors on Open Collective](https://opencollective.com/mattn-go-sqlite3/all/badge.svg?label=financial+contributors)](https://opencollective.com/mattn-go-sqlite3) [![codecov](https://codecov.io/gh/mattn/go-sqlite3/branch/master/graph/badge.svg)](https://codecov.io/gh/mattn/go-sqlite3) @@ -172,15 +172,18 @@ go build --tags "icu json1 fts5 secure_delete" | International Components for Unicode | sqlite_icu | This option causes the International Components for Unicode or "ICU" extension to SQLite to be added to the build | | Introspect PRAGMAS | sqlite_introspect | This option adds some extra PRAGMA statements.
    • PRAGMA function_list
    • PRAGMA module_list
    • PRAGMA pragma_list
    | | JSON SQL Functions | sqlite_json | When this option is defined in the amalgamation, the JSON SQL functions are added to the build automatically | +| Math Functions | sqlite_math_functions | This compile-time option enables built-in scalar math functions. For more information see [Built-In Mathematical SQL Functions](https://www.sqlite.org/lang_mathfunc.html) | +| OS Trace | sqlite_os_trace | This option enables OSTRACE() debug logging. This can be verbose and should not be used in production. | | Pre Update Hook | sqlite_preupdate_hook | Registers a callback function that is invoked prior to each INSERT, UPDATE, and DELETE operation on a database table. | | Secure Delete | sqlite_secure_delete | This compile-time option changes the default setting of the secure_delete pragma.

    When this option is not used, secure_delete defaults to off. When this option is present, secure_delete defaults to on.

    The secure_delete setting causes deleted content to be overwritten with zeros. There is a small performance penalty since additional I/O must occur.

    On the other hand, secure_delete can prevent fragments of sensitive information from lingering in unused parts of the database file after it has been deleted. See the documentation on the secure_delete pragma for additional information | | Secure Delete (FAST) | sqlite_secure_delete_fast | For more information see [PRAGMA secure_delete](https://www.sqlite.org/pragma.html#pragma_secure_delete) | | Tracing / Debug | sqlite_trace | Activate trace functions | | User Authentication | sqlite_userauth | SQLite User Authentication see [User Authentication](#user-authentication) for more information. | +| Virtual Tables | sqlite_vtable | SQLite Virtual Tables see [SQLite Official VTABLE Documentation](https://www.sqlite.org/vtab.html) for more information, and a [full example here](https://github.com/mattn/go-sqlite3/tree/master/_example/vtable) | # Compilation -This package requires the `CGO_ENABLED=1` ennvironment variable if not set by default, and the presence of the `gcc` compiler. +This package requires the `CGO_ENABLED=1` environment variable if not set by default, and the presence of the `gcc` compiler. If you need to add additional CFLAGS or LDFLAGS to the build command, and do not want to modify this package, then this can be achieved by using the `CGO_CFLAGS` and `CGO_LDFLAGS` environment variables. @@ -216,14 +219,13 @@ This library can be cross-compiled. In some cases you are required to the `CC` environment variable with the cross compiler. ## Cross Compiling from MAC OSX -The simplest way to cross compile from OSX is to use [xgo](https://github.com/karalabe/xgo). +The simplest way to cross compile from OSX is to use [musl-cross](https://github.com/FiloSottile/homebrew-musl-cross). Steps: -- Install [xgo](https://github.com/karalabe/xgo) (`go get github.com/karalabe/xgo`). -- Ensure that your project is within your `GOPATH`. -- Run `xgo local/path/to/project`. +- Install [musl-cross](https://github.com/FiloSottile/homebrew-musl-cross) (`brew install FiloSottile/musl-cross/musl-cross`). +- Run `CC=x86_64-linux-musl-gcc CXX=x86_64-linux-musl-g++ GOARCH=amd64 GOOS=linux CGO_ENABLED=1 go build -ldflags "-linkmode external -extldflags -static"`. -Please refer to the project's [README](https://github.com/karalabe/xgo/blob/master/README.md) for further information. +Please refer to the project's [README](https://github.com/FiloSottile/homebrew-musl-cross#readme) for further information. # Google Cloud Platform diff --git a/vendor/github.com/mattn/go-sqlite3/callback.go b/vendor/github.com/mattn/go-sqlite3/callback.go index b020fe37c0..d305691004 100644 --- a/vendor/github.com/mattn/go-sqlite3/callback.go +++ b/vendor/github.com/mattn/go-sqlite3/callback.go @@ -353,6 +353,20 @@ func callbackRetNil(ctx *C.sqlite3_context, v reflect.Value) error { return nil } +func callbackRetGeneric(ctx *C.sqlite3_context, v reflect.Value) error { + if v.IsNil() { + C.sqlite3_result_null(ctx) + return nil + } + + cb, err := callbackRet(v.Elem().Type()) + if err != nil { + return err + } + + return cb(ctx, v.Elem()) +} + func callbackRet(typ reflect.Type) (callbackRetConverter, error) { switch typ.Kind() { case reflect.Interface: @@ -360,6 +374,11 @@ func callbackRet(typ reflect.Type) (callbackRetConverter, error) { if typ.Implements(errorInterface) { return callbackRetNil, nil } + + if typ.NumMethod() == 0 { + return callbackRetGeneric, nil + } + fallthrough case reflect.Slice: if typ.Elem().Kind() != reflect.Uint8 { diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3-binding.c b/vendor/github.com/mattn/go-sqlite3/sqlite3-binding.c index bb9dc50ec7..dd05f5751f 100644 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3-binding.c +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3-binding.c @@ -1,7 +1,7 @@ #ifndef USE_LIBSQLITE3 /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.37.0. By combining all the individual C code files into this +** version 3.39.4. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a single translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements @@ -453,9 +453,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.37.0" -#define SQLITE_VERSION_NUMBER 3037000 -#define SQLITE_SOURCE_ID "2021-11-27 14:13:22 bd41822c7424d393a30e92ff6cb254d25c26769889c1499a18a0b9339f5d6c8a" +#define SQLITE_VERSION "3.39.4" +#define SQLITE_VERSION_NUMBER 3039004 +#define SQLITE_SOURCE_ID "2022-09-29 15:55:41 a29f9949895322123f7c38fbe94c649a9d6e6c9cd0c3b41c96d694552f26b309" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -873,7 +873,7 @@ SQLITE_API int sqlite3_exec( #define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8)) #define SQLITE_AUTH_USER (SQLITE_AUTH | (1<<8)) #define SQLITE_OK_LOAD_PERMANENTLY (SQLITE_OK | (1<<8)) -#define SQLITE_OK_SYMLINK (SQLITE_OK | (2<<8)) +#define SQLITE_OK_SYMLINK (SQLITE_OK | (2<<8)) /* internal use only */ /* ** CAPI3REF: Flags For File Open Operations @@ -4131,13 +4131,14 @@ SQLITE_API void sqlite3_free_filename(char*); ** sqlite3_extended_errcode() might change with each API call. ** Except, there are some interfaces that are guaranteed to never ** change the value of the error code. The error-code preserving -** interfaces are: +** interfaces include the following: ** **
      **
    • sqlite3_errcode() **
    • sqlite3_extended_errcode() **
    • sqlite3_errmsg() **
    • sqlite3_errmsg16() +**
    • sqlite3_error_offset() **
    ** ** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language @@ -4152,6 +4153,13 @@ SQLITE_API void sqlite3_free_filename(char*); ** ^(Memory to hold the error message string is managed internally ** and must not be freed by the application)^. ** +** ^If the most recent error references a specific token in the input +** SQL, the sqlite3_error_offset() interface returns the byte offset +** of the start of that token. ^The byte offset returned by +** sqlite3_error_offset() assumes that the input SQL is UTF8. +** ^If the most recent error does not reference a specific token in the input +** SQL, then the sqlite3_error_offset() function returns -1. +** ** When the serialized [threading mode] is in use, it might be the ** case that a second error occurs on a separate thread in between ** the time of the first error and the call to these interfaces. @@ -4171,6 +4179,7 @@ SQLITE_API int sqlite3_extended_errcode(sqlite3 *db); SQLITE_API const char *sqlite3_errmsg(sqlite3*); SQLITE_API const void *sqlite3_errmsg16(sqlite3*); SQLITE_API const char *sqlite3_errstr(int); +SQLITE_API int sqlite3_error_offset(sqlite3 *db); /* ** CAPI3REF: Prepared Statement Object @@ -4582,6 +4591,10 @@ SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt); ** be false. ^Similarly, a CREATE TABLE IF NOT EXISTS statement is a ** read-only no-op if the table already exists, but ** sqlite3_stmt_readonly() still returns false for such a statement. +** +** ^If prepared statement X is an [EXPLAIN] or [EXPLAIN QUERY PLAN] +** statement, then sqlite3_stmt_readonly(X) returns the same value as +** if the EXPLAIN or EXPLAIN QUERY PLAN prefix were omitted. */ SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); @@ -4650,6 +4663,8 @@ SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt*); ** ** ^The sqlite3_value objects that are passed as parameters into the ** implementation of [application-defined SQL functions] are protected. +** ^The sqlite3_value objects returned by [sqlite3_vtab_rhs_value()] +** are protected. ** ^The sqlite3_value object returned by ** [sqlite3_column_value()] is unprotected. ** Unprotected sqlite3_value objects may only be used as arguments @@ -5271,6 +5286,10 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); ** even empty strings, are always zero-terminated. ^The return ** value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer. ** +** ^Strings returned by sqlite3_column_text16() always have the endianness +** which is native to the platform, regardless of the text encoding set +** for the database. +** ** Warning: ^The object returned by [sqlite3_column_value()] is an ** [unprotected sqlite3_value] object. In a multithreaded environment, ** an unprotected sqlite3_value object may only be used safely with @@ -5284,7 +5303,7 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); ** [application-defined SQL functions] or [virtual tables], not within ** top-level application code. ** -** The these routines may attempt to convert the datatype of the result. +** These routines may attempt to convert the datatype of the result. ** ^For example, if the internal representation is FLOAT and a text result ** is requested, [sqlite3_snprintf()] is used internally to perform the ** conversion automatically. ^(The following table details the conversions @@ -5309,7 +5328,7 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); ** TEXT BLOB No change ** BLOB INTEGER [CAST] to INTEGER ** BLOB FLOAT [CAST] to REAL -** BLOB TEXT Add a zero terminator if needed +** BLOB TEXT [CAST] to TEXT, ensure zero terminator ** ** )^ ** @@ -5881,7 +5900,8 @@ SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value*); ** object D and returns a pointer to that copy. ^The [sqlite3_value] returned ** is a [protected sqlite3_value] object even if the input is not. ** ^The sqlite3_value_dup(V) interface returns NULL if V is NULL or if a -** memory allocation fails. +** memory allocation fails. ^If V is a [pointer value], then the result +** of sqlite3_value_dup(V) is a NULL value. ** ** ^The sqlite3_value_free(V) interface frees an [sqlite3_value] object ** previously obtained from [sqlite3_value_dup()]. ^If V is a NULL pointer @@ -6563,6 +6583,28 @@ SQLITE_API int sqlite3_get_autocommit(sqlite3*); */ SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*); +/* +** CAPI3REF: Return The Schema Name For A Database Connection +** METHOD: sqlite3 +** +** ^The sqlite3_db_name(D,N) interface returns a pointer to the schema name +** for the N-th database on database connection D, or a NULL pointer of N is +** out of range. An N value of 0 means the main database file. An N of 1 is +** the "temp" schema. Larger values of N correspond to various ATTACH-ed +** databases. +** +** Space to hold the string that is returned by sqlite3_db_name() is managed +** by SQLite itself. The string might be deallocated by any operation that +** changes the schema, including [ATTACH] or [DETACH] or calls to +** [sqlite3_serialize()] or [sqlite3_deserialize()], even operations that +** occur on a different thread. Applications that need to +** remember the string long-term should make their own copy. Applications that +** are accessing the same database connection simultaneously on multiple +** threads should mutex-protect calls to this API and should make their own +** private copy of the result prior to releasing the mutex. +*/ +SQLITE_API const char *sqlite3_db_name(sqlite3 *db, int N); + /* ** CAPI3REF: Return The Filename For A Database Connection ** METHOD: sqlite3 @@ -7429,24 +7471,56 @@ struct sqlite3_index_info { ** ** These macros define the allowed values for the ** [sqlite3_index_info].aConstraint[].op field. Each value represents -** an operator that is part of a constraint term in the wHERE clause of +** an operator that is part of a constraint term in the WHERE clause of ** a query that uses a [virtual table]. -*/ -#define SQLITE_INDEX_CONSTRAINT_EQ 2 -#define SQLITE_INDEX_CONSTRAINT_GT 4 -#define SQLITE_INDEX_CONSTRAINT_LE 8 -#define SQLITE_INDEX_CONSTRAINT_LT 16 -#define SQLITE_INDEX_CONSTRAINT_GE 32 -#define SQLITE_INDEX_CONSTRAINT_MATCH 64 -#define SQLITE_INDEX_CONSTRAINT_LIKE 65 -#define SQLITE_INDEX_CONSTRAINT_GLOB 66 -#define SQLITE_INDEX_CONSTRAINT_REGEXP 67 -#define SQLITE_INDEX_CONSTRAINT_NE 68 -#define SQLITE_INDEX_CONSTRAINT_ISNOT 69 -#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70 -#define SQLITE_INDEX_CONSTRAINT_ISNULL 71 -#define SQLITE_INDEX_CONSTRAINT_IS 72 -#define SQLITE_INDEX_CONSTRAINT_FUNCTION 150 +** +** ^The left-hand operand of the operator is given by the corresponding +** aConstraint[].iColumn field. ^An iColumn of -1 indicates the left-hand +** operand is the rowid. +** The SQLITE_INDEX_CONSTRAINT_LIMIT and SQLITE_INDEX_CONSTRAINT_OFFSET +** operators have no left-hand operand, and so for those operators the +** corresponding aConstraint[].iColumn is meaningless and should not be +** used. +** +** All operator values from SQLITE_INDEX_CONSTRAINT_FUNCTION through +** value 255 are reserved to represent functions that are overloaded +** by the [xFindFunction|xFindFunction method] of the virtual table +** implementation. +** +** The right-hand operands for each constraint might be accessible using +** the [sqlite3_vtab_rhs_value()] interface. Usually the right-hand +** operand is only available if it appears as a single constant literal +** in the input SQL. If the right-hand operand is another column or an +** expression (even a constant expression) or a parameter, then the +** sqlite3_vtab_rhs_value() probably will not be able to extract it. +** ^The SQLITE_INDEX_CONSTRAINT_ISNULL and +** SQLITE_INDEX_CONSTRAINT_ISNOTNULL operators have no right-hand operand +** and hence calls to sqlite3_vtab_rhs_value() for those operators will +** always return SQLITE_NOTFOUND. +** +** The collating sequence to be used for comparison can be found using +** the [sqlite3_vtab_collation()] interface. For most real-world virtual +** tables, the collating sequence of constraints does not matter (for example +** because the constraints are numeric) and so the sqlite3_vtab_collation() +** interface is no commonly needed. +*/ +#define SQLITE_INDEX_CONSTRAINT_EQ 2 +#define SQLITE_INDEX_CONSTRAINT_GT 4 +#define SQLITE_INDEX_CONSTRAINT_LE 8 +#define SQLITE_INDEX_CONSTRAINT_LT 16 +#define SQLITE_INDEX_CONSTRAINT_GE 32 +#define SQLITE_INDEX_CONSTRAINT_MATCH 64 +#define SQLITE_INDEX_CONSTRAINT_LIKE 65 +#define SQLITE_INDEX_CONSTRAINT_GLOB 66 +#define SQLITE_INDEX_CONSTRAINT_REGEXP 67 +#define SQLITE_INDEX_CONSTRAINT_NE 68 +#define SQLITE_INDEX_CONSTRAINT_ISNOT 69 +#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70 +#define SQLITE_INDEX_CONSTRAINT_ISNULL 71 +#define SQLITE_INDEX_CONSTRAINT_IS 72 +#define SQLITE_INDEX_CONSTRAINT_LIMIT 73 +#define SQLITE_INDEX_CONSTRAINT_OFFSET 74 +#define SQLITE_INDEX_CONSTRAINT_FUNCTION 150 /* ** CAPI3REF: Register A Virtual Table Implementation @@ -7475,7 +7549,7 @@ struct sqlite3_index_info { ** destructor. ** ** ^If the third parameter (the pointer to the sqlite3_module object) is -** NULL then no new module is create and any existing modules with the +** NULL then no new module is created and any existing modules with the ** same name are dropped. ** ** See also: [sqlite3_drop_modules()] @@ -8251,7 +8325,8 @@ SQLITE_API int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_SEEK_COUNT 30 #define SQLITE_TESTCTRL_TRACEFLAGS 31 #define SQLITE_TESTCTRL_TUNE 32 -#define SQLITE_TESTCTRL_LAST 32 /* Largest TESTCTRL */ +#define SQLITE_TESTCTRL_LOGEST 33 +#define SQLITE_TESTCTRL_LAST 33 /* Largest TESTCTRL */ /* ** CAPI3REF: SQL Keyword Checking @@ -8774,6 +8849,16 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); ** The counter is incremented on the first [sqlite3_step()] call of each ** cycle. ** +** [[SQLITE_STMTSTATUS_FILTER_MISS]] +** [[SQLITE_STMTSTATUS_FILTER HIT]] +**
    SQLITE_STMTSTATUS_FILTER_HIT
    +** SQLITE_STMTSTATUS_FILTER_MISS
    +**
    ^SQLITE_STMTSTATUS_FILTER_HIT is the number of times that a join +** step was bypassed because a Bloom filter returned not-found. The +** corresponding SQLITE_STMTSTATUS_FILTER_MISS value is the number of +** times that the Bloom filter returned a find, and thus the join step +** had to be processed as normal. +** ** [[SQLITE_STMTSTATUS_MEMUSED]]
    SQLITE_STMTSTATUS_MEMUSED
    **
    ^This is the approximate number of bytes of heap memory ** used to store the prepared statement. ^This value is not actually @@ -8788,6 +8873,8 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); #define SQLITE_STMTSTATUS_VM_STEP 4 #define SQLITE_STMTSTATUS_REPREPARE 5 #define SQLITE_STMTSTATUS_RUN 6 +#define SQLITE_STMTSTATUS_FILTER_MISS 7 +#define SQLITE_STMTSTATUS_FILTER_HIT 8 #define SQLITE_STMTSTATUS_MEMUSED 99 /* @@ -9756,19 +9843,276 @@ SQLITE_API int sqlite3_vtab_nochange(sqlite3_context*); /* ** CAPI3REF: Determine The Collation For a Virtual Table Constraint +** METHOD: sqlite3_index_info ** ** This function may only be called from within a call to the [xBestIndex] -** method of a [virtual table]. +** method of a [virtual table]. This function returns a pointer to a string +** that is the name of the appropriate collation sequence to use for text +** comparisons on the constraint identified by its arguments. +** +** The first argument must be the pointer to the [sqlite3_index_info] object +** that is the first parameter to the xBestIndex() method. The second argument +** must be an index into the aConstraint[] array belonging to the +** sqlite3_index_info structure passed to xBestIndex. +** +** Important: +** The first parameter must be the same pointer that is passed into the +** xBestMethod() method. The first parameter may not be a pointer to a +** different [sqlite3_index_info] object, even an exact copy. ** -** The first argument must be the sqlite3_index_info object that is the -** first parameter to the xBestIndex() method. The second argument must be -** an index into the aConstraint[] array belonging to the sqlite3_index_info -** structure passed to xBestIndex. This function returns a pointer to a buffer -** containing the name of the collation sequence for the corresponding -** constraint. +** The return value is computed as follows: +** +**
      +**
    1. If the constraint comes from a WHERE clause expression that contains +** a [COLLATE operator], then the name of the collation specified by +** that COLLATE operator is returned. +**

    2. If there is no COLLATE operator, but the column that is the subject +** of the constraint specifies an alternative collating sequence via +** a [COLLATE clause] on the column definition within the CREATE TABLE +** statement that was passed into [sqlite3_declare_vtab()], then the +** name of that alternative collating sequence is returned. +**

    3. Otherwise, "BINARY" is returned. +**

    */ SQLITE_API SQLITE_EXPERIMENTAL const char *sqlite3_vtab_collation(sqlite3_index_info*,int); +/* +** CAPI3REF: Determine if a virtual table query is DISTINCT +** METHOD: sqlite3_index_info +** +** This API may only be used from within an [xBestIndex|xBestIndex method] +** of a [virtual table] implementation. The result of calling this +** interface from outside of xBestIndex() is undefined and probably harmful. +** +** ^The sqlite3_vtab_distinct() interface returns an integer between 0 and +** 3. The integer returned by sqlite3_vtab_distinct() +** gives the virtual table additional information about how the query +** planner wants the output to be ordered. As long as the virtual table +** can meet the ordering requirements of the query planner, it may set +** the "orderByConsumed" flag. +** +**
    1. +** ^If the sqlite3_vtab_distinct() interface returns 0, that means +** that the query planner needs the virtual table to return all rows in the +** sort order defined by the "nOrderBy" and "aOrderBy" fields of the +** [sqlite3_index_info] object. This is the default expectation. If the +** virtual table outputs all rows in sorted order, then it is always safe for +** the xBestIndex method to set the "orderByConsumed" flag, regardless of +** the return value from sqlite3_vtab_distinct(). +**

    2. +** ^(If the sqlite3_vtab_distinct() interface returns 1, that means +** that the query planner does not need the rows to be returned in sorted order +** as long as all rows with the same values in all columns identified by the +** "aOrderBy" field are adjacent.)^ This mode is used when the query planner +** is doing a GROUP BY. +**

    3. +** ^(If the sqlite3_vtab_distinct() interface returns 2, that means +** that the query planner does not need the rows returned in any particular +** order, as long as rows with the same values in all "aOrderBy" columns +** are adjacent.)^ ^(Furthermore, only a single row for each particular +** combination of values in the columns identified by the "aOrderBy" field +** needs to be returned.)^ ^It is always ok for two or more rows with the same +** values in all "aOrderBy" columns to be returned, as long as all such rows +** are adjacent. ^The virtual table may, if it chooses, omit extra rows +** that have the same value for all columns identified by "aOrderBy". +** ^However omitting the extra rows is optional. +** This mode is used for a DISTINCT query. +**

    4. +** ^(If the sqlite3_vtab_distinct() interface returns 3, that means +** that the query planner needs only distinct rows but it does need the +** rows to be sorted.)^ ^The virtual table implementation is free to omit +** rows that are identical in all aOrderBy columns, if it wants to, but +** it is not required to omit any rows. This mode is used for queries +** that have both DISTINCT and ORDER BY clauses. +**

    +** +** ^For the purposes of comparing virtual table output values to see if the +** values are same value for sorting purposes, two NULL values are considered +** to be the same. In other words, the comparison operator is "IS" +** (or "IS NOT DISTINCT FROM") and not "==". +** +** If a virtual table implementation is unable to meet the requirements +** specified above, then it must not set the "orderByConsumed" flag in the +** [sqlite3_index_info] object or an incorrect answer may result. +** +** ^A virtual table implementation is always free to return rows in any order +** it wants, as long as the "orderByConsumed" flag is not set. ^When the +** the "orderByConsumed" flag is unset, the query planner will add extra +** [bytecode] to ensure that the final results returned by the SQL query are +** ordered correctly. The use of the "orderByConsumed" flag and the +** sqlite3_vtab_distinct() interface is merely an optimization. ^Careful +** use of the sqlite3_vtab_distinct() interface and the "orderByConsumed" +** flag might help queries against a virtual table to run faster. Being +** overly aggressive and setting the "orderByConsumed" flag when it is not +** valid to do so, on the other hand, might cause SQLite to return incorrect +** results. +*/ +SQLITE_API int sqlite3_vtab_distinct(sqlite3_index_info*); + +/* +** CAPI3REF: Identify and handle IN constraints in xBestIndex +** +** This interface may only be used from within an +** [xBestIndex|xBestIndex() method] of a [virtual table] implementation. +** The result of invoking this interface from any other context is +** undefined and probably harmful. +** +** ^(A constraint on a virtual table of the form +** "[IN operator|column IN (...)]" is +** communicated to the xBestIndex method as a +** [SQLITE_INDEX_CONSTRAINT_EQ] constraint.)^ If xBestIndex wants to use +** this constraint, it must set the corresponding +** aConstraintUsage[].argvIndex to a postive integer. ^(Then, under +** the usual mode of handling IN operators, SQLite generates [bytecode] +** that invokes the [xFilter|xFilter() method] once for each value +** on the right-hand side of the IN operator.)^ Thus the virtual table +** only sees a single value from the right-hand side of the IN operator +** at a time. +** +** In some cases, however, it would be advantageous for the virtual +** table to see all values on the right-hand of the IN operator all at +** once. The sqlite3_vtab_in() interfaces facilitates this in two ways: +** +**
      +**
    1. +** ^A call to sqlite3_vtab_in(P,N,-1) will return true (non-zero) +** if and only if the [sqlite3_index_info|P->aConstraint][N] constraint +** is an [IN operator] that can be processed all at once. ^In other words, +** sqlite3_vtab_in() with -1 in the third argument is a mechanism +** by which the virtual table can ask SQLite if all-at-once processing +** of the IN operator is even possible. +** +**

    2. +** ^A call to sqlite3_vtab_in(P,N,F) with F==1 or F==0 indicates +** to SQLite that the virtual table does or does not want to process +** the IN operator all-at-once, respectively. ^Thus when the third +** parameter (F) is non-negative, this interface is the mechanism by +** which the virtual table tells SQLite how it wants to process the +** IN operator. +**

    +** +** ^The sqlite3_vtab_in(P,N,F) interface can be invoked multiple times +** within the same xBestIndex method call. ^For any given P,N pair, +** the return value from sqlite3_vtab_in(P,N,F) will always be the same +** within the same xBestIndex call. ^If the interface returns true +** (non-zero), that means that the constraint is an IN operator +** that can be processed all-at-once. ^If the constraint is not an IN +** operator or cannot be processed all-at-once, then the interface returns +** false. +** +** ^(All-at-once processing of the IN operator is selected if both of the +** following conditions are met: +** +**
      +**
    1. The P->aConstraintUsage[N].argvIndex value is set to a positive +** integer. This is how the virtual table tells SQLite that it wants to +** use the N-th constraint. +** +**

    2. The last call to sqlite3_vtab_in(P,N,F) for which F was +** non-negative had F>=1. +**

    )^ +** +** ^If either or both of the conditions above are false, then SQLite uses +** the traditional one-at-a-time processing strategy for the IN constraint. +** ^If both conditions are true, then the argvIndex-th parameter to the +** xFilter method will be an [sqlite3_value] that appears to be NULL, +** but which can be passed to [sqlite3_vtab_in_first()] and +** [sqlite3_vtab_in_next()] to find all values on the right-hand side +** of the IN constraint. +*/ +SQLITE_API int sqlite3_vtab_in(sqlite3_index_info*, int iCons, int bHandle); + +/* +** CAPI3REF: Find all elements on the right-hand side of an IN constraint. +** +** These interfaces are only useful from within the +** [xFilter|xFilter() method] of a [virtual table] implementation. +** The result of invoking these interfaces from any other context +** is undefined and probably harmful. +** +** The X parameter in a call to sqlite3_vtab_in_first(X,P) or +** sqlite3_vtab_in_next(X,P) must be one of the parameters to the +** xFilter method which invokes these routines, and specifically +** a parameter that was previously selected for all-at-once IN constraint +** processing use the [sqlite3_vtab_in()] interface in the +** [xBestIndex|xBestIndex method]. ^(If the X parameter is not +** an xFilter argument that was selected for all-at-once IN constraint +** processing, then these routines return [SQLITE_MISUSE])^ or perhaps +** exhibit some other undefined or harmful behavior. +** +** ^(Use these routines to access all values on the right-hand side +** of the IN constraint using code like the following: +** +**
    +**    for(rc=sqlite3_vtab_in_first(pList, &pVal);
    +**        rc==SQLITE_OK && pVal
    +**        rc=sqlite3_vtab_in_next(pList, &pVal)
    +**    ){
    +**      // do something with pVal
    +**    }
    +**    if( rc!=SQLITE_OK ){
    +**      // an error has occurred
    +**    }
    +** 
    )^ +** +** ^On success, the sqlite3_vtab_in_first(X,P) and sqlite3_vtab_in_next(X,P) +** routines return SQLITE_OK and set *P to point to the first or next value +** on the RHS of the IN constraint. ^If there are no more values on the +** right hand side of the IN constraint, then *P is set to NULL and these +** routines return [SQLITE_DONE]. ^The return value might be +** some other value, such as SQLITE_NOMEM, in the event of a malfunction. +** +** The *ppOut values returned by these routines are only valid until the +** next call to either of these routines or until the end of the xFilter +** method from which these routines were called. If the virtual table +** implementation needs to retain the *ppOut values for longer, it must make +** copies. The *ppOut values are [protected sqlite3_value|protected]. +*/ +SQLITE_API int sqlite3_vtab_in_first(sqlite3_value *pVal, sqlite3_value **ppOut); +SQLITE_API int sqlite3_vtab_in_next(sqlite3_value *pVal, sqlite3_value **ppOut); + +/* +** CAPI3REF: Constraint values in xBestIndex() +** METHOD: sqlite3_index_info +** +** This API may only be used from within the [xBestIndex|xBestIndex method] +** of a [virtual table] implementation. The result of calling this interface +** from outside of an xBestIndex method are undefined and probably harmful. +** +** ^When the sqlite3_vtab_rhs_value(P,J,V) interface is invoked from within +** the [xBestIndex] method of a [virtual table] implementation, with P being +** a copy of the [sqlite3_index_info] object pointer passed into xBestIndex and +** J being a 0-based index into P->aConstraint[], then this routine +** attempts to set *V to the value of the right-hand operand of +** that constraint if the right-hand operand is known. ^If the +** right-hand operand is not known, then *V is set to a NULL pointer. +** ^The sqlite3_vtab_rhs_value(P,J,V) interface returns SQLITE_OK if +** and only if *V is set to a value. ^The sqlite3_vtab_rhs_value(P,J,V) +** inteface returns SQLITE_NOTFOUND if the right-hand side of the J-th +** constraint is not available. ^The sqlite3_vtab_rhs_value() interface +** can return an result code other than SQLITE_OK or SQLITE_NOTFOUND if +** something goes wrong. +** +** The sqlite3_vtab_rhs_value() interface is usually only successful if +** the right-hand operand of a constraint is a literal value in the original +** SQL statement. If the right-hand operand is an expression or a reference +** to some other column or a [host parameter], then sqlite3_vtab_rhs_value() +** will probably return [SQLITE_NOTFOUND]. +** +** ^(Some constraints, such as [SQLITE_INDEX_CONSTRAINT_ISNULL] and +** [SQLITE_INDEX_CONSTRAINT_ISNOTNULL], have no right-hand operand. For such +** constraints, sqlite3_vtab_rhs_value() always returns SQLITE_NOTFOUND.)^ +** +** ^The [sqlite3_value] object returned in *V is a protected sqlite3_value +** and remains valid for the duration of the xBestIndex method call. +** ^When xBestIndex returns, the sqlite3_value object returned by +** sqlite3_vtab_rhs_value() is automatically deallocated. +** +** The "_rhs_" in the name of this routine is an abbreviation for +** "Right-Hand Side". +*/ +SQLITE_API int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value **ppVal); + /* ** CAPI3REF: Conflict resolution modes ** KEYWORDS: {conflict resolution mode} @@ -12801,6 +13145,11 @@ struct fts5_api { /************** End of sqlite3.h *********************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ +/* +** Reuse the STATIC_LRU for mutex access to sqlite3_temp_directory. +*/ +#define SQLITE_MUTEX_STATIC_TEMPDIR SQLITE_MUTEX_STATIC_VFS1 + /* ** Include the configuration header output by 'configure' if we're using the ** autoconf-based build @@ -13622,78 +13971,79 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*); #define TK_SLASH 109 #define TK_REM 110 #define TK_CONCAT 111 -#define TK_COLLATE 112 -#define TK_BITNOT 113 -#define TK_ON 114 -#define TK_INDEXED 115 -#define TK_STRING 116 -#define TK_JOIN_KW 117 -#define TK_CONSTRAINT 118 -#define TK_DEFAULT 119 -#define TK_NULL 120 -#define TK_PRIMARY 121 -#define TK_UNIQUE 122 -#define TK_CHECK 123 -#define TK_REFERENCES 124 -#define TK_AUTOINCR 125 -#define TK_INSERT 126 -#define TK_DELETE 127 -#define TK_UPDATE 128 -#define TK_SET 129 -#define TK_DEFERRABLE 130 -#define TK_FOREIGN 131 -#define TK_DROP 132 -#define TK_UNION 133 -#define TK_ALL 134 -#define TK_EXCEPT 135 -#define TK_INTERSECT 136 -#define TK_SELECT 137 -#define TK_VALUES 138 -#define TK_DISTINCT 139 -#define TK_DOT 140 -#define TK_FROM 141 -#define TK_JOIN 142 -#define TK_USING 143 -#define TK_ORDER 144 -#define TK_GROUP 145 -#define TK_HAVING 146 -#define TK_LIMIT 147 -#define TK_WHERE 148 -#define TK_RETURNING 149 -#define TK_INTO 150 -#define TK_NOTHING 151 -#define TK_FLOAT 152 -#define TK_BLOB 153 -#define TK_INTEGER 154 -#define TK_VARIABLE 155 -#define TK_CASE 156 -#define TK_WHEN 157 -#define TK_THEN 158 -#define TK_ELSE 159 -#define TK_INDEX 160 -#define TK_ALTER 161 -#define TK_ADD 162 -#define TK_WINDOW 163 -#define TK_OVER 164 -#define TK_FILTER 165 -#define TK_COLUMN 166 -#define TK_AGG_FUNCTION 167 -#define TK_AGG_COLUMN 168 -#define TK_TRUEFALSE 169 -#define TK_ISNOT 170 -#define TK_FUNCTION 171 -#define TK_UMINUS 172 -#define TK_UPLUS 173 -#define TK_TRUTH 174 -#define TK_REGISTER 175 -#define TK_VECTOR 176 -#define TK_SELECT_COLUMN 177 -#define TK_IF_NULL_ROW 178 -#define TK_ASTERISK 179 -#define TK_SPAN 180 -#define TK_ERROR 181 -#define TK_SPACE 182 -#define TK_ILLEGAL 183 +#define TK_PTR 112 +#define TK_COLLATE 113 +#define TK_BITNOT 114 +#define TK_ON 115 +#define TK_INDEXED 116 +#define TK_STRING 117 +#define TK_JOIN_KW 118 +#define TK_CONSTRAINT 119 +#define TK_DEFAULT 120 +#define TK_NULL 121 +#define TK_PRIMARY 122 +#define TK_UNIQUE 123 +#define TK_CHECK 124 +#define TK_REFERENCES 125 +#define TK_AUTOINCR 126 +#define TK_INSERT 127 +#define TK_DELETE 128 +#define TK_UPDATE 129 +#define TK_SET 130 +#define TK_DEFERRABLE 131 +#define TK_FOREIGN 132 +#define TK_DROP 133 +#define TK_UNION 134 +#define TK_ALL 135 +#define TK_EXCEPT 136 +#define TK_INTERSECT 137 +#define TK_SELECT 138 +#define TK_VALUES 139 +#define TK_DISTINCT 140 +#define TK_DOT 141 +#define TK_FROM 142 +#define TK_JOIN 143 +#define TK_USING 144 +#define TK_ORDER 145 +#define TK_GROUP 146 +#define TK_HAVING 147 +#define TK_LIMIT 148 +#define TK_WHERE 149 +#define TK_RETURNING 150 +#define TK_INTO 151 +#define TK_NOTHING 152 +#define TK_FLOAT 153 +#define TK_BLOB 154 +#define TK_INTEGER 155 +#define TK_VARIABLE 156 +#define TK_CASE 157 +#define TK_WHEN 158 +#define TK_THEN 159 +#define TK_ELSE 160 +#define TK_INDEX 161 +#define TK_ALTER 162 +#define TK_ADD 163 +#define TK_WINDOW 164 +#define TK_OVER 165 +#define TK_FILTER 166 +#define TK_COLUMN 167 +#define TK_AGG_FUNCTION 168 +#define TK_AGG_COLUMN 169 +#define TK_TRUEFALSE 170 +#define TK_ISNOT 171 +#define TK_FUNCTION 172 +#define TK_UMINUS 173 +#define TK_UPLUS 174 +#define TK_TRUTH 175 +#define TK_REGISTER 176 +#define TK_VECTOR 177 +#define TK_SELECT_COLUMN 178 +#define TK_IF_NULL_ROW 179 +#define TK_ASTERISK 180 +#define TK_SPAN 181 +#define TK_ERROR 182 +#define TK_SPACE 183 +#define TK_ILLEGAL 184 /************** End of parse.h ***********************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ @@ -14043,8 +14393,19 @@ typedef INT16_TYPE LogEst; /* ** Round up a number to the next larger multiple of 8. This is used ** to force 8-byte alignment on 64-bit architectures. +** +** ROUND8() always does the rounding, for any argument. +** +** ROUND8P() assumes that the argument is already an integer number of +** pointers in size, and so it is a no-op on systems where the pointer +** size is 8. */ #define ROUND8(x) (((x)+7)&~7) +#if SQLITE_PTRSIZE==8 +# define ROUND8P(x) (x) +#else +# define ROUND8P(x) (((x)+7)&~7) +#endif /* ** Round down to the nearest multiple of 8 @@ -14107,22 +14468,23 @@ typedef INT16_TYPE LogEst; #endif /* -** SELECTTRACE_ENABLED will be either 1 or 0 depending on whether or not -** the Select query generator tracing logic is turned on. +** TREETRACE_ENABLED will be either 1 or 0 depending on whether or not +** the Abstract Syntax Tree tracing logic is turned on. */ #if !defined(SQLITE_AMALGAMATION) -SQLITE_PRIVATE u32 sqlite3SelectTrace; +SQLITE_PRIVATE u32 sqlite3TreeTrace; #endif #if defined(SQLITE_DEBUG) \ - && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_SELECTTRACE)) -# define SELECTTRACE_ENABLED 1 + && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_SELECTTRACE) \ + || defined(SQLITE_ENABLE_TREETRACE)) +# define TREETRACE_ENABLED 1 # define SELECTTRACE(K,P,S,X) \ - if(sqlite3SelectTrace&(K)) \ + if(sqlite3TreeTrace&(K)) \ sqlite3DebugPrintf("%u/%d/%p: ",(S)->selId,(P)->addrExplain,(S)),\ sqlite3DebugPrintf X #else # define SELECTTRACE(K,P,S,X) -# define SELECTTRACE_ENABLED 0 +# define TREETRACE_ENABLED 0 #endif /* @@ -14207,7 +14569,7 @@ struct BusyHandler { ** pointer will work here as long as it is distinct from SQLITE_STATIC ** and SQLITE_TRANSIENT. */ -#define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3OomFault) +#define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3OomClear) /* ** When SQLITE_OMIT_WSD is defined, it means that the target platform does @@ -14283,6 +14645,7 @@ typedef struct Lookaside Lookaside; typedef struct LookasideSlot LookasideSlot; typedef struct Module Module; typedef struct NameContext NameContext; +typedef struct OnOrUsing OnOrUsing; typedef struct Parse Parse; typedef struct ParseCleanup ParseCleanup; typedef struct PreUpdate PreUpdate; @@ -14335,10 +14698,11 @@ typedef struct With With; /* ** A bit in a Bitmask */ -#define MASKBIT(n) (((Bitmask)1)<<(n)) -#define MASKBIT64(n) (((u64)1)<<(n)) -#define MASKBIT32(n) (((unsigned int)1)<<(n)) -#define ALLBITS ((Bitmask)-1) +#define MASKBIT(n) (((Bitmask)1)<<(n)) +#define MASKBIT64(n) (((u64)1)<<(n)) +#define MASKBIT32(n) (((unsigned int)1)<<(n)) +#define SMASKBIT32(n) ((n)<=31?((unsigned int)1)<<(n):0) +#define ALLBITS ((Bitmask)-1) /* A VList object records a mapping between parameters/variables/wildcards ** in the SQL statement (such as $abc, @pqr, or :xyz) and the integer @@ -14400,14 +14764,15 @@ typedef struct Pager Pager; typedef struct PgHdr DbPage; /* -** Page number PAGER_MJ_PGNO is never used in an SQLite database (it is +** Page number PAGER_SJ_PGNO is never used in an SQLite database (it is ** reserved for working around a windows/posix incompatibility). It is ** used in the journal to signify that the remainder of the journal file ** is devoted to storing a super-journal name - there are no more pages to ** roll back. See comments for function writeSuperJournal() in pager.c ** for details. */ -#define PAGER_MJ_PGNO(x) ((Pgno)((PENDING_BYTE/((x)->pageSize))+1)) +#define PAGER_SJ_PGNO_COMPUTED(x) ((Pgno)((PENDING_BYTE/((x)->pageSize))+1)) +#define PAGER_SJ_PGNO(x) ((x)->lckPgno) /* ** Allowed values for the flags parameter to sqlite3PagerOpen(). @@ -15084,7 +15449,6 @@ struct VdbeOp { #ifdef SQLITE_ENABLE_CURSOR_HINTS Expr *pExpr; /* Used when p4type is P4_EXPR */ #endif - int (*xAdvance)(BtCursor *, int); } p4; #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS char *zComment; /* Comment to improve readability */ @@ -15135,21 +15499,19 @@ typedef struct VdbeOpList VdbeOpList; #define P4_COLLSEQ (-2) /* P4 is a pointer to a CollSeq structure */ #define P4_INT32 (-3) /* P4 is a 32-bit signed integer */ #define P4_SUBPROGRAM (-4) /* P4 is a pointer to a SubProgram structure */ -#define P4_ADVANCE (-5) /* P4 is a pointer to BtreeNext() or BtreePrev() */ -#define P4_TABLE (-6) /* P4 is a pointer to a Table structure */ +#define P4_TABLE (-5) /* P4 is a pointer to a Table structure */ /* Above do not own any resources. Must free those below */ -#define P4_FREE_IF_LE (-7) -#define P4_DYNAMIC (-7) /* Pointer to memory from sqliteMalloc() */ -#define P4_FUNCDEF (-8) /* P4 is a pointer to a FuncDef structure */ -#define P4_KEYINFO (-9) /* P4 is a pointer to a KeyInfo structure */ -#define P4_EXPR (-10) /* P4 is a pointer to an Expr tree */ -#define P4_MEM (-11) /* P4 is a pointer to a Mem* structure */ -#define P4_VTAB (-12) /* P4 is a pointer to an sqlite3_vtab structure */ -#define P4_REAL (-13) /* P4 is a 64-bit floating point value */ -#define P4_INT64 (-14) /* P4 is a 64-bit signed integer */ -#define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */ -#define P4_FUNCCTX (-16) /* P4 is a pointer to an sqlite3_context object */ -#define P4_DYNBLOB (-17) /* Pointer to memory from sqliteMalloc() */ +#define P4_FREE_IF_LE (-6) +#define P4_DYNAMIC (-6) /* Pointer to memory from sqliteMalloc() */ +#define P4_FUNCDEF (-7) /* P4 is a pointer to a FuncDef structure */ +#define P4_KEYINFO (-8) /* P4 is a pointer to a KeyInfo structure */ +#define P4_EXPR (-9) /* P4 is a pointer to an Expr tree */ +#define P4_MEM (-10) /* P4 is a pointer to a Mem* structure */ +#define P4_VTAB (-11) /* P4 is a pointer to an sqlite3_vtab structure */ +#define P4_REAL (-12) /* P4 is a 64-bit floating point value */ +#define P4_INT64 (-13) /* P4 is a 64-bit signed integer */ +#define P4_INTARRAY (-14) /* P4 is a vector of 32-bit integers */ +#define P4_FUNCCTX (-15) /* P4 is a pointer to an sqlite3_context object */ /* Error message codes for OP_Halt */ #define P5_ConstraintNotNull 1 @@ -15194,42 +15556,42 @@ typedef struct VdbeOpList VdbeOpList; #define OP_Savepoint 0 #define OP_AutoCommit 1 #define OP_Transaction 2 -#define OP_SorterNext 3 /* jump */ -#define OP_Prev 4 /* jump */ -#define OP_Next 5 /* jump */ -#define OP_Checkpoint 6 -#define OP_JournalMode 7 -#define OP_Vacuum 8 -#define OP_VFilter 9 /* jump, synopsis: iplan=r[P3] zplan='P4' */ -#define OP_VUpdate 10 /* synopsis: data=r[P3@P2] */ -#define OP_Goto 11 /* jump */ -#define OP_Gosub 12 /* jump */ -#define OP_InitCoroutine 13 /* jump */ -#define OP_Yield 14 /* jump */ -#define OP_MustBeInt 15 /* jump */ -#define OP_Jump 16 /* jump */ -#define OP_Once 17 /* jump */ -#define OP_If 18 /* jump */ +#define OP_Checkpoint 3 +#define OP_JournalMode 4 +#define OP_Vacuum 5 +#define OP_VFilter 6 /* jump, synopsis: iplan=r[P3] zplan='P4' */ +#define OP_VUpdate 7 /* synopsis: data=r[P3@P2] */ +#define OP_Goto 8 /* jump */ +#define OP_Gosub 9 /* jump */ +#define OP_InitCoroutine 10 /* jump */ +#define OP_Yield 11 /* jump */ +#define OP_MustBeInt 12 /* jump */ +#define OP_Jump 13 /* jump */ +#define OP_Once 14 /* jump */ +#define OP_If 15 /* jump */ +#define OP_IfNot 16 /* jump */ +#define OP_IsNullOrType 17 /* jump, synopsis: if typeof(r[P1]) IN (P3,5) goto P2 */ +#define OP_IfNullRow 18 /* jump, synopsis: if P1.nullRow then r[P3]=NULL, goto P2 */ #define OP_Not 19 /* same as TK_NOT, synopsis: r[P2]= !r[P1] */ -#define OP_IfNot 20 /* jump */ -#define OP_IsNullOrType 21 /* jump, synopsis: if typeof(r[P1]) IN (P3,5) goto P2 */ -#define OP_IfNullRow 22 /* jump, synopsis: if P1.nullRow then r[P3]=NULL, goto P2 */ -#define OP_SeekLT 23 /* jump, synopsis: key=r[P3@P4] */ -#define OP_SeekLE 24 /* jump, synopsis: key=r[P3@P4] */ -#define OP_SeekGE 25 /* jump, synopsis: key=r[P3@P4] */ -#define OP_SeekGT 26 /* jump, synopsis: key=r[P3@P4] */ -#define OP_IfNotOpen 27 /* jump, synopsis: if( !csr[P1] ) goto P2 */ -#define OP_IfNoHope 28 /* jump, synopsis: key=r[P3@P4] */ -#define OP_NoConflict 29 /* jump, synopsis: key=r[P3@P4] */ -#define OP_NotFound 30 /* jump, synopsis: key=r[P3@P4] */ -#define OP_Found 31 /* jump, synopsis: key=r[P3@P4] */ -#define OP_SeekRowid 32 /* jump, synopsis: intkey=r[P3] */ -#define OP_NotExists 33 /* jump, synopsis: intkey=r[P3] */ -#define OP_Last 34 /* jump */ -#define OP_IfSmaller 35 /* jump */ -#define OP_SorterSort 36 /* jump */ -#define OP_Sort 37 /* jump */ -#define OP_Rewind 38 /* jump */ +#define OP_SeekLT 20 /* jump, synopsis: key=r[P3@P4] */ +#define OP_SeekLE 21 /* jump, synopsis: key=r[P3@P4] */ +#define OP_SeekGE 22 /* jump, synopsis: key=r[P3@P4] */ +#define OP_SeekGT 23 /* jump, synopsis: key=r[P3@P4] */ +#define OP_IfNotOpen 24 /* jump, synopsis: if( !csr[P1] ) goto P2 */ +#define OP_IfNoHope 25 /* jump, synopsis: key=r[P3@P4] */ +#define OP_NoConflict 26 /* jump, synopsis: key=r[P3@P4] */ +#define OP_NotFound 27 /* jump, synopsis: key=r[P3@P4] */ +#define OP_Found 28 /* jump, synopsis: key=r[P3@P4] */ +#define OP_SeekRowid 29 /* jump, synopsis: intkey=r[P3] */ +#define OP_NotExists 30 /* jump, synopsis: intkey=r[P3] */ +#define OP_Last 31 /* jump */ +#define OP_IfSmaller 32 /* jump */ +#define OP_SorterSort 33 /* jump */ +#define OP_Sort 34 /* jump */ +#define OP_Rewind 35 /* jump */ +#define OP_SorterNext 36 /* jump */ +#define OP_Prev 37 /* jump */ +#define OP_Next 38 /* jump */ #define OP_IdxLE 39 /* jump, synopsis: key=r[P3@P4] */ #define OP_IdxGT 40 /* jump, synopsis: key=r[P3@P4] */ #define OP_IdxLT 41 /* jump, synopsis: key=r[P3@P4] */ @@ -15254,45 +15616,45 @@ typedef struct VdbeOpList VdbeOpList; #define OP_DecrJumpZero 60 /* jump, synopsis: if (--r[P1])==0 goto P2 */ #define OP_IncrVacuum 61 /* jump */ #define OP_VNext 62 /* jump */ -#define OP_Init 63 /* jump, synopsis: Start at P2 */ -#define OP_PureFunc 64 /* synopsis: r[P3]=func(r[P2@NP]) */ -#define OP_Function 65 /* synopsis: r[P3]=func(r[P2@NP]) */ -#define OP_Return 66 -#define OP_EndCoroutine 67 -#define OP_HaltIfNull 68 /* synopsis: if r[P3]=null halt */ -#define OP_Halt 69 -#define OP_Integer 70 /* synopsis: r[P2]=P1 */ -#define OP_Int64 71 /* synopsis: r[P2]=P4 */ -#define OP_String 72 /* synopsis: r[P2]='P4' (len=P1) */ -#define OP_Null 73 /* synopsis: r[P2..P3]=NULL */ -#define OP_SoftNull 74 /* synopsis: r[P1]=NULL */ -#define OP_Blob 75 /* synopsis: r[P2]=P4 (len=P1) */ -#define OP_Variable 76 /* synopsis: r[P2]=parameter(P1,P4) */ -#define OP_Move 77 /* synopsis: r[P2@P3]=r[P1@P3] */ -#define OP_Copy 78 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */ -#define OP_SCopy 79 /* synopsis: r[P2]=r[P1] */ -#define OP_IntCopy 80 /* synopsis: r[P2]=r[P1] */ -#define OP_ChngCntRow 81 /* synopsis: output=r[P1] */ -#define OP_ResultRow 82 /* synopsis: output=r[P1@P2] */ -#define OP_CollSeq 83 -#define OP_AddImm 84 /* synopsis: r[P1]=r[P1]+P2 */ -#define OP_RealAffinity 85 -#define OP_Cast 86 /* synopsis: affinity(r[P1]) */ -#define OP_Permutation 87 -#define OP_Compare 88 /* synopsis: r[P1@P3] <-> r[P2@P3] */ -#define OP_IsTrue 89 /* synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 */ -#define OP_ZeroOrNull 90 /* synopsis: r[P2] = 0 OR NULL */ -#define OP_Offset 91 /* synopsis: r[P3] = sqlite_offset(P1) */ -#define OP_Column 92 /* synopsis: r[P3]=PX */ -#define OP_TypeCheck 93 /* synopsis: typecheck(r[P1@P2]) */ -#define OP_Affinity 94 /* synopsis: affinity(r[P1@P2]) */ -#define OP_MakeRecord 95 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ -#define OP_Count 96 /* synopsis: r[P2]=count() */ -#define OP_ReadCookie 97 -#define OP_SetCookie 98 -#define OP_ReopenIdx 99 /* synopsis: root=P2 iDb=P3 */ -#define OP_OpenRead 100 /* synopsis: root=P2 iDb=P3 */ -#define OP_OpenWrite 101 /* synopsis: root=P2 iDb=P3 */ +#define OP_Filter 63 /* jump, synopsis: if key(P3@P4) not in filter(P1) goto P2 */ +#define OP_Init 64 /* jump, synopsis: Start at P2 */ +#define OP_PureFunc 65 /* synopsis: r[P3]=func(r[P2@NP]) */ +#define OP_Function 66 /* synopsis: r[P3]=func(r[P2@NP]) */ +#define OP_Return 67 +#define OP_EndCoroutine 68 +#define OP_HaltIfNull 69 /* synopsis: if r[P3]=null halt */ +#define OP_Halt 70 +#define OP_Integer 71 /* synopsis: r[P2]=P1 */ +#define OP_Int64 72 /* synopsis: r[P2]=P4 */ +#define OP_String 73 /* synopsis: r[P2]='P4' (len=P1) */ +#define OP_BeginSubrtn 74 /* synopsis: r[P2]=NULL */ +#define OP_Null 75 /* synopsis: r[P2..P3]=NULL */ +#define OP_SoftNull 76 /* synopsis: r[P1]=NULL */ +#define OP_Blob 77 /* synopsis: r[P2]=P4 (len=P1) */ +#define OP_Variable 78 /* synopsis: r[P2]=parameter(P1,P4) */ +#define OP_Move 79 /* synopsis: r[P2@P3]=r[P1@P3] */ +#define OP_Copy 80 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */ +#define OP_SCopy 81 /* synopsis: r[P2]=r[P1] */ +#define OP_IntCopy 82 /* synopsis: r[P2]=r[P1] */ +#define OP_FkCheck 83 +#define OP_ResultRow 84 /* synopsis: output=r[P1@P2] */ +#define OP_CollSeq 85 +#define OP_AddImm 86 /* synopsis: r[P1]=r[P1]+P2 */ +#define OP_RealAffinity 87 +#define OP_Cast 88 /* synopsis: affinity(r[P1]) */ +#define OP_Permutation 89 +#define OP_Compare 90 /* synopsis: r[P1@P3] <-> r[P2@P3] */ +#define OP_IsTrue 91 /* synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 */ +#define OP_ZeroOrNull 92 /* synopsis: r[P2] = 0 OR NULL */ +#define OP_Offset 93 /* synopsis: r[P3] = sqlite_offset(P1) */ +#define OP_Column 94 /* synopsis: r[P3]=PX cursor P1 column P2 */ +#define OP_TypeCheck 95 /* synopsis: typecheck(r[P1@P2]) */ +#define OP_Affinity 96 /* synopsis: affinity(r[P1@P2]) */ +#define OP_MakeRecord 97 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ +#define OP_Count 98 /* synopsis: r[P2]=count() */ +#define OP_ReadCookie 99 +#define OP_SetCookie 100 +#define OP_ReopenIdx 101 /* synopsis: root=P2 iDb=P3 */ #define OP_BitAnd 102 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */ #define OP_BitOr 103 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */ #define OP_ShiftLeft 104 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */ -#define OP_AggInverse 159 /* synopsis: accum=r[P3] inverse(r[P2@P5]) */ -#define OP_AggStep 160 /* synopsis: accum=r[P3] step(r[P2@P5]) */ -#define OP_AggStep1 161 /* synopsis: accum=r[P3] step(r[P2@P5]) */ -#define OP_AggValue 162 /* synopsis: r[P3]=value N=P2 */ -#define OP_AggFinal 163 /* synopsis: accum=r[P1] N=P2 */ -#define OP_Expire 164 -#define OP_CursorLock 165 -#define OP_CursorUnlock 166 -#define OP_TableLock 167 /* synopsis: iDb=P1 root=P2 write=P3 */ -#define OP_VBegin 168 -#define OP_VCreate 169 -#define OP_VDestroy 170 -#define OP_VOpen 171 -#define OP_VColumn 172 /* synopsis: r[P3]=vcolumn(P2) */ -#define OP_VRename 173 -#define OP_Pagecount 174 -#define OP_MaxPgcnt 175 -#define OP_Trace 176 -#define OP_CursorHint 177 -#define OP_ReleaseReg 178 /* synopsis: release r[P1@P2] mask P3 */ -#define OP_Noop 179 -#define OP_Explain 180 -#define OP_Abortable 181 +#define OP_OpenRead 112 /* synopsis: root=P2 iDb=P3 */ +#define OP_OpenWrite 113 /* synopsis: root=P2 iDb=P3 */ +#define OP_BitNot 114 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */ +#define OP_OpenDup 115 +#define OP_OpenAutoindex 116 /* synopsis: nColumn=P2 */ +#define OP_String8 117 /* same as TK_STRING, synopsis: r[P2]='P4' */ +#define OP_OpenEphemeral 118 /* synopsis: nColumn=P2 */ +#define OP_SorterOpen 119 +#define OP_SequenceTest 120 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */ +#define OP_OpenPseudo 121 /* synopsis: P3 columns in r[P2] */ +#define OP_Close 122 +#define OP_ColumnsUsed 123 +#define OP_SeekScan 124 /* synopsis: Scan-ahead up to P1 rows */ +#define OP_SeekHit 125 /* synopsis: set P2<=seekHit<=P3 */ +#define OP_Sequence 126 /* synopsis: r[P2]=cursor[P1].ctr++ */ +#define OP_NewRowid 127 /* synopsis: r[P2]=rowid */ +#define OP_Insert 128 /* synopsis: intkey=r[P3] data=r[P2] */ +#define OP_RowCell 129 +#define OP_Delete 130 +#define OP_ResetCount 131 +#define OP_SorterCompare 132 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ +#define OP_SorterData 133 /* synopsis: r[P2]=data */ +#define OP_RowData 134 /* synopsis: r[P2]=data */ +#define OP_Rowid 135 /* synopsis: r[P2]=PX rowid of P1 */ +#define OP_NullRow 136 +#define OP_SeekEnd 137 +#define OP_IdxInsert 138 /* synopsis: key=r[P2] */ +#define OP_SorterInsert 139 /* synopsis: key=r[P2] */ +#define OP_IdxDelete 140 /* synopsis: key=r[P2@P3] */ +#define OP_DeferredSeek 141 /* synopsis: Move P3 to P1.rowid if needed */ +#define OP_IdxRowid 142 /* synopsis: r[P2]=rowid */ +#define OP_FinishSeek 143 +#define OP_Destroy 144 +#define OP_Clear 145 +#define OP_ResetSorter 146 +#define OP_CreateBtree 147 /* synopsis: r[P2]=root iDb=P1 flags=P3 */ +#define OP_SqlExec 148 +#define OP_ParseSchema 149 +#define OP_LoadAnalysis 150 +#define OP_DropTable 151 +#define OP_DropIndex 152 +#define OP_Real 153 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ +#define OP_DropTrigger 154 +#define OP_IntegrityCk 155 +#define OP_RowSetAdd 156 /* synopsis: rowset(P1)=r[P2] */ +#define OP_Param 157 +#define OP_FkCounter 158 /* synopsis: fkctr[P1]+=P2 */ +#define OP_MemMax 159 /* synopsis: r[P1]=max(r[P1],r[P2]) */ +#define OP_OffsetLimit 160 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */ +#define OP_AggInverse 161 /* synopsis: accum=r[P3] inverse(r[P2@P5]) */ +#define OP_AggStep 162 /* synopsis: accum=r[P3] step(r[P2@P5]) */ +#define OP_AggStep1 163 /* synopsis: accum=r[P3] step(r[P2@P5]) */ +#define OP_AggValue 164 /* synopsis: r[P3]=value N=P2 */ +#define OP_AggFinal 165 /* synopsis: accum=r[P1] N=P2 */ +#define OP_Expire 166 +#define OP_CursorLock 167 +#define OP_CursorUnlock 168 +#define OP_TableLock 169 /* synopsis: iDb=P1 root=P2 write=P3 */ +#define OP_VBegin 170 +#define OP_VCreate 171 +#define OP_VDestroy 172 +#define OP_VOpen 173 +#define OP_VInitIn 174 /* synopsis: r[P2]=ValueList(P1,P3) */ +#define OP_VColumn 175 /* synopsis: r[P3]=vcolumn(P2) */ +#define OP_VRename 176 +#define OP_Pagecount 177 +#define OP_MaxPgcnt 178 +#define OP_ClrSubtype 179 /* synopsis: r[P1].subtype = 0 */ +#define OP_FilterAdd 180 /* synopsis: filter(P1) += key(P3@P4) */ +#define OP_Trace 181 +#define OP_CursorHint 182 +#define OP_ReleaseReg 183 /* synopsis: release r[P1@P2] mask P3 */ +#define OP_Noop 184 +#define OP_Explain 185 +#define OP_Abortable 186 /* Properties such as "out2" or "jump" that are specified in ** comments following the "case" for each opcode in the vdbe.c @@ -15385,29 +15752,30 @@ typedef struct VdbeOpList VdbeOpList; #define OPFLG_OUT2 0x10 /* out2: P2 is an output */ #define OPFLG_OUT3 0x20 /* out3: P3 is an output */ #define OPFLG_INITIALIZER {\ -/* 0 */ 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x10,\ -/* 8 */ 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x03, 0x03,\ -/* 16 */ 0x01, 0x01, 0x03, 0x12, 0x03, 0x03, 0x01, 0x09,\ -/* 24 */ 0x09, 0x09, 0x09, 0x01, 0x09, 0x09, 0x09, 0x09,\ -/* 32 */ 0x09, 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\ +/* 0 */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,\ +/* 8 */ 0x01, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 0x03,\ +/* 16 */ 0x03, 0x03, 0x01, 0x12, 0x09, 0x09, 0x09, 0x09,\ +/* 24 */ 0x01, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x01,\ +/* 32 */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\ /* 40 */ 0x01, 0x01, 0x01, 0x26, 0x26, 0x23, 0x0b, 0x01,\ /* 48 */ 0x01, 0x03, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\ /* 56 */ 0x0b, 0x0b, 0x01, 0x03, 0x03, 0x01, 0x01, 0x01,\ -/* 64 */ 0x00, 0x00, 0x02, 0x02, 0x08, 0x00, 0x10, 0x10,\ -/* 72 */ 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,\ -/* 80 */ 0x10, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00,\ -/* 88 */ 0x00, 0x12, 0x1e, 0x20, 0x00, 0x00, 0x00, 0x00,\ -/* 96 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x26, 0x26,\ +/* 64 */ 0x01, 0x00, 0x00, 0x02, 0x02, 0x08, 0x00, 0x10,\ +/* 72 */ 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10, 0x00,\ +/* 80 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x02, 0x02,\ +/* 88 */ 0x02, 0x00, 0x00, 0x12, 0x1e, 0x20, 0x00, 0x00,\ +/* 96 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x26, 0x26,\ /* 104 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,\ -/* 112 */ 0x00, 0x12, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,\ -/* 120 */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\ -/* 128 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,\ -/* 136 */ 0x04, 0x04, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00,\ -/* 144 */ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ -/* 152 */ 0x10, 0x00, 0x06, 0x10, 0x00, 0x04, 0x1a, 0x00,\ -/* 160 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ -/* 168 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10,\ -/* 176 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,} +/* 112 */ 0x00, 0x00, 0x12, 0x00, 0x00, 0x10, 0x00, 0x00,\ +/* 120 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10,\ +/* 128 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\ +/* 136 */ 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x10, 0x00,\ +/* 144 */ 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,\ +/* 152 */ 0x00, 0x10, 0x00, 0x00, 0x06, 0x10, 0x00, 0x04,\ +/* 160 */ 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ +/* 168 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,\ +/* 176 */ 0x00, 0x10, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00,\ +/* 184 */ 0x00, 0x00, 0x00,} /* The resolve3P2Values() routine is able to run faster if it knows ** the value of the largest JUMP opcode. The smaller the maximum @@ -15415,7 +15783,7 @@ typedef struct VdbeOpList VdbeOpList; ** generated this include file strives to group all JUMP opcodes ** together near the beginning of the list. */ -#define SQLITE_MX_JUMP_OPCODE 63 /* Maximum JUMP opcode */ +#define SQLITE_MX_JUMP_OPCODE 64 /* Maximum JUMP opcode */ /************** End of opcodes.h *********************************************/ /************** Continuing where we left off in vdbe.h ***********************/ @@ -15453,8 +15821,10 @@ SQLITE_PRIVATE void sqlite3VdbeVerifyNoResultRow(Vdbe *p); #endif #if defined(SQLITE_DEBUG) SQLITE_PRIVATE void sqlite3VdbeVerifyAbortable(Vdbe *p, int); +SQLITE_PRIVATE void sqlite3VdbeNoJumpsOutsideSubrtn(Vdbe*,int,int,int); #else # define sqlite3VdbeVerifyAbortable(A,B) +# define sqlite3VdbeNoJumpsOutsideSubrtn(A,B,C,D) #endif SQLITE_PRIVATE VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp,int iLineno); #ifndef SQLITE_OMIT_EXPLAIN @@ -15499,7 +15869,6 @@ SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Parse*); SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeReusable(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe*); -SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3*,Vdbe*); SQLITE_PRIVATE void sqlite3VdbeMakeReady(Vdbe*,Parse*); SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe*, int); @@ -15948,6 +16317,13 @@ SQLITE_PRIVATE int sqlite3PCacheIsDirty(PCache *pCache); # define SQLITE_MAX_PATHLEN FILENAME_MAX #endif +/* Maximum number of symlinks that will be resolved while trying to +** expand a filename in xFullPathname() in the VFS. +*/ +#ifndef SQLITE_MAX_SYMLINK +# define SQLITE_MAX_SYMLINK 200 +#endif + /* ** The default size of a disk sector */ @@ -16476,6 +16852,7 @@ struct sqlite3 { u32 nSchemaLock; /* Do not reset the schema when non-zero */ unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */ int errCode; /* Most recent error code (SQLITE_*) */ + int errByteOffset; /* Byte offset of error in SQL statement */ int errMask; /* & result codes with this before returning */ int iSysErrno; /* Errno value from last system error */ u32 dbOptFlags; /* Flags to enable/disable optimizations */ @@ -16710,6 +17087,12 @@ struct sqlite3 { #define SQLITE_SeekScan 0x00020000 /* The OP_SeekScan optimization */ #define SQLITE_OmitOrderBy 0x00040000 /* Omit pointless ORDER BY */ /* TH3 expects this value ^^^^^^^^^^ to be 0x40000. Coordinate any change */ +#define SQLITE_BloomFilter 0x00080000 /* Use a Bloom filter on searches */ +#define SQLITE_BloomPulldown 0x00100000 /* Run Bloom filters early */ +#define SQLITE_BalancedMerge 0x00200000 /* Balance multi-way merges */ +#define SQLITE_ReleaseReg 0x00400000 /* Use OP_ReleaseReg for testing */ +#define SQLITE_FlttnUnionAll 0x00800000 /* Disable the UNION ALL flattener */ + /* TH3 expects this value ^^^^^^^^^^ See flatten04.test */ #define SQLITE_AllOpts 0xffffffff /* All optimizations */ /* @@ -16812,7 +17195,7 @@ struct FuncDestructor { #define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a ** single query - might change over time */ #define SQLITE_FUNC_TEST 0x4000 /* Built-in testing functions */ -#define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() function */ +/* 0x8000 -- available for reuse */ #define SQLITE_FUNC_WINDOW 0x00010000 /* Built-in window-only function */ #define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */ #define SQLITE_FUNC_DIRECT 0x00080000 /* Not for use in TRIGGERs or VIEWs */ @@ -16829,6 +17212,7 @@ struct FuncDestructor { #define INLINEFUNC_expr_compare 3 #define INLINEFUNC_affinity 4 #define INLINEFUNC_iif 5 +#define INLINEFUNC_sqlite_offset 6 #define INLINEFUNC_unlikely 99 /* Default case */ /* @@ -16883,7 +17267,7 @@ struct FuncDestructor { ** are interpreted in the same way as the first 4 parameters to ** FUNCTION(). ** -** WFUNCTION(zName, nArg, iArg, xStep, xFinal, xValue, xInverse) +** WAGGREGATE(zName, nArg, iArg, xStep, xFinal, xValue, xInverse) ** Used to create an aggregate function definition implemented by ** the C functions xStep and xFinal. The first four parameters ** are interpreted in the same way as the first 4 parameters to @@ -16910,6 +17294,10 @@ struct FuncDestructor { #define MFUNCTION(zName, nArg, xPtr, xFunc) \ {nArg, SQLITE_FUNC_BUILTIN|SQLITE_FUNC_CONSTANT|SQLITE_UTF8, \ xPtr, 0, xFunc, 0, 0, 0, #zName, {0} } +#define JFUNCTION(zName, nArg, iArg, xFunc) \ + {nArg, SQLITE_FUNC_BUILTIN|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS|\ + SQLITE_FUNC_CONSTANT|SQLITE_UTF8, \ + SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} } #define INLINE_FUNC(zName, nArg, iArg, mFlags) \ {nArg, SQLITE_FUNC_BUILTIN|\ SQLITE_UTF8|SQLITE_FUNC_INLINE|SQLITE_FUNC_CONSTANT|(mFlags), \ @@ -17051,6 +17439,7 @@ struct Column { #define COLFLAG_NOTAVAIL 0x0080 /* STORED column not yet calculated */ #define COLFLAG_BUSY 0x0100 /* Blocks recursion on GENERATED columns */ #define COLFLAG_HASCOLL 0x0200 /* Has collating sequence name in zCnName */ +#define COLFLAG_NOEXPAND 0x0400 /* Omit this column when expanding "*" */ #define COLFLAG_GENERATED 0x0060 /* Combo: _STORED, _VIRTUAL */ #define COLFLAG_NOINSERT 0x0062 /* Combo: _HIDDEN, _STORED, _VIRTUAL */ @@ -17457,6 +17846,11 @@ struct KeyInfo { struct UnpackedRecord { KeyInfo *pKeyInfo; /* Collation and sort-order information */ Mem *aMem; /* Values */ + union { + char *z; /* Cache of aMem[0].z for vdbeRecordCompareString() */ + i64 i; /* Cache of aMem[0].u.i for vdbeRecordCompareInt() */ + } u; + int n; /* Cache of aMem[0].n used by vdbeRecordCompareString() */ u16 nField; /* Number of entries in apMem[] */ i8 default_rc; /* Comparison result if keys are equal */ u8 errCode; /* Error detected by xRecordCompare (CORRUPT or NOMEM) */ @@ -17764,7 +18158,10 @@ struct Expr { ** TK_VARIABLE: variable number (always >= 1). ** TK_SELECT_COLUMN: column of the result vector */ i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */ - int iRightJoinTable; /* If EP_FromJoin, the right table of the join */ + union { + int iJoin; /* If EP_OuterON or EP_InnerON, the right table */ + int iOfst; /* else: start of token from start of statement */ + } w; AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */ union { Table *pTab; /* TK_COLUMN: Table containing column. Can be NULL @@ -17783,29 +18180,29 @@ struct Expr { ** EP_Agg == NC_HasAgg == SF_HasAgg ** EP_Win == NC_HasWin */ -#define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */ -#define EP_Distinct 0x000002 /* Aggregate function with DISTINCT keyword */ -#define EP_HasFunc 0x000004 /* Contains one or more functions of any kind */ -#define EP_FixedCol 0x000008 /* TK_Column with a known fixed value */ +#define EP_OuterON 0x000001 /* Originates in ON/USING clause of outer join */ +#define EP_InnerON 0x000002 /* Originates in ON/USING of an inner join */ +#define EP_Distinct 0x000004 /* Aggregate function with DISTINCT keyword */ +#define EP_HasFunc 0x000008 /* Contains one or more functions of any kind */ #define EP_Agg 0x000010 /* Contains one or more aggregate functions */ -#define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */ -#define EP_DblQuoted 0x000040 /* token.z was originally in "..." */ -#define EP_InfixFunc 0x000080 /* True for an infix function: LIKE, GLOB, etc */ -#define EP_Collate 0x000100 /* Tree contains a TK_COLLATE operator */ -#define EP_Commuted 0x000200 /* Comparison operator has been commuted */ -#define EP_IntValue 0x000400 /* Integer value contained in u.iValue */ -#define EP_xIsSelect 0x000800 /* x.pSelect is valid (otherwise x.pList is) */ -#define EP_Skip 0x001000 /* Operator does not contribute to affinity */ -#define EP_Reduced 0x002000 /* Expr struct EXPR_REDUCEDSIZE bytes only */ -#define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */ +#define EP_FixedCol 0x000020 /* TK_Column with a known fixed value */ +#define EP_VarSelect 0x000040 /* pSelect is correlated, not constant */ +#define EP_DblQuoted 0x000080 /* token.z was originally in "..." */ +#define EP_InfixFunc 0x000100 /* True for an infix function: LIKE, GLOB, etc */ +#define EP_Collate 0x000200 /* Tree contains a TK_COLLATE operator */ +#define EP_Commuted 0x000400 /* Comparison operator has been commuted */ +#define EP_IntValue 0x000800 /* Integer value contained in u.iValue */ +#define EP_xIsSelect 0x001000 /* x.pSelect is valid (otherwise x.pList is) */ +#define EP_Skip 0x002000 /* Operator does not contribute to affinity */ +#define EP_Reduced 0x004000 /* Expr struct EXPR_REDUCEDSIZE bytes only */ #define EP_Win 0x008000 /* Contains window functions */ -#define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */ -#define EP_IfNullRow 0x020000 /* The TK_IF_NULL_ROW opcode */ -#define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */ -#define EP_ConstFunc 0x080000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */ -#define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */ -#define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */ - /* 0x400000 // Available */ +#define EP_TokenOnly 0x010000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */ +#define EP_MemToken 0x020000 /* Need to sqlite3DbFree() Expr.zToken */ +#define EP_IfNullRow 0x040000 /* The TK_IF_NULL_ROW opcode */ +#define EP_Unlikely 0x080000 /* unlikely() or likelihood() function */ +#define EP_ConstFunc 0x100000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */ +#define EP_CanBeNull 0x200000 /* Can be null despite NOT NULL constraint */ +#define EP_Subquery 0x400000 /* Tree contains a TK_SELECT operator */ #define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */ #define EP_WinFunc 0x1000000 /* TK_FUNCTION with Expr.y.pWin set */ #define EP_Subrtn 0x2000000 /* Uses Expr.y.sub. TK_IN, _SELECT, or _EXISTS */ @@ -17828,8 +18225,8 @@ struct Expr { #define ExprHasAllProperty(E,P) (((E)->flags&(P))==(P)) #define ExprSetProperty(E,P) (E)->flags|=(P) #define ExprClearProperty(E,P) (E)->flags&=~(P) -#define ExprAlwaysTrue(E) (((E)->flags&(EP_FromJoin|EP_IsTrue))==EP_IsTrue) -#define ExprAlwaysFalse(E) (((E)->flags&(EP_FromJoin|EP_IsFalse))==EP_IsFalse) +#define ExprAlwaysTrue(E) (((E)->flags&(EP_OuterON|EP_IsTrue))==EP_IsTrue) +#define ExprAlwaysFalse(E) (((E)->flags&(EP_OuterON|EP_IsFalse))==EP_IsFalse) /* Macros used to ensure that the correct members of unions are accessed ** in Expr. @@ -17916,12 +18313,18 @@ struct ExprList { struct ExprList_item { /* For each expression in the list */ Expr *pExpr; /* The parse tree for this expression */ char *zEName; /* Token associated with this expression */ - u8 sortFlags; /* Mask of KEYINFO_ORDER_* flags */ - unsigned eEName :2; /* Meaning of zEName */ - unsigned done :1; /* A flag to indicate when processing is finished */ - unsigned reusable :1; /* Constant expression is reusable */ - unsigned bSorterRef :1; /* Defer evaluation until after sorting */ - unsigned bNulls: 1; /* True if explicit "NULLS FIRST/LAST" */ + struct { + u8 sortFlags; /* Mask of KEYINFO_ORDER_* flags */ + unsigned eEName :2; /* Meaning of zEName */ + unsigned done :1; /* Indicates when processing is finished */ + unsigned reusable :1; /* Constant expression is reusable */ + unsigned bSorterRef :1; /* Defer evaluation until after sorting */ + unsigned bNulls :1; /* True if explicit "NULLS FIRST/LAST" */ + unsigned bUsed :1; /* This column used in a SF_NestedFrom subquery */ + unsigned bUsingTerm:1; /* Term from the USING clause of a NestedFrom */ + unsigned bNoExpand: 1; /* Term is an auxiliary in NestedFrom and should + ** not be expanded by "*" in parent queries */ + } fg; union { struct { /* Used by any ExprList other than Parse.pConsExpr */ u16 iOrderByCol; /* For ORDER BY, column number in result set */ @@ -17956,13 +18359,25 @@ struct ExprList { ** If "a" is the k-th column of table "t", then IdList.a[0].idx==k. */ struct IdList { + int nId; /* Number of identifiers on the list */ + u8 eU4; /* Which element of a.u4 is valid */ struct IdList_item { char *zName; /* Name of the identifier */ - int idx; /* Index in some Table.aCol[] of a column named zName */ - } *a; - int nId; /* Number of identifiers on the list */ + union { + int idx; /* Index in some Table.aCol[] of a column named zName */ + Expr *pExpr; /* Expr to implement a USING variable -- NOT USED */ + } u4; + } a[1]; }; +/* +** Allowed values for IdList.eType, which determines which value of the a.u4 +** is valid. +*/ +#define EU4_NONE 0 /* Does not use IdList.a.u4 */ +#define EU4_IDX 1 /* Uses IdList.a.u4.idx */ +#define EU4_EXPR 2 /* Uses IdList.a.u4.pExpr -- NOT CURRENTLY USED */ + /* ** The SrcItem object represents a single term in the FROM clause of a query. ** The SrcList object is mostly an array of SrcItems. @@ -17990,15 +18405,22 @@ struct SrcItem { unsigned isIndexedBy :1; /* True if there is an INDEXED BY clause */ unsigned isTabFunc :1; /* True if table-valued-function syntax */ unsigned isCorrelated :1; /* True if sub-query is correlated */ + unsigned isMaterialized:1; /* This is a materialized view */ unsigned viaCoroutine :1; /* Implemented as a co-routine */ unsigned isRecursive :1; /* True for recursive reference in WITH */ unsigned fromDDL :1; /* Comes from sqlite_schema */ unsigned isCte :1; /* This is a CTE */ unsigned notCte :1; /* This item may not match a CTE */ + unsigned isUsing :1; /* u3.pUsing is valid */ + unsigned isOn :1; /* u3.pOn was once valid and non-NULL */ + unsigned isSynthUsing :1; /* u3.pUsing is synthensized from NATURAL */ + unsigned isNestedFrom :1; /* pSelect is a SF_NestedFrom subquery */ } fg; int iCursor; /* The VDBE cursor number used to access this table */ - Expr *pOn; /* The ON clause of a join */ - IdList *pUsing; /* The USING clause of a join */ + union { + Expr *pOn; /* fg.isUsing==0 => The ON clause of a join */ + IdList *pUsing; /* fg.isUsing==1 => The USING clause of a join */ + } u3; Bitmask colUsed; /* Bit N (1<" clause */ @@ -18010,6 +18432,15 @@ struct SrcItem { } u2; }; +/* +** The OnOrUsing object represents either an ON clause or a USING clause. +** It can never be both at the same time, but it can be neither. +*/ +struct OnOrUsing { + Expr *pOn; /* The ON clause of a join */ + IdList *pUsing; /* The USING clause of a join */ +}; + /* ** The following structure describes the FROM clause of a SELECT statement. ** Each table or subquery in the FROM clause is a separate element of @@ -18038,14 +18469,15 @@ struct SrcList { /* ** Permitted values of the SrcList.a.jointype field */ -#define JT_INNER 0x0001 /* Any kind of inner or cross join */ -#define JT_CROSS 0x0002 /* Explicit use of the CROSS keyword */ -#define JT_NATURAL 0x0004 /* True for a "natural" join */ -#define JT_LEFT 0x0008 /* Left outer join */ -#define JT_RIGHT 0x0010 /* Right outer join */ -#define JT_OUTER 0x0020 /* The "OUTER" keyword is present */ -#define JT_ERROR 0x0040 /* unknown or unsupported join type */ - +#define JT_INNER 0x01 /* Any kind of inner or cross join */ +#define JT_CROSS 0x02 /* Explicit use of the CROSS keyword */ +#define JT_NATURAL 0x04 /* True for a "natural" join */ +#define JT_LEFT 0x08 /* Left outer join */ +#define JT_RIGHT 0x10 /* Right outer join */ +#define JT_OUTER 0x20 /* The "OUTER" keyword is present */ +#define JT_LTORJ 0x40 /* One of the LEFT operands of a RIGHT JOIN + ** Mnemonic: Left Table Of Right Join */ +#define JT_ERROR 0x80 /* unknown or unsupported join type */ /* ** Flags appropriate for the wctrlFlags parameter of sqlite3WhereBegin() @@ -18068,7 +18500,7 @@ struct SrcList { #define WHERE_SORTBYGROUP 0x0200 /* Support sqlite3WhereIsSorted() */ #define WHERE_AGG_DISTINCT 0x0400 /* Query is "SELECT agg(DISTINCT ...)" */ #define WHERE_ORDERBY_LIMIT 0x0800 /* ORDERBY+LIMIT on the inner loop */ - /* 0x1000 not currently used */ +#define WHERE_RIGHT_JOIN 0x1000 /* Processing a RIGHT JOIN */ /* 0x2000 not currently used */ #define WHERE_USE_LIMIT 0x4000 /* Use the LIMIT in cost estimates */ /* 0x8000 not currently used */ @@ -18264,6 +18696,9 @@ struct Select { #define SF_CopyCte 0x4000000 /* SELECT statement is a copy of a CTE */ #define SF_OrderByReqd 0x8000000 /* The ORDER BY clause may not be omitted */ +/* True if S exists and has SF_NestedFrom */ +#define IsNestedFrom(S) ((S)!=0 && ((S)->selFlags&SF_NestedFrom)!=0) + /* ** The results of a SELECT can be distributed in several ways, as defined ** by one of the following macros. The "SRT" prefix means "SELECT Result @@ -18475,6 +18910,7 @@ struct Parse { u8 okConstFactor; /* OK to factor out constants */ u8 disableLookaside; /* Number of times lookaside has been disabled */ u8 disableVtab; /* Disable all virtual tables for this parse */ + u8 withinRJSubrtn; /* Nesting level for RIGHT JOIN body subroutines */ #if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) u8 earlyCleanup; /* OOM inside sqlite3ParserAddCleanup() */ #endif @@ -18504,6 +18940,8 @@ struct Parse { AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */ Parse *pToplevel; /* Parse structure for main program (or NULL) */ Table *pTriggerTab; /* Table triggers are being coded for */ + TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */ + ParseCleanup *pCleanup; /* List of cleanup operations to run after parse */ union { int addrCrTab; /* Address of OP_CreateBtree on CREATE TABLE */ Returning *pReturning; /* The RETURNING clause */ @@ -18524,6 +18962,7 @@ struct Parse { **************************************************************************/ int aTempReg[8]; /* Holding area for temporary registers */ + Parse *pOuterParse; /* Outer Parse object when nested */ Token sNameToken; /* Token with unqualified schema object name */ /************************************************************************ @@ -18558,9 +18997,7 @@ struct Parse { Token sArg; /* Complete text of a module argument */ Table **apVtabLock; /* Pointer to virtual tables needing locking */ #endif - TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */ With *pWith; /* Current WITH clause, or NULL */ - ParseCleanup *pCleanup; /* List of cleanup operations to run after parse */ #ifndef SQLITE_OMIT_ALTERTABLE RenameToken *pRename; /* Tokens subject to renaming by ALTER TABLE */ #endif @@ -18576,7 +19013,8 @@ struct Parse { /* ** Sizes and pointers of various parts of the Parse object. */ -#define PARSE_HDR_SZ offsetof(Parse,aTempReg) /* Recursive part w/o aColCache*/ +#define PARSE_HDR(X) (((char*)(X))+offsetof(Parse,zErrMsg)) +#define PARSE_HDR_SZ (offsetof(Parse,aTempReg)-offsetof(Parse,zErrMsg)) /* Recursive part w/o aColCache*/ #define PARSE_RECURSE_SZ offsetof(Parse,sLastToken) /* Recursive part */ #define PARSE_TAIL_SZ (sizeof(Parse)-PARSE_RECURSE_SZ) /* Non-recursive part */ #define PARSE_TAIL(X) (((char*)(X))+PARSE_RECURSE_SZ) /* Pointer to tail */ @@ -18645,20 +19083,20 @@ struct AuthContext { #define OPFLAG_PREFORMAT 0x80 /* OP_Insert uses preformatted cell */ /* - * Each trigger present in the database schema is stored as an instance of - * struct Trigger. - * - * Pointers to instances of struct Trigger are stored in two ways. - * 1. In the "trigHash" hash table (part of the sqlite3* that represents the - * database). This allows Trigger structures to be retrieved by name. - * 2. All triggers associated with a single table form a linked list, using the - * pNext member of struct Trigger. A pointer to the first element of the - * linked list is stored as the "pTrigger" member of the associated - * struct Table. - * - * The "step_list" member points to the first element of a linked list - * containing the SQL statements specified as the trigger program. - */ +** Each trigger present in the database schema is stored as an instance of +** struct Trigger. +** +** Pointers to instances of struct Trigger are stored in two ways. +** 1. In the "trigHash" hash table (part of the sqlite3* that represents the +** database). This allows Trigger structures to be retrieved by name. +** 2. All triggers associated with a single table form a linked list, using the +** pNext member of struct Trigger. A pointer to the first element of the +** linked list is stored as the "pTrigger" member of the associated +** struct Table. +** +** The "step_list" member points to the first element of a linked list +** containing the SQL statements specified as the trigger program. +*/ struct Trigger { char *zName; /* The name of the trigger */ char *table; /* The table or view to which the trigger applies */ @@ -18685,43 +19123,48 @@ struct Trigger { #define TRIGGER_AFTER 2 /* - * An instance of struct TriggerStep is used to store a single SQL statement - * that is a part of a trigger-program. - * - * Instances of struct TriggerStep are stored in a singly linked list (linked - * using the "pNext" member) referenced by the "step_list" member of the - * associated struct Trigger instance. The first element of the linked list is - * the first step of the trigger-program. - * - * The "op" member indicates whether this is a "DELETE", "INSERT", "UPDATE" or - * "SELECT" statement. The meanings of the other members is determined by the - * value of "op" as follows: - * - * (op == TK_INSERT) - * orconf -> stores the ON CONFLICT algorithm - * pSelect -> If this is an INSERT INTO ... SELECT ... statement, then - * this stores a pointer to the SELECT statement. Otherwise NULL. - * zTarget -> Dequoted name of the table to insert into. - * pExprList -> If this is an INSERT INTO ... VALUES ... statement, then - * this stores values to be inserted. Otherwise NULL. - * pIdList -> If this is an INSERT INTO ... () VALUES ... - * statement, then this stores the column-names to be - * inserted into. - * - * (op == TK_DELETE) - * zTarget -> Dequoted name of the table to delete from. - * pWhere -> The WHERE clause of the DELETE statement if one is specified. - * Otherwise NULL. - * - * (op == TK_UPDATE) - * zTarget -> Dequoted name of the table to update. - * pWhere -> The WHERE clause of the UPDATE statement if one is specified. - * Otherwise NULL. - * pExprList -> A list of the columns to update and the expressions to update - * them to. See sqlite3Update() documentation of "pChanges" - * argument. - * - */ +** An instance of struct TriggerStep is used to store a single SQL statement +** that is a part of a trigger-program. +** +** Instances of struct TriggerStep are stored in a singly linked list (linked +** using the "pNext" member) referenced by the "step_list" member of the +** associated struct Trigger instance. The first element of the linked list is +** the first step of the trigger-program. +** +** The "op" member indicates whether this is a "DELETE", "INSERT", "UPDATE" or +** "SELECT" statement. The meanings of the other members is determined by the +** value of "op" as follows: +** +** (op == TK_INSERT) +** orconf -> stores the ON CONFLICT algorithm +** pSelect -> The content to be inserted - either a SELECT statement or +** a VALUES clause. +** zTarget -> Dequoted name of the table to insert into. +** pIdList -> If this is an INSERT INTO ... () VALUES ... +** statement, then this stores the column-names to be +** inserted into. +** pUpsert -> The ON CONFLICT clauses for an Upsert +** +** (op == TK_DELETE) +** zTarget -> Dequoted name of the table to delete from. +** pWhere -> The WHERE clause of the DELETE statement if one is specified. +** Otherwise NULL. +** +** (op == TK_UPDATE) +** zTarget -> Dequoted name of the table to update. +** pWhere -> The WHERE clause of the UPDATE statement if one is specified. +** Otherwise NULL. +** pExprList -> A list of the columns to update and the expressions to update +** them to. See sqlite3Update() documentation of "pChanges" +** argument. +** +** (op == TK_SELECT) +** pSelect -> The SELECT statement +** +** (op == TK_RETURNING) +** pExprList -> The list of expressions that follow the RETURNING keyword. +** +*/ struct TriggerStep { u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT, ** or TK_RETURNING */ @@ -18871,6 +19314,7 @@ struct Sqlite3Config { int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */ #endif int bLocaltimeFault; /* True to fail localtime() calls */ + int (*xAltLocaltime)(const void*,void*); /* Alternative localtime() routine */ int iOnceResetThreshold; /* When to reset OP_Once counters */ u32 szSorterRef; /* Min size in bytes to use sorter-refs */ unsigned int iPrngSeed; /* Alternative fixed seed for the PRNG */ @@ -19075,7 +19519,7 @@ struct Window { Window **ppThis; /* Pointer to this object in Select.pWin list */ Window *pNextWin; /* Next window function belonging to this SELECT */ Expr *pFilter; /* The FILTER expression */ - FuncDef *pFunc; /* The function */ + FuncDef *pWFunc; /* The function */ int iEphCsr; /* Partition buffer or Peer buffer */ int regAccum; /* Accumulator */ int regResult; /* Interim result */ @@ -19330,19 +19774,54 @@ SQLITE_PRIVATE void *sqlite3TestTextToPtr(const char*); #endif #if defined(SQLITE_DEBUG) +SQLITE_PRIVATE void sqlite3TreeViewLine(TreeView*, const char *zFormat, ...); SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView*, const Expr*, u8); SQLITE_PRIVATE void sqlite3TreeViewBareExprList(TreeView*, const ExprList*, const char*); SQLITE_PRIVATE void sqlite3TreeViewExprList(TreeView*, const ExprList*, u8, const char*); +SQLITE_PRIVATE void sqlite3TreeViewBareIdList(TreeView*, const IdList*, const char*); +SQLITE_PRIVATE void sqlite3TreeViewIdList(TreeView*, const IdList*, u8, const char*); +SQLITE_PRIVATE void sqlite3TreeViewColumnList(TreeView*, const Column*, int, u8); SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView*, const SrcList*); SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView*, const Select*, u8); SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView*, const With*, u8); +SQLITE_PRIVATE void sqlite3TreeViewUpsert(TreeView*, const Upsert*, u8); +#if TREETRACE_ENABLED +SQLITE_PRIVATE void sqlite3TreeViewDelete(const With*, const SrcList*, const Expr*, + const ExprList*,const Expr*, const Trigger*); +SQLITE_PRIVATE void sqlite3TreeViewInsert(const With*, const SrcList*, + const IdList*, const Select*, const ExprList*, + int, const Upsert*, const Trigger*); +SQLITE_PRIVATE void sqlite3TreeViewUpdate(const With*, const SrcList*, const ExprList*, + const Expr*, int, const ExprList*, const Expr*, + const Upsert*, const Trigger*); +#endif +#ifndef SQLITE_OMIT_TRIGGER +SQLITE_PRIVATE void sqlite3TreeViewTriggerStep(TreeView*, const TriggerStep*, u8, u8); +SQLITE_PRIVATE void sqlite3TreeViewTrigger(TreeView*, const Trigger*, u8, u8); +#endif #ifndef SQLITE_OMIT_WINDOWFUNC SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView*, const Window*, u8); SQLITE_PRIVATE void sqlite3TreeViewWinFunc(TreeView*, const Window*, u8); #endif +SQLITE_PRIVATE void sqlite3ShowExpr(const Expr*); +SQLITE_PRIVATE void sqlite3ShowExprList(const ExprList*); +SQLITE_PRIVATE void sqlite3ShowIdList(const IdList*); +SQLITE_PRIVATE void sqlite3ShowSrcList(const SrcList*); +SQLITE_PRIVATE void sqlite3ShowSelect(const Select*); +SQLITE_PRIVATE void sqlite3ShowWith(const With*); +SQLITE_PRIVATE void sqlite3ShowUpsert(const Upsert*); +#ifndef SQLITE_OMIT_TRIGGER +SQLITE_PRIVATE void sqlite3ShowTriggerStep(const TriggerStep*); +SQLITE_PRIVATE void sqlite3ShowTriggerStepList(const TriggerStep*); +SQLITE_PRIVATE void sqlite3ShowTrigger(const Trigger*); +SQLITE_PRIVATE void sqlite3ShowTriggerList(const Trigger*); +#endif +#ifndef SQLITE_OMIT_WINDOWFUNC +SQLITE_PRIVATE void sqlite3ShowWindow(const Window*); +SQLITE_PRIVATE void sqlite3ShowWinFunc(const Window*); +#endif #endif - SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*); SQLITE_PRIVATE void sqlite3ErrorMsg(Parse*, const char*, ...); SQLITE_PRIVATE int sqlite3ErrorToParser(sqlite3*,int); @@ -19351,7 +19830,7 @@ SQLITE_PRIVATE void sqlite3DequoteExpr(Expr*); SQLITE_PRIVATE void sqlite3DequoteToken(Token*); SQLITE_PRIVATE void sqlite3TokenInit(Token*,char*); SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char*, int); -SQLITE_PRIVATE int sqlite3RunParser(Parse*, const char*, char **); +SQLITE_PRIVATE int sqlite3RunParser(Parse*, const char*); SQLITE_PRIVATE void sqlite3FinishCoding(Parse*); SQLITE_PRIVATE int sqlite3GetTempReg(Parse*); SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse*,int); @@ -19490,13 +19969,14 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(Parse*, SrcList*, int, int); SQLITE_PRIVATE SrcList *sqlite3SrcListAppendList(Parse *pParse, SrcList *p1, SrcList *p2); SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(Parse*, SrcList*, Token*, Token*); SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*, - Token*, Select*, Expr*, IdList*); + Token*, Select*, OnOrUsing*); SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *, SrcList *, Token *); SQLITE_PRIVATE void sqlite3SrcListFuncArgs(Parse*, SrcList*, ExprList*); SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *, SrcItem *); -SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(SrcList*); +SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(Parse*,SrcList*); SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse*, SrcList*); SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3*, IdList*); +SQLITE_PRIVATE void sqlite3ClearOnOrUsing(sqlite3*, OnOrUsing*); SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3*, SrcList*); SQLITE_PRIVATE Index *sqlite3AllocateIndexObject(sqlite3*,i16,int,char**); SQLITE_PRIVATE void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*, @@ -19512,10 +19992,12 @@ SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,char*); #endif +SQLITE_PRIVATE void sqlite3CodeChangeCount(Vdbe*,int,const char*); SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*, ExprList*, Expr*); SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*,Expr*,int,ExprList*,Expr*, Upsert*); -SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int); +SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*, + ExprList*,Select*,u16,int); SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*); SQLITE_PRIVATE LogEst sqlite3WhereOutputRowCount(WhereInfo*); SQLITE_PRIVATE int sqlite3WhereIsDistinct(WhereInfo*); @@ -19594,6 +20076,7 @@ SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr*); SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*, u8); SQLITE_PRIVATE int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*); SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr*,int); +SQLITE_PRIVATE int sqlite3ExprIsTableConstraint(Expr*,const SrcItem*); #ifdef SQLITE_ENABLE_CURSOR_HINTS SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr*); #endif @@ -19630,9 +20113,14 @@ SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3*,const Select*,int); SQLITE_PRIVATE FuncDef *sqlite3FunctionSearch(int,const char*); SQLITE_PRIVATE void sqlite3InsertBuiltinFuncs(FuncDef*,int); SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,u8,u8); +SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum*,sqlite3_value*); SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void); SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void); +SQLITE_PRIVATE void sqlite3RegisterJsonFunctions(void); SQLITE_PRIVATE void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3*); +#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON) +SQLITE_PRIVATE int sqlite3JsonTableFunctions(sqlite3*); +#endif SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3*); SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3*); SQLITE_PRIVATE void sqlite3ChangeCookie(Parse*, int); @@ -19686,7 +20174,8 @@ SQLITE_PRIVATE SrcList *sqlite3TriggerStepSrc(Parse*, TriggerStep*); SQLITE_PRIVATE int sqlite3JoinType(Parse*, Token*, Token*, Token*); SQLITE_PRIVATE int sqlite3ColumnIndex(Table *pTab, const char *zCol); -SQLITE_PRIVATE void sqlite3SetJoinExpr(Expr*,int); +SQLITE_PRIVATE void sqlite3SrcItemColumnUsed(SrcItem*,int); +SQLITE_PRIVATE void sqlite3SetJoinExpr(Expr*,int,u32); SQLITE_PRIVATE void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int); SQLITE_PRIVATE void sqlite3DeferForeignKey(Parse*, int); #ifndef SQLITE_OMIT_AUTHORIZATION @@ -19722,14 +20211,8 @@ SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte); SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8**); SQLITE_PRIVATE LogEst sqlite3LogEst(u64); SQLITE_PRIVATE LogEst sqlite3LogEstAdd(LogEst,LogEst); -#ifndef SQLITE_OMIT_VIRTUALTABLE SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double); -#endif -#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \ - defined(SQLITE_ENABLE_STAT4) || \ - defined(SQLITE_EXPLAIN_ESTIMATED_ROWS) SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst); -#endif SQLITE_PRIVATE VList *sqlite3VListAdd(sqlite3*,VList*,const char*,int,int); SQLITE_PRIVATE const char *sqlite3VListNumToName(VList*,int); SQLITE_PRIVATE int sqlite3VListNameToNum(VList*,const char*,int); @@ -19916,17 +20399,20 @@ SQLITE_PRIVATE int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *, FuncDestructor *pDestructor ); SQLITE_PRIVATE void sqlite3NoopDestructor(void*); -SQLITE_PRIVATE void sqlite3OomFault(sqlite3*); +SQLITE_PRIVATE void *sqlite3OomFault(sqlite3*); SQLITE_PRIVATE void sqlite3OomClear(sqlite3*); SQLITE_PRIVATE int sqlite3ApiExit(sqlite3 *db, int); SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *); SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int); +SQLITE_PRIVATE int sqlite3StrAccumEnlarge(StrAccum*, int); SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum*); SQLITE_PRIVATE void sqlite3StrAccumSetError(StrAccum*, u8); SQLITE_PRIVATE void sqlite3ResultStrAccum(sqlite3_context*,StrAccum*); SQLITE_PRIVATE void sqlite3SelectDestInit(SelectDest*,int,int); SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int); +SQLITE_PRIVATE void sqlite3RecordErrorByteOffset(sqlite3*,const char*); +SQLITE_PRIVATE void sqlite3RecordErrorOffsetOfExpr(sqlite3*,const Expr*); SQLITE_PRIVATE void sqlite3BackupRestart(sqlite3_backup *); SQLITE_PRIVATE void sqlite3BackupUpdate(sqlite3_backup *, Pgno, const u8 *); @@ -20031,11 +20517,17 @@ SQLITE_PRIVATE int sqlite3VtabCallCreate(sqlite3*, int, const char *, char **); SQLITE_PRIVATE int sqlite3VtabCallConnect(Parse*, Table*); SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3*, int, const char *); SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *, VTable *); + SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*); +#if (defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)) \ + && !defined(SQLITE_OMIT_VIRTUALTABLE) +SQLITE_PRIVATE void sqlite3VtabUsesAllSchemas(sqlite3_index_info*); +#endif SQLITE_PRIVATE sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*); SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe*, const char*, int); SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *); -SQLITE_PRIVATE void sqlite3ParserReset(Parse*); +SQLITE_PRIVATE void sqlite3ParseObjectInit(Parse*,sqlite3*); +SQLITE_PRIVATE void sqlite3ParseObjectReset(Parse*); SQLITE_PRIVATE void *sqlite3ParserAddCleanup(Parse*,void(*)(sqlite3*,void*),void*); #ifdef SQLITE_ENABLE_NORMALIZE SQLITE_PRIVATE char *sqlite3Normalize(Vdbe*, const char*); @@ -20094,6 +20586,7 @@ SQLITE_PRIVATE void sqlite3FkActions(Parse*, Table*, ExprList*, int, int*, int SQLITE_PRIVATE int sqlite3FkRequired(Parse*, Table*, int*, int); SQLITE_PRIVATE u32 sqlite3FkOldmask(Parse*, Table*); SQLITE_PRIVATE FKey *sqlite3FkReferences(Table *); +SQLITE_PRIVATE void sqlite3FkClearTriggerCache(sqlite3*,int); #else #define sqlite3FkActions(a,b,c,d,e,f) #define sqlite3FkCheck(a,b,c,d,e,f) @@ -20101,6 +20594,7 @@ SQLITE_PRIVATE FKey *sqlite3FkReferences(Table *); #define sqlite3FkOldmask(a,b) 0 #define sqlite3FkRequired(a,b,c,d) 0 #define sqlite3FkReferences(a) 0 + #define sqlite3FkClearTriggerCache(a,b) #endif #ifndef SQLITE_OMIT_FOREIGN_KEY SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *, Table*); @@ -20466,6 +20960,14 @@ SQLITE_API extern int sqlite3_open_file_count; /************** End of os_common.h *******************************************/ /************** Begin file ctime.c *******************************************/ +/* DO NOT EDIT! +** This file is automatically generated by the script in the canonical +** SQLite source tree at tool/mkctimec.tcl. +** +** To modify this header, edit any of the various lists in that script +** which specify categories of generated conditionals in this file. +*/ + /* ** 2010 February 23 ** @@ -20514,9 +21016,6 @@ SQLITE_API extern int sqlite3_open_file_count; */ static const char * const sqlite3azCompileOpt[] = { -/* -** BEGIN CODE GENERATED BY tool/mkctime.tcl -*/ #ifdef SQLITE_32BIT_ROWID "32BIT_ROWID", #endif @@ -20725,9 +21224,6 @@ static const char * const sqlite3azCompileOpt[] = { #ifdef SQLITE_ENABLE_IOTRACE "ENABLE_IOTRACE", #endif -#ifdef SQLITE_ENABLE_JSON1 - "ENABLE_JSON1", -#endif #ifdef SQLITE_ENABLE_LOAD_EXTENSION "ENABLE_LOAD_EXTENSION", #endif @@ -20773,9 +21269,6 @@ static const char * const sqlite3azCompileOpt[] = { #ifdef SQLITE_ENABLE_RTREE "ENABLE_RTREE", #endif -#ifdef SQLITE_ENABLE_SELECTTRACE - "ENABLE_SELECTTRACE", -#endif #ifdef SQLITE_ENABLE_SESSION "ENABLE_SESSION", #endif @@ -20797,6 +21290,9 @@ static const char * const sqlite3azCompileOpt[] = { #ifdef SQLITE_ENABLE_STMT_SCANSTATUS "ENABLE_STMT_SCANSTATUS", #endif +#ifdef SQLITE_ENABLE_TREETRACE + "ENABLE_TREETRACE", +#endif #ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION "ENABLE_UNKNOWN_SQL_FUNCTION", #endif @@ -21051,6 +21547,9 @@ static const char * const sqlite3azCompileOpt[] = { #ifdef SQLITE_OMIT_INTROSPECTION_PRAGMAS "OMIT_INTROSPECTION_PRAGMAS", #endif +#ifdef SQLITE_OMIT_JSON + "OMIT_JSON", +#endif #ifdef SQLITE_OMIT_LIKE_OPTIMIZATION "OMIT_LIKE_OPTIMIZATION", #endif @@ -21239,10 +21738,8 @@ static const char * const sqlite3azCompileOpt[] = { #ifdef SQLITE_ZERO_MALLOC "ZERO_MALLOC", #endif -/* -** END CODE GENERATED BY tool/mkctime.tcl -*/ -}; + +} ; SQLITE_PRIVATE const char **sqlite3CompileOptions(int *pnOpt){ *pnOpt = sizeof(sqlite3azCompileOpt) / sizeof(sqlite3azCompileOpt[0]); @@ -21541,9 +22038,13 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = { 0, /* xTestCallback */ #endif 0, /* bLocaltimeFault */ + 0, /* xAltLocaltime */ 0x7ffffffe, /* iOnceResetThreshold */ SQLITE_DEFAULT_SORTERREF_SIZE, /* szSorterRef */ 0, /* iPrngSeed */ +#ifdef SQLITE_DEBUG + {0,0,0,0,0,0} /* aTune */ +#endif }; /* @@ -21598,7 +22099,7 @@ SQLITE_PRIVATE int sqlite3PendingByte = 0x40000000; /* ** Tracing flags set by SQLITE_TESTCTRL_TRACEFLAGS. */ -SQLITE_PRIVATE u32 sqlite3SelectTrace = 0; +SQLITE_PRIVATE u32 sqlite3TreeTrace = 0; SQLITE_PRIVATE u32 sqlite3WhereTrace = 0; /* #include "opcodes.h" */ @@ -21754,7 +22255,7 @@ typedef struct AuxData AuxData; typedef struct VdbeCursor VdbeCursor; struct VdbeCursor { u8 eCurType; /* One of the CURTYPE_* values above */ - i8 iDb; /* Index of cursor database in db->aDb[] (or -1) */ + i8 iDb; /* Index of cursor database in db->aDb[] */ u8 nullRow; /* True if pointing to a row with no data */ u8 deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */ u8 isTable; /* True for rowid tables. False for indexes */ @@ -21765,11 +22266,13 @@ struct VdbeCursor { Bool isEphemeral:1; /* True for an ephemeral table */ Bool useRandomRowid:1; /* Generate new record numbers semi-randomly */ Bool isOrdered:1; /* True if the table is not BTREE_UNORDERED */ - Bool hasBeenDuped:1; /* This cursor was source or target of OP_OpenDup */ + Bool noReuse:1; /* OpenEphemeral may not reuse this cursor */ u16 seekHit; /* See the OP_SeekHit and OP_IfNoHope opcodes */ - Btree *pBtx; /* Separate file holding temporary table */ + union { /* pBtx for isEphermeral. pAltMap otherwise */ + Btree *pBtx; /* Separate file holding temporary table */ + u32 *aAltMap; /* Mapping from table to index column numbers */ + } ub; i64 seqCount; /* Sequence counter */ - u32 *aAltMap; /* Mapping from table to index column numbers */ /* Cached OP_Column parse information is only valid if cacheStatus matches ** Vdbe.cacheCtr. Vdbe.cacheCtr will never take on the value of @@ -21811,6 +22314,11 @@ struct VdbeCursor { u32 aType[1]; /* Type values record decode. MUST BE LAST */ }; +/* Return true if P is a null-only cursor +*/ +#define IsNullCursor(P) \ + ((P)->eCurType==CURTYPE_PSEUDO && (P)->nullRow && (P)->seekResult==0) + /* ** A value for VdbeCursor.cacheStatus that means the cache is always invalid. @@ -21885,16 +22393,16 @@ struct sqlite3_value { const char *zPType; /* Pointer type when MEM_Term|MEM_Subtype|MEM_Null */ FuncDef *pDef; /* Used only when flags==MEM_Agg */ } u; + char *z; /* String or BLOB value */ + int n; /* Number of characters in string value, excluding '\0' */ u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */ u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */ u8 eSubtype; /* Subtype for this value */ - int n; /* Number of characters in string value, excluding '\0' */ - char *z; /* String or BLOB value */ /* ShallowCopy only needs to copy the information above */ - char *zMalloc; /* Space to hold MEM_Str or MEM_Blob if szMalloc>0 */ + sqlite3 *db; /* The associated database connection */ int szMalloc; /* Size of the zMalloc allocation */ u32 uTemp; /* Transient storage for serial_type in OP_MakeRecord */ - sqlite3 *db; /* The associated database connection */ + char *zMalloc; /* Space to hold MEM_Str or MEM_Blob if szMalloc>0 */ void (*xDel)(void*);/* Destructor for Mem.z - only valid if MEM_Dyn */ #ifdef SQLITE_DEBUG Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */ @@ -21906,11 +22414,43 @@ struct sqlite3_value { ** Size of struct Mem not including the Mem.zMalloc member or anything that ** follows. */ -#define MEMCELLSIZE offsetof(Mem,zMalloc) +#define MEMCELLSIZE offsetof(Mem,db) -/* One or more of the following flags are set to indicate the validOK +/* One or more of the following flags are set to indicate the ** representations of the value stored in the Mem struct. ** +** * MEM_Null An SQL NULL value +** +** * MEM_Null|MEM_Zero An SQL NULL with the virtual table +** UPDATE no-change flag set +** +** * MEM_Null|MEM_Term| An SQL NULL, but also contains a +** MEM_Subtype pointer accessible using +** sqlite3_value_pointer(). +** +** * MEM_Null|MEM_Cleared Special SQL NULL that compares non-equal +** to other NULLs even using the IS operator. +** +** * MEM_Str A string, stored in Mem.z with +** length Mem.n. Zero-terminated if +** MEM_Term is set. This flag is +** incompatible with MEM_Blob and +** MEM_Null, but can appear with MEM_Int, +** MEM_Real, and MEM_IntReal. +** +** * MEM_Blob A blob, stored in Mem.z length Mem.n. +** Incompatible with MEM_Str, MEM_Null, +** MEM_Int, MEM_Real, and MEM_IntReal. +** +** * MEM_Blob|MEM_Zero A blob in Mem.z of length Mem.n plus +** MEM.u.i extra 0x00 bytes at the end. +** +** * MEM_Int Integer stored in Mem.u.i. +** +** * MEM_Real Real stored in Mem.u.r. +** +** * MEM_IntReal Real stored as an integer in Mem.u.i. +** ** If the MEM_Null flag is set, then the value is an SQL NULL value. ** For a pointer type created using sqlite3_bind_pointer() or ** sqlite3_result_pointer() the MEM_Term and MEM_Subtype flags are also set. @@ -21921,6 +22461,7 @@ struct sqlite3_value { ** set, then the string is nul terminated. The MEM_Int and MEM_Real ** flags may coexist with the MEM_Str flag. */ +#define MEM_Undefined 0x0000 /* Value is undefined */ #define MEM_Null 0x0001 /* Value is NULL (or a pointer) */ #define MEM_Str 0x0002 /* Value is a string */ #define MEM_Int 0x0004 /* Value is an integer */ @@ -21928,28 +22469,24 @@ struct sqlite3_value { #define MEM_Blob 0x0010 /* Value is a BLOB */ #define MEM_IntReal 0x0020 /* MEM_Int that stringifies like MEM_Real */ #define MEM_AffMask 0x003f /* Mask of affinity bits */ + +/* Extra bits that modify the meanings of the core datatypes above +*/ #define MEM_FromBind 0x0040 /* Value originates from sqlite3_bind() */ -#define MEM_Undefined 0x0080 /* Value is undefined */ + /* 0x0080 // Available */ #define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */ -#define MEM_TypeMask 0xc1bf /* Mask of type bits */ - +#define MEM_Term 0x0200 /* String in Mem.z is zero terminated */ +#define MEM_Zero 0x0400 /* Mem.i contains count of 0s appended to blob */ +#define MEM_Subtype 0x0800 /* Mem.eSubtype is valid */ +#define MEM_TypeMask 0x0dbf /* Mask of type bits */ -/* Whenever Mem contains a valid string or blob representation, one of -** the following flags must be set to determine the memory management -** policy for Mem.z. The MEM_Term flag tells us whether or not the -** string is \000 or \u0000 terminated +/* Bits that determine the storage for Mem.z for a string or blob or +** aggregate accumulator. */ -#define MEM_Term 0x0200 /* String in Mem.z is zero terminated */ -#define MEM_Dyn 0x0400 /* Need to call Mem.xDel() on Mem.z */ -#define MEM_Static 0x0800 /* Mem.z points to a static string */ -#define MEM_Ephem 0x1000 /* Mem.z points to an ephemeral string */ -#define MEM_Agg 0x2000 /* Mem.z points to an agg function context */ -#define MEM_Zero 0x4000 /* Mem.i contains count of 0s appended to blob */ -#define MEM_Subtype 0x8000 /* Mem.eSubtype is valid */ -#ifdef SQLITE_OMIT_INCRBLOB - #undef MEM_Zero - #define MEM_Zero 0x0000 -#endif +#define MEM_Dyn 0x1000 /* Need to call Mem.xDel() on Mem.z */ +#define MEM_Static 0x2000 /* Mem.z points to a static string */ +#define MEM_Ephem 0x4000 /* Mem.z points to an ephemeral string */ +#define MEM_Agg 0x8000 /* Mem.z points to an agg function context */ /* Return TRUE if Mem X contains dynamically allocated content - anything ** that needs to be deallocated to avoid a leak. @@ -21971,11 +22508,15 @@ struct sqlite3_value { && (X)->n==0 && (X)->u.nZero==0) /* -** Return true if a memory cell is not marked as invalid. This macro +** Return true if a memory cell has been initialized and is valid. ** is for use inside assert() statements only. +** +** A Memory cell is initialized if at least one of the +** MEM_Null, MEM_Str, MEM_Int, MEM_Real, MEM_Blob, or MEM_IntReal bits +** is set. It is "undefined" if all those bits are zero. */ #ifdef SQLITE_DEBUG -#define memIsValid(M) ((M)->flags & MEM_Undefined)==0 +#define memIsValid(M) ((M)->flags & MEM_AffMask)!=0 #endif /* @@ -22013,6 +22554,7 @@ struct sqlite3_context { Vdbe *pVdbe; /* The VM that owns this context */ int iOp; /* Instruction number of OP_Function */ int isError; /* Error code returned by the function. */ + u8 enc; /* Encoding to use for results */ u8 skipFlag; /* Skip accumulator loading if true */ u8 argc; /* Number of arguments */ sqlite3_value *argv[1]; /* Argument set */ @@ -22061,7 +22603,6 @@ struct Vdbe { Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */ Parse *pParse; /* Parsing context used to create this Vdbe */ ynVar nVar; /* Number of entries in aVar[] */ - u32 iVdbeMagic; /* Magic number defining state of the SQL statement */ int nMem; /* Number of memory locations currently allocated */ int nCursor; /* Number of slots in apCsr[] */ u32 cacheCtr; /* VdbeCursor row cache generation counter */ @@ -22099,17 +22640,16 @@ struct Vdbe { u8 errorAction; /* Recovery action to do in case of an error */ u8 minWriteFileFormat; /* Minimum file format for writable database files */ u8 prepFlags; /* SQLITE_PREPARE_* flags */ - u8 doingRerun; /* True if rerunning after an auto-reprepare */ + u8 eVdbeState; /* On of the VDBE_*_STATE values */ bft expired:2; /* 1: recompile VM immediately 2: when convenient */ bft explain:2; /* True if EXPLAIN present on SQL command */ bft changeCntOn:1; /* True to update the change-counter */ - bft runOnlyOnce:1; /* Automatically expire on reset */ bft usesStmtJournal:1; /* True if uses a statement journal */ bft readOnly:1; /* True for statements that do not write */ bft bIsReader:1; /* True for statements that read */ yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */ yDbMask lockMask; /* Subset of btreeMask that requires a lock */ - u32 aCounter[7]; /* Counters used by sqlite3_stmt_status() */ + u32 aCounter[9]; /* Counters used by sqlite3_stmt_status() */ char *zSql; /* Text of the SQL statement that generated this */ #ifdef SQLITE_ENABLE_NORMALIZE char *zNormSql; /* Normalization of the associated SQL statement */ @@ -22130,13 +22670,12 @@ struct Vdbe { }; /* -** The following are allowed values for Vdbe.magic +** The following are allowed values for Vdbe.eVdbeState */ -#define VDBE_MAGIC_INIT 0x16bceaa5 /* Building a VDBE program */ -#define VDBE_MAGIC_RUN 0x2df20da3 /* VDBE is ready to execute */ -#define VDBE_MAGIC_HALT 0x319c2973 /* VDBE has completed execution */ -#define VDBE_MAGIC_RESET 0x48fa9f76 /* Reset and ready to run again */ -#define VDBE_MAGIC_DEAD 0x5606c3c8 /* The VDBE has been deallocated */ +#define VDBE_INIT_STATE 0 /* Prepared statement under construction */ +#define VDBE_READY_STATE 1 /* Ready to run but not yet started */ +#define VDBE_RUN_STATE 2 /* Run in progress */ +#define VDBE_HALT_STATE 3 /* Finished. Need reset() or finalize() */ /* ** Structure used to store the context required by the @@ -22159,19 +22698,50 @@ struct PreUpdate { Index *pPk; /* PK index if pTab is WITHOUT ROWID */ }; +/* +** An instance of this object is used to pass an vector of values into +** OP_VFilter, the xFilter method of a virtual table. The vector is the +** set of values on the right-hand side of an IN constraint. +** +** The value as passed into xFilter is an sqlite3_value with a "pointer" +** type, such as is generated by sqlite3_result_pointer() and read by +** sqlite3_value_pointer. Such values have MEM_Term|MEM_Subtype|MEM_Null +** and a subtype of 'p'. The sqlite3_vtab_in_first() and _next() interfaces +** know how to use this object to step through all the values in the +** right operand of the IN constraint. +*/ +typedef struct ValueList ValueList; +struct ValueList { + BtCursor *pCsr; /* An ephemeral table holding all values */ + sqlite3_value *pOut; /* Register to hold each decoded output value */ +}; + +/* Size of content associated with serial types that fit into a +** single-byte varint. +*/ +#ifndef SQLITE_AMALGAMATION +SQLITE_PRIVATE const u8 sqlite3SmallTypeSizes[]; +#endif + /* ** Function prototypes */ SQLITE_PRIVATE void sqlite3VdbeError(Vdbe*, const char *, ...); SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*); +SQLITE_PRIVATE void sqlite3VdbeFreeCursorNN(Vdbe*,VdbeCursor*); void sqliteVdbePopStack(Vdbe*,int); +SQLITE_PRIVATE int SQLITE_NOINLINE sqlite3VdbeHandleMovedCursor(VdbeCursor *p); SQLITE_PRIVATE int SQLITE_NOINLINE sqlite3VdbeFinishMoveto(VdbeCursor*); -SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor**, u32*); SQLITE_PRIVATE int sqlite3VdbeCursorRestore(VdbeCursor*); SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32); SQLITE_PRIVATE u8 sqlite3VdbeOneByteSerialTypeLen(u8); -SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(unsigned char*, Mem*, u32); -SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*); +#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT +SQLITE_PRIVATE u64 sqlite3FloatSwap(u64 in); +# define swapMixedEndianFloat(X) X = sqlite3FloatSwap(X) +#else +# define swapMixedEndianFloat(X) +#endif +SQLITE_PRIVATE void sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*); SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(sqlite3*, AuxData**, int, int); int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *); @@ -22217,7 +22787,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetRowSet(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, u8, u8); SQLITE_PRIVATE int sqlite3IntFloatCompare(i64,double); -SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem*); +SQLITE_PRIVATE i64 sqlite3VdbeIntValue(const Mem*); SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem*); SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem*); SQLITE_PRIVATE int sqlite3VdbeBooleanValue(Mem*, int ifNull); @@ -22228,6 +22798,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemCast(Mem*,u8,u8); SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,Mem*); SQLITE_PRIVATE int sqlite3VdbeMemFromBtreeZeroOffset(BtCursor*,u32,Mem*); SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p); +SQLITE_PRIVATE void sqlite3VdbeMemReleaseMalloc(Mem*p); SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*); #ifndef SQLITE_OMIT_WINDOWFUNC SQLITE_PRIVATE int sqlite3VdbeMemAggValue(Mem*, Mem*, FuncDef*); @@ -22630,8 +23201,7 @@ SQLITE_API int sqlite3_db_status( db->pnBytesFreed = &nByte; for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){ - sqlite3VdbeClearObject(db, pVdbe); - sqlite3DbFree(db, pVdbe); + sqlite3VdbeDelete(pVdbe); } db->pnBytesFreed = 0; @@ -23195,8 +23765,10 @@ static void clearYMD_HMS_TZ(DateTime *p){ ** is available. This routine returns 0 on success and ** non-zero on any kind of error. ** -** If the sqlite3GlobalConfig.bLocaltimeFault variable is true then this -** routine will always fail. +** If the sqlite3GlobalConfig.bLocaltimeFault variable is non-zero then this +** routine will always fail. If bLocaltimeFault is nonzero and +** sqlite3GlobalConfig.xAltLocaltime is not NULL, then xAltLocaltime() is +** invoked in place of the OS-defined localtime() function. ** ** EVIDENCE-OF: R-62172-00036 In this implementation, the standard C ** library function localtime_r() is used to assist in the calculation of @@ -23212,14 +23784,30 @@ static int osLocaltime(time_t *t, struct tm *pTm){ sqlite3_mutex_enter(mutex); pX = localtime(t); #ifndef SQLITE_UNTESTABLE - if( sqlite3GlobalConfig.bLocaltimeFault ) pX = 0; + if( sqlite3GlobalConfig.bLocaltimeFault ){ + if( sqlite3GlobalConfig.xAltLocaltime!=0 + && 0==sqlite3GlobalConfig.xAltLocaltime((const void*)t,(void*)pTm) + ){ + pX = pTm; + }else{ + pX = 0; + } + } #endif if( pX ) *pTm = *pX; +#if SQLITE_THREADSAFE>0 sqlite3_mutex_leave(mutex); +#endif rc = pX==0; #else #ifndef SQLITE_UNTESTABLE - if( sqlite3GlobalConfig.bLocaltimeFault ) return 1; + if( sqlite3GlobalConfig.bLocaltimeFault ){ + if( sqlite3GlobalConfig.xAltLocaltime!=0 ){ + return sqlite3GlobalConfig.xAltLocaltime((const void*)t,(void*)pTm); + }else{ + return 1; + } + } #endif #if HAVE_LOCALTIME_R rc = localtime_r(t, pTm)==0; @@ -23234,67 +23822,56 @@ static int osLocaltime(time_t *t, struct tm *pTm){ #ifndef SQLITE_OMIT_LOCALTIME /* -** Compute the difference (in milliseconds) between localtime and UTC -** (a.k.a. GMT) for the time value p where p is in UTC. If no error occurs, -** return this value and set *pRc to SQLITE_OK. -** -** Or, if an error does occur, set *pRc to SQLITE_ERROR. The returned value -** is undefined in this case. +** Assuming the input DateTime is UTC, move it to its localtime equivalent. */ -static sqlite3_int64 localtimeOffset( - DateTime *p, /* Date at which to calculate offset */ - sqlite3_context *pCtx, /* Write error here if one occurs */ - int *pRc /* OUT: Error code. SQLITE_OK or ERROR */ +static int toLocaltime( + DateTime *p, /* Date at which to calculate offset */ + sqlite3_context *pCtx /* Write error here if one occurs */ ){ - DateTime x, y; time_t t; struct tm sLocal; + int iYearDiff; /* Initialize the contents of sLocal to avoid a compiler warning. */ memset(&sLocal, 0, sizeof(sLocal)); - x = *p; - computeYMD_HMS(&x); - if( x.Y<1971 || x.Y>=2038 ){ + computeJD(p); + if( p->iJD<2108667600*(i64)100000 /* 1970-01-01 */ + || p->iJD>2130141456*(i64)100000 /* 2038-01-18 */ + ){ /* EVIDENCE-OF: R-55269-29598 The localtime_r() C function normally only ** works for years between 1970 and 2037. For dates outside this range, ** SQLite attempts to map the year into an equivalent year within this ** range, do the calculation, then map the year back. */ - x.Y = 2000; - x.M = 1; - x.D = 1; - x.h = 0; - x.m = 0; - x.s = 0.0; - } else { - int s = (int)(x.s + 0.5); - x.s = s; + DateTime x = *p; + computeYMD_HMS(&x); + iYearDiff = (2000 + x.Y%4) - x.Y; + x.Y += iYearDiff; + x.validJD = 0; + computeJD(&x); + t = (time_t)(x.iJD/1000 - 21086676*(i64)10000); + }else{ + iYearDiff = 0; + t = (time_t)(p->iJD/1000 - 21086676*(i64)10000); } - x.tz = 0; - x.validJD = 0; - computeJD(&x); - t = (time_t)(x.iJD/1000 - 21086676*(i64)10000); if( osLocaltime(&t, &sLocal) ){ sqlite3_result_error(pCtx, "local time unavailable", -1); - *pRc = SQLITE_ERROR; - return 0; + return SQLITE_ERROR; } - y.Y = sLocal.tm_year + 1900; - y.M = sLocal.tm_mon + 1; - y.D = sLocal.tm_mday; - y.h = sLocal.tm_hour; - y.m = sLocal.tm_min; - y.s = sLocal.tm_sec; - y.validYMD = 1; - y.validHMS = 1; - y.validJD = 0; - y.rawS = 0; - y.validTZ = 0; - y.isError = 0; - computeJD(&y); - *pRc = SQLITE_OK; - return y.iJD - x.iJD; + p->Y = sLocal.tm_year + 1900 - iYearDiff; + p->M = sLocal.tm_mon + 1; + p->D = sLocal.tm_mday; + p->h = sLocal.tm_hour; + p->m = sLocal.tm_min; + p->s = sLocal.tm_sec + (p->iJD%1000)*0.001; + p->validYMD = 1; + p->validHMS = 1; + p->validJD = 0; + p->rawS = 0; + p->validTZ = 0; + p->isError = 0; + return SQLITE_OK; } #endif /* SQLITE_OMIT_LOCALTIME */ @@ -23307,18 +23884,17 @@ static sqlite3_int64 localtimeOffset( ** of several units of time. */ static const struct { - u8 eType; /* Transformation type code */ - u8 nName; /* Length of th name */ - char *zName; /* Name of the transformation */ - double rLimit; /* Maximum NNN value for this transform */ - double rXform; /* Constant used for this transform */ + u8 nName; /* Length of the name */ + char zName[7]; /* Name of the transformation */ + float rLimit; /* Maximum NNN value for this transform */ + float rXform; /* Constant used for this transform */ } aXformType[] = { - { 0, 6, "second", 464269060800.0, 1000.0 }, - { 0, 6, "minute", 7737817680.0, 60000.0 }, - { 0, 4, "hour", 128963628.0, 3600000.0 }, - { 0, 3, "day", 5373485.0, 86400000.0 }, - { 1, 5, "month", 176546.0, 2592000000.0 }, - { 2, 4, "year", 14713.0, 31536000000.0 }, + { 6, "second", 4.6427e+14, 1.0 }, + { 6, "minute", 7.7379e+12, 60.0 }, + { 4, "hour", 1.2897e+11, 3600.0 }, + { 3, "day", 5373485.0, 86400.0 }, + { 5, "month", 176546.0, 2592000.0 }, + { 4, "year", 14713.0, 31536000.0 }, }; /* @@ -23349,11 +23925,55 @@ static int parseModifier( sqlite3_context *pCtx, /* Function context */ const char *z, /* The text of the modifier */ int n, /* Length of zMod in bytes */ - DateTime *p /* The date/time value to be modified */ + DateTime *p, /* The date/time value to be modified */ + int idx /* Parameter index of the modifier */ ){ int rc = 1; double r; switch(sqlite3UpperToLower[(u8)z[0]] ){ + case 'a': { + /* + ** auto + ** + ** If rawS is available, then interpret as a julian day number, or + ** a unix timestamp, depending on its magnitude. + */ + if( sqlite3_stricmp(z, "auto")==0 ){ + if( idx>1 ) return 1; /* IMP: R-33611-57934 */ + if( !p->rawS || p->validJD ){ + rc = 0; + p->rawS = 0; + }else if( p->s>=-21086676*(i64)10000 /* -4713-11-24 12:00:00 */ + && p->s<=(25340230*(i64)10000)+799 /* 9999-12-31 23:59:59 */ + ){ + r = p->s*1000.0 + 210866760000000.0; + clearYMD_HMS_TZ(p); + p->iJD = (sqlite3_int64)(r + 0.5); + p->validJD = 1; + p->rawS = 0; + rc = 0; + } + } + break; + } + case 'j': { + /* + ** julianday + ** + ** Always interpret the prior number as a julian-day value. If this + ** is not the first modifier, or if the prior argument is not a numeric + ** value in the allowed range of julian day numbers understood by + ** SQLite (0..5373484.5) then the result will be NULL. + */ + if( sqlite3_stricmp(z, "julianday")==0 ){ + if( idx>1 ) return 1; /* IMP: R-31176-64601 */ + if( p->validJD && p->rawS ){ + rc = 0; + p->rawS = 0; + } + } + break; + } #ifndef SQLITE_OMIT_LOCALTIME case 'l': { /* localtime @@ -23362,9 +23982,7 @@ static int parseModifier( ** show local time. */ if( sqlite3_stricmp(z, "localtime")==0 && sqlite3NotPureFunc(pCtx) ){ - computeJD(p); - p->iJD += localtimeOffset(p, pCtx, &rc); - clearYMD_HMS_TZ(p); + rc = toLocaltime(p, pCtx); } break; } @@ -23377,6 +23995,7 @@ static int parseModifier( ** seconds since 1970. Convert to a real julian day number. */ if( sqlite3_stricmp(z, "unixepoch")==0 && p->rawS ){ + if( idx>1 ) return 1; /* IMP: R-49255-55373 */ r = p->s*1000.0 + 210866760000000.0; if( r>=0.0 && r<464269060800000.0 ){ clearYMD_HMS_TZ(p); @@ -23389,18 +24008,31 @@ static int parseModifier( #ifndef SQLITE_OMIT_LOCALTIME else if( sqlite3_stricmp(z, "utc")==0 && sqlite3NotPureFunc(pCtx) ){ if( p->tzSet==0 ){ - sqlite3_int64 c1; + i64 iOrigJD; /* Original localtime */ + i64 iGuess; /* Guess at the corresponding utc time */ + int cnt = 0; /* Safety to prevent infinite loop */ + int iErr; /* Guess is off by this much */ + computeJD(p); - c1 = localtimeOffset(p, pCtx, &rc); - if( rc==SQLITE_OK ){ - p->iJD -= c1; - clearYMD_HMS_TZ(p); - p->iJD += c1 - localtimeOffset(p, pCtx, &rc); - } + iGuess = iOrigJD = p->iJD; + iErr = 0; + do{ + DateTime new; + memset(&new, 0, sizeof(new)); + iGuess -= iErr; + new.iJD = iGuess; + new.validJD = 1; + rc = toLocaltime(&new, pCtx); + if( rc ) return rc; + computeJD(&new); + iErr = new.iJD - iOrigJD; + }while( iErr && cnt++<3 ); + memset(p, 0, sizeof(*p)); + p->iJD = iGuess; + p->validJD = 1; p->tzSet = 1; - }else{ - rc = SQLITE_OK; } + rc = SQLITE_OK; } #endif break; @@ -23516,9 +24148,10 @@ static int parseModifier( && sqlite3_strnicmp(aXformType[i].zName, z, n)==0 && r>-aXformType[i].rLimit && rM += (int)r; x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12; @@ -23528,8 +24161,9 @@ static int parseModifier( r -= (int)r; break; } - case 2: { /* Special processing to add years */ + case 5: { /* Special processing to add years */ int y = (int)r; + assert( strcmp(aXformType[i].zName,"year")==0 ); computeYMD_HMS(p); p->Y += y; p->validJD = 0; @@ -23538,7 +24172,7 @@ static int parseModifier( } } computeJD(p); - p->iJD += (sqlite3_int64)(r*aXformType[i].rXform + rRounder); + p->iJD += (sqlite3_int64)(r*1000.0*aXformType[i].rXform + rRounder); rc = 0; break; } @@ -23588,7 +24222,7 @@ static int isDate( for(i=1; iisError || !validJulianDay(p->iJD) ) return 1; @@ -23618,6 +24252,24 @@ static void juliandayFunc( } } +/* +** unixepoch( TIMESTRING, MOD, MOD, ...) +** +** Return the number of seconds (including fractional seconds) since +** the unix epoch of 1970-01-01 00:00:00 GMT. +*/ +static void unixepochFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + DateTime x; + if( isDate(context, argc, argv, &x)==0 ){ + computeJD(&x); + sqlite3_result_int64(context, x.iJD/1000 - 21086676*(i64)10000); + } +} + /* ** datetime( TIMESTRING, MOD, MOD, ...) ** @@ -23630,11 +24282,38 @@ static void datetimeFunc( ){ DateTime x; if( isDate(context, argc, argv, &x)==0 ){ - char zBuf[100]; + int Y, s; + char zBuf[24]; computeYMD_HMS(&x); - sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d %02d:%02d:%02d", - x.Y, x.M, x.D, x.h, x.m, (int)(x.s)); - sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); + Y = x.Y; + if( Y<0 ) Y = -Y; + zBuf[1] = '0' + (Y/1000)%10; + zBuf[2] = '0' + (Y/100)%10; + zBuf[3] = '0' + (Y/10)%10; + zBuf[4] = '0' + (Y)%10; + zBuf[5] = '-'; + zBuf[6] = '0' + (x.M/10)%10; + zBuf[7] = '0' + (x.M)%10; + zBuf[8] = '-'; + zBuf[9] = '0' + (x.D/10)%10; + zBuf[10] = '0' + (x.D)%10; + zBuf[11] = ' '; + zBuf[12] = '0' + (x.h/10)%10; + zBuf[13] = '0' + (x.h)%10; + zBuf[14] = ':'; + zBuf[15] = '0' + (x.m/10)%10; + zBuf[16] = '0' + (x.m)%10; + zBuf[17] = ':'; + s = (int)x.s; + zBuf[18] = '0' + (s/10)%10; + zBuf[19] = '0' + (s)%10; + zBuf[20] = 0; + if( x.Y<0 ){ + zBuf[0] = '-'; + sqlite3_result_text(context, zBuf, 20, SQLITE_TRANSIENT); + }else{ + sqlite3_result_text(context, &zBuf[1], 19, SQLITE_TRANSIENT); + } } } @@ -23650,10 +24329,20 @@ static void timeFunc( ){ DateTime x; if( isDate(context, argc, argv, &x)==0 ){ - char zBuf[100]; + int s; + char zBuf[16]; computeHMS(&x); - sqlite3_snprintf(sizeof(zBuf), zBuf, "%02d:%02d:%02d", x.h, x.m, (int)x.s); - sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); + zBuf[0] = '0' + (x.h/10)%10; + zBuf[1] = '0' + (x.h)%10; + zBuf[2] = ':'; + zBuf[3] = '0' + (x.m/10)%10; + zBuf[4] = '0' + (x.m)%10; + zBuf[5] = ':'; + s = (int)x.s; + zBuf[6] = '0' + (s/10)%10; + zBuf[7] = '0' + (s)%10; + zBuf[8] = 0; + sqlite3_result_text(context, zBuf, 8, SQLITE_TRANSIENT); } } @@ -23669,10 +24358,28 @@ static void dateFunc( ){ DateTime x; if( isDate(context, argc, argv, &x)==0 ){ - char zBuf[100]; + int Y; + char zBuf[16]; computeYMD(&x); - sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d", x.Y, x.M, x.D); - sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); + Y = x.Y; + if( Y<0 ) Y = -Y; + zBuf[1] = '0' + (Y/1000)%10; + zBuf[2] = '0' + (Y/100)%10; + zBuf[3] = '0' + (Y/10)%10; + zBuf[4] = '0' + (Y)%10; + zBuf[5] = '-'; + zBuf[6] = '0' + (x.M/10)%10; + zBuf[7] = '0' + (x.M)%10; + zBuf[8] = '-'; + zBuf[9] = '0' + (x.D/10)%10; + zBuf[10] = '0' + (x.D)%10; + zBuf[11] = 0; + if( x.Y<0 ){ + zBuf[0] = '-'; + sqlite3_result_text(context, zBuf, 11, SQLITE_TRANSIENT); + }else{ + sqlite3_result_text(context, &zBuf[1], 10, SQLITE_TRANSIENT); + } } } @@ -23894,6 +24601,7 @@ SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){ static FuncDef aDateTimeFuncs[] = { #ifndef SQLITE_OMIT_DATETIME_FUNCS PURE_DATE(julianday, -1, 0, 0, juliandayFunc ), + PURE_DATE(unixepoch, -1, 0, 0, unixepochFunc ), PURE_DATE(date, -1, 0, 0, dateFunc ), PURE_DATE(time, -1, 0, 0, timeFunc ), PURE_DATE(datetime, -1, 0, 0, datetimeFunc ), @@ -26448,8 +27156,13 @@ static void *memsys5Realloc(void *pPrior, int nBytes){ */ static int memsys5Roundup(int n){ int iFullSz; - if( n > 0x40000000 ) return 0; - for(iFullSz=mem5.szAtom; iFullSz0x40000000 ) return 0; + for(iFullSz=mem5.szAtom*8; iFullSz=n ) return iFullSz/2; return iFullSz; } @@ -28830,8 +29543,9 @@ SQLITE_PRIVATE char *sqlite3DbSpanDup(sqlite3 *db, const char *zStart, const cha ** Free any prior content in *pz and replace it with a copy of zNew. */ SQLITE_PRIVATE void sqlite3SetString(char **pz, sqlite3 *db, const char *zNew){ + char *z = sqlite3DbStrDup(db, zNew); sqlite3DbFree(db, *pz); - *pz = sqlite3DbStrDup(db, zNew); + *pz = z; } /* @@ -28839,8 +29553,15 @@ SQLITE_PRIVATE void sqlite3SetString(char **pz, sqlite3 *db, const char *zNew){ ** has happened. This routine will set db->mallocFailed, and also ** temporarily disable the lookaside memory allocator and interrupt ** any running VDBEs. +** +** Always return a NULL pointer so that this routine can be invoked using +** +** return sqlite3OomFault(db); +** +** and thereby avoid unnecessary stack frame allocations for the overwhelmingly +** common case where no OOM occurs. */ -SQLITE_PRIVATE void sqlite3OomFault(sqlite3 *db){ +SQLITE_PRIVATE void *sqlite3OomFault(sqlite3 *db){ if( db->mallocFailed==0 && db->bBenignMalloc==0 ){ db->mallocFailed = 1; if( db->nVdbeExec>0 ){ @@ -28848,9 +29569,16 @@ SQLITE_PRIVATE void sqlite3OomFault(sqlite3 *db){ } DisableLookaside; if( db->pParse ){ + Parse *pParse; + sqlite3ErrorMsg(db->pParse, "out of memory"); db->pParse->rc = SQLITE_NOMEM_BKPT; + for(pParse=db->pParse->pOuterParse; pParse; pParse = pParse->pOuterParse){ + pParse->nErr++; + pParse->rc = SQLITE_NOMEM; + } } } + return 0; } /* @@ -29713,8 +30441,8 @@ SQLITE_API void sqlite3_str_vappendf( case etSQLESCAPE: /* %q: Escape ' characters */ case etSQLESCAPE2: /* %Q: Escape ' and enclose in '...' */ case etSQLESCAPE3: { /* %w: Escape " characters */ - int i, j, k, n, isnull; - int needQuote; + i64 i, j, k, n; + int needQuote, isnull; char ch; char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */ char *escarg; @@ -29759,12 +30487,22 @@ SQLITE_API void sqlite3_str_vappendf( goto adjust_width_for_utf8; } case etTOKEN: { - Token *pToken; if( (pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return; - pToken = va_arg(ap, Token*); - assert( bArgList==0 ); - if( pToken && pToken->n ){ - sqlite3_str_append(pAccum, (const char*)pToken->z, pToken->n); + if( flag_alternateform ){ + /* %#T means an Expr pointer that uses Expr.u.zToken */ + Expr *pExpr = va_arg(ap,Expr*); + if( ALWAYS(pExpr) && ALWAYS(!ExprHasProperty(pExpr,EP_IntValue)) ){ + sqlite3_str_appendall(pAccum, (const char*)pExpr->u.zToken); + sqlite3RecordErrorOffsetOfExpr(pAccum->db, pExpr); + } + }else{ + /* %T means a Token pointer */ + Token *pToken = va_arg(ap, Token*); + assert( bArgList==0 ); + if( pToken && pToken->n ){ + sqlite3_str_append(pAccum, (const char*)pToken->z, pToken->n); + sqlite3RecordErrorByteOffset(pAccum->db, pToken->z); + } } length = width = 0; break; @@ -29784,8 +30522,14 @@ SQLITE_API void sqlite3_str_vappendf( sqlite3_str_appendall(pAccum, pItem->zName); }else if( pItem->zAlias ){ sqlite3_str_appendall(pAccum, pItem->zAlias); - }else if( ALWAYS(pItem->pSelect) ){ - sqlite3_str_appendf(pAccum, "SUBQUERY %u", pItem->pSelect->selId); + }else{ + Select *pSel = pItem->pSelect; + assert( pSel!=0 ); + if( pSel->selFlags & SF_NestedFrom ){ + sqlite3_str_appendf(pAccum, "(join-%u)", pSel->selId); + }else{ + sqlite3_str_appendf(pAccum, "(subquery-%u)", pSel->selId); + } } length = width = 0; break; @@ -29819,6 +30563,44 @@ SQLITE_API void sqlite3_str_vappendf( }/* End for loop over the format string */ } /* End of function */ + +/* +** The z string points to the first character of a token that is +** associated with an error. If db does not already have an error +** byte offset recorded, try to compute the error byte offset for +** z and set the error byte offset in db. +*/ +SQLITE_PRIVATE void sqlite3RecordErrorByteOffset(sqlite3 *db, const char *z){ + const Parse *pParse; + const char *zText; + const char *zEnd; + assert( z!=0 ); + if( NEVER(db==0) ) return; + if( db->errByteOffset!=(-2) ) return; + pParse = db->pParse; + if( NEVER(pParse==0) ) return; + zText =pParse->zTail; + if( NEVER(zText==0) ) return; + zEnd = &zText[strlen(zText)]; + if( SQLITE_WITHIN(z,zText,zEnd) ){ + db->errByteOffset = (int)(z-zText); + } +} + +/* +** If pExpr has a byte offset for the start of a token, record that as +** as the error offset. +*/ +SQLITE_PRIVATE void sqlite3RecordErrorOffsetOfExpr(sqlite3 *db, const Expr *pExpr){ + while( pExpr + && (ExprHasProperty(pExpr,EP_OuterON|EP_InnerON) || pExpr->w.iOfst<=0) + ){ + pExpr = pExpr->pLeft; + } + if( pExpr==0 ) return; + db->errByteOffset = pExpr->w.iOfst; +} + /* ** Enlarge the memory allocation on a StrAccum object so that it is ** able to accept at least N more bytes of text. @@ -29826,7 +30608,7 @@ SQLITE_API void sqlite3_str_vappendf( ** Return the number of bytes of text that StrAccum is able to accept ** after the attempted enlargement. The value returned might be zero. */ -static int sqlite3StrAccumEnlarge(StrAccum *p, int N){ +SQLITE_PRIVATE int sqlite3StrAccumEnlarge(StrAccum *p, int N){ char *zNew; assert( p->nChar+(i64)N >= p->nAlloc ); /* Only called if really needed */ if( p->accError ){ @@ -30272,40 +31054,44 @@ SQLITE_API void sqlite3_str_appendf(StrAccum *p, const char *zFormat, ...){ ** Add a new subitem to the tree. The moreToFollow flag indicates that this ** is not the last item in the tree. */ -static TreeView *sqlite3TreeViewPush(TreeView *p, u8 moreToFollow){ +static void sqlite3TreeViewPush(TreeView **pp, u8 moreToFollow){ + TreeView *p = *pp; if( p==0 ){ - p = sqlite3_malloc64( sizeof(*p) ); - if( p==0 ) return 0; + *pp = p = sqlite3_malloc64( sizeof(*p) ); + if( p==0 ) return; memset(p, 0, sizeof(*p)); }else{ p->iLevel++; } assert( moreToFollow==0 || moreToFollow==1 ); - if( p->iLevelbLine) ) p->bLine[p->iLevel] = moreToFollow; - return p; + if( p->iLevel<(int)sizeof(p->bLine) ) p->bLine[p->iLevel] = moreToFollow; } /* ** Finished with one layer of the tree */ -static void sqlite3TreeViewPop(TreeView *p){ +static void sqlite3TreeViewPop(TreeView **pp){ + TreeView *p = *pp; if( p==0 ) return; p->iLevel--; - if( p->iLevel<0 ) sqlite3_free(p); + if( p->iLevel<0 ){ + sqlite3_free(p); + *pp = 0; + } } /* ** Generate a single line of output for the tree, with a prefix that contains ** all the appropriate tree lines */ -static void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){ +SQLITE_PRIVATE void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){ va_list ap; int i; StrAccum acc; - char zBuf[500]; + char zBuf[1000]; sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0); if( p ){ - for(i=0; iiLevel && ibLine)-1; i++){ + for(i=0; iiLevel && i<(int)sizeof(p->bLine)-1; i++){ sqlite3_str_append(&acc, p->bLine[i] ? "| " : " ", 4); } sqlite3_str_append(&acc, p->bLine[i] ? "|-- " : "'-- ", 4); @@ -30326,10 +31112,57 @@ static void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){ ** Shorthand for starting a new tree item that consists of a single label */ static void sqlite3TreeViewItem(TreeView *p, const char *zLabel,u8 moreFollows){ - p = sqlite3TreeViewPush(p, moreFollows); + sqlite3TreeViewPush(&p, moreFollows); sqlite3TreeViewLine(p, "%s", zLabel); } +/* +** Show a list of Column objects in tree format. +*/ +SQLITE_PRIVATE void sqlite3TreeViewColumnList( + TreeView *pView, + const Column *aCol, + int nCol, + u8 moreToFollow +){ + int i; + sqlite3TreeViewPush(&pView, moreToFollow); + sqlite3TreeViewLine(pView, "COLUMNS"); + for(i=0; inCte>0 ){ - pView = sqlite3TreeViewPush(pView, 1); + sqlite3TreeViewPush(&pView, moreToFollow); for(i=0; inCte; i++){ StrAccum x; char zLine[1000]; @@ -30359,6 +31192,10 @@ SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 m } sqlite3_str_appendf(&x, ")"); } + if( pCte->eM10d!=M10d_Any ){ + sqlite3_str_appendf(&x, " %sMATERIALIZED", + pCte->eM10d==M10d_No ? "NOT " : ""); + } if( pCte->pUse ){ sqlite3_str_appendf(&x, " (pUse=0x%p, nUse=%d)", pCte->pUse, pCte->pUse->nUse); @@ -30366,9 +31203,9 @@ SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 m sqlite3StrAccumFinish(&x); sqlite3TreeViewItem(pView, zLine, inCte-1); sqlite3TreeViewSelect(pView, pCte->pSelect, 0); - sqlite3TreeViewPop(pView); + sqlite3TreeViewPop(&pView); } - sqlite3TreeViewPop(pView); + sqlite3TreeViewPop(&pView); } } @@ -30377,10 +31214,12 @@ SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 m */ SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){ int i; + if( pSrc==0 ) return; for(i=0; inSrc; i++){ const SrcItem *pItem = &pSrc->a[i]; StrAccum x; - char zLine[100]; + int n = 0; + char zLine[1000]; sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0); x.printfFlags |= SQLITE_PRINTF_INTERNAL; sqlite3_str_appendf(&x, "{%d:*} %!S", pItem->iCursor, pItem); @@ -30388,26 +31227,48 @@ SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc) sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx", pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab, pItem->colUsed); } - if( pItem->fg.jointype & JT_LEFT ){ + if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))==(JT_LEFT|JT_RIGHT) ){ + sqlite3_str_appendf(&x, " FULL-OUTER-JOIN"); + }else if( pItem->fg.jointype & JT_LEFT ){ sqlite3_str_appendf(&x, " LEFT-JOIN"); + }else if( pItem->fg.jointype & JT_RIGHT ){ + sqlite3_str_appendf(&x, " RIGHT-JOIN"); }else if( pItem->fg.jointype & JT_CROSS ){ sqlite3_str_appendf(&x, " CROSS-JOIN"); } + if( pItem->fg.jointype & JT_LTORJ ){ + sqlite3_str_appendf(&x, " LTORJ"); + } if( pItem->fg.fromDDL ){ sqlite3_str_appendf(&x, " DDL"); } if( pItem->fg.isCte ){ sqlite3_str_appendf(&x, " CteUse=0x%p", pItem->u2.pCteUse); } + if( pItem->fg.isOn || (pItem->fg.isUsing==0 && pItem->u3.pOn!=0) ){ + sqlite3_str_appendf(&x, " ON"); + } sqlite3StrAccumFinish(&x); sqlite3TreeViewItem(pView, zLine, inSrc-1); + n = 0; + if( pItem->pSelect ) n++; + if( pItem->fg.isTabFunc ) n++; + if( pItem->fg.isUsing ) n++; + if( pItem->fg.isUsing ){ + sqlite3TreeViewIdList(pView, pItem->u3.pUsing, (--n)>0, "USING"); + } if( pItem->pSelect ){ - sqlite3TreeViewSelect(pView, pItem->pSelect, 0); + if( pItem->pTab ){ + Table *pTab = pItem->pTab; + sqlite3TreeViewColumnList(pView, pTab->aCol, pTab->nCol, 1); + } + assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) ); + sqlite3TreeViewSelect(pView, pItem->pSelect, (--n)>0); } if( pItem->fg.isTabFunc ){ sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:"); } - sqlite3TreeViewPop(pView); + sqlite3TreeViewPop(&pView); } } @@ -30421,11 +31282,11 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m sqlite3TreeViewLine(pView, "nil-SELECT"); return; } - pView = sqlite3TreeViewPush(pView, moreToFollow); + sqlite3TreeViewPush(&pView, moreToFollow); if( p->pWith ){ sqlite3TreeViewWith(pView, p->pWith, 1); cnt = 1; - sqlite3TreeViewPush(pView, 1); + sqlite3TreeViewPush(&pView, 1); } do{ if( p->selFlags & SF_WhereBegin ){ @@ -30439,7 +31300,7 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m (int)p->nSelectRow ); } - if( cnt++ ) sqlite3TreeViewPop(pView); + if( cnt++ ) sqlite3TreeViewPop(&pView); if( p->pPrior ){ n = 1000; }else{ @@ -30462,24 +31323,24 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m #ifndef SQLITE_OMIT_WINDOWFUNC if( p->pWin ){ Window *pX; - pView = sqlite3TreeViewPush(pView, (n--)>0); + sqlite3TreeViewPush(&pView, (n--)>0); sqlite3TreeViewLine(pView, "window-functions"); for(pX=p->pWin; pX; pX=pX->pNextWin){ sqlite3TreeViewWinFunc(pView, pX, pX->pNextWin!=0); } - sqlite3TreeViewPop(pView); + sqlite3TreeViewPop(&pView); } #endif if( p->pSrc && p->pSrc->nSrc ){ - pView = sqlite3TreeViewPush(pView, (n--)>0); + sqlite3TreeViewPush(&pView, (n--)>0); sqlite3TreeViewLine(pView, "FROM"); sqlite3TreeViewSrcList(pView, p->pSrc); - sqlite3TreeViewPop(pView); + sqlite3TreeViewPop(&pView); } if( p->pWhere ){ sqlite3TreeViewItem(pView, "WHERE", (n--)>0); sqlite3TreeViewExpr(pView, p->pWhere, 0); - sqlite3TreeViewPop(pView); + sqlite3TreeViewPop(&pView); } if( p->pGroupBy ){ sqlite3TreeViewExprList(pView, p->pGroupBy, (n--)>0, "GROUPBY"); @@ -30487,7 +31348,7 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m if( p->pHaving ){ sqlite3TreeViewItem(pView, "HAVING", (n--)>0); sqlite3TreeViewExpr(pView, p->pHaving, 0); - sqlite3TreeViewPop(pView); + sqlite3TreeViewPop(&pView); } #ifndef SQLITE_OMIT_WINDOWFUNC if( p->pWinDefn ){ @@ -30496,7 +31357,7 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m for(pX=p->pWinDefn; pX; pX=pX->pNextWin){ sqlite3TreeViewWindow(pView, pX, pX->pNextWin!=0); } - sqlite3TreeViewPop(pView); + sqlite3TreeViewPop(&pView); } #endif if( p->pOrderBy ){ @@ -30508,9 +31369,9 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m if( p->pLimit->pRight ){ sqlite3TreeViewItem(pView, "OFFSET", (n--)>0); sqlite3TreeViewExpr(pView, p->pLimit->pRight, 0); - sqlite3TreeViewPop(pView); + sqlite3TreeViewPop(&pView); } - sqlite3TreeViewPop(pView); + sqlite3TreeViewPop(&pView); } if( p->pPrior ){ const char *zOp = "UNION"; @@ -30523,7 +31384,7 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m } p = p->pPrior; }while( p!=0 ); - sqlite3TreeViewPop(pView); + sqlite3TreeViewPop(&pView); } #ifndef SQLITE_OMIT_WINDOWFUNC @@ -30539,24 +31400,24 @@ SQLITE_PRIVATE void sqlite3TreeViewBound( switch( eBound ){ case TK_UNBOUNDED: { sqlite3TreeViewItem(pView, "UNBOUNDED", moreToFollow); - sqlite3TreeViewPop(pView); + sqlite3TreeViewPop(&pView); break; } case TK_CURRENT: { sqlite3TreeViewItem(pView, "CURRENT", moreToFollow); - sqlite3TreeViewPop(pView); + sqlite3TreeViewPop(&pView); break; } case TK_PRECEDING: { sqlite3TreeViewItem(pView, "PRECEDING", moreToFollow); sqlite3TreeViewExpr(pView, pExpr, 0); - sqlite3TreeViewPop(pView); + sqlite3TreeViewPop(&pView); break; } case TK_FOLLOWING: { sqlite3TreeViewItem(pView, "FOLLOWING", moreToFollow); sqlite3TreeViewExpr(pView, pExpr, 0); - sqlite3TreeViewPop(pView); + sqlite3TreeViewPop(&pView); break; } } @@ -30569,12 +31430,13 @@ SQLITE_PRIVATE void sqlite3TreeViewBound( */ SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u8 more){ int nElement = 0; + if( pWin==0 ) return; if( pWin->pFilter ){ sqlite3TreeViewItem(pView, "FILTER", 1); sqlite3TreeViewExpr(pView, pWin->pFilter, 0); - sqlite3TreeViewPop(pView); + sqlite3TreeViewPop(&pView); } - pView = sqlite3TreeViewPush(pView, more); + sqlite3TreeViewPush(&pView, more); if( pWin->zName ){ sqlite3TreeViewLine(pView, "OVER %s (%p)", pWin->zName, pWin); }else{ @@ -30585,9 +31447,9 @@ SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u if( pWin->eFrmType ) nElement++; if( pWin->eExclude ) nElement++; if( pWin->zBase ){ - sqlite3TreeViewPush(pView, (--nElement)>0); + sqlite3TreeViewPush(&pView, (--nElement)>0); sqlite3TreeViewLine(pView, "window: %s", pWin->zBase); - sqlite3TreeViewPop(pView); + sqlite3TreeViewPop(&pView); } if( pWin->pPartition ){ sqlite3TreeViewExprList(pView, pWin->pPartition, nElement>0,"PARTITION-BY"); @@ -30605,7 +31467,7 @@ SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u sqlite3TreeViewItem(pView, zBuf, (--nElement)>0); sqlite3TreeViewBound(pView, pWin->eStart, pWin->pStart, 1); sqlite3TreeViewBound(pView, pWin->eEnd, pWin->pEnd, 0); - sqlite3TreeViewPop(pView); + sqlite3TreeViewPop(&pView); } if( pWin->eExclude ){ char zBuf[30]; @@ -30620,11 +31482,11 @@ SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u zExclude = zBuf; break; } - sqlite3TreeViewPush(pView, 0); + sqlite3TreeViewPush(&pView, 0); sqlite3TreeViewLine(pView, "EXCLUDE %s", zExclude); - sqlite3TreeViewPop(pView); + sqlite3TreeViewPop(&pView); } - sqlite3TreeViewPop(pView); + sqlite3TreeViewPop(&pView); } #endif /* SQLITE_OMIT_WINDOWFUNC */ @@ -30633,11 +31495,12 @@ SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u ** Generate a human-readable explanation for a Window Function object */ SQLITE_PRIVATE void sqlite3TreeViewWinFunc(TreeView *pView, const Window *pWin, u8 more){ - pView = sqlite3TreeViewPush(pView, more); + if( pWin==0 ) return; + sqlite3TreeViewPush(&pView, more); sqlite3TreeViewLine(pView, "WINFUNC %s(%d)", - pWin->pFunc->zName, pWin->pFunc->nArg); + pWin->pWFunc->zName, pWin->pWFunc->nArg); sqlite3TreeViewWindow(pView, pWin, 0); - sqlite3TreeViewPop(pView); + sqlite3TreeViewPop(&pView); } #endif /* SQLITE_OMIT_WINDOWFUNC */ @@ -30648,10 +31511,10 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m const char *zBinOp = 0; /* Binary operator */ const char *zUniOp = 0; /* Unary operator */ char zFlgs[200]; - pView = sqlite3TreeViewPush(pView, moreToFollow); + sqlite3TreeViewPush(&pView, moreToFollow); if( pExpr==0 ){ sqlite3TreeViewLine(pView, "nil"); - sqlite3TreeViewPop(pView); + sqlite3TreeViewPop(&pView); return; } if( pExpr->flags || pExpr->affExpr || pExpr->vvaFlags ){ @@ -30659,8 +31522,11 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m sqlite3StrAccumInit(&x, 0, zFlgs, sizeof(zFlgs), 0); sqlite3_str_appendf(&x, " fg.af=%x.%c", pExpr->flags, pExpr->affExpr ? pExpr->affExpr : 'n'); - if( ExprHasProperty(pExpr, EP_FromJoin) ){ - sqlite3_str_appendf(&x, " iRJT=%d", pExpr->iRightJoinTable); + if( ExprHasProperty(pExpr, EP_OuterON) ){ + sqlite3_str_appendf(&x, " outer.iJoin=%d", pExpr->w.iJoin); + } + if( ExprHasProperty(pExpr, EP_InnerON) ){ + sqlite3_str_appendf(&x, " inner.iJoin=%d", pExpr->w.iJoin); } if( ExprHasProperty(pExpr, EP_FromDDL) ){ sqlite3_str_appendf(&x, " DDL"); @@ -30884,7 +31750,17 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m break; } case TK_IN: { - sqlite3TreeViewLine(pView, "IN flags=0x%x", pExpr->flags); + sqlite3_str *pStr = sqlite3_str_new(0); + char *z; + sqlite3_str_appendf(pStr, "IN flags=0x%x", pExpr->flags); + if( pExpr->iTable ) sqlite3_str_appendf(pStr, " iTable=%d",pExpr->iTable); + if( ExprHasProperty(pExpr, EP_Subrtn) ){ + sqlite3_str_appendf(pStr, " subrtn(%d,%d)", + pExpr->y.sub.regReturn, pExpr->y.sub.iAddr); + } + z = sqlite3_str_finish(pStr); + sqlite3TreeViewLine(pView, z); + sqlite3_free(z); sqlite3TreeViewExpr(pView, pExpr->pLeft, 1); if( ExprUseXSelect(pExpr) ){ sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0); @@ -31008,7 +31884,7 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m sqlite3TreeViewLine(pView, "%s%s", zUniOp, zFlgs); sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); } - sqlite3TreeViewPop(pView); + sqlite3TreeViewPop(&pView); } @@ -31030,13 +31906,25 @@ SQLITE_PRIVATE void sqlite3TreeViewBareExprList( int j = pList->a[i].u.x.iOrderByCol; char *zName = pList->a[i].zEName; int moreToFollow = inExpr - 1; - if( pList->a[i].eEName!=ENAME_NAME ) zName = 0; if( j || zName ){ - sqlite3TreeViewPush(pView, moreToFollow); + sqlite3TreeViewPush(&pView, moreToFollow); moreToFollow = 0; sqlite3TreeViewLine(pView, 0); if( zName ){ - fprintf(stdout, "AS %s ", zName); + switch( pList->a[i].fg.eEName ){ + default: + fprintf(stdout, "AS %s ", zName); + break; + case ENAME_TAB: + fprintf(stdout, "TABLE-ALIAS-NAME(\"%s\") ", zName); + if( pList->a[i].fg.bUsed ) fprintf(stdout, "(used) "); + if( pList->a[i].fg.bUsingTerm ) fprintf(stdout, "(USING-term) "); + if( pList->a[i].fg.bNoExpand ) fprintf(stdout, "(NoExpand) "); + break; + case ENAME_SPAN: + fprintf(stdout, "SPAN(\"%s\") ", zName); + break; + } } if( j ){ fprintf(stdout, "iOrderByCol=%d", j); @@ -31046,7 +31934,7 @@ SQLITE_PRIVATE void sqlite3TreeViewBareExprList( } sqlite3TreeViewExpr(pView, pList->a[i].pExpr, moreToFollow); if( j || zName ){ - sqlite3TreeViewPop(pView); + sqlite3TreeViewPop(&pView); } } } @@ -31057,10 +31945,377 @@ SQLITE_PRIVATE void sqlite3TreeViewExprList( u8 moreToFollow, const char *zLabel ){ - pView = sqlite3TreeViewPush(pView, moreToFollow); + sqlite3TreeViewPush(&pView, moreToFollow); sqlite3TreeViewBareExprList(pView, pList, zLabel); - sqlite3TreeViewPop(pView); + sqlite3TreeViewPop(&pView); +} + +/* +** Generate a human-readable explanation of an id-list. +*/ +SQLITE_PRIVATE void sqlite3TreeViewBareIdList( + TreeView *pView, + const IdList *pList, + const char *zLabel +){ + if( zLabel==0 || zLabel[0]==0 ) zLabel = "LIST"; + if( pList==0 ){ + sqlite3TreeViewLine(pView, "%s (empty)", zLabel); + }else{ + int i; + sqlite3TreeViewLine(pView, "%s", zLabel); + for(i=0; inId; i++){ + char *zName = pList->a[i].zName; + int moreToFollow = inId - 1; + if( zName==0 ) zName = "(null)"; + sqlite3TreeViewPush(&pView, moreToFollow); + sqlite3TreeViewLine(pView, 0); + if( pList->eU4==EU4_NONE ){ + fprintf(stdout, "%s\n", zName); + }else if( pList->eU4==EU4_IDX ){ + fprintf(stdout, "%s (%d)\n", zName, pList->a[i].u4.idx); + }else{ + assert( pList->eU4==EU4_EXPR ); + if( pList->a[i].u4.pExpr==0 ){ + fprintf(stdout, "%s (pExpr=NULL)\n", zName); + }else{ + fprintf(stdout, "%s\n", zName); + sqlite3TreeViewPush(&pView, inId-1); + sqlite3TreeViewExpr(pView, pList->a[i].u4.pExpr, 0); + sqlite3TreeViewPop(&pView); + } + } + sqlite3TreeViewPop(&pView); + } + } +} +SQLITE_PRIVATE void sqlite3TreeViewIdList( + TreeView *pView, + const IdList *pList, + u8 moreToFollow, + const char *zLabel +){ + sqlite3TreeViewPush(&pView, moreToFollow); + sqlite3TreeViewBareIdList(pView, pList, zLabel); + sqlite3TreeViewPop(&pView); +} + +/* +** Generate a human-readable explanation of a list of Upsert objects +*/ +SQLITE_PRIVATE void sqlite3TreeViewUpsert( + TreeView *pView, + const Upsert *pUpsert, + u8 moreToFollow +){ + if( pUpsert==0 ) return; + sqlite3TreeViewPush(&pView, moreToFollow); + while( pUpsert ){ + int n; + sqlite3TreeViewPush(&pView, pUpsert->pNextUpsert!=0 || moreToFollow); + sqlite3TreeViewLine(pView, "ON CONFLICT DO %s", + pUpsert->isDoUpdate ? "UPDATE" : "NOTHING"); + n = (pUpsert->pUpsertSet!=0) + (pUpsert->pUpsertWhere!=0); + sqlite3TreeViewExprList(pView, pUpsert->pUpsertTarget, (n--)>0, "TARGET"); + sqlite3TreeViewExprList(pView, pUpsert->pUpsertSet, (n--)>0, "SET"); + if( pUpsert->pUpsertWhere ){ + sqlite3TreeViewItem(pView, "WHERE", (n--)>0); + sqlite3TreeViewExpr(pView, pUpsert->pUpsertWhere, 0); + sqlite3TreeViewPop(&pView); + } + sqlite3TreeViewPop(&pView); + pUpsert = pUpsert->pNextUpsert; + } + sqlite3TreeViewPop(&pView); +} + +#if TREETRACE_ENABLED +/* +** Generate a human-readable diagram of the data structure that go +** into generating an DELETE statement. +*/ +SQLITE_PRIVATE void sqlite3TreeViewDelete( + const With *pWith, + const SrcList *pTabList, + const Expr *pWhere, + const ExprList *pOrderBy, + const Expr *pLimit, + const Trigger *pTrigger +){ + int n = 0; + TreeView *pView = 0; + sqlite3TreeViewPush(&pView, 0); + sqlite3TreeViewLine(pView, "DELETE"); + if( pWith ) n++; + if( pTabList ) n++; + if( pWhere ) n++; + if( pOrderBy ) n++; + if( pLimit ) n++; + if( pTrigger ) n++; + if( pWith ){ + sqlite3TreeViewPush(&pView, (--n)>0); + sqlite3TreeViewWith(pView, pWith, 0); + sqlite3TreeViewPop(&pView); + } + if( pTabList ){ + sqlite3TreeViewPush(&pView, (--n)>0); + sqlite3TreeViewLine(pView, "FROM"); + sqlite3TreeViewSrcList(pView, pTabList); + sqlite3TreeViewPop(&pView); + } + if( pWhere ){ + sqlite3TreeViewPush(&pView, (--n)>0); + sqlite3TreeViewLine(pView, "WHERE"); + sqlite3TreeViewExpr(pView, pWhere, 0); + sqlite3TreeViewPop(&pView); + } + if( pOrderBy ){ + sqlite3TreeViewExprList(pView, pOrderBy, (--n)>0, "ORDER-BY"); + } + if( pLimit ){ + sqlite3TreeViewPush(&pView, (--n)>0); + sqlite3TreeViewLine(pView, "LIMIT"); + sqlite3TreeViewExpr(pView, pLimit, 0); + sqlite3TreeViewPop(&pView); + } + if( pTrigger ){ + sqlite3TreeViewTrigger(pView, pTrigger, (--n)>0, 1); + } + sqlite3TreeViewPop(&pView); +} +#endif /* TREETRACE_ENABLED */ + +#if TREETRACE_ENABLED +/* +** Generate a human-readable diagram of the data structure that go +** into generating an INSERT statement. +*/ +SQLITE_PRIVATE void sqlite3TreeViewInsert( + const With *pWith, + const SrcList *pTabList, + const IdList *pColumnList, + const Select *pSelect, + const ExprList *pExprList, + int onError, + const Upsert *pUpsert, + const Trigger *pTrigger +){ + TreeView *pView = 0; + int n = 0; + const char *zLabel = "INSERT"; + switch( onError ){ + case OE_Replace: zLabel = "REPLACE"; break; + case OE_Ignore: zLabel = "INSERT OR IGNORE"; break; + case OE_Rollback: zLabel = "INSERT OR ROLLBACK"; break; + case OE_Abort: zLabel = "INSERT OR ABORT"; break; + case OE_Fail: zLabel = "INSERT OR FAIL"; break; + } + sqlite3TreeViewPush(&pView, 0); + sqlite3TreeViewLine(pView, zLabel); + if( pWith ) n++; + if( pTabList ) n++; + if( pColumnList ) n++; + if( pSelect ) n++; + if( pExprList ) n++; + if( pUpsert ) n++; + if( pTrigger ) n++; + if( pWith ){ + sqlite3TreeViewPush(&pView, (--n)>0); + sqlite3TreeViewWith(pView, pWith, 0); + sqlite3TreeViewPop(&pView); + } + if( pTabList ){ + sqlite3TreeViewPush(&pView, (--n)>0); + sqlite3TreeViewLine(pView, "INTO"); + sqlite3TreeViewSrcList(pView, pTabList); + sqlite3TreeViewPop(&pView); + } + if( pColumnList ){ + sqlite3TreeViewIdList(pView, pColumnList, (--n)>0, "COLUMNS"); + } + if( pSelect ){ + sqlite3TreeViewPush(&pView, (--n)>0); + sqlite3TreeViewLine(pView, "DATA-SOURCE"); + sqlite3TreeViewSelect(pView, pSelect, 0); + sqlite3TreeViewPop(&pView); + } + if( pExprList ){ + sqlite3TreeViewExprList(pView, pExprList, (--n)>0, "VALUES"); + } + if( pUpsert ){ + sqlite3TreeViewPush(&pView, (--n)>0); + sqlite3TreeViewLine(pView, "UPSERT"); + sqlite3TreeViewUpsert(pView, pUpsert, 0); + sqlite3TreeViewPop(&pView); + } + if( pTrigger ){ + sqlite3TreeViewTrigger(pView, pTrigger, (--n)>0, 1); + } + sqlite3TreeViewPop(&pView); } +#endif /* TREETRACE_ENABLED */ + +#if TREETRACE_ENABLED +/* +** Generate a human-readable diagram of the data structure that go +** into generating an UPDATE statement. +*/ +SQLITE_PRIVATE void sqlite3TreeViewUpdate( + const With *pWith, + const SrcList *pTabList, + const ExprList *pChanges, + const Expr *pWhere, + int onError, + const ExprList *pOrderBy, + const Expr *pLimit, + const Upsert *pUpsert, + const Trigger *pTrigger +){ + int n = 0; + TreeView *pView = 0; + const char *zLabel = "UPDATE"; + switch( onError ){ + case OE_Replace: zLabel = "UPDATE OR REPLACE"; break; + case OE_Ignore: zLabel = "UPDATE OR IGNORE"; break; + case OE_Rollback: zLabel = "UPDATE OR ROLLBACK"; break; + case OE_Abort: zLabel = "UPDATE OR ABORT"; break; + case OE_Fail: zLabel = "UPDATE OR FAIL"; break; + } + sqlite3TreeViewPush(&pView, 0); + sqlite3TreeViewLine(pView, zLabel); + if( pWith ) n++; + if( pTabList ) n++; + if( pChanges ) n++; + if( pWhere ) n++; + if( pOrderBy ) n++; + if( pLimit ) n++; + if( pUpsert ) n++; + if( pTrigger ) n++; + if( pWith ){ + sqlite3TreeViewPush(&pView, (--n)>0); + sqlite3TreeViewWith(pView, pWith, 0); + sqlite3TreeViewPop(&pView); + } + if( pTabList ){ + sqlite3TreeViewPush(&pView, (--n)>0); + sqlite3TreeViewLine(pView, "FROM"); + sqlite3TreeViewSrcList(pView, pTabList); + sqlite3TreeViewPop(&pView); + } + if( pChanges ){ + sqlite3TreeViewExprList(pView, pChanges, (--n)>0, "SET"); + } + if( pWhere ){ + sqlite3TreeViewPush(&pView, (--n)>0); + sqlite3TreeViewLine(pView, "WHERE"); + sqlite3TreeViewExpr(pView, pWhere, 0); + sqlite3TreeViewPop(&pView); + } + if( pOrderBy ){ + sqlite3TreeViewExprList(pView, pOrderBy, (--n)>0, "ORDER-BY"); + } + if( pLimit ){ + sqlite3TreeViewPush(&pView, (--n)>0); + sqlite3TreeViewLine(pView, "LIMIT"); + sqlite3TreeViewExpr(pView, pLimit, 0); + sqlite3TreeViewPop(&pView); + } + if( pUpsert ){ + sqlite3TreeViewPush(&pView, (--n)>0); + sqlite3TreeViewLine(pView, "UPSERT"); + sqlite3TreeViewUpsert(pView, pUpsert, 0); + sqlite3TreeViewPop(&pView); + } + if( pTrigger ){ + sqlite3TreeViewTrigger(pView, pTrigger, (--n)>0, 1); + } + sqlite3TreeViewPop(&pView); +} +#endif /* TREETRACE_ENABLED */ + +#ifndef SQLITE_OMIT_TRIGGER +/* +** Show a human-readable graph of a TriggerStep +*/ +SQLITE_PRIVATE void sqlite3TreeViewTriggerStep( + TreeView *pView, + const TriggerStep *pStep, + u8 moreToFollow, + u8 showFullList +){ + int cnt = 0; + if( pStep==0 ) return; + sqlite3TreeViewPush(&pView, + moreToFollow || (showFullList && pStep->pNext!=0)); + do{ + if( cnt++ && pStep->pNext==0 ){ + sqlite3TreeViewPop(&pView); + sqlite3TreeViewPush(&pView, 0); + } + sqlite3TreeViewLine(pView, "%s", pStep->zSpan ? pStep->zSpan : "RETURNING"); + }while( showFullList && (pStep = pStep->pNext)!=0 ); + sqlite3TreeViewPop(&pView); +} + +/* +** Show a human-readable graph of a Trigger +*/ +SQLITE_PRIVATE void sqlite3TreeViewTrigger( + TreeView *pView, + const Trigger *pTrigger, + u8 moreToFollow, + u8 showFullList +){ + int cnt = 0; + if( pTrigger==0 ) return; + sqlite3TreeViewPush(&pView, + moreToFollow || (showFullList && pTrigger->pNext!=0)); + do{ + if( cnt++ && pTrigger->pNext==0 ){ + sqlite3TreeViewPop(&pView); + sqlite3TreeViewPush(&pView, 0); + } + sqlite3TreeViewLine(pView, "TRIGGER %s", pTrigger->zName); + sqlite3TreeViewPush(&pView, 0); + sqlite3TreeViewTriggerStep(pView, pTrigger->step_list, 0, 1); + sqlite3TreeViewPop(&pView); + }while( showFullList && (pTrigger = pTrigger->pNext)!=0 ); + sqlite3TreeViewPop(&pView); +} +#endif /* SQLITE_OMIT_TRIGGER */ + + +/* +** These simplified versions of the tree-view routines omit unnecessary +** parameters. These variants are intended to be used from a symbolic +** debugger, such as "gdb", during interactive debugging sessions. +** +** This routines are given external linkage so that they will always be +** accessible to the debugging, and to avoid warnings about unused +** functions. But these routines only exist in debugging builds, so they +** do not contaminate the interface. +*/ +SQLITE_PRIVATE void sqlite3ShowExpr(const Expr *p){ sqlite3TreeViewExpr(0,p,0); } +SQLITE_PRIVATE void sqlite3ShowExprList(const ExprList *p){ sqlite3TreeViewExprList(0,p,0,0);} +SQLITE_PRIVATE void sqlite3ShowIdList(const IdList *p){ sqlite3TreeViewIdList(0,p,0,0); } +SQLITE_PRIVATE void sqlite3ShowSrcList(const SrcList *p){ sqlite3TreeViewSrcList(0,p); } +SQLITE_PRIVATE void sqlite3ShowSelect(const Select *p){ sqlite3TreeViewSelect(0,p,0); } +SQLITE_PRIVATE void sqlite3ShowWith(const With *p){ sqlite3TreeViewWith(0,p,0); } +SQLITE_PRIVATE void sqlite3ShowUpsert(const Upsert *p){ sqlite3TreeViewUpsert(0,p,0); } +#ifndef SQLITE_OMIT_TRIGGER +SQLITE_PRIVATE void sqlite3ShowTriggerStep(const TriggerStep *p){ + sqlite3TreeViewTriggerStep(0,p,0,0); +} +SQLITE_PRIVATE void sqlite3ShowTriggerStepList(const TriggerStep *p){ + sqlite3TreeViewTriggerStep(0,p,0,1); +} +SQLITE_PRIVATE void sqlite3ShowTrigger(const Trigger *p){ sqlite3TreeViewTrigger(0,p,0,0); } +SQLITE_PRIVATE void sqlite3ShowTriggerList(const Trigger *p){ sqlite3TreeViewTrigger(0,p,0,1);} +#endif +#ifndef SQLITE_OMIT_WINDOWFUNC +SQLITE_PRIVATE void sqlite3ShowWindow(const Window *p){ sqlite3TreeViewWindow(0,p,0); } +SQLITE_PRIVATE void sqlite3ShowWinFunc(const Window *p){ sqlite3TreeViewWinFunc(0,p,0); } +#endif #endif /* SQLITE_DEBUG */ @@ -32142,7 +33397,11 @@ static SQLITE_NOINLINE void sqlite3ErrorFinish(sqlite3 *db, int err_code){ SQLITE_PRIVATE void sqlite3Error(sqlite3 *db, int err_code){ assert( db!=0 ); db->errCode = err_code; - if( err_code || db->pErr ) sqlite3ErrorFinish(db, err_code); + if( err_code || db->pErr ){ + sqlite3ErrorFinish(db, err_code); + }else{ + db->errByteOffset = -1; + } } /* @@ -32152,6 +33411,7 @@ SQLITE_PRIVATE void sqlite3Error(sqlite3 *db, int err_code){ SQLITE_PRIVATE void sqlite3ErrorClear(sqlite3 *db){ assert( db!=0 ); db->errCode = SQLITE_OK; + db->errByteOffset = -1; if( db->pErr ) sqlite3ValueSetNull(db->pErr); } @@ -32172,17 +33432,8 @@ SQLITE_PRIVATE void sqlite3SystemError(sqlite3 *db, int rc){ ** handle "db". The error code is set to "err_code". ** ** If it is not NULL, string zFormat specifies the format of the -** error string in the style of the printf functions: The following -** format characters are allowed: -** -** %s Insert a string -** %z A string that should be freed after use -** %d Insert an integer -** %T Insert a token -** %S Insert the first element of a SrcList -** -** zFormat and any string tokens that follow it are assumed to be -** encoded in UTF-8. +** error string. zFormat and any string tokens that follow it are +** assumed to be encoded in UTF-8. ** ** To clear the most recent error for sqlite handle "db", sqlite3Error ** should be called with err_code set to SQLITE_OK and zFormat set @@ -32206,13 +33457,6 @@ SQLITE_PRIVATE void sqlite3ErrorWithMsg(sqlite3 *db, int err_code, const char *z /* ** Add an error message to pParse->zErrMsg and increment pParse->nErr. -** The following formatting characters are allowed: -** -** %s Insert a string -** %z A string that should be freed after use -** %d Insert an integer -** %T Insert a token -** %S Insert the first element of a SrcList ** ** This function should be used to report any error that occurs while ** compiling an SQL statement (i.e. within sqlite3_prepare()). The @@ -32225,11 +33469,19 @@ SQLITE_PRIVATE void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){ char *zMsg; va_list ap; sqlite3 *db = pParse->db; + assert( db!=0 ); + assert( db->pParse==pParse || db->pParse->pToplevel==pParse ); + db->errByteOffset = -2; va_start(ap, zFormat); zMsg = sqlite3VMPrintf(db, zFormat, ap); va_end(ap); + if( db->errByteOffset<-1 ) db->errByteOffset = -1; if( db->suppressErr ){ sqlite3DbFree(db, zMsg); + if( db->mallocFailed ){ + pParse->nErr++; + pParse->rc = SQLITE_NOMEM; + } }else{ pParse->nErr++; sqlite3DbFree(db, pParse->zErrMsg); @@ -33611,7 +34863,6 @@ SQLITE_PRIVATE LogEst sqlite3LogEst(u64 x){ return a[x&7] + y - 10; } -#ifndef SQLITE_OMIT_VIRTUALTABLE /* ** Convert a double into a LogEst ** In other words, compute an approximation for 10*log2(x). @@ -33626,16 +34877,9 @@ SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double x){ e = (a>>52) - 1022; return e*10; } -#endif /* SQLITE_OMIT_VIRTUALTABLE */ -#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \ - defined(SQLITE_ENABLE_STAT4) || \ - defined(SQLITE_EXPLAIN_ESTIMATED_ROWS) /* ** Convert a LogEst into an integer. -** -** Note that this routine is only used when one or more of various -** non-standard compile-time options is enabled. */ SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst x){ u64 n; @@ -33643,17 +34887,9 @@ SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst x){ x /= 10; if( n>=5 ) n -= 2; else if( n>=1 ) n -= 1; -#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \ - defined(SQLITE_EXPLAIN_ESTIMATED_ROWS) if( x>60 ) return (u64)LARGEST_INT64; -#else - /* If only SQLITE_ENABLE_STAT4 is on, then the largest input - ** possible to this routine is 310, resulting in a maximum x of 31 */ - assert( x<=60 ); -#endif return x>=3 ? (n+8)<<(x-3) : (n+8)>>(3-x); } -#endif /* defined SCANSTAT or STAT4 or ESTIMATED_ROWS */ /* ** Add a new name/number pair to a VList. This might require that the @@ -34047,42 +35283,42 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ /* 0 */ "Savepoint" OpHelp(""), /* 1 */ "AutoCommit" OpHelp(""), /* 2 */ "Transaction" OpHelp(""), - /* 3 */ "SorterNext" OpHelp(""), - /* 4 */ "Prev" OpHelp(""), - /* 5 */ "Next" OpHelp(""), - /* 6 */ "Checkpoint" OpHelp(""), - /* 7 */ "JournalMode" OpHelp(""), - /* 8 */ "Vacuum" OpHelp(""), - /* 9 */ "VFilter" OpHelp("iplan=r[P3] zplan='P4'"), - /* 10 */ "VUpdate" OpHelp("data=r[P3@P2]"), - /* 11 */ "Goto" OpHelp(""), - /* 12 */ "Gosub" OpHelp(""), - /* 13 */ "InitCoroutine" OpHelp(""), - /* 14 */ "Yield" OpHelp(""), - /* 15 */ "MustBeInt" OpHelp(""), - /* 16 */ "Jump" OpHelp(""), - /* 17 */ "Once" OpHelp(""), - /* 18 */ "If" OpHelp(""), + /* 3 */ "Checkpoint" OpHelp(""), + /* 4 */ "JournalMode" OpHelp(""), + /* 5 */ "Vacuum" OpHelp(""), + /* 6 */ "VFilter" OpHelp("iplan=r[P3] zplan='P4'"), + /* 7 */ "VUpdate" OpHelp("data=r[P3@P2]"), + /* 8 */ "Goto" OpHelp(""), + /* 9 */ "Gosub" OpHelp(""), + /* 10 */ "InitCoroutine" OpHelp(""), + /* 11 */ "Yield" OpHelp(""), + /* 12 */ "MustBeInt" OpHelp(""), + /* 13 */ "Jump" OpHelp(""), + /* 14 */ "Once" OpHelp(""), + /* 15 */ "If" OpHelp(""), + /* 16 */ "IfNot" OpHelp(""), + /* 17 */ "IsNullOrType" OpHelp("if typeof(r[P1]) IN (P3,5) goto P2"), + /* 18 */ "IfNullRow" OpHelp("if P1.nullRow then r[P3]=NULL, goto P2"), /* 19 */ "Not" OpHelp("r[P2]= !r[P1]"), - /* 20 */ "IfNot" OpHelp(""), - /* 21 */ "IsNullOrType" OpHelp("if typeof(r[P1]) IN (P3,5) goto P2"), - /* 22 */ "IfNullRow" OpHelp("if P1.nullRow then r[P3]=NULL, goto P2"), - /* 23 */ "SeekLT" OpHelp("key=r[P3@P4]"), - /* 24 */ "SeekLE" OpHelp("key=r[P3@P4]"), - /* 25 */ "SeekGE" OpHelp("key=r[P3@P4]"), - /* 26 */ "SeekGT" OpHelp("key=r[P3@P4]"), - /* 27 */ "IfNotOpen" OpHelp("if( !csr[P1] ) goto P2"), - /* 28 */ "IfNoHope" OpHelp("key=r[P3@P4]"), - /* 29 */ "NoConflict" OpHelp("key=r[P3@P4]"), - /* 30 */ "NotFound" OpHelp("key=r[P3@P4]"), - /* 31 */ "Found" OpHelp("key=r[P3@P4]"), - /* 32 */ "SeekRowid" OpHelp("intkey=r[P3]"), - /* 33 */ "NotExists" OpHelp("intkey=r[P3]"), - /* 34 */ "Last" OpHelp(""), - /* 35 */ "IfSmaller" OpHelp(""), - /* 36 */ "SorterSort" OpHelp(""), - /* 37 */ "Sort" OpHelp(""), - /* 38 */ "Rewind" OpHelp(""), + /* 20 */ "SeekLT" OpHelp("key=r[P3@P4]"), + /* 21 */ "SeekLE" OpHelp("key=r[P3@P4]"), + /* 22 */ "SeekGE" OpHelp("key=r[P3@P4]"), + /* 23 */ "SeekGT" OpHelp("key=r[P3@P4]"), + /* 24 */ "IfNotOpen" OpHelp("if( !csr[P1] ) goto P2"), + /* 25 */ "IfNoHope" OpHelp("key=r[P3@P4]"), + /* 26 */ "NoConflict" OpHelp("key=r[P3@P4]"), + /* 27 */ "NotFound" OpHelp("key=r[P3@P4]"), + /* 28 */ "Found" OpHelp("key=r[P3@P4]"), + /* 29 */ "SeekRowid" OpHelp("intkey=r[P3]"), + /* 30 */ "NotExists" OpHelp("intkey=r[P3]"), + /* 31 */ "Last" OpHelp(""), + /* 32 */ "IfSmaller" OpHelp(""), + /* 33 */ "SorterSort" OpHelp(""), + /* 34 */ "Sort" OpHelp(""), + /* 35 */ "Rewind" OpHelp(""), + /* 36 */ "SorterNext" OpHelp(""), + /* 37 */ "Prev" OpHelp(""), + /* 38 */ "Next" OpHelp(""), /* 39 */ "IdxLE" OpHelp("key=r[P3@P4]"), /* 40 */ "IdxGT" OpHelp("key=r[P3@P4]"), /* 41 */ "IdxLT" OpHelp("key=r[P3@P4]"), @@ -34107,45 +35343,45 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ /* 60 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"), /* 61 */ "IncrVacuum" OpHelp(""), /* 62 */ "VNext" OpHelp(""), - /* 63 */ "Init" OpHelp("Start at P2"), - /* 64 */ "PureFunc" OpHelp("r[P3]=func(r[P2@NP])"), - /* 65 */ "Function" OpHelp("r[P3]=func(r[P2@NP])"), - /* 66 */ "Return" OpHelp(""), - /* 67 */ "EndCoroutine" OpHelp(""), - /* 68 */ "HaltIfNull" OpHelp("if r[P3]=null halt"), - /* 69 */ "Halt" OpHelp(""), - /* 70 */ "Integer" OpHelp("r[P2]=P1"), - /* 71 */ "Int64" OpHelp("r[P2]=P4"), - /* 72 */ "String" OpHelp("r[P2]='P4' (len=P1)"), - /* 73 */ "Null" OpHelp("r[P2..P3]=NULL"), - /* 74 */ "SoftNull" OpHelp("r[P1]=NULL"), - /* 75 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"), - /* 76 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"), - /* 77 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"), - /* 78 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"), - /* 79 */ "SCopy" OpHelp("r[P2]=r[P1]"), - /* 80 */ "IntCopy" OpHelp("r[P2]=r[P1]"), - /* 81 */ "ChngCntRow" OpHelp("output=r[P1]"), - /* 82 */ "ResultRow" OpHelp("output=r[P1@P2]"), - /* 83 */ "CollSeq" OpHelp(""), - /* 84 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"), - /* 85 */ "RealAffinity" OpHelp(""), - /* 86 */ "Cast" OpHelp("affinity(r[P1])"), - /* 87 */ "Permutation" OpHelp(""), - /* 88 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"), - /* 89 */ "IsTrue" OpHelp("r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4"), - /* 90 */ "ZeroOrNull" OpHelp("r[P2] = 0 OR NULL"), - /* 91 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"), - /* 92 */ "Column" OpHelp("r[P3]=PX"), - /* 93 */ "TypeCheck" OpHelp("typecheck(r[P1@P2])"), - /* 94 */ "Affinity" OpHelp("affinity(r[P1@P2])"), - /* 95 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), - /* 96 */ "Count" OpHelp("r[P2]=count()"), - /* 97 */ "ReadCookie" OpHelp(""), - /* 98 */ "SetCookie" OpHelp(""), - /* 99 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), - /* 100 */ "OpenRead" OpHelp("root=P2 iDb=P3"), - /* 101 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), + /* 63 */ "Filter" OpHelp("if key(P3@P4) not in filter(P1) goto P2"), + /* 64 */ "Init" OpHelp("Start at P2"), + /* 65 */ "PureFunc" OpHelp("r[P3]=func(r[P2@NP])"), + /* 66 */ "Function" OpHelp("r[P3]=func(r[P2@NP])"), + /* 67 */ "Return" OpHelp(""), + /* 68 */ "EndCoroutine" OpHelp(""), + /* 69 */ "HaltIfNull" OpHelp("if r[P3]=null halt"), + /* 70 */ "Halt" OpHelp(""), + /* 71 */ "Integer" OpHelp("r[P2]=P1"), + /* 72 */ "Int64" OpHelp("r[P2]=P4"), + /* 73 */ "String" OpHelp("r[P2]='P4' (len=P1)"), + /* 74 */ "BeginSubrtn" OpHelp("r[P2]=NULL"), + /* 75 */ "Null" OpHelp("r[P2..P3]=NULL"), + /* 76 */ "SoftNull" OpHelp("r[P1]=NULL"), + /* 77 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"), + /* 78 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"), + /* 79 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"), + /* 80 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"), + /* 81 */ "SCopy" OpHelp("r[P2]=r[P1]"), + /* 82 */ "IntCopy" OpHelp("r[P2]=r[P1]"), + /* 83 */ "FkCheck" OpHelp(""), + /* 84 */ "ResultRow" OpHelp("output=r[P1@P2]"), + /* 85 */ "CollSeq" OpHelp(""), + /* 86 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"), + /* 87 */ "RealAffinity" OpHelp(""), + /* 88 */ "Cast" OpHelp("affinity(r[P1])"), + /* 89 */ "Permutation" OpHelp(""), + /* 90 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"), + /* 91 */ "IsTrue" OpHelp("r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4"), + /* 92 */ "ZeroOrNull" OpHelp("r[P2] = 0 OR NULL"), + /* 93 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"), + /* 94 */ "Column" OpHelp("r[P3]=PX cursor P1 column P2"), + /* 95 */ "TypeCheck" OpHelp("typecheck(r[P1@P2])"), + /* 96 */ "Affinity" OpHelp("affinity(r[P1@P2])"), + /* 97 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), + /* 98 */ "Count" OpHelp("r[P2]=count()"), + /* 99 */ "ReadCookie" OpHelp(""), + /* 100 */ "SetCookie" OpHelp(""), + /* 101 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), /* 102 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"), /* 103 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"), /* 104 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"), - /* 159 */ "AggInverse" OpHelp("accum=r[P3] inverse(r[P2@P5])"), - /* 160 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"), - /* 161 */ "AggStep1" OpHelp("accum=r[P3] step(r[P2@P5])"), - /* 162 */ "AggValue" OpHelp("r[P3]=value N=P2"), - /* 163 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), - /* 164 */ "Expire" OpHelp(""), - /* 165 */ "CursorLock" OpHelp(""), - /* 166 */ "CursorUnlock" OpHelp(""), - /* 167 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), - /* 168 */ "VBegin" OpHelp(""), - /* 169 */ "VCreate" OpHelp(""), - /* 170 */ "VDestroy" OpHelp(""), - /* 171 */ "VOpen" OpHelp(""), - /* 172 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), - /* 173 */ "VRename" OpHelp(""), - /* 174 */ "Pagecount" OpHelp(""), - /* 175 */ "MaxPgcnt" OpHelp(""), - /* 176 */ "Trace" OpHelp(""), - /* 177 */ "CursorHint" OpHelp(""), - /* 178 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"), - /* 179 */ "Noop" OpHelp(""), - /* 180 */ "Explain" OpHelp(""), - /* 181 */ "Abortable" OpHelp(""), + /* 112 */ "OpenRead" OpHelp("root=P2 iDb=P3"), + /* 113 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), + /* 114 */ "BitNot" OpHelp("r[P2]= ~r[P1]"), + /* 115 */ "OpenDup" OpHelp(""), + /* 116 */ "OpenAutoindex" OpHelp("nColumn=P2"), + /* 117 */ "String8" OpHelp("r[P2]='P4'"), + /* 118 */ "OpenEphemeral" OpHelp("nColumn=P2"), + /* 119 */ "SorterOpen" OpHelp(""), + /* 120 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"), + /* 121 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), + /* 122 */ "Close" OpHelp(""), + /* 123 */ "ColumnsUsed" OpHelp(""), + /* 124 */ "SeekScan" OpHelp("Scan-ahead up to P1 rows"), + /* 125 */ "SeekHit" OpHelp("set P2<=seekHit<=P3"), + /* 126 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), + /* 127 */ "NewRowid" OpHelp("r[P2]=rowid"), + /* 128 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), + /* 129 */ "RowCell" OpHelp(""), + /* 130 */ "Delete" OpHelp(""), + /* 131 */ "ResetCount" OpHelp(""), + /* 132 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"), + /* 133 */ "SorterData" OpHelp("r[P2]=data"), + /* 134 */ "RowData" OpHelp("r[P2]=data"), + /* 135 */ "Rowid" OpHelp("r[P2]=PX rowid of P1"), + /* 136 */ "NullRow" OpHelp(""), + /* 137 */ "SeekEnd" OpHelp(""), + /* 138 */ "IdxInsert" OpHelp("key=r[P2]"), + /* 139 */ "SorterInsert" OpHelp("key=r[P2]"), + /* 140 */ "IdxDelete" OpHelp("key=r[P2@P3]"), + /* 141 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"), + /* 142 */ "IdxRowid" OpHelp("r[P2]=rowid"), + /* 143 */ "FinishSeek" OpHelp(""), + /* 144 */ "Destroy" OpHelp(""), + /* 145 */ "Clear" OpHelp(""), + /* 146 */ "ResetSorter" OpHelp(""), + /* 147 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"), + /* 148 */ "SqlExec" OpHelp(""), + /* 149 */ "ParseSchema" OpHelp(""), + /* 150 */ "LoadAnalysis" OpHelp(""), + /* 151 */ "DropTable" OpHelp(""), + /* 152 */ "DropIndex" OpHelp(""), + /* 153 */ "Real" OpHelp("r[P2]=P4"), + /* 154 */ "DropTrigger" OpHelp(""), + /* 155 */ "IntegrityCk" OpHelp(""), + /* 156 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), + /* 157 */ "Param" OpHelp(""), + /* 158 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), + /* 159 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), + /* 160 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"), + /* 161 */ "AggInverse" OpHelp("accum=r[P3] inverse(r[P2@P5])"), + /* 162 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"), + /* 163 */ "AggStep1" OpHelp("accum=r[P3] step(r[P2@P5])"), + /* 164 */ "AggValue" OpHelp("r[P3]=value N=P2"), + /* 165 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), + /* 166 */ "Expire" OpHelp(""), + /* 167 */ "CursorLock" OpHelp(""), + /* 168 */ "CursorUnlock" OpHelp(""), + /* 169 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), + /* 170 */ "VBegin" OpHelp(""), + /* 171 */ "VCreate" OpHelp(""), + /* 172 */ "VDestroy" OpHelp(""), + /* 173 */ "VOpen" OpHelp(""), + /* 174 */ "VInitIn" OpHelp("r[P2]=ValueList(P1,P3)"), + /* 175 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), + /* 176 */ "VRename" OpHelp(""), + /* 177 */ "Pagecount" OpHelp(""), + /* 178 */ "MaxPgcnt" OpHelp(""), + /* 179 */ "ClrSubtype" OpHelp("r[P1].subtype = 0"), + /* 180 */ "FilterAdd" OpHelp("filter(P1) += key(P3@P4)"), + /* 181 */ "Trace" OpHelp(""), + /* 182 */ "CursorHint" OpHelp(""), + /* 183 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"), + /* 184 */ "Noop" OpHelp(""), + /* 185 */ "Explain" OpHelp(""), + /* 186 */ "Abortable" OpHelp(""), }; return azName[i]; } @@ -39145,11 +40386,17 @@ static int unixShmLock( int flags /* What to do with the lock */ ){ unixFile *pDbFd = (unixFile*)fd; /* Connection holding shared memory */ - unixShm *p = pDbFd->pShm; /* The shared memory being locked */ - unixShmNode *pShmNode = p->pShmNode; /* The underlying file iNode */ + unixShm *p; /* The shared memory being locked */ + unixShmNode *pShmNode; /* The underlying file iNode */ int rc = SQLITE_OK; /* Result code */ u16 mask; /* Mask of locks to take or release */ - int *aLock = pShmNode->aLock; + int *aLock; + + p = pDbFd->pShm; + if( p==0 ) return SQLITE_IOERR_SHMLOCK; + pShmNode = p->pShmNode; + if( NEVER(pShmNode==0) ) return SQLITE_IOERR_SHMLOCK; + aLock = pShmNode->aLock; assert( pShmNode==pDbFd->pInode->pShmNode ); assert( pShmNode->pInode==pDbFd->pInode ); @@ -40084,6 +41331,7 @@ static const char *unixTempFileDir(void){ static int unixGetTempname(int nBuf, char *zBuf){ const char *zDir; int iLimit = 0; + int rc = SQLITE_OK; /* It's odd to simulate an io-error here, but really this is just ** using the io-error infrastructure to test that SQLite handles this @@ -40092,18 +41340,26 @@ static int unixGetTempname(int nBuf, char *zBuf){ zBuf[0] = 0; SimulateIOError( return SQLITE_IOERR ); + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); zDir = unixTempFileDir(); - if( zDir==0 ) return SQLITE_IOERR_GETTEMPPATH; - do{ - u64 r; - sqlite3_randomness(sizeof(r), &r); - assert( nBuf>2 ); - zBuf[nBuf-2] = 0; - sqlite3_snprintf(nBuf, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX"%llx%c", - zDir, r, 0); - if( zBuf[nBuf-2]!=0 || (iLimit++)>10 ) return SQLITE_ERROR; - }while( osAccess(zBuf,0)==0 ); - return SQLITE_OK; + if( zDir==0 ){ + rc = SQLITE_IOERR_GETTEMPPATH; + }else{ + do{ + u64 r; + sqlite3_randomness(sizeof(r), &r); + assert( nBuf>2 ); + zBuf[nBuf-2] = 0; + sqlite3_snprintf(nBuf, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX"%llx%c", + zDir, r, 0); + if( zBuf[nBuf-2]!=0 || (iLimit++)>10 ){ + rc = SQLITE_ERROR; + break; + } + }while( osAccess(zBuf,0)==0 ); + } + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); + return rc; } #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) @@ -40246,20 +41502,23 @@ static int findCreateFileMode( ** ** where NN is a decimal number. The NN naming schemes are ** used by the test_multiplex.c module. + ** + ** In normal operation, the journal file name will always contain + ** a '-' character. However in 8+3 filename mode, or if a corrupt + ** rollback journal specifies a super-journal with a goofy name, then + ** the '-' might be missing or the '-' might be the first character in + ** the filename. In that case, just return SQLITE_OK with *pMode==0. */ nDb = sqlite3Strlen30(zPath) - 1; - while( zPath[nDb]!='-' ){ - /* In normal operation, the journal file name will always contain - ** a '-' character. However in 8+3 filename mode, or if a corrupt - ** rollback journal specifies a super-journal with a goofy name, then - ** the '-' might be missing. */ - if( nDb==0 || zPath[nDb]=='.' ) return SQLITE_OK; + while( nDb>0 && zPath[nDb]!='.' ){ + if( zPath[nDb]=='-' ){ + memcpy(zDb, zPath, nDb); + zDb[nDb] = '\0'; + rc = getFileMode(zDb, pMode, pUid, pGid); + break; + } nDb--; } - memcpy(zDb, zPath, nDb); - zDb[nDb] = '\0'; - - rc = getFileMode(zDb, pMode, pUid, pGid); }else if( flags & SQLITE_OPEN_DELETEONCLOSE ){ *pMode = 0600; }else if( flags & SQLITE_OPEN_URI ){ @@ -40649,86 +41908,99 @@ static int unixAccess( } /* -** If the last component of the pathname in z[0]..z[j-1] is something -** other than ".." then back it out and return true. If the last -** component is empty or if it is ".." then return false. +** A pathname under construction */ -static int unixBackupDir(const char *z, int *pJ){ - int j = *pJ; - int i; - if( j<=0 ) return 0; - for(i=j-1; i>0 && z[i-1]!='/'; i--){} - if( i==0 ) return 0; - if( z[i]=='.' && i==j-2 && z[i+1]=='.' ) return 0; - *pJ = i-1; - return 1; -} +typedef struct DbPath DbPath; +struct DbPath { + int rc; /* Non-zero following any error */ + int nSymlink; /* Number of symlinks resolved */ + char *zOut; /* Write the pathname here */ + int nOut; /* Bytes of space available to zOut[] */ + int nUsed; /* Bytes of zOut[] currently being used */ +}; + +/* Forward reference */ +static void appendAllPathElements(DbPath*,const char*); /* -** Convert a relative pathname into a full pathname. Also -** simplify the pathname as follows: -** -** Remove all instances of /./ -** Remove all isntances of /X/../ for any X +** Append a single path element to the DbPath under construction */ -static int mkFullPathname( - const char *zPath, /* Input path */ - char *zOut, /* Output buffer */ - int nOut /* Allocated size of buffer zOut */ +static void appendOnePathElement( + DbPath *pPath, /* Path under construction, to which to append zName */ + const char *zName, /* Name to append to pPath. Not zero-terminated */ + int nName /* Number of significant bytes in zName */ ){ - int nPath = sqlite3Strlen30(zPath); - int iOff = 0; - int i, j; - if( zPath[0]!='/' ){ - if( osGetcwd(zOut, nOut-2)==0 ){ - return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath); + assert( nName>0 ); + assert( zName!=0 ); + if( zName[0]=='.' ){ + if( nName==1 ) return; + if( zName[1]=='.' && nName==2 ){ + if( pPath->nUsed<=1 ){ + pPath->rc = SQLITE_ERROR; + return; + } + assert( pPath->zOut[0]=='/' ); + while( pPath->zOut[--pPath->nUsed]!='/' ){} + return; } - iOff = sqlite3Strlen30(zOut); - zOut[iOff++] = '/'; - } - if( (iOff+nPath+1)>nOut ){ - /* SQLite assumes that xFullPathname() nul-terminates the output buffer - ** even if it returns an error. */ - zOut[iOff] = '\0'; - return SQLITE_CANTOPEN_BKPT; } - sqlite3_snprintf(nOut-iOff, &zOut[iOff], "%s", zPath); - - /* Remove duplicate '/' characters. Except, two // at the beginning - ** of a pathname is allowed since this is important on windows. */ - for(i=j=1; zOut[i]; i++){ - zOut[j++] = zOut[i]; - while( zOut[i]=='/' && zOut[i+1]=='/' ) i++; + if( pPath->nUsed + nName + 2 >= pPath->nOut ){ + pPath->rc = SQLITE_ERROR; + return; } - zOut[j] = 0; - - assert( zOut[0]=='/' ); - for(i=j=0; zOut[i]; i++){ - if( zOut[i]=='/' ){ - /* Skip over internal "/." directory components */ - if( zOut[i+1]=='.' && zOut[i+2]=='/' ){ - i += 1; - continue; + pPath->zOut[pPath->nUsed++] = '/'; + memcpy(&pPath->zOut[pPath->nUsed], zName, nName); + pPath->nUsed += nName; +#if defined(HAVE_READLINK) && defined(HAVE_LSTAT) + if( pPath->rc==SQLITE_OK ){ + const char *zIn; + struct stat buf; + pPath->zOut[pPath->nUsed] = 0; + zIn = pPath->zOut; + if( osLstat(zIn, &buf)!=0 ){ + if( errno!=ENOENT ){ + pPath->rc = unixLogError(SQLITE_CANTOPEN_BKPT, "lstat", zIn); } - - /* If this is a "/.." directory component then back out the - ** previous term of the directory if it is something other than "..". - */ - if( zOut[i+1]=='.' - && zOut[i+2]=='.' - && zOut[i+3]=='/' - && unixBackupDir(zOut, &j) - ){ - i += 2; - continue; + }else if( S_ISLNK(buf.st_mode) ){ + ssize_t got; + char zLnk[SQLITE_MAX_PATHLEN+2]; + if( pPath->nSymlink++ > SQLITE_MAX_SYMLINK ){ + pPath->rc = SQLITE_CANTOPEN_BKPT; + return; + } + got = osReadlink(zIn, zLnk, sizeof(zLnk)-2); + if( got<=0 || got>=(ssize_t)sizeof(zLnk)-2 ){ + pPath->rc = unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zIn); + return; + } + zLnk[got] = 0; + if( zLnk[0]=='/' ){ + pPath->nUsed = 0; + }else{ + pPath->nUsed -= nName + 1; } + appendAllPathElements(pPath, zLnk); } - if( ALWAYS(j>=0) ) zOut[j] = zOut[i]; - j++; } - if( NEVER(j==0) ) zOut[j++] = '/'; - zOut[j] = 0; - return SQLITE_OK; +#endif +} + +/* +** Append all path elements in zPath to the DbPath under construction. +*/ +static void appendAllPathElements( + DbPath *pPath, /* Path under construction, to which to append zName */ + const char *zPath /* Path to append to pPath. Is zero-terminated */ +){ + int i = 0; + int j = 0; + do{ + while( zPath[i] && zPath[i]!='/' ){ i++; } + if( i>j ){ + appendOnePathElement(pPath, &zPath[j], i-j); + } + j = i+1; + }while( zPath[i++] ); } /* @@ -40746,86 +42018,27 @@ static int unixFullPathname( int nOut, /* Size of output buffer in bytes */ char *zOut /* Output buffer */ ){ -#if !defined(HAVE_READLINK) || !defined(HAVE_LSTAT) - return mkFullPathname(zPath, zOut, nOut); -#else - int rc = SQLITE_OK; - int nByte; - int nLink = 0; /* Number of symbolic links followed so far */ - const char *zIn = zPath; /* Input path for each iteration of loop */ - char *zDel = 0; - - assert( pVfs->mxPathname==MAX_PATHNAME ); + DbPath path; UNUSED_PARAMETER(pVfs); - - /* It's odd to simulate an io-error here, but really this is just - ** using the io-error infrastructure to test that SQLite handles this - ** function failing. This function could fail if, for example, the - ** current working directory has been unlinked. - */ - SimulateIOError( return SQLITE_ERROR ); - - do { - - /* Call stat() on path zIn. Set bLink to true if the path is a symbolic - ** link, or false otherwise. */ - int bLink = 0; - struct stat buf; - if( osLstat(zIn, &buf)!=0 ){ - if( errno!=ENOENT ){ - rc = unixLogError(SQLITE_CANTOPEN_BKPT, "lstat", zIn); - } - }else{ - bLink = S_ISLNK(buf.st_mode); - } - - if( bLink ){ - nLink++; - if( zDel==0 ){ - zDel = sqlite3_malloc(nOut); - if( zDel==0 ) rc = SQLITE_NOMEM_BKPT; - }else if( nLink>=SQLITE_MAX_SYMLINKS ){ - rc = SQLITE_CANTOPEN_BKPT; - } - - if( rc==SQLITE_OK ){ - nByte = osReadlink(zIn, zDel, nOut-1); - if( nByte<0 ){ - rc = unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zIn); - }else{ - if( zDel[0]!='/' ){ - int n; - for(n = sqlite3Strlen30(zIn); n>0 && zIn[n-1]!='/'; n--); - if( nByte+n+1>nOut ){ - rc = SQLITE_CANTOPEN_BKPT; - }else{ - memmove(&zDel[n], zDel, nByte+1); - memcpy(zDel, zIn, n); - nByte += n; - } - } - zDel[nByte] = '\0'; - } - } - - zIn = zDel; - } - - assert( rc!=SQLITE_OK || zIn!=zOut || zIn[0]=='/' ); - if( rc==SQLITE_OK && zIn!=zOut ){ - rc = mkFullPathname(zIn, zOut, nOut); + path.rc = 0; + path.nUsed = 0; + path.nSymlink = 0; + path.nOut = nOut; + path.zOut = zOut; + if( zPath[0]!='/' ){ + char zPwd[SQLITE_MAX_PATHLEN+2]; + if( osGetcwd(zPwd, sizeof(zPwd)-2)==0 ){ + return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath); } - if( bLink==0 ) break; - zIn = zOut; - }while( rc==SQLITE_OK ); - - sqlite3_free(zDel); - if( rc==SQLITE_OK && nLink ) rc = SQLITE_OK_SYMLINK; - return rc; -#endif /* HAVE_READLINK && HAVE_LSTAT */ + appendAllPathElements(&path, zPwd); + } + appendAllPathElements(&path, zPath); + zOut[path.nUsed] = 0; + if( path.rc || path.nUsed<2 ) return SQLITE_CANTOPEN_BKPT; + if( path.nSymlink ) return SQLITE_OK_SYMLINK; + return SQLITE_OK; } - #ifndef SQLITE_OMIT_LOAD_EXTENSION /* ** Interfaces for opening a shared library, finding entry points @@ -44285,10 +45498,12 @@ SQLITE_API int sqlite3_win32_set_directory8( const char *zValue /* New value for directory being set or reset */ ){ char **ppDirectory = 0; + int rc; #ifndef SQLITE_OMIT_AUTOINIT - int rc = sqlite3_initialize(); + rc = sqlite3_initialize(); if( rc ) return rc; #endif + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); if( type==SQLITE_WIN32_DATA_DIRECTORY_TYPE ){ ppDirectory = &sqlite3_data_directory; }else if( type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE ){ @@ -44303,14 +45518,19 @@ SQLITE_API int sqlite3_win32_set_directory8( if( zValue && zValue[0] ){ zCopy = sqlite3_mprintf("%s", zValue); if ( zCopy==0 ){ - return SQLITE_NOMEM_BKPT; + rc = SQLITE_NOMEM_BKPT; + goto set_directory8_done; } } sqlite3_free(*ppDirectory); *ppDirectory = zCopy; - return SQLITE_OK; + rc = SQLITE_OK; + }else{ + rc = SQLITE_ERROR; } - return SQLITE_ERROR; +set_directory8_done: + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); + return rc; } /* @@ -46437,10 +47657,14 @@ static int winShmLock( winFile *pDbFd = (winFile*)fd; /* Connection holding shared memory */ winShm *p = pDbFd->pShm; /* The shared memory being locked */ winShm *pX; /* For looping over all siblings */ - winShmNode *pShmNode = p->pShmNode; + winShmNode *pShmNode; int rc = SQLITE_OK; /* Result code */ u16 mask; /* Mask of locks to take or release */ + if( p==0 ) return SQLITE_IOERR_SHMLOCK; + pShmNode = p->pShmNode; + if( NEVER(pShmNode==0) ) return SQLITE_IOERR_SHMLOCK; + assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK ); assert( n>=1 ); assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED) @@ -47080,6 +48304,18 @@ static int winMakeEndInDirSep(int nBuf, char *zBuf){ return 0; } +/* +** If sqlite3_temp_directory is not, take the mutex and return true. +** +** If sqlite3_temp_directory is NULL, omit the mutex and return false. +*/ +static int winTempDirDefined(void){ + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); + if( sqlite3_temp_directory!=0 ) return 1; + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); + return 0; +} + /* ** Create a temporary file name and store the resulting pointer into pzBuf. ** The pointer returned in pzBuf must be freed via sqlite3_free(). @@ -47116,20 +48352,23 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){ */ nDir = nMax - (nPre + 15); assert( nDir>0 ); - if( sqlite3_temp_directory ){ + if( winTempDirDefined() ){ int nDirLen = sqlite3Strlen30(sqlite3_temp_directory); if( nDirLen>0 ){ if( !winIsDirSep(sqlite3_temp_directory[nDirLen-1]) ){ nDirLen++; } if( nDirLen>nDir ){ + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); sqlite3_free(zBuf); OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n")); return winLogError(SQLITE_ERROR, 0, "winGetTempname1", 0); } sqlite3_snprintf(nMax, zBuf, "%s", sqlite3_temp_directory); } + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); } + #if defined(__CYGWIN__) else{ static const char *azDirs[] = { @@ -47918,7 +49157,7 @@ static BOOL winIsVerbatimPathname( ** pathname into zOut[]. zOut[] will be at least pVfs->mxPathname ** bytes in size. */ -static int winFullPathname( +static int winFullPathnameNoMutex( sqlite3_vfs *pVfs, /* Pointer to vfs object */ const char *zRelative, /* Possibly relative input path */ int nFull, /* Size of output buffer in bytes */ @@ -48097,6 +49336,19 @@ static int winFullPathname( } #endif } +static int winFullPathname( + sqlite3_vfs *pVfs, /* Pointer to vfs object */ + const char *zRelative, /* Possibly relative input path */ + int nFull, /* Size of output buffer in bytes */ + char *zFull /* Output buffer */ +){ + int rc; + sqlite3_mutex *pMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR); + sqlite3_mutex_enter(pMutex); + rc = winFullPathnameNoMutex(pVfs, zRelative, nFull, zFull); + sqlite3_mutex_leave(pMutex); + return rc; +} #ifndef SQLITE_OMIT_LOAD_EXTENSION /* @@ -50441,14 +51693,24 @@ SQLITE_PRIVATE void sqlite3PcacheClearSyncFlags(PCache *pCache){ */ SQLITE_PRIVATE void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){ PCache *pCache = p->pCache; + sqlite3_pcache_page *pOther; assert( p->nRef>0 ); assert( newPgno>0 ); assert( sqlite3PcachePageSanity(p) ); pcacheTrace(("%p.MOVE %d -> %d\n",pCache,p->pgno,newPgno)); + pOther = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, newPgno, 0); + if( pOther ){ + PgHdr *pXPage = (PgHdr*)pOther->pExtra; + assert( pXPage->nRef==0 ); + pXPage->nRef++; + pCache->nRefSum++; + sqlite3PcacheDrop(pXPage); + } sqlite3GlobalConfig.pcache2.xRekey(pCache->pCache, p->pPage, p->pgno,newPgno); p->pgno = newPgno; if( (p->flags&PGHDR_DIRTY) && (p->flags&PGHDR_NEED_SYNC) ){ pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT); + assert( sqlite3PcachePageSanity(p) ); } } @@ -51830,23 +53092,26 @@ static void pcache1Rekey( PCache1 *pCache = (PCache1 *)p; PgHdr1 *pPage = (PgHdr1 *)pPg; PgHdr1 **pp; - unsigned int h; + unsigned int hOld, hNew; assert( pPage->iKey==iOld ); assert( pPage->pCache==pCache ); + assert( iOld!=iNew ); /* The page number really is changing */ pcache1EnterMutex(pCache->pGroup); - h = iOld%pCache->nHash; - pp = &pCache->apHash[h]; + assert( pcache1FetchNoMutex(p, iOld, 0)==pPage ); /* pPg really is iOld */ + hOld = iOld%pCache->nHash; + pp = &pCache->apHash[hOld]; while( (*pp)!=pPage ){ pp = &(*pp)->pNext; } *pp = pPage->pNext; - h = iNew%pCache->nHash; + assert( pcache1FetchNoMutex(p, iNew, 0)==0 ); /* iNew not in cache */ + hNew = iNew%pCache->nHash; pPage->iKey = iNew; - pPage->pNext = pCache->apHash[h]; - pCache->apHash[h] = pPage; + pPage->pNext = pCache->apHash[hNew]; + pCache->apHash[hNew] = pPage; if( iNew>pCache->iMaxKey ){ pCache->iMaxKey = iNew; } @@ -53339,6 +54604,7 @@ struct Pager { u32 vfsFlags; /* Flags for sqlite3_vfs.xOpen() */ u32 sectorSize; /* Assumed sector size during rollback */ Pgno mxPgno; /* Maximum allowed size of the database */ + Pgno lckPgno; /* Page number for the locking page */ i64 pageSize; /* Number of bytes in a page */ i64 journalSizeLimit; /* Size limit for persistent journal files */ char *zFilename; /* Name of the database file */ @@ -54325,7 +55591,7 @@ static int readJournalHdr( ** journal file descriptor is advanced to the next sector boundary before ** anything is written. The format is: ** -** + 4 bytes: PAGER_MJ_PGNO. +** + 4 bytes: PAGER_SJ_PGNO. ** + N bytes: super-journal filename in utf-8. ** + 4 bytes: N (length of super-journal name in bytes, no nul-terminator). ** + 4 bytes: super-journal name checksum. @@ -54373,7 +55639,7 @@ static int writeSuperJournal(Pager *pPager, const char *zSuper){ /* Write the super-journal data to the end of the journal file. If ** an error occurs, return the error code to the caller. */ - if( (0 != (rc = write32bits(pPager->jfd, iHdrOff, PAGER_MJ_PGNO(pPager)))) + if( (0 != (rc = write32bits(pPager->jfd, iHdrOff, PAGER_SJ_PGNO(pPager)))) || (0 != (rc = sqlite3OsWrite(pPager->jfd, zSuper, nSuper, iHdrOff+4))) || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nSuper, nSuper))) || (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nSuper+4, cksum))) @@ -54883,7 +56149,7 @@ static u32 pager_cksum(Pager *pPager, const u8 *aData){ ** corrupted, SQLITE_DONE is returned. Data is considered corrupted in ** two circumstances: ** -** * If the record page-number is illegal (0 or PAGER_MJ_PGNO), or +** * If the record page-number is illegal (0 or PAGER_SJ_PGNO), or ** * If the record is being rolled back from the main journal file ** and the checksum field does not match the record content. ** @@ -54943,7 +56209,7 @@ static int pager_playback_one_page( ** it could cause invalid data to be written into the journal. We need to ** detect this invalid data (with high probability) and ignore it. */ - if( pgno==0 || pgno==PAGER_MJ_PGNO(pPager) ){ + if( pgno==0 || pgno==PAGER_SJ_PGNO(pPager) ){ assert( !isSavepnt ); return SQLITE_DONE; } @@ -55280,6 +56546,7 @@ static int pager_truncate(Pager *pPager, Pgno nPage){ memset(pTmp, 0, szPage); testcase( (newSize-szPage) == currentSize ); testcase( (newSize-szPage) > currentSize ); + sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_SIZE_HINT, &newSize); rc = sqlite3OsWrite(pPager->fd, pTmp, szPage, newSize-szPage); } if( rc==SQLITE_OK ){ @@ -55502,6 +56769,9 @@ static int pager_playback(Pager *pPager, int isHot){ goto end_playback; } pPager->dbSize = mxPg; + if( pPager->mxPgnomxPgno = mxPg; + } } /* Copy original pages out of the journal and back into the @@ -56398,6 +57668,7 @@ SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager *pPager, u32 *pPageSize, int nR pPager->pTmpSpace = pNew; pPager->dbSize = (Pgno)((nByte+pageSize-1)/pageSize); pPager->pageSize = pageSize; + pPager->lckPgno = (Pgno)(PENDING_BYTE/pageSize) + 1; }else{ sqlite3PageFree(pNew); } @@ -56558,8 +57829,7 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){ ** current database image, in pages, OR ** ** b) if the page content were written at this time, it would not -** be necessary to write the current content out to the sub-journal -** (as determined by function subjRequiresPage()). +** be necessary to write the current content out to the sub-journal. ** ** If the condition asserted by this function were not true, and the ** dirty page were to be discarded from the cache via the pagerStress() @@ -56574,8 +57844,16 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){ */ #if defined(SQLITE_DEBUG) static void assertTruncateConstraintCb(PgHdr *pPg){ + Pager *pPager = pPg->pPager; assert( pPg->flags&PGHDR_DIRTY ); - assert( !subjRequiresPage(pPg) || pPg->pgno<=pPg->pPager->dbSize ); + if( pPg->pgno>pPager->dbSize ){ /* if (a) is false */ + Pgno pgno = pPg->pgno; + int i; + for(i=0; ipPager->nSavepoint; i++){ + PagerSavepoint *p = &pPager->aSavepoint[i]; + assert( p->nOrigpInSavepoint,pgno) ); + } + } } static void assertTruncateConstraint(Pager *pPager){ sqlite3PcacheIterateDirty(pPager->pPCache, assertTruncateConstraintCb); @@ -56597,7 +57875,6 @@ static void assertTruncateConstraint(Pager *pPager){ */ SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){ assert( pPager->dbSize>=nPage || CORRUPT_DB ); - testcase( pPager->dbSizeeState>=PAGER_WRITER_CACHEMOD ); pPager->dbSize = nPage; @@ -57916,7 +59193,7 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){ ** may mean that the pager was in the error-state when this ** function was called and the journal file does not exist. */ - if( !isOpen(pPager->jfd) ){ + if( !isOpen(pPager->jfd) && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){ sqlite3_vfs * const pVfs = pPager->pVfs; int bExists; /* True if journal file exists */ rc = sqlite3OsAccess( @@ -58161,7 +59438,7 @@ static int getPageNormal( if( pPg->pPager && !noContent ){ /* In this case the pcache already contains an initialized copy of ** the page. Return without further ado. */ - assert( pgno!=PAGER_MJ_PGNO(pPager) ); + assert( pgno!=PAGER_SJ_PGNO(pPager) ); pPager->aStat[PAGER_STAT_HIT]++; return SQLITE_OK; @@ -58172,7 +59449,7 @@ static int getPageNormal( ** (*) obsolete. Was: maximum page number is 2^31 ** (2) Never try to fetch the locking page */ - if( pgno==PAGER_MJ_PGNO(pPager) ){ + if( pgno==PAGER_SJ_PGNO(pPager) ){ rc = SQLITE_CORRUPT_BKPT; goto pager_acquire_err; } @@ -58318,6 +59595,7 @@ SQLITE_PRIVATE int sqlite3PagerGet( DbPage **ppPage, /* Write a pointer to the page here */ int flags /* PAGER_GET_XXX flags */ ){ + /* printf("PAGE %u\n", pgno); fflush(stdout); */ return pPager->xGet(pPager, pgno, ppPage, flags); } @@ -58466,6 +59744,7 @@ static int pager_open_journal(Pager *pPager){ if( rc!=SQLITE_OK ){ sqlite3BitvecDestroy(pPager->pInJournal); pPager->pInJournal = 0; + pPager->journalOff = 0; }else{ assert( pPager->eState==PAGER_WRITER_LOCKED ); pPager->eState = PAGER_WRITER_CACHEMOD; @@ -58570,7 +59849,7 @@ static SQLITE_NOINLINE int pagerAddPageToRollbackJournal(PgHdr *pPg){ /* We should never write to the journal file the page that ** contains the database locks. The following assert verifies ** that we do not. */ - assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) ); + assert( pPg->pgno!=PAGER_SJ_PGNO(pPager) ); assert( pPager->journalHdr<=pPager->journalOff ); pData2 = pPg->pData; @@ -58749,7 +60028,7 @@ static SQLITE_NOINLINE int pagerWriteLargeSector(PgHdr *pPg){ Pgno pg = pg1+ii; PgHdr *pPage; if( pg==pPg->pgno || !sqlite3BitvecTest(pPager->pInJournal, pg) ){ - if( pg!=PAGER_MJ_PGNO(pPager) ){ + if( pg!=PAGER_SJ_PGNO(pPager) ){ rc = sqlite3PagerGet(pPager, pg, &pPage, 0); if( rc==SQLITE_OK ){ rc = pager_write(pPage); @@ -59227,7 +60506,7 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne( ** last page is never written out to disk, leaving the database file ** undersized. Fix this now if it is the case. */ if( pPager->dbSize>pPager->dbFileSize ){ - Pgno nNew = pPager->dbSize - (pPager->dbSize==PAGER_MJ_PGNO(pPager)); + Pgno nNew = pPager->dbSize - (pPager->dbSize==PAGER_SJ_PGNO(pPager)); assert( pPager->eState==PAGER_WRITER_DBMOD ); rc = pager_truncate(pPager, nNew); if( rc!=SQLITE_OK ) goto commit_phase_one_exit; @@ -59923,12 +61202,12 @@ SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){ u8 eOld = pPager->journalMode; /* Prior journalmode */ /* The eMode parameter is always valid */ - assert( eMode==PAGER_JOURNALMODE_DELETE - || eMode==PAGER_JOURNALMODE_TRUNCATE - || eMode==PAGER_JOURNALMODE_PERSIST - || eMode==PAGER_JOURNALMODE_OFF - || eMode==PAGER_JOURNALMODE_WAL - || eMode==PAGER_JOURNALMODE_MEMORY ); + assert( eMode==PAGER_JOURNALMODE_DELETE /* 0 */ + || eMode==PAGER_JOURNALMODE_PERSIST /* 1 */ + || eMode==PAGER_JOURNALMODE_OFF /* 2 */ + || eMode==PAGER_JOURNALMODE_TRUNCATE /* 3 */ + || eMode==PAGER_JOURNALMODE_MEMORY /* 4 */ + || eMode==PAGER_JOURNALMODE_WAL /* 5 */ ); /* This routine is only called from the OP_JournalMode opcode, and ** the logic there will never allow a temporary file to be changed @@ -59965,7 +61244,6 @@ SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){ assert( isOpen(pPager->fd) || pPager->exclusiveMode ); if( !pPager->exclusiveMode && (eOld & 5)==1 && (eMode & 1)==0 ){ - /* In this case we would like to delete the journal file. If it is ** not possible, then that is not a problem. Deleting the journal file ** here is an optimization only. @@ -60022,7 +61300,7 @@ SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager *pPager){ SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager *pPager){ assert( assert_pager_state(pPager) ); if( pPager->eState>=PAGER_WRITER_CACHEMOD ) return 0; - if( NEVER(isOpen(pPager->jfd) && pPager->journalOff>0) ) return 0; + if( isOpen(pPager->jfd) && pPager->journalOff>0 ) return 0; return 1; } @@ -60077,6 +61355,18 @@ SQLITE_PRIVATE int sqlite3PagerCheckpoint( int *pnCkpt /* OUT: Final number of checkpointed frames */ ){ int rc = SQLITE_OK; + if( pPager->pWal==0 && pPager->journalMode==PAGER_JOURNALMODE_WAL ){ + /* This only happens when a database file is zero bytes in size opened and + ** then "PRAGMA journal_mode=WAL" is run and then sqlite3_wal_checkpoint() + ** is invoked without any intervening transactions. We need to start + ** a transaction to initialize pWal. The PRAGMA table_list statement is + ** used for this since it starts transactions on every database file, + ** including all ATTACHed databases. This seems expensive for a single + ** sqlite3_wal_checkpoint() call, but it happens very rarely. + ** https://sqlite.org/forum/forumpost/fd0f19d229156939 + */ + sqlite3_exec(db, "PRAGMA table_list",0,0,0); + } if( pPager->pWal ){ rc = sqlite3WalCheckpoint(pPager->pWal, db, eMode, (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler), @@ -62976,7 +64266,9 @@ static int walBeginShmUnreliable(Wal *pWal, int *pChanged){ } /* Allocate a buffer to read frames into */ - szFrame = pWal->hdr.szPage + WAL_FRAME_HDRSIZE; + assert( (pWal->szPage & (pWal->szPage-1))==0 ); + assert( pWal->szPage>=512 && pWal->szPage<=65536 ); + szFrame = pWal->szPage + WAL_FRAME_HDRSIZE; aFrame = (u8 *)sqlite3_malloc64(szFrame); if( aFrame==0 ){ rc = SQLITE_NOMEM_BKPT; @@ -62990,7 +64282,7 @@ static int walBeginShmUnreliable(Wal *pWal, int *pChanged){ ** the caller. */ aSaveCksum[0] = pWal->hdr.aFrameCksum[0]; aSaveCksum[1] = pWal->hdr.aFrameCksum[1]; - for(iOffset=walFrameOffset(pWal->hdr.mxFrame+1, pWal->hdr.szPage); + for(iOffset=walFrameOffset(pWal->hdr.mxFrame+1, pWal->szPage); iOffset+szFrame<=szWal; iOffset+=szFrame ){ @@ -64841,7 +66133,9 @@ struct MemPage { u8 *apOvfl[4]; /* Pointers to the body of overflow cells */ BtShared *pBt; /* Pointer to BtShared that this page is part of */ u8 *aData; /* Pointer to disk image of the page data */ - u8 *aDataEnd; /* One byte past the end of usable data */ + u8 *aDataEnd; /* One byte past the end of the entire page - not just + ** the usable space, the entire page. Used to prevent + ** corruption-induced buffer overflow. */ u8 *aCellIdx; /* The cell index area */ u8 *aDataOfst; /* Same as aData for leaves. aData+4 for interior */ DbPage *pDbPage; /* Pager page handle */ @@ -65146,7 +66440,7 @@ struct BtCursor { /* ** The database page the PENDING_BYTE occupies. This page is never used. */ -# define PENDING_BYTE_PAGE(pBt) PAGER_MJ_PGNO(pBt) +#define PENDING_BYTE_PAGE(pBt) ((Pgno)((PENDING_BYTE/((pBt)->pageSize))+1)) /* ** These macros define the location of the pointer-map entry for a @@ -65787,7 +67081,7 @@ static int hasSharedCacheTableLock( int bSeen = 0; for(p=sqliteHashFirst(&pSchema->idxHash); p; p=sqliteHashNext(p)){ Index *pIdx = (Index *)sqliteHashData(p); - if( pIdx->tnum==(int)iRoot ){ + if( pIdx->tnum==iRoot ){ if( bSeen ){ /* Two or more indexes share the same root page. There must ** be imposter tables. So just return true. The assert is not @@ -66380,7 +67674,7 @@ SQLITE_PRIVATE void sqlite3BtreeClearCursor(BtCursor *pCur){ /* ** In this version of BtreeMoveto, pKey is a packed index record ** such as is generated by the OP_MakeRecord opcode. Unpack the -** record and then call BtreeMovetoUnpacked() to do the work. +** record and then call sqlite3BtreeIndexMoveto() to do the work. */ static int btreeMoveto( BtCursor *pCur, /* Cursor open on the btree to be searched */ @@ -66798,18 +68092,32 @@ static void btreeParseCellPtr( ** ** pIter += getVarint(pIter, (u64*)&pInfo->nKey); ** - ** The code is inlined to avoid a function call. + ** The code is inlined and the loop is unrolled for performance. + ** This routine is a high-runner. */ iKey = *pIter; if( iKey>=0x80 ){ - u8 *pEnd = &pIter[7]; - iKey &= 0x7f; - while(1){ - iKey = (iKey<<7) | (*++pIter & 0x7f); - if( (*pIter)<0x80 ) break; - if( pIter>=pEnd ){ - iKey = (iKey<<8) | *++pIter; - break; + u8 x; + iKey = ((iKey&0x7f)<<7) | ((x = *++pIter) & 0x7f); + if( x>=0x80 ){ + iKey = (iKey<<7) | ((x =*++pIter) & 0x7f); + if( x>=0x80 ){ + iKey = (iKey<<7) | ((x = *++pIter) & 0x7f); + if( x>=0x80 ){ + iKey = (iKey<<7) | ((x = *++pIter) & 0x7f); + if( x>=0x80 ){ + iKey = (iKey<<7) | ((x = *++pIter) & 0x7f); + if( x>=0x80 ){ + iKey = (iKey<<7) | ((x = *++pIter) & 0x7f); + if( x>=0x80 ){ + iKey = (iKey<<7) | ((x = *++pIter) & 0x7f); + if( x>=0x80 ){ + iKey = (iKey<<8) | (*++pIter); + } + } + } + } + } } } } @@ -66819,7 +68127,7 @@ static void btreeParseCellPtr( pInfo->nPayload = nPayload; pInfo->pPayload = pIter; testcase( nPayload==pPage->maxLocal ); - testcase( nPayload==pPage->maxLocal+1 ); + testcase( nPayload==(u32)pPage->maxLocal+1 ); if( nPayload<=pPage->maxLocal ){ /* This is the (easy) common case where the entire payload fits ** on the local page. No overflow is required. @@ -66856,7 +68164,7 @@ static void btreeParseCellPtrIndex( pInfo->nPayload = nPayload; pInfo->pPayload = pIter; testcase( nPayload==pPage->maxLocal ); - testcase( nPayload==pPage->maxLocal+1 ); + testcase( nPayload==(u32)pPage->maxLocal+1 ); if( nPayload<=pPage->maxLocal ){ /* This is the (easy) common case where the entire payload fits ** on the local page. No overflow is required. @@ -66886,6 +68194,7 @@ static void btreeParseCell( ** the space used by the cell pointer. ** ** cellSizePtrNoPayload() => table internal nodes +** cellSizePtrTableLeaf() => table leaf nodes ** cellSizePtr() => all index nodes & table leaf nodes */ static u16 cellSizePtr(MemPage *pPage, u8 *pCell){ @@ -66911,15 +68220,8 @@ static u16 cellSizePtr(MemPage *pPage, u8 *pCell){ }while( *(pIter)>=0x80 && pIterintKey ){ - /* pIter now points at the 64-bit integer key value, a variable length - ** integer. The following block moves pIter to point at the first byte - ** past the end of the key value. */ - pEnd = &pIter[9]; - while( (*pIter++)&0x80 && pItermaxLocal ); - testcase( nSize==pPage->maxLocal+1 ); + testcase( nSize==(u32)pPage->maxLocal+1 ); if( nSize<=pPage->maxLocal ){ nSize += (u32)(pIter - pCell); if( nSize<4 ) nSize = 4; @@ -66927,7 +68229,7 @@ static u16 cellSizePtr(MemPage *pPage, u8 *pCell){ int minLocal = pPage->minLocal; nSize = minLocal + (nSize - minLocal) % (pPage->pBt->usableSize - 4); testcase( nSize==pPage->maxLocal ); - testcase( nSize==pPage->maxLocal+1 ); + testcase( nSize==(u32)pPage->maxLocal+1 ); if( nSize>pPage->maxLocal ){ nSize = minLocal; } @@ -66957,6 +68259,58 @@ static u16 cellSizePtrNoPayload(MemPage *pPage, u8 *pCell){ assert( debuginfo.nSize==(u16)(pIter - pCell) || CORRUPT_DB ); return (u16)(pIter - pCell); } +static u16 cellSizePtrTableLeaf(MemPage *pPage, u8 *pCell){ + u8 *pIter = pCell; /* For looping over bytes of pCell */ + u8 *pEnd; /* End mark for a varint */ + u32 nSize; /* Size value to return */ + +#ifdef SQLITE_DEBUG + /* The value returned by this function should always be the same as + ** the (CellInfo.nSize) value found by doing a full parse of the + ** cell. If SQLITE_DEBUG is defined, an assert() at the bottom of + ** this function verifies that this invariant is not violated. */ + CellInfo debuginfo; + pPage->xParseCell(pPage, pCell, &debuginfo); +#endif + + nSize = *pIter; + if( nSize>=0x80 ){ + pEnd = &pIter[8]; + nSize &= 0x7f; + do{ + nSize = (nSize<<7) | (*++pIter & 0x7f); + }while( *(pIter)>=0x80 && pItermaxLocal ); + testcase( nSize==(u32)pPage->maxLocal+1 ); + if( nSize<=pPage->maxLocal ){ + nSize += (u32)(pIter - pCell); + if( nSize<4 ) nSize = 4; + }else{ + int minLocal = pPage->minLocal; + nSize = minLocal + (nSize - minLocal) % (pPage->pBt->usableSize - 4); + testcase( nSize==pPage->maxLocal ); + testcase( nSize==(u32)pPage->maxLocal+1 ); + if( nSize>pPage->maxLocal ){ + nSize = minLocal; + } + nSize += 4 + (u16)(pIter - pCell); + } + assert( nSize==debuginfo.nSize || CORRUPT_DB ); + return (u16)nSize; +} #ifdef SQLITE_DEBUG @@ -66970,7 +68324,7 @@ static u16 cellSize(MemPage *pPage, int iCell){ #ifndef SQLITE_OMIT_AUTOVACUUM /* ** The cell pCell is currently part of page pSrc but will ultimately be part -** of pPage. (pSrc and pPager are often the same.) If pCell contains a +** of pPage. (pSrc and pPage are often the same.) If pCell contains a ** pointer to an overflow page, insert an entry into the pointer-map for ** the overflow page that will be valid after pCell has been moved to pPage. */ @@ -67061,7 +68415,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){ if( iFree2+sz2 > usableSize ) return SQLITE_CORRUPT_PAGE(pPage); memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz)); sz += sz2; - }else if( NEVER(iFree+sz>usableSize) ){ + }else if( iFree+sz>usableSize ){ return SQLITE_CORRUPT_PAGE(pPage); } @@ -67145,7 +68499,8 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){ const int hdr = pPg->hdrOffset; /* Offset to page header */ u8 * const aData = pPg->aData; /* Page data */ int iAddr = hdr + 1; /* Address of ptr to pc */ - int pc = get2byte(&aData[iAddr]); /* Address of a free slot */ + u8 *pTmp = &aData[iAddr]; /* Temporary ptr into aData[] */ + int pc = get2byte(pTmp); /* Address of a free slot */ int x; /* Excess size of the slot */ int maxPC = pPg->pBt->usableSize - nByte; /* Max address for a usable slot */ int size; /* Size of the free slot */ @@ -67155,7 +68510,8 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){ /* EVIDENCE-OF: R-22710-53328 The third and fourth bytes of each ** freeblock form a big-endian integer which is the size of the freeblock ** in bytes, including the 4-byte header. */ - size = get2byte(&aData[pc+2]); + pTmp = &aData[pc+2]; + size = get2byte(pTmp); if( (x = size - nByte)>=0 ){ testcase( x==4 ); testcase( x==3 ); @@ -67168,6 +68524,8 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){ ** fragmented bytes within the page. */ memcpy(&aData[iAddr], &aData[pc], 2); aData[hdr+7] += (u8)x; + testcase( pc+x>maxPC ); + return &aData[pc]; }else if( x+pc > maxPC ){ /* This slot extends off the end of the usable part of the page */ *pRc = SQLITE_CORRUPT_PAGE(pPg); @@ -67180,7 +68538,8 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){ return &aData[pc + x]; } iAddr = pc; - pc = get2byte(&aData[pc]); + pTmp = &aData[pc]; + pc = get2byte(pTmp); if( pc<=iAddr+size ){ if( pc ){ /* The next slot in the chain is not past the end of the current slot */ @@ -67214,6 +68573,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ u8 * const data = pPage->aData; /* Local cache of pPage->aData */ int top; /* First byte of cell content area */ int rc = SQLITE_OK; /* Integer return code */ + u8 *pTmp; /* Temp ptr into data[] */ int gap; /* First byte of gap between cell pointers and cell content */ assert( sqlite3PagerIswriteable(pPage->pDbPage) ); @@ -67232,7 +68592,8 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ ** then the cell content offset of an empty page wants to be 65536. ** However, that integer is too large to be stored in a 2-byte unsigned ** integer, so a value of 0 is used in its place. */ - top = get2byte(&data[hdr+5]); + pTmp = &data[hdr+5]; + top = get2byte(pTmp); assert( top<=(int)pPage->pBt->usableSize ); /* by btreeComputeFreeSpace() */ if( gap>top ){ if( top==0 && pPage->pBt->usableSize==65536 ){ @@ -67314,6 +68675,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ u16 x; /* Offset to cell content area */ u32 iEnd = iStart + iSize; /* First byte past the iStart buffer */ unsigned char *data = pPage->aData; /* Page content */ + u8 *pTmp; /* Temporary ptr into data[] */ assert( pPage->pBt!=0 ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); @@ -67341,7 +68703,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ if( iFreeBlk>pPage->pBt->usableSize-4 ){ /* TH3: corrupt081.100 */ return SQLITE_CORRUPT_PAGE(pPage); } - assert( iFreeBlk>iPtr || iFreeBlk==0 ); + assert( iFreeBlk>iPtr || iFreeBlk==0 || CORRUPT_DB ); /* At this point: ** iFreeBlk: First freeblock after iStart, or zero if none @@ -67376,7 +68738,8 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_PAGE(pPage); data[hdr+7] -= nFrag; } - x = get2byte(&data[hdr+5]); + pTmp = &data[hdr+5]; + x = get2byte(pTmp); if( iStart<=x ){ /* The new freeblock is at the beginning of the cell content area, ** so just extend the cell content area rather than create another @@ -67420,7 +68783,6 @@ static int decodeFlags(MemPage *pPage, int flagByte){ pPage->leaf = (u8)(flagByte>>3); assert( PTF_LEAF == 1<<3 ); flagByte &= ~PTF_LEAF; pPage->childPtrSize = 4-4*pPage->leaf; - pPage->xCellSize = cellSizePtr; pBt = pPage->pBt; if( flagByte==(PTF_LEAFDATA | PTF_INTKEY) ){ /* EVIDENCE-OF: R-07291-35328 A value of 5 (0x05) means the page is an @@ -67432,6 +68794,7 @@ static int decodeFlags(MemPage *pPage, int flagByte){ pPage->intKey = 1; if( pPage->leaf ){ pPage->intKeyLeaf = 1; + pPage->xCellSize = cellSizePtrTableLeaf; pPage->xParseCell = btreeParseCellPtr; }else{ pPage->intKeyLeaf = 0; @@ -67449,12 +68812,17 @@ static int decodeFlags(MemPage *pPage, int flagByte){ assert( (PTF_ZERODATA|PTF_LEAF)==10 ); pPage->intKey = 0; pPage->intKeyLeaf = 0; + pPage->xCellSize = cellSizePtr; pPage->xParseCell = btreeParseCellPtrIndex; pPage->maxLocal = pBt->maxLocal; pPage->minLocal = pBt->minLocal; }else{ /* EVIDENCE-OF: R-47608-56469 Any other value for the b-tree page type is ** an error. */ + pPage->intKey = 0; + pPage->intKeyLeaf = 0; + pPage->xCellSize = cellSizePtr; + pPage->xParseCell = btreeParseCellPtrIndex; return SQLITE_CORRUPT_PAGE(pPage); } pPage->max1bytePayload = pBt->max1bytePayload; @@ -67612,7 +68980,7 @@ static int btreeInitPage(MemPage *pPage){ pPage->nOverflow = 0; pPage->cellOffset = pPage->hdrOffset + 8 + pPage->childPtrSize; pPage->aCellIdx = data + pPage->childPtrSize + 8; - pPage->aDataEnd = pPage->aData + pBt->usableSize; + pPage->aDataEnd = pPage->aData + pBt->pageSize; pPage->aDataOfst = pPage->aData + pPage->childPtrSize; /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the ** number of cells on the page. */ @@ -67647,7 +69015,7 @@ static void zeroPage(MemPage *pPage, int flags){ u8 hdr = pPage->hdrOffset; u16 first; - assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno ); + assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno || CORRUPT_DB ); assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage ); assert( sqlite3PagerGetData(pPage->pDbPage) == data ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); @@ -67663,7 +69031,7 @@ static void zeroPage(MemPage *pPage, int flags){ pPage->nFree = (u16)(pBt->usableSize - first); decodeFlags(pPage, flags); pPage->cellOffset = first; - pPage->aDataEnd = &data[pBt->usableSize]; + pPage->aDataEnd = &data[pBt->pageSize]; pPage->aCellIdx = &data[first]; pPage->aDataOfst = &data[pPage->childPtrSize]; pPage->nOverflow = 0; @@ -67789,7 +69157,7 @@ static int getAndInitPage( goto getAndInitPage_error2; } } - assert( (*ppPage)->pgno==pgno ); + assert( (*ppPage)->pgno==pgno || CORRUPT_DB ); assert( (*ppPage)->aData==sqlite3PagerGetData(pDbPage) ); /* If obtaining a child page for a cursor, we must verify that the page is @@ -67808,7 +69176,9 @@ static int getAndInitPage( pCur->pPage = pCur->apPage[pCur->iPage]; } testcase( pgno==0 ); - assert( pgno!=0 || rc==SQLITE_CORRUPT ); + assert( pgno!=0 || rc==SQLITE_CORRUPT + || rc==SQLITE_IOERR_NOMEM + || rc==SQLITE_NOMEM ); return rc; } @@ -68266,30 +69636,38 @@ static int removeFromSharingList(BtShared *pBt){ ** MX_CELL_SIZE(pBt) bytes with a 4-byte prefix for a left-child ** pointer. */ -static void allocateTempSpace(BtShared *pBt){ - if( !pBt->pTmpSpace ){ - pBt->pTmpSpace = sqlite3PageMalloc( pBt->pageSize ); - - /* One of the uses of pBt->pTmpSpace is to format cells before - ** inserting them into a leaf page (function fillInCell()). If - ** a cell is less than 4 bytes in size, it is rounded up to 4 bytes - ** by the various routines that manipulate binary cells. Which - ** can mean that fillInCell() only initializes the first 2 or 3 - ** bytes of pTmpSpace, but that the first 4 bytes are copied from - ** it into a database page. This is not actually a problem, but it - ** does cause a valgrind error when the 1 or 2 bytes of unitialized - ** data is passed to system call write(). So to avoid this error, - ** zero the first 4 bytes of temp space here. - ** - ** Also: Provide four bytes of initialized space before the - ** beginning of pTmpSpace as an area available to prepend the - ** left-child pointer to the beginning of a cell. - */ - if( pBt->pTmpSpace ){ - memset(pBt->pTmpSpace, 0, 8); - pBt->pTmpSpace += 4; - } +static SQLITE_NOINLINE int allocateTempSpace(BtShared *pBt){ + assert( pBt!=0 ); + assert( pBt->pTmpSpace==0 ); + /* This routine is called only by btreeCursor() when allocating the + ** first write cursor for the BtShared object */ + assert( pBt->pCursor!=0 && (pBt->pCursor->curFlags & BTCF_WriteFlag)!=0 ); + pBt->pTmpSpace = sqlite3PageMalloc( pBt->pageSize ); + if( pBt->pTmpSpace==0 ){ + BtCursor *pCur = pBt->pCursor; + pBt->pCursor = pCur->pNext; /* Unlink the cursor */ + memset(pCur, 0, sizeof(*pCur)); + return SQLITE_NOMEM_BKPT; } + + /* One of the uses of pBt->pTmpSpace is to format cells before + ** inserting them into a leaf page (function fillInCell()). If + ** a cell is less than 4 bytes in size, it is rounded up to 4 bytes + ** by the various routines that manipulate binary cells. Which + ** can mean that fillInCell() only initializes the first 2 or 3 + ** bytes of pTmpSpace, but that the first 4 bytes are copied from + ** it into a database page. This is not actually a problem, but it + ** does cause a valgrind error when the 1 or 2 bytes of unitialized + ** data is passed to system call write(). So to avoid this error, + ** zero the first 4 bytes of temp space here. + ** + ** Also: Provide four bytes of initialized space before the + ** beginning of pTmpSpace as an area available to prepend the + ** left-child pointer to the beginning of a cell. + */ + memset(pBt->pTmpSpace, 0, 8); + pBt->pTmpSpace += 4; + return SQLITE_OK; } /* @@ -68786,9 +70164,13 @@ static int lockBtree(BtShared *pBt){ pageSize-usableSize); return rc; } - if( sqlite3WritableSchema(pBt->db)==0 && nPage>nPageFile ){ - rc = SQLITE_CORRUPT_BKPT; - goto page1_init_failed; + if( nPage>nPageFile ){ + if( sqlite3WritableSchema(pBt->db)==0 ){ + rc = SQLITE_CORRUPT_BKPT; + goto page1_init_failed; + }else{ + nPage = nPageFile; + } } /* EVIDENCE-OF: R-28312-64704 However, the usable size is not allowed to ** be less than 480. In other words, if the page size is 512, then the @@ -69418,12 +70800,17 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){ } do { MemPage *pFreePg; + Pgno dbSize = btreePagecount(pBt); rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iNear, eMode); if( rc!=SQLITE_OK ){ releasePage(pLastPg); return rc; } releasePage(pFreePg); + if( iFreePg>dbSize ){ + releasePage(pLastPg); + return SQLITE_CORRUPT_BKPT; + } }while( bCommit && iFreePg>nFin ); assert( iFreePgaData[28]); testcase( nPage==0 ); if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage); - testcase( pBt->nPage!=nPage ); + testcase( pBt->nPage!=(u32)nPage ); pBt->nPage = nPage; } @@ -70030,10 +71417,6 @@ static int btreeCursor( assert( pBt->pPage1 && pBt->pPage1->aData ); assert( wrFlag==0 || (pBt->btsFlags & BTS_READ_ONLY)==0 ); - if( wrFlag ){ - allocateTempSpace(pBt); - if( pBt->pTmpSpace==0 ) return SQLITE_NOMEM_BKPT; - } if( iTable<=1 ){ if( iTable<1 ){ return SQLITE_CORRUPT_BKPT; @@ -70050,19 +71433,25 @@ static int btreeCursor( pCur->pKeyInfo = pKeyInfo; pCur->pBtree = p; pCur->pBt = pBt; - pCur->curFlags = wrFlag ? BTCF_WriteFlag : 0; - pCur->curPagerFlags = wrFlag ? 0 : PAGER_GET_READONLY; + pCur->curFlags = 0; /* If there are two or more cursors on the same btree, then all such ** cursors *must* have the BTCF_Multiple flag set. */ for(pX=pBt->pCursor; pX; pX=pX->pNext){ if( pX->pgnoRoot==iTable ){ pX->curFlags |= BTCF_Multiple; - pCur->curFlags |= BTCF_Multiple; + pCur->curFlags = BTCF_Multiple; } } + pCur->eState = CURSOR_INVALID; pCur->pNext = pBt->pCursor; pBt->pCursor = pCur; - pCur->eState = CURSOR_INVALID; + if( wrFlag ){ + pCur->curFlags |= BTCF_WriteFlag; + pCur->curPagerFlags = 0; + if( pBt->pTmpSpace==0 ) return allocateTempSpace(pBt); + }else{ + pCur->curPagerFlags = PAGER_GET_READONLY; + } return SQLITE_OK; } static int btreeCursorWithLock( @@ -70837,7 +72226,7 @@ static int moveToRoot(BtCursor *pCur){ while( --pCur->iPage ){ releasePageNotNull(pCur->apPage[pCur->iPage]); } - pCur->pPage = pCur->apPage[0]; + pRoot = pCur->pPage = pCur->apPage[0]; goto skip_init; } }else if( pCur->pgnoRoot==0 ){ @@ -70862,7 +72251,7 @@ static int moveToRoot(BtCursor *pCur){ pCur->curIntKey = pCur->pPage->intKey; } pRoot = pCur->pPage; - assert( pRoot->pgno==pCur->pgnoRoot ); + assert( pRoot->pgno==pCur->pgnoRoot || CORRUPT_DB ); /* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor ** expected to open it on an index b-tree. Otherwise, if pKeyInfo is @@ -70884,7 +72273,6 @@ static int moveToRoot(BtCursor *pCur){ pCur->info.nSize = 0; pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl); - pRoot = pCur->pPage; if( pRoot->nCell>0 ){ pCur->eState = CURSOR_VALID; }else if( !pRoot->leaf ){ @@ -71125,7 +72513,6 @@ SQLITE_PRIVATE int sqlite3BtreeTableMoveto( upr = pPage->nCell-1; assert( biasRight==0 || biasRight==1 ); idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */ - pCur->ix = (u16)idx; for(;;){ i64 nCellKey; pCell = findCellPastPtr(pPage, idx); @@ -71185,6 +72572,69 @@ SQLITE_PRIVATE int sqlite3BtreeTableMoveto( return rc; } +/* +** Compare the "idx"-th cell on the page the cursor pCur is currently +** pointing to to pIdxKey using xRecordCompare. Return negative or +** zero if the cell is less than or equal pIdxKey. Return positive +** if unknown. +** +** Return value negative: Cell at pCur[idx] less than pIdxKey +** +** Return value is zero: Cell at pCur[idx] equals pIdxKey +** +** Return value positive: Nothing is known about the relationship +** of the cell at pCur[idx] and pIdxKey. +** +** This routine is part of an optimization. It is always safe to return +** a positive value as that will cause the optimization to be skipped. +*/ +static int indexCellCompare( + BtCursor *pCur, + int idx, + UnpackedRecord *pIdxKey, + RecordCompare xRecordCompare +){ + MemPage *pPage = pCur->pPage; + int c; + int nCell; /* Size of the pCell cell in bytes */ + u8 *pCell = findCellPastPtr(pPage, idx); + + nCell = pCell[0]; + if( nCell<=pPage->max1bytePayload ){ + /* This branch runs if the record-size field of the cell is a + ** single byte varint and the record fits entirely on the main + ** b-tree page. */ + testcase( pCell+nCell+1==pPage->aDataEnd ); + c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey); + }else if( !(pCell[1] & 0x80) + && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal + ){ + /* The record-size field is a 2 byte varint and the record + ** fits entirely on the main b-tree page. */ + testcase( pCell+nCell+2==pPage->aDataEnd ); + c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey); + }else{ + /* If the record extends into overflow pages, do not attempt + ** the optimization. */ + c = 99; + } + return c; +} + +/* +** Return true (non-zero) if pCur is current pointing to the last +** page of a table. +*/ +static int cursorOnLastPage(BtCursor *pCur){ + int i; + assert( pCur->eState==CURSOR_VALID ); + for(i=0; iiPage; i++){ + MemPage *pPage = pCur->apPage[i]; + if( pCur->aiIdx[i]nCell ) return 0; + } + return 1; +} + /* Move the cursor so that it points to an entry in an index table ** near the key pIdxKey. Return a success code. ** @@ -71235,6 +72685,43 @@ SQLITE_PRIVATE int sqlite3BtreeIndexMoveto( || pIdxKey->default_rc==-1 ); + + /* Check to see if we can skip a lot of work. Two cases: + ** + ** (1) If the cursor is already pointing to the very last cell + ** in the table and the pIdxKey search key is greater than or + ** equal to that last cell, then no movement is required. + ** + ** (2) If the cursor is on the last page of the table and the first + ** cell on that last page is less than or equal to the pIdxKey + ** search key, then we can start the search on the current page + ** without needing to go back to root. + */ + if( pCur->eState==CURSOR_VALID + && pCur->pPage->leaf + && cursorOnLastPage(pCur) + ){ + int c; + if( pCur->ix==pCur->pPage->nCell-1 + && (c = indexCellCompare(pCur, pCur->ix, pIdxKey, xRecordCompare))<=0 + && pIdxKey->errCode==SQLITE_OK + ){ + *pRes = c; + return SQLITE_OK; /* Cursor already pointing at the correct spot */ + } + if( pCur->iPage>0 + && indexCellCompare(pCur, 0, pIdxKey, xRecordCompare)<=0 + && pIdxKey->errCode==SQLITE_OK + ){ + pCur->curFlags &= ~BTCF_ValidOvfl; + if( !pCur->pPage->isInit ){ + return SQLITE_CORRUPT_BKPT; + } + goto bypass_moveto_root; /* Start search on the current page */ + } + pIdxKey->errCode = SQLITE_OK; + } + rc = moveToRoot(pCur); if( rc ){ if( rc==SQLITE_EMPTY ){ @@ -71244,12 +72731,14 @@ SQLITE_PRIVATE int sqlite3BtreeIndexMoveto( } return rc; } + +bypass_moveto_root: assert( pCur->pPage ); assert( pCur->pPage->isInit ); assert( pCur->eState==CURSOR_VALID ); assert( pCur->pPage->nCell > 0 ); - assert( pCur->iPage==0 || pCur->apPage[0]->intKey==pCur->curIntKey ); - assert( pCur->curIntKey || pIdxKey ); + assert( pCur->curIntKey==0 ); + assert( pIdxKey!=0 ); for(;;){ int lwr, upr, idx, c; Pgno chldPg; @@ -71263,11 +72752,10 @@ SQLITE_PRIVATE int sqlite3BtreeIndexMoveto( ** be the right kind (index or table) of b-tree page. Otherwise ** a moveToChild() or moveToRoot() call would have detected corruption. */ assert( pPage->nCell>0 ); - assert( pPage->intKey==(pIdxKey==0) ); + assert( pPage->intKey==0 ); lwr = 0; upr = pPage->nCell-1; idx = upr>>1; /* idx = (lwr+upr)/2; */ - pCur->ix = (u16)idx; for(;;){ int nCell; /* Size of the pCell cell in bytes */ pCell = findCellPastPtr(pPage, idx); @@ -71356,7 +72844,7 @@ SQLITE_PRIVATE int sqlite3BtreeIndexMoveto( assert( lwr==upr+1 || (pPage->intKey && !pPage->leaf) ); assert( pPage->isInit ); if( pPage->leaf ){ - assert( pCur->ixpPage->nCell ); + assert( pCur->ixpPage->nCell || CORRUPT_DB ); pCur->ix = (u16)idx; *pRes = c; rc = SQLITE_OK; @@ -71959,7 +73447,7 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){ assert( CORRUPT_DB || iPage>1 ); assert( !pMemPage || pMemPage->pgno==iPage ); - if( NEVER(iPage<2) || iPage>pBt->nPage ){ + if( iPage<2 || iPage>pBt->nPage ){ return SQLITE_CORRUPT_BKPT; } if( pMemPage ){ @@ -72383,16 +73871,24 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){ int hdr; /* Beginning of the header. 0 most pages. 100 page 1 */ if( *pRC ) return; - assert( idx>=0 && idxnCell ); + assert( idx>=0 ); + assert( idxnCell ); assert( CORRUPT_DB || sz==cellSize(pPage, idx) ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( pPage->nFree>=0 ); data = pPage->aData; ptr = &pPage->aCellIdx[2*idx]; + assert( pPage->pBt->usableSize > (u32)(ptr-data) ); pc = get2byte(ptr); hdr = pPage->hdrOffset; - testcase( pc==get2byte(&data[hdr+5]) ); +#if 0 /* Not required. Omit for efficiency */ + if( pcnCell*2 ){ + *pRC = SQLITE_CORRUPT_BKPT; + return; + } +#endif + testcase( pc==(u32)get2byte(&data[hdr+5]) ); testcase( pc+sz==pPage->pBt->usableSize ); if( pc+sz > pPage->pBt->usableSize ){ *pRC = SQLITE_CORRUPT_BKPT; @@ -72684,7 +74180,7 @@ static int rebuildPage( assert( i(u32)usableSize) ){ j = 0; } + if( j>(u32)usableSize ){ j = 0; } memcpy(&pTmp[j], &aData[j], usableSize - j); for(k=0; pCArray->ixNx[k]<=i && ALWAYS(kpPg->aDataEnd) ) goto editpage_fail; + if( pData>pPg->aDataEnd ) goto editpage_fail; /* Add cells to the start of the page */ if( iNewpgno; - aPgFlags[i] = apNew[i]->pDbPage->flags; - for(j=0; jpgno; + assert( apNew[i]->pDbPage->flags & PGHDR_WRITEABLE ); + assert( apNew[i]->pDbPage->flags & PGHDR_DIRTY ); } - for(i=0; ipgno < apNew[iB]->pgno ) iB = j; } - pgno = aPgOrder[iBest]; - aPgOrder[iBest] = 0xffffffff; - if( iBest!=i ){ - if( iBest>i ){ - sqlite3PagerRekey(apNew[iBest]->pDbPage, pBt->nPage+iBest+1, 0); - } - sqlite3PagerRekey(apNew[i]->pDbPage, pgno, aPgFlags[iBest]); - apNew[i]->pgno = pgno; + + /* If apNew[i] has a page number that is bigger than any of the + ** subsequence apNew[i] entries, then swap apNew[i] with the subsequent + ** entry that has the smallest page number (which we know to be + ** entry apNew[iB]). + */ + if( iB!=i ){ + Pgno pgnoA = apNew[i]->pgno; + Pgno pgnoB = apNew[iB]->pgno; + Pgno pgnoTemp = (PENDING_BYTE/pBt->pageSize)+1; + u16 fgA = apNew[i]->pDbPage->flags; + u16 fgB = apNew[iB]->pDbPage->flags; + sqlite3PagerRekey(apNew[i]->pDbPage, pgnoTemp, fgB); + sqlite3PagerRekey(apNew[iB]->pDbPage, pgnoA, fgA); + sqlite3PagerRekey(apNew[i]->pDbPage, pgnoB, fgB); + apNew[i]->pgno = pgnoB; + apNew[iB]->pgno = pgnoA; } } @@ -73872,7 +75363,7 @@ static int balance_nonroot( iOvflSpace += sz; assert( sz<=pBt->maxLocal+23 ); assert( iOvflSpace <= (int)pBt->pageSize ); - for(k=0; b.ixNx[k]<=i && ALWAYS(kpBt->usableSize * 2 / 3; u8 aBalanceQuickSpace[13]; u8 *pFree = 0; @@ -74135,7 +75625,11 @@ static int balance(BtCursor *pCur){ MemPage *pPage = pCur->pPage; if( NEVER(pPage->nFree<0) && btreeComputeFreeSpace(pPage) ) break; - if( pPage->nOverflow==0 && pPage->nFree<=nMin ){ + if( pPage->nOverflow==0 && pPage->nFree*3<=(int)pCur->pBt->usableSize*2 ){ + /* No rebalance required as long as: + ** (1) There are no overflow cells + ** (2) The amount of free space on the page is less than 2/3rds of + ** the total usable space on the page. */ break; }else if( (iPage = pCur->iPage)==0 ){ if( pPage->nOverflow && (rc = anotherValidCursor(pCur))==SQLITE_OK ){ @@ -74355,7 +75849,7 @@ static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){ ** pX.pData,nData,nZero fields must be zero. ** ** If the seekResult parameter is non-zero, then a successful call to -** MovetoUnpacked() to seek cursor pCur to (pKey,nKey) has already +** sqlite3BtreeIndexMoveto() to seek cursor pCur to (pKey,nKey) has already ** been performed. In other words, if seekResult!=0 then the cursor ** is currently pointing to a cell that will be adjacent to the cell ** to be inserted. If seekResult<0 then pCur points to a cell that is @@ -74373,7 +75867,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( BtCursor *pCur, /* Insert data into the table of this cursor */ const BtreePayload *pX, /* Content of the row to be inserted */ int flags, /* True if this is likely an append */ - int seekResult /* Result of prior MovetoUnpacked() call */ + int seekResult /* Result of prior IndexMoveto() call */ ){ int rc; int loc = seekResult; /* -1: before desired location +1: after */ @@ -74388,24 +75882,6 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( assert( (flags & (BTREE_SAVEPOSITION|BTREE_APPEND|BTREE_PREFORMAT))==flags ); assert( (flags & BTREE_PREFORMAT)==0 || seekResult || pCur->pKeyInfo==0 ); - if( pCur->eState==CURSOR_FAULT ){ - assert( pCur->skipNext!=SQLITE_OK ); - return pCur->skipNext; - } - - assert( cursorOwnsBtShared(pCur) ); - assert( (pCur->curFlags & BTCF_WriteFlag)!=0 - && pBt->inTransaction==TRANS_WRITE - && (pBt->btsFlags & BTS_READ_ONLY)==0 ); - assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) ); - - /* Assert that the caller has been consistent. If this cursor was opened - ** expecting an index b-tree, then the caller should be inserting blob - ** keys with no associated data. If the cursor was opened expecting an - ** intkey table, the caller should be inserting integer keys with a - ** blob of associated data. */ - assert( (flags & BTREE_PREFORMAT) || (pX->pKey==0)==(pCur->pKeyInfo==0) ); - /* Save the positions of any other cursors open on this table. ** ** In some cases, the call to btreeMoveto() below is a no-op. For @@ -74430,6 +75906,29 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( } } + /* Ensure that the cursor is not in the CURSOR_FAULT state and that it + ** points to a valid cell. + */ + if( pCur->eState>=CURSOR_REQUIRESEEK ){ + testcase( pCur->eState==CURSOR_REQUIRESEEK ); + testcase( pCur->eState==CURSOR_FAULT ); + rc = moveToRoot(pCur); + if( rc && rc!=SQLITE_EMPTY ) return rc; + } + + assert( cursorOwnsBtShared(pCur) ); + assert( (pCur->curFlags & BTCF_WriteFlag)!=0 + && pBt->inTransaction==TRANS_WRITE + && (pBt->btsFlags & BTS_READ_ONLY)==0 ); + assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) ); + + /* Assert that the caller has been consistent. If this cursor was opened + ** expecting an index b-tree, then the caller should be inserting blob + ** keys with no associated data. If the cursor was opened expecting an + ** intkey table, the caller should be inserting integer keys with a + ** blob of associated data. */ + assert( (flags & BTREE_PREFORMAT) || (pX->pKey==0)==(pCur->pKeyInfo==0) ); + if( pCur->pKeyInfo==0 ){ assert( pX->pKey==0 ); /* If this is an insert into a table b-tree, invalidate any incrblob @@ -74518,14 +76017,14 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( } } assert( pCur->eState==CURSOR_VALID - || (pCur->eState==CURSOR_INVALID && loc) - || CORRUPT_DB ); + || (pCur->eState==CURSOR_INVALID && loc) ); pPage = pCur->pPage; assert( pPage->intKey || pX->nKey>=0 || (flags & BTREE_PREFORMAT) ); assert( pPage->leaf || !pPage->intKey ); if( pPage->nFree<0 ){ if( NEVER(pCur->eState>CURSOR_INVALID) ){ + /* ^^^^^--- due to the moveToRoot() call above */ rc = SQLITE_CORRUPT_BKPT; }else{ rc = btreeComputeFreeSpace(pPage); @@ -74536,7 +76035,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n", pCur->pgnoRoot, pX->nKey, pX->nData, pPage->pgno, loc==0 ? "overwrite" : "new entry")); - assert( pPage->isInit ); + assert( pPage->isInit || CORRUPT_DB ); newCell = pBt->pTmpSpace; assert( newCell!=0 ); if( flags & BTREE_PREFORMAT ){ @@ -74687,7 +76186,11 @@ SQLITE_PRIVATE int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64 u32 nRem; /* Bytes of data still to copy */ getCellInfo(pSrc); - aOut += putVarint32(aOut, pSrc->info.nPayload); + if( pSrc->info.nPayload<0x80 ){ + *(aOut++) = pSrc->info.nPayload; + }else{ + aOut += sqlite3PutVarint(aOut, pSrc->info.nPayload); + } if( pDest->pKeyInfo==0 ) aOut += putVarint(aOut, iKey); nIn = pSrc->info.nLocal; aIn = pSrc->info.pPayload; @@ -74791,14 +76294,13 @@ SQLITE_PRIVATE int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64 SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ Btree *p = pCur->pBtree; BtShared *pBt = p->pBt; - int rc; /* Return code */ - MemPage *pPage; /* Page to delete cell from */ - unsigned char *pCell; /* Pointer to cell to delete */ - int iCellIdx; /* Index of cell to delete */ - int iCellDepth; /* Depth of node containing pCell */ - CellInfo info; /* Size of the cell being deleted */ - int bSkipnext = 0; /* Leaf cursor in SKIPNEXT state */ - u8 bPreserve = flags & BTREE_SAVEPOSITION; /* Keep cursor valid */ + int rc; /* Return code */ + MemPage *pPage; /* Page to delete cell from */ + unsigned char *pCell; /* Pointer to cell to delete */ + int iCellIdx; /* Index of cell to delete */ + int iCellDepth; /* Depth of node containing pCell */ + CellInfo info; /* Size of the cell being deleted */ + u8 bPreserve; /* Keep cursor valid. 2 for CURSOR_SKIPNEXT */ assert( cursorOwnsBtShared(pCur) ); assert( pBt->inTransaction==TRANS_WRITE ); @@ -74807,31 +76309,49 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) ); assert( !hasReadConflicts(p, pCur->pgnoRoot) ); assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 ); - if( pCur->eState==CURSOR_REQUIRESEEK ){ - rc = btreeRestoreCursorPosition(pCur); - assert( rc!=SQLITE_OK || CORRUPT_DB || pCur->eState==CURSOR_VALID ); - if( rc || pCur->eState!=CURSOR_VALID ) return rc; + if( pCur->eState!=CURSOR_VALID ){ + if( pCur->eState>=CURSOR_REQUIRESEEK ){ + rc = btreeRestoreCursorPosition(pCur); + assert( rc!=SQLITE_OK || CORRUPT_DB || pCur->eState==CURSOR_VALID ); + if( rc || pCur->eState!=CURSOR_VALID ) return rc; + }else{ + return SQLITE_CORRUPT_BKPT; + } } - assert( CORRUPT_DB || pCur->eState==CURSOR_VALID ); + assert( pCur->eState==CURSOR_VALID ); iCellDepth = pCur->iPage; iCellIdx = pCur->ix; pPage = pCur->pPage; + if( pPage->nCell<=iCellIdx ){ + return SQLITE_CORRUPT_BKPT; + } pCell = findCell(pPage, iCellIdx); - if( pPage->nFree<0 && btreeComputeFreeSpace(pPage) ) return SQLITE_CORRUPT; + if( pPage->nFree<0 && btreeComputeFreeSpace(pPage) ){ + return SQLITE_CORRUPT_BKPT; + } - /* If the bPreserve flag is set to true, then the cursor position must + /* If the BTREE_SAVEPOSITION bit is on, then the cursor position must ** be preserved following this delete operation. If the current delete ** will cause a b-tree rebalance, then this is done by saving the cursor ** key and leaving the cursor in CURSOR_REQUIRESEEK state before ** returning. ** - ** Or, if the current delete will not cause a rebalance, then the cursor + ** If the current delete will not cause a rebalance, then the cursor ** will be left in CURSOR_SKIPNEXT state pointing to the entry immediately - ** before or after the deleted entry. In this case set bSkipnext to true. */ + ** before or after the deleted entry. + ** + ** The bPreserve value records which path is required: + ** + ** bPreserve==0 Not necessary to save the cursor position + ** bPreserve==1 Use CURSOR_REQUIRESEEK to save the cursor position + ** bPreserve==2 Cursor won't move. Set CURSOR_SKIPNEXT. + */ + bPreserve = (flags & BTREE_SAVEPOSITION)!=0; if( bPreserve ){ if( !pPage->leaf - || (pPage->nFree+cellSizePtr(pPage,pCell)+2)>(int)(pBt->usableSize*2/3) + || (pPage->nFree+pPage->xCellSize(pPage,pCell)+2) > + (int)(pBt->usableSize*2/3) || pPage->nCell==1 /* See dbfuzz001.test for a test case */ ){ /* A b-tree rebalance will be required after deleting this entry. @@ -74839,7 +76359,7 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ rc = saveCursorKey(pCur); if( rc ) return rc; }else{ - bSkipnext = 1; + bPreserve = 2; } } @@ -74927,7 +76447,15 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ ** been corrected, so be it. Otherwise, after balancing the leaf node, ** walk the cursor up the tree to the internal node and balance it as ** well. */ - rc = balance(pCur); + assert( pCur->pPage->nOverflow==0 ); + assert( pCur->pPage->nFree>=0 ); + if( pCur->pPage->nFree*3<=(int)pCur->pBt->usableSize*2 ){ + /* Optimization: If the free space is less than 2/3rds of the page, + ** then balance() will always be a no-op. No need to invoke it. */ + rc = SQLITE_OK; + }else{ + rc = balance(pCur); + } if( rc==SQLITE_OK && pCur->iPage>iCellDepth ){ releasePageNotNull(pCur->pPage); pCur->iPage--; @@ -74939,8 +76467,8 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ } if( rc==SQLITE_OK ){ - if( bSkipnext ){ - assert( bPreserve && (pCur->iPage==iCellDepth || CORRUPT_DB) ); + if( bPreserve>1 ){ + assert( (pCur->iPage==iCellDepth || CORRUPT_DB) ); assert( pPage==pCur->pPage || CORRUPT_DB ); assert( (pPage->nCell>0 || CORRUPT_DB) && iCellIdx<=pPage->nCell ); pCur->eState = CURSOR_SKIPNEXT; @@ -75150,7 +76678,7 @@ static int clearDatabasePage( rc = getAndInitPage(pBt, pgno, &pPage, 0, 0); if( rc ) return rc; if( (pBt->openFlags & BTREE_SINGLE)==0 - && sqlite3PagerPageRefcount(pPage->pDbPage)!=1 + && sqlite3PagerPageRefcount(pPage->pDbPage) != (1 + (pgno==1)) ){ rc = SQLITE_CORRUPT_BKPT; goto cleardatabasepage_out; @@ -76530,14 +78058,13 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){ if( i==1 ){ Parse sParse; int rc = 0; - memset(&sParse, 0, sizeof(sParse)); - sParse.db = pDb; + sqlite3ParseObjectInit(&sParse,pDb); if( sqlite3OpenTempDatabase(&sParse) ){ sqlite3ErrorWithMsg(pErrorDb, sParse.rc, "%s", sParse.zErrMsg); rc = SQLITE_ERROR; } sqlite3DbFree(pErrorDb, sParse.zErrMsg); - sqlite3ParserReset(&sParse); + sqlite3ParseObjectReset(&sParse); if( rc ){ return 0; } @@ -77423,7 +78950,11 @@ SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){ assert( !sqlite3VdbeMemIsRowSet(pMem) ); assert( desiredEnc==SQLITE_UTF8 || desiredEnc==SQLITE_UTF16LE || desiredEnc==SQLITE_UTF16BE ); - if( !(pMem->flags&MEM_Str) || pMem->enc==desiredEnc ){ + if( !(pMem->flags&MEM_Str) ){ + pMem->enc = desiredEnc; + return SQLITE_OK; + } + if( pMem->enc==desiredEnc ){ return SQLITE_OK; } assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); @@ -77672,9 +79203,10 @@ SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){ Mem t; assert( pFunc!=0 ); assert( pMem!=0 ); + assert( pMem->db!=0 ); assert( pFunc->xFinalize!=0 ); assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef ); - assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); + assert( sqlite3_mutex_held(pMem->db->mutex) ); memset(&ctx, 0, sizeof(ctx)); memset(&t, 0, sizeof(t)); t.flags = MEM_Null; @@ -77682,6 +79214,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){ ctx.pOut = &t; ctx.pMem = pMem; ctx.pFunc = pFunc; + ctx.enc = ENC(t.db); pFunc->xFinalize(&ctx); /* IMP: R-24505-23230 */ assert( (pMem->flags & MEM_Dyn)==0 ); if( pMem->szMalloc>0 ) sqlite3DbFreeNN(pMem->db, pMem->zMalloc); @@ -77703,12 +79236,14 @@ SQLITE_PRIVATE int sqlite3VdbeMemAggValue(Mem *pAccum, Mem *pOut, FuncDef *pFunc assert( pFunc!=0 ); assert( pFunc->xValue!=0 ); assert( (pAccum->flags & MEM_Null)!=0 || pFunc==pAccum->u.pDef ); - assert( pAccum->db==0 || sqlite3_mutex_held(pAccum->db->mutex) ); + assert( pAccum->db!=0 ); + assert( sqlite3_mutex_held(pAccum->db->mutex) ); memset(&ctx, 0, sizeof(ctx)); sqlite3VdbeMemSetNull(pOut); ctx.pOut = pOut; ctx.pMem = pAccum; ctx.pFunc = pFunc; + ctx.enc = ENC(pAccum->db); pFunc->xValue(&ctx); return ctx.isError; } @@ -77774,6 +79309,14 @@ SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p){ } } +/* Like sqlite3VdbeMemRelease() but faster for cases where we +** know in advance that the Mem is not MEM_Dyn or MEM_Agg. +*/ +SQLITE_PRIVATE void sqlite3VdbeMemReleaseMalloc(Mem *p){ + assert( !VdbeMemDynamic(p) ); + if( p->szMalloc ) vdbeMemClear(p); +} + /* ** Convert a 64-bit IEEE double into a 64-bit signed integer. ** If the double is out of range of a 64-bit signed integer then @@ -77815,12 +79358,12 @@ static SQLITE_NOINLINE i64 doubleToInt64(double r){ ** ** If pMem represents a string value, its encoding might be changed. */ -static SQLITE_NOINLINE i64 memIntValue(Mem *pMem){ +static SQLITE_NOINLINE i64 memIntValue(const Mem *pMem){ i64 value = 0; sqlite3Atoi64(pMem->z, &value, pMem->n, pMem->enc); return value; } -SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem *pMem){ +SQLITE_PRIVATE i64 sqlite3VdbeIntValue(const Mem *pMem){ int flags; assert( pMem!=0 ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); @@ -78135,6 +79678,7 @@ SQLITE_PRIVATE void sqlite3VdbeMemSetPointer( void (*xDestructor)(void*) ){ assert( pMem->flags==MEM_Null ); + vdbeMemClear(pMem); pMem->u.zPType = zPType ? zPType : ""; pMem->z = pPtr; pMem->flags = MEM_Null|MEM_Dyn|MEM_Subtype|MEM_Term; @@ -78317,6 +79861,13 @@ SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){ ** stored without allocating memory, then it is. If a memory allocation ** is required to store the string, then value of pMem is unchanged. In ** either case, SQLITE_TOOBIG is returned. +** +** The "enc" parameter is the text encoding for the string, or zero +** to store a blob. +** +** If n is negative, then the string consists of all bytes up to but +** excluding the first zero character. The n parameter must be +** non-negative for blobs. */ SQLITE_PRIVATE int sqlite3VdbeMemSetStr( Mem *pMem, /* Memory cell to set to string value */ @@ -78327,11 +79878,12 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr( ){ i64 nByte = n; /* New value for pMem->n */ int iLimit; /* Maximum allowed string or blob size */ - u16 flags = 0; /* New value for pMem->flags */ + u16 flags; /* New value for pMem->flags */ assert( pMem!=0 ); assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) ); assert( !sqlite3VdbeMemIsRowSet(pMem) ); + assert( enc!=0 || n>=0 ); /* If z is a NULL pointer, set pMem to contain an SQL NULL. */ if( !z ){ @@ -78344,7 +79896,6 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr( }else{ iLimit = SQLITE_MAX_LENGTH; } - flags = (enc==0?MEM_Blob:MEM_Str); if( nByte<0 ){ assert( enc!=0 ); if( enc==SQLITE_UTF8 ){ @@ -78352,7 +79903,23 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr( }else{ for(nByte=0; nByte<=iLimit && (z[nByte] | z[nByte+1]); nByte+=2){} } - flags |= MEM_Term; + flags= MEM_Str|MEM_Term; + }else if( enc==0 ){ + flags = MEM_Blob; + enc = SQLITE_UTF8; + }else{ + flags = MEM_Str; + } + if( nByte>iLimit ){ + if( xDel && xDel!=SQLITE_TRANSIENT ){ + if( xDel==SQLITE_DYNAMIC ){ + sqlite3DbFree(pMem->db, (void*)z); + }else{ + xDel((void*)z); + } + } + sqlite3VdbeMemSetNull(pMem); + return sqlite3ErrorToParser(pMem->db, SQLITE_TOOBIG); } /* The following block sets the new values of Mem.z and Mem.xDel. It @@ -78364,9 +79931,6 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr( if( flags&MEM_Term ){ nAlloc += (enc==SQLITE_UTF8?1:2); } - if( nByte>iLimit ){ - return sqlite3ErrorToParser(pMem->db, SQLITE_TOOBIG); - } testcase( nAlloc==0 ); testcase( nAlloc==31 ); testcase( nAlloc==32 ); @@ -78388,16 +79952,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr( pMem->n = (int)(nByte & 0x7fffffff); pMem->flags = flags; - if( enc ){ - pMem->enc = enc; -#ifdef SQLITE_ENABLE_SESSION - }else if( pMem->db==0 ){ - pMem->enc = SQLITE_UTF8; -#endif - }else{ - assert( pMem->db!=0 ); - pMem->enc = ENC(pMem->db); - } + pMem->enc = enc; #ifndef SQLITE_OMIT_UTF16 if( enc>SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){ @@ -78405,9 +79960,6 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr( } #endif - if( nByte>iLimit ){ - return sqlite3ErrorToParser(pMem->db, SQLITE_TOOBIG); - } return SQLITE_OK; } @@ -78685,10 +80237,12 @@ static int valueFromFunction( goto value_from_function_out; } - assert( pCtx->pParse->rc==SQLITE_OK ); + testcase( pCtx->pParse->rc==SQLITE_ERROR ); + testcase( pCtx->pParse->rc==SQLITE_OK ); memset(&ctx, 0, sizeof(ctx)); ctx.pOut = pVal; ctx.pFunc = pFunc; + ctx.enc = ENC(db); pFunc->xSFunc(&ctx, nVal, apVal); if( ctx.isError ){ rc = ctx.isError; @@ -78749,11 +80303,7 @@ static int valueFromExpr( assert( pExpr!=0 ); while( (op = pExpr->op)==TK_UPLUS || op==TK_SPAN ) pExpr = pExpr->pLeft; -#if defined(SQLITE_ENABLE_STAT4) if( op==TK_REGISTER ) op = pExpr->op2; -#else - if( NEVER(op==TK_REGISTER) ) op = pExpr->op2; -#endif /* Compressed expressions only appear when parsing the DEFAULT clause ** on a table column definition, and hence only when pCtx==0. This @@ -78768,8 +80318,8 @@ static int valueFromExpr( rc = valueFromExpr(db, pExpr->pLeft, enc, aff, ppVal, pCtx); testcase( rc!=SQLITE_OK ); if( *ppVal ){ - sqlite3VdbeMemCast(*ppVal, aff, SQLITE_UTF8); - sqlite3ValueApplyAffinity(*ppVal, affinity, SQLITE_UTF8); + sqlite3VdbeMemCast(*ppVal, aff, enc); + sqlite3ValueApplyAffinity(*ppVal, affinity, enc); } return rc; } @@ -78868,7 +80418,7 @@ static int valueFromExpr( no_mem: #ifdef SQLITE_ENABLE_STAT4 - if( pCtx==0 || pCtx->pParse->nErr==0 ) + if( pCtx==0 || NEVER(pCtx->pParse->nErr==0) ) #endif sqlite3OomFault(db); sqlite3DbFree(db, zVal); @@ -79203,7 +80753,7 @@ SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse *pParse){ p->pNext = db->pVdbe; p->pPrev = 0; db->pVdbe = p; - p->iVdbeMagic = VDBE_MAGIC_INIT; + assert( p->eVdbeState==VDBE_INIT_STATE ); p->pParse = pParse; pParse->pVdbe = p; assert( pParse->aLabel==0 ); @@ -79348,7 +80898,7 @@ static int growOpArray(Vdbe *v, int nOp){ return SQLITE_NOMEM; } - assert( nOp<=(1024/sizeof(Op)) ); + assert( nOp<=(int)(1024/sizeof(Op)) ); assert( nNew>=(v->nOpAlloc+nOp) ); pNew = sqlite3DbRealloc(p->db, v->aOp, nNew*sizeof(Op)); if( pNew ){ @@ -79404,7 +80954,7 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){ VdbeOp *pOp; i = p->nOp; - assert( p->iVdbeMagic==VDBE_MAGIC_INIT ); + assert( p->eVdbeState==VDBE_INIT_STATE ); assert( op>=0 && op<0xff ); if( p->nOpAlloc<=i ){ return growOp3(p, op, p1, p2, p3); @@ -79549,6 +81099,7 @@ SQLITE_PRIVATE int sqlite3VdbeAddFunctionCall( addr = sqlite3VdbeAddOp4(v, eCallCtx ? OP_PureFunc : OP_Function, p1, p2, p3, (char*)pCtx, P4_FUNCCTX); sqlite3VdbeChangeP5(v, eCallCtx & NC_SelfRef); + sqlite3MayAbort(pParse); return addr; } @@ -79736,7 +81287,7 @@ static SQLITE_NOINLINE void resizeResolveLabel(Parse *p, Vdbe *v, int j){ SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe *v, int x){ Parse *p = v->pParse; int j = ADDR(x); - assert( v->iVdbeMagic==VDBE_MAGIC_INIT ); + assert( v->eVdbeState==VDBE_INIT_STATE ); assert( j<-p->nLabel ); assert( j>=0 ); #ifdef SQLITE_DEBUG @@ -79756,14 +81307,20 @@ SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe *v, int x){ ** Mark the VDBE as one that can only be run one time. */ SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe *p){ - p->runOnlyOnce = 1; + sqlite3VdbeAddOp2(p, OP_Expire, 1, 1); } /* -** Mark the VDBE as one that can only be run multiple times. +** Mark the VDBE as one that can be run multiple times. */ SQLITE_PRIVATE void sqlite3VdbeReusable(Vdbe *p){ - p->runOnlyOnce = 0; + int i; + for(i=1; ALWAYS(inOp); i++){ + if( ALWAYS(p->aOp[i].opcode==OP_Expire) ){ + p->aOp[1].opcode = OP_Noop; + break; + } + } } #ifdef SQLITE_DEBUG /* sqlite3AssertMayAbort() logic */ @@ -79867,6 +81424,8 @@ SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){ int hasInitCoroutine = 0; Op *pOp; VdbeOpIter sIter; + + if( v==0 ) return 0; memset(&sIter, 0, sizeof(sIter)); sIter.v = v; @@ -79876,6 +81435,7 @@ SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){ || opcode==OP_VDestroy || opcode==OP_VCreate || opcode==OP_ParseSchema + || opcode==OP_Function || opcode==OP_PureFunc || ((opcode==OP_Halt || opcode==OP_HaltIfNull) && ((pOp->p1)!=SQLITE_OK && pOp->p2==OE_Abort)) ){ @@ -79950,7 +81510,7 @@ SQLITE_PRIVATE void sqlite3VdbeAssertAbortable(Vdbe *p){ ** (3) Update the Vdbe.readOnly and Vdbe.bIsReader flags to accurately ** indicate what the prepared statement actually does. ** -** (4) Initialize the p4.xAdvance pointer on opcodes that use it. +** (4) (discontinued) ** ** (5) Reclaim the memory allocated for storing labels. ** @@ -79996,25 +81556,6 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ p->bIsReader = 1; break; } - case OP_Next: - case OP_SorterNext: { - pOp->p4.xAdvance = sqlite3BtreeNext; - pOp->p4type = P4_ADVANCE; - /* The code generator never codes any of these opcodes as a jump - ** to a label. They are always coded as a jump backwards to a - ** known address */ - assert( pOp->p2>=0 ); - break; - } - case OP_Prev: { - pOp->p4.xAdvance = sqlite3BtreePrevious; - pOp->p4type = P4_ADVANCE; - /* The code generator never codes any of these opcodes as a jump - ** to a label. They are always coded as a jump backwards to a - ** known address */ - assert( pOp->p2>=0 ); - break; - } #ifndef SQLITE_OMIT_VIRTUALTABLE case OP_VUpdate: { if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2; @@ -80050,18 +81591,104 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ if( pOp==p->aOp ) break; pOp--; } - sqlite3DbFree(p->db, pParse->aLabel); - pParse->aLabel = 0; + if( aLabel ){ + sqlite3DbFreeNN(p->db, pParse->aLabel); + pParse->aLabel = 0; + } pParse->nLabel = 0; *pMaxFuncArgs = nMaxArgs; assert( p->bIsReader!=0 || DbMaskAllZero(p->btreeMask) ); } +#ifdef SQLITE_DEBUG +/* +** Check to see if a subroutine contains a jump to a location outside of +** the subroutine. If a jump outside the subroutine is detected, add code +** that will cause the program to halt with an error message. +** +** The subroutine consists of opcodes between iFirst and iLast. Jumps to +** locations within the subroutine are acceptable. iRetReg is a register +** that contains the return address. Jumps to outside the range of iFirst +** through iLast are also acceptable as long as the jump destination is +** an OP_Return to iReturnAddr. +** +** A jump to an unresolved label means that the jump destination will be +** beyond the current address. That is normally a jump to an early +** termination and is consider acceptable. +** +** This routine only runs during debug builds. The purpose is (of course) +** to detect invalid escapes out of a subroutine. The OP_Halt opcode +** is generated rather than an assert() or other error, so that ".eqp full" +** will still work to show the original bytecode, to aid in debugging. +*/ +SQLITE_PRIVATE void sqlite3VdbeNoJumpsOutsideSubrtn( + Vdbe *v, /* The byte-code program under construction */ + int iFirst, /* First opcode of the subroutine */ + int iLast, /* Last opcode of the subroutine */ + int iRetReg /* Subroutine return address register */ +){ + VdbeOp *pOp; + Parse *pParse; + int i; + sqlite3_str *pErr = 0; + assert( v!=0 ); + pParse = v->pParse; + assert( pParse!=0 ); + if( pParse->nErr ) return; + assert( iLast>=iFirst ); + assert( iLastnOp ); + pOp = &v->aOp[iFirst]; + for(i=iFirst; i<=iLast; i++, pOp++){ + if( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP)!=0 ){ + int iDest = pOp->p2; /* Jump destination */ + if( iDest==0 ) continue; + if( pOp->opcode==OP_Gosub ) continue; + if( iDest<0 ){ + int j = ADDR(iDest); + assert( j>=0 ); + if( j>=-pParse->nLabel || pParse->aLabel[j]<0 ){ + continue; + } + iDest = pParse->aLabel[j]; + } + if( iDestiLast ){ + int j = iDest; + for(; jnOp; j++){ + VdbeOp *pX = &v->aOp[j]; + if( pX->opcode==OP_Return ){ + if( pX->p1==iRetReg ) break; + continue; + } + if( pX->opcode==OP_Noop ) continue; + if( pX->opcode==OP_Explain ) continue; + if( pErr==0 ){ + pErr = sqlite3_str_new(0); + }else{ + sqlite3_str_appendchar(pErr, 1, '\n'); + } + sqlite3_str_appendf(pErr, + "Opcode at %d jumps to %d which is outside the " + "subroutine at %d..%d", + i, iDest, iFirst, iLast); + break; + } + } + } + } + if( pErr ){ + char *zErr = sqlite3_str_finish(pErr); + sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_INTERNAL, OE_Abort, 0, zErr, 0); + sqlite3_free(zErr); + sqlite3MayAbort(pParse); + } +} +#endif /* SQLITE_DEBUG */ + /* ** Return the address of the next instruction to be inserted. */ SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe *p){ - assert( p->iVdbeMagic==VDBE_MAGIC_INIT ); + assert( p->eVdbeState==VDBE_INIT_STATE ); return p->nOp; } @@ -80146,7 +81773,7 @@ SQLITE_PRIVATE VdbeOp *sqlite3VdbeAddOpList( int i; VdbeOp *pOut, *pFirst; assert( nOp>0 ); - assert( p->iVdbeMagic==VDBE_MAGIC_INIT ); + assert( p->eVdbeState==VDBE_INIT_STATE ); if( p->nOp + nOp > p->nOpAlloc && growOpArray(p, nOp) ){ return 0; } @@ -80298,7 +81925,6 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){ case P4_REAL: case P4_INT64: case P4_DYNAMIC: - case P4_DYNBLOB: case P4_INTARRAY: { sqlite3DbFree(db, p4); break; @@ -80338,13 +81964,16 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){ ** nOp entries. */ static void vdbeFreeOpArray(sqlite3 *db, Op *aOp, int nOp){ + assert( nOp>=0 ); if( aOp ){ - Op *pOp; - for(pOp=&aOp[nOp-1]; pOp>=aOp; pOp--){ + Op *pOp = &aOp[nOp-1]; + while(1){ /* Exit via break */ if( pOp->p4type <= P4_FREE_IF_LE ) freeP4(db, pOp->p4type, pOp->p4.p); #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS sqlite3DbFree(db, pOp->zComment); #endif + if( pOp==aOp ) break; + pOp--; } sqlite3DbFreeNN(db, aOp); } @@ -80406,7 +82035,7 @@ SQLITE_PRIVATE void sqlite3VdbeReleaseRegisters( u32 mask, /* Mask of registers to NOT release */ int bUndefine /* If true, mark registers as undefined */ ){ - if( N==0 ) return; + if( N==0 || OptimizationDisabled(pParse->db, SQLITE_ReleaseReg) ) return; assert( pParse->pVdbe ); assert( iFirst>=1 ); assert( iFirst+N-1<=pParse->nMem ); @@ -80470,7 +82099,7 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int sqlite3 *db; assert( p!=0 ); db = p->db; - assert( p->iVdbeMagic==VDBE_MAGIC_INIT ); + assert( p->eVdbeState==VDBE_INIT_STATE ); assert( p->aOp!=0 || db->mallocFailed ); if( db->mallocFailed ){ if( n!=P4_VTAB ) freeP4(db, n, (void*)*(char**)&zP4); @@ -80546,8 +82175,7 @@ SQLITE_PRIVATE void sqlite3VdbeSetP4KeyInfo(Parse *pParse, Index *pIdx){ */ static void vdbeVComment(Vdbe *p, const char *zFormat, va_list ap){ assert( p->nOp>0 || p->aOp==0 ); - assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed - || p->pParse->nErr>0 ); + assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->pParse->nErr>0 ); if( p->nOp ){ assert( p->aOp ); sqlite3DbFree(p->db, p->aOp[p->nOp-1].zComment); @@ -80599,7 +82227,7 @@ SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){ /* C89 specifies that the constant "dummy" will be initialized to all ** zeros, which is correct. MSVC generates a warning, nevertheless. */ static VdbeOp dummy; /* Ignore the MSVC warning about no initializer */ - assert( p->iVdbeMagic==VDBE_MAGIC_INIT ); + assert( p->eVdbeState==VDBE_INIT_STATE ); if( addr<0 ){ addr = p->nOp - 1; } @@ -80666,8 +82294,11 @@ SQLITE_PRIVATE char *sqlite3VdbeDisplayComment( if( c=='4' ){ sqlite3_str_appendall(&x, zP4); }else if( c=='X' ){ - sqlite3_str_appendall(&x, pOp->zComment); - seenCom = 1; + if( pOp->zComment && pOp->zComment[0] ){ + sqlite3_str_appendall(&x, pOp->zComment); + seenCom = 1; + break; + } }else{ int v1 = translateP(c, pOp); int v2; @@ -80896,10 +82527,6 @@ SQLITE_PRIVATE char *sqlite3VdbeDisplayP4(sqlite3 *db, Op *pOp){ zP4 = "program"; break; } - case P4_DYNBLOB: - case P4_ADVANCE: { - break; - } case P4_TABLE: { zP4 = pOp->p4.pTab->zName; break; @@ -81031,21 +82658,40 @@ SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE *pOut, int pc, VdbeOp *pOp){ /* ** Initialize an array of N Mem element. +** +** This is a high-runner, so only those fields that really do need to +** be initialized are set. The Mem structure is organized so that +** the fields that get initialized are nearby and hopefully on the same +** cache line. +** +** Mem.flags = flags +** Mem.db = db +** Mem.szMalloc = 0 +** +** All other fields of Mem can safely remain uninitialized for now. They +** will be initialized before use. */ static void initMemArray(Mem *p, int N, sqlite3 *db, u16 flags){ - while( (N--)>0 ){ - p->db = db; - p->flags = flags; - p->szMalloc = 0; + if( N>0 ){ + do{ + p->flags = flags; + p->db = db; + p->szMalloc = 0; #ifdef SQLITE_DEBUG - p->pScopyFrom = 0; + p->pScopyFrom = 0; #endif - p++; + p++; + }while( (--N)>0 ); } } /* -** Release an array of N Mem elements +** Release auxiliary memory held in an array of N Mem elements. +** +** After this routine returns, all Mem elements in the array will still +** be valid. Those Mem elements that were not holding auxiliary resources +** will be unchanged. Mem elements which had something freed will be +** set to MEM_Undefined. */ static void releaseMemArray(Mem *p, int N){ if( p && N ){ @@ -81078,12 +82724,17 @@ static void releaseMemArray(Mem *p, int N){ if( p->flags&(MEM_Agg|MEM_Dyn) ){ testcase( (p->flags & MEM_Dyn)!=0 && p->xDel==sqlite3VdbeFrameMemDel ); sqlite3VdbeMemRelease(p); + p->flags = MEM_Undefined; }else if( p->szMalloc ){ sqlite3DbFreeNN(db, p->zMalloc); p->szMalloc = 0; + p->flags = MEM_Undefined; } - - p->flags = MEM_Undefined; +#ifdef SQLITE_DEBUG + else{ + p->flags = MEM_Undefined; + } +#endif }while( (++p)nChildMem]; assert( sqlite3VdbeFrameIsValid(p) ); for(i=0; inChildCsr; i++){ - sqlite3VdbeFreeCursor(p->v, apCsr[i]); + if( apCsr[i] ) sqlite3VdbeFreeCursorNN(p->v, apCsr[i]); } releaseMemArray(aMem, p->nChildMem); sqlite3VdbeDeleteAuxData(p->v->db, &p->pAuxData, -1, 0); @@ -81281,7 +82932,7 @@ SQLITE_PRIVATE int sqlite3VdbeList( Op *pOp; /* Current opcode */ assert( p->explain ); - assert( p->iVdbeMagic==VDBE_MAGIC_RUN ); + assert( p->eVdbeState==VDBE_RUN_STATE ); assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY || p->rc==SQLITE_NOMEM ); /* Even though this opcode does not use dynamic strings for @@ -81436,11 +83087,11 @@ struct ReusableSpace { static void *allocSpace( struct ReusableSpace *p, /* Bulk memory available for allocation */ void *pBuf, /* Pointer to a prior allocation */ - sqlite3_int64 nByte /* Bytes of memory needed */ + sqlite3_int64 nByte /* Bytes of memory needed. */ ){ assert( EIGHT_BYTE_ALIGNMENT(p->pSpace) ); if( pBuf==0 ){ - nByte = ROUND8(nByte); + nByte = ROUND8P(nByte); if( nByte <= p->nFree ){ p->nFree -= nByte; pBuf = &p->pSpace[p->nFree]; @@ -81461,14 +83112,15 @@ SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe *p){ int i; #endif assert( p!=0 ); - assert( p->iVdbeMagic==VDBE_MAGIC_INIT || p->iVdbeMagic==VDBE_MAGIC_RESET ); + assert( p->eVdbeState==VDBE_INIT_STATE + || p->eVdbeState==VDBE_READY_STATE + || p->eVdbeState==VDBE_HALT_STATE ); /* There should be at least one opcode. */ assert( p->nOp>0 ); - /* Set the magic to VDBE_MAGIC_RUN sooner rather than later. */ - p->iVdbeMagic = VDBE_MAGIC_RUN; + p->eVdbeState = VDBE_READY_STATE; #ifdef SQLITE_DEBUG for(i=0; inMem; i++){ @@ -81524,7 +83176,7 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( assert( p!=0 ); assert( p->nOp>0 ); assert( pParse!=0 ); - assert( p->iVdbeMagic==VDBE_MAGIC_INIT ); + assert( p->eVdbeState==VDBE_INIT_STATE ); assert( pParse==p->pParse ); p->pVList = pParse->pVList; pParse->pVList = 0; @@ -81547,7 +83199,7 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( ** opcode array. This extra memory will be reallocated for other elements ** of the prepared statement. */ - n = ROUND8(sizeof(Op)*p->nOp); /* Bytes of opcode memory used */ + n = ROUND8P(sizeof(Op)*p->nOp); /* Bytes of opcode memory used */ x.pSpace = &((u8*)p->aOp)[n]; /* Unused opcode memory */ assert( EIGHT_BYTE_ALIGNMENT(x.pSpace) ); x.nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused memory */ @@ -81635,11 +83287,9 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( ** happens to hold. */ SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){ - if( pCx==0 ){ - return; - } - assert( pCx->pBtx==0 || pCx->eCurType==CURTYPE_BTREE ); - assert( pCx->pBtx==0 || pCx->isEphemeral ); + if( pCx ) sqlite3VdbeFreeCursorNN(p,pCx); +} +SQLITE_PRIVATE void sqlite3VdbeFreeCursorNN(Vdbe *p, VdbeCursor *pCx){ switch( pCx->eCurType ){ case CURTYPE_SORTER: { sqlite3VdbeSorterClose(p->db, pCx); @@ -81667,14 +83317,12 @@ SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){ ** Close all cursors in the current frame. */ static void closeCursorsInFrame(Vdbe *p){ - if( p->apCsr ){ - int i; - for(i=0; inCursor; i++){ - VdbeCursor *pC = p->apCsr[i]; - if( pC ){ - sqlite3VdbeFreeCursor(p, pC); - p->apCsr[i] = 0; - } + int i; + for(i=0; inCursor; i++){ + VdbeCursor *pC = p->apCsr[i]; + if( pC ){ + sqlite3VdbeFreeCursorNN(p, pC); + p->apCsr[i] = 0; } } } @@ -81723,9 +83371,7 @@ static void closeAllCursors(Vdbe *p){ } assert( p->nFrame==0 ); closeCursorsInFrame(p); - if( p->aMem ){ - releaseMemArray(p->aMem, p->nMem); - } + releaseMemArray(p->aMem, p->nMem); while( p->pDelFrame ){ VdbeFrame *pDel = p->pDelFrame; p->pDelFrame = pDel->pParent; @@ -82165,7 +83811,8 @@ SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *p, int deferred){ p->rc = SQLITE_CONSTRAINT_FOREIGNKEY; p->errorAction = OE_Abort; sqlite3VdbeError(p, "FOREIGN KEY constraint failed"); - return SQLITE_ERROR; + if( (p->prepFlags & SQLITE_PREPARE_SAVESQL)==0 ) return SQLITE_ERROR; + return SQLITE_CONSTRAINT_FOREIGNKEY; } return SQLITE_OK; } @@ -82204,9 +83851,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){ ** one, or the complete transaction if there is no statement transaction. */ - if( p->iVdbeMagic!=VDBE_MAGIC_RUN ){ - return SQLITE_OK; - } + assert( p->eVdbeState==VDBE_RUN_STATE ); if( db->mallocFailed ){ p->rc = SQLITE_NOMEM_BKPT; } @@ -82215,7 +83860,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){ /* No commit or rollback needed if the program never started or if the ** SQL statement does not read or write a database file. */ - if( p->pc>=0 && p->bIsReader ){ + if( p->bIsReader ){ int mrc; /* Primary error code from p->rc */ int eStatementOp = 0; int isSpecialError; /* Set to true if a 'special' error */ @@ -82363,15 +84008,13 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){ } /* We have successfully halted and closed the VM. Record this fact. */ - if( p->pc>=0 ){ - db->nVdbeActive--; - if( !p->readOnly ) db->nVdbeWrite--; - if( p->bIsReader ) db->nVdbeRead--; - assert( db->nVdbeActive>=db->nVdbeRead ); - assert( db->nVdbeRead>=db->nVdbeWrite ); - assert( db->nVdbeWrite>=0 ); - } - p->iVdbeMagic = VDBE_MAGIC_HALT; + db->nVdbeActive--; + if( !p->readOnly ) db->nVdbeWrite--; + if( p->bIsReader ) db->nVdbeRead--; + assert( db->nVdbeActive>=db->nVdbeRead ); + assert( db->nVdbeRead>=db->nVdbeWrite ); + assert( db->nVdbeWrite>=0 ); + p->eVdbeState = VDBE_HALT_STATE; checkActiveVdbeCnt(db); if( db->mallocFailed ){ p->rc = SQLITE_NOMEM_BKPT; @@ -82420,6 +84063,7 @@ SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p){ sqlite3ValueSetNull(db->pErr); } db->errCode = rc; + db->errByteOffset = -1; return rc; } @@ -82452,8 +84096,8 @@ static void vdbeInvokeSqllog(Vdbe *v){ ** again. ** ** To look at it another way, this routine resets the state of the -** virtual machine from VDBE_MAGIC_RUN or VDBE_MAGIC_HALT back to -** VDBE_MAGIC_INIT. +** virtual machine from VDBE_RUN_STATE or VDBE_HALT_STATE back to +** VDBE_READY_STATE. */ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){ #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) @@ -82467,7 +84111,7 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){ ** error, then it might not have been halted properly. So halt ** it now. */ - sqlite3VdbeHalt(p); + if( p->eVdbeState==VDBE_RUN_STATE ) sqlite3VdbeHalt(p); /* If the VDBE has been run even partially, then transfer the error code ** and error message from the VDBE into the main database structure. But @@ -82481,13 +84125,6 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){ }else{ db->errCode = p->rc; } - if( p->runOnlyOnce ) p->expired = 1; - }else if( p->rc && p->expired ){ - /* The expired flag was set on the VDBE before the first call - ** to sqlite3_step(). For consistency (since sqlite3_step() was - ** called), set the database error in this case as well. - */ - sqlite3ErrorWithMsg(db, p->rc, p->zErrMsg ? "%s" : 0, p->zErrMsg); } /* Reset register contents and reclaim error message memory. @@ -82544,7 +84181,6 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){ } } #endif - p->iVdbeMagic = VDBE_MAGIC_RESET; return p->rc & db->errMask; } @@ -82554,7 +84190,10 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){ */ SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe *p){ int rc = SQLITE_OK; - if( p->iVdbeMagic==VDBE_MAGIC_RUN || p->iVdbeMagic==VDBE_MAGIC_HALT ){ + assert( VDBE_RUN_STATE>VDBE_READY_STATE ); + assert( VDBE_HALT_STATE>VDBE_READY_STATE ); + assert( VDBE_INIT_STATEeVdbeState>=VDBE_READY_STATE ){ rc = sqlite3VdbeReset(p); assert( (rc & p->db->errMask)==rc ); } @@ -82606,22 +84245,24 @@ SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(sqlite3 *db, AuxData **pp, int iOp, ** VdbeDelete() also unlinks the Vdbe from the list of VMs associated with ** the database connection and frees the object itself. */ -SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){ +static void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){ SubProgram *pSub, *pNext; assert( p->db==0 || p->db==db ); - releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); + if( p->aColName ){ + releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); + sqlite3DbFreeNN(db, p->aColName); + } for(pSub=p->pProgram; pSub; pSub=pNext){ pNext = pSub->pNext; vdbeFreeOpArray(db, pSub->aOp, pSub->nOp); sqlite3DbFree(db, pSub); } - if( p->iVdbeMagic!=VDBE_MAGIC_INIT ){ + if( p->eVdbeState!=VDBE_INIT_STATE ){ releaseMemArray(p->aVar, p->nVar); - sqlite3DbFree(db, p->pVList); - sqlite3DbFree(db, p->pFree); + if( p->pVList ) sqlite3DbFreeNN(db, p->pVList); + if( p->pFree ) sqlite3DbFreeNN(db, p->pFree); } vdbeFreeOpArray(db, p->aOp, p->nOp); - sqlite3DbFree(db, p->aColName); sqlite3DbFree(db, p->zSql); #ifdef SQLITE_ENABLE_NORMALIZE sqlite3DbFree(db, p->zNormSql); @@ -82654,17 +84295,17 @@ SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){ db = p->db; assert( sqlite3_mutex_held(db->mutex) ); sqlite3VdbeClearObject(db, p); - if( p->pPrev ){ - p->pPrev->pNext = p->pNext; - }else{ - assert( db->pVdbe==p ); - db->pVdbe = p->pNext; - } - if( p->pNext ){ - p->pNext->pPrev = p->pPrev; + if( db->pnBytesFreed==0 ){ + if( p->pPrev ){ + p->pPrev->pNext = p->pNext; + }else{ + assert( db->pVdbe==p ); + db->pVdbe = p->pNext; + } + if( p->pNext ){ + p->pNext->pPrev = p->pPrev; + } } - p->iVdbeMagic = VDBE_MAGIC_DEAD; - p->db = 0; sqlite3DbFreeNN(db, p); } @@ -82699,7 +84340,7 @@ SQLITE_PRIVATE int SQLITE_NOINLINE sqlite3VdbeFinishMoveto(VdbeCursor *p){ ** is supposed to be pointing. If the row was deleted out from under the ** cursor, set the cursor to point to a NULL row. */ -static int SQLITE_NOINLINE handleMovedCursor(VdbeCursor *p){ +SQLITE_PRIVATE int SQLITE_NOINLINE sqlite3VdbeHandleMovedCursor(VdbeCursor *p){ int isDifferentRow, rc; assert( p->eCurType==CURTYPE_BTREE ); assert( p->uc.pCursor!=0 ); @@ -82715,41 +84356,9 @@ static int SQLITE_NOINLINE handleMovedCursor(VdbeCursor *p){ ** if need be. Return any I/O error from the restore operation. */ SQLITE_PRIVATE int sqlite3VdbeCursorRestore(VdbeCursor *p){ - assert( p->eCurType==CURTYPE_BTREE ); - if( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){ - return handleMovedCursor(p); - } - return SQLITE_OK; -} - -/* -** Make sure the cursor p is ready to read or write the row to which it -** was last positioned. Return an error code if an OOM fault or I/O error -** prevents us from positioning the cursor to its correct position. -** -** If a MoveTo operation is pending on the given cursor, then do that -** MoveTo now. If no move is pending, check to see if the row has been -** deleted out from under the cursor and if it has, mark the row as -** a NULL row. -** -** If the cursor is already pointing to the correct row and that row has -** not been deleted out from under the cursor, then this routine is a no-op. -*/ -SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor **pp, u32 *piCol){ - VdbeCursor *p = *pp; - assert( p->eCurType==CURTYPE_BTREE || p->eCurType==CURTYPE_PSEUDO ); - if( p->deferredMoveto ){ - u32 iMap; - assert( !p->isEphemeral ); - if( p->aAltMap && (iMap = p->aAltMap[1+*piCol])>0 && !p->nullRow ){ - *pp = p->pAltCursor; - *piCol = iMap - 1; - return SQLITE_OK; - } - return sqlite3VdbeFinishMoveto(p); - } + assert( p->eCurType==CURTYPE_BTREE || IsNullCursor(p) ); if( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){ - return handleMovedCursor(p); + return sqlite3VdbeHandleMovedCursor(p); } return SQLITE_OK; } @@ -82760,7 +84369,7 @@ SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor **pp, u32 *piCol){ ** sqlite3VdbeSerialType() ** sqlite3VdbeSerialTypeLen() ** sqlite3VdbeSerialLen() -** sqlite3VdbeSerialPut() +** sqlite3VdbeSerialPut() <--- in-lined into OP_MakeRecord as of 2022-04-02 ** sqlite3VdbeSerialGet() ** ** encapsulate the code that serializes values for storage in SQLite @@ -82872,7 +84481,7 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem *pMem, int file_format, u32 *pLen){ /* ** The sizes for serial types less than 128 */ -static const u8 sqlite3SmallTypeSizes[] = { +SQLITE_PRIVATE const u8 sqlite3SmallTypeSizes[128] = { /* 0 1 2 3 4 5 6 7 8 9 */ /* 0 */ 0, 1, 2, 3, 4, 6, 8, 8, 0, 0, /* 10 */ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, @@ -82941,7 +84550,7 @@ SQLITE_PRIVATE u8 sqlite3VdbeOneByteSerialTypeLen(u8 serial_type){ ** so we trust him. */ #ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT -static u64 floatSwap(u64 in){ +SQLITE_PRIVATE u64 sqlite3FloatSwap(u64 in){ union { u64 r; u32 i[2]; @@ -82954,59 +84563,8 @@ static u64 floatSwap(u64 in){ u.i[1] = t; return u.r; } -# define swapMixedEndianFloat(X) X = floatSwap(X) -#else -# define swapMixedEndianFloat(X) -#endif +#endif /* SQLITE_MIXED_ENDIAN_64BIT_FLOAT */ -/* -** Write the serialized data blob for the value stored in pMem into -** buf. It is assumed that the caller has allocated sufficient space. -** Return the number of bytes written. -** -** nBuf is the amount of space left in buf[]. The caller is responsible -** for allocating enough space to buf[] to hold the entire field, exclusive -** of the pMem->u.nZero bytes for a MEM_Zero value. -** -** Return the number of bytes actually written into buf[]. The number -** of bytes in the zero-filled tail is included in the return value only -** if those bytes were zeroed in buf[]. -*/ -SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){ - u32 len; - - /* Integer and Real */ - if( serial_type<=7 && serial_type>0 ){ - u64 v; - u32 i; - if( serial_type==7 ){ - assert( sizeof(v)==sizeof(pMem->u.r) ); - memcpy(&v, &pMem->u.r, sizeof(v)); - swapMixedEndianFloat(v); - }else{ - v = pMem->u.i; - } - len = i = sqlite3SmallTypeSizes[serial_type]; - assert( i>0 ); - do{ - buf[--i] = (u8)(v&0xFF); - v >>= 8; - }while( i ); - return len; - } - - /* String or blob */ - if( serial_type>=12 ){ - assert( pMem->n + ((pMem->flags & MEM_Zero)?pMem->u.nZero:0) - == (int)sqlite3VdbeSerialTypeLen(serial_type) ); - len = pMem->n; - if( len>0 ) memcpy(buf, pMem->z, len); - return len; - } - - /* NULL or constants 0 or 1 */ - return 0; -} /* Input "x" is a sequence of unsigned characters that represent a ** big-endian integer. Return the equivalent native integer @@ -83019,14 +84577,14 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){ /* ** Deserialize the data blob pointed to by buf as serial type serial_type -** and store the result in pMem. Return the number of bytes read. +** and store the result in pMem. ** ** This function is implemented as two separate routines for performance. ** The few cases that require local variables are broken out into a separate ** routine so that in most cases the overhead of moving the stack pointer ** is avoided. */ -static u32 serialGet( +static void serialGet( const unsigned char *buf, /* Buffer to deserialize from */ u32 serial_type, /* Serial type to deserialize */ Mem *pMem /* Memory cell to write value into */ @@ -83060,9 +84618,8 @@ static u32 serialGet( memcpy(&pMem->u.r, &x, sizeof(x)); pMem->flags = IsNaN(x) ? MEM_Null : MEM_Real; } - return 8; } -SQLITE_PRIVATE u32 sqlite3VdbeSerialGet( +SQLITE_PRIVATE void sqlite3VdbeSerialGet( const unsigned char *buf, /* Buffer to deserialize from */ u32 serial_type, /* Serial type to deserialize */ Mem *pMem /* Memory cell to write value into */ @@ -83073,13 +84630,13 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialGet( pMem->flags = MEM_Null|MEM_Zero; pMem->n = 0; pMem->u.nZero = 0; - break; + return; } case 11: /* Reserved for future use */ case 0: { /* Null */ /* EVIDENCE-OF: R-24078-09375 Value is a NULL. */ pMem->flags = MEM_Null; - break; + return; } case 1: { /* EVIDENCE-OF: R-44885-25196 Value is an 8-bit twos-complement @@ -83087,7 +84644,7 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialGet( pMem->u.i = ONE_BYTE_INT(buf); pMem->flags = MEM_Int; testcase( pMem->u.i<0 ); - return 1; + return; } case 2: { /* 2-byte signed integer */ /* EVIDENCE-OF: R-49794-35026 Value is a big-endian 16-bit @@ -83095,7 +84652,7 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialGet( pMem->u.i = TWO_BYTE_INT(buf); pMem->flags = MEM_Int; testcase( pMem->u.i<0 ); - return 2; + return; } case 3: { /* 3-byte signed integer */ /* EVIDENCE-OF: R-37839-54301 Value is a big-endian 24-bit @@ -83103,7 +84660,7 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialGet( pMem->u.i = THREE_BYTE_INT(buf); pMem->flags = MEM_Int; testcase( pMem->u.i<0 ); - return 3; + return; } case 4: { /* 4-byte signed integer */ /* EVIDENCE-OF: R-01849-26079 Value is a big-endian 32-bit @@ -83115,7 +84672,7 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialGet( #endif pMem->flags = MEM_Int; testcase( pMem->u.i<0 ); - return 4; + return; } case 5: { /* 6-byte signed integer */ /* EVIDENCE-OF: R-50385-09674 Value is a big-endian 48-bit @@ -83123,13 +84680,14 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialGet( pMem->u.i = FOUR_BYTE_UINT(buf+2) + (((i64)1)<<32)*TWO_BYTE_INT(buf); pMem->flags = MEM_Int; testcase( pMem->u.i<0 ); - return 6; + return; } case 6: /* 8-byte signed integer */ case 7: { /* IEEE floating point */ /* These use local variables, so do them in a separate routine ** to avoid having to move the frame pointer in the common case */ - return serialGet(buf,serial_type,pMem); + serialGet(buf,serial_type,pMem); + return; } case 8: /* Integer 0 */ case 9: { /* Integer 1 */ @@ -83137,7 +84695,7 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialGet( /* EVIDENCE-OF: R-18143-12121 Value is the integer 1. */ pMem->u.i = serial_type-8; pMem->flags = MEM_Int; - return 0; + return; } default: { /* EVIDENCE-OF: R-14606-31564 Value is a BLOB that is (N-12)/2 bytes in @@ -83148,10 +84706,10 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialGet( pMem->z = (char *)buf; pMem->n = (serial_type-12)/2; pMem->flags = aFlag[serial_type&1]; - return pMem->n; + return; } } - return 0; + return; } /* ** This routine is used to allocate sufficient space for an UnpackedRecord @@ -83172,10 +84730,10 @@ SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord( ){ UnpackedRecord *p; /* Unpacked record to return */ int nByte; /* Number of bytes required for *p */ - nByte = ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nKeyField+1); + nByte = ROUND8P(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nKeyField+1); p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte); if( !p ) return 0; - p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))]; + p->aMem = (Mem*)&((char*)p)[ROUND8P(sizeof(UnpackedRecord))]; assert( pKeyInfo->aSortFlags!=0 ); p->pKeyInfo = pKeyInfo; p->nField = pKeyInfo->nKeyField + 1; @@ -83214,7 +84772,8 @@ SQLITE_PRIVATE void sqlite3VdbeRecordUnpack( /* pMem->flags = 0; // sqlite3VdbeSerialGet() will set this for us */ pMem->szMalloc = 0; pMem->z = 0; - d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem); + sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem); + d += sqlite3VdbeSerialTypeLen(serial_type); pMem++; if( (++u)>=p->nField ) break; } @@ -83298,7 +84857,8 @@ static int vdbeRecordCompareDebug( /* Extract the values to be compared. */ - d1 += sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1); + sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1); + d1 += sqlite3VdbeSerialTypeLen(serial_type1); /* Do the comparison */ @@ -83409,8 +84969,8 @@ static int vdbeCompareMemString( }else{ rc = pColl->xCmp(pColl->pUser, c1.n, v1, c2.n, v2); } - sqlite3VdbeMemRelease(&c1); - sqlite3VdbeMemRelease(&c2); + sqlite3VdbeMemReleaseMalloc(&c1); + sqlite3VdbeMemReleaseMalloc(&c2); return rc; } } @@ -83671,14 +85231,22 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip( ** two elements in the keys are equal. Fix the various stack variables so ** that this routine begins comparing at the second field. */ if( bSkip ){ - u32 s1; - idx1 = 1 + getVarint32(&aKey1[1], s1); + u32 s1 = aKey1[1]; + if( s1<0x80 ){ + idx1 = 2; + }else{ + idx1 = 1 + sqlite3GetVarint32(&aKey1[1], &s1); + } szHdr1 = aKey1[0]; d1 = szHdr1 + sqlite3VdbeSerialTypeLen(s1); i = 1; pRhs++; }else{ - idx1 = getVarint32(aKey1, szHdr1); + if( (szHdr1 = aKey1[0])<0x80 ){ + idx1 = 1; + }else{ + idx1 = sqlite3GetVarint32(aKey1, &szHdr1); + } d1 = szHdr1; i = 0; } @@ -83934,7 +85502,8 @@ static int vdbeRecordCompareInt( return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2); } - v = pPKey2->aMem[0].u.i; + assert( pPKey2->u.i == pPKey2->aMem[0].u.i ); + v = pPKey2->u.i; if( v>lhs ){ res = pPKey2->r1; }else if( vaMem[0].flags & MEM_Str ); + assert( pPKey2->aMem[0].n == pPKey2->n ); + assert( pPKey2->aMem[0].z == pPKey2->u.z ); vdbeAssertFieldCountWithinLimits(nKey1, pKey1, pPKey2->pKeyInfo); - serial_type = (u8)(aKey1[1]); - if( serial_type >= 0x80 ){ - sqlite3GetVarint32(&aKey1[1], (u32*)&serial_type); - } + serial_type = (signed char)(aKey1[1]); + +vrcs_restart: if( serial_type<12 ){ + if( serial_type<0 ){ + sqlite3GetVarint32(&aKey1[1], (u32*)&serial_type); + if( serial_type>=12 ) goto vrcs_restart; + assert( CORRUPT_DB ); + } res = pPKey2->r1; /* (pKey1/nKey1) is a number or a null */ }else if( !(serial_type & 0x01) ){ res = pPKey2->r2; /* (pKey1/nKey1) is a blob */ @@ -83988,15 +85563,15 @@ static int vdbeRecordCompareString( pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT; return 0; /* Corruption */ } - nCmp = MIN( pPKey2->aMem[0].n, nStr ); - res = memcmp(&aKey1[szHdr], pPKey2->aMem[0].z, nCmp); + nCmp = MIN( pPKey2->n, nStr ); + res = memcmp(&aKey1[szHdr], pPKey2->u.z, nCmp); if( res>0 ){ res = pPKey2->r2; }else if( res<0 ){ res = pPKey2->r1; }else{ - res = nStr - pPKey2->aMem[0].n; + res = nStr - pPKey2->n; if( res==0 ){ if( pPKey2->nField>1 ){ res = sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1); @@ -84051,6 +85626,7 @@ SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){ p->r2 = 1; } if( (flags & MEM_Int) ){ + p->u.i = p->aMem[0].u.i; return vdbeRecordCompareInt; } testcase( flags & MEM_Real ); @@ -84060,6 +85636,8 @@ SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){ && p->pKeyInfo->aColl[0]==0 ){ assert( flags & MEM_Str ); + p->u.z = p->aMem[0].z; + p->n = p->aMem[0].n; return vdbeRecordCompareString; } } @@ -84102,7 +85680,7 @@ SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){ /* The index entry must begin with a header size */ getVarint32NR((u8*)m.z, szHdr); testcase( szHdr==3 ); - testcase( szHdr==m.n ); + testcase( szHdr==(u32)m.n ); testcase( szHdr>0x7fffffff ); assert( m.n>=0 ); if( unlikely(szHdr<3 || szHdr>(unsigned)m.n) ){ @@ -84132,14 +85710,14 @@ SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){ /* Fetch the integer off the end of the index record */ sqlite3VdbeSerialGet((u8*)&m.z[m.n-lenRowid], typeRowid, &v); *rowid = v.u.i; - sqlite3VdbeMemRelease(&m); + sqlite3VdbeMemReleaseMalloc(&m); return SQLITE_OK; /* Jump here if database corruption is detected after m has been ** allocated. Free the m object and return SQLITE_CORRUPT. */ idx_rowid_corruption: testcase( m.szMalloc!=0 ); - sqlite3VdbeMemRelease(&m); + sqlite3VdbeMemReleaseMalloc(&m); return SQLITE_CORRUPT_BKPT; } @@ -84181,7 +85759,7 @@ SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare( return rc; } *res = sqlite3VdbeRecordCompareWithSkip(m.n, m.z, pUnpacked, 0); - sqlite3VdbeMemRelease(&m); + sqlite3VdbeMemReleaseMalloc(&m); return SQLITE_OK; } @@ -84348,7 +85926,7 @@ static void vdbeFreeUnpacked(sqlite3 *db, int nField, UnpackedRecord *p){ int i; for(i=0; iaMem[i]; - if( pMem->zMalloc ) sqlite3VdbeMemRelease(pMem); + if( pMem->zMalloc ) sqlite3VdbeMemReleaseMalloc(pMem); } sqlite3DbFreeNN(db, p); } @@ -84775,6 +86353,9 @@ SQLITE_API sqlite3_value *sqlite3_value_dup(const sqlite3_value *pOrig){ sqlite3ValueFree(pNew); pNew = 0; } + }else if( pNew->flags & MEM_Null ){ + /* Do not duplicate pointer values */ + pNew->flags &= ~(MEM_Term|MEM_Subtype); } return pNew; } @@ -84805,7 +86386,8 @@ static void setResultStrOrError( u8 enc, /* Encoding of z. 0 for BLOBs */ void (*xDel)(void*) /* Destructor function */ ){ - int rc = sqlite3VdbeMemSetStr(pCtx->pOut, z, n, enc, xDel); + Mem *pOut = pCtx->pOut; + int rc = sqlite3VdbeMemSetStr(pOut, z, n, enc, xDel); if( rc ){ if( rc==SQLITE_TOOBIG ){ sqlite3_result_error_toobig(pCtx); @@ -84815,6 +86397,11 @@ static void setResultStrOrError( assert( rc==SQLITE_NOMEM ); sqlite3_result_error_nomem(pCtx); } + return; + } + sqlite3VdbeChangeEncoding(pOut, pCtx->enc); + if( sqlite3VdbeMemTooBig(pOut) ){ + sqlite3_result_error_toobig(pCtx); } } static int invokeValueDestructor( @@ -84958,17 +86545,22 @@ SQLITE_API void sqlite3_result_text16le( } #endif /* SQLITE_OMIT_UTF16 */ SQLITE_API void sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){ + Mem *pOut = pCtx->pOut; assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - sqlite3VdbeMemCopy(pCtx->pOut, pValue); + sqlite3VdbeMemCopy(pOut, pValue); + sqlite3VdbeChangeEncoding(pOut, pCtx->enc); + if( sqlite3VdbeMemTooBig(pOut) ){ + sqlite3_result_error_toobig(pCtx); + } } SQLITE_API void sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){ - assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); - sqlite3VdbeMemSetZeroBlob(pCtx->pOut, n); + sqlite3_result_zeroblob64(pCtx, n>0 ? n : 0); } SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context *pCtx, u64 n){ Mem *pOut = pCtx->pOut; assert( sqlite3_mutex_held(pOut->db->mutex) ); if( n>(u64)pOut->db->aLimit[SQLITE_LIMIT_LENGTH] ){ + sqlite3_result_error_toobig(pCtx); return SQLITE_TOOBIG; } #ifndef SQLITE_OMIT_INCRBLOB @@ -84984,8 +86576,8 @@ SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){ if( pCtx->pVdbe ) pCtx->pVdbe->rcApp = errCode; #endif if( pCtx->pOut->flags & MEM_Null ){ - sqlite3VdbeMemSetStr(pCtx->pOut, sqlite3ErrStr(errCode), -1, - SQLITE_UTF8, SQLITE_STATIC); + setResultStrOrError(pCtx, sqlite3ErrStr(errCode), -1, SQLITE_UTF8, + SQLITE_STATIC); } } @@ -85059,80 +86651,83 @@ static int sqlite3Step(Vdbe *p){ int rc; assert(p); - if( p->iVdbeMagic!=VDBE_MAGIC_RUN ){ - /* We used to require that sqlite3_reset() be called before retrying - ** sqlite3_step() after any error or after SQLITE_DONE. But beginning - ** with version 3.7.0, we changed this so that sqlite3_reset() would - ** be called automatically instead of throwing the SQLITE_MISUSE error. - ** This "automatic-reset" change is not technically an incompatibility, - ** since any application that receives an SQLITE_MISUSE is broken by - ** definition. - ** - ** Nevertheless, some published applications that were originally written - ** for version 3.6.23 or earlier do in fact depend on SQLITE_MISUSE - ** returns, and those were broken by the automatic-reset change. As a - ** a work-around, the SQLITE_OMIT_AUTORESET compile-time restores the - ** legacy behavior of returning SQLITE_MISUSE for cases where the - ** previous sqlite3_step() returned something other than a SQLITE_LOCKED - ** or SQLITE_BUSY error. - */ -#ifdef SQLITE_OMIT_AUTORESET - if( (rc = p->rc&0xff)==SQLITE_BUSY || rc==SQLITE_LOCKED ){ - sqlite3_reset((sqlite3_stmt*)p); - }else{ - return SQLITE_MISUSE_BKPT; - } -#else - sqlite3_reset((sqlite3_stmt*)p); -#endif - } - - /* Check that malloc() has not failed. If it has, return early. */ db = p->db; - if( db->mallocFailed ){ - p->rc = SQLITE_NOMEM; - return SQLITE_NOMEM_BKPT; - } + if( p->eVdbeState!=VDBE_RUN_STATE ){ + restart_step: + if( p->eVdbeState==VDBE_READY_STATE ){ + if( p->expired ){ + p->rc = SQLITE_SCHEMA; + rc = SQLITE_ERROR; + if( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 ){ + /* If this statement was prepared using saved SQL and an + ** error has occurred, then return the error code in p->rc to the + ** caller. Set the error code in the database handle to the same + ** value. + */ + rc = sqlite3VdbeTransferError(p); + } + goto end_of_step; + } - if( p->pc<0 && p->expired ){ - p->rc = SQLITE_SCHEMA; - rc = SQLITE_ERROR; - if( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 ){ - /* If this statement was prepared using saved SQL and an - ** error has occurred, then return the error code in p->rc to the - ** caller. Set the error code in the database handle to the same value. + /* If there are no other statements currently running, then + ** reset the interrupt flag. This prevents a call to sqlite3_interrupt + ** from interrupting a statement that has not yet started. */ - rc = sqlite3VdbeTransferError(p); - } - goto end_of_step; - } - if( p->pc<0 ){ - /* If there are no other statements currently running, then - ** reset the interrupt flag. This prevents a call to sqlite3_interrupt - ** from interrupting a statement that has not yet started. - */ - if( db->nVdbeActive==0 ){ - AtomicStore(&db->u1.isInterrupted, 0); - } + if( db->nVdbeActive==0 ){ + AtomicStore(&db->u1.isInterrupted, 0); + } - assert( db->nVdbeWrite>0 || db->autoCommit==0 - || (db->nDeferredCons==0 && db->nDeferredImmCons==0) - ); + assert( db->nVdbeWrite>0 || db->autoCommit==0 + || (db->nDeferredCons==0 && db->nDeferredImmCons==0) + ); #ifndef SQLITE_OMIT_TRACE - if( (db->mTrace & (SQLITE_TRACE_PROFILE|SQLITE_TRACE_XPROFILE))!=0 - && !db->init.busy && p->zSql ){ - sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime); - }else{ - assert( p->startTime==0 ); - } + if( (db->mTrace & (SQLITE_TRACE_PROFILE|SQLITE_TRACE_XPROFILE))!=0 + && !db->init.busy && p->zSql ){ + sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime); + }else{ + assert( p->startTime==0 ); + } #endif - db->nVdbeActive++; - if( p->readOnly==0 ) db->nVdbeWrite++; - if( p->bIsReader ) db->nVdbeRead++; - p->pc = 0; + db->nVdbeActive++; + if( p->readOnly==0 ) db->nVdbeWrite++; + if( p->bIsReader ) db->nVdbeRead++; + p->pc = 0; + p->eVdbeState = VDBE_RUN_STATE; + }else + + if( ALWAYS(p->eVdbeState==VDBE_HALT_STATE) ){ + /* We used to require that sqlite3_reset() be called before retrying + ** sqlite3_step() after any error or after SQLITE_DONE. But beginning + ** with version 3.7.0, we changed this so that sqlite3_reset() would + ** be called automatically instead of throwing the SQLITE_MISUSE error. + ** This "automatic-reset" change is not technically an incompatibility, + ** since any application that receives an SQLITE_MISUSE is broken by + ** definition. + ** + ** Nevertheless, some published applications that were originally written + ** for version 3.6.23 or earlier do in fact depend on SQLITE_MISUSE + ** returns, and those were broken by the automatic-reset change. As a + ** a work-around, the SQLITE_OMIT_AUTORESET compile-time restores the + ** legacy behavior of returning SQLITE_MISUSE for cases where the + ** previous sqlite3_step() returned something other than a SQLITE_LOCKED + ** or SQLITE_BUSY error. + */ +#ifdef SQLITE_OMIT_AUTORESET + if( (rc = p->rc&0xff)==SQLITE_BUSY || rc==SQLITE_LOCKED ){ + sqlite3_reset((sqlite3_stmt*)p); + }else{ + return SQLITE_MISUSE_BKPT; + } +#else + sqlite3_reset((sqlite3_stmt*)p); +#endif + assert( p->eVdbeState==VDBE_READY_STATE ); + goto restart_step; + } } + #ifdef SQLITE_DEBUG p->rcApp = SQLITE_OK; #endif @@ -85147,7 +86742,12 @@ static int sqlite3Step(Vdbe *p){ db->nVdbeExec--; } - if( rc!=SQLITE_ROW ){ + if( rc==SQLITE_ROW ){ + assert( p->rc==SQLITE_OK ); + assert( db->mallocFailed==0 ); + db->errCode = SQLITE_ROW; + return SQLITE_ROW; + }else{ #ifndef SQLITE_OMIT_TRACE /* If the statement completed successfully, invoke the profile callback */ checkProfileCallback(db, p); @@ -85199,7 +86799,6 @@ SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){ } db = v->db; sqlite3_mutex_enter(db->mutex); - v->doingRerun = 0; while( (rc = sqlite3Step(v))==SQLITE_SCHEMA && cnt++ < SQLITE_MAX_SCHEMA_RETRY ){ int savedPc = v->pc; @@ -85225,7 +86824,13 @@ SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){ break; } sqlite3_reset(pStmt); - if( savedPc>=0 ) v->doingRerun = 1; + if( savedPc>=0 ){ + /* Setting minWriteFileFormat to 254 is a signal to the OP_Init and + ** OP_Trace opcodes to *not* perform SQLITE_TRACE_STMT because it has + ** already been done once on a prior invocation that failed due to + ** SQLITE_SCHEMA. tag-20220401a */ + v->minWriteFileFormat = 254; + } assert( v->expired==0 ); } sqlite3_mutex_leave(db->mutex); @@ -85276,6 +86881,70 @@ SQLITE_API int sqlite3_vtab_nochange(sqlite3_context *p){ return sqlite3_value_nochange(p->pOut); } +/* +** Implementation of sqlite3_vtab_in_first() (if bNext==0) and +** sqlite3_vtab_in_next() (if bNext!=0). +*/ +static int valueFromValueList( + sqlite3_value *pVal, /* Pointer to the ValueList object */ + sqlite3_value **ppOut, /* Store the next value from the list here */ + int bNext /* 1 for _next(). 0 for _first() */ +){ + int rc; + ValueList *pRhs; + + *ppOut = 0; + if( pVal==0 ) return SQLITE_MISUSE; + pRhs = (ValueList*)sqlite3_value_pointer(pVal, "ValueList"); + if( pRhs==0 ) return SQLITE_MISUSE; + if( bNext ){ + rc = sqlite3BtreeNext(pRhs->pCsr, 0); + }else{ + int dummy = 0; + rc = sqlite3BtreeFirst(pRhs->pCsr, &dummy); + assert( rc==SQLITE_OK || sqlite3BtreeEof(pRhs->pCsr) ); + if( sqlite3BtreeEof(pRhs->pCsr) ) rc = SQLITE_DONE; + } + if( rc==SQLITE_OK ){ + u32 sz; /* Size of current row in bytes */ + Mem sMem; /* Raw content of current row */ + memset(&sMem, 0, sizeof(sMem)); + sz = sqlite3BtreePayloadSize(pRhs->pCsr); + rc = sqlite3VdbeMemFromBtreeZeroOffset(pRhs->pCsr,(int)sz,&sMem); + if( rc==SQLITE_OK ){ + u8 *zBuf = (u8*)sMem.z; + u32 iSerial; + sqlite3_value *pOut = pRhs->pOut; + int iOff = 1 + getVarint32(&zBuf[1], iSerial); + sqlite3VdbeSerialGet(&zBuf[iOff], iSerial, pOut); + pOut->enc = ENC(pOut->db); + if( (pOut->flags & MEM_Ephem)!=0 && sqlite3VdbeMemMakeWriteable(pOut) ){ + rc = SQLITE_NOMEM; + }else{ + *ppOut = pOut; + } + } + sqlite3VdbeMemRelease(&sMem); + } + return rc; +} + +/* +** Set the iterator value pVal to point to the first value in the set. +** Set (*ppOut) to point to this value before returning. +*/ +SQLITE_API int sqlite3_vtab_in_first(sqlite3_value *pVal, sqlite3_value **ppOut){ + return valueFromValueList(pVal, ppOut, 0); +} + +/* +** Set the iterator value pVal to point to the next value in the set. +** Set (*ppOut) to point to this value before returning. +*/ +SQLITE_API int sqlite3_vtab_in_next(sqlite3_value *pVal, sqlite3_value **ppOut){ + return valueFromValueList(pVal, ppOut, 1); +} + /* ** Return the current time for a statement. If the current time ** is requested more than once within the same run of a single prepared @@ -85470,15 +87139,15 @@ static const Mem *columnNullValue(void){ #endif = { /* .u = */ {0}, + /* .z = */ (char*)0, + /* .n = */ (int)0, /* .flags = */ (u16)MEM_Null, /* .enc = */ (u8)0, /* .eSubtype = */ (u8)0, - /* .n = */ (int)0, - /* .z = */ (char*)0, - /* .zMalloc = */ (char*)0, + /* .db = */ (sqlite3*)0, /* .szMalloc = */ (int)0, /* .uTemp = */ (u32)0, - /* .db = */ (sqlite3*)0, + /* .zMalloc = */ (char*)0, /* .xDel = */ (void(*)(void*))0, #ifdef SQLITE_DEBUG /* .pScopyFrom = */ (Mem*)0, @@ -85775,7 +87444,7 @@ static int vdbeUnbind(Vdbe *p, int i){ return SQLITE_MISUSE_BKPT; } sqlite3_mutex_enter(p->db->mutex); - if( p->iVdbeMagic!=VDBE_MAGIC_RUN || p->pc>=0 ){ + if( p->eVdbeState!=VDBE_READY_STATE ){ sqlite3Error(p->db, SQLITE_MISUSE); sqlite3_mutex_leave(p->db->mutex); sqlite3_log(SQLITE_MISUSE, @@ -85960,7 +87629,10 @@ SQLITE_API int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_valu break; } case SQLITE_FLOAT: { - rc = sqlite3_bind_double(pStmt, i, pValue->u.r); + assert( pValue->flags & (MEM_Real|MEM_IntReal) ); + rc = sqlite3_bind_double(pStmt, i, + (pValue->flags & MEM_Real) ? pValue->u.r : (double)pValue->u.i + ); break; } case SQLITE_BLOB: { @@ -86125,7 +87797,7 @@ SQLITE_API int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt){ */ SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt *pStmt){ Vdbe *v = (Vdbe*)pStmt; - return v!=0 && v->iVdbeMagic==VDBE_MAGIC_RUN && v->pc>=0; + return v!=0 && v->eVdbeState==VDBE_RUN_STATE; } /* @@ -86171,8 +87843,7 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){ sqlite3_mutex_enter(db->mutex); v = 0; db->pnBytesFreed = (int*)&v; - sqlite3VdbeClearObject(db, pVdbe); - sqlite3DbFree(db, pVdbe); + sqlite3VdbeDelete(pVdbe); db->pnBytesFreed = 0; sqlite3_mutex_leave(db->mutex); }else{ @@ -86940,7 +88611,6 @@ static VdbeCursor *allocateCursor( Vdbe *p, /* The virtual machine */ int iCur, /* Index of the new VdbeCursor */ int nField, /* Number of fields in the table or index */ - int iDb, /* Database the cursor belongs to, or -1 */ u8 eCurType /* Type of the new cursor */ ){ /* Find the memory cell that will be used to store the blob of memory @@ -86966,12 +88636,12 @@ static VdbeCursor *allocateCursor( int nByte; VdbeCursor *pCx = 0; nByte = - ROUND8(sizeof(VdbeCursor)) + 2*sizeof(u32)*nField + + ROUND8P(sizeof(VdbeCursor)) + 2*sizeof(u32)*nField + (eCurType==CURTYPE_BTREE?sqlite3BtreeCursorSize():0); assert( iCur>=0 && iCurnCursor ); if( p->apCsr[iCur] ){ /*OPTIMIZATION-IF-FALSE*/ - sqlite3VdbeFreeCursor(p, p->apCsr[iCur]); + sqlite3VdbeFreeCursorNN(p, p->apCsr[iCur]); p->apCsr[iCur] = 0; } @@ -86997,12 +88667,11 @@ static VdbeCursor *allocateCursor( p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->zMalloc; memset(pCx, 0, offsetof(VdbeCursor,pAltCursor)); pCx->eCurType = eCurType; - pCx->iDb = iDb; pCx->nField = nField; pCx->aOffset = &pCx->aType[nField]; if( eCurType==CURTYPE_BTREE ){ pCx->uc.pCursor = (BtCursor*) - &pMem->z[ROUND8(sizeof(VdbeCursor))+2*sizeof(u32)*nField]; + &pMem->z[ROUND8P(sizeof(VdbeCursor))+2*sizeof(u32)*nField]; sqlite3BtreeCursorZero(pCx->uc.pCursor); } return pCx; @@ -87370,6 +89039,29 @@ static Mem *out2Prerelease(Vdbe *p, VdbeOp *pOp){ } } +/* +** Compute a bloom filter hash using pOp->p4.i registers from aMem[] beginning +** with pOp->p3. Return the hash. +*/ +static u64 filterHash(const Mem *aMem, const Op *pOp){ + int i, mx; + u64 h = 0; + + assert( pOp->p4type==P4_INT32 ); + for(i=pOp->p3, mx=i+pOp->p4.i; iflags & (MEM_Int|MEM_IntReal) ){ + h += p->u.i; + }else if( p->flags & MEM_Real ){ + h += sqlite3VdbeIntValue(p); + }else if( p->flags & (MEM_Str|MEM_Blob) ){ + h += p->n; + if( p->flags & MEM_Zero ) h += p->u.nZero; + } + } + return h; +} + /* ** Return the symbolic name for the data type of a pMem */ @@ -87418,7 +89110,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec( #endif /*** INSERT STACK UNION HERE ***/ - assert( p->iVdbeMagic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */ + assert( p->eVdbeState==VDBE_RUN_STATE ); /* sqlite3_step() verifies this */ sqlite3VdbeEnter(p); #ifndef SQLITE_OMIT_PROGRESS_CALLBACK if( db->xProgress ){ @@ -87661,24 +89353,39 @@ case OP_Gosub: { /* jump */ pIn1->flags = MEM_Int; pIn1->u.i = (int)(pOp-aOp); REGISTER_TRACE(pOp->p1, pIn1); - - /* Most jump operations do a goto to this spot in order to update - ** the pOp pointer. */ -jump_to_p2: - pOp = &aOp[pOp->p2 - 1]; - break; + goto jump_to_p2_and_check_for_interrupt; } -/* Opcode: Return P1 * * * * +/* Opcode: Return P1 P2 P3 * * +** +** Jump to the address stored in register P1. If P1 is a return address +** register, then this accomplishes a return from a subroutine. ** -** Jump to the next instruction after the address in register P1. After -** the jump, register P1 becomes undefined. +** If P3 is 1, then the jump is only taken if register P1 holds an integer +** values, otherwise execution falls through to the next opcode, and the +** OP_Return becomes a no-op. If P3 is 0, then register P1 must hold an +** integer or else an assert() is raised. P3 should be set to 1 when +** this opcode is used in combination with OP_BeginSubrtn, and set to 0 +** otherwise. +** +** The value in register P1 is unchanged by this opcode. +** +** P2 is not used by the byte-code engine. However, if P2 is positive +** and also less than the current address, then the "EXPLAIN" output +** formatter in the CLI will indent all opcodes from the P2 opcode up +** to be not including the current Return. P2 should be the first opcode +** in the subroutine from which this opcode is returning. Thus the P2 +** value is a byte-code indentation hint. See tag-20220407a in +** wherecode.c and shell.c. */ case OP_Return: { /* in1 */ pIn1 = &aMem[pOp->p1]; - assert( pIn1->flags==MEM_Int ); - pOp = &aOp[pIn1->u.i]; - pIn1->flags = MEM_Undefined; + if( pIn1->flags & MEM_Int ){ + if( pOp->p3 ){ VdbeBranchTaken(1, 2); } + pOp = &aOp[pIn1->u.i]; + }else if( ALWAYS(pOp->p3) ){ + VdbeBranchTaken(0, 2); + } break; } @@ -87701,7 +89408,14 @@ case OP_InitCoroutine: { /* jump */ assert( !VdbeMemDynamic(pOut) ); pOut->u.i = pOp->p3 - 1; pOut->flags = MEM_Int; - if( pOp->p2 ) goto jump_to_p2; + if( pOp->p2==0 ) break; + + /* Most jump operations do a goto to this spot in order to update + ** the pOp pointer. */ +jump_to_p2: + assert( pOp->p2>0 ); /* There are never any jumps to instruction 0 */ + assert( pOp->p2nOp ); /* Jumps must be in range */ + pOp = &aOp[pOp->p2 - 1]; break; } @@ -87803,11 +89517,10 @@ case OP_Halt: { VdbeFrame *pFrame; int pcx; - pcx = (int)(pOp - aOp); #ifdef SQLITE_DEBUG if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); } #endif - if( pOp->p1==SQLITE_OK && p->pFrame ){ + if( p->pFrame && pOp->p1==SQLITE_OK ){ /* Halt the sub-program. Return control to the parent frame. */ pFrame = p->pFrame; p->pFrame = pFrame->pParent; @@ -87829,7 +89542,6 @@ case OP_Halt: { } p->rc = pOp->p1; p->errorAction = (u8)pOp->p2; - p->pc = pcx; assert( pOp->p5<=4 ); if( p->rc ){ if( pOp->p5 ){ @@ -87846,6 +89558,7 @@ case OP_Halt: { }else{ sqlite3VdbeError(p, "%s", pOp->p4.z); } + pcx = (int)(pOp - aOp); sqlite3_log(pOp->p1, "abort at %d in [%s]: %s", pcx, p->zSql, p->zErrMsg); } rc = sqlite3VdbeHalt(p); @@ -87971,6 +89684,28 @@ case OP_String: { /* out2 */ break; } +/* Opcode: BeginSubrtn * P2 * * * +** Synopsis: r[P2]=NULL +** +** Mark the beginning of a subroutine that can be entered in-line +** or that can be called using OP_Gosub. The subroutine should +** be terminated by an OP_Return instruction that has a P1 operand that +** is the same as the P2 operand to this opcode and that has P3 set to 1. +** If the subroutine is entered in-line, then the OP_Return will simply +** fall through. But if the subroutine is entered using OP_Gosub, then +** the OP_Return will jump back to the first instruction after the OP_Gosub. +** +** This routine works by loading a NULL into the P2 register. When the +** return address register contains a NULL, the OP_Return instruction is +** a no-op that simply falls through to the next instruction (assuming that +** the OP_Return opcode has a P3 value of 1). Thus if the subroutine is +** entered in-line, then the OP_Return will cause in-line execution to +** continue. But if the subroutine is entered via OP_Gosub, then the +** OP_Return will cause a return to the address following the OP_Gosub. +** +** This opcode is identical to OP_Null. It has a different name +** only to make the byte code easier to read and verify. +*/ /* Opcode: Null P1 P2 P3 * * ** Synopsis: r[P2..P3]=NULL ** @@ -87983,6 +89718,7 @@ case OP_String: { /* out2 */ ** NULL values will not compare equal even if SQLITE_NULLEQ is set on ** OP_Ne or OP_Eq. */ +case OP_BeginSubrtn: case OP_Null: { /* out2 */ int cnt; u16 nullFlag; @@ -88024,12 +89760,18 @@ case OP_SoftNull: { ** Synopsis: r[P2]=P4 (len=P1) ** ** P4 points to a blob of data P1 bytes long. Store this -** blob in register P2. +** blob in register P2. If P4 is a NULL pointer, then construct +** a zero-filled blob that is P1 bytes long in P2. */ case OP_Blob: { /* out2 */ assert( pOp->p1 <= SQLITE_MAX_LENGTH ); pOut = out2Prerelease(p, pOp); - sqlite3VdbeMemSetStr(pOut, pOp->p4.z, pOp->p1, 0, 0); + if( pOp->p4.z==0 ){ + sqlite3VdbeMemSetZeroBlob(pOut, pOp->p1); + if( sqlite3VdbeMemExpandBlob(pOut) ) goto no_mem; + }else{ + sqlite3VdbeMemSetStr(pOut, pOp->p4.z, pOp->p1, 0, 0); + } pOut->enc = encoding; UPDATE_MAX_BLOBSIZE(pOut); break; @@ -88107,11 +89849,16 @@ case OP_Move: { break; } -/* Opcode: Copy P1 P2 P3 * * +/* Opcode: Copy P1 P2 P3 * P5 ** Synopsis: r[P2@P3+1]=r[P1@P3+1] ** ** Make a copy of registers P1..P1+P3 into registers P2..P2+P3. ** +** If the 0x0002 bit of P5 is set then also clear the MEM_Subtype flag in the +** destination. The 0x0001 bit of P5 indicates that this Copy opcode cannot +** be merged. The 0x0001 bit is used by the query planner and does not +** come into play during query execution. +** ** This instruction makes a deep copy of the value. A duplicate ** is made of any string or blob constant. See also OP_SCopy. */ @@ -88126,6 +89873,9 @@ case OP_Copy: { memAboutToChange(p, pOut); sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); Deephemeralize(pOut); + if( (pOut->flags & MEM_Subtype)!=0 && (pOp->p5 & 0x0002)!=0 ){ + pOut->flags &= ~MEM_Subtype; + } #ifdef SQLITE_DEBUG pOut->pScopyFrom = 0; #endif @@ -88178,24 +89928,22 @@ case OP_IntCopy: { /* out2 */ break; } -/* Opcode: ChngCntRow P1 P2 * * * -** Synopsis: output=r[P1] +/* Opcode: FkCheck * * * * * ** -** Output value in register P1 as the chance count for a DML statement, -** due to the "PRAGMA count_changes=ON" setting. Or, if there was a -** foreign key error in the statement, trigger the error now. +** Halt with an SQLITE_CONSTRAINT error if there are any unresolved +** foreign key constraint violations. If there are no foreign key +** constraint violations, this is a no-op. ** -** This opcode is a variant of OP_ResultRow that checks the foreign key -** immediate constraint count and throws an error if the count is -** non-zero. The P2 opcode must be 1. +** FK constraint violations are also checked when the prepared statement +** exits. This opcode is used to raise foreign key constraint errors prior +** to returning results such as a row change count or the result of a +** RETURNING clause. */ -case OP_ChngCntRow: { - assert( pOp->p2==1 ); +case OP_FkCheck: { if( (rc = sqlite3VdbeCheckFk(p,0))!=SQLITE_OK ){ goto abort_due_to_error; } - /* Fall through to the next case, OP_ResultRow */ - /* no break */ deliberate_fall_through + break; } /* Opcode: ResultRow P1 P2 * * * @@ -88208,45 +89956,32 @@ case OP_ChngCntRow: { ** the result row. */ case OP_ResultRow: { - Mem *pMem; - int i; assert( p->nResColumn==pOp->p2 ); assert( pOp->p1>0 || CORRUPT_DB ); assert( pOp->p1+pOp->p2<=(p->nMem+1 - p->nCursor)+1 ); - /* Invalidate all ephemeral cursor row caches */ p->cacheCtr = (p->cacheCtr + 2)|1; - - /* Make sure the results of the current row are \000 terminated - ** and have an assigned type. The results are de-ephemeralized as - ** a side effect. - */ - pMem = p->pResultSet = &aMem[pOp->p1]; - for(i=0; ip2; i++){ - assert( memIsValid(&pMem[i]) ); - Deephemeralize(&pMem[i]); - assert( (pMem[i].flags & MEM_Ephem)==0 - || (pMem[i].flags & (MEM_Str|MEM_Blob))==0 ); - sqlite3VdbeMemNulTerminate(&pMem[i]); - REGISTER_TRACE(pOp->p1+i, &pMem[i]); + p->pResultSet = &aMem[pOp->p1]; #ifdef SQLITE_DEBUG - /* The registers in the result will not be used again when the - ** prepared statement restarts. This is because sqlite3_column() - ** APIs might have caused type conversions of made other changes to - ** the register values. Therefore, we can go ahead and break any - ** OP_SCopy dependencies. */ - pMem[i].pScopyFrom = 0; -#endif + { + Mem *pMem = p->pResultSet; + int i; + for(i=0; ip2; i++){ + assert( memIsValid(&pMem[i]) ); + REGISTER_TRACE(pOp->p1+i, &pMem[i]); + /* The registers in the result will not be used again when the + ** prepared statement restarts. This is because sqlite3_column() + ** APIs might have caused type conversions of made other changes to + ** the register values. Therefore, we can go ahead and break any + ** OP_SCopy dependencies. */ + pMem[i].pScopyFrom = 0; + } } +#endif if( db->mallocFailed ) goto no_mem; - if( db->mTrace & SQLITE_TRACE_ROW ){ db->trace.xV2(SQLITE_TRACE_ROW, db->pTraceArg, p, 0); } - - - /* Return SQLITE_ROW - */ p->pc = (int)(pOp - aOp) + 1; rc = SQLITE_ROW; goto vdbe_return; @@ -88301,7 +90036,7 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */ if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } - if( sqlite3VdbeMemGrow(pOut, (int)nByte+3, pOut==pIn2) ){ + if( sqlite3VdbeMemGrow(pOut, (int)nByte+2, pOut==pIn2) ){ goto no_mem; } MemSetTypeFlag(pOut, MEM_Str); @@ -88313,9 +90048,9 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */ memcpy(&pOut->z[pIn2->n], pIn1->z, pIn1->n); assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) ); pIn1->flags = flags1; + if( encoding>SQLITE_UTF8 ) nByte &= ~1; pOut->z[nByte]=0; pOut->z[nByte+1] = 0; - pOut->z[nByte+2] = 0; pOut->flags |= MEM_Term; pOut->n = (int)nByte; pOut->enc = encoding; @@ -88760,23 +90495,23 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ assert( (pOp->p5 & SQLITE_AFF_MASK)!=SQLITE_AFF_TEXT || CORRUPT_DB ); /* Common case of comparison of two integers */ if( pIn3->u.i > pIn1->u.i ){ - iCompare = +1; if( sqlite3aGTb[pOp->opcode] ){ VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3); goto jump_to_p2; } + iCompare = +1; }else if( pIn3->u.i < pIn1->u.i ){ - iCompare = -1; if( sqlite3aLTb[pOp->opcode] ){ VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3); goto jump_to_p2; } + iCompare = -1; }else{ - iCompare = 0; if( sqlite3aEQb[pOp->opcode] ){ VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3); goto jump_to_p2; } + iCompare = 0; } VdbeBranchTaken(0, (pOp->p5 & SQLITE_NULLEQ)?2:3); break; @@ -88803,11 +90538,11 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ ** then the result is always NULL. ** The jump is taken if the SQLITE_JUMPIFNULL bit is set. */ - iCompare = 1; /* Operands are not equal */ VdbeBranchTaken(2,3); if( pOp->p5 & SQLITE_JUMPIFNULL ){ goto jump_to_p2; } + iCompare = 1; /* Operands are not equal */ break; } }else{ @@ -88833,7 +90568,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */ sqlite3VdbeMemStringify(pIn1, encoding, 1); testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) ); flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask); - if( NEVER(pIn1==pIn3) ) flags3 = flags1 | MEM_Str; + if( pIn1==pIn3 ) flags3 = flags1 | MEM_Str; } if( (flags3 & MEM_Str)==0 && (flags3&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){ testcase( pIn3->flags & MEM_Int ); @@ -88913,9 +90648,8 @@ case OP_ElseEq: { /* same as TK_ESCAPE, jump */ ** Set the permutation used by the OP_Compare operator in the next ** instruction. The permutation is stored in the P4 operand. ** -** The permutation is only valid until the next OP_Compare that has -** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should -** occur immediately prior to the OP_Compare. +** The permutation is only valid for the next opcode which must be +** an OP_Compare that has the OPFLAG_PERMUTE bit set in P5. ** ** The first integer in the P4 integer array is the length of the array ** and does not become part of the permutation. @@ -88947,6 +90681,8 @@ case OP_Permutation: { ** The comparison is a sort comparison, so NULLs compare equal, ** NULLs are less than numbers, numbers are less than strings, ** and strings are less than blobs. +** +** This opcode must be immediately followed by an OP_Jump opcode. */ case OP_Compare: { int n; @@ -89005,6 +90741,7 @@ case OP_Compare: { break; } } + assert( pOp[1].opcode==OP_Jump ); break; } @@ -89013,8 +90750,11 @@ case OP_Compare: { ** Jump to the instruction at address P1, P2, or P3 depending on whether ** in the most recent OP_Compare instruction the P1 vector was less than ** equal to, or greater than the P2 vector, respectively. +** +** This opcode must immediately follow an OP_Compare opcode. */ case OP_Jump: { /* jump */ + assert( pOp>aOp && pOp[-1].opcode==OP_Compare ); if( iCompare<0 ){ VdbeBranchTaken(0,4); pOp = &aOp[pOp->p1 - 1]; }else if( iCompare==0 ){ @@ -89301,17 +91041,25 @@ case OP_Offset: { /* out3 */ assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; pOut = &p->aMem[pOp->p3]; - if( NEVER(pC==0) || pC->eCurType!=CURTYPE_BTREE ){ + if( pC==0 || pC->eCurType!=CURTYPE_BTREE ){ sqlite3VdbeMemSetNull(pOut); }else{ - sqlite3VdbeMemSetInt64(pOut, sqlite3BtreeOffset(pC->uc.pCursor)); + if( pC->deferredMoveto ){ + rc = sqlite3VdbeFinishMoveto(pC); + if( rc ) goto abort_due_to_error; + } + if( sqlite3BtreeEof(pC->uc.pCursor) ){ + sqlite3VdbeMemSetNull(pOut); + }else{ + sqlite3VdbeMemSetInt64(pOut, sqlite3BtreeOffset(pC->uc.pCursor)); + } } break; } #endif /* SQLITE_ENABLE_OFFSET_SQL_FUNC */ /* Opcode: Column P1 P2 P3 P4 P5 -** Synopsis: r[P3]=PX +** Synopsis: r[P3]=PX cursor P1 column P2 ** ** Interpret the data that cursor P1 points to as a structure built using ** the MakeRecord instruction. (See the MakeRecord opcode for additional @@ -89333,7 +91081,7 @@ case OP_Offset: { /* out3 */ case OP_Column: { u32 p2; /* column number to retrieve */ VdbeCursor *pC; /* The VDBE cursor */ - BtCursor *pCrsr; /* The BTree cursor */ + BtCursor *pCrsr; /* The B-Tree cursor corresponding to pC */ u32 *aOffset; /* aOffset[i] is offset to start of data for i-th column */ int len; /* The length of the serialized data for the column */ int i; /* Loop counter */ @@ -89347,43 +91095,53 @@ case OP_Column: { Mem *pReg; /* PseudoTable input register */ assert( pOp->p1>=0 && pOp->p1nCursor ); + assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) ); pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); p2 = (u32)pOp->p2; - /* If the cursor cache is stale (meaning it is not currently point at - ** the correct row) then bring it up-to-date by doing the necessary - ** B-Tree seek. */ - rc = sqlite3VdbeCursorMoveto(&pC, &p2); - if( rc ) goto abort_due_to_error; - - assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) ); - pDest = &aMem[pOp->p3]; - memAboutToChange(p, pDest); +op_column_restart: assert( pC!=0 ); - assert( p2<(u32)pC->nField ); + assert( p2<(u32)pC->nField + || (pC->eCurType==CURTYPE_PSEUDO && pC->seekResult==0) ); aOffset = pC->aOffset; + assert( aOffset==pC->aType+pC->nField ); assert( pC->eCurType!=CURTYPE_VTAB ); assert( pC->eCurType!=CURTYPE_PSEUDO || pC->nullRow ); assert( pC->eCurType!=CURTYPE_SORTER ); if( pC->cacheStatus!=p->cacheCtr ){ /*OPTIMIZATION-IF-FALSE*/ if( pC->nullRow ){ - if( pC->eCurType==CURTYPE_PSEUDO ){ + if( pC->eCurType==CURTYPE_PSEUDO && pC->seekResult>0 ){ /* For the special case of as pseudo-cursor, the seekResult field ** identifies the register that holds the record */ - assert( pC->seekResult>0 ); pReg = &aMem[pC->seekResult]; assert( pReg->flags & MEM_Blob ); assert( memIsValid(pReg) ); pC->payloadSize = pC->szRow = pReg->n; pC->aRow = (u8*)pReg->z; }else{ + pDest = &aMem[pOp->p3]; + memAboutToChange(p, pDest); sqlite3VdbeMemSetNull(pDest); goto op_column_out; } }else{ pCrsr = pC->uc.pCursor; + if( pC->deferredMoveto ){ + u32 iMap; + assert( !pC->isEphemeral ); + if( pC->ub.aAltMap && (iMap = pC->ub.aAltMap[1+p2])>0 ){ + pC = pC->pAltCursor; + p2 = iMap - 1; + goto op_column_restart; + } + rc = sqlite3VdbeFinishMoveto(pC); + if( rc ) goto abort_due_to_error; + }else if( sqlite3BtreeCursorHasMoved(pCrsr) ){ + rc = sqlite3VdbeHandleMovedCursor(pC); + if( rc ) goto abort_due_to_error; + goto op_column_restart; + } assert( pC->eCurType==CURTYPE_BTREE ); assert( pCrsr ); assert( sqlite3BtreeCursorIsValid(pCrsr) ); @@ -89391,15 +91149,15 @@ case OP_Column: { pC->aRow = sqlite3BtreePayloadFetch(pCrsr, &pC->szRow); assert( pC->szRow<=pC->payloadSize ); assert( pC->szRow<=65536 ); /* Maximum page size is 64KiB */ - if( pC->payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){ - goto too_big; - } } pC->cacheStatus = p->cacheCtr; - pC->iHdrOffset = getVarint32(pC->aRow, aOffset[0]); + if( (aOffset[0] = pC->aRow[0])<0x80 ){ + pC->iHdrOffset = 1; + }else{ + pC->iHdrOffset = sqlite3GetVarint32(pC->aRow, aOffset); + } pC->nHdrParsed = 0; - if( pC->szRowaRow does not have to hold the entire row, but it does at least ** need to cover the header of the record. If pC->aRow does not contain @@ -89439,6 +91197,10 @@ case OP_Column: { testcase( aOffset[0]==0 ); goto op_column_read_header; } + }else if( sqlite3BtreeCursorHasMoved(pC->uc.pCursor) ){ + rc = sqlite3VdbeHandleMovedCursor(pC); + if( rc ) goto abort_due_to_error; + goto op_column_restart; } /* Make sure at least the first p2+1 entries of the header have been @@ -89507,6 +91269,8 @@ case OP_Column: { ** columns. So the result will be either the default value or a NULL. */ if( pC->nHdrParsed<=p2 ){ + pDest = &aMem[pOp->p3]; + memAboutToChange(p, pDest); if( pOp->p4type==P4_MEM ){ sqlite3VdbeMemShallowCopy(pDest, pOp->p4.pMem, MEM_Static); }else{ @@ -89524,6 +91288,8 @@ case OP_Column: { */ assert( p2nHdrParsed ); assert( rc==SQLITE_OK ); + pDest = &aMem[pOp->p3]; + memAboutToChange(p, pDest); assert( sqlite3VdbeCheckMemInvariants(pDest) ); if( VdbeMemDynamic(pDest) ){ sqlite3VdbeMemSetNull(pDest); @@ -89544,6 +91310,7 @@ case OP_Column: { pDest->n = len = (t-12)/2; pDest->enc = encoding; if( pDest->szMalloc < len+2 ){ + if( len>db->aLimit[SQLITE_LIMIT_LENGTH] ) goto too_big; pDest->flags = MEM_Null; if( sqlite3VdbeMemGrow(pDest, len+2, 0) ) goto no_mem; }else{ @@ -89576,6 +91343,7 @@ case OP_Column: { */ sqlite3VdbeSerialGet((u8*)sqlite3CtypeMap, t, pDest); }else{ + if( len>db->aLimit[SQLITE_LIMIT_LENGTH] ) goto too_big; rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, aOffset[p2], len, pDest); if( rc!=SQLITE_OK ) goto abort_due_to_error; sqlite3VdbeSerialGet((const u8*)pDest->z, t, pDest); @@ -89658,6 +91426,8 @@ case OP_TypeCheck: { break; } case COLTYPE_REAL: { + testcase( (pIn1->flags & (MEM_Real|MEM_IntReal))==MEM_Real ); + testcase( (pIn1->flags & (MEM_Real|MEM_IntReal))==MEM_IntReal ); if( pIn1->flags & MEM_Int ){ /* When applying REAL affinity, if the result is still an MEM_Int ** that will fit in 6 bytes, then change the type to MEM_IntReal @@ -89675,7 +91445,7 @@ case OP_TypeCheck: { pIn1->flags |= MEM_Real; pIn1->flags &= ~MEM_Int; } - }else if( (pIn1->flags & MEM_Real)==0 ){ + }else if( (pIn1->flags & (MEM_Real|MEM_IntReal))==0 ){ goto vdbe_type_error; } break; @@ -89786,7 +91556,6 @@ case OP_MakeRecord: { Mem *pLast; /* Last field of the record */ int nField; /* Number of fields in the record */ char *zAffinity; /* The affinity string for the record */ - int file_format; /* File format to use for encoding */ u32 len; /* Length of a field */ u8 *zHdr; /* Where to write next byte of the header */ u8 *zPayload; /* Where to write next byte of the payload */ @@ -89815,7 +91584,6 @@ case OP_MakeRecord: { pData0 = &aMem[nField]; nField = pOp->p2; pLast = &pData0[nField-1]; - file_format = p->minWriteFileFormat; /* Identify the output register */ assert( pOp->p3p1 || pOp->p3>=pOp->p1+pOp->p2 ); @@ -89914,10 +91682,10 @@ case OP_MakeRecord: { testcase( uu==127 ); testcase( uu==128 ); testcase( uu==32767 ); testcase( uu==32768 ); testcase( uu==8388607 ); testcase( uu==8388608 ); - testcase( uu==2147483647 ); testcase( uu==2147483648 ); + testcase( uu==2147483647 ); testcase( uu==2147483648LL ); testcase( uu==140737488355327LL ); testcase( uu==140737488355328LL ); if( uu<=127 ){ - if( (i&1)==i && file_format>=4 ){ + if( (i&1)==i && p->minWriteFileFormat>=4 ){ pRec->uTemp = 8+(u32)uu; }else{ nData++; @@ -90022,18 +91790,60 @@ case OP_MakeRecord: { zPayload = zHdr + nHdr; /* Write the record */ - zHdr += putVarint32(zHdr, nHdr); + if( nHdr<0x80 ){ + *(zHdr++) = nHdr; + }else{ + zHdr += sqlite3PutVarint(zHdr,nHdr); + } assert( pData0<=pLast ); pRec = pData0; - do{ + while( 1 /*exit-by-break*/ ){ serial_type = pRec->uTemp; /* EVIDENCE-OF: R-06529-47362 Following the size varint are one or more - ** additional varints, one per column. */ - zHdr += putVarint32(zHdr, serial_type); /* serial type */ - /* EVIDENCE-OF: R-64536-51728 The values for each column in the record + ** additional varints, one per column. + ** EVIDENCE-OF: R-64536-51728 The values for each column in the record ** immediately follow the header. */ - zPayload += sqlite3VdbeSerialPut(zPayload, pRec, serial_type); /* content */ - }while( (++pRec)<=pLast ); + if( serial_type<=7 ){ + *(zHdr++) = serial_type; + if( serial_type==0 ){ + /* NULL value. No change in zPayload */ + }else{ + u64 v; + u32 i; + if( serial_type==7 ){ + assert( sizeof(v)==sizeof(pRec->u.r) ); + memcpy(&v, &pRec->u.r, sizeof(v)); + swapMixedEndianFloat(v); + }else{ + v = pRec->u.i; + } + len = i = sqlite3SmallTypeSizes[serial_type]; + assert( i>0 ); + while( 1 /*exit-by-break*/ ){ + zPayload[--i] = (u8)(v&0xFF); + if( i==0 ) break; + v >>= 8; + } + zPayload += len; + } + }else if( serial_type<0x80 ){ + *(zHdr++) = serial_type; + if( serial_type>=14 && pRec->n>0 ){ + assert( pRec->z!=0 ); + memcpy(zPayload, pRec->z, pRec->n); + zPayload += pRec->n; + } + }else{ + zHdr += sqlite3PutVarint(zHdr, serial_type); + if( pRec->n ){ + assert( pRec->z!=0 ); + memcpy(zPayload, pRec->z, pRec->n); + zPayload += pRec->n; + } + } + if( pRec==pLast ) break; + pRec++; + } assert( nHdr==(int)(zHdr - (u8*)pOut->z) ); assert( nByte==(int)(zPayload - (u8*)pOut->z) ); @@ -90042,7 +91852,7 @@ case OP_MakeRecord: { break; } -/* Opcode: Count P1 P2 p3 * * +/* Opcode: Count P1 P2 P3 * * ** Synopsis: r[P2]=count() ** ** Store the number of entries (an integer value) in the table or index @@ -90252,7 +92062,10 @@ case OP_Savepoint: { } } if( rc ) goto abort_due_to_error; - + if( p->eVdbeState==VDBE_HALT_STATE ){ + rc = SQLITE_DONE; + goto vdbe_return; + } break; } @@ -90356,6 +92169,7 @@ case OP_AutoCommit: { */ case OP_Transaction: { Btree *pBt; + Db *pDb; int iMeta = 0; assert( p->bIsReader ); @@ -90375,7 +92189,8 @@ case OP_Transaction: { } goto abort_due_to_error; } - pBt = db->aDb[pOp->p1].pBt; + pDb = &db->aDb[pOp->p1]; + pBt = pDb->pBt; if( pBt ){ rc = sqlite3BtreeBeginTrans(pBt, pOp->p2, &iMeta); @@ -90416,8 +92231,7 @@ case OP_Transaction: { assert( pOp->p5==0 || pOp->p4type==P4_INT32 ); if( rc==SQLITE_OK && pOp->p5 - && (iMeta!=pOp->p3 - || db->aDb[pOp->p1].pSchema->iGeneration!=pOp->p4.i) + && (iMeta!=pOp->p3 || pDb->pSchema->iGeneration!=pOp->p4.i) ){ /* ** IMPLEMENTATION-OF: R-03189-51135 As each SQL statement runs, the schema @@ -90444,6 +92258,11 @@ case OP_Transaction: { } p->expired = 1; rc = SQLITE_SCHEMA; + + /* Set changeCntOn to 0 to prevent the value returned by sqlite3_changes() + ** from being modified in sqlite3VdbeHalt(). If this statement is + ** reprepared, changeCntOn will be set again. */ + p->changeCntOn = 0; } if( rc ) goto abort_due_to_error; break; @@ -90510,8 +92329,9 @@ case OP_SetCookie: { rc = sqlite3BtreeUpdateMeta(pDb->pBt, pOp->p2, pOp->p3); if( pOp->p2==BTREE_SCHEMA_VERSION ){ /* When the schema cookie changes, record the new cookie internally */ - pDb->pSchema->schema_cookie = pOp->p3 - pOp->p5; + *(u32*)&pDb->pSchema->schema_cookie = *(u32*)&pOp->p3 - pOp->p5; db->mDbFlags |= DBFLAG_SchemaChange; + sqlite3FkClearTriggerCache(db, pOp->p1); }else if( pOp->p2==BTREE_FILE_FORMAT ){ /* Record changes in the file format */ pDb->pSchema->file_format = pOp->p3; @@ -90689,8 +92509,9 @@ case OP_OpenWrite: assert( pOp->p1>=0 ); assert( nField>=0 ); testcase( nField==0 ); /* Table with INTEGER PRIMARY KEY and nothing else */ - pCur = allocateCursor(p, pOp->p1, nField, iDb, CURTYPE_BTREE); + pCur = allocateCursor(p, pOp->p1, nField, CURTYPE_BTREE); if( pCur==0 ) goto no_mem; + pCur->iDb = iDb; pCur->nullRow = 1; pCur->isOrdered = 1; pCur->pgnoRoot = p2; @@ -90732,7 +92553,7 @@ case OP_OpenDup: { assert( pOrig ); assert( pOrig->isEphemeral ); /* Only ephemeral cursors can be duplicated */ - pCx = allocateCursor(p, pOp->p1, pOrig->nField, -1, CURTYPE_BTREE); + pCx = allocateCursor(p, pOp->p1, pOrig->nField, CURTYPE_BTREE); if( pCx==0 ) goto no_mem; pCx->nullRow = 1; pCx->isEphemeral = 1; @@ -90740,10 +92561,10 @@ case OP_OpenDup: { pCx->isTable = pOrig->isTable; pCx->pgnoRoot = pOrig->pgnoRoot; pCx->isOrdered = pOrig->isOrdered; - pCx->pBtx = pOrig->pBtx; - pCx->hasBeenDuped = 1; - pOrig->hasBeenDuped = 1; - rc = sqlite3BtreeCursor(pCx->pBtx, pCx->pgnoRoot, BTREE_WRCSR, + pCx->ub.pBtx = pOrig->ub.pBtx; + pCx->noReuse = 1; + pOrig->noReuse = 1; + rc = sqlite3BtreeCursor(pCx->ub.pBtx, pCx->pgnoRoot, BTREE_WRCSR, pCx->pKeyInfo, pCx->uc.pCursor); /* The sqlite3BtreeCursor() routine can only fail for the first cursor ** opened for a database. Since there is already an open cursor when this @@ -90809,23 +92630,23 @@ case OP_OpenEphemeral: { aMem[pOp->p3].z = ""; } pCx = p->apCsr[pOp->p1]; - if( pCx && !pCx->hasBeenDuped && ALWAYS(pOp->p2<=pCx->nField) ){ + if( pCx && !pCx->noReuse && ALWAYS(pOp->p2<=pCx->nField) ){ /* If the ephermeral table is already open and has no duplicates from ** OP_OpenDup, then erase all existing content so that the table is ** empty again, rather than creating a new table. */ assert( pCx->isEphemeral ); pCx->seqCount = 0; pCx->cacheStatus = CACHE_STALE; - rc = sqlite3BtreeClearTable(pCx->pBtx, pCx->pgnoRoot, 0); + rc = sqlite3BtreeClearTable(pCx->ub.pBtx, pCx->pgnoRoot, 0); }else{ - pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, CURTYPE_BTREE); + pCx = allocateCursor(p, pOp->p1, pOp->p2, CURTYPE_BTREE); if( pCx==0 ) goto no_mem; pCx->isEphemeral = 1; - rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBtx, + rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->ub.pBtx, BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags); if( rc==SQLITE_OK ){ - rc = sqlite3BtreeBeginTrans(pCx->pBtx, 1, 0); + rc = sqlite3BtreeBeginTrans(pCx->ub.pBtx, 1, 0); if( rc==SQLITE_OK ){ /* If a transient index is required, create it by calling ** sqlite3BtreeCreateTable() with the BTREE_BLOBKEY flag before @@ -90834,26 +92655,26 @@ case OP_OpenEphemeral: { */ if( (pCx->pKeyInfo = pKeyInfo = pOp->p4.pKeyInfo)!=0 ){ assert( pOp->p4type==P4_KEYINFO ); - rc = sqlite3BtreeCreateTable(pCx->pBtx, &pCx->pgnoRoot, + rc = sqlite3BtreeCreateTable(pCx->ub.pBtx, &pCx->pgnoRoot, BTREE_BLOBKEY | pOp->p5); if( rc==SQLITE_OK ){ assert( pCx->pgnoRoot==SCHEMA_ROOT+1 ); assert( pKeyInfo->db==db ); assert( pKeyInfo->enc==ENC(db) ); - rc = sqlite3BtreeCursor(pCx->pBtx, pCx->pgnoRoot, BTREE_WRCSR, + rc = sqlite3BtreeCursor(pCx->ub.pBtx, pCx->pgnoRoot, BTREE_WRCSR, pKeyInfo, pCx->uc.pCursor); } pCx->isTable = 0; }else{ pCx->pgnoRoot = SCHEMA_ROOT; - rc = sqlite3BtreeCursor(pCx->pBtx, SCHEMA_ROOT, BTREE_WRCSR, + rc = sqlite3BtreeCursor(pCx->ub.pBtx, SCHEMA_ROOT, BTREE_WRCSR, 0, pCx->uc.pCursor); pCx->isTable = 1; } } pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED); if( rc ){ - sqlite3BtreeClose(pCx->pBtx); + sqlite3BtreeClose(pCx->ub.pBtx); } } } @@ -90877,7 +92698,7 @@ case OP_SorterOpen: { assert( pOp->p1>=0 ); assert( pOp->p2>=0 ); - pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, CURTYPE_SORTER); + pCx = allocateCursor(p, pOp->p1, pOp->p2, CURTYPE_SORTER); if( pCx==0 ) goto no_mem; pCx->pKeyInfo = pOp->p4.pKeyInfo; assert( pCx->pKeyInfo->db==db ); @@ -90926,7 +92747,7 @@ case OP_OpenPseudo: { assert( pOp->p1>=0 ); assert( pOp->p3>=0 ); - pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, CURTYPE_PSEUDO); + pCx = allocateCursor(p, pOp->p1, pOp->p3, CURTYPE_PSEUDO); if( pCx==0 ) goto no_mem; pCx->nullRow = 1; pCx->seekResult = pOp->p2; @@ -91558,11 +93379,8 @@ case OP_NoConflict: /* jump, in3 */ case OP_NotFound: /* jump, in3 */ case OP_Found: { /* jump, in3 */ int alreadyExists; - int takeJump; int ii; VdbeCursor *pC; - int res; - UnpackedRecord *pFree; UnpackedRecord *pIdxKey; UnpackedRecord r; @@ -91577,14 +93395,15 @@ case OP_Found: { /* jump, in3 */ #ifdef SQLITE_DEBUG pC->seekOp = pOp->opcode; #endif - pIn3 = &aMem[pOp->p3]; + r.aMem = &aMem[pOp->p3]; assert( pC->eCurType==CURTYPE_BTREE ); assert( pC->uc.pCursor!=0 ); assert( pC->isTable==0 ); - if( pOp->p4.i>0 ){ + r.nField = (u16)pOp->p4.i; + if( r.nField>0 ){ + /* Key values in an array of registers */ r.pKeyInfo = pC->pKeyInfo; - r.nField = (u16)pOp->p4.i; - r.aMem = pIn3; + r.default_rc = 0; #ifdef SQLITE_DEBUG for(ii=0; iip3+ii, &r.aMem[ii]); } #endif - pIdxKey = &r; - pFree = 0; + rc = sqlite3BtreeIndexMoveto(pC->uc.pCursor, &r, &pC->seekResult); }else{ - assert( pIn3->flags & MEM_Blob ); - rc = ExpandBlob(pIn3); + /* Composite key generated by OP_MakeRecord */ + assert( r.aMem->flags & MEM_Blob ); + assert( pOp->opcode!=OP_NoConflict ); + rc = ExpandBlob(r.aMem); assert( rc==SQLITE_OK || rc==SQLITE_NOMEM ); if( rc ) goto no_mem; - pFree = pIdxKey = sqlite3VdbeAllocUnpackedRecord(pC->pKeyInfo); + pIdxKey = sqlite3VdbeAllocUnpackedRecord(pC->pKeyInfo); if( pIdxKey==0 ) goto no_mem; - sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey); + sqlite3VdbeRecordUnpack(pC->pKeyInfo, r.aMem->n, r.aMem->z, pIdxKey); + pIdxKey->default_rc = 0; + rc = sqlite3BtreeIndexMoveto(pC->uc.pCursor, pIdxKey, &pC->seekResult); + sqlite3DbFreeNN(db, pIdxKey); } - pIdxKey->default_rc = 0; - takeJump = 0; - if( pOp->opcode==OP_NoConflict ){ - /* For the OP_NoConflict opcode, take the jump if any of the - ** input fields are NULL, since any key with a NULL will not - ** conflict */ - for(ii=0; iinField; ii++){ - if( pIdxKey->aMem[ii].flags & MEM_Null ){ - takeJump = 1; - break; - } - } - } - rc = sqlite3BtreeIndexMoveto(pC->uc.pCursor, pIdxKey, &res); - if( pFree ) sqlite3DbFreeNN(db, pFree); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } - pC->seekResult = res; - alreadyExists = (res==0); + alreadyExists = (pC->seekResult==0); pC->nullRow = 1-alreadyExists; pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; @@ -91630,9 +93437,25 @@ case OP_Found: { /* jump, in3 */ VdbeBranchTaken(alreadyExists!=0,2); if( alreadyExists ) goto jump_to_p2; }else{ - VdbeBranchTaken(takeJump||alreadyExists==0,2); - if( takeJump || !alreadyExists ) goto jump_to_p2; - if( pOp->opcode==OP_IfNoHope ) pC->seekHit = pOp->p4.i; + if( !alreadyExists ){ + VdbeBranchTaken(1,2); + goto jump_to_p2; + } + if( pOp->opcode==OP_NoConflict ){ + /* For the OP_NoConflict opcode, take the jump if any of the + ** input fields are NULL, since any key with a NULL will not + ** conflict */ + for(ii=0; iiopcode==OP_IfNoHope ){ + pC->seekHit = pOp->p4.i; + } } break; } @@ -92323,7 +94146,7 @@ case OP_RowData: { } /* Opcode: Rowid P1 P2 * * * -** Synopsis: r[P2]=rowid +** Synopsis: r[P2]=PX rowid of P1 ** ** Store in register P2 an integer which is the key of the table entry that ** P1 is currently point to. @@ -92378,13 +94201,25 @@ case OP_Rowid: { /* out2 */ ** Move the cursor P1 to a null row. Any OP_Column operations ** that occur while the cursor is on the null row will always ** write a NULL. +** +** If cursor P1 is not previously opened, open it now to a special +** pseudo-cursor that always returns NULL for every column. */ case OP_NullRow: { VdbeCursor *pC; assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; - assert( pC!=0 ); + if( pC==0 ){ + /* If the cursor is not already open, create a special kind of + ** pseudo-cursor that always gives null rows. */ + pC = allocateCursor(p, pOp->p1, 1, CURTYPE_PSEUDO); + if( pC==0 ) goto no_mem; + pC->seekResult = 0; + pC->isTable = 1; + pC->noReuse = 1; + pC->uc.pCursor = sqlite3BtreeFakeValidCursor(); + } pC->nullRow = 1; pC->cacheStatus = CACHE_STALE; if( pC->eCurType==CURTYPE_BTREE ){ @@ -92557,7 +94392,7 @@ case OP_Rewind: { /* jump */ break; } -/* Opcode: Next P1 P2 P3 P4 P5 +/* Opcode: Next P1 P2 P3 * P5 ** ** Advance cursor P1 so that it points to the next key/data pair in its ** table or index. If there are no more key/value pairs then fall through @@ -92576,15 +94411,12 @@ case OP_Rewind: { /* jump */ ** omitted if that index had been unique. P3 is usually 0. P3 is ** always either 0 or 1. ** -** P4 is always of type P4_ADVANCE. The function pointer points to -** sqlite3BtreeNext(). -** ** If P5 is positive and the jump is taken, then event counter ** number P5-1 in the prepared statement is incremented. ** ** See also: Prev */ -/* Opcode: Prev P1 P2 P3 P4 P5 +/* Opcode: Prev P1 P2 P3 * P5 ** ** Back up cursor P1 so that it points to the previous key/data pair in its ** table or index. If there is no previous key/value pairs then fall through @@ -92604,9 +94436,6 @@ case OP_Rewind: { /* jump */ ** omitted if that index had been unique. P3 is usually 0. P3 is ** always either 0 or 1. ** -** P4 is always of type P4_ADVANCE. The function pointer points to -** sqlite3BtreePrevious(). -** ** If P5 is positive and the jump is taken, then event counter ** number P5-1 in the prepared statement is incremented. */ @@ -92624,30 +94453,33 @@ case OP_SorterNext: { /* jump */ assert( isSorter(pC) ); rc = sqlite3VdbeSorterNext(db, pC); goto next_tail; + case OP_Prev: /* jump */ -case OP_Next: /* jump */ assert( pOp->p1>=0 && pOp->p1nCursor ); assert( pOp->p5aCounter) ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( pC->deferredMoveto==0 ); assert( pC->eCurType==CURTYPE_BTREE ); - assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext ); - assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious ); + assert( pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE + || pC->seekOp==OP_Last || pC->seekOp==OP_IfNoHope + || pC->seekOp==OP_NullRow); + rc = sqlite3BtreePrevious(pC->uc.pCursor, pOp->p3); + goto next_tail; - /* The Next opcode is only used after SeekGT, SeekGE, Rewind, and Found. - ** The Prev opcode is only used after SeekLT, SeekLE, and Last. */ - assert( pOp->opcode!=OP_Next - || pC->seekOp==OP_SeekGT || pC->seekOp==OP_SeekGE +case OP_Next: /* jump */ + assert( pOp->p1>=0 && pOp->p1nCursor ); + assert( pOp->p5aCounter) ); + pC = p->apCsr[pOp->p1]; + assert( pC!=0 ); + assert( pC->deferredMoveto==0 ); + assert( pC->eCurType==CURTYPE_BTREE ); + assert( pC->seekOp==OP_SeekGT || pC->seekOp==OP_SeekGE || pC->seekOp==OP_Rewind || pC->seekOp==OP_Found || pC->seekOp==OP_NullRow|| pC->seekOp==OP_SeekRowid || pC->seekOp==OP_IfNoHope); - assert( pOp->opcode!=OP_Prev - || pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE - || pC->seekOp==OP_Last || pC->seekOp==OP_IfNoHope - || pC->seekOp==OP_NullRow); + rc = sqlite3BtreeNext(pC->uc.pCursor, pOp->p3); - rc = pOp->p4.xAdvance(pC->uc.pCursor, pOp->p3); next_tail: pC->cacheStatus = CACHE_STALE; VdbeBranchTaken(rc==SQLITE_OK,2); @@ -92834,9 +94666,9 @@ case OP_IdxRowid: { /* out2 */ assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); - assert( pC->eCurType==CURTYPE_BTREE ); + assert( pC->eCurType==CURTYPE_BTREE || IsNullCursor(pC) ); assert( pC->uc.pCursor!=0 ); - assert( pC->isTable==0 ); + assert( pC->isTable==0 || IsNullCursor(pC) ); assert( pC->deferredMoveto==0 ); assert( !pC->nullRow || pOp->opcode==OP_IdxRowid ); @@ -92865,10 +94697,11 @@ case OP_IdxRowid: { /* out2 */ pTabCur->nullRow = 0; pTabCur->movetoTarget = rowid; pTabCur->deferredMoveto = 1; + pTabCur->cacheStatus = CACHE_STALE; assert( pOp->p4type==P4_INTARRAY || pOp->p4.ai==0 ); - pTabCur->aAltMap = pOp->p4.ai; - assert( !pC->isEphemeral ); assert( !pTabCur->isEphemeral ); + pTabCur->ub.aAltMap = pOp->p4.ai; + assert( !pC->isEphemeral ); pTabCur->pAltCursor = pC; }else{ pOut = out2Prerelease(p, pOp); @@ -92999,7 +94832,7 @@ case OP_IdxGE: { /* jump */ rc = sqlite3VdbeMemFromBtreeZeroOffset(pCur, (u32)nCellKey, &m); if( rc ) goto abort_due_to_error; res = sqlite3VdbeRecordCompareWithSkip(m.n, m.z, &r, 0); - sqlite3VdbeMemRelease(&m); + sqlite3VdbeMemReleaseMalloc(&m); } /* End of inlined sqlite3VdbeIdxKeyCompare() */ @@ -93880,6 +95713,7 @@ case OP_AggStep: { pCtx->pVdbe = p; pCtx->skipFlag = 0; pCtx->isError = 0; + pCtx->enc = encoding; pCtx->argc = n; pOp->p4type = P4_FUNCCTX; pOp->p4.pCtx = pCtx; @@ -94009,9 +95843,6 @@ case OP_AggFinal: { } sqlite3VdbeChangeEncoding(pMem, encoding); UPDATE_MAX_BLOBSIZE(pMem); - if( sqlite3VdbeMemTooBig(pMem) ){ - goto too_big; - } break; } @@ -94390,7 +96221,7 @@ case OP_VOpen: { pVCur->pVtab = pVtab; /* Initialize vdbe cursor object */ - pCur = allocateCursor(p, pOp->p1, 0, -1, CURTYPE_VTAB); + pCur = allocateCursor(p, pOp->p1, 0, CURTYPE_VTAB); if( pCur ){ pCur->uc.pVCur = pVCur; pVtab->nRef++; @@ -94403,6 +96234,34 @@ case OP_VOpen: { } #endif /* SQLITE_OMIT_VIRTUALTABLE */ +#ifndef SQLITE_OMIT_VIRTUALTABLE +/* Opcode: VInitIn P1 P2 P3 * * +** Synopsis: r[P2]=ValueList(P1,P3) +** +** Set register P2 to be a pointer to a ValueList object for cursor P1 +** with cache register P3 and output register P3+1. This ValueList object +** can be used as the first argument to sqlite3_vtab_in_first() and +** sqlite3_vtab_in_next() to extract all of the values stored in the P1 +** cursor. Register P3 is used to hold the values returned by +** sqlite3_vtab_in_first() and sqlite3_vtab_in_next(). +*/ +case OP_VInitIn: { /* out2 */ + VdbeCursor *pC; /* The cursor containing the RHS values */ + ValueList *pRhs; /* New ValueList object to put in reg[P2] */ + + pC = p->apCsr[pOp->p1]; + pRhs = sqlite3_malloc64( sizeof(*pRhs) ); + if( pRhs==0 ) goto no_mem; + pRhs->pCsr = pC->uc.pCursor; + pRhs->pOut = &aMem[pOp->p3]; + pOut = out2Prerelease(p, pOp); + pOut->flags = MEM_Null; + sqlite3VdbeMemSetPointer(pOut, pRhs, "ValueList", sqlite3_free); + break; +} +#endif /* SQLITE_OMIT_VIRTUALTABLE */ + + #ifndef SQLITE_OMIT_VIRTUALTABLE /* Opcode: VFilter P1 P2 P3 P4 * ** Synopsis: iplan=r[P3] zplan='P4' @@ -94491,7 +96350,6 @@ case OP_VColumn: { VdbeCursor *pCur = p->apCsr[pOp->p1]; assert( pCur!=0 ); - assert( pCur->eCurType==CURTYPE_VTAB ); assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) ); pDest = &aMem[pOp->p3]; memAboutToChange(p, pDest); @@ -94499,11 +96357,13 @@ case OP_VColumn: { sqlite3VdbeMemSetNull(pDest); break; } + assert( pCur->eCurType==CURTYPE_VTAB ); pVtab = pCur->uc.pVCur->pVtab; pModule = pVtab->pModule; assert( pModule->xColumn ); memset(&sContext, 0, sizeof(sContext)); sContext.pOut = pDest; + sContext.enc = encoding; assert( pOp->p5==OPFLAG_NOCHNG || pOp->p5==0 ); if( pOp->p5 & OPFLAG_NOCHNG ){ sqlite3VdbeMemSetNull(pDest); @@ -94522,9 +96382,6 @@ case OP_VColumn: { REGISTER_TRACE(pOp->p3, pDest); UPDATE_MAX_BLOBSIZE(pDest); - if( sqlite3VdbeMemTooBig(pDest) ){ - goto too_big; - } if( rc ) goto abort_due_to_error; break; } @@ -94791,6 +96648,7 @@ case OP_Function: { /* group */ if( pCtx->pOut != pOut ){ pCtx->pVdbe = p; pCtx->pOut = pOut; + pCtx->enc = encoding; for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i]; } assert( pCtx->pVdbe==p ); @@ -94817,17 +96675,98 @@ case OP_Function: { /* group */ if( rc ) goto abort_due_to_error; } - /* Copy the result of the function into register P3 */ - if( pOut->flags & (MEM_Str|MEM_Blob) ){ - sqlite3VdbeChangeEncoding(pOut, encoding); - if( sqlite3VdbeMemTooBig(pOut) ) goto too_big; - } + assert( (pOut->flags&MEM_Str)==0 + || pOut->enc==encoding + || db->mallocFailed ); + assert( !sqlite3VdbeMemTooBig(pOut) ); REGISTER_TRACE(pOp->p3, pOut); UPDATE_MAX_BLOBSIZE(pOut); break; } +/* Opcode: ClrSubtype P1 * * * * +** Synopsis: r[P1].subtype = 0 +** +** Clear the subtype from register P1. +*/ +case OP_ClrSubtype: { /* in1 */ + pIn1 = &aMem[pOp->p1]; + pIn1->flags &= ~MEM_Subtype; + break; +} + +/* Opcode: FilterAdd P1 * P3 P4 * +** Synopsis: filter(P1) += key(P3@P4) +** +** Compute a hash on the P4 registers starting with r[P3] and +** add that hash to the bloom filter contained in r[P1]. +*/ +case OP_FilterAdd: { + u64 h; + + assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); + pIn1 = &aMem[pOp->p1]; + assert( pIn1->flags & MEM_Blob ); + assert( pIn1->n>0 ); + h = filterHash(aMem, pOp); +#ifdef SQLITE_DEBUG + if( db->flags&SQLITE_VdbeTrace ){ + int ii; + for(ii=pOp->p3; iip3+pOp->p4.i; ii++){ + registerTrace(ii, &aMem[ii]); + } + printf("hash: %llu modulo %d -> %u\n", h, pIn1->n, (int)(h%pIn1->n)); + } +#endif + h %= pIn1->n; + pIn1->z[h/8] |= 1<<(h&7); + break; +} + +/* Opcode: Filter P1 P2 P3 P4 * +** Synopsis: if key(P3@P4) not in filter(P1) goto P2 +** +** Compute a hash on the key contained in the P4 registers starting +** with r[P3]. Check to see if that hash is found in the +** bloom filter hosted by register P1. If it is not present then +** maybe jump to P2. Otherwise fall through. +** +** False negatives are harmless. It is always safe to fall through, +** even if the value is in the bloom filter. A false negative causes +** more CPU cycles to be used, but it should still yield the correct +** answer. However, an incorrect answer may well arise from a +** false positive - if the jump is taken when it should fall through. +*/ +case OP_Filter: { /* jump */ + u64 h; + + assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) ); + pIn1 = &aMem[pOp->p1]; + assert( (pIn1->flags & MEM_Blob)!=0 ); + assert( pIn1->n >= 1 ); + h = filterHash(aMem, pOp); +#ifdef SQLITE_DEBUG + if( db->flags&SQLITE_VdbeTrace ){ + int ii; + for(ii=pOp->p3; iip3+pOp->p4.i; ii++){ + registerTrace(ii, &aMem[ii]); + } + printf("hash: %llu modulo %d -> %u\n", h, pIn1->n, (int)(h%pIn1->n)); + } +#endif + h %= pIn1->n; + if( (pIn1->z[h/8] & (1<<(h&7)))==0 ){ + VdbeBranchTaken(1, 2); + p->aCounter[SQLITE_STMTSTATUS_FILTER_HIT]++; + goto jump_to_p2; + }else{ + p->aCounter[SQLITE_STMTSTATUS_FILTER_MISS]++; + VdbeBranchTaken(0, 2); + } + break; +} + /* Opcode: Trace P1 P2 * P4 * ** ** Write P4 on the statement trace output if statement tracing is @@ -94876,7 +96815,7 @@ case OP_Init: { /* jump */ #ifndef SQLITE_OMIT_TRACE if( (db->mTrace & (SQLITE_TRACE_STMT|SQLITE_TRACE_LEGACY))!=0 - && !p->doingRerun + && p->minWriteFileFormat!=254 /* tag-20220401a */ && (zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0 ){ #ifndef SQLITE_OMIT_DEPRECATED @@ -95105,7 +97044,7 @@ default: { /* This is really OP_Noop, OP_Explain */ testcase( sqlite3GlobalConfig.xLog!=0 ); sqlite3_log(rc, "statement aborts at %d: [%s] %s", (int)(pOp - aOp), p->zSql, p->zErrMsg); - sqlite3VdbeHalt(p); + if( p->eVdbeState==VDBE_RUN_STATE ) sqlite3VdbeHalt(p); if( rc==SQLITE_IOERR_NOMEM ) sqlite3OomFault(db); if( rc==SQLITE_CORRUPT && db->autoCommit==0 ){ db->flags |= SQLITE_CorruptRdOnly; @@ -95318,10 +97257,9 @@ SQLITE_API int sqlite3_blob_open( sqlite3_mutex_enter(db->mutex); pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob)); - do { - memset(&sParse, 0, sizeof(Parse)); + while(1){ + sqlite3ParseObjectInit(&sParse,db); if( !pBlob ) goto blob_open_out; - sParse.db = db; sqlite3DbFree(db, zErr); zErr = 0; @@ -95498,7 +97436,9 @@ SQLITE_API int sqlite3_blob_open( goto blob_open_out; } rc = blobSeekToRow(pBlob, iRow, &zErr); - } while( (++nAttempt)=SQLITE_MAX_SCHEMA_RETRY || rc!=SQLITE_SCHEMA ) break; + sqlite3ParseObjectReset(&sParse); + } blob_open_out: if( rc==SQLITE_OK && db->mallocFailed==0 ){ @@ -95509,7 +97449,7 @@ SQLITE_API int sqlite3_blob_open( } sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr); sqlite3DbFree(db, zErr); - sqlite3ParserReset(&sParse); + sqlite3ParseObjectReset(&sParse); rc = sqlite3ApiExit(db, rc); sqlite3_mutex_leave(db->mutex); return rc; @@ -96644,7 +98584,8 @@ SQLITE_PRIVATE int sqlite3VdbeSorterInit( } #endif - assert( pCsr->pKeyInfo && pCsr->pBtx==0 ); + assert( pCsr->pKeyInfo ); + assert( !pCsr->isEphemeral ); assert( pCsr->eCurType==CURTYPE_SORTER ); szKeyInfo = sizeof(KeyInfo) + (pCsr->pKeyInfo->nKeyField-1)*sizeof(CollSeq*); sz = sizeof(VdbeSorter) + nWorker * sizeof(SortSubtask); @@ -99057,6 +100998,9 @@ static int memjrnlCreateFile(MemJournal *p){ } +/* Forward reference */ +static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size); + /* ** Write data to the file. */ @@ -99087,22 +101031,20 @@ static int memjrnlWrite( ** the in-memory journal is being used by a connection using the ** atomic-write optimization. In this case the first 28 bytes of the ** journal file may be written as part of committing the transaction. */ - assert( iOfst==p->endpoint.iOffset || iOfst==0 ); -#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \ - || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) + assert( iOfst<=p->endpoint.iOffset ); + if( iOfst>0 && iOfst!=p->endpoint.iOffset ){ + memjrnlTruncate(pJfd, iOfst); + } if( iOfst==0 && p->pFirst ){ assert( p->nChunkSize>iAmt ); memcpy((u8*)p->pFirst->zChunk, zBuf, iAmt); - }else -#else - assert( iOfst>0 || p->pFirst==0 ); -#endif - { + }else{ while( nWrite>0 ){ FileChunk *pChunk = p->endpoint.pChunk; int iChunkOffset = (int)(p->endpoint.iOffset%p->nChunkSize); int iSpace = MIN(nWrite, p->nChunkSize - iChunkOffset); + assert( pChunk!=0 || iChunkOffset==0 ); if( iChunkOffset==0 ){ /* New chunk is required to extend the file. */ FileChunk *pNew = sqlite3_malloc(fileChunkSize(p->nChunkSize)); @@ -99117,10 +101059,11 @@ static int memjrnlWrite( assert( !p->pFirst ); p->pFirst = pNew; } - p->endpoint.pChunk = pNew; + pChunk = p->endpoint.pChunk = pNew; } - memcpy((u8*)p->endpoint.pChunk->zChunk + iChunkOffset, zWrite, iSpace); + assert( pChunk!=0 ); + memcpy((u8*)pChunk->zChunk + iChunkOffset, zWrite, iSpace); zWrite += iSpace; nWrite -= iSpace; p->endpoint.iOffset += iSpace; @@ -99144,7 +101087,7 @@ static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){ p->pFirst = 0; }else{ i64 iOff = p->nChunkSize; - for(pIter=p->pFirst; ALWAYS(pIter) && iOff<=size; pIter=pIter->pNext){ + for(pIter=p->pFirst; ALWAYS(pIter) && iOffpNext){ iOff += p->nChunkSize; } if( ALWAYS(pIter) ){ @@ -99663,51 +101606,24 @@ static void resolveAlias( sqlite3ExprDelete(db, pDup); pDup = 0; }else{ + Expr temp; incrAggFunctionDepth(pDup, nSubquery); if( pExpr->op==TK_COLLATE ){ assert( !ExprHasProperty(pExpr, EP_IntValue) ); pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken); } - - /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This - ** prevents ExprDelete() from deleting the Expr structure itself, - ** allowing it to be repopulated by the memcpy() on the following line. - ** The pExpr->u.zToken might point into memory that will be freed by the - ** sqlite3DbFree(db, pDup) on the last line of this block, so be sure to - ** make a copy of the token before doing the sqlite3DbFree(). - */ - ExprSetProperty(pExpr, EP_Static); - sqlite3ExprDelete(db, pExpr); - memcpy(pExpr, pDup, sizeof(*pExpr)); - if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){ - assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 ); - pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken); - pExpr->flags |= EP_MemToken; - } + memcpy(&temp, pDup, sizeof(Expr)); + memcpy(pDup, pExpr, sizeof(Expr)); + memcpy(pExpr, &temp, sizeof(Expr)); if( ExprHasProperty(pExpr, EP_WinFunc) ){ if( ALWAYS(pExpr->y.pWin!=0) ){ pExpr->y.pWin->pOwner = pExpr; } } - sqlite3DbFree(db, pDup); - } -} - - -/* -** Return TRUE if the name zCol occurs anywhere in the USING clause. -** -** Return FALSE if the USING clause is NULL or if it does not contain -** zCol. -*/ -static int nameInUsingClause(IdList *pUsing, const char *zCol){ - if( pUsing ){ - int k; - for(k=0; knId; k++){ - if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ) return 1; - } + sqlite3ParserAddCleanup(pParse, + (void(*)(sqlite3*,void*))sqlite3ExprDelete, + pDup); } - return 0; } /* @@ -99725,7 +101641,7 @@ SQLITE_PRIVATE int sqlite3MatchEName( ){ int n; const char *zSpan; - if( pItem->eEName!=ENAME_TAB ) return 0; + if( pItem->fg.eEName!=ENAME_TAB ) return 0; zSpan = pItem->zEName; for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){} if( zDb && (sqlite3StrNICmp(zSpan, zDb, n)!=0 || zDb[n]!=0) ){ @@ -99786,6 +101702,29 @@ SQLITE_PRIVATE Bitmask sqlite3ExprColUsed(Expr *pExpr){ } } +/* +** Create a new expression term for the column specified by pMatch and +** iColumn. Append this new expression term to the FULL JOIN Match set +** in *ppList. Create a new *ppList if this is the first term in the +** set. +*/ +static void extendFJMatch( + Parse *pParse, /* Parsing context */ + ExprList **ppList, /* ExprList to extend */ + SrcItem *pMatch, /* Source table containing the column */ + i16 iColumn /* The column number */ +){ + Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLUMN, 0, 0); + if( pNew ){ + pNew->iTable = pMatch->iCursor; + pNew->iColumn = iColumn; + pNew->y.pTab = pMatch->pTab; + assert( (pMatch->fg.jointype & (JT_LEFT|JT_LTORJ))!=0 ); + ExprSetProperty(pNew, EP_CanBeNull); + *ppList = sqlite3ExprListAppend(pParse, *ppList, pNew); + } +} + /* ** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up ** that name in the set of source tables in pSrcList and make the pExpr @@ -99831,11 +101770,13 @@ static int lookupName( NameContext *pTopNC = pNC; /* First namecontext in the list */ Schema *pSchema = 0; /* Schema of the expression */ int eNewExprOp = TK_COLUMN; /* New value for pExpr->op on success */ - Table *pTab = 0; /* Table hold the row */ + Table *pTab = 0; /* Table holding the row */ Column *pCol; /* A column of pTab */ + ExprList *pFJMatch = 0; /* Matches for FULL JOIN .. USING */ assert( pNC ); /* the name context cannot be NULL. */ assert( zCol ); /* The Z in X.Y.Z cannot be NULL */ + assert( zDb==0 || zTab!=0 ); assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) ); /* Initialize the node to no-match */ @@ -99884,25 +101825,65 @@ static int lookupName( pTab = pItem->pTab; assert( pTab!=0 && pTab->zName!=0 ); assert( pTab->nCol>0 || pParse->nErr ); - if( pItem->pSelect && (pItem->pSelect->selFlags & SF_NestedFrom)!=0 ){ + assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) ); + if( pItem->fg.isNestedFrom ){ + /* In this case, pItem is a subquery that has been formed from a + ** parenthesized subset of the FROM clause terms. Example: + ** .... FROM t1 LEFT JOIN (t2 RIGHT JOIN t3 USING(x)) USING(y) ... + ** \_________________________/ + ** This pItem -------------^ + */ int hit = 0; + assert( pItem->pSelect!=0 ); pEList = pItem->pSelect->pEList; + assert( pEList!=0 ); + assert( pEList->nExpr==pTab->nCol ); for(j=0; jnExpr; j++){ - if( sqlite3MatchEName(&pEList->a[j], zCol, zTab, zDb) ){ - cnt++; - cntTab = 2; - pMatch = pItem; - pExpr->iColumn = j; - hit = 1; + if( !sqlite3MatchEName(&pEList->a[j], zCol, zTab, zDb) ){ + continue; + } + if( cnt>0 ){ + if( pItem->fg.isUsing==0 + || sqlite3IdListIndex(pItem->u3.pUsing, zCol)<0 + ){ + /* Two or more tables have the same column name which is + ** not joined by USING. This is an error. Signal as much + ** by clearing pFJMatch and letting cnt go above 1. */ + sqlite3ExprListDelete(db, pFJMatch); + pFJMatch = 0; + }else + if( (pItem->fg.jointype & JT_RIGHT)==0 ){ + /* An INNER or LEFT JOIN. Use the left-most table */ + continue; + }else + if( (pItem->fg.jointype & JT_LEFT)==0 ){ + /* A RIGHT JOIN. Use the right-most table */ + cnt = 0; + sqlite3ExprListDelete(db, pFJMatch); + pFJMatch = 0; + }else{ + /* For a FULL JOIN, we must construct a coalesce() func */ + extendFJMatch(pParse, &pFJMatch, pMatch, pExpr->iColumn); + } } + cnt++; + cntTab = 2; + pMatch = pItem; + pExpr->iColumn = j; + pEList->a[j].fg.bUsed = 1; + hit = 1; + if( pEList->a[j].fg.bUsingTerm ) break; } if( hit || zTab==0 ) continue; } - if( zDb && pTab->pSchema!=pSchema ){ - continue; - } + assert( zDb==0 || zTab!=0 ); if( zTab ){ - const char *zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName; + const char *zTabName; + if( zDb ){ + if( pTab->pSchema!=pSchema ) continue; + if( pSchema==0 && strcmp(zDb,"*")!=0 ) continue; + } + zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName; assert( zTabName!=0 ); if( sqlite3StrICmp(zTabName, zTab)!=0 ){ continue; @@ -99917,18 +101898,37 @@ static int lookupName( if( pCol->hName==hCol && sqlite3StrICmp(pCol->zCnName, zCol)==0 ){ - /* If there has been exactly one prior match and this match - ** is for the right-hand table of a NATURAL JOIN or is in a - ** USING clause, then skip this match. - */ - if( cnt==1 ){ - if( pItem->fg.jointype & JT_NATURAL ) continue; - if( nameInUsingClause(pItem->pUsing, zCol) ) continue; + if( cnt>0 ){ + if( pItem->fg.isUsing==0 + || sqlite3IdListIndex(pItem->u3.pUsing, zCol)<0 + ){ + /* Two or more tables have the same column name which is + ** not joined by USING. This is an error. Signal as much + ** by clearing pFJMatch and letting cnt go above 1. */ + sqlite3ExprListDelete(db, pFJMatch); + pFJMatch = 0; + }else + if( (pItem->fg.jointype & JT_RIGHT)==0 ){ + /* An INNER or LEFT JOIN. Use the left-most table */ + continue; + }else + if( (pItem->fg.jointype & JT_LEFT)==0 ){ + /* A RIGHT JOIN. Use the right-most table */ + cnt = 0; + sqlite3ExprListDelete(db, pFJMatch); + pFJMatch = 0; + }else{ + /* For a FULL JOIN, we must construct a coalesce() func */ + extendFJMatch(pParse, &pFJMatch, pMatch, pExpr->iColumn); + } } cnt++; pMatch = pItem; /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */ pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j; + if( pItem->fg.isNestedFrom ){ + sqlite3SrcItemColumnUsed(pItem, j); + } break; } } @@ -99941,9 +101941,7 @@ static int lookupName( pExpr->iTable = pMatch->iCursor; assert( ExprUseYTab(pExpr) ); pExpr->y.pTab = pMatch->pTab; - /* RIGHT JOIN not (yet) supported */ - assert( (pMatch->fg.jointype & JT_RIGHT)==0 ); - if( (pMatch->fg.jointype & JT_LEFT)!=0 ){ + if( (pMatch->fg.jointype & (JT_LEFT|JT_LTORJ))!=0 ){ ExprSetProperty(pExpr, EP_CanBeNull); } pSchema = pExpr->y.pTab->pSchema; @@ -100030,6 +102028,7 @@ static int lookupName( pExpr->y.pTab = pTab; if( pParse->bReturning ){ eNewExprOp = TK_REGISTER; + pExpr->op2 = TK_COLUMN; pExpr->iTable = pNC->uNC.iBaseReg + (pTab->nCol+1)*pExpr->iTable + sqlite3TableColumnToStorage(pTab, iCol) + 1; }else{ @@ -100096,7 +102095,7 @@ static int lookupName( assert( pEList!=0 ); for(j=0; jnExpr; j++){ char *zAs = pEList->a[j].zEName; - if( pEList->a[j].eEName==ENAME_NAME + if( pEList->a[j].fg.eEName==ENAME_NAME && sqlite3_stricmp(zAs, zCol)==0 ){ Expr *pOrig; @@ -100183,11 +102182,37 @@ static int lookupName( } /* - ** cnt==0 means there was not match. cnt>1 means there were two or - ** more matches. Either way, we have an error. + ** cnt==0 means there was not match. + ** cnt>1 means there were two or more matches. + ** + ** cnt==0 is always an error. cnt>1 is often an error, but might + ** be multiple matches for a NATURAL LEFT JOIN or a LEFT JOIN USING. */ + assert( pFJMatch==0 || cnt>0 ); + assert( !ExprHasProperty(pExpr, EP_xIsSelect|EP_IntValue) ); if( cnt!=1 ){ const char *zErr; + if( pFJMatch ){ + if( pFJMatch->nExpr==cnt-1 ){ + if( ExprHasProperty(pExpr,EP_Leaf) ){ + ExprClearProperty(pExpr,EP_Leaf); + }else{ + sqlite3ExprDelete(db, pExpr->pLeft); + pExpr->pLeft = 0; + sqlite3ExprDelete(db, pExpr->pRight); + pExpr->pRight = 0; + } + extendFJMatch(pParse, &pFJMatch, pMatch, pExpr->iColumn); + pExpr->op = TK_FUNCTION; + pExpr->u.zToken = "coalesce"; + pExpr->x.pList = pFJMatch; + cnt = 1; + goto lookupname_end; + }else{ + sqlite3ExprListDelete(db, pFJMatch); + pFJMatch = 0; + } + } zErr = cnt==0 ? "no such column" : "ambiguous column name"; if( zDb ){ sqlite3ErrorMsg(pParse, "%s: %s.%s.%s", zErr, zDb, zTab, zCol); @@ -100196,9 +102221,20 @@ static int lookupName( }else{ sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol); } + sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr); pParse->checkSchema = 1; pTopNC->nNcErr++; } + assert( pFJMatch==0 ); + + /* Remove all substructure from pExpr */ + if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){ + sqlite3ExprDelete(db, pExpr->pLeft); + pExpr->pLeft = 0; + sqlite3ExprDelete(db, pExpr->pRight); + pExpr->pRight = 0; + ExprSetProperty(pExpr, EP_Leaf); + } /* If a column from a table in pSrcList is referenced, then record ** this fact in the pSrcList.a[].colUsed bitmask. Column 0 causes @@ -100218,16 +102254,7 @@ static int lookupName( pMatch->colUsed |= sqlite3ExprColUsed(pExpr); } - /* Clean up and return - */ - if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){ - sqlite3ExprDelete(db, pExpr->pLeft); - pExpr->pLeft = 0; - sqlite3ExprDelete(db, pExpr->pRight); - pExpr->pRight = 0; - } pExpr->op = eNewExprOp; - ExprSetProperty(pExpr, EP_Leaf); lookupname_end: if( cnt==1 ){ assert( pNC!=0 ); @@ -100304,7 +102331,8 @@ static void notValidImpl( Parse *pParse, /* Leave error message here */ NameContext *pNC, /* The name context */ const char *zMsg, /* Type of error */ - Expr *pExpr /* Invalidate this expression on error */ + Expr *pExpr, /* Invalidate this expression on error */ + Expr *pError /* Associate error with this expression */ ){ const char *zIn = "partial index WHERE clauses"; if( pNC->ncFlags & NC_IdxExpr ) zIn = "index expressions"; @@ -100316,10 +102344,11 @@ static void notValidImpl( #endif sqlite3ErrorMsg(pParse, "%s prohibited in %s", zMsg, zIn); if( pExpr ) pExpr->op = TK_NULL; + sqlite3RecordErrorOffsetOfExpr(pParse->db, pError); } -#define sqlite3ResolveNotValid(P,N,M,X,E) \ +#define sqlite3ResolveNotValid(P,N,M,X,E,R) \ assert( ((X)&~(NC_IsCheck|NC_PartIdx|NC_IdxExpr|NC_GenCol))==0 ); \ - if( ((N)->ncFlags & (X))!=0 ) notValidImpl(P,N,M,E); + if( ((N)->ncFlags & (X))!=0 ) notValidImpl(P,N,M,E,R); /* ** Expression p should encode a floating point value between 1.0 and 0.0. @@ -100410,7 +102439,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ } sqlite3WalkExpr(pWalker, pExpr->pLeft); if( 0==sqlite3ExprCanBeNull(pExpr->pLeft) && !IN_RENAME_OBJECT ){ - testcase( ExprHasProperty(pExpr, EP_FromJoin) ); + testcase( ExprHasProperty(pExpr, EP_OuterON) ); assert( !ExprHasProperty(pExpr, EP_IntValue) ); if( pExpr->op==TK_NOTNULL ){ pExpr->u.zToken = "true"; @@ -100454,7 +102483,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ testcase( pNC->ncFlags & NC_IdxExpr ); testcase( pNC->ncFlags & NC_GenCol ); sqlite3ResolveNotValid(pParse, pNC, "the \".\" operator", - NC_IdxExpr|NC_GenCol, 0); + NC_IdxExpr|NC_GenCol, 0, pExpr); pRight = pExpr->pRight; if( pRight->op==TK_ID ){ zDb = 0; @@ -100485,7 +102514,6 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ int no_such_func = 0; /* True if no such function exists */ int wrong_num_args = 0; /* True if wrong number of arguments */ int is_agg = 0; /* True if is an aggregate function */ - int nId; /* Number of characters in function name */ const char *zId; /* The function name. */ FuncDef *pDef; /* Information about the function */ u8 enc = ENC(pParse->db); /* The database encoding */ @@ -100495,7 +102523,6 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ #endif assert( !ExprHasProperty(pExpr, EP_xIsSelect|EP_IntValue) ); zId = pExpr->u.zToken; - nId = sqlite3Strlen30(zId); pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0); if( pDef==0 ){ pDef = sqlite3FindFunction(pParse->db, zId, -2, enc, 0); @@ -100512,8 +102539,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ pExpr->iTable = exprProbability(pList->a[1].pExpr); if( pExpr->iTable<0 ){ sqlite3ErrorMsg(pParse, - "second argument to likelihood() must be a " - "constant between 0.0 and 1.0"); + "second argument to %#T() must be a " + "constant between 0.0 and 1.0", pExpr); pNC->nNcErr++; } }else{ @@ -100534,8 +102561,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ int auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0,pDef->zName,0); if( auth!=SQLITE_OK ){ if( auth==SQLITE_DENY ){ - sqlite3ErrorMsg(pParse, "not authorized to use function: %s", - pDef->zName); + sqlite3ErrorMsg(pParse, "not authorized to use function: %#T", + pExpr); pNC->nNcErr++; } pExpr->op = TK_NULL; @@ -100558,7 +102585,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ ** in a CHECK constraint. SQLServer, MySQL, and PostgreSQL all ** all this. */ sqlite3ResolveNotValid(pParse, pNC, "non-deterministic functions", - NC_IdxExpr|NC_PartIdx|NC_GenCol, 0); + NC_IdxExpr|NC_PartIdx|NC_GenCol, 0, pExpr); }else{ assert( (NC_SelfRef & 0xff)==NC_SelfRef ); /* Must fit in 8 bits */ pExpr->op2 = pNC->ncFlags & NC_SelfRef; @@ -100571,7 +102598,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ /* Internal-use-only functions are disallowed unless the ** SQL is being compiled using sqlite3NestedParse() or ** the SQLITE_TESTCTRL_INTERNAL_FUNCTIONS test-control has be - ** used to activate internal functionsn for testing purposes */ + ** used to activate internal functions for testing purposes */ no_such_func = 1; pDef = 0; }else @@ -100590,7 +102617,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ ); if( pDef && pDef->xValue==0 && pWin ){ sqlite3ErrorMsg(pParse, - "%.*s() may not be used as a window function", nId, zId + "%#T() may not be used as a window function", pExpr ); pNC->nNcErr++; }else if( @@ -100604,13 +102631,13 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ }else{ zType = "aggregate"; } - sqlite3ErrorMsg(pParse, "misuse of %s function %.*s()",zType,nId,zId); + sqlite3ErrorMsg(pParse, "misuse of %s function %#T()",zType,pExpr); pNC->nNcErr++; is_agg = 0; } #else if( (is_agg && (pNC->ncFlags & NC_AllowAgg)==0) ){ - sqlite3ErrorMsg(pParse,"misuse of aggregate function %.*s()",nId,zId); + sqlite3ErrorMsg(pParse,"misuse of aggregate function %#T()",pExpr); pNC->nNcErr++; is_agg = 0; } @@ -100620,18 +102647,18 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ && pParse->explain==0 #endif ){ - sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId); + sqlite3ErrorMsg(pParse, "no such function: %#T", pExpr); pNC->nNcErr++; }else if( wrong_num_args ){ - sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()", - nId, zId); + sqlite3ErrorMsg(pParse,"wrong number of arguments to function %#T()", + pExpr); pNC->nNcErr++; } #ifndef SQLITE_OMIT_WINDOWFUNC else if( is_agg==0 && ExprHasProperty(pExpr, EP_WinFunc) ){ sqlite3ErrorMsg(pParse, - "FILTER may not be used with non-aggregate %.*s()", - nId, zId + "FILTER may not be used with non-aggregate %#T()", + pExpr ); pNC->nNcErr++; } @@ -100716,7 +102743,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ testcase( pNC->ncFlags & NC_IdxExpr ); testcase( pNC->ncFlags & NC_GenCol ); if( pNC->ncFlags & NC_SelfRef ){ - notValidImpl(pParse, pNC, "subqueries", pExpr); + notValidImpl(pParse, pNC, "subqueries", pExpr, pExpr); }else{ sqlite3WalkSelect(pWalker, pExpr->x.pSelect); } @@ -100734,7 +102761,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ testcase( pNC->ncFlags & NC_IdxExpr ); testcase( pNC->ncFlags & NC_GenCol ); sqlite3ResolveNotValid(pParse, pNC, "parameters", - NC_IsCheck|NC_PartIdx|NC_IdxExpr|NC_GenCol, pExpr); + NC_IsCheck|NC_PartIdx|NC_IdxExpr|NC_GenCol, pExpr, pExpr); break; } case TK_IS: @@ -100786,11 +102813,13 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ testcase( pExpr->op==TK_ISNOT ); testcase( pExpr->op==TK_BETWEEN ); sqlite3ErrorMsg(pParse, "row value misused"); + sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr); } break; } } - return (pParse->nErr || pParse->db->mallocFailed) ? WRC_Abort : WRC_Continue; + assert( pParse->db->mallocFailed==0 || pParse->nErr!=0 ); + return pParse->nErr ? WRC_Abort : WRC_Continue; } /* @@ -100819,7 +102848,7 @@ static int resolveAsName( assert( !ExprHasProperty(pE, EP_IntValue) ); zCol = pE->u.zToken; for(i=0; inExpr; i++){ - if( pEList->a[i].eEName==ENAME_NAME + if( pEList->a[i].fg.eEName==ENAME_NAME && sqlite3_stricmp(pEList->a[i].zEName, zCol)==0 ){ return i+1; @@ -100898,11 +102927,13 @@ static void resolveOutOfRangeError( Parse *pParse, /* The error context into which to write the error */ const char *zType, /* "ORDER" or "GROUP" */ int i, /* The index (1-based) of the term out of range */ - int mx /* Largest permissible value of i */ + int mx, /* Largest permissible value of i */ + Expr *pError /* Associate the error with the expression */ ){ sqlite3ErrorMsg(pParse, "%r %s BY term out of range - should be " "between 1 and %d", i, zType, mx); + sqlite3RecordErrorOffsetOfExpr(pParse->db, pError); } /* @@ -100938,7 +102969,7 @@ static int resolveCompoundOrderBy( return 1; } for(i=0; inExpr; i++){ - pOrderBy->a[i].done = 0; + pOrderBy->a[i].fg.done = 0; } pSelect->pNext = 0; while( pSelect->pPrior ){ @@ -100953,12 +102984,12 @@ static int resolveCompoundOrderBy( for(i=0, pItem=pOrderBy->a; inExpr; i++, pItem++){ int iCol = -1; Expr *pE, *pDup; - if( pItem->done ) continue; + if( pItem->fg.done ) continue; pE = sqlite3ExprSkipCollateAndLikely(pItem->pExpr); if( NEVER(pE==0) ) continue; if( sqlite3ExprIsInteger(pE, &iCol) ){ if( iCol<=0 || iCol>pEList->nExpr ){ - resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr); + resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr, pE); return 1; } }else{ @@ -101006,7 +103037,7 @@ static int resolveCompoundOrderBy( sqlite3ExprDelete(db, pE); pItem->u.x.iOrderByCol = (u16)iCol; } - pItem->done = 1; + pItem->fg.done = 1; }else{ moreToDo = 1; } @@ -101014,7 +103045,7 @@ static int resolveCompoundOrderBy( pSelect = pSelect->pNext; } for(i=0; inExpr; i++){ - if( pOrderBy->a[i].done==0 ){ + if( pOrderBy->a[i].fg.done==0 ){ sqlite3ErrorMsg(pParse, "%r ORDER BY term does not match any " "column in the result set", i+1); return 1; @@ -101054,7 +103085,7 @@ SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy( for(i=0, pItem=pOrderBy->a; inExpr; i++, pItem++){ if( pItem->u.x.iOrderByCol ){ if( pItem->u.x.iOrderByCol>pEList->nExpr ){ - resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr); + resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr, 0); return 1; } resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr,0); @@ -101146,7 +103177,7 @@ static int resolveOrderGroupBy( ** number so that sqlite3ResolveOrderGroupBy() will convert the ** order-by term to a copy of the result-set expression */ if( iCol<1 || iCol>0xffff ){ - resolveOutOfRangeError(pParse, zType, i+1, nResult); + resolveOutOfRangeError(pParse, zType, i+1, nResult, pE2); return 1; } pItem->u.x.iOrderByCol = (u16)iCol; @@ -101204,7 +103235,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ */ if( (p->selFlags & SF_Expanded)==0 ){ sqlite3SelectPrep(pParse, p, pOuterNC); - return (pParse->nErr || db->mallocFailed) ? WRC_Abort : WRC_Prune; + return pParse->nErr ? WRC_Abort : WRC_Prune; } isCompound = p->pPrior!=0; @@ -101252,7 +103283,8 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ if( pItem->zName ) pParse->zAuthContext = pItem->zName; sqlite3ResolveSelectNames(pParse, pItem->pSelect, pOuterNC); pParse->zAuthContext = zSavedContext; - if( pParse->nErr || db->mallocFailed ) return WRC_Abort; + if( pParse->nErr ) return WRC_Abort; + assert( db->mallocFailed==0 ); /* If the number of references to the outer context changed when ** expressions in the sub-select were resolved, the sub-select @@ -101303,8 +103335,8 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ sNC.uNC.pEList = p->pEList; sNC.ncFlags |= NC_UEList; if( p->pHaving ){ - if( !pGroupBy ){ - sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING"); + if( (p->selFlags & SF_Aggregate)==0 ){ + sqlite3ErrorMsg(pParse, "HAVING clause on a non-aggregate query"); return WRC_Abort; } if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort; @@ -102398,9 +104430,8 @@ static void heightOfSelect(const Select *pSelect, int *pnHeight){ ** if appropriate. */ static void exprSetHeight(Expr *p){ - int nHeight = 0; - heightOfExpr(p->pLeft, &nHeight); - heightOfExpr(p->pRight, &nHeight); + int nHeight = p->pLeft ? p->pLeft->nHeight : 0; + if( p->pRight && p->pRight->nHeight>nHeight ) nHeight = p->pRight->nHeight; if( ExprUseXSelect(p) ){ heightOfSelect(p->x.pSelect, &nHeight); }else if( p->x.pList ){ @@ -102699,6 +104730,8 @@ SQLITE_PRIVATE Expr *sqlite3ExprFunction( sqlite3ExprListDelete(db, pList); /* Avoid memory leak when malloc fails */ return 0; } + assert( !ExprHasProperty(pNew, EP_InnerON|EP_OuterON) ); + pNew->w.iOfst = (int)(pToken->z - pParse->zTail); if( pList && pList->nExpr > pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] && !pParse->nested @@ -102742,7 +104775,7 @@ SQLITE_PRIVATE void sqlite3ExprFunctionUsable( ** SQLITE_DBCONFIG_TRUSTED_SCHEMA is off (meaning ** that the schema is possibly tainted). */ - sqlite3ErrorMsg(pParse, "unsafe use of %s()", pDef->zName); + sqlite3ErrorMsg(pParse, "unsafe use of %#T()", pExpr); } } } @@ -102798,6 +104831,7 @@ SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n if( bOk==0 || i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d", db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]); + sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr); return; } x = (ynVar)i; @@ -102825,6 +104859,7 @@ SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n pExpr->iColumn = x; if( x>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){ sqlite3ErrorMsg(pParse, "too many SQL variables"); + sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr); } } @@ -102876,6 +104911,18 @@ SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){ if( p ) sqlite3ExprDeleteNN(db, p); } +/* +** Clear both elements of an OnOrUsing object +*/ +SQLITE_PRIVATE void sqlite3ClearOnOrUsing(sqlite3 *db, OnOrUsing *p){ + if( p==0 ){ + /* Nothing to clear */ + }else if( p->pOn ){ + sqlite3ExprDeleteNN(db, p->pOn); + }else if( p->pUsing ){ + sqlite3IdListDelete(db, p->pUsing); + } +} /* ** Arrange to cause pExpr to be deleted when the pParse is deleted. @@ -102962,7 +105009,7 @@ static int dupedExprStructSize(const Expr *p, int flags){ nSize = EXPR_FULLSIZE; }else{ assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) ); - assert( !ExprHasProperty(p, EP_FromJoin) ); + assert( !ExprHasProperty(p, EP_OuterON) ); assert( !ExprHasProperty(p, EP_MemToken) ); assert( !ExprHasVVAProperty(p, EP_NoReduce) ); if( p->pLeft || p->x.pList ){ @@ -103142,6 +105189,7 @@ SQLITE_PRIVATE With *sqlite3WithDup(sqlite3 *db, With *p){ pRet->a[i].pSelect = sqlite3SelectDup(db, p->a[i].pSelect, 0); pRet->a[i].pCols = sqlite3ExprListDup(db, p->a[i].pCols, 0); pRet->a[i].zName = sqlite3DbStrDup(db, p->a[i].zName); + pRet->a[i].eM10d = p->a[i].eM10d; } } } @@ -103242,11 +105290,8 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, const ExprList *p, int } } pItem->zEName = sqlite3DbStrDup(db, pOldItem->zEName); - pItem->sortFlags = pOldItem->sortFlags; - pItem->eEName = pOldItem->eEName; - pItem->done = 0; - pItem->bNulls = pOldItem->bNulls; - pItem->bSorterRef = pOldItem->bSorterRef; + pItem->fg = pOldItem->fg; + pItem->fg.done = 0; pItem->u = pOldItem->u; } return pNew; @@ -103298,8 +105343,12 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, const SrcList *p, int fla pTab->nTabRef++; } pNewItem->pSelect = sqlite3SelectDup(db, pOldItem->pSelect, flags); - pNewItem->pOn = sqlite3ExprDup(db, pOldItem->pOn, flags); - pNewItem->pUsing = sqlite3IdListDup(db, pOldItem->pUsing); + if( pOldItem->fg.isUsing ){ + assert( pNewItem->fg.isUsing ); + pNewItem->u3.pUsing = sqlite3IdListDup(db, pOldItem->u3.pUsing); + }else{ + pNewItem->u3.pOn = sqlite3ExprDup(db, pOldItem->u3.pOn, flags); + } pNewItem->colUsed = pOldItem->colUsed; } return pNew; @@ -103309,22 +105358,16 @@ SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3 *db, const IdList *p){ int i; assert( db!=0 ); if( p==0 ) return 0; - pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew) ); + assert( p->eU4!=EU4_EXPR ); + pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew)+(p->nId-1)*sizeof(p->a[0]) ); if( pNew==0 ) return 0; pNew->nId = p->nId; - pNew->a = sqlite3DbMallocRawNN(db, p->nId*sizeof(p->a[0]) ); - if( pNew->a==0 ){ - sqlite3DbFreeNN(db, pNew); - return 0; - } - /* Note that because the size of the allocation for p->a[] is not - ** necessarily a power of two, sqlite3IdListAppend() may not be called - ** on the duplicate created by this function. */ + pNew->eU4 = p->eU4; for(i=0; inId; i++){ struct IdList_item *pNewItem = &pNew->a[i]; - struct IdList_item *pOldItem = &p->a[i]; + const struct IdList_item *pOldItem = &p->a[i]; pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName); - pNewItem->idx = pOldItem->idx; + pNewItem->u4 = pOldItem->u4; } return pNew; } @@ -103548,16 +105591,16 @@ SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList *p, int iSortOrder, int ); pItem = &p->a[p->nExpr-1]; - assert( pItem->bNulls==0 ); + assert( pItem->fg.bNulls==0 ); if( iSortOrder==SQLITE_SO_UNDEFINED ){ iSortOrder = SQLITE_SO_ASC; } - pItem->sortFlags = (u8)iSortOrder; + pItem->fg.sortFlags = (u8)iSortOrder; if( eNulls!=SQLITE_SO_UNDEFINED ){ - pItem->bNulls = 1; + pItem->fg.bNulls = 1; if( iSortOrder!=eNulls ){ - pItem->sortFlags |= KEYINFO_ORDER_BIGNULL; + pItem->fg.sortFlags |= KEYINFO_ORDER_BIGNULL; } } } @@ -103583,7 +105626,7 @@ SQLITE_PRIVATE void sqlite3ExprListSetName( assert( pList->nExpr>0 ); pItem = &pList->a[pList->nExpr-1]; assert( pItem->zEName==0 ); - assert( pItem->eEName==ENAME_NAME ); + assert( pItem->fg.eEName==ENAME_NAME ); pItem->zEName = sqlite3DbStrNDup(pParse->db, pName->z, pName->n); if( dequote ){ /* If dequote==0, then pName->z does not point to part of a DDL @@ -103618,7 +105661,7 @@ SQLITE_PRIVATE void sqlite3ExprListSetSpan( assert( pList->nExpr>0 ); if( pItem->zEName==0 ){ pItem->zEName = sqlite3DbSpanDup(db, zStart, zEnd); - pItem->eEName = ENAME_SPAN; + pItem->fg.eEName = ENAME_SPAN; } } } @@ -103790,9 +105833,9 @@ SQLITE_PRIVATE Expr *sqlite3ExprSimplifiedAndOr(Expr *pExpr){ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){ /* If pWalker->eCode is 2 then any term of the expression that comes from - ** the ON or USING clauses of a left join disqualifies the expression + ** the ON or USING clauses of an outer join disqualifies the expression ** from being considered constant. */ - if( pWalker->eCode==2 && ExprHasProperty(pExpr, EP_FromJoin) ){ + if( pWalker->eCode==2 && ExprHasProperty(pExpr, EP_OuterON) ){ pWalker->eCode = 0; return WRC_Abort; } @@ -103911,6 +105954,42 @@ SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr *p, int iCur){ return exprIsConst(p, 3, iCur); } +/* +** Check pExpr to see if it is an invariant constraint on data source pSrc. +** This is an optimization. False negatives will perhaps cause slower +** queries, but false positives will yield incorrect answers. So when in +** doubt, return 0. +** +** To be an invariant constraint, the following must be true: +** +** (1) pExpr cannot refer to any table other than pSrc->iCursor. +** +** (2) pExpr cannot use subqueries or non-deterministic functions. +** +** (3) pSrc cannot be part of the left operand for a RIGHT JOIN. +** (Is there some way to relax this constraint?) +** +** (4) If pSrc is the right operand of a LEFT JOIN, then... +** (4a) pExpr must come from an ON clause.. + (4b) and specifically the ON clause associated with the LEFT JOIN. +** +** (5) If pSrc is not the right operand of a LEFT JOIN or the left +** operand of a RIGHT JOIN, then pExpr must be from the WHERE +** clause, not an ON clause. +*/ +SQLITE_PRIVATE int sqlite3ExprIsTableConstraint(Expr *pExpr, const SrcItem *pSrc){ + if( pSrc->fg.jointype & JT_LTORJ ){ + return 0; /* rule (3) */ + } + if( pSrc->fg.jointype & JT_LEFT ){ + if( !ExprHasProperty(pExpr, EP_OuterON) ) return 0; /* rule (4a) */ + if( pExpr->w.iJoin!=pSrc->iCursor ) return 0; /* rule (4b) */ + }else{ + if( ExprHasProperty(pExpr, EP_OuterON) ) return 0; /* rule (5) */ + } + return sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor); /* rules (1), (2) */ +} + /* ** sqlite3WalkExpr() callback used by sqlite3ExprIsConstantOrGroupBy(). @@ -104086,7 +106165,7 @@ SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr *p){ return ExprHasProperty(p, EP_CanBeNull) || p->y.pTab==0 || /* Reference to column of index on expression */ (p->iColumn>=0 - && ALWAYS(p->y.pTab->aCol!=0) /* Defense against OOM problems */ + && p->y.pTab->aCol!=0 /* Possible due to prior error */ && p->y.pTab->aCol[p->iColumn].notNull==0); default: return 1; @@ -104238,7 +106317,7 @@ static int sqlite3InRhsIsConstant(Expr *pIn){ ** all members of the RHS set, skipping duplicates. ** ** A cursor is opened on the b-tree object that is the RHS of the IN operator -** and pX->iTable is set to the index of that cursor. +** and the *piTab parameter is set to the index of that cursor. ** ** The returned value of this function indicates the b-tree type, as follows: ** @@ -104258,7 +106337,10 @@ static int sqlite3InRhsIsConstant(Expr *pIn){ ** If the RHS of the IN operator is a list or a more complex subquery, then ** an ephemeral table might need to be generated from the RHS and then ** pX->iTable made to point to the ephemeral table instead of an -** existing table. +** existing table. In this case, the creation and initialization of the +** ephmeral table might be put inside of a subroutine, the EP_Subrtn flag +** will be set on pX and the pX->y.sub fields will be set to show where +** the subroutine is coded. ** ** The inFlags parameter must contain, at a minimum, one of the bits ** IN_INDEX_MEMBERSHIP or IN_INDEX_LOOP but not both. If inFlags contains @@ -104319,12 +106401,13 @@ SQLITE_PRIVATE int sqlite3FindInIndex( ){ Select *p; /* SELECT to the right of IN operator */ int eType = 0; /* Type of RHS table. IN_INDEX_* */ - int iTab = pParse->nTab++; /* Cursor of the RHS table */ + int iTab; /* Cursor of the RHS table */ int mustBeUnique; /* True if RHS must be unique */ Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */ assert( pX->op==TK_IN ); mustBeUnique = (inFlags & IN_INDEX_LOOP)!=0; + iTab = pParse->nTab++; /* If the RHS of this IN(...) operator is a SELECT, and if it matters ** whether or not the SELECT result contains NULL values, check whether @@ -104432,8 +106515,7 @@ SQLITE_PRIVATE int sqlite3FindInIndex( CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs); int j; - assert( pReq!=0 || pRhs->iColumn==XN_ROWID - || pParse->nErr || db->mallocFailed ); + assert( pReq!=0 || pRhs->iColumn==XN_ROWID || pParse->nErr ); for(j=0; jaiColumn[j]!=pRhs->iColumn ) continue; assert( pIdx->azColl[j] ); @@ -104491,6 +106573,8 @@ SQLITE_PRIVATE int sqlite3FindInIndex( && ExprUseXList(pX) && (!sqlite3InRhsIsConstant(pX) || pX->x.pList->nExpr<=2) ){ + pParse->nTab--; /* Back out the allocation of the unused cursor */ + iTab = -1; /* Cursor is not allocated */ eType = IN_INDEX_NOOP; } @@ -104657,6 +106741,7 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN( assert( ExprUseYSub(pExpr) ); sqlite3VdbeAddOp2(v, OP_Gosub, pExpr->y.sub.regReturn, pExpr->y.sub.iAddr); + assert( iTab!=pExpr->iTable ); sqlite3VdbeAddOp2(v, OP_OpenDup, iTab, pExpr->iTable); sqlite3VdbeJumpHere(v, addrOnce); return; @@ -104668,8 +106753,7 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN( assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) ); pExpr->y.sub.regReturn = ++pParse->nMem; pExpr->y.sub.iAddr = - sqlite3VdbeAddOp2(v, OP_Integer, 0, pExpr->y.sub.regReturn) + 1; - VdbeComment((v, "return address")); + sqlite3VdbeAddOp2(v, OP_BeginSubrtn, 0, pExpr->y.sub.regReturn) + 1; addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); } @@ -104771,6 +106855,7 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN( ** expression we need to rerun this code each time. */ if( addrOnce && !sqlite3ExprIsConstant(pE2) ){ + sqlite3VdbeChangeToNoop(v, addrOnce-1); sqlite3VdbeChangeToNoop(v, addrOnce); ExprClearProperty(pExpr, EP_Subrtn); addrOnce = 0; @@ -104791,8 +106876,11 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN( sqlite3VdbeJumpHere(v, addrOnce); /* Subroutine return */ assert( ExprUseYSub(pExpr) ); - sqlite3VdbeAddOp1(v, OP_Return, pExpr->y.sub.regReturn); - sqlite3VdbeChangeP1(v, pExpr->y.sub.iAddr-1, sqlite3VdbeCurrentAddr(v)-1); + assert( sqlite3VdbeGetOp(v,pExpr->y.sub.iAddr-1)->opcode==OP_BeginSubrtn + || pParse->nErr ); + sqlite3VdbeAddOp3(v, OP_Return, pExpr->y.sub.regReturn, + pExpr->y.sub.iAddr, 1); + VdbeCoverage(v); sqlite3ClearTempRegCache(pParse); } } @@ -104846,9 +106934,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ ExprSetProperty(pExpr, EP_Subrtn); pExpr->y.sub.regReturn = ++pParse->nMem; pExpr->y.sub.iAddr = - sqlite3VdbeAddOp2(v, OP_Integer, 0, pExpr->y.sub.regReturn) + 1; - VdbeComment((v, "return address")); - + sqlite3VdbeAddOp2(v, OP_BeginSubrtn, 0, pExpr->y.sub.regReturn) + 1; /* The evaluation of the EXISTS/SELECT must be repeated every time it ** is encountered if any of the following is true: @@ -104909,10 +106995,8 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ } pSel->iLimit = 0; if( sqlite3Select(pParse, pSel, &dest) ){ - if( pParse->nErr ){ - pExpr->op2 = pExpr->op; - pExpr->op = TK_ERROR; - } + pExpr->op2 = pExpr->op; + pExpr->op = TK_ERROR; return 0; } pExpr->iTable = rReg = dest.iSDParm; @@ -104923,8 +107007,11 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ /* Subroutine return */ assert( ExprUseYSub(pExpr) ); - sqlite3VdbeAddOp1(v, OP_Return, pExpr->y.sub.regReturn); - sqlite3VdbeChangeP1(v, pExpr->y.sub.iAddr-1, sqlite3VdbeCurrentAddr(v)-1); + assert( sqlite3VdbeGetOp(v,pExpr->y.sub.iAddr-1)->opcode==OP_BeginSubrtn + || pParse->nErr ); + sqlite3VdbeAddOp3(v, OP_Return, pExpr->y.sub.regReturn, + pExpr->y.sub.iAddr, 1); + VdbeCoverage(v); sqlite3ClearTempRegCache(pParse); return rReg; } @@ -105129,10 +107216,9 @@ static void sqlite3ExprCodeIN( }else{ destStep2 = destStep6 = sqlite3VdbeMakeLabel(pParse); } - if( pParse->nErr ) goto sqlite3ExprCodeIN_finished; for(i=0; ipLeft, i); - if( pParse->db->mallocFailed ) goto sqlite3ExprCodeIN_oom_error; + if( pParse->nErr ) goto sqlite3ExprCodeIN_oom_error; if( sqlite3ExprCanBeNull(p) ){ sqlite3VdbeAddOp2(v, OP_IsNull, rLhs+i, destStep2); VdbeCoverage(v); @@ -105270,11 +107356,12 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){ c = sqlite3DecOrHexToI64(z, &value); if( (c==3 && !negFlag) || (c==2) || (negFlag && value==SMALLEST_INT64)){ #ifdef SQLITE_OMIT_FLOATING_POINT - sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z); + sqlite3ErrorMsg(pParse, "oversized integer: %s%#T", negFlag?"-":"",pExpr); #else #ifndef SQLITE_OMIT_HEX_INTEGER if( sqlite3_strnicmp(z,"0x",2)==0 ){ - sqlite3ErrorMsg(pParse, "hex literal too big: %s%s", negFlag?"-":"",z); + sqlite3ErrorMsg(pParse, "hex literal too big: %s%#T", + negFlag?"-":"",pExpr); }else #endif { @@ -105358,6 +107445,7 @@ SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable( } if( iCol<0 || iCol==pTab->iPKey ){ sqlite3VdbeAddOp2(v, OP_Rowid, iTabCur, regOut); + VdbeComment((v, "%s.rowid", pTab->zName)); }else{ int op; int x; @@ -105528,7 +107616,17 @@ static int exprCodeInlineFunction( caseExpr.x.pList = pFarg; return sqlite3ExprCodeTarget(pParse, &caseExpr, target); } - +#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC + case INLINEFUNC_sqlite_offset: { + Expr *pArg = pFarg->a[0].pExpr; + if( pArg->op==TK_COLUMN && pArg->iTable>=0 ){ + sqlite3VdbeAddOp3(v, OP_Offset, pArg->iTable, pArg->iColumn, target); + }else{ + sqlite3VdbeAddOp2(v, OP_Null, 0, target); + } + break; + } +#endif default: { /* The UNLIKELY() function is a no-op. The result is the value ** of the first argument. @@ -105950,7 +108048,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) || NEVER(pExpr->iAgg>=pInfo->nFunc) ){ assert( !ExprHasProperty(pExpr, EP_IntValue) ); - sqlite3ErrorMsg(pParse, "misuse of aggregate: %s()", pExpr->u.zToken); + sqlite3ErrorMsg(pParse, "misuse of aggregate: %#T()", pExpr); }else{ return pInfo->aFunc[pExpr->iAgg].iMem; } @@ -105991,7 +108089,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) } #endif if( pDef==0 || pDef->xFinalize!=0 ){ - sqlite3ErrorMsg(pParse, "unknown function: %s()", zId); + sqlite3ErrorMsg(pParse, "unknown function: %#T()", pExpr); break; } if( pDef->funcFlags & SQLITE_FUNC_INLINE ){ @@ -106067,20 +108165,8 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) if( !pColl ) pColl = db->pDfltColl; sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ); } -#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC - if( (pDef->funcFlags & SQLITE_FUNC_OFFSET)!=0 && ALWAYS(pFarg!=0) ){ - Expr *pArg = pFarg->a[0].pExpr; - if( pArg->op==TK_COLUMN ){ - sqlite3VdbeAddOp3(v, OP_Offset, pArg->iTable, pArg->iColumn, target); - }else{ - sqlite3VdbeAddOp2(v, OP_Null, 0, target); - } - }else -#endif - { - sqlite3VdbeAddFunctionCall(pParse, constMask, r1, target, nFarg, - pDef, pExpr->op2); - } + sqlite3VdbeAddFunctionCall(pParse, constMask, r1, target, nFarg, + pDef, pExpr->op2); if( nFarg ){ if( constMask==0 ){ sqlite3ReleaseTempRange(pParse, r1, nFarg); @@ -106110,16 +108196,18 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) } case TK_SELECT_COLUMN: { int n; - if( pExpr->pLeft->iTable==0 ){ - pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft); + Expr *pLeft = pExpr->pLeft; + if( pLeft->iTable==0 || pParse->withinRJSubrtn > pLeft->op2 ){ + pLeft->iTable = sqlite3CodeSubselect(pParse, pLeft); + pLeft->op2 = pParse->withinRJSubrtn; } - assert( pExpr->pLeft->op==TK_SELECT || pExpr->pLeft->op==TK_ERROR ); - n = sqlite3ExprVectorSize(pExpr->pLeft); + assert( pLeft->op==TK_SELECT || pLeft->op==TK_ERROR ); + n = sqlite3ExprVectorSize(pLeft); if( pExpr->iTable!=n ){ sqlite3ErrorMsg(pParse, "%d columns assigned %d values", pExpr->iTable, n); } - return pExpr->pLeft->iTable + pExpr->iColumn; + return pLeft->iTable + pExpr->iColumn; } case TK_IN: { int destIfFalse = sqlite3VdbeMakeLabel(pParse); @@ -106150,8 +108238,24 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) exprCodeBetween(pParse, pExpr, target, 0, 0); return target; } + case TK_COLLATE: { + if( !ExprHasProperty(pExpr, EP_Collate) + && ALWAYS(pExpr->pLeft) + && pExpr->pLeft->op==TK_FUNCTION + ){ + inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); + if( inReg!=target ){ + sqlite3VdbeAddOp2(v, OP_SCopy, inReg, target); + inReg = target; + } + sqlite3VdbeAddOp1(v, OP_ClrSubtype, inReg); + return inReg; + }else{ + pExpr = pExpr->pLeft; + goto expr_code_doover; /* 2018-04-28: Prevent deep recursion. */ + } + } case TK_SPAN: - case TK_COLLATE: case TK_UPLUS: { pExpr = pExpr->pLeft; goto expr_code_doover; /* 2018-04-28: Prevent deep recursion. OSSFuzz. */ @@ -106392,7 +108496,9 @@ SQLITE_PRIVATE int sqlite3ExprCodeRunJustOnce( struct ExprList_item *pItem; int i; for(pItem=p->a, i=p->nExpr; i>0; pItem++, i--){ - if( pItem->reusable && sqlite3ExprCompare(0,pItem->pExpr,pExpr,-1)==0 ){ + if( pItem->fg.reusable + && sqlite3ExprCompare(0,pItem->pExpr,pExpr,-1)==0 + ){ return pItem->u.iConstExprReg; } } @@ -106415,7 +108521,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeRunJustOnce( p = sqlite3ExprListAppend(pParse, p, pExpr); if( p ){ struct ExprList_item *pItem = &p->a[p->nExpr-1]; - pItem->reusable = regDest<0; + pItem->fg.reusable = regDest<0; if( regDest<0 ) regDest = ++pParse->nMem; pItem->u.iConstExprReg = regDest; } @@ -106549,7 +108655,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeExprList( for(pItem=pList->a, i=0; ipExpr; #ifdef SQLITE_ENABLE_SORTER_REFERENCES - if( pItem->bSorterRef ){ + if( pItem->fg.bSorterRef ){ i--; n--; }else @@ -106643,8 +108749,8 @@ static void exprCodeBetween( ** so that the sqlite3ExprCodeTarget() routine will not attempt to move ** it into the Parse.pConstExpr list. We should use a new bit for this, ** for clarity, but we are out of bits in the Expr.flags field so we - ** have to reuse the EP_FromJoin bit. Bummer. */ - pDel->flags |= EP_FromJoin; + ** have to reuse the EP_OuterON bit. Bummer. */ + pDel->flags |= EP_OuterON; sqlite3ExprCodeTarget(pParse, &exprAnd, dest); } sqlite3ReleaseTempReg(pParse, regFree1); @@ -107174,7 +109280,7 @@ SQLITE_PRIVATE int sqlite3ExprListCompare(const ExprList *pA, const ExprList *pB int res; Expr *pExprA = pA->a[i].pExpr; Expr *pExprB = pB->a[i].pExpr; - if( pA->a[i].sortFlags!=pB->a[i].sortFlags ) return 1; + if( pA->a[i].fg.sortFlags!=pB->a[i].fg.sortFlags ) return 1; if( (res = sqlite3ExprCompare(0, pExprA, pExprB, iTab)) ) return res; } return 0; @@ -107329,7 +109435,7 @@ SQLITE_PRIVATE int sqlite3ExprImpliesExpr( static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ testcase( pExpr->op==TK_AGG_COLUMN ); testcase( pExpr->op==TK_AGG_FUNCTION ); - if( ExprHasProperty(pExpr, EP_FromJoin) ) return WRC_Prune; + if( ExprHasProperty(pExpr, EP_OuterON) ) return WRC_Prune; switch( pExpr->op ){ case TK_ISNOT: case TK_ISNULL: @@ -107426,8 +109532,8 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ ** False positives are not allowed, however. A false positive may result ** in an incorrect answer. ** -** Terms of p that are marked with EP_FromJoin (and hence that come from -** the ON or USING clauses of LEFT JOINS) are excluded from the analysis. +** Terms of p that are marked with EP_OuterON (and hence that come from +** the ON or USING clauses of OUTER JOINS) are excluded from the analysis. ** ** This routine is used to check if a LEFT JOIN can be converted into ** an ordinary JOIN. The p argument is the WHERE clause. If the WHERE @@ -108307,7 +110413,9 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ int r1; /* Temporary registers */ db = pParse->db; - if( pParse->nErr || db->mallocFailed ) return; + assert( db->pParse==pParse ); + if( pParse->nErr ) return; + assert( db->mallocFailed==0 ); pNew = pParse->pNewTable; assert( pNew ); @@ -108433,7 +110541,7 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ " THEN raise(ABORT,'CHECK constraint failed')" " ELSE raise(ABORT,'NOT NULL constraint failed')" " END" - " FROM pragma_quick_check(\"%w\",\"%w\")" + " FROM pragma_quick_check(%Q,%Q)" " WHERE quick_check GLOB 'CHECK*' OR quick_check GLOB 'NULL*'", zTab, zDb ); @@ -108612,7 +110720,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameColumn( if( 0==sqlite3StrICmp(pTab->aCol[iCol].zCnName, zOld) ) break; } if( iCol==pTab->nCol ){ - sqlite3ErrorMsg(pParse, "no such column: \"%s\"", zOld); + sqlite3ErrorMsg(pParse, "no such column: \"%T\"", pOld); goto exit_rename_column; } @@ -108718,7 +110826,9 @@ struct RenameCtx { ** following a valid object, it may not be used in comparison operations. */ static void renameTokenCheckAll(Parse *pParse, const void *pPtr){ - if( pParse->nErr==0 && pParse->db->mallocFailed==0 ){ + assert( pParse==pParse->db->pParse ); + assert( pParse->db->mallocFailed==0 || pParse->nErr!=0 ); + if( pParse->nErr==0 ){ const RenameToken *p; u8 i = 0; for(p=pParse->pRename; p; p=p->pNext){ @@ -108837,11 +110947,10 @@ static void unmapColumnIdlistNames( Parse *pParse, const IdList *pIdList ){ - if( pIdList ){ - int ii; - for(ii=0; iinId; ii++){ - sqlite3RenameTokenRemap(pParse, 0, (const void*)pIdList->a[ii].zName); - } + int ii; + assert( pIdList!=0 ); + for(ii=0; iinId; ii++){ + sqlite3RenameTokenRemap(pParse, 0, (const void*)pIdList->a[ii].zName); } } @@ -108860,7 +110969,7 @@ static int renameUnmapSelectCb(Walker *pWalker, Select *p){ if( ALWAYS(p->pEList) ){ ExprList *pList = p->pEList; for(i=0; inExpr; i++){ - if( pList->a[i].zEName && pList->a[i].eEName==ENAME_NAME ){ + if( pList->a[i].zEName && pList->a[i].fg.eEName==ENAME_NAME ){ sqlite3RenameTokenRemap(pParse, 0, (void*)pList->a[i].zEName); } } @@ -108869,8 +110978,11 @@ static int renameUnmapSelectCb(Walker *pWalker, Select *p){ SrcList *pSrc = p->pSrc; for(i=0; inSrc; i++){ sqlite3RenameTokenRemap(pParse, 0, (void*)pSrc->a[i].zName); - sqlite3WalkExpr(pWalker, pSrc->a[i].pOn); - unmapColumnIdlistNames(pParse, pSrc->a[i].pUsing); + if( pSrc->a[i].fg.isUsing==0 ){ + sqlite3WalkExpr(pWalker, pSrc->a[i].u3.pOn); + }else{ + unmapColumnIdlistNames(pParse, pSrc->a[i].u3.pUsing); + } } } @@ -108906,7 +111018,7 @@ SQLITE_PRIVATE void sqlite3RenameExprlistUnmap(Parse *pParse, ExprList *pEList){ sWalker.xExprCallback = renameUnmapExprCb; sqlite3WalkExprList(&sWalker, pEList); for(i=0; inExpr; i++){ - if( ALWAYS(pEList->a[i].eEName==ENAME_NAME) ){ + if( ALWAYS(pEList->a[i].fg.eEName==ENAME_NAME) ){ sqlite3RenameTokenRemap(pParse, 0, (void*)pEList->a[i].zEName); } } @@ -109040,12 +111152,12 @@ static void renameColumnParseError( const char *zN = (const char*)sqlite3_value_text(pObject); char *zErr; - zErr = sqlite3_mprintf("error in %s %s%s%s: %s", + zErr = sqlite3MPrintf(pParse->db, "error in %s %s%s%s: %s", zT, zN, (zWhen[0] ? " " : ""), zWhen, pParse->zErrMsg ); sqlite3_result_error(pCtx, zErr, -1); - sqlite3_free(zErr); + sqlite3DbFree(pParse->db, zErr); } /* @@ -109064,7 +111176,7 @@ static void renameColumnElistNames( int i; for(i=0; inExpr; i++){ const char *zName = pEList->a[i].zEName; - if( ALWAYS(pEList->a[i].eEName==ENAME_NAME) + if( ALWAYS(pEList->a[i].fg.eEName==ENAME_NAME) && ALWAYS(zName!=0) && 0==sqlite3_stricmp(zName, zOld) ){ @@ -109109,24 +111221,22 @@ static int renameParseSql( int bTemp /* True if SQL is from temp schema */ ){ int rc; - char *zErr = 0; + sqlite3ParseObjectInit(p, db); + if( zSql==0 ){ + return SQLITE_NOMEM; + } + if( sqlite3StrNICmp(zSql,"CREATE ",7)!=0 ){ + return SQLITE_CORRUPT_BKPT; + } db->init.iDb = bTemp ? 1 : sqlite3FindDbName(db, zDb); - - /* Parse the SQL statement passed as the first argument. If no error - ** occurs and the parse does not result in a new table, index or - ** trigger object, the database must be corrupt. */ - memset(p, 0, sizeof(Parse)); p->eParseMode = PARSE_MODE_RENAME; p->db = db; p->nQueryLoop = 1; - rc = zSql ? sqlite3RunParser(p, zSql, &zErr) : SQLITE_NOMEM; - assert( p->zErrMsg==0 ); - assert( rc!=SQLITE_OK || zErr==0 ); - p->zErrMsg = zErr; + rc = sqlite3RunParser(p, zSql); if( db->mallocFailed ) rc = SQLITE_NOMEM; if( rc==SQLITE_OK - && p->pNewTable==0 && p->pNewIndex==0 && p->pNewTrigger==0 + && NEVER(p->pNewTable==0 && p->pNewIndex==0 && p->pNewTrigger==0) ){ rc = SQLITE_CORRUPT_BKPT; } @@ -109296,27 +111406,33 @@ static int renameResolveTrigger(Parse *pParse){ if( rc==SQLITE_OK && pStep->zTarget ){ SrcList *pSrc = sqlite3TriggerStepSrc(pParse, pStep); if( pSrc ){ - int i; - for(i=0; inSrc && rc==SQLITE_OK; i++){ - SrcItem *p = &pSrc->a[i]; - p->iCursor = pParse->nTab++; - if( p->pSelect ){ - sqlite3SelectPrep(pParse, p->pSelect, 0); - sqlite3ExpandSubquery(pParse, p); - assert( i>0 ); - assert( pStep->pFrom->a[i-1].pSelect ); - sqlite3SelectPrep(pParse, pStep->pFrom->a[i-1].pSelect, 0); - }else{ - p->pTab = sqlite3LocateTableItem(pParse, 0, p); - if( p->pTab==0 ){ - rc = SQLITE_ERROR; - }else{ - p->pTab->nTabRef++; - rc = sqlite3ViewGetColumnNames(pParse, p->pTab); + Select *pSel = sqlite3SelectNew( + pParse, pStep->pExprList, pSrc, 0, 0, 0, 0, 0, 0 + ); + if( pSel==0 ){ + pStep->pExprList = 0; + pSrc = 0; + rc = SQLITE_NOMEM; + }else{ + sqlite3SelectPrep(pParse, pSel, 0); + rc = pParse->nErr ? SQLITE_ERROR : SQLITE_OK; + assert( pStep->pExprList==0 || pStep->pExprList==pSel->pEList ); + assert( pSrc==pSel->pSrc ); + if( pStep->pExprList ) pSel->pEList = 0; + pSel->pSrc = 0; + sqlite3SelectDelete(db, pSel); + } + if( pStep->pFrom ){ + int i; + for(i=0; ipFrom->nSrc && rc==SQLITE_OK; i++){ + SrcItem *p = &pStep->pFrom->a[i]; + if( p->pSelect ){ + sqlite3SelectPrep(pParse, p->pSelect, 0); } } } - if( rc==SQLITE_OK && db->mallocFailed ){ + + if( db->mallocFailed ){ rc = SQLITE_NOMEM; } sNC.pSrcList = pSrc; @@ -109404,13 +111520,13 @@ static void renameParseCleanup(Parse *pParse){ sqlite3DeleteTrigger(db, pParse->pNewTrigger); sqlite3DbFree(db, pParse->zErrMsg); renameTokenFree(db, pParse->pRename); - sqlite3ParserReset(pParse); + sqlite3ParseObjectReset(pParse); } /* ** SQL function: ** -** sqlite_rename_column(zSql, iCol, bQuote, zNew, zTable, zOld) +** sqlite_rename_column(SQL,TYPE,OBJ,DB,TABLE,COL,NEWNAME,QUOTE,TEMP) ** ** 0. zSql: SQL statement to rewrite ** 1. type: Type of object ("table", "view" etc.) @@ -109428,7 +111544,8 @@ static void renameParseCleanup(Parse *pParse){ ** ** This function is used internally by the ALTER TABLE RENAME COLUMN command. ** It is only accessible to SQL created using sqlite3NestedParse(). It is -** not reachable from ordinary SQL passed into sqlite3_prepare(). +** not reachable from ordinary SQL passed into sqlite3_prepare() unless the +** SQLITE_TESTCTRL_INTERNAL_FUNCTIONS test setting is enabled. */ static void renameColumnFunc( sqlite3_context *context, @@ -109577,7 +111694,9 @@ static void renameColumnFunc( renameColumnFunc_done: if( rc!=SQLITE_OK ){ - if( sParse.zErrMsg ){ + if( rc==SQLITE_ERROR && sqlite3WritableSchema(db) ){ + sqlite3_result_value(context, argv[0]); + }else if( sParse.zErrMsg ){ renameColumnParseError(context, "", argv[1], argv[2], &sParse); }else{ sqlite3_result_error_code(context, rc); @@ -109765,6 +111884,15 @@ static void renameTableFunc( if( pStep->zTarget && 0==sqlite3_stricmp(pStep->zTarget, zOld) ){ renameTokenFind(&sParse, &sCtx, pStep->zTarget); } + if( pStep->pFrom ){ + int i; + for(i=0; ipFrom->nSrc; i++){ + SrcItem *pItem = &pStep->pFrom->a[i]; + if( 0==sqlite3_stricmp(pItem->zName, zOld) ){ + renameTokenFind(&sParse, &sCtx, pItem->zName); + } + } + } } } } @@ -109776,7 +111904,9 @@ static void renameTableFunc( rc = renameEditSql(context, &sCtx, zInput, zNew, bQuote); } if( rc!=SQLITE_OK ){ - if( sParse.zErrMsg ){ + if( rc==SQLITE_ERROR && sqlite3WritableSchema(db) ){ + sqlite3_result_value(context, argv[3]); + }else if( sParse.zErrMsg ){ renameColumnParseError(context, "", argv[1], argv[2], &sParse); }else{ sqlite3_result_error_code(context, rc); @@ -109801,10 +111931,10 @@ static int renameQuotefixExprCb(Walker *pWalker, Expr *pExpr){ return WRC_Continue; } -/* -** The implementation of an SQL scalar function that rewrites DDL statements -** so that any string literals that use double-quotes are modified so that -** they use single quotes. +/* SQL function: sqlite_rename_quotefix(DB,SQL) +** +** Rewrite the DDL statement "SQL" so that any string literals that use +** double-quotes use single quotes instead. ** ** Two arguments must be passed: ** @@ -109823,6 +111953,10 @@ static int renameQuotefixExprCb(Walker *pWalker, Expr *pExpr){ ** returns the string: ** ** CREATE VIEW v1 AS SELECT "a", 'string' FROM t1 +** +** If there is a error in the input SQL, then raise an error, except +** if PRAGMA writable_schema=ON, then just return the input string +** unmodified following an error. */ static void renameQuotefixFunc( sqlite3_context *context, @@ -109897,7 +112031,11 @@ static void renameQuotefixFunc( renameTokenFree(db, sCtx.pList); } if( rc!=SQLITE_OK ){ - sqlite3_result_error_code(context, rc); + if( sqlite3WritableSchema(db) && rc==SQLITE_ERROR ){ + sqlite3_result_value(context, argv[1]); + }else{ + sqlite3_result_error_code(context, rc); + } } renameParseCleanup(&sParse); } @@ -109909,7 +112047,8 @@ static void renameQuotefixFunc( sqlite3BtreeLeaveAll(db); } -/* +/* Function: sqlite_rename_test(DB,SQL,TYPE,NAME,ISTEMP,WHEN,DQS) +** ** An SQL user function that checks that there are no parse or symbol ** resolution problems in a CREATE TRIGGER|TABLE|VIEW|INDEX statement. ** After an ALTER TABLE .. RENAME operation is performed and the schema @@ -109924,11 +112063,13 @@ static void renameQuotefixFunc( ** 5: "when" part of error message. ** 6: True to disable the DQS quirk when parsing SQL. ** -** Unless it finds an error, this function normally returns NULL. However, it -** returns integer value 1 if: +** The return value is computed as follows: ** -** * the SQL argument creates a trigger, and -** * the table that the trigger is attached to is in database zDb. +** A. If an error is seen and not in PRAGMA writable_schema=ON mode, +** then raise the error. +** B. Else if a trigger is created and the the table that the trigger is +** attached to is in database zDb, then return 1. +** C. Otherwise return NULL. */ static void renameTableTest( sqlite3_context *context, @@ -109973,12 +112114,16 @@ static void renameTableTest( if( rc==SQLITE_OK ){ int i1 = sqlite3SchemaToIndex(db, sParse.pNewTrigger->pTabSchema); int i2 = sqlite3FindDbName(db, zDb); - if( i1==i2 ) sqlite3_result_int(context, 1); + if( i1==i2 ){ + /* Handle output case B */ + sqlite3_result_int(context, 1); + } } } } - if( rc!=SQLITE_OK && zWhen ){ + if( rc!=SQLITE_OK && zWhen && !sqlite3WritableSchema(db) ){ + /* Output case A */ renameColumnParseError(context, zWhen, argv[2], argv[3],&sParse); } renameParseCleanup(&sParse); @@ -110094,7 +112239,7 @@ SQLITE_PRIVATE void sqlite3AlterDropColumn(Parse *pParse, SrcList *pSrc, const T } iCol = sqlite3ColumnIndex(pTab, zCol); if( iCol<0 ){ - sqlite3ErrorMsg(pParse, "no such column: \"%s\"", zCol); + sqlite3ErrorMsg(pParse, "no such column: \"%T\"", pName); goto exit_drop_column; } @@ -110118,6 +112263,12 @@ SQLITE_PRIVATE void sqlite3AlterDropColumn(Parse *pParse, SrcList *pSrc, const T iDb = sqlite3SchemaToIndex(db, pTab->pSchema); assert( iDb>=0 ); zDb = db->aDb[iDb].zDbSName; +#ifndef SQLITE_OMIT_AUTHORIZATION + /* Invoke the authorization callback. */ + if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, zCol) ){ + goto exit_drop_column; + } +#endif renameTestSchema(pParse, zDb, iDb==1, "", 0); renameFixQuotes(pParse, zDb, iDb==1); sqlite3NestedParse(pParse, @@ -111065,9 +113216,14 @@ static void statGet( ** * "WHERE a=? AND b=?" matches 2 rows. ** ** If D is the count of distinct values and K is the total number of - ** rows, then each estimate is computed as: + ** rows, then each estimate is usually computed as: ** ** I = (K+D-1)/D + ** + ** In other words, I is K/D rounded up to the next whole integer. + ** However, if I is between 1.0 and 1.1 (in other words if I is + ** close to 1.0 but just a little larger) then do not round up but + ** instead keep the I value at 1.0. */ sqlite3_str sStat; /* Text of the constructed "stat" line */ int i; /* Loop counter */ @@ -111078,6 +113234,7 @@ static void statGet( for(i=0; inKeyCol; i++){ u64 nDistinct = p->current.anDLt[i] + 1; u64 iVal = (p->nRow + nDistinct - 1) / nDistinct; + if( iVal==2 && p->nRow*10 <= nDistinct*11 ) iVal = 1; sqlite3_str_appendf(&sStat, " %llu", iVal); assert( p->current.anEq[i] ); } @@ -111241,7 +113398,7 @@ static void analyzeOneTable( memcpy(pStat1->zName, "sqlite_stat1", 13); pStat1->nCol = 3; pStat1->iPKey = -1; - sqlite3VdbeAddOp4(pParse->pVdbe, OP_Noop, 0, 0, 0,(char*)pStat1,P4_DYNBLOB); + sqlite3VdbeAddOp4(pParse->pVdbe, OP_Noop, 0, 0, 0,(char*)pStat1,P4_DYNAMIC); } #endif @@ -112505,7 +114662,7 @@ static void codeAttach( } #ifndef SQLITE_OMIT_AUTHORIZATION - if( pAuthArg ){ + if( ALWAYS(pAuthArg) ){ char *zAuthArg; if( pAuthArg->op==TK_STRING ){ assert( !ExprHasProperty(pAuthArg, EP_IntValue) ); @@ -112631,7 +114788,11 @@ static int fixSelectCb(Walker *p, Select *pSelect){ pItem->fg.fromDDL = 1; } #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) - if( sqlite3WalkExpr(&pFix->w, pList->a[i].pOn) ) return WRC_Abort; + if( pList->a[i].fg.isUsing==0 + && sqlite3WalkExpr(&pFix->w, pList->a[i].u3.pOn) + ){ + return WRC_Abort; + } #endif } if( pSelect->pWith ){ @@ -113166,11 +115327,13 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ assert( pParse->pToplevel==0 ); db = pParse->db; + assert( db->pParse==pParse ); if( pParse->nested ) return; - if( db->mallocFailed || pParse->nErr ){ - if( pParse->rc==SQLITE_OK ) pParse->rc = SQLITE_ERROR; + if( pParse->nErr ){ + if( db->mallocFailed ) pParse->rc = SQLITE_NOMEM; return; } + assert( db->mallocFailed==0 ); /* Begin by generating some termination code at the end of the ** vdbe program @@ -113193,9 +115356,8 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ int i; int reg; - if( pReturning->nRetCol==0 ){ - assert( CORRUPT_DB ); - }else{ + if( pReturning->nRetCol ){ + sqlite3VdbeAddOp0(v, OP_FkCheck); addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, pReturning->iRetCur); VdbeCoverage(v); @@ -113234,7 +115396,9 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ int iDb, i; assert( sqlite3VdbeGetOp(v, 0)->opcode==OP_Init ); sqlite3VdbeJumpHere(v, 0); - for(iDb=0; iDbnDb; iDb++){ + assert( db->nDb>0 ); + iDb = 0; + do{ Schema *pSchema; if( DbMaskTest(pParse->cookieMask, iDb)==0 ) continue; sqlite3VdbeUsesBtree(v, iDb); @@ -113249,7 +115413,7 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1); VdbeComment((v, "usesStmtJournal=%d", pParse->mayAbort && pParse->isMultiWrite)); - } + }while( ++iDbnDb ); #ifndef SQLITE_OMIT_VIRTUALTABLE for(i=0; inVtabLock; i++){ char *vtab = (char *)sqlite3GetVTable(db, pParse->apVtabLock[i]); @@ -113288,9 +115452,7 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ if( pParse->bReturning ){ Returning *pRet = pParse->u1.pReturning; - if( pRet->nRetCol==0 ){ - assert( CORRUPT_DB ); - }else{ + if( pRet->nRetCol ){ sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRet->iRetCur, pRet->nRetCol); } } @@ -113302,7 +115464,9 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ /* Get the VDBE program ready for execution */ - if( v && pParse->nErr==0 && !db->mallocFailed ){ + assert( v!=0 || pParse->nErr ); + assert( db->mallocFailed==0 || pParse->nErr ); + if( pParse->nErr==0 ){ /* A minimum of one cursor is required if autoincrement is used * See ticket [a696379c1f08866] */ assert( pParse->pAinc==0 || pParse->nTab>0 ); @@ -113329,7 +115493,6 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){ SQLITE_PRIVATE void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){ va_list ap; char *zSql; - char *zErrMsg = 0; sqlite3 *db = pParse->db; u32 savedDbFlags = db->mDbFlags; char saveBuf[PARSE_TAIL_SZ]; @@ -113351,9 +115514,8 @@ SQLITE_PRIVATE void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){ memcpy(saveBuf, PARSE_TAIL(pParse), PARSE_TAIL_SZ); memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ); db->mDbFlags |= DBFLAG_PreferBuiltin; - sqlite3RunParser(pParse, zSql, &zErrMsg); + sqlite3RunParser(pParse, zSql); db->mDbFlags = savedDbFlags; - sqlite3DbFree(db, zErrMsg); sqlite3DbFree(db, zSql); memcpy(PARSE_TAIL(pParse), saveBuf, PARSE_TAIL_SZ); pParse->nested--; @@ -114313,7 +116475,8 @@ SQLITE_PRIVATE void sqlite3StartTable( pTable = sqlite3FindTable(db, zName, zDb); if( pTable ){ if( !noErr ){ - sqlite3ErrorMsg(pParse, "table %T already exists", pName); + sqlite3ErrorMsg(pParse, "%s %T already exists", + (IsView(pTable)? "view" : "table"), pName); }else{ assert( !db->init.busy || CORRUPT_DB ); sqlite3CodeVerifySchema(pParse, iDb); @@ -114909,7 +117072,7 @@ SQLITE_PRIVATE void sqlite3AddPrimaryKey( pTab->keyConf = (u8)onError; assert( autoInc==0 || autoInc==1 ); pTab->tabFlags |= autoInc*TF_Autoincrement; - if( pList ) pParse->iPkSortOrder = pList->a[0].sortFlags; + if( pList ) pParse->iPkSortOrder = pList->a[0].fg.sortFlags; (void)sqlite3HasExplicitNulls(pParse, pList); }else if( autoInc ){ #ifndef SQLITE_OMIT_AUTOINCREMENT @@ -115403,15 +117566,16 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ if( IN_RENAME_OBJECT ){ sqlite3RenameTokenRemap(pParse, pList->a[0].pExpr, &pTab->iPKey); } - pList->a[0].sortFlags = pParse->iPkSortOrder; + pList->a[0].fg.sortFlags = pParse->iPkSortOrder; assert( pParse->pNewTable==pTab ); pTab->iPKey = -1; sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0, SQLITE_IDXTYPE_PRIMARYKEY); - if( db->mallocFailed || pParse->nErr ){ + if( pParse->nErr ){ pTab->tabFlags &= ~TF_WithoutRowid; return; } + assert( db->mallocFailed==0 ); pPk = sqlite3PrimaryKeyIndex(pTab); assert( pPk->nKeyCol==1 ); }else{ @@ -115842,6 +118006,11 @@ SQLITE_PRIVATE void sqlite3EndTable( int addrInsLoop; /* Top of the loop for inserting rows */ Table *pSelTab; /* A table that describes the SELECT results */ + if( IN_SPECIAL_PARSE ){ + pParse->rc = SQLITE_ERROR; + pParse->nErr++; + return; + } regYield = ++pParse->nMem; regRec = ++pParse->nMem; regRowid = ++pParse->nMem; @@ -116068,7 +118237,6 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ Table *pSelTab; /* A fake table from which we get the result set */ Select *pSel; /* Copy of the SELECT that implements the view */ int nErr = 0; /* Number of errors encountered */ - int n; /* Temporarily holds the number of cursors assigned */ sqlite3 *db = pParse->db; /* Database connection for malloc errors */ #ifndef SQLITE_OMIT_VIRTUALTABLE int rc; @@ -116126,8 +118294,9 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ pSel = sqlite3SelectDup(db, pTable->u.view.pSelect, 0); if( pSel ){ u8 eParseMode = pParse->eParseMode; + int nTab = pParse->nTab; + int nSelect = pParse->nSelect; pParse->eParseMode = PARSE_MODE_NORMAL; - n = pParse->nTab; sqlite3SrcListAssignCursors(pParse, pSel->pSrc); pTable->nCol = -1; DisableLookaside; @@ -116139,7 +118308,8 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ #else pSelTab = sqlite3ResultSetOfSelect(pParse, pSel, SQLITE_AFF_NONE); #endif - pParse->nTab = n; + pParse->nTab = nTab; + pParse->nSelect = nSelect; if( pSelTab==0 ){ pTable->nCol = 0; nErr++; @@ -116152,10 +118322,10 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ */ sqlite3ColumnsFromExprList(pParse, pTable->pCheck, &pTable->nCol, &pTable->aCol); - if( db->mallocFailed==0 - && pParse->nErr==0 + if( pParse->nErr==0 && pTable->nCol==pSel->pEList->nExpr ){ + assert( db->mallocFailed==0 ); sqlite3SelectAddColumnTypeAndCollation(pParse, pTable, pSel, SQLITE_AFF_NONE); } @@ -116774,7 +118944,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ tnum = pIndex->tnum; } pKey = sqlite3KeyInfoOfIndex(pParse, pIndex); - assert( pKey!=0 || db->mallocFailed || pParse->nErr ); + assert( pKey!=0 || pParse->nErr ); /* Open the sorter cursor if we are to use one. */ iSorter = pParse->nTab++; @@ -116884,8 +119054,8 @@ SQLITE_PRIVATE int sqlite3HasExplicitNulls(Parse *pParse, ExprList *pList){ if( pList ){ int i; for(i=0; inExpr; i++){ - if( pList->a[i].bNulls ){ - u8 sf = pList->a[i].sortFlags; + if( pList->a[i].fg.bNulls ){ + u8 sf = pList->a[i].fg.sortFlags; sqlite3ErrorMsg(pParse, "unsupported use of NULLS %s", (sf==0 || sf==3) ? "FIRST" : "LAST" ); @@ -116938,9 +119108,11 @@ SQLITE_PRIVATE void sqlite3CreateIndex( char *zExtra = 0; /* Extra space after the Index object */ Index *pPk = 0; /* PRIMARY KEY index for WITHOUT ROWID tables */ - if( db->mallocFailed || pParse->nErr>0 ){ + assert( db->pParse==pParse ); + if( pParse->nErr ){ goto exit_create_index; } + assert( db->mallocFailed==0 ); if( IN_DECLARE_VTAB && idxType!=SQLITE_IDXTYPE_PRIMARYKEY ){ goto exit_create_index; } @@ -117004,7 +119176,6 @@ SQLITE_PRIVATE void sqlite3CreateIndex( pDb = &db->aDb[iDb]; assert( pTab!=0 ); - assert( pParse->nErr==0 ); if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 && db->init.busy==0 && pTblName!=0 @@ -117237,7 +119408,7 @@ SQLITE_PRIVATE void sqlite3CreateIndex( goto exit_create_index; } pIndex->azColl[i] = zColl; - requestedSortOrder = pListItem->sortFlags & sortOrderMask; + requestedSortOrder = pListItem->fg.sortFlags & sortOrderMask; pIndex->aSortOrder[i] = (u8)requestedSortOrder; } @@ -117428,13 +119599,13 @@ SQLITE_PRIVATE void sqlite3CreateIndex( /* Add an entry in sqlite_schema for this index */ sqlite3NestedParse(pParse, - "INSERT INTO %Q." LEGACY_SCHEMA_TABLE " VALUES('index',%Q,%Q,#%d,%Q);", - db->aDb[iDb].zDbSName, - pIndex->zName, - pTab->zName, - iMem, - zStmt - ); + "INSERT INTO %Q." LEGACY_SCHEMA_TABLE " VALUES('index',%Q,%Q,#%d,%Q);", + db->aDb[iDb].zDbSName, + pIndex->zName, + pTab->zName, + iMem, + zStmt + ); sqlite3DbFree(db, zStmt); /* Fill the index with data and reparse the schema. Code an OP_Expire @@ -117568,10 +119739,10 @@ SQLITE_PRIVATE void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists sqlite3 *db = pParse->db; int iDb; - assert( pParse->nErr==0 ); /* Never called with prior errors */ if( db->mallocFailed ){ goto exit_drop_index; } + assert( pParse->nErr==0 ); /* Never called with prior non-OOM errors */ assert( pName->nSrc==1 ); if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ goto exit_drop_index; @@ -117680,18 +119851,17 @@ SQLITE_PRIVATE IdList *sqlite3IdListAppend(Parse *pParse, IdList *pList, Token * if( pList==0 ){ pList = sqlite3DbMallocZero(db, sizeof(IdList) ); if( pList==0 ) return 0; + }else{ + IdList *pNew; + pNew = sqlite3DbRealloc(db, pList, + sizeof(IdList) + pList->nId*sizeof(pList->a)); + if( pNew==0 ){ + sqlite3IdListDelete(db, pList); + return 0; + } + pList = pNew; } - pList->a = sqlite3ArrayAllocate( - db, - pList->a, - sizeof(pList->a[0]), - &pList->nId, - &i - ); - if( i<0 ){ - sqlite3IdListDelete(db, pList); - return 0; - } + i = pList->nId++; pList->a[i].zName = sqlite3NameFromToken(db, pToken); if( IN_RENAME_OBJECT && pList->a[i].zName ){ sqlite3RenameTokenMap(pParse, (void*)pList->a[i].zName, pToken); @@ -117705,10 +119875,10 @@ SQLITE_PRIVATE IdList *sqlite3IdListAppend(Parse *pParse, IdList *pList, Token * SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3 *db, IdList *pList){ int i; if( pList==0 ) return; + assert( pList->eU4!=EU4_EXPR ); /* EU4_EXPR mode is not currently used */ for(i=0; inId; i++){ sqlite3DbFree(db, pList->a[i].zName); } - sqlite3DbFree(db, pList->a); sqlite3DbFreeNN(db, pList); } @@ -117718,7 +119888,7 @@ SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3 *db, IdList *pList){ */ SQLITE_PRIVATE int sqlite3IdListIndex(IdList *pList, const char *zName){ int i; - if( pList==0 ) return -1; + assert( pList!=0 ); for(i=0; inId; i++){ if( sqlite3StrICmp(pList->a[i].zName, zName)==0 ) return i; } @@ -117921,8 +120091,11 @@ SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){ if( pItem->fg.isTabFunc ) sqlite3ExprListDelete(db, pItem->u1.pFuncArg); sqlite3DeleteTable(db, pItem->pTab); if( pItem->pSelect ) sqlite3SelectDelete(db, pItem->pSelect); - if( pItem->pOn ) sqlite3ExprDelete(db, pItem->pOn); - if( pItem->pUsing ) sqlite3IdListDelete(db, pItem->pUsing); + if( pItem->fg.isUsing ){ + sqlite3IdListDelete(db, pItem->u3.pUsing); + }else if( pItem->u3.pOn ){ + sqlite3ExprDelete(db, pItem->u3.pOn); + } } sqlite3DbFreeNN(db, pList); } @@ -117950,14 +120123,13 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm( Token *pDatabase, /* Name of the database containing pTable */ Token *pAlias, /* The right-hand side of the AS subexpression */ Select *pSubquery, /* A subquery used in place of a table name */ - Expr *pOn, /* The ON clause of a join */ - IdList *pUsing /* The USING clause of a join */ + OnOrUsing *pOnUsing /* Either the ON clause or the USING clause */ ){ SrcItem *pItem; sqlite3 *db = pParse->db; - if( !p && (pOn || pUsing) ){ + if( !p && pOnUsing!=0 && (pOnUsing->pOn || pOnUsing->pUsing) ){ sqlite3ErrorMsg(pParse, "a JOIN clause is required before %s", - (pOn ? "ON" : "USING") + (pOnUsing->pOn ? "ON" : "USING") ); goto append_from_error; } @@ -117977,15 +120149,27 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm( if( pAlias->n ){ pItem->zAlias = sqlite3NameFromToken(db, pAlias); } - pItem->pSelect = pSubquery; - pItem->pOn = pOn; - pItem->pUsing = pUsing; + if( pSubquery ){ + pItem->pSelect = pSubquery; + if( pSubquery->selFlags & SF_NestedFrom ){ + pItem->fg.isNestedFrom = 1; + } + } + assert( pOnUsing==0 || pOnUsing->pOn==0 || pOnUsing->pUsing==0 ); + assert( pItem->fg.isUsing==0 ); + if( pOnUsing==0 ){ + pItem->u3.pOn = 0; + }else if( pOnUsing->pUsing ){ + pItem->fg.isUsing = 1; + pItem->u3.pUsing = pOnUsing->pUsing; + }else{ + pItem->u3.pOn = pOnUsing->pOn; + } return p; - append_from_error: +append_from_error: assert( p==0 ); - sqlite3ExprDelete(db, pOn); - sqlite3IdListDelete(db, pUsing); + sqlite3ClearOnOrUsing(db, pOnUsing); sqlite3SelectDelete(db, pSubquery); return 0; } @@ -118030,6 +120214,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppendList(Parse *pParse, SrcList *p1, Src p1 = pNew; memcpy(&p1->a[1], p2->a, p2->nSrc*sizeof(SrcItem)); sqlite3DbFree(pParse->db, p2); + p1->a[0].fg.jointype |= (JT_LTORJ & p1->a[1].fg.jointype); } } return p1; @@ -118066,14 +120251,34 @@ SQLITE_PRIVATE void sqlite3SrcListFuncArgs(Parse *pParse, SrcList *p, ExprList * ** The operator is "natural cross join". The A and B operands are stored ** in p->a[0] and p->a[1], respectively. The parser initially stores the ** operator with A. This routine shifts that operator over to B. +** +** Additional changes: +** +** * All tables to the left of the right-most RIGHT JOIN are tagged with +** JT_LTORJ (mnemonic: Left Table Of Right Join) so that the +** code generator can easily tell that the table is part of +** the left operand of at least one RIGHT JOIN. */ -SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(SrcList *p){ - if( p ){ - int i; - for(i=p->nSrc-1; i>0; i--){ - p->a[i].fg.jointype = p->a[i-1].fg.jointype; - } +SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(Parse *pParse, SrcList *p){ + (void)pParse; + if( p && p->nSrc>1 ){ + int i = p->nSrc-1; + u8 allFlags = 0; + do{ + allFlags |= p->a[i].fg.jointype = p->a[i-1].fg.jointype; + }while( (--i)>0 ); p->a[0].fg.jointype = 0; + + /* All terms to the left of a RIGHT JOIN should be tagged with the + ** JT_LTORJ flags */ + if( allFlags & JT_RIGHT ){ + for(i=p->nSrc-1; ALWAYS(i>0) && (p->a[i].fg.jointype&JT_RIGHT)==0; i--){} + i--; + assert( i>=0 ); + do{ + p->a[i].fg.jointype |= JT_LTORJ; + }while( (--i)>=0 ); + } } } @@ -119012,7 +121217,6 @@ SQLITE_PRIVATE void sqlite3InsertBuiltinFuncs( const char *zName = aDef[i].zName; int nName = sqlite3Strlen30(zName); int h = SQLITE_FUNC_HASH(zName[0], nName); - assert( zName[0]>='a' && zName[0]<='z' ); assert( aDef[i].funcFlags & SQLITE_FUNC_BUILTIN ); pOther = sqlite3FunctionSearch(h, zName); if( pOther ){ @@ -119239,6 +121443,16 @@ SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){ return pTab; } +/* Generate byte-code that will report the number of rows modified +** by a DELETE, INSERT, or UPDATE statement. +*/ +SQLITE_PRIVATE void sqlite3CodeChangeCount(Vdbe *v, int regCounter, const char *zColName){ + sqlite3VdbeAddOp0(v, OP_FkCheck); + sqlite3VdbeAddOp2(v, OP_ResultRow, regCounter, 1); + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zColName, SQLITE_STATIC); +} + /* Return true if table pTab is read-only. ** ** A table is read-only if any of the following are true: @@ -119313,8 +121527,8 @@ SQLITE_PRIVATE void sqlite3MaterializeView( assert( pFrom->nSrc==1 ); pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName); pFrom->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName); - assert( pFrom->a[0].pOn==0 ); - assert( pFrom->a[0].pUsing==0 ); + assert( pFrom->a[0].fg.isUsing==0 ); + assert( pFrom->a[0].u3.pOn==0 ); } pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, pOrderBy, SF_IncludeHidden, pLimit); @@ -119478,12 +121692,13 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( memset(&sContext, 0, sizeof(sContext)); db = pParse->db; - if( pParse->nErr || db->mallocFailed ){ + assert( db->pParse==pParse ); + if( pParse->nErr ){ goto delete_from_cleanup; } + assert( db->mallocFailed==0 ); assert( pTabList->nSrc==1 ); - /* Locate the table which we want to delete. This table has to be ** put in an SrcList structure because some of the subroutines we ** will be calling are designed to work with multiple tables and expect @@ -119508,6 +121723,14 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( # define isView 0 #endif +#if TREETRACE_ENABLED + if( sqlite3TreeTrace & 0x10000 ){ + sqlite3TreeViewLine(0, "In sqlite3Delete() at %s:%d", __FILE__, __LINE__); + sqlite3TreeViewDelete(pParse->pWith, pTabList, pWhere, + pOrderBy, pLimit, pTrigger); + } +#endif + #ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT if( !isView ){ pWhere = sqlite3LimitWhere( @@ -119661,7 +121884,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( ** ONEPASS_SINGLE: One-pass approach - at most one row deleted. ** ONEPASS_MULTI: One-pass approach - any number of rows may be deleted. */ - pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, wcf, iTabCur+1); + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0,0,wcf,iTabCur+1); if( pWInfo==0 ) goto delete_from_cleanup; eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass); assert( IsVirtual(pTab)==0 || eOnePass!=ONEPASS_MULTI ); @@ -119814,9 +122037,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( ** invoke the callback function. */ if( memCnt ){ - sqlite3VdbeAddOp2(v, OP_ChngCntRow, memCnt, 1); - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", SQLITE_STATIC); + sqlite3CodeChangeCount(v, memCnt, "rows deleted"); } delete_from_cleanup: @@ -120267,6 +122488,18 @@ static void typeofFunc( sqlite3_result_text(context, azType[i], -1, SQLITE_STATIC); } +/* subtype(X) +** +** Return the subtype of X +*/ +static void subtypeFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + UNUSED_PARAMETER(argc); + sqlite3_result_int(context, sqlite3_value_subtype(argv[0])); +} /* ** Implementation of the length() function @@ -120428,7 +122661,7 @@ static void instrFunc( } /* -** Implementation of the printf() function. +** Implementation of the printf() (a.k.a. format()) SQL function. */ static void printfFunc( sqlite3_context *context, @@ -121197,39 +123430,42 @@ static const char hexdigits[] = { }; /* -** Implementation of the QUOTE() function. This function takes a single -** argument. If the argument is numeric, the return value is the same as -** the argument. If the argument is NULL, the return value is the string -** "NULL". Otherwise, the argument is enclosed in single quotes with -** single-quote escapes. +** Append to pStr text that is the SQL literal representation of the +** value contained in pValue. */ -static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ - assert( argc==1 ); - UNUSED_PARAMETER(argc); - switch( sqlite3_value_type(argv[0]) ){ +SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue){ + /* As currently implemented, the string must be initially empty. + ** we might relax this requirement in the future, but that will + ** require enhancements to the implementation. */ + assert( pStr!=0 && pStr->nChar==0 ); + + switch( sqlite3_value_type(pValue) ){ case SQLITE_FLOAT: { double r1, r2; - char zBuf[50]; - r1 = sqlite3_value_double(argv[0]); - sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.15g", r1); - sqlite3AtoF(zBuf, &r2, 20, SQLITE_UTF8); - if( r1!=r2 ){ - sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.20e", r1); + const char *zVal; + r1 = sqlite3_value_double(pValue); + sqlite3_str_appendf(pStr, "%!.15g", r1); + zVal = sqlite3_str_value(pStr); + if( zVal ){ + sqlite3AtoF(zVal, &r2, pStr->nChar, SQLITE_UTF8); + if( r1!=r2 ){ + sqlite3_str_reset(pStr); + sqlite3_str_appendf(pStr, "%!.20e", r1); + } } - sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); break; } case SQLITE_INTEGER: { - sqlite3_result_value(context, argv[0]); + sqlite3_str_appendf(pStr, "%lld", sqlite3_value_int64(pValue)); break; } case SQLITE_BLOB: { - char *zText = 0; - char const *zBlob = sqlite3_value_blob(argv[0]); - int nBlob = sqlite3_value_bytes(argv[0]); - assert( zBlob==sqlite3_value_blob(argv[0]) ); /* No encoding change */ - zText = (char *)contextMalloc(context, (2*(i64)nBlob)+4); - if( zText ){ + char const *zBlob = sqlite3_value_blob(pValue); + int nBlob = sqlite3_value_bytes(pValue); + assert( zBlob==sqlite3_value_blob(pValue) ); /* No encoding change */ + sqlite3StrAccumEnlarge(pStr, nBlob*2 + 4); + if( pStr->accError==0 ){ + char *zText = pStr->zText; int i; for(i=0; i>4)&0x0F]; @@ -121239,42 +123475,48 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ zText[(nBlob*2)+3] = '\0'; zText[0] = 'X'; zText[1] = '\''; - sqlite3_result_text(context, zText, -1, SQLITE_TRANSIENT); - sqlite3_free(zText); + pStr->nChar = nBlob*2 + 3; } break; } case SQLITE_TEXT: { - int i,j; - u64 n; - const unsigned char *zArg = sqlite3_value_text(argv[0]); - char *z; - - if( zArg==0 ) return; - for(i=0, n=0; zArg[i]; i++){ if( zArg[i]=='\'' ) n++; } - z = contextMalloc(context, ((i64)i)+((i64)n)+3); - if( z ){ - z[0] = '\''; - for(i=0, j=1; zArg[i]; i++){ - z[j++] = zArg[i]; - if( zArg[i]=='\'' ){ - z[j++] = '\''; - } - } - z[j++] = '\''; - z[j] = 0; - sqlite3_result_text(context, z, j, sqlite3_free); - } + const unsigned char *zArg = sqlite3_value_text(pValue); + sqlite3_str_appendf(pStr, "%Q", zArg); break; } default: { - assert( sqlite3_value_type(argv[0])==SQLITE_NULL ); - sqlite3_result_text(context, "NULL", 4, SQLITE_STATIC); + assert( sqlite3_value_type(pValue)==SQLITE_NULL ); + sqlite3_str_append(pStr, "NULL", 4); break; } } } +/* +** Implementation of the QUOTE() function. +** +** The quote(X) function returns the text of an SQL literal which is the +** value of its argument suitable for inclusion into an SQL statement. +** Strings are surrounded by single-quotes with escapes on interior quotes +** as needed. BLOBs are encoded as hexadecimal literals. Strings with +** embedded NUL characters cannot be represented as string literals in SQL +** and hence the returned string literal is truncated prior to the first NUL. +*/ +static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + sqlite3_str str; + sqlite3 *db = sqlite3_context_db_handle(context); + assert( argc==1 ); + UNUSED_PARAMETER(argc); + sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]); + sqlite3QuoteValue(&str,argv[0]); + sqlite3_result_text(context, sqlite3StrAccumFinish(&str), str.nChar, + SQLITE_DYNAMIC); + if( str.accError!=SQLITE_OK ){ + sqlite3_result_null(context); + sqlite3_result_error_code(context, str.accError); + } +} + /* ** The unicode() function. Return the integer unicode code-point value ** for the first character of the input string. @@ -122247,11 +124489,11 @@ static void logFunc( switch( SQLITE_PTR_TO_INT(sqlite3_user_data(context)) ){ case 1: /* Convert from natural logarithm to log base 10 */ - ans *= 1.0/M_LN10; + ans /= M_LN10; break; case 2: /* Convert from natural logarithm to log base 2 */ - ans *= 1.0/M_LN2; + ans /= M_LN2; break; default: break; @@ -122390,8 +124632,7 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){ INLINE_FUNC(likelihood, 2, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY), INLINE_FUNC(likely, 1, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY), #ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC - FUNCTION2(sqlite_offset, 1, 0, 0, noopFunc, SQLITE_FUNC_OFFSET| - SQLITE_FUNC_TYPEOF), + INLINE_FUNC(sqlite_offset, 1, INLINEFUNC_sqlite_offset, 0 ), #endif FUNCTION(ltrim, 1, 1, 0, trimFunc ), FUNCTION(ltrim, 2, 1, 0, trimFunc ), @@ -122408,9 +124649,11 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){ WAGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize, minMaxValue, 0, SQLITE_FUNC_MINMAX|SQLITE_FUNC_ANYORDER ), FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF), + FUNCTION2(subtype, 1, 0, 0, subtypeFunc, SQLITE_FUNC_TYPEOF), FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH), FUNCTION(instr, 2, 0, 0, instrFunc ), FUNCTION(printf, -1, 0, 0, printfFunc ), + FUNCTION(format, -1, 0, 0, printfFunc ), FUNCTION(unicode, 1, 0, 0, unicodeFunc ), FUNCTION(char, -1, 0, 0, charFunc ), FUNCTION(abs, 1, 0, 0, absFunc ), @@ -122509,6 +124752,7 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){ #endif sqlite3WindowFunctions(); sqlite3RegisterDateTimeFunctions(); + sqlite3RegisterJsonFunctions(); sqlite3InsertBuiltinFuncs(aBuiltinFunc, ArraySize(aBuiltinFunc)); #if 0 /* Enable to print out how the built-in functions are hashed */ @@ -122923,7 +125167,6 @@ static void fkLookupParent( }else{ int nCol = pFKey->nCol; int regTemp = sqlite3GetTempRange(pParse, nCol); - int regRec = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_OpenRead, iCur, pIdx->tnum, iDb); sqlite3VdbeSetP4KeyInfo(pParse, pIdx); @@ -122963,11 +125206,10 @@ static void fkLookupParent( sqlite3VdbeGoto(v, iOk); } - sqlite3VdbeAddOp4(v, OP_MakeRecord, regTemp, nCol, regRec, + sqlite3VdbeAddOp4(v, OP_Affinity, regTemp, nCol, 0, sqlite3IndexAffinityStr(pParse->db,pIdx), nCol); - sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0); VdbeCoverage(v); - - sqlite3ReleaseTempReg(pParse, regRec); + sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regTemp, nCol); + VdbeCoverage(v); sqlite3ReleaseTempRange(pParse, regTemp, nCol); } } @@ -123069,14 +125311,10 @@ static Expr *exprTableColumn( ** Operation | FK type | Action taken ** -------------------------------------------------------------------------- ** DELETE immediate Increment the "immediate constraint counter". -** Or, if the ON (UPDATE|DELETE) action is RESTRICT, -** throw a "FOREIGN KEY constraint failed" exception. ** ** INSERT immediate Decrement the "immediate constraint counter". ** ** DELETE deferred Increment the "deferred constraint counter". -** Or, if the ON (UPDATE|DELETE) action is RESTRICT, -** throw a "FOREIGN KEY constraint failed" exception. ** ** INSERT deferred Decrement the "deferred constraint counter". ** @@ -123184,7 +125422,7 @@ static void fkScanChildren( ** clause. For each row found, increment either the deferred or immediate ** foreign key constraint counter. */ if( pParse->nErr==0 ){ - pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0); + pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0, 0); sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); if( pWInfo ){ sqlite3WhereEnd(pWInfo); @@ -123235,6 +125473,25 @@ static void fkTriggerDelete(sqlite3 *dbMem, Trigger *p){ } } +/* +** Clear the apTrigger[] cache of CASCADE triggers for all foreign keys +** in a particular database. This needs to happen when the schema +** changes. +*/ +SQLITE_PRIVATE void sqlite3FkClearTriggerCache(sqlite3 *db, int iDb){ + HashElem *k; + Hash *pHash = &db->aDb[iDb].pSchema->tblHash; + for(k=sqliteHashFirst(pHash); k; k=sqliteHashNext(k)){ + Table *pTab = sqliteHashData(k); + FKey *pFKey; + if( !IsOrdinaryTable(pTab) ) continue; + for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){ + fkTriggerDelete(db, pFKey->apTrigger[0]); pFKey->apTrigger[0] = 0; + fkTriggerDelete(db, pFKey->apTrigger[1]); pFKey->apTrigger[1] = 0; + } + } +} + /* ** This function is called to generate code that runs when table pTab is ** being dropped from the database. The SrcList passed as the second argument @@ -123705,9 +125962,9 @@ SQLITE_PRIVATE int sqlite3FkRequired( ** ** It returns a pointer to a Trigger structure containing a trigger ** equivalent to the ON UPDATE or ON DELETE action specified by pFKey. -** If the action is "NO ACTION" or "RESTRICT", then a NULL pointer is -** returned (these actions require no special handling by the triggers -** sub-system, code for them is created by fkScanChildren()). +** If the action is "NO ACTION" then a NULL pointer is returned (these actions +** require no special handling by the triggers sub-system, code for them is +** created by fkScanChildren()). ** ** For example, if pFKey is the foreign key and pTab is table "p" in ** the following schema: @@ -123836,18 +126093,23 @@ static Trigger *fkActionTrigger( nFrom = sqlite3Strlen30(zFrom); if( action==OE_Restrict ){ + int iDb = sqlite3SchemaToIndex(db, pTab->pSchema); Token tFrom; + Token tDb; Expr *pRaise; tFrom.z = zFrom; tFrom.n = nFrom; + tDb.z = db->aDb[iDb].zDbSName; + tDb.n = sqlite3Strlen30(tDb.z); + pRaise = sqlite3Expr(db, TK_RAISE, "FOREIGN KEY constraint failed"); if( pRaise ){ pRaise->affExpr = OE_Abort; } pSelect = sqlite3SelectNew(pParse, sqlite3ExprListAppend(pParse, 0, pRaise), - sqlite3SrcListAppend(pParse, 0, &tFrom, 0), + sqlite3SrcListAppend(pParse, 0, &tDb, &tFrom), pWhere, 0, 0, 0, 0, 0 ); @@ -124035,7 +126297,7 @@ SQLITE_PRIVATE void sqlite3OpenTable( }else{ Index *pPk = sqlite3PrimaryKeyIndex(pTab); assert( pPk!=0 ); - assert( pPk->tnum==pTab->tnum ); + assert( pPk->tnum==pTab->tnum || CORRUPT_DB ); sqlite3VdbeAddOp3(v, opcode, iCur, pPk->tnum, iDb); sqlite3VdbeSetP4KeyInfo(pParse, pPk); VdbeComment((v, "%s", pTab->zName)); @@ -124173,7 +126435,7 @@ SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){ } for(i=j=0; inCol; i++){ - assert( pTab->aCol[i].affinity!=0 ); + assert( pTab->aCol[i].affinity!=0 || sqlite3VdbeParser(v)->nErr>0 ); if( (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ){ zColAff[j++] = pTab->aCol[i].affinity; } @@ -124707,9 +126969,11 @@ SQLITE_PRIVATE void sqlite3Insert( #endif db = pParse->db; - if( pParse->nErr || db->mallocFailed ){ + assert( db->pParse==pParse ); + if( pParse->nErr ){ goto insert_cleanup; } + assert( db->mallocFailed==0 ); dest.iSDParm = 0; /* Suppress a harmless compiler warning */ /* If the Select object is really just a simple VALUES() list with a @@ -124755,6 +127019,14 @@ SQLITE_PRIVATE void sqlite3Insert( #endif assert( (pTrigger && tmask) || (pTrigger==0 && tmask==0) ); +#if TREETRACE_ENABLED + if( sqlite3TreeTrace & 0x10000 ){ + sqlite3TreeViewLine(0, "In sqlite3Insert() at %s:%d", __FILE__, __LINE__); + sqlite3TreeViewInsert(pParse->pWith, pTabList, pColumn, pSelect, pList, + onError, pUpsert, pTrigger); + } +#endif + /* If pTab is really a view, make sure it has been initialized. ** ViewGetColumnNames() is a no-op if pTab is not a view. */ @@ -124785,7 +127057,11 @@ SQLITE_PRIVATE void sqlite3Insert( ** ** This is the 2nd template. */ - if( pColumn==0 && xferOptimization(pParse, pTab, pSelect, onError, iDb) ){ + if( pColumn==0 + && pSelect!=0 + && pTrigger==0 + && xferOptimization(pParse, pTab, pSelect, onError, iDb) + ){ assert( !pTrigger ); assert( pList==0 ); goto insert_end; @@ -124829,13 +127105,15 @@ SQLITE_PRIVATE void sqlite3Insert( */ bIdListInOrder = (pTab->tabFlags & (TF_OOOHidden|TF_HasStored))==0; if( pColumn ){ + assert( pColumn->eU4!=EU4_EXPR ); + pColumn->eU4 = EU4_IDX; for(i=0; inId; i++){ - pColumn->a[i].idx = -1; + pColumn->a[i].u4.idx = -1; } for(i=0; inId; i++){ for(j=0; jnCol; j++){ if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zCnName)==0 ){ - pColumn->a[i].idx = j; + pColumn->a[i].u4.idx = j; if( i!=j ) bIdListInOrder = 0; if( j==pTab->iPKey ){ ipkColumn = i; assert( !withoutRowid ); @@ -124885,7 +127163,9 @@ SQLITE_PRIVATE void sqlite3Insert( dest.nSdst = pTab->nCol; rc = sqlite3Select(pParse, pSelect, &dest); regFromSelect = dest.iSdst; - if( rc || db->mallocFailed || pParse->nErr ) goto insert_cleanup; + assert( db->pParse==pParse ); + if( rc || pParse->nErr ) goto insert_cleanup; + assert( db->mallocFailed==0 ); sqlite3VdbeEndCoroutine(v, regYield); sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */ assert( pSelect->pEList ); @@ -125135,7 +127415,8 @@ SQLITE_PRIVATE void sqlite3Insert( } } if( pColumn ){ - for(j=0; jnId && pColumn->a[j].idx!=i; j++){} + assert( pColumn->eU4==EU4_IDX ); + for(j=0; jnId && pColumn->a[j].u4.idx!=i; j++){} if( j>=pColumn->nId ){ /* A column not named in the insert column list gets its ** default value */ @@ -125374,9 +127655,7 @@ SQLITE_PRIVATE void sqlite3Insert( ** invoke the callback function. */ if( regRowCount ){ - sqlite3VdbeAddOp2(v, OP_ChngCntRow, regRowCount, 1); - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", SQLITE_STATIC); + sqlite3CodeChangeCount(v, regRowCount, "rows inserted"); } insert_cleanup: @@ -126001,6 +128280,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( if( onError==OE_Replace /* IPK rule is REPLACE */ && onError!=overrideError /* Rules for other constraints are different */ && pTab->pIndex /* There exist other constraints */ + && !upsertIpkDelay /* IPK check already deferred by UPSERT */ ){ ipkTop = sqlite3VdbeAddOp0(v, OP_Goto)+1; VdbeComment((v, "defer IPK REPLACE until last")); @@ -126267,7 +128547,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( if( isUpdate ){ /* If currently processing the PRIMARY KEY of a WITHOUT ROWID ** table, only conflict if the new PRIMARY KEY values are actually - ** different from the old. + ** different from the old. See TH3 withoutrowid04.test. ** ** For a UNIQUE index, only conflict if the PRIMARY KEY values ** of the matched index row are different from the original PRIMARY @@ -126409,6 +128689,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( if( ipkTop ){ sqlite3VdbeGoto(v, ipkTop); VdbeComment((v, "Do IPK REPLACE")); + assert( ipkBottom>0 ); sqlite3VdbeJumpHere(v, ipkBottom); } @@ -126539,7 +128820,6 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion( } pik_flags = (useSeekResult ? OPFLAG_USESEEKRESULT : 0); if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){ - assert( pParse->nested==0 ); pik_flags |= OPFLAG_NCHANGE; pik_flags |= (update_flags & OPFLAG_SAVEPOSITION); if( update_flags==0 ){ @@ -126755,18 +129035,13 @@ static int xferOptimization( int destHasUniqueIdx = 0; /* True if pDest has a UNIQUE index */ int regData, regRowid; /* Registers holding data and rowid */ - if( pSelect==0 ){ - return 0; /* Must be of the form INSERT INTO ... SELECT ... */ - } + assert( pSelect!=0 ); if( pParse->pWith || pSelect->pWith ){ /* Do not attempt to process this query if there are an WITH clauses ** attached to it. Proceeding may generate a false "no such table: xxx" ** error if pSelect reads from a CTE named "xxx". */ return 0; } - if( sqlite3TriggerList(pParse, pDest) ){ - return 0; /* tab1 must not have triggers */ - } #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pDest) ){ return 0; /* tab1 must not be a virtual table */ @@ -127629,6 +129904,19 @@ struct sqlite3_api_routines { int (*autovacuum_pages)(sqlite3*, unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int), void*, void(*)(void*)); + /* Version 3.38.0 and later */ + int (*error_offset)(sqlite3*); + int (*vtab_rhs_value)(sqlite3_index_info*,int,sqlite3_value**); + int (*vtab_distinct)(sqlite3_index_info*); + int (*vtab_in)(sqlite3_index_info*,int,int); + int (*vtab_in_first)(sqlite3_value*,sqlite3_value**); + int (*vtab_in_next)(sqlite3_value*,sqlite3_value**); + /* Version 3.39.0 and later */ + int (*deserialize)(sqlite3*,const char*,unsigned char*, + sqlite3_int64,sqlite3_int64,unsigned); + unsigned char *(*serialize)(sqlite3*,const char *,sqlite3_int64*, + unsigned int); + const char *(*db_name)(sqlite3*,int); }; /* @@ -127940,6 +130228,19 @@ typedef int (*sqlite3_loadext_entry)( #define sqlite3_total_changes64 sqlite3_api->total_changes64 /* Version 3.37.0 and later */ #define sqlite3_autovacuum_pages sqlite3_api->autovacuum_pages +/* Version 3.38.0 and later */ +#define sqlite3_error_offset sqlite3_api->error_offset +#define sqlite3_vtab_rhs_value sqlite3_api->vtab_rhs_value +#define sqlite3_vtab_distinct sqlite3_api->vtab_distinct +#define sqlite3_vtab_in sqlite3_api->vtab_in +#define sqlite3_vtab_in_first sqlite3_api->vtab_in_first +#define sqlite3_vtab_in_next sqlite3_api->vtab_in_next +/* Version 3.39.0 and later */ +#ifndef SQLITE_OMIT_DESERIALIZE +#define sqlite3_deserialize sqlite3_api->deserialize +#define sqlite3_serialize sqlite3_api->serialize +#endif +#define sqlite3_db_name sqlite3_api->db_name #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) @@ -128429,6 +130730,30 @@ static const sqlite3_api_routines sqlite3Apis = { sqlite3_total_changes64, /* Version 3.37.0 and later */ sqlite3_autovacuum_pages, + /* Version 3.38.0 and later */ + sqlite3_error_offset, +#ifndef SQLITE_OMIT_VIRTUALTABLE + sqlite3_vtab_rhs_value, + sqlite3_vtab_distinct, + sqlite3_vtab_in, + sqlite3_vtab_in_first, + sqlite3_vtab_in_next, +#else + 0, + 0, + 0, + 0, + 0, +#endif + /* Version 3.39.0 and later */ +#ifndef SQLITE_OMIT_DESERIALIZE + sqlite3_deserialize, + sqlite3_serialize, +#else + 0, + 0, +#endif + sqlite3_db_name }; /* True if x is the directory separator character @@ -129099,7 +131424,7 @@ static const PragmaName aPragmaName[] = { #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) {/* zName: */ "database_list", /* ePragTyp: */ PragTyp_DATABASE_LIST, - /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0, + /* ePragFlg: */ PragFlg_Result0, /* ColNames: */ 47, 3, /* iArg: */ 0 }, #endif @@ -129787,15 +132112,16 @@ static void pragmaFunclistLine( int isBuiltin, /* True if this is a built-in function */ int showInternFuncs /* True if showing internal functions */ ){ + u32 mask = + SQLITE_DETERMINISTIC | + SQLITE_DIRECTONLY | + SQLITE_SUBTYPE | + SQLITE_INNOCUOUS | + SQLITE_FUNC_INTERNAL + ; + if( showInternFuncs ) mask = 0xffffffff; for(; p; p=p->pNext){ const char *zType; - static const u32 mask = - SQLITE_DETERMINISTIC | - SQLITE_DIRECTONLY | - SQLITE_SUBTYPE | - SQLITE_INNOCUOUS | - SQLITE_FUNC_INTERNAL - ; static const char *azEnc[] = { 0, "utf8", "utf16le", "utf16be" }; assert( SQLITE_FUNC_ENCMASK==0x3 ); @@ -130287,7 +132613,7 @@ SQLITE_PRIVATE void sqlite3Pragma( */ #ifndef SQLITE_OMIT_AUTOVACUUM case PragTyp_INCREMENTAL_VACUUM: { - int iLimit, addr; + int iLimit = 0, addr; if( zRight==0 || !sqlite3GetInt32(zRight, &iLimit) || iLimit<=0 ){ iLimit = 0x7fffffff; } @@ -130444,6 +132770,7 @@ SQLITE_PRIVATE void sqlite3Pragma( ** */ case PragTyp_TEMP_STORE_DIRECTORY: { + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); if( !zRight ){ returnSingleText(v, sqlite3_temp_directory); }else{ @@ -130453,6 +132780,7 @@ SQLITE_PRIVATE void sqlite3Pragma( rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res); if( rc!=SQLITE_OK || res==0 ){ sqlite3ErrorMsg(pParse, "not a writable directory"); + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); goto pragma_out; } } @@ -130470,6 +132798,7 @@ SQLITE_PRIVATE void sqlite3Pragma( } #endif /* SQLITE_OMIT_WSD */ } + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); break; } @@ -130488,6 +132817,7 @@ SQLITE_PRIVATE void sqlite3Pragma( ** */ case PragTyp_DATA_STORE_DIRECTORY: { + sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); if( !zRight ){ returnSingleText(v, sqlite3_data_directory); }else{ @@ -130497,6 +132827,7 @@ SQLITE_PRIVATE void sqlite3Pragma( rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res); if( rc!=SQLITE_OK || res==0 ){ sqlite3ErrorMsg(pParse, "not a writable directory"); + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); goto pragma_out; } } @@ -130508,6 +132839,7 @@ SQLITE_PRIVATE void sqlite3Pragma( } #endif /* SQLITE_OMIT_WSD */ } + sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); break; } #endif @@ -130730,6 +133062,10 @@ SQLITE_PRIVATE void sqlite3Pragma( (void)sqlite3_finalize(pDummy); sqlite3DbFree(db, zSql); } + if( db->mallocFailed ){ + sqlite3ErrorMsg(db->pParse, "out of memory"); + db->pParse->rc = SQLITE_NOMEM_BKPT; + } pHash = &db->aDb[ii].pSchema->tblHash; break; } @@ -130971,7 +133307,6 @@ SQLITE_PRIVATE void sqlite3Pragma( HashElem *k; /* Loop counter: Next table in schema */ int x; /* result variable */ int regResult; /* 3 registers to hold a result row */ - int regKey; /* Register to hold key for checking the FK */ int regRow; /* Registers to hold a row from pTab */ int addrTop; /* Top of a loop checking foreign keys */ int addrOk; /* Jump here if the key is OK */ @@ -130979,7 +133314,6 @@ SQLITE_PRIVATE void sqlite3Pragma( regResult = pParse->nMem+1; pParse->nMem += 4; - regKey = ++pParse->nMem; regRow = ++pParse->nMem; k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash); while( k ){ @@ -131046,9 +133380,9 @@ SQLITE_PRIVATE void sqlite3Pragma( /* Generate code to query the parent index for a matching parent ** key. If a match is found, jump to addrOk. */ if( pIdx ){ - sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, pFK->nCol, regKey, + sqlite3VdbeAddOp4(v, OP_Affinity, regRow, pFK->nCol, 0, sqlite3IndexAffinityStr(db,pIdx), pFK->nCol); - sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0); + sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regRow, pFK->nCol); VdbeCoverage(v); }else if( pParent ){ int jmp = sqlite3VdbeCurrentAddr(v)+2; @@ -132587,7 +134921,7 @@ SQLITE_PRIVATE int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFl sqlite3ResetAllSchemasOfConnection(db); pDb = &db->aDb[iDb]; }else - if( rc==SQLITE_OK || (db->flags&SQLITE_NoSchemaError)){ + if( rc==SQLITE_OK || ((db->flags&SQLITE_NoSchemaError) && rc!=SQLITE_NOMEM)){ /* Hack: If the SQLITE_NoSchemaError flag is set, then consider ** the schema loaded, even if errors (other than OOM) occurred. In ** this situation the current sqlite3_prepare() operation will fail, @@ -132766,8 +135100,14 @@ SQLITE_PRIVATE int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){ /* ** Free all memory allocations in the pParse object */ -SQLITE_PRIVATE void sqlite3ParserReset(Parse *pParse){ +SQLITE_PRIVATE void sqlite3ParseObjectReset(Parse *pParse){ sqlite3 *db = pParse->db; + assert( db!=0 ); + assert( db->pParse==pParse ); + assert( pParse->nested==0 ); +#ifndef SQLITE_OMIT_SHARED_CACHE + sqlite3DbFree(db, pParse->aTableLock); +#endif while( pParse->pCleanup ){ ParseCleanup *pCleanup = pParse->pCleanup; pParse->pCleanup = pCleanup->pNext; @@ -132778,11 +135118,12 @@ SQLITE_PRIVATE void sqlite3ParserReset(Parse *pParse){ if( pParse->pConstExpr ){ sqlite3ExprListDelete(db, pParse->pConstExpr); } - if( db ){ - assert( db->lookaside.bDisable >= pParse->disableLookaside ); - db->lookaside.bDisable -= pParse->disableLookaside; - db->lookaside.sz = db->lookaside.bDisable ? 0 : db->lookaside.szTrue; - } + assert( db->lookaside.bDisable >= pParse->disableLookaside ); + db->lookaside.bDisable -= pParse->disableLookaside; + db->lookaside.sz = db->lookaside.bDisable ? 0 : db->lookaside.szTrue; + assert( pParse->db->pParse==pParse ); + db->pParse = pParse->pOuterParse; + pParse->db = 0; pParse->disableLookaside = 0; } @@ -132795,7 +135136,7 @@ SQLITE_PRIVATE void sqlite3ParserReset(Parse *pParse){ ** cost for this mechansim (an extra malloc), so it should not be used ** for common cleanups that happen on most calls. But for less ** common cleanups, we save a single NULL-pointer comparison in -** sqlite3ParserReset(), which reduces the total CPU cycle count. +** sqlite3ParseObjectReset(), which reduces the total CPU cycle count. ** ** If a memory allocation error occurs, then the cleanup happens immediately. ** When either SQLITE_DEBUG or SQLITE_COVERAGE_TEST are defined, the @@ -132835,6 +135176,33 @@ SQLITE_PRIVATE void *sqlite3ParserAddCleanup( return pPtr; } +/* +** Turn bulk memory into a valid Parse object and link that Parse object +** into database connection db. +** +** Call sqlite3ParseObjectReset() to undo this operation. +** +** Caution: Do not confuse this routine with sqlite3ParseObjectInit() which +** is generated by Lemon. +*/ +SQLITE_PRIVATE void sqlite3ParseObjectInit(Parse *pParse, sqlite3 *db){ + memset(PARSE_HDR(pParse), 0, PARSE_HDR_SZ); + memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ); + assert( db->pParse!=pParse ); + pParse->pOuterParse = db->pParse; + db->pParse = pParse; + pParse->db = db; + if( db->mallocFailed ) sqlite3ErrorMsg(pParse, "out of memory"); +} + +/* +** Maximum number of times that we will try again to prepare a statement +** that returns SQLITE_ERROR_RETRY. +*/ +#ifndef SQLITE_MAX_PREPARE_RETRY +# define SQLITE_MAX_PREPARE_RETRY 25 +#endif + /* ** Compile the UTF-8 encoded SQL statement zSql into a statement handle. */ @@ -132847,16 +135215,19 @@ static int sqlite3Prepare( sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */ const char **pzTail /* OUT: End of parsed string */ ){ - char *zErrMsg = 0; /* Error message */ int rc = SQLITE_OK; /* Result code */ int i; /* Loop counter */ Parse sParse; /* Parsing context */ - memset(&sParse, 0, PARSE_HDR_SZ); + /* sqlite3ParseObjectInit(&sParse, db); // inlined for performance */ + memset(PARSE_HDR(&sParse), 0, PARSE_HDR_SZ); memset(PARSE_TAIL(&sParse), 0, PARSE_TAIL_SZ); + sParse.pOuterParse = db->pParse; + db->pParse = &sParse; + sParse.db = db; sParse.pReprepare = pReprepare; assert( ppStmt && *ppStmt==0 ); - /* assert( !db->mallocFailed ); // not true with SQLITE_USE_ALLOCA */ + if( db->mallocFailed ) sqlite3ErrorMsg(&sParse, "out of memory"); assert( sqlite3_mutex_held(db->mutex) ); /* For a long-term use prepared statement avoid the use of @@ -132909,7 +135280,6 @@ static int sqlite3Prepare( sqlite3VtabUnlockList(db); - sParse.db = db; if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){ char *zSqlCopy; int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH]; @@ -132922,14 +135292,14 @@ static int sqlite3Prepare( } zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes); if( zSqlCopy ){ - sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg); + sqlite3RunParser(&sParse, zSqlCopy); sParse.zTail = &zSql[sParse.zTail-zSqlCopy]; sqlite3DbFree(db, zSqlCopy); }else{ sParse.zTail = &zSql[nBytes]; } }else{ - sqlite3RunParser(&sParse, zSql, &zErrMsg); + sqlite3RunParser(&sParse, zSql); } assert( 0==sParse.nQueryLoop ); @@ -132945,7 +135315,7 @@ static int sqlite3Prepare( sParse.checkSchema = 0; } if( sParse.rc!=SQLITE_OK && sParse.rc!=SQLITE_DONE ){ - if( sParse.checkSchema ){ + if( sParse.checkSchema && db->init.busy==0 ){ schemaIsValid(&sParse); } if( sParse.pVdbe ){ @@ -132953,14 +135323,14 @@ static int sqlite3Prepare( } assert( 0==(*ppStmt) ); rc = sParse.rc; - if( zErrMsg ){ - sqlite3ErrorWithMsg(db, rc, "%s", zErrMsg); - sqlite3DbFree(db, zErrMsg); + if( sParse.zErrMsg ){ + sqlite3ErrorWithMsg(db, rc, "%s", sParse.zErrMsg); + sqlite3DbFree(db, sParse.zErrMsg); }else{ sqlite3Error(db, rc); } }else{ - assert( zErrMsg==0 ); + assert( sParse.zErrMsg==0 ); *ppStmt = (sqlite3_stmt*)sParse.pVdbe; rc = SQLITE_OK; sqlite3ErrorClear(db); @@ -132976,7 +135346,7 @@ static int sqlite3Prepare( end_prepare: - sqlite3ParserReset(&sParse); + sqlite3ParseObjectReset(&sParse); return rc; } static int sqlite3LockAndPrepare( @@ -133006,7 +135376,8 @@ static int sqlite3LockAndPrepare( ** reset is considered a permanent error. */ rc = sqlite3Prepare(db, zSql, nBytes, prepFlags, pOld, ppStmt, pzTail); assert( rc==SQLITE_OK || *ppStmt==0 ); - }while( rc==SQLITE_ERROR_RETRY + if( rc==SQLITE_OK || db->mallocFailed ) break; + }while( (rc==SQLITE_ERROR_RETRY && (cnt++) same as JOIN +** NATURAL CROSS JOIN -> same as NATURAL JOIN +** OUTER LEFT JOIN -> same as LEFT JOIN +** LEFT NATURAL JOIN -> same as NATURAL LEFT JOIN +** LEFT RIGHT JOIN -> same as FULL JOIN +** RIGHT OUTER FULL JOIN -> same as FULL JOIN +** CROSS CROSS CROSS JOIN -> same as JOIN +** +** The only restrictions on the join type name are: +** +** * "INNER" cannot appear together with "OUTER", "LEFT", "RIGHT", +** or "FULL". +** +** * "CROSS" cannot appear together with "OUTER", "LEFT", "RIGHT, +** or "FULL". +** +** * If "OUTER" is present then there must also be one of +** "LEFT", "RIGHT", or "FULL" */ SQLITE_PRIVATE int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){ int jointype = 0; @@ -133442,13 +135859,13 @@ SQLITE_PRIVATE int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *p u8 nChar; /* Length of the keyword in characters */ u8 code; /* Join type mask */ } aKeyword[] = { - /* natural */ { 0, 7, JT_NATURAL }, - /* left */ { 6, 4, JT_LEFT|JT_OUTER }, - /* outer */ { 10, 5, JT_OUTER }, - /* right */ { 14, 5, JT_RIGHT|JT_OUTER }, - /* full */ { 19, 4, JT_LEFT|JT_RIGHT|JT_OUTER }, - /* inner */ { 23, 5, JT_INNER }, - /* cross */ { 28, 5, JT_INNER|JT_CROSS }, + /* (0) natural */ { 0, 7, JT_NATURAL }, + /* (1) left */ { 6, 4, JT_LEFT|JT_OUTER }, + /* (2) outer */ { 10, 5, JT_OUTER }, + /* (3) right */ { 14, 5, JT_RIGHT|JT_OUTER }, + /* (4) full */ { 19, 4, JT_LEFT|JT_RIGHT|JT_OUTER }, + /* (5) inner */ { 23, 5, JT_INNER }, + /* (6) cross */ { 28, 5, JT_INNER|JT_CROSS }, }; int i, j; apAll[0] = pA; @@ -133471,18 +135888,15 @@ SQLITE_PRIVATE int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *p } if( (jointype & (JT_INNER|JT_OUTER))==(JT_INNER|JT_OUTER) || - (jointype & JT_ERROR)!=0 + (jointype & JT_ERROR)!=0 || + (jointype & (JT_OUTER|JT_LEFT|JT_RIGHT))==JT_OUTER ){ - const char *zSp = " "; - assert( pB!=0 ); - if( pC==0 ){ zSp++; } - sqlite3ErrorMsg(pParse, "unknown or unsupported join type: " - "%T %T%s%T", pA, pB, zSp, pC); - jointype = JT_INNER; - }else if( (jointype & JT_OUTER)!=0 - && (jointype & (JT_LEFT|JT_RIGHT))!=JT_LEFT ){ - sqlite3ErrorMsg(pParse, - "RIGHT and FULL OUTER JOINs are not currently supported"); + const char *zSp1 = " "; + const char *zSp2 = " "; + if( pB==0 ){ zSp1++; } + if( pC==0 ){ zSp2++; } + sqlite3ErrorMsg(pParse, "unknown join type: " + "%T%s%T%s%T", pA, zSp1, pB, zSp2, pC); jointype = JT_INNER; } return jointype; @@ -133503,8 +135917,25 @@ SQLITE_PRIVATE int sqlite3ColumnIndex(Table *pTab, const char *zCol){ } /* -** Search the first N tables in pSrc, from left to right, looking for a -** table that has a column named zCol. +** Mark a subquery result column as having been used. +*/ +SQLITE_PRIVATE void sqlite3SrcItemColumnUsed(SrcItem *pItem, int iCol){ + assert( pItem!=0 ); + assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) ); + if( pItem->fg.isNestedFrom ){ + ExprList *pResults; + assert( pItem->pSelect!=0 ); + pResults = pItem->pSelect->pEList; + assert( pResults!=0 ); + assert( iCol>=0 && iColnExpr ); + pResults->a[iCol].fg.bUsed = 1; + } +} + +/* +** Search the tables iStart..iEnd (inclusive) in pSrc, looking for a +** table that has a column named zCol. The search is left-to-right. +** The first match found is returned. ** ** When found, set *piTab and *piCol to the table index and column index ** of the matching column and return TRUE. @@ -133513,22 +135944,27 @@ SQLITE_PRIVATE int sqlite3ColumnIndex(Table *pTab, const char *zCol){ */ static int tableAndColumnIndex( SrcList *pSrc, /* Array of tables to search */ - int N, /* Number of tables in pSrc->a[] to search */ + int iStart, /* First member of pSrc->a[] to check */ + int iEnd, /* Last member of pSrc->a[] to check */ const char *zCol, /* Name of the column we are looking for */ int *piTab, /* Write index of pSrc->a[] here */ int *piCol, /* Write index of pSrc->a[*piTab].pTab->aCol[] here */ - int bIgnoreHidden /* True to ignore hidden columns */ + int bIgnoreHidden /* Ignore hidden columns */ ){ int i; /* For looping over tables in pSrc */ int iCol; /* Index of column matching zCol */ + assert( iEndnSrc ); + assert( iStart>=0 ); assert( (piTab==0)==(piCol==0) ); /* Both or neither are NULL */ - for(i=0; ia[i].pTab, zCol); if( iCol>=0 && (bIgnoreHidden==0 || IsHiddenColumn(&pSrc->a[i].pTab->aCol[iCol])==0) ){ if( piTab ){ + sqlite3SrcItemColumnUsed(&pSrc->a[i], iCol); *piTab = i; *piCol = iCol; } @@ -133539,66 +135975,19 @@ static int tableAndColumnIndex( } /* -** This function is used to add terms implied by JOIN syntax to the -** WHERE clause expression of a SELECT statement. The new term, which -** is ANDed with the existing WHERE clause, is of the form: -** -** (tab1.col1 = tab2.col2) -** -** where tab1 is the iSrc'th table in SrcList pSrc and tab2 is the -** (iSrc+1)'th. Column col1 is column iColLeft of tab1, and col2 is -** column iColRight of tab2. -*/ -static void addWhereTerm( - Parse *pParse, /* Parsing context */ - SrcList *pSrc, /* List of tables in FROM clause */ - int iLeft, /* Index of first table to join in pSrc */ - int iColLeft, /* Index of column in first table */ - int iRight, /* Index of second table in pSrc */ - int iColRight, /* Index of column in second table */ - int isOuterJoin, /* True if this is an OUTER join */ - Expr **ppWhere /* IN/OUT: The WHERE clause to add to */ -){ - sqlite3 *db = pParse->db; - Expr *pE1; - Expr *pE2; - Expr *pEq; - - assert( iLeftnSrc>iRight ); - assert( pSrc->a[iLeft].pTab ); - assert( pSrc->a[iRight].pTab ); - - pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iColLeft); - pE2 = sqlite3CreateColumnExpr(db, pSrc, iRight, iColRight); - - pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2); - assert( pE2!=0 || pEq==0 ); /* Due to db->mallocFailed test - ** in sqlite3DbMallocRawNN() called from - ** sqlite3PExpr(). */ - if( pEq && isOuterJoin ){ - ExprSetProperty(pEq, EP_FromJoin); - assert( !ExprHasProperty(pEq, EP_TokenOnly|EP_Reduced) ); - ExprSetVVAProperty(pEq, EP_NoReduce); - pEq->iRightJoinTable = pE2->iTable; - } - *ppWhere = sqlite3ExprAnd(pParse, *ppWhere, pEq); -} - -/* -** Set the EP_FromJoin property on all terms of the given expression. -** And set the Expr.iRightJoinTable to iTable for every term in the +** Set the EP_OuterON property on all terms of the given expression. +** And set the Expr.w.iJoin to iTable for every term in the ** expression. ** -** The EP_FromJoin property is used on terms of an expression to tell -** the LEFT OUTER JOIN processing logic that this term is part of the +** The EP_OuterON property is used on terms of an expression to tell +** the OUTER JOIN processing logic that this term is part of the ** join restriction specified in the ON or USING clause and not a part ** of the more general WHERE clause. These terms are moved over to the ** WHERE clause during join processing but we need to remember that they ** originated in the ON or USING clause. ** -** The Expr.iRightJoinTable tells the WHERE clause processing that the -** expression depends on table iRightJoinTable even if that table is not +** The Expr.w.iJoin tells the WHERE clause processing that the +** expression depends on table w.iJoin even if that table is not ** explicitly mentioned in the expression. That information is needed ** for cases like this: ** @@ -133611,39 +136000,48 @@ static void addWhereTerm( ** after the t1 loop and rows with t1.x!=5 will never appear in ** the output, which is incorrect. */ -SQLITE_PRIVATE void sqlite3SetJoinExpr(Expr *p, int iTable){ +SQLITE_PRIVATE void sqlite3SetJoinExpr(Expr *p, int iTable, u32 joinFlag){ + assert( joinFlag==EP_OuterON || joinFlag==EP_InnerON ); while( p ){ - ExprSetProperty(p, EP_FromJoin); + ExprSetProperty(p, joinFlag); assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) ); ExprSetVVAProperty(p, EP_NoReduce); - p->iRightJoinTable = iTable; + p->w.iJoin = iTable; if( p->op==TK_FUNCTION ){ assert( ExprUseXList(p) ); if( p->x.pList ){ int i; for(i=0; ix.pList->nExpr; i++){ - sqlite3SetJoinExpr(p->x.pList->a[i].pExpr, iTable); + sqlite3SetJoinExpr(p->x.pList->a[i].pExpr, iTable, joinFlag); } } } - sqlite3SetJoinExpr(p->pLeft, iTable); + sqlite3SetJoinExpr(p->pLeft, iTable, joinFlag); p = p->pRight; } } -/* Undo the work of sqlite3SetJoinExpr(). In the expression p, convert every -** term that is marked with EP_FromJoin and iRightJoinTable==iTable into -** an ordinary term that omits the EP_FromJoin mark. +/* Undo the work of sqlite3SetJoinExpr(). This is used when a LEFT JOIN +** is simplified into an ordinary JOIN, and when an ON expression is +** "pushed down" into the WHERE clause of a subquery. ** -** This happens when a LEFT JOIN is simplified into an ordinary JOIN. +** Convert every term that is marked with EP_OuterON and w.iJoin==iTable into +** an ordinary term that omits the EP_OuterON mark. Or if iTable<0, then +** just clear every EP_OuterON and EP_InnerON mark from the expression tree. +** +** If nullable is true, that means that Expr p might evaluate to NULL even +** if it is a reference to a NOT NULL column. This can happen, for example, +** if the table that p references is on the left side of a RIGHT JOIN. +** If nullable is true, then take care to not remove the EP_CanBeNull bit. +** See forum thread https://sqlite.org/forum/forumpost/b40696f50145d21c */ -static void unsetJoinExpr(Expr *p, int iTable){ +static void unsetJoinExpr(Expr *p, int iTable, int nullable){ while( p ){ - if( ExprHasProperty(p, EP_FromJoin) - && (iTable<0 || p->iRightJoinTable==iTable) ){ - ExprClearProperty(p, EP_FromJoin); + if( iTable<0 || (ExprHasProperty(p, EP_OuterON) && p->w.iJoin==iTable) ){ + ExprClearProperty(p, EP_OuterON|EP_InnerON); + if( iTable>=0 ) ExprSetProperty(p, EP_InnerON); } - if( p->op==TK_COLUMN && p->iTable==iTable ){ + if( p->op==TK_COLUMN && p->iTable==iTable && !nullable ){ ExprClearProperty(p, EP_CanBeNull); } if( p->op==TK_FUNCTION ){ @@ -133651,30 +136049,37 @@ static void unsetJoinExpr(Expr *p, int iTable){ if( p->x.pList ){ int i; for(i=0; ix.pList->nExpr; i++){ - unsetJoinExpr(p->x.pList->a[i].pExpr, iTable); + unsetJoinExpr(p->x.pList->a[i].pExpr, iTable, nullable); } } } - unsetJoinExpr(p->pLeft, iTable); + unsetJoinExpr(p->pLeft, iTable, nullable); p = p->pRight; } } /* ** This routine processes the join information for a SELECT statement. -** ON and USING clauses are converted into extra terms of the WHERE clause. -** NATURAL joins also create extra WHERE clause terms. +** +** * A NATURAL join is converted into a USING join. After that, we +** do not need to be concerned with NATURAL joins and we only have +** think about USING joins. +** +** * ON and USING clauses result in extra terms being added to the +** WHERE clause to enforce the specified constraints. The extra +** WHERE clause terms will be tagged with EP_OuterON or +** EP_InnerON so that we know that they originated in ON/USING. ** ** The terms of a FROM clause are contained in the Select.pSrc structure. ** The left most table is the first entry in Select.pSrc. The right-most ** table is the last entry. The join operator is held in the entry to -** the left. Thus entry 0 contains the join operator for the join between +** the right. Thus entry 1 contains the join operator for the join between ** entries 0 and 1. Any ON or USING clauses associated with the join are -** also attached to the left entry. +** also attached to the right entry. ** ** This routine returns the number of errors encountered. */ -static int sqliteProcessJoin(Parse *pParse, Select *p){ +static int sqlite3ProcessJoin(Parse *pParse, Select *p){ SrcList *pSrc; /* All tables in the FROM clause */ int i, j; /* Loop counters */ SrcItem *pLeft; /* Left table being joined */ @@ -133685,49 +136090,41 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){ pRight = &pLeft[1]; for(i=0; inSrc-1; i++, pRight++, pLeft++){ Table *pRightTab = pRight->pTab; - int isOuter; + u32 joinType; if( NEVER(pLeft->pTab==0 || pRightTab==0) ) continue; - isOuter = (pRight->fg.jointype & JT_OUTER)!=0; + joinType = (pRight->fg.jointype & JT_OUTER)!=0 ? EP_OuterON : EP_InnerON; - /* When the NATURAL keyword is present, add WHERE clause terms for - ** every column that the two tables have in common. + /* If this is a NATURAL join, synthesize an approprate USING clause + ** to specify which columns should be joined. */ if( pRight->fg.jointype & JT_NATURAL ){ - if( pRight->pOn || pRight->pUsing ){ + IdList *pUsing = 0; + if( pRight->fg.isUsing || pRight->u3.pOn ){ sqlite3ErrorMsg(pParse, "a NATURAL join may not have " "an ON or USING clause", 0); return 1; } for(j=0; jnCol; j++){ char *zName; /* Name of column in the right table */ - int iLeft; /* Matching left table */ - int iLeftCol; /* Matching column in the left table */ if( IsHiddenColumn(&pRightTab->aCol[j]) ) continue; zName = pRightTab->aCol[j].zCnName; - if( tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol, 1) ){ - addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, j, - isOuter, &p->pWhere); + if( tableAndColumnIndex(pSrc, 0, i, zName, 0, 0, 1) ){ + pUsing = sqlite3IdListAppend(pParse, pUsing, 0); + if( pUsing ){ + assert( pUsing->nId>0 ); + assert( pUsing->a[pUsing->nId-1].zName==0 ); + pUsing->a[pUsing->nId-1].zName = sqlite3DbStrDup(pParse->db, zName); + } } } - } - - /* Disallow both ON and USING clauses in the same join - */ - if( pRight->pOn && pRight->pUsing ){ - sqlite3ErrorMsg(pParse, "cannot have both ON and USING " - "clauses in the same join"); - return 1; - } - - /* Add the ON clause to the end of the WHERE clause, connected by - ** an AND operator. - */ - if( pRight->pOn ){ - if( isOuter ) sqlite3SetJoinExpr(pRight->pOn, pRight->iCursor); - p->pWhere = sqlite3ExprAnd(pParse, p->pWhere, pRight->pOn); - pRight->pOn = 0; + if( pUsing ){ + pRight->fg.isUsing = 1; + pRight->fg.isSynthUsing = 1; + pRight->u3.pUsing = pUsing; + } + if( pParse->nErr ) return 1; } /* Create extra terms on the WHERE clause for each column named @@ -133737,27 +136134,88 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){ ** Report an error if any column mentioned in the USING clause is ** not contained in both tables to be joined. */ - if( pRight->pUsing ){ - IdList *pList = pRight->pUsing; + if( pRight->fg.isUsing ){ + IdList *pList = pRight->u3.pUsing; + sqlite3 *db = pParse->db; + assert( pList!=0 ); for(j=0; jnId; j++){ char *zName; /* Name of the term in the USING clause */ int iLeft; /* Table on the left with matching column name */ int iLeftCol; /* Column number of matching column on the left */ int iRightCol; /* Column number of matching column on the right */ + Expr *pE1; /* Reference to the column on the LEFT of the join */ + Expr *pE2; /* Reference to the column on the RIGHT of the join */ + Expr *pEq; /* Equality constraint. pE1 == pE2 */ zName = pList->a[j].zName; iRightCol = sqlite3ColumnIndex(pRightTab, zName); if( iRightCol<0 - || !tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol, 0) + || tableAndColumnIndex(pSrc, 0, i, zName, &iLeft, &iLeftCol, + pRight->fg.isSynthUsing)==0 ){ sqlite3ErrorMsg(pParse, "cannot join using column %s - column " "not present in both tables", zName); return 1; } - addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, iRightCol, - isOuter, &p->pWhere); + pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iLeftCol); + sqlite3SrcItemColumnUsed(&pSrc->a[iLeft], iLeftCol); + if( (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){ + /* This branch runs if the query contains one or more RIGHT or FULL + ** JOINs. If only a single table on the left side of this join + ** contains the zName column, then this branch is a no-op. + ** But if there are two or more tables on the left side + ** of the join, construct a coalesce() function that gathers all + ** such tables. Raise an error if more than one of those references + ** to zName is not also within a prior USING clause. + ** + ** We really ought to raise an error if there are two or more + ** non-USING references to zName on the left of an INNER or LEFT + ** JOIN. But older versions of SQLite do not do that, so we avoid + ** adding a new error so as to not break legacy applications. + */ + ExprList *pFuncArgs = 0; /* Arguments to the coalesce() */ + static const Token tkCoalesce = { "coalesce", 8 }; + while( tableAndColumnIndex(pSrc, iLeft+1, i, zName, &iLeft, &iLeftCol, + pRight->fg.isSynthUsing)!=0 ){ + if( pSrc->a[iLeft].fg.isUsing==0 + || sqlite3IdListIndex(pSrc->a[iLeft].u3.pUsing, zName)<0 + ){ + sqlite3ErrorMsg(pParse, "ambiguous reference to %s in USING()", + zName); + break; + } + pFuncArgs = sqlite3ExprListAppend(pParse, pFuncArgs, pE1); + pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iLeftCol); + sqlite3SrcItemColumnUsed(&pSrc->a[iLeft], iLeftCol); + } + if( pFuncArgs ){ + pFuncArgs = sqlite3ExprListAppend(pParse, pFuncArgs, pE1); + pE1 = sqlite3ExprFunction(pParse, pFuncArgs, &tkCoalesce, 0); + } + } + pE2 = sqlite3CreateColumnExpr(db, pSrc, i+1, iRightCol); + sqlite3SrcItemColumnUsed(pRight, iRightCol); + pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2); + assert( pE2!=0 || pEq==0 ); + if( pEq ){ + ExprSetProperty(pEq, joinType); + assert( !ExprHasProperty(pEq, EP_TokenOnly|EP_Reduced) ); + ExprSetVVAProperty(pEq, EP_NoReduce); + pEq->w.iJoin = pE2->iTable; + } + p->pWhere = sqlite3ExprAnd(pParse, p->pWhere, pEq); } } + + /* Add the ON clause to the end of the WHERE clause, connected by + ** an AND operator. + */ + else if( pRight->u3.pOn ){ + sqlite3SetJoinExpr(pRight->u3.pOn, pRight->iCursor, joinType); + p->pWhere = sqlite3ExprAnd(pParse, p->pWhere, pRight->u3.pOn); + pRight->u3.pOn = 0; + pRight->fg.isOn = 1; + } } return 0; } @@ -134146,7 +136604,7 @@ static void fixDistinctOpenEph( ** retrieved directly from table t1. If the values are very large, this ** can be more efficient than storing them directly in the sorter records. ** -** The ExprList_item.bSorterRef flag is set for each expression in pEList +** The ExprList_item.fg.bSorterRef flag is set for each expression in pEList ** for which the sorter-reference optimization should be enabled. ** Additionally, the pSort->aDefer[] array is populated with entries ** for all cursors required to evaluate all selected expressions. Finally. @@ -134206,7 +136664,7 @@ static void selectExprDefer( nDefer++; } } - pItem->bSorterRef = 1; + pItem->fg.bSorterRef = 1; } } } @@ -134337,7 +136795,7 @@ static void selectInnerLoop( for(i=0; inExpr; i++){ if( pEList->a[i].u.x.iOrderByCol>0 #ifdef SQLITE_ENABLE_SORTER_REFERENCES - || pEList->a[i].bSorterRef + || pEList->a[i].fg.bSorterRef #endif ){ nResultCol--; @@ -134630,7 +137088,7 @@ SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){ p->nRef = 1; memset(&p[1], 0, nExtra); }else{ - sqlite3OomFault(db); + return (KeyInfo*)sqlite3OomFault(db); } return p; } @@ -134699,7 +137157,7 @@ SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoFromExprList( assert( sqlite3KeyInfoIsWriteable(pInfo) ); for(i=iStart, pItem=pList->a+iStart; iaColl[i-iStart] = sqlite3ExprNNCollSeq(pParse, pItem->pExpr); - pInfo->aSortFlags[i-iStart] = pItem->sortFlags; + pInfo->aSortFlags[i-iStart] = pItem->fg.sortFlags; } } return pInfo; @@ -134801,6 +137259,9 @@ static void generateSortTail( iTab = pSort->iECursor; if( eDest==SRT_Output || eDest==SRT_Coroutine || eDest==SRT_Mem ){ + if( eDest==SRT_Mem && p->iOffset ){ + sqlite3VdbeAddOp2(v, OP_Null, 0, pDest->iSdst); + } regRowid = 0; regRow = pDest->iSdst; }else{ @@ -134824,7 +137285,7 @@ static void generateSortTail( if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce); addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak); VdbeCoverage(v); - codeOffset(v, p->iOffset, addrContinue); + assert( p->iLimit==0 && p->iOffset==0 ); sqlite3VdbeAddOp3(v, OP_SorterData, iTab, regSortOut, iSortTab); bSeq = 0; }else{ @@ -134832,10 +137293,13 @@ static void generateSortTail( codeOffset(v, p->iOffset, addrContinue); iSortTab = iTab; bSeq = 1; + if( p->iOffset>0 ){ + sqlite3VdbeAddOp2(v, OP_AddImm, p->iLimit, -1); + } } for(i=0, iCol=nKey+bSeq-1; i=0; i--){ #ifdef SQLITE_ENABLE_SORTER_REFERENCES - if( aOutEx[i].bSorterRef ){ + if( aOutEx[i].fg.bSorterRef ){ sqlite3ExprCode(pParse, aOutEx[i].pExpr, regRow+i); }else #endif @@ -135238,7 +137702,7 @@ SQLITE_PRIVATE void sqlite3GenerateColumnNames( assert( p->op!=TK_AGG_COLUMN ); /* Agg processing has not run yet */ assert( p->op!=TK_COLUMN || (ExprUseYTab(p) && p->y.pTab!=0) ); /* Covering idx not yet coded */ - if( pEList->a[i].zEName && pEList->a[i].eEName==ENAME_NAME ){ + if( pEList->a[i].zEName && pEList->a[i].fg.eEName==ENAME_NAME ){ /* An AS clause always takes first priority */ char *zName = pEList->a[i].zEName; sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT); @@ -135323,22 +137787,25 @@ SQLITE_PRIVATE int sqlite3ColumnsFromExprList( *paCol = aCol; for(i=0, pCol=aCol; imallocFailed; i++, pCol++){ + struct ExprList_item *pX = &pEList->a[i]; + struct ExprList_item *pCollide; /* Get an appropriate name for the column */ - if( (zName = pEList->a[i].zEName)!=0 && pEList->a[i].eEName==ENAME_NAME ){ + if( (zName = pX->zEName)!=0 && pX->fg.eEName==ENAME_NAME ){ /* If the column contains an "AS " phrase, use as the name */ }else{ - Expr *pColExpr = sqlite3ExprSkipCollateAndLikely(pEList->a[i].pExpr); + Expr *pColExpr = sqlite3ExprSkipCollateAndLikely(pX->pExpr); while( ALWAYS(pColExpr!=0) && pColExpr->op==TK_DOT ){ pColExpr = pColExpr->pRight; assert( pColExpr!=0 ); } if( pColExpr->op==TK_COLUMN && ALWAYS( ExprUseYTab(pColExpr) ) - && (pTab = pColExpr->y.pTab)!=0 + && ALWAYS( pColExpr->y.pTab!=0 ) ){ /* For columns use the column name name */ int iCol = pColExpr->iColumn; + pTab = pColExpr->y.pTab; if( iCol<0 ) iCol = pTab->iPKey; zName = iCol>=0 ? pTab->aCol[iCol].zCnName : "rowid"; }else if( pColExpr->op==TK_ID ){ @@ -135346,7 +137813,7 @@ SQLITE_PRIVATE int sqlite3ColumnsFromExprList( zName = pColExpr->u.zToken; }else{ /* Use the original text of the column expression as its name */ - zName = pEList->a[i].zEName; + assert( zName==pX->zEName ); /* pointer comparison intended */ } } if( zName && !sqlite3IsTrueOrFalse(zName) ){ @@ -135359,7 +137826,10 @@ SQLITE_PRIVATE int sqlite3ColumnsFromExprList( ** append an integer to the name so that it becomes unique. */ cnt = 0; - while( zName && sqlite3HashFind(&ht, zName)!=0 ){ + while( zName && (pCollide = sqlite3HashFind(&ht, zName))!=0 ){ + if( pCollide->fg.bUsingTerm ){ + pCol->colFlags |= COLFLAG_NOEXPAND; + } nName = sqlite3Strlen30(zName); if( nName>0 ){ for(j=nName-1; j>0 && sqlite3Isdigit(zName[j]); j--){} @@ -135370,8 +137840,11 @@ SQLITE_PRIVATE int sqlite3ColumnsFromExprList( } pCol->zCnName = zName; pCol->hName = sqlite3StrIHash(zName); + if( pX->fg.bNoExpand ){ + pCol->colFlags |= COLFLAG_NOEXPAND; + } sqlite3ColumnPropertiesFromName(0, pCol); - if( zName && sqlite3HashInsert(&ht, zName, pCol)==pCol ){ + if( zName && sqlite3HashInsert(&ht, zName, pX)==pX ){ sqlite3OomFault(db); } } @@ -135628,7 +138101,7 @@ static KeyInfo *multiSelectOrderByKeyInfo(Parse *pParse, Select *p, int nExtra){ } assert( sqlite3KeyInfoIsWriteable(pRet) ); pRet->aColl[i] = pColl; - pRet->aSortFlags[i] = pOrderBy->a[i].sortFlags; + pRet->aSortFlags[i] = pOrderBy->a[i].fg.sortFlags; } } @@ -135846,7 +138319,7 @@ static int multiSelectOrderBy( ** The "LIMIT of exactly 1" case of condition (1) comes about when a VALUES ** clause occurs within scalar expression (ex: "SELECT (VALUES(1),(2),(3))"). ** The sqlite3CodeSubselect will have added the LIMIT 1 clause in tht case. -** Since the limit is exactly 1, we only need to evalutes the left-most VALUES. +** Since the limit is exactly 1, we only need to evaluate the left-most VALUES. */ static int multiSelectValues( Parse *pParse, /* Parsing context */ @@ -136522,6 +138995,8 @@ static int multiSelectOrderBy( ){ int i, j; /* Loop counters */ Select *pPrior; /* Another SELECT immediately to our left */ + Select *pSplit; /* Left-most SELECT in the right-hand group */ + int nSelect; /* Number of SELECT statements in the compound */ Vdbe *v; /* Generate code to this VDBE */ SelectDest destA; /* Destination for coroutine A */ SelectDest destB; /* Destination for coroutine B */ @@ -136567,8 +139042,7 @@ static int multiSelectOrderBy( /* Patch up the ORDER BY clause */ op = p->op; - pPrior = p->pPrior; - assert( pPrior->pOrderBy==0 ); + assert( p->pPrior->pOrderBy==0 ); pOrderBy = p->pOrderBy; assert( pOrderBy ); nOrderBy = pOrderBy->nExpr; @@ -136618,11 +139092,6 @@ static int multiSelectOrderBy( pKeyMerge = 0; } - /* Reattach the ORDER BY clause to the query. - */ - p->pOrderBy = pOrderBy; - pPrior->pOrderBy = sqlite3ExprListDup(pParse->db, pOrderBy, 0); - /* Allocate a range of temporary registers and the KeyInfo needed ** for the logic that removes duplicate result rows when the ** operator is UNION, EXCEPT, or INTERSECT (but not UNION ALL). @@ -136647,12 +139116,30 @@ static int multiSelectOrderBy( /* Separate the left and the right query from one another */ - p->pPrior = 0; + nSelect = 1; + if( (op==TK_ALL || op==TK_UNION) + && OptimizationEnabled(db, SQLITE_BalancedMerge) + ){ + for(pSplit=p; pSplit->pPrior!=0 && pSplit->op==op; pSplit=pSplit->pPrior){ + nSelect++; + assert( pSplit->pPrior->pNext==pSplit ); + } + } + if( nSelect<=3 ){ + pSplit = p; + }else{ + pSplit = p; + for(i=2; ipPrior; } + } + pPrior = pSplit->pPrior; + assert( pPrior!=0 ); + pSplit->pPrior = 0; pPrior->pNext = 0; + assert( p->pOrderBy == pOrderBy ); + assert( pOrderBy!=0 || db->mallocFailed ); + pPrior->pOrderBy = sqlite3ExprListDup(pParse->db, pOrderBy, 0); sqlite3ResolveOrderGroupBy(pParse, p, p->pOrderBy, "ORDER"); - if( pPrior->pPrior==0 ){ - sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, "ORDER"); - } + sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, "ORDER"); /* Compute the limit registers */ computeLimitRegisters(pParse, p, labelEnd); @@ -136801,14 +139288,14 @@ static int multiSelectOrderBy( */ sqlite3VdbeResolveLabel(v, labelEnd); - /* Reassembly the compound query so that it will be freed correctly + /* Reassemble the compound query so that it will be freed correctly ** by the calling function */ - if( p->pPrior ){ - sqlite3SelectDelete(db, p->pPrior); + if( pSplit->pPrior ){ + sqlite3ParserAddCleanup(pParse, + (void(*)(sqlite3*,void*))sqlite3SelectDelete, pSplit->pPrior); } - p->pPrior = pPrior; - pPrior->pNext = p; - + pSplit->pPrior = pPrior; + pPrior->pNext = pSplit; sqlite3ExprListDelete(db, pPrior->pOrderBy); pPrior->pOrderBy = 0; @@ -136826,12 +139313,40 @@ static int multiSelectOrderBy( ** ** All references to columns in table iTable are to be replaced by corresponding ** expressions in pEList. +** +** ## About "isOuterJoin": +** +** The isOuterJoin column indicates that the replacement will occur into a +** position in the parent that NULL-able due to an OUTER JOIN. Either the +** target slot in the parent is the right operand of a LEFT JOIN, or one of +** the left operands of a RIGHT JOIN. In either case, we need to potentially +** bypass the substituted expression with OP_IfNullRow. +** +** Suppose the original expression integer constant. Even though the table +** has the nullRow flag set, because the expression is an integer constant, +** it will not be NULLed out. So instead, we insert an OP_IfNullRow opcode +** that checks to see if the nullRow flag is set on the table. If the nullRow +** flag is set, then the value in the register is set to NULL and the original +** expression is bypassed. If the nullRow flag is not set, then the original +** expression runs to populate the register. +** +** Example where this is needed: +** +** CREATE TABLE t1(a INTEGER PRIMARY KEY, b INT); +** CREATE TABLE t2(x INT UNIQUE); +** +** SELECT a,b,m,x FROM t1 LEFT JOIN (SELECT 59 AS m,x FROM t2) ON b=x; +** +** When the subquery on the right side of the LEFT JOIN is flattened, we +** have to add OP_IfNullRow in front of the OP_Integer that implements the +** "m" value of the subquery so that a NULL will be loaded instead of 59 +** when processing a non-matched row of the left. */ typedef struct SubstContext { Parse *pParse; /* The parsing context */ int iTable; /* Replace references to this table */ int iNewTable; /* New table number */ - int isLeftJoin; /* Add TK_IF_NULL_ROW opcodes on each replacement */ + int isOuterJoin; /* Add TK_IF_NULL_ROW opcodes on each replacement */ ExprList *pEList; /* Replacement expressions */ } SubstContext; @@ -136857,10 +139372,11 @@ static Expr *substExpr( Expr *pExpr /* Expr in which substitution occurs */ ){ if( pExpr==0 ) return 0; - if( ExprHasProperty(pExpr, EP_FromJoin) - && pExpr->iRightJoinTable==pSubst->iTable + if( ExprHasProperty(pExpr, EP_OuterON|EP_InnerON) + && pExpr->w.iJoin==pSubst->iTable ){ - pExpr->iRightJoinTable = pSubst->iNewTable; + testcase( ExprHasProperty(pExpr, EP_InnerON) ); + pExpr->w.iJoin = pSubst->iNewTable; } if( pExpr->op==TK_COLUMN && pExpr->iTable==pSubst->iTable @@ -136881,7 +139397,7 @@ static Expr *substExpr( sqlite3VectorErrorMsg(pSubst->pParse, pCopy); }else{ sqlite3 *db = pSubst->pParse->db; - if( pSubst->isLeftJoin && pCopy->op!=TK_COLUMN ){ + if( pSubst->isOuterJoin && pCopy->op!=TK_COLUMN ){ memset(&ifNullRow, 0, sizeof(ifNullRow)); ifNullRow.op = TK_IF_NULL_ROW; ifNullRow.pLeft = pCopy; @@ -136895,14 +139411,20 @@ static Expr *substExpr( sqlite3ExprDelete(db, pNew); return pExpr; } - if( pSubst->isLeftJoin ){ + if( pSubst->isOuterJoin ){ ExprSetProperty(pNew, EP_CanBeNull); } - if( ExprHasProperty(pExpr,EP_FromJoin) ){ - sqlite3SetJoinExpr(pNew, pExpr->iRightJoinTable); + if( ExprHasProperty(pExpr,EP_OuterON|EP_InnerON) ){ + sqlite3SetJoinExpr(pNew, pExpr->w.iJoin, + pExpr->flags & (EP_OuterON|EP_InnerON)); } sqlite3ExprDelete(db, pExpr); pExpr = pNew; + if( pExpr->op==TK_TRUEFALSE ){ + pExpr->u.iValue = sqlite3ExprTruthValue(pExpr); + pExpr->op = TK_INTEGER; + ExprSetProperty(pExpr, EP_IntValue); + } /* Ensure that the expression now has an implicit collation sequence, ** just as it did when it was a column of a view or sub-query. */ @@ -137063,8 +139585,8 @@ static int renumberCursorsCb(Walker *pWalker, Expr *pExpr){ if( op==TK_COLUMN || op==TK_IF_NULL_ROW ){ renumberCursorDoMapping(pWalker, &pExpr->iTable); } - if( ExprHasProperty(pExpr, EP_FromJoin) ){ - renumberCursorDoMapping(pWalker, &pExpr->iRightJoinTable); + if( ExprHasProperty(pExpr, EP_OuterON) ){ + renumberCursorDoMapping(pWalker, &pExpr->w.iJoin); } return WRC_Continue; } @@ -137149,6 +139671,7 @@ static void renumberCursors( ** table and ** (3c) the outer query may not be an aggregate. ** (3d) the outer query may not be DISTINCT. +** See also (26) for restrictions on RIGHT JOIN. ** ** (4) The subquery can not be DISTINCT. ** @@ -137200,6 +139723,9 @@ static void renumberCursors( ** (17d2) DISTINCT ** (17e) the subquery may not contain window functions, and ** (17f) the subquery must not be the RHS of a LEFT JOIN. +** (17g) either the subquery is the first element of the outer +** query or there are no RIGHT or FULL JOINs in any arm +** of the subquery. (This is a duplicate of condition (27b).) ** ** The parent and sub-query may contain WHERE clauses. Subject to ** rules (11), (13) and (14), they may also contain ORDER BY, @@ -137247,6 +139773,23 @@ static void renumberCursors( ** function in the select list or ORDER BY clause, flattening ** is not attempted. ** +** (26) The subquery may not be the right operand of a RIGHT JOIN. +** See also (3) for restrictions on LEFT JOIN. +** +** (27) The subquery may not contain a FULL or RIGHT JOIN unless it +** is the first element of the parent query. This must be the +** the case if: +** (27a) the subquery is not compound query, and +** (27b) the subquery is a compound query and the RIGHT JOIN occurs +** in any arm of the compound query. (See also (17g).) +** +** (28) The subquery is not a MATERIALIZED CTE. +** +** (29) Either the subquery is not the right-hand operand of a join with an +** ON or USING clause nor the right-hand operand of a NATURAL JOIN, or +** the right-most table within the FROM clause of the subquery +** is not part of an outer join. +** ** ** In this routine, the "p" parameter is a pointer to the outer query. ** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query @@ -137272,7 +139815,7 @@ static int flattenSubquery( SrcList *pSubSrc; /* The FROM clause of the subquery */ int iParent; /* VDBE cursor number of the pSub result set temp table */ int iNewParent = -1;/* Replacement table for iParent */ - int isLeftJoin = 0; /* True if pSub is the right side of a LEFT JOIN */ + int isOuterJoin = 0; /* True if pSub is the right side of a LEFT JOIN */ int i; /* Loop counter */ Expr *pWhere; /* The WHERE clause */ SrcItem *pSubitem; /* The subquery */ @@ -137345,26 +139888,64 @@ static int flattenSubquery( ** ** See also tickets #306, #350, and #3300. */ - if( (pSubitem->fg.jointype & JT_OUTER)!=0 ){ - isLeftJoin = 1; - if( pSubSrc->nSrc>1 /* (3a) */ - || isAgg /* (3b) */ - || IsVirtual(pSubSrc->a[0].pTab) /* (3c) */ - || (p->selFlags & SF_Distinct)!=0 /* (3d) */ + if( (pSubitem->fg.jointype & (JT_OUTER|JT_LTORJ))!=0 ){ + if( pSubSrc->nSrc>1 /* (3a) */ + || isAgg /* (3c) */ + || IsVirtual(pSubSrc->a[0].pTab) /* (3b) */ + || (p->selFlags & SF_Distinct)!=0 /* (3d) */ + || (pSubitem->fg.jointype & JT_RIGHT)!=0 /* (26) */ ){ return 0; } + isOuterJoin = 1; } #ifdef SQLITE_EXTRA_IFNULLROW else if( iFrom>0 && !isAgg ){ - /* Setting isLeftJoin to -1 causes OP_IfNullRow opcodes to be generated for + /* Setting isOuterJoin to -1 causes OP_IfNullRow opcodes to be generated for ** every reference to any result column from subquery in a join, even ** though they are not necessary. This will stress-test the OP_IfNullRow ** opcode. */ - isLeftJoin = -1; + isOuterJoin = -1; } #endif + assert( pSubSrc->nSrc>0 ); /* True by restriction (7) */ + if( iFrom>0 && (pSubSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){ + return 0; /* Restriction (27a) */ + } + if( pSubitem->fg.isCte && pSubitem->u2.pCteUse->eM10d==M10d_Yes ){ + return 0; /* (28) */ + } + + /* Restriction (29): + ** + ** We do not want two constraints on the same term of the flattened + ** query where one constraint has EP_InnerON and the other is EP_OuterON. + ** To prevent this, one or the other of the following conditions must be + ** false: + ** + ** (29a) The right-most entry in the FROM clause of the subquery + ** must not be part of an outer join. + ** + ** (29b) The subquery itself must not be the right operand of a + ** NATURAL join or a join that as an ON or USING clause. + ** + ** These conditions are sufficient to keep an EP_OuterON from being + ** flattened into an EP_InnerON. Restrictions (3a) and (27a) prevent + ** an EP_InnerON from being flattened into an EP_OuterON. + */ + if( pSubSrc->nSrc>=2 + && (pSubSrc->a[pSubSrc->nSrc-1].fg.jointype & JT_OUTER)!=0 + ){ + if( (pSubitem->fg.jointype & JT_NATURAL)!=0 + || pSubitem->fg.isUsing + || NEVER(pSubitem->u3.pOn!=0) /* ON clause already shifted into WHERE */ + || pSubitem->fg.isOn + ){ + return 0; + } + } + /* Restriction (17): If the sub-query is a compound SELECT, then it must ** use only the UNION ALL operator. And none of the simple select queries ** that make up the compound SELECT are allowed to be aggregate or distinct @@ -137374,7 +139955,7 @@ static int flattenSubquery( if( pSub->pOrderBy ){ return 0; /* Restriction (20) */ } - if( isAgg || (p->selFlags & SF_Distinct)!=0 || isLeftJoin>0 ){ + if( isAgg || (p->selFlags & SF_Distinct)!=0 || isOuterJoin>0 ){ return 0; /* (17d1), (17d2), or (17f) */ } for(pSub1=pSub; pSub1; pSub1=pSub1->pPrior){ @@ -137392,6 +139973,12 @@ static int flattenSubquery( ){ return 0; } + if( iFrom>0 && (pSub1->pSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){ + /* Without this restriction, the JT_LTORJ flag would end up being + ** omitted on left-hand tables of the right join that is being + ** flattened. */ + return 0; /* Restrictions (17g), (27b) */ + } testcase( pSub1->pSrc->nSrc>1 ); } @@ -137408,6 +139995,7 @@ static int flattenSubquery( if( pSrc->nSrc>1 ){ if( pParse->nSelect>500 ) return 0; + if( OptimizationDisabled(db, SQLITE_FlttnUnionAll) ) return 0; aCsrMap = sqlite3DbMallocZero(db, ((i64)pParse->nTab+1)*sizeof(int)); if( aCsrMap ) aCsrMap[0] = pParse->nTab; } @@ -137432,7 +140020,7 @@ static int flattenSubquery( pSubitem->zName = 0; pSubitem->zAlias = 0; pSubitem->pSelect = 0; - assert( pSubitem->pOn==0 ); + assert( pSubitem->fg.isUsing!=0 || pSubitem->u3.pOn==0 ); /* If the sub-query is a compound SELECT statement, then (by restrictions ** 17 and 18 above) it must be a UNION ALL and the parent query must @@ -137542,6 +140130,7 @@ static int flattenSubquery( for(pParent=p; pParent; pParent=pParent->pPrior, pSub=pSub->pPrior){ int nSubSrc; u8 jointype = 0; + u8 ltorj = pSrc->a[iFrom].fg.jointype & JT_LTORJ; assert( pSub!=0 ); pSubSrc = pSub->pSrc; /* FROM clause of subquery */ nSubSrc = pSubSrc->nSrc; /* Number of terms in subquery FROM clause */ @@ -137576,13 +140165,16 @@ static int flattenSubquery( ** outer query. */ for(i=0; ia[i+iFrom].pUsing); - assert( pSrc->a[i+iFrom].fg.isTabFunc==0 ); - pSrc->a[i+iFrom] = pSubSrc->a[i]; + SrcItem *pItem = &pSrc->a[i+iFrom]; + if( pItem->fg.isUsing ) sqlite3IdListDelete(db, pItem->u3.pUsing); + assert( pItem->fg.isTabFunc==0 ); + *pItem = pSubSrc->a[i]; + pItem->fg.jointype |= ltorj; iNewParent = pSubSrc->a[i].iCursor; memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i])); } - pSrc->a[iFrom].fg.jointype = jointype; + pSrc->a[iFrom].fg.jointype &= JT_LTORJ; + pSrc->a[iFrom].fg.jointype |= jointype | ltorj; /* Now begin substituting subquery result set expressions for ** references to the iParent in the outer query. @@ -137617,8 +140209,8 @@ static int flattenSubquery( } pWhere = pSub->pWhere; pSub->pWhere = 0; - if( isLeftJoin>0 ){ - sqlite3SetJoinExpr(pWhere, iNewParent); + if( isOuterJoin>0 ){ + sqlite3SetJoinExpr(pWhere, iNewParent, EP_OuterON); } if( pWhere ){ if( pParent->pWhere ){ @@ -137632,7 +140224,7 @@ static int flattenSubquery( x.pParse = pParse; x.iTable = iParent; x.iNewTable = iNewParent; - x.isLeftJoin = isLeftJoin; + x.isOuterJoin = isOuterJoin; x.pEList = pSub->pEList; substSelect(&x, pParent, 0); } @@ -137667,8 +140259,8 @@ static int flattenSubquery( sqlite3WalkSelect(&w,pSub1); sqlite3SelectDelete(db, pSub1); -#if SELECTTRACE_ENABLED - if( sqlite3SelectTrace & 0x100 ){ +#if TREETRACE_ENABLED + if( sqlite3TreeTrace & 0x100 ){ SELECTTRACE(0x100,pParse,p,("After flattening:\n")); sqlite3TreeViewSelect(0, p, 0); } @@ -137689,6 +140281,8 @@ struct WhereConst { int nConst; /* Number for COLUMN=CONSTANT terms */ int nChng; /* Number of times a constant is propagated */ int bHasAffBlob; /* At least one column in apExpr[] as affinity BLOB */ + u32 mExcludeOn; /* Which ON expressions to exclude from considertion. + ** Either EP_OuterON or EP_InnerON|EP_OuterON */ Expr **apExpr; /* [i*2] is COLUMN and [i*2+1] is VALUE */ }; @@ -137751,7 +140345,11 @@ static void constInsert( static void findConstInWhere(WhereConst *pConst, Expr *pExpr){ Expr *pRight, *pLeft; if( NEVER(pExpr==0) ) return; - if( ExprHasProperty(pExpr, EP_FromJoin) ) return; + if( ExprHasProperty(pExpr, pConst->mExcludeOn) ){ + testcase( ExprHasProperty(pExpr, EP_OuterON) ); + testcase( ExprHasProperty(pExpr, EP_InnerON) ); + return; + } if( pExpr->op==TK_AND ){ findConstInWhere(pConst, pExpr->pRight); findConstInWhere(pConst, pExpr->pLeft); @@ -137787,9 +140385,10 @@ static int propagateConstantExprRewriteOne( int i; if( pConst->pOomFault[0] ) return WRC_Prune; if( pExpr->op!=TK_COLUMN ) return WRC_Continue; - if( ExprHasProperty(pExpr, EP_FixedCol|EP_FromJoin) ){ + if( ExprHasProperty(pExpr, EP_FixedCol|pConst->mExcludeOn) ){ testcase( ExprHasProperty(pExpr, EP_FixedCol) ); - testcase( ExprHasProperty(pExpr, EP_FromJoin) ); + testcase( ExprHasProperty(pExpr, EP_OuterON) ); + testcase( ExprHasProperty(pExpr, EP_InnerON) ); return WRC_Continue; } for(i=0; inConst; i++){ @@ -137913,6 +140512,17 @@ static int propagateConstants( x.nChng = 0; x.apExpr = 0; x.bHasAffBlob = 0; + if( ALWAYS(p->pSrc!=0) + && p->pSrc->nSrc>0 + && (p->pSrc->a[0].fg.jointype & JT_LTORJ)!=0 + ){ + /* Do not propagate constants on any ON clause if there is a + ** RIGHT JOIN anywhere in the query */ + x.mExcludeOn = EP_InnerON | EP_OuterON; + }else{ + /* Do not propagate constants through the ON clause of a LEFT JOIN */ + x.mExcludeOn = EP_OuterON; + } findConstInWhere(&x, p->pWhere); if( x.nConst ){ memset(&w, 0, sizeof(w)); @@ -138032,13 +140642,13 @@ static int pushDownWhereTerms( Parse *pParse, /* Parse context (for malloc() and error reporting) */ Select *pSubq, /* The subquery whose WHERE clause is to be augmented */ Expr *pWhere, /* The WHERE clause of the outer query */ - int iCursor, /* Cursor number of the subquery */ - int isLeftJoin /* True if pSubq is the right term of a LEFT JOIN */ + SrcItem *pSrc /* The subquery term of the outer FROM clause */ ){ Expr *pNew; int nChng = 0; if( pWhere==0 ) return 0; if( pSubq->selFlags & (SF_Recursive|SF_MultiPart) ) return 0; + if( pSrc->fg.jointype & (JT_LTORJ|JT_RIGHT) ) return 0; #ifndef SQLITE_OMIT_WINDOWFUNC if( pSubq->pPrior ){ @@ -138068,30 +140678,35 @@ static int pushDownWhereTerms( return 0; /* restriction (3) */ } while( pWhere->op==TK_AND ){ - nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, - iCursor, isLeftJoin); + nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, pSrc); pWhere = pWhere->pLeft; } + +#if 0 /* Legacy code. Checks now done by sqlite3ExprIsTableConstraint() */ if( isLeftJoin - && (ExprHasProperty(pWhere,EP_FromJoin)==0 - || pWhere->iRightJoinTable!=iCursor) + && (ExprHasProperty(pWhere,EP_OuterON)==0 + || pWhere->w.iJoin!=iCursor) ){ return 0; /* restriction (4) */ } - if( ExprHasProperty(pWhere,EP_FromJoin) && pWhere->iRightJoinTable!=iCursor ){ + if( ExprHasProperty(pWhere,EP_OuterON) + && pWhere->w.iJoin!=iCursor + ){ return 0; /* restriction (5) */ } - if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){ +#endif + + if( sqlite3ExprIsTableConstraint(pWhere, pSrc) ){ nChng++; pSubq->selFlags |= SF_PushDown; while( pSubq ){ SubstContext x; pNew = sqlite3ExprDup(pParse->db, pWhere, 0); - unsetJoinExpr(pNew, -1); + unsetJoinExpr(pNew, -1, 1); x.pParse = pParse; - x.iTable = iCursor; - x.iNewTable = iCursor; - x.isLeftJoin = 0; + x.iTable = pSrc->iCursor; + x.iNewTable = pSrc->iCursor; + x.isOuterJoin = 0; x.pEList = pSubq->pEList; pNew = substExpr(&x, pNew); #ifndef SQLITE_OMIT_WINDOWFUNC @@ -138164,7 +140779,7 @@ static u8 minMaxQuery(sqlite3 *db, Expr *pFunc, ExprList **ppMinMax){ } *ppMinMax = pOrderBy = sqlite3ExprListDup(db, pEList, 0); assert( pOrderBy!=0 || db->mallocFailed ); - if( pOrderBy ) pOrderBy->a[0].sortFlags = sortFlags; + if( pOrderBy ) pOrderBy->a[0].fg.sortFlags = sortFlags; return eRet; } @@ -138196,6 +140811,7 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){ || p->pSrc->nSrc!=1 || p->pSrc->a[0].pSelect || pAggInfo->nFunc!=1 + || p->pHaving ){ return 0; } @@ -138300,7 +140916,7 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){ pNew = sqlite3DbMallocZero(db, sizeof(*pNew) ); if( pNew==0 ) return WRC_Abort; memset(&dummy, 0, sizeof(dummy)); - pNewSrc = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&dummy,pNew,0,0); + pNewSrc = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&dummy,pNew,0); if( pNewSrc==0 ) return WRC_Abort; *pNew = *p; p->pSrc = pNewSrc; @@ -138633,7 +141249,7 @@ SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse *pParse, SrcItem *pFrom){ if( pFrom->zAlias ){ pTab->zName = sqlite3DbStrDup(pParse->db, pFrom->zAlias); }else{ - pTab->zName = sqlite3MPrintf(pParse->db, "subquery_%u", pSel->selId); + pTab->zName = sqlite3MPrintf(pParse->db, "%!S", pFrom); } while( pSel->pPrior ){ pSel = pSel->pPrior; } sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol); @@ -138645,11 +141261,35 @@ SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse *pParse, SrcItem *pFrom){ #else pTab->tabFlags |= TF_Ephemeral; /* Legacy compatibility mode */ #endif + return pParse->nErr ? SQLITE_ERROR : SQLITE_OK; +} - return pParse->nErr ? SQLITE_ERROR : SQLITE_OK; +/* +** Check the N SrcItem objects to the right of pBase. (N might be zero!) +** If any of those SrcItem objects have a USING clause containing zName +** then return true. +** +** If N is zero, or none of the N SrcItem objects to the right of pBase +** contains a USING clause, or if none of the USING clauses contain zName, +** then return false. +*/ +static int inAnyUsingClause( + const char *zName, /* Name we are looking for */ + SrcItem *pBase, /* The base SrcItem. Looking at pBase[1] and following */ + int N /* How many SrcItems to check */ +){ + while( N>0 ){ + N--; + pBase++; + if( pBase->fg.isUsing==0 ) continue; + if( NEVER(pBase->u3.pUsing==0) ) continue; + if( sqlite3IdListIndex(pBase->u3.pUsing, zName)>=0 ) return 1; + } + return 0; } + /* ** This routine is a Walker callback for "expanding" a SELECT statement. ** "Expanding" means to do the following: @@ -138798,7 +141438,8 @@ static int selectExpander(Walker *pWalker, Select *p){ /* Process NATURAL keywords, and ON and USING clauses of joins. */ - if( pParse->nErr || db->mallocFailed || sqliteProcessJoin(pParse, p) ){ + assert( db->mallocFailed==0 || pParse->nErr!=0 ); + if( pParse->nErr || sqlite3ProcessJoin(pParse, p) ){ return WRC_Abort; } @@ -138846,7 +141487,7 @@ static int selectExpander(Walker *pWalker, Select *p){ pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr); if( pNew ){ pNew->a[pNew->nExpr-1].zEName = a[k].zEName; - pNew->a[pNew->nExpr-1].eEName = a[k].eEName; + pNew->a[pNew->nExpr-1].fg.eEName = a[k].fg.eEName; a[k].zEName = 0; } a[k].pExpr = 0; @@ -138861,32 +141502,60 @@ static int selectExpander(Walker *pWalker, Select *p){ zTName = pE->pLeft->u.zToken; } for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){ - Table *pTab = pFrom->pTab; - Select *pSub = pFrom->pSelect; - char *zTabName = pFrom->zAlias; - const char *zSchemaName = 0; - int iDb; - if( zTabName==0 ){ + Table *pTab = pFrom->pTab; /* Table for this data source */ + ExprList *pNestedFrom; /* Result-set of a nested FROM clause */ + char *zTabName; /* AS name for this data source */ + const char *zSchemaName = 0; /* Schema name for this data source */ + int iDb; /* Schema index for this data src */ + IdList *pUsing; /* USING clause for pFrom[1] */ + + if( (zTabName = pFrom->zAlias)==0 ){ zTabName = pTab->zName; } if( db->mallocFailed ) break; - if( pSub==0 || (pSub->selFlags & SF_NestedFrom)==0 ){ - pSub = 0; + assert( (int)pFrom->fg.isNestedFrom == IsNestedFrom(pFrom->pSelect) ); + if( pFrom->fg.isNestedFrom ){ + assert( pFrom->pSelect!=0 ); + pNestedFrom = pFrom->pSelect->pEList; + assert( pNestedFrom!=0 ); + assert( pNestedFrom->nExpr==pTab->nCol ); + }else{ if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){ continue; } + pNestedFrom = 0; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); zSchemaName = iDb>=0 ? db->aDb[iDb].zDbSName : "*"; } + if( i+1nSrc + && pFrom[1].fg.isUsing + && (selFlags & SF_NestedFrom)!=0 + ){ + int ii; + pUsing = pFrom[1].u3.pUsing; + for(ii=0; iinId; ii++){ + const char *zUName = pUsing->a[ii].zName; + pRight = sqlite3Expr(db, TK_ID, zUName); + pNew = sqlite3ExprListAppend(pParse, pNew, pRight); + if( pNew ){ + struct ExprList_item *pX = &pNew->a[pNew->nExpr-1]; + assert( pX->zEName==0 ); + pX->zEName = sqlite3MPrintf(db,"..%s", zUName); + pX->fg.eEName = ENAME_TAB; + pX->fg.bUsingTerm = 1; + } + } + }else{ + pUsing = 0; + } for(j=0; jnCol; j++){ char *zName = pTab->aCol[j].zCnName; - char *zColname; /* The computed column name */ - char *zToFree; /* Malloced string that needs to be freed */ - Token sColname; /* Computed column name as a token */ + struct ExprList_item *pX; /* Newly added ExprList term */ assert( zName ); - if( zTName && pSub - && sqlite3MatchEName(&pSub->pEList->a[j], 0, zTName, 0)==0 + if( zTName + && pNestedFrom + && sqlite3MatchEName(&pNestedFrom->a[j], 0, zTName, 0)==0 ){ continue; } @@ -138900,57 +141569,75 @@ static int selectExpander(Walker *pWalker, Select *p){ ){ continue; } + if( (pTab->aCol[j].colFlags & COLFLAG_NOEXPAND)!=0 + && zTName==0 + && (selFlags & (SF_NestedFrom))==0 + ){ + continue; + } tableSeen = 1; - if( i>0 && zTName==0 ){ - if( (pFrom->fg.jointype & JT_NATURAL)!=0 - && tableAndColumnIndex(pTabList, i, zName, 0, 0, 1) + if( i>0 && zTName==0 && (selFlags & SF_NestedFrom)==0 ){ + if( pFrom->fg.isUsing + && sqlite3IdListIndex(pFrom->u3.pUsing, zName)>=0 ){ - /* In a NATURAL join, omit the join columns from the - ** table to the right of the join */ - continue; - } - if( sqlite3IdListIndex(pFrom->pUsing, zName)>=0 ){ /* In a join with a USING clause, omit columns in the ** using clause from the table on the right. */ continue; } } pRight = sqlite3Expr(db, TK_ID, zName); - zColname = zName; - zToFree = 0; - if( longNames || pTabList->nSrc>1 ){ + if( (pTabList->nSrc>1 + && ( (pFrom->fg.jointype & JT_LTORJ)==0 + || (selFlags & SF_NestedFrom)!=0 + || !inAnyUsingClause(zName,pFrom,pTabList->nSrc-i-1) + ) + ) + || IN_RENAME_OBJECT + ){ Expr *pLeft; pLeft = sqlite3Expr(db, TK_ID, zTabName); pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight); + if( IN_RENAME_OBJECT && pE->pLeft ){ + sqlite3RenameTokenRemap(pParse, pLeft, pE->pLeft); + } if( zSchemaName ){ pLeft = sqlite3Expr(db, TK_ID, zSchemaName); pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pExpr); } - if( longNames ){ - zColname = sqlite3MPrintf(db, "%s.%s", zTabName, zName); - zToFree = zColname; - } }else{ pExpr = pRight; } pNew = sqlite3ExprListAppend(pParse, pNew, pExpr); - sqlite3TokenInit(&sColname, zColname); - sqlite3ExprListSetName(pParse, pNew, &sColname, 0); - if( pNew && (p->selFlags & SF_NestedFrom)!=0 && !IN_RENAME_OBJECT ){ - struct ExprList_item *pX = &pNew->a[pNew->nExpr-1]; - sqlite3DbFree(db, pX->zEName); - if( pSub ){ - pX->zEName = sqlite3DbStrDup(db, pSub->pEList->a[j].zEName); + if( pNew==0 ){ + break; /* OOM */ + } + pX = &pNew->a[pNew->nExpr-1]; + assert( pX->zEName==0 ); + if( (selFlags & SF_NestedFrom)!=0 && !IN_RENAME_OBJECT ){ + if( pNestedFrom ){ + pX->zEName = sqlite3DbStrDup(db, pNestedFrom->a[j].zEName); testcase( pX->zEName==0 ); }else{ pX->zEName = sqlite3MPrintf(db, "%s.%s.%s", - zSchemaName, zTabName, zColname); + zSchemaName, zTabName, zName); testcase( pX->zEName==0 ); } - pX->eEName = ENAME_TAB; + pX->fg.eEName = ENAME_TAB; + if( (pFrom->fg.isUsing + && sqlite3IdListIndex(pFrom->u3.pUsing, zName)>=0) + || (pUsing && sqlite3IdListIndex(pUsing, zName)>=0) + || (pTab->aCol[j].colFlags & COLFLAG_NOEXPAND)!=0 + ){ + pX->fg.bNoExpand = 1; + } + }else if( longNames ){ + pX->zEName = sqlite3MPrintf(db, "%s.%s", zTabName, zName); + pX->fg.eEName = ENAME_NAME; + }else{ + pX->zEName = sqlite3DbStrDup(db, zName); + pX->fg.eEName = ENAME_NAME; } - sqlite3DbFree(db, zToFree); } } if( !tableSeen ){ @@ -138974,6 +141661,12 @@ static int selectExpander(Walker *pWalker, Select *p){ p->selFlags |= SF_ComplexResult; } } +#if TREETRACE_ENABLED + if( sqlite3TreeTrace & 0x100 ){ + SELECTTRACE(0x100,pParse,p,("After result-set wildcard expansion:\n")); + sqlite3TreeViewSelect(0, p, 0); + } +#endif return WRC_Continue; } @@ -139095,12 +141788,13 @@ SQLITE_PRIVATE void sqlite3SelectPrep( NameContext *pOuterNC /* Name context for container */ ){ assert( p!=0 || pParse->db->mallocFailed ); + assert( pParse->db->pParse==pParse ); if( pParse->db->mallocFailed ) return; if( p->selFlags & SF_HasTypeInfo ) return; sqlite3SelectExpand(pParse, p); - if( pParse->nErr || pParse->db->mallocFailed ) return; + if( pParse->nErr ) return; sqlite3ResolveSelectNames(pParse, p, pOuterNC); - if( pParse->nErr || pParse->db->mallocFailed ) return; + if( pParse->nErr ) return; sqlite3SelectAddTypeInfo(pParse, p); } @@ -139117,8 +141811,10 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){ int i; struct AggInfo_func *pFunc; int nReg = pAggInfo->nFunc + pAggInfo->nColumn; + assert( pParse->db->pParse==pParse ); + assert( pParse->db->mallocFailed==0 || pParse->nErr!=0 ); if( nReg==0 ) return; - if( pParse->nErr || pParse->db->mallocFailed ) return; + if( pParse->nErr ) return; #ifdef SQLITE_DEBUG /* Verify that all AggInfo registers are within the range specified by ** AggInfo.mnReg..AggInfo.mxReg */ @@ -139361,8 +142057,8 @@ static void havingToWhere(Parse *pParse, Select *p){ sWalker.xExprCallback = havingToWhereExprCb; sWalker.u.pSelect = p; sqlite3WalkExpr(&sWalker, p->pHaving); -#if SELECTTRACE_ENABLED - if( sWalker.eCode && (sqlite3SelectTrace & 0x100)!=0 ){ +#if TREETRACE_ENABLED + if( sWalker.eCode && (sqlite3TreeTrace & 0x100)!=0 ){ SELECTTRACE(0x100,pParse,p,("Move HAVING terms into WHERE:\n")); sqlite3TreeViewSelect(0, p, 0); } @@ -139494,8 +142190,8 @@ static int countOfViewOptimization(Parse *pParse, Select *p){ p->pEList->a[0].pExpr = pExpr; p->selFlags &= ~SF_Aggregate; -#if SELECTTRACE_ENABLED - if( sqlite3SelectTrace & 0x400 ){ +#if TREETRACE_ENABLED + if( sqlite3TreeTrace & 0x400 ){ SELECTTRACE(0x400,pParse,p,("After count-of-view optimization:\n")); sqlite3TreeViewSelect(0, p, 0); } @@ -139504,6 +142200,29 @@ static int countOfViewOptimization(Parse *pParse, Select *p){ } #endif /* SQLITE_COUNTOFVIEW_OPTIMIZATION */ +/* +** If any term of pSrc, or any SF_NestedFrom sub-query, is not the same +** as pSrcItem but has the same alias as p0, then return true. +** Otherwise return false. +*/ +static int sameSrcAlias(SrcItem *p0, SrcList *pSrc){ + int i; + for(i=0; inSrc; i++){ + SrcItem *p1 = &pSrc->a[i]; + if( p1==p0 ) continue; + if( p0->pTab==p1->pTab && 0==sqlite3_stricmp(p0->zAlias, p1->zAlias) ){ + return 1; + } + if( p1->pSelect + && (p1->pSelect->selFlags & SF_NestedFrom)!=0 + && sameSrcAlias(p0, p1->pSelect->pSrc) + ){ + return 1; + } + } + return 0; +} + /* ** Generate code for the SELECT statement given in the p argument. ** @@ -139541,15 +142260,21 @@ SQLITE_PRIVATE int sqlite3Select( u8 minMaxFlag; /* Flag for min/max queries */ db = pParse->db; + assert( pParse==db->pParse ); v = sqlite3GetVdbe(pParse); - if( p==0 || db->mallocFailed || pParse->nErr ){ + if( p==0 || pParse->nErr ){ return 1; } + assert( db->mallocFailed==0 ); if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1; -#if SELECTTRACE_ENABLED +#if TREETRACE_ENABLED SELECTTRACE(1,pParse,p, ("begin processing:\n", pParse->addrExplain)); - if( sqlite3SelectTrace & 0x100 ){ - sqlite3TreeViewSelect(0, p, 0); + if( sqlite3TreeTrace & 0x10100 ){ + if( (sqlite3TreeTrace & 0x10001)==0x10000 ){ + sqlite3TreeViewLine(0, "In sqlite3Select() at %s:%d", + __FILE__, __LINE__); + } + sqlite3ShowSelect(p); } #endif @@ -139563,9 +142288,9 @@ SQLITE_PRIVATE int sqlite3Select( pDest->eDest==SRT_DistQueue || pDest->eDest==SRT_DistFifo ); /* All of these destinations are also able to ignore the ORDER BY clause */ if( p->pOrderBy ){ -#if SELECTTRACE_ENABLED +#if TREETRACE_ENABLED SELECTTRACE(1,pParse,p, ("dropping superfluous ORDER BY:\n")); - if( sqlite3SelectTrace & 0x100 ){ + if( sqlite3TreeTrace & 0x100 ){ sqlite3TreeViewExprList(0, p->pOrderBy, 0, "ORDERBY"); } #endif @@ -139579,12 +142304,13 @@ SQLITE_PRIVATE int sqlite3Select( p->selFlags |= SF_NoopOrderBy; } sqlite3SelectPrep(pParse, p, 0); - if( pParse->nErr || db->mallocFailed ){ + if( pParse->nErr ){ goto select_end; } + assert( db->mallocFailed==0 ); assert( p->pEList!=0 ); -#if SELECTTRACE_ENABLED - if( sqlite3SelectTrace & 0x104 ){ +#if TREETRACE_ENABLED + if( sqlite3TreeTrace & 0x104 ){ SELECTTRACE(0x104,pParse,p, ("after name resolution:\n")); sqlite3TreeViewSelect(0, p, 0); } @@ -139601,15 +142327,12 @@ SQLITE_PRIVATE int sqlite3Select( ** disallow it altogether. */ if( p->selFlags & SF_UFSrcCheck ){ SrcItem *p0 = &p->pSrc->a[0]; - for(i=1; ipSrc->nSrc; i++){ - SrcItem *p1 = &p->pSrc->a[i]; - if( p0->pTab==p1->pTab && 0==sqlite3_stricmp(p0->zAlias, p1->zAlias) ){ - sqlite3ErrorMsg(pParse, - "target object/alias may not appear in FROM clause: %s", - p0->zAlias ? p0->zAlias : p0->pTab->zName - ); - goto select_end; - } + if( sameSrcAlias(p0, p->pSrc) ){ + sqlite3ErrorMsg(pParse, + "target object/alias may not appear in FROM clause: %s", + p0->zAlias ? p0->zAlias : p0->pTab->zName + ); + goto select_end; } /* Clear the SF_UFSrcCheck flag. The check has already been performed, @@ -139625,11 +142348,11 @@ SQLITE_PRIVATE int sqlite3Select( #ifndef SQLITE_OMIT_WINDOWFUNC if( sqlite3WindowRewrite(pParse, p) ){ - assert( db->mallocFailed || pParse->nErr>0 ); + assert( pParse->nErr ); goto select_end; } -#if SELECTTRACE_ENABLED - if( p->pWin && (sqlite3SelectTrace & 0x108)!=0 ){ +#if TREETRACE_ENABLED + if( p->pWin && (sqlite3TreeTrace & 0x108)!=0 ){ SELECTTRACE(0x104,pParse,p, ("after window rewrite:\n")); sqlite3TreeViewSelect(0, p, 0); } @@ -139657,14 +142380,16 @@ SQLITE_PRIVATE int sqlite3Select( /* Convert LEFT JOIN into JOIN if there are terms of the right table ** of the LEFT JOIN used in the WHERE clause. */ - if( (pItem->fg.jointype & JT_LEFT)!=0 + if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))==JT_LEFT && sqlite3ExprImpliesNonNullRow(p->pWhere, pItem->iCursor) && OptimizationEnabled(db, SQLITE_SimplifyJoin) ){ SELECTTRACE(0x100,pParse,p, ("LEFT-JOIN simplifies to JOIN on term %d\n",i)); pItem->fg.jointype &= ~(JT_LEFT|JT_OUTER); - unsetJoinExpr(p->pWhere, pItem->iCursor); + assert( pItem->iCursor>=0 ); + unsetJoinExpr(p->pWhere, pItem->iCursor, + pTabList->a[0].fg.jointype & JT_LTORJ); } /* No futher action if this term of the FROM clause is no a subquery */ @@ -139717,7 +142442,9 @@ SQLITE_PRIVATE int sqlite3Select( ){ SELECTTRACE(0x100,pParse,p, ("omit superfluous ORDER BY on %r FROM-clause subquery\n",i+1)); - sqlite3ExprListDelete(db, pSub->pOrderBy); + sqlite3ParserAddCleanup(pParse, + (void(*)(sqlite3*,void*))sqlite3ExprListDelete, + pSub->pOrderBy); pSub->pOrderBy = 0; } @@ -139743,7 +142470,7 @@ SQLITE_PRIVATE int sqlite3Select( && i==0 && (p->selFlags & SF_ComplexResult)!=0 && (pTabList->nSrc==1 - || (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0) + || (pTabList->a[1].fg.jointype&(JT_OUTER|JT_CROSS))!=0) ){ continue; } @@ -139767,9 +142494,9 @@ SQLITE_PRIVATE int sqlite3Select( */ if( p->pPrior ){ rc = multiSelect(pParse, p, pDest); -#if SELECTTRACE_ENABLED +#if TREETRACE_ENABLED SELECTTRACE(0x1,pParse,p,("end compound-select processing\n")); - if( (sqlite3SelectTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){ + if( (sqlite3TreeTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){ sqlite3TreeViewSelect(0, p, 0); } #endif @@ -139788,8 +142515,8 @@ SQLITE_PRIVATE int sqlite3Select( && OptimizationEnabled(db, SQLITE_PropagateConst) && propagateConstants(pParse, p) ){ -#if SELECTTRACE_ENABLED - if( sqlite3SelectTrace & 0x100 ){ +#if TREETRACE_ENABLED + if( sqlite3TreeTrace & 0x100 ){ SELECTTRACE(0x100,pParse,p,("After constant propagation:\n")); sqlite3TreeViewSelect(0, p, 0); } @@ -139865,11 +142592,10 @@ SQLITE_PRIVATE int sqlite3Select( if( OptimizationEnabled(db, SQLITE_PushDown) && (pItem->fg.isCte==0 || (pItem->u2.pCteUse->eM10d!=M10d_Yes && pItem->u2.pCteUse->nUse<2)) - && pushDownWhereTerms(pParse, pSub, p->pWhere, pItem->iCursor, - (pItem->fg.jointype & JT_OUTER)!=0) + && pushDownWhereTerms(pParse, pSub, p->pWhere, pItem) ){ -#if SELECTTRACE_ENABLED - if( sqlite3SelectTrace & 0x100 ){ +#if TREETRACE_ENABLED + if( sqlite3TreeTrace & 0x100 ){ SELECTTRACE(0x100,pParse,p, ("After WHERE-clause push-down into subquery %d:\n", pSub->selId)); sqlite3TreeViewSelect(0, p, 0); @@ -139885,18 +142611,19 @@ SQLITE_PRIVATE int sqlite3Select( /* Generate code to implement the subquery ** - ** The subquery is implemented as a co-routine if: + ** The subquery is implemented as a co-routine if all of the following are + ** true: + ** ** (1) the subquery is guaranteed to be the outer loop (so that ** it does not need to be computed more than once), and ** (2) the subquery is not a CTE that should be materialized - ** - ** TODO: Are there other reasons beside (1) and (2) to use a co-routine - ** implementation? + ** (3) the subquery is not part of a left operand for a RIGHT JOIN */ if( i==0 && (pTabList->nSrc==1 - || (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0) /* (1) */ - && (pItem->fg.isCte==0 || pItem->u2.pCteUse->eM10d!=M10d_Yes) /* (2) */ + || (pTabList->a[1].fg.jointype&(JT_OUTER|JT_CROSS))!=0) /* (1) */ + && (pItem->fg.isCte==0 || pItem->u2.pCteUse->eM10d!=M10d_Yes) /* (2) */ + && (pTabList->a[0].fg.jointype & JT_LTORJ)==0 /* (3) */ ){ /* Implement a co-routine that will return a single row of the result ** set on each invocation. @@ -139942,11 +142669,11 @@ SQLITE_PRIVATE int sqlite3Select( ** the same view can reuse the materialization. */ int topAddr; int onceAddr = 0; - int retAddr; pItem->regReturn = ++pParse->nMem; - topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn); + topAddr = sqlite3VdbeAddOp0(v, OP_Goto); pItem->addrFillSub = topAddr+1; + pItem->fg.isMaterialized = 1; if( pItem->fg.isCorrelated==0 ){ /* If the subquery is not correlated and if we are not inside of ** a trigger, then we only need to compute the value of the subquery @@ -139961,9 +142688,9 @@ SQLITE_PRIVATE int sqlite3Select( sqlite3Select(pParse, pSub, &dest); pItem->pTab->nRowLogEst = pSub->nSelectRow; if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr); - retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn); + sqlite3VdbeAddOp2(v, OP_Return, pItem->regReturn, topAddr+1); VdbeComment((v, "end %!S", pItem)); - sqlite3VdbeChangeP1(v, topAddr, retAddr); + sqlite3VdbeJumpHere(v, topAddr); sqlite3ClearTempRegCache(pParse); if( pItem->fg.isCte && pItem->fg.isCorrelated==0 ){ CteUse *pCteUse = pItem->u2.pCteUse; @@ -139987,8 +142714,8 @@ SQLITE_PRIVATE int sqlite3Select( pHaving = p->pHaving; sDistinct.isTnct = (p->selFlags & SF_Distinct)!=0; -#if SELECTTRACE_ENABLED - if( sqlite3SelectTrace & 0x400 ){ +#if TREETRACE_ENABLED + if( sqlite3TreeTrace & 0x400 ){ SELECTTRACE(0x400,pParse,p,("After all FROM-clause analysis:\n")); sqlite3TreeViewSelect(0, p, 0); } @@ -140022,9 +142749,10 @@ SQLITE_PRIVATE int sqlite3Select( ** the sDistinct.isTnct is still set. Hence, isTnct represents the ** original setting of the SF_Distinct flag, not the current setting */ assert( sDistinct.isTnct ); + sDistinct.isTnct = 2; -#if SELECTTRACE_ENABLED - if( sqlite3SelectTrace & 0x400 ){ +#if TREETRACE_ENABLED + if( sqlite3TreeTrace & 0x400 ){ SELECTTRACE(0x400,pParse,p,("Transform DISTINCT into GROUP BY:\n")); sqlite3TreeViewSelect(0, p, 0); } @@ -140057,6 +142785,18 @@ SQLITE_PRIVATE int sqlite3Select( */ if( pDest->eDest==SRT_EphemTab ){ sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pDest->iSDParm, pEList->nExpr); + if( p->selFlags & SF_NestedFrom ){ + /* Delete or NULL-out result columns that will never be used */ + int ii; + for(ii=pEList->nExpr-1; ii>0 && pEList->a[ii].fg.bUsed==0; ii--){ + sqlite3ExprDelete(db, pEList->a[ii].pExpr); + sqlite3DbFree(db, pEList->a[ii].zEName); + pEList->nExpr--; + } + for(ii=0; iinExpr; ii++){ + if( pEList->a[ii].fg.bUsed==0 ) pEList->a[ii].pExpr->op = TK_NULL; + } + } } /* Set the limiter. @@ -140101,7 +142841,7 @@ SQLITE_PRIVATE int sqlite3Select( /* Begin the database scan. */ SELECTTRACE(1,pParse,p,("WhereBegin\n")); pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, sSort.pOrderBy, - p->pEList, wctrlFlags, p->nSelectRow); + p->pEList, p, wctrlFlags, p->nSelectRow); if( pWInfo==0 ) goto select_end; if( sqlite3WhereOutputRowCount(pWInfo) < p->nSelectRow ){ p->nSelectRow = sqlite3WhereOutputRowCount(pWInfo); @@ -140206,8 +142946,9 @@ SQLITE_PRIVATE int sqlite3Select( ** ORDER BY to maximize the chances of rows being delivered in an ** order that makes the ORDER BY redundant. */ for(ii=0; iinExpr; ii++){ - u8 sortFlags = sSort.pOrderBy->a[ii].sortFlags & KEYINFO_ORDER_DESC; - pGroupBy->a[ii].sortFlags = sortFlags; + u8 sortFlags; + sortFlags = sSort.pOrderBy->a[ii].fg.sortFlags & KEYINFO_ORDER_DESC; + pGroupBy->a[ii].fg.sortFlags = sortFlags; } if( sqlite3ExprListCompare(pGroupBy, sSort.pOrderBy, -1)==0 ){ orderByGrp = 1; @@ -140276,8 +143017,8 @@ SQLITE_PRIVATE int sqlite3Select( } pAggInfo->mxReg = pParse->nMem; if( db->mallocFailed ) goto select_end; -#if SELECTTRACE_ENABLED - if( sqlite3SelectTrace & 0x400 ){ +#if TREETRACE_ENABLED + if( sqlite3TreeTrace & 0x400 ){ int ii; SELECTTRACE(0x400,pParse,p,("After aggregate analysis %p:\n", pAggInfo)); sqlite3TreeViewSelect(0, p, 0); @@ -140365,7 +143106,8 @@ SQLITE_PRIVATE int sqlite3Select( sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset); SELECTTRACE(1,pParse,p,("WhereBegin\n")); pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, pDistinct, - WHERE_GROUPBY | (orderByGrp ? WHERE_SORTBYGROUP : 0) | distFlag, 0 + 0, (sDistinct.isTnct==2 ? WHERE_DISTINCTBY : WHERE_GROUPBY) + | (orderByGrp ? WHERE_SORTBYGROUP : 0) | distFlag, 0 ); if( pWInfo==0 ){ sqlite3ExprListDelete(db, pDistinct); @@ -140547,7 +143289,7 @@ SQLITE_PRIVATE int sqlite3Select( VdbeComment((v, "indicate accumulator empty")); sqlite3VdbeAddOp1(v, OP_Return, regReset); - if( eDist!=WHERE_DISTINCT_NOOP ){ + if( distFlag!=0 && eDist!=WHERE_DISTINCT_NOOP ){ struct AggInfo_func *pF = &pAggInfo->aFunc[0]; fixDistinctOpenEph(pParse, eDist, pF->iDistinct, pF->iDistAddr); } @@ -140663,7 +143405,7 @@ SQLITE_PRIVATE int sqlite3Select( SELECTTRACE(1,pParse,p,("WhereBegin\n")); pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMaxOrderBy, - pDistinct, minMaxFlag|distFlag, 0); + pDistinct, 0, minMaxFlag|distFlag, 0); if( pWInfo==0 ){ goto select_end; } @@ -140671,8 +143413,10 @@ SQLITE_PRIVATE int sqlite3Select( eDist = sqlite3WhereIsDistinct(pWInfo); updateAccumulator(pParse, regAcc, pAggInfo, eDist); if( eDist!=WHERE_DISTINCT_NOOP ){ - struct AggInfo_func *pF = &pAggInfo->aFunc[0]; - fixDistinctOpenEph(pParse, eDist, pF->iDistinct, pF->iDistAddr); + struct AggInfo_func *pF = pAggInfo->aFunc; + if( pF ){ + fixDistinctOpenEph(pParse, eDist, pF->iDistinct, pF->iDistAddr); + } } if( regAcc ) sqlite3VdbeAddOp2(v, OP_Integer, 1, regAcc); @@ -140720,7 +143464,7 @@ SQLITE_PRIVATE int sqlite3Select( */ select_end: assert( db->mallocFailed==0 || db->mallocFailed==1 ); - pParse->nErr += db->mallocFailed; + assert( db->mallocFailed==0 || pParse->nErr!=0 ); sqlite3ExprListDelete(db, pMinMaxOrderBy); #ifdef SQLITE_DEBUG if( pAggInfo && !db->mallocFailed ){ @@ -140739,9 +143483,9 @@ SQLITE_PRIVATE int sqlite3Select( } #endif -#if SELECTTRACE_ENABLED +#if TREETRACE_ENABLED SELECTTRACE(0x1,pParse,p,("end processing\n")); - if( (sqlite3SelectTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){ + if( (sqlite3TreeTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){ sqlite3TreeViewSelect(0, p, 0); } #endif @@ -141006,9 +143750,7 @@ SQLITE_PRIVATE Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){ Trigger *pList; /* List of triggers to return */ HashElem *p; /* Loop variable for TEMP triggers */ - if( pParse->disableTriggers ){ - return 0; - } + assert( pParse->disableTriggers==0 ); pTmpSchema = pParse->db->aDb[1].pSchema; p = sqliteHashFirst(&pTmpSchema->trigHash); pList = pTab->pTrigger; @@ -141021,11 +143763,10 @@ SQLITE_PRIVATE Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){ ){ pTrig->pNext = pList; pList = pTrig; - }else if( pTrig->op==TK_RETURNING + }else if( pTrig->op==TK_RETURNING ){ #ifndef SQLITE_OMIT_VIRTUALTABLE - && pParse->db->pVtabCtx==0 + assert( pParse->db->pVtabCtx==0 ); #endif - ){ assert( pParse->bReturning ); assert( &(pParse->u1.pReturning->retTrig) == pTrig ); pTrig->table = pTab->zName; @@ -141308,6 +144049,23 @@ SQLITE_PRIVATE void sqlite3FinishTrigger( Vdbe *v; char *z; + /* If this is a new CREATE TABLE statement, and if shadow tables + ** are read-only, and the trigger makes a change to a shadow table, + ** then raise an error - do not allow the trigger to be created. */ + if( sqlite3ReadOnlyShadowTables(db) ){ + TriggerStep *pStep; + for(pStep=pTrig->step_list; pStep; pStep=pStep->pNext){ + if( pStep->zTarget!=0 + && sqlite3ShadowTableName(db, pStep->zTarget) + ){ + sqlite3ErrorMsg(pParse, + "trigger \"%s\" may not write to shadow table \"%s\"", + pTrig->zName, pStep->zTarget); + goto triggerfinish_cleanup; + } + } + } + /* Make an entry in the sqlite_schema table */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto triggerfinish_cleanup; @@ -141400,6 +144158,7 @@ static TriggerStep *triggerStepAllocate( sqlite3 *db = pParse->db; TriggerStep *pTriggerStep; + if( pParse->nErr ) return 0; pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n + 1); if( pTriggerStep ){ char *z = (char*)&pTriggerStep[1]; @@ -141470,7 +144229,7 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep( SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep( Parse *pParse, /* Parser */ Token *pTableName, /* Name of the table to be updated */ - SrcList *pFrom, + SrcList *pFrom, /* FROM clause for an UPDATE-FROM, or NULL */ ExprList *pEList, /* The SET clause: list of column and new values */ Expr *pWhere, /* The WHERE clause */ u8 orconf, /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */ @@ -141683,13 +144442,22 @@ static int checkColumnOverlap(IdList *pIdList, ExprList *pEList){ return 0; } +/* +** Return true if any TEMP triggers exist +*/ +static int tempTriggersExist(sqlite3 *db){ + if( NEVER(db->aDb[1].pSchema==0) ) return 0; + if( sqliteHashFirst(&db->aDb[1].pSchema->trigHash)==0 ) return 0; + return 1; +} + /* ** Return a list of all triggers on table pTab if there exists at least ** one trigger that must be fired when an operation of type 'op' is ** performed on the table, and, if that operation is an UPDATE, if at ** least one of the columns in pChanges is being modified. */ -SQLITE_PRIVATE Trigger *sqlite3TriggersExist( +static SQLITE_NOINLINE Trigger *triggersReallyExist( Parse *pParse, /* Parse context */ Table *pTab, /* The table the contains the triggers */ int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */ @@ -141752,6 +144520,22 @@ SQLITE_PRIVATE Trigger *sqlite3TriggersExist( } return (mask ? pList : 0); } +SQLITE_PRIVATE Trigger *sqlite3TriggersExist( + Parse *pParse, /* Parse context */ + Table *pTab, /* The table the contains the triggers */ + int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */ + ExprList *pChanges, /* Columns that change in an UPDATE statement */ + int *pMask /* OUT: Mask of TRIGGER_BEFORE|TRIGGER_AFTER */ +){ + assert( pTab!=0 ); + if( (pTab->pTrigger==0 && !tempTriggersExist(pParse->db)) + || pParse->disableTriggers + ){ + if( pMask ) *pMask = 0; + return 0; + } + return triggersReallyExist(pParse,pTab,op,pChanges,pMask); +} /* ** Convert the pStep->zTarget string into a SrcList and return a pointer @@ -141781,6 +144565,14 @@ SQLITE_PRIVATE SrcList *sqlite3TriggerStepSrc( } if( pStep->pFrom ){ SrcList *pDup = sqlite3SrcListDup(db, pStep->pFrom, 0); + if( pDup && pDup->nSrc>1 && !IN_RENAME_OBJECT ){ + Select *pSubquery; + Token as; + pSubquery = sqlite3SelectNew(pParse,0,pDup,0,0,0,0,SF_NestedFrom,0); + as.n = 0; + as.z = 0; + pDup = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&as,pSubquery,0); + } pSrc = sqlite3SrcListAppendList(pParse, pSrc, pDup); } }else{ @@ -141836,7 +144628,7 @@ static ExprList *sqlite3ExpandReturning( if( !db->mallocFailed ){ struct ExprList_item *pItem = &pNew->a[pNew->nExpr-1]; pItem->zEName = sqlite3DbStrDup(db, pTab->aCol[jj].zCnName); - pItem->eEName = ENAME_NAME; + pItem->fg.eEName = ENAME_NAME; } } }else{ @@ -141845,7 +144637,7 @@ static ExprList *sqlite3ExpandReturning( if( !db->mallocFailed && ALWAYS(pList->a[i].zEName!=0) ){ struct ExprList_item *pItem = &pNew->a[pNew->nExpr-1]; pItem->zEName = sqlite3DbStrDup(db, pList->a[i].zEName); - pItem->eEName = pList->a[i].eEName; + pItem->fg.eEName = pList->a[i].fg.eEName; } } } @@ -141872,6 +144664,7 @@ static void codeReturningTrigger( assert( v!=0 ); assert( pParse->bReturning ); + assert( db->pParse==pParse ); pReturning = pParse->u1.pReturning; assert( pTrigger == &(pReturning->retTrig) ); memset(&sSelect, 0, sizeof(sSelect)); @@ -141882,12 +144675,13 @@ static void codeReturningTrigger( sFrom.a[0].pTab = pTab; sFrom.a[0].iCursor = -1; sqlite3SelectPrep(pParse, &sSelect, 0); - if( db->mallocFailed==0 && pParse->nErr==0 ){ + if( pParse->nErr==0 ){ + assert( db->mallocFailed==0 ); sqlite3GenerateColumnNames(pParse, &sSelect); } sqlite3ExprListDelete(db, sSelect.pEList); pNew = sqlite3ExpandReturning(pParse, pReturning->pReturnEL, pTab); - if( pNew ){ + if( !db->mallocFailed ){ NameContext sNC; memset(&sNC, 0, sizeof(sNC)); if( pReturning->nRetCol==0 ){ @@ -141899,7 +144693,9 @@ static void codeReturningTrigger( sNC.ncFlags = NC_UBaseReg; pParse->eTriggerOp = pTrigger->op; pParse->pTriggerTab = pTab; - if( sqlite3ResolveExprListNames(&sNC, pNew)==SQLITE_OK ){ + if( sqlite3ResolveExprListNames(&sNC, pNew)==SQLITE_OK + && ALWAYS(!db->mallocFailed) + ){ int i; int nCol = pNew->nExpr; int reg = pParse->nMem+1; @@ -141907,16 +144703,20 @@ static void codeReturningTrigger( pReturning->iRetReg = reg; for(i=0; ia[i].pExpr; + assert( pCol!=0 ); /* Due to !db->mallocFailed ~9 lines above */ sqlite3ExprCodeFactorable(pParse, pCol, reg+i); + if( sqlite3ExprAffinity(pCol)==SQLITE_AFF_REAL ){ + sqlite3VdbeAddOp1(v, OP_RealAffinity, reg+i); + } } sqlite3VdbeAddOp3(v, OP_MakeRecord, reg, i, reg+i); sqlite3VdbeAddOp2(v, OP_NewRowid, pReturning->iRetCur, reg+i+1); sqlite3VdbeAddOp3(v, OP_Insert, pReturning->iRetCur, reg+i, reg+i+1); } - sqlite3ExprListDelete(db, pNew); - pParse->eTriggerOp = 0; - pParse->pTriggerTab = 0; } + sqlite3ExprListDelete(db, pNew); + pParse->eTriggerOp = 0; + pParse->pTriggerTab = 0; } @@ -142058,8 +144858,8 @@ static TriggerPrg *codeRowTrigger( Vdbe *v; /* Temporary VM */ NameContext sNC; /* Name context for sub-vdbe */ SubProgram *pProgram = 0; /* Sub-vdbe for trigger program */ - Parse *pSubParse; /* Parse context for sub-vdbe */ int iEndTrigger = 0; /* Label to jump to if WHEN is false */ + Parse sSubParse; /* Parse context for sub-vdbe */ assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) ); assert( pTop->pVdbe ); @@ -142081,19 +144881,17 @@ static TriggerPrg *codeRowTrigger( /* Allocate and populate a new Parse context to use for coding the ** trigger sub-program. */ - pSubParse = sqlite3StackAllocZero(db, sizeof(Parse)); - if( !pSubParse ) return 0; + sqlite3ParseObjectInit(&sSubParse, db); memset(&sNC, 0, sizeof(sNC)); - sNC.pParse = pSubParse; - pSubParse->db = db; - pSubParse->pTriggerTab = pTab; - pSubParse->pToplevel = pTop; - pSubParse->zAuthContext = pTrigger->zName; - pSubParse->eTriggerOp = pTrigger->op; - pSubParse->nQueryLoop = pParse->nQueryLoop; - pSubParse->disableVtab = pParse->disableVtab; - - v = sqlite3GetVdbe(pSubParse); + sNC.pParse = &sSubParse; + sSubParse.pTriggerTab = pTab; + sSubParse.pToplevel = pTop; + sSubParse.zAuthContext = pTrigger->zName; + sSubParse.eTriggerOp = pTrigger->op; + sSubParse.nQueryLoop = pParse->nQueryLoop; + sSubParse.disableVtab = pParse->disableVtab; + + v = sqlite3GetVdbe(&sSubParse); if( v ){ VdbeComment((v, "Start: %s.%s (%s %s%s%s ON %s)", pTrigger->zName, onErrorText(orconf), @@ -142119,14 +144917,14 @@ static TriggerPrg *codeRowTrigger( if( db->mallocFailed==0 && SQLITE_OK==sqlite3ResolveExprNames(&sNC, pWhen) ){ - iEndTrigger = sqlite3VdbeMakeLabel(pSubParse); - sqlite3ExprIfFalse(pSubParse, pWhen, iEndTrigger, SQLITE_JUMPIFNULL); + iEndTrigger = sqlite3VdbeMakeLabel(&sSubParse); + sqlite3ExprIfFalse(&sSubParse, pWhen, iEndTrigger, SQLITE_JUMPIFNULL); } sqlite3ExprDelete(db, pWhen); } /* Code the trigger program into the sub-vdbe. */ - codeTriggerProgram(pSubParse, pTrigger->step_list, orconf); + codeTriggerProgram(&sSubParse, pTrigger->step_list, orconf); /* Insert an OP_Halt at the end of the sub-program. */ if( iEndTrigger ){ @@ -142134,23 +144932,24 @@ static TriggerPrg *codeRowTrigger( } sqlite3VdbeAddOp0(v, OP_Halt); VdbeComment((v, "End: %s.%s", pTrigger->zName, onErrorText(orconf))); + transferParseError(pParse, &sSubParse); - transferParseError(pParse, pSubParse); - if( db->mallocFailed==0 && pParse->nErr==0 ){ + if( pParse->nErr==0 ){ + assert( db->mallocFailed==0 ); pProgram->aOp = sqlite3VdbeTakeOpArray(v, &pProgram->nOp, &pTop->nMaxArg); } - pProgram->nMem = pSubParse->nMem; - pProgram->nCsr = pSubParse->nTab; + pProgram->nMem = sSubParse.nMem; + pProgram->nCsr = sSubParse.nTab; pProgram->token = (void *)pTrigger; - pPrg->aColmask[0] = pSubParse->oldmask; - pPrg->aColmask[1] = pSubParse->newmask; + pPrg->aColmask[0] = sSubParse.oldmask; + pPrg->aColmask[1] = sSubParse.newmask; sqlite3VdbeDelete(v); + }else{ + transferParseError(pParse, &sSubParse); } - assert( !pSubParse->pTriggerPrg && !pSubParse->nMaxArg ); - sqlite3ParserReset(pSubParse); - sqlite3StackFree(db, pSubParse); - + assert( !sSubParse.pTriggerPrg && !sSubParse.nMaxArg ); + sqlite3ParseObjectReset(&sSubParse); return pPrg; } @@ -142183,6 +144982,7 @@ static TriggerPrg *getRowTrigger( /* If an existing TriggerPrg could not be located, create a new one. */ if( !pPrg ){ pPrg = codeRowTrigger(pParse, pTrigger, pTab, orconf); + pParse->db->errByteOffset = -1; } return pPrg; @@ -142205,7 +145005,7 @@ SQLITE_PRIVATE void sqlite3CodeRowTriggerDirect( Vdbe *v = sqlite3GetVdbe(pParse); /* Main VM */ TriggerPrg *pPrg; pPrg = getRowTrigger(pParse, p, pTab, orconf); - assert( pPrg || pParse->nErr || pParse->db->mallocFailed ); + assert( pPrg || pParse->nErr ); /* Code the OP_Program opcode in the parent VDBE. P4 of the OP_Program ** is a pointer to the sub-vdbe containing the trigger program. */ @@ -142723,9 +145523,11 @@ SQLITE_PRIVATE void sqlite3Update( memset(&sContext, 0, sizeof(sContext)); db = pParse->db; - if( pParse->nErr || db->mallocFailed ){ + assert( db->pParse==pParse ); + if( pParse->nErr ){ goto update_cleanup; } + assert( db->mallocFailed==0 ); /* Locate the table which we want to update. */ @@ -142750,6 +145552,14 @@ SQLITE_PRIVATE void sqlite3Update( # define isView 0 #endif +#if TREETRACE_ENABLED + if( sqlite3TreeTrace & 0x10000 ){ + sqlite3TreeViewLine(0, "In sqlite3Update() at %s:%d", __FILE__, __LINE__); + sqlite3TreeViewUpdate(pParse->pWith, pTabList, pChanges, pWhere, + onError, pOrderBy, pLimit, pUpsert, pTrigger); + } +#endif + /* If there was a FROM clause, set nChangeFrom to the number of expressions ** in the change-list. Otherwise, set it to 0. There cannot be a FROM ** clause if this function is being called to generate code for part of @@ -143097,7 +145907,7 @@ SQLITE_PRIVATE void sqlite3Update( if( !pParse->nested && !pTrigger && !hasFK && !chngKey && !bReplace ){ flags |= WHERE_ONEPASS_MULTIROW; } - pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, flags,iIdxCur); + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0,0,0,flags,iIdxCur); if( pWInfo==0 ) goto update_cleanup; /* A one-pass strategy that might update more than one row may not @@ -143394,7 +146204,7 @@ SQLITE_PRIVATE void sqlite3Update( }else{ sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue,regOldRowid); } - VdbeCoverageNeverTaken(v); + VdbeCoverage(v); } /* Do FK constraint checks. */ @@ -143497,9 +146307,7 @@ SQLITE_PRIVATE void sqlite3Update( ** that information. */ if( regRowCount ){ - sqlite3VdbeAddOp2(v, OP_ChngCntRow, regRowCount, 1); - sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", SQLITE_STATIC); + sqlite3CodeChangeCount(v, regRowCount, "rows updated"); } update_cleanup: @@ -143621,7 +146429,9 @@ static void updateVirtualTable( regRowid = ++pParse->nMem; /* Start scanning the virtual table */ - pWInfo = sqlite3WhereBegin(pParse, pSrc,pWhere,0,0,WHERE_ONEPASS_DESIRED,0); + pWInfo = sqlite3WhereBegin( + pParse, pSrc, pWhere, 0, 0, 0, WHERE_ONEPASS_DESIRED, 0 + ); if( pWInfo==0 ) return; /* Populate the argument registers. */ @@ -144400,6 +147210,7 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3RunVacuum( assert( rc==SQLITE_OK ); if( pOut==0 ){ + nRes = sqlite3BtreeGetRequestedReserve(pTemp); rc = sqlite3BtreeSetPageSize(pMain, sqlite3BtreeGetPageSize(pTemp), nRes,1); } @@ -145248,7 +148059,6 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ VtabCtx *pCtx; int rc = SQLITE_OK; Table *pTab; - char *zErr = 0; Parse sParse; int initBusy; @@ -145267,9 +148077,9 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ pTab = pCtx->pTab; assert( IsVirtual(pTab) ); - memset(&sParse, 0, sizeof(sParse)); + sqlite3ParseObjectInit(&sParse, db); sParse.eParseMode = PARSE_MODE_DECLARE_VTAB; - sParse.db = db; + sParse.disableTriggers = 1; /* We should never be able to reach this point while loading the ** schema. Nevertheless, defend against that (turn off db->init.busy) ** in case a bug arises. */ @@ -145277,11 +148087,12 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ initBusy = db->init.busy; db->init.busy = 0; sParse.nQueryLoop = 1; - if( SQLITE_OK==sqlite3RunParser(&sParse, zCreateTable, &zErr) - && sParse.pNewTable - && !db->mallocFailed + if( SQLITE_OK==sqlite3RunParser(&sParse, zCreateTable) + && ALWAYS(sParse.pNewTable!=0) + && ALWAYS(!db->mallocFailed) && IsOrdinaryTable(sParse.pNewTable) ){ + assert( sParse.zErrMsg==0 ); if( !pTab->aCol ){ Table *pNew = sParse.pNewTable; Index *pIdx; @@ -145311,8 +148122,9 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ } pCtx->bDeclared = 1; }else{ - sqlite3ErrorWithMsg(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr); - sqlite3DbFree(db, zErr); + sqlite3ErrorWithMsg(db, SQLITE_ERROR, + (sParse.zErrMsg ? "%s" : 0), sParse.zErrMsg); + sqlite3DbFree(db, sParse.zErrMsg); rc = SQLITE_ERROR; } sParse.eParseMode = PARSE_MODE_NORMAL; @@ -145321,7 +148133,7 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ sqlite3VdbeFinalize(sParse.pVdbe); } sqlite3DeleteTable(db, sParse.pNewTable); - sqlite3ParserReset(&sParse); + sqlite3ParseObjectReset(&sParse); db->init.busy = initBusy; assert( (rc&0xff)==rc ); @@ -145841,6 +148653,28 @@ typedef struct WhereLoopBuilder WhereLoopBuilder; typedef struct WhereScan WhereScan; typedef struct WhereOrCost WhereOrCost; typedef struct WhereOrSet WhereOrSet; +typedef struct WhereMemBlock WhereMemBlock; +typedef struct WhereRightJoin WhereRightJoin; + +/* +** This object is a header on a block of allocated memory that will be +** automatically freed when its WInfo oject is destructed. +*/ +struct WhereMemBlock { + WhereMemBlock *pNext; /* Next block in the chain */ + u64 sz; /* Bytes of space */ +}; + +/* +** Extra information attached to a WhereLevel that is a RIGHT JOIN. +*/ +struct WhereRightJoin { + int iMatch; /* Cursor used to determine prior matched rows */ + int regBloom; /* Bloom filter for iRJMatch */ + int regReturn; /* Return register for the interior subroutine */ + int addrSubrtn; /* Starting address for the interior subroutine */ + int endSubrtn; /* The last opcode in the interior subroutine */ +}; /* ** This object contains information needed to implement a single nested @@ -145873,6 +148707,8 @@ struct WhereLevel { u32 iLikeRepCntr; /* LIKE range processing counter register (times 2) */ int addrLikeRep; /* LIKE range processing address */ #endif + int regFilter; /* Bloom filter */ + WhereRightJoin *pRJ; /* Extra information for RIGHT JOIN */ u8 iFrom; /* Which entry in the FROM clause */ u8 op, p3, p5; /* Opcode, P3 & P5 of the opcode that ends the loop */ int p1, p2; /* Operands of the opcode used to end the loop */ @@ -145931,10 +148767,12 @@ struct WhereLoop { } btree; struct { /* Information for virtual tables */ int idxNum; /* Index number */ - u8 needFree; /* True if sqlite3_free(idxStr) is needed */ + u32 needFree : 1; /* True if sqlite3_free(idxStr) is needed */ + u32 bOmitOffset : 1; /* True to let virtual table handle offset */ i8 isOrdered; /* True if satisfies ORDER BY */ u16 omitMask; /* Terms that may be omitted */ char *idxStr; /* Index identifier string */ + u32 mHandleIn; /* Terms to handle as IN(...) instead of == */ } vtab; } u; u32 wsFlags; /* WHERE_* flags describing the plan */ @@ -146078,7 +148916,7 @@ struct WhereTerm { #define TERM_COPIED 0x0008 /* Has a child */ #define TERM_ORINFO 0x0010 /* Need to free the WhereTerm.u.pOrInfo object */ #define TERM_ANDINFO 0x0020 /* Need to free the WhereTerm.u.pAndInfo obj */ -#define TERM_OR_OK 0x0040 /* Used during OR-clause processing */ +#define TERM_OK 0x0040 /* Used during OR-clause processing */ #define TERM_VNULL 0x0080 /* Manufactured x>NULL or x<=NULL term */ #define TERM_LIKEOPT 0x0100 /* Virtual terms from the LIKE optimization */ #define TERM_LIKECOND 0x0200 /* Conditionally this LIKE operator term */ @@ -146091,6 +148929,7 @@ struct WhereTerm { #else # define TERM_HIGHTRUTH 0 /* Only used with STAT4 */ #endif +#define TERM_SLICE 0x8000 /* One slice of a row-value/vector comparison */ /* ** An instance of the WhereScan object is used as an iterator for locating @@ -146101,11 +148940,11 @@ struct WhereScan { WhereClause *pWC; /* WhereClause currently being scanned */ const char *zCollName; /* Required collating sequence, if not NULL */ Expr *pIdxExpr; /* Search for this index expression */ + int k; /* Resume scanning at this->pWC->a[this->k] */ + u32 opMask; /* Acceptable operators */ char idxaff; /* Must match this affinity, if zCollName!=NULL */ + unsigned char iEquiv; /* Current slot in aiCur[] and aiColumn[] */ unsigned char nEquiv; /* Number of entries in aiCur[] and aiColumn[] */ - unsigned char iEquiv; /* Next unused slot in aiCur[] and aiColumn[] */ - u32 opMask; /* Acceptable operators */ - int k; /* Resume scanning at this->pWC->a[this->k] */ int aiCur[11]; /* Cursors in the equivalence class */ i16 aiColumn[11]; /* Corresponding column number in the eq-class */ }; @@ -146129,6 +148968,7 @@ struct WhereClause { u8 hasOr; /* True if any a[].eOperator is WO_OR */ int nTerm; /* Number of terms */ int nSlot; /* Number of entries in a[] */ + int nBase; /* Number of terms through the last non-Virtual */ WhereTerm *a; /* Each a[] describes a term of the WHERE cluase */ #if defined(SQLITE_SMALL_STACK) WhereTerm aStatic[1]; /* Initial static space for a[] */ @@ -146186,11 +149026,6 @@ struct WhereMaskSet { int ix[BMS]; /* Cursor assigned to each bit */ }; -/* -** Initialize a WhereMaskSet object -*/ -#define initMaskSet(P) (P)->n=0 - /* ** This object is a convenience wrapper holding all information needed ** to construct WhereLoop objects for a particular query. @@ -146198,7 +149033,6 @@ struct WhereMaskSet { struct WhereLoopBuilder { WhereInfo *pWInfo; /* Information about this WHERE */ WhereClause *pWC; /* WHERE clause terms */ - ExprList *pOrderBy; /* ORDER BY clause */ WhereLoop *pNew; /* Template WhereLoop */ WhereOrSet *pOrSet; /* Record best loops here, if not NULL */ #ifdef SQLITE_ENABLE_STAT4 @@ -146266,6 +149100,9 @@ struct WhereInfo { ExprList *pOrderBy; /* The ORDER BY clause or NULL */ ExprList *pResultSet; /* Result set of the query */ Expr *pWhere; /* The complete WHERE clause */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + Select *pLimit; /* Used to access LIMIT expr/registers for vtabs */ +#endif int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */ int iContinue; /* Jump here to continue with next record */ int iBreak; /* Jump here to break out of the loop */ @@ -146285,6 +149122,7 @@ struct WhereInfo { int iEndWhere; /* End of the WHERE clause itself */ WhereLoop *pLoops; /* List of all WhereLoop objects */ WhereExprMod *pExprMods; /* Expression modifications */ + WhereMemBlock *pMemToFree;/* Memory to free when this object destroyed */ Bitmask revMask; /* Mask of ORDER BY terms that need reversing */ WhereClause sWC; /* Decomposition of the WHERE clause */ WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */ @@ -146310,6 +149148,8 @@ SQLITE_PRIVATE WhereTerm *sqlite3WhereFindTerm( u32 op, /* Mask of WO_xx values describing operator */ Index *pIdx /* Must be compatible with this index, if not NULL */ ); +SQLITE_PRIVATE void *sqlite3WhereMalloc(WhereInfo *pWInfo, u64 nByte); +SQLITE_PRIVATE void *sqlite3WhereRealloc(WhereInfo *pWInfo, void *pOld, u64 nByte); /* wherecode.c: */ #ifndef SQLITE_OMIT_EXPLAIN @@ -146319,8 +149159,14 @@ SQLITE_PRIVATE int sqlite3WhereExplainOneScan( WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */ u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */ ); +SQLITE_PRIVATE int sqlite3WhereExplainBloomFilter( + const Parse *pParse, /* Parse context */ + const WhereInfo *pWInfo, /* WHERE clause */ + const WhereLevel *pLevel /* Bloom filter on this level */ +); #else # define sqlite3WhereExplainOneScan(u,v,w,x) 0 +# define sqlite3WhereExplainBloomFilter(u,v,w) 0 #endif /* SQLITE_OMIT_EXPLAIN */ #ifdef SQLITE_ENABLE_STMT_SCANSTATUS SQLITE_PRIVATE void sqlite3WhereAddScanStatus( @@ -146340,11 +149186,17 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( WhereLevel *pLevel, /* The current level pointer */ Bitmask notReady /* Which tables are currently available */ ); +SQLITE_PRIVATE SQLITE_NOINLINE void sqlite3WhereRightJoinLoop( + WhereInfo *pWInfo, + int iLevel, + WhereLevel *pLevel +); /* whereexpr.c: */ SQLITE_PRIVATE void sqlite3WhereClauseInit(WhereClause*,WhereInfo*); SQLITE_PRIVATE void sqlite3WhereClauseClear(WhereClause*); SQLITE_PRIVATE void sqlite3WhereSplit(WhereClause*,Expr*,u8); +SQLITE_PRIVATE void sqlite3WhereAddLimit(WhereClause*, Select*); SQLITE_PRIVATE Bitmask sqlite3WhereExprUsage(WhereMaskSet*, Expr*); SQLITE_PRIVATE Bitmask sqlite3WhereExprUsageNN(WhereMaskSet*, Expr*); SQLITE_PRIVATE Bitmask sqlite3WhereExprListUsage(WhereMaskSet*, ExprList*); @@ -146381,8 +149233,9 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(Parse*, SrcItem*, WhereClause*); #define WO_AND 0x0400 /* Two or more AND-connected terms */ #define WO_EQUIV 0x0800 /* Of the form A==B, both columns */ #define WO_NOOP 0x1000 /* This term does not restrict search space */ +#define WO_ROWVAL 0x2000 /* A row-value term */ -#define WO_ALL 0x1fff /* Mask of all possible WO_* values */ +#define WO_ALL 0x3fff /* Mask of all possible WO_* values */ #define WO_SINGLE 0x01ff /* Mask of all non-compound WO_* values */ /* @@ -146413,6 +149266,9 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(Parse*, SrcItem*, WhereClause*); #define WHERE_BIGNULL_SORT 0x00080000 /* Column nEq of index is BIGNULL */ #define WHERE_IN_SEEKSCAN 0x00100000 /* Seek-scan optimization for IN */ #define WHERE_TRANSCONS 0x00200000 /* Uses a transitive constraint */ +#define WHERE_BLOOMFILTER 0x00400000 /* Consider using a Bloom-filter */ +#define WHERE_SELFCULL 0x00800000 /* nOut reduced by extra WHERE terms */ +#define WHERE_OMIT_OFFSET 0x01000000 /* Set offset counter to zero */ #endif /* !defined(SQLITE_WHEREINT_H) */ @@ -146575,19 +149431,27 @@ SQLITE_PRIVATE int sqlite3WhereExplainOneScan( explainIndexRange(&str, pLoop); } }else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){ - const char *zRangeOp; + char cRangeOp; +#if 0 /* Better output, but breaks many tests */ + const Table *pTab = pItem->pTab; + const char *zRowid = pTab->iPKey>=0 ? pTab->aCol[pTab->iPKey].zCnName: + "rowid"; +#else + const char *zRowid = "rowid"; +#endif + sqlite3_str_appendf(&str, " USING INTEGER PRIMARY KEY (%s", zRowid); if( flags&(WHERE_COLUMN_EQ|WHERE_COLUMN_IN) ){ - zRangeOp = "="; + cRangeOp = '='; }else if( (flags&WHERE_BOTH_LIMIT)==WHERE_BOTH_LIMIT ){ - zRangeOp = ">? AND rowid<"; + sqlite3_str_appendf(&str, ">? AND %s", zRowid); + cRangeOp = '<'; }else if( flags&WHERE_BTM_LIMIT ){ - zRangeOp = ">"; + cRangeOp = '>'; }else{ assert( flags&WHERE_TOP_LIMIT); - zRangeOp = "<"; + cRangeOp = '<'; } - sqlite3_str_appendf(&str, - " USING INTEGER PRIMARY KEY (rowid%s?)",zRangeOp); + sqlite3_str_appendf(&str, "%c?)", cRangeOp); } #ifndef SQLITE_OMIT_VIRTUALTABLE else if( (flags & WHERE_VIRTUALTABLE)!=0 ){ @@ -146595,6 +149459,9 @@ SQLITE_PRIVATE int sqlite3WhereExplainOneScan( pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr); } #endif + if( pItem->fg.jointype & JT_LEFT ){ + sqlite3_str_appendf(&str, " LEFT-JOIN"); + } #ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS if( pLoop->nOut>=10 ){ sqlite3_str_appendf(&str, " (~%llu rows)", @@ -146610,6 +149477,56 @@ SQLITE_PRIVATE int sqlite3WhereExplainOneScan( } return ret; } + +/* +** Add a single OP_Explain opcode that describes a Bloom filter. +** +** Or if not processing EXPLAIN QUERY PLAN and not in a SQLITE_DEBUG and/or +** SQLITE_ENABLE_STMT_SCANSTATUS build, then OP_Explain opcodes are not +** required and this routine is a no-op. +** +** If an OP_Explain opcode is added to the VM, its address is returned. +** Otherwise, if no OP_Explain is coded, zero is returned. +*/ +SQLITE_PRIVATE int sqlite3WhereExplainBloomFilter( + const Parse *pParse, /* Parse context */ + const WhereInfo *pWInfo, /* WHERE clause */ + const WhereLevel *pLevel /* Bloom filter on this level */ +){ + int ret = 0; + SrcItem *pItem = &pWInfo->pTabList->a[pLevel->iFrom]; + Vdbe *v = pParse->pVdbe; /* VM being constructed */ + sqlite3 *db = pParse->db; /* Database handle */ + char *zMsg; /* Text to add to EQP output */ + int i; /* Loop counter */ + WhereLoop *pLoop; /* The where loop */ + StrAccum str; /* EQP output string */ + char zBuf[100]; /* Initial space for EQP output string */ + + sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH); + str.printfFlags = SQLITE_PRINTF_INTERNAL; + sqlite3_str_appendf(&str, "BLOOM FILTER ON %S (", pItem); + pLoop = pLevel->pWLoop; + if( pLoop->wsFlags & WHERE_IPK ){ + const Table *pTab = pItem->pTab; + if( pTab->iPKey>=0 ){ + sqlite3_str_appendf(&str, "%s=?", pTab->aCol[pTab->iPKey].zCnName); + }else{ + sqlite3_str_appendf(&str, "rowid=?"); + } + }else{ + for(i=pLoop->nSkip; iu.btree.nEq; i++){ + const char *z = explainIndexColumnName(pLoop->u.btree.pIndex, i); + if( i>pLoop->nSkip ) sqlite3_str_append(&str, " AND ", 5); + sqlite3_str_appendf(&str, "%s=?", z); + } + } + sqlite3_str_append(&str, ")", 1); + zMsg = sqlite3StrAccumFinish(&str); + ret = sqlite3VdbeAddOp4(v, OP_Explain, sqlite3VdbeCurrentAddr(v), + pParse->addrExplain, 0, zMsg,P4_DYNAMIC); + return ret; +} #endif /* SQLITE_OMIT_EXPLAIN */ #ifdef SQLITE_ENABLE_STMT_SCANSTATUS @@ -146688,7 +149605,7 @@ static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){ int nLoop = 0; assert( pTerm!=0 ); while( (pTerm->wtFlags & TERM_CODED)==0 - && (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin)) + && (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_OuterON)) && (pLevel->notReady & pTerm->prereqAll)==0 ){ if( nLoop && (pTerm->wtFlags & TERM_LIKE)!=0 ){ @@ -146949,16 +149866,22 @@ static int codeEqualityTerm( if( !ExprUseXSelect(pX) || pX->x.pSelect->pEList->nExpr==1 ){ eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0, &iTab); }else{ - sqlite3 *db = pParse->db; - pX = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX); - - if( !db->mallocFailed ){ - aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq); + Expr *pExpr = pTerm->pExpr; + if( pExpr->iTable==0 || !ExprHasProperty(pExpr, EP_Subrtn) ){ + sqlite3 *db = pParse->db; + pX = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX); + if( !db->mallocFailed ){ + aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq); + eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap,&iTab); + pExpr->iTable = iTab; + } + sqlite3ExprDelete(db, pX); + }else{ + int n = sqlite3ExprVectorSize(pX->pLeft); + aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*MAX(nEq,n)); eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap, &iTab); - pTerm->pExpr->iTable = iTab; } - sqlite3ExprDelete(db, pX); - pX = pTerm->pExpr; + pX = pExpr; } if( eType==IN_INDEX_INDEX_DESC ){ @@ -146981,8 +149904,9 @@ static int codeEqualityTerm( i = pLevel->u.in.nIn; pLevel->u.in.nIn += nEq; pLevel->u.in.aInLoop = - sqlite3DbReallocOrFree(pParse->db, pLevel->u.in.aInLoop, - sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn); + sqlite3WhereRealloc(pTerm->pWC->pWInfo, + pLevel->u.in.aInLoop, + sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn); pIn = pLevel->u.in.aInLoop; if( pIn ){ int iMap = 0; /* Index in aiMap[] */ @@ -147133,6 +150057,7 @@ static int codeAllEqualityTerms( VdbeCoverageIf(v, bRev!=0); VdbeComment((v, "begin skip-scan on %s", pIdx->zName)); j = sqlite3VdbeAddOp0(v, OP_Goto); + assert( pLevel->addrSkip==0 ); pLevel->addrSkip = sqlite3VdbeAddOp4Int(v, (bRev?OP_SeekLT:OP_SeekGT), iIdxCur, 0, regBase, nSkip); VdbeCoverageIf(v, bRev==0); @@ -147165,6 +150090,9 @@ static int codeAllEqualityTerms( sqlite3VdbeAddOp2(v, OP_Copy, r1, regBase+j); } } + } + for(j=nSkip; jaLTerm[j]; if( pTerm->eOperator & WO_IN ){ if( pTerm->pExpr->flags & EP_xIsSelect ){ /* No affinity ever needs to be (or should be) applied to a value @@ -147179,7 +150107,8 @@ static int codeAllEqualityTerms( sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk); VdbeCoverage(v); } - if( pParse->db->mallocFailed==0 && pParse->nErr==0 ){ + if( pParse->nErr==0 ){ + assert( pParse->db->mallocFailed==0 ); if( sqlite3CompareAffinity(pRight, zAff[j])==SQLITE_AFF_BLOB ){ zAff[j] = SQLITE_AFF_BLOB; } @@ -147369,7 +150298,7 @@ static void codeCursorHint( sWalker.pParse = pParse; sWalker.u.pCCurHint = &sHint; pWC = &pWInfo->sWC; - for(i=0; inTerm; i++){ + for(i=0; inBase; i++){ pTerm = &pWC->a[i]; if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; if( pTerm->prereqAll & pLevel->notReady ) continue; @@ -147398,8 +150327,8 @@ static void codeCursorHint( */ if( pTabItem->fg.jointype & JT_LEFT ){ Expr *pExpr = pTerm->pExpr; - if( !ExprHasProperty(pExpr, EP_FromJoin) - || pExpr->iRightJoinTable!=pTabItem->iCursor + if( !ExprHasProperty(pExpr, EP_OuterON) + || pExpr->w.iJoin!=pTabItem->iCursor ){ sWalker.eCode = 0; sWalker.xExprCallback = codeCursorHintIsOrFunction; @@ -147407,7 +150336,7 @@ static void codeCursorHint( if( sWalker.eCode ) continue; } }else{ - if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) continue; + if( ExprHasProperty(pTerm->pExpr, EP_OuterON) ) continue; } /* All terms in pWLoop->aLTerm[] except pEndRange are used to initialize @@ -147455,13 +150384,21 @@ static void codeCursorHint( ** ** OP_DeferredSeek $iCur $iRowid ** +** Which causes a seek on $iCur to the row with rowid $iRowid. +** ** However, if the scan currently being coded is a branch of an OR-loop and -** the statement currently being coded is a SELECT, then P3 of OP_DeferredSeek -** is set to iIdxCur and P4 is set to point to an array of integers -** containing one entry for each column of the table cursor iCur is open -** on. For each table column, if the column is the i'th column of the -** index, then the corresponding array entry is set to (i+1). If the column -** does not appear in the index at all, the array entry is set to 0. +** the statement currently being coded is a SELECT, then additional information +** is added that might allow OP_Column to omit the seek and instead do its +** lookup on the index, thus avoiding an expensive seek operation. To +** enable this optimization, the P3 of OP_DeferredSeek is set to iIdxCur +** and P4 is set to an array of integers containing one entry for each column +** in the table. For each table column, if the column is the i'th +** column of the index, then the corresponding array entry is set to (i+1). +** If the column does not appear in the index at all, the array entry is set +** to 0. The OP_Column opcode can check this array to see if the column it +** wants is in the index and if it is, it will substitute the index cursor +** and column number and continue with those new values, rather than seeking +** the table cursor. */ static void codeDeferredSeek( WhereInfo *pWInfo, /* Where clause context */ @@ -147477,7 +150414,7 @@ static void codeDeferredSeek( pWInfo->bDeferredSeek = 1; sqlite3VdbeAddOp3(v, OP_DeferredSeek, iIdxCur, 0, iCur); - if( (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE) + if( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN)) && DbMaskAllZero(sqlite3ParseToplevel(pParse)->writeMask) ){ int i; @@ -147571,12 +150508,12 @@ static void preserveExpr(IdxExprTrans *pTrans, Expr *pExpr){ static int whereIndexExprTransNode(Walker *p, Expr *pExpr){ IdxExprTrans *pX = p->u.pIdxTrans; if( sqlite3ExprCompare(0, pExpr, pX->pIdxExpr, pX->iTabCur)==0 ){ + pExpr = sqlite3ExprSkipCollate(pExpr); preserveExpr(pX, pExpr); pExpr->affExpr = sqlite3ExprAffinity(pExpr); pExpr->op = TK_COLUMN; pExpr->iTable = pX->iIdxCur; pExpr->iColumn = pX->iIdxCol; - testcase( ExprHasProperty(pExpr, EP_Skip) ); testcase( ExprHasProperty(pExpr, EP_Unlikely) ); ExprClearProperty(pExpr, EP_Skip|EP_Unlikely|EP_WinFunc|EP_Subrtn); pExpr->y.pTab = 0; @@ -147700,6 +150637,68 @@ static void whereApplyPartialIndexConstraints( } } +/* +** This routine is called right after An OP_Filter has been generated and +** before the corresponding index search has been performed. This routine +** checks to see if there are additional Bloom filters in inner loops that +** can be checked prior to doing the index lookup. If there are available +** inner-loop Bloom filters, then evaluate those filters now, before the +** index lookup. The idea is that a Bloom filter check is way faster than +** an index lookup, and the Bloom filter might return false, meaning that +** the index lookup can be skipped. +** +** We know that an inner loop uses a Bloom filter because it has the +** WhereLevel.regFilter set. If an inner-loop Bloom filter is checked, +** then clear the WhereLevel.regFilter value to prevent the Bloom filter +** from being checked a second time when the inner loop is evaluated. +*/ +static SQLITE_NOINLINE void filterPullDown( + Parse *pParse, /* Parsing context */ + WhereInfo *pWInfo, /* Complete information about the WHERE clause */ + int iLevel, /* Which level of pWInfo->a[] should be coded */ + int addrNxt, /* Jump here to bypass inner loops */ + Bitmask notReady /* Loops that are not ready */ +){ + while( ++iLevel < pWInfo->nLevel ){ + WhereLevel *pLevel = &pWInfo->a[iLevel]; + WhereLoop *pLoop = pLevel->pWLoop; + if( pLevel->regFilter==0 ) continue; + if( pLevel->pWLoop->nSkip ) continue; + /* ,--- Because sqlite3ConstructBloomFilter() has will not have set + ** vvvvv--' pLevel->regFilter if this were true. */ + if( NEVER(pLoop->prereq & notReady) ) continue; + assert( pLevel->addrBrk==0 ); + pLevel->addrBrk = addrNxt; + if( pLoop->wsFlags & WHERE_IPK ){ + WhereTerm *pTerm = pLoop->aLTerm[0]; + int regRowid; + assert( pTerm!=0 ); + assert( pTerm->pExpr!=0 ); + testcase( pTerm->wtFlags & TERM_VIRTUAL ); + regRowid = sqlite3GetTempReg(pParse); + regRowid = codeEqualityTerm(pParse, pTerm, pLevel, 0, 0, regRowid); + sqlite3VdbeAddOp4Int(pParse->pVdbe, OP_Filter, pLevel->regFilter, + addrNxt, regRowid, 1); + VdbeCoverage(pParse->pVdbe); + }else{ + u16 nEq = pLoop->u.btree.nEq; + int r1; + char *zStartAff; + + assert( pLoop->wsFlags & WHERE_INDEXED ); + assert( (pLoop->wsFlags & WHERE_COLUMN_IN)==0 ); + r1 = codeAllEqualityTerms(pParse,pLevel,0,0,&zStartAff); + codeApplyAffinity(pParse, r1, nEq, zStartAff); + sqlite3DbFree(pParse->db, zStartAff); + sqlite3VdbeAddOp4Int(pParse->pVdbe, OP_Filter, pLevel->regFilter, + addrNxt, r1, nEq); + VdbeCoverage(pParse->pVdbe); + } + pLevel->regFilter = 0; + pLevel->addrBrk = 0; + } +} + /* ** Generate code for the start of the iLevel-th loop in the WHERE clause ** implementation described by pWInfo. @@ -147770,7 +150769,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( ** initialize a memory cell that records if this table matches any ** row of the left table of the join. */ - assert( (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE) + assert( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN)) || pLevel->iFrom>0 || (pTabItem[0].fg.jointype & JT_LEFT)==0 ); if( pLevel->iFrom>0 && (pTabItem[0].fg.jointype & JT_LEFT)!=0 ){ @@ -147781,7 +150780,10 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( /* Compute a safe address to jump to if we discover that the table for ** this loop is empty and can never contribute content. */ - for(j=iLevel; j>0 && pWInfo->a[j].iLeftJoin==0; j--){} + for(j=iLevel; j>0; j--){ + if( pWInfo->a[j].iLeftJoin ) break; + if( pWInfo->a[j].pRJ ) break; + } addrHalt = pWInfo->a[j].addrBrk; /* Special case of a FROM clause subquery implemented as a co-routine */ @@ -147802,7 +150804,6 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( int iReg; /* P3 Value for OP_VFilter */ int addrNotFound; int nConstraint = pLoop->nLTerm; - int iIn; /* Counter for IN constraints */ iReg = sqlite3GetTempRange(pParse, nConstraint+2); addrNotFound = pLevel->addrBrk; @@ -147811,11 +150812,27 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( pTerm = pLoop->aLTerm[j]; if( NEVER(pTerm==0) ) continue; if( pTerm->eOperator & WO_IN ){ - codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget); - addrNotFound = pLevel->addrNxt; + if( SMASKBIT32(j) & pLoop->u.vtab.mHandleIn ){ + int iTab = pParse->nTab++; + int iCache = ++pParse->nMem; + sqlite3CodeRhsOfIN(pParse, pTerm->pExpr, iTab); + sqlite3VdbeAddOp3(v, OP_VInitIn, iTab, iTarget, iCache); + }else{ + codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget); + addrNotFound = pLevel->addrNxt; + } }else{ Expr *pRight = pTerm->pExpr->pRight; codeExprOrVector(pParse, pRight, iTarget, 1); + if( pTerm->eMatchOp==SQLITE_INDEX_CONSTRAINT_OFFSET + && pLoop->u.vtab.bOmitOffset + ){ + assert( pTerm->eOperator==WO_AUX ); + assert( pWInfo->pLimit!=0 ); + assert( pWInfo->pLimit->iOffset>0 ); + sqlite3VdbeAddOp2(v, OP_Integer, 0, pWInfo->pLimit->iOffset); + VdbeComment((v,"Zero OFFSET counter")); + } } } sqlite3VdbeAddOp2(v, OP_Integer, pLoop->u.vtab.idxNum, iReg); @@ -147832,44 +150849,54 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( pLevel->op = pWInfo->eOnePass ? OP_Noop : OP_VNext; pLevel->p2 = sqlite3VdbeCurrentAddr(v); assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 ); - if( pLoop->wsFlags & WHERE_IN_ABLE ){ - iIn = pLevel->u.in.nIn; - }else{ - iIn = 0; - } - for(j=nConstraint-1; j>=0; j--){ + + for(j=0; jaLTerm[j]; - if( (pTerm->eOperator & WO_IN)!=0 ) iIn--; if( j<16 && (pLoop->u.vtab.omitMask>>j)&1 ){ disableTerm(pLevel, pTerm); - }else if( (pTerm->eOperator & WO_IN)!=0 - && sqlite3ExprVectorSize(pTerm->pExpr->pLeft)==1 + continue; + } + if( (pTerm->eOperator & WO_IN)!=0 + && (SMASKBIT32(j) & pLoop->u.vtab.mHandleIn)==0 + && !db->mallocFailed ){ Expr *pCompare; /* The comparison operator */ Expr *pRight; /* RHS of the comparison */ VdbeOp *pOp; /* Opcode to access the value of the IN constraint */ + int iIn; /* IN loop corresponding to the j-th constraint */ /* Reload the constraint value into reg[iReg+j+2]. The same value ** was loaded into the same register prior to the OP_VFilter, but ** the xFilter implementation might have changed the datatype or - ** encoding of the value in the register, so it *must* be reloaded. */ - assert( pLevel->u.in.aInLoop!=0 || db->mallocFailed ); - if( !db->mallocFailed ){ - assert( iIn>=0 && iInu.in.nIn ); + ** encoding of the value in the register, so it *must* be reloaded. + */ + for(iIn=0; ALWAYS(iInu.in.nIn); iIn++){ pOp = sqlite3VdbeGetOp(v, pLevel->u.in.aInLoop[iIn].addrInTop); - assert( pOp->opcode==OP_Column || pOp->opcode==OP_Rowid ); - assert( pOp->opcode!=OP_Column || pOp->p3==iReg+j+2 ); - assert( pOp->opcode!=OP_Rowid || pOp->p2==iReg+j+2 ); - testcase( pOp->opcode==OP_Rowid ); - sqlite3VdbeAddOp3(v, pOp->opcode, pOp->p1, pOp->p2, pOp->p3); + if( (pOp->opcode==OP_Column && pOp->p3==iReg+j+2) + || (pOp->opcode==OP_Rowid && pOp->p2==iReg+j+2) + ){ + testcase( pOp->opcode==OP_Rowid ); + sqlite3VdbeAddOp3(v, pOp->opcode, pOp->p1, pOp->p2, pOp->p3); + break; + } } /* Generate code that will continue to the next row if - ** the IN constraint is not satisfied */ + ** the IN constraint is not satisfied + */ pCompare = sqlite3PExpr(pParse, TK_EQ, 0, 0); - assert( pCompare!=0 || db->mallocFailed ); - if( pCompare ){ - pCompare->pLeft = pTerm->pExpr->pLeft; + if( !db->mallocFailed ){ + int iFld = pTerm->u.x.iField; + Expr *pLeft = pTerm->pExpr->pLeft; + assert( pLeft!=0 ); + if( iFld>0 ){ + assert( pLeft->op==TK_VECTOR ); + assert( ExprUseXList(pLeft) ); + assert( iFld<=pLeft->x.pList->nExpr ); + pCompare->pLeft = pLeft->x.pList->a[iFld-1].pExpr; + }else{ + pCompare->pLeft = pLeft; + } pCompare->pRight = pRight = sqlite3Expr(db, TK_REGISTER, 0); if( pRight ){ pRight->iTable = iReg+j+2; @@ -147878,11 +150905,11 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( ); } pCompare->pLeft = 0; - sqlite3ExprDelete(db, pCompare); } + sqlite3ExprDelete(db, pCompare); } } - assert( iIn==0 || db->mallocFailed ); + /* These registers need to be preserved in case there is an IN operator ** loop. So we could deallocate the registers here (and potentially ** reuse them later) if (pLoop->wsFlags & WHERE_IN_ABLE)==0. But it seems @@ -147910,6 +150937,12 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, bRev, iReleaseReg); if( iRowidReg!=iReleaseReg ) sqlite3ReleaseTempReg(pParse, iReleaseReg); addrNxt = pLevel->addrNxt; + if( pLevel->regFilter ){ + sqlite3VdbeAddOp4Int(v, OP_Filter, pLevel->regFilter, addrNxt, + iRowidReg, 1); + VdbeCoverage(v); + filterPullDown(pParse, pWInfo, iLevel, addrNxt, notReady); + } sqlite3VdbeAddOp3(v, OP_SeekRowid, iCur, addrNxt, iRowidReg); VdbeCoverage(v); pLevel->op = OP_Noop; @@ -148235,6 +151268,12 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( sqlite3VdbeAddOp2(v, OP_Integer, 1, regBignull); VdbeComment((v, "NULL-scan pass ctr")); } + if( pLevel->regFilter ){ + sqlite3VdbeAddOp4Int(v, OP_Filter, pLevel->regFilter, addrNxt, + regBase, nEq); + VdbeCoverage(v); + filterPullDown(pParse, pWInfo, iLevel, addrNxt, notReady); + } op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev]; assert( op!=0 ); @@ -148371,7 +151410,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( /* Seek the table cursor, if required */ omitTable = (pLoop->wsFlags & WHERE_IDX_ONLY)!=0 - && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0; + && (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))==0; if( omitTable ){ /* pIdx is a covering index. No need to access the main table. */ }else if( HasRowid(pIdx->pTable) ){ @@ -148405,7 +151444,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( ** move forward to the next index. ** https://sqlite.org/src/info/4e8e4857d32d401f */ - if( (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0 ){ + if( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))==0 ){ whereIndexExprTrans(pIdx, iCur, iIdxCur, pWInfo); } @@ -148424,7 +151463,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( /* The following assert() is not a requirement, merely an observation: ** The OR-optimization doesn't work for the right hand table of ** a LEFT JOIN: */ - assert( (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0 ); + assert( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))==0 ); } /* Record the instruction used to terminate the loop. */ @@ -148562,7 +151601,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( iRetInit = sqlite3VdbeAddOp2(v, OP_Integer, 0, regReturn); /* If the original WHERE clause is z of the form: (x1 OR x2 OR ...) AND y - ** Then for every term xN, evaluate as the subexpression: xN AND z + ** Then for every term xN, evaluate as the subexpression: xN AND y ** That way, terms in y that are factored into the disjunction will ** be picked up by the recursive calls to sqlite3WhereBegin() below. ** @@ -148574,6 +151613,20 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( ** This optimization also only applies if the (x1 OR x2 OR ...) term ** is not contained in the ON clause of a LEFT JOIN. ** See ticket http://www.sqlite.org/src/info/f2369304e4 + ** + ** 2022-02-04: Do not push down slices of a row-value comparison. + ** In other words, "w" or "y" may not be a slice of a vector. Otherwise, + ** the initialization of the right-hand operand of the vector comparison + ** might not occur, or might occur only in an OR branch that is not + ** taken. dbsqlfuzz 80a9fade844b4fb43564efc972bcb2c68270f5d1. + ** + ** 2022-03-03: Do not push down expressions that involve subqueries. + ** The subquery might get coded as a subroutine. Any table-references + ** in the subquery might be resolved to index-references for the index on + ** the OR branch in which the subroutine is coded. But if the subroutine + ** is invoked from a different OR branch that uses a different index, such + ** index-references will not work. tag-20220303a + ** https://sqlite.org/forum/forumpost/36937b197273d403 */ if( pWC->nTerm>1 ){ int iTerm; @@ -148582,9 +151635,12 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( if( &pWC->a[iTerm] == pTerm ) continue; testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL ); testcase( pWC->a[iTerm].wtFlags & TERM_CODED ); - if( (pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_CODED))!=0 ) continue; + testcase( pWC->a[iTerm].wtFlags & TERM_SLICE ); + if( (pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_CODED|TERM_SLICE))!=0 ){ + continue; + } if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue; - testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO ); + if( ExprHasProperty(pExpr, EP_Subquery) ) continue; /* tag-20220303a */ pExpr = sqlite3ExprDup(db, pExpr, 0); pAndExpr = sqlite3ExprAnd(pParse, pAndExpr, pExpr); } @@ -148611,7 +151667,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( Expr *pDelete; /* Local copy of OR clause term */ int jmp1 = 0; /* Address of jump operation */ testcase( (pTabItem[0].fg.jointype & JT_LEFT)!=0 - && !ExprHasProperty(pOrExpr, EP_FromJoin) + && !ExprHasProperty(pOrExpr, EP_OuterON) ); /* See TH3 vtab25.400 and ticket 614b25314c766238 */ pDelete = pOrExpr = sqlite3ExprDup(db, pOrExpr, 0); if( db->mallocFailed ){ @@ -148625,9 +151681,9 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( /* Loop through table entries that match term pOrTerm. */ ExplainQueryPlan((pParse, 1, "INDEX %d", ii+1)); WHERETRACE(0xffff, ("Subplan for OR-clause:\n")); - pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0, + pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0, 0, WHERE_OR_SUBCLAUSE, iCovCur); - assert( pSubWInfo || pParse->nErr || db->mallocFailed ); + assert( pSubWInfo || pParse->nErr ); if( pSubWInfo ){ WhereLoop *pSubLoop; int addrExplain = sqlite3WhereExplainOneScan( @@ -148749,6 +151805,14 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( sqlite3VdbeGoto(v, pLevel->addrBrk); sqlite3VdbeResolveLabel(v, iLoopBody); + /* Set the P2 operand of the OP_Return opcode that will end the current + ** loop to point to this spot, which is the top of the next containing + ** loop. The byte-code formatter will use that P2 value as a hint to + ** indent everything in between the this point and the final OP_Return. + ** See tag-20220407a in vdbe.c and shell.c */ + assert( pLevel->op==OP_Return ); + pLevel->p2 = sqlite3VdbeCurrentAddr(v); + if( pWInfo->nLevel>1 ){ sqlite3StackFree(db, pOrTab); } if( !untestedTerms ) disableTerm(pLevel, pTerm); }else @@ -148811,10 +151875,22 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( } pE = pTerm->pExpr; assert( pE!=0 ); - if( (pTabItem->fg.jointype&JT_LEFT) && !ExprHasProperty(pE,EP_FromJoin) ){ - continue; + if( pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT) ){ + if( !ExprHasProperty(pE,EP_OuterON|EP_InnerON) ){ + /* Defer processing WHERE clause constraints until after outer + ** join processing. tag-20220513a */ + continue; + }else if( (pTabItem->fg.jointype & JT_LEFT)==JT_LEFT + && !ExprHasProperty(pE,EP_OuterON) ){ + continue; + }else{ + Bitmask m = sqlite3WhereGetMask(&pWInfo->sMaskSet, pE->w.iJoin); + if( m & pLevel->notReady ){ + /* An ON clause that is not ripe */ + continue; + } + } } - if( iLoop==1 && !sqlite3ExprCoveredByIndex(pE, pLevel->iTabCur, pIdx) ){ iNext = 2; continue; @@ -148866,14 +151942,14 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( ** then we cannot use the "t1.a=t2.b" constraint, but we can code ** the implied "t1.a=123" constraint. */ - for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){ + for(pTerm=pWC->a, j=pWC->nBase; j>0; j--, pTerm++){ Expr *pE, sEAlt; WhereTerm *pAlt; if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) continue; if( (pTerm->eOperator & WO_EQUIV)==0 ) continue; if( pTerm->leftCursor!=iCur ) continue; - if( pTabItem->fg.jointype & JT_LEFT ) continue; + if( pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT) ) continue; pE = pTerm->pExpr; #ifdef WHERETRACE_ENABLED /* 0x800 */ if( sqlite3WhereTrace & 0x800 ){ @@ -148881,7 +151957,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( sqlite3WhereTermPrint(pTerm, pWC->nTerm-j); } #endif - assert( !ExprHasProperty(pE, EP_FromJoin) ); + assert( !ExprHasProperty(pE, EP_OuterON) ); assert( (pTerm->prereqRight & pLevel->notReady)!=0 ); assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 ); pAlt = sqlite3WhereFindTerm(pWC, iCur, pTerm->u.x.leftColumn, notReady, @@ -148904,6 +151980,47 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( pAlt->wtFlags |= TERM_CODED; } + /* For a RIGHT OUTER JOIN, record the fact that the current row has + ** been matched at least once. + */ + if( pLevel->pRJ ){ + Table *pTab; + int nPk; + int r; + int jmp1 = 0; + WhereRightJoin *pRJ = pLevel->pRJ; + + /* pTab is the right-hand table of the RIGHT JOIN. Generate code that + ** will record that the current row of that table has been matched at + ** least once. This is accomplished by storing the PK for the row in + ** both the iMatch index and the regBloom Bloom filter. + */ + pTab = pWInfo->pTabList->a[pLevel->iFrom].pTab; + if( HasRowid(pTab) ){ + r = sqlite3GetTempRange(pParse, 2); + sqlite3ExprCodeGetColumnOfTable(v, pTab, pLevel->iTabCur, -1, r+1); + nPk = 1; + }else{ + int iPk; + Index *pPk = sqlite3PrimaryKeyIndex(pTab); + nPk = pPk->nKeyCol; + r = sqlite3GetTempRange(pParse, nPk+1); + for(iPk=0; iPkaiColumn[iPk]; + sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol,r+1+iPk); + } + } + jmp1 = sqlite3VdbeAddOp4Int(v, OP_Found, pRJ->iMatch, 0, r+1, nPk); + VdbeCoverage(v); + VdbeComment((v, "match against %s", pTab->zName)); + sqlite3VdbeAddOp3(v, OP_MakeRecord, r+1, nPk, r); + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pRJ->iMatch, r, r+1, nPk); + sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pRJ->regBloom, 0, r+1, nPk); + sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); + sqlite3VdbeJumpHere(v, jmp1); + sqlite3ReleaseTempRange(pParse, r, nPk+1); + } + /* For a LEFT OUTER JOIN, generate code that will record the fact that ** at least one row of the right table has matched the left table. */ @@ -148911,7 +152028,31 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( pLevel->addrFirst = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin); VdbeComment((v, "record LEFT JOIN hit")); - for(pTerm=pWC->a, j=0; jnTerm; j++, pTerm++){ + if( pLevel->pRJ==0 ){ + goto code_outer_join_constraints; /* WHERE clause constraints */ + } + } + + if( pLevel->pRJ ){ + /* Create a subroutine used to process all interior loops and code + ** of the RIGHT JOIN. During normal operation, the subroutine will + ** be in-line with the rest of the code. But at the end, a separate + ** loop will run that invokes this subroutine for unmatched rows + ** of pTab, with all tables to left begin set to NULL. + */ + WhereRightJoin *pRJ = pLevel->pRJ; + sqlite3VdbeAddOp2(v, OP_BeginSubrtn, 0, pRJ->regReturn); + pRJ->addrSubrtn = sqlite3VdbeCurrentAddr(v); + assert( pParse->withinRJSubrtn < 255 ); + pParse->withinRJSubrtn++; + + /* WHERE clause constraints must be deferred until after outer join + ** row elimination has completed, since WHERE clause constraints apply + ** to the results of the OUTER JOIN. The following loop generates the + ** appropriate WHERE clause constraint checks. tag-20220513a. + */ + code_outer_join_constraints: + for(pTerm=pWC->a, j=0; jnBase; j++, pTerm++){ testcase( pTerm->wtFlags & TERM_VIRTUAL ); testcase( pTerm->wtFlags & TERM_CODED ); if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; @@ -148919,6 +152060,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( assert( pWInfo->untestedTerms ); continue; } + if( pTabItem->fg.jointype & JT_LTORJ ) continue; assert( pTerm->pExpr ); sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL); pTerm->wtFlags |= TERM_CODED; @@ -148939,6 +152081,96 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( return pLevel->notReady; } +/* +** Generate the code for the loop that finds all non-matched terms +** for a RIGHT JOIN. +*/ +SQLITE_PRIVATE SQLITE_NOINLINE void sqlite3WhereRightJoinLoop( + WhereInfo *pWInfo, + int iLevel, + WhereLevel *pLevel +){ + Parse *pParse = pWInfo->pParse; + Vdbe *v = pParse->pVdbe; + WhereRightJoin *pRJ = pLevel->pRJ; + Expr *pSubWhere = 0; + WhereClause *pWC = &pWInfo->sWC; + WhereInfo *pSubWInfo; + WhereLoop *pLoop = pLevel->pWLoop; + SrcItem *pTabItem = &pWInfo->pTabList->a[pLevel->iFrom]; + SrcList sFrom; + Bitmask mAll = 0; + int k; + + ExplainQueryPlan((pParse, 1, "RIGHT-JOIN %s", pTabItem->pTab->zName)); + sqlite3VdbeNoJumpsOutsideSubrtn(v, pRJ->addrSubrtn, pRJ->endSubrtn, + pRJ->regReturn); + for(k=0; ka[k].pWLoop->maskSelf; + sqlite3VdbeAddOp1(v, OP_NullRow, pWInfo->a[k].iTabCur); + iIdxCur = pWInfo->a[k].iIdxCur; + if( iIdxCur ){ + sqlite3VdbeAddOp1(v, OP_NullRow, iIdxCur); + } + } + if( (pTabItem->fg.jointype & JT_LTORJ)==0 ){ + mAll |= pLoop->maskSelf; + for(k=0; knTerm; k++){ + WhereTerm *pTerm = &pWC->a[k]; + if( (pTerm->wtFlags & (TERM_VIRTUAL|TERM_SLICE))!=0 + && pTerm->eOperator!=WO_ROWVAL + ){ + break; + } + if( pTerm->prereqAll & ~mAll ) continue; + if( ExprHasProperty(pTerm->pExpr, EP_OuterON|EP_InnerON) ) continue; + pSubWhere = sqlite3ExprAnd(pParse, pSubWhere, + sqlite3ExprDup(pParse->db, pTerm->pExpr, 0)); + } + } + sFrom.nSrc = 1; + sFrom.nAlloc = 1; + memcpy(&sFrom.a[0], pTabItem, sizeof(SrcItem)); + sFrom.a[0].fg.jointype = 0; + assert( pParse->withinRJSubrtn < 100 ); + pParse->withinRJSubrtn++; + pSubWInfo = sqlite3WhereBegin(pParse, &sFrom, pSubWhere, 0, 0, 0, + WHERE_RIGHT_JOIN, 0); + if( pSubWInfo ){ + int iCur = pLevel->iTabCur; + int r = ++pParse->nMem; + int nPk; + int jmp; + int addrCont = sqlite3WhereContinueLabel(pSubWInfo); + Table *pTab = pTabItem->pTab; + if( HasRowid(pTab) ){ + sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, -1, r); + nPk = 1; + }else{ + int iPk; + Index *pPk = sqlite3PrimaryKeyIndex(pTab); + nPk = pPk->nKeyCol; + pParse->nMem += nPk - 1; + for(iPk=0; iPkaiColumn[iPk]; + sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol,r+iPk); + } + } + jmp = sqlite3VdbeAddOp4Int(v, OP_Filter, pRJ->regBloom, 0, r, nPk); + VdbeCoverage(v); + sqlite3VdbeAddOp4Int(v, OP_Found, pRJ->iMatch, addrCont, r, nPk); + VdbeCoverage(v); + sqlite3VdbeJumpHere(v, jmp); + sqlite3VdbeAddOp2(v, OP_Gosub, pRJ->regReturn, pRJ->addrSubrtn); + sqlite3WhereEnd(pSubWInfo); + } + sqlite3ExprDelete(pParse->db, pSubWhere); + ExplainQueryPlanPop(pParse); + assert( pParse->withinRJSubrtn>0 ); + pParse->withinRJSubrtn--; +} + /************** End of wherecode.c *******************************************/ /************** Begin file whereexpr.c ***************************************/ /* @@ -149007,7 +152239,7 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){ if( pWC->nTerm>=pWC->nSlot ){ WhereTerm *pOld = pWC->a; sqlite3 *db = pWC->pWInfo->pParse->db; - pWC->a = sqlite3DbMallocRawNN(db, sizeof(pWC->a[0])*pWC->nSlot*2 ); + pWC->a = sqlite3WhereMalloc(pWC->pWInfo, sizeof(pWC->a[0])*pWC->nSlot*2 ); if( pWC->a==0 ){ if( wtFlags & TERM_DYNAMIC ){ sqlite3ExprDelete(db, p); @@ -149016,12 +152248,10 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){ return 0; } memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm); - if( pOld!=pWC->aStatic ){ - sqlite3DbFree(db, pOld); - } - pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]); + pWC->nSlot = pWC->nSlot*2; } pTerm = &pWC->a[idx = pWC->nTerm++]; + if( (wtFlags & TERM_VIRTUAL)==0 ) pWC->nBase = pWC->nTerm; if( p && ExprHasProperty(p, EP_Unlikely) ){ pTerm->truthProb = sqlite3LogEst(p->iTable) - 270; }else{ @@ -149364,7 +152594,7 @@ static int isAuxiliaryVtabOperator( assert( pVtab!=0 ); assert( pVtab->pModule!=0 ); assert( !ExprHasProperty(pExpr, EP_IntValue) ); - pMod = (sqlite3_module *)pVtab->pModule; + pMod = (sqlite3_module *)pVtab->pModule; if( pMod->xFindFunction!=0 ){ i = pMod->xFindFunction(pVtab,2, pExpr->u.zToken, &xNotUsed, &pNotUsed); if( i>=SQLITE_INDEX_CONSTRAINT_FUNCTION ){ @@ -149406,9 +152636,9 @@ static int isAuxiliaryVtabOperator( ** a join, then transfer the appropriate markings over to derived. */ static void transferJoinMarkings(Expr *pDerived, Expr *pBase){ - if( pDerived ){ - pDerived->flags |= pBase->flags & EP_FromJoin; - pDerived->iRightJoinTable = pBase->iRightJoinTable; + if( pDerived && ExprHasProperty(pBase, EP_OuterON|EP_InnerON) ){ + pDerived->flags |= pBase->flags & (EP_OuterON|EP_InnerON); + pDerived->w.iJoin = pBase->w.iJoin; } } @@ -149738,7 +152968,7 @@ static void exprAnalyzeOrTerm( pOrTerm = pOrWc->a; for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){ assert( pOrTerm->eOperator & WO_EQ ); - pOrTerm->wtFlags &= ~TERM_OR_OK; + pOrTerm->wtFlags &= ~TERM_OK; if( pOrTerm->leftCursor==iCursor ){ /* This is the 2-bit case and we are on the second iteration and ** current term is from the first iteration. So skip this term. */ @@ -149779,7 +153009,7 @@ static void exprAnalyzeOrTerm( assert( pOrTerm->eOperator & WO_EQ ); assert( (pOrTerm->eOperator & (WO_OR|WO_AND))==0 ); if( pOrTerm->leftCursor!=iCursor ){ - pOrTerm->wtFlags &= ~TERM_OR_OK; + pOrTerm->wtFlags &= ~TERM_OK; }else if( pOrTerm->u.x.leftColumn!=iColumn || (iColumn==XN_EXPR && sqlite3ExprCompare(pParse, pOrTerm->pExpr->pLeft, pLeft, -1) )){ @@ -149795,7 +153025,7 @@ static void exprAnalyzeOrTerm( if( affRight!=0 && affRight!=affLeft ){ okToChngToIN = 0; }else{ - pOrTerm->wtFlags |= TERM_OR_OK; + pOrTerm->wtFlags |= TERM_OK; } } } @@ -149812,7 +153042,7 @@ static void exprAnalyzeOrTerm( Expr *pNew; /* The complete IN operator */ for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){ - if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue; + if( (pOrTerm->wtFlags & TERM_OK)==0 ) continue; assert( pOrTerm->eOperator & WO_EQ ); assert( (pOrTerm->eOperator & (WO_OR|WO_AND))==0 ); assert( pOrTerm->leftCursor==iCursor ); @@ -149862,7 +153092,7 @@ static int termIsEquivalence(Parse *pParse, Expr *pExpr){ CollSeq *pColl; if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0; if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0; - if( ExprHasProperty(pExpr, EP_FromJoin) ) return 0; + if( ExprHasProperty(pExpr, EP_OuterON) ) return 0; aff1 = sqlite3ExprAffinity(pExpr->pLeft); aff2 = sqlite3ExprAffinity(pExpr->pRight); if( aff1!=aff2 @@ -149893,7 +153123,9 @@ static Bitmask exprSelectUsage(WhereMaskSet *pMaskSet, Select *pS){ int i; for(i=0; inSrc; i++){ mask |= exprSelectUsage(pMaskSet, pSrc->a[i].pSelect); - mask |= sqlite3WhereExprUsage(pMaskSet, pSrc->a[i].pOn); + if( pSrc->a[i].fg.isUsing==0 ){ + mask |= sqlite3WhereExprUsage(pMaskSet, pSrc->a[i].u3.pOn); + } if( pSrc->a[i].fg.isTabFunc ){ mask |= sqlite3WhereExprListUsage(pMaskSet, pSrc->a[i].u1.pFuncArg); } @@ -150013,10 +153245,13 @@ static void exprAnalyze( if( db->mallocFailed ){ return; } + assert( pWC->nTerm > idxTerm ); pTerm = &pWC->a[idxTerm]; pMaskSet = &pWInfo->sMaskSet; pExpr = pTerm->pExpr; + assert( pExpr!=0 ); /* Because malloc() has not failed */ assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE ); + pMaskSet->bVarSelect = 0; prereqLeft = sqlite3WhereExprUsage(pMaskSet, pExpr->pLeft); op = pExpr->op; if( op==TK_IN ){ @@ -150027,22 +153262,50 @@ static void exprAnalyze( }else{ pTerm->prereqRight = sqlite3WhereExprListUsage(pMaskSet, pExpr->x.pList); } - }else if( op==TK_ISNULL ){ - pTerm->prereqRight = 0; + prereqAll = prereqLeft | pTerm->prereqRight; }else{ pTerm->prereqRight = sqlite3WhereExprUsage(pMaskSet, pExpr->pRight); + if( pExpr->pLeft==0 + || ExprHasProperty(pExpr, EP_xIsSelect|EP_IfNullRow) + || pExpr->x.pList!=0 + ){ + prereqAll = sqlite3WhereExprUsageNN(pMaskSet, pExpr); + }else{ + prereqAll = prereqLeft | pTerm->prereqRight; + } } - pMaskSet->bVarSelect = 0; - prereqAll = sqlite3WhereExprUsageNN(pMaskSet, pExpr); if( pMaskSet->bVarSelect ) pTerm->wtFlags |= TERM_VARSELECT; - if( ExprHasProperty(pExpr, EP_FromJoin) ){ - Bitmask x = sqlite3WhereGetMask(pMaskSet, pExpr->iRightJoinTable); - prereqAll |= x; - extraRight = x-1; /* ON clause terms may not be used with an index - ** on left table of a LEFT JOIN. Ticket #3015 */ - if( (prereqAll>>1)>=x ){ - sqlite3ErrorMsg(pParse, "ON clause references tables to its right"); - return; + +#ifdef SQLITE_DEBUG + if( prereqAll!=sqlite3WhereExprUsageNN(pMaskSet, pExpr) ){ + printf("\n*** Incorrect prereqAll computed for:\n"); + sqlite3TreeViewExpr(0,pExpr,0); + assert( 0 ); + } +#endif + + if( ExprHasProperty(pExpr, EP_OuterON|EP_InnerON) ){ + Bitmask x = sqlite3WhereGetMask(pMaskSet, pExpr->w.iJoin); + if( ExprHasProperty(pExpr, EP_OuterON) ){ + prereqAll |= x; + extraRight = x-1; /* ON clause terms may not be used with an index + ** on left table of a LEFT JOIN. Ticket #3015 */ + if( (prereqAll>>1)>=x ){ + sqlite3ErrorMsg(pParse, "ON clause references tables to its right"); + return; + } + }else if( (prereqAll>>1)>=x ){ + /* The ON clause of an INNER JOIN references a table to its right. + ** Most other SQL database engines raise an error. But SQLite versions + ** 3.0 through 3.38 just put the ON clause constraint into the WHERE + ** clause and carried on. Beginning with 3.39, raise an error only + ** if there is a RIGHT or FULL JOIN in the query. This makes SQLite + ** more like other systems, and also preserves legacy. */ + if( ALWAYS(pSrc->nSrc>0) && (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){ + sqlite3ErrorMsg(pParse, "ON clause references tables to its right"); + return; + } + ExprClearProperty(pExpr, EP_InnerON); } } pTerm->prereqAll = prereqAll; @@ -150110,7 +153373,7 @@ static void exprAnalyze( pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask; }else if( op==TK_ISNULL - && !ExprHasProperty(pExpr,EP_FromJoin) + && !ExprHasProperty(pExpr,EP_OuterON) && 0==sqlite3ExprCanBeNull(pLeft) ){ assert( !ExprHasProperty(pExpr, EP_IntValue) ); @@ -150181,7 +153444,7 @@ static void exprAnalyze( else if( pExpr->op==TK_NOTNULL ){ if( pExpr->pLeft->op==TK_COLUMN && pExpr->pLeft->iColumn>=0 - && !ExprHasProperty(pExpr, EP_FromJoin) + && !ExprHasProperty(pExpr, EP_OuterON) ){ Expr *pNewExpr; Expr *pLeft = pExpr->pLeft; @@ -150304,7 +153567,10 @@ static void exprAnalyze( ** no longer used. ** ** This is only required if at least one side of the comparison operation - ** is not a sub-select. */ + ** is not a sub-select. + ** + ** tag-20220128a + */ if( (pExpr->op==TK_EQ || pExpr->op==TK_IS) && (nLeft = sqlite3ExprVectorSize(pExpr->pLeft))>1 && sqlite3ExprVectorSize(pExpr->pRight)==nLeft @@ -150321,12 +153587,12 @@ static void exprAnalyze( pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight); transferJoinMarkings(pNew, pExpr); - idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC); + idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC|TERM_SLICE); exprAnalyze(pSrc, pWC, idxNew); } pTerm = &pWC->a[idxTerm]; pTerm->wtFlags |= TERM_CODED|TERM_VIRTUAL; /* Disable the original */ - pTerm->eOperator = 0; + pTerm->eOperator = WO_ROWVAL; } /* If there is a vector IN term - e.g. "(a, b) IN (SELECT ...)" - create @@ -150351,7 +153617,7 @@ static void exprAnalyze( int i; for(i=0; ipLeft); i++){ int idxNew; - idxNew = whereClauseInsert(pWC, pExpr, TERM_VIRTUAL); + idxNew = whereClauseInsert(pWC, pExpr, TERM_VIRTUAL|TERM_SLICE); pWC->a[idxNew].u.x.iField = i+1; exprAnalyze(pSrc, pWC, idxNew); markTermAsChild(pWC, idxNew, idxTerm); @@ -150382,9 +153648,9 @@ static void exprAnalyze( Expr *pNewExpr; pNewExpr = sqlite3PExpr(pParse, TK_MATCH, 0, sqlite3ExprDup(db, pRight, 0)); - if( ExprHasProperty(pExpr, EP_FromJoin) && pNewExpr ){ - ExprSetProperty(pNewExpr, EP_FromJoin); - pNewExpr->iRightJoinTable = pExpr->iRightJoinTable; + if( ExprHasProperty(pExpr, EP_OuterON) && pNewExpr ){ + ExprSetProperty(pNewExpr, EP_OuterON); + pNewExpr->w.iJoin = pExpr->w.iJoin; } idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC); testcase( idxNew==0 ); @@ -150447,6 +153713,113 @@ SQLITE_PRIVATE void sqlite3WhereSplit(WhereClause *pWC, Expr *pExpr, u8 op){ } } +/* +** Add either a LIMIT (if eMatchOp==SQLITE_INDEX_CONSTRAINT_LIMIT) or +** OFFSET (if eMatchOp==SQLITE_INDEX_CONSTRAINT_OFFSET) term to the +** where-clause passed as the first argument. The value for the term +** is found in register iReg. +** +** In the common case where the value is a simple integer +** (example: "LIMIT 5 OFFSET 10") then the expression codes as a +** TK_INTEGER so that it will be available to sqlite3_vtab_rhs_value(). +** If not, then it codes as a TK_REGISTER expression. +*/ +static void whereAddLimitExpr( + WhereClause *pWC, /* Add the constraint to this WHERE clause */ + int iReg, /* Register that will hold value of the limit/offset */ + Expr *pExpr, /* Expression that defines the limit/offset */ + int iCsr, /* Cursor to which the constraint applies */ + int eMatchOp /* SQLITE_INDEX_CONSTRAINT_LIMIT or _OFFSET */ +){ + Parse *pParse = pWC->pWInfo->pParse; + sqlite3 *db = pParse->db; + Expr *pNew; + int iVal = 0; + + if( sqlite3ExprIsInteger(pExpr, &iVal) && iVal>=0 ){ + Expr *pVal = sqlite3Expr(db, TK_INTEGER, 0); + if( pVal==0 ) return; + ExprSetProperty(pVal, EP_IntValue); + pVal->u.iValue = iVal; + pNew = sqlite3PExpr(pParse, TK_MATCH, 0, pVal); + }else{ + Expr *pVal = sqlite3Expr(db, TK_REGISTER, 0); + if( pVal==0 ) return; + pVal->iTable = iReg; + pNew = sqlite3PExpr(pParse, TK_MATCH, 0, pVal); + } + if( pNew ){ + WhereTerm *pTerm; + int idx; + idx = whereClauseInsert(pWC, pNew, TERM_DYNAMIC|TERM_VIRTUAL); + pTerm = &pWC->a[idx]; + pTerm->leftCursor = iCsr; + pTerm->eOperator = WO_AUX; + pTerm->eMatchOp = eMatchOp; + } +} + +/* +** Possibly add terms corresponding to the LIMIT and OFFSET clauses of the +** SELECT statement passed as the second argument. These terms are only +** added if: +** +** 1. The SELECT statement has a LIMIT clause, and +** 2. The SELECT statement is not an aggregate or DISTINCT query, and +** 3. The SELECT statement has exactly one object in its from clause, and +** that object is a virtual table, and +** 4. There are no terms in the WHERE clause that will not be passed +** to the virtual table xBestIndex method. +** 5. The ORDER BY clause, if any, will be made available to the xBestIndex +** method. +** +** LIMIT and OFFSET terms are ignored by most of the planner code. They +** exist only so that they may be passed to the xBestIndex method of the +** single virtual table in the FROM clause of the SELECT. +*/ +SQLITE_PRIVATE void sqlite3WhereAddLimit(WhereClause *pWC, Select *p){ + assert( p==0 || (p->pGroupBy==0 && (p->selFlags & SF_Aggregate)==0) ); + if( (p && p->pLimit) /* 1 */ + && (p->selFlags & (SF_Distinct|SF_Aggregate))==0 /* 2 */ + && (p->pSrc->nSrc==1 && IsVirtual(p->pSrc->a[0].pTab)) /* 3 */ + ){ + ExprList *pOrderBy = p->pOrderBy; + int iCsr = p->pSrc->a[0].iCursor; + int ii; + + /* Check condition (4). Return early if it is not met. */ + for(ii=0; iinTerm; ii++){ + if( pWC->a[ii].wtFlags & TERM_CODED ){ + /* This term is a vector operation that has been decomposed into + ** other, subsequent terms. It can be ignored. See tag-20220128a */ + assert( pWC->a[ii].wtFlags & TERM_VIRTUAL ); + assert( pWC->a[ii].eOperator==WO_ROWVAL ); + continue; + } + if( pWC->a[ii].leftCursor!=iCsr ) return; + } + + /* Check condition (5). Return early if it is not met. */ + if( pOrderBy ){ + for(ii=0; iinExpr; ii++){ + Expr *pExpr = pOrderBy->a[ii].pExpr; + if( pExpr->op!=TK_COLUMN ) return; + if( pExpr->iTable!=iCsr ) return; + if( pOrderBy->a[ii].fg.sortFlags & KEYINFO_ORDER_BIGNULL ) return; + } + } + + /* All conditions are met. Add the terms to the where-clause object. */ + assert( p->pLimit->op==TK_LIMIT ); + whereAddLimitExpr(pWC, p->iLimit, p->pLimit->pLeft, + iCsr, SQLITE_INDEX_CONSTRAINT_LIMIT); + if( p->iOffset>0 ){ + whereAddLimitExpr(pWC, p->iOffset, p->pLimit->pRight, + iCsr, SQLITE_INDEX_CONSTRAINT_OFFSET); + } + } +} + /* ** Initialize a preallocated WhereClause structure. */ @@ -150458,6 +153831,7 @@ SQLITE_PRIVATE void sqlite3WhereClauseInit( pWC->hasOr = 0; pWC->pOuter = 0; pWC->nTerm = 0; + pWC->nBase = 0; pWC->nSlot = ArraySize(pWC->aStatic); pWC->a = pWC->aStatic; } @@ -150468,22 +153842,36 @@ SQLITE_PRIVATE void sqlite3WhereClauseInit( ** sqlite3WhereClauseInit(). */ SQLITE_PRIVATE void sqlite3WhereClauseClear(WhereClause *pWC){ - int i; - WhereTerm *a; sqlite3 *db = pWC->pWInfo->pParse->db; - for(i=pWC->nTerm-1, a=pWC->a; i>=0; i--, a++){ - if( a->wtFlags & TERM_DYNAMIC ){ - sqlite3ExprDelete(db, a->pExpr); + assert( pWC->nTerm>=pWC->nBase ); + if( pWC->nTerm>0 ){ + WhereTerm *a = pWC->a; + WhereTerm *aLast = &pWC->a[pWC->nTerm-1]; +#ifdef SQLITE_DEBUG + int i; + /* Verify that every term past pWC->nBase is virtual */ + for(i=pWC->nBase; inTerm; i++){ + assert( (pWC->a[i].wtFlags & TERM_VIRTUAL)!=0 ); } - if( a->wtFlags & TERM_ORINFO ){ - whereOrInfoDelete(db, a->u.pOrInfo); - }else if( a->wtFlags & TERM_ANDINFO ){ - whereAndInfoDelete(db, a->u.pAndInfo); +#endif + while(1){ + assert( a->eMatchOp==0 || a->eOperator==WO_AUX ); + if( a->wtFlags & TERM_DYNAMIC ){ + sqlite3ExprDelete(db, a->pExpr); + } + if( a->wtFlags & (TERM_ORINFO|TERM_ANDINFO) ){ + if( a->wtFlags & TERM_ORINFO ){ + assert( (a->wtFlags & TERM_ANDINFO)==0 ); + whereOrInfoDelete(db, a->u.pOrInfo); + }else{ + assert( (a->wtFlags & TERM_ANDINFO)!=0 ); + whereAndInfoDelete(db, a->u.pAndInfo); + } + } + if( a==aLast ) break; + a++; } } - if( pWC->a!=pWC->aStatic ){ - sqlite3DbFree(db, pWC->a); - } } @@ -150491,15 +153879,38 @@ SQLITE_PRIVATE void sqlite3WhereClauseClear(WhereClause *pWC){ ** These routines walk (recursively) an expression tree and generate ** a bitmask indicating which tables are used in that expression ** tree. +** +** sqlite3WhereExprUsage(MaskSet, Expr) -> +** +** Return a Bitmask of all tables referenced by Expr. Expr can be +** be NULL, in which case 0 is returned. +** +** sqlite3WhereExprUsageNN(MaskSet, Expr) -> +** +** Same as sqlite3WhereExprUsage() except that Expr must not be +** NULL. The "NN" suffix on the name stands for "Not Null". +** +** sqlite3WhereExprListUsage(MaskSet, ExprList) -> +** +** Return a Bitmask of all tables referenced by every expression +** in the expression list ExprList. ExprList can be NULL, in which +** case 0 is returned. +** +** sqlite3WhereExprUsageFull(MaskSet, ExprList) -> +** +** Internal use only. Called only by sqlite3WhereExprUsageNN() for +** complex expressions that require pushing register values onto +** the stack. Many calls to sqlite3WhereExprUsageNN() do not need +** the more complex analysis done by this routine. Hence, the +** computations done by this routine are broken out into a separate +** "no-inline" function to avoid the stack push overhead in the +** common case where it is not needed. */ -SQLITE_PRIVATE Bitmask sqlite3WhereExprUsageNN(WhereMaskSet *pMaskSet, Expr *p){ +static SQLITE_NOINLINE Bitmask sqlite3WhereExprUsageFull( + WhereMaskSet *pMaskSet, + Expr *p +){ Bitmask mask; - if( p->op==TK_COLUMN && !ExprHasProperty(p, EP_FixedCol) ){ - return sqlite3WhereGetMask(pMaskSet, p->iTable); - }else if( ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){ - assert( p->op!=TK_IF_NULL_ROW ); - return 0; - } mask = (p->op==TK_IF_NULL_ROW) ? sqlite3WhereGetMask(pMaskSet, p->iTable) : 0; if( p->pLeft ) mask |= sqlite3WhereExprUsageNN(pMaskSet, p->pLeft); if( p->pRight ){ @@ -150521,6 +153932,15 @@ SQLITE_PRIVATE Bitmask sqlite3WhereExprUsageNN(WhereMaskSet *pMaskSet, Expr *p){ #endif return mask; } +SQLITE_PRIVATE Bitmask sqlite3WhereExprUsageNN(WhereMaskSet *pMaskSet, Expr *p){ + if( p->op==TK_COLUMN && !ExprHasProperty(p, EP_FixedCol) ){ + return sqlite3WhereGetMask(pMaskSet, p->iTable); + }else if( ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){ + assert( p->op!=TK_IF_NULL_ROW ); + return 0; + } + return sqlite3WhereExprUsageFull(pMaskSet, p); +} SQLITE_PRIVATE Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){ return p ? sqlite3WhereExprUsageNN(pMaskSet,p) : 0; } @@ -150578,6 +153998,7 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs( if( pArgs==0 ) return; for(j=k=0; jnExpr; j++){ Expr *pRhs; + u32 joinType; while( knCol && (pTab->aCol[k].colFlags & COLFLAG_HIDDEN)==0 ){k++;} if( k>=pTab->nCol ){ sqlite3ErrorMsg(pParse, "too many arguments on %s() - max %d", @@ -150590,12 +154011,16 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs( pColRef->iColumn = k++; assert( ExprUseYTab(pColRef) ); pColRef->y.pTab = pTab; + pItem->colUsed |= sqlite3ExprColUsed(pColRef); pRhs = sqlite3PExpr(pParse, TK_UPLUS, sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0); pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, pRhs); - if( pItem->fg.jointype & JT_LEFT ){ - sqlite3SetJoinExpr(pTerm, pItem->iCursor); + if( pItem->fg.jointype & (JT_LEFT|JT_LTORJ) ){ + joinType = EP_OuterON; + }else{ + joinType = EP_InnerON; } + sqlite3SetJoinExpr(pTerm, pItem->iCursor, joinType); whereClauseInsert(pWC, pTerm, TERM_DYNAMIC); } } @@ -150634,8 +154059,14 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs( */ typedef struct HiddenIndexInfo HiddenIndexInfo; struct HiddenIndexInfo { - WhereClause *pWC; /* The Where clause being analyzed */ - Parse *pParse; /* The parsing context */ + WhereClause *pWC; /* The Where clause being analyzed */ + Parse *pParse; /* The parsing context */ + int eDistinct; /* Value to return from sqlite3_vtab_distinct() */ + u32 mIn; /* Mask of terms that are IN (...) */ + u32 mHandleIn; /* Terms that vtab will handle as IN (...) */ + sqlite3_value *aRhs[1]; /* RHS values for constraints. MUST BE LAST + ** because extra space is allocated to hold up + ** to nTerm such values */ }; /* Forward declaration of methods */ @@ -150700,7 +154131,7 @@ SQLITE_PRIVATE int sqlite3WhereOrderByLimitOptLabel(WhereInfo *pWInfo){ } pInner = &pWInfo->a[pWInfo->nLevel-1]; assert( pInner->addrNxt!=0 ); - return pInner->addrNxt; + return pInner->pRJ ? pWInfo->iContinue : pInner->addrNxt; } /* @@ -150838,7 +154269,12 @@ static int whereOrInsert( SQLITE_PRIVATE Bitmask sqlite3WhereGetMask(WhereMaskSet *pMaskSet, int iCursor){ int i; assert( pMaskSet->n<=(int)sizeof(Bitmask)*8 ); - for(i=0; in; i++){ + assert( pMaskSet->n>0 || pMaskSet->ix[0]<0 ); + assert( iCursor>=-1 ); + if( pMaskSet->ix[0]==iCursor ){ + return 1; + } + for(i=1; in; i++){ if( pMaskSet->ix[i]==iCursor ){ return MASKBIT(i); } @@ -150846,6 +154282,30 @@ SQLITE_PRIVATE Bitmask sqlite3WhereGetMask(WhereMaskSet *pMaskSet, int iCursor){ return 0; } +/* Allocate memory that is automatically freed when pWInfo is freed. +*/ +SQLITE_PRIVATE void *sqlite3WhereMalloc(WhereInfo *pWInfo, u64 nByte){ + WhereMemBlock *pBlock; + pBlock = sqlite3DbMallocRawNN(pWInfo->pParse->db, nByte+sizeof(*pBlock)); + if( pBlock ){ + pBlock->pNext = pWInfo->pMemToFree; + pBlock->sz = nByte; + pWInfo->pMemToFree = pBlock; + pBlock++; + } + return (void*)pBlock; +} +SQLITE_PRIVATE void *sqlite3WhereRealloc(WhereInfo *pWInfo, void *pOld, u64 nByte){ + void *pNew = sqlite3WhereMalloc(pWInfo, nByte); + if( pNew && pOld ){ + WhereMemBlock *pOldBlk = (WhereMemBlock*)pOld; + pOldBlk--; + assert( pOldBlk->szsz); + } + return pNew; +} + /* ** Create a new mask for cursor iCursor. ** @@ -150899,7 +154359,7 @@ static WhereTerm *whereScanNext(WhereScan *pScan){ && (iColumn!=XN_EXPR || sqlite3ExprCompareSkip(pTerm->pExpr->pLeft, pScan->pIdxExpr,iCur)==0) - && (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin)) + && (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_OuterON)) ){ if( (pTerm->eOperator & WO_EQUIV)!=0 && pScan->nEquivaiCur) @@ -151023,16 +154483,16 @@ static WhereTerm *whereScanInit( if( pIdx ){ int j = iColumn; iColumn = pIdx->aiColumn[j]; - if( iColumn==XN_EXPR ){ - pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr; - pScan->zCollName = pIdx->azColl[j]; - pScan->aiColumn[0] = XN_EXPR; - return whereScanInitIndexExpr(pScan); - }else if( iColumn==pIdx->pTable->iPKey ){ + if( iColumn==pIdx->pTable->iPKey ){ iColumn = XN_ROWID; }else if( iColumn>=0 ){ pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity; pScan->zCollName = pIdx->azColl[j]; + }else if( iColumn==XN_EXPR ){ + pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr; + pScan->zCollName = pIdx->azColl[j]; + pScan->aiColumn[0] = XN_EXPR; + return whereScanInitIndexExpr(pScan); } }else if( iColumn==XN_EXPR ){ return 0; @@ -151251,6 +154711,7 @@ static void translateColumnToCopy( pOp->p1 = pOp->p2 + iRegister; pOp->p2 = pOp->p3; pOp->p3 = 0; + pOp->p5 = 2; /* Cause the MEM_Subtype flag to be cleared */ }else if( pOp->opcode==OP_Rowid ){ pOp->opcode = OP_Sequence; pOp->p1 = iAutoidxCur; @@ -151275,12 +154736,14 @@ static void whereTraceIndexInfoInputs(sqlite3_index_info *p){ int i; if( !sqlite3WhereTrace ) return; for(i=0; inConstraint; i++){ - sqlite3DebugPrintf(" constraint[%d]: col=%d termid=%d op=%d usabled=%d\n", + sqlite3DebugPrintf( + " constraint[%d]: col=%d termid=%d op=%d usabled=%d collseq=%s\n", i, p->aConstraint[i].iColumn, p->aConstraint[i].iTermOffset, p->aConstraint[i].op, - p->aConstraint[i].usable); + p->aConstraint[i].usable, + sqlite3_vtab_collation(p,i)); } for(i=0; inOrderBy; i++){ sqlite3DebugPrintf(" orderby[%d]: col=%d desc=%d\n", @@ -151316,21 +154779,24 @@ static void whereTraceIndexInfoOutputs(sqlite3_index_info *p){ ** index existed. */ static int termCanDriveIndex( - WhereTerm *pTerm, /* WHERE clause term to check */ - SrcItem *pSrc, /* Table we are trying to access */ - Bitmask notReady /* Tables in outer loops of the join */ + const WhereTerm *pTerm, /* WHERE clause term to check */ + const SrcItem *pSrc, /* Table we are trying to access */ + const Bitmask notReady /* Tables in outer loops of the join */ ){ char aff; if( pTerm->leftCursor!=pSrc->iCursor ) return 0; if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) return 0; - if( (pSrc->fg.jointype & JT_LEFT) - && !ExprHasProperty(pTerm->pExpr, EP_FromJoin) - && (pTerm->eOperator & WO_IS) - ){ - /* Cannot use an IS term from the WHERE clause as an index driver for - ** the RHS of a LEFT JOIN. Such a term can only be used if it is from - ** the ON clause. */ - return 0; + assert( (pSrc->fg.jointype & JT_RIGHT)==0 ); + if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0 ){ + testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_LEFT ); + testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_LTORJ ); + testcase( ExprHasProperty(pTerm->pExpr, EP_OuterON) ) + testcase( ExprHasProperty(pTerm->pExpr, EP_InnerON) ); + if( !ExprHasProperty(pTerm->pExpr, EP_OuterON|EP_InnerON) + || pTerm->pExpr->w.iJoin != pSrc->iCursor + ){ + return 0; /* See tag-20191211-001 */ + } } if( (pTerm->prereqRight & notReady)!=0 ) return 0; assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 ); @@ -151349,11 +154815,11 @@ static int termCanDriveIndex( ** and to set up the WhereLevel object pLevel so that the code generator ** makes use of the automatic index. */ -static void constructAutomaticIndex( +static SQLITE_NOINLINE void constructAutomaticIndex( Parse *pParse, /* The parsing context */ - WhereClause *pWC, /* The WHERE clause */ - SrcItem *pSrc, /* The FROM clause term to get the next index */ - Bitmask notReady, /* Mask of cursors that are not available */ + const WhereClause *pWC, /* The WHERE clause */ + const SrcItem *pSrc, /* The FROM clause term to get the next index */ + const Bitmask notReady, /* Mask of cursors that are not available */ WhereLevel *pLevel /* Write new index here */ ){ int nKeyCol; /* Number of columns in the constructed index */ @@ -151395,13 +154861,12 @@ static void constructAutomaticIndex( idxCols = 0; for(pTerm=pWC->a; pTermpExpr; - assert( !ExprHasProperty(pExpr, EP_FromJoin) /* prereq always non-zero */ - || pExpr->iRightJoinTable!=pSrc->iCursor /* for the right-hand */ - || pLoop->prereq!=0 ); /* table of a LEFT JOIN */ - if( pLoop->prereq==0 - && (pTerm->wtFlags & TERM_VIRTUAL)==0 - && !ExprHasProperty(pExpr, EP_FromJoin) - && sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor) ){ + /* Make the automatic index a partial index if there are terms in the + ** WHERE clause (or the ON clause of a LEFT join) that constrain which + ** rows of the target table (pSrc) that can be used. */ + if( (pTerm->wtFlags & TERM_VIRTUAL)==0 + && sqlite3ExprIsTableConstraint(pExpr, pSrc) + ){ pPartial = sqlite3ExprAnd(pParse, pPartial, sqlite3ExprDup(pParse->db, pExpr, 0)); } @@ -151508,6 +154973,10 @@ static void constructAutomaticIndex( sqlite3VdbeAddOp2(v, OP_OpenAutoindex, pLevel->iIdxCur, nKeyCol+1); sqlite3VdbeSetP4KeyInfo(pParse, pIdx); VdbeComment((v, "for %s", pTable->zName)); + if( OptimizationEnabled(pParse->db, SQLITE_BloomFilter) ){ + pLevel->regFilter = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Blob, 10000, pLevel->regFilter); + } /* Fill the automatic index with content */ pTabItem = &pWC->pWInfo->pTabList->a[pLevel->iFrom]; @@ -151530,6 +154999,10 @@ static void constructAutomaticIndex( regBase = sqlite3GenerateIndexKey( pParse, pIdx, pLevel->iTabCur, regRecord, 0, 0, 0, 0 ); + if( pLevel->regFilter ){ + sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0, + regBase, pLoop->u.btree.nEq); + } sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord); sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); if( pPartial ) sqlite3VdbeResolveLabel(v, iContinue); @@ -151556,22 +155029,149 @@ static void constructAutomaticIndex( } #endif /* SQLITE_OMIT_AUTOMATIC_INDEX */ +/* +** Generate bytecode that will initialize a Bloom filter that is appropriate +** for pLevel. +** +** If there are inner loops within pLevel that have the WHERE_BLOOMFILTER +** flag set, initialize a Bloomfilter for them as well. Except don't do +** this recursive initialization if the SQLITE_BloomPulldown optimization has +** been turned off. +** +** When the Bloom filter is initialized, the WHERE_BLOOMFILTER flag is cleared +** from the loop, but the regFilter value is set to a register that implements +** the Bloom filter. When regFilter is positive, the +** sqlite3WhereCodeOneLoopStart() will generate code to test the Bloom filter +** and skip the subsequence B-Tree seek if the Bloom filter indicates that +** no matching rows exist. +** +** This routine may only be called if it has previously been determined that +** the loop would benefit from a Bloom filter, and the WHERE_BLOOMFILTER bit +** is set. +*/ +static SQLITE_NOINLINE void sqlite3ConstructBloomFilter( + WhereInfo *pWInfo, /* The WHERE clause */ + int iLevel, /* Index in pWInfo->a[] that is pLevel */ + WhereLevel *pLevel, /* Make a Bloom filter for this FROM term */ + Bitmask notReady /* Loops that are not ready */ +){ + int addrOnce; /* Address of opening OP_Once */ + int addrTop; /* Address of OP_Rewind */ + int addrCont; /* Jump here to skip a row */ + const WhereTerm *pTerm; /* For looping over WHERE clause terms */ + const WhereTerm *pWCEnd; /* Last WHERE clause term */ + Parse *pParse = pWInfo->pParse; /* Parsing context */ + Vdbe *v = pParse->pVdbe; /* VDBE under construction */ + WhereLoop *pLoop = pLevel->pWLoop; /* The loop being coded */ + int iCur; /* Cursor for table getting the filter */ + + assert( pLoop!=0 ); + assert( v!=0 ); + assert( pLoop->wsFlags & WHERE_BLOOMFILTER ); + + addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); + do{ + const SrcItem *pItem; + const Table *pTab; + u64 sz; + sqlite3WhereExplainBloomFilter(pParse, pWInfo, pLevel); + addrCont = sqlite3VdbeMakeLabel(pParse); + iCur = pLevel->iTabCur; + pLevel->regFilter = ++pParse->nMem; + + /* The Bloom filter is a Blob held in a register. Initialize it + ** to zero-filled blob of at least 80K bits, but maybe more if the + ** estimated size of the table is larger. We could actually + ** measure the size of the table at run-time using OP_Count with + ** P3==1 and use that value to initialize the blob. But that makes + ** testing complicated. By basing the blob size on the value in the + ** sqlite_stat1 table, testing is much easier. + */ + pItem = &pWInfo->pTabList->a[pLevel->iFrom]; + assert( pItem!=0 ); + pTab = pItem->pTab; + assert( pTab!=0 ); + sz = sqlite3LogEstToInt(pTab->nRowLogEst); + if( sz<10000 ){ + sz = 10000; + }else if( sz>10000000 ){ + sz = 10000000; + } + sqlite3VdbeAddOp2(v, OP_Blob, (int)sz, pLevel->regFilter); + + addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v); + pWCEnd = &pWInfo->sWC.a[pWInfo->sWC.nTerm]; + for(pTerm=pWInfo->sWC.a; pTermpExpr; + if( (pTerm->wtFlags & TERM_VIRTUAL)==0 + && sqlite3ExprIsTableConstraint(pExpr, pItem) + ){ + sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL); + } + } + if( pLoop->wsFlags & WHERE_IPK ){ + int r1 = sqlite3GetTempReg(pParse); + sqlite3VdbeAddOp2(v, OP_Rowid, iCur, r1); + sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0, r1, 1); + sqlite3ReleaseTempReg(pParse, r1); + }else{ + Index *pIdx = pLoop->u.btree.pIndex; + int n = pLoop->u.btree.nEq; + int r1 = sqlite3GetTempRange(pParse, n); + int jj; + for(jj=0; jjaiColumn[jj]; + assert( pIdx->pTable==pItem->pTab ); + sqlite3ExprCodeGetColumnOfTable(v, pIdx->pTable, iCur, iCol,r1+jj); + } + sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0, r1, n); + sqlite3ReleaseTempRange(pParse, r1, n); + } + sqlite3VdbeResolveLabel(v, addrCont); + sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); + VdbeCoverage(v); + sqlite3VdbeJumpHere(v, addrTop); + pLoop->wsFlags &= ~WHERE_BLOOMFILTER; + if( OptimizationDisabled(pParse->db, SQLITE_BloomPulldown) ) break; + while( ++iLevel < pWInfo->nLevel ){ + const SrcItem *pTabItem; + pLevel = &pWInfo->a[iLevel]; + pTabItem = &pWInfo->pTabList->a[pLevel->iFrom]; + if( pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ) ) continue; + pLoop = pLevel->pWLoop; + if( NEVER(pLoop==0) ) continue; + if( pLoop->prereq & notReady ) continue; + if( (pLoop->wsFlags & (WHERE_BLOOMFILTER|WHERE_COLUMN_IN)) + ==WHERE_BLOOMFILTER + ){ + /* This is a candidate for bloom-filter pull-down (early evaluation). + ** The test that WHERE_COLUMN_IN is omitted is important, as we are + ** not able to do early evaluation of bloom filters that make use of + ** the IN operator */ + break; + } + } + }while( iLevel < pWInfo->nLevel ); + sqlite3VdbeJumpHere(v, addrOnce); +} + + #ifndef SQLITE_OMIT_VIRTUALTABLE /* ** Allocate and populate an sqlite3_index_info structure. It is the ** responsibility of the caller to eventually release the structure -** by passing the pointer returned by this function to sqlite3_free(). +** by passing the pointer returned by this function to freeIndexInfo(). */ static sqlite3_index_info *allocateIndexInfo( - Parse *pParse, /* The parsing context */ + WhereInfo *pWInfo, /* The WHERE clause */ WhereClause *pWC, /* The WHERE clause being analyzed */ Bitmask mUnusable, /* Ignore terms with these prereqs */ SrcItem *pSrc, /* The FROM clause term that is the vtab */ - ExprList *pOrderBy, /* The ORDER BY clause */ u16 *pmNoOmit /* Mask of terms not to omit */ ){ int i, j; int nTerm; + Parse *pParse = pWInfo->pParse; struct sqlite3_index_constraint *pIdxCons; struct sqlite3_index_orderby *pIdxOrderBy; struct sqlite3_index_constraint_usage *pUsage; @@ -151580,10 +155180,21 @@ static sqlite3_index_info *allocateIndexInfo( int nOrderBy; sqlite3_index_info *pIdxInfo; u16 mNoOmit = 0; + const Table *pTab; + int eDistinct = 0; + ExprList *pOrderBy = pWInfo->pOrderBy; + + assert( pSrc!=0 ); + pTab = pSrc->pTab; + assert( pTab!=0 ); + assert( IsVirtual(pTab) ); - /* Count the number of possible WHERE clause constraints referring - ** to this virtual table */ + /* Find all WHERE clause constraints referring to this virtual table. + ** Mark each term with the TERM_OK flag. Set nTerm to the number of + ** terms found. + */ for(i=nTerm=0, pTerm=pWC->a; inTerm; i++, pTerm++){ + pTerm->wtFlags &= ~TERM_OK; if( pTerm->leftCursor != pSrc->iCursor ) continue; if( pTerm->prereqRight & mUnusable ) continue; assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) ); @@ -151593,9 +155204,29 @@ static sqlite3_index_info *allocateIndexInfo( testcase( pTerm->eOperator & WO_ALL ); if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue; if( pTerm->wtFlags & TERM_VNULL ) continue; + assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 ); - assert( pTerm->u.x.leftColumn>=(-1) ); + assert( pTerm->u.x.leftColumn>=XN_ROWID ); + assert( pTerm->u.x.leftColumnnCol ); + + /* tag-20191211-002: WHERE-clause constraints are not useful to the + ** right-hand table of a LEFT JOIN nor to the either table of a + ** RIGHT JOIN. See tag-20191211-001 for the + ** equivalent restriction for ordinary tables. */ + if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0 ){ + testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_LEFT ); + testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_RIGHT ); + testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_LTORJ ); + testcase( ExprHasProperty(pTerm->pExpr, EP_OuterON) ); + testcase( ExprHasProperty(pTerm->pExpr, EP_InnerON) ); + if( !ExprHasProperty(pTerm->pExpr, EP_OuterON|EP_InnerON) + || pTerm->pExpr->w.iJoin != pSrc->iCursor + ){ + continue; + } + } nTerm++; + pTerm->wtFlags |= TERM_OK; } /* If the ORDER BY clause contains only columns in the current @@ -151607,11 +155238,49 @@ static sqlite3_index_info *allocateIndexInfo( int n = pOrderBy->nExpr; for(i=0; ia[i].pExpr; - if( pExpr->op!=TK_COLUMN || pExpr->iTable!=pSrc->iCursor ) break; - if( pOrderBy->a[i].sortFlags & KEYINFO_ORDER_BIGNULL ) break; + Expr *pE2; + + /* Skip over constant terms in the ORDER BY clause */ + if( sqlite3ExprIsConstant(pExpr) ){ + continue; + } + + /* Virtual tables are unable to deal with NULLS FIRST */ + if( pOrderBy->a[i].fg.sortFlags & KEYINFO_ORDER_BIGNULL ) break; + + /* First case - a direct column references without a COLLATE operator */ + if( pExpr->op==TK_COLUMN && pExpr->iTable==pSrc->iCursor ){ + assert( pExpr->iColumn>=XN_ROWID && pExpr->iColumnnCol ); + continue; + } + + /* 2nd case - a column reference with a COLLATE operator. Only match + ** of the COLLATE operator matches the collation of the column. */ + if( pExpr->op==TK_COLLATE + && (pE2 = pExpr->pLeft)->op==TK_COLUMN + && pE2->iTable==pSrc->iCursor + ){ + const char *zColl; /* The collating sequence name */ + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + assert( pExpr->u.zToken!=0 ); + assert( pE2->iColumn>=XN_ROWID && pE2->iColumnnCol ); + pExpr->iColumn = pE2->iColumn; + if( pE2->iColumn<0 ) continue; /* Collseq does not matter for rowid */ + zColl = sqlite3ColumnColl(&pTab->aCol[pE2->iColumn]); + if( zColl==0 ) zColl = sqlite3StrBINARY; + if( sqlite3_stricmp(pExpr->u.zToken, zColl)==0 ) continue; + } + + /* No matches cause a break out of the loop */ + break; } - if( i==n){ + if( i==n ){ nOrderBy = n; + if( (pWInfo->wctrlFlags & WHERE_DISTINCTBY) ){ + eDistinct = 2 + ((pWInfo->wctrlFlags & WHERE_SORTBYGROUP)!=0); + }else if( pWInfo->wctrlFlags & WHERE_GROUPBY ){ + eDistinct = 1; + } } } @@ -151619,47 +155288,35 @@ static sqlite3_index_info *allocateIndexInfo( */ pIdxInfo = sqlite3DbMallocZero(pParse->db, sizeof(*pIdxInfo) + (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm - + sizeof(*pIdxOrderBy)*nOrderBy + sizeof(*pHidden) ); + + sizeof(*pIdxOrderBy)*nOrderBy + sizeof(*pHidden) + + sizeof(sqlite3_value*)*nTerm ); if( pIdxInfo==0 ){ sqlite3ErrorMsg(pParse, "out of memory"); return 0; } pHidden = (struct HiddenIndexInfo*)&pIdxInfo[1]; - pIdxCons = (struct sqlite3_index_constraint*)&pHidden[1]; + pIdxCons = (struct sqlite3_index_constraint*)&pHidden->aRhs[nTerm]; pIdxOrderBy = (struct sqlite3_index_orderby*)&pIdxCons[nTerm]; pUsage = (struct sqlite3_index_constraint_usage*)&pIdxOrderBy[nOrderBy]; - pIdxInfo->nOrderBy = nOrderBy; pIdxInfo->aConstraint = pIdxCons; pIdxInfo->aOrderBy = pIdxOrderBy; pIdxInfo->aConstraintUsage = pUsage; pHidden->pWC = pWC; pHidden->pParse = pParse; + pHidden->eDistinct = eDistinct; + pHidden->mIn = 0; for(i=j=0, pTerm=pWC->a; inTerm; i++, pTerm++){ u16 op; - if( pTerm->leftCursor != pSrc->iCursor ) continue; - if( pTerm->prereqRight & mUnusable ) continue; - assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) ); - testcase( pTerm->eOperator & WO_IN ); - testcase( pTerm->eOperator & WO_IS ); - testcase( pTerm->eOperator & WO_ISNULL ); - testcase( pTerm->eOperator & WO_ALL ); - if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue; - if( pTerm->wtFlags & TERM_VNULL ) continue; - - /* tag-20191211-002: WHERE-clause constraints are not useful to the - ** right-hand table of a LEFT JOIN. See tag-20191211-001 for the - ** equivalent restriction for ordinary tables. */ - if( (pSrc->fg.jointype & JT_LEFT)!=0 - && !ExprHasProperty(pTerm->pExpr, EP_FromJoin) - ){ - continue; - } - assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 ); - assert( pTerm->u.x.leftColumn>=(-1) ); + if( (pTerm->wtFlags & TERM_OK)==0 ) continue; pIdxCons[j].iColumn = pTerm->u.x.leftColumn; pIdxCons[j].iTermOffset = i; op = pTerm->eOperator & WO_ALL; - if( op==WO_IN ) op = WO_EQ; + if( op==WO_IN ){ + if( (pTerm->wtFlags & TERM_SLICE)==0 ){ + pHidden->mIn |= SMASKBIT32(j); + } + op = WO_EQ; + } if( op==WO_AUX ){ pIdxCons[j].op = pTerm->eMatchOp; }else if( op & (WO_ISNULL|WO_IS) ){ @@ -151692,17 +155349,42 @@ static sqlite3_index_info *allocateIndexInfo( j++; } + assert( j==nTerm ); pIdxInfo->nConstraint = j; - for(i=0; ia[i].pExpr; - pIdxOrderBy[i].iColumn = pExpr->iColumn; - pIdxOrderBy[i].desc = pOrderBy->a[i].sortFlags & KEYINFO_ORDER_DESC; + if( sqlite3ExprIsConstant(pExpr) ) continue; + assert( pExpr->op==TK_COLUMN + || (pExpr->op==TK_COLLATE && pExpr->pLeft->op==TK_COLUMN + && pExpr->iColumn==pExpr->pLeft->iColumn) ); + pIdxOrderBy[j].iColumn = pExpr->iColumn; + pIdxOrderBy[j].desc = pOrderBy->a[i].fg.sortFlags & KEYINFO_ORDER_DESC; + j++; } + pIdxInfo->nOrderBy = j; *pmNoOmit = mNoOmit; return pIdxInfo; } +/* +** Free an sqlite3_index_info structure allocated by allocateIndexInfo() +** and possibly modified by xBestIndex methods. +*/ +static void freeIndexInfo(sqlite3 *db, sqlite3_index_info *pIdxInfo){ + HiddenIndexInfo *pHidden; + int i; + assert( pIdxInfo!=0 ); + pHidden = (HiddenIndexInfo*)&pIdxInfo[1]; + assert( pHidden->pParse!=0 ); + assert( pHidden->pParse->db==db ); + for(i=0; inConstraint; i++){ + sqlite3ValueFree(pHidden->aRhs[i]); /* IMP: R-14553-25174 */ + pHidden->aRhs[i] = 0; + } + sqlite3DbFree(db, pIdxInfo); +} + /* ** The table object reference passed as the second argument to this function ** must represent a virtual table. This function invokes the xBestIndex() @@ -151724,7 +155406,9 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){ int rc; whereTraceIndexInfoInputs(p); + pParse->db->nSchemaLock++; rc = pVtab->pModule->xBestIndex(pVtab, p); + pParse->db->nSchemaLock--; whereTraceIndexInfoOutputs(p); if( rc!=SQLITE_OK && rc!=SQLITE_CONSTRAINT ){ @@ -151778,7 +155462,7 @@ static int whereKeyStats( #endif assert( pRec!=0 ); assert( pIdx->nSample>0 ); - assert( pRec->nField>0 && pRec->nField<=pIdx->nSampleCol ); + assert( pRec->nField>0 ); /* Do a binary search to find the first sample greater than or equal ** to pRec. If pRec contains a single field, the set of samples to search @@ -151824,7 +155508,7 @@ static int whereKeyStats( ** it is extended to two fields. The duplicates that this creates do not ** cause any problems. */ - nField = pRec->nField; + nField = MIN(pRec->nField, pIdx->nSample); iCol = 0; iSample = pIdx->nSample * nField; do{ @@ -152415,7 +156099,7 @@ SQLITE_PRIVATE void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm){ memcpy(zType, "....", 5); if( pTerm->wtFlags & TERM_VIRTUAL ) zType[0] = 'V'; if( pTerm->eOperator & WO_EQUIV ) zType[1] = 'E'; - if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) zType[2] = 'L'; + if( ExprHasProperty(pTerm->pExpr, EP_OuterON) ) zType[2] = 'L'; if( pTerm->wtFlags & TERM_CODED ) zType[3] = 'C'; if( pTerm->eOperator & WO_SINGLE ){ assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 ); @@ -152498,9 +156182,9 @@ SQLITE_PRIVATE void sqlite3WhereLoopPrint(WhereLoop *p, WhereClause *pWC){ sqlite3_free(z); } if( p->wsFlags & WHERE_SKIPSCAN ){ - sqlite3DebugPrintf(" f %05x %d-%d", p->wsFlags, p->nLTerm,p->nSkip); + sqlite3DebugPrintf(" f %06x %d-%d", p->wsFlags, p->nLTerm,p->nSkip); }else{ - sqlite3DebugPrintf(" f %05x N %d", p->wsFlags, p->nLTerm); + sqlite3DebugPrintf(" f %06x N %d", p->wsFlags, p->nLTerm); } sqlite3DebugPrintf(" cost %d,%d,%d\n", p->rSetup, p->rRun, p->nOut); if( p->nLTerm && (sqlite3WhereTrace & 0x100)!=0 ){ @@ -152596,15 +156280,7 @@ static void whereLoopDelete(sqlite3 *db, WhereLoop *p){ ** Free a WhereInfo structure */ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){ - int i; assert( pWInfo!=0 ); - for(i=0; inLevel; i++){ - WhereLevel *pLevel = &pWInfo->a[i]; - if( pLevel->pWLoop && (pLevel->pWLoop->wsFlags & WHERE_IN_ABLE)!=0 ){ - assert( (pLevel->pWLoop->wsFlags & WHERE_MULTI_OR)==0 ); - sqlite3DbFree(db, pLevel->u.in.aInLoop); - } - } sqlite3WhereClauseClear(&pWInfo->sWC); while( pWInfo->pLoops ){ WhereLoop *p = pWInfo->pLoops; @@ -152612,6 +156288,11 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){ whereLoopDelete(db, p); } assert( pWInfo->pExprMods==0 ); + while( pWInfo->pMemToFree ){ + WhereMemBlock *pNext = pWInfo->pMemToFree->pNext; + sqlite3DbFreeNN(db, pWInfo->pMemToFree); + pWInfo->pMemToFree = pNext; + } sqlite3DbFreeNN(db, pWInfo); } @@ -152960,11 +156641,11 @@ static void whereLoopOutputAdjust( LogEst iReduce = 0; /* pLoop->nOut should not exceed nRow-iReduce */ assert( (pLoop->wsFlags & WHERE_AUTO_INDEX)==0 ); - for(i=pWC->nTerm, pTerm=pWC->a; i>0; i--, pTerm++){ + for(i=pWC->nBase, pTerm=pWC->a; i>0; i--, pTerm++){ assert( pTerm!=0 ); - if( (pTerm->wtFlags & TERM_VIRTUAL)!=0 ) break; - if( (pTerm->prereqAll & pLoop->maskSelf)==0 ) continue; if( (pTerm->prereqAll & notAllowed)!=0 ) continue; + if( (pTerm->prereqAll & pLoop->maskSelf)==0 ) continue; + if( (pTerm->wtFlags & TERM_VIRTUAL)!=0 ) continue; for(j=pLoop->nLTerm-1; j>=0; j--){ pX = pLoop->aLTerm[j]; if( pX==0 ) continue; @@ -152972,6 +156653,23 @@ static void whereLoopOutputAdjust( if( pX->iParent>=0 && (&pWC->a[pX->iParent])==pTerm ) break; } if( j<0 ){ + if( pLoop->maskSelf==pTerm->prereqAll ){ + /* If there are extra terms in the WHERE clause not used by an index + ** that depend only on the table being scanned, and that will tend to + ** cause many rows to be omitted, then mark that table as + ** "self-culling". + ** + ** 2022-03-24: Self-culling only applies if either the extra terms + ** are straight comparison operators that are non-true with NULL + ** operand, or if the loop is not an OUTER JOIN. + */ + if( (pTerm->eOperator & 0x3f)!=0 + || (pWC->pWInfo->pTabList->a[pLoop->iTab].fg.jointype + & (JT_LEFT|JT_LTORJ))==0 + ){ + pLoop->wsFlags |= WHERE_SELFCULL; + } + } if( pTerm->truthProb<=0 ){ /* If a truth probability is specified using the likelihood() hints, ** then use the probability provided by the application. */ @@ -152999,7 +156697,9 @@ static void whereLoopOutputAdjust( } } } - if( pLoop->nOut > nRow-iReduce ) pLoop->nOut = nRow - iReduce; + if( pLoop->nOut > nRow-iReduce ){ + pLoop->nOut = nRow - iReduce; + } } /* @@ -153172,12 +156872,29 @@ static int whereLoopAddBtreeIndex( if( pTerm->wtFlags & TERM_LIKEOPT && pTerm->eOperator==WO_LT ) continue; /* tag-20191211-001: Do not allow constraints from the WHERE clause to - ** be used by the right table of a LEFT JOIN. Only constraints in the - ** ON clause are allowed. See tag-20191211-002 for the vtab equivalent. */ - if( (pSrc->fg.jointype & JT_LEFT)!=0 - && !ExprHasProperty(pTerm->pExpr, EP_FromJoin) - ){ - continue; + ** be used by the right table of a LEFT JOIN nor by the left table of a + ** RIGHT JOIN. Only constraints in the ON clause are allowed. + ** See tag-20191211-002 for the vtab equivalent. + ** + ** 2022-06-06: See https://sqlite.org/forum/forumpost/206d99a16dd9212f + ** for an example of a WHERE clause constraints that may not be used on + ** the right table of a RIGHT JOIN because the constraint implies a + ** not-NULL condition on the left table of the RIGHT JOIN. + ** + ** 2022-06-10: The same condition applies to termCanDriveIndex() above. + ** https://sqlite.org/forum/forumpost/51e6959f61 + */ + if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0 ){ + testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_LEFT ); + testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_RIGHT ); + testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_LTORJ ); + testcase( ExprHasProperty(pTerm->pExpr, EP_OuterON) ) + testcase( ExprHasProperty(pTerm->pExpr, EP_InnerON) ); + if( !ExprHasProperty(pTerm->pExpr, EP_OuterON|EP_InnerON) + || pTerm->pExpr->w.iJoin != pSrc->iCursor + ){ + continue; + } } if( IsUniqueIndex(pProbe) && saved_nEq==pProbe->nKeyCol-1 ){ @@ -153529,23 +157246,26 @@ static int indexMightHelpWithOrderBy( */ static int whereUsablePartialIndex( int iTab, /* The table for which we want an index */ - int isLeft, /* True if iTab is the right table of a LEFT JOIN */ + u8 jointype, /* The JT_* flags on the join */ WhereClause *pWC, /* The WHERE clause of the query */ Expr *pWhere /* The WHERE clause from the partial index */ ){ int i; WhereTerm *pTerm; - Parse *pParse = pWC->pWInfo->pParse; + Parse *pParse; + + if( jointype & JT_LTORJ ) return 0; + pParse = pWC->pWInfo->pParse; while( pWhere->op==TK_AND ){ - if( !whereUsablePartialIndex(iTab,isLeft,pWC,pWhere->pLeft) ) return 0; + if( !whereUsablePartialIndex(iTab,jointype,pWC,pWhere->pLeft) ) return 0; pWhere = pWhere->pRight; } if( pParse->db->flags & SQLITE_EnableQPSG ) pParse = 0; for(i=0, pTerm=pWC->a; inTerm; i++, pTerm++){ Expr *pExpr; pExpr = pTerm->pExpr; - if( (!ExprHasProperty(pExpr, EP_FromJoin) || pExpr->iRightJoinTable==iTab) - && (isLeft==0 || ExprHasProperty(pExpr, EP_FromJoin)) + if( (!ExprHasProperty(pExpr, EP_OuterON) || pExpr->w.iJoin==iTab) + && ((jointype & JT_OUTER)==0 || ExprHasProperty(pExpr, EP_OuterON)) && sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, iTab) && (pTerm->wtFlags & TERM_VNULL)==0 ){ @@ -153654,13 +157374,14 @@ static int whereLoopAddBtree( #ifndef SQLITE_OMIT_AUTOMATIC_INDEX /* Automatic indexes */ if( !pBuilder->pOrSet /* Not part of an OR optimization */ - && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0 + && (pWInfo->wctrlFlags & (WHERE_RIGHT_JOIN|WHERE_OR_SUBCLAUSE))==0 && (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0 && !pSrc->fg.isIndexedBy /* Has no INDEXED BY clause */ && !pSrc->fg.notIndexed /* Has no NOT INDEXED clause */ && HasRowid(pTab) /* Not WITHOUT ROWID table. (FIXME: Why not?) */ && !pSrc->fg.isCorrelated /* Not a correlated subquery */ && !pSrc->fg.isRecursive /* Not a recursive common table expression. */ + && (pSrc->fg.jointype & JT_RIGHT)==0 /* Not the right tab of a RIGHT JOIN */ ){ /* Generate auto-index WhereLoops */ LogEst rLogSize; /* Logarithm of the number of rows in the table */ @@ -153710,9 +157431,8 @@ static int whereLoopAddBtree( for(; rc==SQLITE_OK && pProbe; pProbe=(pSrc->fg.isIndexedBy ? 0 : pProbe->pNext), iSortIdx++ ){ - int isLeft = (pSrc->fg.jointype & JT_OUTER)!=0; if( pProbe->pPartIdxWhere!=0 - && !whereUsablePartialIndex(pSrc->iCursor, isLeft, pWC, + && !whereUsablePartialIndex(pSrc->iCursor, pSrc->fg.jointype, pWC, pProbe->pPartIdxWhere) ){ testcase( pNew->iTab!=pSrc->iCursor ); /* See ticket [98d973b8f5] */ @@ -153820,7 +157540,14 @@ static int whereLoopAddBtree( } ApplyCostMultiplier(pNew->rRun, pTab->costMult); whereLoopOutputAdjust(pWC, pNew, rSize); - rc = whereLoopInsert(pBuilder, pNew); + if( (pSrc->fg.jointype & JT_RIGHT)!=0 && pProbe->aColExpr ){ + /* Do not do an SCAN of a index-on-expression in a RIGHT JOIN + ** because the cursor used to access the index might not be + ** positioned to the correct row during the right-join no-match + ** loop. */ + }else{ + rc = whereLoopInsert(pBuilder, pNew); + } pNew->nOut = rSize; if( rc ) break; } @@ -153846,6 +157573,15 @@ static int whereLoopAddBtree( #ifndef SQLITE_OMIT_VIRTUALTABLE +/* +** Return true if pTerm is a virtual table LIMIT or OFFSET term. +*/ +static int isLimitTerm(WhereTerm *pTerm){ + assert( pTerm->eOperator==WO_AUX || pTerm->eMatchOp==0 ); + return pTerm->eMatchOp>=SQLITE_INDEX_CONSTRAINT_LIMIT + && pTerm->eMatchOp<=SQLITE_INDEX_CONSTRAINT_OFFSET; +} + /* ** Argument pIdxInfo is already populated with all constraints that may ** be used by the virtual table identified by pBuilder->pNew->iTab. This @@ -153873,9 +157609,11 @@ static int whereLoopAddVirtualOne( u16 mExclude, /* Exclude terms using these operators */ sqlite3_index_info *pIdxInfo, /* Populated object for xBestIndex */ u16 mNoOmit, /* Do not omit these constraints */ - int *pbIn /* OUT: True if plan uses an IN(...) op */ + int *pbIn, /* OUT: True if plan uses an IN(...) op */ + int *pbRetryLimit /* OUT: Retry without LIMIT/OFFSET */ ){ WhereClause *pWC = pBuilder->pWC; + HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1]; struct sqlite3_index_constraint *pIdxCons; struct sqlite3_index_constraint_usage *pUsage = pIdxInfo->aConstraintUsage; int i; @@ -153898,6 +157636,7 @@ static int whereLoopAddVirtualOne( pIdxCons->usable = 0; if( (pTerm->prereqRight & mUsable)==pTerm->prereqRight && (pTerm->eOperator & mExclude)==0 + && (pbRetryLimit || !isLimitTerm(pTerm)) ){ pIdxCons->usable = 1; } @@ -153913,6 +157652,7 @@ static int whereLoopAddVirtualOne( pIdxInfo->estimatedRows = 25; pIdxInfo->idxFlags = 0; pIdxInfo->colUsed = (sqlite3_int64)pSrc->colUsed; + pHidden->mHandleIn = 0; /* Invoke the virtual table xBestIndex() method */ rc = vtabBestIndex(pParse, pSrc->pTab, pIdxInfo); @@ -153930,8 +157670,8 @@ static int whereLoopAddVirtualOne( mxTerm = -1; assert( pNew->nLSlot>=nConstraint ); - for(i=0; iaLTerm[i] = 0; - pNew->u.vtab.omitMask = 0; + memset(pNew->aLTerm, 0, sizeof(pNew->aLTerm[0])*nConstraint ); + memset(&pNew->u.vtab, 0, sizeof(pNew->u.vtab)); pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint; for(i=0; ieMatchOp==SQLITE_INDEX_CONSTRAINT_OFFSET ){ + pNew->u.vtab.bOmitOffset = 1; + } } - if( (pTerm->eOperator & WO_IN)!=0 ){ + if( SMASKBIT32(i) & pHidden->mHandleIn ){ + pNew->u.vtab.mHandleIn |= MASKBIT32(iTerm); + }else if( (pTerm->eOperator & WO_IN)!=0 ){ /* A virtual table that is constrained by an IN clause may not ** consume the ORDER BY clause because (1) the order of IN terms ** is not necessarily related to the order of output terms and @@ -153976,6 +157721,22 @@ static int whereLoopAddVirtualOne( pIdxInfo->idxFlags &= ~SQLITE_INDEX_SCAN_UNIQUE; *pbIn = 1; assert( (mExclude & WO_IN)==0 ); } + + assert( pbRetryLimit || !isLimitTerm(pTerm) ); + if( isLimitTerm(pTerm) && *pbIn ){ + /* If there is an IN(...) term handled as an == (separate call to + ** xFilter for each value on the RHS of the IN) and a LIMIT or + ** OFFSET term handled as well, the plan is unusable. Set output + ** variable *pbRetryLimit to true to tell the caller to retry with + ** LIMIT and OFFSET disabled. */ + if( pIdxInfo->needToFreeIdxStr ){ + sqlite3_free(pIdxInfo->idxStr); + pIdxInfo->idxStr = 0; + pIdxInfo->needToFreeIdxStr = 0; + } + *pbRetryLimit = 1; + return SQLITE_OK; + } } } @@ -154020,11 +157781,19 @@ static int whereLoopAddVirtualOne( } /* -** If this function is invoked from within an xBestIndex() callback, it -** returns a pointer to a buffer containing the name of the collation -** sequence associated with element iCons of the sqlite3_index_info.aConstraint -** array. Or, if iCons is out of range or there is no active xBestIndex -** call, return NULL. +** Return the collating sequence for a constraint passed into xBestIndex. +** +** pIdxInfo must be an sqlite3_index_info structure passed into xBestIndex. +** This routine depends on there being a HiddenIndexInfo structure immediately +** following the sqlite3_index_info structure. +** +** Return a pointer to the collation name: +** +** 1. If there is an explicit COLLATE operator on the constaint, return it. +** +** 2. Else, if the column has an alternative collation, return that. +** +** 3. Otherwise, return "BINARY". */ SQLITE_API const char *sqlite3_vtab_collation(sqlite3_index_info *pIdxInfo, int iCons){ HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1]; @@ -154041,6 +157810,97 @@ SQLITE_API const char *sqlite3_vtab_collation(sqlite3_index_info *pIdxInfo, int return zRet; } +/* +** Return true if constraint iCons is really an IN(...) constraint, or +** false otherwise. If iCons is an IN(...) constraint, set (if bHandle!=0) +** or clear (if bHandle==0) the flag to handle it using an iterator. +*/ +SQLITE_API int sqlite3_vtab_in(sqlite3_index_info *pIdxInfo, int iCons, int bHandle){ + HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1]; + u32 m = SMASKBIT32(iCons); + if( m & pHidden->mIn ){ + if( bHandle==0 ){ + pHidden->mHandleIn &= ~m; + }else if( bHandle>0 ){ + pHidden->mHandleIn |= m; + } + return 1; + } + return 0; +} + +/* +** This interface is callable from within the xBestIndex callback only. +** +** If possible, set (*ppVal) to point to an object containing the value +** on the right-hand-side of constraint iCons. +*/ +SQLITE_API int sqlite3_vtab_rhs_value( + sqlite3_index_info *pIdxInfo, /* Copy of first argument to xBestIndex */ + int iCons, /* Constraint for which RHS is wanted */ + sqlite3_value **ppVal /* Write value extracted here */ +){ + HiddenIndexInfo *pH = (HiddenIndexInfo*)&pIdxInfo[1]; + sqlite3_value *pVal = 0; + int rc = SQLITE_OK; + if( iCons<0 || iCons>=pIdxInfo->nConstraint ){ + rc = SQLITE_MISUSE; /* EV: R-30545-25046 */ + }else{ + if( pH->aRhs[iCons]==0 ){ + WhereTerm *pTerm = &pH->pWC->a[pIdxInfo->aConstraint[iCons].iTermOffset]; + rc = sqlite3ValueFromExpr( + pH->pParse->db, pTerm->pExpr->pRight, ENC(pH->pParse->db), + SQLITE_AFF_BLOB, &pH->aRhs[iCons] + ); + testcase( rc!=SQLITE_OK ); + } + pVal = pH->aRhs[iCons]; + } + *ppVal = pVal; + + if( rc==SQLITE_OK && pVal==0 ){ /* IMP: R-19933-32160 */ + rc = SQLITE_NOTFOUND; /* IMP: R-36424-56542 */ + } + + return rc; +} + +/* +** Return true if ORDER BY clause may be handled as DISTINCT. +*/ +SQLITE_API int sqlite3_vtab_distinct(sqlite3_index_info *pIdxInfo){ + HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1]; + assert( pHidden->eDistinct>=0 && pHidden->eDistinct<=3 ); + return pHidden->eDistinct; +} + +#if (defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)) \ + && !defined(SQLITE_OMIT_VIRTUALTABLE) +/* +** Cause the prepared statement that is associated with a call to +** xBestIndex to potentiall use all schemas. If the statement being +** prepared is read-only, then just start read transactions on all +** schemas. But if this is a write operation, start writes on all +** schemas. +** +** This is used by the (built-in) sqlite_dbpage virtual table. +*/ +SQLITE_PRIVATE void sqlite3VtabUsesAllSchemas(sqlite3_index_info *pIdxInfo){ + HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1]; + Parse *pParse = pHidden->pParse; + int nDb = pParse->db->nDb; + int i; + for(i=0; iwriteMask ){ + for(i=0; ipNew->iTab. That table is guaranteed to be a virtual table. @@ -154082,6 +157942,7 @@ static int whereLoopAddVirtual( WhereLoop *pNew; Bitmask mBest; /* Tables used by best possible plan */ u16 mNoOmit; + int bRetry = 0; /* True to retry with LIMIT/OFFSET disabled */ assert( (mPrereq & mUnusable)==0 ); pWInfo = pBuilder->pWInfo; @@ -154090,8 +157951,7 @@ static int whereLoopAddVirtual( pNew = pBuilder->pNew; pSrc = &pWInfo->pTabList->a[pNew->iTab]; assert( IsVirtual(pSrc->pTab) ); - p = allocateIndexInfo(pParse, pWC, mUnusable, pSrc, pBuilder->pOrderBy, - &mNoOmit); + p = allocateIndexInfo(pWInfo, pWC, mUnusable, pSrc, &mNoOmit); if( p==0 ) return SQLITE_NOMEM_BKPT; pNew->rSetup = 0; pNew->wsFlags = WHERE_VIRTUALTABLE; @@ -154099,14 +157959,22 @@ static int whereLoopAddVirtual( pNew->u.vtab.needFree = 0; nConstraint = p->nConstraint; if( whereLoopResize(pParse->db, pNew, nConstraint) ){ - sqlite3DbFree(pParse->db, p); + freeIndexInfo(pParse->db, p); return SQLITE_NOMEM_BKPT; } /* First call xBestIndex() with all constraints usable. */ WHERETRACE(0x800, ("BEGIN %s.addVirtual()\n", pSrc->pTab->zName)); WHERETRACE(0x40, (" VirtualOne: all usable\n")); - rc = whereLoopAddVirtualOne(pBuilder, mPrereq, ALLBITS, 0, p, mNoOmit, &bIn); + rc = whereLoopAddVirtualOne( + pBuilder, mPrereq, ALLBITS, 0, p, mNoOmit, &bIn, &bRetry + ); + if( bRetry ){ + assert( rc==SQLITE_OK ); + rc = whereLoopAddVirtualOne( + pBuilder, mPrereq, ALLBITS, 0, p, mNoOmit, &bIn, 0 + ); + } /* If the call to xBestIndex() with all terms enabled produced a plan ** that does not require any source tables (IOW: a plan with mBest==0) @@ -154124,7 +157992,7 @@ static int whereLoopAddVirtual( if( bIn ){ WHERETRACE(0x40, (" VirtualOne: all usable w/o IN\n")); rc = whereLoopAddVirtualOne( - pBuilder, mPrereq, ALLBITS, WO_IN, p, mNoOmit, &bIn); + pBuilder, mPrereq, ALLBITS, WO_IN, p, mNoOmit, &bIn, 0); assert( bIn==0 ); mBestNoIn = pNew->prereq & ~mPrereq; if( mBestNoIn==0 ){ @@ -154151,7 +158019,7 @@ static int whereLoopAddVirtual( WHERETRACE(0x40, (" VirtualOne: mPrev=%04llx mNext=%04llx\n", (sqlite3_uint64)mPrev, (sqlite3_uint64)mNext)); rc = whereLoopAddVirtualOne( - pBuilder, mPrereq, mNext|mPrereq, 0, p, mNoOmit, &bIn); + pBuilder, mPrereq, mNext|mPrereq, 0, p, mNoOmit, &bIn, 0); if( pNew->prereq==mPrereq ){ seenZero = 1; if( bIn==0 ) seenZeroNoIN = 1; @@ -154164,7 +158032,7 @@ static int whereLoopAddVirtual( if( rc==SQLITE_OK && seenZero==0 ){ WHERETRACE(0x40, (" VirtualOne: all disabled\n")); rc = whereLoopAddVirtualOne( - pBuilder, mPrereq, mPrereq, 0, p, mNoOmit, &bIn); + pBuilder, mPrereq, mPrereq, 0, p, mNoOmit, &bIn, 0); if( bIn==0 ) seenZeroNoIN = 1; } @@ -154174,12 +158042,12 @@ static int whereLoopAddVirtual( if( rc==SQLITE_OK && seenZeroNoIN==0 ){ WHERETRACE(0x40, (" VirtualOne: all disabled and w/o IN\n")); rc = whereLoopAddVirtualOne( - pBuilder, mPrereq, mPrereq, WO_IN, p, mNoOmit, &bIn); + pBuilder, mPrereq, mPrereq, WO_IN, p, mNoOmit, &bIn, 0); } } if( p->needToFreeIdxStr ) sqlite3_free(p->idxStr); - sqlite3DbFreeNN(pParse->db, p); + freeIndexInfo(pParse->db, p); WHERETRACE(0x800, ("END %s.addVirtual(), rc=%d\n", pSrc->pTab->zName, rc)); return rc; } @@ -154212,6 +158080,9 @@ static int whereLoopAddOr( pItem = pWInfo->pTabList->a + pNew->iTab; iCur = pItem->iCursor; + /* The multi-index OR optimization does not work for RIGHT and FULL JOIN */ + if( pItem->fg.jointype & JT_RIGHT ) return SQLITE_OK; + for(pTerm=pWC->a; pTermeOperator & WO_OR)!=0 && (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0 @@ -154223,7 +158094,6 @@ static int whereLoopAddOr( int i, j; sSubBuild = *pBuilder; - sSubBuild.pOrderBy = 0; sSubBuild.pOrSet = &sCur; WHERETRACE(0x200, ("Begin processing OR-clause %p\n", pTerm)); @@ -154235,6 +158105,7 @@ static int whereLoopAddOr( tempWC.pOuter = pWC; tempWC.op = TK_AND; tempWC.nTerm = 1; + tempWC.nBase = 1; tempWC.a = pOrTerm; sSubBuild.pWC = &tempWC; }else{ @@ -154325,8 +158196,11 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){ SrcItem *pEnd = &pTabList->a[pWInfo->nLevel]; sqlite3 *db = pWInfo->pParse->db; int rc = SQLITE_OK; + int bFirstPastRJ = 0; + int hasRightJoin = 0; WhereLoop *pNew; + /* Loop over the tables in the join, from left to right */ pNew = pBuilder->pNew; whereLoopInit(pNew); @@ -154336,18 +158210,30 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){ pNew->iTab = iTab; pBuilder->iPlanLimit += SQLITE_QUERY_PLANNER_LIMIT_INCR; pNew->maskSelf = sqlite3WhereGetMask(&pWInfo->sMaskSet, pItem->iCursor); - if( (pItem->fg.jointype & (JT_LEFT|JT_CROSS))!=0 ){ - /* This condition is true when pItem is the FROM clause term on the - ** right-hand-side of a LEFT or CROSS JOIN. */ - mPrereq = mPrior; - }else{ + if( bFirstPastRJ + || (pItem->fg.jointype & (JT_OUTER|JT_CROSS|JT_LTORJ))!=0 + ){ + /* Add prerequisites to prevent reordering of FROM clause terms + ** across CROSS joins and outer joins. The bFirstPastRJ boolean + ** prevents the right operand of a RIGHT JOIN from being swapped with + ** other elements even further to the right. + ** + ** The JT_LTORJ case and the hasRightJoin flag work together to + ** prevent FROM-clause terms from moving from the right side of + ** a LEFT JOIN over to the left side of that join if the LEFT JOIN + ** is itself on the left side of a RIGHT JOIN. + */ + if( pItem->fg.jointype & JT_LTORJ ) hasRightJoin = 1; + mPrereq |= mPrior; + bFirstPastRJ = (pItem->fg.jointype & JT_RIGHT)!=0; + }else if( !hasRightJoin ){ mPrereq = 0; } #ifndef SQLITE_OMIT_VIRTUALTABLE if( IsVirtual(pItem->pTab) ){ SrcItem *p; for(p=&pItem[1]; pfg.jointype & (JT_LEFT|JT_CROSS)) ){ + if( mUnusable || (p->fg.jointype & (JT_OUTER|JT_CROSS)) ){ mUnusable |= sqlite3WhereGetMask(&pWInfo->sMaskSet, p->iCursor); } } @@ -154472,7 +158358,9 @@ static i8 wherePathSatisfiesOrderBy( pLoop = pLast; } if( pLoop->wsFlags & WHERE_VIRTUALTABLE ){ - if( pLoop->u.vtab.isOrdered && (wctrlFlags & WHERE_DISTINCTBY)==0 ){ + if( pLoop->u.vtab.isOrdered + && ((wctrlFlags&(WHERE_DISTINCTBY|WHERE_SORTBYGROUP))!=WHERE_DISTINCTBY) + ){ obSat = obDone; } break; @@ -154650,16 +158538,18 @@ static i8 wherePathSatisfiesOrderBy( /* Make sure the sort order is compatible in an ORDER BY clause. ** Sort order is irrelevant for a GROUP BY clause. */ if( revSet ){ - if( (rev ^ revIdx)!=(pOrderBy->a[i].sortFlags&KEYINFO_ORDER_DESC) ){ + if( (rev ^ revIdx) + != (pOrderBy->a[i].fg.sortFlags&KEYINFO_ORDER_DESC) + ){ isMatch = 0; } }else{ - rev = revIdx ^ (pOrderBy->a[i].sortFlags & KEYINFO_ORDER_DESC); + rev = revIdx ^ (pOrderBy->a[i].fg.sortFlags & KEYINFO_ORDER_DESC); if( rev ) *pRevMask |= MASKBIT(iLoop); revSet = 1; } } - if( isMatch && (pOrderBy->a[i].sortFlags & KEYINFO_ORDER_BIGNULL) ){ + if( isMatch && (pOrderBy->a[i].fg.sortFlags & KEYINFO_ORDER_BIGNULL) ){ if( j==pLoop->u.btree.nEq ){ pLoop->wsFlags |= WHERE_BIGNULL_SORT; }else{ @@ -154739,7 +158629,7 @@ static i8 wherePathSatisfiesOrderBy( ** SELECT * FROM t1 GROUP BY y,x ORDER BY y,x; -- IsSorted()==0 */ SQLITE_PRIVATE int sqlite3WhereIsSorted(WhereInfo *pWInfo){ - assert( pWInfo->wctrlFlags & WHERE_GROUPBY ); + assert( pWInfo->wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY) ); assert( pWInfo->wctrlFlags & WHERE_SORTBYGROUP ); return pWInfo->sorted; } @@ -155140,12 +159030,12 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){ } pWInfo->bOrderedInnerLoop = 0; if( pWInfo->pOrderBy ){ + pWInfo->nOBSat = pFrom->isOrdered; if( pWInfo->wctrlFlags & WHERE_DISTINCTBY ){ if( pFrom->isOrdered==pWInfo->pOrderBy->nExpr ){ pWInfo->eDistinct = WHERE_DISTINCT_ORDERED; } }else{ - pWInfo->nOBSat = pFrom->isOrdered; pWInfo->revMask = pFrom->revLoop; if( pWInfo->nOBSat<=0 ){ pWInfo->nOBSat = 0; @@ -155224,7 +159114,11 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){ pItem = pWInfo->pTabList->a; pTab = pItem->pTab; if( IsVirtual(pTab) ) return 0; - if( pItem->fg.isIndexedBy ) return 0; + if( pItem->fg.isIndexedBy || pItem->fg.notIndexed ){ + testcase( pItem->fg.isIndexedBy ); + testcase( pItem->fg.notIndexed ); + return 0; + } iCur = pItem->iCursor; pWC = &pWInfo->sWC; pLoop = pBuilder->pNew; @@ -155342,6 +159236,150 @@ static void showAllWhereLoops(WhereInfo *pWInfo, WhereClause *pWC){ # define WHERETRACE_ALL_LOOPS(W,C) #endif +/* Attempt to omit tables from a join that do not affect the result. +** For a table to not affect the result, the following must be true: +** +** 1) The query must not be an aggregate. +** 2) The table must be the RHS of a LEFT JOIN. +** 3) Either the query must be DISTINCT, or else the ON or USING clause +** must contain a constraint that limits the scan of the table to +** at most a single row. +** 4) The table must not be referenced by any part of the query apart +** from its own USING or ON clause. +** +** For example, given: +** +** CREATE TABLE t1(ipk INTEGER PRIMARY KEY, v1); +** CREATE TABLE t2(ipk INTEGER PRIMARY KEY, v2); +** CREATE TABLE t3(ipk INTEGER PRIMARY KEY, v3); +** +** then table t2 can be omitted from the following: +** +** SELECT v1, v3 FROM t1 +** LEFT JOIN t2 ON (t1.ipk=t2.ipk) +** LEFT JOIN t3 ON (t1.ipk=t3.ipk) +** +** or from: +** +** SELECT DISTINCT v1, v3 FROM t1 +** LEFT JOIN t2 +** LEFT JOIN t3 ON (t1.ipk=t3.ipk) +*/ +static SQLITE_NOINLINE Bitmask whereOmitNoopJoin( + WhereInfo *pWInfo, + Bitmask notReady +){ + int i; + Bitmask tabUsed; + + /* Preconditions checked by the caller */ + assert( pWInfo->nLevel>=2 ); + assert( OptimizationEnabled(pWInfo->pParse->db, SQLITE_OmitNoopJoin) ); + + /* These two preconditions checked by the caller combine to guarantee + ** condition (1) of the header comment */ + assert( pWInfo->pResultSet!=0 ); + assert( 0==(pWInfo->wctrlFlags & WHERE_AGG_DISTINCT) ); + + tabUsed = sqlite3WhereExprListUsage(&pWInfo->sMaskSet, pWInfo->pResultSet); + if( pWInfo->pOrderBy ){ + tabUsed |= sqlite3WhereExprListUsage(&pWInfo->sMaskSet, pWInfo->pOrderBy); + } + for(i=pWInfo->nLevel-1; i>=1; i--){ + WhereTerm *pTerm, *pEnd; + SrcItem *pItem; + WhereLoop *pLoop; + pLoop = pWInfo->a[i].pWLoop; + pItem = &pWInfo->pTabList->a[pLoop->iTab]; + if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))!=JT_LEFT ) continue; + if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT)==0 + && (pLoop->wsFlags & WHERE_ONEROW)==0 + ){ + continue; + } + if( (tabUsed & pLoop->maskSelf)!=0 ) continue; + pEnd = pWInfo->sWC.a + pWInfo->sWC.nTerm; + for(pTerm=pWInfo->sWC.a; pTermprereqAll & pLoop->maskSelf)!=0 ){ + if( !ExprHasProperty(pTerm->pExpr, EP_OuterON) + || pTerm->pExpr->w.iJoin!=pItem->iCursor + ){ + break; + } + } + } + if( pTerm drop loop %c not used\n", pLoop->cId)); + notReady &= ~pLoop->maskSelf; + for(pTerm=pWInfo->sWC.a; pTermprereqAll & pLoop->maskSelf)!=0 ){ + pTerm->wtFlags |= TERM_CODED; + } + } + if( i!=pWInfo->nLevel-1 ){ + int nByte = (pWInfo->nLevel-1-i) * sizeof(WhereLevel); + memmove(&pWInfo->a[i], &pWInfo->a[i+1], nByte); + } + pWInfo->nLevel--; + assert( pWInfo->nLevel>0 ); + } + return notReady; +} + +/* +** Check to see if there are any SEARCH loops that might benefit from +** using a Bloom filter. Consider a Bloom filter if: +** +** (1) The SEARCH happens more than N times where N is the number +** of rows in the table that is being considered for the Bloom +** filter. +** (2) Some searches are expected to find zero rows. (This is determined +** by the WHERE_SELFCULL flag on the term.) +** (3) Bloom-filter processing is not disabled. (Checked by the +** caller.) +** (4) The size of the table being searched is known by ANALYZE. +** +** This block of code merely checks to see if a Bloom filter would be +** appropriate, and if so sets the WHERE_BLOOMFILTER flag on the +** WhereLoop. The implementation of the Bloom filter comes further +** down where the code for each WhereLoop is generated. +*/ +static SQLITE_NOINLINE void whereCheckIfBloomFilterIsUseful( + const WhereInfo *pWInfo +){ + int i; + LogEst nSearch; + + assert( pWInfo->nLevel>=2 ); + assert( OptimizationEnabled(pWInfo->pParse->db, SQLITE_BloomFilter) ); + nSearch = pWInfo->a[0].pWLoop->nOut; + for(i=1; inLevel; i++){ + WhereLoop *pLoop = pWInfo->a[i].pWLoop; + const unsigned int reqFlags = (WHERE_SELFCULL|WHERE_COLUMN_EQ); + if( (pLoop->wsFlags & reqFlags)==reqFlags + /* vvvvvv--- Always the case if WHERE_COLUMN_EQ is defined */ + && ALWAYS((pLoop->wsFlags & (WHERE_IPK|WHERE_INDEXED))!=0) + ){ + SrcItem *pItem = &pWInfo->pTabList->a[pLoop->iTab]; + Table *pTab = pItem->pTab; + pTab->tabFlags |= TF_StatsUsed; + if( nSearch > pTab->nRowLogEst + && (pTab->tabFlags & TF_HasStat1)!=0 + ){ + testcase( pItem->fg.jointype & JT_LEFT ); + pLoop->wsFlags |= WHERE_BLOOMFILTER; + pLoop->wsFlags &= ~WHERE_IDX_ONLY; + WHERETRACE(0xffff, ( + "-> use Bloom-filter on loop %c because there are ~%.1e " + "lookups into %s which has only ~%.1e rows\n", + pLoop->cId, (double)sqlite3LogEstToInt(nSearch), pTab->zName, + (double)sqlite3LogEstToInt(pTab->nRowLogEst))); + } + } + nSearch += pLoop->nOut; + } +} + /* ** Generate the beginning of the loop used for WHERE clause processing. ** The return value is a pointer to an opaque structure that contains @@ -155436,6 +159474,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( Expr *pWhere, /* The WHERE clause */ ExprList *pOrderBy, /* An ORDER BY (or GROUP BY) clause, or NULL */ ExprList *pResultSet, /* Query result set. Req'd for DISTINCT */ + Select *pLimit, /* Use this LIMIT/OFFSET clause, if any */ u16 wctrlFlags, /* The WHERE_* flags defined in sqliteInt.h */ int iAuxArg /* If WHERE_OR_SUBCLAUSE is set, index cursor number ** If WHERE_USE_LIMIT, then the limit amount */ @@ -155470,13 +159509,6 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( /* An ORDER/GROUP BY clause of more than 63 terms cannot be optimized */ testcase( pOrderBy && pOrderBy->nExpr==BMS-1 ); if( pOrderBy && pOrderBy->nExpr>=BMS ) pOrderBy = 0; - sWLB.pOrderBy = pOrderBy; - - /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via - ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */ - if( OptimizationDisabled(db, SQLITE_DistinctOpt) ){ - wctrlFlags &= ~WHERE_WANT_DISTINCT; - } /* The number of tables in the FROM clause is limited by the number of ** bits in a Bitmask @@ -155501,7 +159533,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( ** field (type Bitmask) it must be aligned on an 8-byte boundary on ** some architectures. Hence the ROUND8() below. */ - nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel)); + nByteWInfo = ROUND8P(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel)); pWInfo = sqlite3DbMallocRawNN(db, nByteWInfo + sizeof(WhereLoop)); if( db->mallocFailed ){ sqlite3DbFree(db, pWInfo); @@ -155519,11 +159551,18 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( pWInfo->wctrlFlags = wctrlFlags; pWInfo->iLimit = iAuxArg; pWInfo->savedNQueryLoop = pParse->nQueryLoop; +#ifndef SQLITE_OMIT_VIRTUALTABLE + pWInfo->pLimit = pLimit; +#endif memset(&pWInfo->nOBSat, 0, offsetof(WhereInfo,sWC) - offsetof(WhereInfo,nOBSat)); memset(&pWInfo->a[0], 0, sizeof(WhereLoop)+nTabList*sizeof(WhereLevel)); assert( pWInfo->eOnePass==ONEPASS_OFF ); /* ONEPASS defaults to OFF */ pMaskSet = &pWInfo->sMaskSet; + pMaskSet->n = 0; + pMaskSet->ix[0] = -99; /* Initialize ix[0] to a value that can never be + ** a valid cursor number, to avoid an initial + ** test for pMaskSet->n==0 in sqlite3WhereGetMask() */ sWLB.pWInfo = pWInfo; sWLB.pWC = &pWInfo->sWC; sWLB.pNew = (WhereLoop*)(((char*)pWInfo)+nByteWInfo); @@ -155536,7 +159575,6 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( /* Split the WHERE clause into separate subexpressions where each ** subexpression is separated by an AND operator. */ - initMaskSet(pMaskSet); sqlite3WhereClauseInit(&pWInfo->sWC, pWInfo); sqlite3WhereSplit(&pWInfo->sWC, pWhere, TK_AND); @@ -155544,7 +159582,9 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( */ if( nTabList==0 ){ if( pOrderBy ) pWInfo->nOBSat = pOrderBy->nExpr; - if( wctrlFlags & WHERE_WANT_DISTINCT ){ + if( (wctrlFlags & WHERE_WANT_DISTINCT)!=0 + && OptimizationEnabled(db, SQLITE_DistinctOpt) + ){ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; } ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW")); @@ -155582,7 +159622,8 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( /* Analyze all of the subexpressions. */ sqlite3WhereExprAnalyze(pTabList, &pWInfo->sWC); - if( db->mallocFailed ) goto whereBeginError; + sqlite3WhereAddLimit(&pWInfo->sWC, pLimit); + if( pParse->nErr ) goto whereBeginError; /* Special case: WHERE terms that do not refer to any tables in the join ** (constant expressions). Evaluate each such term, and jump over all the @@ -155595,7 +159636,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( ** FROM ... WHERE random()>0; -- eval random() once per row ** FROM ... WHERE (SELECT random())>0; -- eval random() once overall */ - for(ii=0; iinTerm; ii++){ + for(ii=0; iinBase; ii++){ WhereTerm *pT = &sWLB.pWC->a[ii]; if( pT->wtFlags & TERM_VIRTUAL ) continue; if( pT->prereqAll==0 && (nTabList==0 || exprIsDeterministic(pT->pExpr)) ){ @@ -155605,7 +159646,12 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( } if( wctrlFlags & WHERE_WANT_DISTINCT ){ - if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){ + if( OptimizationDisabled(db, SQLITE_DistinctOpt) ){ + /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via + ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */ + wctrlFlags &= ~WHERE_WANT_DISTINCT; + pWInfo->wctrlFlags &= ~WHERE_WANT_DISTINCT; + }else if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){ /* The DISTINCT marking is pointless. Ignore it. */ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; }else if( pOrderBy==0 ){ @@ -155676,9 +159722,10 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( if( pWInfo->pOrderBy==0 && (db->flags & SQLITE_ReverseOrder)!=0 ){ pWInfo->revMask = ALLBITS; } - if( pParse->nErr || db->mallocFailed ){ + if( pParse->nErr ){ goto whereBeginError; } + assert( db->mallocFailed==0 ); #ifdef WHERETRACE_ENABLED if( sqlite3WhereTrace ){ sqlite3DebugPrintf("---- Solution nRow=%d", pWInfo->nRowOut); @@ -155706,34 +159753,15 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( } #endif - /* Attempt to omit tables from the join that do not affect the result. - ** For a table to not affect the result, the following must be true: - ** - ** 1) The query must not be an aggregate. - ** 2) The table must be the RHS of a LEFT JOIN. - ** 3) Either the query must be DISTINCT, or else the ON or USING clause - ** must contain a constraint that limits the scan of the table to - ** at most a single row. - ** 4) The table must not be referenced by any part of the query apart - ** from its own USING or ON clause. - ** - ** For example, given: - ** - ** CREATE TABLE t1(ipk INTEGER PRIMARY KEY, v1); - ** CREATE TABLE t2(ipk INTEGER PRIMARY KEY, v2); - ** CREATE TABLE t3(ipk INTEGER PRIMARY KEY, v3); + /* Attempt to omit tables from a join that do not affect the result. + ** See the comment on whereOmitNoopJoin() for further information. ** - ** then table t2 can be omitted from the following: - ** - ** SELECT v1, v3 FROM t1 - ** LEFT JOIN t2 ON (t1.ipk=t2.ipk) - ** LEFT JOIN t3 ON (t1.ipk=t3.ipk) - ** - ** or from: - ** - ** SELECT DISTINCT v1, v3 FROM t1 - ** LEFT JOIN t2 - ** LEFT JOIN t3 ON (t1.ipk=t3.ipk) + ** This query optimization is factored out into a separate "no-inline" + ** procedure to keep the sqlite3WhereBegin() procedure from becoming + ** too large. If sqlite3WhereBegin() becomes too large, that prevents + ** some C-compiler optimizers from in-lining the + ** sqlite3WhereCodeOneLoopStart() procedure, and it is important to + ** in-line sqlite3WhereCodeOneLoopStart() for performance reasons. */ notReady = ~(Bitmask)0; if( pWInfo->nLevel>=2 @@ -155741,49 +159769,20 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( && 0==(wctrlFlags & WHERE_AGG_DISTINCT) /* condition (1) above */ && OptimizationEnabled(db, SQLITE_OmitNoopJoin) ){ - int i; - Bitmask tabUsed = sqlite3WhereExprListUsage(pMaskSet, pResultSet); - if( sWLB.pOrderBy ){ - tabUsed |= sqlite3WhereExprListUsage(pMaskSet, sWLB.pOrderBy); - } - for(i=pWInfo->nLevel-1; i>=1; i--){ - WhereTerm *pTerm, *pEnd; - SrcItem *pItem; - pLoop = pWInfo->a[i].pWLoop; - pItem = &pWInfo->pTabList->a[pLoop->iTab]; - if( (pItem->fg.jointype & JT_LEFT)==0 ) continue; - if( (wctrlFlags & WHERE_WANT_DISTINCT)==0 - && (pLoop->wsFlags & WHERE_ONEROW)==0 - ){ - continue; - } - if( (tabUsed & pLoop->maskSelf)!=0 ) continue; - pEnd = sWLB.pWC->a + sWLB.pWC->nTerm; - for(pTerm=sWLB.pWC->a; pTermprereqAll & pLoop->maskSelf)!=0 ){ - if( !ExprHasProperty(pTerm->pExpr, EP_FromJoin) - || pTerm->pExpr->iRightJoinTable!=pItem->iCursor - ){ - break; - } - } - } - if( pTerm drop loop %c not used\n", pLoop->cId)); - notReady &= ~pLoop->maskSelf; - for(pTerm=sWLB.pWC->a; pTermprereqAll & pLoop->maskSelf)!=0 ){ - pTerm->wtFlags |= TERM_CODED; - } - } - if( i!=pWInfo->nLevel-1 ){ - int nByte = (pWInfo->nLevel-1-i) * sizeof(WhereLevel); - memmove(&pWInfo->a[i], &pWInfo->a[i+1], nByte); - } - pWInfo->nLevel--; - nTabList--; - } + notReady = whereOmitNoopJoin(pWInfo, notReady); + nTabList = pWInfo->nLevel; + assert( nTabList>0 ); } + + /* Check to see if there are any SEARCH loops that might benefit from + ** using a Bloom filter. + */ + if( pWInfo->nLevel>=2 + && OptimizationEnabled(db, SQLITE_BloomFilter) + ){ + whereCheckIfBloomFilterIsUseful(pWInfo); + } + #if defined(WHERETRACE_ENABLED) if( sqlite3WhereTrace & 0x100 ){ /* Display all terms of the WHERE clause */ sqlite3DebugPrintf("---- WHERE clause at end of analysis:\n"); @@ -155856,8 +159855,10 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( /* noop */ }else #endif - if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 - && (wctrlFlags & WHERE_OR_SUBCLAUSE)==0 ){ + if( ((pLoop->wsFlags & WHERE_IDX_ONLY)==0 + && (wctrlFlags & WHERE_OR_SUBCLAUSE)==0) + || (pTabItem->fg.jointype & (JT_LTORJ|JT_RIGHT))!=0 + ){ int op = OP_OpenRead; if( pWInfo->eOnePass!=ONEPASS_OFF ){ op = OP_OpenWrite; @@ -155870,6 +159871,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( if( pWInfo->eOnePass==ONEPASS_OFF && pTab->nColtabFlags & (TF_HasGenerated|TF_WithoutRowid))==0 + && (pLoop->wsFlags & (WHERE_AUTO_INDEX|WHERE_BLOOMFILTER))==0 ){ /* If we know that only a prefix of the record will be used, ** it is advantageous to reduce the "column count" field in @@ -155925,6 +159927,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( iIndexCur = pParse->nTab++; } pLevel->iIdxCur = iIndexCur; + assert( pIx!=0 ); assert( pIx->pSchema==pTab->pSchema ); assert( iIndexCur>=0 ); if( op ){ @@ -155958,6 +159961,37 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( } } if( iDb>=0 ) sqlite3CodeVerifySchema(pParse, iDb); + if( (pTabItem->fg.jointype & JT_RIGHT)!=0 + && (pLevel->pRJ = sqlite3WhereMalloc(pWInfo, sizeof(WhereRightJoin)))!=0 + ){ + WhereRightJoin *pRJ = pLevel->pRJ; + pRJ->iMatch = pParse->nTab++; + pRJ->regBloom = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Blob, 65536, pRJ->regBloom); + pRJ->regReturn = ++pParse->nMem; + sqlite3VdbeAddOp2(v, OP_Null, 0, pRJ->regReturn); + assert( pTab==pTabItem->pTab ); + if( HasRowid(pTab) ){ + KeyInfo *pInfo; + sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRJ->iMatch, 1); + pInfo = sqlite3KeyInfoAlloc(pParse->db, 1, 0); + if( pInfo ){ + pInfo->aColl[0] = 0; + pInfo->aSortFlags[0] = 0; + sqlite3VdbeAppendP4(v, pInfo, P4_KEYINFO); + } + }else{ + Index *pPk = sqlite3PrimaryKeyIndex(pTab); + sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRJ->iMatch, pPk->nKeyCol); + sqlite3VdbeSetP4KeyInfo(pParse, pPk); + } + pLoop->wsFlags &= ~WHERE_IDX_ONLY; + /* The nature of RIGHT JOIN processing is such that it messes up + ** the output order. So omit any ORDER BY/GROUP BY elimination + ** optimizations. We need to do an actual sort for RIGHT JOIN. */ + pWInfo->nOBSat = 0; + pWInfo->eDistinct = WHERE_DISTINCT_UNORDERED; + } } pWInfo->iTop = sqlite3VdbeCurrentAddr(v); if( db->mallocFailed ) goto whereBeginError; @@ -155969,16 +160003,31 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( for(ii=0; iinErr ) goto whereBeginError; pLevel = &pWInfo->a[ii]; wsFlags = pLevel->pWLoop->wsFlags; + pSrc = &pTabList->a[pLevel->iFrom]; + if( pSrc->fg.isMaterialized ){ + if( pSrc->fg.isCorrelated ){ + sqlite3VdbeAddOp2(v, OP_Gosub, pSrc->regReturn, pSrc->addrFillSub); + }else{ + int iOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); + sqlite3VdbeAddOp2(v, OP_Gosub, pSrc->regReturn, pSrc->addrFillSub); + sqlite3VdbeJumpHere(v, iOnce); + } + } + if( (wsFlags & (WHERE_AUTO_INDEX|WHERE_BLOOMFILTER))!=0 ){ + if( (wsFlags & WHERE_AUTO_INDEX)!=0 ){ #ifndef SQLITE_OMIT_AUTOMATIC_INDEX - if( (pLevel->pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 ){ - constructAutomaticIndex(pParse, &pWInfo->sWC, - &pTabList->a[pLevel->iFrom], notReady, pLevel); + constructAutomaticIndex(pParse, &pWInfo->sWC, + &pTabList->a[pLevel->iFrom], notReady, pLevel); +#endif + }else{ + sqlite3ConstructBloomFilter(pWInfo, ii, pLevel, notReady); + } if( db->mallocFailed ) goto whereBeginError; } -#endif addrExplain = sqlite3WhereExplainOneScan( pParse, pTabList, pLevel, wctrlFlags ); @@ -156026,6 +160075,26 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( } #endif +#ifdef SQLITE_DEBUG +/* +** Return true if cursor iCur is opened by instruction k of the +** bytecode. Used inside of assert() only. +*/ +static int cursorIsOpen(Vdbe *v, int iCur, int k){ + while( k>=0 ){ + VdbeOp *pOp = sqlite3VdbeGetOp(v,k--); + if( pOp->p1!=iCur ) continue; + if( pOp->opcode==OP_Close ) return 0; + if( pOp->opcode==OP_OpenRead ) return 1; + if( pOp->opcode==OP_OpenWrite ) return 1; + if( pOp->opcode==OP_OpenDup ) return 1; + if( pOp->opcode==OP_OpenAutoindex ) return 1; + if( pOp->opcode==OP_OpenEphemeral ) return 1; + } + return 0; +} +#endif /* SQLITE_DEBUG */ + /* ** Generate the end of the WHERE loop. See comments on ** sqlite3WhereBegin() for additional information. @@ -156039,6 +160108,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ SrcList *pTabList = pWInfo->pTabList; sqlite3 *db = pParse->db; int iEnd = sqlite3VdbeCurrentAddr(v); + int nRJ = 0; /* Generate loop termination code. */ @@ -156046,6 +160116,17 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ for(i=pWInfo->nLevel-1; i>=0; i--){ int addr; pLevel = &pWInfo->a[i]; + if( pLevel->pRJ ){ + /* Terminate the subroutine that forms the interior of the loop of + ** the RIGHT JOIN table */ + WhereRightJoin *pRJ = pLevel->pRJ; + sqlite3VdbeResolveLabel(v, pLevel->addrCont); + pLevel->addrCont = 0; + pRJ->endSubrtn = sqlite3VdbeCurrentAddr(v); + sqlite3VdbeAddOp3(v, OP_Return, pRJ->regReturn, pRJ->addrSubrtn, 1); + VdbeCoverage(v); + nRJ++; + } pLoop = pLevel->pWLoop; if( pLevel->op!=OP_Noop ){ #ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT @@ -156073,7 +160154,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ } #endif /* SQLITE_DISABLE_SKIPAHEAD_DISTINCT */ /* The common case: Advance to the next row */ - sqlite3VdbeResolveLabel(v, pLevel->addrCont); + if( pLevel->addrCont ) sqlite3VdbeResolveLabel(v, pLevel->addrCont); sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3); sqlite3VdbeChangeP5(v, pLevel->p5); VdbeCoverage(v); @@ -156088,7 +160169,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ #ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT if( addrSeek ) sqlite3VdbeJumpHere(v, addrSeek); #endif - }else{ + }else if( pLevel->addrCont ){ sqlite3VdbeResolveLabel(v, pLevel->addrCont); } if( (pLoop->wsFlags & WHERE_IN_ABLE)!=0 && pLevel->u.in.nIn>0 ){ @@ -156138,6 +160219,10 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ } } sqlite3VdbeResolveLabel(v, pLevel->addrBrk); + if( pLevel->pRJ ){ + sqlite3VdbeAddOp3(v, OP_Return, pLevel->pRJ->regReturn, 0, 1); + VdbeCoverage(v); + } if( pLevel->addrSkip ){ sqlite3VdbeGoto(v, pLevel->addrSkip); VdbeComment((v, "next skip-scan on %s", pLoop->u.btree.pIndex->zName)); @@ -156181,12 +160266,8 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ pWInfo->pTabList->a[pLevel->iFrom].pTab->zName)); } - /* The "break" point is here, just past the end of the outer loop. - ** Set it. - */ - sqlite3VdbeResolveLabel(v, pWInfo->iBreak); - assert( pWInfo->nLevel<=pTabList->nSrc ); + if( pWInfo->pExprMods ) whereUndoExprMods(pWInfo); for(i=0, pLevel=pWInfo->a; inLevel; i++, pLevel++){ int k, last; VdbeOp *pOp, *pLastOp; @@ -156196,6 +160277,15 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ assert( pTab!=0 ); pLoop = pLevel->pWLoop; + /* Do RIGHT JOIN processing. Generate code that will output the + ** unmatched rows of the right operand of the RIGHT JOIN with + ** all of the columns of the left operand set to NULL. + */ + if( pLevel->pRJ ){ + sqlite3WhereRightJoinLoop(pWInfo, i, pLevel); + continue; + } + /* For a co-routine, change all OP_Column references to the table of ** the co-routine into OP_Copy of result contained in a register. ** OP_Rowid becomes OP_Null. @@ -156207,29 +160297,6 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ continue; } -#ifdef SQLITE_ENABLE_EARLY_CURSOR_CLOSE - /* Close all of the cursors that were opened by sqlite3WhereBegin. - ** Except, do not close cursors that will be reused by the OR optimization - ** (WHERE_OR_SUBCLAUSE). And do not close the OP_OpenWrite cursors - ** created for the ONEPASS optimization. - */ - if( (pTab->tabFlags & TF_Ephemeral)==0 - && !IsView(pTab) - && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0 - ){ - int ws = pLoop->wsFlags; - if( pWInfo->eOnePass==ONEPASS_OFF && (ws & WHERE_IDX_ONLY)==0 ){ - sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor); - } - if( (ws & WHERE_INDEXED)!=0 - && (ws & (WHERE_IPK|WHERE_AUTO_INDEX))==0 - && pLevel->iIdxCur!=pWInfo->aiCurOnePass[1] - ){ - sqlite3VdbeAddOp1(v, OP_Close, pLevel->iIdxCur); - } - } -#endif - /* If this scan uses an index, make VDBE code substitutions to read data ** from the index instead of from the table where possible. In some cases ** this optimization prevents the table from ever being read, which can @@ -156278,6 +160345,11 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ ){ int x = pOp->p2; assert( pIdx->pTable==pTab ); +#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC + if( pOp->opcode==OP_Offset ){ + /* Do not need to translate the column number */ + }else +#endif if( !HasRowid(pTab) ){ Index *pPk = sqlite3PrimaryKeyIndex(pTab); x = pPk->aiColumn[x]; @@ -156291,9 +160363,22 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ pOp->p2 = x; pOp->p1 = pLevel->iIdxCur; OpcodeRewriteTrace(db, k, pOp); + }else{ + /* Unable to translate the table reference into an index + ** reference. Verify that this is harmless - that the + ** table being referenced really is open. + */ +#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC + assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 + || cursorIsOpen(v,pOp->p1,k) + || pOp->opcode==OP_Offset + ); +#else + assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 + || cursorIsOpen(v,pOp->p1,k) + ); +#endif } - assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || x>=0 - || pWInfo->eOnePass ); }else if( pOp->opcode==OP_Rowid ){ pOp->p1 = pLevel->iIdxCur; pOp->opcode = OP_IdxRowid; @@ -156312,11 +160397,16 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ } } + /* The "break" point is here, just past the end of the outer loop. + ** Set it. + */ + sqlite3VdbeResolveLabel(v, pWInfo->iBreak); + /* Final cleanup */ - if( pWInfo->pExprMods ) whereUndoExprMods(pWInfo); pParse->nQueryLoop = pWInfo->savedNQueryLoop; whereInfoFree(db, pWInfo); + pParse->withinRJSubrtn -= nRJ; return; } @@ -157048,7 +161138,7 @@ SQLITE_PRIVATE void sqlite3WindowUpdate( } } } - pWin->pFunc = pFunc; + pWin->pWFunc = pFunc; } /* @@ -157240,7 +161330,7 @@ static ExprList *exprListAppendList( } } pList = sqlite3ExprListAppend(pParse, pList, pDup); - if( pList ) pList->a[nInit+i].sortFlags = pAppend->a[i].sortFlags; + if( pList ) pList->a[nInit+i].fg.sortFlags = pAppend->a[i].fg.sortFlags; } } return pList; @@ -157281,7 +161371,11 @@ static int disallowAggregatesInOrderByCb(Walker *pWalker, Expr *pExpr){ */ SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){ int rc = SQLITE_OK; - if( p->pWin && p->pPrior==0 && ALWAYS((p->selFlags & SF_WinRewrite)==0) ){ + if( p->pWin + && p->pPrior==0 + && ALWAYS((p->selFlags & SF_WinRewrite)==0) + && ALWAYS(!IN_RENAME_OBJECT) + ){ Vdbe *v = sqlite3GetVdbe(pParse); sqlite3 *db = pParse->db; Select *pSub = 0; /* The subquery */ @@ -157356,8 +161450,9 @@ SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){ for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ ExprList *pArgs; assert( ExprUseXList(pWin->pOwner) ); + assert( pWin->pWFunc!=0 ); pArgs = pWin->pOwner->x.pList; - if( pWin->pFunc->funcFlags & SQLITE_FUNC_SUBTYPE ){ + if( pWin->pWFunc->funcFlags & SQLITE_FUNC_SUBTYPE ){ selectWindowRewriteEList(pParse, pMWin, pSrc, pArgs, pTab, &pSublist); pWin->iArgCol = (pSublist ? pSublist->nExpr : 0); pWin->bExprArgs = 1; @@ -157430,12 +161525,7 @@ SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){ sqlite3ParserAddCleanup(pParse, sqlite3DbFree, pTab); } - if( rc ){ - if( pParse->nErr==0 ){ - assert( pParse->db->mallocFailed ); - sqlite3ErrorToParser(pParse->db, SQLITE_NOMEM); - } - } + assert( rc==SQLITE_OK || pParse->nErr!=0 ); return rc; } @@ -157744,7 +161834,7 @@ SQLITE_PRIVATE void sqlite3WindowCodeInit(Parse *pParse, Select *pSelect){ } for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ - FuncDef *p = pWin->pFunc; + FuncDef *p = pWin->pWFunc; if( (p->funcFlags & SQLITE_FUNC_MINMAX) && pWin->eStart!=TK_UNBOUNDED ){ /* The inline versions of min() and max() require a single ephemeral ** table and 3 registers. The registers are used as follows: @@ -157761,7 +161851,7 @@ SQLITE_PRIVATE void sqlite3WindowCodeInit(Parse *pParse, Select *pSelect){ pWin->csrApp = pParse->nTab++; pWin->regApp = pParse->nMem+1; pParse->nMem += 3; - if( pKeyInfo && pWin->pFunc->zName[1]=='i' ){ + if( pKeyInfo && pWin->pWFunc->zName[1]=='i' ){ assert( pKeyInfo->aSortFlags[0]==0 ); pKeyInfo->aSortFlags[0] = KEYINFO_ORDER_DESC; } @@ -157984,7 +162074,7 @@ static void windowAggStep( Vdbe *v = sqlite3GetVdbe(pParse); Window *pWin; for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ - FuncDef *pFunc = pWin->pFunc; + FuncDef *pFunc = pWin->pWFunc; int regArg; int nArg = pWin->bExprArgs ? 0 : windowArgCount(pWin); int i; @@ -158053,7 +162143,7 @@ static void windowAggStep( for(iEnd=sqlite3VdbeCurrentAddr(v); iOpopcode==OP_Column && pOp->p1==pWin->iEphCsr ){ + if( pOp->opcode==OP_Column && pOp->p1==pMWin->iEphCsr ){ pOp->p1 = csr; } } @@ -158098,7 +162188,7 @@ static void windowAggFinal(WindowCodeArg *p, int bFin){ for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ if( pMWin->regStartRowid==0 - && (pWin->pFunc->funcFlags & SQLITE_FUNC_MINMAX) + && (pWin->pWFunc->funcFlags & SQLITE_FUNC_MINMAX) && (pWin->eStart!=TK_UNBOUNDED) ){ sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult); @@ -158112,12 +162202,12 @@ static void windowAggFinal(WindowCodeArg *p, int bFin){ int nArg = windowArgCount(pWin); if( bFin ){ sqlite3VdbeAddOp2(v, OP_AggFinal, pWin->regAccum, nArg); - sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF); + sqlite3VdbeAppendP4(v, pWin->pWFunc, P4_FUNCDEF); sqlite3VdbeAddOp2(v, OP_Copy, pWin->regAccum, pWin->regResult); sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum); }else{ sqlite3VdbeAddOp3(v, OP_AggValue,pWin->regAccum,nArg,pWin->regResult); - sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF); + sqlite3VdbeAppendP4(v, pWin->pWFunc, P4_FUNCDEF); } } } @@ -158246,7 +162336,7 @@ static void windowReturnOneRow(WindowCodeArg *p){ Window *pWin; for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ - FuncDef *pFunc = pWin->pFunc; + FuncDef *pFunc = pWin->pWFunc; assert( ExprUseXList(pWin->pOwner) ); if( pFunc->zName==nth_valueName || pFunc->zName==first_valueName @@ -158318,7 +162408,7 @@ static int windowInitAccum(Parse *pParse, Window *pMWin){ int nArg = 0; Window *pWin; for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ - FuncDef *pFunc = pWin->pFunc; + FuncDef *pFunc = pWin->pWFunc; assert( pWin->regAccum ); sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum); nArg = MAX(nArg, windowArgCount(pWin)); @@ -158348,7 +162438,7 @@ static int windowCacheFrame(Window *pMWin){ Window *pWin; if( pMWin->regStartRowid ) return 1; for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ - FuncDef *pFunc = pWin->pFunc; + FuncDef *pFunc = pWin->pWFunc; if( (pFunc->zName==nth_valueName) || (pFunc->zName==first_valueName) || (pFunc->zName==leadName) @@ -158441,7 +162531,7 @@ static void windowCodeRangeTest( assert( op==OP_Ge || op==OP_Gt || op==OP_Le ); assert( pOrderBy && pOrderBy->nExpr==1 ); - if( pOrderBy->a[0].sortFlags & KEYINFO_ORDER_DESC ){ + if( pOrderBy->a[0].fg.sortFlags & KEYINFO_ORDER_DESC ){ switch( op ){ case OP_Ge: op = OP_Le; break; case OP_Gt: op = OP_Lt; break; @@ -158474,7 +162564,7 @@ static void windowCodeRangeTest( ** Additionally, if either reg1 or reg2 are NULL but the jump to lbl is ** not taken, control jumps over the comparison operator coded below this ** block. */ - if( pOrderBy->a[0].sortFlags & KEYINFO_ORDER_BIGNULL ){ + if( pOrderBy->a[0].fg.sortFlags & KEYINFO_ORDER_BIGNULL ){ /* This block runs if reg1 contains a NULL. */ int addr = sqlite3VdbeAddOp1(v, OP_NotNull, reg1); VdbeCoverage(v); switch( op ){ @@ -158706,7 +162796,7 @@ SQLITE_PRIVATE Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p){ pNew->zName = sqlite3DbStrDup(db, p->zName); pNew->zBase = sqlite3DbStrDup(db, p->zBase); pNew->pFilter = sqlite3ExprDup(db, p->pFilter, 0); - pNew->pFunc = p->pFunc; + pNew->pWFunc = p->pWFunc; pNew->pPartition = sqlite3ExprListDup(db, p->pPartition, 0); pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, 0); pNew->eFrmType = p->eFrmType; @@ -159583,10 +163673,7 @@ static void updateDeleteLimitError( } - /* Construct a new Expr object from a single identifier. Use the - ** new Expr to populate pOut. Set the span of pOut to be the identifier - ** that created the expression. - */ + /* Construct a new Expr object from a single token */ static Expr *tokenExpr(Parse *pParse, int op, Token t){ Expr *p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr)+t.n+1); if( p ){ @@ -159595,7 +163682,7 @@ static void updateDeleteLimitError( p->affExpr = 0; p->flags = EP_Leaf; ExprClearVVAProperties(p); - p->iAgg = -1; + /* p->iAgg = -1; // Not required */ p->pLeft = p->pRight = 0; p->pAggInfo = 0; memset(&p->x, 0, sizeof(p->x)); @@ -159606,6 +163693,7 @@ static void updateDeleteLimitError( p->u.zToken = (char*)&p[1]; memcpy(p->u.zToken, t.z, t.n); p->u.zToken[t.n] = 0; + p->w.iOfst = (int)(t.z - pParse->zTail); if( sqlite3Isquote(p->u.zToken[0]) ){ sqlite3DequoteExpr(p); } @@ -159772,78 +163860,79 @@ static void updateDeleteLimitError( #define TK_SLASH 109 #define TK_REM 110 #define TK_CONCAT 111 -#define TK_COLLATE 112 -#define TK_BITNOT 113 -#define TK_ON 114 -#define TK_INDEXED 115 -#define TK_STRING 116 -#define TK_JOIN_KW 117 -#define TK_CONSTRAINT 118 -#define TK_DEFAULT 119 -#define TK_NULL 120 -#define TK_PRIMARY 121 -#define TK_UNIQUE 122 -#define TK_CHECK 123 -#define TK_REFERENCES 124 -#define TK_AUTOINCR 125 -#define TK_INSERT 126 -#define TK_DELETE 127 -#define TK_UPDATE 128 -#define TK_SET 129 -#define TK_DEFERRABLE 130 -#define TK_FOREIGN 131 -#define TK_DROP 132 -#define TK_UNION 133 -#define TK_ALL 134 -#define TK_EXCEPT 135 -#define TK_INTERSECT 136 -#define TK_SELECT 137 -#define TK_VALUES 138 -#define TK_DISTINCT 139 -#define TK_DOT 140 -#define TK_FROM 141 -#define TK_JOIN 142 -#define TK_USING 143 -#define TK_ORDER 144 -#define TK_GROUP 145 -#define TK_HAVING 146 -#define TK_LIMIT 147 -#define TK_WHERE 148 -#define TK_RETURNING 149 -#define TK_INTO 150 -#define TK_NOTHING 151 -#define TK_FLOAT 152 -#define TK_BLOB 153 -#define TK_INTEGER 154 -#define TK_VARIABLE 155 -#define TK_CASE 156 -#define TK_WHEN 157 -#define TK_THEN 158 -#define TK_ELSE 159 -#define TK_INDEX 160 -#define TK_ALTER 161 -#define TK_ADD 162 -#define TK_WINDOW 163 -#define TK_OVER 164 -#define TK_FILTER 165 -#define TK_COLUMN 166 -#define TK_AGG_FUNCTION 167 -#define TK_AGG_COLUMN 168 -#define TK_TRUEFALSE 169 -#define TK_ISNOT 170 -#define TK_FUNCTION 171 -#define TK_UMINUS 172 -#define TK_UPLUS 173 -#define TK_TRUTH 174 -#define TK_REGISTER 175 -#define TK_VECTOR 176 -#define TK_SELECT_COLUMN 177 -#define TK_IF_NULL_ROW 178 -#define TK_ASTERISK 179 -#define TK_SPAN 180 -#define TK_ERROR 181 -#define TK_SPACE 182 -#define TK_ILLEGAL 183 +#define TK_PTR 112 +#define TK_COLLATE 113 +#define TK_BITNOT 114 +#define TK_ON 115 +#define TK_INDEXED 116 +#define TK_STRING 117 +#define TK_JOIN_KW 118 +#define TK_CONSTRAINT 119 +#define TK_DEFAULT 120 +#define TK_NULL 121 +#define TK_PRIMARY 122 +#define TK_UNIQUE 123 +#define TK_CHECK 124 +#define TK_REFERENCES 125 +#define TK_AUTOINCR 126 +#define TK_INSERT 127 +#define TK_DELETE 128 +#define TK_UPDATE 129 +#define TK_SET 130 +#define TK_DEFERRABLE 131 +#define TK_FOREIGN 132 +#define TK_DROP 133 +#define TK_UNION 134 +#define TK_ALL 135 +#define TK_EXCEPT 136 +#define TK_INTERSECT 137 +#define TK_SELECT 138 +#define TK_VALUES 139 +#define TK_DISTINCT 140 +#define TK_DOT 141 +#define TK_FROM 142 +#define TK_JOIN 143 +#define TK_USING 144 +#define TK_ORDER 145 +#define TK_GROUP 146 +#define TK_HAVING 147 +#define TK_LIMIT 148 +#define TK_WHERE 149 +#define TK_RETURNING 150 +#define TK_INTO 151 +#define TK_NOTHING 152 +#define TK_FLOAT 153 +#define TK_BLOB 154 +#define TK_INTEGER 155 +#define TK_VARIABLE 156 +#define TK_CASE 157 +#define TK_WHEN 158 +#define TK_THEN 159 +#define TK_ELSE 160 +#define TK_INDEX 161 +#define TK_ALTER 162 +#define TK_ADD 163 +#define TK_WINDOW 164 +#define TK_OVER 165 +#define TK_FILTER 166 +#define TK_COLUMN 167 +#define TK_AGG_FUNCTION 168 +#define TK_AGG_COLUMN 169 +#define TK_TRUEFALSE 170 +#define TK_ISNOT 171 +#define TK_FUNCTION 172 +#define TK_UMINUS 173 +#define TK_UPLUS 174 +#define TK_TRUTH 175 +#define TK_REGISTER 176 +#define TK_VECTOR 177 +#define TK_SELECT_COLUMN 178 +#define TK_IF_NULL_ROW 179 +#define TK_ASTERISK 180 +#define TK_SPAN 181 +#define TK_ERROR 182 +#define TK_SPACE 183 +#define TK_ILLEGAL 184 #endif /**************** End token definitions ***************************************/ @@ -159903,30 +163992,31 @@ static void updateDeleteLimitError( #endif /************* Begin control #defines *****************************************/ #define YYCODETYPE unsigned short int -#define YYNOCODE 318 +#define YYNOCODE 319 #define YYACTIONTYPE unsigned short int #define YYWILDCARD 101 #define sqlite3ParserTOKENTYPE Token typedef union { int yyinit; sqlite3ParserTOKENTYPE yy0; - With* yy43; - u32 yy51; - int yy64; - struct FrameBound yy81; - struct {int value; int mask;} yy83; - TriggerStep* yy95; - Upsert* yy138; - IdList* yy240; - Cte* yy255; - Select* yy303; - Window* yy375; - u8 yy534; - ExprList* yy562; - struct TrigEvent yy570; - const char* yy600; - SrcList* yy607; - Expr* yy626; + TriggerStep* yy33; + Window* yy41; + Select* yy47; + SrcList* yy131; + struct TrigEvent yy180; + struct {int value; int mask;} yy231; + IdList* yy254; + u32 yy285; + ExprList* yy322; + Cte* yy385; + int yy394; + Upsert* yy444; + u8 yy516; + With* yy521; + const char* yy522; + Expr* yy528; + OnOrUsing yy561; + struct FrameBound yy595; } YYMINORTYPE; #ifndef YYSTACKDEPTH #define YYSTACKDEPTH 100 @@ -159942,18 +164032,18 @@ typedef union { #define sqlite3ParserCTX_FETCH Parse *pParse=yypParser->pParse; #define sqlite3ParserCTX_STORE yypParser->pParse=pParse; #define YYFALLBACK 1 -#define YYNSTATE 572 -#define YYNRULE 401 -#define YYNRULE_WITH_ACTION 339 -#define YYNTOKEN 184 -#define YY_MAX_SHIFT 571 -#define YY_MIN_SHIFTREDUCE 829 -#define YY_MAX_SHIFTREDUCE 1229 -#define YY_ERROR_ACTION 1230 -#define YY_ACCEPT_ACTION 1231 -#define YY_NO_ACTION 1232 -#define YY_MIN_REDUCE 1233 -#define YY_MAX_REDUCE 1633 +#define YYNSTATE 576 +#define YYNRULE 405 +#define YYNRULE_WITH_ACTION 342 +#define YYNTOKEN 185 +#define YY_MAX_SHIFT 575 +#define YY_MIN_SHIFTREDUCE 835 +#define YY_MAX_SHIFTREDUCE 1239 +#define YY_ERROR_ACTION 1240 +#define YY_ACCEPT_ACTION 1241 +#define YY_NO_ACTION 1242 +#define YY_MIN_REDUCE 1243 +#define YY_MAX_REDUCE 1647 /************* End control #defines *******************************************/ #define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0]))) @@ -160020,606 +164110,618 @@ typedef union { ** yy_default[] Default action for each state. ** *********** Begin parsing tables **********************************************/ -#define YY_ACTTAB_COUNT (2037) +#define YY_ACTTAB_COUNT (2098) static const YYACTIONTYPE yy_action[] = { - /* 0 */ 564, 115, 112, 220, 169, 199, 115, 112, 220, 564, - /* 10 */ 375, 1266, 564, 376, 564, 270, 1309, 1309, 406, 407, - /* 20 */ 1084, 199, 1513, 41, 41, 515, 489, 521, 558, 558, - /* 30 */ 558, 965, 41, 41, 395, 41, 41, 51, 51, 966, - /* 40 */ 296, 1269, 296, 122, 123, 113, 1207, 1207, 1041, 1044, - /* 50 */ 1034, 1034, 120, 120, 121, 121, 121, 121, 564, 407, - /* 60 */ 275, 275, 275, 275, 1268, 115, 112, 220, 115, 112, - /* 70 */ 220, 1512, 846, 561, 516, 561, 115, 112, 220, 250, - /* 80 */ 217, 71, 71, 122, 123, 113, 1207, 1207, 1041, 1044, - /* 90 */ 1034, 1034, 120, 120, 121, 121, 121, 121, 440, 440, - /* 100 */ 440, 1149, 119, 119, 119, 119, 118, 118, 117, 117, - /* 110 */ 117, 116, 442, 1183, 1149, 116, 442, 1149, 546, 513, - /* 120 */ 1548, 1554, 374, 442, 6, 1183, 1154, 522, 1154, 407, - /* 130 */ 1556, 461, 373, 1554, 535, 99, 463, 332, 121, 121, - /* 140 */ 121, 121, 119, 119, 119, 119, 118, 118, 117, 117, - /* 150 */ 117, 116, 442, 122, 123, 113, 1207, 1207, 1041, 1044, - /* 160 */ 1034, 1034, 120, 120, 121, 121, 121, 121, 1257, 1183, - /* 170 */ 1184, 1185, 243, 1064, 564, 502, 499, 498, 567, 124, - /* 180 */ 567, 1183, 1184, 1185, 474, 497, 119, 119, 119, 119, - /* 190 */ 118, 118, 117, 117, 117, 116, 442, 70, 70, 407, - /* 200 */ 121, 121, 121, 121, 114, 117, 117, 117, 116, 442, - /* 210 */ 1409, 1469, 119, 119, 119, 119, 118, 118, 117, 117, - /* 220 */ 117, 116, 442, 122, 123, 113, 1207, 1207, 1041, 1044, - /* 230 */ 1034, 1034, 120, 120, 121, 121, 121, 121, 407, 1031, - /* 240 */ 1031, 1042, 1045, 81, 382, 541, 378, 80, 119, 119, - /* 250 */ 119, 119, 118, 118, 117, 117, 117, 116, 442, 381, - /* 260 */ 463, 332, 122, 123, 113, 1207, 1207, 1041, 1044, 1034, - /* 270 */ 1034, 120, 120, 121, 121, 121, 121, 262, 215, 512, - /* 280 */ 1424, 422, 119, 119, 119, 119, 118, 118, 117, 117, - /* 290 */ 117, 116, 442, 1231, 1, 1, 571, 2, 1235, 1573, - /* 300 */ 571, 2, 1235, 307, 1149, 141, 1600, 307, 407, 141, - /* 310 */ 1183, 361, 1317, 1035, 866, 531, 1317, 1149, 359, 1567, - /* 320 */ 1149, 119, 119, 119, 119, 118, 118, 117, 117, 117, - /* 330 */ 116, 442, 122, 123, 113, 1207, 1207, 1041, 1044, 1034, - /* 340 */ 1034, 120, 120, 121, 121, 121, 121, 275, 275, 1001, - /* 350 */ 426, 275, 275, 1128, 1627, 1021, 1627, 137, 542, 1541, - /* 360 */ 561, 272, 950, 950, 561, 1423, 1183, 1184, 1185, 1594, - /* 370 */ 866, 1012, 530, 315, 231, 1011, 468, 1276, 231, 119, - /* 380 */ 119, 119, 119, 118, 118, 117, 117, 117, 116, 442, - /* 390 */ 1570, 119, 119, 119, 119, 118, 118, 117, 117, 117, - /* 400 */ 116, 442, 330, 359, 1567, 564, 446, 1011, 1011, 1013, - /* 410 */ 446, 207, 564, 306, 555, 407, 363, 1021, 363, 346, - /* 420 */ 184, 118, 118, 117, 117, 117, 116, 442, 71, 71, - /* 430 */ 439, 438, 1126, 1012, 472, 71, 71, 1011, 205, 122, - /* 440 */ 123, 113, 1207, 1207, 1041, 1044, 1034, 1034, 120, 120, - /* 450 */ 121, 121, 121, 121, 219, 219, 472, 1183, 407, 570, - /* 460 */ 1183, 1235, 503, 1477, 149, 546, 307, 489, 141, 1011, - /* 470 */ 1011, 1013, 546, 140, 545, 1317, 1214, 191, 1214, 950, - /* 480 */ 950, 514, 122, 123, 113, 1207, 1207, 1041, 1044, 1034, - /* 490 */ 1034, 120, 120, 121, 121, 121, 121, 563, 119, 119, - /* 500 */ 119, 119, 118, 118, 117, 117, 117, 116, 442, 283, - /* 510 */ 275, 275, 415, 1183, 1184, 1185, 1183, 1184, 1185, 372, - /* 520 */ 1183, 243, 344, 561, 502, 499, 498, 1539, 407, 1540, - /* 530 */ 1183, 288, 870, 143, 497, 1549, 185, 231, 9, 6, - /* 540 */ 253, 119, 119, 119, 119, 118, 118, 117, 117, 117, - /* 550 */ 116, 442, 122, 123, 113, 1207, 1207, 1041, 1044, 1034, - /* 560 */ 1034, 120, 120, 121, 121, 121, 121, 407, 137, 446, - /* 570 */ 447, 863, 169, 1183, 397, 1204, 1183, 1184, 1185, 931, - /* 580 */ 526, 1001, 98, 339, 564, 342, 1183, 1184, 1185, 306, - /* 590 */ 555, 122, 123, 113, 1207, 1207, 1041, 1044, 1034, 1034, - /* 600 */ 120, 120, 121, 121, 121, 121, 452, 71, 71, 275, - /* 610 */ 275, 119, 119, 119, 119, 118, 118, 117, 117, 117, - /* 620 */ 116, 442, 561, 417, 306, 555, 1183, 1307, 1307, 1183, - /* 630 */ 1184, 1185, 1204, 1149, 330, 458, 318, 407, 363, 470, - /* 640 */ 431, 1167, 32, 541, 527, 350, 1149, 1629, 393, 1149, - /* 650 */ 119, 119, 119, 119, 118, 118, 117, 117, 117, 116, - /* 660 */ 442, 122, 123, 113, 1207, 1207, 1041, 1044, 1034, 1034, - /* 670 */ 120, 120, 121, 121, 121, 121, 407, 199, 472, 1183, - /* 680 */ 1022, 472, 1183, 1184, 1185, 386, 151, 539, 1548, 277, - /* 690 */ 400, 137, 6, 317, 5, 564, 562, 3, 920, 920, - /* 700 */ 122, 123, 113, 1207, 1207, 1041, 1044, 1034, 1034, 120, - /* 710 */ 120, 121, 121, 121, 121, 411, 505, 83, 71, 71, - /* 720 */ 119, 119, 119, 119, 118, 118, 117, 117, 117, 116, - /* 730 */ 442, 1183, 218, 428, 1183, 1183, 1184, 1185, 363, 261, - /* 740 */ 278, 358, 508, 353, 507, 248, 407, 306, 555, 1539, - /* 750 */ 1006, 349, 363, 291, 489, 302, 293, 1542, 281, 119, - /* 760 */ 119, 119, 119, 118, 118, 117, 117, 117, 116, 442, - /* 770 */ 122, 123, 113, 1207, 1207, 1041, 1044, 1034, 1034, 120, - /* 780 */ 120, 121, 121, 121, 121, 407, 148, 1183, 1184, 1185, - /* 790 */ 1183, 1184, 1185, 275, 275, 1304, 1257, 1283, 483, 1476, - /* 800 */ 150, 489, 480, 564, 1187, 1304, 561, 1587, 1255, 122, - /* 810 */ 123, 113, 1207, 1207, 1041, 1044, 1034, 1034, 120, 120, - /* 820 */ 121, 121, 121, 121, 564, 886, 13, 13, 520, 119, - /* 830 */ 119, 119, 119, 118, 118, 117, 117, 117, 116, 442, - /* 840 */ 1183, 420, 417, 564, 269, 269, 1316, 13, 13, 1539, - /* 850 */ 1546, 16, 16, 322, 6, 407, 506, 561, 1089, 1089, - /* 860 */ 486, 1187, 425, 1539, 887, 292, 71, 71, 119, 119, - /* 870 */ 119, 119, 118, 118, 117, 117, 117, 116, 442, 122, - /* 880 */ 123, 113, 1207, 1207, 1041, 1044, 1034, 1034, 120, 120, - /* 890 */ 121, 121, 121, 121, 564, 12, 1183, 1184, 1185, 407, - /* 900 */ 275, 275, 451, 303, 834, 835, 836, 417, 489, 276, - /* 910 */ 276, 1547, 284, 561, 319, 6, 321, 71, 71, 429, - /* 920 */ 451, 450, 561, 952, 101, 113, 1207, 1207, 1041, 1044, - /* 930 */ 1034, 1034, 120, 120, 121, 121, 121, 121, 119, 119, - /* 940 */ 119, 119, 118, 118, 117, 117, 117, 116, 442, 1105, - /* 950 */ 1183, 489, 564, 1312, 437, 455, 478, 564, 246, 245, - /* 960 */ 244, 1409, 1545, 547, 1106, 405, 6, 1544, 196, 1258, - /* 970 */ 413, 6, 105, 462, 103, 71, 71, 286, 564, 1107, - /* 980 */ 13, 13, 119, 119, 119, 119, 118, 118, 117, 117, - /* 990 */ 117, 116, 442, 451, 104, 427, 337, 320, 275, 275, - /* 1000 */ 906, 13, 13, 564, 1482, 1105, 1183, 1184, 1185, 126, - /* 1010 */ 907, 561, 546, 564, 407, 478, 295, 1321, 253, 200, - /* 1020 */ 1106, 548, 1482, 1484, 280, 1409, 55, 55, 1287, 561, - /* 1030 */ 478, 380, 423, 951, 407, 1107, 71, 71, 122, 123, - /* 1040 */ 113, 1207, 1207, 1041, 1044, 1034, 1034, 120, 120, 121, - /* 1050 */ 121, 121, 121, 1204, 407, 287, 552, 309, 122, 123, - /* 1060 */ 113, 1207, 1207, 1041, 1044, 1034, 1034, 120, 120, 121, - /* 1070 */ 121, 121, 121, 441, 1128, 1628, 146, 1628, 122, 111, - /* 1080 */ 113, 1207, 1207, 1041, 1044, 1034, 1034, 120, 120, 121, - /* 1090 */ 121, 121, 121, 404, 403, 1482, 424, 119, 119, 119, - /* 1100 */ 119, 118, 118, 117, 117, 117, 116, 442, 1183, 564, - /* 1110 */ 1204, 544, 1086, 858, 329, 361, 1086, 119, 119, 119, - /* 1120 */ 119, 118, 118, 117, 117, 117, 116, 442, 564, 294, - /* 1130 */ 144, 523, 56, 56, 224, 564, 510, 119, 119, 119, - /* 1140 */ 119, 118, 118, 117, 117, 117, 116, 442, 484, 1409, - /* 1150 */ 537, 15, 15, 1126, 434, 439, 438, 407, 13, 13, - /* 1160 */ 1523, 12, 926, 1211, 1183, 1184, 1185, 925, 1213, 536, - /* 1170 */ 858, 557, 413, 193, 1525, 494, 1212, 448, 1160, 1222, - /* 1180 */ 1183, 564, 123, 113, 1207, 1207, 1041, 1044, 1034, 1034, - /* 1190 */ 120, 120, 121, 121, 121, 121, 1521, 1149, 564, 965, - /* 1200 */ 564, 1214, 247, 1214, 13, 13, 1409, 966, 538, 564, - /* 1210 */ 1149, 108, 556, 1149, 4, 310, 392, 1227, 17, 194, - /* 1220 */ 485, 43, 43, 57, 57, 306, 555, 524, 559, 1160, - /* 1230 */ 464, 564, 44, 44, 392, 1127, 1183, 1184, 1185, 479, - /* 1240 */ 119, 119, 119, 119, 118, 118, 117, 117, 117, 116, - /* 1250 */ 442, 443, 564, 327, 13, 13, 564, 418, 1315, 414, - /* 1260 */ 171, 564, 311, 553, 213, 529, 1253, 564, 517, 543, - /* 1270 */ 412, 108, 556, 137, 4, 58, 58, 435, 314, 59, - /* 1280 */ 59, 274, 217, 549, 60, 60, 349, 476, 559, 1353, - /* 1290 */ 61, 61, 1021, 275, 275, 1228, 213, 564, 106, 106, - /* 1300 */ 8, 275, 275, 275, 275, 107, 561, 443, 566, 565, - /* 1310 */ 564, 443, 1011, 1228, 561, 564, 561, 564, 275, 275, - /* 1320 */ 62, 62, 1352, 553, 247, 456, 564, 98, 110, 306, - /* 1330 */ 555, 561, 564, 45, 45, 405, 1203, 533, 46, 46, - /* 1340 */ 47, 47, 532, 465, 1011, 1011, 1013, 1014, 27, 49, - /* 1350 */ 49, 564, 1021, 405, 469, 50, 50, 564, 106, 106, - /* 1360 */ 305, 564, 84, 204, 405, 107, 564, 443, 566, 565, - /* 1370 */ 405, 564, 1011, 564, 63, 63, 564, 1599, 564, 895, - /* 1380 */ 64, 64, 457, 477, 65, 65, 147, 96, 38, 14, - /* 1390 */ 14, 1528, 412, 564, 66, 66, 128, 128, 926, 67, - /* 1400 */ 67, 52, 52, 925, 1011, 1011, 1013, 1014, 27, 1572, - /* 1410 */ 1171, 445, 208, 1123, 279, 394, 68, 68, 228, 390, - /* 1420 */ 390, 389, 264, 387, 1171, 445, 843, 877, 279, 108, - /* 1430 */ 556, 453, 4, 390, 390, 389, 264, 387, 564, 225, - /* 1440 */ 843, 313, 328, 1003, 98, 252, 559, 544, 471, 312, - /* 1450 */ 252, 564, 208, 225, 564, 313, 473, 30, 252, 279, - /* 1460 */ 466, 69, 69, 312, 390, 390, 389, 264, 387, 443, - /* 1470 */ 333, 843, 98, 564, 53, 53, 323, 157, 157, 227, - /* 1480 */ 495, 553, 249, 289, 225, 564, 313, 162, 31, 1501, - /* 1490 */ 135, 564, 1500, 227, 312, 533, 158, 158, 885, 884, - /* 1500 */ 534, 162, 873, 301, 135, 564, 481, 226, 76, 76, - /* 1510 */ 1021, 347, 1071, 98, 54, 54, 106, 106, 1067, 564, - /* 1520 */ 249, 226, 519, 107, 227, 443, 566, 565, 72, 72, - /* 1530 */ 1011, 334, 162, 564, 230, 135, 108, 556, 959, 4, - /* 1540 */ 252, 408, 129, 129, 564, 1349, 306, 555, 564, 923, - /* 1550 */ 564, 110, 226, 559, 564, 408, 73, 73, 564, 873, - /* 1560 */ 306, 555, 1011, 1011, 1013, 1014, 27, 130, 130, 1071, - /* 1570 */ 449, 131, 131, 127, 127, 357, 443, 156, 156, 892, - /* 1580 */ 893, 155, 155, 338, 449, 356, 408, 564, 553, 968, - /* 1590 */ 969, 306, 555, 1015, 341, 564, 108, 556, 564, 4, - /* 1600 */ 1132, 1286, 533, 564, 856, 343, 145, 532, 345, 1300, - /* 1610 */ 136, 136, 1083, 559, 1083, 449, 564, 1021, 134, 134, - /* 1620 */ 1284, 132, 132, 106, 106, 1285, 133, 133, 564, 352, - /* 1630 */ 107, 564, 443, 566, 565, 1340, 443, 1011, 362, 75, - /* 1640 */ 75, 1082, 564, 1082, 564, 924, 1561, 110, 553, 551, - /* 1650 */ 1015, 77, 77, 1361, 74, 74, 1408, 1336, 1347, 550, - /* 1660 */ 1414, 1265, 1256, 1244, 1243, 42, 42, 48, 48, 1011, - /* 1670 */ 1011, 1013, 1014, 27, 1245, 1580, 490, 1021, 267, 202, - /* 1680 */ 1333, 365, 11, 106, 106, 930, 367, 210, 369, 391, - /* 1690 */ 107, 1395, 443, 566, 565, 223, 1390, 1011, 500, 454, - /* 1700 */ 282, 1400, 285, 108, 556, 214, 4, 325, 1383, 1283, - /* 1710 */ 475, 355, 1473, 1583, 1472, 1399, 371, 1222, 326, 398, - /* 1720 */ 559, 290, 331, 197, 100, 556, 209, 4, 198, 1011, - /* 1730 */ 1011, 1013, 1014, 27, 385, 256, 1520, 1518, 554, 1219, - /* 1740 */ 416, 559, 83, 443, 173, 206, 182, 221, 459, 167, - /* 1750 */ 177, 460, 175, 493, 233, 553, 79, 178, 1396, 179, - /* 1760 */ 35, 180, 96, 1402, 443, 396, 36, 467, 1478, 1401, - /* 1770 */ 482, 237, 1404, 399, 82, 186, 553, 1467, 89, 488, - /* 1780 */ 190, 268, 239, 491, 1021, 340, 240, 401, 1246, 1489, - /* 1790 */ 106, 106, 336, 509, 1294, 241, 1303, 107, 430, 443, - /* 1800 */ 566, 565, 1302, 91, 1011, 1021, 1598, 1301, 1273, 215, - /* 1810 */ 1597, 106, 106, 402, 877, 432, 354, 1272, 107, 1271, - /* 1820 */ 443, 566, 565, 1596, 1566, 1011, 1293, 433, 518, 299, - /* 1830 */ 300, 360, 95, 525, 1344, 364, 1011, 1011, 1013, 1014, - /* 1840 */ 27, 254, 255, 1552, 436, 1551, 125, 544, 10, 379, - /* 1850 */ 1326, 1453, 102, 97, 1345, 528, 304, 1011, 1011, 1013, - /* 1860 */ 1014, 27, 366, 377, 1343, 1342, 368, 370, 1325, 384, - /* 1870 */ 201, 383, 34, 1368, 1367, 568, 1177, 266, 263, 265, - /* 1880 */ 1505, 159, 569, 1241, 1236, 1506, 160, 142, 1504, 1503, - /* 1890 */ 297, 211, 830, 161, 212, 78, 444, 203, 308, 222, - /* 1900 */ 1081, 139, 1079, 316, 174, 163, 1203, 229, 176, 909, - /* 1910 */ 324, 232, 1095, 181, 409, 410, 172, 164, 165, 419, - /* 1920 */ 183, 85, 86, 421, 166, 87, 88, 1098, 1094, 234, - /* 1930 */ 235, 152, 18, 236, 335, 1087, 1216, 252, 187, 487, - /* 1940 */ 238, 188, 37, 845, 492, 356, 242, 496, 351, 501, - /* 1950 */ 189, 90, 19, 504, 348, 20, 875, 92, 298, 168, - /* 1960 */ 888, 153, 93, 511, 94, 1165, 154, 1047, 1134, 39, - /* 1970 */ 216, 1133, 271, 273, 958, 192, 953, 110, 1151, 1155, - /* 1980 */ 251, 7, 21, 1159, 1139, 22, 1153, 33, 23, 24, - /* 1990 */ 25, 540, 1158, 195, 98, 1062, 26, 1048, 1046, 1050, - /* 2000 */ 1104, 1051, 1103, 257, 258, 28, 40, 1173, 1016, 857, - /* 2010 */ 109, 29, 560, 388, 138, 1172, 259, 170, 260, 1232, - /* 2020 */ 1232, 919, 1232, 1232, 1232, 1232, 1232, 1232, 1232, 1232, - /* 2030 */ 1232, 1232, 1589, 1232, 1232, 1232, 1588, + /* 0 */ 568, 208, 568, 118, 115, 229, 568, 118, 115, 229, + /* 10 */ 568, 1314, 377, 1293, 408, 562, 562, 562, 568, 409, + /* 20 */ 378, 1314, 1276, 41, 41, 41, 41, 208, 1526, 71, + /* 30 */ 71, 971, 419, 41, 41, 491, 303, 279, 303, 972, + /* 40 */ 397, 71, 71, 125, 126, 80, 1217, 1217, 1050, 1053, + /* 50 */ 1040, 1040, 123, 123, 124, 124, 124, 124, 476, 409, + /* 60 */ 1241, 1, 1, 575, 2, 1245, 550, 118, 115, 229, + /* 70 */ 317, 480, 146, 480, 524, 118, 115, 229, 529, 1327, + /* 80 */ 417, 523, 142, 125, 126, 80, 1217, 1217, 1050, 1053, + /* 90 */ 1040, 1040, 123, 123, 124, 124, 124, 124, 118, 115, + /* 100 */ 229, 327, 122, 122, 122, 122, 121, 121, 120, 120, + /* 110 */ 120, 119, 116, 444, 284, 284, 284, 284, 442, 442, + /* 120 */ 442, 1567, 376, 1569, 1192, 375, 1163, 565, 1163, 565, + /* 130 */ 409, 1567, 537, 259, 226, 444, 101, 145, 449, 316, + /* 140 */ 559, 240, 122, 122, 122, 122, 121, 121, 120, 120, + /* 150 */ 120, 119, 116, 444, 125, 126, 80, 1217, 1217, 1050, + /* 160 */ 1053, 1040, 1040, 123, 123, 124, 124, 124, 124, 142, + /* 170 */ 294, 1192, 339, 448, 120, 120, 120, 119, 116, 444, + /* 180 */ 127, 1192, 1193, 1194, 148, 441, 440, 568, 119, 116, + /* 190 */ 444, 124, 124, 124, 124, 117, 122, 122, 122, 122, + /* 200 */ 121, 121, 120, 120, 120, 119, 116, 444, 454, 113, + /* 210 */ 13, 13, 546, 122, 122, 122, 122, 121, 121, 120, + /* 220 */ 120, 120, 119, 116, 444, 422, 316, 559, 1192, 1193, + /* 230 */ 1194, 149, 1224, 409, 1224, 124, 124, 124, 124, 122, + /* 240 */ 122, 122, 122, 121, 121, 120, 120, 120, 119, 116, + /* 250 */ 444, 465, 342, 1037, 1037, 1051, 1054, 125, 126, 80, + /* 260 */ 1217, 1217, 1050, 1053, 1040, 1040, 123, 123, 124, 124, + /* 270 */ 124, 124, 1279, 522, 222, 1192, 568, 409, 224, 514, + /* 280 */ 175, 82, 83, 122, 122, 122, 122, 121, 121, 120, + /* 290 */ 120, 120, 119, 116, 444, 1007, 16, 16, 1192, 133, + /* 300 */ 133, 125, 126, 80, 1217, 1217, 1050, 1053, 1040, 1040, + /* 310 */ 123, 123, 124, 124, 124, 124, 122, 122, 122, 122, + /* 320 */ 121, 121, 120, 120, 120, 119, 116, 444, 1041, 546, + /* 330 */ 1192, 373, 1192, 1193, 1194, 252, 1434, 399, 504, 501, + /* 340 */ 500, 111, 560, 566, 4, 926, 926, 433, 499, 340, + /* 350 */ 460, 328, 360, 394, 1237, 1192, 1193, 1194, 563, 568, + /* 360 */ 122, 122, 122, 122, 121, 121, 120, 120, 120, 119, + /* 370 */ 116, 444, 284, 284, 369, 1580, 1607, 441, 440, 154, + /* 380 */ 409, 445, 71, 71, 1286, 565, 1221, 1192, 1193, 1194, + /* 390 */ 85, 1223, 271, 557, 543, 515, 1561, 568, 98, 1222, + /* 400 */ 6, 1278, 472, 142, 125, 126, 80, 1217, 1217, 1050, + /* 410 */ 1053, 1040, 1040, 123, 123, 124, 124, 124, 124, 550, + /* 420 */ 13, 13, 1027, 507, 1224, 1192, 1224, 549, 109, 109, + /* 430 */ 222, 568, 1238, 175, 568, 427, 110, 197, 445, 570, + /* 440 */ 569, 430, 1552, 1017, 325, 551, 1192, 270, 287, 368, + /* 450 */ 510, 363, 509, 257, 71, 71, 543, 71, 71, 359, + /* 460 */ 316, 559, 1613, 122, 122, 122, 122, 121, 121, 120, + /* 470 */ 120, 120, 119, 116, 444, 1017, 1017, 1019, 1020, 27, + /* 480 */ 284, 284, 1192, 1193, 1194, 1158, 568, 1612, 409, 901, + /* 490 */ 190, 550, 356, 565, 550, 937, 533, 517, 1158, 516, + /* 500 */ 413, 1158, 552, 1192, 1193, 1194, 568, 544, 1554, 51, + /* 510 */ 51, 214, 125, 126, 80, 1217, 1217, 1050, 1053, 1040, + /* 520 */ 1040, 123, 123, 124, 124, 124, 124, 1192, 474, 135, + /* 530 */ 135, 409, 284, 284, 1490, 505, 121, 121, 120, 120, + /* 540 */ 120, 119, 116, 444, 1007, 565, 518, 217, 541, 1561, + /* 550 */ 316, 559, 142, 6, 532, 125, 126, 80, 1217, 1217, + /* 560 */ 1050, 1053, 1040, 1040, 123, 123, 124, 124, 124, 124, + /* 570 */ 1555, 122, 122, 122, 122, 121, 121, 120, 120, 120, + /* 580 */ 119, 116, 444, 485, 1192, 1193, 1194, 482, 281, 1267, + /* 590 */ 957, 252, 1192, 373, 504, 501, 500, 1192, 340, 571, + /* 600 */ 1192, 571, 409, 292, 499, 957, 876, 191, 480, 316, + /* 610 */ 559, 384, 290, 380, 122, 122, 122, 122, 121, 121, + /* 620 */ 120, 120, 120, 119, 116, 444, 125, 126, 80, 1217, + /* 630 */ 1217, 1050, 1053, 1040, 1040, 123, 123, 124, 124, 124, + /* 640 */ 124, 409, 394, 1136, 1192, 869, 100, 284, 284, 1192, + /* 650 */ 1193, 1194, 373, 1093, 1192, 1193, 1194, 1192, 1193, 1194, + /* 660 */ 565, 455, 32, 373, 233, 125, 126, 80, 1217, 1217, + /* 670 */ 1050, 1053, 1040, 1040, 123, 123, 124, 124, 124, 124, + /* 680 */ 1433, 959, 568, 228, 958, 122, 122, 122, 122, 121, + /* 690 */ 121, 120, 120, 120, 119, 116, 444, 1158, 228, 1192, + /* 700 */ 157, 1192, 1193, 1194, 1553, 13, 13, 301, 957, 1232, + /* 710 */ 1158, 153, 409, 1158, 373, 1583, 1176, 5, 369, 1580, + /* 720 */ 429, 1238, 3, 957, 122, 122, 122, 122, 121, 121, + /* 730 */ 120, 120, 120, 119, 116, 444, 125, 126, 80, 1217, + /* 740 */ 1217, 1050, 1053, 1040, 1040, 123, 123, 124, 124, 124, + /* 750 */ 124, 409, 208, 567, 1192, 1028, 1192, 1193, 1194, 1192, + /* 760 */ 388, 852, 155, 1552, 286, 402, 1098, 1098, 488, 568, + /* 770 */ 465, 342, 1319, 1319, 1552, 125, 126, 80, 1217, 1217, + /* 780 */ 1050, 1053, 1040, 1040, 123, 123, 124, 124, 124, 124, + /* 790 */ 129, 568, 13, 13, 374, 122, 122, 122, 122, 121, + /* 800 */ 121, 120, 120, 120, 119, 116, 444, 302, 568, 453, + /* 810 */ 528, 1192, 1193, 1194, 13, 13, 1192, 1193, 1194, 1297, + /* 820 */ 463, 1267, 409, 1317, 1317, 1552, 1012, 453, 452, 200, + /* 830 */ 299, 71, 71, 1265, 122, 122, 122, 122, 121, 121, + /* 840 */ 120, 120, 120, 119, 116, 444, 125, 126, 80, 1217, + /* 850 */ 1217, 1050, 1053, 1040, 1040, 123, 123, 124, 124, 124, + /* 860 */ 124, 409, 227, 1073, 1158, 284, 284, 419, 312, 278, + /* 870 */ 278, 285, 285, 1419, 406, 405, 382, 1158, 565, 568, + /* 880 */ 1158, 1196, 565, 1600, 565, 125, 126, 80, 1217, 1217, + /* 890 */ 1050, 1053, 1040, 1040, 123, 123, 124, 124, 124, 124, + /* 900 */ 453, 1482, 13, 13, 1536, 122, 122, 122, 122, 121, + /* 910 */ 121, 120, 120, 120, 119, 116, 444, 201, 568, 354, + /* 920 */ 1586, 575, 2, 1245, 840, 841, 842, 1562, 317, 1212, + /* 930 */ 146, 6, 409, 255, 254, 253, 206, 1327, 9, 1196, + /* 940 */ 262, 71, 71, 424, 122, 122, 122, 122, 121, 121, + /* 950 */ 120, 120, 120, 119, 116, 444, 125, 126, 80, 1217, + /* 960 */ 1217, 1050, 1053, 1040, 1040, 123, 123, 124, 124, 124, + /* 970 */ 124, 568, 284, 284, 568, 1213, 409, 574, 313, 1245, + /* 980 */ 349, 1296, 352, 419, 317, 565, 146, 491, 525, 1643, + /* 990 */ 395, 371, 491, 1327, 70, 70, 1295, 71, 71, 240, + /* 1000 */ 1325, 104, 80, 1217, 1217, 1050, 1053, 1040, 1040, 123, + /* 1010 */ 123, 124, 124, 124, 124, 122, 122, 122, 122, 121, + /* 1020 */ 121, 120, 120, 120, 119, 116, 444, 1114, 284, 284, + /* 1030 */ 428, 448, 1525, 1213, 439, 284, 284, 1489, 1352, 311, + /* 1040 */ 474, 565, 1115, 971, 491, 491, 217, 1263, 565, 1538, + /* 1050 */ 568, 972, 207, 568, 1027, 240, 383, 1116, 519, 122, + /* 1060 */ 122, 122, 122, 121, 121, 120, 120, 120, 119, 116, + /* 1070 */ 444, 1018, 107, 71, 71, 1017, 13, 13, 912, 568, + /* 1080 */ 1495, 568, 284, 284, 97, 526, 491, 448, 913, 1326, + /* 1090 */ 1322, 545, 409, 284, 284, 565, 151, 209, 1495, 1497, + /* 1100 */ 262, 450, 55, 55, 56, 56, 565, 1017, 1017, 1019, + /* 1110 */ 443, 332, 409, 527, 12, 295, 125, 126, 80, 1217, + /* 1120 */ 1217, 1050, 1053, 1040, 1040, 123, 123, 124, 124, 124, + /* 1130 */ 124, 347, 409, 864, 1534, 1213, 125, 126, 80, 1217, + /* 1140 */ 1217, 1050, 1053, 1040, 1040, 123, 123, 124, 124, 124, + /* 1150 */ 124, 1137, 1641, 474, 1641, 371, 125, 114, 80, 1217, + /* 1160 */ 1217, 1050, 1053, 1040, 1040, 123, 123, 124, 124, 124, + /* 1170 */ 124, 1495, 329, 474, 331, 122, 122, 122, 122, 121, + /* 1180 */ 121, 120, 120, 120, 119, 116, 444, 203, 1419, 568, + /* 1190 */ 1294, 864, 464, 1213, 436, 122, 122, 122, 122, 121, + /* 1200 */ 121, 120, 120, 120, 119, 116, 444, 553, 1137, 1642, + /* 1210 */ 539, 1642, 15, 15, 892, 122, 122, 122, 122, 121, + /* 1220 */ 121, 120, 120, 120, 119, 116, 444, 568, 298, 538, + /* 1230 */ 1135, 1419, 1559, 1560, 1331, 409, 6, 6, 1169, 1268, + /* 1240 */ 415, 320, 284, 284, 1419, 508, 565, 525, 300, 457, + /* 1250 */ 43, 43, 568, 893, 12, 565, 330, 478, 425, 407, + /* 1260 */ 126, 80, 1217, 1217, 1050, 1053, 1040, 1040, 123, 123, + /* 1270 */ 124, 124, 124, 124, 568, 57, 57, 288, 1192, 1419, + /* 1280 */ 496, 458, 392, 392, 391, 273, 389, 1135, 1558, 849, + /* 1290 */ 1169, 407, 6, 568, 321, 1158, 470, 44, 44, 1557, + /* 1300 */ 1114, 426, 234, 6, 323, 256, 540, 256, 1158, 431, + /* 1310 */ 568, 1158, 322, 17, 487, 1115, 58, 58, 122, 122, + /* 1320 */ 122, 122, 121, 121, 120, 120, 120, 119, 116, 444, + /* 1330 */ 1116, 216, 481, 59, 59, 1192, 1193, 1194, 111, 560, + /* 1340 */ 324, 4, 236, 456, 526, 568, 237, 456, 568, 437, + /* 1350 */ 168, 556, 420, 141, 479, 563, 568, 293, 568, 1095, + /* 1360 */ 568, 293, 568, 1095, 531, 568, 872, 8, 60, 60, + /* 1370 */ 235, 61, 61, 568, 414, 568, 414, 568, 445, 62, + /* 1380 */ 62, 45, 45, 46, 46, 47, 47, 199, 49, 49, + /* 1390 */ 557, 568, 359, 568, 100, 486, 50, 50, 63, 63, + /* 1400 */ 64, 64, 561, 415, 535, 410, 568, 1027, 568, 534, + /* 1410 */ 316, 559, 316, 559, 65, 65, 14, 14, 568, 1027, + /* 1420 */ 568, 512, 932, 872, 1018, 109, 109, 931, 1017, 66, + /* 1430 */ 66, 131, 131, 110, 451, 445, 570, 569, 416, 177, + /* 1440 */ 1017, 132, 132, 67, 67, 568, 467, 568, 932, 471, + /* 1450 */ 1364, 283, 226, 931, 315, 1363, 407, 568, 459, 407, + /* 1460 */ 1017, 1017, 1019, 239, 407, 86, 213, 1350, 52, 52, + /* 1470 */ 68, 68, 1017, 1017, 1019, 1020, 27, 1585, 1180, 447, + /* 1480 */ 69, 69, 288, 97, 108, 1541, 106, 392, 392, 391, + /* 1490 */ 273, 389, 568, 879, 849, 883, 568, 111, 560, 466, + /* 1500 */ 4, 568, 152, 30, 38, 568, 1132, 234, 396, 323, + /* 1510 */ 111, 560, 527, 4, 563, 53, 53, 322, 568, 163, + /* 1520 */ 163, 568, 337, 468, 164, 164, 333, 563, 76, 76, + /* 1530 */ 568, 289, 1514, 568, 31, 1513, 568, 445, 338, 483, + /* 1540 */ 100, 54, 54, 344, 72, 72, 296, 236, 1080, 557, + /* 1550 */ 445, 879, 1360, 134, 134, 168, 73, 73, 141, 161, + /* 1560 */ 161, 1574, 557, 535, 568, 319, 568, 348, 536, 1009, + /* 1570 */ 473, 261, 261, 891, 890, 235, 535, 568, 1027, 568, + /* 1580 */ 475, 534, 261, 367, 109, 109, 521, 136, 136, 130, + /* 1590 */ 130, 1027, 110, 366, 445, 570, 569, 109, 109, 1017, + /* 1600 */ 162, 162, 156, 156, 568, 110, 1080, 445, 570, 569, + /* 1610 */ 410, 351, 1017, 568, 353, 316, 559, 568, 343, 568, + /* 1620 */ 100, 497, 357, 258, 100, 898, 899, 140, 140, 355, + /* 1630 */ 1310, 1017, 1017, 1019, 1020, 27, 139, 139, 362, 451, + /* 1640 */ 137, 137, 138, 138, 1017, 1017, 1019, 1020, 27, 1180, + /* 1650 */ 447, 568, 372, 288, 111, 560, 1021, 4, 392, 392, + /* 1660 */ 391, 273, 389, 568, 1141, 849, 568, 1076, 568, 258, + /* 1670 */ 492, 563, 568, 211, 75, 75, 555, 962, 234, 261, + /* 1680 */ 323, 111, 560, 929, 4, 113, 77, 77, 322, 74, + /* 1690 */ 74, 42, 42, 1373, 445, 48, 48, 1418, 563, 974, + /* 1700 */ 975, 1092, 1091, 1092, 1091, 862, 557, 150, 930, 1346, + /* 1710 */ 113, 1358, 554, 1424, 1021, 1275, 1266, 1254, 236, 1253, + /* 1720 */ 1255, 445, 1593, 1343, 308, 276, 168, 309, 11, 141, + /* 1730 */ 393, 310, 232, 557, 1405, 1027, 335, 291, 1400, 219, + /* 1740 */ 336, 109, 109, 936, 297, 1410, 235, 341, 477, 110, + /* 1750 */ 502, 445, 570, 569, 1393, 1409, 1017, 400, 1293, 365, + /* 1760 */ 223, 1486, 1027, 1485, 1355, 1356, 1354, 1353, 109, 109, + /* 1770 */ 204, 1596, 1232, 558, 265, 218, 110, 205, 445, 570, + /* 1780 */ 569, 410, 387, 1017, 1533, 179, 316, 559, 1017, 1017, + /* 1790 */ 1019, 1020, 27, 230, 1531, 1229, 79, 560, 85, 4, + /* 1800 */ 418, 215, 548, 81, 84, 188, 1406, 173, 181, 461, + /* 1810 */ 451, 35, 462, 563, 183, 1017, 1017, 1019, 1020, 27, + /* 1820 */ 184, 1491, 185, 186, 495, 242, 98, 398, 1412, 36, + /* 1830 */ 1411, 484, 91, 469, 401, 1414, 445, 192, 1480, 246, + /* 1840 */ 1502, 490, 346, 277, 248, 196, 493, 511, 557, 350, + /* 1850 */ 1256, 249, 250, 403, 1313, 1312, 111, 560, 432, 4, + /* 1860 */ 1311, 1304, 93, 1611, 883, 1610, 224, 404, 434, 520, + /* 1870 */ 263, 435, 1579, 563, 1283, 1282, 364, 1027, 306, 1281, + /* 1880 */ 264, 1609, 1565, 109, 109, 370, 1303, 307, 1564, 438, + /* 1890 */ 128, 110, 1378, 445, 570, 569, 445, 546, 1017, 10, + /* 1900 */ 1466, 105, 381, 1377, 34, 572, 99, 1336, 557, 314, + /* 1910 */ 1186, 530, 272, 274, 379, 210, 1335, 547, 385, 386, + /* 1920 */ 275, 573, 1251, 1246, 411, 412, 1518, 165, 178, 1519, + /* 1930 */ 1017, 1017, 1019, 1020, 27, 1517, 1516, 1027, 78, 147, + /* 1940 */ 166, 220, 221, 109, 109, 836, 304, 167, 446, 212, + /* 1950 */ 318, 110, 231, 445, 570, 569, 144, 1090, 1017, 1088, + /* 1960 */ 326, 180, 169, 1212, 182, 334, 238, 915, 241, 1104, + /* 1970 */ 187, 170, 171, 421, 87, 88, 423, 189, 89, 90, + /* 1980 */ 172, 1107, 243, 1103, 244, 158, 18, 245, 345, 247, + /* 1990 */ 1017, 1017, 1019, 1020, 27, 261, 1096, 193, 1226, 489, + /* 2000 */ 194, 37, 366, 851, 494, 251, 195, 506, 92, 19, + /* 2010 */ 498, 358, 20, 503, 881, 361, 94, 894, 305, 159, + /* 2020 */ 513, 39, 95, 1174, 160, 1056, 966, 1143, 96, 174, + /* 2030 */ 1142, 225, 280, 282, 198, 960, 113, 1164, 1160, 260, + /* 2040 */ 21, 22, 23, 1162, 1168, 1167, 1148, 24, 33, 25, + /* 2050 */ 202, 542, 26, 100, 1071, 102, 1057, 103, 7, 1055, + /* 2060 */ 1059, 1113, 1060, 1112, 266, 267, 28, 40, 390, 1022, + /* 2070 */ 863, 112, 29, 564, 1182, 1181, 268, 176, 143, 925, + /* 2080 */ 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, 1242, + /* 2090 */ 1242, 1242, 1242, 1242, 269, 1602, 1242, 1601, }; static const YYCODETYPE yy_lookahead[] = { - /* 0 */ 192, 273, 274, 275, 192, 192, 273, 274, 275, 192, - /* 10 */ 218, 215, 192, 218, 192, 212, 234, 235, 205, 19, - /* 20 */ 11, 192, 294, 215, 216, 203, 192, 203, 209, 210, - /* 30 */ 211, 31, 215, 216, 205, 215, 216, 215, 216, 39, - /* 40 */ 227, 215, 229, 43, 44, 45, 46, 47, 48, 49, - /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 192, 19, - /* 60 */ 238, 239, 238, 239, 215, 273, 274, 275, 273, 274, - /* 70 */ 275, 237, 21, 251, 252, 251, 273, 274, 275, 255, - /* 80 */ 256, 215, 216, 43, 44, 45, 46, 47, 48, 49, - /* 90 */ 50, 51, 52, 53, 54, 55, 56, 57, 209, 210, - /* 100 */ 211, 76, 102, 103, 104, 105, 106, 107, 108, 109, - /* 110 */ 110, 111, 112, 59, 89, 111, 112, 92, 252, 307, - /* 120 */ 308, 313, 314, 112, 312, 59, 86, 261, 88, 19, - /* 130 */ 313, 80, 315, 313, 314, 25, 127, 128, 54, 55, - /* 140 */ 56, 57, 102, 103, 104, 105, 106, 107, 108, 109, - /* 150 */ 110, 111, 112, 43, 44, 45, 46, 47, 48, 49, - /* 160 */ 50, 51, 52, 53, 54, 55, 56, 57, 192, 115, - /* 170 */ 116, 117, 118, 122, 192, 121, 122, 123, 202, 69, - /* 180 */ 204, 115, 116, 117, 192, 131, 102, 103, 104, 105, - /* 190 */ 106, 107, 108, 109, 110, 111, 112, 215, 216, 19, - /* 200 */ 54, 55, 56, 57, 58, 108, 109, 110, 111, 112, - /* 210 */ 192, 160, 102, 103, 104, 105, 106, 107, 108, 109, - /* 220 */ 110, 111, 112, 43, 44, 45, 46, 47, 48, 49, - /* 230 */ 50, 51, 52, 53, 54, 55, 56, 57, 19, 46, - /* 240 */ 47, 48, 49, 24, 248, 192, 250, 67, 102, 103, - /* 250 */ 104, 105, 106, 107, 108, 109, 110, 111, 112, 277, - /* 260 */ 127, 128, 43, 44, 45, 46, 47, 48, 49, 50, - /* 270 */ 51, 52, 53, 54, 55, 56, 57, 26, 164, 165, - /* 280 */ 272, 263, 102, 103, 104, 105, 106, 107, 108, 109, - /* 290 */ 110, 111, 112, 184, 185, 186, 187, 188, 189, 186, - /* 300 */ 187, 188, 189, 194, 76, 196, 229, 194, 19, 196, - /* 310 */ 59, 192, 203, 120, 59, 87, 203, 89, 310, 311, - /* 320 */ 92, 102, 103, 104, 105, 106, 107, 108, 109, 110, - /* 330 */ 111, 112, 43, 44, 45, 46, 47, 48, 49, 50, - /* 340 */ 51, 52, 53, 54, 55, 56, 57, 238, 239, 73, - /* 350 */ 231, 238, 239, 22, 23, 100, 25, 81, 305, 306, - /* 360 */ 251, 23, 25, 25, 251, 272, 115, 116, 117, 214, - /* 370 */ 115, 116, 144, 192, 265, 120, 114, 222, 265, 102, - /* 380 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - /* 390 */ 192, 102, 103, 104, 105, 106, 107, 108, 109, 110, - /* 400 */ 111, 112, 126, 310, 311, 192, 297, 152, 153, 154, - /* 410 */ 297, 149, 192, 137, 138, 19, 192, 100, 192, 23, - /* 420 */ 22, 106, 107, 108, 109, 110, 111, 112, 215, 216, - /* 430 */ 106, 107, 101, 116, 192, 215, 216, 120, 149, 43, - /* 440 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - /* 450 */ 54, 55, 56, 57, 117, 117, 192, 59, 19, 187, - /* 460 */ 59, 189, 23, 282, 240, 252, 194, 192, 196, 152, - /* 470 */ 153, 154, 252, 72, 261, 203, 152, 25, 154, 142, - /* 480 */ 142, 261, 43, 44, 45, 46, 47, 48, 49, 50, - /* 490 */ 51, 52, 53, 54, 55, 56, 57, 192, 102, 103, - /* 500 */ 104, 105, 106, 107, 108, 109, 110, 111, 112, 267, - /* 510 */ 238, 239, 237, 115, 116, 117, 115, 116, 117, 192, - /* 520 */ 59, 118, 16, 251, 121, 122, 123, 303, 19, 303, - /* 530 */ 59, 267, 23, 72, 131, 308, 22, 265, 22, 312, - /* 540 */ 24, 102, 103, 104, 105, 106, 107, 108, 109, 110, - /* 550 */ 111, 112, 43, 44, 45, 46, 47, 48, 49, 50, - /* 560 */ 51, 52, 53, 54, 55, 56, 57, 19, 81, 297, - /* 570 */ 295, 23, 192, 59, 203, 59, 115, 116, 117, 108, - /* 580 */ 192, 73, 25, 77, 192, 79, 115, 116, 117, 137, - /* 590 */ 138, 43, 44, 45, 46, 47, 48, 49, 50, 51, - /* 600 */ 52, 53, 54, 55, 56, 57, 119, 215, 216, 238, - /* 610 */ 239, 102, 103, 104, 105, 106, 107, 108, 109, 110, - /* 620 */ 111, 112, 251, 192, 137, 138, 59, 234, 235, 115, - /* 630 */ 116, 117, 116, 76, 126, 127, 128, 19, 192, 268, - /* 640 */ 19, 23, 22, 192, 252, 24, 89, 300, 301, 92, - /* 650 */ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - /* 660 */ 112, 43, 44, 45, 46, 47, 48, 49, 50, 51, - /* 670 */ 52, 53, 54, 55, 56, 57, 19, 192, 192, 59, - /* 680 */ 23, 192, 115, 116, 117, 200, 240, 307, 308, 22, - /* 690 */ 205, 81, 312, 262, 22, 192, 133, 22, 135, 136, - /* 700 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, - /* 710 */ 53, 54, 55, 56, 57, 197, 95, 150, 215, 216, - /* 720 */ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - /* 730 */ 112, 59, 192, 112, 59, 115, 116, 117, 192, 118, - /* 740 */ 119, 120, 121, 122, 123, 124, 19, 137, 138, 303, - /* 750 */ 23, 130, 192, 267, 192, 252, 267, 306, 203, 102, - /* 760 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - /* 770 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, - /* 780 */ 53, 54, 55, 56, 57, 19, 240, 115, 116, 117, - /* 790 */ 115, 116, 117, 238, 239, 222, 192, 224, 280, 237, - /* 800 */ 240, 192, 284, 192, 59, 232, 251, 140, 204, 43, - /* 810 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - /* 820 */ 54, 55, 56, 57, 192, 35, 215, 216, 192, 102, - /* 830 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, - /* 840 */ 59, 230, 192, 192, 238, 239, 237, 215, 216, 303, - /* 850 */ 308, 215, 216, 16, 312, 19, 66, 251, 126, 127, - /* 860 */ 128, 116, 230, 303, 74, 203, 215, 216, 102, 103, - /* 870 */ 104, 105, 106, 107, 108, 109, 110, 111, 112, 43, - /* 880 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - /* 890 */ 54, 55, 56, 57, 192, 212, 115, 116, 117, 19, - /* 900 */ 238, 239, 192, 252, 7, 8, 9, 192, 192, 238, - /* 910 */ 239, 308, 262, 251, 77, 312, 79, 215, 216, 129, - /* 920 */ 210, 211, 251, 142, 158, 45, 46, 47, 48, 49, - /* 930 */ 50, 51, 52, 53, 54, 55, 56, 57, 102, 103, - /* 940 */ 104, 105, 106, 107, 108, 109, 110, 111, 112, 12, - /* 950 */ 59, 192, 192, 237, 252, 243, 192, 192, 126, 127, - /* 960 */ 128, 192, 308, 203, 27, 253, 312, 308, 285, 207, - /* 970 */ 208, 312, 157, 290, 159, 215, 216, 262, 192, 42, - /* 980 */ 215, 216, 102, 103, 104, 105, 106, 107, 108, 109, - /* 990 */ 110, 111, 112, 283, 158, 230, 237, 160, 238, 239, - /* 1000 */ 63, 215, 216, 192, 192, 12, 115, 116, 117, 22, - /* 1010 */ 73, 251, 252, 192, 19, 192, 230, 239, 24, 24, - /* 1020 */ 27, 261, 210, 211, 99, 192, 215, 216, 225, 251, - /* 1030 */ 192, 192, 263, 142, 19, 42, 215, 216, 43, 44, - /* 1040 */ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - /* 1050 */ 55, 56, 57, 59, 19, 291, 63, 132, 43, 44, - /* 1060 */ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - /* 1070 */ 55, 56, 57, 252, 22, 23, 22, 25, 43, 44, - /* 1080 */ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - /* 1090 */ 55, 56, 57, 106, 107, 283, 263, 102, 103, 104, - /* 1100 */ 105, 106, 107, 108, 109, 110, 111, 112, 59, 192, - /* 1110 */ 116, 144, 29, 59, 291, 192, 33, 102, 103, 104, - /* 1120 */ 105, 106, 107, 108, 109, 110, 111, 112, 192, 291, - /* 1130 */ 163, 19, 215, 216, 15, 192, 108, 102, 103, 104, - /* 1140 */ 105, 106, 107, 108, 109, 110, 111, 112, 65, 192, - /* 1150 */ 66, 215, 216, 101, 231, 106, 107, 19, 215, 216, - /* 1160 */ 192, 212, 134, 114, 115, 116, 117, 139, 119, 85, - /* 1170 */ 116, 207, 208, 230, 192, 19, 127, 192, 94, 60, - /* 1180 */ 59, 192, 44, 45, 46, 47, 48, 49, 50, 51, - /* 1190 */ 52, 53, 54, 55, 56, 57, 192, 76, 192, 31, - /* 1200 */ 192, 152, 46, 154, 215, 216, 192, 39, 87, 192, - /* 1210 */ 89, 19, 20, 92, 22, 192, 22, 23, 22, 230, - /* 1220 */ 263, 215, 216, 215, 216, 137, 138, 115, 36, 145, - /* 1230 */ 128, 192, 215, 216, 22, 23, 115, 116, 117, 290, - /* 1240 */ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - /* 1250 */ 112, 59, 192, 151, 215, 216, 192, 61, 203, 298, - /* 1260 */ 299, 192, 192, 71, 25, 144, 203, 192, 203, 230, - /* 1270 */ 114, 19, 20, 81, 22, 215, 216, 263, 192, 215, - /* 1280 */ 216, 255, 256, 203, 215, 216, 130, 19, 36, 192, - /* 1290 */ 215, 216, 100, 238, 239, 101, 25, 192, 106, 107, - /* 1300 */ 48, 238, 239, 238, 239, 113, 251, 115, 116, 117, - /* 1310 */ 192, 59, 120, 101, 251, 192, 251, 192, 238, 239, - /* 1320 */ 215, 216, 192, 71, 46, 243, 192, 25, 25, 137, - /* 1330 */ 138, 251, 192, 215, 216, 253, 25, 85, 215, 216, - /* 1340 */ 215, 216, 90, 243, 152, 153, 154, 155, 156, 215, - /* 1350 */ 216, 192, 100, 253, 243, 215, 216, 192, 106, 107, - /* 1360 */ 243, 192, 148, 149, 253, 113, 192, 115, 116, 117, - /* 1370 */ 253, 192, 120, 192, 215, 216, 192, 23, 192, 25, - /* 1380 */ 215, 216, 192, 115, 215, 216, 22, 148, 24, 215, - /* 1390 */ 216, 192, 114, 192, 215, 216, 215, 216, 134, 215, - /* 1400 */ 216, 215, 216, 139, 152, 153, 154, 155, 156, 0, - /* 1410 */ 1, 2, 141, 23, 5, 25, 215, 216, 24, 10, - /* 1420 */ 11, 12, 13, 14, 1, 2, 17, 125, 5, 19, - /* 1430 */ 20, 268, 22, 10, 11, 12, 13, 14, 192, 30, - /* 1440 */ 17, 32, 23, 23, 25, 25, 36, 144, 23, 40, - /* 1450 */ 25, 192, 141, 30, 192, 32, 23, 22, 25, 5, - /* 1460 */ 128, 215, 216, 40, 10, 11, 12, 13, 14, 59, - /* 1470 */ 23, 17, 25, 192, 215, 216, 192, 215, 216, 70, - /* 1480 */ 23, 71, 25, 151, 30, 192, 32, 78, 53, 192, - /* 1490 */ 81, 192, 192, 70, 40, 85, 215, 216, 119, 120, - /* 1500 */ 90, 78, 59, 254, 81, 192, 192, 98, 215, 216, - /* 1510 */ 100, 23, 59, 25, 215, 216, 106, 107, 23, 192, - /* 1520 */ 25, 98, 19, 113, 70, 115, 116, 117, 215, 216, - /* 1530 */ 120, 192, 78, 192, 140, 81, 19, 20, 23, 22, - /* 1540 */ 25, 132, 215, 216, 192, 192, 137, 138, 192, 23, - /* 1550 */ 192, 25, 98, 36, 192, 132, 215, 216, 192, 116, - /* 1560 */ 137, 138, 152, 153, 154, 155, 156, 215, 216, 116, - /* 1570 */ 161, 215, 216, 215, 216, 120, 59, 215, 216, 7, - /* 1580 */ 8, 215, 216, 192, 161, 130, 132, 192, 71, 83, - /* 1590 */ 84, 137, 138, 59, 192, 192, 19, 20, 192, 22, - /* 1600 */ 97, 225, 85, 192, 23, 192, 25, 90, 192, 192, - /* 1610 */ 215, 216, 152, 36, 154, 161, 192, 100, 215, 216, - /* 1620 */ 192, 215, 216, 106, 107, 225, 215, 216, 192, 192, - /* 1630 */ 113, 192, 115, 116, 117, 257, 59, 120, 192, 215, - /* 1640 */ 216, 152, 192, 154, 192, 23, 317, 25, 71, 235, - /* 1650 */ 116, 215, 216, 192, 215, 216, 192, 192, 192, 192, - /* 1660 */ 192, 192, 192, 192, 192, 215, 216, 215, 216, 152, - /* 1670 */ 153, 154, 155, 156, 192, 192, 287, 100, 286, 241, - /* 1680 */ 254, 254, 242, 106, 107, 108, 254, 213, 254, 190, - /* 1690 */ 113, 270, 115, 116, 117, 296, 266, 120, 219, 258, - /* 1700 */ 244, 270, 258, 19, 20, 228, 22, 292, 266, 224, - /* 1710 */ 292, 218, 218, 195, 218, 270, 258, 60, 245, 270, - /* 1720 */ 36, 245, 244, 248, 19, 20, 242, 22, 248, 152, - /* 1730 */ 153, 154, 155, 156, 244, 140, 199, 199, 279, 38, - /* 1740 */ 199, 36, 150, 59, 296, 149, 22, 296, 18, 43, - /* 1750 */ 236, 199, 233, 18, 198, 71, 293, 236, 271, 236, - /* 1760 */ 269, 236, 148, 271, 59, 245, 269, 245, 282, 271, - /* 1770 */ 199, 198, 233, 245, 293, 233, 71, 245, 157, 62, - /* 1780 */ 22, 199, 198, 220, 100, 199, 198, 220, 199, 289, - /* 1790 */ 106, 107, 288, 114, 226, 198, 217, 113, 64, 115, - /* 1800 */ 116, 117, 217, 22, 120, 100, 223, 217, 217, 164, - /* 1810 */ 223, 106, 107, 220, 125, 24, 217, 219, 113, 217, - /* 1820 */ 115, 116, 117, 217, 311, 120, 226, 112, 304, 281, - /* 1830 */ 281, 220, 114, 143, 260, 259, 152, 153, 154, 155, - /* 1840 */ 156, 199, 91, 316, 82, 316, 147, 144, 22, 199, - /* 1850 */ 249, 276, 157, 146, 260, 145, 278, 152, 153, 154, - /* 1860 */ 155, 156, 259, 248, 260, 260, 259, 259, 249, 245, - /* 1870 */ 247, 246, 25, 264, 264, 201, 13, 6, 193, 193, - /* 1880 */ 212, 206, 191, 191, 191, 212, 206, 221, 212, 212, - /* 1890 */ 221, 213, 4, 206, 213, 212, 3, 22, 162, 15, - /* 1900 */ 23, 16, 23, 138, 150, 129, 25, 24, 141, 20, - /* 1910 */ 16, 143, 1, 141, 302, 302, 299, 129, 129, 61, - /* 1920 */ 150, 53, 53, 37, 129, 53, 53, 115, 1, 34, - /* 1930 */ 140, 5, 22, 114, 160, 68, 75, 25, 68, 41, - /* 1940 */ 140, 114, 24, 20, 19, 130, 124, 67, 24, 67, - /* 1950 */ 22, 22, 22, 96, 23, 22, 59, 22, 67, 37, - /* 1960 */ 28, 23, 148, 22, 25, 23, 23, 23, 23, 22, - /* 1970 */ 140, 97, 23, 23, 115, 22, 142, 25, 88, 75, - /* 1980 */ 34, 44, 34, 75, 23, 34, 86, 22, 34, 34, - /* 1990 */ 34, 24, 93, 25, 25, 23, 34, 23, 23, 23, - /* 2000 */ 23, 11, 23, 25, 22, 22, 22, 1, 23, 23, - /* 2010 */ 22, 22, 25, 15, 23, 1, 140, 25, 140, 318, - /* 2020 */ 318, 134, 318, 318, 318, 318, 318, 318, 318, 318, - /* 2030 */ 318, 318, 140, 318, 318, 318, 140, 318, 318, 318, - /* 2040 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - /* 2050 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - /* 2060 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - /* 2070 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - /* 2080 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - /* 2090 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - /* 2100 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - /* 2110 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - /* 2120 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - /* 2130 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - /* 2140 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - /* 2150 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - /* 2160 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - /* 2170 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - /* 2180 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - /* 2190 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - /* 2200 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - /* 2210 */ 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, - /* 2220 */ 318, + /* 0 */ 193, 193, 193, 274, 275, 276, 193, 274, 275, 276, + /* 10 */ 193, 223, 219, 225, 206, 210, 211, 212, 193, 19, + /* 20 */ 219, 233, 216, 216, 217, 216, 217, 193, 295, 216, + /* 30 */ 217, 31, 193, 216, 217, 193, 228, 213, 230, 39, + /* 40 */ 206, 216, 217, 43, 44, 45, 46, 47, 48, 49, + /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 193, 19, + /* 60 */ 185, 186, 187, 188, 189, 190, 253, 274, 275, 276, + /* 70 */ 195, 193, 197, 193, 261, 274, 275, 276, 253, 204, + /* 80 */ 238, 204, 81, 43, 44, 45, 46, 47, 48, 49, + /* 90 */ 50, 51, 52, 53, 54, 55, 56, 57, 274, 275, + /* 100 */ 276, 262, 102, 103, 104, 105, 106, 107, 108, 109, + /* 110 */ 110, 111, 112, 113, 239, 240, 239, 240, 210, 211, + /* 120 */ 212, 314, 315, 314, 59, 316, 86, 252, 88, 252, + /* 130 */ 19, 314, 315, 256, 257, 113, 25, 72, 296, 138, + /* 140 */ 139, 266, 102, 103, 104, 105, 106, 107, 108, 109, + /* 150 */ 110, 111, 112, 113, 43, 44, 45, 46, 47, 48, + /* 160 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 81, + /* 170 */ 292, 59, 292, 298, 108, 109, 110, 111, 112, 113, + /* 180 */ 69, 116, 117, 118, 72, 106, 107, 193, 111, 112, + /* 190 */ 113, 54, 55, 56, 57, 58, 102, 103, 104, 105, + /* 200 */ 106, 107, 108, 109, 110, 111, 112, 113, 120, 25, + /* 210 */ 216, 217, 145, 102, 103, 104, 105, 106, 107, 108, + /* 220 */ 109, 110, 111, 112, 113, 231, 138, 139, 116, 117, + /* 230 */ 118, 164, 153, 19, 155, 54, 55, 56, 57, 102, + /* 240 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + /* 250 */ 113, 128, 129, 46, 47, 48, 49, 43, 44, 45, + /* 260 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + /* 270 */ 56, 57, 216, 193, 25, 59, 193, 19, 165, 166, + /* 280 */ 193, 67, 24, 102, 103, 104, 105, 106, 107, 108, + /* 290 */ 109, 110, 111, 112, 113, 73, 216, 217, 59, 216, + /* 300 */ 217, 43, 44, 45, 46, 47, 48, 49, 50, 51, + /* 310 */ 52, 53, 54, 55, 56, 57, 102, 103, 104, 105, + /* 320 */ 106, 107, 108, 109, 110, 111, 112, 113, 121, 145, + /* 330 */ 59, 193, 116, 117, 118, 119, 273, 204, 122, 123, + /* 340 */ 124, 19, 20, 134, 22, 136, 137, 19, 132, 127, + /* 350 */ 128, 129, 24, 22, 23, 116, 117, 118, 36, 193, + /* 360 */ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + /* 370 */ 112, 113, 239, 240, 311, 312, 215, 106, 107, 241, + /* 380 */ 19, 59, 216, 217, 223, 252, 115, 116, 117, 118, + /* 390 */ 151, 120, 26, 71, 193, 308, 309, 193, 149, 128, + /* 400 */ 313, 216, 269, 81, 43, 44, 45, 46, 47, 48, + /* 410 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 253, + /* 420 */ 216, 217, 100, 95, 153, 59, 155, 261, 106, 107, + /* 430 */ 25, 193, 101, 193, 193, 231, 114, 25, 116, 117, + /* 440 */ 118, 113, 304, 121, 193, 204, 59, 119, 120, 121, + /* 450 */ 122, 123, 124, 125, 216, 217, 193, 216, 217, 131, + /* 460 */ 138, 139, 230, 102, 103, 104, 105, 106, 107, 108, + /* 470 */ 109, 110, 111, 112, 113, 153, 154, 155, 156, 157, + /* 480 */ 239, 240, 116, 117, 118, 76, 193, 23, 19, 25, + /* 490 */ 22, 253, 23, 252, 253, 108, 87, 204, 89, 261, + /* 500 */ 198, 92, 261, 116, 117, 118, 193, 306, 307, 216, + /* 510 */ 217, 150, 43, 44, 45, 46, 47, 48, 49, 50, + /* 520 */ 51, 52, 53, 54, 55, 56, 57, 59, 193, 216, + /* 530 */ 217, 19, 239, 240, 283, 23, 106, 107, 108, 109, + /* 540 */ 110, 111, 112, 113, 73, 252, 253, 142, 308, 309, + /* 550 */ 138, 139, 81, 313, 145, 43, 44, 45, 46, 47, + /* 560 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + /* 570 */ 307, 102, 103, 104, 105, 106, 107, 108, 109, 110, + /* 580 */ 111, 112, 113, 281, 116, 117, 118, 285, 23, 193, + /* 590 */ 25, 119, 59, 193, 122, 123, 124, 59, 127, 203, + /* 600 */ 59, 205, 19, 268, 132, 25, 23, 22, 193, 138, + /* 610 */ 139, 249, 204, 251, 102, 103, 104, 105, 106, 107, + /* 620 */ 108, 109, 110, 111, 112, 113, 43, 44, 45, 46, + /* 630 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + /* 640 */ 57, 19, 22, 23, 59, 23, 25, 239, 240, 116, + /* 650 */ 117, 118, 193, 11, 116, 117, 118, 116, 117, 118, + /* 660 */ 252, 269, 22, 193, 15, 43, 44, 45, 46, 47, + /* 670 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + /* 680 */ 273, 143, 193, 118, 143, 102, 103, 104, 105, 106, + /* 690 */ 107, 108, 109, 110, 111, 112, 113, 76, 118, 59, + /* 700 */ 241, 116, 117, 118, 304, 216, 217, 292, 143, 60, + /* 710 */ 89, 241, 19, 92, 193, 193, 23, 22, 311, 312, + /* 720 */ 231, 101, 22, 143, 102, 103, 104, 105, 106, 107, + /* 730 */ 108, 109, 110, 111, 112, 113, 43, 44, 45, 46, + /* 740 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + /* 750 */ 57, 19, 193, 193, 59, 23, 116, 117, 118, 59, + /* 760 */ 201, 21, 241, 304, 22, 206, 127, 128, 129, 193, + /* 770 */ 128, 129, 235, 236, 304, 43, 44, 45, 46, 47, + /* 780 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + /* 790 */ 22, 193, 216, 217, 193, 102, 103, 104, 105, 106, + /* 800 */ 107, 108, 109, 110, 111, 112, 113, 231, 193, 193, + /* 810 */ 193, 116, 117, 118, 216, 217, 116, 117, 118, 226, + /* 820 */ 80, 193, 19, 235, 236, 304, 23, 211, 212, 231, + /* 830 */ 204, 216, 217, 205, 102, 103, 104, 105, 106, 107, + /* 840 */ 108, 109, 110, 111, 112, 113, 43, 44, 45, 46, + /* 850 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + /* 860 */ 57, 19, 193, 123, 76, 239, 240, 193, 253, 239, + /* 870 */ 240, 239, 240, 193, 106, 107, 193, 89, 252, 193, + /* 880 */ 92, 59, 252, 141, 252, 43, 44, 45, 46, 47, + /* 890 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + /* 900 */ 284, 161, 216, 217, 193, 102, 103, 104, 105, 106, + /* 910 */ 107, 108, 109, 110, 111, 112, 113, 231, 193, 16, + /* 920 */ 187, 188, 189, 190, 7, 8, 9, 309, 195, 25, + /* 930 */ 197, 313, 19, 127, 128, 129, 262, 204, 22, 117, + /* 940 */ 24, 216, 217, 263, 102, 103, 104, 105, 106, 107, + /* 950 */ 108, 109, 110, 111, 112, 113, 43, 44, 45, 46, + /* 960 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + /* 970 */ 57, 193, 239, 240, 193, 59, 19, 188, 253, 190, + /* 980 */ 77, 226, 79, 193, 195, 252, 197, 193, 19, 301, + /* 990 */ 302, 193, 193, 204, 216, 217, 226, 216, 217, 266, + /* 1000 */ 204, 159, 45, 46, 47, 48, 49, 50, 51, 52, + /* 1010 */ 53, 54, 55, 56, 57, 102, 103, 104, 105, 106, + /* 1020 */ 107, 108, 109, 110, 111, 112, 113, 12, 239, 240, + /* 1030 */ 232, 298, 238, 117, 253, 239, 240, 238, 259, 260, + /* 1040 */ 193, 252, 27, 31, 193, 193, 142, 204, 252, 193, + /* 1050 */ 193, 39, 262, 193, 100, 266, 278, 42, 204, 102, + /* 1060 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + /* 1070 */ 113, 117, 159, 216, 217, 121, 216, 217, 63, 193, + /* 1080 */ 193, 193, 239, 240, 115, 116, 193, 298, 73, 238, + /* 1090 */ 238, 231, 19, 239, 240, 252, 22, 24, 211, 212, + /* 1100 */ 24, 193, 216, 217, 216, 217, 252, 153, 154, 155, + /* 1110 */ 253, 16, 19, 144, 213, 268, 43, 44, 45, 46, + /* 1120 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + /* 1130 */ 57, 238, 19, 59, 193, 59, 43, 44, 45, 46, + /* 1140 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + /* 1150 */ 57, 22, 23, 193, 25, 193, 43, 44, 45, 46, + /* 1160 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, + /* 1170 */ 57, 284, 77, 193, 79, 102, 103, 104, 105, 106, + /* 1180 */ 107, 108, 109, 110, 111, 112, 113, 286, 193, 193, + /* 1190 */ 193, 117, 291, 117, 232, 102, 103, 104, 105, 106, + /* 1200 */ 107, 108, 109, 110, 111, 112, 113, 204, 22, 23, + /* 1210 */ 66, 25, 216, 217, 35, 102, 103, 104, 105, 106, + /* 1220 */ 107, 108, 109, 110, 111, 112, 113, 193, 268, 85, + /* 1230 */ 101, 193, 309, 309, 240, 19, 313, 313, 94, 208, + /* 1240 */ 209, 193, 239, 240, 193, 66, 252, 19, 268, 244, + /* 1250 */ 216, 217, 193, 74, 213, 252, 161, 19, 263, 254, + /* 1260 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + /* 1270 */ 54, 55, 56, 57, 193, 216, 217, 5, 59, 193, + /* 1280 */ 19, 244, 10, 11, 12, 13, 14, 101, 309, 17, + /* 1290 */ 146, 254, 313, 193, 193, 76, 115, 216, 217, 309, + /* 1300 */ 12, 263, 30, 313, 32, 46, 87, 46, 89, 130, + /* 1310 */ 193, 92, 40, 22, 263, 27, 216, 217, 102, 103, + /* 1320 */ 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, + /* 1330 */ 42, 150, 291, 216, 217, 116, 117, 118, 19, 20, + /* 1340 */ 193, 22, 70, 260, 116, 193, 24, 264, 193, 263, + /* 1350 */ 78, 63, 61, 81, 116, 36, 193, 260, 193, 29, + /* 1360 */ 193, 264, 193, 33, 145, 193, 59, 48, 216, 217, + /* 1370 */ 98, 216, 217, 193, 115, 193, 115, 193, 59, 216, + /* 1380 */ 217, 216, 217, 216, 217, 216, 217, 255, 216, 217, + /* 1390 */ 71, 193, 131, 193, 25, 65, 216, 217, 216, 217, + /* 1400 */ 216, 217, 208, 209, 85, 133, 193, 100, 193, 90, + /* 1410 */ 138, 139, 138, 139, 216, 217, 216, 217, 193, 100, + /* 1420 */ 193, 108, 135, 116, 117, 106, 107, 140, 121, 216, + /* 1430 */ 217, 216, 217, 114, 162, 116, 117, 118, 299, 300, + /* 1440 */ 121, 216, 217, 216, 217, 193, 244, 193, 135, 244, + /* 1450 */ 193, 256, 257, 140, 244, 193, 254, 193, 193, 254, + /* 1460 */ 153, 154, 155, 141, 254, 149, 150, 258, 216, 217, + /* 1470 */ 216, 217, 153, 154, 155, 156, 157, 0, 1, 2, + /* 1480 */ 216, 217, 5, 115, 158, 193, 160, 10, 11, 12, + /* 1490 */ 13, 14, 193, 59, 17, 126, 193, 19, 20, 129, + /* 1500 */ 22, 193, 22, 22, 24, 193, 23, 30, 25, 32, + /* 1510 */ 19, 20, 144, 22, 36, 216, 217, 40, 193, 216, + /* 1520 */ 217, 193, 152, 129, 216, 217, 193, 36, 216, 217, + /* 1530 */ 193, 99, 193, 193, 53, 193, 193, 59, 23, 193, + /* 1540 */ 25, 216, 217, 193, 216, 217, 152, 70, 59, 71, + /* 1550 */ 59, 117, 193, 216, 217, 78, 216, 217, 81, 216, + /* 1560 */ 217, 318, 71, 85, 193, 133, 193, 193, 90, 23, + /* 1570 */ 23, 25, 25, 120, 121, 98, 85, 193, 100, 193, + /* 1580 */ 23, 90, 25, 121, 106, 107, 19, 216, 217, 216, + /* 1590 */ 217, 100, 114, 131, 116, 117, 118, 106, 107, 121, + /* 1600 */ 216, 217, 216, 217, 193, 114, 117, 116, 117, 118, + /* 1610 */ 133, 193, 121, 193, 193, 138, 139, 193, 23, 193, + /* 1620 */ 25, 23, 23, 25, 25, 7, 8, 216, 217, 193, + /* 1630 */ 193, 153, 154, 155, 156, 157, 216, 217, 193, 162, + /* 1640 */ 216, 217, 216, 217, 153, 154, 155, 156, 157, 1, + /* 1650 */ 2, 193, 193, 5, 19, 20, 59, 22, 10, 11, + /* 1660 */ 12, 13, 14, 193, 97, 17, 193, 23, 193, 25, + /* 1670 */ 288, 36, 193, 242, 216, 217, 236, 23, 30, 25, + /* 1680 */ 32, 19, 20, 23, 22, 25, 216, 217, 40, 216, + /* 1690 */ 217, 216, 217, 193, 59, 216, 217, 193, 36, 83, + /* 1700 */ 84, 153, 153, 155, 155, 23, 71, 25, 23, 193, + /* 1710 */ 25, 193, 193, 193, 117, 193, 193, 193, 70, 193, + /* 1720 */ 193, 59, 193, 255, 255, 287, 78, 255, 243, 81, + /* 1730 */ 191, 255, 297, 71, 271, 100, 293, 245, 267, 214, + /* 1740 */ 246, 106, 107, 108, 246, 271, 98, 245, 293, 114, + /* 1750 */ 220, 116, 117, 118, 267, 271, 121, 271, 225, 219, + /* 1760 */ 229, 219, 100, 219, 259, 259, 259, 259, 106, 107, + /* 1770 */ 249, 196, 60, 280, 141, 243, 114, 249, 116, 117, + /* 1780 */ 118, 133, 245, 121, 200, 297, 138, 139, 153, 154, + /* 1790 */ 155, 156, 157, 297, 200, 38, 19, 20, 151, 22, + /* 1800 */ 200, 150, 140, 294, 294, 22, 272, 43, 234, 18, + /* 1810 */ 162, 270, 200, 36, 237, 153, 154, 155, 156, 157, + /* 1820 */ 237, 283, 237, 237, 18, 199, 149, 246, 272, 270, + /* 1830 */ 272, 200, 158, 246, 246, 234, 59, 234, 246, 199, + /* 1840 */ 290, 62, 289, 200, 199, 22, 221, 115, 71, 200, + /* 1850 */ 200, 199, 199, 221, 218, 218, 19, 20, 64, 22, + /* 1860 */ 218, 227, 22, 224, 126, 224, 165, 221, 24, 305, + /* 1870 */ 200, 113, 312, 36, 218, 220, 218, 100, 282, 218, + /* 1880 */ 91, 218, 317, 106, 107, 221, 227, 282, 317, 82, + /* 1890 */ 148, 114, 265, 116, 117, 118, 59, 145, 121, 22, + /* 1900 */ 277, 158, 200, 265, 25, 202, 147, 250, 71, 279, + /* 1910 */ 13, 146, 194, 194, 249, 248, 250, 140, 247, 246, + /* 1920 */ 6, 192, 192, 192, 303, 303, 213, 207, 300, 213, + /* 1930 */ 153, 154, 155, 156, 157, 213, 213, 100, 213, 222, + /* 1940 */ 207, 214, 214, 106, 107, 4, 222, 207, 3, 22, + /* 1950 */ 163, 114, 15, 116, 117, 118, 16, 23, 121, 23, + /* 1960 */ 139, 151, 130, 25, 142, 16, 24, 20, 144, 1, + /* 1970 */ 142, 130, 130, 61, 53, 53, 37, 151, 53, 53, + /* 1980 */ 130, 116, 34, 1, 141, 5, 22, 115, 161, 141, + /* 1990 */ 153, 154, 155, 156, 157, 25, 68, 68, 75, 41, + /* 2000 */ 115, 24, 131, 20, 19, 125, 22, 96, 22, 22, + /* 2010 */ 67, 23, 22, 67, 59, 24, 22, 28, 67, 23, + /* 2020 */ 22, 22, 149, 23, 23, 23, 116, 23, 25, 37, + /* 2030 */ 97, 141, 23, 23, 22, 143, 25, 75, 88, 34, + /* 2040 */ 34, 34, 34, 86, 75, 93, 23, 34, 22, 34, + /* 2050 */ 25, 24, 34, 25, 23, 142, 23, 142, 44, 23, + /* 2060 */ 23, 23, 11, 23, 25, 22, 22, 22, 15, 23, + /* 2070 */ 23, 22, 22, 25, 1, 1, 141, 25, 23, 135, + /* 2080 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, + /* 2090 */ 319, 319, 319, 319, 141, 141, 319, 141, 319, 319, + /* 2100 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, + /* 2110 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, + /* 2120 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, + /* 2130 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, + /* 2140 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, + /* 2150 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, + /* 2160 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, + /* 2170 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, + /* 2180 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, + /* 2190 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, + /* 2200 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, + /* 2210 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, + /* 2220 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, + /* 2230 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, + /* 2240 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, + /* 2250 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, + /* 2260 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, + /* 2270 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319, + /* 2280 */ 319, 319, 319, }; -#define YY_SHIFT_COUNT (571) +#define YY_SHIFT_COUNT (575) #define YY_SHIFT_MIN (0) -#define YY_SHIFT_MAX (2014) +#define YY_SHIFT_MAX (2074) static const unsigned short int yy_shift_ofst[] = { - /* 0 */ 1423, 1409, 1454, 1192, 1192, 610, 1252, 1410, 1517, 1684, - /* 10 */ 1684, 1684, 276, 0, 0, 180, 1015, 1684, 1684, 1684, - /* 20 */ 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, - /* 30 */ 1049, 1049, 1121, 1121, 54, 487, 610, 610, 610, 610, - /* 40 */ 610, 40, 110, 219, 289, 396, 439, 509, 548, 618, - /* 50 */ 657, 727, 766, 836, 995, 1015, 1015, 1015, 1015, 1015, - /* 60 */ 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, 1015, - /* 70 */ 1015, 1015, 1015, 1035, 1015, 1138, 880, 880, 1577, 1684, - /* 80 */ 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, - /* 90 */ 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, - /* 100 */ 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, 1684, - /* 110 */ 1684, 1684, 1684, 1705, 1684, 1684, 1684, 1684, 1684, 1684, - /* 120 */ 1684, 1684, 1684, 1684, 1684, 1684, 1684, 146, 84, 84, - /* 130 */ 84, 84, 84, 277, 315, 401, 97, 461, 251, 66, - /* 140 */ 66, 51, 1156, 66, 66, 324, 324, 66, 452, 452, - /* 150 */ 452, 452, 133, 114, 114, 4, 11, 2037, 2037, 621, - /* 160 */ 621, 621, 567, 398, 398, 398, 398, 937, 937, 228, - /* 170 */ 251, 331, 1052, 66, 66, 66, 66, 66, 66, 66, - /* 180 */ 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, - /* 190 */ 66, 66, 66, 557, 557, 66, 9, 25, 25, 745, - /* 200 */ 745, 967, 1088, 2037, 2037, 2037, 2037, 2037, 2037, 2037, - /* 210 */ 255, 317, 317, 514, 403, 620, 471, 672, 781, 891, - /* 220 */ 675, 66, 66, 66, 66, 66, 66, 66, 66, 66, - /* 230 */ 66, 508, 66, 66, 66, 66, 66, 66, 66, 66, - /* 240 */ 66, 66, 66, 66, 790, 790, 790, 66, 66, 66, - /* 250 */ 338, 66, 66, 66, 516, 1084, 66, 66, 993, 66, - /* 260 */ 66, 66, 66, 66, 66, 66, 66, 732, 1083, 563, - /* 270 */ 994, 994, 994, 994, 337, 563, 563, 1028, 987, 897, - /* 280 */ 1119, 262, 1214, 1271, 1112, 1214, 1112, 1268, 1239, 262, - /* 290 */ 262, 1239, 262, 1271, 1268, 1302, 1354, 1278, 1168, 1168, - /* 300 */ 1168, 1112, 1303, 1303, 815, 1311, 1264, 1364, 1657, 1657, - /* 310 */ 1595, 1595, 1701, 1701, 1595, 1592, 1596, 1724, 1706, 1730, - /* 320 */ 1730, 1730, 1730, 1595, 1735, 1614, 1596, 1596, 1614, 1724, - /* 330 */ 1706, 1614, 1706, 1614, 1595, 1735, 1621, 1717, 1595, 1735, - /* 340 */ 1758, 1595, 1735, 1595, 1735, 1758, 1679, 1679, 1679, 1734, - /* 350 */ 1781, 1781, 1758, 1679, 1689, 1679, 1734, 1679, 1679, 1645, - /* 360 */ 1791, 1715, 1715, 1758, 1690, 1718, 1690, 1718, 1690, 1718, - /* 370 */ 1690, 1718, 1595, 1751, 1751, 1762, 1762, 1699, 1703, 1826, - /* 380 */ 1595, 1695, 1699, 1707, 1710, 1614, 1847, 1863, 1863, 1871, - /* 390 */ 1871, 1871, 2037, 2037, 2037, 2037, 2037, 2037, 2037, 2037, - /* 400 */ 2037, 2037, 2037, 2037, 2037, 2037, 2037, 193, 837, 1194, - /* 410 */ 1212, 506, 832, 1054, 1390, 925, 1435, 1394, 1102, 1332, - /* 420 */ 1419, 1196, 1420, 1425, 1433, 1447, 1457, 1488, 1443, 1379, - /* 430 */ 1572, 1455, 1503, 1453, 1495, 1515, 1506, 1526, 1460, 1489, - /* 440 */ 1581, 1622, 1534, 667, 1888, 1893, 1875, 1736, 1884, 1885, - /* 450 */ 1877, 1879, 1765, 1754, 1776, 1881, 1881, 1883, 1767, 1889, - /* 460 */ 1768, 1894, 1911, 1772, 1788, 1881, 1789, 1858, 1886, 1881, - /* 470 */ 1770, 1868, 1869, 1872, 1873, 1795, 1812, 1895, 1790, 1927, - /* 480 */ 1926, 1910, 1819, 1774, 1867, 1912, 1870, 1861, 1898, 1800, - /* 490 */ 1827, 1918, 1923, 1925, 1815, 1822, 1928, 1880, 1929, 1930, - /* 500 */ 1931, 1933, 1882, 1897, 1924, 1857, 1932, 1935, 1891, 1922, - /* 510 */ 1938, 1814, 1941, 1942, 1943, 1944, 1939, 1945, 1947, 1874, - /* 520 */ 1830, 1949, 1950, 1859, 1946, 1953, 1834, 1952, 1948, 1951, - /* 530 */ 1954, 1955, 1890, 1904, 1900, 1937, 1908, 1899, 1956, 1961, - /* 540 */ 1965, 1967, 1968, 1969, 1962, 1972, 1952, 1974, 1975, 1976, - /* 550 */ 1977, 1978, 1979, 1982, 1990, 1983, 1984, 1985, 1986, 1988, - /* 560 */ 1989, 1987, 1887, 1876, 1878, 1892, 1896, 1992, 1991, 1998, - /* 570 */ 2006, 2014, + /* 0 */ 1648, 1477, 1272, 322, 322, 1, 1319, 1478, 1491, 1837, + /* 10 */ 1837, 1837, 471, 0, 0, 214, 1093, 1837, 1837, 1837, + /* 20 */ 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, + /* 30 */ 271, 271, 1219, 1219, 216, 88, 1, 1, 1, 1, + /* 40 */ 1, 40, 111, 258, 361, 469, 512, 583, 622, 693, + /* 50 */ 732, 803, 842, 913, 1073, 1093, 1093, 1093, 1093, 1093, + /* 60 */ 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, + /* 70 */ 1093, 1093, 1093, 1113, 1093, 1216, 957, 957, 1635, 1662, + /* 80 */ 1777, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, + /* 90 */ 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, + /* 100 */ 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, + /* 110 */ 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, + /* 120 */ 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, + /* 130 */ 137, 181, 181, 181, 181, 181, 181, 181, 94, 430, + /* 140 */ 66, 65, 112, 366, 533, 533, 740, 1261, 533, 533, + /* 150 */ 79, 79, 533, 412, 412, 412, 77, 412, 123, 113, + /* 160 */ 113, 22, 22, 2098, 2098, 328, 328, 328, 239, 468, + /* 170 */ 468, 468, 468, 1015, 1015, 409, 366, 1129, 1186, 533, + /* 180 */ 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, + /* 190 */ 533, 533, 533, 533, 533, 533, 533, 533, 533, 969, + /* 200 */ 621, 621, 533, 642, 788, 788, 1228, 1228, 822, 822, + /* 210 */ 67, 1274, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 1307, + /* 220 */ 954, 954, 585, 472, 640, 387, 695, 538, 541, 700, + /* 230 */ 533, 533, 533, 533, 533, 533, 533, 533, 533, 533, + /* 240 */ 222, 533, 533, 533, 533, 533, 533, 533, 533, 533, + /* 250 */ 533, 533, 533, 1179, 1179, 1179, 533, 533, 533, 565, + /* 260 */ 533, 533, 533, 916, 1144, 533, 533, 1288, 533, 533, + /* 270 */ 533, 533, 533, 533, 533, 533, 639, 1330, 209, 1076, + /* 280 */ 1076, 1076, 1076, 580, 209, 209, 1313, 768, 917, 649, + /* 290 */ 1181, 1316, 405, 1316, 1238, 249, 1181, 1181, 249, 1181, + /* 300 */ 405, 1238, 1369, 464, 1259, 1012, 1012, 1012, 1368, 1368, + /* 310 */ 1368, 1368, 184, 184, 1326, 904, 1287, 1480, 1712, 1712, + /* 320 */ 1633, 1633, 1757, 1757, 1633, 1647, 1651, 1783, 1764, 1791, + /* 330 */ 1791, 1791, 1791, 1633, 1806, 1677, 1651, 1651, 1677, 1783, + /* 340 */ 1764, 1677, 1764, 1677, 1633, 1806, 1674, 1779, 1633, 1806, + /* 350 */ 1823, 1633, 1806, 1633, 1806, 1823, 1732, 1732, 1732, 1794, + /* 360 */ 1840, 1840, 1823, 1732, 1738, 1732, 1794, 1732, 1732, 1701, + /* 370 */ 1844, 1758, 1758, 1823, 1633, 1789, 1789, 1807, 1807, 1742, + /* 380 */ 1752, 1877, 1633, 1743, 1742, 1759, 1765, 1677, 1879, 1897, + /* 390 */ 1897, 1914, 1914, 1914, 2098, 2098, 2098, 2098, 2098, 2098, + /* 400 */ 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 2098, 207, + /* 410 */ 1095, 331, 620, 903, 806, 1074, 1483, 1432, 1481, 1322, + /* 420 */ 1370, 1394, 1515, 1291, 1546, 1547, 1557, 1595, 1598, 1599, + /* 430 */ 1434, 1453, 1618, 1462, 1567, 1489, 1644, 1654, 1616, 1660, + /* 440 */ 1548, 1549, 1682, 1685, 1597, 742, 1941, 1945, 1927, 1787, + /* 450 */ 1937, 1940, 1934, 1936, 1821, 1810, 1832, 1938, 1938, 1942, + /* 460 */ 1822, 1947, 1824, 1949, 1968, 1828, 1841, 1938, 1842, 1912, + /* 470 */ 1939, 1938, 1826, 1921, 1922, 1925, 1926, 1850, 1865, 1948, + /* 480 */ 1843, 1982, 1980, 1964, 1872, 1827, 1928, 1970, 1929, 1923, + /* 490 */ 1958, 1848, 1885, 1977, 1983, 1985, 1871, 1880, 1984, 1943, + /* 500 */ 1986, 1987, 1988, 1990, 1946, 1955, 1991, 1911, 1989, 1994, + /* 510 */ 1951, 1992, 1996, 1873, 1998, 2000, 2001, 2002, 2003, 2004, + /* 520 */ 1999, 1933, 1890, 2009, 2010, 1910, 2005, 2012, 1892, 2011, + /* 530 */ 2006, 2007, 2008, 2013, 1950, 1962, 1957, 2014, 1969, 1952, + /* 540 */ 2015, 2023, 2026, 2027, 2025, 2028, 2018, 1913, 1915, 2031, + /* 550 */ 2011, 2033, 2036, 2037, 2038, 2039, 2040, 2043, 2051, 2044, + /* 560 */ 2045, 2046, 2047, 2049, 2050, 2048, 1944, 1935, 1953, 1954, + /* 570 */ 1956, 2052, 2055, 2053, 2073, 2074, }; -#define YY_REDUCE_COUNT (406) -#define YY_REDUCE_MIN (-272) -#define YY_REDUCE_MAX (1693) +#define YY_REDUCE_COUNT (408) +#define YY_REDUCE_MIN (-271) +#define YY_REDUCE_MAX (1740) static const short yy_reduce_ofst[] = { - /* 0 */ 109, 113, 272, 760, -178, -176, -192, -183, -180, -134, - /* 10 */ 213, 220, 371, -208, -205, -272, -197, 611, 632, 765, - /* 20 */ 786, 392, 943, 989, 503, 651, 1039, -18, 702, 821, - /* 30 */ 710, 812, -188, 380, -187, 555, 662, 1055, 1063, 1065, - /* 40 */ 1080, -267, -267, -267, -267, -267, -267, -267, -267, -267, - /* 50 */ -267, -267, -267, -267, -267, -267, -267, -267, -267, -267, - /* 60 */ -267, -267, -267, -267, -267, -267, -267, -267, -267, -267, - /* 70 */ -267, -267, -267, -267, -267, -267, -267, -267, 636, 811, - /* 80 */ 917, 936, 1006, 1008, 1017, 1060, 1064, 1069, 1075, 1105, - /* 90 */ 1118, 1123, 1125, 1134, 1140, 1159, 1165, 1169, 1174, 1179, - /* 100 */ 1181, 1184, 1186, 1201, 1246, 1259, 1262, 1281, 1293, 1299, - /* 110 */ 1313, 1327, 1341, 1352, 1356, 1358, 1362, 1366, 1395, 1403, - /* 120 */ 1406, 1411, 1424, 1436, 1439, 1450, 1452, -267, -267, -267, - /* 130 */ -267, -267, -267, -267, -267, 224, -267, 446, -24, 275, - /* 140 */ 546, 518, 573, 560, 53, -181, -111, 485, 606, 671, - /* 150 */ 606, 671, 683, 8, 93, -267, -267, -267, -267, 155, - /* 160 */ 155, 155, 181, 242, 264, 486, 489, -218, 393, 227, - /* 170 */ 604, 347, 347, -171, 431, 650, 715, -166, 562, 609, - /* 180 */ 716, 764, 18, 823, 769, 833, 838, 957, 759, 119, - /* 190 */ 923, 226, 1014, 542, 603, 451, 949, 654, 659, 762, - /* 200 */ 964, -4, 778, 961, 712, 1082, 1100, 1111, 1026, 1117, - /* 210 */ -204, -174, -151, -8, 77, 198, 305, 327, 388, 540, - /* 220 */ 839, 968, 982, 985, 1004, 1023, 1070, 1086, 1097, 1130, - /* 230 */ 1190, 1163, 1199, 1284, 1297, 1300, 1314, 1339, 1353, 1391, - /* 240 */ 1402, 1413, 1416, 1417, 803, 1376, 1400, 1428, 1437, 1446, - /* 250 */ 1378, 1461, 1464, 1465, 1249, 1329, 1466, 1467, 1414, 1468, - /* 260 */ 305, 1469, 1470, 1471, 1472, 1482, 1483, 1389, 1392, 1438, - /* 270 */ 1426, 1427, 1432, 1434, 1378, 1438, 1438, 1440, 1474, 1499, - /* 280 */ 1399, 1421, 1430, 1456, 1441, 1442, 1444, 1415, 1473, 1431, - /* 290 */ 1445, 1476, 1449, 1478, 1418, 1479, 1477, 1485, 1493, 1494, - /* 300 */ 1496, 1458, 1475, 1480, 1459, 1490, 1484, 1518, 1448, 1451, - /* 310 */ 1537, 1538, 1463, 1481, 1541, 1486, 1487, 1491, 1519, 1514, - /* 320 */ 1521, 1523, 1525, 1552, 1556, 1520, 1492, 1498, 1522, 1497, - /* 330 */ 1539, 1528, 1542, 1532, 1571, 1573, 1500, 1504, 1582, 1584, - /* 340 */ 1563, 1586, 1588, 1589, 1597, 1567, 1579, 1585, 1590, 1568, - /* 350 */ 1583, 1587, 1593, 1591, 1598, 1599, 1600, 1602, 1606, 1513, - /* 360 */ 1524, 1548, 1549, 1611, 1574, 1576, 1594, 1603, 1604, 1607, - /* 370 */ 1605, 1608, 1642, 1527, 1529, 1609, 1610, 1601, 1615, 1575, - /* 380 */ 1650, 1578, 1619, 1623, 1625, 1624, 1674, 1685, 1686, 1691, - /* 390 */ 1692, 1693, 1612, 1613, 1617, 1675, 1668, 1673, 1676, 1677, - /* 400 */ 1680, 1666, 1669, 1678, 1681, 1683, 1687, + /* 0 */ -125, 733, 789, 241, 293, -123, -193, -191, -183, -187, + /* 10 */ 166, 238, 133, -207, -199, -267, -176, -6, 204, 489, + /* 20 */ 576, -175, 598, 686, 615, 725, 860, 778, 781, 857, + /* 30 */ 616, 887, 87, 240, -192, 408, 626, 796, 843, 854, + /* 40 */ 1003, -271, -271, -271, -271, -271, -271, -271, -271, -271, + /* 50 */ -271, -271, -271, -271, -271, -271, -271, -271, -271, -271, + /* 60 */ -271, -271, -271, -271, -271, -271, -271, -271, -271, -271, + /* 70 */ -271, -271, -271, -271, -271, -271, -271, -271, 80, 83, + /* 80 */ 313, 886, 888, 996, 1034, 1059, 1081, 1100, 1117, 1152, + /* 90 */ 1155, 1163, 1165, 1167, 1169, 1172, 1180, 1182, 1184, 1198, + /* 100 */ 1200, 1213, 1215, 1225, 1227, 1252, 1254, 1264, 1299, 1303, + /* 110 */ 1308, 1312, 1325, 1328, 1337, 1340, 1343, 1371, 1373, 1384, + /* 120 */ 1386, 1411, 1420, 1424, 1426, 1458, 1470, 1473, 1475, 1479, + /* 130 */ -271, -271, -271, -271, -271, -271, -271, -271, -271, -271, + /* 140 */ -271, 138, 459, 396, -158, 470, 302, -212, 521, 201, + /* 150 */ -195, -92, 559, 630, 632, 630, -271, 632, 901, 63, + /* 160 */ 407, -271, -271, -271, -271, 161, 161, 161, 251, 335, + /* 170 */ 847, 960, 980, 537, 588, 618, 628, 688, 688, -166, + /* 180 */ -161, 674, 790, 794, 799, 851, 852, -122, 680, -120, + /* 190 */ 995, 1038, 415, 1051, 893, 798, 962, 400, 1086, 779, + /* 200 */ 923, 924, 263, 1041, 979, 990, 1083, 1097, 1031, 1194, + /* 210 */ 362, 994, 1139, 1005, 1037, 1202, 1205, 1195, 1210, -194, + /* 220 */ 56, 185, -135, 232, 522, 560, 601, 617, 669, 683, + /* 230 */ 711, 856, 908, 941, 1048, 1101, 1147, 1257, 1262, 1265, + /* 240 */ 392, 1292, 1333, 1339, 1342, 1346, 1350, 1359, 1374, 1418, + /* 250 */ 1421, 1436, 1437, 593, 755, 770, 997, 1445, 1459, 1209, + /* 260 */ 1500, 1504, 1516, 1132, 1243, 1518, 1519, 1440, 1520, 560, + /* 270 */ 1522, 1523, 1524, 1526, 1527, 1529, 1382, 1438, 1431, 1468, + /* 280 */ 1469, 1472, 1476, 1209, 1431, 1431, 1485, 1525, 1539, 1435, + /* 290 */ 1463, 1471, 1492, 1487, 1443, 1494, 1474, 1484, 1498, 1486, + /* 300 */ 1502, 1455, 1530, 1531, 1533, 1540, 1542, 1544, 1505, 1506, + /* 310 */ 1507, 1508, 1521, 1528, 1493, 1537, 1532, 1575, 1488, 1496, + /* 320 */ 1584, 1594, 1509, 1510, 1600, 1538, 1534, 1541, 1574, 1577, + /* 330 */ 1583, 1585, 1586, 1612, 1626, 1581, 1556, 1558, 1587, 1559, + /* 340 */ 1601, 1588, 1603, 1592, 1631, 1640, 1550, 1553, 1643, 1645, + /* 350 */ 1625, 1649, 1652, 1650, 1653, 1632, 1636, 1637, 1642, 1634, + /* 360 */ 1639, 1641, 1646, 1656, 1655, 1658, 1659, 1661, 1663, 1560, + /* 370 */ 1564, 1596, 1605, 1664, 1670, 1565, 1571, 1627, 1638, 1657, + /* 380 */ 1665, 1623, 1702, 1630, 1666, 1667, 1671, 1673, 1703, 1718, + /* 390 */ 1719, 1729, 1730, 1731, 1621, 1622, 1628, 1720, 1713, 1716, + /* 400 */ 1722, 1723, 1733, 1717, 1724, 1727, 1728, 1725, 1740, }; static const YYACTIONTYPE yy_default[] = { - /* 0 */ 1633, 1633, 1633, 1462, 1230, 1341, 1230, 1230, 1230, 1462, - /* 10 */ 1462, 1462, 1230, 1371, 1371, 1515, 1263, 1230, 1230, 1230, - /* 20 */ 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1461, 1230, 1230, - /* 30 */ 1230, 1230, 1550, 1550, 1230, 1230, 1230, 1230, 1230, 1230, - /* 40 */ 1230, 1230, 1380, 1230, 1387, 1230, 1230, 1230, 1230, 1230, - /* 50 */ 1463, 1464, 1230, 1230, 1230, 1514, 1516, 1479, 1394, 1393, - /* 60 */ 1392, 1391, 1497, 1358, 1385, 1378, 1382, 1457, 1458, 1456, - /* 70 */ 1460, 1464, 1463, 1230, 1381, 1428, 1442, 1427, 1230, 1230, - /* 80 */ 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, - /* 90 */ 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, - /* 100 */ 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, - /* 110 */ 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, - /* 120 */ 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1436, 1441, 1447, - /* 130 */ 1440, 1437, 1430, 1429, 1431, 1230, 1432, 1230, 1254, 1230, - /* 140 */ 1230, 1251, 1305, 1230, 1230, 1230, 1230, 1230, 1534, 1533, - /* 150 */ 1230, 1230, 1263, 1422, 1421, 1433, 1434, 1444, 1443, 1522, - /* 160 */ 1586, 1585, 1480, 1230, 1230, 1230, 1230, 1230, 1230, 1550, - /* 170 */ 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, - /* 180 */ 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, - /* 190 */ 1230, 1230, 1230, 1550, 1550, 1230, 1263, 1550, 1550, 1259, - /* 200 */ 1259, 1365, 1230, 1529, 1332, 1332, 1332, 1332, 1341, 1332, - /* 210 */ 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, - /* 220 */ 1230, 1230, 1230, 1230, 1230, 1519, 1517, 1230, 1230, 1230, - /* 230 */ 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, - /* 240 */ 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, - /* 250 */ 1230, 1230, 1230, 1230, 1337, 1230, 1230, 1230, 1230, 1230, - /* 260 */ 1230, 1230, 1230, 1230, 1230, 1230, 1579, 1230, 1492, 1319, - /* 270 */ 1337, 1337, 1337, 1337, 1339, 1320, 1318, 1331, 1264, 1237, - /* 280 */ 1625, 1397, 1386, 1338, 1360, 1386, 1360, 1622, 1384, 1397, - /* 290 */ 1397, 1384, 1397, 1338, 1622, 1280, 1602, 1275, 1371, 1371, - /* 300 */ 1371, 1360, 1365, 1365, 1459, 1338, 1331, 1230, 1625, 1625, - /* 310 */ 1346, 1346, 1624, 1624, 1346, 1480, 1609, 1406, 1308, 1314, - /* 320 */ 1314, 1314, 1314, 1346, 1248, 1384, 1609, 1609, 1384, 1406, - /* 330 */ 1308, 1384, 1308, 1384, 1346, 1248, 1496, 1619, 1346, 1248, - /* 340 */ 1470, 1346, 1248, 1346, 1248, 1470, 1306, 1306, 1306, 1295, - /* 350 */ 1230, 1230, 1470, 1306, 1280, 1306, 1295, 1306, 1306, 1568, - /* 360 */ 1230, 1474, 1474, 1470, 1364, 1359, 1364, 1359, 1364, 1359, - /* 370 */ 1364, 1359, 1346, 1560, 1560, 1374, 1374, 1379, 1365, 1465, - /* 380 */ 1346, 1230, 1379, 1377, 1375, 1384, 1298, 1582, 1582, 1578, - /* 390 */ 1578, 1578, 1630, 1630, 1529, 1595, 1263, 1263, 1263, 1263, - /* 400 */ 1595, 1282, 1282, 1264, 1264, 1263, 1595, 1230, 1230, 1230, - /* 410 */ 1230, 1230, 1230, 1590, 1230, 1524, 1481, 1350, 1230, 1230, - /* 420 */ 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, - /* 430 */ 1230, 1230, 1535, 1230, 1230, 1230, 1230, 1230, 1230, 1230, - /* 440 */ 1230, 1230, 1230, 1411, 1230, 1233, 1526, 1230, 1230, 1230, - /* 450 */ 1230, 1230, 1230, 1230, 1230, 1388, 1389, 1351, 1230, 1230, - /* 460 */ 1230, 1230, 1230, 1230, 1230, 1403, 1230, 1230, 1230, 1398, - /* 470 */ 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1621, 1230, - /* 480 */ 1230, 1230, 1230, 1230, 1230, 1495, 1494, 1230, 1230, 1348, - /* 490 */ 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, - /* 500 */ 1230, 1230, 1230, 1278, 1230, 1230, 1230, 1230, 1230, 1230, - /* 510 */ 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, - /* 520 */ 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1376, 1230, 1230, - /* 530 */ 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, - /* 540 */ 1230, 1230, 1565, 1366, 1230, 1230, 1612, 1230, 1230, 1230, - /* 550 */ 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, 1230, - /* 560 */ 1230, 1606, 1322, 1413, 1230, 1412, 1416, 1252, 1230, 1242, - /* 570 */ 1230, 1230, + /* 0 */ 1647, 1647, 1647, 1475, 1240, 1351, 1240, 1240, 1240, 1475, + /* 10 */ 1475, 1475, 1240, 1381, 1381, 1528, 1273, 1240, 1240, 1240, + /* 20 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1474, 1240, 1240, + /* 30 */ 1240, 1240, 1563, 1563, 1240, 1240, 1240, 1240, 1240, 1240, + /* 40 */ 1240, 1240, 1390, 1240, 1397, 1240, 1240, 1240, 1240, 1240, + /* 50 */ 1476, 1477, 1240, 1240, 1240, 1527, 1529, 1492, 1404, 1403, + /* 60 */ 1402, 1401, 1510, 1369, 1395, 1388, 1392, 1470, 1471, 1469, + /* 70 */ 1473, 1477, 1476, 1240, 1391, 1438, 1454, 1437, 1240, 1240, + /* 80 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, + /* 90 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, + /* 100 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, + /* 110 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, + /* 120 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, + /* 130 */ 1446, 1453, 1452, 1451, 1460, 1450, 1447, 1440, 1439, 1441, + /* 140 */ 1442, 1240, 1240, 1264, 1240, 1240, 1261, 1315, 1240, 1240, + /* 150 */ 1240, 1240, 1240, 1547, 1546, 1240, 1443, 1240, 1273, 1432, + /* 160 */ 1431, 1457, 1444, 1456, 1455, 1535, 1599, 1598, 1493, 1240, + /* 170 */ 1240, 1240, 1240, 1240, 1240, 1563, 1240, 1240, 1240, 1240, + /* 180 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, + /* 190 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1371, + /* 200 */ 1563, 1563, 1240, 1273, 1563, 1563, 1372, 1372, 1269, 1269, + /* 210 */ 1375, 1240, 1542, 1342, 1342, 1342, 1342, 1351, 1342, 1240, + /* 220 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, + /* 230 */ 1240, 1240, 1240, 1240, 1532, 1530, 1240, 1240, 1240, 1240, + /* 240 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, + /* 250 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, + /* 260 */ 1240, 1240, 1240, 1347, 1240, 1240, 1240, 1240, 1240, 1240, + /* 270 */ 1240, 1240, 1240, 1240, 1240, 1592, 1240, 1505, 1329, 1347, + /* 280 */ 1347, 1347, 1347, 1349, 1330, 1328, 1341, 1274, 1247, 1639, + /* 290 */ 1407, 1396, 1348, 1396, 1636, 1394, 1407, 1407, 1394, 1407, + /* 300 */ 1348, 1636, 1290, 1615, 1285, 1381, 1381, 1381, 1371, 1371, + /* 310 */ 1371, 1371, 1375, 1375, 1472, 1348, 1341, 1240, 1639, 1639, + /* 320 */ 1357, 1357, 1638, 1638, 1357, 1493, 1623, 1416, 1318, 1324, + /* 330 */ 1324, 1324, 1324, 1357, 1258, 1394, 1623, 1623, 1394, 1416, + /* 340 */ 1318, 1394, 1318, 1394, 1357, 1258, 1509, 1633, 1357, 1258, + /* 350 */ 1483, 1357, 1258, 1357, 1258, 1483, 1316, 1316, 1316, 1305, + /* 360 */ 1240, 1240, 1483, 1316, 1290, 1316, 1305, 1316, 1316, 1581, + /* 370 */ 1240, 1487, 1487, 1483, 1357, 1573, 1573, 1384, 1384, 1389, + /* 380 */ 1375, 1478, 1357, 1240, 1389, 1387, 1385, 1394, 1308, 1595, + /* 390 */ 1595, 1591, 1591, 1591, 1644, 1644, 1542, 1608, 1273, 1273, + /* 400 */ 1273, 1273, 1608, 1292, 1292, 1274, 1274, 1273, 1608, 1240, + /* 410 */ 1240, 1240, 1240, 1240, 1240, 1603, 1240, 1537, 1494, 1361, + /* 420 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, + /* 430 */ 1240, 1240, 1240, 1240, 1548, 1240, 1240, 1240, 1240, 1240, + /* 440 */ 1240, 1240, 1240, 1240, 1240, 1421, 1240, 1243, 1539, 1240, + /* 450 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1398, 1399, 1362, + /* 460 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1413, 1240, 1240, + /* 470 */ 1240, 1408, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, + /* 480 */ 1635, 1240, 1240, 1240, 1240, 1240, 1240, 1508, 1507, 1240, + /* 490 */ 1240, 1359, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, + /* 500 */ 1240, 1240, 1240, 1240, 1240, 1288, 1240, 1240, 1240, 1240, + /* 510 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, + /* 520 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1386, + /* 530 */ 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, + /* 540 */ 1240, 1240, 1240, 1240, 1578, 1376, 1240, 1240, 1240, 1240, + /* 550 */ 1626, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, 1240, + /* 560 */ 1240, 1240, 1240, 1240, 1240, 1619, 1332, 1423, 1240, 1422, + /* 570 */ 1426, 1262, 1240, 1252, 1240, 1240, }; /********** End of lemon-generated parsing tables *****************************/ @@ -160751,6 +164853,7 @@ static const YYCODETYPE yyFallback[] = { 0, /* SLASH => nothing */ 0, /* REM => nothing */ 0, /* CONCAT => nothing */ + 0, /* PTR => nothing */ 0, /* COLLATE => nothing */ 0, /* BITNOT => nothing */ 0, /* ON => nothing */ @@ -161023,212 +165126,213 @@ static const char *const yyTokenName[] = { /* 109 */ "SLASH", /* 110 */ "REM", /* 111 */ "CONCAT", - /* 112 */ "COLLATE", - /* 113 */ "BITNOT", - /* 114 */ "ON", - /* 115 */ "INDEXED", - /* 116 */ "STRING", - /* 117 */ "JOIN_KW", - /* 118 */ "CONSTRAINT", - /* 119 */ "DEFAULT", - /* 120 */ "NULL", - /* 121 */ "PRIMARY", - /* 122 */ "UNIQUE", - /* 123 */ "CHECK", - /* 124 */ "REFERENCES", - /* 125 */ "AUTOINCR", - /* 126 */ "INSERT", - /* 127 */ "DELETE", - /* 128 */ "UPDATE", - /* 129 */ "SET", - /* 130 */ "DEFERRABLE", - /* 131 */ "FOREIGN", - /* 132 */ "DROP", - /* 133 */ "UNION", - /* 134 */ "ALL", - /* 135 */ "EXCEPT", - /* 136 */ "INTERSECT", - /* 137 */ "SELECT", - /* 138 */ "VALUES", - /* 139 */ "DISTINCT", - /* 140 */ "DOT", - /* 141 */ "FROM", - /* 142 */ "JOIN", - /* 143 */ "USING", - /* 144 */ "ORDER", - /* 145 */ "GROUP", - /* 146 */ "HAVING", - /* 147 */ "LIMIT", - /* 148 */ "WHERE", - /* 149 */ "RETURNING", - /* 150 */ "INTO", - /* 151 */ "NOTHING", - /* 152 */ "FLOAT", - /* 153 */ "BLOB", - /* 154 */ "INTEGER", - /* 155 */ "VARIABLE", - /* 156 */ "CASE", - /* 157 */ "WHEN", - /* 158 */ "THEN", - /* 159 */ "ELSE", - /* 160 */ "INDEX", - /* 161 */ "ALTER", - /* 162 */ "ADD", - /* 163 */ "WINDOW", - /* 164 */ "OVER", - /* 165 */ "FILTER", - /* 166 */ "COLUMN", - /* 167 */ "AGG_FUNCTION", - /* 168 */ "AGG_COLUMN", - /* 169 */ "TRUEFALSE", - /* 170 */ "ISNOT", - /* 171 */ "FUNCTION", - /* 172 */ "UMINUS", - /* 173 */ "UPLUS", - /* 174 */ "TRUTH", - /* 175 */ "REGISTER", - /* 176 */ "VECTOR", - /* 177 */ "SELECT_COLUMN", - /* 178 */ "IF_NULL_ROW", - /* 179 */ "ASTERISK", - /* 180 */ "SPAN", - /* 181 */ "ERROR", - /* 182 */ "SPACE", - /* 183 */ "ILLEGAL", - /* 184 */ "input", - /* 185 */ "cmdlist", - /* 186 */ "ecmd", - /* 187 */ "cmdx", - /* 188 */ "explain", - /* 189 */ "cmd", - /* 190 */ "transtype", - /* 191 */ "trans_opt", - /* 192 */ "nm", - /* 193 */ "savepoint_opt", - /* 194 */ "create_table", - /* 195 */ "create_table_args", - /* 196 */ "createkw", - /* 197 */ "temp", - /* 198 */ "ifnotexists", - /* 199 */ "dbnm", - /* 200 */ "columnlist", - /* 201 */ "conslist_opt", - /* 202 */ "table_option_set", - /* 203 */ "select", - /* 204 */ "table_option", - /* 205 */ "columnname", - /* 206 */ "carglist", - /* 207 */ "typetoken", - /* 208 */ "typename", - /* 209 */ "signed", - /* 210 */ "plus_num", - /* 211 */ "minus_num", - /* 212 */ "scanpt", - /* 213 */ "scantok", - /* 214 */ "ccons", - /* 215 */ "term", - /* 216 */ "expr", - /* 217 */ "onconf", - /* 218 */ "sortorder", - /* 219 */ "autoinc", - /* 220 */ "eidlist_opt", - /* 221 */ "refargs", - /* 222 */ "defer_subclause", - /* 223 */ "generated", - /* 224 */ "refarg", - /* 225 */ "refact", - /* 226 */ "init_deferred_pred_opt", - /* 227 */ "conslist", - /* 228 */ "tconscomma", - /* 229 */ "tcons", - /* 230 */ "sortlist", - /* 231 */ "eidlist", - /* 232 */ "defer_subclause_opt", - /* 233 */ "orconf", - /* 234 */ "resolvetype", - /* 235 */ "raisetype", - /* 236 */ "ifexists", - /* 237 */ "fullname", - /* 238 */ "selectnowith", - /* 239 */ "oneselect", - /* 240 */ "wqlist", - /* 241 */ "multiselect_op", - /* 242 */ "distinct", - /* 243 */ "selcollist", - /* 244 */ "from", - /* 245 */ "where_opt", - /* 246 */ "groupby_opt", - /* 247 */ "having_opt", - /* 248 */ "orderby_opt", - /* 249 */ "limit_opt", - /* 250 */ "window_clause", - /* 251 */ "values", - /* 252 */ "nexprlist", - /* 253 */ "sclp", - /* 254 */ "as", - /* 255 */ "seltablist", - /* 256 */ "stl_prefix", - /* 257 */ "joinop", - /* 258 */ "indexed_opt", - /* 259 */ "on_opt", - /* 260 */ "using_opt", + /* 112 */ "PTR", + /* 113 */ "COLLATE", + /* 114 */ "BITNOT", + /* 115 */ "ON", + /* 116 */ "INDEXED", + /* 117 */ "STRING", + /* 118 */ "JOIN_KW", + /* 119 */ "CONSTRAINT", + /* 120 */ "DEFAULT", + /* 121 */ "NULL", + /* 122 */ "PRIMARY", + /* 123 */ "UNIQUE", + /* 124 */ "CHECK", + /* 125 */ "REFERENCES", + /* 126 */ "AUTOINCR", + /* 127 */ "INSERT", + /* 128 */ "DELETE", + /* 129 */ "UPDATE", + /* 130 */ "SET", + /* 131 */ "DEFERRABLE", + /* 132 */ "FOREIGN", + /* 133 */ "DROP", + /* 134 */ "UNION", + /* 135 */ "ALL", + /* 136 */ "EXCEPT", + /* 137 */ "INTERSECT", + /* 138 */ "SELECT", + /* 139 */ "VALUES", + /* 140 */ "DISTINCT", + /* 141 */ "DOT", + /* 142 */ "FROM", + /* 143 */ "JOIN", + /* 144 */ "USING", + /* 145 */ "ORDER", + /* 146 */ "GROUP", + /* 147 */ "HAVING", + /* 148 */ "LIMIT", + /* 149 */ "WHERE", + /* 150 */ "RETURNING", + /* 151 */ "INTO", + /* 152 */ "NOTHING", + /* 153 */ "FLOAT", + /* 154 */ "BLOB", + /* 155 */ "INTEGER", + /* 156 */ "VARIABLE", + /* 157 */ "CASE", + /* 158 */ "WHEN", + /* 159 */ "THEN", + /* 160 */ "ELSE", + /* 161 */ "INDEX", + /* 162 */ "ALTER", + /* 163 */ "ADD", + /* 164 */ "WINDOW", + /* 165 */ "OVER", + /* 166 */ "FILTER", + /* 167 */ "COLUMN", + /* 168 */ "AGG_FUNCTION", + /* 169 */ "AGG_COLUMN", + /* 170 */ "TRUEFALSE", + /* 171 */ "ISNOT", + /* 172 */ "FUNCTION", + /* 173 */ "UMINUS", + /* 174 */ "UPLUS", + /* 175 */ "TRUTH", + /* 176 */ "REGISTER", + /* 177 */ "VECTOR", + /* 178 */ "SELECT_COLUMN", + /* 179 */ "IF_NULL_ROW", + /* 180 */ "ASTERISK", + /* 181 */ "SPAN", + /* 182 */ "ERROR", + /* 183 */ "SPACE", + /* 184 */ "ILLEGAL", + /* 185 */ "input", + /* 186 */ "cmdlist", + /* 187 */ "ecmd", + /* 188 */ "cmdx", + /* 189 */ "explain", + /* 190 */ "cmd", + /* 191 */ "transtype", + /* 192 */ "trans_opt", + /* 193 */ "nm", + /* 194 */ "savepoint_opt", + /* 195 */ "create_table", + /* 196 */ "create_table_args", + /* 197 */ "createkw", + /* 198 */ "temp", + /* 199 */ "ifnotexists", + /* 200 */ "dbnm", + /* 201 */ "columnlist", + /* 202 */ "conslist_opt", + /* 203 */ "table_option_set", + /* 204 */ "select", + /* 205 */ "table_option", + /* 206 */ "columnname", + /* 207 */ "carglist", + /* 208 */ "typetoken", + /* 209 */ "typename", + /* 210 */ "signed", + /* 211 */ "plus_num", + /* 212 */ "minus_num", + /* 213 */ "scanpt", + /* 214 */ "scantok", + /* 215 */ "ccons", + /* 216 */ "term", + /* 217 */ "expr", + /* 218 */ "onconf", + /* 219 */ "sortorder", + /* 220 */ "autoinc", + /* 221 */ "eidlist_opt", + /* 222 */ "refargs", + /* 223 */ "defer_subclause", + /* 224 */ "generated", + /* 225 */ "refarg", + /* 226 */ "refact", + /* 227 */ "init_deferred_pred_opt", + /* 228 */ "conslist", + /* 229 */ "tconscomma", + /* 230 */ "tcons", + /* 231 */ "sortlist", + /* 232 */ "eidlist", + /* 233 */ "defer_subclause_opt", + /* 234 */ "orconf", + /* 235 */ "resolvetype", + /* 236 */ "raisetype", + /* 237 */ "ifexists", + /* 238 */ "fullname", + /* 239 */ "selectnowith", + /* 240 */ "oneselect", + /* 241 */ "wqlist", + /* 242 */ "multiselect_op", + /* 243 */ "distinct", + /* 244 */ "selcollist", + /* 245 */ "from", + /* 246 */ "where_opt", + /* 247 */ "groupby_opt", + /* 248 */ "having_opt", + /* 249 */ "orderby_opt", + /* 250 */ "limit_opt", + /* 251 */ "window_clause", + /* 252 */ "values", + /* 253 */ "nexprlist", + /* 254 */ "sclp", + /* 255 */ "as", + /* 256 */ "seltablist", + /* 257 */ "stl_prefix", + /* 258 */ "joinop", + /* 259 */ "on_using", + /* 260 */ "indexed_by", /* 261 */ "exprlist", /* 262 */ "xfullname", /* 263 */ "idlist", - /* 264 */ "nulls", - /* 265 */ "with", - /* 266 */ "where_opt_ret", - /* 267 */ "setlist", - /* 268 */ "insert_cmd", - /* 269 */ "idlist_opt", - /* 270 */ "upsert", - /* 271 */ "returning", - /* 272 */ "filter_over", - /* 273 */ "likeop", - /* 274 */ "between_op", - /* 275 */ "in_op", - /* 276 */ "paren_exprlist", - /* 277 */ "case_operand", - /* 278 */ "case_exprlist", - /* 279 */ "case_else", - /* 280 */ "uniqueflag", - /* 281 */ "collate", - /* 282 */ "vinto", - /* 283 */ "nmnum", - /* 284 */ "trigger_decl", - /* 285 */ "trigger_cmd_list", - /* 286 */ "trigger_time", - /* 287 */ "trigger_event", - /* 288 */ "foreach_clause", - /* 289 */ "when_clause", - /* 290 */ "trigger_cmd", - /* 291 */ "trnm", - /* 292 */ "tridxby", - /* 293 */ "database_kw_opt", - /* 294 */ "key_opt", - /* 295 */ "add_column_fullname", - /* 296 */ "kwcolumn_opt", - /* 297 */ "create_vtab", - /* 298 */ "vtabarglist", - /* 299 */ "vtabarg", - /* 300 */ "vtabargtoken", - /* 301 */ "lp", - /* 302 */ "anylist", - /* 303 */ "wqitem", - /* 304 */ "wqas", - /* 305 */ "windowdefn_list", - /* 306 */ "windowdefn", - /* 307 */ "window", - /* 308 */ "frame_opt", - /* 309 */ "part_opt", - /* 310 */ "filter_clause", - /* 311 */ "over_clause", - /* 312 */ "range_or_rows", - /* 313 */ "frame_bound", - /* 314 */ "frame_bound_s", - /* 315 */ "frame_bound_e", - /* 316 */ "frame_exclude_opt", - /* 317 */ "frame_exclude", + /* 264 */ "indexed_opt", + /* 265 */ "nulls", + /* 266 */ "with", + /* 267 */ "where_opt_ret", + /* 268 */ "setlist", + /* 269 */ "insert_cmd", + /* 270 */ "idlist_opt", + /* 271 */ "upsert", + /* 272 */ "returning", + /* 273 */ "filter_over", + /* 274 */ "likeop", + /* 275 */ "between_op", + /* 276 */ "in_op", + /* 277 */ "paren_exprlist", + /* 278 */ "case_operand", + /* 279 */ "case_exprlist", + /* 280 */ "case_else", + /* 281 */ "uniqueflag", + /* 282 */ "collate", + /* 283 */ "vinto", + /* 284 */ "nmnum", + /* 285 */ "trigger_decl", + /* 286 */ "trigger_cmd_list", + /* 287 */ "trigger_time", + /* 288 */ "trigger_event", + /* 289 */ "foreach_clause", + /* 290 */ "when_clause", + /* 291 */ "trigger_cmd", + /* 292 */ "trnm", + /* 293 */ "tridxby", + /* 294 */ "database_kw_opt", + /* 295 */ "key_opt", + /* 296 */ "add_column_fullname", + /* 297 */ "kwcolumn_opt", + /* 298 */ "create_vtab", + /* 299 */ "vtabarglist", + /* 300 */ "vtabarg", + /* 301 */ "vtabargtoken", + /* 302 */ "lp", + /* 303 */ "anylist", + /* 304 */ "wqitem", + /* 305 */ "wqas", + /* 306 */ "windowdefn_list", + /* 307 */ "windowdefn", + /* 308 */ "window", + /* 309 */ "frame_opt", + /* 310 */ "part_opt", + /* 311 */ "filter_clause", + /* 312 */ "over_clause", + /* 313 */ "range_or_rows", + /* 314 */ "frame_bound", + /* 315 */ "frame_bound_s", + /* 316 */ "frame_bound_e", + /* 317 */ "frame_exclude_opt", + /* 318 */ "frame_exclude", }; #endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */ @@ -161345,29 +165449,29 @@ static const char *const yyRuleName[] = { /* 106 */ "from ::= FROM seltablist", /* 107 */ "stl_prefix ::= seltablist joinop", /* 108 */ "stl_prefix ::=", - /* 109 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt", - /* 110 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt", - /* 111 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt", - /* 112 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt", - /* 113 */ "dbnm ::=", - /* 114 */ "dbnm ::= DOT nm", - /* 115 */ "fullname ::= nm", - /* 116 */ "fullname ::= nm DOT nm", - /* 117 */ "xfullname ::= nm", - /* 118 */ "xfullname ::= nm DOT nm", - /* 119 */ "xfullname ::= nm DOT nm AS nm", - /* 120 */ "xfullname ::= nm AS nm", - /* 121 */ "joinop ::= COMMA|JOIN", - /* 122 */ "joinop ::= JOIN_KW JOIN", - /* 123 */ "joinop ::= JOIN_KW nm JOIN", - /* 124 */ "joinop ::= JOIN_KW nm nm JOIN", - /* 125 */ "on_opt ::= ON expr", - /* 126 */ "on_opt ::=", - /* 127 */ "indexed_opt ::=", - /* 128 */ "indexed_opt ::= INDEXED BY nm", - /* 129 */ "indexed_opt ::= NOT INDEXED", - /* 130 */ "using_opt ::= USING LP idlist RP", - /* 131 */ "using_opt ::=", + /* 109 */ "seltablist ::= stl_prefix nm dbnm as on_using", + /* 110 */ "seltablist ::= stl_prefix nm dbnm as indexed_by on_using", + /* 111 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using", + /* 112 */ "seltablist ::= stl_prefix LP select RP as on_using", + /* 113 */ "seltablist ::= stl_prefix LP seltablist RP as on_using", + /* 114 */ "dbnm ::=", + /* 115 */ "dbnm ::= DOT nm", + /* 116 */ "fullname ::= nm", + /* 117 */ "fullname ::= nm DOT nm", + /* 118 */ "xfullname ::= nm", + /* 119 */ "xfullname ::= nm DOT nm", + /* 120 */ "xfullname ::= nm DOT nm AS nm", + /* 121 */ "xfullname ::= nm AS nm", + /* 122 */ "joinop ::= COMMA|JOIN", + /* 123 */ "joinop ::= JOIN_KW JOIN", + /* 124 */ "joinop ::= JOIN_KW nm JOIN", + /* 125 */ "joinop ::= JOIN_KW nm nm JOIN", + /* 126 */ "on_using ::= ON expr", + /* 127 */ "on_using ::= USING LP idlist RP", + /* 128 */ "on_using ::=", + /* 129 */ "indexed_opt ::=", + /* 130 */ "indexed_by ::= INDEXED BY nm", + /* 131 */ "indexed_by ::= NOT INDEXED", /* 132 */ "orderby_opt ::=", /* 133 */ "orderby_opt ::= ORDER BY sortlist", /* 134 */ "sortlist ::= sortlist COMMA expr sortorder nulls", @@ -161445,198 +165549,202 @@ static const char *const yyRuleName[] = { /* 206 */ "expr ::= expr NOT NULL", /* 207 */ "expr ::= expr IS expr", /* 208 */ "expr ::= expr IS NOT expr", - /* 209 */ "expr ::= NOT expr", - /* 210 */ "expr ::= BITNOT expr", - /* 211 */ "expr ::= PLUS|MINUS expr", - /* 212 */ "between_op ::= BETWEEN", - /* 213 */ "between_op ::= NOT BETWEEN", - /* 214 */ "expr ::= expr between_op expr AND expr", - /* 215 */ "in_op ::= IN", - /* 216 */ "in_op ::= NOT IN", - /* 217 */ "expr ::= expr in_op LP exprlist RP", - /* 218 */ "expr ::= LP select RP", - /* 219 */ "expr ::= expr in_op LP select RP", - /* 220 */ "expr ::= expr in_op nm dbnm paren_exprlist", - /* 221 */ "expr ::= EXISTS LP select RP", - /* 222 */ "expr ::= CASE case_operand case_exprlist case_else END", - /* 223 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", - /* 224 */ "case_exprlist ::= WHEN expr THEN expr", - /* 225 */ "case_else ::= ELSE expr", - /* 226 */ "case_else ::=", - /* 227 */ "case_operand ::= expr", - /* 228 */ "case_operand ::=", - /* 229 */ "exprlist ::=", - /* 230 */ "nexprlist ::= nexprlist COMMA expr", - /* 231 */ "nexprlist ::= expr", - /* 232 */ "paren_exprlist ::=", - /* 233 */ "paren_exprlist ::= LP exprlist RP", - /* 234 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", - /* 235 */ "uniqueflag ::= UNIQUE", - /* 236 */ "uniqueflag ::=", - /* 237 */ "eidlist_opt ::=", - /* 238 */ "eidlist_opt ::= LP eidlist RP", - /* 239 */ "eidlist ::= eidlist COMMA nm collate sortorder", - /* 240 */ "eidlist ::= nm collate sortorder", - /* 241 */ "collate ::=", - /* 242 */ "collate ::= COLLATE ID|STRING", - /* 243 */ "cmd ::= DROP INDEX ifexists fullname", - /* 244 */ "cmd ::= VACUUM vinto", - /* 245 */ "cmd ::= VACUUM nm vinto", - /* 246 */ "vinto ::= INTO expr", - /* 247 */ "vinto ::=", - /* 248 */ "cmd ::= PRAGMA nm dbnm", - /* 249 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", - /* 250 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", - /* 251 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", - /* 252 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", - /* 253 */ "plus_num ::= PLUS INTEGER|FLOAT", - /* 254 */ "minus_num ::= MINUS INTEGER|FLOAT", - /* 255 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", - /* 256 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", - /* 257 */ "trigger_time ::= BEFORE|AFTER", - /* 258 */ "trigger_time ::= INSTEAD OF", - /* 259 */ "trigger_time ::=", - /* 260 */ "trigger_event ::= DELETE|INSERT", - /* 261 */ "trigger_event ::= UPDATE", - /* 262 */ "trigger_event ::= UPDATE OF idlist", - /* 263 */ "when_clause ::=", - /* 264 */ "when_clause ::= WHEN expr", - /* 265 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", - /* 266 */ "trigger_cmd_list ::= trigger_cmd SEMI", - /* 267 */ "trnm ::= nm DOT nm", - /* 268 */ "tridxby ::= INDEXED BY nm", - /* 269 */ "tridxby ::= NOT INDEXED", - /* 270 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt", - /* 271 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt", - /* 272 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt", - /* 273 */ "trigger_cmd ::= scanpt select scanpt", - /* 274 */ "expr ::= RAISE LP IGNORE RP", - /* 275 */ "expr ::= RAISE LP raisetype COMMA nm RP", - /* 276 */ "raisetype ::= ROLLBACK", - /* 277 */ "raisetype ::= ABORT", - /* 278 */ "raisetype ::= FAIL", - /* 279 */ "cmd ::= DROP TRIGGER ifexists fullname", - /* 280 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", - /* 281 */ "cmd ::= DETACH database_kw_opt expr", - /* 282 */ "key_opt ::=", - /* 283 */ "key_opt ::= KEY expr", - /* 284 */ "cmd ::= REINDEX", - /* 285 */ "cmd ::= REINDEX nm dbnm", - /* 286 */ "cmd ::= ANALYZE", - /* 287 */ "cmd ::= ANALYZE nm dbnm", - /* 288 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", - /* 289 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", - /* 290 */ "cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm", - /* 291 */ "add_column_fullname ::= fullname", - /* 292 */ "cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm", - /* 293 */ "cmd ::= create_vtab", - /* 294 */ "cmd ::= create_vtab LP vtabarglist RP", - /* 295 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", - /* 296 */ "vtabarg ::=", - /* 297 */ "vtabargtoken ::= ANY", - /* 298 */ "vtabargtoken ::= lp anylist RP", - /* 299 */ "lp ::= LP", - /* 300 */ "with ::= WITH wqlist", - /* 301 */ "with ::= WITH RECURSIVE wqlist", - /* 302 */ "wqas ::= AS", - /* 303 */ "wqas ::= AS MATERIALIZED", - /* 304 */ "wqas ::= AS NOT MATERIALIZED", - /* 305 */ "wqitem ::= nm eidlist_opt wqas LP select RP", - /* 306 */ "wqlist ::= wqitem", - /* 307 */ "wqlist ::= wqlist COMMA wqitem", - /* 308 */ "windowdefn_list ::= windowdefn", - /* 309 */ "windowdefn_list ::= windowdefn_list COMMA windowdefn", - /* 310 */ "windowdefn ::= nm AS LP window RP", - /* 311 */ "window ::= PARTITION BY nexprlist orderby_opt frame_opt", - /* 312 */ "window ::= nm PARTITION BY nexprlist orderby_opt frame_opt", - /* 313 */ "window ::= ORDER BY sortlist frame_opt", - /* 314 */ "window ::= nm ORDER BY sortlist frame_opt", - /* 315 */ "window ::= frame_opt", - /* 316 */ "window ::= nm frame_opt", - /* 317 */ "frame_opt ::=", - /* 318 */ "frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt", - /* 319 */ "frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt", - /* 320 */ "range_or_rows ::= RANGE|ROWS|GROUPS", - /* 321 */ "frame_bound_s ::= frame_bound", - /* 322 */ "frame_bound_s ::= UNBOUNDED PRECEDING", - /* 323 */ "frame_bound_e ::= frame_bound", - /* 324 */ "frame_bound_e ::= UNBOUNDED FOLLOWING", - /* 325 */ "frame_bound ::= expr PRECEDING|FOLLOWING", - /* 326 */ "frame_bound ::= CURRENT ROW", - /* 327 */ "frame_exclude_opt ::=", - /* 328 */ "frame_exclude_opt ::= EXCLUDE frame_exclude", - /* 329 */ "frame_exclude ::= NO OTHERS", - /* 330 */ "frame_exclude ::= CURRENT ROW", - /* 331 */ "frame_exclude ::= GROUP|TIES", - /* 332 */ "window_clause ::= WINDOW windowdefn_list", - /* 333 */ "filter_over ::= filter_clause over_clause", - /* 334 */ "filter_over ::= over_clause", - /* 335 */ "filter_over ::= filter_clause", - /* 336 */ "over_clause ::= OVER LP window RP", - /* 337 */ "over_clause ::= OVER nm", - /* 338 */ "filter_clause ::= FILTER LP WHERE expr RP", - /* 339 */ "input ::= cmdlist", - /* 340 */ "cmdlist ::= cmdlist ecmd", - /* 341 */ "cmdlist ::= ecmd", - /* 342 */ "ecmd ::= SEMI", - /* 343 */ "ecmd ::= cmdx SEMI", - /* 344 */ "ecmd ::= explain cmdx SEMI", - /* 345 */ "trans_opt ::=", - /* 346 */ "trans_opt ::= TRANSACTION", - /* 347 */ "trans_opt ::= TRANSACTION nm", - /* 348 */ "savepoint_opt ::= SAVEPOINT", - /* 349 */ "savepoint_opt ::=", - /* 350 */ "cmd ::= create_table create_table_args", - /* 351 */ "table_option_set ::= table_option", - /* 352 */ "columnlist ::= columnlist COMMA columnname carglist", - /* 353 */ "columnlist ::= columnname carglist", - /* 354 */ "nm ::= ID|INDEXED", - /* 355 */ "nm ::= STRING", - /* 356 */ "nm ::= JOIN_KW", - /* 357 */ "typetoken ::= typename", - /* 358 */ "typename ::= ID|STRING", - /* 359 */ "signed ::= plus_num", - /* 360 */ "signed ::= minus_num", - /* 361 */ "carglist ::= carglist ccons", - /* 362 */ "carglist ::=", - /* 363 */ "ccons ::= NULL onconf", - /* 364 */ "ccons ::= GENERATED ALWAYS AS generated", - /* 365 */ "ccons ::= AS generated", - /* 366 */ "conslist_opt ::= COMMA conslist", - /* 367 */ "conslist ::= conslist tconscomma tcons", - /* 368 */ "conslist ::= tcons", - /* 369 */ "tconscomma ::=", - /* 370 */ "defer_subclause_opt ::= defer_subclause", - /* 371 */ "resolvetype ::= raisetype", - /* 372 */ "selectnowith ::= oneselect", - /* 373 */ "oneselect ::= values", - /* 374 */ "sclp ::= selcollist COMMA", - /* 375 */ "as ::= ID|STRING", - /* 376 */ "returning ::=", - /* 377 */ "expr ::= term", - /* 378 */ "likeop ::= LIKE_KW|MATCH", - /* 379 */ "exprlist ::= nexprlist", - /* 380 */ "nmnum ::= plus_num", - /* 381 */ "nmnum ::= nm", - /* 382 */ "nmnum ::= ON", - /* 383 */ "nmnum ::= DELETE", - /* 384 */ "nmnum ::= DEFAULT", - /* 385 */ "plus_num ::= INTEGER|FLOAT", - /* 386 */ "foreach_clause ::=", - /* 387 */ "foreach_clause ::= FOR EACH ROW", - /* 388 */ "trnm ::= nm", - /* 389 */ "tridxby ::=", - /* 390 */ "database_kw_opt ::= DATABASE", - /* 391 */ "database_kw_opt ::=", - /* 392 */ "kwcolumn_opt ::=", - /* 393 */ "kwcolumn_opt ::= COLUMNKW", - /* 394 */ "vtabarglist ::= vtabarg", - /* 395 */ "vtabarglist ::= vtabarglist COMMA vtabarg", - /* 396 */ "vtabarg ::= vtabarg vtabargtoken", - /* 397 */ "anylist ::=", - /* 398 */ "anylist ::= anylist LP anylist RP", - /* 399 */ "anylist ::= anylist ANY", - /* 400 */ "with ::=", + /* 209 */ "expr ::= expr IS NOT DISTINCT FROM expr", + /* 210 */ "expr ::= expr IS DISTINCT FROM expr", + /* 211 */ "expr ::= NOT expr", + /* 212 */ "expr ::= BITNOT expr", + /* 213 */ "expr ::= PLUS|MINUS expr", + /* 214 */ "expr ::= expr PTR expr", + /* 215 */ "between_op ::= BETWEEN", + /* 216 */ "between_op ::= NOT BETWEEN", + /* 217 */ "expr ::= expr between_op expr AND expr", + /* 218 */ "in_op ::= IN", + /* 219 */ "in_op ::= NOT IN", + /* 220 */ "expr ::= expr in_op LP exprlist RP", + /* 221 */ "expr ::= LP select RP", + /* 222 */ "expr ::= expr in_op LP select RP", + /* 223 */ "expr ::= expr in_op nm dbnm paren_exprlist", + /* 224 */ "expr ::= EXISTS LP select RP", + /* 225 */ "expr ::= CASE case_operand case_exprlist case_else END", + /* 226 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", + /* 227 */ "case_exprlist ::= WHEN expr THEN expr", + /* 228 */ "case_else ::= ELSE expr", + /* 229 */ "case_else ::=", + /* 230 */ "case_operand ::= expr", + /* 231 */ "case_operand ::=", + /* 232 */ "exprlist ::=", + /* 233 */ "nexprlist ::= nexprlist COMMA expr", + /* 234 */ "nexprlist ::= expr", + /* 235 */ "paren_exprlist ::=", + /* 236 */ "paren_exprlist ::= LP exprlist RP", + /* 237 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", + /* 238 */ "uniqueflag ::= UNIQUE", + /* 239 */ "uniqueflag ::=", + /* 240 */ "eidlist_opt ::=", + /* 241 */ "eidlist_opt ::= LP eidlist RP", + /* 242 */ "eidlist ::= eidlist COMMA nm collate sortorder", + /* 243 */ "eidlist ::= nm collate sortorder", + /* 244 */ "collate ::=", + /* 245 */ "collate ::= COLLATE ID|STRING", + /* 246 */ "cmd ::= DROP INDEX ifexists fullname", + /* 247 */ "cmd ::= VACUUM vinto", + /* 248 */ "cmd ::= VACUUM nm vinto", + /* 249 */ "vinto ::= INTO expr", + /* 250 */ "vinto ::=", + /* 251 */ "cmd ::= PRAGMA nm dbnm", + /* 252 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", + /* 253 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", + /* 254 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", + /* 255 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", + /* 256 */ "plus_num ::= PLUS INTEGER|FLOAT", + /* 257 */ "minus_num ::= MINUS INTEGER|FLOAT", + /* 258 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", + /* 259 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", + /* 260 */ "trigger_time ::= BEFORE|AFTER", + /* 261 */ "trigger_time ::= INSTEAD OF", + /* 262 */ "trigger_time ::=", + /* 263 */ "trigger_event ::= DELETE|INSERT", + /* 264 */ "trigger_event ::= UPDATE", + /* 265 */ "trigger_event ::= UPDATE OF idlist", + /* 266 */ "when_clause ::=", + /* 267 */ "when_clause ::= WHEN expr", + /* 268 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", + /* 269 */ "trigger_cmd_list ::= trigger_cmd SEMI", + /* 270 */ "trnm ::= nm DOT nm", + /* 271 */ "tridxby ::= INDEXED BY nm", + /* 272 */ "tridxby ::= NOT INDEXED", + /* 273 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt", + /* 274 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt", + /* 275 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt", + /* 276 */ "trigger_cmd ::= scanpt select scanpt", + /* 277 */ "expr ::= RAISE LP IGNORE RP", + /* 278 */ "expr ::= RAISE LP raisetype COMMA nm RP", + /* 279 */ "raisetype ::= ROLLBACK", + /* 280 */ "raisetype ::= ABORT", + /* 281 */ "raisetype ::= FAIL", + /* 282 */ "cmd ::= DROP TRIGGER ifexists fullname", + /* 283 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", + /* 284 */ "cmd ::= DETACH database_kw_opt expr", + /* 285 */ "key_opt ::=", + /* 286 */ "key_opt ::= KEY expr", + /* 287 */ "cmd ::= REINDEX", + /* 288 */ "cmd ::= REINDEX nm dbnm", + /* 289 */ "cmd ::= ANALYZE", + /* 290 */ "cmd ::= ANALYZE nm dbnm", + /* 291 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", + /* 292 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", + /* 293 */ "cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm", + /* 294 */ "add_column_fullname ::= fullname", + /* 295 */ "cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm", + /* 296 */ "cmd ::= create_vtab", + /* 297 */ "cmd ::= create_vtab LP vtabarglist RP", + /* 298 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", + /* 299 */ "vtabarg ::=", + /* 300 */ "vtabargtoken ::= ANY", + /* 301 */ "vtabargtoken ::= lp anylist RP", + /* 302 */ "lp ::= LP", + /* 303 */ "with ::= WITH wqlist", + /* 304 */ "with ::= WITH RECURSIVE wqlist", + /* 305 */ "wqas ::= AS", + /* 306 */ "wqas ::= AS MATERIALIZED", + /* 307 */ "wqas ::= AS NOT MATERIALIZED", + /* 308 */ "wqitem ::= nm eidlist_opt wqas LP select RP", + /* 309 */ "wqlist ::= wqitem", + /* 310 */ "wqlist ::= wqlist COMMA wqitem", + /* 311 */ "windowdefn_list ::= windowdefn", + /* 312 */ "windowdefn_list ::= windowdefn_list COMMA windowdefn", + /* 313 */ "windowdefn ::= nm AS LP window RP", + /* 314 */ "window ::= PARTITION BY nexprlist orderby_opt frame_opt", + /* 315 */ "window ::= nm PARTITION BY nexprlist orderby_opt frame_opt", + /* 316 */ "window ::= ORDER BY sortlist frame_opt", + /* 317 */ "window ::= nm ORDER BY sortlist frame_opt", + /* 318 */ "window ::= frame_opt", + /* 319 */ "window ::= nm frame_opt", + /* 320 */ "frame_opt ::=", + /* 321 */ "frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt", + /* 322 */ "frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt", + /* 323 */ "range_or_rows ::= RANGE|ROWS|GROUPS", + /* 324 */ "frame_bound_s ::= frame_bound", + /* 325 */ "frame_bound_s ::= UNBOUNDED PRECEDING", + /* 326 */ "frame_bound_e ::= frame_bound", + /* 327 */ "frame_bound_e ::= UNBOUNDED FOLLOWING", + /* 328 */ "frame_bound ::= expr PRECEDING|FOLLOWING", + /* 329 */ "frame_bound ::= CURRENT ROW", + /* 330 */ "frame_exclude_opt ::=", + /* 331 */ "frame_exclude_opt ::= EXCLUDE frame_exclude", + /* 332 */ "frame_exclude ::= NO OTHERS", + /* 333 */ "frame_exclude ::= CURRENT ROW", + /* 334 */ "frame_exclude ::= GROUP|TIES", + /* 335 */ "window_clause ::= WINDOW windowdefn_list", + /* 336 */ "filter_over ::= filter_clause over_clause", + /* 337 */ "filter_over ::= over_clause", + /* 338 */ "filter_over ::= filter_clause", + /* 339 */ "over_clause ::= OVER LP window RP", + /* 340 */ "over_clause ::= OVER nm", + /* 341 */ "filter_clause ::= FILTER LP WHERE expr RP", + /* 342 */ "input ::= cmdlist", + /* 343 */ "cmdlist ::= cmdlist ecmd", + /* 344 */ "cmdlist ::= ecmd", + /* 345 */ "ecmd ::= SEMI", + /* 346 */ "ecmd ::= cmdx SEMI", + /* 347 */ "ecmd ::= explain cmdx SEMI", + /* 348 */ "trans_opt ::=", + /* 349 */ "trans_opt ::= TRANSACTION", + /* 350 */ "trans_opt ::= TRANSACTION nm", + /* 351 */ "savepoint_opt ::= SAVEPOINT", + /* 352 */ "savepoint_opt ::=", + /* 353 */ "cmd ::= create_table create_table_args", + /* 354 */ "table_option_set ::= table_option", + /* 355 */ "columnlist ::= columnlist COMMA columnname carglist", + /* 356 */ "columnlist ::= columnname carglist", + /* 357 */ "nm ::= ID|INDEXED", + /* 358 */ "nm ::= STRING", + /* 359 */ "nm ::= JOIN_KW", + /* 360 */ "typetoken ::= typename", + /* 361 */ "typename ::= ID|STRING", + /* 362 */ "signed ::= plus_num", + /* 363 */ "signed ::= minus_num", + /* 364 */ "carglist ::= carglist ccons", + /* 365 */ "carglist ::=", + /* 366 */ "ccons ::= NULL onconf", + /* 367 */ "ccons ::= GENERATED ALWAYS AS generated", + /* 368 */ "ccons ::= AS generated", + /* 369 */ "conslist_opt ::= COMMA conslist", + /* 370 */ "conslist ::= conslist tconscomma tcons", + /* 371 */ "conslist ::= tcons", + /* 372 */ "tconscomma ::=", + /* 373 */ "defer_subclause_opt ::= defer_subclause", + /* 374 */ "resolvetype ::= raisetype", + /* 375 */ "selectnowith ::= oneselect", + /* 376 */ "oneselect ::= values", + /* 377 */ "sclp ::= selcollist COMMA", + /* 378 */ "as ::= ID|STRING", + /* 379 */ "indexed_opt ::= indexed_by", + /* 380 */ "returning ::=", + /* 381 */ "expr ::= term", + /* 382 */ "likeop ::= LIKE_KW|MATCH", + /* 383 */ "exprlist ::= nexprlist", + /* 384 */ "nmnum ::= plus_num", + /* 385 */ "nmnum ::= nm", + /* 386 */ "nmnum ::= ON", + /* 387 */ "nmnum ::= DELETE", + /* 388 */ "nmnum ::= DEFAULT", + /* 389 */ "plus_num ::= INTEGER|FLOAT", + /* 390 */ "foreach_clause ::=", + /* 391 */ "foreach_clause ::= FOR EACH ROW", + /* 392 */ "trnm ::= nm", + /* 393 */ "tridxby ::=", + /* 394 */ "database_kw_opt ::= DATABASE", + /* 395 */ "database_kw_opt ::=", + /* 396 */ "kwcolumn_opt ::=", + /* 397 */ "kwcolumn_opt ::= COLUMNKW", + /* 398 */ "vtabarglist ::= vtabarg", + /* 399 */ "vtabarglist ::= vtabarglist COMMA vtabarg", + /* 400 */ "vtabarg ::= vtabarg vtabargtoken", + /* 401 */ "anylist ::=", + /* 402 */ "anylist ::= anylist LP anylist RP", + /* 403 */ "anylist ::= anylist ANY", + /* 404 */ "with ::=", }; #endif /* NDEBUG */ @@ -161762,99 +165870,97 @@ static void yy_destructor( ** inside the C code. */ /********* Begin destructor definitions ***************************************/ - case 203: /* select */ - case 238: /* selectnowith */ - case 239: /* oneselect */ - case 251: /* values */ + case 204: /* select */ + case 239: /* selectnowith */ + case 240: /* oneselect */ + case 252: /* values */ { -sqlite3SelectDelete(pParse->db, (yypminor->yy303)); -} - break; - case 215: /* term */ - case 216: /* expr */ - case 245: /* where_opt */ - case 247: /* having_opt */ - case 259: /* on_opt */ - case 266: /* where_opt_ret */ - case 277: /* case_operand */ - case 279: /* case_else */ - case 282: /* vinto */ - case 289: /* when_clause */ - case 294: /* key_opt */ - case 310: /* filter_clause */ +sqlite3SelectDelete(pParse->db, (yypminor->yy47)); +} + break; + case 216: /* term */ + case 217: /* expr */ + case 246: /* where_opt */ + case 248: /* having_opt */ + case 267: /* where_opt_ret */ + case 278: /* case_operand */ + case 280: /* case_else */ + case 283: /* vinto */ + case 290: /* when_clause */ + case 295: /* key_opt */ + case 311: /* filter_clause */ { -sqlite3ExprDelete(pParse->db, (yypminor->yy626)); +sqlite3ExprDelete(pParse->db, (yypminor->yy528)); } break; - case 220: /* eidlist_opt */ - case 230: /* sortlist */ - case 231: /* eidlist */ - case 243: /* selcollist */ - case 246: /* groupby_opt */ - case 248: /* orderby_opt */ - case 252: /* nexprlist */ - case 253: /* sclp */ + case 221: /* eidlist_opt */ + case 231: /* sortlist */ + case 232: /* eidlist */ + case 244: /* selcollist */ + case 247: /* groupby_opt */ + case 249: /* orderby_opt */ + case 253: /* nexprlist */ + case 254: /* sclp */ case 261: /* exprlist */ - case 267: /* setlist */ - case 276: /* paren_exprlist */ - case 278: /* case_exprlist */ - case 309: /* part_opt */ + case 268: /* setlist */ + case 277: /* paren_exprlist */ + case 279: /* case_exprlist */ + case 310: /* part_opt */ { -sqlite3ExprListDelete(pParse->db, (yypminor->yy562)); +sqlite3ExprListDelete(pParse->db, (yypminor->yy322)); } break; - case 237: /* fullname */ - case 244: /* from */ - case 255: /* seltablist */ - case 256: /* stl_prefix */ + case 238: /* fullname */ + case 245: /* from */ + case 256: /* seltablist */ + case 257: /* stl_prefix */ case 262: /* xfullname */ { -sqlite3SrcListDelete(pParse->db, (yypminor->yy607)); +sqlite3SrcListDelete(pParse->db, (yypminor->yy131)); } break; - case 240: /* wqlist */ + case 241: /* wqlist */ { -sqlite3WithDelete(pParse->db, (yypminor->yy43)); +sqlite3WithDelete(pParse->db, (yypminor->yy521)); } break; - case 250: /* window_clause */ - case 305: /* windowdefn_list */ + case 251: /* window_clause */ + case 306: /* windowdefn_list */ { -sqlite3WindowListDelete(pParse->db, (yypminor->yy375)); +sqlite3WindowListDelete(pParse->db, (yypminor->yy41)); } break; - case 260: /* using_opt */ case 263: /* idlist */ - case 269: /* idlist_opt */ + case 270: /* idlist_opt */ { -sqlite3IdListDelete(pParse->db, (yypminor->yy240)); +sqlite3IdListDelete(pParse->db, (yypminor->yy254)); } break; - case 272: /* filter_over */ - case 306: /* windowdefn */ - case 307: /* window */ - case 308: /* frame_opt */ - case 311: /* over_clause */ + case 273: /* filter_over */ + case 307: /* windowdefn */ + case 308: /* window */ + case 309: /* frame_opt */ + case 312: /* over_clause */ { -sqlite3WindowDelete(pParse->db, (yypminor->yy375)); +sqlite3WindowDelete(pParse->db, (yypminor->yy41)); } break; - case 285: /* trigger_cmd_list */ - case 290: /* trigger_cmd */ + case 286: /* trigger_cmd_list */ + case 291: /* trigger_cmd */ { -sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy95)); +sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy33)); } break; - case 287: /* trigger_event */ + case 288: /* trigger_event */ { -sqlite3IdListDelete(pParse->db, (yypminor->yy570).b); +sqlite3IdListDelete(pParse->db, (yypminor->yy180).b); } break; - case 313: /* frame_bound */ - case 314: /* frame_bound_s */ - case 315: /* frame_bound_e */ + case 314: /* frame_bound */ + case 315: /* frame_bound_s */ + case 316: /* frame_bound_e */ { -sqlite3ExprDelete(pParse->db, (yypminor->yy81).pExpr); +sqlite3ExprDelete(pParse->db, (yypminor->yy595).pExpr); } break; /********* End destructor definitions *****************************************/ @@ -162145,407 +166251,411 @@ static void yy_shift( /* For rule J, yyRuleInfoLhs[J] contains the symbol on the left-hand side ** of that rule */ static const YYCODETYPE yyRuleInfoLhs[] = { - 188, /* (0) explain ::= EXPLAIN */ - 188, /* (1) explain ::= EXPLAIN QUERY PLAN */ - 187, /* (2) cmdx ::= cmd */ - 189, /* (3) cmd ::= BEGIN transtype trans_opt */ - 190, /* (4) transtype ::= */ - 190, /* (5) transtype ::= DEFERRED */ - 190, /* (6) transtype ::= IMMEDIATE */ - 190, /* (7) transtype ::= EXCLUSIVE */ - 189, /* (8) cmd ::= COMMIT|END trans_opt */ - 189, /* (9) cmd ::= ROLLBACK trans_opt */ - 189, /* (10) cmd ::= SAVEPOINT nm */ - 189, /* (11) cmd ::= RELEASE savepoint_opt nm */ - 189, /* (12) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */ - 194, /* (13) create_table ::= createkw temp TABLE ifnotexists nm dbnm */ - 196, /* (14) createkw ::= CREATE */ - 198, /* (15) ifnotexists ::= */ - 198, /* (16) ifnotexists ::= IF NOT EXISTS */ - 197, /* (17) temp ::= TEMP */ - 197, /* (18) temp ::= */ - 195, /* (19) create_table_args ::= LP columnlist conslist_opt RP table_option_set */ - 195, /* (20) create_table_args ::= AS select */ - 202, /* (21) table_option_set ::= */ - 202, /* (22) table_option_set ::= table_option_set COMMA table_option */ - 204, /* (23) table_option ::= WITHOUT nm */ - 204, /* (24) table_option ::= nm */ - 205, /* (25) columnname ::= nm typetoken */ - 207, /* (26) typetoken ::= */ - 207, /* (27) typetoken ::= typename LP signed RP */ - 207, /* (28) typetoken ::= typename LP signed COMMA signed RP */ - 208, /* (29) typename ::= typename ID|STRING */ - 212, /* (30) scanpt ::= */ - 213, /* (31) scantok ::= */ - 214, /* (32) ccons ::= CONSTRAINT nm */ - 214, /* (33) ccons ::= DEFAULT scantok term */ - 214, /* (34) ccons ::= DEFAULT LP expr RP */ - 214, /* (35) ccons ::= DEFAULT PLUS scantok term */ - 214, /* (36) ccons ::= DEFAULT MINUS scantok term */ - 214, /* (37) ccons ::= DEFAULT scantok ID|INDEXED */ - 214, /* (38) ccons ::= NOT NULL onconf */ - 214, /* (39) ccons ::= PRIMARY KEY sortorder onconf autoinc */ - 214, /* (40) ccons ::= UNIQUE onconf */ - 214, /* (41) ccons ::= CHECK LP expr RP */ - 214, /* (42) ccons ::= REFERENCES nm eidlist_opt refargs */ - 214, /* (43) ccons ::= defer_subclause */ - 214, /* (44) ccons ::= COLLATE ID|STRING */ - 223, /* (45) generated ::= LP expr RP */ - 223, /* (46) generated ::= LP expr RP ID */ - 219, /* (47) autoinc ::= */ - 219, /* (48) autoinc ::= AUTOINCR */ - 221, /* (49) refargs ::= */ - 221, /* (50) refargs ::= refargs refarg */ - 224, /* (51) refarg ::= MATCH nm */ - 224, /* (52) refarg ::= ON INSERT refact */ - 224, /* (53) refarg ::= ON DELETE refact */ - 224, /* (54) refarg ::= ON UPDATE refact */ - 225, /* (55) refact ::= SET NULL */ - 225, /* (56) refact ::= SET DEFAULT */ - 225, /* (57) refact ::= CASCADE */ - 225, /* (58) refact ::= RESTRICT */ - 225, /* (59) refact ::= NO ACTION */ - 222, /* (60) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ - 222, /* (61) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ - 226, /* (62) init_deferred_pred_opt ::= */ - 226, /* (63) init_deferred_pred_opt ::= INITIALLY DEFERRED */ - 226, /* (64) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ - 201, /* (65) conslist_opt ::= */ - 228, /* (66) tconscomma ::= COMMA */ - 229, /* (67) tcons ::= CONSTRAINT nm */ - 229, /* (68) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ - 229, /* (69) tcons ::= UNIQUE LP sortlist RP onconf */ - 229, /* (70) tcons ::= CHECK LP expr RP onconf */ - 229, /* (71) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ - 232, /* (72) defer_subclause_opt ::= */ - 217, /* (73) onconf ::= */ - 217, /* (74) onconf ::= ON CONFLICT resolvetype */ - 233, /* (75) orconf ::= */ - 233, /* (76) orconf ::= OR resolvetype */ - 234, /* (77) resolvetype ::= IGNORE */ - 234, /* (78) resolvetype ::= REPLACE */ - 189, /* (79) cmd ::= DROP TABLE ifexists fullname */ - 236, /* (80) ifexists ::= IF EXISTS */ - 236, /* (81) ifexists ::= */ - 189, /* (82) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ - 189, /* (83) cmd ::= DROP VIEW ifexists fullname */ - 189, /* (84) cmd ::= select */ - 203, /* (85) select ::= WITH wqlist selectnowith */ - 203, /* (86) select ::= WITH RECURSIVE wqlist selectnowith */ - 203, /* (87) select ::= selectnowith */ - 238, /* (88) selectnowith ::= selectnowith multiselect_op oneselect */ - 241, /* (89) multiselect_op ::= UNION */ - 241, /* (90) multiselect_op ::= UNION ALL */ - 241, /* (91) multiselect_op ::= EXCEPT|INTERSECT */ - 239, /* (92) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ - 239, /* (93) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */ - 251, /* (94) values ::= VALUES LP nexprlist RP */ - 251, /* (95) values ::= values COMMA LP nexprlist RP */ - 242, /* (96) distinct ::= DISTINCT */ - 242, /* (97) distinct ::= ALL */ - 242, /* (98) distinct ::= */ - 253, /* (99) sclp ::= */ - 243, /* (100) selcollist ::= sclp scanpt expr scanpt as */ - 243, /* (101) selcollist ::= sclp scanpt STAR */ - 243, /* (102) selcollist ::= sclp scanpt nm DOT STAR */ - 254, /* (103) as ::= AS nm */ - 254, /* (104) as ::= */ - 244, /* (105) from ::= */ - 244, /* (106) from ::= FROM seltablist */ - 256, /* (107) stl_prefix ::= seltablist joinop */ - 256, /* (108) stl_prefix ::= */ - 255, /* (109) seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */ - 255, /* (110) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */ - 255, /* (111) seltablist ::= stl_prefix LP select RP as on_opt using_opt */ - 255, /* (112) seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ - 199, /* (113) dbnm ::= */ - 199, /* (114) dbnm ::= DOT nm */ - 237, /* (115) fullname ::= nm */ - 237, /* (116) fullname ::= nm DOT nm */ - 262, /* (117) xfullname ::= nm */ - 262, /* (118) xfullname ::= nm DOT nm */ - 262, /* (119) xfullname ::= nm DOT nm AS nm */ - 262, /* (120) xfullname ::= nm AS nm */ - 257, /* (121) joinop ::= COMMA|JOIN */ - 257, /* (122) joinop ::= JOIN_KW JOIN */ - 257, /* (123) joinop ::= JOIN_KW nm JOIN */ - 257, /* (124) joinop ::= JOIN_KW nm nm JOIN */ - 259, /* (125) on_opt ::= ON expr */ - 259, /* (126) on_opt ::= */ - 258, /* (127) indexed_opt ::= */ - 258, /* (128) indexed_opt ::= INDEXED BY nm */ - 258, /* (129) indexed_opt ::= NOT INDEXED */ - 260, /* (130) using_opt ::= USING LP idlist RP */ - 260, /* (131) using_opt ::= */ - 248, /* (132) orderby_opt ::= */ - 248, /* (133) orderby_opt ::= ORDER BY sortlist */ - 230, /* (134) sortlist ::= sortlist COMMA expr sortorder nulls */ - 230, /* (135) sortlist ::= expr sortorder nulls */ - 218, /* (136) sortorder ::= ASC */ - 218, /* (137) sortorder ::= DESC */ - 218, /* (138) sortorder ::= */ - 264, /* (139) nulls ::= NULLS FIRST */ - 264, /* (140) nulls ::= NULLS LAST */ - 264, /* (141) nulls ::= */ - 246, /* (142) groupby_opt ::= */ - 246, /* (143) groupby_opt ::= GROUP BY nexprlist */ - 247, /* (144) having_opt ::= */ - 247, /* (145) having_opt ::= HAVING expr */ - 249, /* (146) limit_opt ::= */ - 249, /* (147) limit_opt ::= LIMIT expr */ - 249, /* (148) limit_opt ::= LIMIT expr OFFSET expr */ - 249, /* (149) limit_opt ::= LIMIT expr COMMA expr */ - 189, /* (150) cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */ - 245, /* (151) where_opt ::= */ - 245, /* (152) where_opt ::= WHERE expr */ - 266, /* (153) where_opt_ret ::= */ - 266, /* (154) where_opt_ret ::= WHERE expr */ - 266, /* (155) where_opt_ret ::= RETURNING selcollist */ - 266, /* (156) where_opt_ret ::= WHERE expr RETURNING selcollist */ - 189, /* (157) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */ - 267, /* (158) setlist ::= setlist COMMA nm EQ expr */ - 267, /* (159) setlist ::= setlist COMMA LP idlist RP EQ expr */ - 267, /* (160) setlist ::= nm EQ expr */ - 267, /* (161) setlist ::= LP idlist RP EQ expr */ - 189, /* (162) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */ - 189, /* (163) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */ - 270, /* (164) upsert ::= */ - 270, /* (165) upsert ::= RETURNING selcollist */ - 270, /* (166) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */ - 270, /* (167) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */ - 270, /* (168) upsert ::= ON CONFLICT DO NOTHING returning */ - 270, /* (169) upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */ - 271, /* (170) returning ::= RETURNING selcollist */ - 268, /* (171) insert_cmd ::= INSERT orconf */ - 268, /* (172) insert_cmd ::= REPLACE */ - 269, /* (173) idlist_opt ::= */ - 269, /* (174) idlist_opt ::= LP idlist RP */ + 189, /* (0) explain ::= EXPLAIN */ + 189, /* (1) explain ::= EXPLAIN QUERY PLAN */ + 188, /* (2) cmdx ::= cmd */ + 190, /* (3) cmd ::= BEGIN transtype trans_opt */ + 191, /* (4) transtype ::= */ + 191, /* (5) transtype ::= DEFERRED */ + 191, /* (6) transtype ::= IMMEDIATE */ + 191, /* (7) transtype ::= EXCLUSIVE */ + 190, /* (8) cmd ::= COMMIT|END trans_opt */ + 190, /* (9) cmd ::= ROLLBACK trans_opt */ + 190, /* (10) cmd ::= SAVEPOINT nm */ + 190, /* (11) cmd ::= RELEASE savepoint_opt nm */ + 190, /* (12) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */ + 195, /* (13) create_table ::= createkw temp TABLE ifnotexists nm dbnm */ + 197, /* (14) createkw ::= CREATE */ + 199, /* (15) ifnotexists ::= */ + 199, /* (16) ifnotexists ::= IF NOT EXISTS */ + 198, /* (17) temp ::= TEMP */ + 198, /* (18) temp ::= */ + 196, /* (19) create_table_args ::= LP columnlist conslist_opt RP table_option_set */ + 196, /* (20) create_table_args ::= AS select */ + 203, /* (21) table_option_set ::= */ + 203, /* (22) table_option_set ::= table_option_set COMMA table_option */ + 205, /* (23) table_option ::= WITHOUT nm */ + 205, /* (24) table_option ::= nm */ + 206, /* (25) columnname ::= nm typetoken */ + 208, /* (26) typetoken ::= */ + 208, /* (27) typetoken ::= typename LP signed RP */ + 208, /* (28) typetoken ::= typename LP signed COMMA signed RP */ + 209, /* (29) typename ::= typename ID|STRING */ + 213, /* (30) scanpt ::= */ + 214, /* (31) scantok ::= */ + 215, /* (32) ccons ::= CONSTRAINT nm */ + 215, /* (33) ccons ::= DEFAULT scantok term */ + 215, /* (34) ccons ::= DEFAULT LP expr RP */ + 215, /* (35) ccons ::= DEFAULT PLUS scantok term */ + 215, /* (36) ccons ::= DEFAULT MINUS scantok term */ + 215, /* (37) ccons ::= DEFAULT scantok ID|INDEXED */ + 215, /* (38) ccons ::= NOT NULL onconf */ + 215, /* (39) ccons ::= PRIMARY KEY sortorder onconf autoinc */ + 215, /* (40) ccons ::= UNIQUE onconf */ + 215, /* (41) ccons ::= CHECK LP expr RP */ + 215, /* (42) ccons ::= REFERENCES nm eidlist_opt refargs */ + 215, /* (43) ccons ::= defer_subclause */ + 215, /* (44) ccons ::= COLLATE ID|STRING */ + 224, /* (45) generated ::= LP expr RP */ + 224, /* (46) generated ::= LP expr RP ID */ + 220, /* (47) autoinc ::= */ + 220, /* (48) autoinc ::= AUTOINCR */ + 222, /* (49) refargs ::= */ + 222, /* (50) refargs ::= refargs refarg */ + 225, /* (51) refarg ::= MATCH nm */ + 225, /* (52) refarg ::= ON INSERT refact */ + 225, /* (53) refarg ::= ON DELETE refact */ + 225, /* (54) refarg ::= ON UPDATE refact */ + 226, /* (55) refact ::= SET NULL */ + 226, /* (56) refact ::= SET DEFAULT */ + 226, /* (57) refact ::= CASCADE */ + 226, /* (58) refact ::= RESTRICT */ + 226, /* (59) refact ::= NO ACTION */ + 223, /* (60) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ + 223, /* (61) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ + 227, /* (62) init_deferred_pred_opt ::= */ + 227, /* (63) init_deferred_pred_opt ::= INITIALLY DEFERRED */ + 227, /* (64) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ + 202, /* (65) conslist_opt ::= */ + 229, /* (66) tconscomma ::= COMMA */ + 230, /* (67) tcons ::= CONSTRAINT nm */ + 230, /* (68) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ + 230, /* (69) tcons ::= UNIQUE LP sortlist RP onconf */ + 230, /* (70) tcons ::= CHECK LP expr RP onconf */ + 230, /* (71) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ + 233, /* (72) defer_subclause_opt ::= */ + 218, /* (73) onconf ::= */ + 218, /* (74) onconf ::= ON CONFLICT resolvetype */ + 234, /* (75) orconf ::= */ + 234, /* (76) orconf ::= OR resolvetype */ + 235, /* (77) resolvetype ::= IGNORE */ + 235, /* (78) resolvetype ::= REPLACE */ + 190, /* (79) cmd ::= DROP TABLE ifexists fullname */ + 237, /* (80) ifexists ::= IF EXISTS */ + 237, /* (81) ifexists ::= */ + 190, /* (82) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ + 190, /* (83) cmd ::= DROP VIEW ifexists fullname */ + 190, /* (84) cmd ::= select */ + 204, /* (85) select ::= WITH wqlist selectnowith */ + 204, /* (86) select ::= WITH RECURSIVE wqlist selectnowith */ + 204, /* (87) select ::= selectnowith */ + 239, /* (88) selectnowith ::= selectnowith multiselect_op oneselect */ + 242, /* (89) multiselect_op ::= UNION */ + 242, /* (90) multiselect_op ::= UNION ALL */ + 242, /* (91) multiselect_op ::= EXCEPT|INTERSECT */ + 240, /* (92) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ + 240, /* (93) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */ + 252, /* (94) values ::= VALUES LP nexprlist RP */ + 252, /* (95) values ::= values COMMA LP nexprlist RP */ + 243, /* (96) distinct ::= DISTINCT */ + 243, /* (97) distinct ::= ALL */ + 243, /* (98) distinct ::= */ + 254, /* (99) sclp ::= */ + 244, /* (100) selcollist ::= sclp scanpt expr scanpt as */ + 244, /* (101) selcollist ::= sclp scanpt STAR */ + 244, /* (102) selcollist ::= sclp scanpt nm DOT STAR */ + 255, /* (103) as ::= AS nm */ + 255, /* (104) as ::= */ + 245, /* (105) from ::= */ + 245, /* (106) from ::= FROM seltablist */ + 257, /* (107) stl_prefix ::= seltablist joinop */ + 257, /* (108) stl_prefix ::= */ + 256, /* (109) seltablist ::= stl_prefix nm dbnm as on_using */ + 256, /* (110) seltablist ::= stl_prefix nm dbnm as indexed_by on_using */ + 256, /* (111) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */ + 256, /* (112) seltablist ::= stl_prefix LP select RP as on_using */ + 256, /* (113) seltablist ::= stl_prefix LP seltablist RP as on_using */ + 200, /* (114) dbnm ::= */ + 200, /* (115) dbnm ::= DOT nm */ + 238, /* (116) fullname ::= nm */ + 238, /* (117) fullname ::= nm DOT nm */ + 262, /* (118) xfullname ::= nm */ + 262, /* (119) xfullname ::= nm DOT nm */ + 262, /* (120) xfullname ::= nm DOT nm AS nm */ + 262, /* (121) xfullname ::= nm AS nm */ + 258, /* (122) joinop ::= COMMA|JOIN */ + 258, /* (123) joinop ::= JOIN_KW JOIN */ + 258, /* (124) joinop ::= JOIN_KW nm JOIN */ + 258, /* (125) joinop ::= JOIN_KW nm nm JOIN */ + 259, /* (126) on_using ::= ON expr */ + 259, /* (127) on_using ::= USING LP idlist RP */ + 259, /* (128) on_using ::= */ + 264, /* (129) indexed_opt ::= */ + 260, /* (130) indexed_by ::= INDEXED BY nm */ + 260, /* (131) indexed_by ::= NOT INDEXED */ + 249, /* (132) orderby_opt ::= */ + 249, /* (133) orderby_opt ::= ORDER BY sortlist */ + 231, /* (134) sortlist ::= sortlist COMMA expr sortorder nulls */ + 231, /* (135) sortlist ::= expr sortorder nulls */ + 219, /* (136) sortorder ::= ASC */ + 219, /* (137) sortorder ::= DESC */ + 219, /* (138) sortorder ::= */ + 265, /* (139) nulls ::= NULLS FIRST */ + 265, /* (140) nulls ::= NULLS LAST */ + 265, /* (141) nulls ::= */ + 247, /* (142) groupby_opt ::= */ + 247, /* (143) groupby_opt ::= GROUP BY nexprlist */ + 248, /* (144) having_opt ::= */ + 248, /* (145) having_opt ::= HAVING expr */ + 250, /* (146) limit_opt ::= */ + 250, /* (147) limit_opt ::= LIMIT expr */ + 250, /* (148) limit_opt ::= LIMIT expr OFFSET expr */ + 250, /* (149) limit_opt ::= LIMIT expr COMMA expr */ + 190, /* (150) cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */ + 246, /* (151) where_opt ::= */ + 246, /* (152) where_opt ::= WHERE expr */ + 267, /* (153) where_opt_ret ::= */ + 267, /* (154) where_opt_ret ::= WHERE expr */ + 267, /* (155) where_opt_ret ::= RETURNING selcollist */ + 267, /* (156) where_opt_ret ::= WHERE expr RETURNING selcollist */ + 190, /* (157) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */ + 268, /* (158) setlist ::= setlist COMMA nm EQ expr */ + 268, /* (159) setlist ::= setlist COMMA LP idlist RP EQ expr */ + 268, /* (160) setlist ::= nm EQ expr */ + 268, /* (161) setlist ::= LP idlist RP EQ expr */ + 190, /* (162) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */ + 190, /* (163) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */ + 271, /* (164) upsert ::= */ + 271, /* (165) upsert ::= RETURNING selcollist */ + 271, /* (166) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */ + 271, /* (167) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */ + 271, /* (168) upsert ::= ON CONFLICT DO NOTHING returning */ + 271, /* (169) upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */ + 272, /* (170) returning ::= RETURNING selcollist */ + 269, /* (171) insert_cmd ::= INSERT orconf */ + 269, /* (172) insert_cmd ::= REPLACE */ + 270, /* (173) idlist_opt ::= */ + 270, /* (174) idlist_opt ::= LP idlist RP */ 263, /* (175) idlist ::= idlist COMMA nm */ 263, /* (176) idlist ::= nm */ - 216, /* (177) expr ::= LP expr RP */ - 216, /* (178) expr ::= ID|INDEXED */ - 216, /* (179) expr ::= JOIN_KW */ - 216, /* (180) expr ::= nm DOT nm */ - 216, /* (181) expr ::= nm DOT nm DOT nm */ - 215, /* (182) term ::= NULL|FLOAT|BLOB */ - 215, /* (183) term ::= STRING */ - 215, /* (184) term ::= INTEGER */ - 216, /* (185) expr ::= VARIABLE */ - 216, /* (186) expr ::= expr COLLATE ID|STRING */ - 216, /* (187) expr ::= CAST LP expr AS typetoken RP */ - 216, /* (188) expr ::= ID|INDEXED LP distinct exprlist RP */ - 216, /* (189) expr ::= ID|INDEXED LP STAR RP */ - 216, /* (190) expr ::= ID|INDEXED LP distinct exprlist RP filter_over */ - 216, /* (191) expr ::= ID|INDEXED LP STAR RP filter_over */ - 215, /* (192) term ::= CTIME_KW */ - 216, /* (193) expr ::= LP nexprlist COMMA expr RP */ - 216, /* (194) expr ::= expr AND expr */ - 216, /* (195) expr ::= expr OR expr */ - 216, /* (196) expr ::= expr LT|GT|GE|LE expr */ - 216, /* (197) expr ::= expr EQ|NE expr */ - 216, /* (198) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ - 216, /* (199) expr ::= expr PLUS|MINUS expr */ - 216, /* (200) expr ::= expr STAR|SLASH|REM expr */ - 216, /* (201) expr ::= expr CONCAT expr */ - 273, /* (202) likeop ::= NOT LIKE_KW|MATCH */ - 216, /* (203) expr ::= expr likeop expr */ - 216, /* (204) expr ::= expr likeop expr ESCAPE expr */ - 216, /* (205) expr ::= expr ISNULL|NOTNULL */ - 216, /* (206) expr ::= expr NOT NULL */ - 216, /* (207) expr ::= expr IS expr */ - 216, /* (208) expr ::= expr IS NOT expr */ - 216, /* (209) expr ::= NOT expr */ - 216, /* (210) expr ::= BITNOT expr */ - 216, /* (211) expr ::= PLUS|MINUS expr */ - 274, /* (212) between_op ::= BETWEEN */ - 274, /* (213) between_op ::= NOT BETWEEN */ - 216, /* (214) expr ::= expr between_op expr AND expr */ - 275, /* (215) in_op ::= IN */ - 275, /* (216) in_op ::= NOT IN */ - 216, /* (217) expr ::= expr in_op LP exprlist RP */ - 216, /* (218) expr ::= LP select RP */ - 216, /* (219) expr ::= expr in_op LP select RP */ - 216, /* (220) expr ::= expr in_op nm dbnm paren_exprlist */ - 216, /* (221) expr ::= EXISTS LP select RP */ - 216, /* (222) expr ::= CASE case_operand case_exprlist case_else END */ - 278, /* (223) case_exprlist ::= case_exprlist WHEN expr THEN expr */ - 278, /* (224) case_exprlist ::= WHEN expr THEN expr */ - 279, /* (225) case_else ::= ELSE expr */ - 279, /* (226) case_else ::= */ - 277, /* (227) case_operand ::= expr */ - 277, /* (228) case_operand ::= */ - 261, /* (229) exprlist ::= */ - 252, /* (230) nexprlist ::= nexprlist COMMA expr */ - 252, /* (231) nexprlist ::= expr */ - 276, /* (232) paren_exprlist ::= */ - 276, /* (233) paren_exprlist ::= LP exprlist RP */ - 189, /* (234) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ - 280, /* (235) uniqueflag ::= UNIQUE */ - 280, /* (236) uniqueflag ::= */ - 220, /* (237) eidlist_opt ::= */ - 220, /* (238) eidlist_opt ::= LP eidlist RP */ - 231, /* (239) eidlist ::= eidlist COMMA nm collate sortorder */ - 231, /* (240) eidlist ::= nm collate sortorder */ - 281, /* (241) collate ::= */ - 281, /* (242) collate ::= COLLATE ID|STRING */ - 189, /* (243) cmd ::= DROP INDEX ifexists fullname */ - 189, /* (244) cmd ::= VACUUM vinto */ - 189, /* (245) cmd ::= VACUUM nm vinto */ - 282, /* (246) vinto ::= INTO expr */ - 282, /* (247) vinto ::= */ - 189, /* (248) cmd ::= PRAGMA nm dbnm */ - 189, /* (249) cmd ::= PRAGMA nm dbnm EQ nmnum */ - 189, /* (250) cmd ::= PRAGMA nm dbnm LP nmnum RP */ - 189, /* (251) cmd ::= PRAGMA nm dbnm EQ minus_num */ - 189, /* (252) cmd ::= PRAGMA nm dbnm LP minus_num RP */ - 210, /* (253) plus_num ::= PLUS INTEGER|FLOAT */ - 211, /* (254) minus_num ::= MINUS INTEGER|FLOAT */ - 189, /* (255) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ - 284, /* (256) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ - 286, /* (257) trigger_time ::= BEFORE|AFTER */ - 286, /* (258) trigger_time ::= INSTEAD OF */ - 286, /* (259) trigger_time ::= */ - 287, /* (260) trigger_event ::= DELETE|INSERT */ - 287, /* (261) trigger_event ::= UPDATE */ - 287, /* (262) trigger_event ::= UPDATE OF idlist */ - 289, /* (263) when_clause ::= */ - 289, /* (264) when_clause ::= WHEN expr */ - 285, /* (265) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ - 285, /* (266) trigger_cmd_list ::= trigger_cmd SEMI */ - 291, /* (267) trnm ::= nm DOT nm */ - 292, /* (268) tridxby ::= INDEXED BY nm */ - 292, /* (269) tridxby ::= NOT INDEXED */ - 290, /* (270) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */ - 290, /* (271) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ - 290, /* (272) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ - 290, /* (273) trigger_cmd ::= scanpt select scanpt */ - 216, /* (274) expr ::= RAISE LP IGNORE RP */ - 216, /* (275) expr ::= RAISE LP raisetype COMMA nm RP */ - 235, /* (276) raisetype ::= ROLLBACK */ - 235, /* (277) raisetype ::= ABORT */ - 235, /* (278) raisetype ::= FAIL */ - 189, /* (279) cmd ::= DROP TRIGGER ifexists fullname */ - 189, /* (280) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ - 189, /* (281) cmd ::= DETACH database_kw_opt expr */ - 294, /* (282) key_opt ::= */ - 294, /* (283) key_opt ::= KEY expr */ - 189, /* (284) cmd ::= REINDEX */ - 189, /* (285) cmd ::= REINDEX nm dbnm */ - 189, /* (286) cmd ::= ANALYZE */ - 189, /* (287) cmd ::= ANALYZE nm dbnm */ - 189, /* (288) cmd ::= ALTER TABLE fullname RENAME TO nm */ - 189, /* (289) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ - 189, /* (290) cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */ - 295, /* (291) add_column_fullname ::= fullname */ - 189, /* (292) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ - 189, /* (293) cmd ::= create_vtab */ - 189, /* (294) cmd ::= create_vtab LP vtabarglist RP */ - 297, /* (295) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ - 299, /* (296) vtabarg ::= */ - 300, /* (297) vtabargtoken ::= ANY */ - 300, /* (298) vtabargtoken ::= lp anylist RP */ - 301, /* (299) lp ::= LP */ - 265, /* (300) with ::= WITH wqlist */ - 265, /* (301) with ::= WITH RECURSIVE wqlist */ - 304, /* (302) wqas ::= AS */ - 304, /* (303) wqas ::= AS MATERIALIZED */ - 304, /* (304) wqas ::= AS NOT MATERIALIZED */ - 303, /* (305) wqitem ::= nm eidlist_opt wqas LP select RP */ - 240, /* (306) wqlist ::= wqitem */ - 240, /* (307) wqlist ::= wqlist COMMA wqitem */ - 305, /* (308) windowdefn_list ::= windowdefn */ - 305, /* (309) windowdefn_list ::= windowdefn_list COMMA windowdefn */ - 306, /* (310) windowdefn ::= nm AS LP window RP */ - 307, /* (311) window ::= PARTITION BY nexprlist orderby_opt frame_opt */ - 307, /* (312) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ - 307, /* (313) window ::= ORDER BY sortlist frame_opt */ - 307, /* (314) window ::= nm ORDER BY sortlist frame_opt */ - 307, /* (315) window ::= frame_opt */ - 307, /* (316) window ::= nm frame_opt */ - 308, /* (317) frame_opt ::= */ - 308, /* (318) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ - 308, /* (319) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ - 312, /* (320) range_or_rows ::= RANGE|ROWS|GROUPS */ - 314, /* (321) frame_bound_s ::= frame_bound */ - 314, /* (322) frame_bound_s ::= UNBOUNDED PRECEDING */ - 315, /* (323) frame_bound_e ::= frame_bound */ - 315, /* (324) frame_bound_e ::= UNBOUNDED FOLLOWING */ - 313, /* (325) frame_bound ::= expr PRECEDING|FOLLOWING */ - 313, /* (326) frame_bound ::= CURRENT ROW */ - 316, /* (327) frame_exclude_opt ::= */ - 316, /* (328) frame_exclude_opt ::= EXCLUDE frame_exclude */ - 317, /* (329) frame_exclude ::= NO OTHERS */ - 317, /* (330) frame_exclude ::= CURRENT ROW */ - 317, /* (331) frame_exclude ::= GROUP|TIES */ - 250, /* (332) window_clause ::= WINDOW windowdefn_list */ - 272, /* (333) filter_over ::= filter_clause over_clause */ - 272, /* (334) filter_over ::= over_clause */ - 272, /* (335) filter_over ::= filter_clause */ - 311, /* (336) over_clause ::= OVER LP window RP */ - 311, /* (337) over_clause ::= OVER nm */ - 310, /* (338) filter_clause ::= FILTER LP WHERE expr RP */ - 184, /* (339) input ::= cmdlist */ - 185, /* (340) cmdlist ::= cmdlist ecmd */ - 185, /* (341) cmdlist ::= ecmd */ - 186, /* (342) ecmd ::= SEMI */ - 186, /* (343) ecmd ::= cmdx SEMI */ - 186, /* (344) ecmd ::= explain cmdx SEMI */ - 191, /* (345) trans_opt ::= */ - 191, /* (346) trans_opt ::= TRANSACTION */ - 191, /* (347) trans_opt ::= TRANSACTION nm */ - 193, /* (348) savepoint_opt ::= SAVEPOINT */ - 193, /* (349) savepoint_opt ::= */ - 189, /* (350) cmd ::= create_table create_table_args */ - 202, /* (351) table_option_set ::= table_option */ - 200, /* (352) columnlist ::= columnlist COMMA columnname carglist */ - 200, /* (353) columnlist ::= columnname carglist */ - 192, /* (354) nm ::= ID|INDEXED */ - 192, /* (355) nm ::= STRING */ - 192, /* (356) nm ::= JOIN_KW */ - 207, /* (357) typetoken ::= typename */ - 208, /* (358) typename ::= ID|STRING */ - 209, /* (359) signed ::= plus_num */ - 209, /* (360) signed ::= minus_num */ - 206, /* (361) carglist ::= carglist ccons */ - 206, /* (362) carglist ::= */ - 214, /* (363) ccons ::= NULL onconf */ - 214, /* (364) ccons ::= GENERATED ALWAYS AS generated */ - 214, /* (365) ccons ::= AS generated */ - 201, /* (366) conslist_opt ::= COMMA conslist */ - 227, /* (367) conslist ::= conslist tconscomma tcons */ - 227, /* (368) conslist ::= tcons */ - 228, /* (369) tconscomma ::= */ - 232, /* (370) defer_subclause_opt ::= defer_subclause */ - 234, /* (371) resolvetype ::= raisetype */ - 238, /* (372) selectnowith ::= oneselect */ - 239, /* (373) oneselect ::= values */ - 253, /* (374) sclp ::= selcollist COMMA */ - 254, /* (375) as ::= ID|STRING */ - 271, /* (376) returning ::= */ - 216, /* (377) expr ::= term */ - 273, /* (378) likeop ::= LIKE_KW|MATCH */ - 261, /* (379) exprlist ::= nexprlist */ - 283, /* (380) nmnum ::= plus_num */ - 283, /* (381) nmnum ::= nm */ - 283, /* (382) nmnum ::= ON */ - 283, /* (383) nmnum ::= DELETE */ - 283, /* (384) nmnum ::= DEFAULT */ - 210, /* (385) plus_num ::= INTEGER|FLOAT */ - 288, /* (386) foreach_clause ::= */ - 288, /* (387) foreach_clause ::= FOR EACH ROW */ - 291, /* (388) trnm ::= nm */ - 292, /* (389) tridxby ::= */ - 293, /* (390) database_kw_opt ::= DATABASE */ - 293, /* (391) database_kw_opt ::= */ - 296, /* (392) kwcolumn_opt ::= */ - 296, /* (393) kwcolumn_opt ::= COLUMNKW */ - 298, /* (394) vtabarglist ::= vtabarg */ - 298, /* (395) vtabarglist ::= vtabarglist COMMA vtabarg */ - 299, /* (396) vtabarg ::= vtabarg vtabargtoken */ - 302, /* (397) anylist ::= */ - 302, /* (398) anylist ::= anylist LP anylist RP */ - 302, /* (399) anylist ::= anylist ANY */ - 265, /* (400) with ::= */ + 217, /* (177) expr ::= LP expr RP */ + 217, /* (178) expr ::= ID|INDEXED */ + 217, /* (179) expr ::= JOIN_KW */ + 217, /* (180) expr ::= nm DOT nm */ + 217, /* (181) expr ::= nm DOT nm DOT nm */ + 216, /* (182) term ::= NULL|FLOAT|BLOB */ + 216, /* (183) term ::= STRING */ + 216, /* (184) term ::= INTEGER */ + 217, /* (185) expr ::= VARIABLE */ + 217, /* (186) expr ::= expr COLLATE ID|STRING */ + 217, /* (187) expr ::= CAST LP expr AS typetoken RP */ + 217, /* (188) expr ::= ID|INDEXED LP distinct exprlist RP */ + 217, /* (189) expr ::= ID|INDEXED LP STAR RP */ + 217, /* (190) expr ::= ID|INDEXED LP distinct exprlist RP filter_over */ + 217, /* (191) expr ::= ID|INDEXED LP STAR RP filter_over */ + 216, /* (192) term ::= CTIME_KW */ + 217, /* (193) expr ::= LP nexprlist COMMA expr RP */ + 217, /* (194) expr ::= expr AND expr */ + 217, /* (195) expr ::= expr OR expr */ + 217, /* (196) expr ::= expr LT|GT|GE|LE expr */ + 217, /* (197) expr ::= expr EQ|NE expr */ + 217, /* (198) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ + 217, /* (199) expr ::= expr PLUS|MINUS expr */ + 217, /* (200) expr ::= expr STAR|SLASH|REM expr */ + 217, /* (201) expr ::= expr CONCAT expr */ + 274, /* (202) likeop ::= NOT LIKE_KW|MATCH */ + 217, /* (203) expr ::= expr likeop expr */ + 217, /* (204) expr ::= expr likeop expr ESCAPE expr */ + 217, /* (205) expr ::= expr ISNULL|NOTNULL */ + 217, /* (206) expr ::= expr NOT NULL */ + 217, /* (207) expr ::= expr IS expr */ + 217, /* (208) expr ::= expr IS NOT expr */ + 217, /* (209) expr ::= expr IS NOT DISTINCT FROM expr */ + 217, /* (210) expr ::= expr IS DISTINCT FROM expr */ + 217, /* (211) expr ::= NOT expr */ + 217, /* (212) expr ::= BITNOT expr */ + 217, /* (213) expr ::= PLUS|MINUS expr */ + 217, /* (214) expr ::= expr PTR expr */ + 275, /* (215) between_op ::= BETWEEN */ + 275, /* (216) between_op ::= NOT BETWEEN */ + 217, /* (217) expr ::= expr between_op expr AND expr */ + 276, /* (218) in_op ::= IN */ + 276, /* (219) in_op ::= NOT IN */ + 217, /* (220) expr ::= expr in_op LP exprlist RP */ + 217, /* (221) expr ::= LP select RP */ + 217, /* (222) expr ::= expr in_op LP select RP */ + 217, /* (223) expr ::= expr in_op nm dbnm paren_exprlist */ + 217, /* (224) expr ::= EXISTS LP select RP */ + 217, /* (225) expr ::= CASE case_operand case_exprlist case_else END */ + 279, /* (226) case_exprlist ::= case_exprlist WHEN expr THEN expr */ + 279, /* (227) case_exprlist ::= WHEN expr THEN expr */ + 280, /* (228) case_else ::= ELSE expr */ + 280, /* (229) case_else ::= */ + 278, /* (230) case_operand ::= expr */ + 278, /* (231) case_operand ::= */ + 261, /* (232) exprlist ::= */ + 253, /* (233) nexprlist ::= nexprlist COMMA expr */ + 253, /* (234) nexprlist ::= expr */ + 277, /* (235) paren_exprlist ::= */ + 277, /* (236) paren_exprlist ::= LP exprlist RP */ + 190, /* (237) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ + 281, /* (238) uniqueflag ::= UNIQUE */ + 281, /* (239) uniqueflag ::= */ + 221, /* (240) eidlist_opt ::= */ + 221, /* (241) eidlist_opt ::= LP eidlist RP */ + 232, /* (242) eidlist ::= eidlist COMMA nm collate sortorder */ + 232, /* (243) eidlist ::= nm collate sortorder */ + 282, /* (244) collate ::= */ + 282, /* (245) collate ::= COLLATE ID|STRING */ + 190, /* (246) cmd ::= DROP INDEX ifexists fullname */ + 190, /* (247) cmd ::= VACUUM vinto */ + 190, /* (248) cmd ::= VACUUM nm vinto */ + 283, /* (249) vinto ::= INTO expr */ + 283, /* (250) vinto ::= */ + 190, /* (251) cmd ::= PRAGMA nm dbnm */ + 190, /* (252) cmd ::= PRAGMA nm dbnm EQ nmnum */ + 190, /* (253) cmd ::= PRAGMA nm dbnm LP nmnum RP */ + 190, /* (254) cmd ::= PRAGMA nm dbnm EQ minus_num */ + 190, /* (255) cmd ::= PRAGMA nm dbnm LP minus_num RP */ + 211, /* (256) plus_num ::= PLUS INTEGER|FLOAT */ + 212, /* (257) minus_num ::= MINUS INTEGER|FLOAT */ + 190, /* (258) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ + 285, /* (259) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ + 287, /* (260) trigger_time ::= BEFORE|AFTER */ + 287, /* (261) trigger_time ::= INSTEAD OF */ + 287, /* (262) trigger_time ::= */ + 288, /* (263) trigger_event ::= DELETE|INSERT */ + 288, /* (264) trigger_event ::= UPDATE */ + 288, /* (265) trigger_event ::= UPDATE OF idlist */ + 290, /* (266) when_clause ::= */ + 290, /* (267) when_clause ::= WHEN expr */ + 286, /* (268) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ + 286, /* (269) trigger_cmd_list ::= trigger_cmd SEMI */ + 292, /* (270) trnm ::= nm DOT nm */ + 293, /* (271) tridxby ::= INDEXED BY nm */ + 293, /* (272) tridxby ::= NOT INDEXED */ + 291, /* (273) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */ + 291, /* (274) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ + 291, /* (275) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ + 291, /* (276) trigger_cmd ::= scanpt select scanpt */ + 217, /* (277) expr ::= RAISE LP IGNORE RP */ + 217, /* (278) expr ::= RAISE LP raisetype COMMA nm RP */ + 236, /* (279) raisetype ::= ROLLBACK */ + 236, /* (280) raisetype ::= ABORT */ + 236, /* (281) raisetype ::= FAIL */ + 190, /* (282) cmd ::= DROP TRIGGER ifexists fullname */ + 190, /* (283) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ + 190, /* (284) cmd ::= DETACH database_kw_opt expr */ + 295, /* (285) key_opt ::= */ + 295, /* (286) key_opt ::= KEY expr */ + 190, /* (287) cmd ::= REINDEX */ + 190, /* (288) cmd ::= REINDEX nm dbnm */ + 190, /* (289) cmd ::= ANALYZE */ + 190, /* (290) cmd ::= ANALYZE nm dbnm */ + 190, /* (291) cmd ::= ALTER TABLE fullname RENAME TO nm */ + 190, /* (292) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ + 190, /* (293) cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */ + 296, /* (294) add_column_fullname ::= fullname */ + 190, /* (295) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ + 190, /* (296) cmd ::= create_vtab */ + 190, /* (297) cmd ::= create_vtab LP vtabarglist RP */ + 298, /* (298) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ + 300, /* (299) vtabarg ::= */ + 301, /* (300) vtabargtoken ::= ANY */ + 301, /* (301) vtabargtoken ::= lp anylist RP */ + 302, /* (302) lp ::= LP */ + 266, /* (303) with ::= WITH wqlist */ + 266, /* (304) with ::= WITH RECURSIVE wqlist */ + 305, /* (305) wqas ::= AS */ + 305, /* (306) wqas ::= AS MATERIALIZED */ + 305, /* (307) wqas ::= AS NOT MATERIALIZED */ + 304, /* (308) wqitem ::= nm eidlist_opt wqas LP select RP */ + 241, /* (309) wqlist ::= wqitem */ + 241, /* (310) wqlist ::= wqlist COMMA wqitem */ + 306, /* (311) windowdefn_list ::= windowdefn */ + 306, /* (312) windowdefn_list ::= windowdefn_list COMMA windowdefn */ + 307, /* (313) windowdefn ::= nm AS LP window RP */ + 308, /* (314) window ::= PARTITION BY nexprlist orderby_opt frame_opt */ + 308, /* (315) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ + 308, /* (316) window ::= ORDER BY sortlist frame_opt */ + 308, /* (317) window ::= nm ORDER BY sortlist frame_opt */ + 308, /* (318) window ::= frame_opt */ + 308, /* (319) window ::= nm frame_opt */ + 309, /* (320) frame_opt ::= */ + 309, /* (321) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ + 309, /* (322) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ + 313, /* (323) range_or_rows ::= RANGE|ROWS|GROUPS */ + 315, /* (324) frame_bound_s ::= frame_bound */ + 315, /* (325) frame_bound_s ::= UNBOUNDED PRECEDING */ + 316, /* (326) frame_bound_e ::= frame_bound */ + 316, /* (327) frame_bound_e ::= UNBOUNDED FOLLOWING */ + 314, /* (328) frame_bound ::= expr PRECEDING|FOLLOWING */ + 314, /* (329) frame_bound ::= CURRENT ROW */ + 317, /* (330) frame_exclude_opt ::= */ + 317, /* (331) frame_exclude_opt ::= EXCLUDE frame_exclude */ + 318, /* (332) frame_exclude ::= NO OTHERS */ + 318, /* (333) frame_exclude ::= CURRENT ROW */ + 318, /* (334) frame_exclude ::= GROUP|TIES */ + 251, /* (335) window_clause ::= WINDOW windowdefn_list */ + 273, /* (336) filter_over ::= filter_clause over_clause */ + 273, /* (337) filter_over ::= over_clause */ + 273, /* (338) filter_over ::= filter_clause */ + 312, /* (339) over_clause ::= OVER LP window RP */ + 312, /* (340) over_clause ::= OVER nm */ + 311, /* (341) filter_clause ::= FILTER LP WHERE expr RP */ + 185, /* (342) input ::= cmdlist */ + 186, /* (343) cmdlist ::= cmdlist ecmd */ + 186, /* (344) cmdlist ::= ecmd */ + 187, /* (345) ecmd ::= SEMI */ + 187, /* (346) ecmd ::= cmdx SEMI */ + 187, /* (347) ecmd ::= explain cmdx SEMI */ + 192, /* (348) trans_opt ::= */ + 192, /* (349) trans_opt ::= TRANSACTION */ + 192, /* (350) trans_opt ::= TRANSACTION nm */ + 194, /* (351) savepoint_opt ::= SAVEPOINT */ + 194, /* (352) savepoint_opt ::= */ + 190, /* (353) cmd ::= create_table create_table_args */ + 203, /* (354) table_option_set ::= table_option */ + 201, /* (355) columnlist ::= columnlist COMMA columnname carglist */ + 201, /* (356) columnlist ::= columnname carglist */ + 193, /* (357) nm ::= ID|INDEXED */ + 193, /* (358) nm ::= STRING */ + 193, /* (359) nm ::= JOIN_KW */ + 208, /* (360) typetoken ::= typename */ + 209, /* (361) typename ::= ID|STRING */ + 210, /* (362) signed ::= plus_num */ + 210, /* (363) signed ::= minus_num */ + 207, /* (364) carglist ::= carglist ccons */ + 207, /* (365) carglist ::= */ + 215, /* (366) ccons ::= NULL onconf */ + 215, /* (367) ccons ::= GENERATED ALWAYS AS generated */ + 215, /* (368) ccons ::= AS generated */ + 202, /* (369) conslist_opt ::= COMMA conslist */ + 228, /* (370) conslist ::= conslist tconscomma tcons */ + 228, /* (371) conslist ::= tcons */ + 229, /* (372) tconscomma ::= */ + 233, /* (373) defer_subclause_opt ::= defer_subclause */ + 235, /* (374) resolvetype ::= raisetype */ + 239, /* (375) selectnowith ::= oneselect */ + 240, /* (376) oneselect ::= values */ + 254, /* (377) sclp ::= selcollist COMMA */ + 255, /* (378) as ::= ID|STRING */ + 264, /* (379) indexed_opt ::= indexed_by */ + 272, /* (380) returning ::= */ + 217, /* (381) expr ::= term */ + 274, /* (382) likeop ::= LIKE_KW|MATCH */ + 261, /* (383) exprlist ::= nexprlist */ + 284, /* (384) nmnum ::= plus_num */ + 284, /* (385) nmnum ::= nm */ + 284, /* (386) nmnum ::= ON */ + 284, /* (387) nmnum ::= DELETE */ + 284, /* (388) nmnum ::= DEFAULT */ + 211, /* (389) plus_num ::= INTEGER|FLOAT */ + 289, /* (390) foreach_clause ::= */ + 289, /* (391) foreach_clause ::= FOR EACH ROW */ + 292, /* (392) trnm ::= nm */ + 293, /* (393) tridxby ::= */ + 294, /* (394) database_kw_opt ::= DATABASE */ + 294, /* (395) database_kw_opt ::= */ + 297, /* (396) kwcolumn_opt ::= */ + 297, /* (397) kwcolumn_opt ::= COLUMNKW */ + 299, /* (398) vtabarglist ::= vtabarg */ + 299, /* (399) vtabarglist ::= vtabarglist COMMA vtabarg */ + 300, /* (400) vtabarg ::= vtabarg vtabargtoken */ + 303, /* (401) anylist ::= */ + 303, /* (402) anylist ::= anylist LP anylist RP */ + 303, /* (403) anylist ::= anylist ANY */ + 266, /* (404) with ::= */ }; /* For rule J, yyRuleInfoNRhs[J] contains the negative of the number @@ -162660,29 +166770,29 @@ static const signed char yyRuleInfoNRhs[] = { -2, /* (106) from ::= FROM seltablist */ -2, /* (107) stl_prefix ::= seltablist joinop */ 0, /* (108) stl_prefix ::= */ - -7, /* (109) seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */ - -9, /* (110) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */ - -7, /* (111) seltablist ::= stl_prefix LP select RP as on_opt using_opt */ - -7, /* (112) seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ - 0, /* (113) dbnm ::= */ - -2, /* (114) dbnm ::= DOT nm */ - -1, /* (115) fullname ::= nm */ - -3, /* (116) fullname ::= nm DOT nm */ - -1, /* (117) xfullname ::= nm */ - -3, /* (118) xfullname ::= nm DOT nm */ - -5, /* (119) xfullname ::= nm DOT nm AS nm */ - -3, /* (120) xfullname ::= nm AS nm */ - -1, /* (121) joinop ::= COMMA|JOIN */ - -2, /* (122) joinop ::= JOIN_KW JOIN */ - -3, /* (123) joinop ::= JOIN_KW nm JOIN */ - -4, /* (124) joinop ::= JOIN_KW nm nm JOIN */ - -2, /* (125) on_opt ::= ON expr */ - 0, /* (126) on_opt ::= */ - 0, /* (127) indexed_opt ::= */ - -3, /* (128) indexed_opt ::= INDEXED BY nm */ - -2, /* (129) indexed_opt ::= NOT INDEXED */ - -4, /* (130) using_opt ::= USING LP idlist RP */ - 0, /* (131) using_opt ::= */ + -5, /* (109) seltablist ::= stl_prefix nm dbnm as on_using */ + -6, /* (110) seltablist ::= stl_prefix nm dbnm as indexed_by on_using */ + -8, /* (111) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */ + -6, /* (112) seltablist ::= stl_prefix LP select RP as on_using */ + -6, /* (113) seltablist ::= stl_prefix LP seltablist RP as on_using */ + 0, /* (114) dbnm ::= */ + -2, /* (115) dbnm ::= DOT nm */ + -1, /* (116) fullname ::= nm */ + -3, /* (117) fullname ::= nm DOT nm */ + -1, /* (118) xfullname ::= nm */ + -3, /* (119) xfullname ::= nm DOT nm */ + -5, /* (120) xfullname ::= nm DOT nm AS nm */ + -3, /* (121) xfullname ::= nm AS nm */ + -1, /* (122) joinop ::= COMMA|JOIN */ + -2, /* (123) joinop ::= JOIN_KW JOIN */ + -3, /* (124) joinop ::= JOIN_KW nm JOIN */ + -4, /* (125) joinop ::= JOIN_KW nm nm JOIN */ + -2, /* (126) on_using ::= ON expr */ + -4, /* (127) on_using ::= USING LP idlist RP */ + 0, /* (128) on_using ::= */ + 0, /* (129) indexed_opt ::= */ + -3, /* (130) indexed_by ::= INDEXED BY nm */ + -2, /* (131) indexed_by ::= NOT INDEXED */ 0, /* (132) orderby_opt ::= */ -3, /* (133) orderby_opt ::= ORDER BY sortlist */ -5, /* (134) sortlist ::= sortlist COMMA expr sortorder nulls */ @@ -162760,198 +166870,202 @@ static const signed char yyRuleInfoNRhs[] = { -3, /* (206) expr ::= expr NOT NULL */ -3, /* (207) expr ::= expr IS expr */ -4, /* (208) expr ::= expr IS NOT expr */ - -2, /* (209) expr ::= NOT expr */ - -2, /* (210) expr ::= BITNOT expr */ - -2, /* (211) expr ::= PLUS|MINUS expr */ - -1, /* (212) between_op ::= BETWEEN */ - -2, /* (213) between_op ::= NOT BETWEEN */ - -5, /* (214) expr ::= expr between_op expr AND expr */ - -1, /* (215) in_op ::= IN */ - -2, /* (216) in_op ::= NOT IN */ - -5, /* (217) expr ::= expr in_op LP exprlist RP */ - -3, /* (218) expr ::= LP select RP */ - -5, /* (219) expr ::= expr in_op LP select RP */ - -5, /* (220) expr ::= expr in_op nm dbnm paren_exprlist */ - -4, /* (221) expr ::= EXISTS LP select RP */ - -5, /* (222) expr ::= CASE case_operand case_exprlist case_else END */ - -5, /* (223) case_exprlist ::= case_exprlist WHEN expr THEN expr */ - -4, /* (224) case_exprlist ::= WHEN expr THEN expr */ - -2, /* (225) case_else ::= ELSE expr */ - 0, /* (226) case_else ::= */ - -1, /* (227) case_operand ::= expr */ - 0, /* (228) case_operand ::= */ - 0, /* (229) exprlist ::= */ - -3, /* (230) nexprlist ::= nexprlist COMMA expr */ - -1, /* (231) nexprlist ::= expr */ - 0, /* (232) paren_exprlist ::= */ - -3, /* (233) paren_exprlist ::= LP exprlist RP */ - -12, /* (234) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ - -1, /* (235) uniqueflag ::= UNIQUE */ - 0, /* (236) uniqueflag ::= */ - 0, /* (237) eidlist_opt ::= */ - -3, /* (238) eidlist_opt ::= LP eidlist RP */ - -5, /* (239) eidlist ::= eidlist COMMA nm collate sortorder */ - -3, /* (240) eidlist ::= nm collate sortorder */ - 0, /* (241) collate ::= */ - -2, /* (242) collate ::= COLLATE ID|STRING */ - -4, /* (243) cmd ::= DROP INDEX ifexists fullname */ - -2, /* (244) cmd ::= VACUUM vinto */ - -3, /* (245) cmd ::= VACUUM nm vinto */ - -2, /* (246) vinto ::= INTO expr */ - 0, /* (247) vinto ::= */ - -3, /* (248) cmd ::= PRAGMA nm dbnm */ - -5, /* (249) cmd ::= PRAGMA nm dbnm EQ nmnum */ - -6, /* (250) cmd ::= PRAGMA nm dbnm LP nmnum RP */ - -5, /* (251) cmd ::= PRAGMA nm dbnm EQ minus_num */ - -6, /* (252) cmd ::= PRAGMA nm dbnm LP minus_num RP */ - -2, /* (253) plus_num ::= PLUS INTEGER|FLOAT */ - -2, /* (254) minus_num ::= MINUS INTEGER|FLOAT */ - -5, /* (255) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ - -11, /* (256) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ - -1, /* (257) trigger_time ::= BEFORE|AFTER */ - -2, /* (258) trigger_time ::= INSTEAD OF */ - 0, /* (259) trigger_time ::= */ - -1, /* (260) trigger_event ::= DELETE|INSERT */ - -1, /* (261) trigger_event ::= UPDATE */ - -3, /* (262) trigger_event ::= UPDATE OF idlist */ - 0, /* (263) when_clause ::= */ - -2, /* (264) when_clause ::= WHEN expr */ - -3, /* (265) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ - -2, /* (266) trigger_cmd_list ::= trigger_cmd SEMI */ - -3, /* (267) trnm ::= nm DOT nm */ - -3, /* (268) tridxby ::= INDEXED BY nm */ - -2, /* (269) tridxby ::= NOT INDEXED */ - -9, /* (270) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */ - -8, /* (271) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ - -6, /* (272) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ - -3, /* (273) trigger_cmd ::= scanpt select scanpt */ - -4, /* (274) expr ::= RAISE LP IGNORE RP */ - -6, /* (275) expr ::= RAISE LP raisetype COMMA nm RP */ - -1, /* (276) raisetype ::= ROLLBACK */ - -1, /* (277) raisetype ::= ABORT */ - -1, /* (278) raisetype ::= FAIL */ - -4, /* (279) cmd ::= DROP TRIGGER ifexists fullname */ - -6, /* (280) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ - -3, /* (281) cmd ::= DETACH database_kw_opt expr */ - 0, /* (282) key_opt ::= */ - -2, /* (283) key_opt ::= KEY expr */ - -1, /* (284) cmd ::= REINDEX */ - -3, /* (285) cmd ::= REINDEX nm dbnm */ - -1, /* (286) cmd ::= ANALYZE */ - -3, /* (287) cmd ::= ANALYZE nm dbnm */ - -6, /* (288) cmd ::= ALTER TABLE fullname RENAME TO nm */ - -7, /* (289) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ - -6, /* (290) cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */ - -1, /* (291) add_column_fullname ::= fullname */ - -8, /* (292) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ - -1, /* (293) cmd ::= create_vtab */ - -4, /* (294) cmd ::= create_vtab LP vtabarglist RP */ - -8, /* (295) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ - 0, /* (296) vtabarg ::= */ - -1, /* (297) vtabargtoken ::= ANY */ - -3, /* (298) vtabargtoken ::= lp anylist RP */ - -1, /* (299) lp ::= LP */ - -2, /* (300) with ::= WITH wqlist */ - -3, /* (301) with ::= WITH RECURSIVE wqlist */ - -1, /* (302) wqas ::= AS */ - -2, /* (303) wqas ::= AS MATERIALIZED */ - -3, /* (304) wqas ::= AS NOT MATERIALIZED */ - -6, /* (305) wqitem ::= nm eidlist_opt wqas LP select RP */ - -1, /* (306) wqlist ::= wqitem */ - -3, /* (307) wqlist ::= wqlist COMMA wqitem */ - -1, /* (308) windowdefn_list ::= windowdefn */ - -3, /* (309) windowdefn_list ::= windowdefn_list COMMA windowdefn */ - -5, /* (310) windowdefn ::= nm AS LP window RP */ - -5, /* (311) window ::= PARTITION BY nexprlist orderby_opt frame_opt */ - -6, /* (312) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ - -4, /* (313) window ::= ORDER BY sortlist frame_opt */ - -5, /* (314) window ::= nm ORDER BY sortlist frame_opt */ - -1, /* (315) window ::= frame_opt */ - -2, /* (316) window ::= nm frame_opt */ - 0, /* (317) frame_opt ::= */ - -3, /* (318) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ - -6, /* (319) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ - -1, /* (320) range_or_rows ::= RANGE|ROWS|GROUPS */ - -1, /* (321) frame_bound_s ::= frame_bound */ - -2, /* (322) frame_bound_s ::= UNBOUNDED PRECEDING */ - -1, /* (323) frame_bound_e ::= frame_bound */ - -2, /* (324) frame_bound_e ::= UNBOUNDED FOLLOWING */ - -2, /* (325) frame_bound ::= expr PRECEDING|FOLLOWING */ - -2, /* (326) frame_bound ::= CURRENT ROW */ - 0, /* (327) frame_exclude_opt ::= */ - -2, /* (328) frame_exclude_opt ::= EXCLUDE frame_exclude */ - -2, /* (329) frame_exclude ::= NO OTHERS */ - -2, /* (330) frame_exclude ::= CURRENT ROW */ - -1, /* (331) frame_exclude ::= GROUP|TIES */ - -2, /* (332) window_clause ::= WINDOW windowdefn_list */ - -2, /* (333) filter_over ::= filter_clause over_clause */ - -1, /* (334) filter_over ::= over_clause */ - -1, /* (335) filter_over ::= filter_clause */ - -4, /* (336) over_clause ::= OVER LP window RP */ - -2, /* (337) over_clause ::= OVER nm */ - -5, /* (338) filter_clause ::= FILTER LP WHERE expr RP */ - -1, /* (339) input ::= cmdlist */ - -2, /* (340) cmdlist ::= cmdlist ecmd */ - -1, /* (341) cmdlist ::= ecmd */ - -1, /* (342) ecmd ::= SEMI */ - -2, /* (343) ecmd ::= cmdx SEMI */ - -3, /* (344) ecmd ::= explain cmdx SEMI */ - 0, /* (345) trans_opt ::= */ - -1, /* (346) trans_opt ::= TRANSACTION */ - -2, /* (347) trans_opt ::= TRANSACTION nm */ - -1, /* (348) savepoint_opt ::= SAVEPOINT */ - 0, /* (349) savepoint_opt ::= */ - -2, /* (350) cmd ::= create_table create_table_args */ - -1, /* (351) table_option_set ::= table_option */ - -4, /* (352) columnlist ::= columnlist COMMA columnname carglist */ - -2, /* (353) columnlist ::= columnname carglist */ - -1, /* (354) nm ::= ID|INDEXED */ - -1, /* (355) nm ::= STRING */ - -1, /* (356) nm ::= JOIN_KW */ - -1, /* (357) typetoken ::= typename */ - -1, /* (358) typename ::= ID|STRING */ - -1, /* (359) signed ::= plus_num */ - -1, /* (360) signed ::= minus_num */ - -2, /* (361) carglist ::= carglist ccons */ - 0, /* (362) carglist ::= */ - -2, /* (363) ccons ::= NULL onconf */ - -4, /* (364) ccons ::= GENERATED ALWAYS AS generated */ - -2, /* (365) ccons ::= AS generated */ - -2, /* (366) conslist_opt ::= COMMA conslist */ - -3, /* (367) conslist ::= conslist tconscomma tcons */ - -1, /* (368) conslist ::= tcons */ - 0, /* (369) tconscomma ::= */ - -1, /* (370) defer_subclause_opt ::= defer_subclause */ - -1, /* (371) resolvetype ::= raisetype */ - -1, /* (372) selectnowith ::= oneselect */ - -1, /* (373) oneselect ::= values */ - -2, /* (374) sclp ::= selcollist COMMA */ - -1, /* (375) as ::= ID|STRING */ - 0, /* (376) returning ::= */ - -1, /* (377) expr ::= term */ - -1, /* (378) likeop ::= LIKE_KW|MATCH */ - -1, /* (379) exprlist ::= nexprlist */ - -1, /* (380) nmnum ::= plus_num */ - -1, /* (381) nmnum ::= nm */ - -1, /* (382) nmnum ::= ON */ - -1, /* (383) nmnum ::= DELETE */ - -1, /* (384) nmnum ::= DEFAULT */ - -1, /* (385) plus_num ::= INTEGER|FLOAT */ - 0, /* (386) foreach_clause ::= */ - -3, /* (387) foreach_clause ::= FOR EACH ROW */ - -1, /* (388) trnm ::= nm */ - 0, /* (389) tridxby ::= */ - -1, /* (390) database_kw_opt ::= DATABASE */ - 0, /* (391) database_kw_opt ::= */ - 0, /* (392) kwcolumn_opt ::= */ - -1, /* (393) kwcolumn_opt ::= COLUMNKW */ - -1, /* (394) vtabarglist ::= vtabarg */ - -3, /* (395) vtabarglist ::= vtabarglist COMMA vtabarg */ - -2, /* (396) vtabarg ::= vtabarg vtabargtoken */ - 0, /* (397) anylist ::= */ - -4, /* (398) anylist ::= anylist LP anylist RP */ - -2, /* (399) anylist ::= anylist ANY */ - 0, /* (400) with ::= */ + -6, /* (209) expr ::= expr IS NOT DISTINCT FROM expr */ + -5, /* (210) expr ::= expr IS DISTINCT FROM expr */ + -2, /* (211) expr ::= NOT expr */ + -2, /* (212) expr ::= BITNOT expr */ + -2, /* (213) expr ::= PLUS|MINUS expr */ + -3, /* (214) expr ::= expr PTR expr */ + -1, /* (215) between_op ::= BETWEEN */ + -2, /* (216) between_op ::= NOT BETWEEN */ + -5, /* (217) expr ::= expr between_op expr AND expr */ + -1, /* (218) in_op ::= IN */ + -2, /* (219) in_op ::= NOT IN */ + -5, /* (220) expr ::= expr in_op LP exprlist RP */ + -3, /* (221) expr ::= LP select RP */ + -5, /* (222) expr ::= expr in_op LP select RP */ + -5, /* (223) expr ::= expr in_op nm dbnm paren_exprlist */ + -4, /* (224) expr ::= EXISTS LP select RP */ + -5, /* (225) expr ::= CASE case_operand case_exprlist case_else END */ + -5, /* (226) case_exprlist ::= case_exprlist WHEN expr THEN expr */ + -4, /* (227) case_exprlist ::= WHEN expr THEN expr */ + -2, /* (228) case_else ::= ELSE expr */ + 0, /* (229) case_else ::= */ + -1, /* (230) case_operand ::= expr */ + 0, /* (231) case_operand ::= */ + 0, /* (232) exprlist ::= */ + -3, /* (233) nexprlist ::= nexprlist COMMA expr */ + -1, /* (234) nexprlist ::= expr */ + 0, /* (235) paren_exprlist ::= */ + -3, /* (236) paren_exprlist ::= LP exprlist RP */ + -12, /* (237) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ + -1, /* (238) uniqueflag ::= UNIQUE */ + 0, /* (239) uniqueflag ::= */ + 0, /* (240) eidlist_opt ::= */ + -3, /* (241) eidlist_opt ::= LP eidlist RP */ + -5, /* (242) eidlist ::= eidlist COMMA nm collate sortorder */ + -3, /* (243) eidlist ::= nm collate sortorder */ + 0, /* (244) collate ::= */ + -2, /* (245) collate ::= COLLATE ID|STRING */ + -4, /* (246) cmd ::= DROP INDEX ifexists fullname */ + -2, /* (247) cmd ::= VACUUM vinto */ + -3, /* (248) cmd ::= VACUUM nm vinto */ + -2, /* (249) vinto ::= INTO expr */ + 0, /* (250) vinto ::= */ + -3, /* (251) cmd ::= PRAGMA nm dbnm */ + -5, /* (252) cmd ::= PRAGMA nm dbnm EQ nmnum */ + -6, /* (253) cmd ::= PRAGMA nm dbnm LP nmnum RP */ + -5, /* (254) cmd ::= PRAGMA nm dbnm EQ minus_num */ + -6, /* (255) cmd ::= PRAGMA nm dbnm LP minus_num RP */ + -2, /* (256) plus_num ::= PLUS INTEGER|FLOAT */ + -2, /* (257) minus_num ::= MINUS INTEGER|FLOAT */ + -5, /* (258) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ + -11, /* (259) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ + -1, /* (260) trigger_time ::= BEFORE|AFTER */ + -2, /* (261) trigger_time ::= INSTEAD OF */ + 0, /* (262) trigger_time ::= */ + -1, /* (263) trigger_event ::= DELETE|INSERT */ + -1, /* (264) trigger_event ::= UPDATE */ + -3, /* (265) trigger_event ::= UPDATE OF idlist */ + 0, /* (266) when_clause ::= */ + -2, /* (267) when_clause ::= WHEN expr */ + -3, /* (268) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ + -2, /* (269) trigger_cmd_list ::= trigger_cmd SEMI */ + -3, /* (270) trnm ::= nm DOT nm */ + -3, /* (271) tridxby ::= INDEXED BY nm */ + -2, /* (272) tridxby ::= NOT INDEXED */ + -9, /* (273) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */ + -8, /* (274) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ + -6, /* (275) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ + -3, /* (276) trigger_cmd ::= scanpt select scanpt */ + -4, /* (277) expr ::= RAISE LP IGNORE RP */ + -6, /* (278) expr ::= RAISE LP raisetype COMMA nm RP */ + -1, /* (279) raisetype ::= ROLLBACK */ + -1, /* (280) raisetype ::= ABORT */ + -1, /* (281) raisetype ::= FAIL */ + -4, /* (282) cmd ::= DROP TRIGGER ifexists fullname */ + -6, /* (283) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ + -3, /* (284) cmd ::= DETACH database_kw_opt expr */ + 0, /* (285) key_opt ::= */ + -2, /* (286) key_opt ::= KEY expr */ + -1, /* (287) cmd ::= REINDEX */ + -3, /* (288) cmd ::= REINDEX nm dbnm */ + -1, /* (289) cmd ::= ANALYZE */ + -3, /* (290) cmd ::= ANALYZE nm dbnm */ + -6, /* (291) cmd ::= ALTER TABLE fullname RENAME TO nm */ + -7, /* (292) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ + -6, /* (293) cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */ + -1, /* (294) add_column_fullname ::= fullname */ + -8, /* (295) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ + -1, /* (296) cmd ::= create_vtab */ + -4, /* (297) cmd ::= create_vtab LP vtabarglist RP */ + -8, /* (298) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ + 0, /* (299) vtabarg ::= */ + -1, /* (300) vtabargtoken ::= ANY */ + -3, /* (301) vtabargtoken ::= lp anylist RP */ + -1, /* (302) lp ::= LP */ + -2, /* (303) with ::= WITH wqlist */ + -3, /* (304) with ::= WITH RECURSIVE wqlist */ + -1, /* (305) wqas ::= AS */ + -2, /* (306) wqas ::= AS MATERIALIZED */ + -3, /* (307) wqas ::= AS NOT MATERIALIZED */ + -6, /* (308) wqitem ::= nm eidlist_opt wqas LP select RP */ + -1, /* (309) wqlist ::= wqitem */ + -3, /* (310) wqlist ::= wqlist COMMA wqitem */ + -1, /* (311) windowdefn_list ::= windowdefn */ + -3, /* (312) windowdefn_list ::= windowdefn_list COMMA windowdefn */ + -5, /* (313) windowdefn ::= nm AS LP window RP */ + -5, /* (314) window ::= PARTITION BY nexprlist orderby_opt frame_opt */ + -6, /* (315) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ + -4, /* (316) window ::= ORDER BY sortlist frame_opt */ + -5, /* (317) window ::= nm ORDER BY sortlist frame_opt */ + -1, /* (318) window ::= frame_opt */ + -2, /* (319) window ::= nm frame_opt */ + 0, /* (320) frame_opt ::= */ + -3, /* (321) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ + -6, /* (322) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ + -1, /* (323) range_or_rows ::= RANGE|ROWS|GROUPS */ + -1, /* (324) frame_bound_s ::= frame_bound */ + -2, /* (325) frame_bound_s ::= UNBOUNDED PRECEDING */ + -1, /* (326) frame_bound_e ::= frame_bound */ + -2, /* (327) frame_bound_e ::= UNBOUNDED FOLLOWING */ + -2, /* (328) frame_bound ::= expr PRECEDING|FOLLOWING */ + -2, /* (329) frame_bound ::= CURRENT ROW */ + 0, /* (330) frame_exclude_opt ::= */ + -2, /* (331) frame_exclude_opt ::= EXCLUDE frame_exclude */ + -2, /* (332) frame_exclude ::= NO OTHERS */ + -2, /* (333) frame_exclude ::= CURRENT ROW */ + -1, /* (334) frame_exclude ::= GROUP|TIES */ + -2, /* (335) window_clause ::= WINDOW windowdefn_list */ + -2, /* (336) filter_over ::= filter_clause over_clause */ + -1, /* (337) filter_over ::= over_clause */ + -1, /* (338) filter_over ::= filter_clause */ + -4, /* (339) over_clause ::= OVER LP window RP */ + -2, /* (340) over_clause ::= OVER nm */ + -5, /* (341) filter_clause ::= FILTER LP WHERE expr RP */ + -1, /* (342) input ::= cmdlist */ + -2, /* (343) cmdlist ::= cmdlist ecmd */ + -1, /* (344) cmdlist ::= ecmd */ + -1, /* (345) ecmd ::= SEMI */ + -2, /* (346) ecmd ::= cmdx SEMI */ + -3, /* (347) ecmd ::= explain cmdx SEMI */ + 0, /* (348) trans_opt ::= */ + -1, /* (349) trans_opt ::= TRANSACTION */ + -2, /* (350) trans_opt ::= TRANSACTION nm */ + -1, /* (351) savepoint_opt ::= SAVEPOINT */ + 0, /* (352) savepoint_opt ::= */ + -2, /* (353) cmd ::= create_table create_table_args */ + -1, /* (354) table_option_set ::= table_option */ + -4, /* (355) columnlist ::= columnlist COMMA columnname carglist */ + -2, /* (356) columnlist ::= columnname carglist */ + -1, /* (357) nm ::= ID|INDEXED */ + -1, /* (358) nm ::= STRING */ + -1, /* (359) nm ::= JOIN_KW */ + -1, /* (360) typetoken ::= typename */ + -1, /* (361) typename ::= ID|STRING */ + -1, /* (362) signed ::= plus_num */ + -1, /* (363) signed ::= minus_num */ + -2, /* (364) carglist ::= carglist ccons */ + 0, /* (365) carglist ::= */ + -2, /* (366) ccons ::= NULL onconf */ + -4, /* (367) ccons ::= GENERATED ALWAYS AS generated */ + -2, /* (368) ccons ::= AS generated */ + -2, /* (369) conslist_opt ::= COMMA conslist */ + -3, /* (370) conslist ::= conslist tconscomma tcons */ + -1, /* (371) conslist ::= tcons */ + 0, /* (372) tconscomma ::= */ + -1, /* (373) defer_subclause_opt ::= defer_subclause */ + -1, /* (374) resolvetype ::= raisetype */ + -1, /* (375) selectnowith ::= oneselect */ + -1, /* (376) oneselect ::= values */ + -2, /* (377) sclp ::= selcollist COMMA */ + -1, /* (378) as ::= ID|STRING */ + -1, /* (379) indexed_opt ::= indexed_by */ + 0, /* (380) returning ::= */ + -1, /* (381) expr ::= term */ + -1, /* (382) likeop ::= LIKE_KW|MATCH */ + -1, /* (383) exprlist ::= nexprlist */ + -1, /* (384) nmnum ::= plus_num */ + -1, /* (385) nmnum ::= nm */ + -1, /* (386) nmnum ::= ON */ + -1, /* (387) nmnum ::= DELETE */ + -1, /* (388) nmnum ::= DEFAULT */ + -1, /* (389) plus_num ::= INTEGER|FLOAT */ + 0, /* (390) foreach_clause ::= */ + -3, /* (391) foreach_clause ::= FOR EACH ROW */ + -1, /* (392) trnm ::= nm */ + 0, /* (393) tridxby ::= */ + -1, /* (394) database_kw_opt ::= DATABASE */ + 0, /* (395) database_kw_opt ::= */ + 0, /* (396) kwcolumn_opt ::= */ + -1, /* (397) kwcolumn_opt ::= COLUMNKW */ + -1, /* (398) vtabarglist ::= vtabarg */ + -3, /* (399) vtabarglist ::= vtabarglist COMMA vtabarg */ + -2, /* (400) vtabarg ::= vtabarg vtabargtoken */ + 0, /* (401) anylist ::= */ + -4, /* (402) anylist ::= anylist LP anylist RP */ + -2, /* (403) anylist ::= anylist ANY */ + 0, /* (404) with ::= */ }; static void yy_accept(yyParser*); /* Forward Declaration */ @@ -163003,16 +167117,16 @@ static YYACTIONTYPE yy_reduce( { sqlite3FinishCoding(pParse); } break; case 3: /* cmd ::= BEGIN transtype trans_opt */ -{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy64);} +{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy394);} break; case 4: /* transtype ::= */ -{yymsp[1].minor.yy64 = TK_DEFERRED;} +{yymsp[1].minor.yy394 = TK_DEFERRED;} break; case 5: /* transtype ::= DEFERRED */ case 6: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==6); case 7: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==7); - case 320: /* range_or_rows ::= RANGE|ROWS|GROUPS */ yytestcase(yyruleno==320); -{yymsp[0].minor.yy64 = yymsp[0].major; /*A-overwrites-X*/} + case 323: /* range_or_rows ::= RANGE|ROWS|GROUPS */ yytestcase(yyruleno==323); +{yymsp[0].minor.yy394 = yymsp[0].major; /*A-overwrites-X*/} break; case 8: /* cmd ::= COMMIT|END trans_opt */ case 9: /* cmd ::= ROLLBACK trans_opt */ yytestcase(yyruleno==9); @@ -163035,7 +167149,7 @@ static YYACTIONTYPE yy_reduce( break; case 13: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */ { - sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy64,0,0,yymsp[-2].minor.yy64); + sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy394,0,0,yymsp[-2].minor.yy394); } break; case 14: /* createkw ::= CREATE */ @@ -163048,39 +167162,39 @@ static YYACTIONTYPE yy_reduce( case 72: /* defer_subclause_opt ::= */ yytestcase(yyruleno==72); case 81: /* ifexists ::= */ yytestcase(yyruleno==81); case 98: /* distinct ::= */ yytestcase(yyruleno==98); - case 241: /* collate ::= */ yytestcase(yyruleno==241); -{yymsp[1].minor.yy64 = 0;} + case 244: /* collate ::= */ yytestcase(yyruleno==244); +{yymsp[1].minor.yy394 = 0;} break; case 16: /* ifnotexists ::= IF NOT EXISTS */ -{yymsp[-2].minor.yy64 = 1;} +{yymsp[-2].minor.yy394 = 1;} break; case 17: /* temp ::= TEMP */ -{yymsp[0].minor.yy64 = pParse->db->init.busy==0;} +{yymsp[0].minor.yy394 = pParse->db->init.busy==0;} break; case 19: /* create_table_args ::= LP columnlist conslist_opt RP table_option_set */ { - sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy51,0); + sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy285,0); } break; case 20: /* create_table_args ::= AS select */ { - sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy303); - sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy303); + sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy47); + sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy47); } break; case 21: /* table_option_set ::= */ -{yymsp[1].minor.yy51 = 0;} +{yymsp[1].minor.yy285 = 0;} break; case 22: /* table_option_set ::= table_option_set COMMA table_option */ -{yylhsminor.yy51 = yymsp[-2].minor.yy51|yymsp[0].minor.yy51;} - yymsp[-2].minor.yy51 = yylhsminor.yy51; +{yylhsminor.yy285 = yymsp[-2].minor.yy285|yymsp[0].minor.yy285;} + yymsp[-2].minor.yy285 = yylhsminor.yy285; break; case 23: /* table_option ::= WITHOUT nm */ { if( yymsp[0].minor.yy0.n==5 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"rowid",5)==0 ){ - yymsp[-1].minor.yy51 = TF_WithoutRowid | TF_NoVisibleRowid; + yymsp[-1].minor.yy285 = TF_WithoutRowid | TF_NoVisibleRowid; }else{ - yymsp[-1].minor.yy51 = 0; + yymsp[-1].minor.yy285 = 0; sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z); } } @@ -163088,13 +167202,13 @@ static YYACTIONTYPE yy_reduce( case 24: /* table_option ::= nm */ { if( yymsp[0].minor.yy0.n==6 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"strict",6)==0 ){ - yylhsminor.yy51 = TF_Strict; + yylhsminor.yy285 = TF_Strict; }else{ - yylhsminor.yy51 = 0; + yylhsminor.yy285 = 0; sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z); } } - yymsp[0].minor.yy51 = yylhsminor.yy51; + yymsp[0].minor.yy285 = yylhsminor.yy285; break; case 25: /* columnname ::= nm typetoken */ {sqlite3AddColumn(pParse,yymsp[-1].minor.yy0,yymsp[0].minor.yy0);} @@ -163120,7 +167234,7 @@ static YYACTIONTYPE yy_reduce( case 30: /* scanpt ::= */ { assert( yyLookahead!=YYNOCODE ); - yymsp[1].minor.yy600 = yyLookaheadToken.z; + yymsp[1].minor.yy522 = yyLookaheadToken.z; } break; case 31: /* scantok ::= */ @@ -163134,17 +167248,17 @@ static YYACTIONTYPE yy_reduce( {pParse->constraintName = yymsp[0].minor.yy0;} break; case 33: /* ccons ::= DEFAULT scantok term */ -{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy626,yymsp[-1].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);} +{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy528,yymsp[-1].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);} break; case 34: /* ccons ::= DEFAULT LP expr RP */ -{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy626,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);} +{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy528,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);} break; case 35: /* ccons ::= DEFAULT PLUS scantok term */ -{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy626,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);} +{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy528,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);} break; case 36: /* ccons ::= DEFAULT MINUS scantok term */ { - Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy626, 0); + Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy528, 0); sqlite3AddDefaultValue(pParse,p,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]); } break; @@ -163159,307 +167273,315 @@ static YYACTIONTYPE yy_reduce( } break; case 38: /* ccons ::= NOT NULL onconf */ -{sqlite3AddNotNull(pParse, yymsp[0].minor.yy64);} +{sqlite3AddNotNull(pParse, yymsp[0].minor.yy394);} break; case 39: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */ -{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy64,yymsp[0].minor.yy64,yymsp[-2].minor.yy64);} +{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy394,yymsp[0].minor.yy394,yymsp[-2].minor.yy394);} break; case 40: /* ccons ::= UNIQUE onconf */ -{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy64,0,0,0,0, +{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy394,0,0,0,0, SQLITE_IDXTYPE_UNIQUE);} break; case 41: /* ccons ::= CHECK LP expr RP */ -{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy626,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy0.z);} +{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy528,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy0.z);} break; case 42: /* ccons ::= REFERENCES nm eidlist_opt refargs */ -{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy562,yymsp[0].minor.yy64);} +{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy322,yymsp[0].minor.yy394);} break; case 43: /* ccons ::= defer_subclause */ -{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy64);} +{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy394);} break; case 44: /* ccons ::= COLLATE ID|STRING */ {sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);} break; case 45: /* generated ::= LP expr RP */ -{sqlite3AddGenerated(pParse,yymsp[-1].minor.yy626,0);} +{sqlite3AddGenerated(pParse,yymsp[-1].minor.yy528,0);} break; case 46: /* generated ::= LP expr RP ID */ -{sqlite3AddGenerated(pParse,yymsp[-2].minor.yy626,&yymsp[0].minor.yy0);} +{sqlite3AddGenerated(pParse,yymsp[-2].minor.yy528,&yymsp[0].minor.yy0);} break; case 48: /* autoinc ::= AUTOINCR */ -{yymsp[0].minor.yy64 = 1;} +{yymsp[0].minor.yy394 = 1;} break; case 49: /* refargs ::= */ -{ yymsp[1].minor.yy64 = OE_None*0x0101; /* EV: R-19803-45884 */} +{ yymsp[1].minor.yy394 = OE_None*0x0101; /* EV: R-19803-45884 */} break; case 50: /* refargs ::= refargs refarg */ -{ yymsp[-1].minor.yy64 = (yymsp[-1].minor.yy64 & ~yymsp[0].minor.yy83.mask) | yymsp[0].minor.yy83.value; } +{ yymsp[-1].minor.yy394 = (yymsp[-1].minor.yy394 & ~yymsp[0].minor.yy231.mask) | yymsp[0].minor.yy231.value; } break; case 51: /* refarg ::= MATCH nm */ -{ yymsp[-1].minor.yy83.value = 0; yymsp[-1].minor.yy83.mask = 0x000000; } +{ yymsp[-1].minor.yy231.value = 0; yymsp[-1].minor.yy231.mask = 0x000000; } break; case 52: /* refarg ::= ON INSERT refact */ -{ yymsp[-2].minor.yy83.value = 0; yymsp[-2].minor.yy83.mask = 0x000000; } +{ yymsp[-2].minor.yy231.value = 0; yymsp[-2].minor.yy231.mask = 0x000000; } break; case 53: /* refarg ::= ON DELETE refact */ -{ yymsp[-2].minor.yy83.value = yymsp[0].minor.yy64; yymsp[-2].minor.yy83.mask = 0x0000ff; } +{ yymsp[-2].minor.yy231.value = yymsp[0].minor.yy394; yymsp[-2].minor.yy231.mask = 0x0000ff; } break; case 54: /* refarg ::= ON UPDATE refact */ -{ yymsp[-2].minor.yy83.value = yymsp[0].minor.yy64<<8; yymsp[-2].minor.yy83.mask = 0x00ff00; } +{ yymsp[-2].minor.yy231.value = yymsp[0].minor.yy394<<8; yymsp[-2].minor.yy231.mask = 0x00ff00; } break; case 55: /* refact ::= SET NULL */ -{ yymsp[-1].minor.yy64 = OE_SetNull; /* EV: R-33326-45252 */} +{ yymsp[-1].minor.yy394 = OE_SetNull; /* EV: R-33326-45252 */} break; case 56: /* refact ::= SET DEFAULT */ -{ yymsp[-1].minor.yy64 = OE_SetDflt; /* EV: R-33326-45252 */} +{ yymsp[-1].minor.yy394 = OE_SetDflt; /* EV: R-33326-45252 */} break; case 57: /* refact ::= CASCADE */ -{ yymsp[0].minor.yy64 = OE_Cascade; /* EV: R-33326-45252 */} +{ yymsp[0].minor.yy394 = OE_Cascade; /* EV: R-33326-45252 */} break; case 58: /* refact ::= RESTRICT */ -{ yymsp[0].minor.yy64 = OE_Restrict; /* EV: R-33326-45252 */} +{ yymsp[0].minor.yy394 = OE_Restrict; /* EV: R-33326-45252 */} break; case 59: /* refact ::= NO ACTION */ -{ yymsp[-1].minor.yy64 = OE_None; /* EV: R-33326-45252 */} +{ yymsp[-1].minor.yy394 = OE_None; /* EV: R-33326-45252 */} break; case 60: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ -{yymsp[-2].minor.yy64 = 0;} +{yymsp[-2].minor.yy394 = 0;} break; case 61: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ case 76: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==76); case 171: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==171); -{yymsp[-1].minor.yy64 = yymsp[0].minor.yy64;} +{yymsp[-1].minor.yy394 = yymsp[0].minor.yy394;} break; case 63: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ case 80: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==80); - case 213: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==213); - case 216: /* in_op ::= NOT IN */ yytestcase(yyruleno==216); - case 242: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==242); -{yymsp[-1].minor.yy64 = 1;} + case 216: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==216); + case 219: /* in_op ::= NOT IN */ yytestcase(yyruleno==219); + case 245: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==245); +{yymsp[-1].minor.yy394 = 1;} break; case 64: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ -{yymsp[-1].minor.yy64 = 0;} +{yymsp[-1].minor.yy394 = 0;} break; case 66: /* tconscomma ::= COMMA */ {pParse->constraintName.n = 0;} break; case 68: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */ -{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy562,yymsp[0].minor.yy64,yymsp[-2].minor.yy64,0);} +{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy322,yymsp[0].minor.yy394,yymsp[-2].minor.yy394,0);} break; case 69: /* tcons ::= UNIQUE LP sortlist RP onconf */ -{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy562,yymsp[0].minor.yy64,0,0,0,0, +{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy322,yymsp[0].minor.yy394,0,0,0,0, SQLITE_IDXTYPE_UNIQUE);} break; case 70: /* tcons ::= CHECK LP expr RP onconf */ -{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy626,yymsp[-3].minor.yy0.z,yymsp[-1].minor.yy0.z);} +{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy528,yymsp[-3].minor.yy0.z,yymsp[-1].minor.yy0.z);} break; case 71: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */ { - sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy562, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy562, yymsp[-1].minor.yy64); - sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy64); + sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy322, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy322, yymsp[-1].minor.yy394); + sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy394); } break; case 73: /* onconf ::= */ case 75: /* orconf ::= */ yytestcase(yyruleno==75); -{yymsp[1].minor.yy64 = OE_Default;} +{yymsp[1].minor.yy394 = OE_Default;} break; case 74: /* onconf ::= ON CONFLICT resolvetype */ -{yymsp[-2].minor.yy64 = yymsp[0].minor.yy64;} +{yymsp[-2].minor.yy394 = yymsp[0].minor.yy394;} break; case 77: /* resolvetype ::= IGNORE */ -{yymsp[0].minor.yy64 = OE_Ignore;} +{yymsp[0].minor.yy394 = OE_Ignore;} break; case 78: /* resolvetype ::= REPLACE */ case 172: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==172); -{yymsp[0].minor.yy64 = OE_Replace;} +{yymsp[0].minor.yy394 = OE_Replace;} break; case 79: /* cmd ::= DROP TABLE ifexists fullname */ { - sqlite3DropTable(pParse, yymsp[0].minor.yy607, 0, yymsp[-1].minor.yy64); + sqlite3DropTable(pParse, yymsp[0].minor.yy131, 0, yymsp[-1].minor.yy394); } break; case 82: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ { - sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy562, yymsp[0].minor.yy303, yymsp[-7].minor.yy64, yymsp[-5].minor.yy64); + sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy322, yymsp[0].minor.yy47, yymsp[-7].minor.yy394, yymsp[-5].minor.yy394); } break; case 83: /* cmd ::= DROP VIEW ifexists fullname */ { - sqlite3DropTable(pParse, yymsp[0].minor.yy607, 1, yymsp[-1].minor.yy64); + sqlite3DropTable(pParse, yymsp[0].minor.yy131, 1, yymsp[-1].minor.yy394); } break; case 84: /* cmd ::= select */ { SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0, 0}; - sqlite3Select(pParse, yymsp[0].minor.yy303, &dest); - sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy303); + sqlite3Select(pParse, yymsp[0].minor.yy47, &dest); + sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy47); } break; case 85: /* select ::= WITH wqlist selectnowith */ -{yymsp[-2].minor.yy303 = attachWithToSelect(pParse,yymsp[0].minor.yy303,yymsp[-1].minor.yy43);} +{yymsp[-2].minor.yy47 = attachWithToSelect(pParse,yymsp[0].minor.yy47,yymsp[-1].minor.yy521);} break; case 86: /* select ::= WITH RECURSIVE wqlist selectnowith */ -{yymsp[-3].minor.yy303 = attachWithToSelect(pParse,yymsp[0].minor.yy303,yymsp[-1].minor.yy43);} +{yymsp[-3].minor.yy47 = attachWithToSelect(pParse,yymsp[0].minor.yy47,yymsp[-1].minor.yy521);} break; case 87: /* select ::= selectnowith */ { - Select *p = yymsp[0].minor.yy303; + Select *p = yymsp[0].minor.yy47; if( p ){ parserDoubleLinkSelect(pParse, p); } - yymsp[0].minor.yy303 = p; /*A-overwrites-X*/ + yymsp[0].minor.yy47 = p; /*A-overwrites-X*/ } break; case 88: /* selectnowith ::= selectnowith multiselect_op oneselect */ { - Select *pRhs = yymsp[0].minor.yy303; - Select *pLhs = yymsp[-2].minor.yy303; + Select *pRhs = yymsp[0].minor.yy47; + Select *pLhs = yymsp[-2].minor.yy47; if( pRhs && pRhs->pPrior ){ SrcList *pFrom; Token x; x.n = 0; parserDoubleLinkSelect(pParse, pRhs); - pFrom = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&x,pRhs,0,0); + pFrom = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&x,pRhs,0); pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0); } if( pRhs ){ - pRhs->op = (u8)yymsp[-1].minor.yy64; + pRhs->op = (u8)yymsp[-1].minor.yy394; pRhs->pPrior = pLhs; if( ALWAYS(pLhs) ) pLhs->selFlags &= ~SF_MultiValue; pRhs->selFlags &= ~SF_MultiValue; - if( yymsp[-1].minor.yy64!=TK_ALL ) pParse->hasCompound = 1; + if( yymsp[-1].minor.yy394!=TK_ALL ) pParse->hasCompound = 1; }else{ sqlite3SelectDelete(pParse->db, pLhs); } - yymsp[-2].minor.yy303 = pRhs; + yymsp[-2].minor.yy47 = pRhs; } break; case 89: /* multiselect_op ::= UNION */ case 91: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==91); -{yymsp[0].minor.yy64 = yymsp[0].major; /*A-overwrites-OP*/} +{yymsp[0].minor.yy394 = yymsp[0].major; /*A-overwrites-OP*/} break; case 90: /* multiselect_op ::= UNION ALL */ -{yymsp[-1].minor.yy64 = TK_ALL;} +{yymsp[-1].minor.yy394 = TK_ALL;} break; case 92: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ { - yymsp[-8].minor.yy303 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy562,yymsp[-5].minor.yy607,yymsp[-4].minor.yy626,yymsp[-3].minor.yy562,yymsp[-2].minor.yy626,yymsp[-1].minor.yy562,yymsp[-7].minor.yy64,yymsp[0].minor.yy626); + yymsp[-8].minor.yy47 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy322,yymsp[-5].minor.yy131,yymsp[-4].minor.yy528,yymsp[-3].minor.yy322,yymsp[-2].minor.yy528,yymsp[-1].minor.yy322,yymsp[-7].minor.yy394,yymsp[0].minor.yy528); } break; case 93: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */ { - yymsp[-9].minor.yy303 = sqlite3SelectNew(pParse,yymsp[-7].minor.yy562,yymsp[-6].minor.yy607,yymsp[-5].minor.yy626,yymsp[-4].minor.yy562,yymsp[-3].minor.yy626,yymsp[-1].minor.yy562,yymsp[-8].minor.yy64,yymsp[0].minor.yy626); - if( yymsp[-9].minor.yy303 ){ - yymsp[-9].minor.yy303->pWinDefn = yymsp[-2].minor.yy375; + yymsp[-9].minor.yy47 = sqlite3SelectNew(pParse,yymsp[-7].minor.yy322,yymsp[-6].minor.yy131,yymsp[-5].minor.yy528,yymsp[-4].minor.yy322,yymsp[-3].minor.yy528,yymsp[-1].minor.yy322,yymsp[-8].minor.yy394,yymsp[0].minor.yy528); + if( yymsp[-9].minor.yy47 ){ + yymsp[-9].minor.yy47->pWinDefn = yymsp[-2].minor.yy41; }else{ - sqlite3WindowListDelete(pParse->db, yymsp[-2].minor.yy375); + sqlite3WindowListDelete(pParse->db, yymsp[-2].minor.yy41); } } break; case 94: /* values ::= VALUES LP nexprlist RP */ { - yymsp[-3].minor.yy303 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy562,0,0,0,0,0,SF_Values,0); + yymsp[-3].minor.yy47 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy322,0,0,0,0,0,SF_Values,0); } break; case 95: /* values ::= values COMMA LP nexprlist RP */ { - Select *pRight, *pLeft = yymsp[-4].minor.yy303; - pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy562,0,0,0,0,0,SF_Values|SF_MultiValue,0); + Select *pRight, *pLeft = yymsp[-4].minor.yy47; + pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy322,0,0,0,0,0,SF_Values|SF_MultiValue,0); if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue; if( pRight ){ pRight->op = TK_ALL; pRight->pPrior = pLeft; - yymsp[-4].minor.yy303 = pRight; + yymsp[-4].minor.yy47 = pRight; }else{ - yymsp[-4].minor.yy303 = pLeft; + yymsp[-4].minor.yy47 = pLeft; } } break; case 96: /* distinct ::= DISTINCT */ -{yymsp[0].minor.yy64 = SF_Distinct;} +{yymsp[0].minor.yy394 = SF_Distinct;} break; case 97: /* distinct ::= ALL */ -{yymsp[0].minor.yy64 = SF_All;} +{yymsp[0].minor.yy394 = SF_All;} break; case 99: /* sclp ::= */ case 132: /* orderby_opt ::= */ yytestcase(yyruleno==132); case 142: /* groupby_opt ::= */ yytestcase(yyruleno==142); - case 229: /* exprlist ::= */ yytestcase(yyruleno==229); - case 232: /* paren_exprlist ::= */ yytestcase(yyruleno==232); - case 237: /* eidlist_opt ::= */ yytestcase(yyruleno==237); -{yymsp[1].minor.yy562 = 0;} + case 232: /* exprlist ::= */ yytestcase(yyruleno==232); + case 235: /* paren_exprlist ::= */ yytestcase(yyruleno==235); + case 240: /* eidlist_opt ::= */ yytestcase(yyruleno==240); +{yymsp[1].minor.yy322 = 0;} break; case 100: /* selcollist ::= sclp scanpt expr scanpt as */ { - yymsp[-4].minor.yy562 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy562, yymsp[-2].minor.yy626); - if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy562, &yymsp[0].minor.yy0, 1); - sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy562,yymsp[-3].minor.yy600,yymsp[-1].minor.yy600); + yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy322, yymsp[-2].minor.yy528); + if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy322, &yymsp[0].minor.yy0, 1); + sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy322,yymsp[-3].minor.yy522,yymsp[-1].minor.yy522); } break; case 101: /* selcollist ::= sclp scanpt STAR */ { Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0); - yymsp[-2].minor.yy562 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy562, p); + yymsp[-2].minor.yy322 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy322, p); } break; case 102: /* selcollist ::= sclp scanpt nm DOT STAR */ { Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0); - Expr *pLeft = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1); + Expr *pLeft = tokenExpr(pParse, TK_ID, yymsp[-2].minor.yy0); Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight); - yymsp[-4].minor.yy562 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy562, pDot); + yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322, pDot); } break; case 103: /* as ::= AS nm */ - case 114: /* dbnm ::= DOT nm */ yytestcase(yyruleno==114); - case 253: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==253); - case 254: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==254); + case 115: /* dbnm ::= DOT nm */ yytestcase(yyruleno==115); + case 256: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==256); + case 257: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==257); {yymsp[-1].minor.yy0 = yymsp[0].minor.yy0;} break; case 105: /* from ::= */ case 108: /* stl_prefix ::= */ yytestcase(yyruleno==108); -{yymsp[1].minor.yy607 = 0;} +{yymsp[1].minor.yy131 = 0;} break; case 106: /* from ::= FROM seltablist */ { - yymsp[-1].minor.yy607 = yymsp[0].minor.yy607; - sqlite3SrcListShiftJoinType(yymsp[-1].minor.yy607); + yymsp[-1].minor.yy131 = yymsp[0].minor.yy131; + sqlite3SrcListShiftJoinType(pParse,yymsp[-1].minor.yy131); } break; case 107: /* stl_prefix ::= seltablist joinop */ { - if( ALWAYS(yymsp[-1].minor.yy607 && yymsp[-1].minor.yy607->nSrc>0) ) yymsp[-1].minor.yy607->a[yymsp[-1].minor.yy607->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy64; + if( ALWAYS(yymsp[-1].minor.yy131 && yymsp[-1].minor.yy131->nSrc>0) ) yymsp[-1].minor.yy131->a[yymsp[-1].minor.yy131->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy394; +} + break; + case 109: /* seltablist ::= stl_prefix nm dbnm as on_using */ +{ + yymsp[-4].minor.yy131 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-4].minor.yy131,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy561); } break; - case 109: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */ + case 110: /* seltablist ::= stl_prefix nm dbnm as indexed_by on_using */ { - yymsp[-6].minor.yy607 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy607,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy626,yymsp[0].minor.yy240); - sqlite3SrcListIndexedBy(pParse, yymsp[-6].minor.yy607, &yymsp[-2].minor.yy0); + yymsp[-5].minor.yy131 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy131,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,0,&yymsp[0].minor.yy561); + sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy131, &yymsp[-1].minor.yy0); } break; - case 110: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */ + case 111: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */ { - yymsp[-8].minor.yy607 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-8].minor.yy607,&yymsp[-7].minor.yy0,&yymsp[-6].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy626,yymsp[0].minor.yy240); - sqlite3SrcListFuncArgs(pParse, yymsp[-8].minor.yy607, yymsp[-4].minor.yy562); + yymsp[-7].minor.yy131 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-7].minor.yy131,&yymsp[-6].minor.yy0,&yymsp[-5].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy561); + sqlite3SrcListFuncArgs(pParse, yymsp[-7].minor.yy131, yymsp[-3].minor.yy322); } break; - case 111: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */ + case 112: /* seltablist ::= stl_prefix LP select RP as on_using */ { - yymsp[-6].minor.yy607 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy607,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy303,yymsp[-1].minor.yy626,yymsp[0].minor.yy240); + yymsp[-5].minor.yy131 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy131,0,0,&yymsp[-1].minor.yy0,yymsp[-3].minor.yy47,&yymsp[0].minor.yy561); } break; - case 112: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ + case 113: /* seltablist ::= stl_prefix LP seltablist RP as on_using */ { - if( yymsp[-6].minor.yy607==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy626==0 && yymsp[0].minor.yy240==0 ){ - yymsp[-6].minor.yy607 = yymsp[-4].minor.yy607; - }else if( yymsp[-4].minor.yy607->nSrc==1 ){ - yymsp[-6].minor.yy607 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy607,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy626,yymsp[0].minor.yy240); - if( yymsp[-6].minor.yy607 ){ - SrcItem *pNew = &yymsp[-6].minor.yy607->a[yymsp[-6].minor.yy607->nSrc-1]; - SrcItem *pOld = yymsp[-4].minor.yy607->a; + if( yymsp[-5].minor.yy131==0 && yymsp[-1].minor.yy0.n==0 && yymsp[0].minor.yy561.pOn==0 && yymsp[0].minor.yy561.pUsing==0 ){ + yymsp[-5].minor.yy131 = yymsp[-3].minor.yy131; + }else if( yymsp[-3].minor.yy131->nSrc==1 ){ + yymsp[-5].minor.yy131 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy131,0,0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy561); + if( yymsp[-5].minor.yy131 ){ + SrcItem *pNew = &yymsp[-5].minor.yy131->a[yymsp[-5].minor.yy131->nSrc-1]; + SrcItem *pOld = yymsp[-3].minor.yy131->a; pNew->zName = pOld->zName; pNew->zDatabase = pOld->zDatabase; pNew->pSelect = pOld->pSelect; + if( pNew->pSelect && (pNew->pSelect->selFlags & SF_NestedFrom)!=0 ){ + pNew->fg.isNestedFrom = 1; + } if( pOld->fg.isTabFunc ){ pNew->u1.pFuncArg = pOld->u1.pFuncArg; pOld->u1.pFuncArg = 0; @@ -163469,267 +167591,277 @@ static YYACTIONTYPE yy_reduce( pOld->zName = pOld->zDatabase = 0; pOld->pSelect = 0; } - sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy607); + sqlite3SrcListDelete(pParse->db, yymsp[-3].minor.yy131); }else{ Select *pSubquery; - sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy607); - pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy607,0,0,0,0,SF_NestedFrom,0); - yymsp[-6].minor.yy607 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy607,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy626,yymsp[0].minor.yy240); + sqlite3SrcListShiftJoinType(pParse,yymsp[-3].minor.yy131); + pSubquery = sqlite3SelectNew(pParse,0,yymsp[-3].minor.yy131,0,0,0,0,SF_NestedFrom,0); + yymsp[-5].minor.yy131 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy131,0,0,&yymsp[-1].minor.yy0,pSubquery,&yymsp[0].minor.yy561); } } break; - case 113: /* dbnm ::= */ - case 127: /* indexed_opt ::= */ yytestcase(yyruleno==127); + case 114: /* dbnm ::= */ + case 129: /* indexed_opt ::= */ yytestcase(yyruleno==129); {yymsp[1].minor.yy0.z=0; yymsp[1].minor.yy0.n=0;} break; - case 115: /* fullname ::= nm */ + case 116: /* fullname ::= nm */ { - yylhsminor.yy607 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); - if( IN_RENAME_OBJECT && yylhsminor.yy607 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy607->a[0].zName, &yymsp[0].minor.yy0); + yylhsminor.yy131 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); + if( IN_RENAME_OBJECT && yylhsminor.yy131 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy131->a[0].zName, &yymsp[0].minor.yy0); } - yymsp[0].minor.yy607 = yylhsminor.yy607; + yymsp[0].minor.yy131 = yylhsminor.yy131; break; - case 116: /* fullname ::= nm DOT nm */ + case 117: /* fullname ::= nm DOT nm */ { - yylhsminor.yy607 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); - if( IN_RENAME_OBJECT && yylhsminor.yy607 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy607->a[0].zName, &yymsp[0].minor.yy0); + yylhsminor.yy131 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); + if( IN_RENAME_OBJECT && yylhsminor.yy131 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy131->a[0].zName, &yymsp[0].minor.yy0); } - yymsp[-2].minor.yy607 = yylhsminor.yy607; + yymsp[-2].minor.yy131 = yylhsminor.yy131; break; - case 117: /* xfullname ::= nm */ -{yymsp[0].minor.yy607 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/} + case 118: /* xfullname ::= nm */ +{yymsp[0].minor.yy131 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/} break; - case 118: /* xfullname ::= nm DOT nm */ -{yymsp[-2].minor.yy607 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/} + case 119: /* xfullname ::= nm DOT nm */ +{yymsp[-2].minor.yy131 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/} break; - case 119: /* xfullname ::= nm DOT nm AS nm */ + case 120: /* xfullname ::= nm DOT nm AS nm */ { - yymsp[-4].minor.yy607 = sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); /*A-overwrites-X*/ - if( yymsp[-4].minor.yy607 ) yymsp[-4].minor.yy607->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); + yymsp[-4].minor.yy131 = sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); /*A-overwrites-X*/ + if( yymsp[-4].minor.yy131 ) yymsp[-4].minor.yy131->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); } break; - case 120: /* xfullname ::= nm AS nm */ + case 121: /* xfullname ::= nm AS nm */ { - yymsp[-2].minor.yy607 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,0); /*A-overwrites-X*/ - if( yymsp[-2].minor.yy607 ) yymsp[-2].minor.yy607->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); + yymsp[-2].minor.yy131 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,0); /*A-overwrites-X*/ + if( yymsp[-2].minor.yy131 ) yymsp[-2].minor.yy131->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0); } break; - case 121: /* joinop ::= COMMA|JOIN */ -{ yymsp[0].minor.yy64 = JT_INNER; } + case 122: /* joinop ::= COMMA|JOIN */ +{ yymsp[0].minor.yy394 = JT_INNER; } break; - case 122: /* joinop ::= JOIN_KW JOIN */ -{yymsp[-1].minor.yy64 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/} + case 123: /* joinop ::= JOIN_KW JOIN */ +{yymsp[-1].minor.yy394 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/} break; - case 123: /* joinop ::= JOIN_KW nm JOIN */ -{yymsp[-2].minor.yy64 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/} + case 124: /* joinop ::= JOIN_KW nm JOIN */ +{yymsp[-2].minor.yy394 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/} break; - case 124: /* joinop ::= JOIN_KW nm nm JOIN */ -{yymsp[-3].minor.yy64 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/} + case 125: /* joinop ::= JOIN_KW nm nm JOIN */ +{yymsp[-3].minor.yy394 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/} break; - case 125: /* on_opt ::= ON expr */ - case 145: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==145); - case 152: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==152); - case 154: /* where_opt_ret ::= WHERE expr */ yytestcase(yyruleno==154); - case 225: /* case_else ::= ELSE expr */ yytestcase(yyruleno==225); - case 246: /* vinto ::= INTO expr */ yytestcase(yyruleno==246); -{yymsp[-1].minor.yy626 = yymsp[0].minor.yy626;} + case 126: /* on_using ::= ON expr */ +{yymsp[-1].minor.yy561.pOn = yymsp[0].minor.yy528; yymsp[-1].minor.yy561.pUsing = 0;} break; - case 126: /* on_opt ::= */ - case 144: /* having_opt ::= */ yytestcase(yyruleno==144); - case 146: /* limit_opt ::= */ yytestcase(yyruleno==146); - case 151: /* where_opt ::= */ yytestcase(yyruleno==151); - case 153: /* where_opt_ret ::= */ yytestcase(yyruleno==153); - case 226: /* case_else ::= */ yytestcase(yyruleno==226); - case 228: /* case_operand ::= */ yytestcase(yyruleno==228); - case 247: /* vinto ::= */ yytestcase(yyruleno==247); -{yymsp[1].minor.yy626 = 0;} + case 127: /* on_using ::= USING LP idlist RP */ +{yymsp[-3].minor.yy561.pOn = 0; yymsp[-3].minor.yy561.pUsing = yymsp[-1].minor.yy254;} break; - case 128: /* indexed_opt ::= INDEXED BY nm */ + case 128: /* on_using ::= */ +{yymsp[1].minor.yy561.pOn = 0; yymsp[1].minor.yy561.pUsing = 0;} + break; + case 130: /* indexed_by ::= INDEXED BY nm */ {yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;} break; - case 129: /* indexed_opt ::= NOT INDEXED */ + case 131: /* indexed_by ::= NOT INDEXED */ {yymsp[-1].minor.yy0.z=0; yymsp[-1].minor.yy0.n=1;} break; - case 130: /* using_opt ::= USING LP idlist RP */ -{yymsp[-3].minor.yy240 = yymsp[-1].minor.yy240;} - break; - case 131: /* using_opt ::= */ - case 173: /* idlist_opt ::= */ yytestcase(yyruleno==173); -{yymsp[1].minor.yy240 = 0;} - break; case 133: /* orderby_opt ::= ORDER BY sortlist */ case 143: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==143); -{yymsp[-2].minor.yy562 = yymsp[0].minor.yy562;} +{yymsp[-2].minor.yy322 = yymsp[0].minor.yy322;} break; case 134: /* sortlist ::= sortlist COMMA expr sortorder nulls */ { - yymsp[-4].minor.yy562 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy562,yymsp[-2].minor.yy626); - sqlite3ExprListSetSortOrder(yymsp[-4].minor.yy562,yymsp[-1].minor.yy64,yymsp[0].minor.yy64); + yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322,yymsp[-2].minor.yy528); + sqlite3ExprListSetSortOrder(yymsp[-4].minor.yy322,yymsp[-1].minor.yy394,yymsp[0].minor.yy394); } break; case 135: /* sortlist ::= expr sortorder nulls */ { - yymsp[-2].minor.yy562 = sqlite3ExprListAppend(pParse,0,yymsp[-2].minor.yy626); /*A-overwrites-Y*/ - sqlite3ExprListSetSortOrder(yymsp[-2].minor.yy562,yymsp[-1].minor.yy64,yymsp[0].minor.yy64); + yymsp[-2].minor.yy322 = sqlite3ExprListAppend(pParse,0,yymsp[-2].minor.yy528); /*A-overwrites-Y*/ + sqlite3ExprListSetSortOrder(yymsp[-2].minor.yy322,yymsp[-1].minor.yy394,yymsp[0].minor.yy394); } break; case 136: /* sortorder ::= ASC */ -{yymsp[0].minor.yy64 = SQLITE_SO_ASC;} +{yymsp[0].minor.yy394 = SQLITE_SO_ASC;} break; case 137: /* sortorder ::= DESC */ -{yymsp[0].minor.yy64 = SQLITE_SO_DESC;} +{yymsp[0].minor.yy394 = SQLITE_SO_DESC;} break; case 138: /* sortorder ::= */ case 141: /* nulls ::= */ yytestcase(yyruleno==141); -{yymsp[1].minor.yy64 = SQLITE_SO_UNDEFINED;} +{yymsp[1].minor.yy394 = SQLITE_SO_UNDEFINED;} break; case 139: /* nulls ::= NULLS FIRST */ -{yymsp[-1].minor.yy64 = SQLITE_SO_ASC;} +{yymsp[-1].minor.yy394 = SQLITE_SO_ASC;} break; case 140: /* nulls ::= NULLS LAST */ -{yymsp[-1].minor.yy64 = SQLITE_SO_DESC;} +{yymsp[-1].minor.yy394 = SQLITE_SO_DESC;} + break; + case 144: /* having_opt ::= */ + case 146: /* limit_opt ::= */ yytestcase(yyruleno==146); + case 151: /* where_opt ::= */ yytestcase(yyruleno==151); + case 153: /* where_opt_ret ::= */ yytestcase(yyruleno==153); + case 229: /* case_else ::= */ yytestcase(yyruleno==229); + case 231: /* case_operand ::= */ yytestcase(yyruleno==231); + case 250: /* vinto ::= */ yytestcase(yyruleno==250); +{yymsp[1].minor.yy528 = 0;} + break; + case 145: /* having_opt ::= HAVING expr */ + case 152: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==152); + case 154: /* where_opt_ret ::= WHERE expr */ yytestcase(yyruleno==154); + case 228: /* case_else ::= ELSE expr */ yytestcase(yyruleno==228); + case 249: /* vinto ::= INTO expr */ yytestcase(yyruleno==249); +{yymsp[-1].minor.yy528 = yymsp[0].minor.yy528;} break; case 147: /* limit_opt ::= LIMIT expr */ -{yymsp[-1].minor.yy626 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy626,0);} +{yymsp[-1].minor.yy528 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy528,0);} break; case 148: /* limit_opt ::= LIMIT expr OFFSET expr */ -{yymsp[-3].minor.yy626 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy626,yymsp[0].minor.yy626);} +{yymsp[-3].minor.yy528 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy528,yymsp[0].minor.yy528);} break; case 149: /* limit_opt ::= LIMIT expr COMMA expr */ -{yymsp[-3].minor.yy626 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy626,yymsp[-2].minor.yy626);} +{yymsp[-3].minor.yy528 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy528,yymsp[-2].minor.yy528);} break; case 150: /* cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret */ { - sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy607, &yymsp[-1].minor.yy0); - sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy607,yymsp[0].minor.yy626,0,0); + sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy131, &yymsp[-1].minor.yy0); + sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy131,yymsp[0].minor.yy528,0,0); } break; case 155: /* where_opt_ret ::= RETURNING selcollist */ -{sqlite3AddReturning(pParse,yymsp[0].minor.yy562); yymsp[-1].minor.yy626 = 0;} +{sqlite3AddReturning(pParse,yymsp[0].minor.yy322); yymsp[-1].minor.yy528 = 0;} break; case 156: /* where_opt_ret ::= WHERE expr RETURNING selcollist */ -{sqlite3AddReturning(pParse,yymsp[0].minor.yy562); yymsp[-3].minor.yy626 = yymsp[-2].minor.yy626;} +{sqlite3AddReturning(pParse,yymsp[0].minor.yy322); yymsp[-3].minor.yy528 = yymsp[-2].minor.yy528;} break; case 157: /* cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret */ { - sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy607, &yymsp[-4].minor.yy0); - sqlite3ExprListCheckLength(pParse,yymsp[-2].minor.yy562,"set list"); - yymsp[-5].minor.yy607 = sqlite3SrcListAppendList(pParse, yymsp[-5].minor.yy607, yymsp[-1].minor.yy607); - sqlite3Update(pParse,yymsp[-5].minor.yy607,yymsp[-2].minor.yy562,yymsp[0].minor.yy626,yymsp[-6].minor.yy64,0,0,0); + sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy131, &yymsp[-4].minor.yy0); + sqlite3ExprListCheckLength(pParse,yymsp[-2].minor.yy322,"set list"); + if( yymsp[-1].minor.yy131 ){ + SrcList *pFromClause = yymsp[-1].minor.yy131; + if( pFromClause->nSrc>1 ){ + Select *pSubquery; + Token as; + pSubquery = sqlite3SelectNew(pParse,0,pFromClause,0,0,0,0,SF_NestedFrom,0); + as.n = 0; + as.z = 0; + pFromClause = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&as,pSubquery,0); + } + yymsp[-5].minor.yy131 = sqlite3SrcListAppendList(pParse, yymsp[-5].minor.yy131, pFromClause); + } + sqlite3Update(pParse,yymsp[-5].minor.yy131,yymsp[-2].minor.yy322,yymsp[0].minor.yy528,yymsp[-6].minor.yy394,0,0,0); } break; case 158: /* setlist ::= setlist COMMA nm EQ expr */ { - yymsp[-4].minor.yy562 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy562, yymsp[0].minor.yy626); - sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy562, &yymsp[-2].minor.yy0, 1); + yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy322, yymsp[0].minor.yy528); + sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy322, &yymsp[-2].minor.yy0, 1); } break; case 159: /* setlist ::= setlist COMMA LP idlist RP EQ expr */ { - yymsp[-6].minor.yy562 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy562, yymsp[-3].minor.yy240, yymsp[0].minor.yy626); + yymsp[-6].minor.yy322 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy322, yymsp[-3].minor.yy254, yymsp[0].minor.yy528); } break; case 160: /* setlist ::= nm EQ expr */ { - yylhsminor.yy562 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy626); - sqlite3ExprListSetName(pParse, yylhsminor.yy562, &yymsp[-2].minor.yy0, 1); + yylhsminor.yy322 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy528); + sqlite3ExprListSetName(pParse, yylhsminor.yy322, &yymsp[-2].minor.yy0, 1); } - yymsp[-2].minor.yy562 = yylhsminor.yy562; + yymsp[-2].minor.yy322 = yylhsminor.yy322; break; case 161: /* setlist ::= LP idlist RP EQ expr */ { - yymsp[-4].minor.yy562 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy240, yymsp[0].minor.yy626); + yymsp[-4].minor.yy322 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy254, yymsp[0].minor.yy528); } break; case 162: /* cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */ { - sqlite3Insert(pParse, yymsp[-3].minor.yy607, yymsp[-1].minor.yy303, yymsp[-2].minor.yy240, yymsp[-5].minor.yy64, yymsp[0].minor.yy138); + sqlite3Insert(pParse, yymsp[-3].minor.yy131, yymsp[-1].minor.yy47, yymsp[-2].minor.yy254, yymsp[-5].minor.yy394, yymsp[0].minor.yy444); } break; case 163: /* cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */ { - sqlite3Insert(pParse, yymsp[-4].minor.yy607, 0, yymsp[-3].minor.yy240, yymsp[-6].minor.yy64, 0); + sqlite3Insert(pParse, yymsp[-4].minor.yy131, 0, yymsp[-3].minor.yy254, yymsp[-6].minor.yy394, 0); } break; case 164: /* upsert ::= */ -{ yymsp[1].minor.yy138 = 0; } +{ yymsp[1].minor.yy444 = 0; } break; case 165: /* upsert ::= RETURNING selcollist */ -{ yymsp[-1].minor.yy138 = 0; sqlite3AddReturning(pParse,yymsp[0].minor.yy562); } +{ yymsp[-1].minor.yy444 = 0; sqlite3AddReturning(pParse,yymsp[0].minor.yy322); } break; case 166: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */ -{ yymsp[-11].minor.yy138 = sqlite3UpsertNew(pParse->db,yymsp[-8].minor.yy562,yymsp[-6].minor.yy626,yymsp[-2].minor.yy562,yymsp[-1].minor.yy626,yymsp[0].minor.yy138);} +{ yymsp[-11].minor.yy444 = sqlite3UpsertNew(pParse->db,yymsp[-8].minor.yy322,yymsp[-6].minor.yy528,yymsp[-2].minor.yy322,yymsp[-1].minor.yy528,yymsp[0].minor.yy444);} break; case 167: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */ -{ yymsp[-8].minor.yy138 = sqlite3UpsertNew(pParse->db,yymsp[-5].minor.yy562,yymsp[-3].minor.yy626,0,0,yymsp[0].minor.yy138); } +{ yymsp[-8].minor.yy444 = sqlite3UpsertNew(pParse->db,yymsp[-5].minor.yy322,yymsp[-3].minor.yy528,0,0,yymsp[0].minor.yy444); } break; case 168: /* upsert ::= ON CONFLICT DO NOTHING returning */ -{ yymsp[-4].minor.yy138 = sqlite3UpsertNew(pParse->db,0,0,0,0,0); } +{ yymsp[-4].minor.yy444 = sqlite3UpsertNew(pParse->db,0,0,0,0,0); } break; case 169: /* upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */ -{ yymsp[-7].minor.yy138 = sqlite3UpsertNew(pParse->db,0,0,yymsp[-2].minor.yy562,yymsp[-1].minor.yy626,0);} +{ yymsp[-7].minor.yy444 = sqlite3UpsertNew(pParse->db,0,0,yymsp[-2].minor.yy322,yymsp[-1].minor.yy528,0);} break; case 170: /* returning ::= RETURNING selcollist */ -{sqlite3AddReturning(pParse,yymsp[0].minor.yy562);} +{sqlite3AddReturning(pParse,yymsp[0].minor.yy322);} + break; + case 173: /* idlist_opt ::= */ +{yymsp[1].minor.yy254 = 0;} break; case 174: /* idlist_opt ::= LP idlist RP */ -{yymsp[-2].minor.yy240 = yymsp[-1].minor.yy240;} +{yymsp[-2].minor.yy254 = yymsp[-1].minor.yy254;} break; case 175: /* idlist ::= idlist COMMA nm */ -{yymsp[-2].minor.yy240 = sqlite3IdListAppend(pParse,yymsp[-2].minor.yy240,&yymsp[0].minor.yy0);} +{yymsp[-2].minor.yy254 = sqlite3IdListAppend(pParse,yymsp[-2].minor.yy254,&yymsp[0].minor.yy0);} break; case 176: /* idlist ::= nm */ -{yymsp[0].minor.yy240 = sqlite3IdListAppend(pParse,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/} +{yymsp[0].minor.yy254 = sqlite3IdListAppend(pParse,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/} break; case 177: /* expr ::= LP expr RP */ -{yymsp[-2].minor.yy626 = yymsp[-1].minor.yy626;} +{yymsp[-2].minor.yy528 = yymsp[-1].minor.yy528;} break; case 178: /* expr ::= ID|INDEXED */ case 179: /* expr ::= JOIN_KW */ yytestcase(yyruleno==179); -{yymsp[0].minor.yy626=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/} +{yymsp[0].minor.yy528=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/} break; case 180: /* expr ::= nm DOT nm */ { - Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1); - Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1); - if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenMap(pParse, (void*)temp2, &yymsp[0].minor.yy0); - sqlite3RenameTokenMap(pParse, (void*)temp1, &yymsp[-2].minor.yy0); - } - yylhsminor.yy626 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2); + Expr *temp1 = tokenExpr(pParse,TK_ID,yymsp[-2].minor.yy0); + Expr *temp2 = tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); + yylhsminor.yy528 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2); } - yymsp[-2].minor.yy626 = yylhsminor.yy626; + yymsp[-2].minor.yy528 = yylhsminor.yy528; break; case 181: /* expr ::= nm DOT nm DOT nm */ { - Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-4].minor.yy0, 1); - Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1); - Expr *temp3 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1); + Expr *temp1 = tokenExpr(pParse,TK_ID,yymsp[-4].minor.yy0); + Expr *temp2 = tokenExpr(pParse,TK_ID,yymsp[-2].minor.yy0); + Expr *temp3 = tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3); if( IN_RENAME_OBJECT ){ - sqlite3RenameTokenMap(pParse, (void*)temp3, &yymsp[0].minor.yy0); - sqlite3RenameTokenMap(pParse, (void*)temp2, &yymsp[-2].minor.yy0); + sqlite3RenameTokenRemap(pParse, 0, temp1); } - yylhsminor.yy626 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4); + yylhsminor.yy528 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4); } - yymsp[-4].minor.yy626 = yylhsminor.yy626; + yymsp[-4].minor.yy528 = yylhsminor.yy528; break; case 182: /* term ::= NULL|FLOAT|BLOB */ case 183: /* term ::= STRING */ yytestcase(yyruleno==183); -{yymsp[0].minor.yy626=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/} +{yymsp[0].minor.yy528=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/} break; case 184: /* term ::= INTEGER */ { - yylhsminor.yy626 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1); + yylhsminor.yy528 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1); + if( yylhsminor.yy528 ) yylhsminor.yy528->w.iOfst = (int)(yymsp[0].minor.yy0.z - pParse->zTail); } - yymsp[0].minor.yy626 = yylhsminor.yy626; + yymsp[0].minor.yy528 = yylhsminor.yy528; break; case 185: /* expr ::= VARIABLE */ { if( !(yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1])) ){ u32 n = yymsp[0].minor.yy0.n; - yymsp[0].minor.yy626 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0); - sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy626, n); + yymsp[0].minor.yy528 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0); + sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy528, n); }else{ /* When doing a nested parse, one can include terms in an expression ** that look like this: #1 #2 ... These terms refer to registers @@ -163738,65 +167870,65 @@ static YYACTIONTYPE yy_reduce( assert( t.n>=2 ); if( pParse->nested==0 ){ sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &t); - yymsp[0].minor.yy626 = 0; + yymsp[0].minor.yy528 = 0; }else{ - yymsp[0].minor.yy626 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0); - if( yymsp[0].minor.yy626 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy626->iTable); + yymsp[0].minor.yy528 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0); + if( yymsp[0].minor.yy528 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy528->iTable); } } } break; case 186: /* expr ::= expr COLLATE ID|STRING */ { - yymsp[-2].minor.yy626 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy626, &yymsp[0].minor.yy0, 1); + yymsp[-2].minor.yy528 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy528, &yymsp[0].minor.yy0, 1); } break; case 187: /* expr ::= CAST LP expr AS typetoken RP */ { - yymsp[-5].minor.yy626 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1); - sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy626, yymsp[-3].minor.yy626, 0); + yymsp[-5].minor.yy528 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1); + sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy528, yymsp[-3].minor.yy528, 0); } break; case 188: /* expr ::= ID|INDEXED LP distinct exprlist RP */ { - yylhsminor.yy626 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy562, &yymsp[-4].minor.yy0, yymsp[-2].minor.yy64); + yylhsminor.yy528 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy322, &yymsp[-4].minor.yy0, yymsp[-2].minor.yy394); } - yymsp[-4].minor.yy626 = yylhsminor.yy626; + yymsp[-4].minor.yy528 = yylhsminor.yy528; break; case 189: /* expr ::= ID|INDEXED LP STAR RP */ { - yylhsminor.yy626 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0, 0); + yylhsminor.yy528 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0, 0); } - yymsp[-3].minor.yy626 = yylhsminor.yy626; + yymsp[-3].minor.yy528 = yylhsminor.yy528; break; case 190: /* expr ::= ID|INDEXED LP distinct exprlist RP filter_over */ { - yylhsminor.yy626 = sqlite3ExprFunction(pParse, yymsp[-2].minor.yy562, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy64); - sqlite3WindowAttach(pParse, yylhsminor.yy626, yymsp[0].minor.yy375); + yylhsminor.yy528 = sqlite3ExprFunction(pParse, yymsp[-2].minor.yy322, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy394); + sqlite3WindowAttach(pParse, yylhsminor.yy528, yymsp[0].minor.yy41); } - yymsp[-5].minor.yy626 = yylhsminor.yy626; + yymsp[-5].minor.yy528 = yylhsminor.yy528; break; case 191: /* expr ::= ID|INDEXED LP STAR RP filter_over */ { - yylhsminor.yy626 = sqlite3ExprFunction(pParse, 0, &yymsp[-4].minor.yy0, 0); - sqlite3WindowAttach(pParse, yylhsminor.yy626, yymsp[0].minor.yy375); + yylhsminor.yy528 = sqlite3ExprFunction(pParse, 0, &yymsp[-4].minor.yy0, 0); + sqlite3WindowAttach(pParse, yylhsminor.yy528, yymsp[0].minor.yy41); } - yymsp[-4].minor.yy626 = yylhsminor.yy626; + yymsp[-4].minor.yy528 = yylhsminor.yy528; break; case 192: /* term ::= CTIME_KW */ { - yylhsminor.yy626 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0, 0); + yylhsminor.yy528 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0, 0); } - yymsp[0].minor.yy626 = yylhsminor.yy626; + yymsp[0].minor.yy528 = yylhsminor.yy528; break; case 193: /* expr ::= LP nexprlist COMMA expr RP */ { - ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy562, yymsp[-1].minor.yy626); - yymsp[-4].minor.yy626 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); - if( yymsp[-4].minor.yy626 ){ - yymsp[-4].minor.yy626->x.pList = pList; + ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy322, yymsp[-1].minor.yy528); + yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); + if( yymsp[-4].minor.yy528 ){ + yymsp[-4].minor.yy528->x.pList = pList; if( ALWAYS(pList->nExpr) ){ - yymsp[-4].minor.yy626->flags |= pList->a[0].pExpr->flags & EP_Propagate; + yymsp[-4].minor.yy528->flags |= pList->a[0].pExpr->flags & EP_Propagate; } }else{ sqlite3ExprListDelete(pParse->db, pList); @@ -163804,7 +167936,7 @@ static YYACTIONTYPE yy_reduce( } break; case 194: /* expr ::= expr AND expr */ -{yymsp[-2].minor.yy626=sqlite3ExprAnd(pParse,yymsp[-2].minor.yy626,yymsp[0].minor.yy626);} +{yymsp[-2].minor.yy528=sqlite3ExprAnd(pParse,yymsp[-2].minor.yy528,yymsp[0].minor.yy528);} break; case 195: /* expr ::= expr OR expr */ case 196: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==196); @@ -163813,7 +167945,7 @@ static YYACTIONTYPE yy_reduce( case 199: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==199); case 200: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==200); case 201: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==201); -{yymsp[-2].minor.yy626=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy626,yymsp[0].minor.yy626);} +{yymsp[-2].minor.yy528=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy528,yymsp[0].minor.yy528);} break; case 202: /* likeop ::= NOT LIKE_KW|MATCH */ {yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.n|=0x80000000; /*yymsp[-1].minor.yy0-overwrite-yymsp[0].minor.yy0*/} @@ -163823,11 +167955,11 @@ static YYACTIONTYPE yy_reduce( ExprList *pList; int bNot = yymsp[-1].minor.yy0.n & 0x80000000; yymsp[-1].minor.yy0.n &= 0x7fffffff; - pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy626); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy626); - yymsp[-2].minor.yy626 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0); - if( bNot ) yymsp[-2].minor.yy626 = sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy626, 0); - if( yymsp[-2].minor.yy626 ) yymsp[-2].minor.yy626->flags |= EP_InfixFunc; + pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy528); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy528); + yymsp[-2].minor.yy528 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0); + if( bNot ) yymsp[-2].minor.yy528 = sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy528, 0); + if( yymsp[-2].minor.yy528 ) yymsp[-2].minor.yy528->flags |= EP_InfixFunc; } break; case 204: /* expr ::= expr likeop expr ESCAPE expr */ @@ -163835,62 +167967,82 @@ static YYACTIONTYPE yy_reduce( ExprList *pList; int bNot = yymsp[-3].minor.yy0.n & 0x80000000; yymsp[-3].minor.yy0.n &= 0x7fffffff; - pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy626); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy626); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy626); - yymsp[-4].minor.yy626 = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0, 0); - if( bNot ) yymsp[-4].minor.yy626 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy626, 0); - if( yymsp[-4].minor.yy626 ) yymsp[-4].minor.yy626->flags |= EP_InfixFunc; + pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy528); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy528); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy528); + yymsp[-4].minor.yy528 = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0, 0); + if( bNot ) yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy528, 0); + if( yymsp[-4].minor.yy528 ) yymsp[-4].minor.yy528->flags |= EP_InfixFunc; } break; case 205: /* expr ::= expr ISNULL|NOTNULL */ -{yymsp[-1].minor.yy626 = sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy626,0);} +{yymsp[-1].minor.yy528 = sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy528,0);} break; case 206: /* expr ::= expr NOT NULL */ -{yymsp[-2].minor.yy626 = sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy626,0);} +{yymsp[-2].minor.yy528 = sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy528,0);} break; case 207: /* expr ::= expr IS expr */ { - yymsp[-2].minor.yy626 = sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy626,yymsp[0].minor.yy626); - binaryToUnaryIfNull(pParse, yymsp[0].minor.yy626, yymsp[-2].minor.yy626, TK_ISNULL); + yymsp[-2].minor.yy528 = sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy528,yymsp[0].minor.yy528); + binaryToUnaryIfNull(pParse, yymsp[0].minor.yy528, yymsp[-2].minor.yy528, TK_ISNULL); } break; case 208: /* expr ::= expr IS NOT expr */ { - yymsp[-3].minor.yy626 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy626,yymsp[0].minor.yy626); - binaryToUnaryIfNull(pParse, yymsp[0].minor.yy626, yymsp[-3].minor.yy626, TK_NOTNULL); + yymsp[-3].minor.yy528 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy528,yymsp[0].minor.yy528); + binaryToUnaryIfNull(pParse, yymsp[0].minor.yy528, yymsp[-3].minor.yy528, TK_NOTNULL); +} + break; + case 209: /* expr ::= expr IS NOT DISTINCT FROM expr */ +{ + yymsp[-5].minor.yy528 = sqlite3PExpr(pParse,TK_IS,yymsp[-5].minor.yy528,yymsp[0].minor.yy528); + binaryToUnaryIfNull(pParse, yymsp[0].minor.yy528, yymsp[-5].minor.yy528, TK_ISNULL); +} + break; + case 210: /* expr ::= expr IS DISTINCT FROM expr */ +{ + yymsp[-4].minor.yy528 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-4].minor.yy528,yymsp[0].minor.yy528); + binaryToUnaryIfNull(pParse, yymsp[0].minor.yy528, yymsp[-4].minor.yy528, TK_NOTNULL); } break; - case 209: /* expr ::= NOT expr */ - case 210: /* expr ::= BITNOT expr */ yytestcase(yyruleno==210); -{yymsp[-1].minor.yy626 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy626, 0);/*A-overwrites-B*/} + case 211: /* expr ::= NOT expr */ + case 212: /* expr ::= BITNOT expr */ yytestcase(yyruleno==212); +{yymsp[-1].minor.yy528 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy528, 0);/*A-overwrites-B*/} break; - case 211: /* expr ::= PLUS|MINUS expr */ + case 213: /* expr ::= PLUS|MINUS expr */ { - yymsp[-1].minor.yy626 = sqlite3PExpr(pParse, yymsp[-1].major==TK_PLUS ? TK_UPLUS : TK_UMINUS, yymsp[0].minor.yy626, 0); + yymsp[-1].minor.yy528 = sqlite3PExpr(pParse, yymsp[-1].major==TK_PLUS ? TK_UPLUS : TK_UMINUS, yymsp[0].minor.yy528, 0); /*A-overwrites-B*/ } break; - case 212: /* between_op ::= BETWEEN */ - case 215: /* in_op ::= IN */ yytestcase(yyruleno==215); -{yymsp[0].minor.yy64 = 0;} + case 214: /* expr ::= expr PTR expr */ +{ + ExprList *pList = sqlite3ExprListAppend(pParse, 0, yymsp[-2].minor.yy528); + pList = sqlite3ExprListAppend(pParse, pList, yymsp[0].minor.yy528); + yylhsminor.yy528 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0); +} + yymsp[-2].minor.yy528 = yylhsminor.yy528; + break; + case 215: /* between_op ::= BETWEEN */ + case 218: /* in_op ::= IN */ yytestcase(yyruleno==218); +{yymsp[0].minor.yy394 = 0;} break; - case 214: /* expr ::= expr between_op expr AND expr */ + case 217: /* expr ::= expr between_op expr AND expr */ { - ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy626); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy626); - yymsp[-4].minor.yy626 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy626, 0); - if( yymsp[-4].minor.yy626 ){ - yymsp[-4].minor.yy626->x.pList = pList; + ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy528); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy528); + yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy528, 0); + if( yymsp[-4].minor.yy528 ){ + yymsp[-4].minor.yy528->x.pList = pList; }else{ sqlite3ExprListDelete(pParse->db, pList); } - if( yymsp[-3].minor.yy64 ) yymsp[-4].minor.yy626 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy626, 0); + if( yymsp[-3].minor.yy394 ) yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy528, 0); } break; - case 217: /* expr ::= expr in_op LP exprlist RP */ + case 220: /* expr ::= expr in_op LP exprlist RP */ { - if( yymsp[-1].minor.yy562==0 ){ + if( yymsp[-1].minor.yy322==0 ){ /* Expressions of the form ** ** expr1 IN () @@ -163899,205 +168051,206 @@ static YYACTIONTYPE yy_reduce( ** simplify to constants 0 (false) and 1 (true), respectively, ** regardless of the value of expr1. */ - sqlite3ExprUnmapAndDelete(pParse, yymsp[-4].minor.yy626); - yymsp[-4].minor.yy626 = sqlite3Expr(pParse->db, TK_INTEGER, yymsp[-3].minor.yy64 ? "1" : "0"); - }else{ - Expr *pRHS = yymsp[-1].minor.yy562->a[0].pExpr; - if( yymsp[-1].minor.yy562->nExpr==1 && sqlite3ExprIsConstant(pRHS) && yymsp[-4].minor.yy626->op!=TK_VECTOR ){ - yymsp[-1].minor.yy562->a[0].pExpr = 0; - sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy562); + sqlite3ExprUnmapAndDelete(pParse, yymsp[-4].minor.yy528); + yymsp[-4].minor.yy528 = sqlite3Expr(pParse->db, TK_STRING, yymsp[-3].minor.yy394 ? "true" : "false"); + if( yymsp[-4].minor.yy528 ) sqlite3ExprIdToTrueFalse(yymsp[-4].minor.yy528); + }else{ + Expr *pRHS = yymsp[-1].minor.yy322->a[0].pExpr; + if( yymsp[-1].minor.yy322->nExpr==1 && sqlite3ExprIsConstant(pRHS) && yymsp[-4].minor.yy528->op!=TK_VECTOR ){ + yymsp[-1].minor.yy322->a[0].pExpr = 0; + sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy322); pRHS = sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0); - yymsp[-4].minor.yy626 = sqlite3PExpr(pParse, TK_EQ, yymsp[-4].minor.yy626, pRHS); + yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_EQ, yymsp[-4].minor.yy528, pRHS); }else{ - yymsp[-4].minor.yy626 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy626, 0); - if( yymsp[-4].minor.yy626==0 ){ - sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy562); - }else if( yymsp[-4].minor.yy626->pLeft->op==TK_VECTOR ){ - int nExpr = yymsp[-4].minor.yy626->pLeft->x.pList->nExpr; - Select *pSelectRHS = sqlite3ExprListToValues(pParse, nExpr, yymsp[-1].minor.yy562); + yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy528, 0); + if( yymsp[-4].minor.yy528==0 ){ + sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy322); + }else if( yymsp[-4].minor.yy528->pLeft->op==TK_VECTOR ){ + int nExpr = yymsp[-4].minor.yy528->pLeft->x.pList->nExpr; + Select *pSelectRHS = sqlite3ExprListToValues(pParse, nExpr, yymsp[-1].minor.yy322); if( pSelectRHS ){ parserDoubleLinkSelect(pParse, pSelectRHS); - sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy626, pSelectRHS); + sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy528, pSelectRHS); } }else{ - yymsp[-4].minor.yy626->x.pList = yymsp[-1].minor.yy562; - sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy626); + yymsp[-4].minor.yy528->x.pList = yymsp[-1].minor.yy322; + sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy528); } } - if( yymsp[-3].minor.yy64 ) yymsp[-4].minor.yy626 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy626, 0); + if( yymsp[-3].minor.yy394 ) yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy528, 0); } } break; - case 218: /* expr ::= LP select RP */ + case 221: /* expr ::= LP select RP */ { - yymsp[-2].minor.yy626 = sqlite3PExpr(pParse, TK_SELECT, 0, 0); - sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy626, yymsp[-1].minor.yy303); + yymsp[-2].minor.yy528 = sqlite3PExpr(pParse, TK_SELECT, 0, 0); + sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy528, yymsp[-1].minor.yy47); } break; - case 219: /* expr ::= expr in_op LP select RP */ + case 222: /* expr ::= expr in_op LP select RP */ { - yymsp[-4].minor.yy626 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy626, 0); - sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy626, yymsp[-1].minor.yy303); - if( yymsp[-3].minor.yy64 ) yymsp[-4].minor.yy626 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy626, 0); + yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy528, 0); + sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy528, yymsp[-1].minor.yy47); + if( yymsp[-3].minor.yy394 ) yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy528, 0); } break; - case 220: /* expr ::= expr in_op nm dbnm paren_exprlist */ + case 223: /* expr ::= expr in_op nm dbnm paren_exprlist */ { SrcList *pSrc = sqlite3SrcListAppend(pParse, 0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0); - if( yymsp[0].minor.yy562 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy562); - yymsp[-4].minor.yy626 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy626, 0); - sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy626, pSelect); - if( yymsp[-3].minor.yy64 ) yymsp[-4].minor.yy626 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy626, 0); + if( yymsp[0].minor.yy322 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy322); + yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy528, 0); + sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy528, pSelect); + if( yymsp[-3].minor.yy394 ) yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy528, 0); } break; - case 221: /* expr ::= EXISTS LP select RP */ + case 224: /* expr ::= EXISTS LP select RP */ { Expr *p; - p = yymsp[-3].minor.yy626 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0); - sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy303); + p = yymsp[-3].minor.yy528 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0); + sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy47); } break; - case 222: /* expr ::= CASE case_operand case_exprlist case_else END */ + case 225: /* expr ::= CASE case_operand case_exprlist case_else END */ { - yymsp[-4].minor.yy626 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy626, 0); - if( yymsp[-4].minor.yy626 ){ - yymsp[-4].minor.yy626->x.pList = yymsp[-1].minor.yy626 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy562,yymsp[-1].minor.yy626) : yymsp[-2].minor.yy562; - sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy626); + yymsp[-4].minor.yy528 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy528, 0); + if( yymsp[-4].minor.yy528 ){ + yymsp[-4].minor.yy528->x.pList = yymsp[-1].minor.yy528 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy322,yymsp[-1].minor.yy528) : yymsp[-2].minor.yy322; + sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy528); }else{ - sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy562); - sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy626); + sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy322); + sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy528); } } break; - case 223: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ + case 226: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ { - yymsp[-4].minor.yy562 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy562, yymsp[-2].minor.yy626); - yymsp[-4].minor.yy562 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy562, yymsp[0].minor.yy626); + yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322, yymsp[-2].minor.yy528); + yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322, yymsp[0].minor.yy528); } break; - case 224: /* case_exprlist ::= WHEN expr THEN expr */ + case 227: /* case_exprlist ::= WHEN expr THEN expr */ { - yymsp[-3].minor.yy562 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy626); - yymsp[-3].minor.yy562 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy562, yymsp[0].minor.yy626); + yymsp[-3].minor.yy322 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy528); + yymsp[-3].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy322, yymsp[0].minor.yy528); } break; - case 227: /* case_operand ::= expr */ -{yymsp[0].minor.yy626 = yymsp[0].minor.yy626; /*A-overwrites-X*/} + case 230: /* case_operand ::= expr */ +{yymsp[0].minor.yy528 = yymsp[0].minor.yy528; /*A-overwrites-X*/} break; - case 230: /* nexprlist ::= nexprlist COMMA expr */ -{yymsp[-2].minor.yy562 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy562,yymsp[0].minor.yy626);} + case 233: /* nexprlist ::= nexprlist COMMA expr */ +{yymsp[-2].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy322,yymsp[0].minor.yy528);} break; - case 231: /* nexprlist ::= expr */ -{yymsp[0].minor.yy562 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy626); /*A-overwrites-Y*/} + case 234: /* nexprlist ::= expr */ +{yymsp[0].minor.yy322 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy528); /*A-overwrites-Y*/} break; - case 233: /* paren_exprlist ::= LP exprlist RP */ - case 238: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==238); -{yymsp[-2].minor.yy562 = yymsp[-1].minor.yy562;} + case 236: /* paren_exprlist ::= LP exprlist RP */ + case 241: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==241); +{yymsp[-2].minor.yy322 = yymsp[-1].minor.yy322;} break; - case 234: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ + case 237: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ { sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, - sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy562, yymsp[-10].minor.yy64, - &yymsp[-11].minor.yy0, yymsp[0].minor.yy626, SQLITE_SO_ASC, yymsp[-8].minor.yy64, SQLITE_IDXTYPE_APPDEF); + sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy322, yymsp[-10].minor.yy394, + &yymsp[-11].minor.yy0, yymsp[0].minor.yy528, SQLITE_SO_ASC, yymsp[-8].minor.yy394, SQLITE_IDXTYPE_APPDEF); if( IN_RENAME_OBJECT && pParse->pNewIndex ){ sqlite3RenameTokenMap(pParse, pParse->pNewIndex->zName, &yymsp[-4].minor.yy0); } } break; - case 235: /* uniqueflag ::= UNIQUE */ - case 277: /* raisetype ::= ABORT */ yytestcase(yyruleno==277); -{yymsp[0].minor.yy64 = OE_Abort;} + case 238: /* uniqueflag ::= UNIQUE */ + case 280: /* raisetype ::= ABORT */ yytestcase(yyruleno==280); +{yymsp[0].minor.yy394 = OE_Abort;} break; - case 236: /* uniqueflag ::= */ -{yymsp[1].minor.yy64 = OE_None;} + case 239: /* uniqueflag ::= */ +{yymsp[1].minor.yy394 = OE_None;} break; - case 239: /* eidlist ::= eidlist COMMA nm collate sortorder */ + case 242: /* eidlist ::= eidlist COMMA nm collate sortorder */ { - yymsp[-4].minor.yy562 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy562, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy64, yymsp[0].minor.yy64); + yymsp[-4].minor.yy322 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy322, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy394, yymsp[0].minor.yy394); } break; - case 240: /* eidlist ::= nm collate sortorder */ + case 243: /* eidlist ::= nm collate sortorder */ { - yymsp[-2].minor.yy562 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy64, yymsp[0].minor.yy64); /*A-overwrites-Y*/ + yymsp[-2].minor.yy322 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy394, yymsp[0].minor.yy394); /*A-overwrites-Y*/ } break; - case 243: /* cmd ::= DROP INDEX ifexists fullname */ -{sqlite3DropIndex(pParse, yymsp[0].minor.yy607, yymsp[-1].minor.yy64);} + case 246: /* cmd ::= DROP INDEX ifexists fullname */ +{sqlite3DropIndex(pParse, yymsp[0].minor.yy131, yymsp[-1].minor.yy394);} break; - case 244: /* cmd ::= VACUUM vinto */ -{sqlite3Vacuum(pParse,0,yymsp[0].minor.yy626);} + case 247: /* cmd ::= VACUUM vinto */ +{sqlite3Vacuum(pParse,0,yymsp[0].minor.yy528);} break; - case 245: /* cmd ::= VACUUM nm vinto */ -{sqlite3Vacuum(pParse,&yymsp[-1].minor.yy0,yymsp[0].minor.yy626);} + case 248: /* cmd ::= VACUUM nm vinto */ +{sqlite3Vacuum(pParse,&yymsp[-1].minor.yy0,yymsp[0].minor.yy528);} break; - case 248: /* cmd ::= PRAGMA nm dbnm */ + case 251: /* cmd ::= PRAGMA nm dbnm */ {sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);} break; - case 249: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ + case 252: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);} break; - case 250: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ + case 253: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);} break; - case 251: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ + case 254: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);} break; - case 252: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ + case 255: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);} break; - case 255: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ + case 258: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ { Token all; all.z = yymsp[-3].minor.yy0.z; all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n; - sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy95, &all); + sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy33, &all); } break; - case 256: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ + case 259: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ { - sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy64, yymsp[-4].minor.yy570.a, yymsp[-4].minor.yy570.b, yymsp[-2].minor.yy607, yymsp[0].minor.yy626, yymsp[-10].minor.yy64, yymsp[-8].minor.yy64); + sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy394, yymsp[-4].minor.yy180.a, yymsp[-4].minor.yy180.b, yymsp[-2].minor.yy131, yymsp[0].minor.yy528, yymsp[-10].minor.yy394, yymsp[-8].minor.yy394); yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/ } break; - case 257: /* trigger_time ::= BEFORE|AFTER */ -{ yymsp[0].minor.yy64 = yymsp[0].major; /*A-overwrites-X*/ } + case 260: /* trigger_time ::= BEFORE|AFTER */ +{ yymsp[0].minor.yy394 = yymsp[0].major; /*A-overwrites-X*/ } break; - case 258: /* trigger_time ::= INSTEAD OF */ -{ yymsp[-1].minor.yy64 = TK_INSTEAD;} + case 261: /* trigger_time ::= INSTEAD OF */ +{ yymsp[-1].minor.yy394 = TK_INSTEAD;} break; - case 259: /* trigger_time ::= */ -{ yymsp[1].minor.yy64 = TK_BEFORE; } + case 262: /* trigger_time ::= */ +{ yymsp[1].minor.yy394 = TK_BEFORE; } break; - case 260: /* trigger_event ::= DELETE|INSERT */ - case 261: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==261); -{yymsp[0].minor.yy570.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy570.b = 0;} + case 263: /* trigger_event ::= DELETE|INSERT */ + case 264: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==264); +{yymsp[0].minor.yy180.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy180.b = 0;} break; - case 262: /* trigger_event ::= UPDATE OF idlist */ -{yymsp[-2].minor.yy570.a = TK_UPDATE; yymsp[-2].minor.yy570.b = yymsp[0].minor.yy240;} + case 265: /* trigger_event ::= UPDATE OF idlist */ +{yymsp[-2].minor.yy180.a = TK_UPDATE; yymsp[-2].minor.yy180.b = yymsp[0].minor.yy254;} break; - case 263: /* when_clause ::= */ - case 282: /* key_opt ::= */ yytestcase(yyruleno==282); -{ yymsp[1].minor.yy626 = 0; } + case 266: /* when_clause ::= */ + case 285: /* key_opt ::= */ yytestcase(yyruleno==285); +{ yymsp[1].minor.yy528 = 0; } break; - case 264: /* when_clause ::= WHEN expr */ - case 283: /* key_opt ::= KEY expr */ yytestcase(yyruleno==283); -{ yymsp[-1].minor.yy626 = yymsp[0].minor.yy626; } + case 267: /* when_clause ::= WHEN expr */ + case 286: /* key_opt ::= KEY expr */ yytestcase(yyruleno==286); +{ yymsp[-1].minor.yy528 = yymsp[0].minor.yy528; } break; - case 265: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ + case 268: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ { - assert( yymsp[-2].minor.yy95!=0 ); - yymsp[-2].minor.yy95->pLast->pNext = yymsp[-1].minor.yy95; - yymsp[-2].minor.yy95->pLast = yymsp[-1].minor.yy95; + assert( yymsp[-2].minor.yy33!=0 ); + yymsp[-2].minor.yy33->pLast->pNext = yymsp[-1].minor.yy33; + yymsp[-2].minor.yy33->pLast = yymsp[-1].minor.yy33; } break; - case 266: /* trigger_cmd_list ::= trigger_cmd SEMI */ + case 269: /* trigger_cmd_list ::= trigger_cmd SEMI */ { - assert( yymsp[-1].minor.yy95!=0 ); - yymsp[-1].minor.yy95->pLast = yymsp[-1].minor.yy95; + assert( yymsp[-1].minor.yy33!=0 ); + yymsp[-1].minor.yy33->pLast = yymsp[-1].minor.yy33; } break; - case 267: /* trnm ::= nm DOT nm */ + case 270: /* trnm ::= nm DOT nm */ { yymsp[-2].minor.yy0 = yymsp[0].minor.yy0; sqlite3ErrorMsg(pParse, @@ -164105,369 +168258,370 @@ static YYACTIONTYPE yy_reduce( "statements within triggers"); } break; - case 268: /* tridxby ::= INDEXED BY nm */ + case 271: /* tridxby ::= INDEXED BY nm */ { sqlite3ErrorMsg(pParse, "the INDEXED BY clause is not allowed on UPDATE or DELETE statements " "within triggers"); } break; - case 269: /* tridxby ::= NOT INDEXED */ + case 272: /* tridxby ::= NOT INDEXED */ { sqlite3ErrorMsg(pParse, "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements " "within triggers"); } break; - case 270: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */ -{yylhsminor.yy95 = sqlite3TriggerUpdateStep(pParse, &yymsp[-6].minor.yy0, yymsp[-2].minor.yy607, yymsp[-3].minor.yy562, yymsp[-1].minor.yy626, yymsp[-7].minor.yy64, yymsp[-8].minor.yy0.z, yymsp[0].minor.yy600);} - yymsp[-8].minor.yy95 = yylhsminor.yy95; + case 273: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */ +{yylhsminor.yy33 = sqlite3TriggerUpdateStep(pParse, &yymsp[-6].minor.yy0, yymsp[-2].minor.yy131, yymsp[-3].minor.yy322, yymsp[-1].minor.yy528, yymsp[-7].minor.yy394, yymsp[-8].minor.yy0.z, yymsp[0].minor.yy522);} + yymsp[-8].minor.yy33 = yylhsminor.yy33; break; - case 271: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ + case 274: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */ { - yylhsminor.yy95 = sqlite3TriggerInsertStep(pParse,&yymsp[-4].minor.yy0,yymsp[-3].minor.yy240,yymsp[-2].minor.yy303,yymsp[-6].minor.yy64,yymsp[-1].minor.yy138,yymsp[-7].minor.yy600,yymsp[0].minor.yy600);/*yylhsminor.yy95-overwrites-yymsp[-6].minor.yy64*/ + yylhsminor.yy33 = sqlite3TriggerInsertStep(pParse,&yymsp[-4].minor.yy0,yymsp[-3].minor.yy254,yymsp[-2].minor.yy47,yymsp[-6].minor.yy394,yymsp[-1].minor.yy444,yymsp[-7].minor.yy522,yymsp[0].minor.yy522);/*yylhsminor.yy33-overwrites-yymsp[-6].minor.yy394*/ } - yymsp[-7].minor.yy95 = yylhsminor.yy95; + yymsp[-7].minor.yy33 = yylhsminor.yy33; break; - case 272: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ -{yylhsminor.yy95 = sqlite3TriggerDeleteStep(pParse, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy626, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy600);} - yymsp[-5].minor.yy95 = yylhsminor.yy95; + case 275: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ +{yylhsminor.yy33 = sqlite3TriggerDeleteStep(pParse, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy528, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy522);} + yymsp[-5].minor.yy33 = yylhsminor.yy33; break; - case 273: /* trigger_cmd ::= scanpt select scanpt */ -{yylhsminor.yy95 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy303, yymsp[-2].minor.yy600, yymsp[0].minor.yy600); /*yylhsminor.yy95-overwrites-yymsp[-1].minor.yy303*/} - yymsp[-2].minor.yy95 = yylhsminor.yy95; + case 276: /* trigger_cmd ::= scanpt select scanpt */ +{yylhsminor.yy33 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy47, yymsp[-2].minor.yy522, yymsp[0].minor.yy522); /*yylhsminor.yy33-overwrites-yymsp[-1].minor.yy47*/} + yymsp[-2].minor.yy33 = yylhsminor.yy33; break; - case 274: /* expr ::= RAISE LP IGNORE RP */ + case 277: /* expr ::= RAISE LP IGNORE RP */ { - yymsp[-3].minor.yy626 = sqlite3PExpr(pParse, TK_RAISE, 0, 0); - if( yymsp[-3].minor.yy626 ){ - yymsp[-3].minor.yy626->affExpr = OE_Ignore; + yymsp[-3].minor.yy528 = sqlite3PExpr(pParse, TK_RAISE, 0, 0); + if( yymsp[-3].minor.yy528 ){ + yymsp[-3].minor.yy528->affExpr = OE_Ignore; } } break; - case 275: /* expr ::= RAISE LP raisetype COMMA nm RP */ + case 278: /* expr ::= RAISE LP raisetype COMMA nm RP */ { - yymsp[-5].minor.yy626 = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1); - if( yymsp[-5].minor.yy626 ) { - yymsp[-5].minor.yy626->affExpr = (char)yymsp[-3].minor.yy64; + yymsp[-5].minor.yy528 = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1); + if( yymsp[-5].minor.yy528 ) { + yymsp[-5].minor.yy528->affExpr = (char)yymsp[-3].minor.yy394; } } break; - case 276: /* raisetype ::= ROLLBACK */ -{yymsp[0].minor.yy64 = OE_Rollback;} + case 279: /* raisetype ::= ROLLBACK */ +{yymsp[0].minor.yy394 = OE_Rollback;} break; - case 278: /* raisetype ::= FAIL */ -{yymsp[0].minor.yy64 = OE_Fail;} + case 281: /* raisetype ::= FAIL */ +{yymsp[0].minor.yy394 = OE_Fail;} break; - case 279: /* cmd ::= DROP TRIGGER ifexists fullname */ + case 282: /* cmd ::= DROP TRIGGER ifexists fullname */ { - sqlite3DropTrigger(pParse,yymsp[0].minor.yy607,yymsp[-1].minor.yy64); + sqlite3DropTrigger(pParse,yymsp[0].minor.yy131,yymsp[-1].minor.yy394); } break; - case 280: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ + case 283: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ { - sqlite3Attach(pParse, yymsp[-3].minor.yy626, yymsp[-1].minor.yy626, yymsp[0].minor.yy626); + sqlite3Attach(pParse, yymsp[-3].minor.yy528, yymsp[-1].minor.yy528, yymsp[0].minor.yy528); } break; - case 281: /* cmd ::= DETACH database_kw_opt expr */ + case 284: /* cmd ::= DETACH database_kw_opt expr */ { - sqlite3Detach(pParse, yymsp[0].minor.yy626); + sqlite3Detach(pParse, yymsp[0].minor.yy528); } break; - case 284: /* cmd ::= REINDEX */ + case 287: /* cmd ::= REINDEX */ {sqlite3Reindex(pParse, 0, 0);} break; - case 285: /* cmd ::= REINDEX nm dbnm */ + case 288: /* cmd ::= REINDEX nm dbnm */ {sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 286: /* cmd ::= ANALYZE */ + case 289: /* cmd ::= ANALYZE */ {sqlite3Analyze(pParse, 0, 0);} break; - case 287: /* cmd ::= ANALYZE nm dbnm */ + case 290: /* cmd ::= ANALYZE nm dbnm */ {sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 288: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ + case 291: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ { - sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy607,&yymsp[0].minor.yy0); + sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy131,&yymsp[0].minor.yy0); } break; - case 289: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ + case 292: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ { yymsp[-1].minor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-1].minor.yy0.z) + pParse->sLastToken.n; sqlite3AlterFinishAddColumn(pParse, &yymsp[-1].minor.yy0); } break; - case 290: /* cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */ + case 293: /* cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */ { - sqlite3AlterDropColumn(pParse, yymsp[-3].minor.yy607, &yymsp[0].minor.yy0); + sqlite3AlterDropColumn(pParse, yymsp[-3].minor.yy131, &yymsp[0].minor.yy0); } break; - case 291: /* add_column_fullname ::= fullname */ + case 294: /* add_column_fullname ::= fullname */ { disableLookaside(pParse); - sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy607); + sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy131); } break; - case 292: /* cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ + case 295: /* cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */ { - sqlite3AlterRenameColumn(pParse, yymsp[-5].minor.yy607, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); + sqlite3AlterRenameColumn(pParse, yymsp[-5].minor.yy131, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); } break; - case 293: /* cmd ::= create_vtab */ + case 296: /* cmd ::= create_vtab */ {sqlite3VtabFinishParse(pParse,0);} break; - case 294: /* cmd ::= create_vtab LP vtabarglist RP */ + case 297: /* cmd ::= create_vtab LP vtabarglist RP */ {sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);} break; - case 295: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ + case 298: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ { - sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy64); + sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy394); } break; - case 296: /* vtabarg ::= */ + case 299: /* vtabarg ::= */ {sqlite3VtabArgInit(pParse);} break; - case 297: /* vtabargtoken ::= ANY */ - case 298: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==298); - case 299: /* lp ::= LP */ yytestcase(yyruleno==299); + case 300: /* vtabargtoken ::= ANY */ + case 301: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==301); + case 302: /* lp ::= LP */ yytestcase(yyruleno==302); {sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);} break; - case 300: /* with ::= WITH wqlist */ - case 301: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==301); -{ sqlite3WithPush(pParse, yymsp[0].minor.yy43, 1); } + case 303: /* with ::= WITH wqlist */ + case 304: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==304); +{ sqlite3WithPush(pParse, yymsp[0].minor.yy521, 1); } break; - case 302: /* wqas ::= AS */ -{yymsp[0].minor.yy534 = M10d_Any;} + case 305: /* wqas ::= AS */ +{yymsp[0].minor.yy516 = M10d_Any;} break; - case 303: /* wqas ::= AS MATERIALIZED */ -{yymsp[-1].minor.yy534 = M10d_Yes;} + case 306: /* wqas ::= AS MATERIALIZED */ +{yymsp[-1].minor.yy516 = M10d_Yes;} break; - case 304: /* wqas ::= AS NOT MATERIALIZED */ -{yymsp[-2].minor.yy534 = M10d_No;} + case 307: /* wqas ::= AS NOT MATERIALIZED */ +{yymsp[-2].minor.yy516 = M10d_No;} break; - case 305: /* wqitem ::= nm eidlist_opt wqas LP select RP */ + case 308: /* wqitem ::= nm eidlist_opt wqas LP select RP */ { - yymsp[-5].minor.yy255 = sqlite3CteNew(pParse, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy562, yymsp[-1].minor.yy303, yymsp[-3].minor.yy534); /*A-overwrites-X*/ + yymsp[-5].minor.yy385 = sqlite3CteNew(pParse, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy322, yymsp[-1].minor.yy47, yymsp[-3].minor.yy516); /*A-overwrites-X*/ } break; - case 306: /* wqlist ::= wqitem */ + case 309: /* wqlist ::= wqitem */ { - yymsp[0].minor.yy43 = sqlite3WithAdd(pParse, 0, yymsp[0].minor.yy255); /*A-overwrites-X*/ + yymsp[0].minor.yy521 = sqlite3WithAdd(pParse, 0, yymsp[0].minor.yy385); /*A-overwrites-X*/ } break; - case 307: /* wqlist ::= wqlist COMMA wqitem */ + case 310: /* wqlist ::= wqlist COMMA wqitem */ { - yymsp[-2].minor.yy43 = sqlite3WithAdd(pParse, yymsp[-2].minor.yy43, yymsp[0].minor.yy255); + yymsp[-2].minor.yy521 = sqlite3WithAdd(pParse, yymsp[-2].minor.yy521, yymsp[0].minor.yy385); } break; - case 308: /* windowdefn_list ::= windowdefn */ -{ yylhsminor.yy375 = yymsp[0].minor.yy375; } - yymsp[0].minor.yy375 = yylhsminor.yy375; + case 311: /* windowdefn_list ::= windowdefn */ +{ yylhsminor.yy41 = yymsp[0].minor.yy41; } + yymsp[0].minor.yy41 = yylhsminor.yy41; break; - case 309: /* windowdefn_list ::= windowdefn_list COMMA windowdefn */ + case 312: /* windowdefn_list ::= windowdefn_list COMMA windowdefn */ { - assert( yymsp[0].minor.yy375!=0 ); - sqlite3WindowChain(pParse, yymsp[0].minor.yy375, yymsp[-2].minor.yy375); - yymsp[0].minor.yy375->pNextWin = yymsp[-2].minor.yy375; - yylhsminor.yy375 = yymsp[0].minor.yy375; + assert( yymsp[0].minor.yy41!=0 ); + sqlite3WindowChain(pParse, yymsp[0].minor.yy41, yymsp[-2].minor.yy41); + yymsp[0].minor.yy41->pNextWin = yymsp[-2].minor.yy41; + yylhsminor.yy41 = yymsp[0].minor.yy41; } - yymsp[-2].minor.yy375 = yylhsminor.yy375; + yymsp[-2].minor.yy41 = yylhsminor.yy41; break; - case 310: /* windowdefn ::= nm AS LP window RP */ + case 313: /* windowdefn ::= nm AS LP window RP */ { - if( ALWAYS(yymsp[-1].minor.yy375) ){ - yymsp[-1].minor.yy375->zName = sqlite3DbStrNDup(pParse->db, yymsp[-4].minor.yy0.z, yymsp[-4].minor.yy0.n); + if( ALWAYS(yymsp[-1].minor.yy41) ){ + yymsp[-1].minor.yy41->zName = sqlite3DbStrNDup(pParse->db, yymsp[-4].minor.yy0.z, yymsp[-4].minor.yy0.n); } - yylhsminor.yy375 = yymsp[-1].minor.yy375; + yylhsminor.yy41 = yymsp[-1].minor.yy41; } - yymsp[-4].minor.yy375 = yylhsminor.yy375; + yymsp[-4].minor.yy41 = yylhsminor.yy41; break; - case 311: /* window ::= PARTITION BY nexprlist orderby_opt frame_opt */ + case 314: /* window ::= PARTITION BY nexprlist orderby_opt frame_opt */ { - yymsp[-4].minor.yy375 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy375, yymsp[-2].minor.yy562, yymsp[-1].minor.yy562, 0); + yymsp[-4].minor.yy41 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy41, yymsp[-2].minor.yy322, yymsp[-1].minor.yy322, 0); } break; - case 312: /* window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ + case 315: /* window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */ { - yylhsminor.yy375 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy375, yymsp[-2].minor.yy562, yymsp[-1].minor.yy562, &yymsp[-5].minor.yy0); + yylhsminor.yy41 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy41, yymsp[-2].minor.yy322, yymsp[-1].minor.yy322, &yymsp[-5].minor.yy0); } - yymsp[-5].minor.yy375 = yylhsminor.yy375; + yymsp[-5].minor.yy41 = yylhsminor.yy41; break; - case 313: /* window ::= ORDER BY sortlist frame_opt */ + case 316: /* window ::= ORDER BY sortlist frame_opt */ { - yymsp[-3].minor.yy375 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy375, 0, yymsp[-1].minor.yy562, 0); + yymsp[-3].minor.yy41 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy41, 0, yymsp[-1].minor.yy322, 0); } break; - case 314: /* window ::= nm ORDER BY sortlist frame_opt */ + case 317: /* window ::= nm ORDER BY sortlist frame_opt */ { - yylhsminor.yy375 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy375, 0, yymsp[-1].minor.yy562, &yymsp[-4].minor.yy0); + yylhsminor.yy41 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy41, 0, yymsp[-1].minor.yy322, &yymsp[-4].minor.yy0); } - yymsp[-4].minor.yy375 = yylhsminor.yy375; + yymsp[-4].minor.yy41 = yylhsminor.yy41; break; - case 315: /* window ::= frame_opt */ - case 334: /* filter_over ::= over_clause */ yytestcase(yyruleno==334); + case 318: /* window ::= frame_opt */ + case 337: /* filter_over ::= over_clause */ yytestcase(yyruleno==337); { - yylhsminor.yy375 = yymsp[0].minor.yy375; + yylhsminor.yy41 = yymsp[0].minor.yy41; } - yymsp[0].minor.yy375 = yylhsminor.yy375; + yymsp[0].minor.yy41 = yylhsminor.yy41; break; - case 316: /* window ::= nm frame_opt */ + case 319: /* window ::= nm frame_opt */ { - yylhsminor.yy375 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy375, 0, 0, &yymsp[-1].minor.yy0); + yylhsminor.yy41 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy41, 0, 0, &yymsp[-1].minor.yy0); } - yymsp[-1].minor.yy375 = yylhsminor.yy375; + yymsp[-1].minor.yy41 = yylhsminor.yy41; break; - case 317: /* frame_opt ::= */ + case 320: /* frame_opt ::= */ { - yymsp[1].minor.yy375 = sqlite3WindowAlloc(pParse, 0, TK_UNBOUNDED, 0, TK_CURRENT, 0, 0); + yymsp[1].minor.yy41 = sqlite3WindowAlloc(pParse, 0, TK_UNBOUNDED, 0, TK_CURRENT, 0, 0); } break; - case 318: /* frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ + case 321: /* frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */ { - yylhsminor.yy375 = sqlite3WindowAlloc(pParse, yymsp[-2].minor.yy64, yymsp[-1].minor.yy81.eType, yymsp[-1].minor.yy81.pExpr, TK_CURRENT, 0, yymsp[0].minor.yy534); + yylhsminor.yy41 = sqlite3WindowAlloc(pParse, yymsp[-2].minor.yy394, yymsp[-1].minor.yy595.eType, yymsp[-1].minor.yy595.pExpr, TK_CURRENT, 0, yymsp[0].minor.yy516); } - yymsp[-2].minor.yy375 = yylhsminor.yy375; + yymsp[-2].minor.yy41 = yylhsminor.yy41; break; - case 319: /* frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ + case 322: /* frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */ { - yylhsminor.yy375 = sqlite3WindowAlloc(pParse, yymsp[-5].minor.yy64, yymsp[-3].minor.yy81.eType, yymsp[-3].minor.yy81.pExpr, yymsp[-1].minor.yy81.eType, yymsp[-1].minor.yy81.pExpr, yymsp[0].minor.yy534); + yylhsminor.yy41 = sqlite3WindowAlloc(pParse, yymsp[-5].minor.yy394, yymsp[-3].minor.yy595.eType, yymsp[-3].minor.yy595.pExpr, yymsp[-1].minor.yy595.eType, yymsp[-1].minor.yy595.pExpr, yymsp[0].minor.yy516); } - yymsp[-5].minor.yy375 = yylhsminor.yy375; + yymsp[-5].minor.yy41 = yylhsminor.yy41; break; - case 321: /* frame_bound_s ::= frame_bound */ - case 323: /* frame_bound_e ::= frame_bound */ yytestcase(yyruleno==323); -{yylhsminor.yy81 = yymsp[0].minor.yy81;} - yymsp[0].minor.yy81 = yylhsminor.yy81; + case 324: /* frame_bound_s ::= frame_bound */ + case 326: /* frame_bound_e ::= frame_bound */ yytestcase(yyruleno==326); +{yylhsminor.yy595 = yymsp[0].minor.yy595;} + yymsp[0].minor.yy595 = yylhsminor.yy595; break; - case 322: /* frame_bound_s ::= UNBOUNDED PRECEDING */ - case 324: /* frame_bound_e ::= UNBOUNDED FOLLOWING */ yytestcase(yyruleno==324); - case 326: /* frame_bound ::= CURRENT ROW */ yytestcase(yyruleno==326); -{yylhsminor.yy81.eType = yymsp[-1].major; yylhsminor.yy81.pExpr = 0;} - yymsp[-1].minor.yy81 = yylhsminor.yy81; + case 325: /* frame_bound_s ::= UNBOUNDED PRECEDING */ + case 327: /* frame_bound_e ::= UNBOUNDED FOLLOWING */ yytestcase(yyruleno==327); + case 329: /* frame_bound ::= CURRENT ROW */ yytestcase(yyruleno==329); +{yylhsminor.yy595.eType = yymsp[-1].major; yylhsminor.yy595.pExpr = 0;} + yymsp[-1].minor.yy595 = yylhsminor.yy595; break; - case 325: /* frame_bound ::= expr PRECEDING|FOLLOWING */ -{yylhsminor.yy81.eType = yymsp[0].major; yylhsminor.yy81.pExpr = yymsp[-1].minor.yy626;} - yymsp[-1].minor.yy81 = yylhsminor.yy81; + case 328: /* frame_bound ::= expr PRECEDING|FOLLOWING */ +{yylhsminor.yy595.eType = yymsp[0].major; yylhsminor.yy595.pExpr = yymsp[-1].minor.yy528;} + yymsp[-1].minor.yy595 = yylhsminor.yy595; break; - case 327: /* frame_exclude_opt ::= */ -{yymsp[1].minor.yy534 = 0;} + case 330: /* frame_exclude_opt ::= */ +{yymsp[1].minor.yy516 = 0;} break; - case 328: /* frame_exclude_opt ::= EXCLUDE frame_exclude */ -{yymsp[-1].minor.yy534 = yymsp[0].minor.yy534;} + case 331: /* frame_exclude_opt ::= EXCLUDE frame_exclude */ +{yymsp[-1].minor.yy516 = yymsp[0].minor.yy516;} break; - case 329: /* frame_exclude ::= NO OTHERS */ - case 330: /* frame_exclude ::= CURRENT ROW */ yytestcase(yyruleno==330); -{yymsp[-1].minor.yy534 = yymsp[-1].major; /*A-overwrites-X*/} + case 332: /* frame_exclude ::= NO OTHERS */ + case 333: /* frame_exclude ::= CURRENT ROW */ yytestcase(yyruleno==333); +{yymsp[-1].minor.yy516 = yymsp[-1].major; /*A-overwrites-X*/} break; - case 331: /* frame_exclude ::= GROUP|TIES */ -{yymsp[0].minor.yy534 = yymsp[0].major; /*A-overwrites-X*/} + case 334: /* frame_exclude ::= GROUP|TIES */ +{yymsp[0].minor.yy516 = yymsp[0].major; /*A-overwrites-X*/} break; - case 332: /* window_clause ::= WINDOW windowdefn_list */ -{ yymsp[-1].minor.yy375 = yymsp[0].minor.yy375; } + case 335: /* window_clause ::= WINDOW windowdefn_list */ +{ yymsp[-1].minor.yy41 = yymsp[0].minor.yy41; } break; - case 333: /* filter_over ::= filter_clause over_clause */ + case 336: /* filter_over ::= filter_clause over_clause */ { - if( yymsp[0].minor.yy375 ){ - yymsp[0].minor.yy375->pFilter = yymsp[-1].minor.yy626; + if( yymsp[0].minor.yy41 ){ + yymsp[0].minor.yy41->pFilter = yymsp[-1].minor.yy528; }else{ - sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy626); + sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy528); } - yylhsminor.yy375 = yymsp[0].minor.yy375; + yylhsminor.yy41 = yymsp[0].minor.yy41; } - yymsp[-1].minor.yy375 = yylhsminor.yy375; + yymsp[-1].minor.yy41 = yylhsminor.yy41; break; - case 335: /* filter_over ::= filter_clause */ + case 338: /* filter_over ::= filter_clause */ { - yylhsminor.yy375 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); - if( yylhsminor.yy375 ){ - yylhsminor.yy375->eFrmType = TK_FILTER; - yylhsminor.yy375->pFilter = yymsp[0].minor.yy626; + yylhsminor.yy41 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); + if( yylhsminor.yy41 ){ + yylhsminor.yy41->eFrmType = TK_FILTER; + yylhsminor.yy41->pFilter = yymsp[0].minor.yy528; }else{ - sqlite3ExprDelete(pParse->db, yymsp[0].minor.yy626); + sqlite3ExprDelete(pParse->db, yymsp[0].minor.yy528); } } - yymsp[0].minor.yy375 = yylhsminor.yy375; + yymsp[0].minor.yy41 = yylhsminor.yy41; break; - case 336: /* over_clause ::= OVER LP window RP */ + case 339: /* over_clause ::= OVER LP window RP */ { - yymsp[-3].minor.yy375 = yymsp[-1].minor.yy375; - assert( yymsp[-3].minor.yy375!=0 ); + yymsp[-3].minor.yy41 = yymsp[-1].minor.yy41; + assert( yymsp[-3].minor.yy41!=0 ); } break; - case 337: /* over_clause ::= OVER nm */ + case 340: /* over_clause ::= OVER nm */ { - yymsp[-1].minor.yy375 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); - if( yymsp[-1].minor.yy375 ){ - yymsp[-1].minor.yy375->zName = sqlite3DbStrNDup(pParse->db, yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n); + yymsp[-1].minor.yy41 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window)); + if( yymsp[-1].minor.yy41 ){ + yymsp[-1].minor.yy41->zName = sqlite3DbStrNDup(pParse->db, yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n); } } break; - case 338: /* filter_clause ::= FILTER LP WHERE expr RP */ -{ yymsp[-4].minor.yy626 = yymsp[-1].minor.yy626; } + case 341: /* filter_clause ::= FILTER LP WHERE expr RP */ +{ yymsp[-4].minor.yy528 = yymsp[-1].minor.yy528; } break; default: - /* (339) input ::= cmdlist */ yytestcase(yyruleno==339); - /* (340) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==340); - /* (341) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=341); - /* (342) ecmd ::= SEMI */ yytestcase(yyruleno==342); - /* (343) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==343); - /* (344) ecmd ::= explain cmdx SEMI (NEVER REDUCES) */ assert(yyruleno!=344); - /* (345) trans_opt ::= */ yytestcase(yyruleno==345); - /* (346) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==346); - /* (347) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==347); - /* (348) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==348); - /* (349) savepoint_opt ::= */ yytestcase(yyruleno==349); - /* (350) cmd ::= create_table create_table_args */ yytestcase(yyruleno==350); - /* (351) table_option_set ::= table_option (OPTIMIZED OUT) */ assert(yyruleno!=351); - /* (352) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==352); - /* (353) columnlist ::= columnname carglist */ yytestcase(yyruleno==353); - /* (354) nm ::= ID|INDEXED */ yytestcase(yyruleno==354); - /* (355) nm ::= STRING */ yytestcase(yyruleno==355); - /* (356) nm ::= JOIN_KW */ yytestcase(yyruleno==356); - /* (357) typetoken ::= typename */ yytestcase(yyruleno==357); - /* (358) typename ::= ID|STRING */ yytestcase(yyruleno==358); - /* (359) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=359); - /* (360) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=360); - /* (361) carglist ::= carglist ccons */ yytestcase(yyruleno==361); - /* (362) carglist ::= */ yytestcase(yyruleno==362); - /* (363) ccons ::= NULL onconf */ yytestcase(yyruleno==363); - /* (364) ccons ::= GENERATED ALWAYS AS generated */ yytestcase(yyruleno==364); - /* (365) ccons ::= AS generated */ yytestcase(yyruleno==365); - /* (366) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==366); - /* (367) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==367); - /* (368) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=368); - /* (369) tconscomma ::= */ yytestcase(yyruleno==369); - /* (370) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=370); - /* (371) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=371); - /* (372) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=372); - /* (373) oneselect ::= values */ yytestcase(yyruleno==373); - /* (374) sclp ::= selcollist COMMA */ yytestcase(yyruleno==374); - /* (375) as ::= ID|STRING */ yytestcase(yyruleno==375); - /* (376) returning ::= */ yytestcase(yyruleno==376); - /* (377) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=377); - /* (378) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==378); - /* (379) exprlist ::= nexprlist */ yytestcase(yyruleno==379); - /* (380) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=380); - /* (381) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=381); - /* (382) nmnum ::= ON */ yytestcase(yyruleno==382); - /* (383) nmnum ::= DELETE */ yytestcase(yyruleno==383); - /* (384) nmnum ::= DEFAULT */ yytestcase(yyruleno==384); - /* (385) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==385); - /* (386) foreach_clause ::= */ yytestcase(yyruleno==386); - /* (387) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==387); - /* (388) trnm ::= nm */ yytestcase(yyruleno==388); - /* (389) tridxby ::= */ yytestcase(yyruleno==389); - /* (390) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==390); - /* (391) database_kw_opt ::= */ yytestcase(yyruleno==391); - /* (392) kwcolumn_opt ::= */ yytestcase(yyruleno==392); - /* (393) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==393); - /* (394) vtabarglist ::= vtabarg */ yytestcase(yyruleno==394); - /* (395) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==395); - /* (396) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==396); - /* (397) anylist ::= */ yytestcase(yyruleno==397); - /* (398) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==398); - /* (399) anylist ::= anylist ANY */ yytestcase(yyruleno==399); - /* (400) with ::= */ yytestcase(yyruleno==400); + /* (342) input ::= cmdlist */ yytestcase(yyruleno==342); + /* (343) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==343); + /* (344) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=344); + /* (345) ecmd ::= SEMI */ yytestcase(yyruleno==345); + /* (346) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==346); + /* (347) ecmd ::= explain cmdx SEMI (NEVER REDUCES) */ assert(yyruleno!=347); + /* (348) trans_opt ::= */ yytestcase(yyruleno==348); + /* (349) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==349); + /* (350) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==350); + /* (351) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==351); + /* (352) savepoint_opt ::= */ yytestcase(yyruleno==352); + /* (353) cmd ::= create_table create_table_args */ yytestcase(yyruleno==353); + /* (354) table_option_set ::= table_option (OPTIMIZED OUT) */ assert(yyruleno!=354); + /* (355) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==355); + /* (356) columnlist ::= columnname carglist */ yytestcase(yyruleno==356); + /* (357) nm ::= ID|INDEXED */ yytestcase(yyruleno==357); + /* (358) nm ::= STRING */ yytestcase(yyruleno==358); + /* (359) nm ::= JOIN_KW */ yytestcase(yyruleno==359); + /* (360) typetoken ::= typename */ yytestcase(yyruleno==360); + /* (361) typename ::= ID|STRING */ yytestcase(yyruleno==361); + /* (362) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=362); + /* (363) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=363); + /* (364) carglist ::= carglist ccons */ yytestcase(yyruleno==364); + /* (365) carglist ::= */ yytestcase(yyruleno==365); + /* (366) ccons ::= NULL onconf */ yytestcase(yyruleno==366); + /* (367) ccons ::= GENERATED ALWAYS AS generated */ yytestcase(yyruleno==367); + /* (368) ccons ::= AS generated */ yytestcase(yyruleno==368); + /* (369) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==369); + /* (370) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==370); + /* (371) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=371); + /* (372) tconscomma ::= */ yytestcase(yyruleno==372); + /* (373) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=373); + /* (374) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=374); + /* (375) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=375); + /* (376) oneselect ::= values */ yytestcase(yyruleno==376); + /* (377) sclp ::= selcollist COMMA */ yytestcase(yyruleno==377); + /* (378) as ::= ID|STRING */ yytestcase(yyruleno==378); + /* (379) indexed_opt ::= indexed_by (OPTIMIZED OUT) */ assert(yyruleno!=379); + /* (380) returning ::= */ yytestcase(yyruleno==380); + /* (381) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=381); + /* (382) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==382); + /* (383) exprlist ::= nexprlist */ yytestcase(yyruleno==383); + /* (384) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=384); + /* (385) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=385); + /* (386) nmnum ::= ON */ yytestcase(yyruleno==386); + /* (387) nmnum ::= DELETE */ yytestcase(yyruleno==387); + /* (388) nmnum ::= DEFAULT */ yytestcase(yyruleno==388); + /* (389) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==389); + /* (390) foreach_clause ::= */ yytestcase(yyruleno==390); + /* (391) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==391); + /* (392) trnm ::= nm */ yytestcase(yyruleno==392); + /* (393) tridxby ::= */ yytestcase(yyruleno==393); + /* (394) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==394); + /* (395) database_kw_opt ::= */ yytestcase(yyruleno==395); + /* (396) kwcolumn_opt ::= */ yytestcase(yyruleno==396); + /* (397) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==397); + /* (398) vtabarglist ::= vtabarg */ yytestcase(yyruleno==398); + /* (399) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==399); + /* (400) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==400); + /* (401) anylist ::= */ yytestcase(yyruleno==401); + /* (402) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==402); + /* (403) anylist ::= anylist ANY */ yytestcase(yyruleno==403); + /* (404) with ::= */ yytestcase(yyruleno==404); break; /********** End reduce actions ************************************************/ }; @@ -165590,6 +169744,9 @@ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){ for(i=2; (c=z[i])!=0 && c!='\n'; i++){} *tokenType = TK_SPACE; /* IMP: R-22934-25134 */ return i; + }else if( z[1]=='>' ){ + *tokenType = TK_PTR; + return 2 + (z[2]=='>'); } *tokenType = TK_MINUS; return 1; @@ -165859,13 +170016,9 @@ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){ } /* -** Run the parser on the given SQL string. The parser structure is -** passed in. An SQLITE_ status code is returned. If an error occurs -** then an and attempt is made to write an error message into -** memory obtained from sqlite3_malloc() and to make *pzErrMsg point to that -** error message. +** Run the parser on the given SQL string. */ -SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ +SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql){ int nErr = 0; /* Number of errors encountered */ void *pEngine; /* The LEMON-generated LALR(1) parser */ int n = 0; /* Length of the next token token */ @@ -165886,7 +170039,6 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr } pParse->rc = SQLITE_OK; pParse->zTail = zSql; - assert( pzErrMsg!=0 ); #ifdef SQLITE_DEBUG if( db->flags & SQLITE_ParserTrace ){ printf("parser: [[[%s]]]\n", zSql); @@ -165916,6 +170068,7 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr mxSqlLen -= n; if( mxSqlLen<0 ){ pParse->rc = SQLITE_TOOBIG; + pParse->nErr++; break; } #ifndef SQLITE_OMIT_WINDOWFUNC @@ -165929,6 +170082,7 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr #endif /* SQLITE_OMIT_WINDOWFUNC */ if( AtomicLoad(&db->u1.isInterrupted) ){ pParse->rc = SQLITE_INTERRUPT; + pParse->nErr++; break; } if( tokenType==TK_SPACE ){ @@ -165958,7 +170112,10 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr tokenType = analyzeFilterKeyword((const u8*)&zSql[6], lastTokenParsed); #endif /* SQLITE_OMIT_WINDOWFUNC */ }else{ - sqlite3ErrorMsg(pParse, "unrecognized token: \"%.*s\"", n, zSql); + Token x; + x.z = zSql; + x.n = n; + sqlite3ErrorMsg(pParse, "unrecognized token: \"%T\"", &x); break; } } @@ -165986,44 +170143,29 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr if( db->mallocFailed ){ pParse->rc = SQLITE_NOMEM_BKPT; } - if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){ - pParse->zErrMsg = sqlite3MPrintf(db, "%s", sqlite3ErrStr(pParse->rc)); - } - assert( pzErrMsg!=0 ); - if( pParse->zErrMsg ){ - *pzErrMsg = pParse->zErrMsg; - sqlite3_log(pParse->rc, "%s in \"%s\"", - *pzErrMsg, pParse->zTail); - pParse->zErrMsg = 0; + if( pParse->zErrMsg || (pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE) ){ + if( pParse->zErrMsg==0 ){ + pParse->zErrMsg = sqlite3MPrintf(db, "%s", sqlite3ErrStr(pParse->rc)); + } + sqlite3_log(pParse->rc, "%s in \"%s\"", pParse->zErrMsg, pParse->zTail); nErr++; } pParse->zTail = zSql; - if( pParse->pVdbe && pParse->nErr>0 && pParse->nested==0 ){ - sqlite3VdbeDelete(pParse->pVdbe); - pParse->pVdbe = 0; - } -#ifndef SQLITE_OMIT_SHARED_CACHE - if( pParse->nested==0 ){ - sqlite3DbFree(db, pParse->aTableLock); - pParse->aTableLock = 0; - pParse->nTableLock = 0; - } -#endif #ifndef SQLITE_OMIT_VIRTUALTABLE sqlite3_free(pParse->apVtabLock); #endif - if( !IN_SPECIAL_PARSE ){ + if( pParse->pNewTable && !IN_SPECIAL_PARSE ){ /* If the pParse->declareVtab flag is set, do not delete any table ** structure built up in pParse->pNewTable. The calling code (see vtab.c) ** will take responsibility for freeing the Table structure. */ sqlite3DeleteTable(db, pParse->pNewTable); } - if( !IN_RENAME_OBJECT ){ + if( pParse->pNewTrigger && !IN_RENAME_OBJECT ){ sqlite3DeleteTrigger(db, pParse->pNewTrigger); } - sqlite3DbFree(db, pParse->pVList); + if( pParse->pVList ) sqlite3DbFreeNN(db, pParse->pVList); db->pParse = pParentParse; assert( nErr==0 || pParse->rc!=SQLITE_OK ); return nErr; @@ -166605,9 +170747,6 @@ SQLITE_PRIVATE int sqlite3Fts2Init(sqlite3*); #ifdef SQLITE_ENABLE_FTS5 SQLITE_PRIVATE int sqlite3Fts5Init(sqlite3*); #endif -#ifdef SQLITE_ENABLE_JSON1 -SQLITE_PRIVATE int sqlite3Json1Init(sqlite3*); -#endif #ifdef SQLITE_ENABLE_STMTVTAB SQLITE_PRIVATE int sqlite3StmtVtabInit(sqlite3*); #endif @@ -166642,8 +170781,8 @@ static int (*const sqlite3BuiltinExtensions[])(sqlite3*) = { sqlite3DbstatRegister, #endif sqlite3TestExtInit, -#ifdef SQLITE_ENABLE_JSON1 - sqlite3Json1Init, +#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON) + sqlite3JsonTableFunctions, #endif #ifdef SQLITE_ENABLE_STMTVTAB sqlite3StmtVtabInit, @@ -169152,6 +173291,19 @@ SQLITE_API const char *sqlite3_errmsg(sqlite3 *db){ return z; } +/* +** Return the byte offset of the most recent error +*/ +SQLITE_API int sqlite3_error_offset(sqlite3 *db){ + int iOffset = -1; + if( db && sqlite3SafetyCheckSickOrOk(db) && db->errCode ){ + sqlite3_mutex_enter(db->mutex); + iOffset = db->errByteOffset; + sqlite3_mutex_leave(db->mutex); + } + return iOffset; +} + #ifndef SQLITE_OMIT_UTF16 /* ** Return UTF-16 encoded English language explanation of the most recent @@ -169412,6 +173564,8 @@ SQLITE_API int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){ if( newLimit>=0 ){ /* IMP: R-52476-28732 */ if( newLimit>aHardLimit[limitId] ){ newLimit = aHardLimit[limitId]; /* IMP: R-51463-25634 */ + }else if( newLimit<1 && limitId==SQLITE_LIMIT_LENGTH ){ + newLimit = 1; } db->aLimit[limitId] = newLimit; } @@ -170572,12 +174726,16 @@ SQLITE_API int sqlite3_test_control(int op, ...){ ** sqlite3_test_control(). */ case SQLITE_TESTCTRL_FAULT_INSTALL: { - /* MSVC is picky about pulling func ptrs from va lists. - ** http://support.microsoft.com/kb/47961 + /* A bug in MSVC prevents it from understanding pointers to functions + ** types in the second argument to va_arg(). Work around the problem + ** using a typedef. + ** http://support.microsoft.com/kb/47961 <-- dead hyperlink + ** Search at http://web.archive.org/ to find the 2015-03-16 archive + ** of the link above to see the original text. ** sqlite3GlobalConfig.xTestCallback = va_arg(ap, int(*)(int)); */ - typedef int(*TESTCALLBACKFUNC_t)(int); - sqlite3GlobalConfig.xTestCallback = va_arg(ap, TESTCALLBACKFUNC_t); + typedef int(*sqlite3FaultFuncType)(int); + sqlite3GlobalConfig.xTestCallback = va_arg(ap, sqlite3FaultFuncType); rc = sqlite3FaultSim(0); break; } @@ -170636,6 +174794,28 @@ SQLITE_API int sqlite3_test_control(int op, ...){ volatile int x = 0; assert( /*side-effects-ok*/ (x = va_arg(ap,int))!=0 ); rc = x; +#if defined(SQLITE_DEBUG) + /* Invoke these debugging routines so that the compiler does not + ** issue "defined but not used" warnings. */ + if( x==9999 ){ + sqlite3ShowExpr(0); + sqlite3ShowExpr(0); + sqlite3ShowExprList(0); + sqlite3ShowIdList(0); + sqlite3ShowSrcList(0); + sqlite3ShowWith(0); + sqlite3ShowUpsert(0); + sqlite3ShowTriggerStep(0); + sqlite3ShowTriggerStepList(0); + sqlite3ShowTrigger(0); + sqlite3ShowTriggerList(0); +#ifndef SQLITE_OMIT_WINDOWFUNC + sqlite3ShowWindow(0); + sqlite3ShowWinFunc(0); +#endif + sqlite3ShowSelect(0); + } +#endif break; } @@ -170704,13 +174884,27 @@ SQLITE_API int sqlite3_test_control(int op, ...){ break; } - /* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff); + /* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, onoff, xAlt); + ** + ** If parameter onoff is 1, subsequent calls to localtime() fail. + ** If 2, then invoke xAlt() instead of localtime(). If 0, normal + ** processing. + ** + ** xAlt arguments are void pointers, but they really want to be: ** - ** If parameter onoff is non-zero, subsequent calls to localtime() - ** and its variants fail. If onoff is zero, undo this setting. + ** int xAlt(const time_t*, struct tm*); + ** + ** xAlt should write results in to struct tm object of its 2nd argument + ** and return zero on success, or return non-zero on failure. */ case SQLITE_TESTCTRL_LOCALTIME_FAULT: { sqlite3GlobalConfig.bLocaltimeFault = va_arg(ap, int); + if( sqlite3GlobalConfig.bLocaltimeFault==2 ){ + typedef int(*sqlite3LocaltimeType)(const void*,void*); + sqlite3GlobalConfig.xAltLocaltime = va_arg(ap, sqlite3LocaltimeType); + }else{ + sqlite3GlobalConfig.xAltLocaltime = 0; + } break; } @@ -170815,12 +175009,16 @@ SQLITE_API int sqlite3_test_control(int op, ...){ */ case SQLITE_TESTCTRL_IMPOSTER: { sqlite3 *db = va_arg(ap, sqlite3*); + int iDb; sqlite3_mutex_enter(db->mutex); - db->init.iDb = sqlite3FindDbName(db, va_arg(ap,const char*)); - db->init.busy = db->init.imposterTable = va_arg(ap,int); - db->init.newTnum = va_arg(ap,int); - if( db->init.busy==0 && db->init.newTnum>0 ){ - sqlite3ResetAllSchemasOfConnection(db); + iDb = sqlite3FindDbName(db, va_arg(ap,const char*)); + if( iDb>=0 ){ + db->init.iDb = iDb; + db->init.busy = db->init.imposterTable = va_arg(ap,int); + db->init.newTnum = va_arg(ap,int); + if( db->init.busy==0 && db->init.newTnum>0 ){ + sqlite3ResetAllSchemasOfConnection(db); + } } sqlite3_mutex_leave(db->mutex); break; @@ -170879,8 +175077,8 @@ SQLITE_API int sqlite3_test_control(int op, ...){ ** ** "ptr" is a pointer to a u32. ** - ** op==0 Store the current sqlite3SelectTrace in *ptr - ** op==1 Set sqlite3SelectTrace to the value *ptr + ** op==0 Store the current sqlite3TreeTrace in *ptr + ** op==1 Set sqlite3TreeTrace to the value *ptr ** op==3 Store the current sqlite3WhereTrace in *ptr ** op==3 Set sqlite3WhereTrace to the value *ptr */ @@ -170888,14 +175086,36 @@ SQLITE_API int sqlite3_test_control(int op, ...){ int opTrace = va_arg(ap, int); u32 *ptr = va_arg(ap, u32*); switch( opTrace ){ - case 0: *ptr = sqlite3SelectTrace; break; - case 1: sqlite3SelectTrace = *ptr; break; - case 2: *ptr = sqlite3WhereTrace; break; - case 3: sqlite3WhereTrace = *ptr; break; + case 0: *ptr = sqlite3TreeTrace; break; + case 1: sqlite3TreeTrace = *ptr; break; + case 2: *ptr = sqlite3WhereTrace; break; + case 3: sqlite3WhereTrace = *ptr; break; } break; } + /* sqlite3_test_control(SQLITE_TESTCTRL_LOGEST, + ** double fIn, // Input value + ** int *pLogEst, // sqlite3LogEstFromDouble(fIn) + ** u64 *pInt, // sqlite3LogEstToInt(*pLogEst) + ** int *pLogEst2 // sqlite3LogEst(*pInt) + ** ); + ** + ** Test access for the LogEst conversion routines. + */ + case SQLITE_TESTCTRL_LOGEST: { + double rIn = va_arg(ap, double); + LogEst rLogEst = sqlite3LogEstFromDouble(rIn); + int *pI1 = va_arg(ap,int*); + u64 *pU64 = va_arg(ap,u64*); + int *pI2 = va_arg(ap,int*); + *pI1 = rLogEst; + *pU64 = sqlite3LogEstToInt(rLogEst); + *pI2 = sqlite3LogEst(*pU64); + break; + } + + #if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_WSD) /* sqlite3_test_control(SQLITE_TESTCTRL_TUNE, id, *piValue) ** @@ -171106,6 +175326,24 @@ SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){ return iDb<0 ? 0 : db->aDb[iDb].pBt; } +/* +** Return the name of the N-th database schema. Return NULL if N is out +** of range. +*/ +SQLITE_API const char *sqlite3_db_name(sqlite3 *db, int N){ +#ifdef SQLITE_ENABLE_API_ARMOR + if( !sqlite3SafetyCheckOk(db) ){ + (void)SQLITE_MISUSE_BKPT; + return 0; + } +#endif + if( N<0 || N>=db->nDb ){ + return 0; + }else{ + return db->aDb[N].zDbSName; + } +} + /* ** Return the filename of the database associated with a database ** connection. @@ -172793,7 +177031,7 @@ struct Fts3MultiSegReader { int nAdvance; /* How many seg-readers to advance */ Fts3SegFilter *pFilter; /* Pointer to filter object */ char *aBuffer; /* Buffer to merge doclists in */ - int nBuffer; /* Allocated size of aBuffer[] in bytes */ + i64 nBuffer; /* Allocated size of aBuffer[] in bytes */ int iColFilter; /* If >=0, filter for this column */ int bRestart; @@ -172876,7 +177114,7 @@ SQLITE_PRIVATE int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *) SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr); /* fts3_tokenize_vtab.c */ -SQLITE_PRIVATE int sqlite3Fts3InitTok(sqlite3*, Fts3Hash *); +SQLITE_PRIVATE int sqlite3Fts3InitTok(sqlite3*, Fts3Hash *, void(*xDestroy)(void*)); /* fts3_unicode2.c (functions generated by parsing unicode text files) */ #ifndef SQLITE_DISABLE_FTS3_UNICODE @@ -172909,6 +177147,12 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeIsdiacritic(int); SQLITE_EXTENSION_INIT1 #endif +typedef struct Fts3HashWrapper Fts3HashWrapper; +struct Fts3HashWrapper { + Fts3Hash hash; /* Hash table */ + int nRef; /* Number of pointers to this object */ +}; + static int fts3EvalNext(Fts3Cursor *pCsr); static int fts3EvalStart(Fts3Cursor *pCsr); static int fts3TermSegReaderCursor( @@ -173773,7 +178017,7 @@ static int fts3InitVtab( sqlite3_vtab **ppVTab, /* Write the resulting vtab structure here */ char **pzErr /* Write any error message here */ ){ - Fts3Hash *pHash = (Fts3Hash *)pAux; + Fts3Hash *pHash = &((Fts3HashWrapper*)pAux)->hash; Fts3Table *p = 0; /* Pointer to allocated vtab */ int rc = SQLITE_OK; /* Return code */ int i; /* Iterator variable */ @@ -175483,7 +179727,7 @@ static int fts3TermSelectMerge( ** ** Similar padding is added in the fts3DoclistOrMerge() function. */ - pTS->aaOutput[0] = sqlite3_malloc(nDoclist + FTS3_VARINT_MAX + 1); + pTS->aaOutput[0] = sqlite3_malloc64((i64)nDoclist + FTS3_VARINT_MAX + 1); pTS->anOutput[0] = nDoclist; if( pTS->aaOutput[0] ){ memcpy(pTS->aaOutput[0], aDoclist, nDoclist); @@ -176608,9 +180852,12 @@ static const sqlite3_module fts3Module = { ** allocated for the tokenizer hash table. */ static void hashDestroy(void *p){ - Fts3Hash *pHash = (Fts3Hash *)p; - sqlite3Fts3HashClear(pHash); - sqlite3_free(pHash); + Fts3HashWrapper *pHash = (Fts3HashWrapper *)p; + pHash->nRef--; + if( pHash->nRef<=0 ){ + sqlite3Fts3HashClear(&pHash->hash); + sqlite3_free(pHash); + } } /* @@ -176640,7 +180887,7 @@ SQLITE_PRIVATE void sqlite3Fts3IcuTokenizerModule(sqlite3_tokenizer_module const */ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){ int rc = SQLITE_OK; - Fts3Hash *pHash = 0; + Fts3HashWrapper *pHash = 0; const sqlite3_tokenizer_module *pSimple = 0; const sqlite3_tokenizer_module *pPorter = 0; #ifndef SQLITE_DISABLE_FTS3_UNICODE @@ -176668,23 +180915,24 @@ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){ sqlite3Fts3PorterTokenizerModule(&pPorter); /* Allocate and initialize the hash-table used to store tokenizers. */ - pHash = sqlite3_malloc(sizeof(Fts3Hash)); + pHash = sqlite3_malloc(sizeof(Fts3HashWrapper)); if( !pHash ){ rc = SQLITE_NOMEM; }else{ - sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1); + sqlite3Fts3HashInit(&pHash->hash, FTS3_HASH_STRING, 1); + pHash->nRef = 0; } /* Load the built-in tokenizers into the hash table */ if( rc==SQLITE_OK ){ - if( sqlite3Fts3HashInsert(pHash, "simple", 7, (void *)pSimple) - || sqlite3Fts3HashInsert(pHash, "porter", 7, (void *)pPorter) + if( sqlite3Fts3HashInsert(&pHash->hash, "simple", 7, (void *)pSimple) + || sqlite3Fts3HashInsert(&pHash->hash, "porter", 7, (void *)pPorter) #ifndef SQLITE_DISABLE_FTS3_UNICODE - || sqlite3Fts3HashInsert(pHash, "unicode61", 10, (void *)pUnicode) + || sqlite3Fts3HashInsert(&pHash->hash, "unicode61", 10, (void *)pUnicode) #endif #ifdef SQLITE_ENABLE_ICU - || (pIcu && sqlite3Fts3HashInsert(pHash, "icu", 4, (void *)pIcu)) + || (pIcu && sqlite3Fts3HashInsert(&pHash->hash, "icu", 4, (void *)pIcu)) #endif ){ rc = SQLITE_NOMEM; @@ -176693,7 +180941,7 @@ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){ #ifdef SQLITE_TEST if( rc==SQLITE_OK ){ - rc = sqlite3Fts3ExprInitTestInterface(db, pHash); + rc = sqlite3Fts3ExprInitTestInterface(db, &pHash->hash); } #endif @@ -176702,23 +180950,26 @@ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){ ** module with sqlite. */ if( SQLITE_OK==rc - && SQLITE_OK==(rc = sqlite3Fts3InitHashTable(db, pHash, "fts3_tokenizer")) + && SQLITE_OK==(rc=sqlite3Fts3InitHashTable(db,&pHash->hash,"fts3_tokenizer")) && SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1)) && SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", 1)) && SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 1)) && SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 2)) && SQLITE_OK==(rc = sqlite3_overload_function(db, "optimize", 1)) ){ + pHash->nRef++; rc = sqlite3_create_module_v2( db, "fts3", &fts3Module, (void *)pHash, hashDestroy ); if( rc==SQLITE_OK ){ + pHash->nRef++; rc = sqlite3_create_module_v2( - db, "fts4", &fts3Module, (void *)pHash, 0 + db, "fts4", &fts3Module, (void *)pHash, hashDestroy ); } if( rc==SQLITE_OK ){ - rc = sqlite3Fts3InitTok(db, (void *)pHash); + pHash->nRef++; + rc = sqlite3Fts3InitTok(db, (void *)pHash, hashDestroy); } return rc; } @@ -176727,7 +180978,7 @@ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){ /* An error has occurred. Delete the hash table and return the error code. */ assert( rc!=SQLITE_OK ); if( pHash ){ - sqlite3Fts3HashClear(pHash); + sqlite3Fts3HashClear(&pHash->hash); sqlite3_free(pHash); } return rc; @@ -176896,8 +181147,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){ char *aPoslist = 0; /* Position list for deferred tokens */ int nPoslist = 0; /* Number of bytes in aPoslist */ int iPrev = -1; /* Token number of previous deferred token */ - - assert( pPhrase->doclist.bFreeList==0 ); + char *aFree = (pPhrase->doclist.bFreeList ? pPhrase->doclist.pList : 0); for(iToken=0; iTokennToken; iToken++){ Fts3PhraseToken *pToken = &pPhrase->aToken[iToken]; @@ -176911,6 +181161,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){ if( pList==0 ){ sqlite3_free(aPoslist); + sqlite3_free(aFree); pPhrase->doclist.pList = 0; pPhrase->doclist.nList = 0; return SQLITE_OK; @@ -176931,6 +181182,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){ nPoslist = (int)(aOut - aPoslist); if( nPoslist==0 ){ sqlite3_free(aPoslist); + sqlite3_free(aFree); pPhrase->doclist.pList = 0; pPhrase->doclist.nList = 0; return SQLITE_OK; @@ -176963,13 +181215,14 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){ nDistance = iPrev - nMaxUndeferred; } - aOut = (char *)sqlite3_malloc(nPoslist+8); + aOut = (char *)sqlite3Fts3MallocZero(nPoslist+FTS3_BUFFER_PADDING); if( !aOut ){ sqlite3_free(aPoslist); return SQLITE_NOMEM; } pPhrase->doclist.pList = aOut; + assert( p1 && p2 ); if( fts3PoslistPhraseMerge(&aOut, nDistance, 0, 1, &p1, &p2) ){ pPhrase->doclist.bFreeList = 1; pPhrase->doclist.nList = (int)(aOut - pPhrase->doclist.pList); @@ -176982,6 +181235,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){ } } + if( pPhrase->doclist.pList!=aFree ) sqlite3_free(aFree); return SQLITE_OK; } #endif /* SQLITE_DISABLE_FTS4_DEFERRED */ @@ -177074,7 +181328,7 @@ SQLITE_PRIVATE void sqlite3Fts3DoclistPrev( assert( nDoclist>0 ); assert( *pbEof==0 ); - assert( p || *piDocid==0 ); + assert_fts3_nc( p || *piDocid==0 ); assert( !p || (p>aDoclist && p<&aDoclist[nDoclist]) ); if( p==0 ){ @@ -177330,7 +181584,7 @@ static int fts3EvalIncrPhraseNext( if( bEof==0 ){ int nList = 0; int nByte = a[p->nToken-1].nList; - char *aDoclist = sqlite3_malloc(nByte+FTS3_BUFFER_PADDING); + char *aDoclist = sqlite3_malloc64((i64)nByte+FTS3_BUFFER_PADDING); if( !aDoclist ) return SQLITE_NOMEM; memcpy(aDoclist, a[p->nToken-1].pList, nByte+1); memset(&aDoclist[nByte], 0, FTS3_BUFFER_PADDING); @@ -178156,11 +182410,10 @@ static int fts3EvalTestExpr( default: { #ifndef SQLITE_DISABLE_FTS4_DEFERRED - if( pCsr->pDeferred - && (pExpr->iDocid==pCsr->iPrevId || pExpr->bDeferred) - ){ + if( pCsr->pDeferred && (pExpr->bDeferred || ( + pExpr->iDocid==pCsr->iPrevId && pExpr->pPhrase->doclist.pList + ))){ Fts3Phrase *pPhrase = pExpr->pPhrase; - assert( pExpr->bDeferred || pPhrase->doclist.bFreeList==0 ); if( pExpr->bDeferred ){ fts3EvalInvalidatePoslist(pPhrase); } @@ -181567,7 +185820,7 @@ static int porterNext( if( n>c->nAllocated ){ char *pNew; c->nAllocated = n+20; - pNew = sqlite3_realloc(c->zToken, c->nAllocated); + pNew = sqlite3_realloc64(c->zToken, c->nAllocated); if( !pNew ) return SQLITE_NOMEM; c->zToken = pNew; } @@ -182319,7 +186572,7 @@ static int simpleNext( if( n>c->nTokenAllocated ){ char *pNew; c->nTokenAllocated = n+20; - pNew = sqlite3_realloc(c->pToken, c->nTokenAllocated); + pNew = sqlite3_realloc64(c->pToken, c->nTokenAllocated); if( !pNew ) return SQLITE_NOMEM; c->pToken = pNew; } @@ -182791,7 +187044,7 @@ static int fts3tokRowidMethod( ** Register the fts3tok module with database connection db. Return SQLITE_OK ** if successful or an error code if sqlite3_create_module() fails. */ -SQLITE_PRIVATE int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash){ +SQLITE_PRIVATE int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash, void(*xDestroy)(void*)){ static const sqlite3_module fts3tok_module = { 0, /* iVersion */ fts3tokConnectMethod, /* xCreate */ @@ -182820,7 +187073,9 @@ SQLITE_PRIVATE int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash){ }; int rc; /* Return code */ - rc = sqlite3_create_module(db, "fts3tokenize", &fts3tok_module, (void*)pHash); + rc = sqlite3_create_module_v2( + db, "fts3tokenize", &fts3tok_module, (void*)pHash, xDestroy + ); return rc; } @@ -183479,7 +187734,7 @@ static int fts3PendingListAppendVarint( /* Allocate or grow the PendingList as required. */ if( !p ){ - p = sqlite3_malloc(sizeof(*p) + 100); + p = sqlite3_malloc64(sizeof(*p) + 100); if( !p ){ return SQLITE_NOMEM; } @@ -183488,14 +187743,14 @@ static int fts3PendingListAppendVarint( p->nData = 0; } else if( p->nData+FTS3_VARINT_MAX+1>p->nSpace ){ - int nNew = p->nSpace * 2; - p = sqlite3_realloc(p, sizeof(*p) + nNew); + i64 nNew = p->nSpace * 2; + p = sqlite3_realloc64(p, sizeof(*p) + nNew); if( !p ){ sqlite3_free(*pp); *pp = 0; return SQLITE_NOMEM; } - p->nSpace = nNew; + p->nSpace = (int)nNew; p->aData = (char *)&p[1]; } @@ -184052,7 +188307,7 @@ SQLITE_PRIVATE int sqlite3Fts3ReadBlock( int nByte = sqlite3_blob_bytes(p->pSegments); *pnBlob = nByte; if( paBlob ){ - char *aByte = sqlite3_malloc(nByte + FTS3_NODE_PADDING); + char *aByte = sqlite3_malloc64((i64)nByte + FTS3_NODE_PADDING); if( !aByte ){ rc = SQLITE_NOMEM; }else{ @@ -184169,7 +188424,7 @@ static int fts3SegReaderNext( int nTerm = fts3HashKeysize(pElem); if( (nTerm+1)>pReader->nTermAlloc ){ sqlite3_free(pReader->zTerm); - pReader->zTerm = (char*)sqlite3_malloc((nTerm+1)*2); + pReader->zTerm = (char*)sqlite3_malloc64(((i64)nTerm+1)*2); if( !pReader->zTerm ) return SQLITE_NOMEM; pReader->nTermAlloc = (nTerm+1)*2; } @@ -184177,7 +188432,7 @@ static int fts3SegReaderNext( pReader->zTerm[nTerm] = '\0'; pReader->nTerm = nTerm; - aCopy = (char*)sqlite3_malloc(nCopy); + aCopy = (char*)sqlite3_malloc64(nCopy); if( !aCopy ) return SQLITE_NOMEM; memcpy(aCopy, pList->aData, nCopy); pReader->nNode = pReader->nDoclist = nCopy; @@ -184464,7 +188719,7 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderNew( nExtra = nRoot + FTS3_NODE_PADDING; } - pReader = (Fts3SegReader *)sqlite3_malloc(sizeof(Fts3SegReader) + nExtra); + pReader = (Fts3SegReader *)sqlite3_malloc64(sizeof(Fts3SegReader) + nExtra); if( !pReader ){ return SQLITE_NOMEM; } @@ -184556,7 +188811,7 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderPending( if( nElem==nAlloc ){ Fts3HashElem **aElem2; nAlloc += 16; - aElem2 = (Fts3HashElem **)sqlite3_realloc( + aElem2 = (Fts3HashElem **)sqlite3_realloc64( aElem, nAlloc*sizeof(Fts3HashElem *) ); if( !aElem2 ){ @@ -184890,7 +189145,7 @@ static int fts3NodeAddTerm( ** this is not expected to be a serious problem. */ assert( pTree->aData==(char *)&pTree[1] ); - pTree->aData = (char *)sqlite3_malloc(nReq); + pTree->aData = (char *)sqlite3_malloc64(nReq); if( !pTree->aData ){ return SQLITE_NOMEM; } @@ -184908,7 +189163,7 @@ static int fts3NodeAddTerm( if( isCopyTerm ){ if( pTree->nMalloczMalloc, nTerm*2); + char *zNew = sqlite3_realloc64(pTree->zMalloc, (i64)nTerm*2); if( !zNew ){ return SQLITE_NOMEM; } @@ -184934,7 +189189,7 @@ static int fts3NodeAddTerm( ** now. Instead, the term is inserted into the parent of pTree. If pTree ** has no parent, one is created here. */ - pNew = (SegmentNode *)sqlite3_malloc(sizeof(SegmentNode) + p->nNodeSize); + pNew = (SegmentNode *)sqlite3_malloc64(sizeof(SegmentNode) + p->nNodeSize); if( !pNew ){ return SQLITE_NOMEM; } @@ -185072,7 +189327,7 @@ static int fts3SegWriterAdd( ){ int nPrefix; /* Size of term prefix in bytes */ int nSuffix; /* Size of term suffix in bytes */ - int nReq; /* Number of bytes required on leaf page */ + i64 nReq; /* Number of bytes required on leaf page */ int nData; SegmentWriter *pWriter = *ppWriter; @@ -185081,13 +189336,13 @@ static int fts3SegWriterAdd( sqlite3_stmt *pStmt; /* Allocate the SegmentWriter structure */ - pWriter = (SegmentWriter *)sqlite3_malloc(sizeof(SegmentWriter)); + pWriter = (SegmentWriter *)sqlite3_malloc64(sizeof(SegmentWriter)); if( !pWriter ) return SQLITE_NOMEM; memset(pWriter, 0, sizeof(SegmentWriter)); *ppWriter = pWriter; /* Allocate a buffer in which to accumulate data */ - pWriter->aData = (char *)sqlite3_malloc(p->nNodeSize); + pWriter->aData = (char *)sqlite3_malloc64(p->nNodeSize); if( !pWriter->aData ) return SQLITE_NOMEM; pWriter->nSize = p->nNodeSize; @@ -185162,7 +189417,7 @@ static int fts3SegWriterAdd( ** the buffer to make it large enough. */ if( nReq>pWriter->nSize ){ - char *aNew = sqlite3_realloc(pWriter->aData, nReq); + char *aNew = sqlite3_realloc64(pWriter->aData, nReq); if( !aNew ) return SQLITE_NOMEM; pWriter->aData = aNew; pWriter->nSize = nReq; @@ -185187,7 +189442,7 @@ static int fts3SegWriterAdd( */ if( isCopyTerm ){ if( nTerm>pWriter->nMalloc ){ - char *zNew = sqlite3_realloc(pWriter->zMalloc, nTerm*2); + char *zNew = sqlite3_realloc64(pWriter->zMalloc, (i64)nTerm*2); if( !zNew ){ return SQLITE_NOMEM; } @@ -185495,12 +189750,12 @@ static void fts3ColumnFilter( static int fts3MsrBufferData( Fts3MultiSegReader *pMsr, /* Multi-segment-reader handle */ char *pList, - int nList + i64 nList ){ if( nList>pMsr->nBuffer ){ char *pNew; pMsr->nBuffer = nList*2; - pNew = (char *)sqlite3_realloc(pMsr->aBuffer, pMsr->nBuffer); + pNew = (char *)sqlite3_realloc64(pMsr->aBuffer, pMsr->nBuffer); if( !pNew ) return SQLITE_NOMEM; pMsr->aBuffer = pNew; } @@ -185556,7 +189811,7 @@ SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext( fts3SegReaderSort(pMsr->apSegment, nMerge, j, xCmp); if( nList>0 && fts3SegReaderIsPending(apSegment[0]) ){ - rc = fts3MsrBufferData(pMsr, pList, nList+1); + rc = fts3MsrBufferData(pMsr, pList, (i64)nList+1); if( rc!=SQLITE_OK ) return rc; assert( (pMsr->aBuffer[nList] & 0xFE)==0x00 ); pList = pMsr->aBuffer; @@ -185693,11 +189948,11 @@ SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr){ return SQLITE_OK; } -static int fts3GrowSegReaderBuffer(Fts3MultiSegReader *pCsr, int nReq){ +static int fts3GrowSegReaderBuffer(Fts3MultiSegReader *pCsr, i64 nReq){ if( nReq>pCsr->nBuffer ){ char *aNew; pCsr->nBuffer = nReq*2; - aNew = sqlite3_realloc(pCsr->aBuffer, pCsr->nBuffer); + aNew = sqlite3_realloc64(pCsr->aBuffer, pCsr->nBuffer); if( !aNew ){ return SQLITE_NOMEM; } @@ -185788,7 +190043,8 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderStep( ){ pCsr->nDoclist = apSegment[0]->nDoclist; if( fts3SegReaderIsPending(apSegment[0]) ){ - rc = fts3MsrBufferData(pCsr, apSegment[0]->aDoclist, pCsr->nDoclist); + rc = fts3MsrBufferData(pCsr, apSegment[0]->aDoclist, + (i64)pCsr->nDoclist); pCsr->aDoclist = pCsr->aBuffer; }else{ pCsr->aDoclist = apSegment[0]->aDoclist; @@ -185841,7 +190097,8 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderStep( nByte = sqlite3Fts3VarintLen(iDelta) + (isRequirePos?nList+1:0); - rc = fts3GrowSegReaderBuffer(pCsr, nByte+nDoclist+FTS3_NODE_PADDING); + rc = fts3GrowSegReaderBuffer(pCsr, + (i64)nByte+nDoclist+FTS3_NODE_PADDING); if( rc ) return rc; if( isFirst ){ @@ -185867,7 +190124,7 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderStep( fts3SegReaderSort(apSegment, nMerge, j, xCmp); } if( nDoclist>0 ){ - rc = fts3GrowSegReaderBuffer(pCsr, nDoclist+FTS3_NODE_PADDING); + rc = fts3GrowSegReaderBuffer(pCsr, (i64)nDoclist+FTS3_NODE_PADDING); if( rc ) return rc; memset(&pCsr->aBuffer[nDoclist], 0, FTS3_NODE_PADDING); pCsr->aDoclist = pCsr->aBuffer; @@ -186580,7 +190837,7 @@ struct NodeReader { static void blobGrowBuffer(Blob *pBlob, int nMin, int *pRc){ if( *pRc==SQLITE_OK && nMin>pBlob->nAlloc ){ int nAlloc = nMin; - char *a = (char *)sqlite3_realloc(pBlob->a, nAlloc); + char *a = (char *)sqlite3_realloc64(pBlob->a, nAlloc); if( a ){ pBlob->nAlloc = nAlloc; pBlob->a = a; @@ -186729,6 +190986,8 @@ static int fts3IncrmergePush( pBlk->n += sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nPrefix); } pBlk->n += sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nSuffix); + assert( nPrefix+nSuffix<=nTerm ); + assert( nPrefix>=0 ); memcpy(&pBlk->a[pBlk->n], &zTerm[nPrefix], nSuffix); pBlk->n += nSuffix; @@ -186851,6 +191110,7 @@ static int fts3IncrmergeAppend( pLeaf = &pWriter->aNodeWriter[0]; nPrefix = fts3PrefixCompress(pLeaf->key.a, pLeaf->key.n, zTerm, nTerm); nSuffix = nTerm - nPrefix; + if(nSuffix<=0 ) return FTS_CORRUPT_VTAB; nSpace = sqlite3Fts3VarintLen(nPrefix); nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix; @@ -187374,7 +191634,7 @@ static int fts3RepackSegdirLevel( if( nIdx>=nAlloc ){ int *aNew; nAlloc += 16; - aNew = sqlite3_realloc(aIdx, nAlloc*sizeof(int)); + aNew = sqlite3_realloc64(aIdx, nAlloc*sizeof(int)); if( !aNew ){ rc = SQLITE_NOMEM; break; @@ -187748,7 +192008,7 @@ SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){ /* Allocate space for the cursor, filter and writer objects */ const int nAlloc = sizeof(*pCsr) + sizeof(*pFilter) + sizeof(*pWriter); - pWriter = (IncrmergeWriter *)sqlite3_malloc(nAlloc); + pWriter = (IncrmergeWriter *)sqlite3_malloc64(nAlloc); if( !pWriter ) return SQLITE_NOMEM; pFilter = (Fts3SegFilter *)&pWriter[1]; pCsr = (Fts3MultiSegReader *)&pFilter[1]; @@ -188384,7 +192644,7 @@ SQLITE_PRIVATE int sqlite3Fts3DeferredTokenList( return SQLITE_OK; } - pRet = (char *)sqlite3_malloc(p->pList->nData); + pRet = (char *)sqlite3_malloc64(p->pList->nData); if( !pRet ) return SQLITE_NOMEM; nSkip = sqlite3Fts3GetVarint(p->pList->aData, &dummy); @@ -188404,7 +192664,7 @@ SQLITE_PRIVATE int sqlite3Fts3DeferToken( int iCol /* Column that token must appear in (or -1) */ ){ Fts3DeferredToken *pDeferred; - pDeferred = sqlite3_malloc(sizeof(*pDeferred)); + pDeferred = sqlite3_malloc64(sizeof(*pDeferred)); if( !pDeferred ){ return SQLITE_NOMEM; } @@ -191179,7 +195439,7 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int c, int eRemoveDiacritic){ #endif /* !defined(SQLITE_DISABLE_FTS3_UNICODE) */ /************** End of fts3_unicode2.c ***************************************/ -/************** Begin file json1.c *******************************************/ +/************** Begin file json.c ********************************************/ /* ** 2015-08-12 ** @@ -191192,10 +195452,10 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int c, int eRemoveDiacritic){ ** ****************************************************************************** ** -** This SQLite extension implements JSON functions. The interface is -** modeled after MySQL JSON functions: +** This SQLite JSON functions. ** -** https://dev.mysql.com/doc/refman/5.7/en/json.html +** This file began as an extension in ext/misc/json1.c in 2015. That +** extension proved so useful that it has now been moved into the core. ** ** For the time being, all JSON is stored as pure text. (We might add ** a JSONB type in the future which stores a binary encoding of JSON in @@ -191203,48 +195463,8 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int c, int eRemoveDiacritic){ ** This implementation parses JSON text at 250 MB/s, so it is hard to see ** how JSONB might improve on that.) */ -#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_JSON1) -#if !defined(SQLITEINT_H) -/* #include "sqlite3ext.h" */ -#endif -SQLITE_EXTENSION_INIT1 -/* #include */ -/* #include */ -/* #include */ -/* #include */ - -/* Mark a function parameter as unused, to suppress nuisance compiler -** warnings. */ -#ifndef UNUSED_PARAM -# define UNUSED_PARAM(X) (void)(X) -#endif - -#ifndef LARGEST_INT64 -# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32)) -# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64) -#endif - -#ifndef deliberate_fall_through -# define deliberate_fall_through -#endif - -/* -** Versions of isspace(), isalnum() and isdigit() to which it is safe -** to pass signed char values. -*/ -#ifdef sqlite3Isdigit - /* Use the SQLite core versions if this routine is part of the - ** SQLite amalgamation */ -# define safe_isdigit(x) sqlite3Isdigit(x) -# define safe_isalnum(x) sqlite3Isalnum(x) -# define safe_isxdigit(x) sqlite3Isxdigit(x) -#else - /* Use the standard library for separate compilation */ -#include /* amalgamator: keep */ -# define safe_isdigit(x) isdigit((unsigned char)(x)) -# define safe_isalnum(x) isalnum((unsigned char)(x)) -# define safe_isxdigit(x) isxdigit((unsigned char)(x)) -#endif +#ifndef SQLITE_OMIT_JSON +/* #include "sqliteInt.h" */ /* ** Growing our own isspace() routine this way is twice as fast as @@ -191269,44 +195489,14 @@ static const char jsonIsSpace[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; -#define safe_isspace(x) (jsonIsSpace[(unsigned char)x]) +#define fast_isspace(x) (jsonIsSpace[(unsigned char)x]) -#ifndef SQLITE_AMALGAMATION - /* Unsigned integer types. These are already defined in the sqliteInt.h, - ** but the definitions need to be repeated for separate compilation. */ - typedef sqlite3_uint64 u64; - typedef unsigned int u32; - typedef unsigned short int u16; - typedef unsigned char u8; -# if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST) -# define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1 -# endif -# if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS) -# define ALWAYS(X) (1) -# define NEVER(X) (0) -# elif !defined(NDEBUG) -# define ALWAYS(X) ((X)?1:(assert(0),0)) -# define NEVER(X) ((X)?(assert(0),1):0) -# else -# define ALWAYS(X) (X) -# define NEVER(X) (X) -# endif -# define testcase(X) -#endif #if !defined(SQLITE_DEBUG) && !defined(SQLITE_COVERAGE_TEST) # define VVA(X) #else # define VVA(X) X #endif -/* -** Some of the testcase() macros in this file are problematic for gcov -** in that they generate false-miss errors randomly. This is a gcov problem, -** not a problem in this case. But to work around it, we disable the -** problematic test cases for production builds. -*/ -#define json_testcase(X) - /* Objects */ typedef struct JsonString JsonString; typedef struct JsonNode JsonNode; @@ -191764,10 +195954,10 @@ static u8 jsonHexToInt(int h){ */ static u32 jsonHexToInt4(const char *z){ u32 v; - assert( safe_isxdigit(z[0]) ); - assert( safe_isxdigit(z[1]) ); - assert( safe_isxdigit(z[2]) ); - assert( safe_isxdigit(z[3]) ); + assert( sqlite3Isxdigit(z[0]) ); + assert( sqlite3Isxdigit(z[1]) ); + assert( sqlite3Isxdigit(z[2]) ); + assert( sqlite3Isxdigit(z[3]) ); v = (jsonHexToInt(z[0])<<12) + (jsonHexToInt(z[1])<<8) + (jsonHexToInt(z[2])<<4) @@ -192002,7 +196192,7 @@ static int jsonParseAddNode( */ static int jsonIs4Hex(const char *z){ int i; - for(i=0; i<4; i++) if( !safe_isxdigit(z[i]) ) return 0; + for(i=0; i<4; i++) if( !sqlite3Isxdigit(z[i]) ) return 0; return 1; } @@ -192021,13 +196211,13 @@ static int jsonParseValue(JsonParse *pParse, u32 i){ int x; JsonNode *pNode; const char *z = pParse->zJson; - while( safe_isspace(z[i]) ){ i++; } + while( fast_isspace(z[i]) ){ i++; } if( (c = z[i])=='{' ){ /* Parse object */ iThis = jsonParseAddNode(pParse, JSON_OBJECT, 0, 0); if( iThis<0 ) return -1; for(j=i+1;;j++){ - while( safe_isspace(z[j]) ){ j++; } + while( fast_isspace(z[j]) ){ j++; } if( ++pParse->iDepth > JSON_MAX_DEPTH ) return -1; x = jsonParseValue(pParse, j); if( x<0 ){ @@ -192040,14 +196230,14 @@ static int jsonParseValue(JsonParse *pParse, u32 i){ if( pNode->eType!=JSON_STRING ) return -1; pNode->jnFlags |= JNODE_LABEL; j = x; - while( safe_isspace(z[j]) ){ j++; } + while( fast_isspace(z[j]) ){ j++; } if( z[j]!=':' ) return -1; j++; x = jsonParseValue(pParse, j); pParse->iDepth--; if( x<0 ) return -1; j = x; - while( safe_isspace(z[j]) ){ j++; } + while( fast_isspace(z[j]) ){ j++; } c = z[j]; if( c==',' ) continue; if( c!='}' ) return -1; @@ -192061,7 +196251,7 @@ static int jsonParseValue(JsonParse *pParse, u32 i){ if( iThis<0 ) return -1; memset(&pParse->aNode[iThis].u, 0, sizeof(pParse->aNode[iThis].u)); for(j=i+1;;j++){ - while( safe_isspace(z[j]) ){ j++; } + while( fast_isspace(z[j]) ){ j++; } if( ++pParse->iDepth > JSON_MAX_DEPTH ) return -1; x = jsonParseValue(pParse, j); pParse->iDepth--; @@ -192070,7 +196260,7 @@ static int jsonParseValue(JsonParse *pParse, u32 i){ return -1; } j = x; - while( safe_isspace(z[j]) ){ j++; } + while( fast_isspace(z[j]) ){ j++; } c = z[j]; if( c==',' ) continue; if( c!=']' ) return -1; @@ -192107,17 +196297,17 @@ static int jsonParseValue(JsonParse *pParse, u32 i){ return j+1; }else if( c=='n' && strncmp(z+i,"null",4)==0 - && !safe_isalnum(z[i+4]) ){ + && !sqlite3Isalnum(z[i+4]) ){ jsonParseAddNode(pParse, JSON_NULL, 0, 0); return i+4; }else if( c=='t' && strncmp(z+i,"true",4)==0 - && !safe_isalnum(z[i+4]) ){ + && !sqlite3Isalnum(z[i+4]) ){ jsonParseAddNode(pParse, JSON_TRUE, 0, 0); return i+4; }else if( c=='f' && strncmp(z+i,"false",5)==0 - && !safe_isalnum(z[i+5]) ){ + && !sqlite3Isalnum(z[i+5]) ){ jsonParseAddNode(pParse, JSON_FALSE, 0, 0); return i+5; }else if( c=='-' || (c>='0' && c<='9') ){ @@ -192188,7 +196378,7 @@ static int jsonParse( if( pParse->oom ) i = -1; if( i>0 ){ assert( pParse->iDepth==0 ); - while( safe_isspace(zJson[i]) ) i++; + while( fast_isspace(zJson[i]) ) i++; if( zJson[i] ) i = -1; } if( i<=0 ){ @@ -192371,14 +196561,15 @@ static JsonNode *jsonLookupStep( *pzErr = zPath; return 0; } + testcase( nKey==0 ); }else{ zKey = zPath; for(i=0; zPath[i] && zPath[i]!='.' && zPath[i]!='['; i++){} nKey = i; - } - if( nKey==0 ){ - *pzErr = zPath; - return 0; + if( nKey==0 ){ + *pzErr = zPath; + return 0; + } } j = 1; for(;;){ @@ -192416,7 +196607,7 @@ static JsonNode *jsonLookupStep( }else if( zPath[0]=='[' ){ i = 0; j = 1; - while( safe_isdigit(zPath[j]) ){ + while( sqlite3Isdigit(zPath[j]) ){ i = i*10 + zPath[j] - '0'; j++; } @@ -192437,13 +196628,13 @@ static JsonNode *jsonLookupStep( j = 1; } j = 2; - if( zPath[2]=='-' && safe_isdigit(zPath[3]) ){ + if( zPath[2]=='-' && sqlite3Isdigit(zPath[3]) ){ unsigned int x = 0; j = 3; do{ x = x*10 + zPath[j] - '0'; j++; - }while( safe_isdigit(zPath[j]) ); + }while( sqlite3Isdigit(zPath[j]) ); if( x>i ) return 0; i -= x; } @@ -192662,7 +196853,7 @@ static void jsonTest1Func( int argc, sqlite3_value **argv ){ - UNUSED_PARAM(argc); + UNUSED_PARAMETER(argc); sqlite3_result_int(ctx, sqlite3_value_subtype(argv[0])==JSON_SUBTYPE); } #endif /* SQLITE_DEBUG */ @@ -192683,7 +196874,7 @@ static void jsonQuoteFunc( sqlite3_value **argv ){ JsonString jx; - UNUSED_PARAM(argc); + UNUSED_PARAMETER(argc); jsonInit(&jx, ctx); jsonAppendValue(&jx, argv[0]); @@ -192754,13 +196945,34 @@ static void jsonArrayLengthFunc( sqlite3_result_int64(ctx, n); } +/* +** Bit values for the flags passed into jsonExtractFunc() or +** jsonSetFunc() via the user-data value. +*/ +#define JSON_JSON 0x01 /* Result is always JSON */ +#define JSON_SQL 0x02 /* Result is always SQL */ +#define JSON_ABPATH 0x03 /* Allow abbreviated JSON path specs */ +#define JSON_ISSET 0x04 /* json_set(), not json_insert() */ + /* ** json_extract(JSON, PATH, ...) +** "->"(JSON,PATH) +** "->>"(JSON,PATH) +** +** Return the element described by PATH. Return NULL if that PATH element +** is not found. ** -** Return the element described by PATH. Return NULL if there is no -** PATH element. If there are multiple PATHs, then return a JSON array -** with the result from each path. Throw an error if the JSON or any PATH -** is malformed. +** If JSON_JSON is set or if more that one PATH argument is supplied then +** always return a JSON representation of the result. If JSON_SQL is set, +** then always return an SQL representation of the result. If neither flag +** is present and argc==2, then return JSON for objects and arrays and SQL +** for all other values. +** +** When multiple PATH arguments are supplied, the result is a JSON array +** containing the result of each PATH. +** +** Abbreviated JSON path expressions are allows if JSON_ABPATH, for +** compatibility with PG. */ static void jsonExtractFunc( sqlite3_context *ctx, @@ -192770,35 +196982,77 @@ static void jsonExtractFunc( JsonParse *p; /* The parse */ JsonNode *pNode; const char *zPath; + int flags = SQLITE_PTR_TO_INT(sqlite3_user_data(ctx)); JsonString jx; - int i; if( argc<2 ) return; p = jsonParseCached(ctx, argv, ctx); if( p==0 ) return; - jsonInit(&jx, ctx); - jsonAppendChar(&jx, '['); - for(i=1; inErr ) break; - if( argc>2 ){ + if( argc==2 ){ + /* With a single PATH argument */ + zPath = (const char*)sqlite3_value_text(argv[1]); + if( zPath==0 ) return; + if( flags & JSON_ABPATH ){ + if( zPath[0]!='$' ){ + /* The -> and ->> operators accept abbreviated PATH arguments. This + ** is mostly for compatibility with PostgreSQL, but also for + ** convenience. + ** + ** NUMBER ==> $[NUMBER] // PG compatible + ** LABEL ==> $.LABEL // PG compatible + ** [NUMBER] ==> $[NUMBER] // Not PG. Purely for convenience + */ + jsonInit(&jx, ctx); + if( sqlite3Isdigit(zPath[0]) ){ + jsonAppendRaw(&jx, "$[", 2); + jsonAppendRaw(&jx, zPath, (int)strlen(zPath)); + jsonAppendRaw(&jx, "]", 2); + }else{ + jsonAppendRaw(&jx, "$.", 1 + (zPath[0]!='[')); + jsonAppendRaw(&jx, zPath, (int)strlen(zPath)); + jsonAppendChar(&jx, 0); + } + pNode = jx.bErr ? 0 : jsonLookup(p, jx.zBuf, 0, ctx); + jsonReset(&jx); + }else{ + pNode = jsonLookup(p, zPath, 0, ctx); + } + if( pNode ){ + if( flags & JSON_JSON ){ + jsonReturnJson(pNode, ctx, 0); + }else{ + jsonReturn(pNode, ctx, 0); + sqlite3_result_subtype(ctx, 0); + } + } + }else{ + pNode = jsonLookup(p, zPath, 0, ctx); + if( p->nErr==0 && pNode ) jsonReturn(pNode, ctx, 0); + } + }else{ + /* Two or more PATH arguments results in a JSON array with each + ** element of the array being the value selected by one of the PATHs */ + int i; + jsonInit(&jx, ctx); + jsonAppendChar(&jx, '['); + for(i=1; inErr ) break; jsonAppendSeparator(&jx); if( pNode ){ jsonRenderNode(pNode, &jx, 0); }else{ jsonAppendRaw(&jx, "null", 4); } - }else if( pNode ){ - jsonReturn(pNode, ctx, 0); } + if( i==argc ){ + jsonAppendChar(&jx, ']'); + jsonResult(&jx); + sqlite3_result_subtype(ctx, JSON_SUBTYPE); + } + jsonReset(&jx); } - if( argc>2 && i==argc ){ - jsonAppendChar(&jx, ']'); - jsonResult(&jx); - sqlite3_result_subtype(ctx, JSON_SUBTYPE); - } - jsonReset(&jx); } /* This is the RFC 7396 MergePatch algorithm. @@ -192814,7 +197068,7 @@ static JsonNode *jsonMergePatch( if( pPatch->eType!=JSON_OBJECT ){ return pPatch; } - assert( iTarget>=0 && iTargetnNode ); + assert( iTargetnNode ); pTarget = &pParse->aNode[iTarget]; assert( (pPatch->jnFlags & JNODE_APPEND)==0 ); if( pTarget->eType!=JSON_OBJECT ){ @@ -192894,7 +197148,7 @@ static void jsonPatchFunc( JsonParse y; /* The patch */ JsonNode *pResult; /* The result of the merge */ - UNUSED_PARAM(argc); + UNUSED_PARAMETER(argc); if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return; if( jsonParse(&y, ctx, (const char*)sqlite3_value_text(argv[1])) ){ jsonParseReset(&x); @@ -193015,7 +197269,7 @@ static void jsonReplaceFunc( if( x.nErr ) goto replace_err; if( pNode ){ assert( pNode->eU==0 || pNode->eU==1 || pNode->eU==4 ); - json_testcase( pNode->eU!=0 && pNode->eU!=1 ); + testcase( pNode->eU!=0 && pNode->eU!=1 ); pNode->jnFlags |= (u8)JNODE_REPLACE; VVA( pNode->eU = 4 ); pNode->u.iReplace = i + 1; @@ -193031,6 +197285,7 @@ static void jsonReplaceFunc( jsonParseReset(&x); } + /* ** json_set(JSON, PATH, VALUE, ...) ** @@ -193053,7 +197308,7 @@ static void jsonSetFunc( const char *zPath; u32 i; int bApnd; - int bIsSet = *(int*)sqlite3_user_data(ctx); + int bIsSet = sqlite3_user_data(ctx)!=0; if( argc<1 ) return; if( (argc&1)==0 ) { @@ -193072,8 +197327,8 @@ static void jsonSetFunc( }else if( x.nErr ){ goto jsonSetDone; }else if( pNode && (bApnd || bIsSet) ){ - json_testcase( pNode->eU!=0 && pNode->eU!=1 && pNode->eU!=4 ); - assert( pNode->eU!=3 || pNode->eU!=5 ); + testcase( pNode->eU!=0 && pNode->eU!=1 ); + assert( pNode->eU!=3 && pNode->eU!=5 ); VVA( pNode->eU = 4 ); pNode->jnFlags |= (u8)JNODE_REPLACE; pNode->u.iReplace = i + 1; @@ -193093,8 +197348,8 @@ static void jsonSetFunc( ** json_type(JSON) ** json_type(JSON, PATH) ** -** Return the top-level "type" of a JSON string. Throw an error if -** either the JSON or PATH inputs are not well-formed. +** Return the top-level "type" of a JSON string. json_type() raises an +** error if either the JSON or PATH inputs are not well-formed. */ static void jsonTypeFunc( sqlite3_context *ctx, @@ -193130,7 +197385,7 @@ static void jsonValidFunc( sqlite3_value **argv ){ JsonParse *p; /* The parse */ - UNUSED_PARAM(argc); + UNUSED_PARAMETER(argc); p = jsonParseCached(ctx, argv, 0); sqlite3_result_int(ctx, p!=0); } @@ -193150,7 +197405,7 @@ static void jsonArrayStep( sqlite3_value **argv ){ JsonString *pStr; - UNUSED_PARAM(argc); + UNUSED_PARAMETER(argc); pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr)); if( pStr ){ if( pStr->zBuf==0 ){ @@ -193210,8 +197465,8 @@ static void jsonGroupInverse( char *z; char c; JsonString *pStr; - UNUSED_PARAM(argc); - UNUSED_PARAM(argv); + UNUSED_PARAMETER(argc); + UNUSED_PARAMETER(argv); pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0); #ifdef NEVER /* pStr is always non-NULL since jsonArrayStep() or jsonObjectStep() will @@ -193255,7 +197510,7 @@ static void jsonObjectStep( JsonString *pStr; const char *z; u32 n; - UNUSED_PARAM(argc); + UNUSED_PARAMETER(argc); pStr = (JsonString*)sqlite3_aggregate_context(ctx, sizeof(*pStr)); if( pStr ){ if( pStr->zBuf==0 ){ @@ -193346,10 +197601,10 @@ static int jsonEachConnect( #define JEACH_JSON 8 #define JEACH_ROOT 9 - UNUSED_PARAM(pzErr); - UNUSED_PARAM(argv); - UNUSED_PARAM(argc); - UNUSED_PARAM(pAux); + UNUSED_PARAMETER(pzErr); + UNUSED_PARAMETER(argv); + UNUSED_PARAMETER(argc); + UNUSED_PARAMETER(pAux); rc = sqlite3_declare_vtab(db, "CREATE TABLE x(key,value,type,atom,id,parent,fullkey,path," "json HIDDEN,root HIDDEN)"); @@ -193372,7 +197627,7 @@ static int jsonEachDisconnect(sqlite3_vtab *pVtab){ static int jsonEachOpenEach(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ JsonEachCursor *pCur; - UNUSED_PARAM(p); + UNUSED_PARAMETER(p); pCur = sqlite3_malloc( sizeof(*pCur) ); if( pCur==0 ) return SQLITE_NOMEM; memset(pCur, 0, sizeof(*pCur)); @@ -193432,7 +197687,7 @@ static int jsonEachNext(sqlite3_vtab_cursor *cur){ p->eType = pUp->eType; if( pUp->eType==JSON_ARRAY ){ assert( pUp->eU==0 || pUp->eU==3 ); - json_testcase( pUp->eU==3 ); + testcase( pUp->eU==3 ); VVA( pUp->eU = 3 ); if( iUp==p->i-1 ){ pUp->u.iKey = 0; @@ -193462,6 +197717,33 @@ static int jsonEachNext(sqlite3_vtab_cursor *cur){ return SQLITE_OK; } +/* Append an object label to the JSON Path being constructed +** in pStr. +*/ +static void jsonAppendObjectPathElement( + JsonString *pStr, + JsonNode *pNode +){ + int jj, nn; + const char *z; + assert( pNode->eType==JSON_STRING ); + assert( pNode->jnFlags & JNODE_LABEL ); + assert( pNode->eU==1 ); + z = pNode->u.zJContent; + nn = pNode->n; + assert( nn>=2 ); + assert( z[0]=='"' ); + assert( z[nn-1]=='"' ); + if( nn>2 && sqlite3Isalpha(z[1]) ){ + for(jj=2; jjeType==JSON_OBJECT ); if( (pNode->jnFlags & JNODE_LABEL)==0 ) pNode--; - assert( pNode->eType==JSON_STRING ); - assert( pNode->jnFlags & JNODE_LABEL ); - assert( pNode->eU==1 ); - jsonPrintf(pNode->n+1, pStr, ".%.*s", pNode->n-2, pNode->u.zJContent+1); + jsonAppendObjectPathElement(pStr, pNode); } } @@ -193560,8 +197839,7 @@ static int jsonEachColumn( if( p->eType==JSON_ARRAY ){ jsonPrintf(30, &x, "[%d]", p->iRowid); }else if( p->eType==JSON_OBJECT ){ - assert( pThis->eU==1 ); - jsonPrintf(pThis->n, &x, ".%.*s", pThis->n-2, pThis->u.zJContent+1); + jsonAppendObjectPathElement(&x, pThis); } } jsonResult(&x); @@ -193619,7 +197897,7 @@ static int jsonEachBestIndex( /* This implementation assumes that JSON and ROOT are the last two ** columns in the table */ assert( JEACH_ROOT == JEACH_JSON+1 ); - UNUSED_PARAM(tab); + UNUSED_PARAMETER(tab); aIdx[0] = aIdx[1] = -1; pConstraint = pIdxInfo->aConstraint; for(i=0; inConstraint; i++, pConstraint++){ @@ -193675,8 +197953,8 @@ static int jsonEachFilter( const char *zRoot = 0; sqlite3_int64 n; - UNUSED_PARAM(idxStr); - UNUSED_PARAM(argc); + UNUSED_PARAMETER(idxStr); + UNUSED_PARAMETER(argc); jsonEachCursorReset(p); if( idxNum==0 ) return SQLITE_OK; z = (const char*)sqlite3_value_text(argv[0]); @@ -193801,108 +198079,68 @@ static sqlite3_module jsonTreeModule = { 0 /* xShadowName */ }; #endif /* SQLITE_OMIT_VIRTUALTABLE */ - -/**************************************************************************** -** The following routines are the only publically visible identifiers in this -** file. Call the following routines in order to register the various SQL -** functions and the virtual table implemented by this file. -****************************************************************************/ - -SQLITE_PRIVATE int sqlite3Json1Init(sqlite3 *db){ - int rc = SQLITE_OK; - unsigned int i; - static const struct { - const char *zName; - int nArg; - int flag; - void (*xFunc)(sqlite3_context*,int,sqlite3_value**); - } aFunc[] = { - { "json", 1, 0, jsonRemoveFunc }, - { "json_array", -1, 0, jsonArrayFunc }, - { "json_array_length", 1, 0, jsonArrayLengthFunc }, - { "json_array_length", 2, 0, jsonArrayLengthFunc }, - { "json_extract", -1, 0, jsonExtractFunc }, - { "json_insert", -1, 0, jsonSetFunc }, - { "json_object", -1, 0, jsonObjectFunc }, - { "json_patch", 2, 0, jsonPatchFunc }, - { "json_quote", 1, 0, jsonQuoteFunc }, - { "json_remove", -1, 0, jsonRemoveFunc }, - { "json_replace", -1, 0, jsonReplaceFunc }, - { "json_set", -1, 1, jsonSetFunc }, - { "json_type", 1, 0, jsonTypeFunc }, - { "json_type", 2, 0, jsonTypeFunc }, - { "json_valid", 1, 0, jsonValidFunc }, - +#endif /* !defined(SQLITE_OMIT_JSON) */ + +/* +** Register JSON functions. +*/ +SQLITE_PRIVATE void sqlite3RegisterJsonFunctions(void){ +#ifndef SQLITE_OMIT_JSON + static FuncDef aJsonFunc[] = { + JFUNCTION(json, 1, 0, jsonRemoveFunc), + JFUNCTION(json_array, -1, 0, jsonArrayFunc), + JFUNCTION(json_array_length, 1, 0, jsonArrayLengthFunc), + JFUNCTION(json_array_length, 2, 0, jsonArrayLengthFunc), + JFUNCTION(json_extract, -1, 0, jsonExtractFunc), + JFUNCTION(->, 2, JSON_JSON, jsonExtractFunc), + JFUNCTION(->>, 2, JSON_SQL, jsonExtractFunc), + JFUNCTION(json_insert, -1, 0, jsonSetFunc), + JFUNCTION(json_object, -1, 0, jsonObjectFunc), + JFUNCTION(json_patch, 2, 0, jsonPatchFunc), + JFUNCTION(json_quote, 1, 0, jsonQuoteFunc), + JFUNCTION(json_remove, -1, 0, jsonRemoveFunc), + JFUNCTION(json_replace, -1, 0, jsonReplaceFunc), + JFUNCTION(json_set, -1, JSON_ISSET, jsonSetFunc), + JFUNCTION(json_type, 1, 0, jsonTypeFunc), + JFUNCTION(json_type, 2, 0, jsonTypeFunc), + JFUNCTION(json_valid, 1, 0, jsonValidFunc), #if SQLITE_DEBUG - /* DEBUG and TESTING functions */ - { "json_parse", 1, 0, jsonParseFunc }, - { "json_test1", 1, 0, jsonTest1Func }, -#endif - }; - static const struct { - const char *zName; - int nArg; - void (*xStep)(sqlite3_context*,int,sqlite3_value**); - void (*xFinal)(sqlite3_context*); - void (*xValue)(sqlite3_context*); - } aAgg[] = { - { "json_group_array", 1, - jsonArrayStep, jsonArrayFinal, jsonArrayValue }, - { "json_group_object", 2, - jsonObjectStep, jsonObjectFinal, jsonObjectValue }, + JFUNCTION(json_parse, 1, 0, jsonParseFunc), + JFUNCTION(json_test1, 1, 0, jsonTest1Func), +#endif + WAGGREGATE(json_group_array, 1, 0, 0, + jsonArrayStep, jsonArrayFinal, jsonArrayValue, jsonGroupInverse, + SQLITE_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS), + WAGGREGATE(json_group_object, 2, 0, 0, + jsonObjectStep, jsonObjectFinal, jsonObjectValue, jsonGroupInverse, + SQLITE_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS) }; -#ifndef SQLITE_OMIT_VIRTUALTABLE + sqlite3InsertBuiltinFuncs(aJsonFunc, ArraySize(aJsonFunc)); +#endif +} + +#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON) +/* +** Register the JSON table-valued functions +*/ +SQLITE_PRIVATE int sqlite3JsonTableFunctions(sqlite3 *db){ + int rc = SQLITE_OK; static const struct { - const char *zName; - sqlite3_module *pModule; + const char *zName; + sqlite3_module *pModule; } aMod[] = { { "json_each", &jsonEachModule }, { "json_tree", &jsonTreeModule }, }; -#endif - static const int enc = - SQLITE_UTF8 | - SQLITE_DETERMINISTIC | - SQLITE_INNOCUOUS; - for(i=0; iz[0]) ) p->z++; + while( fast_isspace(p->z[0]) ) p->z++; return p->z[0]; } @@ -200008,7 +204243,7 @@ static int geopolyUpdate( sqlite3_free(p); nChange = 1; } - for(jj=1; jjnAux; jj++){ + for(jj=1; jjorderByConsumed = 1; } + sqlite3VtabUsesAllSchemas(pIdxInfo); return SQLITE_OK; } @@ -208328,7 +212565,7 @@ static int dbpageUpdate( goto update_fail; } pBt = pTab->db->aDb[iDb].pBt; - if( pgno<1 || pBt==0 || pgno>(int)sqlite3BtreeLastPage(pBt) ){ + if( pgno<1 || pBt==0 || pgno>sqlite3BtreeLastPage(pBt) ){ zErr = "bad page number"; goto update_fail; } @@ -220878,6 +225115,9 @@ static Fts5ExprNearset *sqlite3Fts5ParseNearset( }else{ if( pRet->nPhrase>0 ){ Fts5ExprPhrase *pLast = pRet->apPhrase[pRet->nPhrase-1]; + assert( pParse!=0 ); + assert( pParse->apPhrase!=0 ); + assert( pParse->nPhrase>=2 ); assert( pLast==pParse->apPhrase[pParse->nPhrase-2] ); if( pPhrase->nTerm==0 ){ fts5ExprPhraseFree(pPhrase); @@ -223177,7 +227417,7 @@ struct Fts5Index { sqlite3_stmt *pWriter; /* "INSERT ... %_data VALUES(?,?)" */ sqlite3_stmt *pDeleter; /* "DELETE FROM %_data ... id>=? AND id<=?" */ sqlite3_stmt *pIdxWriter; /* "INSERT ... %_idx VALUES(?,?,?,?)" */ - sqlite3_stmt *pIdxDeleter; /* "DELETE FROM %_idx WHERE segid=? */ + sqlite3_stmt *pIdxDeleter; /* "DELETE FROM %_idx WHERE segid=?" */ sqlite3_stmt *pIdxSelect; int nRead; /* Total number of blocks read */ @@ -224760,8 +229000,12 @@ static void fts5SegIterReverseNewPage(Fts5Index *p, Fts5SegIter *pIter){ int iRowidOff; iRowidOff = fts5LeafFirstRowidOff(pNew); if( iRowidOff ){ - pIter->pLeaf = pNew; - pIter->iLeafOffset = iRowidOff; + if( iRowidOff>=pNew->szLeaf ){ + p->rc = FTS5_CORRUPT; + }else{ + pIter->pLeaf = pNew; + pIter->iLeafOffset = iRowidOff; + } } } @@ -228442,7 +232686,7 @@ static int sqlite3Fts5IndexQuery( if( sqlite3Fts5BufferSize(&p->rc, &buf, nToken+1)==0 ){ int iIdx = 0; /* Index to search */ int iPrefixIdx = 0; /* +1 prefix index */ - if( nToken ) memcpy(&buf.p[1], pToken, nToken); + if( nToken>0 ) memcpy(&buf.p[1], pToken, nToken); /* Figure out which index to search and set iIdx accordingly. If this ** is a prefix query for which there is no prefix index, set iIdx to @@ -230501,7 +234745,7 @@ static int fts5SorterNext(Fts5Cursor *pCsr){ rc = sqlite3_step(pSorter->pStmt); if( rc==SQLITE_DONE ){ rc = SQLITE_OK; - CsrFlagSet(pCsr, FTS5CSR_EOF); + CsrFlagSet(pCsr, FTS5CSR_EOF|FTS5CSR_REQUIRE_CONTENT); }else if( rc==SQLITE_ROW ){ const u8 *a; const u8 *aBlob; @@ -232490,7 +236734,7 @@ static void fts5SourceIdFunc( ){ assert( nArg==0 ); UNUSED_PARAM2(nArg, apUnused); - sqlite3_result_text(pCtx, "fts5: 2021-11-27 14:13:22 bd41822c7424d393a30e92ff6cb254d25c26769889c1499a18a0b9339f5d6c8a", -1, SQLITE_TRANSIENT); + sqlite3_result_text(pCtx, "fts5: 2022-09-29 15:55:41 a29f9949895322123f7c38fbe94c649a9d6e6c9cd0c3b41c96d694552f26b309", -1, SQLITE_TRANSIENT); } /* @@ -237161,6 +241405,16 @@ SQLITE_EXTENSION_INIT1 #ifndef SQLITE_OMIT_VIRTUALTABLE + +#define STMT_NUM_INTEGER_COLUMN 10 +typedef struct StmtRow StmtRow; +struct StmtRow { + sqlite3_int64 iRowid; /* Rowid value */ + char *zSql; /* column "sql" */ + int aCol[STMT_NUM_INTEGER_COLUMN+1]; /* all other column values */ + StmtRow *pNext; /* Next row to return */ +}; + /* stmt_vtab is a subclass of sqlite3_vtab which will ** serve as the underlying representation of a stmt virtual table */ @@ -237178,8 +241432,7 @@ typedef struct stmt_cursor stmt_cursor; struct stmt_cursor { sqlite3_vtab_cursor base; /* Base class - must be first */ sqlite3 *db; /* Database connection for this cursor */ - sqlite3_stmt *pStmt; /* Statement cursor is currently pointing at */ - sqlite3_int64 iRowid; /* The rowid */ + StmtRow *pRow; /* Current row */ }; /* @@ -237223,7 +241476,7 @@ static int stmtConnect( "CREATE TABLE x(sql,ncol,ro,busy,nscan,nsort,naidx,nstep," "reprep,run,mem)"); if( rc==SQLITE_OK ){ - pNew = sqlite3_malloc( sizeof(*pNew) ); + pNew = sqlite3_malloc64( sizeof(*pNew) ); *ppVtab = (sqlite3_vtab*)pNew; if( pNew==0 ) return SQLITE_NOMEM; memset(pNew, 0, sizeof(*pNew)); @@ -237245,7 +241498,7 @@ static int stmtDisconnect(sqlite3_vtab *pVtab){ */ static int stmtOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ stmt_cursor *pCur; - pCur = sqlite3_malloc( sizeof(*pCur) ); + pCur = sqlite3_malloc64( sizeof(*pCur) ); if( pCur==0 ) return SQLITE_NOMEM; memset(pCur, 0, sizeof(*pCur)); pCur->db = ((stmt_vtab*)p)->db; @@ -237253,10 +241506,21 @@ static int stmtOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){ return SQLITE_OK; } +static void stmtCsrReset(stmt_cursor *pCur){ + StmtRow *pRow = 0; + StmtRow *pNext = 0; + for(pRow=pCur->pRow; pRow; pRow=pNext){ + pNext = pRow->pNext; + sqlite3_free(pRow); + } + pCur->pRow = 0; +} + /* ** Destructor for a stmt_cursor. */ static int stmtClose(sqlite3_vtab_cursor *cur){ + stmtCsrReset((stmt_cursor*)cur); sqlite3_free(cur); return SQLITE_OK; } @@ -237267,8 +241531,9 @@ static int stmtClose(sqlite3_vtab_cursor *cur){ */ static int stmtNext(sqlite3_vtab_cursor *cur){ stmt_cursor *pCur = (stmt_cursor*)cur; - pCur->iRowid++; - pCur->pStmt = sqlite3_next_stmt(pCur->db, pCur->pStmt); + StmtRow *pNext = pCur->pRow->pNext; + sqlite3_free(pCur->pRow); + pCur->pRow = pNext; return SQLITE_OK; } @@ -237282,39 +241547,11 @@ static int stmtColumn( int i /* Which column to return */ ){ stmt_cursor *pCur = (stmt_cursor*)cur; - switch( i ){ - case STMT_COLUMN_SQL: { - sqlite3_result_text(ctx, sqlite3_sql(pCur->pStmt), -1, SQLITE_TRANSIENT); - break; - } - case STMT_COLUMN_NCOL: { - sqlite3_result_int(ctx, sqlite3_column_count(pCur->pStmt)); - break; - } - case STMT_COLUMN_RO: { - sqlite3_result_int(ctx, sqlite3_stmt_readonly(pCur->pStmt)); - break; - } - case STMT_COLUMN_BUSY: { - sqlite3_result_int(ctx, sqlite3_stmt_busy(pCur->pStmt)); - break; - } - default: { - assert( i==STMT_COLUMN_MEM ); - i = SQLITE_STMTSTATUS_MEMUSED + - STMT_COLUMN_NSCAN - SQLITE_STMTSTATUS_FULLSCAN_STEP; - /* Fall thru */ - } - case STMT_COLUMN_NSCAN: - case STMT_COLUMN_NSORT: - case STMT_COLUMN_NAIDX: - case STMT_COLUMN_NSTEP: - case STMT_COLUMN_REPREP: - case STMT_COLUMN_RUN: { - sqlite3_result_int(ctx, sqlite3_stmt_status(pCur->pStmt, - i-STMT_COLUMN_NSCAN+SQLITE_STMTSTATUS_FULLSCAN_STEP, 0)); - break; - } + StmtRow *pRow = pCur->pRow; + if( i==STMT_COLUMN_SQL ){ + sqlite3_result_text(ctx, pRow->zSql, -1, SQLITE_TRANSIENT); + }else{ + sqlite3_result_int(ctx, pRow->aCol[i]); } return SQLITE_OK; } @@ -237325,7 +241562,7 @@ static int stmtColumn( */ static int stmtRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ stmt_cursor *pCur = (stmt_cursor*)cur; - *pRowid = pCur->iRowid; + *pRowid = pCur->pRow->iRowid; return SQLITE_OK; } @@ -237335,7 +241572,7 @@ static int stmtRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ */ static int stmtEof(sqlite3_vtab_cursor *cur){ stmt_cursor *pCur = (stmt_cursor*)cur; - return pCur->pStmt==0; + return pCur->pRow==0; } /* @@ -237350,9 +241587,53 @@ static int stmtFilter( int argc, sqlite3_value **argv ){ stmt_cursor *pCur = (stmt_cursor *)pVtabCursor; - pCur->pStmt = 0; - pCur->iRowid = 0; - return stmtNext(pVtabCursor); + sqlite3_stmt *p = 0; + sqlite3_int64 iRowid = 1; + StmtRow **ppRow = 0; + + stmtCsrReset(pCur); + ppRow = &pCur->pRow; + for(p=sqlite3_next_stmt(pCur->db, 0); p; p=sqlite3_next_stmt(pCur->db, p)){ + const char *zSql = sqlite3_sql(p); + sqlite3_int64 nSql = zSql ? strlen(zSql)+1 : 0; + StmtRow *pNew = (StmtRow*)sqlite3_malloc64(sizeof(StmtRow) + nSql); + + if( pNew==0 ) return SQLITE_NOMEM; + memset(pNew, 0, sizeof(StmtRow)); + if( zSql ){ + pNew->zSql = (char*)&pNew[1]; + memcpy(pNew->zSql, zSql, nSql); + } + pNew->aCol[STMT_COLUMN_NCOL] = sqlite3_column_count(p); + pNew->aCol[STMT_COLUMN_RO] = sqlite3_stmt_readonly(p); + pNew->aCol[STMT_COLUMN_BUSY] = sqlite3_stmt_busy(p); + pNew->aCol[STMT_COLUMN_NSCAN] = sqlite3_stmt_status( + p, SQLITE_STMTSTATUS_FULLSCAN_STEP, 0 + ); + pNew->aCol[STMT_COLUMN_NSORT] = sqlite3_stmt_status( + p, SQLITE_STMTSTATUS_SORT, 0 + ); + pNew->aCol[STMT_COLUMN_NAIDX] = sqlite3_stmt_status( + p, SQLITE_STMTSTATUS_AUTOINDEX, 0 + ); + pNew->aCol[STMT_COLUMN_NSTEP] = sqlite3_stmt_status( + p, SQLITE_STMTSTATUS_VM_STEP, 0 + ); + pNew->aCol[STMT_COLUMN_REPREP] = sqlite3_stmt_status( + p, SQLITE_STMTSTATUS_REPREPARE, 0 + ); + pNew->aCol[STMT_COLUMN_RUN] = sqlite3_stmt_status( + p, SQLITE_STMTSTATUS_RUN, 0 + ); + pNew->aCol[STMT_COLUMN_MEM] = sqlite3_stmt_status( + p, SQLITE_STMTSTATUS_MEMUSED, 0 + ); + pNew->iRowid = iRowid++; + *ppRow = pNew; + ppRow = &pNew->pNext; + } + + return SQLITE_OK; } /* diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3-binding.h b/vendor/github.com/mattn/go-sqlite3/sqlite3-binding.h index 6bf2c58aed..ab00ef50c7 100644 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3-binding.h +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3-binding.h @@ -147,9 +147,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.37.0" -#define SQLITE_VERSION_NUMBER 3037000 -#define SQLITE_SOURCE_ID "2021-11-27 14:13:22 bd41822c7424d393a30e92ff6cb254d25c26769889c1499a18a0b9339f5d6c8a" +#define SQLITE_VERSION "3.39.4" +#define SQLITE_VERSION_NUMBER 3039004 +#define SQLITE_SOURCE_ID "2022-09-29 15:55:41 a29f9949895322123f7c38fbe94c649a9d6e6c9cd0c3b41c96d694552f26b309" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -567,7 +567,7 @@ SQLITE_API int sqlite3_exec( #define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8)) #define SQLITE_AUTH_USER (SQLITE_AUTH | (1<<8)) #define SQLITE_OK_LOAD_PERMANENTLY (SQLITE_OK | (1<<8)) -#define SQLITE_OK_SYMLINK (SQLITE_OK | (2<<8)) +#define SQLITE_OK_SYMLINK (SQLITE_OK | (2<<8)) /* internal use only */ /* ** CAPI3REF: Flags For File Open Operations @@ -3825,13 +3825,14 @@ SQLITE_API void sqlite3_free_filename(char*); ** sqlite3_extended_errcode() might change with each API call. ** Except, there are some interfaces that are guaranteed to never ** change the value of the error code. The error-code preserving -** interfaces are: +** interfaces include the following: ** **
      **
    • sqlite3_errcode() **
    • sqlite3_extended_errcode() **
    • sqlite3_errmsg() **
    • sqlite3_errmsg16() +**
    • sqlite3_error_offset() **
    ** ** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language @@ -3846,6 +3847,13 @@ SQLITE_API void sqlite3_free_filename(char*); ** ^(Memory to hold the error message string is managed internally ** and must not be freed by the application)^. ** +** ^If the most recent error references a specific token in the input +** SQL, the sqlite3_error_offset() interface returns the byte offset +** of the start of that token. ^The byte offset returned by +** sqlite3_error_offset() assumes that the input SQL is UTF8. +** ^If the most recent error does not reference a specific token in the input +** SQL, then the sqlite3_error_offset() function returns -1. +** ** When the serialized [threading mode] is in use, it might be the ** case that a second error occurs on a separate thread in between ** the time of the first error and the call to these interfaces. @@ -3865,6 +3873,7 @@ SQLITE_API int sqlite3_extended_errcode(sqlite3 *db); SQLITE_API const char *sqlite3_errmsg(sqlite3*); SQLITE_API const void *sqlite3_errmsg16(sqlite3*); SQLITE_API const char *sqlite3_errstr(int); +SQLITE_API int sqlite3_error_offset(sqlite3 *db); /* ** CAPI3REF: Prepared Statement Object @@ -4276,6 +4285,10 @@ SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt); ** be false. ^Similarly, a CREATE TABLE IF NOT EXISTS statement is a ** read-only no-op if the table already exists, but ** sqlite3_stmt_readonly() still returns false for such a statement. +** +** ^If prepared statement X is an [EXPLAIN] or [EXPLAIN QUERY PLAN] +** statement, then sqlite3_stmt_readonly(X) returns the same value as +** if the EXPLAIN or EXPLAIN QUERY PLAN prefix were omitted. */ SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); @@ -4344,6 +4357,8 @@ SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt*); ** ** ^The sqlite3_value objects that are passed as parameters into the ** implementation of [application-defined SQL functions] are protected. +** ^The sqlite3_value objects returned by [sqlite3_vtab_rhs_value()] +** are protected. ** ^The sqlite3_value object returned by ** [sqlite3_column_value()] is unprotected. ** Unprotected sqlite3_value objects may only be used as arguments @@ -4965,6 +4980,10 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); ** even empty strings, are always zero-terminated. ^The return ** value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer. ** +** ^Strings returned by sqlite3_column_text16() always have the endianness +** which is native to the platform, regardless of the text encoding set +** for the database. +** ** Warning: ^The object returned by [sqlite3_column_value()] is an ** [unprotected sqlite3_value] object. In a multithreaded environment, ** an unprotected sqlite3_value object may only be used safely with @@ -4978,7 +4997,7 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); ** [application-defined SQL functions] or [virtual tables], not within ** top-level application code. ** -** The these routines may attempt to convert the datatype of the result. +** These routines may attempt to convert the datatype of the result. ** ^For example, if the internal representation is FLOAT and a text result ** is requested, [sqlite3_snprintf()] is used internally to perform the ** conversion automatically. ^(The following table details the conversions @@ -5003,7 +5022,7 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt); ** TEXT BLOB No change ** BLOB INTEGER [CAST] to INTEGER ** BLOB FLOAT [CAST] to REAL -** BLOB TEXT Add a zero terminator if needed +** BLOB TEXT [CAST] to TEXT, ensure zero terminator ** ** )^ ** @@ -5575,7 +5594,8 @@ SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value*); ** object D and returns a pointer to that copy. ^The [sqlite3_value] returned ** is a [protected sqlite3_value] object even if the input is not. ** ^The sqlite3_value_dup(V) interface returns NULL if V is NULL or if a -** memory allocation fails. +** memory allocation fails. ^If V is a [pointer value], then the result +** of sqlite3_value_dup(V) is a NULL value. ** ** ^The sqlite3_value_free(V) interface frees an [sqlite3_value] object ** previously obtained from [sqlite3_value_dup()]. ^If V is a NULL pointer @@ -6257,6 +6277,28 @@ SQLITE_API int sqlite3_get_autocommit(sqlite3*); */ SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*); +/* +** CAPI3REF: Return The Schema Name For A Database Connection +** METHOD: sqlite3 +** +** ^The sqlite3_db_name(D,N) interface returns a pointer to the schema name +** for the N-th database on database connection D, or a NULL pointer of N is +** out of range. An N value of 0 means the main database file. An N of 1 is +** the "temp" schema. Larger values of N correspond to various ATTACH-ed +** databases. +** +** Space to hold the string that is returned by sqlite3_db_name() is managed +** by SQLite itself. The string might be deallocated by any operation that +** changes the schema, including [ATTACH] or [DETACH] or calls to +** [sqlite3_serialize()] or [sqlite3_deserialize()], even operations that +** occur on a different thread. Applications that need to +** remember the string long-term should make their own copy. Applications that +** are accessing the same database connection simultaneously on multiple +** threads should mutex-protect calls to this API and should make their own +** private copy of the result prior to releasing the mutex. +*/ +SQLITE_API const char *sqlite3_db_name(sqlite3 *db, int N); + /* ** CAPI3REF: Return The Filename For A Database Connection ** METHOD: sqlite3 @@ -7123,24 +7165,56 @@ struct sqlite3_index_info { ** ** These macros define the allowed values for the ** [sqlite3_index_info].aConstraint[].op field. Each value represents -** an operator that is part of a constraint term in the wHERE clause of +** an operator that is part of a constraint term in the WHERE clause of ** a query that uses a [virtual table]. -*/ -#define SQLITE_INDEX_CONSTRAINT_EQ 2 -#define SQLITE_INDEX_CONSTRAINT_GT 4 -#define SQLITE_INDEX_CONSTRAINT_LE 8 -#define SQLITE_INDEX_CONSTRAINT_LT 16 -#define SQLITE_INDEX_CONSTRAINT_GE 32 -#define SQLITE_INDEX_CONSTRAINT_MATCH 64 -#define SQLITE_INDEX_CONSTRAINT_LIKE 65 -#define SQLITE_INDEX_CONSTRAINT_GLOB 66 -#define SQLITE_INDEX_CONSTRAINT_REGEXP 67 -#define SQLITE_INDEX_CONSTRAINT_NE 68 -#define SQLITE_INDEX_CONSTRAINT_ISNOT 69 -#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70 -#define SQLITE_INDEX_CONSTRAINT_ISNULL 71 -#define SQLITE_INDEX_CONSTRAINT_IS 72 -#define SQLITE_INDEX_CONSTRAINT_FUNCTION 150 +** +** ^The left-hand operand of the operator is given by the corresponding +** aConstraint[].iColumn field. ^An iColumn of -1 indicates the left-hand +** operand is the rowid. +** The SQLITE_INDEX_CONSTRAINT_LIMIT and SQLITE_INDEX_CONSTRAINT_OFFSET +** operators have no left-hand operand, and so for those operators the +** corresponding aConstraint[].iColumn is meaningless and should not be +** used. +** +** All operator values from SQLITE_INDEX_CONSTRAINT_FUNCTION through +** value 255 are reserved to represent functions that are overloaded +** by the [xFindFunction|xFindFunction method] of the virtual table +** implementation. +** +** The right-hand operands for each constraint might be accessible using +** the [sqlite3_vtab_rhs_value()] interface. Usually the right-hand +** operand is only available if it appears as a single constant literal +** in the input SQL. If the right-hand operand is another column or an +** expression (even a constant expression) or a parameter, then the +** sqlite3_vtab_rhs_value() probably will not be able to extract it. +** ^The SQLITE_INDEX_CONSTRAINT_ISNULL and +** SQLITE_INDEX_CONSTRAINT_ISNOTNULL operators have no right-hand operand +** and hence calls to sqlite3_vtab_rhs_value() for those operators will +** always return SQLITE_NOTFOUND. +** +** The collating sequence to be used for comparison can be found using +** the [sqlite3_vtab_collation()] interface. For most real-world virtual +** tables, the collating sequence of constraints does not matter (for example +** because the constraints are numeric) and so the sqlite3_vtab_collation() +** interface is no commonly needed. +*/ +#define SQLITE_INDEX_CONSTRAINT_EQ 2 +#define SQLITE_INDEX_CONSTRAINT_GT 4 +#define SQLITE_INDEX_CONSTRAINT_LE 8 +#define SQLITE_INDEX_CONSTRAINT_LT 16 +#define SQLITE_INDEX_CONSTRAINT_GE 32 +#define SQLITE_INDEX_CONSTRAINT_MATCH 64 +#define SQLITE_INDEX_CONSTRAINT_LIKE 65 +#define SQLITE_INDEX_CONSTRAINT_GLOB 66 +#define SQLITE_INDEX_CONSTRAINT_REGEXP 67 +#define SQLITE_INDEX_CONSTRAINT_NE 68 +#define SQLITE_INDEX_CONSTRAINT_ISNOT 69 +#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70 +#define SQLITE_INDEX_CONSTRAINT_ISNULL 71 +#define SQLITE_INDEX_CONSTRAINT_IS 72 +#define SQLITE_INDEX_CONSTRAINT_LIMIT 73 +#define SQLITE_INDEX_CONSTRAINT_OFFSET 74 +#define SQLITE_INDEX_CONSTRAINT_FUNCTION 150 /* ** CAPI3REF: Register A Virtual Table Implementation @@ -7169,7 +7243,7 @@ struct sqlite3_index_info { ** destructor. ** ** ^If the third parameter (the pointer to the sqlite3_module object) is -** NULL then no new module is create and any existing modules with the +** NULL then no new module is created and any existing modules with the ** same name are dropped. ** ** See also: [sqlite3_drop_modules()] @@ -7945,7 +8019,8 @@ SQLITE_API int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_SEEK_COUNT 30 #define SQLITE_TESTCTRL_TRACEFLAGS 31 #define SQLITE_TESTCTRL_TUNE 32 -#define SQLITE_TESTCTRL_LAST 32 /* Largest TESTCTRL */ +#define SQLITE_TESTCTRL_LOGEST 33 +#define SQLITE_TESTCTRL_LAST 33 /* Largest TESTCTRL */ /* ** CAPI3REF: SQL Keyword Checking @@ -8468,6 +8543,16 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); ** The counter is incremented on the first [sqlite3_step()] call of each ** cycle. ** +** [[SQLITE_STMTSTATUS_FILTER_MISS]] +** [[SQLITE_STMTSTATUS_FILTER HIT]] +**
    SQLITE_STMTSTATUS_FILTER_HIT
    +** SQLITE_STMTSTATUS_FILTER_MISS
    +**
    ^SQLITE_STMTSTATUS_FILTER_HIT is the number of times that a join +** step was bypassed because a Bloom filter returned not-found. The +** corresponding SQLITE_STMTSTATUS_FILTER_MISS value is the number of +** times that the Bloom filter returned a find, and thus the join step +** had to be processed as normal. +** ** [[SQLITE_STMTSTATUS_MEMUSED]]
    SQLITE_STMTSTATUS_MEMUSED
    **
    ^This is the approximate number of bytes of heap memory ** used to store the prepared statement. ^This value is not actually @@ -8482,6 +8567,8 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg); #define SQLITE_STMTSTATUS_VM_STEP 4 #define SQLITE_STMTSTATUS_REPREPARE 5 #define SQLITE_STMTSTATUS_RUN 6 +#define SQLITE_STMTSTATUS_FILTER_MISS 7 +#define SQLITE_STMTSTATUS_FILTER_HIT 8 #define SQLITE_STMTSTATUS_MEMUSED 99 /* @@ -9450,19 +9537,276 @@ SQLITE_API int sqlite3_vtab_nochange(sqlite3_context*); /* ** CAPI3REF: Determine The Collation For a Virtual Table Constraint +** METHOD: sqlite3_index_info ** ** This function may only be called from within a call to the [xBestIndex] -** method of a [virtual table]. +** method of a [virtual table]. This function returns a pointer to a string +** that is the name of the appropriate collation sequence to use for text +** comparisons on the constraint identified by its arguments. +** +** The first argument must be the pointer to the [sqlite3_index_info] object +** that is the first parameter to the xBestIndex() method. The second argument +** must be an index into the aConstraint[] array belonging to the +** sqlite3_index_info structure passed to xBestIndex. +** +** Important: +** The first parameter must be the same pointer that is passed into the +** xBestMethod() method. The first parameter may not be a pointer to a +** different [sqlite3_index_info] object, even an exact copy. ** -** The first argument must be the sqlite3_index_info object that is the -** first parameter to the xBestIndex() method. The second argument must be -** an index into the aConstraint[] array belonging to the sqlite3_index_info -** structure passed to xBestIndex. This function returns a pointer to a buffer -** containing the name of the collation sequence for the corresponding -** constraint. +** The return value is computed as follows: +** +**
      +**
    1. If the constraint comes from a WHERE clause expression that contains +** a [COLLATE operator], then the name of the collation specified by +** that COLLATE operator is returned. +**

    2. If there is no COLLATE operator, but the column that is the subject +** of the constraint specifies an alternative collating sequence via +** a [COLLATE clause] on the column definition within the CREATE TABLE +** statement that was passed into [sqlite3_declare_vtab()], then the +** name of that alternative collating sequence is returned. +**

    3. Otherwise, "BINARY" is returned. +**

    */ SQLITE_API SQLITE_EXPERIMENTAL const char *sqlite3_vtab_collation(sqlite3_index_info*,int); +/* +** CAPI3REF: Determine if a virtual table query is DISTINCT +** METHOD: sqlite3_index_info +** +** This API may only be used from within an [xBestIndex|xBestIndex method] +** of a [virtual table] implementation. The result of calling this +** interface from outside of xBestIndex() is undefined and probably harmful. +** +** ^The sqlite3_vtab_distinct() interface returns an integer between 0 and +** 3. The integer returned by sqlite3_vtab_distinct() +** gives the virtual table additional information about how the query +** planner wants the output to be ordered. As long as the virtual table +** can meet the ordering requirements of the query planner, it may set +** the "orderByConsumed" flag. +** +**
    1. +** ^If the sqlite3_vtab_distinct() interface returns 0, that means +** that the query planner needs the virtual table to return all rows in the +** sort order defined by the "nOrderBy" and "aOrderBy" fields of the +** [sqlite3_index_info] object. This is the default expectation. If the +** virtual table outputs all rows in sorted order, then it is always safe for +** the xBestIndex method to set the "orderByConsumed" flag, regardless of +** the return value from sqlite3_vtab_distinct(). +**

    2. +** ^(If the sqlite3_vtab_distinct() interface returns 1, that means +** that the query planner does not need the rows to be returned in sorted order +** as long as all rows with the same values in all columns identified by the +** "aOrderBy" field are adjacent.)^ This mode is used when the query planner +** is doing a GROUP BY. +**

    3. +** ^(If the sqlite3_vtab_distinct() interface returns 2, that means +** that the query planner does not need the rows returned in any particular +** order, as long as rows with the same values in all "aOrderBy" columns +** are adjacent.)^ ^(Furthermore, only a single row for each particular +** combination of values in the columns identified by the "aOrderBy" field +** needs to be returned.)^ ^It is always ok for two or more rows with the same +** values in all "aOrderBy" columns to be returned, as long as all such rows +** are adjacent. ^The virtual table may, if it chooses, omit extra rows +** that have the same value for all columns identified by "aOrderBy". +** ^However omitting the extra rows is optional. +** This mode is used for a DISTINCT query. +**

    4. +** ^(If the sqlite3_vtab_distinct() interface returns 3, that means +** that the query planner needs only distinct rows but it does need the +** rows to be sorted.)^ ^The virtual table implementation is free to omit +** rows that are identical in all aOrderBy columns, if it wants to, but +** it is not required to omit any rows. This mode is used for queries +** that have both DISTINCT and ORDER BY clauses. +**

    +** +** ^For the purposes of comparing virtual table output values to see if the +** values are same value for sorting purposes, two NULL values are considered +** to be the same. In other words, the comparison operator is "IS" +** (or "IS NOT DISTINCT FROM") and not "==". +** +** If a virtual table implementation is unable to meet the requirements +** specified above, then it must not set the "orderByConsumed" flag in the +** [sqlite3_index_info] object or an incorrect answer may result. +** +** ^A virtual table implementation is always free to return rows in any order +** it wants, as long as the "orderByConsumed" flag is not set. ^When the +** the "orderByConsumed" flag is unset, the query planner will add extra +** [bytecode] to ensure that the final results returned by the SQL query are +** ordered correctly. The use of the "orderByConsumed" flag and the +** sqlite3_vtab_distinct() interface is merely an optimization. ^Careful +** use of the sqlite3_vtab_distinct() interface and the "orderByConsumed" +** flag might help queries against a virtual table to run faster. Being +** overly aggressive and setting the "orderByConsumed" flag when it is not +** valid to do so, on the other hand, might cause SQLite to return incorrect +** results. +*/ +SQLITE_API int sqlite3_vtab_distinct(sqlite3_index_info*); + +/* +** CAPI3REF: Identify and handle IN constraints in xBestIndex +** +** This interface may only be used from within an +** [xBestIndex|xBestIndex() method] of a [virtual table] implementation. +** The result of invoking this interface from any other context is +** undefined and probably harmful. +** +** ^(A constraint on a virtual table of the form +** "[IN operator|column IN (...)]" is +** communicated to the xBestIndex method as a +** [SQLITE_INDEX_CONSTRAINT_EQ] constraint.)^ If xBestIndex wants to use +** this constraint, it must set the corresponding +** aConstraintUsage[].argvIndex to a postive integer. ^(Then, under +** the usual mode of handling IN operators, SQLite generates [bytecode] +** that invokes the [xFilter|xFilter() method] once for each value +** on the right-hand side of the IN operator.)^ Thus the virtual table +** only sees a single value from the right-hand side of the IN operator +** at a time. +** +** In some cases, however, it would be advantageous for the virtual +** table to see all values on the right-hand of the IN operator all at +** once. The sqlite3_vtab_in() interfaces facilitates this in two ways: +** +**
      +**
    1. +** ^A call to sqlite3_vtab_in(P,N,-1) will return true (non-zero) +** if and only if the [sqlite3_index_info|P->aConstraint][N] constraint +** is an [IN operator] that can be processed all at once. ^In other words, +** sqlite3_vtab_in() with -1 in the third argument is a mechanism +** by which the virtual table can ask SQLite if all-at-once processing +** of the IN operator is even possible. +** +**

    2. +** ^A call to sqlite3_vtab_in(P,N,F) with F==1 or F==0 indicates +** to SQLite that the virtual table does or does not want to process +** the IN operator all-at-once, respectively. ^Thus when the third +** parameter (F) is non-negative, this interface is the mechanism by +** which the virtual table tells SQLite how it wants to process the +** IN operator. +**

    +** +** ^The sqlite3_vtab_in(P,N,F) interface can be invoked multiple times +** within the same xBestIndex method call. ^For any given P,N pair, +** the return value from sqlite3_vtab_in(P,N,F) will always be the same +** within the same xBestIndex call. ^If the interface returns true +** (non-zero), that means that the constraint is an IN operator +** that can be processed all-at-once. ^If the constraint is not an IN +** operator or cannot be processed all-at-once, then the interface returns +** false. +** +** ^(All-at-once processing of the IN operator is selected if both of the +** following conditions are met: +** +**
      +**
    1. The P->aConstraintUsage[N].argvIndex value is set to a positive +** integer. This is how the virtual table tells SQLite that it wants to +** use the N-th constraint. +** +**

    2. The last call to sqlite3_vtab_in(P,N,F) for which F was +** non-negative had F>=1. +**

    )^ +** +** ^If either or both of the conditions above are false, then SQLite uses +** the traditional one-at-a-time processing strategy for the IN constraint. +** ^If both conditions are true, then the argvIndex-th parameter to the +** xFilter method will be an [sqlite3_value] that appears to be NULL, +** but which can be passed to [sqlite3_vtab_in_first()] and +** [sqlite3_vtab_in_next()] to find all values on the right-hand side +** of the IN constraint. +*/ +SQLITE_API int sqlite3_vtab_in(sqlite3_index_info*, int iCons, int bHandle); + +/* +** CAPI3REF: Find all elements on the right-hand side of an IN constraint. +** +** These interfaces are only useful from within the +** [xFilter|xFilter() method] of a [virtual table] implementation. +** The result of invoking these interfaces from any other context +** is undefined and probably harmful. +** +** The X parameter in a call to sqlite3_vtab_in_first(X,P) or +** sqlite3_vtab_in_next(X,P) must be one of the parameters to the +** xFilter method which invokes these routines, and specifically +** a parameter that was previously selected for all-at-once IN constraint +** processing use the [sqlite3_vtab_in()] interface in the +** [xBestIndex|xBestIndex method]. ^(If the X parameter is not +** an xFilter argument that was selected for all-at-once IN constraint +** processing, then these routines return [SQLITE_MISUSE])^ or perhaps +** exhibit some other undefined or harmful behavior. +** +** ^(Use these routines to access all values on the right-hand side +** of the IN constraint using code like the following: +** +**
    +**    for(rc=sqlite3_vtab_in_first(pList, &pVal);
    +**        rc==SQLITE_OK && pVal
    +**        rc=sqlite3_vtab_in_next(pList, &pVal)
    +**    ){
    +**      // do something with pVal
    +**    }
    +**    if( rc!=SQLITE_OK ){
    +**      // an error has occurred
    +**    }
    +** 
    )^ +** +** ^On success, the sqlite3_vtab_in_first(X,P) and sqlite3_vtab_in_next(X,P) +** routines return SQLITE_OK and set *P to point to the first or next value +** on the RHS of the IN constraint. ^If there are no more values on the +** right hand side of the IN constraint, then *P is set to NULL and these +** routines return [SQLITE_DONE]. ^The return value might be +** some other value, such as SQLITE_NOMEM, in the event of a malfunction. +** +** The *ppOut values returned by these routines are only valid until the +** next call to either of these routines or until the end of the xFilter +** method from which these routines were called. If the virtual table +** implementation needs to retain the *ppOut values for longer, it must make +** copies. The *ppOut values are [protected sqlite3_value|protected]. +*/ +SQLITE_API int sqlite3_vtab_in_first(sqlite3_value *pVal, sqlite3_value **ppOut); +SQLITE_API int sqlite3_vtab_in_next(sqlite3_value *pVal, sqlite3_value **ppOut); + +/* +** CAPI3REF: Constraint values in xBestIndex() +** METHOD: sqlite3_index_info +** +** This API may only be used from within the [xBestIndex|xBestIndex method] +** of a [virtual table] implementation. The result of calling this interface +** from outside of an xBestIndex method are undefined and probably harmful. +** +** ^When the sqlite3_vtab_rhs_value(P,J,V) interface is invoked from within +** the [xBestIndex] method of a [virtual table] implementation, with P being +** a copy of the [sqlite3_index_info] object pointer passed into xBestIndex and +** J being a 0-based index into P->aConstraint[], then this routine +** attempts to set *V to the value of the right-hand operand of +** that constraint if the right-hand operand is known. ^If the +** right-hand operand is not known, then *V is set to a NULL pointer. +** ^The sqlite3_vtab_rhs_value(P,J,V) interface returns SQLITE_OK if +** and only if *V is set to a value. ^The sqlite3_vtab_rhs_value(P,J,V) +** inteface returns SQLITE_NOTFOUND if the right-hand side of the J-th +** constraint is not available. ^The sqlite3_vtab_rhs_value() interface +** can return an result code other than SQLITE_OK or SQLITE_NOTFOUND if +** something goes wrong. +** +** The sqlite3_vtab_rhs_value() interface is usually only successful if +** the right-hand operand of a constraint is a literal value in the original +** SQL statement. If the right-hand operand is an expression or a reference +** to some other column or a [host parameter], then sqlite3_vtab_rhs_value() +** will probably return [SQLITE_NOTFOUND]. +** +** ^(Some constraints, such as [SQLITE_INDEX_CONSTRAINT_ISNULL] and +** [SQLITE_INDEX_CONSTRAINT_ISNOTNULL], have no right-hand operand. For such +** constraints, sqlite3_vtab_rhs_value() always returns SQLITE_NOTFOUND.)^ +** +** ^The [sqlite3_value] object returned in *V is a protected sqlite3_value +** and remains valid for the duration of the xBestIndex method call. +** ^When xBestIndex returns, the sqlite3_value object returned by +** sqlite3_vtab_rhs_value() is automatically deallocated. +** +** The "_rhs_" in the name of this routine is an abbreviation for +** "Right-Hand Side". +*/ +SQLITE_API int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value **ppVal); + /* ** CAPI3REF: Conflict resolution modes ** KEYWORDS: {conflict resolution mode} diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3.go b/vendor/github.com/mattn/go-sqlite3/sqlite3.go index 6ade8c9712..9c0f4d8911 100644 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3.go +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3.go @@ -4,6 +4,7 @@ // Use of this source code is governed by an MIT-style // license that can be found in the LICENSE file. +//go:build cgo // +build cgo package sqlite3 @@ -233,8 +234,14 @@ const ( columnTimestamp string = "timestamp" ) +// This variable can be replaced with -ldflags like below: +// go build -ldflags="-X 'github.com/mattn/go-sqlite3.driverName=my-sqlite3'" +var driverName = "sqlite3" + func init() { - sql.Register("sqlite3", &SQLiteDriver{}) + if driverName != "" { + sql.Register(driverName, &SQLiteDriver{}) + } } // Version returns SQLite library version information. @@ -290,6 +297,51 @@ const ( /*SQLITE_RECURSIVE = C.SQLITE_RECURSIVE*/ ) +// Standard File Control Opcodes +// See: https://www.sqlite.org/c3ref/c_fcntl_begin_atomic_write.html +const ( + SQLITE_FCNTL_LOCKSTATE = int(1) + SQLITE_FCNTL_GET_LOCKPROXYFILE = int(2) + SQLITE_FCNTL_SET_LOCKPROXYFILE = int(3) + SQLITE_FCNTL_LAST_ERRNO = int(4) + SQLITE_FCNTL_SIZE_HINT = int(5) + SQLITE_FCNTL_CHUNK_SIZE = int(6) + SQLITE_FCNTL_FILE_POINTER = int(7) + SQLITE_FCNTL_SYNC_OMITTED = int(8) + SQLITE_FCNTL_WIN32_AV_RETRY = int(9) + SQLITE_FCNTL_PERSIST_WAL = int(10) + SQLITE_FCNTL_OVERWRITE = int(11) + SQLITE_FCNTL_VFSNAME = int(12) + SQLITE_FCNTL_POWERSAFE_OVERWRITE = int(13) + SQLITE_FCNTL_PRAGMA = int(14) + SQLITE_FCNTL_BUSYHANDLER = int(15) + SQLITE_FCNTL_TEMPFILENAME = int(16) + SQLITE_FCNTL_MMAP_SIZE = int(18) + SQLITE_FCNTL_TRACE = int(19) + SQLITE_FCNTL_HAS_MOVED = int(20) + SQLITE_FCNTL_SYNC = int(21) + SQLITE_FCNTL_COMMIT_PHASETWO = int(22) + SQLITE_FCNTL_WIN32_SET_HANDLE = int(23) + SQLITE_FCNTL_WAL_BLOCK = int(24) + SQLITE_FCNTL_ZIPVFS = int(25) + SQLITE_FCNTL_RBU = int(26) + SQLITE_FCNTL_VFS_POINTER = int(27) + SQLITE_FCNTL_JOURNAL_POINTER = int(28) + SQLITE_FCNTL_WIN32_GET_HANDLE = int(29) + SQLITE_FCNTL_PDB = int(30) + SQLITE_FCNTL_BEGIN_ATOMIC_WRITE = int(31) + SQLITE_FCNTL_COMMIT_ATOMIC_WRITE = int(32) + SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE = int(33) + SQLITE_FCNTL_LOCK_TIMEOUT = int(34) + SQLITE_FCNTL_DATA_VERSION = int(35) + SQLITE_FCNTL_SIZE_LIMIT = int(36) + SQLITE_FCNTL_CKPT_DONE = int(37) + SQLITE_FCNTL_RESERVE_BYTES = int(38) + SQLITE_FCNTL_CKPT_START = int(39) + SQLITE_FCNTL_EXTERNAL_READER = int(40) + SQLITE_FCNTL_CKSM_FILE = int(41) +) + // SQLiteDriver implements driver.Driver. type SQLiteDriver struct { Extensions []string @@ -442,10 +494,12 @@ func (ai *aggInfo) Done(ctx *C.sqlite3_context) { // Commit transaction. func (tx *SQLiteTx) Commit() error { _, err := tx.c.exec(context.Background(), "COMMIT", nil) - if err != nil && err.(Error).Code == C.SQLITE_BUSY { - // sqlite3 will leave the transaction open in this scenario. + if err != nil { + // sqlite3 may leave the transaction open in this scenario. // However, database/sql considers the transaction complete once we // return from Commit() - we must clean up to honour its semantics. + // We don't know if the ROLLBACK is strictly necessary, but according + // to sqlite's docs, there is no harm in calling ROLLBACK unnecessarily. tx.c.exec(context.Background(), "ROLLBACK", nil) } return err @@ -1806,6 +1860,31 @@ func (c *SQLiteConn) SetLimit(id int, newVal int) int { return int(C._sqlite3_limit(c.db, C.int(id), C.int(newVal))) } +// SetFileControlInt invokes the xFileControl method on a given database. The +// dbName is the name of the database. It will default to "main" if left blank. +// The op is one of the opcodes prefixed by "SQLITE_FCNTL_". The arg argument +// and return code are both opcode-specific. Please see the SQLite documentation. +// +// This method is not thread-safe as the returned error code can be changed by +// another call if invoked concurrently. +// +// See: sqlite3_file_control, https://www.sqlite.org/c3ref/file_control.html +func (c *SQLiteConn) SetFileControlInt(dbName string, op int, arg int) error { + if dbName == "" { + dbName = "main" + } + + cDBName := C.CString(dbName) + defer C.free(unsafe.Pointer(cDBName)) + + cArg := C.int(arg) + rv := C.sqlite3_file_control(c.db, cDBName, C.int(op), unsafe.Pointer(&cArg)) + if rv != C.SQLITE_OK { + return c.lastError() + } + return nil +} + // Close the statement. func (s *SQLiteStmt) Close() error { s.mu.Lock() diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_json1.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_json1.go deleted file mode 100644 index 7cfce76326..0000000000 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_json1.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (C) 2019 Yasuhiro Matsumoto . -// -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -// +build sqlite_json sqlite_json1 json1 - -package sqlite3 - -/* -#cgo CFLAGS: -DSQLITE_ENABLE_JSON1 -*/ -import "C" diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_math_functions.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_math_functions.go new file mode 100644 index 0000000000..7cd68d3f50 --- /dev/null +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_math_functions.go @@ -0,0 +1,14 @@ +// Copyright (C) 2022 Yasuhiro Matsumoto . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +// +build sqlite_math_functions + +package sqlite3 + +/* +#cgo CFLAGS: -DSQLITE_ENABLE_MATH_FUNCTIONS +#cgo LDFLAGS: -lm +*/ +import "C" diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_os_trace.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_os_trace.go new file mode 100644 index 0000000000..9a30566b3b --- /dev/null +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_os_trace.go @@ -0,0 +1,15 @@ +// Copyright (C) 2022 Yasuhiro Matsumoto . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +//go:build sqlite_os_trace +// +build sqlite_os_trace + +package sqlite3 + +/* +#cgo CFLAGS: -DSQLITE_FORCE_OS_TRACE=1 +#cgo CFLAGS: -DSQLITE_DEBUG_OS_TRACE=1 +*/ +import "C" diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_preupdate_hook.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_preupdate_hook.go index b2e18bbcbb..b43e4821b8 100644 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_preupdate_hook.go +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_preupdate_hook.go @@ -33,7 +33,7 @@ import ( // The callback is passed a SQLitePreUpdateData struct with the data for // the update, as well as methods for fetching copies of impacted data. // -// If there is an existing update hook for this connection, it will be +// If there is an existing preupdate hook for this connection, it will be // removed. If callback is nil the existing hook (if any) will be removed // without creating a new one. func (c *SQLiteConn) RegisterPreUpdateHook(callback func(SQLitePreUpdateData)) { diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_preupdate_omit.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_preupdate_omit.go index 8df453dea3..c510a15b43 100644 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_preupdate_omit.go +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_preupdate_omit.go @@ -13,7 +13,7 @@ package sqlite3 // The callback is passed a SQLitePreUpdateData struct with the data for // the update, as well as methods for fetching copies of impacted data. // -// If there is an existing update hook for this connection, it will be +// If there is an existing preupdate hook for this connection, it will be // removed. If callback is nil the existing hook (if any) will be removed // without creating a new one. func (c *SQLiteConn) RegisterPreUpdateHook(callback func(SQLitePreUpdateData)) { diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_windows.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_windows.go index 9df1961452..81aa2abde3 100644 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3_windows.go +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_windows.go @@ -12,7 +12,6 @@ package sqlite3 #cgo CFLAGS: -fno-stack-check #cgo CFLAGS: -fno-stack-protector #cgo CFLAGS: -mno-stack-arg-probe -#cgo LDFLAGS: -lmingwex -lmingw32 #cgo windows,386 CFLAGS: -D_USE_32BIT_TIME_T */ import "C" diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3ext.h b/vendor/github.com/mattn/go-sqlite3/sqlite3ext.h index fd6e2d4e86..940f162dee 100644 --- a/vendor/github.com/mattn/go-sqlite3/sqlite3ext.h +++ b/vendor/github.com/mattn/go-sqlite3/sqlite3ext.h @@ -349,6 +349,19 @@ struct sqlite3_api_routines { int (*autovacuum_pages)(sqlite3*, unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int), void*, void(*)(void*)); + /* Version 3.38.0 and later */ + int (*error_offset)(sqlite3*); + int (*vtab_rhs_value)(sqlite3_index_info*,int,sqlite3_value**); + int (*vtab_distinct)(sqlite3_index_info*); + int (*vtab_in)(sqlite3_index_info*,int,int); + int (*vtab_in_first)(sqlite3_value*,sqlite3_value**); + int (*vtab_in_next)(sqlite3_value*,sqlite3_value**); + /* Version 3.39.0 and later */ + int (*deserialize)(sqlite3*,const char*,unsigned char*, + sqlite3_int64,sqlite3_int64,unsigned); + unsigned char *(*serialize)(sqlite3*,const char *,sqlite3_int64*, + unsigned int); + const char *(*db_name)(sqlite3*,int); }; /* @@ -660,6 +673,19 @@ typedef int (*sqlite3_loadext_entry)( #define sqlite3_total_changes64 sqlite3_api->total_changes64 /* Version 3.37.0 and later */ #define sqlite3_autovacuum_pages sqlite3_api->autovacuum_pages +/* Version 3.38.0 and later */ +#define sqlite3_error_offset sqlite3_api->error_offset +#define sqlite3_vtab_rhs_value sqlite3_api->vtab_rhs_value +#define sqlite3_vtab_distinct sqlite3_api->vtab_distinct +#define sqlite3_vtab_in sqlite3_api->vtab_in +#define sqlite3_vtab_in_first sqlite3_api->vtab_in_first +#define sqlite3_vtab_in_next sqlite3_api->vtab_in_next +/* Version 3.39.0 and later */ +#ifndef SQLITE_OMIT_DESERIALIZE +#define sqlite3_deserialize sqlite3_api->deserialize +#define sqlite3_serialize sqlite3_api->serialize +#endif +#define sqlite3_db_name sqlite3_api->db_name #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) diff --git a/vendor/github.com/moby/term/doc.go b/vendor/github.com/moby/term/doc.go new file mode 100644 index 0000000000..c9bc032443 --- /dev/null +++ b/vendor/github.com/moby/term/doc.go @@ -0,0 +1,3 @@ +// Package term provides structures and helper functions to work with +// terminal (state, sizes). +package term diff --git a/vendor/github.com/moby/term/tc.go b/vendor/github.com/moby/term/tc.go deleted file mode 100644 index 65556027a6..0000000000 --- a/vendor/github.com/moby/term/tc.go +++ /dev/null @@ -1,19 +0,0 @@ -// +build !windows - -package term - -import ( - "golang.org/x/sys/unix" -) - -func tcget(fd uintptr) (*Termios, error) { - p, err := unix.IoctlGetTermios(int(fd), getTermios) - if err != nil { - return nil, err - } - return p, nil -} - -func tcset(fd uintptr, p *Termios) error { - return unix.IoctlSetTermios(int(fd), setTermios, p) -} diff --git a/vendor/github.com/moby/term/term.go b/vendor/github.com/moby/term/term.go index 29c6acf1c7..f9d8988ef8 100644 --- a/vendor/github.com/moby/term/term.go +++ b/vendor/github.com/moby/term/term.go @@ -1,120 +1,85 @@ -// +build !windows - -// Package term provides structures and helper functions to work with -// terminal (state, sizes). package term -import ( - "errors" - "fmt" - "io" - "os" - "os/signal" - - "golang.org/x/sys/unix" -) +import "io" -var ( - // ErrInvalidState is returned if the state of the terminal is invalid. - ErrInvalidState = errors.New("Invalid terminal state") -) - -// State represents the state of the terminal. -type State struct { - termios Termios -} +// State holds the platform-specific state / console mode for the terminal. +type State terminalState // Winsize represents the size of the terminal window. type Winsize struct { Height uint16 Width uint16 - x uint16 - y uint16 + + // Only used on Unix + x uint16 + y uint16 } // StdStreams returns the standard streams (stdin, stdout, stderr). +// +// On Windows, it attempts to turn on VT handling on all std handles if +// supported, or falls back to terminal emulation. On Unix, this returns +// the standard [os.Stdin], [os.Stdout] and [os.Stderr]. func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) { - return os.Stdin, os.Stdout, os.Stderr + return stdStreams() } // GetFdInfo returns the file descriptor for an os.File and indicates whether the file represents a terminal. -func GetFdInfo(in interface{}) (uintptr, bool) { - var inFd uintptr - var isTerminalIn bool - if file, ok := in.(*os.File); ok { - inFd = file.Fd() - isTerminalIn = IsTerminal(inFd) - } - return inFd, isTerminalIn +func GetFdInfo(in interface{}) (fd uintptr, isTerminal bool) { + return getFdInfo(in) +} + +// GetWinsize returns the window size based on the specified file descriptor. +func GetWinsize(fd uintptr) (*Winsize, error) { + return getWinsize(fd) +} + +// SetWinsize tries to set the specified window size for the specified file +// descriptor. It is only implemented on Unix, and returns an error on Windows. +func SetWinsize(fd uintptr, ws *Winsize) error { + return setWinsize(fd, ws) } // IsTerminal returns true if the given file descriptor is a terminal. func IsTerminal(fd uintptr) bool { - _, err := tcget(fd) - return err == nil + return isTerminal(fd) } // RestoreTerminal restores the terminal connected to the given file descriptor // to a previous state. func RestoreTerminal(fd uintptr, state *State) error { - if state == nil { - return ErrInvalidState - } - return tcset(fd, &state.termios) + return restoreTerminal(fd, state) } // SaveState saves the state of the terminal connected to the given file descriptor. func SaveState(fd uintptr) (*State, error) { - termios, err := tcget(fd) - if err != nil { - return nil, err - } - return &State{termios: *termios}, nil + return saveState(fd) } // DisableEcho applies the specified state to the terminal connected to the file // descriptor, with echo disabled. func DisableEcho(fd uintptr, state *State) error { - newState := state.termios - newState.Lflag &^= unix.ECHO - - if err := tcset(fd, &newState); err != nil { - return err - } - handleInterrupt(fd, state) - return nil + return disableEcho(fd, state) } // SetRawTerminal puts the terminal connected to the given file descriptor into -// raw mode and returns the previous state. On UNIX, this puts both the input -// and output into raw mode. On Windows, it only puts the input into raw mode. -func SetRawTerminal(fd uintptr) (*State, error) { - oldState, err := MakeRaw(fd) - if err != nil { - return nil, err - } - handleInterrupt(fd, oldState) - return oldState, err +// raw mode and returns the previous state. On UNIX, this is the equivalent of +// [MakeRaw], and puts both the input and output into raw mode. On Windows, it +// only puts the input into raw mode. +func SetRawTerminal(fd uintptr) (previousState *State, err error) { + return setRawTerminal(fd) } // SetRawTerminalOutput puts the output of terminal connected to the given file // descriptor into raw mode. On UNIX, this does nothing and returns nil for the // state. On Windows, it disables LF -> CRLF translation. -func SetRawTerminalOutput(fd uintptr) (*State, error) { - return nil, nil +func SetRawTerminalOutput(fd uintptr) (previousState *State, err error) { + return setRawTerminalOutput(fd) } -func handleInterrupt(fd uintptr, state *State) { - sigchan := make(chan os.Signal, 1) - signal.Notify(sigchan, os.Interrupt) - go func() { - for range sigchan { - // quit cleanly and the new terminal item is on a new line - fmt.Println() - signal.Stop(sigchan) - close(sigchan) - RestoreTerminal(fd, state) - os.Exit(1) - } - }() +// MakeRaw puts the terminal (Windows Console) connected to the +// given file descriptor into raw mode and returns the previous state of +// the terminal so that it can be restored. +func MakeRaw(fd uintptr) (previousState *State, err error) { + return makeRaw(fd) } diff --git a/vendor/github.com/moby/term/term_unix.go b/vendor/github.com/moby/term/term_unix.go new file mode 100644 index 0000000000..2ec7706a16 --- /dev/null +++ b/vendor/github.com/moby/term/term_unix.go @@ -0,0 +1,98 @@ +//go:build !windows +// +build !windows + +package term + +import ( + "errors" + "io" + "os" + + "golang.org/x/sys/unix" +) + +// ErrInvalidState is returned if the state of the terminal is invalid. +// +// Deprecated: ErrInvalidState is no longer used. +var ErrInvalidState = errors.New("Invalid terminal state") + +// terminalState holds the platform-specific state / console mode for the terminal. +type terminalState struct { + termios unix.Termios +} + +func stdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) { + return os.Stdin, os.Stdout, os.Stderr +} + +func getFdInfo(in interface{}) (uintptr, bool) { + var inFd uintptr + var isTerminalIn bool + if file, ok := in.(*os.File); ok { + inFd = file.Fd() + isTerminalIn = isTerminal(inFd) + } + return inFd, isTerminalIn +} + +func getWinsize(fd uintptr) (*Winsize, error) { + uws, err := unix.IoctlGetWinsize(int(fd), unix.TIOCGWINSZ) + ws := &Winsize{Height: uws.Row, Width: uws.Col, x: uws.Xpixel, y: uws.Ypixel} + return ws, err +} + +func setWinsize(fd uintptr, ws *Winsize) error { + return unix.IoctlSetWinsize(int(fd), unix.TIOCSWINSZ, &unix.Winsize{ + Row: ws.Height, + Col: ws.Width, + Xpixel: ws.x, + Ypixel: ws.y, + }) +} + +func isTerminal(fd uintptr) bool { + _, err := tcget(fd) + return err == nil +} + +func restoreTerminal(fd uintptr, state *State) error { + if state == nil { + return errors.New("invalid terminal state") + } + return tcset(fd, &state.termios) +} + +func saveState(fd uintptr) (*State, error) { + termios, err := tcget(fd) + if err != nil { + return nil, err + } + return &State{termios: *termios}, nil +} + +func disableEcho(fd uintptr, state *State) error { + newState := state.termios + newState.Lflag &^= unix.ECHO + + return tcset(fd, &newState) +} + +func setRawTerminal(fd uintptr) (*State, error) { + return makeRaw(fd) +} + +func setRawTerminalOutput(fd uintptr) (*State, error) { + return nil, nil +} + +func tcget(fd uintptr) (*unix.Termios, error) { + p, err := unix.IoctlGetTermios(int(fd), getTermios) + if err != nil { + return nil, err + } + return p, nil +} + +func tcset(fd uintptr, p *unix.Termios) error { + return unix.IoctlSetTermios(int(fd), setTermios, p) +} diff --git a/vendor/github.com/moby/term/term_windows.go b/vendor/github.com/moby/term/term_windows.go index ba82960d4a..81ccff0428 100644 --- a/vendor/github.com/moby/term/term_windows.go +++ b/vendor/github.com/moby/term/term_windows.go @@ -1,6 +1,7 @@ package term import ( + "fmt" "io" "os" "os/signal" @@ -9,22 +10,15 @@ import ( "golang.org/x/sys/windows" ) -// State holds the console mode for the terminal. -type State struct { +// terminalState holds the platform-specific state / console mode for the terminal. +type terminalState struct { mode uint32 } -// Winsize is used for window size. -type Winsize struct { - Height uint16 - Width uint16 -} - // vtInputSupported is true if winterm.ENABLE_VIRTUAL_TERMINAL_INPUT is supported by the console var vtInputSupported bool -// StdStreams returns the standard streams (stdin, stdout, stderr). -func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) { +func stdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) { // Turn on VT handling on all std handles, if possible. This might // fail, in which case we will fall back to terminal emulation. var ( @@ -66,10 +60,6 @@ func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) { } } - // Temporarily use STD_INPUT_HANDLE, STD_OUTPUT_HANDLE and - // STD_ERROR_HANDLE from syscall rather than x/sys/windows as long as - // go-ansiterm hasn't switch to x/sys/windows. - // TODO: switch back to x/sys/windows once go-ansiterm has switched if emulateStdin { h := uint32(windows.STD_INPUT_HANDLE) stdIn = windowsconsole.NewAnsiReader(int(h)) @@ -91,16 +81,14 @@ func StdStreams() (stdIn io.ReadCloser, stdOut, stdErr io.Writer) { stdErr = os.Stderr } - return + return stdIn, stdOut, stdErr } -// GetFdInfo returns the file descriptor for an os.File and indicates whether the file represents a terminal. -func GetFdInfo(in interface{}) (uintptr, bool) { +func getFdInfo(in interface{}) (uintptr, bool) { return windowsconsole.GetHandleInfo(in) } -// GetWinsize returns the window size based on the specified file descriptor. -func GetWinsize(fd uintptr) (*Winsize, error) { +func getWinsize(fd uintptr) (*Winsize, error) { var info windows.ConsoleScreenBufferInfo if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil { return nil, err @@ -114,21 +102,21 @@ func GetWinsize(fd uintptr) (*Winsize, error) { return winsize, nil } -// IsTerminal returns true if the given file descriptor is a terminal. -func IsTerminal(fd uintptr) bool { +func setWinsize(fd uintptr, ws *Winsize) error { + return fmt.Errorf("not implemented on Windows") +} + +func isTerminal(fd uintptr) bool { var mode uint32 err := windows.GetConsoleMode(windows.Handle(fd), &mode) return err == nil } -// RestoreTerminal restores the terminal connected to the given file descriptor -// to a previous state. -func RestoreTerminal(fd uintptr, state *State) error { +func restoreTerminal(fd uintptr, state *State) error { return windows.SetConsoleMode(windows.Handle(fd), state.mode) } -// SaveState saves the state of the terminal connected to the given file descriptor. -func SaveState(fd uintptr) (*State, error) { +func saveState(fd uintptr) (*State, error) { var mode uint32 if err := windows.GetConsoleMode(windows.Handle(fd), &mode); err != nil { @@ -138,9 +126,8 @@ func SaveState(fd uintptr) (*State, error) { return &State{mode: mode}, nil } -// DisableEcho disables echo for the terminal connected to the given file descriptor. -// -- See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx -func DisableEcho(fd uintptr, state *State) error { +func disableEcho(fd uintptr, state *State) error { + // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx mode := state.mode mode &^= windows.ENABLE_ECHO_INPUT mode |= windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT @@ -154,69 +141,27 @@ func DisableEcho(fd uintptr, state *State) error { return nil } -// SetRawTerminal puts the terminal connected to the given file descriptor into -// raw mode and returns the previous state. On UNIX, this puts both the input -// and output into raw mode. On Windows, it only puts the input into raw mode. -func SetRawTerminal(fd uintptr) (*State, error) { - state, err := MakeRaw(fd) +func setRawTerminal(fd uintptr) (*State, error) { + oldState, err := MakeRaw(fd) if err != nil { return nil, err } // Register an interrupt handler to catch and restore prior state - restoreAtInterrupt(fd, state) - return state, err + restoreAtInterrupt(fd, oldState) + return oldState, err } -// SetRawTerminalOutput puts the output of terminal connected to the given file -// descriptor into raw mode. On UNIX, this does nothing and returns nil for the -// state. On Windows, it disables LF -> CRLF translation. -func SetRawTerminalOutput(fd uintptr) (*State, error) { - state, err := SaveState(fd) +func setRawTerminalOutput(fd uintptr) (*State, error) { + oldState, err := saveState(fd) if err != nil { return nil, err } // Ignore failures, since winterm.DISABLE_NEWLINE_AUTO_RETURN might not be supported on this // version of Windows. - _ = windows.SetConsoleMode(windows.Handle(fd), state.mode|windows.DISABLE_NEWLINE_AUTO_RETURN) - return state, err -} - -// MakeRaw puts the terminal (Windows Console) connected to the given file descriptor into raw -// mode and returns the previous state of the terminal so that it can be restored. -func MakeRaw(fd uintptr) (*State, error) { - state, err := SaveState(fd) - if err != nil { - return nil, err - } - - mode := state.mode - - // See - // -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx - // -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx - - // Disable these modes - mode &^= windows.ENABLE_ECHO_INPUT - mode &^= windows.ENABLE_LINE_INPUT - mode &^= windows.ENABLE_MOUSE_INPUT - mode &^= windows.ENABLE_WINDOW_INPUT - mode &^= windows.ENABLE_PROCESSED_INPUT - - // Enable these modes - mode |= windows.ENABLE_EXTENDED_FLAGS - mode |= windows.ENABLE_INSERT_MODE - mode |= windows.ENABLE_QUICK_EDIT_MODE - if vtInputSupported { - mode |= windows.ENABLE_VIRTUAL_TERMINAL_INPUT - } - - err = windows.SetConsoleMode(windows.Handle(fd), mode) - if err != nil { - return nil, err - } - return state, nil + _ = windows.SetConsoleMode(windows.Handle(fd), oldState.mode|windows.DISABLE_NEWLINE_AUTO_RETURN) + return oldState, err } func restoreAtInterrupt(fd uintptr, state *State) { diff --git a/vendor/github.com/moby/term/termios.go b/vendor/github.com/moby/term/termios.go deleted file mode 100644 index 0f028e2273..0000000000 --- a/vendor/github.com/moby/term/termios.go +++ /dev/null @@ -1,35 +0,0 @@ -// +build !windows - -package term - -import ( - "golang.org/x/sys/unix" -) - -// Termios is the Unix API for terminal I/O. -type Termios = unix.Termios - -// MakeRaw puts the terminal connected to the given file descriptor into raw -// mode and returns the previous state of the terminal so that it can be -// restored. -func MakeRaw(fd uintptr) (*State, error) { - termios, err := tcget(fd) - if err != nil { - return nil, err - } - - oldState := State{termios: *termios} - - termios.Iflag &^= (unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON) - termios.Oflag &^= unix.OPOST - termios.Lflag &^= (unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN) - termios.Cflag &^= (unix.CSIZE | unix.PARENB) - termios.Cflag |= unix.CS8 - termios.Cc[unix.VMIN] = 1 - termios.Cc[unix.VTIME] = 0 - - if err := tcset(fd, termios); err != nil { - return nil, err - } - return &oldState, nil -} diff --git a/vendor/github.com/moby/term/termios_bsd.go b/vendor/github.com/moby/term/termios_bsd.go index 922dd4baab..45f77e03c7 100644 --- a/vendor/github.com/moby/term/termios_bsd.go +++ b/vendor/github.com/moby/term/termios_bsd.go @@ -1,3 +1,4 @@ +//go:build darwin || freebsd || openbsd || netbsd // +build darwin freebsd openbsd netbsd package term diff --git a/vendor/github.com/moby/term/termios_nonbsd.go b/vendor/github.com/moby/term/termios_nonbsd.go index 038fd61ba1..88b7b21563 100644 --- a/vendor/github.com/moby/term/termios_nonbsd.go +++ b/vendor/github.com/moby/term/termios_nonbsd.go @@ -1,4 +1,5 @@ -//+build !darwin,!freebsd,!netbsd,!openbsd,!windows +//go:build !darwin && !freebsd && !netbsd && !openbsd && !windows +// +build !darwin,!freebsd,!netbsd,!openbsd,!windows package term diff --git a/vendor/github.com/moby/term/termios_unix.go b/vendor/github.com/moby/term/termios_unix.go new file mode 100644 index 0000000000..60c823783c --- /dev/null +++ b/vendor/github.com/moby/term/termios_unix.go @@ -0,0 +1,35 @@ +//go:build !windows +// +build !windows + +package term + +import ( + "golang.org/x/sys/unix" +) + +// Termios is the Unix API for terminal I/O. +// +// Deprecated: use [unix.Termios]. +type Termios = unix.Termios + +func makeRaw(fd uintptr) (*State, error) { + termios, err := tcget(fd) + if err != nil { + return nil, err + } + + oldState := State{termios: *termios} + + termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON + termios.Oflag &^= unix.OPOST + termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN + termios.Cflag &^= unix.CSIZE | unix.PARENB + termios.Cflag |= unix.CS8 + termios.Cc[unix.VMIN] = 1 + termios.Cc[unix.VTIME] = 0 + + if err := tcset(fd, termios); err != nil { + return nil, err + } + return &oldState, nil +} diff --git a/vendor/github.com/moby/term/termios_windows.go b/vendor/github.com/moby/term/termios_windows.go new file mode 100644 index 0000000000..5be4e76011 --- /dev/null +++ b/vendor/github.com/moby/term/termios_windows.go @@ -0,0 +1,37 @@ +package term + +import "golang.org/x/sys/windows" + +func makeRaw(fd uintptr) (*State, error) { + state, err := SaveState(fd) + if err != nil { + return nil, err + } + + mode := state.mode + + // See + // -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx + // -- https://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx + + // Disable these modes + mode &^= windows.ENABLE_ECHO_INPUT + mode &^= windows.ENABLE_LINE_INPUT + mode &^= windows.ENABLE_MOUSE_INPUT + mode &^= windows.ENABLE_WINDOW_INPUT + mode &^= windows.ENABLE_PROCESSED_INPUT + + // Enable these modes + mode |= windows.ENABLE_EXTENDED_FLAGS + mode |= windows.ENABLE_INSERT_MODE + mode |= windows.ENABLE_QUICK_EDIT_MODE + if vtInputSupported { + mode |= windows.ENABLE_VIRTUAL_TERMINAL_INPUT + } + + err = windows.SetConsoleMode(windows.Handle(fd), mode) + if err != nil { + return nil, err + } + return state, nil +} diff --git a/vendor/github.com/moby/term/windows/ansi_reader.go b/vendor/github.com/moby/term/windows/ansi_reader.go index 155251521b..fb34c547aa 100644 --- a/vendor/github.com/moby/term/windows/ansi_reader.go +++ b/vendor/github.com/moby/term/windows/ansi_reader.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package windowsconsole @@ -190,15 +191,14 @@ func keyToString(keyEvent *winterm.KEY_EVENT_RECORD, escapeSequence []byte) stri // -S Suspends printing on the screen (does not stop the program). // -U Deletes all characters on the current line. Also called the KILL key. // -E Quits current command and creates a core - } // +Key generates ESC N Key if !control && alt { - return ansiterm.KEY_ESC_N + strings.ToLower(string(keyEvent.UnicodeChar)) + return ansiterm.KEY_ESC_N + strings.ToLower(string(rune(keyEvent.UnicodeChar))) } - return string(keyEvent.UnicodeChar) + return string(rune(keyEvent.UnicodeChar)) } // formatVirtualKey converts a virtual key (e.g., up arrow) into the appropriate ANSI string. diff --git a/vendor/github.com/moby/term/windows/ansi_writer.go b/vendor/github.com/moby/term/windows/ansi_writer.go index ccb5ef0775..4243307fd3 100644 --- a/vendor/github.com/moby/term/windows/ansi_writer.go +++ b/vendor/github.com/moby/term/windows/ansi_writer.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package windowsconsole diff --git a/vendor/github.com/moby/term/windows/console.go b/vendor/github.com/moby/term/windows/console.go index 993694ddcd..21e57bd52f 100644 --- a/vendor/github.com/moby/term/windows/console.go +++ b/vendor/github.com/moby/term/windows/console.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package windowsconsole @@ -29,8 +30,11 @@ func GetHandleInfo(in interface{}) (uintptr, bool) { // IsConsole returns true if the given file descriptor is a Windows Console. // The code assumes that GetConsoleMode will return an error for file descriptors that are not a console. -// Deprecated: use golang.org/x/sys/windows.GetConsoleMode() or golang.org/x/term.IsTerminal() -var IsConsole = isConsole +// +// Deprecated: use [windows.GetConsoleMode] or [golang.org/x/term.IsTerminal]. +func IsConsole(fd uintptr) bool { + return isConsole(fd) +} func isConsole(fd uintptr) bool { var mode uint32 diff --git a/vendor/github.com/moby/term/winsize.go b/vendor/github.com/moby/term/winsize.go deleted file mode 100644 index 1ef98d5996..0000000000 --- a/vendor/github.com/moby/term/winsize.go +++ /dev/null @@ -1,20 +0,0 @@ -// +build !windows - -package term - -import ( - "golang.org/x/sys/unix" -) - -// GetWinsize returns the window size based on the specified file descriptor. -func GetWinsize(fd uintptr) (*Winsize, error) { - uws, err := unix.IoctlGetWinsize(int(fd), unix.TIOCGWINSZ) - ws := &Winsize{Height: uws.Row, Width: uws.Col, x: uws.Xpixel, y: uws.Ypixel} - return ws, err -} - -// SetWinsize tries to set the specified window size for the specified file descriptor. -func SetWinsize(fd uintptr, ws *Winsize) error { - uws := &unix.Winsize{Row: ws.Height, Col: ws.Width, Xpixel: ws.x, Ypixel: ws.y} - return unix.IoctlSetWinsize(int(fd), unix.TIOCSWINSZ, uws) -} diff --git a/vendor/github.com/onsi/ginkgo/v2/formatter/formatter.go b/vendor/github.com/onsi/ginkgo/v2/formatter/formatter.go index 43b16211d8..743555ddea 100644 --- a/vendor/github.com/onsi/ginkgo/v2/formatter/formatter.go +++ b/vendor/github.com/onsi/ginkgo/v2/formatter/formatter.go @@ -4,6 +4,7 @@ import ( "fmt" "os" "regexp" + "strconv" "strings" ) @@ -50,6 +51,37 @@ func NewWithNoColorBool(noColor bool) Formatter { } func New(colorMode ColorMode) Formatter { + colorAliases := map[string]int{ + "black": 0, + "red": 1, + "green": 2, + "yellow": 3, + "blue": 4, + "magenta": 5, + "cyan": 6, + "white": 7, + } + for colorAlias, n := range colorAliases { + colorAliases[fmt.Sprintf("bright-%s", colorAlias)] = n + 8 + } + + getColor := func(color, defaultEscapeCode string) string { + color = strings.ToUpper(strings.ReplaceAll(color, "-", "_")) + envVar := fmt.Sprintf("GINKGO_CLI_COLOR_%s", color) + envVarColor := os.Getenv(envVar) + if envVarColor == "" { + return defaultEscapeCode + } + if colorCode, ok := colorAliases[envVarColor]; ok { + return fmt.Sprintf("\x1b[38;5;%dm", colorCode) + } + colorCode, err := strconv.Atoi(envVarColor) + if err != nil || colorCode < 0 || colorCode > 255 { + return defaultEscapeCode + } + return fmt.Sprintf("\x1b[38;5;%dm", colorCode) + } + f := Formatter{ ColorMode: colorMode, colors: map[string]string{ @@ -57,18 +89,18 @@ func New(colorMode ColorMode) Formatter { "bold": "\x1b[1m", "underline": "\x1b[4m", - "red": "\x1b[38;5;9m", - "orange": "\x1b[38;5;214m", - "coral": "\x1b[38;5;204m", - "magenta": "\x1b[38;5;13m", - "green": "\x1b[38;5;10m", - "dark-green": "\x1b[38;5;28m", - "yellow": "\x1b[38;5;11m", - "light-yellow": "\x1b[38;5;228m", - "cyan": "\x1b[38;5;14m", - "gray": "\x1b[38;5;243m", - "light-gray": "\x1b[38;5;246m", - "blue": "\x1b[38;5;12m", + "red": getColor("red", "\x1b[38;5;9m"), + "orange": getColor("orange", "\x1b[38;5;214m"), + "coral": getColor("coral", "\x1b[38;5;204m"), + "magenta": getColor("magenta", "\x1b[38;5;13m"), + "green": getColor("green", "\x1b[38;5;10m"), + "dark-green": getColor("dark-green", "\x1b[38;5;28m"), + "yellow": getColor("yellow", "\x1b[38;5;11m"), + "light-yellow": getColor("light-yellow", "\x1b[38;5;228m"), + "cyan": getColor("cyan", "\x1b[38;5;14m"), + "gray": getColor("gray", "\x1b[38;5;243m"), + "light-gray": getColor("light-gray", "\x1b[38;5;246m"), + "blue": getColor("blue", "\x1b[38;5;12m"), }, } colors := []string{} @@ -88,7 +120,10 @@ func (f Formatter) Fi(indentation uint, format string, args ...interface{}) stri } func (f Formatter) Fiw(indentation uint, maxWidth uint, format string, args ...interface{}) string { - out := fmt.Sprintf(f.style(format), args...) + out := f.style(format) + if len(args) > 0 { + out = fmt.Sprintf(out, args...) + } if indentation == 0 && maxWidth == 0 { return out diff --git a/vendor/github.com/onsi/ginkgo/v2/ginkgo/build/build_command.go b/vendor/github.com/onsi/ginkgo/v2/ginkgo/build/build_command.go index f7d2eaf0b3..5db5d1a7bf 100644 --- a/vendor/github.com/onsi/ginkgo/v2/ginkgo/build/build_command.go +++ b/vendor/github.com/onsi/ginkgo/v2/ginkgo/build/build_command.go @@ -39,6 +39,8 @@ func buildSpecs(args []string, cliConfig types.CLIConfig, goFlagsConfig types.Go command.AbortWith("Found no test suites") } + internal.VerifyCLIAndFrameworkVersion(suites) + opc := internal.NewOrderedParallelCompiler(cliConfig.ComputedNumCompilers()) opc.StartCompiling(suites, goFlagsConfig) diff --git a/vendor/github.com/onsi/ginkgo/v2/ginkgo/generators/bootstrap_command.go b/vendor/github.com/onsi/ginkgo/v2/ginkgo/generators/bootstrap_command.go index 0273abe9c6..73aff0b7a1 100644 --- a/vendor/github.com/onsi/ginkgo/v2/ginkgo/generators/bootstrap_command.go +++ b/vendor/github.com/onsi/ginkgo/v2/ginkgo/generators/bootstrap_command.go @@ -2,6 +2,7 @@ package generators import ( "bytes" + "encoding/json" "fmt" "os" "text/template" @@ -25,6 +26,9 @@ func BuildBootstrapCommand() command.Command { {Name: "template", KeyPath: "CustomTemplate", UsageArgument: "template-file", Usage: "If specified, generate will use the contents of the file passed as the bootstrap template"}, + {Name: "template-data", KeyPath: "CustomTemplateData", + UsageArgument: "template-data-file", + Usage: "If specified, generate will use the contents of the file passed as data to be rendered in the bootstrap template"}, }, &conf, types.GinkgoFlagSections{}, @@ -57,6 +61,7 @@ type bootstrapData struct { GomegaImport string GinkgoPackage string GomegaPackage string + CustomData map[string]any } func generateBootstrap(conf GeneratorsConfig) { @@ -95,17 +100,32 @@ func generateBootstrap(conf GeneratorsConfig) { tpl, err := os.ReadFile(conf.CustomTemplate) command.AbortIfError("Failed to read custom bootstrap file:", err) templateText = string(tpl) + if conf.CustomTemplateData != "" { + var tplCustomDataMap map[string]any + tplCustomData, err := os.ReadFile(conf.CustomTemplateData) + command.AbortIfError("Failed to read custom boostrap data file:", err) + if !json.Valid([]byte(tplCustomData)) { + command.AbortWith("Invalid JSON object in custom data file.") + } + //create map from the custom template data + json.Unmarshal(tplCustomData, &tplCustomDataMap) + data.CustomData = tplCustomDataMap + } } else if conf.Agouti { templateText = agoutiBootstrapText } else { templateText = bootstrapText } - bootstrapTemplate, err := template.New("bootstrap").Funcs(sprig.TxtFuncMap()).Parse(templateText) + //Setting the option to explicitly fail if template is rendered trying to access missing key + bootstrapTemplate, err := template.New("bootstrap").Funcs(sprig.TxtFuncMap()).Option("missingkey=error").Parse(templateText) command.AbortIfError("Failed to parse bootstrap template:", err) buf := &bytes.Buffer{} - bootstrapTemplate.Execute(buf, data) + //Being explicit about failing sooner during template rendering + //when accessing custom data rather than during the go fmt command + err = bootstrapTemplate.Execute(buf, data) + command.AbortIfError("Failed to render bootstrap template:", err) buf.WriteTo(f) diff --git a/vendor/github.com/onsi/ginkgo/v2/ginkgo/generators/generate_command.go b/vendor/github.com/onsi/ginkgo/v2/ginkgo/generators/generate_command.go index 93b0b4b25b..48d23f9191 100644 --- a/vendor/github.com/onsi/ginkgo/v2/ginkgo/generators/generate_command.go +++ b/vendor/github.com/onsi/ginkgo/v2/ginkgo/generators/generate_command.go @@ -2,6 +2,7 @@ package generators import ( "bytes" + "encoding/json" "fmt" "os" "path/filepath" @@ -28,6 +29,9 @@ func BuildGenerateCommand() command.Command { {Name: "template", KeyPath: "CustomTemplate", UsageArgument: "template-file", Usage: "If specified, generate will use the contents of the file passed as the test file template"}, + {Name: "template-data", KeyPath: "CustomTemplateData", + UsageArgument: "template-data-file", + Usage: "If specified, generate will use the contents of the file passed as data to be rendered in the test file template"}, }, &conf, types.GinkgoFlagSections{}, @@ -64,6 +68,7 @@ type specData struct { GomegaImport string GinkgoPackage string GomegaPackage string + CustomData map[string]any } func generateTestFiles(conf GeneratorsConfig, args []string) { @@ -122,16 +127,31 @@ func generateTestFileForSubject(subject string, conf GeneratorsConfig) { tpl, err := os.ReadFile(conf.CustomTemplate) command.AbortIfError("Failed to read custom template file:", err) templateText = string(tpl) + if conf.CustomTemplateData != "" { + var tplCustomDataMap map[string]any + tplCustomData, err := os.ReadFile(conf.CustomTemplateData) + command.AbortIfError("Failed to read custom template data file:", err) + if !json.Valid([]byte(tplCustomData)) { + command.AbortWith("Invalid JSON object in custom data file.") + } + //create map from the custom template data + json.Unmarshal(tplCustomData, &tplCustomDataMap) + data.CustomData = tplCustomDataMap + } } else if conf.Agouti { templateText = agoutiSpecText } else { templateText = specText } - specTemplate, err := template.New("spec").Funcs(sprig.TxtFuncMap()).Parse(templateText) + //Setting the option to explicitly fail if template is rendered trying to access missing key + specTemplate, err := template.New("spec").Funcs(sprig.TxtFuncMap()).Option("missingkey=error").Parse(templateText) command.AbortIfError("Failed to read parse test template:", err) - specTemplate.Execute(f, data) + //Being explicit about failing sooner during template rendering + //when accessing custom data rather than during the go fmt command + err = specTemplate.Execute(f, data) + command.AbortIfError("Failed to render bootstrap template:", err) internal.GoFmt(targetFile) } diff --git a/vendor/github.com/onsi/ginkgo/v2/ginkgo/generators/generators_common.go b/vendor/github.com/onsi/ginkgo/v2/ginkgo/generators/generators_common.go index 3086e6056a..3046a4487a 100644 --- a/vendor/github.com/onsi/ginkgo/v2/ginkgo/generators/generators_common.go +++ b/vendor/github.com/onsi/ginkgo/v2/ginkgo/generators/generators_common.go @@ -13,6 +13,7 @@ import ( type GeneratorsConfig struct { Agouti, NoDot, Internal bool CustomTemplate string + CustomTemplateData string } func getPackageAndFormattedName() (string, string, string) { diff --git a/vendor/github.com/onsi/ginkgo/v2/ginkgo/internal/compile.go b/vendor/github.com/onsi/ginkgo/v2/ginkgo/internal/compile.go index 496ec4a28a..86da7340d1 100644 --- a/vendor/github.com/onsi/ginkgo/v2/ginkgo/internal/compile.go +++ b/vendor/github.com/onsi/ginkgo/v2/ginkgo/internal/compile.go @@ -25,7 +25,16 @@ func CompileSuite(suite TestSuite, goFlagsConfig types.GoFlagsConfig) TestSuite return suite } - args, err := types.GenerateGoTestCompileArgs(goFlagsConfig, path, "./") + ginkgoInvocationPath, _ := os.Getwd() + ginkgoInvocationPath, _ = filepath.Abs(ginkgoInvocationPath) + packagePath := suite.AbsPath() + pathToInvocationPath, err := filepath.Rel(packagePath, ginkgoInvocationPath) + if err != nil { + suite.State = TestSuiteStateFailedToCompile + suite.CompilationError = fmt.Errorf("Failed to get relative path from package to the current working directory:\n%s", err.Error()) + return suite + } + args, err := types.GenerateGoTestCompileArgs(goFlagsConfig, path, "./", pathToInvocationPath) if err != nil { suite.State = TestSuiteStateFailedToCompile suite.CompilationError = fmt.Errorf("Failed to generate go test compile flags:\n%s", err.Error()) diff --git a/vendor/github.com/onsi/ginkgo/v2/ginkgo/internal/run.go b/vendor/github.com/onsi/ginkgo/v2/ginkgo/internal/run.go index cad2386717..41052ea19d 100644 --- a/vendor/github.com/onsi/ginkgo/v2/ginkgo/internal/run.go +++ b/vendor/github.com/onsi/ginkgo/v2/ginkgo/internal/run.go @@ -6,6 +6,7 @@ import ( "io" "os" "os/exec" + "path/filepath" "regexp" "strings" "syscall" @@ -63,6 +64,12 @@ func checkForNoTestsWarning(buf *bytes.Buffer) bool { } func runGoTest(suite TestSuite, cliConfig types.CLIConfig, goFlagsConfig types.GoFlagsConfig) TestSuite { + // As we run the go test from the suite directory, make sure the cover profile is absolute + // and placed into the expected output directory when one is configured. + if goFlagsConfig.Cover && !filepath.IsAbs(goFlagsConfig.CoverProfile) { + goFlagsConfig.CoverProfile = AbsPathForGeneratedAsset(goFlagsConfig.CoverProfile, suite, cliConfig, 0) + } + args, err := types.GenerateGoTestRunArgs(goFlagsConfig) command.AbortIfError("Failed to generate test run arguments", err) cmd, buf := buildAndStartCommand(suite, args, true) diff --git a/vendor/github.com/onsi/ginkgo/v2/ginkgo/internal/verify_version.go b/vendor/github.com/onsi/ginkgo/v2/ginkgo/internal/verify_version.go new file mode 100644 index 0000000000..9da1bab3db --- /dev/null +++ b/vendor/github.com/onsi/ginkgo/v2/ginkgo/internal/verify_version.go @@ -0,0 +1,54 @@ +package internal + +import ( + "fmt" + "os/exec" + "regexp" + "strings" + + "github.com/onsi/ginkgo/v2/formatter" + "github.com/onsi/ginkgo/v2/types" +) + +var versiorRe = regexp.MustCompile(`v(\d+\.\d+\.\d+)`) + +func VerifyCLIAndFrameworkVersion(suites TestSuites) { + cliVersion := types.VERSION + mismatches := map[string][]string{} + + for _, suite := range suites { + cmd := exec.Command("go", "list", "-m", "github.com/onsi/ginkgo/v2") + cmd.Dir = suite.Path + output, err := cmd.CombinedOutput() + if err != nil { + continue + } + components := strings.Split(string(output), " ") + if len(components) != 2 { + continue + } + matches := versiorRe.FindStringSubmatch(components[1]) + if matches == nil || len(matches) != 2 { + continue + } + libraryVersion := matches[1] + if cliVersion != libraryVersion { + mismatches[libraryVersion] = append(mismatches[libraryVersion], suite.PackageName) + } + } + + if len(mismatches) == 0 { + return + } + + fmt.Println(formatter.F("{{red}}{{bold}}Ginkgo detected a version mismatch between the Ginkgo CLI and the version of Ginkgo imported by your packages:{{/}}")) + + fmt.Println(formatter.Fi(1, "Ginkgo CLI Version:")) + fmt.Println(formatter.Fi(2, "{{bold}}%s{{/}}", cliVersion)) + fmt.Println(formatter.Fi(1, "Mismatched package versions found:")) + for version, packages := range mismatches { + fmt.Println(formatter.Fi(2, "{{bold}}%s{{/}} used by %s", version, strings.Join(packages, ", "))) + } + fmt.Println("") + fmt.Println(formatter.Fiw(1, formatter.COLS, "{{gray}}Ginkgo will continue to attempt to run but you may see errors (including flag parsing errors) and should either update your go.mod or your version of the Ginkgo CLI to match.\n\nTo install the matching version of the CLI run\n {{bold}}go install github.com/onsi/ginkgo/v2/ginkgo{{/}}{{gray}}\nfrom a path that contains a go.mod file. Alternatively you can use\n {{bold}}go run github.com/onsi/ginkgo/v2/ginkgo{{/}}{{gray}}\nfrom a path that contains a go.mod file to invoke the matching version of the Ginkgo CLI.\n\nIf you are attempting to test multiple packages that each have a different version of the Ginkgo library with a single Ginkgo CLI that is currently unsupported.\n{{/}}")) +} diff --git a/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/ginkgo.go b/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/ginkgo.go index c197bb6862..0b9b19fe74 100644 --- a/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/ginkgo.go +++ b/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/ginkgo.go @@ -1,6 +1,7 @@ package outline import ( + "github.com/onsi/ginkgo/v2/types" "go/ast" "go/token" "strconv" @@ -25,9 +26,10 @@ type ginkgoMetadata struct { // End is the position of first character immediately after the spec or container block End int `json:"end"` - Spec bool `json:"spec"` - Focused bool `json:"focused"` - Pending bool `json:"pending"` + Spec bool `json:"spec"` + Focused bool `json:"focused"` + Pending bool `json:"pending"` + Labels []string `json:"labels"` } // ginkgoNode is used to construct the outline as a tree @@ -145,27 +147,35 @@ func ginkgoNodeFromCallExpr(fset *token.FileSet, ce *ast.CallExpr, ginkgoPackage case "It", "Specify", "Entry": n.Spec = true n.Text = textOrAltFromCallExpr(ce, undefinedTextAlt) + n.Labels = labelFromCallExpr(ce) + n.Pending = pendingFromCallExpr(ce) return &n, ginkgoPackageName != nil && *ginkgoPackageName == packageName case "FIt", "FSpecify", "FEntry": n.Spec = true n.Focused = true n.Text = textOrAltFromCallExpr(ce, undefinedTextAlt) + n.Labels = labelFromCallExpr(ce) return &n, ginkgoPackageName != nil && *ginkgoPackageName == packageName case "PIt", "PSpecify", "XIt", "XSpecify", "PEntry", "XEntry": n.Spec = true n.Pending = true n.Text = textOrAltFromCallExpr(ce, undefinedTextAlt) + n.Labels = labelFromCallExpr(ce) return &n, ginkgoPackageName != nil && *ginkgoPackageName == packageName case "Context", "Describe", "When", "DescribeTable": n.Text = textOrAltFromCallExpr(ce, undefinedTextAlt) + n.Labels = labelFromCallExpr(ce) + n.Pending = pendingFromCallExpr(ce) return &n, ginkgoPackageName != nil && *ginkgoPackageName == packageName case "FContext", "FDescribe", "FWhen", "FDescribeTable": n.Focused = true n.Text = textOrAltFromCallExpr(ce, undefinedTextAlt) + n.Labels = labelFromCallExpr(ce) return &n, ginkgoPackageName != nil && *ginkgoPackageName == packageName case "PContext", "PDescribe", "PWhen", "XContext", "XDescribe", "XWhen", "PDescribeTable", "XDescribeTable": n.Pending = true n.Text = textOrAltFromCallExpr(ce, undefinedTextAlt) + n.Labels = labelFromCallExpr(ce) return &n, ginkgoPackageName != nil && *ginkgoPackageName == packageName case "By": n.Text = textOrAltFromCallExpr(ce, undefinedTextAlt) @@ -216,3 +226,77 @@ func textFromCallExpr(ce *ast.CallExpr) (string, bool) { return text.Value, true } } + +func labelFromCallExpr(ce *ast.CallExpr) []string { + + labels := []string{} + if len(ce.Args) < 2 { + return labels + } + + for _, arg := range ce.Args[1:] { + switch expr := arg.(type) { + case *ast.CallExpr: + id, ok := expr.Fun.(*ast.Ident) + if !ok { + // to skip over cases where the expr.Fun. is actually *ast.SelectorExpr + continue + } + if id.Name == "Label" { + ls := extractLabels(expr) + for _, label := range ls { + labels = append(labels, label) + } + } + } + } + return labels +} + +func extractLabels(expr *ast.CallExpr) []string { + out := []string{} + for _, arg := range expr.Args { + switch expr := arg.(type) { + case *ast.BasicLit: + if expr.Kind == token.STRING { + unquoted, err := strconv.Unquote(expr.Value) + if err != nil { + unquoted = expr.Value + } + validated, err := types.ValidateAndCleanupLabel(unquoted, types.CodeLocation{}) + if err == nil { + out = append(out, validated) + } + } + } + } + + return out +} + +func pendingFromCallExpr(ce *ast.CallExpr) bool { + + pending := false + if len(ce.Args) < 2 { + return pending + } + + for _, arg := range ce.Args[1:] { + switch expr := arg.(type) { + case *ast.CallExpr: + id, ok := expr.Fun.(*ast.Ident) + if !ok { + // to skip over cases where the expr.Fun. is actually *ast.SelectorExpr + continue + } + if id.Name == "Pending" { + pending = true + } + case *ast.Ident: + if expr.Name == "Pending" { + pending = true + } + } + } + return pending +} diff --git a/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/import.go b/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/import.go index 4328ab3910..67ec5ab757 100644 --- a/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/import.go +++ b/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/import.go @@ -47,7 +47,7 @@ func packageNameForImport(f *ast.File, path string) *string { // or nil otherwise. func importSpec(f *ast.File, path string) *ast.ImportSpec { for _, s := range f.Imports { - if importPath(s) == path { + if strings.HasPrefix(importPath(s), path) { return s } } diff --git a/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/outline.go b/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/outline.go index 4b45e76274..c2327cda8c 100644 --- a/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/outline.go +++ b/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/outline.go @@ -85,12 +85,19 @@ func (o *outline) String() string { // one 'width' of spaces for every level of nesting. func (o *outline) StringIndent(width int) string { var b strings.Builder - b.WriteString("Name,Text,Start,End,Spec,Focused,Pending\n") + b.WriteString("Name,Text,Start,End,Spec,Focused,Pending,Labels\n") currentIndent := 0 pre := func(n *ginkgoNode) { b.WriteString(fmt.Sprintf("%*s", currentIndent, "")) - b.WriteString(fmt.Sprintf("%s,%s,%d,%d,%t,%t,%t\n", n.Name, n.Text, n.Start, n.End, n.Spec, n.Focused, n.Pending)) + var labels string + if len(n.Labels) == 1 { + labels = n.Labels[0] + } else { + labels = strings.Join(n.Labels, ", ") + } + //enclosing labels in a double quoted comma separate listed so that when inmported into a CSV app the Labels column has comma separate strings + b.WriteString(fmt.Sprintf("%s,%s,%d,%d,%t,%t,%t,\"%s\"\n", n.Name, n.Text, n.Start, n.End, n.Spec, n.Focused, n.Pending, labels)) currentIndent += width } post := func(n *ginkgoNode) { diff --git a/vendor/github.com/onsi/ginkgo/v2/ginkgo/run/run_command.go b/vendor/github.com/onsi/ginkgo/v2/ginkgo/run/run_command.go index 8ee0acc818..aaed4d570e 100644 --- a/vendor/github.com/onsi/ginkgo/v2/ginkgo/run/run_command.go +++ b/vendor/github.com/onsi/ginkgo/v2/ginkgo/run/run_command.go @@ -24,7 +24,7 @@ func BuildRunCommand() command.Command { panic(err) } - interruptHandler := interrupt_handler.NewInterruptHandler(0, nil) + interruptHandler := interrupt_handler.NewInterruptHandler(nil) interrupt_handler.SwallowSigQuit() return command.Command{ @@ -69,6 +69,8 @@ func (r *SpecRunner) RunSpecs(args []string, additionalArgs []string) { skippedSuites := suites.WithState(internal.TestSuiteStateSkippedByFilter) suites = suites.WithoutState(internal.TestSuiteStateSkippedByFilter) + internal.VerifyCLIAndFrameworkVersion(suites) + if len(skippedSuites) > 0 { fmt.Println("Will skip:") for _, skippedSuite := range skippedSuites { @@ -115,7 +117,7 @@ OUTER_LOOP: } suites[suiteIdx] = suite - if r.interruptHandler.Status().Interrupted { + if r.interruptHandler.Status().Interrupted() { opc.StopAndDrain() break OUTER_LOOP } diff --git a/vendor/github.com/onsi/ginkgo/v2/ginkgo/watch/watch_command.go b/vendor/github.com/onsi/ginkgo/v2/ginkgo/watch/watch_command.go index 83dbeb1e89..bde4193ce7 100644 --- a/vendor/github.com/onsi/ginkgo/v2/ginkgo/watch/watch_command.go +++ b/vendor/github.com/onsi/ginkgo/v2/ginkgo/watch/watch_command.go @@ -22,7 +22,7 @@ func BuildWatchCommand() command.Command { if err != nil { panic(err) } - interruptHandler := interrupt_handler.NewInterruptHandler(0, nil) + interruptHandler := interrupt_handler.NewInterruptHandler(nil) interrupt_handler.SwallowSigQuit() return command.Command{ @@ -65,6 +65,8 @@ type SpecWatcher struct { func (w *SpecWatcher) WatchSpecs(args []string, additionalArgs []string) { suites := internal.FindSuites(args, w.cliConfig, false).WithoutState(internal.TestSuiteStateSkippedByFilter) + internal.VerifyCLIAndFrameworkVersion(suites) + if len(suites) == 0 { command.AbortWith("Found no test suites") } @@ -127,7 +129,7 @@ func (w *SpecWatcher) WatchSpecs(args []string, additionalArgs []string) { w.updateSeed() w.computeSuccinctMode(len(suites)) for idx := range suites { - if w.interruptHandler.Status().Interrupted { + if w.interruptHandler.Status().Interrupted() { return } deltaTracker.WillRun(suites[idx]) @@ -156,7 +158,7 @@ func (w *SpecWatcher) compileAndRun(suite internal.TestSuite, additionalArgs []s fmt.Println(suite.CompilationError.Error()) return suite } - if w.interruptHandler.Status().Interrupted { + if w.interruptHandler.Status().Interrupted() { return suite } suite = internal.RunCompiledSuite(suite, w.suiteConfig, w.reporterConfig, w.cliConfig, w.goFlagsConfig, additionalArgs) diff --git a/vendor/github.com/onsi/ginkgo/v2/internal/interrupt_handler/interrupt_handler.go b/vendor/github.com/onsi/ginkgo/v2/internal/interrupt_handler/interrupt_handler.go index aca7d1c433..8ed86111f7 100644 --- a/vendor/github.com/onsi/ginkgo/v2/internal/interrupt_handler/interrupt_handler.go +++ b/vendor/github.com/onsi/ginkgo/v2/internal/interrupt_handler/interrupt_handler.go @@ -1,39 +1,38 @@ package interrupt_handler import ( - "fmt" "os" "os/signal" - "runtime" "sync" "syscall" "time" - "github.com/onsi/ginkgo/v2/formatter" "github.com/onsi/ginkgo/v2/internal/parallel_support" ) -const TIMEOUT_REPEAT_INTERRUPT_MAXIMUM_DURATION = 30 * time.Second -const TIMEOUT_REPEAT_INTERRUPT_FRACTION_OF_TIMEOUT = 10 -const ABORT_POLLING_INTERVAL = 500 * time.Millisecond -const ABORT_REPEAT_INTERRUPT_DURATION = 30 * time.Second +var ABORT_POLLING_INTERVAL = 500 * time.Millisecond type InterruptCause uint const ( InterruptCauseInvalid InterruptCause = iota - InterruptCauseSignal - InterruptCauseTimeout InterruptCauseAbortByOtherProcess ) +type InterruptLevel uint + +const ( + InterruptLevelUninterrupted InterruptLevel = iota + InterruptLevelCleanupAndReport + InterruptLevelReportOnly + InterruptLevelBailOut +) + func (ic InterruptCause) String() string { switch ic { case InterruptCauseSignal: return "Interrupted by User" - case InterruptCauseTimeout: - return "Interrupted by Timeout" case InterruptCauseAbortByOtherProcess: return "Interrupted by Other Ginkgo Process" } @@ -41,37 +40,51 @@ func (ic InterruptCause) String() string { } type InterruptStatus struct { - Interrupted bool - Channel chan interface{} - Cause InterruptCause + Channel chan interface{} + Level InterruptLevel + Cause InterruptCause +} + +func (s InterruptStatus) Interrupted() bool { + return s.Level != InterruptLevelUninterrupted +} + +func (s InterruptStatus) Message() string { + return s.Cause.String() +} + +func (s InterruptStatus) ShouldIncludeProgressReport() bool { + return s.Cause != InterruptCauseAbortByOtherProcess } type InterruptHandlerInterface interface { Status() InterruptStatus - SetInterruptPlaceholderMessage(string) - ClearInterruptPlaceholderMessage() - InterruptMessageWithStackTraces() string } type InterruptHandler struct { - c chan interface{} - lock *sync.Mutex - interrupted bool - interruptPlaceholderMessage string - interruptCause InterruptCause - client parallel_support.Client - stop chan interface{} + c chan interface{} + lock *sync.Mutex + level InterruptLevel + cause InterruptCause + client parallel_support.Client + stop chan interface{} + signals []os.Signal + requestAbortCheck chan interface{} } -func NewInterruptHandler(timeout time.Duration, client parallel_support.Client) *InterruptHandler { +func NewInterruptHandler(client parallel_support.Client, signals ...os.Signal) *InterruptHandler { + if len(signals) == 0 { + signals = []os.Signal{os.Interrupt, syscall.SIGTERM} + } handler := &InterruptHandler{ - c: make(chan interface{}), - lock: &sync.Mutex{}, - interrupted: false, - stop: make(chan interface{}), - client: client, + c: make(chan interface{}), + lock: &sync.Mutex{}, + stop: make(chan interface{}), + requestAbortCheck: make(chan interface{}), + client: client, + signals: signals, } - handler.registerForInterrupts(timeout) + handler.registerForInterrupts() return handler } @@ -79,30 +92,28 @@ func (handler *InterruptHandler) Stop() { close(handler.stop) } -func (handler *InterruptHandler) registerForInterrupts(timeout time.Duration) { +func (handler *InterruptHandler) registerForInterrupts() { // os signal handling signalChannel := make(chan os.Signal, 1) - signal.Notify(signalChannel, os.Interrupt, syscall.SIGTERM) - - // timeout handling - var timeoutChannel <-chan time.Time - var timeoutTimer *time.Timer - if timeout > 0 { - timeoutTimer = time.NewTimer(timeout) - timeoutChannel = timeoutTimer.C - } + signal.Notify(signalChannel, handler.signals...) // cross-process abort handling - var abortChannel chan bool + var abortChannel chan interface{} if handler.client != nil { - abortChannel = make(chan bool) + abortChannel = make(chan interface{}) go func() { pollTicker := time.NewTicker(ABORT_POLLING_INTERVAL) for { select { case <-pollTicker.C: if handler.client.ShouldAbort() { - abortChannel <- true + close(abortChannel) + pollTicker.Stop() + return + } + case <-handler.requestAbortCheck: + if handler.client.ShouldAbort() { + close(abortChannel) pollTicker.Stop() return } @@ -114,99 +125,53 @@ func (handler *InterruptHandler) registerForInterrupts(timeout time.Duration) { }() } - // listen for any interrupt signals - // note that some (timeouts, cross-process aborts) will only trigger once - // for these we set up a ticker to keep interrupting the suite until it ends - // this ensures any `AfterEach` or `AfterSuite`s that get stuck cleaning up - // get interrupted eventually - go func() { + go func(abortChannel chan interface{}) { var interruptCause InterruptCause - var repeatChannel <-chan time.Time - var repeatTicker *time.Ticker for { select { case <-signalChannel: interruptCause = InterruptCauseSignal - case <-timeoutChannel: - interruptCause = InterruptCauseTimeout - repeatInterruptTimeout := timeout / time.Duration(TIMEOUT_REPEAT_INTERRUPT_FRACTION_OF_TIMEOUT) - if repeatInterruptTimeout > TIMEOUT_REPEAT_INTERRUPT_MAXIMUM_DURATION { - repeatInterruptTimeout = TIMEOUT_REPEAT_INTERRUPT_MAXIMUM_DURATION - } - timeoutTimer.Stop() - repeatTicker = time.NewTicker(repeatInterruptTimeout) - repeatChannel = repeatTicker.C case <-abortChannel: interruptCause = InterruptCauseAbortByOtherProcess - repeatTicker = time.NewTicker(ABORT_REPEAT_INTERRUPT_DURATION) - repeatChannel = repeatTicker.C - case <-repeatChannel: - //do nothing, just interrupt again using the same interruptCause case <-handler.stop: - if timeoutTimer != nil { - timeoutTimer.Stop() - } - if repeatTicker != nil { - repeatTicker.Stop() - } signal.Stop(signalChannel) return } + abortChannel = nil + handler.lock.Lock() - handler.interruptCause = interruptCause - if handler.interruptPlaceholderMessage != "" { - fmt.Println(handler.interruptPlaceholderMessage) + oldLevel := handler.level + handler.cause = interruptCause + if handler.level == InterruptLevelUninterrupted { + handler.level = InterruptLevelCleanupAndReport + } else if handler.level == InterruptLevelCleanupAndReport { + handler.level = InterruptLevelReportOnly + } else if handler.level == InterruptLevelReportOnly { + handler.level = InterruptLevelBailOut + } + if handler.level != oldLevel { + close(handler.c) + handler.c = make(chan interface{}) } - handler.interrupted = true - close(handler.c) - handler.c = make(chan interface{}) handler.lock.Unlock() } - }() + }(abortChannel) } func (handler *InterruptHandler) Status() InterruptStatus { handler.lock.Lock() - defer handler.lock.Unlock() - - return InterruptStatus{ - Interrupted: handler.interrupted, - Channel: handler.c, - Cause: handler.interruptCause, + status := InterruptStatus{ + Level: handler.level, + Channel: handler.c, + Cause: handler.cause, } -} - -func (handler *InterruptHandler) SetInterruptPlaceholderMessage(message string) { - handler.lock.Lock() - defer handler.lock.Unlock() - - handler.interruptPlaceholderMessage = message -} - -func (handler *InterruptHandler) ClearInterruptPlaceholderMessage() { - handler.lock.Lock() - defer handler.lock.Unlock() - - handler.interruptPlaceholderMessage = "" -} + handler.lock.Unlock() -func (handler *InterruptHandler) InterruptMessageWithStackTraces() string { - handler.lock.Lock() - out := fmt.Sprintf("%s\n\n", handler.interruptCause.String()) - defer handler.lock.Unlock() - if handler.interruptCause == InterruptCauseAbortByOtherProcess { - return out - } - out += "Here's a stack trace of all running goroutines:\n" - buf := make([]byte, 8192) - for { - n := runtime.Stack(buf, true) - if n < len(buf) { - buf = buf[:n] - break - } - buf = make([]byte, 2*len(buf)) + if handler.client != nil && handler.client.ShouldAbort() && !status.Interrupted() { + close(handler.requestAbortCheck) + <-status.Channel + return handler.Status() } - out += formatter.Fi(1, "%s", string(buf)) - return out + + return status } diff --git a/vendor/github.com/onsi/ginkgo/v2/internal/parallel_support/client_server.go b/vendor/github.com/onsi/ginkgo/v2/internal/parallel_support/client_server.go index 7d5cb0b631..b3cd64292a 100644 --- a/vendor/github.com/onsi/ginkgo/v2/internal/parallel_support/client_server.go +++ b/vendor/github.com/onsi/ginkgo/v2/internal/parallel_support/client_server.go @@ -42,6 +42,8 @@ type Client interface { PostSuiteWillBegin(report types.Report) error PostDidRun(report types.SpecReport) error PostSuiteDidEnd(report types.Report) error + PostReportBeforeSuiteCompleted(state types.SpecState) error + BlockUntilReportBeforeSuiteCompleted() (types.SpecState, error) PostSynchronizedBeforeSuiteCompleted(state types.SpecState, data []byte) error BlockUntilSynchronizedBeforeSuiteData() (types.SpecState, []byte, error) BlockUntilNonprimaryProcsHaveFinished() error @@ -49,6 +51,7 @@ type Client interface { FetchNextCounter() (int, error) PostAbort() error ShouldAbort() bool + PostEmitProgressReport(report types.ProgressReport) error Write(p []byte) (int, error) } diff --git a/vendor/github.com/onsi/ginkgo/v2/internal/parallel_support/http_client.go b/vendor/github.com/onsi/ginkgo/v2/internal/parallel_support/http_client.go index d076d5d1c1..6547c7a66e 100644 --- a/vendor/github.com/onsi/ginkgo/v2/internal/parallel_support/http_client.go +++ b/vendor/github.com/onsi/ginkgo/v2/internal/parallel_support/http_client.go @@ -94,6 +94,23 @@ func (client *httpClient) PostSuiteDidEnd(report types.Report) error { return client.post("/suite-did-end", report) } +func (client *httpClient) PostEmitProgressReport(report types.ProgressReport) error { + return client.post("/progress-report", report) +} + +func (client *httpClient) PostReportBeforeSuiteCompleted(state types.SpecState) error { + return client.post("/report-before-suite-completed", state) +} + +func (client *httpClient) BlockUntilReportBeforeSuiteCompleted() (types.SpecState, error) { + var state types.SpecState + err := client.poll("/report-before-suite-state", &state) + if err == ErrorGone { + return types.SpecStateFailed, nil + } + return state, err +} + func (client *httpClient) PostSynchronizedBeforeSuiteCompleted(state types.SpecState, data []byte) error { beforeSuiteState := BeforeSuiteState{ State: state, diff --git a/vendor/github.com/onsi/ginkgo/v2/internal/parallel_support/http_server.go b/vendor/github.com/onsi/ginkgo/v2/internal/parallel_support/http_server.go index ca1dcdca55..d2c71ab1b2 100644 --- a/vendor/github.com/onsi/ginkgo/v2/internal/parallel_support/http_server.go +++ b/vendor/github.com/onsi/ginkgo/v2/internal/parallel_support/http_server.go @@ -26,7 +26,7 @@ type httpServer struct { handler *ServerHandler } -//Create a new server, automatically selecting a port +// Create a new server, automatically selecting a port func newHttpServer(parallelTotal int, reporter reporters.Reporter) (*httpServer, error) { listener, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { @@ -38,7 +38,7 @@ func newHttpServer(parallelTotal int, reporter reporters.Reporter) (*httpServer, }, nil } -//Start the server. You don't need to `go s.Start()`, just `s.Start()` +// Start the server. You don't need to `go s.Start()`, just `s.Start()` func (server *httpServer) Start() { httpServer := &http.Server{} mux := http.NewServeMux() @@ -49,8 +49,11 @@ func (server *httpServer) Start() { mux.HandleFunc("/did-run", server.didRun) mux.HandleFunc("/suite-did-end", server.specSuiteDidEnd) mux.HandleFunc("/emit-output", server.emitOutput) + mux.HandleFunc("/progress-report", server.emitProgressReport) //synchronization endpoints + mux.HandleFunc("/report-before-suite-completed", server.handleReportBeforeSuiteCompleted) + mux.HandleFunc("/report-before-suite-state", server.handleReportBeforeSuiteState) mux.HandleFunc("/before-suite-completed", server.handleBeforeSuiteCompleted) mux.HandleFunc("/before-suite-state", server.handleBeforeSuiteState) mux.HandleFunc("/have-nonprimary-procs-finished", server.handleHaveNonprimaryProcsFinished) @@ -62,12 +65,12 @@ func (server *httpServer) Start() { go httpServer.Serve(server.listener) } -//Stop the server +// Stop the server func (server *httpServer) Close() { server.listener.Close() } -//The address the server can be reached it. Pass this into the `ForwardingReporter`. +// The address the server can be reached it. Pass this into the `ForwardingReporter`. func (server *httpServer) Address() string { return "http://" + server.listener.Addr().String() } @@ -92,7 +95,7 @@ func (server *httpServer) RegisterAlive(node int, alive func() bool) { // Streaming Endpoints // -//The server will forward all received messages to Ginkgo reporters registered with `RegisterReporters` +// The server will forward all received messages to Ginkgo reporters registered with `RegisterReporters` func (server *httpServer) decode(writer http.ResponseWriter, request *http.Request, object interface{}) bool { defer request.Body.Close() if json.NewDecoder(request.Body).Decode(object) != nil { @@ -155,6 +158,31 @@ func (server *httpServer) emitOutput(writer http.ResponseWriter, request *http.R server.handleError(server.handler.EmitOutput(output, &n), writer) } +func (server *httpServer) emitProgressReport(writer http.ResponseWriter, request *http.Request) { + var report types.ProgressReport + if !server.decode(writer, request, &report) { + return + } + server.handleError(server.handler.EmitProgressReport(report, voidReceiver), writer) +} + +func (server *httpServer) handleReportBeforeSuiteCompleted(writer http.ResponseWriter, request *http.Request) { + var state types.SpecState + if !server.decode(writer, request, &state) { + return + } + + server.handleError(server.handler.ReportBeforeSuiteCompleted(state, voidReceiver), writer) +} + +func (server *httpServer) handleReportBeforeSuiteState(writer http.ResponseWriter, request *http.Request) { + var state types.SpecState + if server.handleError(server.handler.ReportBeforeSuiteState(voidSender, &state), writer) { + return + } + json.NewEncoder(writer).Encode(state) +} + func (server *httpServer) handleBeforeSuiteCompleted(writer http.ResponseWriter, request *http.Request) { var beforeSuiteState BeforeSuiteState if !server.decode(writer, request, &beforeSuiteState) { diff --git a/vendor/github.com/onsi/ginkgo/v2/internal/parallel_support/rpc_client.go b/vendor/github.com/onsi/ginkgo/v2/internal/parallel_support/rpc_client.go index 4e83b09703..59e8e6fd0a 100644 --- a/vendor/github.com/onsi/ginkgo/v2/internal/parallel_support/rpc_client.go +++ b/vendor/github.com/onsi/ginkgo/v2/internal/parallel_support/rpc_client.go @@ -72,6 +72,23 @@ func (client *rpcClient) Write(p []byte) (int, error) { return n, err } +func (client *rpcClient) PostEmitProgressReport(report types.ProgressReport) error { + return client.client.Call("Server.EmitProgressReport", report, voidReceiver) +} + +func (client *rpcClient) PostReportBeforeSuiteCompleted(state types.SpecState) error { + return client.client.Call("Server.ReportBeforeSuiteCompleted", state, voidReceiver) +} + +func (client *rpcClient) BlockUntilReportBeforeSuiteCompleted() (types.SpecState, error) { + var state types.SpecState + err := client.poll("Server.ReportBeforeSuiteState", &state) + if err == ErrorGone { + return types.SpecStateFailed, nil + } + return state, err +} + func (client *rpcClient) PostSynchronizedBeforeSuiteCompleted(state types.SpecState, data []byte) error { beforeSuiteState := BeforeSuiteState{ State: state, diff --git a/vendor/github.com/onsi/ginkgo/v2/internal/parallel_support/server_handler.go b/vendor/github.com/onsi/ginkgo/v2/internal/parallel_support/server_handler.go index ca471cf394..a6d98793e9 100644 --- a/vendor/github.com/onsi/ginkgo/v2/internal/parallel_support/server_handler.go +++ b/vendor/github.com/onsi/ginkgo/v2/internal/parallel_support/server_handler.go @@ -18,16 +18,17 @@ var voidSender Void // It handles all the business logic to avoid duplication between the two servers type ServerHandler struct { - done chan interface{} - outputDestination io.Writer - reporter reporters.Reporter - alives []func() bool - lock *sync.Mutex - beforeSuiteState BeforeSuiteState - parallelTotal int - counter int - counterLock *sync.Mutex - shouldAbort bool + done chan interface{} + outputDestination io.Writer + reporter reporters.Reporter + alives []func() bool + lock *sync.Mutex + beforeSuiteState BeforeSuiteState + reportBeforeSuiteState types.SpecState + parallelTotal int + counter int + counterLock *sync.Mutex + shouldAbort bool numSuiteDidBegins int numSuiteDidEnds int @@ -37,11 +38,12 @@ type ServerHandler struct { func newServerHandler(parallelTotal int, reporter reporters.Reporter) *ServerHandler { return &ServerHandler{ - reporter: reporter, - lock: &sync.Mutex{}, - counterLock: &sync.Mutex{}, - alives: make([]func() bool, parallelTotal), - beforeSuiteState: BeforeSuiteState{Data: nil, State: types.SpecStateInvalid}, + reporter: reporter, + lock: &sync.Mutex{}, + counterLock: &sync.Mutex{}, + alives: make([]func() bool, parallelTotal), + beforeSuiteState: BeforeSuiteState{Data: nil, State: types.SpecStateInvalid}, + parallelTotal: parallelTotal, outputDestination: os.Stdout, done: make(chan interface{}), @@ -108,6 +110,13 @@ func (handler *ServerHandler) EmitOutput(output []byte, n *int) error { return err } +func (handler *ServerHandler) EmitProgressReport(report types.ProgressReport, _ *Void) error { + handler.lock.Lock() + defer handler.lock.Unlock() + handler.reporter.EmitProgressReport(report) + return nil +} + func (handler *ServerHandler) registerAlive(proc int, alive func() bool) { handler.lock.Lock() defer handler.lock.Unlock() @@ -133,6 +142,29 @@ func (handler *ServerHandler) haveNonprimaryProcsFinished() bool { return true } +func (handler *ServerHandler) ReportBeforeSuiteCompleted(reportBeforeSuiteState types.SpecState, _ *Void) error { + handler.lock.Lock() + defer handler.lock.Unlock() + handler.reportBeforeSuiteState = reportBeforeSuiteState + + return nil +} + +func (handler *ServerHandler) ReportBeforeSuiteState(_ Void, reportBeforeSuiteState *types.SpecState) error { + proc1IsAlive := handler.procIsAlive(1) + handler.lock.Lock() + defer handler.lock.Unlock() + if handler.reportBeforeSuiteState == types.SpecStateInvalid { + if proc1IsAlive { + return ErrorEarly + } else { + return ErrorGone + } + } + *reportBeforeSuiteState = handler.reportBeforeSuiteState + return nil +} + func (handler *ServerHandler) BeforeSuiteCompleted(beforeSuiteState BeforeSuiteState, _ *Void) error { handler.lock.Lock() defer handler.lock.Unlock() diff --git a/vendor/github.com/onsi/ginkgo/v2/reporters/default_reporter.go b/vendor/github.com/onsi/ginkgo/v2/reporters/default_reporter.go index 0edd44bce3..56b7be7587 100644 --- a/vendor/github.com/onsi/ginkgo/v2/reporters/default_reporter.go +++ b/vendor/github.com/onsi/ginkgo/v2/reporters/default_reporter.go @@ -12,6 +12,8 @@ import ( "io" "runtime" "strings" + "sync" + "time" "github.com/onsi/ginkgo/v2/formatter" "github.com/onsi/ginkgo/v2/types" @@ -22,13 +24,16 @@ type DefaultReporter struct { writer io.Writer // managing the emission stream - lastChar string + lastCharWasNewline bool lastEmissionWasDelimiter bool // rendering specDenoter string retryDenoter string formatter formatter.Formatter + + runningInParallel bool + lock *sync.Mutex } func NewDefaultReporterUnderTest(conf types.ReporterConfig, writer io.Writer) *DefaultReporter { @@ -43,12 +48,13 @@ func NewDefaultReporter(conf types.ReporterConfig, writer io.Writer) *DefaultRep conf: conf, writer: writer, - lastChar: "\n", + lastCharWasNewline: true, lastEmissionWasDelimiter: false, specDenoter: "•", retryDenoter: "↺", formatter: formatter.NewWithNoColorBool(conf.NoColor), + lock: &sync.Mutex{}, } if runtime.GOOS == "windows" { reporter.specDenoter = "+" @@ -96,251 +102,557 @@ func (r *DefaultReporter) SuiteWillBegin(report types.Report) { } } -func (r *DefaultReporter) WillRun(report types.SpecReport) { - if r.conf.Verbosity().LT(types.VerbosityLevelVerbose) || report.State.Is(types.SpecStatePending|types.SpecStateSkipped) { +func (r *DefaultReporter) SuiteDidEnd(report types.Report) { + failures := report.SpecReports.WithState(types.SpecStateFailureStates) + if len(failures) > 0 { + r.emitBlock("\n") + if len(failures) > 1 { + r.emitBlock(r.f("{{red}}{{bold}}Summarizing %d Failures:{{/}}", len(failures))) + } else { + r.emitBlock(r.f("{{red}}{{bold}}Summarizing 1 Failure:{{/}}")) + } + for _, specReport := range failures { + highlightColor, heading := "{{red}}", "[FAIL]" + switch specReport.State { + case types.SpecStatePanicked: + highlightColor, heading = "{{magenta}}", "[PANICKED!]" + case types.SpecStateAborted: + highlightColor, heading = "{{coral}}", "[ABORTED]" + case types.SpecStateTimedout: + highlightColor, heading = "{{orange}}", "[TIMEDOUT]" + case types.SpecStateInterrupted: + highlightColor, heading = "{{orange}}", "[INTERRUPTED]" + } + locationBlock := r.codeLocationBlock(specReport, highlightColor, false, true) + r.emitBlock(r.fi(1, highlightColor+"%s{{/}} %s", heading, locationBlock)) + } + } + + //summarize the suite + if r.conf.Verbosity().Is(types.VerbosityLevelSuccinct) && report.SuiteSucceeded { + r.emit(r.f(" {{green}}SUCCESS!{{/}} %s ", report.RunTime)) return } - r.emitDelimiter() - indentation := uint(0) - if report.LeafNodeType.Is(types.NodeTypesForSuiteLevelNodes) { - r.emitBlock(r.f("{{bold}}[%s] %s{{/}}", report.LeafNodeType.String(), report.LeafNodeText)) + r.emitBlock("\n") + color, status := "{{green}}{{bold}}", "SUCCESS!" + if !report.SuiteSucceeded { + color, status = "{{red}}{{bold}}", "FAIL!" + } + + specs := report.SpecReports.WithLeafNodeType(types.NodeTypeIt) //exclude any suite setup nodes + r.emitBlock(r.f(color+"Ran %d of %d Specs in %.3f seconds{{/}}", + specs.CountWithState(types.SpecStatePassed)+specs.CountWithState(types.SpecStateFailureStates), + report.PreRunStats.TotalSpecs, + report.RunTime.Seconds()), + ) + + switch len(report.SpecialSuiteFailureReasons) { + case 0: + r.emit(r.f(color+"%s{{/}} -- ", status)) + case 1: + r.emit(r.f(color+"%s - %s{{/}} -- ", status, report.SpecialSuiteFailureReasons[0])) + default: + r.emitBlock(r.f(color+"%s - %s{{/}}\n", status, strings.Join(report.SpecialSuiteFailureReasons, ", "))) + } + + if len(specs) == 0 && report.SpecReports.WithLeafNodeType(types.NodeTypeBeforeSuite|types.NodeTypeSynchronizedBeforeSuite).CountWithState(types.SpecStateFailureStates) > 0 { + r.emit(r.f("{{cyan}}{{bold}}A BeforeSuite node failed so all tests were skipped.{{/}}\n")) } else { - if len(report.ContainerHierarchyTexts) > 0 { - r.emitBlock(r.cycleJoin(report.ContainerHierarchyTexts, " ")) - indentation = 1 + r.emit(r.f("{{green}}{{bold}}%d Passed{{/}} | ", specs.CountWithState(types.SpecStatePassed))) + r.emit(r.f("{{red}}{{bold}}%d Failed{{/}} | ", specs.CountWithState(types.SpecStateFailureStates))) + if specs.CountOfFlakedSpecs() > 0 { + r.emit(r.f("{{light-yellow}}{{bold}}%d Flaked{{/}} | ", specs.CountOfFlakedSpecs())) } - line := r.fi(indentation, "{{bold}}%s{{/}}", report.LeafNodeText) - labels := report.Labels() - if len(labels) > 0 { - line += r.f(" {{coral}}[%s]{{/}}", strings.Join(labels, ", ")) + if specs.CountOfRepeatedSpecs() > 0 { + r.emit(r.f("{{light-yellow}}{{bold}}%d Repeated{{/}} | ", specs.CountOfRepeatedSpecs())) } - r.emitBlock(line) + r.emit(r.f("{{yellow}}{{bold}}%d Pending{{/}} | ", specs.CountWithState(types.SpecStatePending))) + r.emit(r.f("{{cyan}}{{bold}}%d Skipped{{/}}\n", specs.CountWithState(types.SpecStateSkipped))) } - r.emitBlock(r.fi(indentation, "{{gray}}%s{{/}}", report.LeafNodeLocation)) } -func (r *DefaultReporter) DidRun(report types.SpecReport) { +func (r *DefaultReporter) WillRun(report types.SpecReport) { v := r.conf.Verbosity() - var header, highlightColor string - includeRuntime, emitGinkgoWriterOutput, stream, denoter := true, true, false, r.specDenoter - succinctLocationBlock := v.Is(types.VerbosityLevelSuccinct) + if v.LT(types.VerbosityLevelVerbose) || report.State.Is(types.SpecStatePending|types.SpecStateSkipped) || report.RunningInParallel { + return + } + + r.emitDelimiter(0) + r.emitBlock(r.f(r.codeLocationBlock(report, "{{/}}", v.Is(types.VerbosityLevelVeryVerbose), false))) +} - hasGW := report.CapturedGinkgoWriterOutput != "" - hasStd := report.CapturedStdOutErr != "" - hasEmittableReports := report.ReportEntries.HasVisibility(types.ReportEntryVisibilityAlways) || (report.ReportEntries.HasVisibility(types.ReportEntryVisibilityFailureOrVerbose) && (!report.Failure.IsZero() || v.GTE(types.VerbosityLevelVerbose))) +func (r *DefaultReporter) DidRun(report types.SpecReport) { + v := r.conf.Verbosity() + inParallel := report.RunningInParallel + header := r.specDenoter if report.LeafNodeType.Is(types.NodeTypesForSuiteLevelNodes) { - denoter = fmt.Sprintf("[%s]", report.LeafNodeType) + header = fmt.Sprintf("[%s]", report.LeafNodeType) } + highlightColor := r.highlightColorForState(report.State) + + // have we already been streaming the timeline? + timelineHasBeenStreaming := v.GTE(types.VerbosityLevelVerbose) && !inParallel + + // should we show the timeline? + var timeline types.Timeline + showTimeline := !timelineHasBeenStreaming && (v.GTE(types.VerbosityLevelVerbose) || report.Failed()) + if showTimeline { + timeline = report.Timeline().WithoutHiddenReportEntries() + keepVeryVerboseSpecEvents := v.Is(types.VerbosityLevelVeryVerbose) || + (v.Is(types.VerbosityLevelVerbose) && r.conf.ShowNodeEvents) || + (report.Failed() && r.conf.ShowNodeEvents) + if !keepVeryVerboseSpecEvents { + timeline = timeline.WithoutVeryVerboseSpecEvents() + } + if len(timeline) == 0 && report.CapturedGinkgoWriterOutput == "" { + // the timeline is completely empty - don't show it + showTimeline = false + } + if v.LT(types.VerbosityLevelVeryVerbose) && report.CapturedGinkgoWriterOutput == "" && len(timeline) > 0 { + //if we aren't -vv and the timeline only has a single failure, don't show it as it will appear at the end of the report + failure, isFailure := timeline[0].(types.Failure) + if isFailure && (len(timeline) == 1 || (len(timeline) == 2 && failure.AdditionalFailure != nil)) { + showTimeline = false + } + } + } + + // should we have a separate section for always-visible reports? + showSeparateVisibilityAlwaysReportsSection := !timelineHasBeenStreaming && !showTimeline && report.ReportEntries.HasVisibility(types.ReportEntryVisibilityAlways) + + // should we have a separate section for captured stdout/stderr + showSeparateStdSection := inParallel && (report.CapturedStdOutErr != "") + + // given all that - do we have any actual content to show? or are we a single denoter in a stream? + reportHasContent := v.Is(types.VerbosityLevelVeryVerbose) || showTimeline || showSeparateVisibilityAlwaysReportsSection || showSeparateStdSection || report.Failed() || (v.Is(types.VerbosityLevelVerbose) && !report.State.Is(types.SpecStateSkipped)) + + // should we show a runtime? + includeRuntime := !report.State.Is(types.SpecStateSkipped|types.SpecStatePending) || (report.State.Is(types.SpecStateSkipped) && report.Failure.Message != "") + + // should we show the codelocation block? + showCodeLocation := !timelineHasBeenStreaming || !report.State.Is(types.SpecStatePassed) switch report.State { case types.SpecStatePassed: - highlightColor, succinctLocationBlock = "{{green}}", v.LT(types.VerbosityLevelVerbose) - emitGinkgoWriterOutput = (r.conf.AlwaysEmitGinkgoWriter || v.GTE(types.VerbosityLevelVerbose)) && hasGW + if report.LeafNodeType.Is(types.NodeTypesForSuiteLevelNodes) && !reportHasContent { + return + } if report.LeafNodeType.Is(types.NodeTypesForSuiteLevelNodes) { - if v.GTE(types.VerbosityLevelVerbose) || hasStd || hasEmittableReports { - header = fmt.Sprintf("%s PASSED", denoter) - } else { - return - } - } else { - header, stream = denoter, true - if report.NumAttempts > 1 { - header, stream = fmt.Sprintf("%s [FLAKEY TEST - TOOK %d ATTEMPTS TO PASS]", r.retryDenoter, report.NumAttempts), false - } - if report.RunTime > r.conf.SlowSpecThreshold { - header, stream = fmt.Sprintf("%s [SLOW TEST]", header), false - } + header = fmt.Sprintf("%s PASSED", header) } - if hasStd || emitGinkgoWriterOutput || hasEmittableReports { - stream = false + if report.NumAttempts > 1 && report.MaxFlakeAttempts > 1 { + header, reportHasContent = fmt.Sprintf("%s [FLAKEY TEST - TOOK %d ATTEMPTS TO PASS]", r.retryDenoter, report.NumAttempts), true } case types.SpecStatePending: - highlightColor = "{{yellow}}" - includeRuntime, emitGinkgoWriterOutput = false, false - if v.Is(types.VerbosityLevelSuccinct) { - header, stream = "P", true - } else { - header, succinctLocationBlock = "P [PENDING]", v.LT(types.VerbosityLevelVeryVerbose) + header = "P" + if v.GT(types.VerbosityLevelSuccinct) { + header, reportHasContent = "P [PENDING]", true } case types.SpecStateSkipped: - highlightColor = "{{cyan}}" - if report.Failure.Message != "" || v.Is(types.VerbosityLevelVeryVerbose) { - header = "S [SKIPPED]" - } else { - header, stream = "S", true + header = "S" + if v.Is(types.VerbosityLevelVeryVerbose) || (v.Is(types.VerbosityLevelVerbose) && report.Failure.Message != "") { + header, reportHasContent = "S [SKIPPED]", true + } + default: + header = fmt.Sprintf("%s [%s]", header, r.humanReadableState(report.State)) + if report.MaxMustPassRepeatedly > 1 { + header = fmt.Sprintf("%s DURING REPETITION #%d", header, report.NumAttempts) } - case types.SpecStateFailed: - highlightColor, header = "{{red}}", fmt.Sprintf("%s [FAILED]", denoter) - case types.SpecStatePanicked: - highlightColor, header = "{{magenta}}", fmt.Sprintf("%s! [PANICKED]", denoter) - case types.SpecStateInterrupted: - highlightColor, header = "{{orange}}", fmt.Sprintf("%s! [INTERRUPTED]", denoter) - case types.SpecStateAborted: - highlightColor, header = "{{coral}}", fmt.Sprintf("%s! [ABORTED]", denoter) } - // Emit stream and return - if stream { + // If we have no content to show, jsut emit the header and return + if !reportHasContent { r.emit(r.f(highlightColor + header + "{{/}}")) return } - // Emit header - r.emitDelimiter() if includeRuntime { header = r.f("%s [%.3f seconds]", header, report.RunTime.Seconds()) } - r.emitBlock(r.f(highlightColor + header + "{{/}}")) - // Emit Code Location Block - r.emitBlock(r.codeLocationBlock(report, highlightColor, succinctLocationBlock, false)) + // Emit header + if !timelineHasBeenStreaming { + r.emitDelimiter(0) + } + r.emitBlock(r.f(highlightColor + header + "{{/}}")) + if showCodeLocation { + r.emitBlock(r.codeLocationBlock(report, highlightColor, v.Is(types.VerbosityLevelVeryVerbose), false)) + } //Emit Stdout/Stderr Output - if hasStd { + if showSeparateStdSection { r.emitBlock("\n") - r.emitBlock(r.fi(1, "{{gray}}Begin Captured StdOut/StdErr Output >>{{/}}")) - r.emitBlock(r.fi(2, "%s", report.CapturedStdOutErr)) - r.emitBlock(r.fi(1, "{{gray}}<< End Captured StdOut/StdErr Output{{/}}")) + r.emitBlock(r.fi(1, "{{gray}}Captured StdOut/StdErr Output >>{{/}}")) + r.emitBlock(r.fi(1, "%s", report.CapturedStdOutErr)) + r.emitBlock(r.fi(1, "{{gray}}<< Captured StdOut/StdErr Output{{/}}")) } - //Emit Captured GinkgoWriter Output - if emitGinkgoWriterOutput && hasGW { + if showSeparateVisibilityAlwaysReportsSection { r.emitBlock("\n") - r.emitBlock(r.fi(1, "{{gray}}Begin Captured GinkgoWriter Output >>{{/}}")) - r.emitBlock(r.fi(2, "%s", report.CapturedGinkgoWriterOutput)) - r.emitBlock(r.fi(1, "{{gray}}<< End Captured GinkgoWriter Output{{/}}")) + r.emitBlock(r.fi(1, "{{gray}}Report Entries >>{{/}}")) + for _, entry := range report.ReportEntries.WithVisibility(types.ReportEntryVisibilityAlways) { + r.emitReportEntry(1, entry) + } + r.emitBlock(r.fi(1, "{{gray}}<< Report Entries{{/}}")) } - if hasEmittableReports { + if showTimeline { r.emitBlock("\n") - r.emitBlock(r.fi(1, "{{gray}}Begin Report Entries >>{{/}}")) - reportEntries := report.ReportEntries.WithVisibility(types.ReportEntryVisibilityAlways) - if !report.Failure.IsZero() || v.GTE(types.VerbosityLevelVerbose) { - reportEntries = report.ReportEntries.WithVisibility(types.ReportEntryVisibilityAlways, types.ReportEntryVisibilityFailureOrVerbose) - } - for _, entry := range reportEntries { - r.emitBlock(r.fi(2, "{{bold}}"+entry.Name+"{{gray}} - %s @ %s{{/}}", entry.Location, entry.Time.Format(types.GINKGO_TIME_FORMAT))) - if representation := entry.StringRepresentation(); representation != "" { - r.emitBlock(r.fi(3, representation)) - } - } - r.emitBlock(r.fi(1, "{{gray}}<< End Report Entries{{/}}")) + r.emitBlock(r.fi(1, "{{gray}}Timeline >>{{/}}")) + r.emitTimeline(1, report, timeline) + r.emitBlock(r.fi(1, "{{gray}}<< Timeline{{/}}")) } // Emit Failure Message - if !report.Failure.IsZero() { + if !report.Failure.IsZero() && !v.Is(types.VerbosityLevelVeryVerbose) { r.emitBlock("\n") - r.emitBlock(r.fi(1, highlightColor+"%s{{/}}", report.Failure.Message)) - r.emitBlock(r.fi(1, highlightColor+"In {{bold}}[%s]{{/}}"+highlightColor+" at: {{bold}}%s{{/}}\n", report.Failure.FailureNodeType, report.Failure.Location)) - if report.Failure.ForwardedPanic != "" { - r.emitBlock("\n") - r.emitBlock(r.fi(1, highlightColor+"%s{{/}}", report.Failure.ForwardedPanic)) + r.emitFailure(1, report.State, report.Failure, true) + if len(report.AdditionalFailures) > 0 { + r.emitBlock(r.fi(1, "\nThere were {{bold}}{{red}}additional failures{{/}} detected. To view them in detail run {{bold}}ginkgo -vv{{/}}")) } + } + + r.emitDelimiter(0) +} + +func (r *DefaultReporter) highlightColorForState(state types.SpecState) string { + switch state { + case types.SpecStatePassed: + return "{{green}}" + case types.SpecStatePending: + return "{{yellow}}" + case types.SpecStateSkipped: + return "{{cyan}}" + case types.SpecStateFailed: + return "{{red}}" + case types.SpecStateTimedout: + return "{{orange}}" + case types.SpecStatePanicked: + return "{{magenta}}" + case types.SpecStateInterrupted: + return "{{orange}}" + case types.SpecStateAborted: + return "{{coral}}" + default: + return "{{gray}}" + } +} - if r.conf.FullTrace || report.Failure.ForwardedPanic != "" { - r.emitBlock("\n") - r.emitBlock(r.fi(1, highlightColor+"Full Stack Trace{{/}}")) - r.emitBlock(r.fi(2, "%s", report.Failure.Location.FullStackTrace)) +func (r *DefaultReporter) humanReadableState(state types.SpecState) string { + return strings.ToUpper(state.String()) +} + +func (r *DefaultReporter) emitTimeline(indent uint, report types.SpecReport, timeline types.Timeline) { + isVeryVerbose := r.conf.Verbosity().Is(types.VerbosityLevelVeryVerbose) + gw := report.CapturedGinkgoWriterOutput + cursor := 0 + for _, entry := range timeline { + tl := entry.GetTimelineLocation() + if tl.Offset < len(gw) { + r.emit(r.fi(indent, "%s", gw[cursor:tl.Offset])) + cursor = tl.Offset + } else if cursor < len(gw) { + r.emit(r.fi(indent, "%s", gw[cursor:])) + cursor = len(gw) } + switch x := entry.(type) { + case types.Failure: + if isVeryVerbose { + r.emitFailure(indent, report.State, x, false) + } else { + r.emitShortFailure(indent, report.State, x) + } + case types.AdditionalFailure: + if isVeryVerbose { + r.emitFailure(indent, x.State, x.Failure, true) + } else { + r.emitShortFailure(indent, x.State, x.Failure) + } + case types.ReportEntry: + r.emitReportEntry(indent, x) + case types.ProgressReport: + r.emitProgressReport(indent, false, x) + case types.SpecEvent: + if isVeryVerbose || !x.IsOnlyVisibleAtVeryVerbose() || r.conf.ShowNodeEvents { + r.emitSpecEvent(indent, x, isVeryVerbose) + } + } + } + if cursor < len(gw) { + r.emit(r.fi(indent, "%s", gw[cursor:])) } +} - r.emitDelimiter() +func (r *DefaultReporter) EmitFailure(state types.SpecState, failure types.Failure) { + if r.conf.Verbosity().Is(types.VerbosityLevelVerbose) { + r.emitShortFailure(1, state, failure) + } else if r.conf.Verbosity().Is(types.VerbosityLevelVeryVerbose) { + r.emitFailure(1, state, failure, true) + } } -func (r *DefaultReporter) SuiteDidEnd(report types.Report) { - failures := report.SpecReports.WithState(types.SpecStateFailureStates) - if len(failures) > 0 { - r.emitBlock("\n\n") - if len(failures) > 1 { - r.emitBlock(r.f("{{red}}{{bold}}Summarizing %d Failures:{{/}}", len(failures))) +func (r *DefaultReporter) emitShortFailure(indent uint, state types.SpecState, failure types.Failure) { + r.emitBlock(r.fi(indent, r.highlightColorForState(state)+"[%s]{{/}} in [%s] - %s {{gray}}@ %s{{/}}", + r.humanReadableState(state), + failure.FailureNodeType, + failure.Location, + failure.TimelineLocation.Time.Format(types.GINKGO_TIME_FORMAT), + )) +} + +func (r *DefaultReporter) emitFailure(indent uint, state types.SpecState, failure types.Failure, includeAdditionalFailure bool) { + highlightColor := r.highlightColorForState(state) + r.emitBlock(r.fi(indent, highlightColor+"[%s] %s{{/}}", r.humanReadableState(state), failure.Message)) + r.emitBlock(r.fi(indent, highlightColor+"In {{bold}}[%s]{{/}}"+highlightColor+" at: {{bold}}%s{{/}} {{gray}}@ %s{{/}}\n", failure.FailureNodeType, failure.Location, failure.TimelineLocation.Time.Format(types.GINKGO_TIME_FORMAT))) + if failure.ForwardedPanic != "" { + r.emitBlock("\n") + r.emitBlock(r.fi(indent, highlightColor+"%s{{/}}", failure.ForwardedPanic)) + } + + if r.conf.FullTrace || failure.ForwardedPanic != "" { + r.emitBlock("\n") + r.emitBlock(r.fi(indent, highlightColor+"Full Stack Trace{{/}}")) + r.emitBlock(r.fi(indent+1, "%s", failure.Location.FullStackTrace)) + } + + if !failure.ProgressReport.IsZero() { + r.emitBlock("\n") + r.emitProgressReport(indent, false, failure.ProgressReport) + } + + if failure.AdditionalFailure != nil && includeAdditionalFailure { + r.emitBlock("\n") + r.emitFailure(indent, failure.AdditionalFailure.State, failure.AdditionalFailure.Failure, true) + } +} + +func (r *DefaultReporter) EmitProgressReport(report types.ProgressReport) { + r.emitDelimiter(1) + + if report.RunningInParallel { + r.emit(r.fi(1, "{{coral}}Progress Report for Ginkgo Process #{{bold}}%d{{/}}\n", report.ParallelProcess)) + } + shouldEmitGW := report.RunningInParallel || r.conf.Verbosity().LT(types.VerbosityLevelVerbose) + r.emitProgressReport(1, shouldEmitGW, report) + r.emitDelimiter(1) +} + +func (r *DefaultReporter) emitProgressReport(indent uint, emitGinkgoWriterOutput bool, report types.ProgressReport) { + if report.Message != "" { + r.emitBlock(r.fi(indent, report.Message+"\n")) + indent += 1 + } + if report.LeafNodeText != "" { + subjectIndent := indent + if len(report.ContainerHierarchyTexts) > 0 { + r.emit(r.fi(indent, r.cycleJoin(report.ContainerHierarchyTexts, " "))) + r.emit(" ") + subjectIndent = 0 + } + r.emit(r.fi(subjectIndent, "{{bold}}{{orange}}%s{{/}} (Spec Runtime: %s)\n", report.LeafNodeText, report.Time().Sub(report.SpecStartTime).Round(time.Millisecond))) + r.emit(r.fi(indent+1, "{{gray}}%s{{/}}\n", report.LeafNodeLocation)) + indent += 1 + } + if report.CurrentNodeType != types.NodeTypeInvalid { + r.emit(r.fi(indent, "In {{bold}}{{orange}}[%s]{{/}}", report.CurrentNodeType)) + if report.CurrentNodeText != "" && !report.CurrentNodeType.Is(types.NodeTypeIt) { + r.emit(r.f(" {{bold}}{{orange}}%s{{/}}", report.CurrentNodeText)) + } + + r.emit(r.f(" (Node Runtime: %s)\n", report.Time().Sub(report.CurrentNodeStartTime).Round(time.Millisecond))) + r.emit(r.fi(indent+1, "{{gray}}%s{{/}}\n", report.CurrentNodeLocation)) + indent += 1 + } + if report.CurrentStepText != "" { + r.emit(r.fi(indent, "At {{bold}}{{orange}}[By Step] %s{{/}} (Step Runtime: %s)\n", report.CurrentStepText, report.Time().Sub(report.CurrentStepStartTime).Round(time.Millisecond))) + r.emit(r.fi(indent+1, "{{gray}}%s{{/}}\n", report.CurrentStepLocation)) + indent += 1 + } + + if indent > 0 { + indent -= 1 + } + + if emitGinkgoWriterOutput && report.CapturedGinkgoWriterOutput != "" { + r.emit("\n") + r.emitBlock(r.fi(indent, "{{gray}}Begin Captured GinkgoWriter Output >>{{/}}")) + limit, lines := 10, strings.Split(report.CapturedGinkgoWriterOutput, "\n") + if len(lines) <= limit { + r.emitBlock(r.fi(indent+1, "%s", report.CapturedGinkgoWriterOutput)) } else { - r.emitBlock(r.f("{{red}}{{bold}}Summarizing 1 Failure:{{/}}")) + r.emitBlock(r.fi(indent+1, "{{gray}}...{{/}}")) + for _, line := range lines[len(lines)-limit-1:] { + r.emitBlock(r.fi(indent+1, "%s", line)) + } } - for _, specReport := range failures { - highlightColor, heading := "{{red}}", "[FAIL]" - switch specReport.State { - case types.SpecStatePanicked: - highlightColor, heading = "{{magenta}}", "[PANICKED!]" - case types.SpecStateAborted: - highlightColor, heading = "{{coral}}", "[ABORTED]" - case types.SpecStateInterrupted: - highlightColor, heading = "{{orange}}", "[INTERRUPTED]" + r.emitBlock(r.fi(indent, "{{gray}}<< End Captured GinkgoWriter Output{{/}}")) + } + + if !report.SpecGoroutine().IsZero() { + r.emit("\n") + r.emit(r.fi(indent, "{{bold}}{{underline}}Spec Goroutine{{/}}\n")) + r.emitGoroutines(indent, report.SpecGoroutine()) + } + + if len(report.AdditionalReports) > 0 { + r.emit("\n") + r.emitBlock(r.fi(indent, "{{gray}}Begin Additional Progress Reports >>{{/}}")) + for i, additionalReport := range report.AdditionalReports { + r.emit(r.fi(indent+1, additionalReport)) + if i < len(report.AdditionalReports)-1 { + r.emitBlock(r.fi(indent+1, "{{gray}}%s{{/}}", strings.Repeat("-", 10))) } - locationBlock := r.codeLocationBlock(specReport, highlightColor, true, true) - r.emitBlock(r.fi(1, highlightColor+"%s{{/}} %s", heading, locationBlock)) } + r.emitBlock(r.fi(indent, "{{gray}}<< End Additional Progress Reports{{/}}")) } - //summarize the suite - if r.conf.Verbosity().Is(types.VerbosityLevelSuccinct) && report.SuiteSucceeded { - r.emit(r.f(" {{green}}SUCCESS!{{/}} %s ", report.RunTime)) - return + highlightedGoroutines := report.HighlightedGoroutines() + if len(highlightedGoroutines) > 0 { + r.emit("\n") + r.emit(r.fi(indent, "{{bold}}{{underline}}Goroutines of Interest{{/}}\n")) + r.emitGoroutines(indent, highlightedGoroutines...) } - r.emitBlock("\n") - color, status := "{{green}}{{bold}}", "SUCCESS!" - if !report.SuiteSucceeded { - color, status = "{{red}}{{bold}}", "FAIL!" + otherGoroutines := report.OtherGoroutines() + if len(otherGoroutines) > 0 { + r.emit("\n") + r.emit(r.fi(indent, "{{gray}}{{bold}}{{underline}}Other Goroutines{{/}}\n")) + r.emitGoroutines(indent, otherGoroutines...) } +} - specs := report.SpecReports.WithLeafNodeType(types.NodeTypeIt) //exclude any suite setup nodes - r.emitBlock(r.f(color+"Ran %d of %d Specs in %.3f seconds{{/}}", - specs.CountWithState(types.SpecStatePassed)+specs.CountWithState(types.SpecStateFailureStates), - report.PreRunStats.TotalSpecs, - report.RunTime.Seconds()), - ) +func (r *DefaultReporter) EmitReportEntry(entry types.ReportEntry) { + if r.conf.Verbosity().LT(types.VerbosityLevelVerbose) || entry.Visibility == types.ReportEntryVisibilityNever { + return + } + r.emitReportEntry(1, entry) +} - switch len(report.SpecialSuiteFailureReasons) { - case 0: - r.emit(r.f(color+"%s{{/}} -- ", status)) - case 1: - r.emit(r.f(color+"%s - %s{{/}} -- ", status, report.SpecialSuiteFailureReasons[0])) - default: - r.emitBlock(r.f(color+"%s - %s{{/}}\n", status, strings.Join(report.SpecialSuiteFailureReasons, ", "))) +func (r *DefaultReporter) emitReportEntry(indent uint, entry types.ReportEntry) { + r.emitBlock(r.fi(indent, "{{bold}}"+entry.Name+"{{gray}} "+fmt.Sprintf("- %s @ %s{{/}}", entry.Location, entry.Time.Format(types.GINKGO_TIME_FORMAT)))) + if representation := entry.StringRepresentation(); representation != "" { + r.emitBlock(r.fi(indent+1, representation)) } +} - if len(specs) == 0 && report.SpecReports.WithLeafNodeType(types.NodeTypeBeforeSuite|types.NodeTypeSynchronizedBeforeSuite).CountWithState(types.SpecStateFailureStates) > 0 { - r.emit(r.f("{{cyan}}{{bold}}A BeforeSuite node failed so all tests were skipped.{{/}}\n")) - } else { - r.emit(r.f("{{green}}{{bold}}%d Passed{{/}} | ", specs.CountWithState(types.SpecStatePassed))) - r.emit(r.f("{{red}}{{bold}}%d Failed{{/}} | ", specs.CountWithState(types.SpecStateFailureStates))) - if specs.CountOfFlakedSpecs() > 0 { - r.emit(r.f("{{light-yellow}}{{bold}}%d Flaked{{/}} | ", specs.CountOfFlakedSpecs())) - } - r.emit(r.f("{{yellow}}{{bold}}%d Pending{{/}} | ", specs.CountWithState(types.SpecStatePending))) - r.emit(r.f("{{cyan}}{{bold}}%d Skipped{{/}}\n", specs.CountWithState(types.SpecStateSkipped))) +func (r *DefaultReporter) EmitSpecEvent(event types.SpecEvent) { + v := r.conf.Verbosity() + if v.Is(types.VerbosityLevelVeryVerbose) || (v.Is(types.VerbosityLevelVerbose) && (r.conf.ShowNodeEvents || !event.IsOnlyVisibleAtVeryVerbose())) { + r.emitSpecEvent(1, event, r.conf.Verbosity().Is(types.VerbosityLevelVeryVerbose)) } } -/* Emitting to the writer */ -func (r *DefaultReporter) emit(s string) { - if len(s) > 0 { - r.lastChar = s[len(s)-1:] - r.lastEmissionWasDelimiter = false - r.writer.Write([]byte(s)) +func (r *DefaultReporter) emitSpecEvent(indent uint, event types.SpecEvent, includeLocation bool) { + location := "" + if includeLocation { + location = fmt.Sprintf("- %s ", event.CodeLocation.String()) + } + switch event.SpecEventType { + case types.SpecEventInvalid: + return + case types.SpecEventByStart: + r.emitBlock(r.fi(indent, "{{bold}}STEP:{{/}} %s {{gray}}%s@ %s{{/}}", event.Message, location, event.TimelineLocation.Time.Format(types.GINKGO_TIME_FORMAT))) + case types.SpecEventByEnd: + r.emitBlock(r.fi(indent, "{{bold}}END STEP:{{/}} %s {{gray}}%s@ %s (%s){{/}}", event.Message, location, event.TimelineLocation.Time.Format(types.GINKGO_TIME_FORMAT), event.Duration.Round(time.Millisecond))) + case types.SpecEventNodeStart: + r.emitBlock(r.fi(indent, "> Enter {{bold}}[%s]{{/}} %s {{gray}}%s@ %s{{/}}", event.NodeType.String(), event.Message, location, event.TimelineLocation.Time.Format(types.GINKGO_TIME_FORMAT))) + case types.SpecEventNodeEnd: + r.emitBlock(r.fi(indent, "< Exit {{bold}}[%s]{{/}} %s {{gray}}%s@ %s (%s){{/}}", event.NodeType.String(), event.Message, location, event.TimelineLocation.Time.Format(types.GINKGO_TIME_FORMAT), event.Duration.Round(time.Millisecond))) + case types.SpecEventSpecRepeat: + r.emitBlock(r.fi(indent, "\n{{bold}}Attempt #%d {{green}}Passed{{/}}{{bold}}. Repeating %s{{/}} {{gray}}@ %s{{/}}\n\n", event.Attempt, r.retryDenoter, event.TimelineLocation.Time.Format(types.GINKGO_TIME_FORMAT))) + case types.SpecEventSpecRetry: + r.emitBlock(r.fi(indent, "\n{{bold}}Attempt #%d {{red}}Failed{{/}}{{bold}}. Retrying %s{{/}} {{gray}}@ %s{{/}}\n\n", event.Attempt, r.retryDenoter, event.TimelineLocation.Time.Format(types.GINKGO_TIME_FORMAT))) } } -func (r *DefaultReporter) emitBlock(s string) { - if len(s) > 0 { - if r.lastChar != "\n" { - r.emit("\n") +func (r *DefaultReporter) emitGoroutines(indent uint, goroutines ...types.Goroutine) { + for idx, g := range goroutines { + color := "{{gray}}" + if g.HasHighlights() { + color = "{{orange}}" } - r.emit(s) - if r.lastChar != "\n" { + r.emit(r.fi(indent, color+"goroutine %d [%s]{{/}}\n", g.ID, g.State)) + for _, fc := range g.Stack { + if fc.Highlight { + r.emit(r.fi(indent, color+"{{bold}}> %s{{/}}\n", fc.Function)) + r.emit(r.fi(indent+2, color+"{{bold}}%s:%d{{/}}\n", fc.Filename, fc.Line)) + r.emitSource(indent+3, fc) + } else { + r.emit(r.fi(indent+1, "{{gray}}%s{{/}}\n", fc.Function)) + r.emit(r.fi(indent+2, "{{gray}}%s:%d{{/}}\n", fc.Filename, fc.Line)) + } + } + + if idx+1 < len(goroutines) { r.emit("\n") } } } -func (r *DefaultReporter) emitDelimiter() { - if r.lastEmissionWasDelimiter { +func (r *DefaultReporter) emitSource(indent uint, fc types.FunctionCall) { + lines := fc.Source + if len(lines) == 0 { + return + } + + lTrim := 100000 + for _, line := range lines { + lTrimLine := len(line) - len(strings.TrimLeft(line, " \t")) + if lTrimLine < lTrim && len(line) > 0 { + lTrim = lTrimLine + } + } + if lTrim == 100000 { + lTrim = 0 + } + + for idx, line := range lines { + if len(line) > lTrim { + line = line[lTrim:] + } + if idx == fc.SourceHighlight { + r.emit(r.fi(indent, "{{bold}}{{orange}}> %s{{/}}\n", line)) + } else { + r.emit(r.fi(indent, "| %s\n", line)) + } + } +} + +/* Emitting to the writer */ +func (r *DefaultReporter) emit(s string) { + r._emit(s, false, false) +} + +func (r *DefaultReporter) emitBlock(s string) { + r._emit(s, true, false) +} + +func (r *DefaultReporter) emitDelimiter(indent uint) { + r._emit(r.fi(indent, "{{gray}}%s{{/}}", strings.Repeat("-", 30)), true, true) +} + +// a bit ugly - but we're trying to minimize locking on this hot codepath +func (r *DefaultReporter) _emit(s string, block bool, isDelimiter bool) { + if len(s) == 0 { return } - r.emitBlock(r.f("{{gray}}%s{{/}}", strings.Repeat("-", 30))) - r.lastEmissionWasDelimiter = true + r.lock.Lock() + defer r.lock.Unlock() + if isDelimiter && r.lastEmissionWasDelimiter { + return + } + if block && !r.lastCharWasNewline { + r.writer.Write([]byte("\n")) + } + r.lastCharWasNewline = (s[len(s)-1:] == "\n") + r.writer.Write([]byte(s)) + if block && !r.lastCharWasNewline { + r.writer.Write([]byte("\n")) + r.lastCharWasNewline = true + } + r.lastEmissionWasDelimiter = isDelimiter } /* Rendering text */ @@ -356,13 +668,14 @@ func (r *DefaultReporter) cycleJoin(elements []string, joiner string) string { return r.formatter.CycleJoin(elements, joiner, []string{"{{/}}", "{{gray}}"}) } -func (r *DefaultReporter) codeLocationBlock(report types.SpecReport, highlightColor string, succinct bool, usePreciseFailureLocation bool) string { +func (r *DefaultReporter) codeLocationBlock(report types.SpecReport, highlightColor string, veryVerbose bool, usePreciseFailureLocation bool) string { texts, locations, labels := []string{}, []types.CodeLocation{}, [][]string{} texts, locations, labels = append(texts, report.ContainerHierarchyTexts...), append(locations, report.ContainerHierarchyLocations...), append(labels, report.ContainerHierarchyLabels...) + if report.LeafNodeType.Is(types.NodeTypesForSuiteLevelNodes) { texts = append(texts, r.f("[%s] %s", report.LeafNodeType, report.LeafNodeText)) } else { - texts = append(texts, report.LeafNodeText) + texts = append(texts, r.f(report.LeafNodeText)) } labels = append(labels, report.LeafNodeLabels) locations = append(locations, report.LeafNodeLocation) @@ -372,24 +685,58 @@ func (r *DefaultReporter) codeLocationBlock(report types.SpecReport, highlightCo failureLocation = report.Failure.Location } + highlightIndex := -1 switch report.Failure.FailureNodeContext { case types.FailureNodeAtTopLevel: - texts = append([]string{r.f(highlightColor+"{{bold}}TOP-LEVEL [%s]{{/}}", report.Failure.FailureNodeType)}, texts...) + texts = append([]string{fmt.Sprintf("TOP-LEVEL [%s]", report.Failure.FailureNodeType)}, texts...) locations = append([]types.CodeLocation{failureLocation}, locations...) labels = append([][]string{{}}, labels...) + highlightIndex = 0 case types.FailureNodeInContainer: i := report.Failure.FailureNodeContainerIndex - texts[i] = r.f(highlightColor+"{{bold}}%s [%s]{{/}}", texts[i], report.Failure.FailureNodeType) + texts[i] = fmt.Sprintf("%s [%s]", texts[i], report.Failure.FailureNodeType) locations[i] = failureLocation + highlightIndex = i case types.FailureNodeIsLeafNode: i := len(texts) - 1 - texts[i] = r.f(highlightColor+"{{bold}}[%s] %s{{/}}", report.LeafNodeType, report.LeafNodeText) + texts[i] = fmt.Sprintf("[%s] %s", report.LeafNodeType, report.LeafNodeText) locations[i] = failureLocation + highlightIndex = i + default: + //there is no failure, so we highlight the leaf ndoe + highlightIndex = len(texts) - 1 } out := "" - if succinct { - out += r.f("%s", r.cycleJoin(texts, " ")) + if veryVerbose { + for i := range texts { + if i == highlightIndex { + out += r.fi(uint(i), highlightColor+"{{bold}}%s{{/}}", texts[i]) + } else { + out += r.fi(uint(i), "%s", texts[i]) + } + if len(labels[i]) > 0 { + out += r.f(" {{coral}}[%s]{{/}}", strings.Join(labels[i], ", ")) + } + out += "\n" + out += r.fi(uint(i), "{{gray}}%s{{/}}\n", locations[i]) + } + } else { + for i := range texts { + style := "{{/}}" + if i%2 == 1 { + style = "{{gray}}" + } + if i == highlightIndex { + style = highlightColor + "{{bold}}" + } + out += r.f(style+"%s", texts[i]) + if i < len(texts)-1 { + out += " " + } else { + out += r.f("{{/}}") + } + } flattenedLabels := report.Labels() if len(flattenedLabels) > 0 { out += r.f(" {{coral}}[%s]{{/}}", strings.Join(flattenedLabels, ", ")) @@ -398,17 +745,15 @@ func (r *DefaultReporter) codeLocationBlock(report types.SpecReport, highlightCo if usePreciseFailureLocation { out += r.f("{{gray}}%s{{/}}", failureLocation) } else { - out += r.f("{{gray}}%s{{/}}", locations[len(locations)-1]) - } - } else { - for i := range texts { - out += r.fi(uint(i), "%s", texts[i]) - if len(labels[i]) > 0 { - out += r.f(" {{coral}}[%s]{{/}}", strings.Join(labels[i], ", ")) + leafLocation := locations[len(locations)-1] + if (report.Failure.FailureNodeLocation != types.CodeLocation{}) && (report.Failure.FailureNodeLocation != leafLocation) { + out += r.fi(1, highlightColor+"[%s]{{/}} {{gray}}%s{{/}}\n", report.Failure.FailureNodeType, report.Failure.FailureNodeLocation) + out += r.fi(1, "{{gray}}[%s] %s{{/}}", report.LeafNodeType, leafLocation) + } else { + out += r.f("{{gray}}%s{{/}}", leafLocation) } - out += "\n" - out += r.fi(uint(i), "{{gray}}%s{{/}}\n", locations[i]) } + } return out } diff --git a/vendor/github.com/onsi/ginkgo/v2/reporters/deprecated_reporter.go b/vendor/github.com/onsi/ginkgo/v2/reporters/deprecated_reporter.go index 89d30076bf..613072ebf1 100644 --- a/vendor/github.com/onsi/ginkgo/v2/reporters/deprecated_reporter.go +++ b/vendor/github.com/onsi/ginkgo/v2/reporters/deprecated_reporter.go @@ -35,7 +35,7 @@ func ReportViaDeprecatedReporter(reporter DeprecatedReporter, report types.Repor FailOnPending: report.SuiteConfig.FailOnPending, FailFast: report.SuiteConfig.FailFast, FlakeAttempts: report.SuiteConfig.FlakeAttempts, - EmitSpecProgress: report.SuiteConfig.EmitSpecProgress, + EmitSpecProgress: false, DryRun: report.SuiteConfig.DryRun, ParallelNode: report.SuiteConfig.ParallelProcess, ParallelTotal: report.SuiteConfig.ParallelTotal, diff --git a/vendor/github.com/onsi/ginkgo/v2/reporters/junit_report.go b/vendor/github.com/onsi/ginkgo/v2/reporters/junit_report.go index febcc650b0..592d7f614b 100644 --- a/vendor/github.com/onsi/ginkgo/v2/reporters/junit_report.go +++ b/vendor/github.com/onsi/ginkgo/v2/reporters/junit_report.go @@ -15,12 +15,32 @@ import ( "fmt" "os" "strings" - "time" "github.com/onsi/ginkgo/v2/config" "github.com/onsi/ginkgo/v2/types" ) +type JunitReportConfig struct { + // Spec States for which no timeline should be emitted for system-err + // set this to types.SpecStatePassed|types.SpecStateSkipped|types.SpecStatePending to only match failing specs + OmitTimelinesForSpecState types.SpecState + + // Enable OmitFailureMessageAttr to prevent failure messages appearing in the "message" attribute of the Failure and Error tags + OmitFailureMessageAttr bool + + //Enable OmitCapturedStdOutErr to prevent captured stdout/stderr appearing in system-out + OmitCapturedStdOutErr bool + + // Enable OmitSpecLabels to prevent labels from appearing in the spec name + OmitSpecLabels bool + + // Enable OmitLeafNodeType to prevent the spec leaf node type from appearing in the spec name + OmitLeafNodeType bool + + // Enable OmitSuiteSetupNodes to prevent the creation of testcase entries for setup nodes + OmitSuiteSetupNodes bool +} + type JUnitTestSuites struct { XMLName xml.Name `xml:"testsuites"` // Tests maps onto the total number of specs in all test suites (this includes any suite nodes such as BeforeSuite) @@ -128,6 +148,10 @@ type JUnitFailure struct { } func GenerateJUnitReport(report types.Report, dst string) error { + return GenerateJUnitReportWithConfig(report, dst, JunitReportConfig{}) +} + +func GenerateJUnitReportWithConfig(report types.Report, dst string, config JunitReportConfig) error { suite := JUnitTestSuite{ Name: report.SuiteDescription, Package: report.SuitePath, @@ -149,7 +173,6 @@ func GenerateJUnitReport(report types.Report, dst string) error { {"FailOnPending", fmt.Sprintf("%t", report.SuiteConfig.FailOnPending)}, {"FailFast", fmt.Sprintf("%t", report.SuiteConfig.FailFast)}, {"FlakeAttempts", fmt.Sprintf("%d", report.SuiteConfig.FlakeAttempts)}, - {"EmitSpecProgress", fmt.Sprintf("%t", report.SuiteConfig.EmitSpecProgress)}, {"DryRun", fmt.Sprintf("%t", report.SuiteConfig.DryRun)}, {"ParallelTotal", fmt.Sprintf("%d", report.SuiteConfig.ParallelTotal)}, {"OutputInterceptorMode", report.SuiteConfig.OutputInterceptorMode}, @@ -157,22 +180,33 @@ func GenerateJUnitReport(report types.Report, dst string) error { }, } for _, spec := range report.SpecReports { + if config.OmitSuiteSetupNodes && spec.LeafNodeType != types.NodeTypeIt { + continue + } name := fmt.Sprintf("[%s]", spec.LeafNodeType) + if config.OmitLeafNodeType { + name = "" + } if spec.FullText() != "" { name = name + " " + spec.FullText() } labels := spec.Labels() - if len(labels) > 0 { + if len(labels) > 0 && !config.OmitSpecLabels { name = name + " [" + strings.Join(labels, ", ") + "]" } + name = strings.TrimSpace(name) test := JUnitTestCase{ Name: name, Classname: report.SuiteDescription, Status: spec.State.String(), Time: spec.RunTime.Seconds(), - SystemOut: systemOutForUnstructureReporters(spec), - SystemErr: spec.CapturedGinkgoWriterOutput, + } + if !spec.State.Is(config.OmitTimelinesForSpecState) { + test.SystemErr = systemErrForUnstructuredReporters(spec) + } + if !config.OmitCapturedStdOutErr { + test.SystemOut = systemOutForUnstructuredReporters(spec) } suite.Tests += 1 @@ -191,28 +225,50 @@ func GenerateJUnitReport(report types.Report, dst string) error { test.Failure = &JUnitFailure{ Message: spec.Failure.Message, Type: "failed", - Description: fmt.Sprintf("%s\n%s", spec.Failure.Location.String(), spec.Failure.Location.FullStackTrace), + Description: failureDescriptionForUnstructuredReporters(spec), + } + if config.OmitFailureMessageAttr { + test.Failure.Message = "" + } + suite.Failures += 1 + case types.SpecStateTimedout: + test.Failure = &JUnitFailure{ + Message: spec.Failure.Message, + Type: "timedout", + Description: failureDescriptionForUnstructuredReporters(spec), + } + if config.OmitFailureMessageAttr { + test.Failure.Message = "" } suite.Failures += 1 case types.SpecStateInterrupted: test.Error = &JUnitError{ - Message: "interrupted", + Message: spec.Failure.Message, Type: "interrupted", - Description: spec.Failure.Message, + Description: failureDescriptionForUnstructuredReporters(spec), + } + if config.OmitFailureMessageAttr { + test.Error.Message = "" } suite.Errors += 1 case types.SpecStateAborted: test.Failure = &JUnitFailure{ Message: spec.Failure.Message, Type: "aborted", - Description: fmt.Sprintf("%s\n%s", spec.Failure.Location.String(), spec.Failure.Location.FullStackTrace), + Description: failureDescriptionForUnstructuredReporters(spec), + } + if config.OmitFailureMessageAttr { + test.Failure.Message = "" } suite.Errors += 1 case types.SpecStatePanicked: test.Error = &JUnitError{ Message: spec.Failure.ForwardedPanic, Type: "panicked", - Description: fmt.Sprintf("%s\n%s", spec.Failure.Location.String(), spec.Failure.Location.FullStackTrace), + Description: failureDescriptionForUnstructuredReporters(spec), + } + if config.OmitFailureMessageAttr { + test.Error.Message = "" } suite.Errors += 1 } @@ -278,21 +334,27 @@ func MergeAndCleanupJUnitReports(sources []string, dst string) ([]string, error) return messages, f.Close() } -func systemOutForUnstructureReporters(spec types.SpecReport) string { - systemOut := spec.CapturedStdOutErr - if len(spec.ReportEntries) > 0 { - systemOut += "\nReport Entries:\n" - for i, entry := range spec.ReportEntries { - systemOut += fmt.Sprintf("%s\n%s\n%s\n", entry.Name, entry.Location, entry.Time.Format(time.RFC3339Nano)) - if representation := entry.StringRepresentation(); representation != "" { - systemOut += representation + "\n" - } - if i+1 < len(spec.ReportEntries) { - systemOut += "--\n" - } - } +func failureDescriptionForUnstructuredReporters(spec types.SpecReport) string { + out := &strings.Builder{} + NewDefaultReporter(types.ReporterConfig{NoColor: true, VeryVerbose: true}, out).emitFailure(0, spec.State, spec.Failure, true) + if len(spec.AdditionalFailures) > 0 { + out.WriteString("\nThere were additional failures detected after the initial failure. These are visible in the timeline\n") } - return systemOut + return out.String() +} + +func systemErrForUnstructuredReporters(spec types.SpecReport) string { + return RenderTimeline(spec, true) +} + +func RenderTimeline(spec types.SpecReport, noColor bool) string { + out := &strings.Builder{} + NewDefaultReporter(types.ReporterConfig{NoColor: noColor, VeryVerbose: true}, out).emitTimeline(0, spec, spec.Timeline()) + return out.String() +} + +func systemOutForUnstructuredReporters(spec types.SpecReport) string { + return spec.CapturedStdOutErr } // Deprecated JUnitReporter (so folks can still compile their suites) diff --git a/vendor/github.com/onsi/ginkgo/v2/reporters/reporter.go b/vendor/github.com/onsi/ginkgo/v2/reporters/reporter.go index 29f84e7c1b..5e726c464e 100644 --- a/vendor/github.com/onsi/ginkgo/v2/reporters/reporter.go +++ b/vendor/github.com/onsi/ginkgo/v2/reporters/reporter.go @@ -9,11 +9,21 @@ type Reporter interface { WillRun(report types.SpecReport) DidRun(report types.SpecReport) SuiteDidEnd(report types.Report) + + //Timeline emission + EmitFailure(state types.SpecState, failure types.Failure) + EmitProgressReport(progressReport types.ProgressReport) + EmitReportEntry(entry types.ReportEntry) + EmitSpecEvent(event types.SpecEvent) } type NoopReporter struct{} -func (n NoopReporter) SuiteWillBegin(report types.Report) {} -func (n NoopReporter) WillRun(report types.SpecReport) {} -func (n NoopReporter) DidRun(report types.SpecReport) {} -func (n NoopReporter) SuiteDidEnd(report types.Report) {} +func (n NoopReporter) SuiteWillBegin(report types.Report) {} +func (n NoopReporter) WillRun(report types.SpecReport) {} +func (n NoopReporter) DidRun(report types.SpecReport) {} +func (n NoopReporter) SuiteDidEnd(report types.Report) {} +func (n NoopReporter) EmitFailure(state types.SpecState, failure types.Failure) {} +func (n NoopReporter) EmitProgressReport(progressReport types.ProgressReport) {} +func (n NoopReporter) EmitReportEntry(entry types.ReportEntry) {} +func (n NoopReporter) EmitSpecEvent(event types.SpecEvent) {} diff --git a/vendor/github.com/onsi/ginkgo/v2/reporters/teamcity_report.go b/vendor/github.com/onsi/ginkgo/v2/reporters/teamcity_report.go index f9b1117ca5..c1863496dc 100644 --- a/vendor/github.com/onsi/ginkgo/v2/reporters/teamcity_report.go +++ b/vendor/github.com/onsi/ginkgo/v2/reporters/teamcity_report.go @@ -60,20 +60,24 @@ func GenerateTeamcityReport(report types.Report, dst string) error { } fmt.Fprintf(f, "##teamcity[testIgnored name='%s' message='%s']\n", name, tcEscape(message)) case types.SpecStateFailed: - details := fmt.Sprintf("%s\n%s", spec.Failure.Location.String(), spec.Failure.Location.FullStackTrace) + details := failureDescriptionForUnstructuredReporters(spec) fmt.Fprintf(f, "##teamcity[testFailed name='%s' message='failed - %s' details='%s']\n", name, tcEscape(spec.Failure.Message), tcEscape(details)) case types.SpecStatePanicked: - details := fmt.Sprintf("%s\n%s", spec.Failure.Location.String(), spec.Failure.Location.FullStackTrace) + details := failureDescriptionForUnstructuredReporters(spec) fmt.Fprintf(f, "##teamcity[testFailed name='%s' message='panicked - %s' details='%s']\n", name, tcEscape(spec.Failure.ForwardedPanic), tcEscape(details)) + case types.SpecStateTimedout: + details := failureDescriptionForUnstructuredReporters(spec) + fmt.Fprintf(f, "##teamcity[testFailed name='%s' message='timedout - %s' details='%s']\n", name, tcEscape(spec.Failure.Message), tcEscape(details)) case types.SpecStateInterrupted: - fmt.Fprintf(f, "##teamcity[testFailed name='%s' message='interrupted' details='%s']\n", name, tcEscape(spec.Failure.Message)) + details := failureDescriptionForUnstructuredReporters(spec) + fmt.Fprintf(f, "##teamcity[testFailed name='%s' message='interrupted - %s' details='%s']\n", name, tcEscape(spec.Failure.Message), tcEscape(details)) case types.SpecStateAborted: - details := fmt.Sprintf("%s\n%s", spec.Failure.Location.String(), spec.Failure.Location.FullStackTrace) + details := failureDescriptionForUnstructuredReporters(spec) fmt.Fprintf(f, "##teamcity[testFailed name='%s' message='aborted - %s' details='%s']\n", name, tcEscape(spec.Failure.Message), tcEscape(details)) } - fmt.Fprintf(f, "##teamcity[testStdOut name='%s' out='%s']\n", name, tcEscape(systemOutForUnstructureReporters(spec))) - fmt.Fprintf(f, "##teamcity[testStdErr name='%s' out='%s']\n", name, tcEscape(spec.CapturedGinkgoWriterOutput)) + fmt.Fprintf(f, "##teamcity[testStdOut name='%s' out='%s']\n", name, tcEscape(systemOutForUnstructuredReporters(spec))) + fmt.Fprintf(f, "##teamcity[testStdErr name='%s' out='%s']\n", name, tcEscape(systemErrForUnstructuredReporters(spec))) fmt.Fprintf(f, "##teamcity[testFinished name='%s' duration='%d']\n", name, int(spec.RunTime.Seconds()*1000.0)) } fmt.Fprintf(f, "##teamcity[testSuiteFinished name='%s']\n", tcEscape(report.SuiteDescription)) diff --git a/vendor/github.com/onsi/ginkgo/v2/types/code_location.go b/vendor/github.com/onsi/ginkgo/v2/types/code_location.go index 1291091834..9cd5768170 100644 --- a/vendor/github.com/onsi/ginkgo/v2/types/code_location.go +++ b/vendor/github.com/onsi/ginkgo/v2/types/code_location.go @@ -7,6 +7,7 @@ import ( "runtime" "runtime/debug" "strings" + "sync" ) type CodeLocation struct { @@ -38,6 +39,73 @@ func (codeLocation CodeLocation) ContentsOfLine() string { return lines[codeLocation.LineNumber-1] } +type codeLocationLocator struct { + pcs map[uintptr]bool + helpers map[string]bool + lock *sync.Mutex +} + +func (c *codeLocationLocator) addHelper(pc uintptr) { + c.lock.Lock() + defer c.lock.Unlock() + + if c.pcs[pc] { + return + } + c.lock.Unlock() + f := runtime.FuncForPC(pc) + c.lock.Lock() + if f == nil { + return + } + c.helpers[f.Name()] = true + c.pcs[pc] = true +} + +func (c *codeLocationLocator) hasHelper(name string) bool { + c.lock.Lock() + defer c.lock.Unlock() + return c.helpers[name] +} + +func (c *codeLocationLocator) getCodeLocation(skip int) CodeLocation { + pc := make([]uintptr, 40) + n := runtime.Callers(skip+2, pc) + if n == 0 { + return CodeLocation{} + } + pc = pc[:n] + frames := runtime.CallersFrames(pc) + for { + frame, more := frames.Next() + if !c.hasHelper(frame.Function) { + return CodeLocation{FileName: frame.File, LineNumber: frame.Line} + } + if !more { + break + } + } + return CodeLocation{} +} + +var clLocator = &codeLocationLocator{ + pcs: map[uintptr]bool{}, + helpers: map[string]bool{}, + lock: &sync.Mutex{}, +} + +// MarkAsHelper is used by GinkgoHelper to mark the caller (appropriately offset by skip)as a helper. You can use this directly if you need to provide an optional `skip` to mark functions further up the call stack as helpers. +func MarkAsHelper(optionalSkip ...int) { + skip := 1 + if len(optionalSkip) > 0 { + skip += optionalSkip[0] + } + pc, _, _, ok := runtime.Caller(skip) + if ok { + clLocator.addHelper(pc) + } +} + func NewCustomCodeLocation(message string) CodeLocation { return CodeLocation{ CustomMessage: message, @@ -45,14 +113,13 @@ func NewCustomCodeLocation(message string) CodeLocation { } func NewCodeLocation(skip int) CodeLocation { - _, file, line, _ := runtime.Caller(skip + 1) - return CodeLocation{FileName: file, LineNumber: line} + return clLocator.getCodeLocation(skip + 1) } func NewCodeLocationWithStackTrace(skip int) CodeLocation { - _, file, line, _ := runtime.Caller(skip + 1) - stackTrace := PruneStack(string(debug.Stack()), skip+1) - return CodeLocation{FileName: file, LineNumber: line, FullStackTrace: stackTrace} + cl := clLocator.getCodeLocation(skip + 1) + cl.FullStackTrace = PruneStack(string(debug.Stack()), skip+1) + return cl } // PruneStack removes references to functions that are internal to Ginkgo diff --git a/vendor/github.com/onsi/ginkgo/v2/types/config.go b/vendor/github.com/onsi/ginkgo/v2/types/config.go index 07ef4c3a7f..1014c7b49f 100644 --- a/vendor/github.com/onsi/ginkgo/v2/types/config.go +++ b/vendor/github.com/onsi/ginkgo/v2/types/config.go @@ -8,6 +8,7 @@ package types import ( "flag" "os" + "path/filepath" "runtime" "strconv" "strings" @@ -26,10 +27,14 @@ type SuiteConfig struct { FailOnPending bool FailFast bool FlakeAttempts int - EmitSpecProgress bool DryRun bool + PollProgressAfter time.Duration + PollProgressInterval time.Duration Timeout time.Duration + EmitSpecProgress bool // this is deprecated but its removal is causing compile issue for some users that were setting it manually OutputInterceptorMode string + SourceRoots []string + GracePeriod time.Duration ParallelProcess int ParallelTotal int @@ -42,6 +47,7 @@ func NewDefaultSuiteConfig() SuiteConfig { Timeout: time.Hour, ParallelProcess: 1, ParallelTotal: 1, + GracePeriod: 30 * time.Second, } } @@ -76,13 +82,12 @@ func (vl VerbosityLevel) LT(comp VerbosityLevel) bool { // Configuration for Ginkgo's reporter type ReporterConfig struct { - NoColor bool - SlowSpecThreshold time.Duration - Succinct bool - Verbose bool - VeryVerbose bool - FullTrace bool - AlwaysEmitGinkgoWriter bool + NoColor bool + Succinct bool + Verbose bool + VeryVerbose bool + FullTrace bool + ShowNodeEvents bool JSONReport string JUnitReport string @@ -105,9 +110,7 @@ func (rc ReporterConfig) WillGenerateReport() bool { } func NewDefaultReporterConfig() ReporterConfig { - return ReporterConfig{ - SlowSpecThreshold: 5 * time.Second, - } + return ReporterConfig{} } // Configuration for the Ginkgo CLI @@ -230,6 +233,9 @@ type deprecatedConfig struct { SlowSpecThresholdWithFLoatUnits float64 Stream bool Notify bool + EmitSpecProgress bool + SlowSpecThreshold time.Duration + AlwaysEmitGinkgoWriter bool } // Flags @@ -270,10 +276,16 @@ var SuiteConfigFlags = GinkgoFlags{ {KeyPath: "S.DryRun", Name: "dry-run", SectionKey: "debug", DeprecatedName: "dryRun", DeprecatedDocLink: "changed-command-line-flags", Usage: "If set, ginkgo will walk the test hierarchy without actually running anything. Best paired with -v."}, - {KeyPath: "S.EmitSpecProgress", Name: "progress", SectionKey: "debug", - Usage: "If set, ginkgo will emit progress information as each spec runs to the GinkgoWriter."}, + {KeyPath: "S.PollProgressAfter", Name: "poll-progress-after", SectionKey: "debug", UsageDefaultValue: "0", + Usage: "Emit node progress reports periodically if node hasn't completed after this duration."}, + {KeyPath: "S.PollProgressInterval", Name: "poll-progress-interval", SectionKey: "debug", UsageDefaultValue: "10s", + Usage: "The rate at which to emit node progress reports after poll-progress-after has elapsed."}, + {KeyPath: "S.SourceRoots", Name: "source-root", SectionKey: "debug", + Usage: "The location to look for source code when generating progress reports. You can pass multiple --source-root flags."}, {KeyPath: "S.Timeout", Name: "timeout", SectionKey: "debug", UsageDefaultValue: "1h", Usage: "Test suite fails if it does not complete within the specified timeout."}, + {KeyPath: "S.GracePeriod", Name: "grace-period", SectionKey: "debug", UsageDefaultValue: "30s", + Usage: "When interrupted, Ginkgo will wait for GracePeriod for the current running node to exit before moving on to the next one."}, {KeyPath: "S.OutputInterceptorMode", Name: "output-interceptor-mode", SectionKey: "debug", UsageArgument: "dup, swap, or none", Usage: "If set, ginkgo will use the specified output interception strategy when running in parallel. Defaults to dup on unix and swap on windows."}, @@ -290,6 +302,8 @@ var SuiteConfigFlags = GinkgoFlags{ {KeyPath: "D.RegexScansFilePath", DeprecatedName: "regexScansFilePath", DeprecatedDocLink: "removed--regexscansfilepath", DeprecatedVersion: "2.0.0"}, {KeyPath: "D.DebugParallel", DeprecatedName: "debug", DeprecatedDocLink: "removed--debug", DeprecatedVersion: "2.0.0"}, + {KeyPath: "D.EmitSpecProgress", DeprecatedName: "progress", SectionKey: "debug", + DeprecatedVersion: "2.5.0", Usage: ". The functionality provided by --progress was confusing and is no longer needed. Use --show-node-events instead to see node entry and exit events included in the timeline of failed and verbose specs. Or you can run with -vv to always see all node events. Lastly, --poll-progress-after and the PollProgressAfter decorator now provide a better mechanism for debugging specs that tend to get stuck."}, } // ParallelConfigFlags provides flags for the Ginkgo test process (not the CLI) @@ -306,8 +320,6 @@ var ParallelConfigFlags = GinkgoFlags{ var ReporterConfigFlags = GinkgoFlags{ {KeyPath: "R.NoColor", Name: "no-color", SectionKey: "output", DeprecatedName: "noColor", DeprecatedDocLink: "changed-command-line-flags", Usage: "If set, suppress color output in default reporter."}, - {KeyPath: "R.SlowSpecThreshold", Name: "slow-spec-threshold", SectionKey: "output", UsageArgument: "duration", UsageDefaultValue: "5s", - Usage: "Specs that take longer to run than this threshold are flagged as slow by the default reporter."}, {KeyPath: "R.Verbose", Name: "v", SectionKey: "output", Usage: "If set, emits more output including GinkgoWriter contents."}, {KeyPath: "R.VeryVerbose", Name: "vv", SectionKey: "output", @@ -316,8 +328,8 @@ var ReporterConfigFlags = GinkgoFlags{ Usage: "If set, default reporter prints out a very succinct report"}, {KeyPath: "R.FullTrace", Name: "trace", SectionKey: "output", Usage: "If set, default reporter prints out the full stack trace when a failure occurs"}, - {KeyPath: "R.AlwaysEmitGinkgoWriter", Name: "always-emit-ginkgo-writer", SectionKey: "output", DeprecatedName: "reportPassed", DeprecatedDocLink: "renamed--reportpassed", - Usage: "If set, default reporter prints out captured output of passed tests."}, + {KeyPath: "R.ShowNodeEvents", Name: "show-node-events", SectionKey: "output", + Usage: "If set, default reporter prints node > Enter and < Exit events when specs fail"}, {KeyPath: "R.JSONReport", Name: "json-report", UsageArgument: "filename.json", SectionKey: "output", Usage: "If set, Ginkgo will generate a JSON-formatted test report at the specified location."}, @@ -330,6 +342,8 @@ var ReporterConfigFlags = GinkgoFlags{ Usage: "use --slow-spec-threshold instead and pass in a duration string (e.g. '5s', not '5.0')"}, {KeyPath: "D.NoisyPendings", DeprecatedName: "noisyPendings", DeprecatedDocLink: "removed--noisypendings-and--noisyskippings", DeprecatedVersion: "2.0.0"}, {KeyPath: "D.NoisySkippings", DeprecatedName: "noisySkippings", DeprecatedDocLink: "removed--noisypendings-and--noisyskippings", DeprecatedVersion: "2.0.0"}, + {KeyPath: "D.SlowSpecThreshold", DeprecatedName: "slow-spec-threshold", SectionKey: "output", Usage: "--slow-spec-threshold has been deprecated and will be removed in a future version of Ginkgo. This feature has proved to be more noisy than useful. You can use --poll-progress-after, instead, to get more actionable feedback about potentially slow specs and understand where they might be getting stuck.", DeprecatedVersion: "2.5.0"}, + {KeyPath: "D.AlwaysEmitGinkgoWriter", DeprecatedName: "always-emit-ginkgo-writer", SectionKey: "output", Usage: " - use -v instead, or one of Ginkgo's machine-readable report formats to get GinkgoWriter output for passing specs."}, } // BuildTestSuiteFlagSet attaches to the CommandLine flagset and provides flags for the Ginkgo test process @@ -381,6 +395,10 @@ func VetConfig(flagSet GinkgoFlagSet, suiteConfig SuiteConfig, reporterConfig Re errors = append(errors, GinkgoErrors.DryRunInParallelConfiguration()) } + if suiteConfig.GracePeriod <= 0 { + errors = append(errors, GinkgoErrors.GracePeriodCannotBeZero()) + } + if len(suiteConfig.FocusFiles) > 0 { _, err := ParseFileFilters(suiteConfig.FocusFiles) if err != nil { @@ -583,13 +601,29 @@ func VetAndInitializeCLIAndGoConfig(cliConfig CLIConfig, goFlagsConfig GoFlagsCo } // GenerateGoTestCompileArgs is used by the Ginkgo CLI to generate command line arguments to pass to the go test -c command when compiling the test -func GenerateGoTestCompileArgs(goFlagsConfig GoFlagsConfig, destination string, packageToBuild string) ([]string, error) { +func GenerateGoTestCompileArgs(goFlagsConfig GoFlagsConfig, destination string, packageToBuild string, pathToInvocationPath string) ([]string, error) { // if the user has set the CoverProfile run-time flag make sure to set the build-time cover flag to make sure // the built test binary can generate a coverprofile if goFlagsConfig.CoverProfile != "" { goFlagsConfig.Cover = true } + if goFlagsConfig.CoverPkg != "" { + coverPkgs := strings.Split(goFlagsConfig.CoverPkg, ",") + adjustedCoverPkgs := make([]string, len(coverPkgs)) + for i, coverPkg := range coverPkgs { + coverPkg = strings.Trim(coverPkg, " ") + if strings.HasPrefix(coverPkg, "./") { + // this is a relative coverPkg - we need to reroot it + adjustedCoverPkgs[i] = "./" + filepath.Join(pathToInvocationPath, strings.TrimPrefix(coverPkg, "./")) + } else { + // this is a package name - don't touch it + adjustedCoverPkgs[i] = coverPkg + } + } + goFlagsConfig.CoverPkg = strings.Join(adjustedCoverPkgs, ",") + } + args := []string{"test", "-c", "-o", destination, packageToBuild} goArgs, err := GenerateFlagArgs( GoBuildFlags, diff --git a/vendor/github.com/onsi/ginkgo/v2/types/deprecation_support.go b/vendor/github.com/onsi/ginkgo/v2/types/deprecation_support.go index 2948dfa0c9..e2519f673f 100644 --- a/vendor/github.com/onsi/ginkgo/v2/types/deprecation_support.go +++ b/vendor/github.com/onsi/ginkgo/v2/types/deprecation_support.go @@ -38,7 +38,7 @@ func (d deprecations) Async() Deprecation { func (d deprecations) Measure() Deprecation { return Deprecation{ - Message: "Measure is deprecated and will be removed in Ginkgo V2. Please migrate to gomega/gmeasure.", + Message: "Measure is deprecated and has been removed from Ginkgo V2. Any Measure tests in your spec will not run. Please migrate to gomega/gmeasure.", DocLink: "removed-measure", Version: "1.16.3", } @@ -83,6 +83,13 @@ func (d deprecations) Nodot() Deprecation { } } +func (d deprecations) SuppressProgressReporting() Deprecation { + return Deprecation{ + Message: "Improvements to how reporters emit timeline information means that SuppressProgressReporting is no longer necessary and has been deprecated.", + Version: "2.5.0", + } +} + type DeprecationTracker struct { deprecations map[Deprecation][]CodeLocation lock *sync.Mutex diff --git a/vendor/github.com/onsi/ginkgo/v2/types/errors.go b/vendor/github.com/onsi/ginkgo/v2/types/errors.go index 40331d2982..1e0dbfd9df 100644 --- a/vendor/github.com/onsi/ginkgo/v2/types/errors.go +++ b/vendor/github.com/onsi/ginkgo/v2/types/errors.go @@ -108,8 +108,8 @@ Please ensure all assertions are inside leaf nodes such as {{bold}}BeforeEach{{/ func (g ginkgoErrors) SuiteNodeInNestedContext(nodeType NodeType, cl CodeLocation) error { docLink := "suite-setup-and-cleanup-beforesuite-and-aftersuite" - if nodeType.Is(NodeTypeReportAfterSuite) { - docLink = "reporting-nodes---reportaftersuite" + if nodeType.Is(NodeTypeReportBeforeSuite | NodeTypeReportAfterSuite) { + docLink = "reporting-nodes---reportbeforesuite-and-reportaftersuite" } return GinkgoError{ @@ -125,8 +125,8 @@ func (g ginkgoErrors) SuiteNodeInNestedContext(nodeType NodeType, cl CodeLocatio func (g ginkgoErrors) SuiteNodeDuringRunPhase(nodeType NodeType, cl CodeLocation) error { docLink := "suite-setup-and-cleanup-beforesuite-and-aftersuite" - if nodeType.Is(NodeTypeReportAfterSuite) { - docLink = "reporting-nodes---reportaftersuite" + if nodeType.Is(NodeTypeReportBeforeSuite | NodeTypeReportAfterSuite) { + docLink = "reporting-nodes---reportbeforesuite-and-reportaftersuite" } return GinkgoError{ @@ -180,6 +180,15 @@ func (g ginkgoErrors) InvalidDeclarationOfFocusedAndPending(cl CodeLocation, nod } } +func (g ginkgoErrors) InvalidDeclarationOfFlakeAttemptsAndMustPassRepeatedly(cl CodeLocation, nodeType NodeType) error { + return GinkgoError{ + Heading: "Invalid Combination of Decorators: FlakeAttempts and MustPassRepeatedly", + Message: formatter.F(`[%s] node was decorated with both FlakeAttempts and MustPassRepeatedly. At most one is allowed.`, nodeType), + CodeLocation: cl, + DocLink: "node-decorators-overview", + } +} + func (g ginkgoErrors) UnknownDecorator(cl CodeLocation, nodeType NodeType, decorator interface{}) error { return GinkgoError{ Heading: "Unknown Decorator", @@ -189,20 +198,55 @@ func (g ginkgoErrors) UnknownDecorator(cl CodeLocation, nodeType NodeType, decor } } +func (g ginkgoErrors) InvalidBodyTypeForContainer(t reflect.Type, cl CodeLocation, nodeType NodeType) error { + return GinkgoError{ + Heading: "Invalid Function", + Message: formatter.F(`[%s] node must be passed {{bold}}func(){{/}} - i.e. functions that take nothing and return nothing. You passed {{bold}}%s{{/}} instead.`, nodeType, t), + CodeLocation: cl, + DocLink: "node-decorators-overview", + } +} + func (g ginkgoErrors) InvalidBodyType(t reflect.Type, cl CodeLocation, nodeType NodeType) error { + mustGet := "{{bold}}func(){{/}}, {{bold}}func(ctx SpecContext){{/}}, or {{bold}}func(ctx context.Context){{/}}" + if nodeType.Is(NodeTypeContainer) { + mustGet = "{{bold}}func(){{/}}" + } return GinkgoError{ Heading: "Invalid Function", - Message: formatter.F(`[%s] node must be passed {{bold}}func(){{/}} - i.e. functions that take nothing and return nothing. + Message: formatter.F(`[%s] node must be passed `+mustGet+`. You passed {{bold}}%s{{/}} instead.`, nodeType, t), CodeLocation: cl, DocLink: "node-decorators-overview", } } +func (g ginkgoErrors) InvalidBodyTypeForSynchronizedBeforeSuiteProc1(t reflect.Type, cl CodeLocation) error { + mustGet := "{{bold}}func() []byte{{/}}, {{bold}}func(ctx SpecContext) []byte{{/}}, or {{bold}}func(ctx context.Context) []byte{{/}}, {{bold}}func(){{/}}, {{bold}}func(ctx SpecContext){{/}}, or {{bold}}func(ctx context.Context){{/}}" + return GinkgoError{ + Heading: "Invalid Function", + Message: formatter.F(`[SynchronizedBeforeSuite] node must be passed `+mustGet+` for its first function. +You passed {{bold}}%s{{/}} instead.`, t), + CodeLocation: cl, + DocLink: "node-decorators-overview", + } +} + +func (g ginkgoErrors) InvalidBodyTypeForSynchronizedBeforeSuiteAllProcs(t reflect.Type, cl CodeLocation) error { + mustGet := "{{bold}}func(){{/}}, {{bold}}func(ctx SpecContext){{/}}, or {{bold}}func(ctx context.Context){{/}}, {{bold}}func([]byte){{/}}, {{bold}}func(ctx SpecContext, []byte){{/}}, or {{bold}}func(ctx context.Context, []byte){{/}}" + return GinkgoError{ + Heading: "Invalid Function", + Message: formatter.F(`[SynchronizedBeforeSuite] node must be passed `+mustGet+` for its second function. +You passed {{bold}}%s{{/}} instead.`, t), + CodeLocation: cl, + DocLink: "node-decorators-overview", + } +} + func (g ginkgoErrors) MultipleBodyFunctions(cl CodeLocation, nodeType NodeType) error { return GinkgoError{ Heading: "Multiple Functions", - Message: formatter.F(`[%s] node must be passed a single {{bold}}func(){{/}} - but more than one was passed in.`, nodeType), + Message: formatter.F(`[%s] node must be passed a single function - but more than one was passed in.`, nodeType), CodeLocation: cl, DocLink: "node-decorators-overview", } @@ -211,12 +255,30 @@ func (g ginkgoErrors) MultipleBodyFunctions(cl CodeLocation, nodeType NodeType) func (g ginkgoErrors) MissingBodyFunction(cl CodeLocation, nodeType NodeType) error { return GinkgoError{ Heading: "Missing Functions", - Message: formatter.F(`[%s] node must be passed a single {{bold}}func(){{/}} - but none was passed in.`, nodeType), + Message: formatter.F(`[%s] node must be passed a single function - but none was passed in.`, nodeType), CodeLocation: cl, DocLink: "node-decorators-overview", } } +func (g ginkgoErrors) InvalidTimeoutOrGracePeriodForNonContextNode(cl CodeLocation, nodeType NodeType) error { + return GinkgoError{ + Heading: "Invalid NodeTimeout SpecTimeout, or GracePeriod", + Message: formatter.F(`[%s] was passed NodeTimeout, SpecTimeout, or GracePeriod but does not have a callback that accepts a {{bold}}SpecContext{{/}} or {{bold}}context.Context{{/}}. You must accept a context to enable timeouts and grace periods`, nodeType), + CodeLocation: cl, + DocLink: "spec-timeouts-and-interruptible-nodes", + } +} + +func (g ginkgoErrors) InvalidTimeoutOrGracePeriodForNonContextCleanupNode(cl CodeLocation) error { + return GinkgoError{ + Heading: "Invalid NodeTimeout SpecTimeout, or GracePeriod", + Message: formatter.F(`[DeferCleanup] was passed NodeTimeout or GracePeriod but does not have a callback that accepts a {{bold}}SpecContext{{/}} or {{bold}}context.Context{{/}}. You must accept a context to enable timeouts and grace periods`), + CodeLocation: cl, + DocLink: "spec-timeouts-and-interruptible-nodes", + } +} + /* Ordered Container errors */ func (g ginkgoErrors) InvalidSerialNodeInNonSerialOrderedContainer(cl CodeLocation, nodeType NodeType) error { return GinkgoError{ @@ -236,6 +298,15 @@ func (g ginkgoErrors) SetupNodeNotInOrderedContainer(cl CodeLocation, nodeType N } } +func (g ginkgoErrors) InvalidContinueOnFailureDecoration(cl CodeLocation) error { + return GinkgoError{ + Heading: "ContinueOnFailure not decorating an outermost Ordered Container", + Message: "ContinueOnFailure can only decorate an Ordered container, and this Ordered container must be the outermost Ordered container.", + CodeLocation: cl, + DocLink: "ordered-containers", + } +} + /* DeferCleanup errors */ func (g ginkgoErrors) DeferCleanupInvalidFunction(cl CodeLocation) error { return GinkgoError{ @@ -258,7 +329,7 @@ func (g ginkgoErrors) PushingCleanupNodeDuringTreeConstruction(cl CodeLocation) func (g ginkgoErrors) PushingCleanupInReportingNode(cl CodeLocation, nodeType NodeType) error { return GinkgoError{ Heading: fmt.Sprintf("DeferCleanup cannot be called in %s", nodeType), - Message: "Please inline your cleanup code - Ginkgo won't run cleanup code after a ReportAfterEach or ReportAfterSuite.", + Message: "Please inline your cleanup code - Ginkgo won't run cleanup code after a Reporting node.", CodeLocation: cl, DocLink: "cleaning-up-our-cleanup-code-defercleanup", } @@ -380,6 +451,15 @@ func (g ginkgoErrors) InvalidEntryDescription(cl CodeLocation) error { } } +func (g ginkgoErrors) MissingParametersForTableFunction(cl CodeLocation) error { + return GinkgoError{ + Heading: fmt.Sprintf("No parameters have been passed to the Table Function"), + Message: fmt.Sprintf("The Table Function expected at least 1 parameter"), + CodeLocation: cl, + DocLink: "table-specs", + } +} + func (g ginkgoErrors) IncorrectParameterTypeForTable(i int, name string, cl CodeLocation) error { return GinkgoError{ Heading: "DescribeTable passed incorrect parameter type", @@ -498,6 +578,13 @@ func (g ginkgoErrors) DryRunInParallelConfiguration() error { } } +func (g ginkgoErrors) GracePeriodCannotBeZero() error { + return GinkgoError{ + Heading: "Ginkgo requires a positive --grace-period.", + Message: "Please set --grace-period to a positive duration. The default is 30s.", + } +} + func (g ginkgoErrors) ConflictingVerbosityConfiguration() error { return GinkgoError{ Heading: "Conflicting reporter verbosity settings.", @@ -532,3 +619,12 @@ func (g ginkgoErrors) BothRepeatAndUntilItFails() error { Message: "--until-it-fails directs Ginkgo to rerun specs indefinitely until they fail. --repeat directs Ginkgo to rerun specs a set number of times. You can't set both... which would you like?", } } + +/* Stack-Trace parsing errors */ + +func (g ginkgoErrors) FailedToParseStackTrace(message string) error { + return GinkgoError{ + Heading: "Failed to Parse Stack Trace", + Message: message, + } +} diff --git a/vendor/github.com/onsi/ginkgo/v2/types/label_filter.go b/vendor/github.com/onsi/ginkgo/v2/types/label_filter.go index 0403f9e631..b0d3b651e7 100644 --- a/vendor/github.com/onsi/ginkgo/v2/types/label_filter.go +++ b/vendor/github.com/onsi/ginkgo/v2/types/label_filter.go @@ -272,12 +272,23 @@ func tokenize(input string) func() (*treeNode, error) { } } +func MustParseLabelFilter(input string) LabelFilter { + filter, err := ParseLabelFilter(input) + if err != nil { + panic(err) + } + return filter +} + func ParseLabelFilter(input string) (LabelFilter, error) { if DEBUG_LABEL_FILTER_PARSING { fmt.Println("\n==============") fmt.Println("Input: ", input) fmt.Print("Tokens: ") } + if input == "" { + return func(_ []string) bool { return true }, nil + } nextToken := tokenize(input) root := &treeNode{token: lfTokenRoot} diff --git a/vendor/github.com/onsi/ginkgo/v2/types/report_entry.go b/vendor/github.com/onsi/ginkgo/v2/types/report_entry.go index c64866c602..7b1524b52e 100644 --- a/vendor/github.com/onsi/ginkgo/v2/types/report_entry.go +++ b/vendor/github.com/onsi/ginkgo/v2/types/report_entry.go @@ -6,8 +6,8 @@ import ( "time" ) -//ReportEntryValue wraps a report entry's value ensuring it can be encoded and decoded safely into reports -//and across the network connection when running in parallel +// ReportEntryValue wraps a report entry's value ensuring it can be encoded and decoded safely into reports +// and across the network connection when running in parallel type ReportEntryValue struct { raw interface{} //unexported to prevent gob from freaking out about unregistered structs AsJSON string @@ -50,7 +50,6 @@ func (rev ReportEntryValue) MarshalJSON() ([]byte, error) { }{ Representation: rev.String(), } - asJSON, err := json.Marshal(rev.raw) if err != nil { return nil, err @@ -86,10 +85,12 @@ func (rev *ReportEntryValue) GobDecode(data []byte) error { type ReportEntry struct { // Visibility captures the visibility policy for this ReportEntry Visibility ReportEntryVisibility - // Time captures the time the AddReportEntry was called - Time time.Time // Location captures the location of the AddReportEntry call Location CodeLocation + + Time time.Time //need this for backwards compatibility + TimelineLocation TimelineLocation + // Name captures the name of this report Name string // Value captures the (optional) object passed into AddReportEntry - this can be @@ -98,7 +99,7 @@ type ReportEntry struct { Value ReportEntryValue } -// ColorableStringer is an interface that ReportEntry values can satisfy. If they do then ColorableStirng() is used to generate their representation. +// ColorableStringer is an interface that ReportEntry values can satisfy. If they do then ColorableString() is used to generate their representation. type ColorableStringer interface { ColorableString() string } @@ -121,6 +122,10 @@ func (entry ReportEntry) GetRawValue() interface{} { return entry.Value.GetRawValue() } +func (entry ReportEntry) GetTimelineLocation() TimelineLocation { + return entry.TimelineLocation +} + type ReportEntries []ReportEntry func (re ReportEntries) HasVisibility(visibilities ...ReportEntryVisibility) bool { diff --git a/vendor/github.com/onsi/ginkgo/v2/types/types.go b/vendor/github.com/onsi/ginkgo/v2/types/types.go index f30d23c667..d048a8adab 100644 --- a/vendor/github.com/onsi/ginkgo/v2/types/types.go +++ b/vendor/github.com/onsi/ginkgo/v2/types/types.go @@ -2,6 +2,8 @@ package types import ( "encoding/json" + "fmt" + "sort" "strings" "time" ) @@ -56,19 +58,20 @@ type Report struct { SuiteConfig SuiteConfig //SpecReports is a list of all SpecReports generated by this test run + //It is empty when the SuiteReport is provided to ReportBeforeSuite SpecReports SpecReports } -//PreRunStats contains a set of stats captured before the test run begins. This is primarily used -//by Ginkgo's reporter to tell the user how many specs are in the current suite (PreRunStats.TotalSpecs) -//and how many it intends to run (PreRunStats.SpecsThatWillRun) after applying any relevant focus or skip filters. +// PreRunStats contains a set of stats captured before the test run begins. This is primarily used +// by Ginkgo's reporter to tell the user how many specs are in the current suite (PreRunStats.TotalSpecs) +// and how many it intends to run (PreRunStats.SpecsThatWillRun) after applying any relevant focus or skip filters. type PreRunStats struct { TotalSpecs int SpecsThatWillRun int } -//Add is ued by Ginkgo's parallel aggregation mechanisms to combine test run reports form individual parallel processes -//to form a complete final report. +// Add is used by Ginkgo's parallel aggregation mechanisms to combine test run reports form individual parallel processes +// to form a complete final report. func (report Report) Add(other Report) Report { report.SuiteSucceeded = report.SuiteSucceeded && other.SuiteSucceeded @@ -147,14 +150,24 @@ type SpecReport struct { // ParallelProcess captures the parallel process that this spec ran on ParallelProcess int + // RunningInParallel captures whether this spec is part of a suite that ran in parallel + RunningInParallel bool + //Failure is populated if a spec has failed, panicked, been interrupted, or skipped by the user (e.g. calling Skip()) //It includes detailed information about the Failure Failure Failure - // NumAttempts captures the number of times this Spec was run. Flakey specs can be retried with - // ginkgo --flake-attempts=N + // NumAttempts captures the number of times this Spec was run. + // Flakey specs can be retried with ginkgo --flake-attempts=N or the use of the FlakeAttempts decorator. + // Repeated specs can be retried with the use of the MustPassRepeatedly decorator NumAttempts int + // MaxFlakeAttempts captures whether the spec has been retried with ginkgo --flake-attempts=N or the use of the FlakeAttempts decorator. + MaxFlakeAttempts int + + // MaxMustPassRepeatedly captures whether the spec has the MustPassRepeatedly decorator + MaxMustPassRepeatedly int + // CapturedGinkgoWriterOutput contains text printed to the GinkgoWriter CapturedGinkgoWriterOutput string @@ -165,6 +178,15 @@ type SpecReport struct { // ReportEntries contains any reports added via `AddReportEntry` ReportEntries ReportEntries + + // ProgressReports contains any progress reports generated during this spec. These can either be manually triggered, or automatically generated by Ginkgo via the PollProgressAfter() decorator + ProgressReports []ProgressReport + + // AdditionalFailures contains any failures that occurred after the initial spec failure. These typically occur in cleanup nodes after the initial failure and are only emitted when running in verbose mode. + AdditionalFailures []AdditionalFailure + + // SpecEvents capture additional events that occur during the spec run + SpecEvents SpecEvents } func (report SpecReport) MarshalJSON() ([]byte, error) { @@ -184,9 +206,14 @@ func (report SpecReport) MarshalJSON() ([]byte, error) { ParallelProcess int Failure *Failure `json:",omitempty"` NumAttempts int - CapturedGinkgoWriterOutput string `json:",omitempty"` - CapturedStdOutErr string `json:",omitempty"` - ReportEntries ReportEntries `json:",omitempty"` + MaxFlakeAttempts int + MaxMustPassRepeatedly int + CapturedGinkgoWriterOutput string `json:",omitempty"` + CapturedStdOutErr string `json:",omitempty"` + ReportEntries ReportEntries `json:",omitempty"` + ProgressReports []ProgressReport `json:",omitempty"` + AdditionalFailures []AdditionalFailure `json:",omitempty"` + SpecEvents SpecEvents `json:",omitempty"` }{ ContainerHierarchyTexts: report.ContainerHierarchyTexts, ContainerHierarchyLocations: report.ContainerHierarchyLocations, @@ -203,6 +230,8 @@ func (report SpecReport) MarshalJSON() ([]byte, error) { Failure: nil, ReportEntries: nil, NumAttempts: report.NumAttempts, + MaxFlakeAttempts: report.MaxFlakeAttempts, + MaxMustPassRepeatedly: report.MaxMustPassRepeatedly, CapturedGinkgoWriterOutput: report.CapturedGinkgoWriterOutput, CapturedStdOutErr: report.CapturedStdOutErr, } @@ -213,6 +242,15 @@ func (report SpecReport) MarshalJSON() ([]byte, error) { if len(report.ReportEntries) > 0 { out.ReportEntries = report.ReportEntries } + if len(report.ProgressReports) > 0 { + out.ProgressReports = report.ProgressReports + } + if len(report.AdditionalFailures) > 0 { + out.AdditionalFailures = report.AdditionalFailures + } + if len(report.SpecEvents) > 0 { + out.SpecEvents = report.SpecEvents + } return json.Marshal(out) } @@ -230,13 +268,13 @@ func (report SpecReport) CombinedOutput() string { return report.CapturedStdOutErr + "\n" + report.CapturedGinkgoWriterOutput } -//Failed returns true if report.State is one of the SpecStateFailureStates +// Failed returns true if report.State is one of the SpecStateFailureStates // (SpecStateFailed, SpecStatePanicked, SpecStateinterrupted, SpecStateAborted) func (report SpecReport) Failed() bool { return report.State.Is(SpecStateFailureStates) } -//FullText returns a concatenation of all the report.ContainerHierarchyTexts and report.LeafNodeText +// FullText returns a concatenation of all the report.ContainerHierarchyTexts and report.LeafNodeText func (report SpecReport) FullText() string { texts := []string{} texts = append(texts, report.ContainerHierarchyTexts...) @@ -246,7 +284,7 @@ func (report SpecReport) FullText() string { return strings.Join(texts, " ") } -//Labels returns a deduped set of all the spec's Labels. +// Labels returns a deduped set of all the spec's Labels. func (report SpecReport) Labels() []string { out := []string{} seen := map[string]bool{} @@ -268,7 +306,7 @@ func (report SpecReport) Labels() []string { return out } -//MatchesLabelFilter returns true if the spec satisfies the passed in label filter query +// MatchesLabelFilter returns true if the spec satisfies the passed in label filter query func (report SpecReport) MatchesLabelFilter(query string) (bool, error) { filter, err := ParseLabelFilter(query) if err != nil { @@ -277,29 +315,54 @@ func (report SpecReport) MatchesLabelFilter(query string) (bool, error) { return filter(report.Labels()), nil } -//FileName() returns the name of the file containing the spec +// FileName() returns the name of the file containing the spec func (report SpecReport) FileName() string { return report.LeafNodeLocation.FileName } -//LineNumber() returns the line number of the leaf node +// LineNumber() returns the line number of the leaf node func (report SpecReport) LineNumber() int { return report.LeafNodeLocation.LineNumber } -//FailureMessage() returns the failure message (or empty string if the test hasn't failed) +// FailureMessage() returns the failure message (or empty string if the test hasn't failed) func (report SpecReport) FailureMessage() string { return report.Failure.Message } -//FailureLocation() returns the location of the failure (or an empty CodeLocation if the test hasn't failed) +// FailureLocation() returns the location of the failure (or an empty CodeLocation if the test hasn't failed) func (report SpecReport) FailureLocation() CodeLocation { return report.Failure.Location } +// Timeline() returns a timeline view of the report +func (report SpecReport) Timeline() Timeline { + timeline := Timeline{} + if !report.Failure.IsZero() { + timeline = append(timeline, report.Failure) + if report.Failure.AdditionalFailure != nil { + timeline = append(timeline, *(report.Failure.AdditionalFailure)) + } + } + for _, additionalFailure := range report.AdditionalFailures { + timeline = append(timeline, additionalFailure) + } + for _, reportEntry := range report.ReportEntries { + timeline = append(timeline, reportEntry) + } + for _, progressReport := range report.ProgressReports { + timeline = append(timeline, progressReport) + } + for _, specEvent := range report.SpecEvents { + timeline = append(timeline, specEvent) + } + sort.Sort(timeline) + return timeline +} + type SpecReports []SpecReport -//WithLeafNodeType returns the subset of SpecReports with LeafNodeType matching one of the requested NodeTypes +// WithLeafNodeType returns the subset of SpecReports with LeafNodeType matching one of the requested NodeTypes func (reports SpecReports) WithLeafNodeType(nodeTypes NodeType) SpecReports { count := 0 for i := range reports { @@ -319,7 +382,7 @@ func (reports SpecReports) WithLeafNodeType(nodeTypes NodeType) SpecReports { return out } -//WithState returns the subset of SpecReports with State matching one of the requested SpecStates +// WithState returns the subset of SpecReports with State matching one of the requested SpecStates func (reports SpecReports) WithState(states SpecState) SpecReports { count := 0 for i := range reports { @@ -338,7 +401,7 @@ func (reports SpecReports) WithState(states SpecState) SpecReports { return out } -//CountWithState returns the number of SpecReports with State matching one of the requested SpecStates +// CountWithState returns the number of SpecReports with State matching one of the requested SpecStates func (reports SpecReports) CountWithState(states SpecState) int { n := 0 for i := range reports { @@ -349,17 +412,75 @@ func (reports SpecReports) CountWithState(states SpecState) int { return n } -//CountWithState returns the number of SpecReports that passed after multiple attempts +// If the Spec passes, CountOfFlakedSpecs returns the number of SpecReports that failed after multiple attempts. func (reports SpecReports) CountOfFlakedSpecs() int { n := 0 for i := range reports { - if reports[i].State.Is(SpecStatePassed) && reports[i].NumAttempts > 1 { + if reports[i].MaxFlakeAttempts > 1 && reports[i].State.Is(SpecStatePassed) && reports[i].NumAttempts > 1 { n += 1 } } return n } +// If the Spec fails, CountOfRepeatedSpecs returns the number of SpecReports that passed after multiple attempts +func (reports SpecReports) CountOfRepeatedSpecs() int { + n := 0 + for i := range reports { + if reports[i].MaxMustPassRepeatedly > 1 && reports[i].State.Is(SpecStateFailureStates) && reports[i].NumAttempts > 1 { + n += 1 + } + } + return n +} + +// TimelineLocation captures the location of an event in the spec's timeline +type TimelineLocation struct { + //Offset is the offset (in bytes) of the event relative to the GinkgoWriter stream + Offset int `json:",omitempty"` + + //Order is the order of the event with respect to other events. The absolute value of Order + //is irrelevant. All that matters is that an event with a lower Order occurs before ane vent with a higher Order + Order int `json:",omitempty"` + + Time time.Time +} + +// TimelineEvent represent an event on the timeline +// consumers of Timeline will need to check the concrete type of each entry to determine how to handle it +type TimelineEvent interface { + GetTimelineLocation() TimelineLocation +} + +type Timeline []TimelineEvent + +func (t Timeline) Len() int { return len(t) } +func (t Timeline) Less(i, j int) bool { + return t[i].GetTimelineLocation().Order < t[j].GetTimelineLocation().Order +} +func (t Timeline) Swap(i, j int) { t[i], t[j] = t[j], t[i] } +func (t Timeline) WithoutHiddenReportEntries() Timeline { + out := Timeline{} + for _, event := range t { + if reportEntry, isReportEntry := event.(ReportEntry); isReportEntry && reportEntry.Visibility == ReportEntryVisibilityNever { + continue + } + out = append(out, event) + } + return out +} + +func (t Timeline) WithoutVeryVerboseSpecEvents() Timeline { + out := Timeline{} + for _, event := range t { + if specEvent, isSpecEvent := event.(SpecEvent); isSpecEvent && specEvent.IsOnlyVisibleAtVeryVerbose() { + continue + } + out = append(out, event) + } + return out +} + // Failure captures failure information for an individual test type Failure struct { // Message - the failure message passed into Fail(...). When using a matcher library @@ -372,6 +493,8 @@ type Failure struct { // This CodeLocation will include a fully-populated StackTrace Location CodeLocation + TimelineLocation TimelineLocation + // ForwardedPanic - if the failure represents a captured panic (i.e. Summary.State == SpecStatePanicked) // then ForwardedPanic will be populated with a string representation of the captured panic. ForwardedPanic string `json:",omitempty"` @@ -379,19 +502,32 @@ type Failure struct { // FailureNodeContext - one of three contexts describing the node in which the failure occurred: // FailureNodeIsLeafNode means the failure occurred in the leaf node of the associated SpecReport. None of the other FailureNode fields will be populated // FailureNodeAtTopLevel means the failure occurred in a non-leaf node that is defined at the top-level of the spec (i.e. not in a container). FailureNodeType and FailureNodeLocation will be populated. - // FailureNodeInContainer means the failure occurred in a non-leaf node that is defined within a container. FailureNodeType, FailureNodeLocaiton, and FailureNodeContainerIndex will be populated. + // FailureNodeInContainer means the failure occurred in a non-leaf node that is defined within a container. FailureNodeType, FailureNodeLocation, and FailureNodeContainerIndex will be populated. // // FailureNodeType will contain the NodeType of the node in which the failure occurred. // FailureNodeLocation will contain the CodeLocation of the node in which the failure occurred. // If populated, FailureNodeContainerIndex will be the index into SpecReport.ContainerHierarchyTexts and SpecReport.ContainerHierarchyLocations that represents the parent container of the node in which the failure occurred. - FailureNodeContext FailureNodeContext - FailureNodeType NodeType - FailureNodeLocation CodeLocation - FailureNodeContainerIndex int + FailureNodeContext FailureNodeContext `json:",omitempty"` + + FailureNodeType NodeType `json:",omitempty"` + + FailureNodeLocation CodeLocation `json:",omitempty"` + + FailureNodeContainerIndex int `json:",omitempty"` + + //ProgressReport is populated if the spec was interrupted or timed out + ProgressReport ProgressReport `json:",omitempty"` + + //AdditionalFailure is non-nil if a follow-on failure occurred within the same node after the primary failure. This only happens when a node has timed out or been interrupted. In such cases the AdditionalFailure can include information about where/why the spec was stuck. + AdditionalFailure *AdditionalFailure `json:",omitempty"` } func (f Failure) IsZero() bool { - return f == Failure{} + return f.Message == "" && (f.Location == CodeLocation{}) +} + +func (f Failure) GetTimelineLocation() TimelineLocation { + return f.TimelineLocation } // FailureNodeContext captures the location context for the node containing the failing line of code @@ -424,6 +560,18 @@ func (fnc FailureNodeContext) MarshalJSON() ([]byte, error) { return fncEnumSupport.MarshJSON(uint(fnc)) } +// AdditionalFailure capturs any additional failures that occur after the initial failure of a psec +// these typically occur in clean up nodes after the spec has failed. +// We can't simply use Failure as we want to track the SpecState to know what kind of failure this is +type AdditionalFailure struct { + State SpecState + Failure Failure +} + +func (f AdditionalFailure) GetTimelineLocation() TimelineLocation { + return f.Failure.TimelineLocation +} + // SpecState captures the state of a spec // To determine if a given `state` represents a failure state, use `state.Is(SpecStateFailureStates)` type SpecState uint @@ -438,6 +586,7 @@ const ( SpecStateAborted SpecStatePanicked SpecStateInterrupted + SpecStateTimedout ) var ssEnumSupport = NewEnumSupport(map[uint]string{ @@ -449,11 +598,15 @@ var ssEnumSupport = NewEnumSupport(map[uint]string{ uint(SpecStateAborted): "aborted", uint(SpecStatePanicked): "panicked", uint(SpecStateInterrupted): "interrupted", + uint(SpecStateTimedout): "timedout", }) func (ss SpecState) String() string { return ssEnumSupport.String(uint(ss)) } +func (ss SpecState) GomegaString() string { + return ssEnumSupport.String(uint(ss)) +} func (ss *SpecState) UnmarshalJSON(b []byte) error { out, err := ssEnumSupport.UnmarshJSON(b) *ss = SpecState(out) @@ -463,12 +616,131 @@ func (ss SpecState) MarshalJSON() ([]byte, error) { return ssEnumSupport.MarshJSON(uint(ss)) } -var SpecStateFailureStates = SpecStateFailed | SpecStateAborted | SpecStatePanicked | SpecStateInterrupted +var SpecStateFailureStates = SpecStateFailed | SpecStateTimedout | SpecStateAborted | SpecStatePanicked | SpecStateInterrupted func (ss SpecState) Is(states SpecState) bool { return ss&states != 0 } +// ProgressReport captures the progress of the current spec. It is, effectively, a structured Ginkgo-aware stack trace +type ProgressReport struct { + Message string `json:",omitempty"` + ParallelProcess int `json:",omitempty"` + RunningInParallel bool `json:",omitempty"` + + ContainerHierarchyTexts []string `json:",omitempty"` + LeafNodeText string `json:",omitempty"` + LeafNodeLocation CodeLocation `json:",omitempty"` + SpecStartTime time.Time `json:",omitempty"` + + CurrentNodeType NodeType `json:",omitempty"` + CurrentNodeText string `json:",omitempty"` + CurrentNodeLocation CodeLocation `json:",omitempty"` + CurrentNodeStartTime time.Time `json:",omitempty"` + + CurrentStepText string `json:",omitempty"` + CurrentStepLocation CodeLocation `json:",omitempty"` + CurrentStepStartTime time.Time `json:",omitempty"` + + AdditionalReports []string `json:",omitempty"` + + CapturedGinkgoWriterOutput string `json:",omitempty"` + TimelineLocation TimelineLocation `json:",omitempty"` + + Goroutines []Goroutine `json:",omitempty"` +} + +func (pr ProgressReport) IsZero() bool { + return pr.CurrentNodeType == NodeTypeInvalid +} + +func (pr ProgressReport) Time() time.Time { + return pr.TimelineLocation.Time +} + +func (pr ProgressReport) SpecGoroutine() Goroutine { + for _, goroutine := range pr.Goroutines { + if goroutine.IsSpecGoroutine { + return goroutine + } + } + return Goroutine{} +} + +func (pr ProgressReport) HighlightedGoroutines() []Goroutine { + out := []Goroutine{} + for _, goroutine := range pr.Goroutines { + if goroutine.IsSpecGoroutine || !goroutine.HasHighlights() { + continue + } + out = append(out, goroutine) + } + return out +} + +func (pr ProgressReport) OtherGoroutines() []Goroutine { + out := []Goroutine{} + for _, goroutine := range pr.Goroutines { + if goroutine.IsSpecGoroutine || goroutine.HasHighlights() { + continue + } + out = append(out, goroutine) + } + return out +} + +func (pr ProgressReport) WithoutCapturedGinkgoWriterOutput() ProgressReport { + out := pr + out.CapturedGinkgoWriterOutput = "" + return out +} + +func (pr ProgressReport) WithoutOtherGoroutines() ProgressReport { + out := pr + filteredGoroutines := []Goroutine{} + for _, goroutine := range pr.Goroutines { + if goroutine.IsSpecGoroutine || goroutine.HasHighlights() { + filteredGoroutines = append(filteredGoroutines, goroutine) + } + } + out.Goroutines = filteredGoroutines + return out +} + +func (pr ProgressReport) GetTimelineLocation() TimelineLocation { + return pr.TimelineLocation +} + +type Goroutine struct { + ID uint64 + State string + Stack []FunctionCall + IsSpecGoroutine bool +} + +func (g Goroutine) IsZero() bool { + return g.ID == 0 +} + +func (g Goroutine) HasHighlights() bool { + for _, fc := range g.Stack { + if fc.Highlight { + return true + } + } + + return false +} + +type FunctionCall struct { + Function string + Filename string + Line int + Highlight bool `json:",omitempty"` + Source []string `json:",omitempty"` + SourceHighlight int `json:",omitempty"` +} + // NodeType captures the type of a given Ginkgo Node type NodeType uint @@ -493,6 +765,7 @@ const ( NodeTypeReportBeforeEach NodeTypeReportAfterEach + NodeTypeReportBeforeSuite NodeTypeReportAfterSuite NodeTypeCleanupInvalid @@ -502,7 +775,9 @@ const ( ) var NodeTypesForContainerAndIt = NodeTypeContainer | NodeTypeIt -var NodeTypesForSuiteLevelNodes = NodeTypeBeforeSuite | NodeTypeSynchronizedBeforeSuite | NodeTypeAfterSuite | NodeTypeSynchronizedAfterSuite | NodeTypeReportAfterSuite | NodeTypeCleanupAfterSuite +var NodeTypesForSuiteLevelNodes = NodeTypeBeforeSuite | NodeTypeSynchronizedBeforeSuite | NodeTypeAfterSuite | NodeTypeSynchronizedAfterSuite | NodeTypeReportBeforeSuite | NodeTypeReportAfterSuite | NodeTypeCleanupAfterSuite +var NodeTypesAllowedDuringCleanupInterrupt = NodeTypeAfterEach | NodeTypeJustAfterEach | NodeTypeAfterAll | NodeTypeAfterSuite | NodeTypeSynchronizedAfterSuite | NodeTypeCleanupAfterEach | NodeTypeCleanupAfterAll | NodeTypeCleanupAfterSuite +var NodeTypesAllowedDuringReportInterrupt = NodeTypeReportBeforeEach | NodeTypeReportAfterEach | NodeTypeReportBeforeSuite | NodeTypeReportAfterSuite var ntEnumSupport = NewEnumSupport(map[uint]string{ uint(NodeTypeInvalid): "INVALID NODE TYPE", @@ -520,9 +795,10 @@ var ntEnumSupport = NewEnumSupport(map[uint]string{ uint(NodeTypeSynchronizedAfterSuite): "SynchronizedAfterSuite", uint(NodeTypeReportBeforeEach): "ReportBeforeEach", uint(NodeTypeReportAfterEach): "ReportAfterEach", + uint(NodeTypeReportBeforeSuite): "ReportBeforeSuite", uint(NodeTypeReportAfterSuite): "ReportAfterSuite", - uint(NodeTypeCleanupInvalid): "INVALID CLEANUP NODE", - uint(NodeTypeCleanupAfterEach): "DeferCleanup", + uint(NodeTypeCleanupInvalid): "DeferCleanup", + uint(NodeTypeCleanupAfterEach): "DeferCleanup (Each)", uint(NodeTypeCleanupAfterAll): "DeferCleanup (All)", uint(NodeTypeCleanupAfterSuite): "DeferCleanup (Suite)", }) @@ -542,3 +818,99 @@ func (nt NodeType) MarshalJSON() ([]byte, error) { func (nt NodeType) Is(nodeTypes NodeType) bool { return nt&nodeTypes != 0 } + +/* +SpecEvent captures a vareity of events that can occur when specs run. See SpecEventType for the list of available events. +*/ +type SpecEvent struct { + SpecEventType SpecEventType + + CodeLocation CodeLocation + TimelineLocation TimelineLocation + + Message string `json:",omitempty"` + Duration time.Duration `json:",omitempty"` + NodeType NodeType `json:",omitempty"` + Attempt int `json:",omitempty"` +} + +func (se SpecEvent) GetTimelineLocation() TimelineLocation { + return se.TimelineLocation +} + +func (se SpecEvent) IsOnlyVisibleAtVeryVerbose() bool { + return se.SpecEventType.Is(SpecEventByEnd | SpecEventNodeStart | SpecEventNodeEnd) +} + +func (se SpecEvent) GomegaString() string { + out := &strings.Builder{} + out.WriteString("[" + se.SpecEventType.String() + " SpecEvent] ") + if se.Message != "" { + out.WriteString("Message=") + out.WriteString(`"` + se.Message + `",`) + } + if se.Duration != 0 { + out.WriteString("Duration=" + se.Duration.String() + ",") + } + if se.NodeType != NodeTypeInvalid { + out.WriteString("NodeType=" + se.NodeType.String() + ",") + } + if se.Attempt != 0 { + out.WriteString(fmt.Sprintf("Attempt=%d", se.Attempt) + ",") + } + out.WriteString("CL=" + se.CodeLocation.String() + ",") + out.WriteString(fmt.Sprintf("TL.Offset=%d", se.TimelineLocation.Offset)) + + return out.String() +} + +type SpecEvents []SpecEvent + +func (se SpecEvents) WithType(seType SpecEventType) SpecEvents { + out := SpecEvents{} + for _, event := range se { + if event.SpecEventType.Is(seType) { + out = append(out, event) + } + } + return out +} + +type SpecEventType uint + +const ( + SpecEventInvalid SpecEventType = 0 + + SpecEventByStart SpecEventType = 1 << iota + SpecEventByEnd + SpecEventNodeStart + SpecEventNodeEnd + SpecEventSpecRepeat + SpecEventSpecRetry +) + +var seEnumSupport = NewEnumSupport(map[uint]string{ + uint(SpecEventInvalid): "INVALID SPEC EVENT", + uint(SpecEventByStart): "By", + uint(SpecEventByEnd): "By (End)", + uint(SpecEventNodeStart): "Node", + uint(SpecEventNodeEnd): "Node (End)", + uint(SpecEventSpecRepeat): "Repeat", + uint(SpecEventSpecRetry): "Retry", +}) + +func (se SpecEventType) String() string { + return seEnumSupport.String(uint(se)) +} +func (se *SpecEventType) UnmarshalJSON(b []byte) error { + out, err := seEnumSupport.UnmarshJSON(b) + *se = SpecEventType(out) + return err +} +func (se SpecEventType) MarshalJSON() ([]byte, error) { + return seEnumSupport.MarshJSON(uint(se)) +} + +func (se SpecEventType) Is(specEventTypes SpecEventType) bool { + return se&specEventTypes != 0 +} diff --git a/vendor/github.com/onsi/ginkgo/v2/types/version.go b/vendor/github.com/onsi/ginkgo/v2/types/version.go index c799014918..43066341e1 100644 --- a/vendor/github.com/onsi/ginkgo/v2/types/version.go +++ b/vendor/github.com/onsi/ginkgo/v2/types/version.go @@ -1,3 +1,3 @@ package types -const VERSION = "2.1.6" +const VERSION = "2.9.5" diff --git a/vendor/github.com/onsi/gomega/types/types.go b/vendor/github.com/onsi/gomega/types/types.go index c315ef0656..7c7adb9415 100644 --- a/vendor/github.com/onsi/gomega/types/types.go +++ b/vendor/github.com/onsi/gomega/types/types.go @@ -1,12 +1,13 @@ package types import ( + "context" "time" ) type GomegaFailHandler func(message string, callerSkip ...int) -//A simple *testing.T interface wrapper +// A simple *testing.T interface wrapper type GomegaTestingT interface { Helper() Fatalf(format string, args ...interface{}) @@ -18,11 +19,11 @@ type Gomega interface { Expect(actual interface{}, extra ...interface{}) Assertion ExpectWithOffset(offset int, actual interface{}, extra ...interface{}) Assertion - Eventually(actual interface{}, intervals ...interface{}) AsyncAssertion - EventuallyWithOffset(offset int, actual interface{}, intervals ...interface{}) AsyncAssertion + Eventually(actualOrCtx interface{}, args ...interface{}) AsyncAssertion + EventuallyWithOffset(offset int, actualOrCtx interface{}, args ...interface{}) AsyncAssertion - Consistently(actual interface{}, intervals ...interface{}) AsyncAssertion - ConsistentlyWithOffset(offset int, actual interface{}, intervals ...interface{}) AsyncAssertion + Consistently(actualOrCtx interface{}, args ...interface{}) AsyncAssertion + ConsistentlyWithOffset(offset int, actualOrCtx interface{}, args ...interface{}) AsyncAssertion SetDefaultEventuallyTimeout(time.Duration) SetDefaultEventuallyPollingInterval(time.Duration) @@ -30,9 +31,9 @@ type Gomega interface { SetDefaultConsistentlyPollingInterval(time.Duration) } -//All Gomega matchers must implement the GomegaMatcher interface +// All Gomega matchers must implement the GomegaMatcher interface // -//For details on writing custom matchers, check out: http://onsi.github.io/gomega/#adding-your-own-matchers +// For details on writing custom matchers, check out: http://onsi.github.io/gomega/#adding-your-own-matchers type GomegaMatcher interface { Match(actual interface{}) (success bool, err error) FailureMessage(actual interface{}) (message string) @@ -70,6 +71,11 @@ type AsyncAssertion interface { WithOffset(offset int) AsyncAssertion WithTimeout(interval time.Duration) AsyncAssertion WithPolling(interval time.Duration) AsyncAssertion + Within(timeout time.Duration) AsyncAssertion + ProbeEvery(interval time.Duration) AsyncAssertion + WithContext(ctx context.Context) AsyncAssertion + WithArguments(argsToForward ...interface{}) AsyncAssertion + MustPassRepeatedly(count int) AsyncAssertion } // Assertions are returned by Ω and Expect and enable assertions against Gomega matchers diff --git a/vendor/github.com/opencontainers/image-spec/specs-go/v1/annotations.go b/vendor/github.com/opencontainers/image-spec/specs-go/v1/annotations.go index 581cf7cdfa..6f9e6fd3ab 100644 --- a/vendor/github.com/opencontainers/image-spec/specs-go/v1/annotations.go +++ b/vendor/github.com/opencontainers/image-spec/specs-go/v1/annotations.go @@ -59,4 +59,13 @@ const ( // AnnotationBaseImageName is the annotation key for the image reference of the image's base image. AnnotationBaseImageName = "org.opencontainers.image.base.name" + + // AnnotationArtifactCreated is the annotation key for the date and time on which the artifact was built, conforming to RFC 3339. + AnnotationArtifactCreated = "org.opencontainers.artifact.created" + + // AnnotationArtifactDescription is the annotation key for the human readable description for the artifact. + AnnotationArtifactDescription = "org.opencontainers.artifact.description" + + // AnnotationReferrersFiltersApplied is the annotation key for the comma separated list of filters applied by the registry in the referrers listing. + AnnotationReferrersFiltersApplied = "org.opencontainers.referrers.filtersApplied" ) diff --git a/vendor/github.com/opencontainers/image-spec/specs-go/v1/artifact.go b/vendor/github.com/opencontainers/image-spec/specs-go/v1/artifact.go new file mode 100644 index 0000000000..03d76ce437 --- /dev/null +++ b/vendor/github.com/opencontainers/image-spec/specs-go/v1/artifact.go @@ -0,0 +1,34 @@ +// Copyright 2022 The Linux Foundation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1 + +// Artifact describes an artifact manifest. +// This structure provides `application/vnd.oci.artifact.manifest.v1+json` mediatype when marshalled to JSON. +type Artifact struct { + // MediaType is the media type of the object this schema refers to. + MediaType string `json:"mediaType"` + + // ArtifactType is the IANA media type of the artifact this schema refers to. + ArtifactType string `json:"artifactType"` + + // Blobs is a collection of blobs referenced by this manifest. + Blobs []Descriptor `json:"blobs,omitempty"` + + // Subject (reference) is an optional link from the artifact to another manifest forming an association between the artifact and the other manifest. + Subject *Descriptor `json:"subject,omitempty"` + + // Annotations contains arbitrary metadata for the artifact manifest. + Annotations map[string]string `json:"annotations,omitempty"` +} diff --git a/vendor/github.com/opencontainers/image-spec/specs-go/v1/descriptor.go b/vendor/github.com/opencontainers/image-spec/specs-go/v1/descriptor.go index 6e442a0853..9654aa5af6 100644 --- a/vendor/github.com/opencontainers/image-spec/specs-go/v1/descriptor.go +++ b/vendor/github.com/opencontainers/image-spec/specs-go/v1/descriptor.go @@ -1,4 +1,4 @@ -// Copyright 2016 The Linux Foundation +// Copyright 2016-2022 The Linux Foundation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -35,10 +35,18 @@ type Descriptor struct { // Annotations contains arbitrary metadata relating to the targeted content. Annotations map[string]string `json:"annotations,omitempty"` + // Data is an embedding of the targeted content. This is encoded as a base64 + // string when marshalled to JSON (automatically, by encoding/json). If + // present, Data can be used directly to avoid fetching the targeted content. + Data []byte `json:"data,omitempty"` + // Platform describes the platform which the image in the manifest runs on. // // This should only be used when referring to a manifest. Platform *Platform `json:"platform,omitempty"` + + // ArtifactType is the IANA media type of this artifact. + ArtifactType string `json:"artifactType,omitempty"` } // Platform describes the platform which the image in the manifest runs on. diff --git a/vendor/github.com/opencontainers/image-spec/specs-go/v1/index.go b/vendor/github.com/opencontainers/image-spec/specs-go/v1/index.go index 82da6c6a89..ed4a56e59e 100644 --- a/vendor/github.com/opencontainers/image-spec/specs-go/v1/index.go +++ b/vendor/github.com/opencontainers/image-spec/specs-go/v1/index.go @@ -21,7 +21,7 @@ import "github.com/opencontainers/image-spec/specs-go" type Index struct { specs.Versioned - // MediaType specificies the type of this document data structure e.g. `application/vnd.oci.image.index.v1+json` + // MediaType specifies the type of this document data structure e.g. `application/vnd.oci.image.index.v1+json` MediaType string `json:"mediaType,omitempty"` // Manifests references platform specific manifests. diff --git a/vendor/github.com/opencontainers/image-spec/specs-go/v1/manifest.go b/vendor/github.com/opencontainers/image-spec/specs-go/v1/manifest.go index d72d15ce4b..730a09359b 100644 --- a/vendor/github.com/opencontainers/image-spec/specs-go/v1/manifest.go +++ b/vendor/github.com/opencontainers/image-spec/specs-go/v1/manifest.go @@ -1,4 +1,4 @@ -// Copyright 2016 The Linux Foundation +// Copyright 2016-2022 The Linux Foundation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -20,7 +20,7 @@ import "github.com/opencontainers/image-spec/specs-go" type Manifest struct { specs.Versioned - // MediaType specificies the type of this document data structure e.g. `application/vnd.oci.image.manifest.v1+json` + // MediaType specifies the type of this document data structure e.g. `application/vnd.oci.image.manifest.v1+json` MediaType string `json:"mediaType,omitempty"` // Config references a configuration object for a container, by digest. @@ -30,6 +30,9 @@ type Manifest struct { // Layers is an indexed list of layers referenced by the manifest. Layers []Descriptor `json:"layers"` + // Subject is an optional link from the image manifest to another manifest forming an association between the image manifest and the other manifest. + Subject *Descriptor `json:"subject,omitempty"` + // Annotations contains arbitrary metadata for the image manifest. Annotations map[string]string `json:"annotations,omitempty"` } diff --git a/vendor/github.com/opencontainers/image-spec/specs-go/v1/mediatype.go b/vendor/github.com/opencontainers/image-spec/specs-go/v1/mediatype.go index 4f35ac134f..935b481e3e 100644 --- a/vendor/github.com/opencontainers/image-spec/specs-go/v1/mediatype.go +++ b/vendor/github.com/opencontainers/image-spec/specs-go/v1/mediatype.go @@ -54,4 +54,7 @@ const ( // MediaTypeImageConfig specifies the media type for the image configuration. MediaTypeImageConfig = "application/vnd.oci.image.config.v1+json" + + // MediaTypeArtifactManifest specifies the media type for a content descriptor. + MediaTypeArtifactManifest = "application/vnd.oci.artifact.manifest.v1+json" ) diff --git a/vendor/github.com/opencontainers/image-spec/specs-go/version.go b/vendor/github.com/opencontainers/image-spec/specs-go/version.go index 31f99cf645..d279035796 100644 --- a/vendor/github.com/opencontainers/image-spec/specs-go/version.go +++ b/vendor/github.com/opencontainers/image-spec/specs-go/version.go @@ -20,12 +20,12 @@ const ( // VersionMajor is for an API incompatible changes VersionMajor = 1 // VersionMinor is for functionality in a backwards-compatible manner - VersionMinor = 0 + VersionMinor = 1 // VersionPatch is for backwards-compatible bug fixes - VersionPatch = 2 + VersionPatch = 0 // VersionDev indicates development branch. Releases will be empty string. - VersionDev = "-dev" + VersionDev = "-rc2" ) // Version is the specification version that the package types support. diff --git a/vendor/github.com/operator-framework/api/crds/operators.coreos.com_catalogsources.yaml b/vendor/github.com/operator-framework/api/crds/operators.coreos.com_catalogsources.yaml index 2836d66fed..e42010c7ad 100644 --- a/vendor/github.com/operator-framework/api/crds/operators.coreos.com_catalogsources.yaml +++ b/vendor/github.com/operator-framework/api/crds/operators.coreos.com_catalogsources.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.8.0 + controller-gen.kubebuilder.io/version: v0.9.0 creationTimestamp: null name: catalogsources.operators.coreos.com spec: @@ -71,6 +71,467 @@ spec: description: GrpcPodConfig exposes different overrides for the pod spec of the CatalogSource Pod. Only used when SourceType = SourceTypeGrpc and Image is set. type: object properties: + affinity: + description: Affinity is the catalog source's pod's affinity. + type: object + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the pod. + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node matches the corresponding matchExpressions; the node(s) with the highest sum are the most preferred. + type: array + items: + description: An empty preferred scheduling term matches all objects with implicit weight 0 (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). + type: object + required: + - preference + - weight + properties: + preference: + description: A node selector term, associated with the corresponding weight. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + weight: + description: Weight associated with matching the corresponding nodeSelectorTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to an update), the system may or may not try to eventually evict the pod from its node. + type: object + required: + - nodeSelectorTerms + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. The terms are ORed. + type: array + items: + description: A null or empty node selector term matches no objects. The requirements of them are ANDed. The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + type: object + properties: + matchExpressions: + description: A list of node selector requirements by node's labels. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchFields: + description: A list of node selector requirements by node's fields. + type: array + items: + description: A node selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector applies to. + type: string + operator: + description: Represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: An array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. If the operator is Gt or Lt, the values array must have a single element, which will be interpreted as an integer. This array is replaced during a strategic merge patch. + type: array + items: + type: string + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes that satisfy the affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + weight: + description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. + type: array + items: + description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to nodes that satisfy the anti-affinity expressions specified by this field, but it may choose a node that violates one or more of the expressions. The node that is most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), compute a sum by iterating through the elements of this field and adding "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string + weight: + description: weight associated with matching the corresponding podAffinityTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified by this field are not met at scheduling time, the pod will not be scheduled onto the node. If the anti-affinity requirements specified by this field cease to be met at some point during pod execution (e.g. due to a pod label update), the system may or may not try to eventually evict the pod from its node. When there are multiple elements, the lists of nodes corresponding to each podAffinityTerm are intersected, i.e. all terms must be satisfied. + type: array + items: + description: Defines a set of pods (namely those matching the labelSelector relative to the given namespace(s)) that this pod should be co-located (affinity) or not co-located (anti-affinity) with, where co-located is defined as running on a node whose value of the label with key matches that of any node on which a pod of the set of pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + namespaceSelector: + description: A label query over the set of namespaces that the term applies to. The term is applied to the union of the namespaces selected by this field and the ones listed in the namespaces field. null selector and null or empty namespaces list means "this pod's namespace". An empty selector ({}) matches all namespaces. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector that contains values, a key, and an operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector applies to. + type: string + operator: + description: operator represents a key's relationship to a set of values. Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If the operator is In or NotIn, the values array must be non-empty. If the operator is Exists or DoesNotExist, the values array must be empty. This array is replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of matchExpressions, whose key field is "key", the operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + namespaces: + description: namespaces specifies a static list of namespace names that the term applies to. The term is applied to the union of the namespaces listed in this field and the ones selected by namespaceSelector. null or empty namespaces list and null namespaceSelector means "this pod's namespace". + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. + type: string nodeSelector: description: NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node's labels for the pod to be scheduled on that node. type: object @@ -127,6 +588,9 @@ spec: type: integer publisher: type: string + runAsRoot: + description: RunAsRoot allows admins to indicate that they wish to run the CatalogSource pod in a privileged pod as root. This should only be enabled when running older catalog images which could not be run as non-root. + type: boolean secrets: description: Secrets represent set of secrets that can be used to access the contents of the catalog. It is best to keep this list small, since each will need to be tried for every catalog entry. type: array @@ -152,7 +616,7 @@ spec: description: Represents the state of a CatalogSource. Note that Message and Reason represent the original status information, which may be migrated to be conditions based in the future. Any new features introduced will use conditions. type: array items: - description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" type: object required: - lastTransitionTime diff --git a/vendor/github.com/operator-framework/api/crds/operators.coreos.com_clusterserviceversions.yaml b/vendor/github.com/operator-framework/api/crds/operators.coreos.com_clusterserviceversions.yaml index 37b41c4608..e5a35991bd 100644 --- a/vendor/github.com/operator-framework/api/crds/operators.coreos.com_clusterserviceversions.yaml +++ b/vendor/github.com/operator-framework/api/crds/operators.coreos.com_clusterserviceversions.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.8.0 + controller-gen.kubebuilder.io/version: v0.9.0 creationTimestamp: null name: clusterserviceversions.operators.coreos.com spec: @@ -119,7 +119,7 @@ spec: resources: type: array items: - description: APIResourceReference is a Kubernetes resource type used by a custom resource + description: APIResourceReference is a reference to a Kubernetes resource type that the referrer utilizes. type: object required: - kind @@ -127,10 +127,13 @@ spec: - version properties: kind: + description: Kind of the referenced resource type. type: string name: + description: Plural name of the referenced resource type (CustomResourceDefinition.Spec.Names[].Plural). Empty string if the referenced resource type is not a custom resource. type: string version: + description: API Version of the referenced resource type. type: string specDescriptors: type: array @@ -229,7 +232,7 @@ spec: resources: type: array items: - description: APIResourceReference is a Kubernetes resource type used by a custom resource + description: APIResourceReference is a reference to a Kubernetes resource type that the referrer utilizes. type: object required: - kind @@ -237,10 +240,13 @@ spec: - version properties: kind: + description: Kind of the referenced resource type. type: string name: + description: Plural name of the referenced resource type (CustomResourceDefinition.Spec.Names[].Plural). Empty string if the referenced resource type is not a custom resource. type: string version: + description: API Version of the referenced resource type. type: string specDescriptors: type: array @@ -343,7 +349,7 @@ spec: resources: type: array items: - description: APIResourceReference is a Kubernetes resource type used by a custom resource + description: APIResourceReference is a reference to a Kubernetes resource type that the referrer utilizes. type: object required: - kind @@ -351,10 +357,13 @@ spec: - version properties: kind: + description: Kind of the referenced resource type. type: string name: + description: Plural name of the referenced resource type (CustomResourceDefinition.Spec.Names[].Plural). Empty string if the referenced resource type is not a custom resource. type: string version: + description: API Version of the referenced resource type. type: string specDescriptors: type: array @@ -445,7 +454,7 @@ spec: resources: type: array items: - description: APIResourceReference is a Kubernetes resource type used by a custom resource + description: APIResourceReference is a reference to a Kubernetes resource type that the referrer utilizes. type: object required: - kind @@ -453,10 +462,13 @@ spec: - version properties: kind: + description: Kind of the referenced resource type. type: string name: + description: Plural name of the referenced resource type (CustomResourceDefinition.Spec.Names[].Plural). Empty string if the referenced resource type is not a custom resource. type: string version: + description: API Version of the referenced resource type. type: string specDescriptors: type: array @@ -505,10 +517,13 @@ spec: version: type: string description: + description: Description of the operator. Can include the features, limitations or use-cases of the operator. type: string displayName: + description: The name of the operator in display format. type: string icon: + description: The icon for this operator. type: array items: type: object @@ -550,7 +565,7 @@ spec: - verbs properties: apiGroups: - description: APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of the enumerated resources in any API group will be allowed. + description: APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of the enumerated resources in any API group will be allowed. "" represents the core API group and "*" represents all API groups. type: array items: type: string @@ -672,7 +687,7 @@ spec: description: Type of deployment. Can be "Recreate" or "RollingUpdate". Default is RollingUpdate. type: string template: - description: Template describes the pods that will be created. + description: Template describes the pods that will be created. The only allowed template.spec.restartPolicy value is "Always". type: object properties: metadata: @@ -1325,7 +1340,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -1390,7 +1405,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -1440,7 +1455,7 @@ spec: type: integer format: int32 grpc: - description: GRPC specifies an action involving a GRPC port. This is a beta field and requires enabling GRPCContainerProbe feature gate. + description: GRPC specifies an action involving a GRPC port. type: object required: - port @@ -1472,7 +1487,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -1528,7 +1543,7 @@ spec: description: Name of the container specified as a DNS_LABEL. Each container in a pod must have a unique name (DNS_LABEL). Cannot be updated. type: string ports: - description: List of ports to expose from the container. Exposing a port here gives the system additional information about the network connections a container uses, but is primarily informational. Not specifying a port here DOES NOT prevent that port from being exposed. Any port which is listening on the default "0.0.0.0" address inside a container will be accessible from the network. Cannot be updated. + description: List of ports to expose from the container. Not specifying a port here DOES NOT prevent that port from being exposed. Any port which is listening on the default "0.0.0.0" address inside a container will be accessible from the network. Modifying this array with strategic merge patch may corrupt the data. For more information See https://github.com/kubernetes/kubernetes/issues/108255. Cannot be updated. type: array items: description: ContainerPort represents a network port in a single container. @@ -1576,7 +1591,7 @@ spec: type: integer format: int32 grpc: - description: GRPC specifies an action involving a GRPC port. This is a beta field and requires enabling GRPCContainerProbe feature gate. + description: GRPC specifies an action involving a GRPC port. type: object required: - port @@ -1608,7 +1623,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -1660,10 +1675,42 @@ spec: description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' type: integer format: int32 + resizePolicy: + description: Resources resize policy for the container. + type: array + items: + description: ContainerResizePolicy represents resource resize policy for the container. + type: object + required: + - resourceName + - restartPolicy + properties: + resourceName: + description: 'Name of the resource to which this resource resize policy applies. Supported values: cpu, memory.' + type: string + restartPolicy: + description: Restart policy to apply when specified resource is resized. If not specified, it defaults to NotRequired. + type: string + x-kubernetes-list-type: atomic resources: description: 'Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers." + type: array + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + type: object + required: + - name + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object @@ -1674,7 +1721,7 @@ spec: - type: string x-kubernetes-int-or-string: true requests: - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object additionalProperties: pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ @@ -1787,7 +1834,7 @@ spec: type: integer format: int32 grpc: - description: GRPC specifies an action involving a GRPC port. This is a beta field and requires enabling GRPCContainerProbe feature gate. + description: GRPC specifies an action involving a GRPC port. type: object required: - port @@ -1819,7 +1866,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -1966,10 +2013,10 @@ spec: description: 'EnableServiceLinks indicates whether information about services should be injected into pod''s environment variables, matching the syntax of Docker links. Optional: Defaults to true.' type: boolean ephemeralContainers: - description: List of ephemeral containers run in this pod. Ephemeral containers may be run in an existing pod to perform user-initiated actions such as debugging. This list cannot be specified when creating a pod, and it cannot be modified by updating the pod spec. In order to add an ephemeral container to an existing pod, use the pod's ephemeralcontainers subresource. This field is beta-level and available on clusters that haven't disabled the EphemeralContainers feature gate. + description: List of ephemeral containers run in this pod. Ephemeral containers may be run in an existing pod to perform user-initiated actions such as debugging. This list cannot be specified when creating a pod, and it cannot be modified by updating the pod spec. In order to add an ephemeral container to an existing pod, use the pod's ephemeralcontainers subresource. type: array items: - description: "An EphemeralContainer is a temporary container that you may add to an existing Pod for user-initiated activities such as debugging. Ephemeral containers have no resource or scheduling guarantees, and they will not be restarted when they exit or when a Pod is removed or restarted. The kubelet may evict a Pod if an ephemeral container causes the Pod to exceed its resource allocation. \n To add an ephemeral container, use the ephemeralcontainers subresource of an existing Pod. Ephemeral containers may not be removed or restarted. \n This is a beta feature available on clusters that haven't disabled the EphemeralContainers feature gate." + description: "An EphemeralContainer is a temporary container that you may add to an existing Pod for user-initiated activities such as debugging. Ephemeral containers have no resource or scheduling guarantees, and they will not be restarted when they exit or when a Pod is removed or restarted. The kubelet may evict a Pod if an ephemeral container causes the Pod to exceed its resource allocation. \n To add an ephemeral container, use the ephemeralcontainers subresource of an existing Pod. Ephemeral containers may not be removed or restarted." type: object required: - name @@ -2137,7 +2184,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -2202,7 +2249,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -2252,7 +2299,7 @@ spec: type: integer format: int32 grpc: - description: GRPC specifies an action involving a GRPC port. This is a beta field and requires enabling GRPCContainerProbe feature gate. + description: GRPC specifies an action involving a GRPC port. type: object required: - port @@ -2284,7 +2331,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -2388,7 +2435,7 @@ spec: type: integer format: int32 grpc: - description: GRPC specifies an action involving a GRPC port. This is a beta field and requires enabling GRPCContainerProbe feature gate. + description: GRPC specifies an action involving a GRPC port. type: object required: - port @@ -2420,7 +2467,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -2472,10 +2519,42 @@ spec: description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' type: integer format: int32 + resizePolicy: + description: Resources resize policy for the container. + type: array + items: + description: ContainerResizePolicy represents resource resize policy for the container. + type: object + required: + - resourceName + - restartPolicy + properties: + resourceName: + description: 'Name of the resource to which this resource resize policy applies. Supported values: cpu, memory.' + type: string + restartPolicy: + description: Restart policy to apply when specified resource is resized. If not specified, it defaults to NotRequired. + type: string + x-kubernetes-list-type: atomic resources: description: Resources are not allowed for ephemeral containers. Ephemeral containers use spare resources already allocated to the pod. type: object properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers." + type: array + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + type: object + required: + - name + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object @@ -2486,7 +2565,7 @@ spec: - type: string x-kubernetes-int-or-string: true requests: - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object additionalProperties: pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ @@ -2599,7 +2678,7 @@ spec: type: integer format: int32 grpc: - description: GRPC specifies an action involving a GRPC port. This is a beta field and requires enabling GRPCContainerProbe feature gate. + description: GRPC specifies an action involving a GRPC port. type: object required: - port @@ -2631,7 +2710,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -2772,6 +2851,9 @@ spec: hostPID: description: 'Use the host''s pid namespace. Optional: Default to false.' type: boolean + hostUsers: + description: 'Use the host''s user namespace. Optional: Default to true. If set to true or not present, the pod will be run in the host user namespace, useful for when the pod needs a feature only available to the host user namespace, such as loading a kernel module with CAP_SYS_MODULE. When set to false, a new userns is created for the pod. Setting false is useful for mitigating container breakout vulnerabilities even allowing users to run their containers as root without actually having root privileges on the host. This field is alpha-level and is only honored by servers that enable the UserNamespacesSupport feature.' + type: boolean hostname: description: Specifies the hostname of the Pod If not specified, the pod's hostname will be set to a system-defined value. type: string @@ -2957,7 +3039,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -3022,7 +3104,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -3072,7 +3154,7 @@ spec: type: integer format: int32 grpc: - description: GRPC specifies an action involving a GRPC port. This is a beta field and requires enabling GRPCContainerProbe feature gate. + description: GRPC specifies an action involving a GRPC port. type: object required: - port @@ -3104,7 +3186,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -3160,7 +3242,7 @@ spec: description: Name of the container specified as a DNS_LABEL. Each container in a pod must have a unique name (DNS_LABEL). Cannot be updated. type: string ports: - description: List of ports to expose from the container. Exposing a port here gives the system additional information about the network connections a container uses, but is primarily informational. Not specifying a port here DOES NOT prevent that port from being exposed. Any port which is listening on the default "0.0.0.0" address inside a container will be accessible from the network. Cannot be updated. + description: List of ports to expose from the container. Not specifying a port here DOES NOT prevent that port from being exposed. Any port which is listening on the default "0.0.0.0" address inside a container will be accessible from the network. Modifying this array with strategic merge patch may corrupt the data. For more information See https://github.com/kubernetes/kubernetes/issues/108255. Cannot be updated. type: array items: description: ContainerPort represents a network port in a single container. @@ -3208,7 +3290,7 @@ spec: type: integer format: int32 grpc: - description: GRPC specifies an action involving a GRPC port. This is a beta field and requires enabling GRPCContainerProbe feature gate. + description: GRPC specifies an action involving a GRPC port. type: object required: - port @@ -3240,7 +3322,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -3292,10 +3374,42 @@ spec: description: 'Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' type: integer format: int32 + resizePolicy: + description: Resources resize policy for the container. + type: array + items: + description: ContainerResizePolicy represents resource resize policy for the container. + type: object + required: + - resourceName + - restartPolicy + properties: + resourceName: + description: 'Name of the resource to which this resource resize policy applies. Supported values: cpu, memory.' + type: string + restartPolicy: + description: Restart policy to apply when specified resource is resized. If not specified, it defaults to NotRequired. + type: string + x-kubernetes-list-type: atomic resources: description: 'Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers." + type: array + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + type: object + required: + - name + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object @@ -3306,7 +3420,7 @@ spec: - type: string x-kubernetes-int-or-string: true requests: - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object additionalProperties: pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ @@ -3419,7 +3533,7 @@ spec: type: integer format: int32 grpc: - description: GRPC specifies an action involving a GRPC port. This is a beta field and requires enabling GRPCContainerProbe feature gate. + description: GRPC specifies an action involving a GRPC port. type: object required: - port @@ -3451,7 +3565,7 @@ spec: - value properties: name: - description: The header field name + description: The header field name. This will be canonicalized upon output, so case-variant names will be understood as the same header. type: string value: description: The header field value @@ -3575,7 +3689,7 @@ spec: type: string x-kubernetes-map-type: atomic os: - description: "Specifies the OS of the containers in the pod. Some pod and container fields are restricted if this is set. \n If the OS field is set to linux, the following fields must be unset: -securityContext.windowsOptions \n If the OS field is set to windows, following fields must be unset: - spec.hostPID - spec.hostIPC - spec.securityContext.seLinuxOptions - spec.securityContext.seccompProfile - spec.securityContext.fsGroup - spec.securityContext.fsGroupChangePolicy - spec.securityContext.sysctls - spec.shareProcessNamespace - spec.securityContext.runAsUser - spec.securityContext.runAsGroup - spec.securityContext.supplementalGroups - spec.containers[*].securityContext.seLinuxOptions - spec.containers[*].securityContext.seccompProfile - spec.containers[*].securityContext.capabilities - spec.containers[*].securityContext.readOnlyRootFilesystem - spec.containers[*].securityContext.privileged - spec.containers[*].securityContext.allowPrivilegeEscalation - spec.containers[*].securityContext.procMount - spec.containers[*].securityContext.runAsUser - spec.containers[*].securityContext.runAsGroup This is a beta field and requires the IdentifyPodOS feature" + description: "Specifies the OS of the containers in the pod. Some pod and container fields are restricted if this is set. \n If the OS field is set to linux, the following fields must be unset: -securityContext.windowsOptions \n If the OS field is set to windows, following fields must be unset: - spec.hostPID - spec.hostIPC - spec.hostUsers - spec.securityContext.seLinuxOptions - spec.securityContext.seccompProfile - spec.securityContext.fsGroup - spec.securityContext.fsGroupChangePolicy - spec.securityContext.sysctls - spec.shareProcessNamespace - spec.securityContext.runAsUser - spec.securityContext.runAsGroup - spec.securityContext.supplementalGroups - spec.containers[*].securityContext.seLinuxOptions - spec.containers[*].securityContext.seccompProfile - spec.containers[*].securityContext.capabilities - spec.containers[*].securityContext.readOnlyRootFilesystem - spec.containers[*].securityContext.privileged - spec.containers[*].securityContext.allowPrivilegeEscalation - spec.containers[*].securityContext.procMount - spec.containers[*].securityContext.runAsUser - spec.containers[*].securityContext.runAsGroup" type: object required: - name @@ -3614,8 +3728,33 @@ spec: conditionType: description: ConditionType refers to a condition in the pod's condition list with matching type. type: string + resourceClaims: + description: "ResourceClaims defines which ResourceClaims must be allocated and reserved before the Pod is allowed to start. The resources will be made available to those containers which consume them by name. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable." + type: array + items: + description: PodResourceClaim references exactly one ResourceClaim through a ClaimSource. It adds a name to it that uniquely identifies the ResourceClaim inside the Pod. Containers that need access to the ResourceClaim reference it with this name. + type: object + required: + - name + properties: + name: + description: Name uniquely identifies this resource claim inside the pod. This must be a DNS_LABEL. + type: string + source: + description: Source describes where to find the ResourceClaim. + type: object + properties: + resourceClaimName: + description: ResourceClaimName is the name of a ResourceClaim object in the same namespace as this pod. + type: string + resourceClaimTemplateName: + description: "ResourceClaimTemplateName is the name of a ResourceClaimTemplate object in the same namespace as this pod. \n The template will be used to create a new ResourceClaim, which will be bound to this pod. When this pod is deleted, the ResourceClaim will also be deleted. The name of the ResourceClaim will be -, where is the PodResourceClaim.Name. Pod validation will reject the pod if the concatenated name is not valid for a ResourceClaim (e.g. too long). \n An existing ResourceClaim with that name that is not owned by the pod will not be used for the pod to avoid using an unrelated resource by mistake. Scheduling and pod startup are then blocked until the unrelated ResourceClaim is removed. \n This field is immutable and no changes will be made to the corresponding ResourceClaim by the control plane after creating the ResourceClaim." + type: string + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map restartPolicy: - description: 'Restart policy for all containers within the pod. One of Always, OnFailure, Never. Default to Always. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy' + description: 'Restart policy for all containers within the pod. One of Always, OnFailure, Never. In some contexts, only a subset of those values may be permitted. Default to Always. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy' type: string runtimeClassName: description: 'RuntimeClassName refers to a RuntimeClass object in the node.k8s.io group, which should be used to run this pod. If no RuntimeClass resource matches the named class, the pod will not be run. If unset or empty, the "legacy" RuntimeClass will be used, which is an implicit class with an empty definition that uses the default runtime handler. More info: https://git.k8s.io/enhancements/keps/sig-node/585-runtime-class' @@ -3623,6 +3762,21 @@ spec: schedulerName: description: If specified, the pod will be dispatched by specified scheduler. If not specified, the pod will be dispatched by default scheduler. type: string + schedulingGates: + description: "SchedulingGates is an opaque list of values that if specified will block scheduling the pod. If schedulingGates is not empty, the pod will stay in the SchedulingGated state and the scheduler will not attempt to schedule the pod. \n SchedulingGates can only be set at pod creation time, and be removed only afterwards. \n This is a beta feature enabled by the PodSchedulingReadiness feature gate." + type: array + items: + description: PodSchedulingGate is associated to a Pod to guard its scheduling. + type: object + required: + - name + properties: + name: + description: Name of the scheduling gate. Each scheduling gate must have a unique name field. + type: string + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map securityContext: description: 'SecurityContext holds pod-level security attributes and common container settings. Optional: Defaults to empty. See type description for default values of each field.' type: object @@ -3674,7 +3828,7 @@ spec: description: "type indicates which kind of seccomp profile will be applied. Valid options are: \n Localhost - a profile defined in a file on the node should be used. RuntimeDefault - the container runtime default profile should be used. Unconfined - no profile should be applied." type: string supplementalGroups: - description: A list of groups applied to the first process run in each container, in addition to the container's primary GID. If unspecified, no groups will be added to any container. Note that this field cannot be set when spec.os.name is windows. + description: A list of groups applied to the first process run in each container, in addition to the container's primary GID, the fsGroup (if specified), and group memberships defined in the container image for the uid of the container process. If unspecified, no additional groups are added to any container. Note that group memberships defined in the container image for the uid of the container process are still effective, even if they are not included in this list. Note that this field cannot be set when spec.os.name is windows. type: array items: type: integer @@ -3794,16 +3948,28 @@ spec: type: object additionalProperties: type: string + matchLabelKeys: + description: "MatchLabelKeys is a set of pod label keys to select the pods over which spreading will be calculated. The keys are used to lookup values from the incoming pod labels, those key-value labels are ANDed with labelSelector to select the group of existing pods over which spreading will be calculated for the incoming pod. The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. MatchLabelKeys cannot be set when LabelSelector isn't set. Keys that don't exist in the incoming pod labels will be ignored. A null or empty list means only match against labelSelector. \n This is a beta field and requires the MatchLabelKeysInPodTopologySpread feature gate to be enabled (enabled by default)." + type: array + items: + type: string + x-kubernetes-list-type: atomic maxSkew: description: 'MaxSkew describes the degree to which pods may be unevenly distributed. When `whenUnsatisfiable=DoNotSchedule`, it is the maximum permitted difference between the number of matching pods in the target topology and the global minimum. The global minimum is the minimum number of matching pods in an eligible domain or zero if the number of eligible domains is less than MinDomains. For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same labelSelector spread as 2/2/1: In this case, the global minimum is 1. | zone1 | zone2 | zone3 | | P P | P P | P | - if MaxSkew is 1, incoming pod can only be scheduled to zone3 to become 2/2/2; scheduling it onto zone1(zone2) would make the ActualSkew(3-1) on zone1(zone2) violate MaxSkew(1). - if MaxSkew is 2, incoming pod can be scheduled onto any zone. When `whenUnsatisfiable=ScheduleAnyway`, it is used to give higher precedence to topologies that satisfy it. It''s a required field. Default value is 1 and 0 is not allowed.' type: integer format: int32 minDomains: - description: "MinDomains indicates a minimum number of eligible domains. When the number of eligible domains with matching topology keys is less than minDomains, Pod Topology Spread treats \"global minimum\" as 0, and then the calculation of Skew is performed. And when the number of eligible domains with matching topology keys equals or greater than minDomains, this value has no effect on scheduling. As a result, when the number of eligible domains is less than minDomains, scheduler won't schedule more than maxSkew Pods to those domains. If value is nil, the constraint behaves as if MinDomains is equal to 1. Valid values are integers greater than 0. When value is not nil, WhenUnsatisfiable must be DoNotSchedule. \n For example, in a 3-zone cluster, MaxSkew is set to 2, MinDomains is set to 5 and pods with the same labelSelector spread as 2/2/2: | zone1 | zone2 | zone3 | | P P | P P | P P | The number of domains is less than 5(MinDomains), so \"global minimum\" is treated as 0. In this situation, new pod with the same labelSelector cannot be scheduled, because computed skew will be 3(3 - 0) if new Pod is scheduled to any of the three zones, it will violate MaxSkew. \n This is an alpha field and requires enabling MinDomainsInPodTopologySpread feature gate." + description: "MinDomains indicates a minimum number of eligible domains. When the number of eligible domains with matching topology keys is less than minDomains, Pod Topology Spread treats \"global minimum\" as 0, and then the calculation of Skew is performed. And when the number of eligible domains with matching topology keys equals or greater than minDomains, this value has no effect on scheduling. As a result, when the number of eligible domains is less than minDomains, scheduler won't schedule more than maxSkew Pods to those domains. If value is nil, the constraint behaves as if MinDomains is equal to 1. Valid values are integers greater than 0. When value is not nil, WhenUnsatisfiable must be DoNotSchedule. \n For example, in a 3-zone cluster, MaxSkew is set to 2, MinDomains is set to 5 and pods with the same labelSelector spread as 2/2/2: | zone1 | zone2 | zone3 | | P P | P P | P P | The number of domains is less than 5(MinDomains), so \"global minimum\" is treated as 0. In this situation, new pod with the same labelSelector cannot be scheduled, because computed skew will be 3(3 - 0) if new Pod is scheduled to any of the three zones, it will violate MaxSkew. \n This is a beta field and requires the MinDomainsInPodTopologySpread feature gate to be enabled (enabled by default)." type: integer format: int32 + nodeAffinityPolicy: + description: "NodeAffinityPolicy indicates how we will treat Pod's nodeAffinity/nodeSelector when calculating pod topology spread skew. Options are: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. \n If this value is nil, the behavior is equivalent to the Honor policy. This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag." + type: string + nodeTaintsPolicy: + description: "NodeTaintsPolicy indicates how we will treat node taints when calculating pod topology spread skew. Options are: - Honor: nodes without taints, along with tainted nodes for which the incoming pod has a toleration, are included. - Ignore: node taints are ignored. All nodes are included. \n If this value is nil, the behavior is equivalent to the Ignore policy. This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag." + type: string topologyKey: - description: TopologyKey is the key of node labels. Nodes that have a label with this key and identical values are considered to be in the same topology. We consider each as a "bucket", and try to put balanced number of pods into each bucket. We define a domain as a particular instance of a topology. Also, we define an eligible domain as a domain whose nodes match the node selector. e.g. If TopologyKey is "kubernetes.io/hostname", each Node is a domain of that topology. And, if TopologyKey is "topology.kubernetes.io/zone", each zone is a domain of that topology. It's a required field. + description: TopologyKey is the key of node labels. Nodes that have a label with this key and identical values are considered to be in the same topology. We consider each as a "bucket", and try to put balanced number of pods into each bucket. We define a domain as a particular instance of a topology. Also, we define an eligible domain as a domain whose nodes meet the requirements of nodeAffinityPolicy and nodeTaintsPolicy. e.g. If TopologyKey is "kubernetes.io/hostname", each Node is a domain of that topology. And, if TopologyKey is "topology.kubernetes.io/zone", each zone is a domain of that topology. It's a required field. type: string whenUnsatisfiable: description: 'WhenUnsatisfiable indicates how to deal with a pod if it doesn''t satisfy the spread constraint. - DoNotSchedule (default) tells the scheduler not to schedule it. - ScheduleAnyway tells the scheduler to schedule the pod in any location, but giving higher precedence to topologies that would help reduce the skew. A constraint is considered "Unsatisfiable" for an incoming pod if and only if every possible node assignment for that pod would violate "MaxSkew" on some topology. For example, in a 3-zone cluster, MaxSkew is set to 1, and pods with the same labelSelector spread as 3/1/1: | zone1 | zone2 | zone3 | | P P P | P | P | If WhenUnsatisfiable is set to DoNotSchedule, incoming pod can only be scheduled to zone2(zone3) to become 3/2/1(3/1/2) as ActualSkew(2-1) on zone2(zone3) satisfies MaxSkew(1). In other words, the cluster can still be imbalanced, but scheduler won''t make it *more* imbalanced. It''s a required field.' @@ -4057,7 +4223,7 @@ spec: description: 'medium represents what type of storage medium should back this directory. The default is "" which means to use the node''s default medium. Must be an empty string (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' type: string sizeLimit: - description: 'sizeLimit is the total amount of local storage required for this EmptyDir volume. The size limit is also applicable for memory medium. The maximum usage on memory medium EmptyDir would be the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the limit is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir' + description: 'sizeLimit is the total amount of local storage required for this EmptyDir volume. The size limit is also applicable for memory medium. The maximum usage on memory medium EmptyDir would be the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ anyOf: - type: integer @@ -4086,7 +4252,7 @@ spec: items: type: string dataSource: - description: 'dataSource field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. If the AnyVolumeDataSource feature gate is enabled, this field will always have the same contents as the DataSourceRef field.' + description: 'dataSource field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef, and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. If the namespace is specified, then dataSourceRef will not be copied to dataSource.' type: object required: - kind @@ -4102,7 +4268,7 @@ spec: description: Name is the name of resource being referenced type: string dataSourceRef: - description: 'dataSourceRef specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any local object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the DataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, both fields (DataSource and DataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. There are two important differences between DataSource and DataSourceRef: * While DataSource only allows two specific types of objects, DataSourceRef allows any non-core object, as well as PersistentVolumeClaim objects. * While DataSource ignores disallowed values (dropping them), DataSourceRef preserves all values, and generates an error if a disallowed value is specified. (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled.' + description: 'dataSourceRef specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the dataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, when namespace isn''t specified in dataSourceRef, both fields (dataSource and dataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. When namespace is specified in dataSourceRef, dataSource isn''t set to the same value and must be empty. There are three important differences between dataSource and dataSourceRef: * While dataSource only allows two specific types of objects, dataSourceRef allows any non-core object, as well as PersistentVolumeClaim objects. * While dataSource ignores disallowed values (dropping them), dataSourceRef preserves all values, and generates an error if a disallowed value is specified. * While dataSource only allows local objects, dataSourceRef allows objects in any namespaces. (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled. (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled.' type: object required: - kind @@ -4117,10 +4283,28 @@ spec: name: description: Name is the name of resource being referenced type: string + namespace: + description: Namespace is the namespace of resource being referenced Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled. + type: string resources: description: 'resources represents the minimum resources the volume should have. If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' type: object properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers." + type: array + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + type: object + required: + - name + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object @@ -4131,7 +4315,7 @@ spec: - type: string x-kubernetes-int-or-string: true requests: - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object additionalProperties: pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ @@ -4746,7 +4930,7 @@ spec: - verbs properties: apiGroups: - description: APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of the enumerated resources in any API group will be allowed. + description: APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of the enumerated resources in any API group will be allowed. "" represents the core API group and "*" represents all API groups. type: array items: type: string @@ -4790,6 +4974,7 @@ spec: description: InstallModeType is a supported type of install mode for CSV installation type: string keywords: + description: A list of keywords describing the operator. type: array items: type: string @@ -4799,6 +4984,7 @@ spec: additionalProperties: type: string links: + description: A list of links related to the operator. type: array items: type: object @@ -4808,6 +4994,7 @@ spec: url: type: string maintainers: + description: A list of organizational entities maintaining the operator. type: array items: type: object @@ -4837,6 +5024,7 @@ spec: version: type: string provider: + description: The publishing entity behind the operator. type: object properties: name: @@ -4975,22 +5163,26 @@ spec: type: array items: type: string + x-kubernetes-list-type: atomic apiVersions: description: APIVersions is the API versions the resources belong to. '*' is all versions. If '*' is present, the length of the slice must be one. Required. type: array items: type: string + x-kubernetes-list-type: atomic operations: description: Operations is the operations the admission hook cares about - CREATE, UPDATE, DELETE, CONNECT or * for all of those operations and any future admission operations that are added. If '*' is present, the length of the slice must be one. Required. type: array items: description: OperationType specifies an operation for a request. type: string + x-kubernetes-list-type: atomic resources: description: "Resources is a list of resources this rule applies to. \n For example: 'pods' means pods. 'pods/log' means the log subresource of pods. '*' means all resources, but not subresources. 'pods/*' means all subresources of pods. '*/scale' means all scale subresources. '*/*' means all resources and their subresources. \n If wildcard is present, the validation rule will ensure resources do not overlap with each other. \n Depending on the enclosing object, subresources might not be allowed. Required." type: array items: type: string + x-kubernetes-list-type: atomic scope: description: scope specifies the scope of this rule. Valid values are "Cluster", "Namespaced", and "*" "Cluster" means that only cluster-scoped resources will match this rule. Namespace API objects are cluster-scoped. "Namespaced" means that only namespaced resources will match this rule. "*" means that there are no scope restrictions. Subresources match the scope of their parent resource. Default is "*". type: string diff --git a/vendor/github.com/operator-framework/api/crds/operators.coreos.com_installplans.yaml b/vendor/github.com/operator-framework/api/crds/operators.coreos.com_installplans.yaml index 8e9b85e371..b85b77c562 100644 --- a/vendor/github.com/operator-framework/api/crds/operators.coreos.com_installplans.yaml +++ b/vendor/github.com/operator-framework/api/crds/operators.coreos.com_installplans.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.8.0 + controller-gen.kubebuilder.io/version: v0.9.0 creationTimestamp: null name: installplans.operators.coreos.com spec: diff --git a/vendor/github.com/operator-framework/api/crds/operators.coreos.com_olmconfigs.yaml b/vendor/github.com/operator-framework/api/crds/operators.coreos.com_olmconfigs.yaml index 44dfcd937e..c6ebe96815 100644 --- a/vendor/github.com/operator-framework/api/crds/operators.coreos.com_olmconfigs.yaml +++ b/vendor/github.com/operator-framework/api/crds/operators.coreos.com_olmconfigs.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.8.0 + controller-gen.kubebuilder.io/version: v0.9.0 creationTimestamp: null name: olmconfigs.operators.coreos.com spec: @@ -50,7 +50,7 @@ spec: conditions: type: array items: - description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" type: object required: - lastTransitionTime diff --git a/vendor/github.com/operator-framework/api/crds/operators.coreos.com_operatorconditions.yaml b/vendor/github.com/operator-framework/api/crds/operators.coreos.com_operatorconditions.yaml index aa6bd41955..ef4b7bef73 100644 --- a/vendor/github.com/operator-framework/api/crds/operators.coreos.com_operatorconditions.yaml +++ b/vendor/github.com/operator-framework/api/crds/operators.coreos.com_operatorconditions.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.8.0 + controller-gen.kubebuilder.io/version: v0.9.0 creationTimestamp: null name: operatorconditions.operators.coreos.com spec: @@ -45,7 +45,7 @@ spec: overrides: type: array items: - description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" type: object required: - message @@ -95,7 +95,7 @@ spec: conditions: type: array items: - description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" type: object required: - lastTransitionTime @@ -162,7 +162,7 @@ spec: conditions: type: array items: - description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" type: object required: - lastTransitionTime @@ -209,7 +209,7 @@ spec: overrides: type: array items: - description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" type: object required: - message @@ -259,7 +259,7 @@ spec: conditions: type: array items: - description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" type: object required: - lastTransitionTime diff --git a/vendor/github.com/operator-framework/api/crds/operators.coreos.com_operatorgroups.yaml b/vendor/github.com/operator-framework/api/crds/operators.coreos.com_operatorgroups.yaml index b62f3996a9..f6794075b9 100644 --- a/vendor/github.com/operator-framework/api/crds/operators.coreos.com_operatorgroups.yaml +++ b/vendor/github.com/operator-framework/api/crds/operators.coreos.com_operatorgroups.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.8.0 + controller-gen.kubebuilder.io/version: v0.9.0 creationTimestamp: null name: operatorgroups.operators.coreos.com spec: @@ -99,7 +99,7 @@ spec: description: Conditions is an array of the OperatorGroup's conditions. type: array items: - description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n type FooStatus struct{ // Represents the observations of a foo's current state. // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge // +listType=map // +listMapKey=type Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" type: object required: - lastTransitionTime diff --git a/vendor/github.com/operator-framework/api/crds/operators.coreos.com_operators.yaml b/vendor/github.com/operator-framework/api/crds/operators.coreos.com_operators.yaml index e7dce32925..73b202874f 100644 --- a/vendor/github.com/operator-framework/api/crds/operators.coreos.com_operators.yaml +++ b/vendor/github.com/operator-framework/api/crds/operators.coreos.com_operators.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.8.0 + controller-gen.kubebuilder.io/version: v0.9.0 creationTimestamp: null name: operators.operators.coreos.com spec: diff --git a/vendor/github.com/operator-framework/api/crds/operators.coreos.com_subscriptions.yaml b/vendor/github.com/operator-framework/api/crds/operators.coreos.com_subscriptions.yaml index 3523401502..31e7ae877a 100644 --- a/vendor/github.com/operator-framework/api/crds/operators.coreos.com_subscriptions.yaml +++ b/vendor/github.com/operator-framework/api/crds/operators.coreos.com_subscriptions.yaml @@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.8.0 + controller-gen.kubebuilder.io/version: v0.9.0 creationTimestamp: null name: subscriptions.operators.coreos.com spec: @@ -643,6 +643,21 @@ spec: description: 'Resources represents compute resources required by this container. Immutable. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' type: object properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers." + type: array + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + type: object + required: + - name + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object @@ -653,7 +668,7 @@ spec: - type: string x-kubernetes-int-or-string: true requests: - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object additionalProperties: pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ @@ -987,7 +1002,7 @@ spec: description: 'medium represents what type of storage medium should back this directory. The default is "" which means to use the node''s default medium. Must be an empty string (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' type: string sizeLimit: - description: 'sizeLimit is the total amount of local storage required for this EmptyDir volume. The size limit is also applicable for memory medium. The maximum usage on memory medium EmptyDir would be the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the limit is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir' + description: 'sizeLimit is the total amount of local storage required for this EmptyDir volume. The size limit is also applicable for memory medium. The maximum usage on memory medium EmptyDir would be the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. The default is nil which means that the limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ anyOf: - type: integer @@ -1016,7 +1031,7 @@ spec: items: type: string dataSource: - description: 'dataSource field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. If the AnyVolumeDataSource feature gate is enabled, this field will always have the same contents as the DataSourceRef field.' + description: 'dataSource field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef, and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. If the namespace is specified, then dataSourceRef will not be copied to dataSource.' type: object required: - kind @@ -1032,7 +1047,7 @@ spec: description: Name is the name of resource being referenced type: string dataSourceRef: - description: 'dataSourceRef specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any local object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the DataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, both fields (DataSource and DataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. There are two important differences between DataSource and DataSourceRef: * While DataSource only allows two specific types of objects, DataSourceRef allows any non-core object, as well as PersistentVolumeClaim objects. * While DataSource ignores disallowed values (dropping them), DataSourceRef preserves all values, and generates an error if a disallowed value is specified. (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled.' + description: 'dataSourceRef specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the dataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, when namespace isn''t specified in dataSourceRef, both fields (dataSource and dataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. When namespace is specified in dataSourceRef, dataSource isn''t set to the same value and must be empty. There are three important differences between dataSource and dataSourceRef: * While dataSource only allows two specific types of objects, dataSourceRef allows any non-core object, as well as PersistentVolumeClaim objects. * While dataSource ignores disallowed values (dropping them), dataSourceRef preserves all values, and generates an error if a disallowed value is specified. * While dataSource only allows local objects, dataSourceRef allows objects in any namespaces. (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled. (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled.' type: object required: - kind @@ -1047,10 +1062,28 @@ spec: name: description: Name is the name of resource being referenced type: string + namespace: + description: Namespace is the namespace of resource being referenced Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled. + type: string resources: description: 'resources represents the minimum resources the volume should have. If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' type: object properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers." + type: array + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + type: object + required: + - name + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: description: 'Limits describes the maximum amount of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object @@ -1061,7 +1094,7 @@ spec: - type: string x-kubernetes-int-or-string: true requests: - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object additionalProperties: pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ diff --git a/vendor/github.com/operator-framework/api/crds/zz_defs.go b/vendor/github.com/operator-framework/api/crds/zz_defs.go index ea65d5c73e..6a98bd4bd7 100644 --- a/vendor/github.com/operator-framework/api/crds/zz_defs.go +++ b/vendor/github.com/operator-framework/api/crds/zz_defs.go @@ -85,7 +85,7 @@ func (fi bindataFileInfo) Sys() interface{} { return nil } -var _operatorsCoreosCom_catalogsourcesYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb4\x7b\x6b\x73\xdc\xb6\x92\xf6\x77\xff\x8a\x2e\xbd\x6f\x95\xa4\xec\x0c\x65\x25\xa7\xb2\x27\xb3\xb9\x94\x22\xdb\x59\x55\x62\x5b\x65\xd9\xde\xda\x63\x79\xd7\x18\xb2\x87\x83\x08\x04\x68\x00\x94\x34\x39\x75\xfe\xfb\x56\x37\x00\x92\x73\xe1\xcc\x48\x71\xf4\xc5\x16\x88\x6b\x5f\x9f\x7e\x00\x89\x5a\xbe\x47\xeb\xa4\xd1\x13\x10\xb5\xc4\x7b\x8f\x9a\x7e\x73\xd9\xcd\xdf\x5d\x26\xcd\xc9\xed\xe9\x93\x1b\xa9\x8b\x09\x9c\x37\xce\x9b\xea\x0d\x3a\xd3\xd8\x1c\x9f\xe1\x4c\x6a\xe9\xa5\xd1\x4f\x2a\xf4\xa2\x10\x5e\x4c\x9e\x00\x08\xad\x8d\x17\xd4\xec\xe8\x57\x80\xdc\x68\x6f\x8d\x52\x68\xc7\x25\xea\xec\xa6\x99\xe2\xb4\x91\xaa\x40\xcb\x93\xa7\xa5\x6f\x9f\x66\xdf\x65\x4f\x9f\x00\xe4\x16\x79\xf8\x5b\x59\xa1\xf3\xa2\xaa\x27\xa0\x1b\xa5\x9e\x00\x68\x51\xe1\x04\x72\xe1\x85\x32\x65\xd8\x84\xcb\x4c\x8d\x56\x78\x63\x5d\x96\x1b\x8b\x86\xfe\xa9\x9e\xb8\x1a\x73\x5a\xbd\xb4\xa6\xa9\x27\xb0\xb1\x4f\x98\x2f\x6d\x52\x78\x2c\x8d\x95\xe9\x77\x80\x31\x18\x55\xf1\xff\xe3\xe1\xc3\xb2\x57\xbc\x2c\xb7\x2b\xe9\xfc\xaf\xeb\xdf\x7e\x93\xce\xf3\xf7\x5a\x35\x56\xa8\xd5\x0d\xf3\x27\x37\x37\xd6\xbf\xea\x96\xa7\xe5\x72\xe1\x9d\xcd\xc3\x67\xa9\xcb\x46\x09\xbb\x32\xf6\x09\x80\xcb\x4d\x8d\x13\xe0\xa1\xb5\xc8\xb1\x78\x02\x10\x45\x18\xa7\x1a\x83\x28\x0a\x56\x8b\x50\x97\x56\x6a\x8f\xf6\xdc\xa8\xa6\xd2\xed\x52\xd4\xa7\x40\x97\x5b\x59\x7b\x16\xfd\xdb\x39\x42\x6d\xd1\xfb\x05\x8b\x04\xcc\x0c\xfc\x1c\xd3\xda\xed\x28\x80\xdf\x9d\xd1\x97\xc2\xcf\x27\x90\x91\x84\xb3\x42\xba\x5a\x89\x05\xed\xa6\xd7\x2b\xa8\xe9\x59\xf8\xd6\x6b\xf7\x0b\xda\xba\xf3\x56\xea\x72\xdb\x56\xa8\xdf\xfe\x7b\x08\xa2\x79\xbb\xa8\xd7\xb7\xb0\xd2\xb8\xef\xfa\x75\x33\x55\xd2\xcd\xd1\xee\xbf\x89\x76\xc8\xda\x1e\x2e\x37\x7c\x19\xd8\x48\x6f\xd2\xe4\x50\xd9\x9a\x33\xac\x2d\x70\x56\xae\x9f\xb1\x10\x3e\x35\x86\x4e\xb7\xa7\x42\xd5\x73\x71\x1a\x1b\x5d\x3e\xc7\x4a\x74\xf6\x60\x6a\xd4\x67\x97\x17\xef\xbf\xb9\x5a\xf9\x00\xcb\xd2\x59\xb2\x73\x90\x0e\x04\x58\xac\x8d\x93\xde\xd8\x05\x49\xeb\xfc\xea\xbd\x1b\xc1\xf9\x9b\x67\x6e\x04\x42\x17\xad\xe3\x41\x2d\xf2\x1b\x51\xa2\xcb\xd6\xf6\x6a\xa6\xbf\x63\xee\x7b\xcd\x16\x3f\x37\xd2\x62\xd1\xdf\x05\x89\x27\xc9\x64\xa5\x99\xe4\xdf\x6b\xaa\x2d\xad\xe9\x7b\x8e\x1c\x7e\x7a\x51\x6e\xa9\x7d\xe5\x84\x87\x24\x86\xd0\x0f\x0a\x0a\x70\xe8\xd8\x04\xa2\x8f\x61\x11\x65\x17\x4c\x43\x3a\x3a\xbf\x45\x87\x3a\x84\x3c\x6a\x16\x3a\x9e\x29\x83\x2b\xb4\x34\x90\xdc\xbd\x51\x05\x45\xc2\x5b\xb4\x1e\x2c\xe6\xa6\xd4\xf2\x8f\x76\x36\x07\xde\xf0\x32\x4a\x78\x74\x1e\xd8\x6b\xb5\x50\x70\x2b\x54\x83\x41\x94\x95\x58\x80\x45\x9a\x17\x1a\xdd\x9b\x81\xbb\xb8\x0c\x5e\x1a\x8b\x20\xf5\xcc\x4c\x60\xee\x7d\xed\x26\x27\x27\xa5\xf4\x29\x86\xe7\xa6\xaa\x1a\x2d\xfd\xe2\x84\xc3\xb1\x9c\x36\x14\x0e\x4f\x0a\xbc\x45\x75\xe2\x64\x39\x16\x36\x9f\x4b\x8f\xb9\x6f\x2c\x9e\x88\x5a\x8e\x79\xb3\x9a\xe3\x78\x56\x15\xff\xcf\xc6\xa8\xef\x0e\x57\xc4\xb7\xd1\x98\x21\x85\xcd\xad\xb2\xa6\xe0\x19\xac\x28\x0c\x0f\x67\xe9\x44\x4a\x4d\x24\x95\x37\xcf\xaf\xde\x42\xda\x40\x10\x7b\x90\x70\xd7\xd5\x75\xc2\x26\x41\x49\x3d\x43\x1b\x7a\xce\xac\xa9\x78\x16\xd4\x45\x6d\xa4\xf6\xc1\xa5\x95\x44\xed\xc1\x35\xd3\x4a\x7a\xc7\x36\x87\xce\x93\x1e\x32\x38\xe7\x14\x06\x53\x84\xa6\x26\x4f\x2a\x32\xb8\xd0\x70\x2e\x2a\x54\xe7\xc2\xe1\x5f\x2e\x6a\x92\xa8\x1b\x93\xf8\xf6\x17\x76\x3f\x03\xaf\x0f\x58\xf3\x31\x80\x94\x21\xf7\xea\x3c\xe4\x94\x10\x3c\x70\x53\x04\x86\x2d\xbe\x48\x3f\xa2\x28\x2c\xba\x0d\x1f\xd6\x1c\x32\x74\x0c\x76\x32\x37\x8e\xf4\x27\x3c\xbc\xfe\xed\x25\xe4\x42\x43\xe3\x90\x9c\x27\x37\x5a\x93\x41\x78\x03\x82\x72\xd9\x18\xef\xa5\x63\x03\xb2\x58\x4a\xe7\xed\x22\x83\x17\xc6\x56\xc2\x4f\xe0\xfb\xd4\x34\xe6\xe9\x8c\x05\x59\xff\x38\xf9\xbe\x36\xd6\xff\x08\xaf\xb5\x5a\xd0\xa4\x05\xdc\xcd\x51\xc3\x55\x7b\x36\xf8\xa1\xf7\xcb\x2f\xb6\xce\x33\xb8\x28\xb5\xb1\xa9\x27\x59\xd5\x45\x25\x4a\x84\x99\x44\xc5\x76\xed\xd0\x67\xab\x1a\xdc\xaa\x45\x08\x70\x69\x26\xcb\x97\xa2\xde\x29\x9a\xf3\xd4\x93\xd6\xa2\xe5\xfb\xc9\xbb\xfb\xe8\x0d\x9b\x32\x1d\x89\xfe\x2b\xf2\x1b\x10\x71\x95\x4a\xd4\x63\xc7\x6e\xd3\x13\xd3\x7e\x12\x38\x4f\x13\x90\xfc\xba\xe6\x8b\x18\xb9\xb2\x87\x1e\xbb\x7f\xb2\x07\x8f\xed\x60\xc8\x4e\xa1\xbd\xdc\x94\x45\xf6\x58\xa3\xb4\x75\x7e\x69\x8a\x70\xec\x9d\xab\xfc\xd2\xef\x0d\x78\x5f\x1b\x87\x0e\x0a\x39\x9b\xa1\xa5\xb8\x63\x6e\xd1\x5a\x59\xa0\x83\x99\xb1\xac\xaf\xda\x14\xec\x93\xad\xfe\x96\x52\xed\xa5\x29\xf6\x55\x0c\x2d\xcd\x09\x23\x18\x63\x34\xc3\xc1\xe3\x6e\xf4\x76\xd8\xe1\xbc\xf4\xa3\x4d\x81\x57\xa8\x30\xf7\xc6\x6e\xee\xb1\x22\x93\x57\xbd\x01\x31\xea\xa7\xdf\xee\xe6\x32\x9f\x43\xd5\x38\x8e\xba\xde\x36\xb8\x24\x17\x6f\x60\x26\x3d\x18\x0d\x82\x97\xa5\x58\xbf\x3e\xb2\x12\x3e\x9f\xc7\x1e\x87\x0e\x94\x98\xa2\x72\xab\xf3\x4c\x91\x53\x6e\xd1\x28\x2c\x68\x42\x8e\x25\x3c\xe7\xc0\x11\x76\x48\x09\x42\x28\x6b\xf1\xf6\x76\x99\xc1\x2e\x2b\x0b\x82\x97\xc6\x4a\xbf\x38\x57\xc2\xb9\x21\x9b\x5e\x93\xee\xc5\x8c\xcd\x47\xce\x24\x16\x23\x90\xba\x90\x54\xd2\xb8\x74\xf6\x43\xd7\xce\x9b\x51\x5f\x4a\x70\xbd\xfe\x49\x42\xa9\x0f\xdc\x49\xa5\x48\x58\x05\xce\x44\xa3\x38\x48\xfe\x81\xd6\x80\x64\xeb\xb4\x6c\x57\xda\xa4\xcf\xdb\x85\xb7\xe5\xac\x0e\xf3\x86\xcf\x6a\xb4\xc7\x7b\x3f\xec\x5d\x6b\xe7\x3d\xb8\xda\x34\x94\x53\xc2\x14\xc1\x68\x0e\x84\x9f\x14\x96\x22\x5f\x7c\xa2\xed\x7f\xb2\x48\x1b\xc9\x3d\x16\x9f\x32\xc6\xf9\x4b\x2e\x46\x02\x32\x1c\xb5\x51\xd2\x09\x41\x6a\x52\x39\x39\x9b\xf4\x73\x16\x90\x95\xe5\xdc\x53\xaf\x58\x78\x2c\x6f\x80\x7d\xae\xfd\x48\xa9\x5f\x48\x8d\xf6\xc3\x57\x1f\xd7\x7a\x06\xc8\xc6\xb9\x4a\x29\x73\xd7\xb7\x4f\xdb\x68\x90\x9a\xfc\x1d\xd2\x01\xe1\xac\xa8\xa4\x63\x44\x7a\x74\x79\x75\x76\xbc\x74\x12\xa8\x4c\x81\x23\x3a\x5f\x61\xd0\xe9\x43\x4f\xde\x4e\x13\x3a\x4c\xcb\x08\x4f\xcb\x90\x4d\x44\x6f\xc9\x05\xe5\xcc\xb8\x26\x09\xcc\x50\x60\x99\x62\xbb\xf8\xd5\x19\x7c\x9a\x0a\x87\x4a\x6a\x0c\xb2\xab\xad\xbc\x95\x0a\x4b\x5a\x51\xa7\xda\xd3\x65\x70\xde\x58\x8a\x67\x6a\x11\x0d\x03\x36\x6b\x45\x3a\x68\xf4\x8a\xb9\x25\xcb\x0a\x98\xaf\xaf\x2c\xea\xed\x08\x75\x5d\xf1\x88\x05\x65\x71\x91\xfa\xb1\x6e\xfc\x5c\xe8\x41\xe5\x12\x52\xa4\x89\xa5\x0e\xa3\x64\x11\xa0\x39\x5a\x6b\x6c\x06\xff\x45\xb1\xb3\xa1\x0a\x1b\x8c\x2a\xd0\xa6\xea\x0e\x24\xc5\x4b\x37\x4a\x42\x62\xc4\x1e\x71\x60\x14\xcc\x06\xc1\x0f\x9f\x39\x62\x7e\x0a\x38\xc8\xb8\x24\xed\x37\x83\x6b\x4d\x80\x52\xc0\xac\x21\x08\x98\x6a\x8b\xe0\x73\x7d\xd1\x24\x27\x4c\x13\xf4\x96\x1f\xb5\xdb\xae\x84\x8c\xa6\xd6\xd6\x19\x36\x10\x2c\x34\x97\x6c\xcf\xe7\x82\x21\x8b\x76\x39\x33\x03\x53\x57\x21\x02\xba\xa6\x26\xf8\xe3\xe8\xa4\x9a\x44\x93\x2f\xa5\x9f\xda\x14\x6e\xa3\x00\x68\x5b\xb5\xc5\x5a\xd8\x36\x62\x3b\x84\x7c\x2e\x34\xd5\x7a\x74\xd0\x16\x2b\x13\xf6\xa2\x65\xc5\xd4\x34\x9e\x6d\x2c\xfa\xea\xcc\x34\xba\x00\x0a\x2a\x1d\x9c\xbe\x69\xa6\x68\x35\x7a\x64\x44\x5d\x98\xdc\x11\x98\xce\xb1\xf6\xee\x24\x79\xd3\x49\x6d\x8a\x71\xfa\x65\x2c\x92\x93\x9c\x1c\x1e\x3c\x36\x1a\x41\x92\xfc\x04\x82\xae\x06\x7a\xa1\x6e\xaa\xe1\x00\x3f\xde\x3e\x98\x3a\x74\x62\xdc\xd8\xc9\x1b\x45\x65\x73\xc7\xe9\x6c\xda\x68\x9f\xb4\xe8\xfa\x03\x69\xa2\xc7\x59\x44\x70\x1e\xa2\xdb\xa1\xeb\x4f\xbd\x3d\x68\x0b\x6b\xc5\xd0\x11\xa4\xc7\x6a\x4b\x86\x5b\x27\x54\x28\xb6\x51\x2d\xd6\x6d\x94\x01\x80\xf7\x82\x72\x31\x17\xbf\xe1\x0b\x85\x2b\xbd\x00\xb2\xe7\x88\xf3\x39\xab\xc7\x3c\xe6\xad\xac\x15\xc2\xf7\x37\xb8\x18\x85\xca\x18\x67\x33\xcc\xfd\x8f\xd1\x9f\xa9\x0f\xf7\x67\xe7\x4e\xd4\xc3\xf7\xe9\x7f\x3f\x0e\x9d\x78\xaf\x2c\xbf\x1b\x11\x85\x9f\xb0\xa5\x6d\x3d\x56\x24\xf4\x9c\x07\xac\xa4\xec\x20\x81\x30\x17\xc9\x87\x8f\x95\xc1\xf3\xaa\xf6\x0b\xa8\x50\x68\x97\xf0\x0e\xc5\x8c\x5e\x67\x17\x23\x5c\x2f\xda\x72\x92\x69\x99\x02\xb6\x90\x57\xe6\x2a\xa2\xa0\x11\x5c\x5a\x9c\xa1\xed\x5a\x38\x91\xbd\x32\xcf\xef\x31\x6f\xfc\x20\x2e\xea\xcb\x6d\xab\x4b\xd1\xcf\x0d\x2e\x1e\x20\x90\x5f\x71\x91\x2a\x9a\x70\xb2\x1b\x5c\x04\x63\xe0\xa6\xce\x86\x44\x5d\x2b\x89\xa1\x68\xdf\x26\x99\x1b\x5c\x38\x46\x3d\x34\xfe\x26\xcc\x8e\xd4\x7f\xd4\x59\x49\x02\x9f\xcf\xa9\x6e\x74\xff\x11\xec\x35\x37\xd5\x54\xea\xb0\x58\x98\x3a\xa9\x82\x67\x4f\x02\xd5\x05\xff\xca\xcb\x7c\x09\x71\xa5\x4d\x3d\x40\x66\xaf\xd3\x39\x3a\x46\x04\x04\xed\xe8\xd0\x81\x45\x15\x3c\x7e\x2e\xeb\x44\x34\xf1\xd6\x33\x78\x4f\xe9\xb1\xa3\xc7\xd9\x36\x82\x04\xf8\x54\xcf\x3f\x37\x42\x65\xf0\x2c\x44\x45\x3e\x7d\x6c\x8a\x9d\x48\x90\x9f\x1b\x79\x2b\x14\x55\x35\xde\x50\xca\x2a\x72\x61\x0b\xce\x06\x91\xbd\x72\x26\x68\x4f\xb4\x80\x23\x79\x7b\xa7\x23\xc7\xcc\x19\xd4\xc2\x7a\x99\x37\x4a\xd8\xc4\xc8\x2f\xbe\x88\x44\x3b\xa3\xb9\xc2\xdc\xe8\x62\xab\x07\x0f\x46\xd7\x38\xb6\x2f\x63\x86\x51\x68\xa5\x29\xb8\x70\x93\x15\xae\x1a\xe9\xd1\x72\x71\x63\x66\xc9\xab\x5b\x17\x1b\x05\x54\x73\x27\x5d\x24\xb7\x5a\x02\x41\x06\x82\xe1\xb8\x17\x1e\x5b\xaf\xc8\xe0\xe7\x45\xca\x57\x23\x90\x3e\x20\x72\xc6\x7f\x09\xc3\x24\x93\x8d\xc2\xee\x1c\x6a\x66\x2c\x52\xd1\x7f\x54\x18\x1e\x83\xb7\x32\xf7\xc7\x19\xfc\x83\x20\x3e\x29\x5e\x63\x29\xbc\xbc\x6d\x31\x64\x42\x22\xde\xa2\x20\x4c\x2c\x1c\x3c\x85\x23\x1e\x06\xb2\xaa\xb0\x90\xc2\xa3\x5a\x1c\xc3\x74\xc1\xcb\xb8\x85\xf3\x58\xed\xa3\x3a\xa9\x3d\x96\x4b\xec\xf8\xfa\xcf\x2c\x12\x37\x52\xfb\x6f\xff\xb6\xa5\x27\x6f\xf6\x01\x9a\x7d\xcf\x90\x72\x29\xd4\x04\x94\xb9\xa2\xc2\x36\x07\x99\x36\x8a\xb4\x71\x43\xba\xe8\x0b\xa3\xce\xaf\x7a\xd8\x2f\x85\x99\x56\xc1\xbf\x93\x1d\x08\xb0\xc8\x17\x3c\xd1\x72\xff\x84\x8d\xcb\x7c\x1b\x61\x32\x98\xd1\x86\xf9\x3c\x60\x84\x42\xf0\xff\xdb\xbf\x0d\x10\x25\x81\x8d\x27\x9d\xaf\x73\x7e\xb0\x47\xa2\xec\x26\x1f\x52\xd6\x4e\xb7\x6e\x97\x7f\xd4\x0c\x0c\xf5\x77\x92\x38\x2d\x81\x42\x25\x52\xd4\xf7\x38\xf1\x64\xd0\x56\x78\x61\x36\x0a\x7e\x52\x3b\x2f\xb4\x97\x1c\xd9\x5a\x46\x2d\x31\x6c\x04\xbf\x1f\x42\xe2\xb0\xad\xc5\x40\x13\x8c\x2b\x72\xa6\x6b\xf1\xe1\xc1\x64\x5b\x2a\xf3\x77\xb3\xaf\x97\x89\x10\x08\x6b\x0a\xe7\x64\x49\x28\x13\xee\x90\xab\xe1\x98\x4e\x96\xd1\x66\xa8\x0a\x78\xa0\xfc\x83\xbd\xa9\x6a\x93\x80\xf4\x09\xf7\xe7\x46\xbb\xa6\xc2\x22\xc5\x8c\x02\x6b\xd4\x05\xea\x7c\xc1\x5c\xbf\xba\x45\x9b\xc1\x3b\x47\x9a\x82\xff\x94\x25\xd5\x7d\x71\xd1\x3e\x54\x62\x54\x40\xa9\x7a\x79\x07\xd2\x91\xe8\x66\x68\x2d\x16\xcc\xb6\x01\x61\xa0\x34\x03\x16\x2b\xfd\x1d\x14\x0d\xdf\x40\xac\x6e\xa2\x21\x39\x04\xba\xc0\x52\x51\x93\xe8\xb9\x96\x28\x09\x0e\x4f\x47\x2a\x4d\xb8\x6b\xe0\xfb\x30\x8a\x9d\xde\x74\x71\x54\x06\x82\xb8\x9d\x43\x6a\xff\xcd\xd7\x61\xde\xe5\x42\x98\x09\xec\x95\xc3\x70\xe1\xd6\xe8\x20\x7c\xec\xb3\x34\x29\xcc\x3c\x0d\x53\x6d\x1a\xc7\xe1\x58\x54\xab\x5b\xee\x62\xba\x15\xfa\x06\x0b\x50\x78\x2f\x73\x53\x5a\x51\xcf\x65\x2e\x94\x5a\xb0\x9b\x32\x49\x26\xbd\xe3\xaa\x7f\x0b\x99\x3d\x14\xc6\xdb\x8b\xd1\x07\x93\xba\x0e\x73\x8b\x7e\xf7\x05\xc1\x55\xe8\xd7\x25\x65\x2e\x97\xcd\x2c\x4d\x10\x6c\x24\xda\x5c\x62\xc1\x45\x9e\x93\x23\xb1\xe9\x52\xd5\x1e\x01\x48\xcf\x94\x33\xb8\xe0\x94\x3a\x45\xc7\x56\x7e\x83\x58\x07\x4b\x53\xd2\x79\x70\x15\x73\x2a\x4e\xea\x1c\x01\x45\x3e\x0f\xe2\xd4\x88\x89\x66\xf4\x56\x62\x80\x41\x94\x6a\x17\xad\x6e\x50\xfb\xcd\xa0\x66\x7b\xdd\xb5\xa5\xe6\xda\x2e\xc6\x36\xa6\xec\x96\x64\x17\x8b\x52\x4e\x8c\x37\xf1\xae\x7b\xf4\xf0\x80\xa5\xc3\xed\xd9\x95\x27\xf0\x51\xee\x8e\x35\xef\x96\xba\xb7\xb7\xaf\x73\x73\x97\xee\xe1\xd6\x9c\x9c\x19\x9b\xa4\xdb\x42\xba\x9c\x3c\x1d\x0b\x38\x37\xda\x31\x3e\x0d\xd7\xb1\x7c\x9d\x7a\x2b\x54\x30\x85\x34\x71\x6d\x94\x62\x97\x6f\x52\x39\x41\x38\x5e\x03\x56\x53\x2c\x0a\x2c\xe8\x58\x61\x2b\x03\x69\xee\x4f\x12\xe8\x29\x3f\x5c\x1a\xa5\xb6\x67\xb1\xad\x75\xe9\x3e\x55\x69\x12\xc0\x36\x6c\xb4\x9c\xfa\x92\xc4\x22\x17\x47\x36\x5d\xa0\x47\x5b\x49\x1d\xe1\x11\x41\xdd\x56\xb0\x53\xf4\x77\x88\x1a\xf2\x39\xe6\x37\xad\x2b\xc5\xdb\xec\x15\xad\x45\xfe\x69\x39\x62\x75\x0f\x05\x8c\x52\x5c\x68\x38\x44\x90\x54\x13\x68\xbc\xeb\x73\x56\x1b\xd2\x0d\xa5\xe8\x5b\x21\x95\x98\x2a\xe4\xac\xd9\xfe\x36\x5a\xba\x55\x4f\xf9\xbc\x6e\x94\x22\x10\xab\x0b\x28\xdf\x5c\x9e\x83\xb7\x62\x36\x93\x39\x7d\x2a\xa4\x0d\xac\xef\xf2\x85\xfc\xf2\x82\xdb\xe0\xda\xa0\x47\x38\x2f\x7c\xb3\xa6\xa3\x2d\x0a\xde\xa6\x58\xaa\x43\xe4\x20\x41\xb4\xa4\xca\x37\xcb\xc5\x0a\x6d\x03\x43\xb1\xb5\xc4\x7f\x67\xf0\xca\x70\x8d\x20\x3c\xbc\x44\x47\x69\x97\x05\xf4\x06\x85\x33\xba\x17\x5d\x19\xfd\x5a\x59\x4a\x2d\x54\x3c\x54\x9f\xdf\x6b\x6b\x0f\xc1\x94\x72\x25\x4b\x2b\x7c\x1b\x14\xbb\x7d\xc7\xec\x12\xf3\x62\x60\x42\x33\x38\xd3\x0b\xd6\xf7\x0c\x05\x35\xd0\xcc\xde\x9a\xa2\xc9\x99\x87\x57\x8a\xaf\x7b\xbb\x49\xbe\x68\x18\x5d\xbe\x5e\x38\x4f\x8b\x24\xa0\xe7\xc8\x01\x84\x8c\x57\x4a\x46\x23\x08\x57\x53\x1d\x97\x6c\x32\x50\xe1\x9d\x80\x39\x59\x9c\x5d\x5e\x40\x7a\x30\x97\xc1\x78\x3c\x86\xb7\xd4\xec\xbc\x6d\x72\xce\x2f\xe4\x42\xba\x88\x99\x22\x58\x1f\x1f\x52\x30\xec\xe4\x63\x40\x64\x3e\x02\x04\xab\x85\x9f\x43\x16\x04\x9f\xf5\x44\x01\xf0\x82\x72\xcd\xbd\xa8\x6a\xb2\xfb\x6b\x1d\xa2\xf7\x0b\x63\xae\x82\x92\xc2\x9a\xff\x84\x93\x93\x55\x9b\x30\x53\x82\xa8\x91\x40\x64\xd3\x98\x19\x73\xe8\x96\x8f\x94\xd1\xc0\x5f\xb5\xb9\xd3\x9b\x56\xe7\xb5\x84\xc5\x09\x5c\x1f\x9c\x25\xef\xbb\x3e\x18\xc1\xf5\xc1\xa5\x35\x25\xc1\x56\xa9\x4b\x6a\x20\xa3\xba\x3e\x78\x86\xa5\x15\x05\x16\xd7\x07\x34\xed\xbf\xd5\x54\x61\xbd\x44\x5b\xe2\xaf\xb8\xf8\x81\x27\x6b\x9b\x53\x46\xf8\xa1\xa2\xef\xdc\x4e\x29\x98\xf2\xd4\x0f\x95\xa8\xdb\x86\x97\xa2\x6e\x07\x9f\x77\x76\xf6\xe1\x63\x85\x5e\xdc\x9e\x66\x9d\x46\x3f\xfd\xee\x8c\x9e\x5c\x1f\x74\xfb\x1f\x99\x8a\x2c\xa3\xf6\x8b\xeb\x03\x58\x5a\x75\x72\x7d\xc0\xeb\xa6\xf6\xb4\xc9\xc9\xf5\x01\xad\x44\xcd\xd6\x78\x33\x6d\x66\x93\xeb\x83\xe9\xc2\xa3\x1b\x9d\x8e\x2c\xd6\x23\x02\x4c\x3f\x74\x2b\x5c\x1f\x7c\x22\x9d\x9c\x9c\xc4\x2b\x0c\x56\xa6\x83\x7f\x6d\x26\xab\x77\xc6\xfd\xed\xf5\x1b\x93\xd0\xc2\xf9\xb7\x56\x68\x27\xd3\xfb\xb1\xc1\xae\x55\xf0\xf7\xc1\xef\x96\x63\xc0\xe0\xe7\x60\x0d\x83\x9f\x07\xb2\xe7\x3e\x99\x6b\xfd\x0c\x7b\xb2\xce\xeb\x03\x13\xa4\xa1\x2f\x1d\x4f\xd3\xea\x87\x72\x40\xec\x4d\xbe\x48\x38\x9e\x5c\x3c\xc6\x37\x42\x8c\x9a\xf5\x96\x45\xff\x6d\x0b\xfc\xf6\xed\x47\xa3\x0b\xb4\x8a\x2f\xab\xba\x59\xc3\x4d\x48\x91\x41\xe0\x0d\x44\xcb\xd2\xdc\x90\x23\x71\x76\xd2\x3d\xf2\x9a\xf7\xd5\xce\x48\xb1\x23\xf8\x7c\x9c\x86\x13\x5d\x9e\x63\xed\x39\xd3\x3d\xfe\x8a\x19\x7a\xa4\x0a\x21\xab\xb1\x1f\x36\x8f\x68\x1c\x7b\x0a\x3e\xf6\x8e\xaf\x75\x9a\x4a\x50\xea\x10\x05\xed\xb7\xfb\x16\xca\xb7\x50\x6e\x85\x90\x1a\x2e\x85\x02\xc7\x9f\xf4\x10\x45\x1d\x13\x09\x03\xb3\xda\x2f\x76\x32\x26\x7b\x1d\xbe\x12\xf7\xbf\xa1\x2e\xfd\x7c\x02\xdf\x7c\xfd\xef\xdf\xfe\x7d\xa0\x63\x08\x8c\x58\xfc\x82\x3a\x72\x41\x7b\x8a\x61\x7d\xe0\x2a\x69\xd8\x3d\xf1\x2c\xbb\x3e\x2d\xc9\xdd\x59\xd0\x9d\xe0\x07\x1c\x31\x5d\x36\x35\xc9\x85\x02\x7d\xe0\x1a\x72\x1c\x11\x48\xda\x38\x99\x6c\x03\xb8\x5a\xc0\xe9\xd7\x23\x98\x46\x11\xaf\x87\xef\x0f\xf7\x1f\xb3\x0d\x5b\x96\x0e\xbe\x1b\xad\xec\x47\x3a\x20\x55\x99\x19\x1b\x4e\x28\x31\x2d\x86\x4c\x98\xc8\x80\xf5\x4c\x88\xed\x7e\x77\x29\x6e\x17\x1f\xb8\x1f\x17\x58\x49\x2d\xab\xa6\x9a\xc0\xd3\x81\x2e\x21\xa4\xed\xa9\xcd\xd0\xb9\x03\x02\x82\x42\x57\x69\x45\x45\x90\x27\x07\x59\xa0\xf6\x72\x26\xf9\xd1\x40\x6b\xda\x5c\xee\x87\x81\xe9\x0d\x4a\x2b\x45\x7e\x9e\x42\x71\xa8\x67\xec\x97\x01\xe7\x58\xce\xc0\xf1\xf6\x26\xef\x07\xa8\x45\x8d\xc1\x1b\x42\x01\x03\x78\x5f\x07\xa8\xda\xbb\x86\xa8\x50\x68\xa9\xcb\xf4\xec\x25\x71\xc9\x21\xeb\xde\xcd\x31\xde\x9e\x63\xff\x2e\x28\xa7\x62\xa9\xe0\xba\x49\x40\xd9\x08\x2b\xb4\xa7\x32\xf6\xec\xf2\x22\x60\xf4\x55\x4e\x53\x74\x6f\x21\x93\x37\x06\x57\x0d\xc1\x8a\xb6\x18\xef\xcd\xd9\x63\xbf\x9c\xab\x9e\x3e\xfd\x7a\xab\xca\xdb\x7e\xc3\x57\x78\xc2\x7b\xb4\x7a\x02\xff\xf3\xe1\x6c\xfc\x0f\x31\xfe\xe3\xe3\x51\xfc\xcf\xd3\xf1\x77\xff\x3b\x9a\x7c\xfc\xaa\xf7\xeb\xc7\xe3\x9f\xfe\xff\xc0\x4c\x9b\xc1\xfc\x80\xf9\xc4\x24\x92\x70\x62\xd2\xe8\x28\xbd\x52\x79\x6b\x1b\x1c\xc1\x0b\xa1\x1c\x8e\xe0\x9d\xe6\xd4\xf0\x27\x85\xb6\xfd\x86\x9a\xb2\xf2\x01\xad\x3a\x74\x53\x1e\xbb\xf0\x96\xb6\xf7\x89\xdb\xdd\x56\xbe\xee\x27\xa4\x44\x35\xf4\x22\x4d\xef\xcd\x2d\x3f\xd2\x24\x47\x32\x59\x44\xb8\x59\x6e\xaa\x93\xde\x9b\x5c\x82\xd6\x2f\x85\x5e\x40\x17\xd6\x02\x28\x5d\xb5\x74\xe7\x29\x36\x89\xdc\x1a\xe7\xda\x47\xc5\x0e\x94\xbc\x41\x38\xeb\xea\x46\x0a\x96\x53\xcc\x05\x63\x71\x3b\x95\xde\x8a\x40\xfa\x26\x5c\xd9\x31\x4a\xb3\x46\xc1\x11\x95\xab\x19\x3f\x24\x5b\x8b\xae\xc7\x91\xbd\x9d\x4a\x25\xfd\x22\x94\xd2\xb9\xd1\x33\x25\x63\x09\x50\xd5\xc6\x7a\xa1\x7d\xe4\x19\xb1\xc4\x7b\x90\xdd\xd5\xb7\x74\x70\x54\x68\x77\x7a\xfa\xf5\x37\x57\xcd\xb4\x30\x95\x90\xfa\x45\xe5\x4f\x8e\x7f\x3a\xfa\xdc\x08\xc5\xb7\xbc\xaf\x44\x85\x2f\x2a\x7f\xfc\xe5\xd2\xe2\xe9\xb7\x7b\x78\xd1\xd1\x87\xe0\x2b\x1f\x8f\x3e\x8c\xe3\xff\xbe\x4a\x4d\xc7\x3f\x1d\x5d\x67\x5b\xbf\x1f\x7f\x45\x67\xe8\x79\xe0\xc7\x0f\xe3\xce\xfd\xb2\x8f\x5f\x1d\xff\xd4\xfb\x76\xbc\xc9\x19\xef\xc7\xdd\x53\x91\x31\x55\x01\xe3\x4a\xd4\xe3\x1b\x5c\x0c\x38\xe7\x20\x1c\x5d\x9f\x28\x48\xac\x12\xf5\xa6\xea\x3b\xbc\xad\x7d\x83\xfc\x9e\x33\xdf\x68\xe4\x7f\xf2\x06\x46\x8b\x01\x48\x36\xee\x5e\x60\x3d\x82\x75\xa2\xbc\x13\x98\xb6\x6d\x70\x7a\x0f\x6b\xd9\x0f\x3f\xea\x2d\xef\x17\x77\x2e\xd2\x9e\xf3\xd1\x33\x24\xff\x1e\xf8\xd3\x8f\xbd\xe7\x69\xe4\x60\xa5\xb5\xcc\x61\x5e\x3c\x0b\xd0\x97\x43\x0f\xc3\xb9\xb9\xa1\x3a\xaf\xd1\xf2\x73\x83\x70\xf1\x2c\xc6\xa3\x11\x48\x9d\xab\xa6\x20\xa4\xf0\xee\xdd\xc5\x33\xaa\xdf\x7f\x8e\xe1\xe6\x0e\xa1\x30\xfa\xd0\xc3\xeb\x57\xbf\xfd\x37\x93\x01\xdc\x63\x14\x12\x7a\xb8\x8f\x12\x4a\x86\xbf\x1a\x49\x09\x18\x7e\xc6\xf0\x4e\x8e\x57\xce\x45\xdd\xf2\x27\x1c\xee\xf8\x85\x95\xaa\x09\x40\xdc\x20\xb8\xc6\xc6\xdd\xd1\xc4\xe1\xc6\x97\x64\x0d\xf1\x3e\xb8\x44\xcf\x46\xae\xf8\xaf\x1f\x1e\x23\xb4\xf8\x1e\x5f\x1a\x7d\x45\x28\xf0\x2f\xf0\x0f\x32\xe4\xd7\x11\xb3\xf2\x1a\x8f\x70\x86\x2d\x7f\x84\xb0\xf3\x84\x10\x9d\xe9\x3c\x9c\xf4\x2f\xf7\xa4\xb5\xf3\x3e\x6a\xc5\xc0\x67\xf2\xcd\xe6\x9b\x1d\xfc\xf3\xda\x33\xae\xe5\xd2\x79\xe5\x6f\xc1\x98\x5b\x6d\x2f\x47\xe7\xc2\xc1\x14\x51\x33\x9d\x1b\xd8\x3f\xd4\xd1\xea\xb0\x23\x62\x9b\x7a\xec\xcd\xb8\xd8\xac\xbc\x1d\x92\xdb\x2d\xb5\x2d\x95\xeb\xd2\xd9\xce\x1e\x5c\xa8\xde\xcd\x17\x9b\x64\xe0\x02\x9d\xc9\x0f\x87\x12\x06\x79\xe8\xc1\x86\x0b\x93\x15\x56\x97\x2b\x8b\x48\x6a\xc4\x3a\x63\x7d\x4b\x54\x3d\x2e\x31\x1b\xde\xf0\x6d\xde\x32\xb3\xf7\xf0\x3d\x06\x35\x5f\xa1\xbd\x95\x8f\x4a\x7e\xbb\x1c\x33\x0f\xef\x4c\xce\xfe\x7a\xb7\x22\xe8\xf5\xe8\x45\x98\xfa\xcb\xcd\x8e\xeb\x9b\xad\xef\xdf\x59\x82\xdb\x5e\xf9\x3f\x64\x8e\x87\x26\xcb\x10\x4d\x26\xfc\x17\x17\xa9\xc9\x1b\xcb\x57\xee\xfd\xb6\x66\xda\x02\xe5\x6e\xf6\x58\x03\xc1\x3f\xff\xf5\xe4\xff\x02\x00\x00\xff\xff\x4a\xcc\x94\x67\x43\x3e\x00\x00") +var _operatorsCoreosCom_catalogsourcesYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\xfb\x73\xdc\x36\x92\xff\xef\xfe\x2b\xba\xf4\xfd\x56\x49\xca\xcd\x50\x76\xb2\x95\xdb\xd5\xe6\x51\x5a\x39\xce\xa9\x12\xdb\x2a\xcb\xc9\xd6\xad\xe5\x3b\x63\xc8\x1e\x0e\x22\x12\x60\x00\x50\xf2\x24\x95\xff\xfd\xaa\x1b\x00\xc9\x79\x3f\x64\xc7\x76\x2d\xf9\x8b\x35\x24\x9e\x8d\x46\xf7\xa7\x1f\x80\x45\x25\x7f\x46\x63\xa5\x56\xa7\x20\x2a\x89\x6f\x1d\x2a\xfa\x65\x93\x9b\xbf\xda\x44\xea\x93\xdb\x47\x0f\x6e\xa4\xca\x4e\xe1\xbc\xb6\x4e\x97\x2f\xd0\xea\xda\xa4\xf8\x18\xc7\x52\x49\x27\xb5\x7a\x50\xa2\x13\x99\x70\xe2\xf4\x01\x80\x50\x4a\x3b\x41\xaf\x2d\xfd\x04\x48\xb5\x72\x46\x17\x05\x9a\x61\x8e\x2a\xb9\xa9\x47\x38\xaa\x65\x91\xa1\xe1\xc6\x63\xd7\xb7\x0f\x93\xbf\x25\x0f\x1f\x00\xa4\x06\xb9\xfa\x4b\x59\xa2\x75\xa2\xac\x4e\x41\xd5\x45\xf1\x00\x40\x89\x12\x4f\x21\x15\x4e\x14\x3a\xf7\x83\xb0\x89\xae\xd0\x08\xa7\x8d\x4d\x52\x6d\x50\xd3\x3f\xe5\x03\x5b\x61\x4a\xbd\xe7\x46\xd7\xd5\x29\x2c\x2d\xe3\xdb\x8b\x83\x14\x0e\x73\x6d\x64\xfc\x0d\x30\x04\x5d\x94\xfc\x77\x98\xbc\xef\xf6\x8a\xbb\xe5\xf7\x85\xb4\xee\x87\xc5\x6f\x3f\x4a\xeb\xf8\x7b\x55\xd4\x46\x14\xf3\x03\xe6\x4f\x76\xa2\x8d\x7b\xd6\x76\x4f\xdd\xa5\xc2\x59\x93\xfa\xcf\x52\xe5\x75\x21\xcc\x5c\xdd\x07\x00\x36\xd5\x15\x9e\x02\x57\xad\x44\x8a\xd9\x03\x80\x40\xc2\xd0\xd4\x10\x44\x96\xf1\xb2\x88\xe2\xd2\x48\xe5\xd0\x9c\xeb\xa2\x2e\x55\xd3\x15\x95\xc9\xd0\xa6\x46\x56\x8e\x49\xff\x72\x82\x50\x19\x74\x6e\xca\x24\x01\x3d\x06\x37\xc1\xd8\x77\x53\x0b\xe0\x17\xab\xd5\xa5\x70\x93\x53\x48\x88\xc2\x49\x26\x6d\x55\x88\x29\x8d\xa6\x53\xca\x2f\xd3\x63\xff\xad\xf3\xde\x4d\x69\xe8\xd6\x19\xa9\xf2\x75\x43\xa1\x72\xdb\x8f\xc1\x93\xe6\xe5\xb4\x5a\x1c\xc2\xdc\xcb\x6d\xfb\xaf\xea\x51\x21\xed\x04\xcd\xf6\x83\x68\xaa\x2c\x8c\xe1\x72\xc9\x97\x15\x03\xe9\x34\x1a\x37\x54\xb2\xb0\x19\x16\x3a\x38\xcb\x17\xe7\x98\x09\x17\x5f\xfa\x42\xb7\x8f\x44\x51\x4d\xc4\xa3\xf0\xd2\xa6\x13\x2c\x45\xcb\x0f\xba\x42\x75\x76\x79\xf1\xf3\x17\x57\x73\x1f\x60\x96\x3a\x33\x7c\x0e\xd2\x82\x00\x83\x95\xb6\xd2\x69\x33\x25\x6a\x9d\x5f\xfd\x6c\x07\x70\xfe\xe2\xb1\x1d\x80\x50\x59\xb3\xf1\xa0\x12\xe9\x8d\xc8\xd1\x26\x0b\x63\xd5\xa3\x5f\x30\x75\x9d\xd7\x06\x7f\xad\xa5\xc1\xac\x3b\x0a\x22\x4f\xa4\xc9\xdc\x6b\xa2\x7f\xe7\x55\x65\xa8\x4f\xd7\xd9\xc8\xfe\xe9\x48\xb9\x99\xf7\x73\x33\x3c\x24\x32\xf8\x72\x90\x91\x80\x43\xcb\x2c\x10\xf6\x18\x66\x81\x76\x9e\x35\xa4\xa5\xf9\x1b\xb4\xa8\xbc\xc8\xa3\xd7\x42\x85\x39\x25\x70\x85\x86\x2a\xd2\x76\xaf\x8b\x8c\x24\xe1\x2d\x1a\x07\x06\x53\x9d\x2b\xf9\x5b\xd3\x9a\x05\xa7\xb9\x9b\x42\x38\xb4\x0e\x78\xd7\x2a\x51\xc0\xad\x28\x6a\xf4\xa4\x2c\xc5\x14\x0c\x52\xbb\x50\xab\x4e\x0b\x5c\xc4\x26\xf0\x54\x1b\x04\xa9\xc6\xfa\x14\x26\xce\x55\xf6\xf4\xe4\x24\x97\x2e\xca\xf0\x54\x97\x65\xad\xa4\x9b\x9e\xb0\x38\x96\xa3\x9a\xc4\xe1\x49\x86\xb7\x58\x9c\x58\x99\x0f\x85\x49\x27\xd2\x61\xea\x6a\x83\x27\xa2\x92\x43\x1e\xac\x62\x39\x9e\x94\xd9\xff\x33\x41\xea\xdb\xc3\x39\xf2\x2d\x65\x66\x88\x62\x73\x2d\xad\x49\x78\x7a\x2e\xf2\xd5\xfd\x5c\x5a\x92\xd2\x2b\xa2\xca\x8b\xef\xae\x5e\x42\x1c\x80\x27\xbb\xa7\x70\x5b\xd4\xb6\xc4\x26\x42\x49\x35\x46\xe3\x4b\x8e\x8d\x2e\xb9\x15\x54\x59\xa5\xa5\x72\x7e\x4b\x17\x12\x95\x03\x5b\x8f\x4a\xe9\x2c\xf3\x1c\x5a\x47\xeb\x90\xc0\x39\xab\x30\x18\x21\xd4\x15\xed\xa4\x2c\x81\x0b\x05\xe7\xa2\xc4\xe2\x5c\x58\x7c\xef\xa4\x26\x8a\xda\x21\x91\x6f\x7b\x62\x77\x35\xf0\x62\x85\x85\x3d\x06\x10\x35\xe4\x56\x85\x57\x6d\x4a\xf0\x3b\x70\x99\x04\x86\x35\x7b\x91\x1e\x91\x65\x06\xed\x92\x0f\x0b\x1b\xd2\x17\xf4\x7c\x32\xd1\x96\xd6\x4f\x38\x78\xfe\xe3\x53\x48\x85\x82\xda\x22\x6d\x9e\x54\x2b\x45\x0c\xe1\x34\x08\xd2\x65\x43\x7c\x2b\x2d\x33\x90\xc1\x5c\x5a\x67\xa6\x09\x3c\xd1\xa6\x14\xee\x14\xbe\x8a\xaf\x86\xdc\x9c\x36\x20\xab\x6f\x4e\xbf\xaa\xb4\x71\xdf\xc0\x73\x55\x4c\xa9\xd1\x0c\xee\x26\xa8\xe0\xaa\x99\x1b\x7c\xdd\xf9\xf1\xbd\xa9\xd2\x04\x2e\x72\xa5\x4d\x2c\x49\x5c\x75\x51\x8a\x1c\x61\x2c\xb1\x60\xbe\xb6\xe8\x92\xf9\x15\x5c\xbb\x8a\xe0\xe1\xd2\x58\xe6\x4f\x45\xb5\x91\x34\xe7\xb1\x24\xf5\x45\xdd\x77\x95\x77\xfb\xd1\x69\x66\x65\x9a\x12\xfd\x29\xd2\x1b\x10\xa1\x97\x52\x54\x43\xcb\xdb\xa6\x43\xa6\xed\x28\x70\x1e\x1b\x20\xfa\xb5\xaf\x2f\x82\xe4\x4a\x76\x9d\x76\x77\x66\x3b\xd7\x6d\x61\xc8\x46\xa2\x3d\x5d\xa6\x45\xb6\xe8\x23\x37\x55\x7a\xa9\x33\x3f\xed\x8d\xbd\x7c\xdf\x2d\x0d\xf8\xb6\xd2\x16\x2d\x64\x72\x3c\x46\x43\x72\x47\xdf\xa2\x31\x32\x43\x0b\x63\x6d\x78\xbd\x2a\x9d\xf1\x9e\x6c\xd6\x6f\x46\xd5\x5e\xea\x6c\xdb\x85\xa1\xae\x59\x61\x78\x66\x0c\x6c\xb8\x72\xba\x4b\x77\x3b\x6c\xd8\xbc\xf4\x88\x31\xc3\xff\xe9\xf2\xaf\x73\xf4\x38\x0b\x85\x23\xa7\x06\x44\x15\x44\xc7\xa1\xa5\xe9\x1f\xda\xa6\xcd\x65\xc3\xdd\x62\xc8\xdb\x0c\x9b\x1e\xa5\x33\x3c\xdb\x30\xfc\x85\x29\x3c\xe6\x1f\x23\xb4\x5c\xbd\x19\x2a\x6b\xf0\xac\x2e\x58\xd4\xd4\xc5\xec\x8a\xae\x9a\xc7\x96\x73\xd9\x76\x3e\xbe\x1c\x8e\xd1\x18\xcc\x1e\xd7\xc4\xbf\x57\xcd\xa8\x82\x90\xf2\xaf\xbf\x7b\x8b\x69\xbd\x6a\x8f\xad\x9c\x3a\x81\xe2\x30\x4d\x34\x70\x27\x8b\x22\x74\x47\x02\x25\x7e\xa0\xf9\x32\x8e\x21\xf2\x58\x2f\xa4\xad\x70\xd2\x8e\xa7\x4c\x8e\x86\x60\xf8\x96\x74\x36\x5b\x2c\xcc\xf1\x72\x2c\x31\x83\xd1\x34\xa8\x6b\x12\x9e\x03\x18\xd5\x0e\xa4\x63\x5d\x9e\x4e\xb4\xb6\x08\xc2\xd3\x9d\xdb\xbd\x95\x9a\x91\x12\x68\x85\x24\x7f\x4a\x52\xc8\x61\xe3\x74\x9a\x4f\x78\xe4\x6d\x35\x69\xa1\x24\x89\xdf\xd0\x2a\xb2\x23\x35\x73\x27\xdd\x84\x7f\xe4\x04\xb9\x09\x85\xd9\xba\xa4\x46\xef\x50\xe6\x13\x67\x07\x20\x13\x4c\x78\x75\x51\xa4\x93\x4e\xb3\x25\xa2\xb3\x20\x8a\x22\x0e\xa1\xcb\x12\x5e\x6f\x96\x04\x51\xe0\xa8\xc1\x30\x01\x6f\x0c\x1a\xbd\x3a\xbf\x6a\x4b\xc9\x35\x00\x74\x69\x72\x3c\x80\x54\x97\x55\xed\x88\x26\x34\xc6\xd1\x14\xa4\x23\x9c\xed\xf1\x92\xd1\x75\xee\x67\x82\x45\xe8\x38\x82\x55\xaf\x99\x48\x38\x90\x8d\xa8\x72\x38\xf0\x93\x3b\x88\xf8\x93\x9a\x93\x7e\x12\x3c\xbf\x52\xb8\x74\x12\x20\x70\xaa\x8d\x41\x5b\x69\xc5\x35\xf9\xcb\x77\xed\xd8\xfe\xde\x54\x3a\xb2\xc7\x2d\x31\x27\x32\x9f\x44\x5a\x0a\x83\xfc\x6e\x76\x0d\xd6\xed\x91\x76\x9f\x08\x63\x66\x6c\xc9\x65\x8f\x74\x58\x6e\xd8\x25\x0b\xac\x7d\xa6\x00\xcb\xca\x4d\x3b\x3c\xd1\x59\x3d\x87\xa6\x6c\x68\xc0\x0b\xcc\xdb\xd5\xfa\xf9\xc9\xb2\x2a\x64\x2a\x5d\xe0\x10\x78\x08\x47\xcc\x22\xd2\x91\x28\x03\xa5\x87\xba\x3a\x4e\xe0\x8c\xdd\x17\x5b\x74\xa0\x74\xd3\x7e\x68\x88\x3a\xb5\xba\x6d\x6b\xe3\xdc\xb6\x14\x2a\xfe\x59\x8d\xe9\x16\x9f\x61\x18\x3f\xaa\x74\x1e\xe5\x2d\x2f\xee\x69\xb2\xb1\xe8\xb6\xe2\x2d\x96\x8e\x63\xd8\xa6\xf4\xfc\x52\x7b\x96\xb6\x58\x60\x4a\x26\x29\xd1\x7e\x00\xc2\x5a\x9d\x4a\x42\xf9\x2d\xd3\xce\x72\xba\x9f\xc9\x66\xda\xc3\xae\xf4\x87\x9d\xe7\x4f\xcf\xfc\xc6\xdb\xb6\xde\x02\x35\x0a\x49\xe0\x77\x3c\x47\x95\x19\x81\x35\x9a\xf2\xd7\x43\x0b\x85\x18\x61\x61\xb7\x23\x02\xec\xb4\x6b\xdb\x67\xcb\xfd\xbb\x72\x42\x2b\x27\x12\x6c\xcc\x66\xe1\x49\x68\x93\x6d\x26\xa4\xb2\xc1\x7e\x1e\x80\x80\x1b\x9c\x7a\x53\x9b\x2c\xf8\xe8\xb8\xe0\xc2\x06\xbd\xba\x21\xe6\xb8\xc1\x29\x17\x0a\x76\xf7\x0e\xc3\xdd\x99\x39\xfc\xb3\xcb\x36\x6d\x9f\x21\x0d\x74\xc7\x1a\x71\xd2\x3b\x54\xdb\x9d\x7f\xfd\x73\x83\x6b\x91\xd7\xb2\x67\x01\x92\x30\x4f\xf2\x7a\xf0\x22\xb1\xfe\x8a\x6b\x2c\xaa\xaa\x90\xc8\xf6\xfc\x8e\xdd\xac\xb5\x02\xd6\x3d\x91\x7a\xf7\x9a\xd7\x8b\xc6\xa1\xe1\x19\xf2\xd0\x7a\xe6\xa3\x9d\x3e\x91\x95\xb7\x6f\x2d\xf2\xc6\x8d\x9e\x9f\x9f\x45\x21\x5b\x57\x9b\x65\x3d\x7b\xa1\x06\xf0\x4c\x3b\xfa\xe7\x3b\xb2\x84\xed\x00\x1e\x6b\xb4\xcf\xb4\xe3\x9f\x09\x7c\xef\x3c\xaf\xff\xb8\xa5\x64\x7b\x07\x04\xf2\xe3\xbd\x17\x79\xce\x94\x97\x29\x34\xfd\xae\xcf\xc8\x26\x70\xe1\x61\x4b\xb3\x71\xa5\x85\x0b\x45\xe0\x30\x90\x81\xbd\x78\x5c\x36\x34\x51\xd6\x96\x9d\x3c\x4a\xab\x21\x63\x80\xa5\x6d\x78\xea\x51\x3b\x5d\xfa\xad\x69\x6e\x75\x53\xdf\xb3\xaf\xe1\xc7\x95\x95\x27\xe2\x96\x21\x9d\x54\x79\xd1\x80\xb7\x01\xdc\x4d\x64\x3a\xf1\xa8\x7b\x84\xde\x35\x58\x19\x24\x85\x25\x2c\x89\x2a\x7a\x93\xa3\x21\xb0\x2b\x63\x7b\xde\x31\x59\x88\x14\x33\xc8\x18\x5a\x7a\x27\x9b\x70\x98\xcb\x14\x4a\x34\x39\x42\x45\x9a\x64\xbf\xd5\xdf\x4d\xb0\xfb\x67\x67\xf1\xde\xed\x70\x27\x76\x63\x15\xf9\x84\xb0\xee\x9f\xa4\x1d\x19\x57\xf7\xda\xb1\xd7\x8e\x73\x4f\xaf\x1d\x9b\xa7\xd7\x8e\x1b\x9e\x5e\x3b\xf6\xda\xf1\xbd\x6b\x47\x6f\xcb\xee\x61\x3c\xff\xd3\xbb\x38\xe6\xad\x65\xd6\xb4\x31\x4c\x37\x6b\x36\x93\xbe\xb9\x0a\x02\xe7\x25\x9b\xda\xd2\x07\x49\x8c\x50\x39\xc2\xa3\xe1\xa3\x87\x0f\x77\x31\xaa\xc3\x42\x6e\x55\x63\x1c\x22\x3d\x52\xb9\x2f\x3e\x5f\x5b\x63\x95\xff\xed\x1d\x78\x4d\x03\x8f\x37\x8e\xbc\x19\xec\xb0\xc2\xf1\xc9\xd2\x49\x69\x07\x25\x3a\x10\x6e\xc6\x55\x24\x4b\x1c\x34\xa1\x02\x66\xf8\x10\xa5\x8c\x1e\xd8\x0c\xb4\x0a\x7e\x3c\x22\x7e\xb2\xdf\x08\x52\x14\x3e\xa4\x36\xc2\x66\x14\xba\xa4\x5e\xa5\x72\x71\xbb\xd0\x10\x30\x52\x05\x8e\x30\xc9\x13\xc8\x6a\xae\x26\x54\x08\x9b\x1e\xfb\xd1\xda\xa9\x75\x58\xb2\x27\x57\x1b\xfe\x87\x86\xed\xcc\x94\x0a\xe3\x2d\x2a\x57\x8b\xa2\x98\x02\xde\xca\xd4\x35\xf3\xe3\xa8\xad\x74\xde\xd9\xbe\x9d\x8b\x70\x2b\xe8\xb0\x3d\x5c\x18\x2e\x70\xb0\xdd\x50\x67\x17\x6d\xbf\xd0\xf6\x36\x7b\x72\x4e\x17\xfa\x99\x24\x2b\xc1\xaa\xa3\x76\xbd\x0f\x9c\xff\x64\xe6\x7a\xfe\x62\xb3\xcb\x15\x76\x96\x64\x3b\x48\xaf\x79\x58\x5a\x17\x05\x31\x86\xf7\xc2\x2e\x4e\x60\x89\x77\xd4\x4f\x69\x86\x99\xbd\xe3\xdd\xbb\x98\xcf\x9e\x3d\x26\xaa\x50\x99\x97\xba\xd2\x85\xce\xa7\x5d\x4a\xfb\xf4\x22\x59\x56\xd1\x39\x2e\xc0\xd6\xa3\x00\x1a\x88\xfd\x9e\xcd\x2d\x4d\xef\xf9\xeb\x3d\x7f\xbd\x6d\xb3\xf0\xf4\xb6\x4d\xf3\xf4\xb6\xcd\x86\xa7\xb7\x6d\x7a\xdb\xa6\xf7\xfc\x41\xaf\x1d\xd7\xd0\xa4\xd7\x8e\xd0\x6b\xc7\x95\xf3\xea\xb5\xe3\x5a\xf2\xf4\xda\xb1\xd7\x8e\xcb\x9e\x4a\x67\xf7\x48\x74\xac\x74\xb6\x26\xcf\xd1\x7b\x7d\x52\x3d\x2c\x74\x2a\x5c\xc8\xcb\xa7\x2a\xc1\xcf\x67\x45\xe9\x1d\x51\x03\xf8\x4d\x2b\xf4\xc9\x6b\xb4\x36\xec\x4e\xd2\x6e\x82\x86\x8a\x1f\xd9\xe3\xb5\x89\x4d\x7d\x9e\x64\x9f\x27\xf9\xd1\xe7\x49\x4e\x84\xf5\xeb\xea\x85\xd2\xea\xb4\xc9\xce\x86\x7c\x89\xa6\xfc\x44\xb3\x26\x89\x5d\xc2\x72\xf3\x89\xa7\x76\x49\xfd\xcc\xb3\x10\x2f\xc0\xec\x72\x76\xbe\x01\x2f\xf3\xa4\x44\x96\x61\x06\x15\x9a\xa1\x67\x11\x0d\x63\xa9\xb2\x25\x73\x8d\xf4\xf9\xa0\xd9\x8f\xb3\xf3\xf8\x80\x29\x90\xb3\x03\xd9\xc3\xe7\xda\x75\x1c\xcf\x48\xf8\x8f\x22\x21\x72\x57\x54\x3f\x04\x17\x9c\xbc\x3f\x6c\x89\xeb\x77\x87\xe6\x0c\xa8\xa3\x4b\x78\x7f\xbb\x92\x61\xf9\xaf\x35\x9a\x29\x9f\xff\x68\x01\x6b\x73\xb6\x2e\xc4\xc8\xa4\x85\x54\x58\xaf\x29\x76\x35\x2d\x77\x34\xa3\xf6\xb3\x53\xf6\xf7\x44\xc3\x3c\x5d\xe6\x9b\xf2\x36\x69\xb4\xc1\x3d\xcd\x96\x1a\xe1\x4b\xa2\x00\xad\xf7\x7f\xa7\xf1\xec\x0b\xdd\xf6\x02\x6e\x4b\x99\xe2\x23\x36\xce\x61\x7f\x03\x1d\xf6\x36\xd2\x61\x2f\x43\x1d\xf6\x35\xd6\xe1\x1e\x06\x3b\xec\x67\xb4\xc3\x3c\x2b\xd0\x0a\x05\x94\xf5\x7e\xec\x77\xb8\x8f\x89\x0a\xf7\xb0\xe3\x61\x7e\xaa\x0d\x9b\x9a\xf7\x65\xd4\x33\xaf\xcf\xd8\xf5\x7f\x36\xb1\xf6\xb3\xe9\x61\x9e\x54\xc1\x18\x96\x6c\xd0\x7e\x22\x16\xfe\x9f\x62\x6e\xc3\xbd\x4c\x6e\xd8\xdf\xec\x86\xfd\x39\x83\x55\xdd\x8f\x1c\x4e\xbd\xaf\xc2\xf4\xad\x78\x15\xc1\x67\x70\xc7\xf0\x3b\x69\x02\x5e\x97\x3f\xa0\x12\xd2\x58\xc2\x77\xc1\x67\xd2\xfd\x16\xac\xf3\x6e\x33\xa5\x3f\x42\x4c\xa2\xfa\x56\x14\xa4\x7b\x7c\x1e\x47\xb0\x8b\xa8\xf5\x79\x35\x3d\x80\xbb\x09\x59\x9b\x24\xa5\x9a\xf3\xce\x07\x37\x38\x3d\x18\x2c\x30\xd2\xc1\x85\x3a\xf0\x3a\x6a\x81\x75\x1a\x85\xa6\x55\x31\x85\x03\xfe\x76\xf0\xae\x35\xfb\x1e\x8a\xab\x7b\x85\xca\xbe\x7a\x61\x0f\x2e\x51\xf1\x5a\x97\x77\x0f\x36\xbd\x16\xf1\x81\x8d\xd8\x8b\x6d\x15\x0c\xa7\x5a\x74\x94\x4b\x93\x35\xc2\x3c\xc6\xef\xb3\x68\xfc\xd6\x2a\xdc\x74\x11\xcf\x9c\x87\xc6\xbc\x92\x5a\x4c\x69\x0a\x0b\xaf\x15\x5a\x06\x76\xd8\xb8\x88\x3a\x95\xb9\x6c\xe2\xd3\x41\x5a\x6d\xa7\xb2\xf9\x04\x91\xb6\x06\x63\xc4\x12\x85\xb2\x70\x10\x7d\x4f\x87\xb6\x2d\x71\x90\xb4\xa7\xfb\x9a\x16\x8f\x7e\xff\xe3\x78\xe6\x44\x5f\xdb\x60\x8f\xb4\x7b\xa4\xdd\x23\xed\x1d\x6a\xf5\x48\x7b\xf5\xd3\x23\xed\x1d\x9e\x1e\x69\xf7\x48\x7b\x5d\xc7\x3d\xd2\xee\x91\xf6\xe6\xce\xf7\x43\xda\xfb\xe6\x09\x75\x71\x6f\x08\xce\xf9\x8b\xcc\x84\x93\x69\x9b\x43\x14\x4b\xf9\xbf\xde\x2d\xde\xee\x62\xe9\xe5\x68\xbb\x8b\xc8\x17\x6c\x8b\x64\x03\xb4\x6e\xc0\xf7\x42\xcd\xf5\xa8\xfb\xe3\xca\x85\xda\x83\x37\x3a\x01\x85\x3d\x99\xe3\x65\x0c\x85\x87\x8b\xff\x46\xd8\xc6\xc9\x33\x38\x8a\x11\x97\x63\x22\xbe\xd2\x6e\xf6\xa3\x72\x72\xd8\x96\x68\x62\x30\x1c\x5e\x9c\x39\x6f\x33\x13\x96\x68\xa2\xee\x4d\xa4\xb8\x5d\x4f\x12\x21\x68\x66\xc6\x20\x6d\xb8\xde\x90\xb3\x25\x4c\xad\x14\xb5\xaa\x55\x0c\x1f\x7b\x99\xe3\xef\xe3\x0b\x9c\xe7\xc1\x12\x8f\x87\x11\x53\x4b\xa5\x4e\xbc\x53\x38\x7f\x05\x62\x48\xe5\xd7\x2a\x44\x44\xe9\x4d\x8c\xfa\x46\xa6\xe4\x19\xc9\xa6\xf7\x04\xbe\x63\x3e\xec\x36\x2c\x2d\xd3\x47\x14\x85\xbe\xdb\x45\x24\xfd\x59\xc7\xa2\xee\x76\x3e\x16\x35\x17\xbf\xeb\x4f\x45\xfd\x9b\x9c\x8a\xe2\x8f\x7e\x0b\xbd\xf3\xe3\x51\xf0\xcf\x70\x01\xa1\x41\x26\x55\x59\x17\x4e\x56\x6d\xae\x94\xf5\x5d\x15\x1e\x65\x8e\x43\xe6\xc9\x2c\x5f\x52\x6f\x22\x9d\xcc\xf3\x27\xb7\xc7\xb9\x55\x96\x37\x6d\xc8\xee\x10\x45\x11\xce\x14\x45\x48\xea\x53\x58\xe4\x87\xce\x4c\x78\x1c\xee\x6c\x6d\xac\x19\x16\x32\x47\x24\x0b\x0b\x5a\x50\x92\x6a\x6b\x84\xa8\x37\x8a\x6e\x31\xaa\xde\x5c\xde\xa2\x6a\x25\xe9\x91\x3d\x3e\x8e\x3a\xfc\x9d\x4a\xf8\xf7\x22\xa1\xbf\xea\x48\xd2\x6f\xb6\x91\xd1\x3c\xa1\x46\x4a\xb7\xe4\x6b\x65\xf4\x87\x4c\xc1\xd8\x25\xce\xbf\x9b\x8f\x61\x8f\xf8\xfe\x9f\x18\xdb\xff\x74\x4e\x96\x7d\x60\x0f\xe3\x87\xc8\xad\xff\xe8\xbd\x8a\x7d\x72\x7d\xfb\xdc\x37\xb9\xfe\xbd\x7b\x0e\x3f\x6c\x8e\xfd\x27\xe0\x2d\xfc\x90\x39\xf6\xbd\x87\x70\xed\xa2\x7c\x6c\xa9\xef\xb3\xcf\x5e\x1e\xc1\xde\x1b\xb8\xb7\x16\xde\x51\xe1\xdc\xd7\x0b\xb8\x23\x47\xec\x19\x67\xef\x63\xec\x7f\x4e\x8c\xbd\x47\xbc\x5b\x3e\x3d\xe2\x5d\x49\x94\x1e\xf1\x42\x8f\x78\x37\x4d\xaf\x47\xbc\x6b\xc9\xd3\x23\xde\xb5\x8b\xd2\x23\xde\x1e\xf1\xc2\xa7\x86\x78\xf7\xb9\xa5\xab\x8f\x75\xdf\x2b\xd6\xbd\xab\xb4\xd8\x49\x46\xec\xc8\x07\x3b\xc7\xb6\xfb\xb8\xf6\xc7\x12\xd7\xde\xfa\xc0\xbf\x72\xf2\xbe\x87\xfe\xbb\x6b\xb5\xea\xe4\xbf\xb8\xd5\x32\x83\xaa\x76\xe1\x3c\x75\x7f\xfa\xff\x5d\x9c\xfe\x9f\xa1\x7c\x7f\x05\xc0\x56\x57\x00\xac\xa2\x59\x7f\x0f\x40\x7f\x0f\xc0\x3b\x0e\x42\xf7\xf7\x00\xf4\xf7\x00\xf4\xf7\x00\xc4\xa7\x3f\x9d\x04\xfd\xe9\xa4\xad\x9e\xfe\x74\xd2\xea\xa7\x3f\x9d\xf4\xd1\x7a\x5f\xa1\x3f\x9d\xf4\x71\x7b\x62\xa1\x3f\x9d\xd4\x7b\x67\xb7\x5c\xa8\x4f\xf0\x74\x52\x7f\x0f\xc0\xc7\x9a\xa3\x00\x3d\xd2\xee\x91\x76\x8f\xb4\x7b\xa4\xbd\xfe\xe9\x91\xf6\x0e\x4f\x8f\xb4\x7b\xa4\xbd\xae\xe3\x1e\x69\xf7\x48\x7b\x73\xe7\xfd\x3d\x00\x9f\x50\x6e\x04\xf4\xf7\x00\xf4\xf9\x12\xfd\x3d\x00\xff\xbe\xf7\x00\xcc\xc4\xee\x3f\xdc\x65\x00\xbb\x0f\xa3\xbf\x11\xa0\xbf\x11\xa0\xbf\x11\xa0\xbf\x11\x20\x3e\xfd\x8d\x00\xfe\xf9\x98\x7c\x8d\xfd\xf9\xa8\x95\x44\xe9\xcf\x47\x41\x7f\x3e\x6a\xd3\xf4\x3e\x01\xbf\x61\x7f\x3e\xea\x23\xf4\x15\xf6\xe7\xa3\x7a\xbf\xe0\xfc\xe2\x7c\x22\xe7\xa3\xfa\x1b\x01\x3e\xc6\x68\x7b\x8f\x78\xb7\x7c\x7a\xc4\xbb\x92\x28\x3d\xe2\x85\x1e\xf1\x6e\x9a\x5e\x8f\x78\xd7\x92\xa7\x47\xbc\x6b\x17\xa5\x47\xbc\x3d\xe2\x85\x4f\x0d\xf1\xf6\x37\x02\xf4\x37\x02\xf4\x37\x02\x7c\x8a\x11\xee\x8d\x2b\x4d\x23\xdb\x64\xd0\xce\x2c\xe7\xb3\x4e\x85\x39\xf0\x1e\x4e\x34\x07\xdd\xea\x4c\x8d\x7c\xc0\x3b\xc6\x1f\xf9\xd8\xae\x6b\xe9\x9a\xc0\xd5\x92\x9a\x4c\xbe\x50\xe2\xd0\x7a\x42\xdb\xf9\x76\xe6\xe2\xb5\x9e\xd6\xdc\xe6\x8a\x29\x6c\x21\x6e\x77\x13\xae\x1b\x09\x5b\x19\xa9\x8d\x74\xd3\xf3\x42\x58\xfb\x4c\x94\xb8\x15\x75\x2f\xc6\x2d\xd3\x0e\x40\xaa\x4c\xa6\x8d\x75\xe3\x05\x49\x6c\x97\x01\x10\xf1\x43\xa7\x7c\xa4\x50\x2c\xe3\x03\xdc\x23\x24\xf6\x16\x75\xe1\x68\x8b\xfd\x86\x46\x87\x03\xe9\x06\x3d\x4f\xc5\xcf\xeb\x89\xb7\x66\xae\x16\xd3\x9a\xe7\xaa\x95\xc3\xb7\xee\x5c\xab\xb1\xcc\xb7\x9a\xef\xc1\xd5\xb2\xaa\x90\x0a\x45\xc3\xe6\x0b\x09\xc6\xf0\xa6\xc0\x5c\xa4\xd3\x37\x34\xfc\x37\x06\x69\x20\xb4\x67\xde\x78\xa5\x70\x2e\x9c\x28\x74\x7e\xc5\x11\xb3\xc3\x70\xc3\x84\x05\x94\x7c\x81\x84\x54\xbf\xf8\x0d\xd6\xc8\x0e\xc3\x79\x18\x95\xce\x12\xa2\x5c\x32\x37\x76\x96\xea\xcd\xc7\x00\x00\xd0\xbc\xfa\xec\xf5\x42\xc9\x00\x15\x08\x8c\xd0\x96\xec\xf2\xa7\xa9\x15\xc9\xa0\x4b\x9d\x41\x9c\x20\x9c\x65\xa5\x64\x74\x02\x47\x97\x57\x67\xc7\x33\x33\x81\x92\xaf\xc1\xd0\x06\x32\x8d\x56\x1d\x3a\xb6\x1b\xdc\x04\x6d\x8b\x48\x78\xe7\x73\x40\xd0\xef\x16\x8e\x08\xc6\x3e\x89\x60\x0c\x52\x46\xd8\x74\x7e\x75\x06\x6f\x46\xc2\x62\x21\x15\x7a\xda\x55\x46\xde\xca\x02\x73\xea\xb1\xe3\x5f\x81\xf3\xda\x18\x54\xae\x98\xc6\x9b\x0a\x96\xaf\x8a\xb4\x50\xab\x39\x76\x8b\x9c\xd5\x48\xc7\x66\xb1\xa8\xb4\xc5\x2c\x81\x2b\xae\x31\xf5\x50\x3a\x94\xe3\xb5\x71\x13\xa1\x56\x2e\x2e\x18\xb4\xd4\xb0\x54\xbe\x96\xcc\xd8\xb2\x02\x34\x86\x54\x33\x67\x2f\xd4\x96\x05\x75\x91\xa1\x81\xd4\xb3\x01\xc8\x52\xe4\x5e\xca\x33\x91\x58\xe5\x84\x14\x8f\x40\x98\x25\x84\x5f\x3d\xe7\x56\x69\xf1\x8a\xe8\x66\xbc\x09\x5c\x2b\x32\x5a\x04\x8c\x6b\x57\x1b\x84\x5b\x34\xbc\xba\xbc\xe7\xba\xa4\x89\x9b\x30\x36\xd0\xe9\x7e\xd0\x0c\xbb\x14\x32\xb0\x9a\x8d\x7d\x1a\x1c\xd5\xb2\x60\xb4\x22\x9b\xf9\x59\xcf\xc8\xa2\xe9\x4e\x8f\x41\x57\x65\xb8\x26\xa4\xae\x2a\x6d\x5c\xab\xc3\xd2\xee\xde\x08\x3a\x66\x09\x01\x68\x58\x95\xc1\x8a\x70\x6c\x90\xb4\x16\x21\x9d\x08\x95\x13\x7b\x5c\x2b\x78\xaa\x39\xa5\xc3\xe7\x05\x51\xb7\x62\xa4\x6b\xc7\x3c\x16\xf6\xea\x58\xd7\x2a\x03\x12\x2a\xa7\x30\x71\xae\xb2\xa7\x27\x27\x37\xf5\x08\x8d\x42\x87\x36\x91\xfa\x24\xd3\xa9\x3d\x49\xb5\x4a\xb1\x72\xf6\x24\xee\xa6\x93\x4a\x67\xc3\xf8\x63\x28\xe2\x26\x39\x39\x3c\xd8\x57\x1a\x41\xa4\xfc\x29\xf8\xb5\x5a\x51\x0a\x55\xbd\xe6\x52\x84\xe1\xfa\xca\x54\xa0\x25\xe3\xd2\x42\x4e\x17\x7c\x85\xc8\x1a\x4f\xe1\x2c\x50\x6a\xcb\x37\x57\x79\x44\xf6\xb0\x1d\xe9\x76\x68\xbb\x4d\xaf\x17\xda\xeb\x00\xe4\x06\xc8\xb8\x70\x8d\x07\xcb\x36\x02\x73\xed\x40\x19\x00\x38\x27\xf8\x22\x0f\x42\xe3\xfe\x0b\x89\x2b\x35\x05\xe2\x67\x17\x6e\x75\xe9\x5c\x73\xe2\x0c\xe7\x19\x7d\xd5\x58\x7d\x03\x1c\x8f\x31\x75\xdf\x84\xfd\xdc\xd8\x7f\xbc\xb9\xa3\xa5\xf6\x55\xfc\xeb\x9b\xd5\xc8\x67\x2b\xa3\x6a\x3b\xb7\x98\x1f\xd2\x7a\xb8\x3b\x43\xa1\xef\xb8\xc2\x9c\xca\xf6\x14\xf0\x6d\x11\x7d\x78\x5a\x11\xdb\x79\x23\x21\xe0\x1d\x92\x19\x9d\xc2\x36\x48\xb8\x8e\xb4\x0d\xb8\xaf\xb5\x50\x11\x9e\xe9\x90\x70\x87\x03\xb8\xe4\x3b\x50\xda\x37\xac\xc8\x9e\x69\x9f\x7a\xb7\x12\x17\x75\xe9\xb6\xd1\x1e\xd8\xe8\x18\x9c\x21\xc8\x0f\xad\x1b\xd0\xcf\x6c\xc6\x0d\xd8\x72\xf0\x8c\x95\xb7\x8e\x32\x37\x38\x6d\x5d\x47\xc1\xc9\xc8\x96\xd9\xa0\xe5\x92\x08\x3e\xbd\x27\xe8\xef\x21\x77\x46\x97\x23\xa9\x7c\x67\xbe\xe9\xb8\x14\xdc\x7a\x24\xa8\xca\xf8\x27\x77\xf3\x2e\xc8\xb5\x9d\xb7\x71\x86\x66\xcf\x77\xf0\x2d\x36\xde\x8a\xe5\x5e\xc5\x8e\x2b\xf1\xbb\x5f\x6b\x51\x24\xf0\xd8\x4b\x45\x9e\x7d\x78\x15\x0a\x2d\x78\x57\xee\x64\x91\xa5\xc2\x64\xac\x0d\xfc\x1e\x05\xab\xfd\xea\x89\x06\x70\xc4\xdd\xde\xae\x91\xbf\xe3\x07\x2a\x61\x9c\x4c\xeb\x42\xb0\xda\xc2\x5c\x9b\xe9\x3b\xa1\x68\xcb\x34\x57\x98\x6a\x95\x6d\x30\x78\x57\x48\xd7\x50\xb7\x4b\x63\x86\x51\x68\x64\x48\x65\x93\x25\xce\x33\xe9\xd1\xac\x71\xa3\xc7\x71\x57\x37\x5b\x6c\xe0\x51\xcd\x9d\x64\x58\xd6\xf8\x1b\xa4\x05\xe9\x73\x61\x8f\x3b\xe2\xb1\xd9\x15\x09\xfc\x63\x1a\xf5\xd5\x00\xa4\x8b\x56\x9e\x45\x17\x31\x4c\x64\xd9\x40\xec\x76\x43\x8d\xb5\xc1\x5b\x34\x70\x94\x69\xae\xc3\xe9\x9e\xc7\x09\xfc\x8b\x20\x3e\x7b\x27\x30\xf7\x99\x89\x81\xc5\x23\x12\x71\x7c\x29\x17\x5b\xbb\x0f\xe1\xc8\x67\x89\xca\xb2\xc4\x4c\x0a\x87\xc5\xf4\xd8\x07\x0a\x63\x9e\xe9\x36\x4b\xb7\x4d\x72\x71\x27\xa9\xf8\xcb\xbf\xac\x29\xc9\x83\xdd\x61\x65\x7f\x66\x48\x39\x23\x6a\x3c\xca\x9c\x5b\xc2\x46\x07\xe9\x35\xce\xe3\x8e\xb3\xb8\x83\xfd\xa2\x98\x69\x16\xf8\x17\xe2\x03\x01\x06\x73\xe6\x72\xcf\xb9\xf7\xe0\x71\x99\x2e\x4f\x8e\xde\xa0\xd1\xd6\xc7\x9f\x86\x40\xf0\xff\xcb\xbf\x64\xc2\x89\x15\x05\xfc\x9a\x4f\x2b\x5c\xf2\x7d\x93\xa2\x6c\x1b\x5f\xb5\x58\x1b\xb7\x75\xd3\xfd\x5e\x2d\x30\xd4\x5f\x56\x73\xd6\xa4\xa6\x52\x21\x1e\x11\xd7\x7b\x68\x30\x97\xd6\x99\xc6\xc5\x4b\x96\x22\x97\x73\x1a\xa4\xb2\x4e\x28\x27\x59\xb2\x41\x2c\x39\xb4\x68\x6e\xf9\xd6\x3e\x37\x49\xe0\x39\xd9\x5a\x64\xde\xc0\x1d\xa9\x69\x0f\xb0\x5f\x4e\x2b\x84\xaf\x3b\x3f\xbe\x37\x55\xca\xbc\x16\x04\x8d\x67\x2e\x91\x65\x06\xed\xa2\x7c\x58\xc6\x3e\x6b\xe7\x1f\xcd\xfc\x8d\x24\x38\xbc\x8c\x0e\x81\xe0\x03\xb5\x56\xe6\x84\x32\xe3\xa9\x84\xa0\x4e\x66\xd1\xa6\xb7\x0a\xb8\xa2\xfc\x8d\x77\x53\xd9\x28\x01\xe9\x22\xee\x4f\xb5\xb2\x75\x19\x93\x0b\xc8\xea\xa9\x50\x65\xa8\xd2\x29\xa7\xb1\x16\xb7\x68\x12\xf8\xc9\xd2\x4a\xc1\x7f\xc9\x9c\xec\xbe\xd0\x69\x17\x2a\xc5\xec\xe8\xb9\x11\x48\xdb\xb9\xdb\x8d\xd3\x25\x08\x03\xc5\x16\x30\x9b\x2b\x6f\x63\xc8\x66\x7e\x10\x9c\x5c\x1f\x1c\xf7\x7c\x7a\x22\xb8\xdf\x1a\x47\x89\xdf\xf0\x34\xa5\x5c\xfb\x44\xf9\x4a\x5b\x19\xb3\xba\x1b\x39\x3a\x73\x02\x43\x8f\xfd\xf9\x08\xdf\xee\xac\x21\xcc\xb1\xbf\xb9\xc9\xb0\xe1\x56\x2b\x4f\x7c\xec\x7a\x69\xa2\x98\x79\xe8\x9b\x5a\x56\xcf\xc5\x0b\x33\x67\x87\xdc\xca\x74\x23\xd4\x0d\x66\x50\xe0\x5b\x99\xea\xdc\x88\x6a\x22\x53\x3e\x04\x40\xdb\x94\x9d\x64\x9c\xfa\x2f\x4a\x4c\x0e\x57\x32\xda\x2a\x31\x5e\xd5\xa3\x42\xda\x09\x2e\xc5\x32\x6b\x79\xd4\x62\x6a\xd0\x2d\x95\x20\x33\x2c\x7a\xe5\xcb\xb5\x4a\x39\x46\x4e\x43\x03\x21\x33\xc0\xf3\x1c\x6f\x3c\x22\x71\x9a\xd2\x46\xf2\x47\x67\x94\x6b\x2f\x66\x6c\x68\x98\xc0\x05\xab\xd4\x11\x5a\xe6\xf2\x1b\xc4\xca\x73\x1a\xbb\xf0\x6d\xc9\x3e\x15\x2b\x55\x8a\xfe\x28\x83\x3f\x12\x82\x18\xdd\x8c\xce\x48\xf4\x30\x88\x54\xed\xb4\x59\x1b\x54\x6e\x39\xa8\x59\x6f\x77\xad\xb1\xb9\xd6\x93\xb1\x91\x29\x9b\x29\xd9\xca\xa2\xa8\x13\xe9\x6f\x22\x25\x7f\xd9\x75\x05\xfd\xc9\x93\x2b\x1f\x02\xdd\x2c\x6b\x7e\x9a\x29\x1e\x1c\xeb\x16\x26\xfa\x2e\xb4\x34\xbf\x69\x83\xc7\x26\xae\x6d\x26\x6d\x4a\x3b\x1d\x33\x38\xd7\xca\xc6\xe3\x27\x42\xf9\x13\x25\xb7\xa2\xf0\xac\x10\x1b\xae\x74\xc1\x27\x7b\xb2\x3a\x9a\x13\x3e\x4b\x04\xcb\x11\xf2\xb5\x91\x36\x0e\x65\x85\x9a\xdb\xa0\x62\x37\x69\xc1\xa8\x1f\x2e\x75\x51\xac\xd7\x62\x6b\xed\xd2\x6d\xac\xd2\x48\x80\xad\xaf\xec\xbd\x88\x14\x0b\xbe\x38\xe2\xe9\x0c\x1d\x9a\x52\xaa\x00\x8f\x08\xea\x36\x84\x1d\xa1\xbb\x43\x54\x90\x4e\x30\xbd\xb1\x6d\xac\x83\x2f\x70\x9d\x5b\xb5\xe0\x7f\x9a\x95\x58\x0d\x9e\xa2\x55\x61\x43\xc3\x22\x82\x24\x9b\x40\xe1\x5d\xd7\x67\xb5\x44\xdd\x90\x8a\xbe\x15\xb2\x10\xa3\xc2\x1f\xbb\x6a\x7e\x0d\xba\xe3\x90\x51\x9f\x57\x75\x51\xa0\x0f\xe8\xe5\x2f\x2e\xcf\xc1\x19\x31\x1e\xcb\x94\xc3\x39\xd2\x78\xaf\x6f\x50\x6c\x4b\xa7\xb0\xf9\x52\xe1\x25\x3b\xc2\x3a\xe1\xea\x85\x35\x5a\xb3\xc0\xeb\x16\x96\xec\x10\xb9\xd2\x41\x34\x77\x15\xe7\x8c\xb1\x42\xc3\x40\x6f\x6c\xcd\xf8\xbf\x13\x78\xa6\x5d\xb8\x49\xf7\x29\x5a\x52\xbb\x4c\xa0\x17\x28\xac\x56\x1d\xe9\xca\xe8\xd7\xc8\x5c\x2a\x51\x84\x49\x75\xfd\x7b\x8d\xed\x21\xd8\xa5\x5c\xca\xdc\x08\xd7\x08\xc5\x76\xdc\x41\xbb\x04\xbd\xe8\x3d\xa1\x09\x9c\xa9\x29\xaf\xf7\x18\x05\xbd\xa0\x96\x9d\xd1\x59\x9d\x62\x38\x73\x57\xdb\x6e\x23\xef\x54\x8c\xce\x86\x17\xce\x63\x27\x6d\x2c\x3f\x43\x27\x64\x08\x29\x69\x85\x20\x6c\x45\x76\x5c\xe4\x49\xef\x0a\x6f\x09\xcc\xca\xe2\xec\xf2\x02\x5e\x84\x43\x39\x09\x0c\x87\x43\x1f\xd5\xb4\xce\xd4\x29\xeb\x17\xda\x42\x2a\x0b\x9a\xc2\x73\x1f\x4f\x52\x74\xd2\x60\x82\xe7\xc3\x43\xb0\x4a\xb8\x09\x24\x9e\xf0\x49\x87\x14\x00\x4f\x48\xd7\xbc\x15\x65\x45\x7c\x7f\xad\xbc\xf4\x7e\xa2\xf5\x95\x5f\x24\xdf\xe7\xef\x70\x72\x32\xcf\x13\x7a\x44\x10\x35\x38\x10\x99\x35\xc6\x5a\x1f\xda\xd9\x29\x25\x54\xf1\x07\xa5\xef\xd4\xb2\xde\xb9\x2f\x61\xf0\x14\xae\x0f\xce\xe2\xee\xbb\x3e\x18\xc0\xf5\xc1\xa5\xd1\x39\xa7\x57\xa8\xfc\x3a\xe4\x4b\x5c\x1f\x3c\xc6\xdc\x88\x0c\xb3\xeb\x03\x6a\xf6\x3f\x38\x2f\xe6\x29\x9a\x1c\x7f\xc0\xe9\xd7\xdc\x58\xf3\x3a\x6a\x84\xaf\x7d\x0a\x0d\xbd\x27\x15\x4c\x7a\xea\xeb\x52\x54\xcd\x8b\xa7\xa2\x6a\x2a\x9f\xb7\x7c\xf6\xea\x75\x89\x4e\xdc\x3e\x4a\xda\x15\x7d\xf3\x8b\xd5\xea\xf4\xfa\xa0\x1d\xff\x40\x97\xc4\x19\x95\x9b\x5e\x1f\xc0\x4c\xaf\xa7\xd7\x07\xdc\x6f\x7c\x1f\x07\x79\x7a\x7d\x40\x3d\xd1\x6b\xa3\x9d\x1e\xd5\xe3\xd3\xeb\x83\xd1\xd4\xa1\x1d\x3c\x1a\x18\xac\x06\x04\x98\xbe\x6e\x7b\xb8\x3e\x78\x43\x6b\x72\x72\x12\x42\x18\xe1\x92\xe2\x3f\x96\x3b\xab\x37\xca\xfd\x4d\xf9\x83\x43\x28\x84\x75\x2f\x8d\x50\x96\xfb\x7f\x29\xcb\x65\x2a\x0c\x82\x2d\xc7\xfb\x7d\xe5\x77\xc3\x32\x60\xe5\x67\xcf\x0d\x2b\x3f\xaf\xd0\x9e\xdb\x68\xae\xc5\x39\x6c\xe9\x75\x5e\xac\xd8\x26\x16\x12\x9e\x8b\x7e\x9a\x66\x7d\x48\x07\x84\xd2\x18\x0e\xbc\xd2\x16\x0f\xf2\x8d\xd3\x86\x78\xdd\x42\xca\x57\x6b\xe0\xdf\x85\xc3\xb0\x50\xab\x0c\x4d\xc1\xc1\xaa\xb6\x55\x1f\x09\xc9\x12\xf0\x7e\x03\xd1\x78\x69\x6e\x68\x23\xb1\x76\x52\x1d\xe7\x35\x8f\xab\x69\x91\x64\x47\x38\x0f\xec\x9b\x61\x45\x97\xa6\x58\x39\xd6\x74\xfb\x87\x98\xa1\xe3\x54\x21\x64\x35\x74\xab\xd9\x23\x30\xc7\x96\x84\x0f\xa5\x7d\x7c\x7f\x52\x97\x82\x54\x87\xc8\x68\xbc\xed\x37\x6f\xbe\x79\x73\xcb\x8b\x54\x1f\x14\xf2\x3e\xfe\xb8\x0e\x81\xd4\x41\x91\x88\x26\xf1\x7b\x83\xc7\x64\xab\xc9\x97\xe2\xed\x8f\xa8\x72\x37\x39\x85\x2f\x3e\xff\xcf\x2f\xff\xba\xa2\xa0\x17\x8c\x98\x7d\x8f\x2a\xf8\x82\xb6\x24\xc3\x62\xc5\x79\xa7\x61\x42\x52\x29\x13\x4e\x24\x79\x5b\xa6\x71\x72\xb7\x1c\x74\x27\x2c\x1b\x34\x5e\x5d\xd6\x15\xd1\xe5\x09\x27\xaa\x58\x27\x54\x8a\x03\x02\x49\x4b\x1b\x93\x8d\x00\x2f\xa6\xf0\xe8\x73\x7f\x99\x3f\x77\xbd\x20\xbe\x5f\xbd\x7d\x9d\x2c\x19\xb2\xb4\xf0\xb7\xc1\xdc\x78\xa4\x05\x5a\x2a\x3d\x66\xc6\xf1\x26\xa6\x41\xaf\x09\xa3\x33\x60\x51\x13\x62\x33\xde\x4d\x0b\xb7\xc9\x1f\xb8\x9d\x2f\xb0\x94\x4a\x96\x75\x79\x0a\x0f\x57\x14\xf1\x22\x6d\xcb\xd5\xf4\x85\x5b\x20\x20\x48\x74\xe5\x46\x94\x25\xa7\xa4\xc9\x0c\x95\x93\x63\xc9\x49\x03\x0d\x6b\xb3\xb9\xef\x2b\xc6\x1c\x94\x86\x8a\x9c\x9e\x42\x72\xa8\xc3\xec\x97\x1e\xe7\x18\xd6\xc0\x21\x7a\x93\x76\x05\xd4\xb4\x42\xbf\x1b\xbc\x01\x03\xf8\xb6\xf2\x50\xb5\x13\x86\x28\x51\x28\xa9\xf2\x98\xf6\xd2\xfe\x47\x0e\xf4\xf1\x6e\x82\x21\x7a\x8e\xdd\x58\x50\x4a\xc6\x52\xc6\x76\x93\x80\xbc\x16\x46\x28\x47\x66\xec\xd9\xe5\x85\xc7\xe8\xf3\x3e\x4d\x42\x8e\x25\x16\xe7\xc2\x62\xdc\x8d\x7e\xab\x7a\x61\x15\x6f\x15\x68\xb2\x64\xdf\xd9\x56\x7d\xf4\xf0\xf3\xb5\x4b\xde\x94\x5b\x1d\xc2\x13\xce\xa1\x51\xa7\xf0\x3f\xaf\xce\x86\xff\x12\xc3\xdf\x5e\x1f\x85\x3f\x1e\x0e\xff\xf6\xbf\x83\xd3\xd7\x9f\x75\x7e\xbe\x3e\xfe\xf6\xff\xaf\x68\x69\x39\x98\x5f\xc1\x3e\x41\x89\x44\x9c\x18\x57\x74\x10\xb3\x54\x5e\x9a\x1a\x07\xf0\x44\x14\x16\x07\xf0\x93\x62\xd5\x70\x4f\xa2\xad\x8f\x50\x93\x56\x3e\xa0\x5e\x57\x45\xca\x43\x11\x1e\xd2\xfa\x32\x61\xb8\xeb\xcc\xd7\xed\x88\x14\x5d\x0d\x1d\x49\xa3\x3a\x7c\xe6\x53\xf3\xc6\x5a\x27\x01\xe1\x26\xa9\x2e\x4f\x9a\xef\x1e\x5a\x3f\x15\x6a\x0a\xad\x58\xf3\xa0\x74\x9e\xd3\xad\x23\xd9\x24\x52\xa3\xad\x6d\xcf\xcb\x43\x21\x6f\x10\xce\x5a\xbb\x91\x84\xe5\x08\x53\xc1\x58\xdc\x8c\xa4\x33\xc2\x3b\x7d\x23\xae\x6c\x3d\x4a\xe3\xba\x80\x23\x32\x57\x13\x4e\x24\x5b\x90\xae\xe1\xee\x0d\x31\x92\x05\xff\x17\x08\x64\x4a\xa7\x5a\x8d\x0b\x19\x4c\x80\xb2\xd2\xc6\x09\xe5\x62\x82\x70\x8e\x6f\xfd\xff\xba\xe2\xc3\x0e\xd2\xc2\x51\xa6\xec\xa3\x47\x9f\x7f\x71\x55\x8f\x32\x5d\x0a\xa9\x9e\x94\xee\xe4\xf8\xdb\xa3\x5f\x6b\x51\x70\x94\xf7\x99\x28\xf1\x49\xe9\x56\xff\xff\x15\x3b\xab\xc5\x47\x5f\x6e\xb1\x8b\x8e\x5e\xf9\xbd\xf2\xfa\xe8\xd5\x30\xfc\xf5\x59\x7c\x75\xfc\xed\xd1\x75\xb2\xf6\xfb\xf1\x67\x34\x87\xce\x0e\x7c\xfd\x6a\xd8\x6e\xbf\xe4\xf5\x67\xc7\xdf\x76\xbe\x1d\x2f\xdb\x8c\x6f\x87\x6d\xaa\xc8\x90\xac\x80\x61\x29\xaa\xe1\x0d\x4e\x57\x6c\xce\x95\x70\x74\xb1\x21\x4f\xb1\x52\x54\xcb\xac\xef\xb1\xcc\x9f\x8a\xea\x05\x8e\xd1\xa0\x4a\x97\x32\xf9\x3d\x23\x30\x64\x3f\xac\xf9\xc4\x19\x58\x7b\x78\x9d\x48\xef\x78\x4f\xdb\x3a\x38\xbd\x05\xb7\x6c\x87\x1f\xd5\x9a\xfc\xc5\xcd\x29\xa6\x71\x9e\x7b\xb7\x10\xf7\xf7\xcf\xde\x7f\xb4\x77\x3b\xb5\x5c\x69\x69\xcd\xfa\x30\x2f\x1e\x7b\xe8\xcb\xa2\x87\xe1\xdc\x44\x93\x9d\x57\x2b\xf9\x6b\x8d\x70\xf1\xb8\x39\x9a\x26\x55\x5a\xd4\x7c\x19\xce\x4f\x3f\x5d\x3c\x26\xfb\xfd\x1f\x41\xdc\xdc\x21\x64\x5a\x1d\x3a\x78\xfe\xec\xc7\xff\x66\x67\x00\x97\x18\x78\x85\x1e\xce\xc7\x14\x52\x78\x37\x59\x50\xc0\xf0\x0f\xf4\x79\x72\xdc\x73\x2a\xaa\xc6\x7f\xc2\xe2\x8e\x33\xac\x8a\x8a\x00\xc4\x0d\x82\xad\x4d\x18\x1d\x35\xec\x23\xbe\x9c\x45\x1f\xe2\xc1\x39\xf2\x59\xba\x71\x21\xdc\xea\x7c\xe1\xb5\x44\x4b\xb5\x52\x98\x72\xd0\x9c\x50\xe0\x7b\xd8\x1f\xc4\xc8\xcf\x03\x66\xe5\x3e\xf6\xd8\x0c\x21\xa0\xb6\x37\x5b\xd0\x18\xce\xfd\x4c\xdf\xfb\x4e\x5a\x98\xef\x5e\x3d\x7a\x7f\x26\x47\x36\x5f\x6c\xf0\x3f\x2f\xa4\x71\xcd\x9a\xce\x33\xde\xc3\xe0\x5b\x6d\x82\xa3\x13\x61\x61\x84\xa8\xd8\x9d\xeb\xbd\x7f\xa8\x02\xd7\x61\xeb\x88\xad\xab\xa1\xd3\xc3\x6c\xf9\xe2\x6d\xa0\xdc\x66\xaa\xad\xb1\x5c\xe7\x4e\x99\xee\x6a\xa8\xde\x4d\xa6\xcb\x68\x60\xdb\x4b\x77\x1a\x0c\xb2\xeb\xc4\x56\x1b\x26\x73\x5e\x5d\xb6\x2c\x82\x53\x23\xd8\x19\x8b\x43\x22\xeb\x71\xc6\xb3\xe1\x34\x47\xf3\x66\x3d\x7b\xbb\x8f\xd1\x2f\xf3\x15\x9a\x5b\xb9\x97\xf2\xdb\xb4\x31\x53\x9f\x67\x72\xf6\xfe\xb7\x15\x41\xaf\xbd\x3b\x61\xd7\x5f\xaa\x37\x84\x6f\xd6\xe6\xbf\x33\x05\xd7\x65\xf9\xef\xd2\xc6\xae\xca\xd2\x4b\x93\x53\x3e\x71\x11\x5f\x39\x6d\x38\xe4\xde\x7d\x57\x8f\x1a\xa0\xdc\xb6\x1e\x6c\x20\xf8\xfd\x8f\x07\xff\x17\x00\x00\xff\xff\x25\x01\x0e\x3b\xe7\xe7\x00\x00") func operatorsCoreosCom_catalogsourcesYamlBytes() ([]byte, error) { return bindataRead( @@ -105,7 +105,7 @@ func operatorsCoreosCom_catalogsourcesYaml() (*asset, error) { return a, nil } -var _operatorsCoreosCom_clusterserviceversionsYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xfd\x7b\x77\xe3\xb6\xb5\x30\x8c\xff\xdf\x4f\x81\xe5\xe4\x3c\xb2\x1b\x49\x9e\x69\x7b\xfa\x6b\xe7\xd7\xf7\x64\xf9\xd8\x4e\xe2\x37\x33\x1e\x2d\xdb\x99\x3c\x5d\x49\x4e\x0a\x91\x5b\x12\x6a\x12\x60\x01\x50\xb6\xfa\xe4\xf9\xee\xef\xc2\x06\xc0\x8b\x2e\xb6\x44\x72\xc6\xb2\x07\xe8\x5a\xcd\x58\x24\x41\x70\x63\x63\xdf\x2f\x34\x63\x1f\x40\x2a\x26\xf8\x1b\x42\x33\x06\xf7\x1a\xb8\xf9\x4b\x0d\x6f\xff\xa2\x86\x4c\x1c\xcf\x5f\xff\xee\x96\xf1\xf8\x0d\x39\xcd\x95\x16\xe9\x15\x28\x91\xcb\x08\xce\x60\xc2\x38\xd3\x4c\xf0\xdf\xa5\xa0\x69\x4c\x35\x7d\xf3\x3b\x42\x28\xe7\x42\x53\xf3\xb3\x32\x7f\x12\x12\x09\xae\xa5\x48\x12\x90\x83\x29\xf0\xe1\x6d\x3e\x86\x71\xce\x92\x18\x24\x4e\xee\x5f\x3d\x7f\x35\xfc\xcb\xf0\xd5\xef\x08\x89\x24\xe0\xe3\x37\x2c\x05\xa5\x69\x9a\xbd\x21\x3c\x4f\x92\xdf\x11\xc2\x69\x0a\x6f\x48\x94\xe4\x4a\x83\x54\x20\xe7\x2c\x02\xf7\xbc\x1a\x8a\x0c\x24\xd5\x42\xaa\x61\x24\x24\x08\xf3\x9f\xf4\x77\x2a\x83\xc8\xac\x62\x2a\x45\x9e\xbd\x21\x6b\xef\xb1\xf3\xfa\xc5\x52\x0d\x53\x21\x99\xff\x9b\x90\x01\x11\x49\x8a\xff\x76\x40\xb0\xaf\xbf\xb6\xaf\x77\x90\xc3\xeb\x09\x53\xfa\xfb\xcd\xf7\xbc\x65\x4a\xe3\x7d\x59\x92\x4b\x9a\x6c\xfa\x10\xbc\x45\xcd\x84\xd4\x97\xe5\xb2\xcc\x32\x22\x35\xaf\xfe\xdb\xdd\xc8\xf8\x34\x4f\xa8\xdc\x30\xdb\xef\x08\x51\x91\xc8\xe0\x0d\xc1\xc9\x32\x1a\x41\xfc\x3b\x42\xfc\xbb\xec\xe4\x03\x42\xe3\x18\x37\x92\x26\x23\xc9\xb8\x06\x79\x2a\x92\x3c\xe5\xc5\xcb\xcd\x3d\x31\xa8\x48\xb2\x4c\xe3\x66\xdd\xcc\x00\xa1\x46\xc4\x84\xe8\x19\x90\xd3\xeb\x0f\xc5\xad\x84\xfc\x53\x09\x3e\xa2\x7a\xf6\x86\x0c\xcd\x06\x0c\x63\xa6\xb2\x84\x2e\xcc\x12\x2a\x77\xd9\xdd\x3c\xb3\xd7\x2a\xbf\xeb\x85\x59\xaf\xd2\x92\xf1\xe9\x43\xef\x77\x1f\xb1\xdd\x12\xe6\x95\x7d\xaa\xbe\xfe\xc3\xca\xef\xdb\xbe\xde\x7f\x3e\x35\x6f\x26\x7a\x46\x35\xd1\x33\xa6\x88\xe0\x40\x24\x64\x09\x8d\x40\x3d\xb0\xa0\x35\xb7\xd8\x15\x5d\xad\x5e\xd8\xb0\xa4\xea\x94\x9a\xea\x5c\x0d\xb3\x19\x55\xab\x20\x1e\x2d\xfd\xba\x66\x3a\x7b\xe3\xfc\x35\x4d\xb2\x19\x7d\xed\x7e\x54\xd1\x0c\x52\x5a\xe2\x80\xc8\x80\x9f\x8c\x2e\x3e\xfc\xf1\x7a\xe9\x02\xa9\x43\x67\x2d\xf6\x13\xa6\x0c\xa8\x90\x82\x10\x4f\x42\x70\xef\x16\x19\x90\x7f\xac\x7d\xe6\x3a\x83\xe8\x1f\xc3\x95\x95\x8b\xf1\x3f\x21\xd2\x95\x9f\x25\xfc\x2b\x67\x12\xe2\xea\x8a\x0c\x80\x3c\x59\x5a\xfa\xd9\xc0\xbf\xf2\x53\x26\x0d\x59\xd0\x95\x23\x6f\x47\x85\x2e\xd6\x7e\x5f\xfa\xda\x9e\x01\x89\xfb\xc6\xd8\x90\x44\x50\x88\x8f\x0e\xe3\x20\x76\x70\xb4\x78\xca\x94\x41\x0e\x09\x0a\xb8\x25\x92\x88\x42\xdc\x7d\xd3\x90\x18\x00\x80\x54\x86\x00\xe4\x49\x6c\x68\xe7\x1c\xa4\x26\x12\x22\x31\xe5\xec\xdf\xc5\x6c\x8a\x68\x81\xaf\x49\xa8\x06\xa5\x09\x9e\x5a\x4e\x13\x32\xa7\x49\x0e\x7d\x42\x79\x4c\x52\xba\x20\x12\xcc\xbc\x24\xe7\x95\x19\xf0\x16\x35\x24\xef\x84\x04\xc2\xf8\x44\xbc\x21\x33\xad\x33\xf5\xe6\xf8\x78\xca\xb4\xa7\xfa\x91\x48\xd3\x9c\x33\xbd\x38\x46\x02\xce\xc6\xb9\x21\x9c\xc7\x31\xcc\x21\x39\x56\x6c\x3a\xa0\x32\x9a\x31\x0d\x91\xce\x25\x1c\xd3\x8c\x0d\x70\xb1\x1c\x29\xff\x30\x8d\xbf\x90\x6e\x93\x55\x6f\x09\x7c\x6b\xd1\x99\x78\x02\xfb\x20\xac\x0d\x79\xb5\x98\x64\x1f\xb7\xdf\x52\x82\xd4\xfc\x64\xa0\x72\x75\x7e\x7d\x43\xfc\x02\xdc\xb9\x44\x08\x97\xb7\xaa\x12\xd8\x06\x50\x8c\x4f\x40\xda\x3b\x27\x52\xa4\x38\x0b\xf0\x38\x13\x8c\x6b\xfc\x23\x4a\x18\x70\x4d\x54\x3e\x4e\x99\x56\x88\x73\xa0\xb4\xd9\x87\x21\x39\x45\xa6\x47\xc6\x40\xf2\x2c\xa6\x1a\xe2\x21\xb9\xe0\xe4\x94\xa6\x90\x9c\x52\x05\x1f\x1d\xd4\x06\xa2\x6a\x60\xc0\xb7\x3d\xb0\xab\x3c\x7b\xf5\x81\x95\x33\x46\x88\xe7\xa5\x1b\x77\x67\xe3\x19\x26\x31\x44\x09\x95\x56\x28\x20\x1a\x92\x84\xbc\x7f\xfb\x8e\xcc\xc4\x9d\xc1\x62\xc6\x95\xa6\x49\x82\xa7\xc0\xf1\x67\x4b\x4e\x23\xca\x49\x4a\x39\x9d\x02\xa1\x59\xa6\xc8\x44\x48\x42\xc9\x94\xcd\x81\xfb\xd3\x35\xdc\x76\xf1\x9b\x88\x04\xb1\xc4\x7d\x2d\x83\xf2\x57\xdd\x02\x97\xae\x6c\x22\x1b\x66\xac\xc8\x40\x0f\x40\xed\xa4\xbc\x17\x31\x9b\x93\x9c\x2b\x2d\x73\xdc\xec\x98\xdc\xc2\xc2\x21\x79\x4a\x33\xa2\xb4\x30\x3f\xde\x31\x3d\x23\xb4\x8a\xe0\x54\x23\x16\x8f\x81\x28\xd0\x64\xbc\x20\x46\x8c\x43\x82\xa0\x85\x48\x90\x5a\xe0\xb3\x48\x18\x24\x68\xc9\x60\x0e\x84\xca\x31\xd3\x92\xca\x45\x81\x0d\xcb\x00\x7d\x04\xa8\xf8\xb1\x15\xe1\x61\x33\x48\xc8\x43\xb8\x48\x2c\xb9\x75\xb2\x4b\x5c\x08\x96\x5b\x40\x6f\x74\xe1\xf0\xad\x14\x47\x95\xc3\x37\x50\xc4\xe0\x95\x93\x0f\x0a\xb9\x16\xdf\xe4\x10\x2b\x26\x42\x16\x98\x61\xc0\x56\x45\xc2\x31\x18\x72\x22\x29\x37\x17\xd6\x22\x77\x03\x68\x3d\x84\x36\x66\x88\x3b\xbe\x0e\x47\xab\x73\x53\x29\x6b\x02\x53\x75\x30\x0d\xe9\x86\x99\x1f\x84\x5d\xf1\xb3\x59\xe0\x9c\xc5\x60\x80\xa8\x29\xb3\xa8\x63\x4e\x2b\x1d\x8b\x5c\x5b\xd8\xb9\x5b\x62\x32\x67\x94\xd0\xe9\x54\xc2\x14\x11\x78\xe3\x6b\x1f\x81\x89\x1d\x9b\x0f\x68\x39\x06\x56\x92\x7f\xf0\x0e\x43\x06\x1f\xbc\x81\xaf\x3b\xe6\xd5\x1b\x56\x85\xc5\xfa\x78\x6c\x0f\xed\xa0\x91\x81\x89\x07\xad\x90\x0f\xde\xbc\xcd\xde\xda\xf1\xc8\x0e\xdb\x51\xdf\xe7\xa5\x85\xb8\xab\x63\x73\x3e\x4a\xd2\x6c\xc8\x01\xde\x58\x12\xdf\x31\x90\x0c\xe4\x44\xc8\xd4\x1c\x14\x4e\x28\x89\xac\xfc\x56\x10\x1e\x24\x8d\x3c\x7a\x08\x9c\x64\xdb\xfd\xb7\x63\x1b\x2c\xb0\x63\x40\x32\xaa\x67\x8f\xdc\xb6\xdd\x56\xd9\x51\x05\xda\xa3\x37\x3f\x42\xcd\x56\xe6\x2e\x39\x4c\xe7\x73\x1b\x30\x74\x3e\x29\xf2\x9c\x6d\x66\xad\xa1\xda\x15\xbd\x7b\x07\x4a\x19\x96\x8d\x52\x9a\xa4\x77\x04\x78\x24\x0c\xb1\xf8\x7f\xaf\xdf\x5f\xda\x69\x87\xe4\x42\x13\x96\x66\x09\xa4\x46\x10\x23\xef\xa8\x54\x33\x9a\x80\x44\xee\xf4\x03\x4f\x6b\x7f\x3b\x4c\xcc\x15\xc4\x86\x16\xc5\x90\xd0\x85\x9d\x2c\x86\x48\xc4\x86\x46\x0b\x49\x32\x23\xe0\xa6\x59\xae\x81\x50\x7b\x15\xdf\xcb\xf8\x74\x1d\x91\x6e\x05\x1a\x62\x24\x91\x94\xea\x37\x64\xbc\xd0\x8f\xa1\x3e\x21\xf7\x83\x78\x5b\x1a\x50\x5d\xcc\xe3\x94\xc0\x8e\xad\xe8\x41\x75\xe2\x47\xbf\xd2\x08\xa1\x94\x71\x90\x23\x21\xf5\x36\x44\xcb\x28\x1f\x53\x90\x0f\xde\xe9\x41\xc6\xb8\xfe\xe3\x1f\x1e\xb8\x33\x86\x2c\x11\x0b\x83\x17\x8f\x9f\x95\x2d\xbf\x67\xeb\x73\xbd\xed\x7c\xdb\x9e\xe5\x2d\xe7\xb3\xc6\xa9\x2e\x66\x5a\xa7\x40\x35\x9a\x88\x77\xf5\x6d\x85\x12\xf8\x64\xcc\x6f\x74\xe1\xad\x0d\x57\x30\x01\x09\x3c\x72\xb4\xe9\xfb\x7c\x0c\x92\x83\x06\x55\x11\xa4\x17\x99\xa3\x34\x46\x16\x5c\x66\x77\x4f\xc3\xe5\x1e\x91\x67\xfc\x6d\x8f\x48\x35\xfe\xb6\xc7\x64\x1b\x3b\x76\x61\x9b\x8f\x23\x9d\x1d\x3b\xd1\xd8\xc7\x11\xb0\xc1\xa4\xf3\xf5\xe6\x9c\x16\xf3\x1a\x9d\x78\x0f\x24\xbc\xeb\xda\x32\x6a\xf2\xdd\x84\x41\x12\x13\x66\x84\x37\xb3\x58\x32\x4e\x44\x74\xeb\xec\x96\x57\x67\x44\x09\x2b\xee\x19\x09\xdf\x30\xda\x48\x70\x95\xa7\x40\xd8\x63\x18\x1c\x44\xba\x20\xd2\x05\x91\xee\xb9\x88\x74\xd6\x3f\xb0\x0f\x94\x6a\x69\x21\x1b\x69\x15\xde\x17\xa8\xd5\x43\x23\x50\x2b\x1c\x81\x5a\x3d\x32\x9e\x1d\xb5\xda\x4a\x4e\x7b\x74\xae\xc7\x0e\x72\x30\xa6\x06\x63\x6a\x30\xa6\xba\x11\x78\x99\x1b\x81\x97\x05\x5e\x16\x8c\xa9\x0f\x4d\x19\x8c\xa9\x3b\x4e\x14\x8c\xa9\xc1\x98\x1a\x8c\xa9\xc1\x98\xfa\xd8\xc7\x04\x91\x2e\x88\x74\x41\xa4\xdb\x76\x31\xc1\x98\x1a\x8c\xa9\x0f\x8d\x40\xad\x2a\x23\x50\xab\x07\xc6\xcb\xa6\x56\xed\x8d\xa9\x51\x02\x94\xaf\x57\xaa\x96\xe2\xbf\xf1\x3e\x14\x8d\xd8\x84\xb9\x3c\x08\xf7\x34\x19\xc3\x8c\xce\x99\xc8\x25\xb9\x9b\x01\xf7\x29\x3b\x64\x0a\x5a\x19\x2c\x00\x0d\xeb\x04\xf3\x47\x68\xcd\xc3\xf4\x65\x40\x80\xd3\x71\xb2\x76\xe2\xc7\x48\x89\x7b\xf2\x61\xe3\xf1\x58\x08\xf3\x75\xab\x10\x43\x55\xc7\x6b\x3a\xbb\xc4\x33\x1f\x6c\xca\xb1\x5b\x1f\xd4\x7c\x7a\x75\xd6\x55\x28\x33\xf9\x99\x93\x8b\x62\x56\x82\x96\x69\x4c\x94\x30\x3c\xc4\xfc\xfa\xfe\x8e\x43\x8c\x49\x6e\x7d\xc2\xb4\xb9\xc1\x1c\x7a\x16\x31\x9d\x2c\x8a\x17\x0f\x0f\x76\xdf\xc4\x3d\x0a\x89\x3e\xbd\x3a\xdb\xde\x7c\xef\x37\xe0\x53\x58\xea\x83\x1d\x3e\xd8\xe1\x8b\x11\xc4\xa0\x86\x93\x06\x31\xe8\x81\xf1\xb2\xc5\xa0\x7d\xb7\x5b\x07\x6b\x33\x09\xd6\xe6\x87\x6f\x0b\xd6\xe6\x60\x6d\x0e\xf6\x9b\x0d\x23\x08\x2e\x38\x82\xe0\xf2\xc8\x78\x76\x82\x4b\xb0\x36\x07\x6a\x15\xa8\x55\xa0\x56\xcf\x83\x5a\x3d\xc7\xd0\xdd\x60\xf4\x0b\x46\xbf\x60\xf4\x0b\xdc\x28\x70\xa3\x47\xc6\xb3\xe3\x46\xc1\xe8\xb7\xeb\x44\xc1\xe8\xb7\x76\x04\xa3\xdf\x23\x23\x18\xfd\x82\xd1\x6f\xc3\x08\x82\x4b\xc3\x49\x83\xe0\xf2\xc0\x78\xd9\x82\x4b\x30\xfa\x05\x6a\x15\xa8\x55\xa0\x56\xcf\x83\x5a\xb5\x37\xfa\x3d\x72\x92\x1e\x7e\xf6\xe1\x93\xf2\xe0\xb3\x2c\x7a\xe8\x85\x9b\x20\xfa\x00\x04\x1f\x25\x5c\x8f\x91\xab\x01\x19\x53\x05\x7f\xfe\xd3\x4a\xdd\xf2\xea\x2d\x29\xc4\x8c\x9a\x57\xad\xbd\xe3\x71\x12\x56\xbe\x62\xf3\x9e\x6d\xb1\xf7\xc5\x32\x1a\xce\xe2\x0a\x2b\x3f\x1a\x14\x6b\xb6\x36\xbe\xb0\x37\x5f\x6b\x49\x35\x4c\x17\x95\x42\xde\x68\x93\x2d\x39\x0f\xdf\x50\x80\xbe\x50\x1a\xef\x66\x20\x01\x1f\xf2\xa5\xa7\x95\x9f\x94\xa9\x22\x7a\x39\x6e\x50\xdc\xf7\xb1\x70\x64\xff\x9e\x35\x97\x1f\xdb\xb4\x75\xd5\xb7\xd7\x02\xcb\x03\xe8\xcc\x5a\xaf\xcf\x8a\x14\xe0\x65\x88\x65\x54\x1a\x0a\xe9\xad\xdc\xc8\xb4\x2b\x77\x2f\xc1\x7b\x13\x51\xdc\x82\x53\x3f\xce\xa1\x07\x95\x4c\xe5\x4d\x96\xf5\x6d\x18\xb3\xeb\x81\x31\x02\x99\x32\xa5\x36\x05\x5c\xd7\x97\xfe\x18\xd9\xdc\x82\x5c\x6e\x80\xbf\xff\xa2\xca\x72\x0a\xf1\x09\x77\x40\x8e\x69\x44\x64\x9e\x18\x61\x8a\xc7\xc4\x95\xbf\x26\x34\x8a\x44\xce\x35\xe1\x00\xb1\xb5\x6c\xac\xc3\xd5\x2d\x88\xed\x16\xf2\xd3\xb6\xd2\xd3\xc0\xae\xf3\xd1\xbb\xdc\x37\x9c\xd8\x4f\x58\x5b\x50\xbd\x3a\xb6\x97\xb6\xf0\xf5\x8f\x73\xad\x5d\x58\xe1\xd6\x8c\xb0\xb6\xbf\x23\x91\xb0\x68\x71\x95\x27\x40\x66\x22\x89\x15\x96\xf5\x37\xdc\xbd\x70\x38\x54\x45\xe4\x0c\xef\xc6\xd5\xf7\xc9\x38\xd7\x24\x16\xa0\x08\x17\xda\x17\x06\xa8\x3d\x6e\x5d\x4c\x77\x33\xdb\xda\xc1\x3c\x44\x68\x96\x25\x98\x4a\x21\x8c\xd0\x72\x37\x63\xd1\xcc\xf6\xab\xc9\x68\x04\xeb\x6e\xdb\x5e\x7a\xd9\x4a\xbc\x26\x3b\x89\xd8\xc4\xdb\xac\xc6\x8f\xa1\x0a\xd9\x51\xd6\x26\xb6\x44\xfc\xb7\x52\xe4\xd9\x96\xb7\xaf\x5a\x16\xed\xd3\x86\xca\xeb\xa5\x06\x36\xfe\xa2\x73\x19\xd9\xbd\xb1\xb7\x15\x26\xd1\x21\x21\x17\x13\x92\xe6\x89\x66\x59\x82\x8f\xd8\x6a\x03\x8a\x50\x09\x25\xdf\xe8\x13\xca\x17\xde\x03\xe5\xda\x44\x40\x4c\xe8\xd4\xcc\xa8\xb1\x3f\x8c\x2f\x49\xcf\xf3\x14\xcc\x69\x8e\xcb\x97\xa0\x3a\xc5\x17\xe5\xec\xe4\x8e\x25\x89\x91\x67\x69\x92\x88\xbb\xf5\x6c\x69\xdd\xd8\x4d\x28\x24\xbb\x09\x86\x64\x77\x11\x98\x10\x2e\xb8\x37\xed\xfe\x70\xf5\xb6\xd9\x26\x5e\xd6\xe7\x70\xbd\x40\x40\x1b\x90\x66\x54\x6a\x46\x13\x92\xcb\x44\xd9\x7d\xa4\x46\x09\x90\xbe\x99\xca\x8c\xa2\x67\x30\x02\x65\xbb\x76\x90\xdf\xdb\x9d\x73\x80\xb5\xe7\x53\xf0\x64\x41\xa8\xdd\xf9\x49\x9e\x24\x7d\x32\x61\x9c\x1a\xb2\x0b\x99\xcf\x84\x31\xfa\x13\xb9\x66\x3c\x02\xf3\x4d\x83\x42\xb0\xc0\x15\x99\x19\xcd\xf9\x2e\x0e\x69\xdc\x77\x6d\x45\xac\xb6\xac\xdc\x2b\xcc\x81\x8d\xe8\x38\x01\xec\x6b\xe1\x44\x96\x2b\x91\xa0\x79\xdb\x19\xbe\x63\xdb\x8b\x84\x56\x2f\xff\x37\xe3\xa8\xa4\x90\x2b\x64\x1c\x46\xd9\x01\xa6\x67\x46\xf7\xc9\xb2\x64\x61\x08\x85\xc1\x9d\x12\xa1\x0e\x55\x1e\xcd\xcc\x27\x1d\x64\x22\x56\x07\x86\x8c\x1c\x28\x88\x24\x68\x75\x70\x64\xfe\x5a\xfe\x06\xfc\xbe\xea\x73\xc7\x34\x63\x07\x47\x7d\x82\x00\xc2\x46\x27\x42\xcf\x9e\x2f\x1e\xfa\x6f\xad\xf5\xd7\x7a\x6c\xd4\xb5\xd6\xea\x0c\xae\x6b\x87\xc8\x6c\x13\x0c\x43\xa3\x35\x60\x9e\x94\x41\x4a\x44\x03\xdf\x1e\x6a\x95\x58\x13\x72\xc2\x09\xa4\x99\x5e\x20\x16\xa7\x40\xb9\xbb\x1b\xe6\x20\x17\x7a\x66\xb4\x55\xa6\x9e\xff\xe1\xdf\xd2\xb1\x54\x8e\xb5\x00\x77\x07\xde\x03\xb7\x44\x72\xdb\x59\x69\x19\xb8\xbd\xdf\xf7\xaa\x52\xaf\x11\x9f\x4a\x6a\xfe\x6c\x41\x89\xec\xb5\x11\x18\x3f\x98\x27\xeb\x20\xb4\x3f\x59\x6a\x59\xd0\x8f\xb7\x6f\x6d\x17\x25\x07\xab\xef\x19\x8f\x55\x51\xc9\x28\xb6\x64\xd0\xc1\x7b\x2d\x90\x71\x85\xcf\x11\xc0\xab\xe2\xeb\xb6\x22\xe7\x23\xd3\x57\xf4\x9b\x7d\x50\x49\xb0\x2b\x53\x4d\xca\x31\x74\xaa\x6f\x5d\x4e\x46\x17\x49\xe8\x18\x12\xdb\x72\xc9\x5c\x2d\x97\x4f\x4e\xde\xbe\x2b\xba\x93\x49\xa0\x8f\xd8\xb3\x3e\x82\x22\xb2\x85\xe3\x74\xa5\xc7\xdb\xea\xd8\x5e\xf6\x44\x50\xec\x66\x0c\x26\xd7\xa0\xed\x31\x4b\x69\x66\x4e\x99\x9d\x63\xad\x2d\xf3\x2d\x42\xfa\xf1\xc3\xb2\x93\xcc\xbe\x7d\x4f\xa6\x75\x2f\xd9\xea\xa8\x6c\xe7\xf1\xdd\xe5\xec\x3d\x60\xe1\x28\x47\x0d\xcc\x4b\x08\xed\xe4\x7a\x27\x89\x47\x45\x7f\x3d\x8b\xc1\xca\x26\x46\xdb\x34\x74\xe9\x7f\x2f\xa7\xe8\x78\x0b\x76\x51\x9a\x8c\xde\x9c\x40\xa4\xc5\xc3\x65\xdf\xfc\xcd\x1a\xd2\x2c\x79\xec\xe4\x91\x9d\x15\xac\x94\xf1\x2b\xa0\xf1\xe2\x1a\x22\xc1\xe3\x2d\x09\x6c\x6d\x3f\xde\x31\xce\xd2\x3c\x25\x3c\x4f\xc7\x80\x20\x56\x76\x2e\x24\x24\x56\x79\xa5\x84\xc3\x5d\xb2\x70\xc4\x23\x26\x99\x88\x3d\x3d\x19\x1b\x65\x8b\xc6\x0b\xec\x6f\x86\x05\x52\xf9\xc2\x4c\xc2\x74\xc9\x7d\x24\x89\x24\x55\x46\x2c\xea\xe3\xa4\x4c\x1b\x8e\x35\x06\xf4\x2d\xb1\x18\xcc\x1e\xd3\x39\x65\x89\x11\xad\x87\xe4\x0c\x26\x34\x4f\xb0\x4d\x1f\x79\x45\x0e\xcd\xcb\xbc\x3e\xb5\xee\x01\x23\xee\x2a\x61\x34\x71\xe5\x72\xdc\x71\x41\x47\x3b\x58\xcb\xb7\xa9\xdf\xe7\xc7\xb6\x75\xfc\xfc\xc8\x68\xae\xb6\x55\xc3\x6b\x1b\x73\xc1\x63\x73\x1e\xaa\x92\x68\x85\xa4\x33\xe5\x66\xde\x8e\x65\x3f\x5c\xfb\x60\xcd\xaa\xa5\x98\x4a\x50\xea\x0c\x68\x9c\x30\x0e\xcd\xf1\xeb\x66\x06\x24\xa5\xf7\x88\x63\x9a\xa5\x60\x24\x91\x2a\x86\xd1\xea\x57\x69\x41\x52\x7a\x0b\xc5\xeb\xc9\x18\x26\xd8\x86\x11\x3f\xb8\xb2\xfb\x16\x7f\x26\x94\x25\x10\x0f\xf1\x1d\x95\x59\xca\xee\xc5\x16\x71\xcc\xdf\x8c\xe7\x60\x9e\xca\xa4\x40\x65\xd2\x3e\x5a\xe5\xf1\xc8\x43\xa9\xb9\xd9\xd2\x61\xdf\xb1\x6f\xb4\x04\x8a\xf3\xfb\xc8\x1a\xf9\x24\x50\x85\xb7\x59\xdc\x54\xb9\x9c\x18\xd5\xd1\x6b\x9c\x95\x05\xb9\x56\xaf\xe4\x52\x68\xd7\xf8\xaf\xf8\x40\x7c\xda\x35\xa2\x04\xa5\x59\x8a\x07\x2c\xce\xa5\x6f\x8b\x89\x30\xa3\xeb\xb7\xbe\x76\x54\xfe\xfc\xea\xd5\x96\xf2\xdb\xc7\x47\x7a\x09\xa8\x29\x37\xc1\x97\xcb\x82\x0e\x79\xf2\x6f\x54\x60\xb3\xc7\xcc\x89\xc1\xd8\xdf\x13\x24\xfa\x09\x99\xd2\x8c\x4f\x73\xa6\x66\x64\x0c\xfa\x0e\x80\x13\xb8\xb7\x15\x2e\xc8\xbf\x41\x0a\xdc\x54\x03\xde\xd2\x45\x50\x03\xda\xeb\xfd\x81\xd8\x9c\x29\x26\xf8\x77\x4c\x69\x21\x17\x6f\x59\xca\x1e\x29\x3d\xea\xc7\x6a\x97\xe3\x02\x82\x22\x89\xb1\x37\x31\x8b\xe8\x35\xd8\x0f\x96\x80\x16\x4c\x2d\xac\x7a\x4a\xcc\x39\x19\xd3\xe8\xf6\xa3\x01\xf8\xd5\xbe\x40\xd8\xb3\xeb\x06\x50\x45\x79\xaf\x98\x00\xc9\x96\x45\xca\xf3\x7b\x0b\x9f\x1a\x94\xef\x66\x42\x01\xde\x60\x8d\x8c\xf8\x98\x77\x0a\x30\x55\x10\x0c\x73\xba\x05\x07\x45\xe8\x64\x52\xbf\xa3\x3c\xec\x28\x79\xa6\xb9\xd2\x24\xa5\x3a\x9a\x59\x53\x96\x88\x0b\x71\xa2\xa7\x9c\xd8\xbf\x0b\x94\xb7\x36\x22\xef\x6e\xee\x25\x76\x9d\xe7\xf7\x46\xb7\x7c\xd4\x9b\x53\x1f\x35\x90\x2f\x4f\x53\xd7\x80\x93\xfa\x86\x38\xb9\x2d\xb5\x2d\x82\x6f\xd0\x00\x5c\xfe\x82\xbb\x70\x72\x79\xb6\xbd\x29\xa6\x89\x82\xbb\xb3\x8a\xbb\x6c\xea\x7e\xe0\xa3\xbc\xc9\xd4\x5d\xa9\xdb\xbb\x6d\x6b\xe8\x3e\xa1\xe4\x16\x16\xb6\x8b\xf4\x4a\x5b\x5e\x09\x89\x93\x24\x00\xbb\xd3\x9a\x9b\x5c\x4b\xe9\x1d\xd6\xbb\x33\xf6\xd8\xb1\x9b\x2b\xc2\x8f\x81\x59\xe8\x8e\x4f\xf8\x8f\xde\xe1\xb1\xdd\x11\xdc\x8e\x5b\x58\xec\xf6\xc0\xd2\x76\x9b\x5d\x70\xba\x8f\xdd\x77\xf3\x43\x21\xe8\x15\x5b\xbd\x9b\x8f\xa8\x3a\x76\x36\x51\xf9\xe1\x81\xd8\xea\xf3\x0a\xf4\xab\x5a\x99\xcc\x37\xf6\x94\x45\x46\x73\xa6\x67\x2c\x43\x46\xe4\x9d\x01\xbe\xc9\xf9\x07\x9a\xb0\xb8\x98\xc2\x9e\xdf\x0b\xde\x37\xe2\x93\xf9\x0f\x12\x5d\x2b\xae\x9d\x09\x50\x97\x42\xe3\x2f\x9f\x0c\x40\x76\x99\xad\xc0\x63\xa7\x70\x56\x68\xa4\x32\xa8\x78\x55\xfa\xa3\xab\xa1\xaf\xec\x55\x80\x92\x29\x72\xc1\x89\x90\x1e\x0e\xd8\xb1\xde\x4e\x64\xa7\x40\x3e\x31\xb6\x0e\x0e\xb4\x4f\xaf\x9d\xc3\x81\x4f\xc8\x1a\xf4\x1e\x98\xce\x4d\x85\xf2\x81\xbd\x62\x3b\xe2\x27\x28\xed\x3a\x51\x95\x7a\x27\x37\x8b\x48\x0a\x72\x8a\x1e\x97\x68\x6b\x8f\x43\x7d\x53\x76\xa3\xbb\x76\xec\x4c\x7d\xab\x2f\xdc\x09\x0b\x90\x35\x59\x13\x50\x1b\xe6\x66\x67\xa8\x99\x9c\xfe\x8f\xa1\xe0\xb8\x07\xff\x97\x64\x94\x49\x35\x24\x27\x44\x31\x3e\x4d\xa0\x76\xcd\x69\x18\xd5\x69\xcc\x0c\x4c\x11\x43\x6a\xe7\x34\x71\xba\x14\xe5\x04\xac\xcd\xca\xcc\xbe\xcc\x52\xfb\x4e\x52\x31\x94\xa7\x70\x74\x1d\xdc\xc2\xe2\xa0\xbf\x82\x34\x07\x17\xfc\xc0\xf2\x96\x15\x34\x29\x18\x11\xfa\xc8\x0e\xf0\xda\x41\x97\x5c\x78\x47\x86\xd3\xd4\x8e\x56\x7f\xe9\xd6\x18\xe1\x63\x3b\x1a\x0a\xeb\x35\x2d\xd1\x45\x34\x69\x41\x72\x05\x56\x5a\xc7\x53\x46\xc0\xcb\x99\x28\x55\xa2\x62\xca\xe1\x0e\xa5\xc7\xbd\x11\xfc\x8c\x26\xc1\xf8\xf4\x87\x2c\xa6\x7a\xab\xa0\x52\x3b\x6a\x10\xe9\x5d\xd9\x49\x48\x8e\xb3\x18\xdc\x9a\xb0\x29\xc9\xa8\xa4\xa9\x1a\x92\x91\xab\x6e\x88\x98\xc6\x26\x55\x5b\xa2\x83\xdd\xcd\x22\x03\xf2\xff\x90\xab\xea\x5a\x86\x64\x30\x18\x90\x9b\xf7\x67\xef\xdf\x10\xfb\x8b\x95\xb2\xb5\x20\x13\x81\x4a\x90\xc8\xa5\x79\xd5\x1c\x38\x2a\xfe\x46\xbe\x17\x1c\xde\x4f\xcc\x09\xa1\x1a\xe6\x20\xc9\x9d\xd9\xaa\x88\xc5\x50\x58\xaf\x86\xbd\x8f\x8b\xc7\xcd\x24\x93\x94\xde\x5f\xe7\x72\xba\xc3\x06\x90\x95\x4d\xa8\x9a\x6c\x4a\x65\x12\x51\xaf\x9a\x9d\xab\xa2\x19\xc4\x79\x02\x31\xa1\x63\x31\x87\x9a\xc9\xb6\xfe\x18\xb2\xf4\x1c\xfc\x83\x86\xe7\x8d\x95\x48\x72\x5d\x28\xab\x87\x70\xff\x86\xfc\x27\xba\xb6\x29\xc9\x40\x46\xc0\x35\x9d\xc2\xb2\x19\xc0\xde\xf7\xfa\xd5\x7f\x1c\x39\x7e\x64\x66\x74\xd6\x93\x57\x06\x23\xde\xd1\xfb\x1f\x78\x69\x1a\x64\x8a\xbc\x1a\x92\x93\xa5\x97\xe1\x73\x49\x94\x27\x68\x6b\x41\x77\x7d\xe5\x95\xe3\x05\x91\x22\x47\x87\x3d\xc9\xb3\xba\x36\xfb\x87\xff\xfc\x0f\xa3\xf4\xd1\x34\x4b\xe0\x8d\x2f\x8a\x6a\xd5\x66\x23\xc3\x68\x41\xfe\xf8\xea\x3f\x2c\xf5\x34\xe7\xb3\xd4\x0a\x4b\x98\x51\x03\xb0\x3c\x23\x2c\xb5\xa1\x98\x90\x2c\xca\xea\xaa\xb2\x8e\xfe\x4a\x53\xa9\x55\x9f\xa0\x57\xbf\x10\x0e\xb5\xd0\x34\x59\xd2\xf2\x51\x0b\x87\x3b\x0b\xa4\x58\x20\x4c\x00\x0d\x55\xe4\xf5\x1f\x5f\xfd\xc7\xaa\x39\xe5\x3d\x8f\x00\x9f\xc4\x27\x30\xcc\x62\x6c\x94\xfb\x5b\x96\x24\x10\xf7\x1f\x5d\xfe\x24\x97\x7a\x06\xb2\x4f\x80\x2b\x6f\xac\x32\xeb\x5b\x5a\x1b\xce\x2e\x73\xce\x51\x46\xb0\xd6\x61\xb4\x68\x55\x2c\x5c\xee\x63\x0d\x23\xd4\x24\x15\x4a\xaf\x5f\xf2\xf6\xc7\xcd\x0c\xca\x17\xef\x27\xbb\x8a\x03\x83\x06\x66\x88\xd5\xa7\x1b\x88\x94\xf7\x83\xdb\x22\x53\x72\xc0\xb8\x1e\x08\x39\xb0\xd3\xbc\x21\x5a\xe6\x8f\x7b\x0d\xca\x91\xd6\x4e\xc0\x27\x20\x03\x79\xe5\xbc\xad\xec\xea\x47\x39\xf9\xcd\xcf\x73\x2c\xee\xf8\x66\xca\x81\x84\xd3\xd1\x8c\x86\xa7\xbe\x6e\x71\x5b\x3a\x36\xe6\xed\xe6\xee\xff\xdf\x2a\x76\xef\x40\x0e\xdc\xd9\x2d\x4e\xbb\x91\xab\xd0\xe3\xd1\xdf\xe2\xed\xc5\xb1\xb5\x9c\xcf\xda\x9c\xcc\x0d\xf6\x35\x6b\x28\xd7\xca\x09\x5f\x43\x81\xec\x3a\x4a\x87\x8c\xc6\x88\x02\x73\xce\xd5\xc6\x83\x9e\x00\x55\x7a\x1d\x28\xc2\x41\x7f\x7c\x3c\x1c\xc0\xbf\x3c\xea\x42\xa7\x91\x90\x10\xe4\xa5\x8d\xf1\xd4\x22\xca\xc1\x15\x58\x0f\x9f\x0d\x38\xab\x09\x51\x07\xc5\x91\x30\xfb\x57\x97\xaf\x3e\x56\xd8\x8c\x37\x72\x36\x11\xad\xdd\xa3\x95\xc0\x5e\x67\x3a\x75\xc4\xab\xf0\x28\x5a\x97\xe6\xde\x48\xd1\x29\x68\xfa\x70\x92\xc7\xf2\xa8\x13\xed\x6b\x4d\x79\x4c\x65\xec\x56\xd9\xeb\xa9\x62\xca\x21\x79\x87\xbe\x34\x3e\x11\x6f\xc8\x4c\xeb\x4c\xbd\x39\x3e\x9e\x32\x3d\xbc\xfd\x8b\x1a\x32\x71\x1c\x89\x34\xcd\x39\xd3\x8b\x63\x74\xa0\xb1\x71\xae\x85\x54\xc7\x31\xcc\x21\x39\x56\x6c\x3a\xa0\x32\x9a\x31\x0d\x91\xce\x25\x1c\xd3\x8c\x0d\x4a\x99\x59\x0d\xd3\xf8\x0b\xff\xa2\x8f\x2c\x18\xd7\xce\x10\x5a\x97\xe4\x1c\x06\x39\xbf\xe5\xe2\x8e\x0f\x50\x93\x55\x3b\x9d\xa6\xed\xa2\x18\xfc\x58\x82\xf7\x2e\x81\x0b\x99\x88\x3f\xfa\x26\x98\x8f\x19\x50\x1e\x0f\xac\xd3\xf1\x23\xef\x45\x13\xdb\xee\xa0\x0c\x0c\xd8\x26\xe2\xdc\x8e\x66\xda\x10\x8d\x34\x9b\x43\x23\x27\xb6\x1f\xb5\xed\x7e\xef\x03\x46\xe3\x5c\xda\x1d\xaf\x78\xb3\xbd\x6f\x26\xa5\x0b\x94\x75\xf0\xdd\x44\x58\x56\xce\x45\x0c\xce\xf2\x39\x47\xd5\xfe\xda\x30\xf3\x1b\x23\x0a\x3b\x1f\x37\xda\x7d\x17\x4a\x43\x6a\x89\x93\x7d\x3e\x59\x10\x2d\x17\xd6\x31\x2e\x6f\x8d\xf2\xe9\x3c\xd7\x46\xe2\xbf\xc5\xfb\x94\x12\x11\x43\xd1\xa7\x84\xab\x97\xbb\xbc\x0d\x8f\x92\x4c\x28\x86\xef\x76\x3c\x6f\x37\xcb\x5c\x73\x76\x59\x71\xd3\xfd\xf9\x4f\xbb\x6c\xdd\x04\xdb\x28\xec\x68\x65\xaf\x47\x50\x4c\xaa\x11\xfe\x6e\x7b\x7a\xca\x2b\xae\x46\x2c\x89\x04\x57\x5a\x52\xb6\x39\x87\x69\xfd\x68\xe8\x0a\x69\xee\x6f\x20\x88\x41\x27\x8d\x80\x42\x56\x63\xb0\x3c\x53\x44\xb4\xf4\xa0\xae\x02\xc6\xa6\x38\xf9\x58\x42\x43\xb8\x1a\x9a\x56\x1b\xc0\x88\xb4\x82\x93\x7d\x1a\x26\x20\x25\xc4\x67\x28\x7d\x5e\x17\xdf\x75\x31\xe5\xa2\xf8\xf9\xfc\x1e\xa2\x7c\xdb\x4c\xf0\xd5\xb1\x62\xcb\xf3\x06\x11\x17\x76\x62\x17\x61\x8e\xae\xbf\xe0\xe4\x0f\x81\x60\x77\x82\x88\xa2\x9a\xa9\x89\xcd\x17\x2b\x36\x02\x2a\x8e\xcf\x02\x85\x0b\xf7\x30\xb2\x38\x9b\xfa\xc0\x34\x92\x9b\x68\x26\x84\x32\xa7\x1c\xf7\x13\xe7\x9d\x33\x61\x7d\x7e\x98\xbc\x22\x49\x6a\x68\x8c\x4f\x62\x29\xa7\xb7\x86\xda\xf2\x31\xa6\xac\x0a\x5e\x40\xd0\x7b\xa9\xcc\x34\x68\x78\x34\x7f\x4c\x51\x6a\x52\x9a\xa8\x3c\x35\x93\xde\x01\x9b\xce\xb4\xea\x13\x36\x84\x21\x62\x0d\xd0\x68\x56\x99\x36\x05\xd0\xb5\x2e\x28\x55\x54\xab\x5a\x89\x0f\x8b\xac\x06\x97\x86\xd3\x2f\x78\xcc\xf2\x5e\xae\x05\x57\x9f\x80\x8e\x86\x47\x7d\x52\x26\x8a\x9b\x35\x8e\x17\x84\x69\x30\x34\x1b\x75\x11\x29\xf2\xa9\xfd\x12\xf0\x31\x9d\xb8\xae\x22\xe5\x03\xbd\xa8\x31\xea\x8c\x07\xf6\xe3\x0e\xcc\xbe\xe1\xca\xf3\xd4\xe8\x8b\x05\x51\x47\xb3\xba\x6f\x9c\x23\xa4\x04\x95\x09\xab\x6d\x2e\x1b\xdc\xff\xff\xc5\x43\x87\xea\xa8\x04\xe6\x8c\x4d\x67\x1e\x96\xd4\x31\x82\xfa\x1e\xec\x7e\xf6\x48\x2b\x5f\x8a\x1d\x0d\x3d\x2a\x76\xd4\x7d\xdb\x3e\x5f\xa2\xc4\xaa\xca\xfe\x6b\x90\x69\x01\x45\x44\x11\x24\x19\xce\xce\xed\x1b\xd6\x38\x1c\x23\xaf\xc8\x21\x22\x19\xd3\x3d\x85\x08\x3f\x10\xd9\xd1\x90\x9c\x10\x9e\x17\x67\xee\xa1\x17\x70\x51\xcc\xef\x26\x32\x2f\x55\xa2\x9c\xab\xe1\x17\xb7\x22\x77\x76\x34\xf3\x94\x57\xc7\xc0\x41\x00\x1e\x2f\x8b\xf8\xd0\x24\x16\xd6\x0d\x27\x68\x47\xba\xfd\x1c\xfe\x2b\x9a\xcf\xb1\x12\x60\x81\xc7\xb5\x8c\xa2\x00\x99\xf6\xab\xd2\x53\x71\x20\xeb\xa7\xd8\xc2\xa2\x29\x56\x90\x6e\x30\x83\x74\x04\x57\xd2\x2a\x42\x67\xfd\x58\x0e\x63\xf1\x59\x54\x35\x68\xd7\x88\xfc\x78\x81\x57\x77\x0c\x5e\xda\x3c\xda\x52\xba\x72\xb4\xa2\x79\xe5\x78\x10\xf1\xf6\x2f\xb0\x67\xfd\xe8\x08\x6d\xed\x68\x4f\xda\xca\xb1\x7b\x68\xd0\xa6\x79\x1a\x04\x0c\xad\x1f\x5d\x9d\x4d\x3b\x1a\x04\x17\xad\x1f\x2b\x22\xea\xc7\x89\x35\x5a\x3f\x1a\x1b\x49\xd7\x8f\xa6\x71\x49\xeb\xc7\x52\xaa\xe2\x47\x0a\x52\xea\xd7\x23\x94\xc8\xb7\xda\x9e\xe3\xb7\xad\xf8\x49\x39\x3a\x06\x71\xb3\xc8\xa6\xf5\x63\x59\x00\x7c\x26\x51\x4e\x6b\xa6\xfa\x56\x9b\x69\xde\x6e\x7c\xd8\xe6\xa8\xfb\x38\x1d\xa7\x50\xf4\x5d\xea\x8c\xb7\x33\x63\x44\x75\x26\x01\xcb\x0a\x60\xd8\x97\xb7\xc3\x7c\x9a\xc0\xaa\xf5\xa3\x3b\xc6\x69\x47\x47\xec\xd3\x8e\xce\x90\x1b\x05\x9e\x6f\xac\x5d\xf8\x09\x65\x1d\x6b\x99\x0e\xb2\x4e\x90\x75\x76\x18\x41\xd6\xd9\x76\x04\x59\x67\xd3\x08\xb2\xce\x9a\x11\x64\x9d\x20\xeb\xb4\x1a\xfb\x27\xeb\x58\x4b\x55\x67\x06\xb3\x1f\xad\xc1\x75\xd9\x42\x86\xd2\x94\x0f\xe9\xa9\x9b\xca\x0c\xef\xbf\x76\x24\xf6\x06\xcd\x6b\x2e\x52\x5d\x52\x3e\x05\xf2\x7a\xf0\xfa\xd5\x96\xe9\x80\xeb\x47\x9b\xa0\x9d\xea\xd8\x35\x75\x70\x79\x6c\xf2\x48\x7c\x34\xef\x92\x3b\xa9\x85\xc3\xa3\x26\x61\x6e\x70\x10\x15\x55\xad\x52\xd0\x84\xea\x9a\x41\x9c\xa5\x50\x38\x44\x6b\x29\xc8\x65\x4c\xaf\xe0\xce\xdf\x61\x36\x75\xd8\x6c\x05\x11\x50\x1b\xc7\x3e\x86\x62\x15\x22\x05\x9b\x60\xea\x0f\xbd\x59\x02\x78\x58\x91\x43\x18\x4e\x87\x24\xb6\xc9\xda\x94\xbb\x98\xb1\xa3\x7e\xd5\x3d\x9e\x1a\xe2\x2a\xf1\x3f\x66\xd9\xce\x3f\x0e\x73\xe0\x3a\xa7\x49\xb2\x20\x30\x67\x91\x2e\xbe\x0f\x03\x02\x99\xb6\xce\xce\x36\xae\x94\x16\xe2\x61\x5b\x91\x70\xb0\x72\xb6\x76\xf3\x57\xfb\xd1\x5e\x76\x5b\x59\x47\x73\x7a\xb3\x24\x97\x58\x08\x0d\x37\xaa\x55\xda\xbc\xcd\xfa\x2b\xf1\x9f\x88\xe0\xef\xaf\x9a\xba\xc7\x48\x47\x3c\xa1\x35\x1f\x58\x56\xa0\xf2\x24\x31\xe8\x6d\x3d\x66\xab\x20\x58\xe3\xc9\x5a\x93\x6d\x63\xdd\xac\x69\x25\xeb\x06\xef\xb9\x11\x99\x48\xc4\x74\x51\xdd\x41\xdb\x91\xa5\x52\xde\x86\x12\x95\x8f\x9d\x08\x68\x0e\xd1\xe5\xd2\x96\x07\x5f\xc8\xc6\x11\x7c\x21\x2b\x23\xd8\x07\x96\x47\xb0\x0f\xec\x30\x82\x7d\x60\xcd\x08\xf6\x81\xd5\x11\xec\x03\xc1\x3e\xd0\x66\xbc\x7c\xfb\x00\x09\xbe\x90\x4d\x23\xc8\x3a\xe5\x08\xb2\xce\xf6\x23\xc8\x3a\xab\x23\xc8\x3a\x41\xd6\x09\xb2\x4e\x90\x75\x9a\x8e\x16\xc8\x9d\x89\xb8\xf3\x14\x99\x4c\xc4\x0f\x64\xc8\x58\x7b\x75\x24\x06\x89\x88\x8a\xca\x22\xe6\x11\xe7\xf9\x50\x34\xb5\x26\xf4\x3e\xf9\xb7\xe0\x60\xd3\x13\x6c\xc9\xda\x14\x88\xc0\x26\x10\x99\x88\x0f\xd5\x51\x83\xc0\xf3\x90\x61\x13\x32\x6c\x3e\x83\x0c\x9b\x19\x55\xae\xf0\x11\x92\xd6\xcd\x09\x37\x95\xe3\x7f\x03\x32\xfd\x6c\xf3\x6d\x0c\xc2\x39\x84\xc1\x1e\x71\x25\x52\x58\xd8\xc5\xce\xb7\x0b\xf1\xa8\x0e\x31\xa7\x97\xd9\x16\x3b\x71\x0c\x31\xc9\x40\x0e\x2c\x92\x09\x32\x61\xae\xfe\xd7\x12\xfe\x3a\x08\x3f\xf3\xbc\x99\x3a\x24\x9e\x75\xf2\x4c\xfd\x53\x3a\xf3\x4d\x55\x5d\x74\x35\xae\xf8\xec\x52\x69\xba\xd1\x4a\x07\x44\x3b\x77\xda\xf7\xad\xf4\xd2\xae\x94\x48\x54\xf2\xae\x77\x2a\x73\xbc\x79\xac\x2d\x4e\xfb\xaf\x1c\xe4\x82\x88\x39\xc8\x52\x31\x2a\xba\xf3\xf4\x8b\x26\x33\x11\x75\x05\x90\xbb\x31\xf0\x74\x62\x8a\xe8\x52\x53\xef\xda\x6b\x48\xf6\xac\xfa\xf1\xe6\xd1\xad\xe2\xd0\xa1\xda\xf0\xdc\x6a\x29\x6f\x1e\x9d\x9a\xdf\x48\xc7\x26\x38\xd2\xa1\x19\x8e\x74\x6b\x8a\x23\x9d\x9b\xe3\x48\x97\x26\x39\xf2\xc9\x2b\x40\x6f\x1e\x1d\x9b\x8f\x48\xe7\x56\x3a\xf2\x0c\xeb\x49\x6f\x1e\x1f\x01\xdc\x5d\x5a\xec\x48\xa8\x4e\xdd\x7a\x74\x6d\x50\x23\x5d\x1b\xd5\x48\xd7\x78\xd8\xa8\x0a\xf6\xe6\x11\xea\x63\x7f\x04\x39\xad\x33\x21\xa2\x6d\x4d\xed\xc7\x16\xda\x01\x4e\x16\xbd\x7b\x3f\x95\x02\x64\xb9\x74\xd9\x30\xd6\xbc\xbb\xd2\xab\x0b\x43\x35\xab\x8d\x4d\x7d\xdc\x2a\x62\x34\xfe\x1e\x7b\x83\x57\xce\x2b\xc5\xe3\x2a\x93\xad\xb4\x8e\x29\x4d\x67\x45\xf3\x18\xa3\x14\x94\x4d\xa7\x2a\x0f\xe3\xbd\x43\x1b\x4e\x5a\x4a\x13\x3c\x5e\x0e\x30\x2d\x9f\x40\xfd\xc2\xb6\xb3\x3d\xf0\x76\xec\x9e\x2a\xef\x38\x18\x56\x3b\xdf\xba\x19\x0f\xff\xcf\xff\x3d\xaa\x55\x6f\x29\x27\x0c\xda\xdf\xd6\x23\x68\x7f\xad\x46\xd0\xfe\x36\x8e\xa0\xfd\xb5\x18\x41\xfb\xdb\x6e\x04\xed\x6f\xf3\x08\xda\x5f\xd0\xfe\x1a\x8c\xa0\xfd\x05\xed\xaf\xe9\xf8\x8c\xb5\xbf\x6e\xa3\x9a\xab\xba\x98\x0b\x12\x41\xf9\x51\x53\xcd\xa2\x32\xe2\xd9\xdf\x65\xff\xd5\xad\x0e\x58\xd5\xef\xd6\x6b\x80\x55\x2d\x71\x45\x0b\x1e\x3e\xa2\xee\x15\x0a\xe1\xca\x93\x0f\x6b\x82\x2f\x2d\x72\xbb\x33\x4c\xac\xb8\x84\x3b\x45\xc5\x1b\x1f\x58\x56\x36\x5e\x2f\xa2\xce\x62\x72\xe8\x7d\xf1\xd8\x48\x85\x0b\x5d\xbf\xc8\x35\x1b\x94\x77\x14\xde\x79\x0c\xaa\xa9\xe5\xf3\xd7\x5c\xc8\x45\x0c\x5b\x11\x1f\x55\x62\x8f\x21\x8f\x20\x6b\x6b\xc0\xc6\xb5\x13\xc6\x6d\xa4\xa3\x6f\xfa\x23\xb8\x0f\x9a\xb2\xf4\x14\x29\xa0\xc7\x73\x2b\xfa\xe2\x7a\x50\xfe\x2d\x61\x57\x89\xf2\xa1\x78\xc8\x28\x77\xc9\xb0\x82\xfb\xae\xf4\xb6\xd3\x7c\x29\x2f\x17\xbd\x54\x8a\xb7\x0f\xc9\x39\x62\x7d\x75\x62\xa6\x10\x3e\xd4\xf6\x3f\xe9\x06\x91\xf7\xab\x70\xc3\xdd\xce\x85\x1b\x96\x22\x46\x42\xdd\x86\x50\xb7\xa1\x55\xdd\x06\xbc\x68\x0f\x77\xe7\x05\x1c\xc8\x8f\xae\x3d\x92\x04\x04\x55\x9a\x27\x9a\x65\x65\x04\xb6\xb2\xaf\x4a\xac\x26\x31\x71\x91\xa0\x75\x7c\x37\x6f\xa3\xd1\x6c\x19\xef\x71\x3e\x8c\xd8\x56\x48\x4e\x5c\xb4\x25\x36\x33\xc2\x8a\x03\x5e\xed\xb0\x21\xa5\xec\xf9\x47\x0a\x9e\x21\xc1\x56\xa5\xd6\x6c\x7b\x6d\x19\x3a\x9f\x18\x94\x30\x14\xfb\x01\x06\x51\x6d\x68\x81\x51\xab\x6c\x0e\xbc\xe4\x12\x87\xea\xe8\xc8\x4b\x43\x9d\x72\xaf\x8f\xc2\x7d\xfe\x56\xe1\x12\xff\xb5\x0d\xff\xc1\x0f\x2a\x38\x50\x09\xbe\x92\xff\x3c\xef\x90\xc8\xf6\xd1\x6d\x5d\x58\xe4\x3a\x8b\x6a\x7b\xf2\x88\xb6\xcf\xa9\xf6\xc5\x5e\xfa\x30\xf6\x4e\xeb\x78\x19\x7e\x8b\x90\x30\xba\xfd\x78\x0e\x09\xa3\x4f\xe4\x9b\x78\x3e\x79\xa3\xcf\xd6\x1f\xf1\x5c\xf2\x46\x83\x0f\x62\xa7\xf1\x52\xd3\x39\xeb\xa3\x43\x9f\x43\xf0\x37\x74\x2c\x53\x75\xc2\xfc\x3f\x8e\x9f\xa1\x13\xfc\xeb\x34\xba\x2c\x44\x96\x3d\x65\x64\x59\xd0\xc2\x82\x16\x56\x1f\x41\x0b\x5b\x19\x41\x0b\xdb\x61\x04\x2d\x6c\xf3\x08\x5a\xd8\xea\x08\x5a\x58\xd0\xc2\xb6\x18\x41\x0b\x0b\x5a\xd8\xb6\xe3\x33\xd3\xc2\xba\xab\xb7\x1e\x22\xbc\x3e\x42\x84\x57\x37\x94\xb0\x03\xfa\xd7\x09\xd6\x75\x14\xd1\x15\xa2\xb9\xf6\x3b\x9a\xab\x65\xd9\x39\xae\xd9\xc7\x29\x3d\x57\xdd\xed\x4d\xf5\xe7\xe8\x5c\xb0\x98\x64\xb9\x76\xd5\xb7\x42\x0d\xba\x7d\xae\x41\x57\xdb\xd1\x50\x88\x6e\xab\x42\x74\x9b\x60\x16\xaa\xd1\x6d\x18\xfb\x13\x63\x16\xaa\xd1\xed\x3a\x42\x35\xba\xf5\x23\x54\xa3\x7b\x60\x84\x6a\x74\xa1\x1a\x5d\xa8\x47\xd0\x62\x84\x7a\x04\x6b\x46\xa8\x47\xd0\x7c\x84\x7a\x04\x5b\x8d\x50\x8f\x20\xd4\x23\xa8\x8f\xe0\x85\x6a\x37\x42\x3d\x82\x96\x23\x78\xa6\x42\x3d\x82\x56\x13\x86\x6a\x74\x2f\x2a\x66\x90\x04\xed\x2f\x68\x7f\x5b\x8f\xa0\xfd\x6d\x1c\x41\xfb\x6b\x31\x82\xf6\xb7\xdd\x08\xda\xdf\xe6\x11\xb4\xbf\xa0\xfd\x35\x18\x41\xfb\x0b\xda\x5f\xd3\xf1\x19\x6b\x7f\xa1\x1a\xdd\xde\xc7\x2a\x92\x7d\xcc\x48\x0a\xd5\xe8\x42\xfc\x62\xa3\xed\x0e\xd5\xe8\x1e\x1f\x9f\x7d\x35\xba\x5a\x2c\xdd\xd3\x95\xa4\xdb\x7d\x19\xa1\x2e\x5d\xa8\x4b\x17\xea\xd2\x85\xba\x74\xa1\x2e\x5d\xa8\x4b\xb7\xfd\xd8\x7f\x6f\xc6\xde\xe9\x1f\x2f\xc3\x83\x11\x2a\x22\x6c\x3f\x42\x45\x84\x8d\x23\x54\x44\x08\x15\x11\x82\x37\xa2\xc9\x08\x15\x11\x76\x1c\xc1\xf3\x10\x2a\x22\xec\x34\x42\x5d\xba\x17\x13\x63\x16\xb4\xb0\xa0\x85\xd5\x47\xd0\xc2\x56\x46\xd0\xc2\x76\x18\x41\x0b\xdb\x3c\x82\x16\xb6\x3a\x82\x16\x16\xb4\xb0\x2d\x46\xd0\xc2\x82\x16\xb6\xed\xf8\xcc\xb4\xb0\x50\x97\x6e\xaf\x63\xbd\x42\x5d\xba\x35\x23\xc4\x75\xed\x77\x5c\x57\x43\x5c\xa1\xb9\x16\xa9\xc8\xb9\xbe\x06\x39\x67\x11\x9c\x44\x91\xf9\xeb\x46\xdc\xc2\x8e\xb1\x44\x75\x35\xf4\x81\x69\x09\xe3\x31\x8b\x50\x91\xbc\x9b\x01\x96\x95\x33\xf2\x2d\xde\x47\xa8\xbd\x91\x68\xbc\xb3\x44\x2f\x5c\xa7\x21\x6a\x18\x60\x83\x53\xef\x0a\x2f\x0b\xa1\xb1\x10\x09\x50\xbe\xc3\x93\x8e\x1b\x82\xdc\xf1\x34\xd7\x00\xf2\xd6\x91\xe2\x72\x32\x32\x86\x44\xf0\xa9\x8b\xe7\x71\x27\x60\x48\x4e\xcb\x1b\x22\xca\xf1\xf0\xe4\x52\x02\xd7\xc9\x02\xe1\x80\x05\xae\x50\x6b\x48\xc5\x1c\x62\x24\xd9\x18\x46\x64\xe5\x48\xaa\x49\x02\xd4\xbc\x8b\x43\xf9\x32\x73\x78\x28\x19\xe1\xfc\x76\xd2\x31\xb8\xd0\xa6\x46\x40\xdc\x9d\x36\x36\xa2\x86\x4b\x96\x0d\x27\x36\x21\x5f\x8a\x50\x3f\xaa\x7c\x21\x1e\xcd\x85\xc8\xc9\x1d\xb5\x92\x92\xcc\x39\x1e\x66\xfc\x74\x03\xda\x1d\x5f\xde\x42\x26\x69\x6e\x7e\x18\x20\x55\xdb\xf1\xb1\x36\xe6\x00\x2a\xa7\x8d\x98\x54\x6d\x6b\x7a\x27\x72\x9a\x5b\x91\xd0\xa1\x32\x70\x2d\x17\x18\x6f\x67\x65\x8a\x0a\x26\xa6\x74\x0a\xbd\x9e\x22\xa7\xef\xce\x0c\xf9\xcb\x95\xa1\xd6\xae\xca\x9e\x23\x87\x99\x14\x73\x16\x1b\xe4\xfe\x40\x25\xa3\xe3\xc4\xc8\x9d\x13\x90\xc0\x8d\x58\xf0\xe5\xe1\x87\x93\xab\x5f\x2f\x4f\xde\x9d\x1f\xa1\x04\x0a\xf7\x19\xe5\xe6\x54\xe4\xaa\x0c\x14\x75\xaf\x33\x2f\x02\x3e\x67\x52\x70\xb3\x3e\xd4\xd5\x28\x99\xfb\x59\xa3\xe2\x30\x48\x50\x22\x99\x43\x6c\xe5\xe4\xe2\x6d\x9e\xeb\x30\x9e\xe5\xda\xeb\x8e\x18\xbe\x68\x0e\x10\x8f\x66\x94\x4f\xcd\x3a\xcf\x44\x6e\xe6\xfb\xf2\x4b\x5c\x91\x84\x38\x8f\xac\xe4\x44\x3d\xd6\x7e\xd9\xf7\x9c\xc2\xd0\x7a\x65\x4b\x22\xaa\x88\x66\x7e\xcd\xd5\xcf\x52\x0b\xae\xe9\xfd\x1b\x1b\xbf\x77\xf0\x65\xe5\xd2\x81\x2f\x27\x29\xcc\x2b\x2c\xbf\xb1\xab\x4a\xb0\x92\x61\x42\x0e\xaa\x77\x0f\xc9\xb9\x79\x07\xc4\x55\x00\xda\xf0\x4b\x98\x83\x44\xcd\xd3\x81\xaf\x4f\x24\x4c\xa9\x8c\x13\x50\x18\x78\xe8\x69\xb3\xd5\x0e\x1c\xc0\xa0\xd0\x6b\xb9\xd0\xeb\x88\x09\x79\x27\x30\x08\x71\x22\xde\x90\x99\xd6\x99\x7a\x73\x7c\x7c\x9b\x8f\x41\x72\xd0\xa0\x86\x4c\x1c\xc7\x22\x52\xc7\x9a\xaa\x5b\x75\xcc\xb8\x39\x5c\x83\x98\x6a\x3a\xa8\x9c\xea\x63\xcb\xb9\x07\x91\x48\x53\xca\xe3\x01\x75\xd8\x35\x28\xb6\xf5\xf8\x0b\xc7\x53\x07\xb4\xb8\x8b\xf1\x01\x1d\xa8\x19\x24\x49\xaf\x01\x3e\xb7\x93\xf9\x5a\xc8\x7a\xad\x64\x3c\xf7\xed\xed\x0f\xf0\x79\x71\x5e\x2d\x0c\x86\xe4\x52\x68\x17\x1f\xeb\x42\xb1\x91\x8e\x22\x7c\x37\x1e\xe9\xf3\xcb\x9b\xab\xbf\x8f\xde\x5f\x5c\xde\x84\x93\x1d\x4e\x76\x38\xd9\x2d\x4e\x36\xf0\x79\xeb\x53\xed\x65\xce\xca\x31\x29\xf6\x1b\x39\xb5\x02\xed\x8f\x41\xb1\x01\xad\x25\x44\x3b\x9e\x0c\xea\x35\x08\x9c\xf3\xf9\x07\x5a\xb7\xb0\xf3\xb5\xe0\x20\xee\x06\x2b\x28\x17\x32\x78\x9b\xf8\xf8\x16\xd6\xac\xb6\xee\xab\x46\x52\xa4\x1d\xed\x5d\x4b\xe6\xd5\xcd\x0d\x0d\xb5\xed\xbb\xa4\x69\x59\xa1\x7a\xcd\xae\x0d\xc9\x3b\xaf\xf6\x90\xd3\x5f\x2f\xce\xce\x2f\x6f\x2e\xbe\xb9\x38\xbf\x6a\xae\x47\x77\x60\x71\x41\x9b\x42\x47\x00\xe8\x35\xe4\x92\x99\x84\x39\x13\xb9\x4a\x16\x85\x15\x64\x3d\x11\x58\x3e\xfd\xce\xef\xbb\x28\xf4\xf1\xb5\x8f\x05\x66\xdb\x2d\xb3\x3d\x83\x09\xcd\x13\xab\x3d\x1d\x1c\x0c\x9b\x70\x39\x3b\xba\x42\xdf\x6f\xa4\x68\x51\x81\xb9\x86\xc2\xd7\xb6\x76\xfb\x44\xc8\x8d\xc7\xb8\xe7\xa2\x0f\x6a\xac\xc7\x09\x8f\xd6\x42\xe7\xa4\x47\xeb\x24\x6b\x09\x9d\x96\x5e\x86\x6e\x7c\xef\x91\xe0\x13\x36\x7d\x47\xb3\xef\x61\x71\x05\x93\x76\x66\xe2\x3a\xbc\xd1\xfa\xe8\x5c\xc9\x68\xab\x34\xec\xcc\xbe\xac\x9d\x9b\xa6\x33\x27\x4d\x57\xd1\x19\xed\x23\x33\xba\x0b\xa4\xe8\x24\x88\x62\xa5\x1e\xbe\xb5\x43\x3b\x8b\x72\x57\x31\x36\x9d\x78\xee\xdb\x71\x79\x3f\xea\xcc\xae\xca\xee\x1d\x9d\xd5\xdb\xaa\x1d\x91\xe0\x11\x64\x5a\x1d\x8b\xb9\xe1\x5c\x70\x77\x7c\x27\xe4\xad\xd1\x23\x8c\xee\x3a\xb0\x58\xab\x8e\xd1\x67\x70\xfc\x85\x75\x83\xdd\xbc\x3f\x7b\xff\x86\x9c\xc4\xb1\x6b\x6e\x92\x2b\x98\xe4\x89\x6b\x27\x30\x24\x34\x63\x1f\x40\x2a\x26\x78\x9f\xdc\x32\x1e\xf7\x49\xce\xe2\xaf\x9b\x13\x67\x3f\x3a\xdc\x05\x91\x59\x57\x67\xc7\x3b\x71\x8d\x3e\x96\x45\x8d\x77\x15\x44\xc4\x70\x2d\xa6\x15\xe2\xa6\xb7\x3a\x3b\x21\xa3\x23\xd0\xec\x6e\xa2\x5f\x1e\xb8\x85\xdd\xd2\xd5\x5e\x49\x58\xad\x8b\xd3\x21\x6a\x26\xe2\x37\x44\xe5\x59\x26\xa4\x56\x24\x05\x4d\x8d\xd2\x3b\x34\x18\xd6\xaf\xff\x89\xbe\xaa\x3e\xf9\x47\xf1\x23\x3a\x9c\xd4\x4f\xbd\xde\xdf\xbe\x3f\xff\xfb\x7f\xf5\x7a\xbf\xfc\xa3\x7a\x15\x59\xa1\x8d\x02\xaa\xdf\xa2\x32\x88\x86\x5c\xc4\x70\x89\xef\xc0\x3f\x55\xcd\xcd\xe2\x2e\x68\xaa\x73\x35\x9c\x09\xa5\x2f\x46\xc5\x9f\x99\x88\x97\xff\x52\x2d\x24\x0e\xb2\x9f\x8c\x01\xb7\x68\x44\xf5\x6c\x4f\xd8\x43\x49\x4b\x3a\x3e\xaa\x6e\xd6\x6a\x13\x9d\x94\xe2\x3f\xbf\xf1\x20\x30\xd2\xd3\x9d\x64\x5a\xa3\xeb\xcd\xa5\x82\x8b\x49\xdf\x9c\xda\x52\xec\x9c\xbf\x6e\x5d\x1f\xa5\x53\xd2\x56\xec\x60\xc7\x00\x43\x88\x38\x68\xd9\x83\x5c\x30\xd8\x55\x17\xf3\xc9\xe8\x82\xcc\x2d\x84\xf7\x06\x38\x3e\xbd\xf7\x9b\x8f\x4a\xe3\x8a\xa6\x4b\x0e\x54\x85\x86\xf8\xc6\x06\x05\x15\x49\xc6\x24\x61\x29\x73\xb1\x86\xae\x41\x93\x22\x87\xf6\xc7\x61\x94\xe5\x7d\x77\xc3\x30\x85\x54\xc8\x45\xf1\x27\x64\x33\x48\x8d\xa6\x35\x50\x5a\x48\x3a\x85\x7e\xf1\xb8\x7d\xac\xf8\xcb\x3e\x58\x7b\xc1\xea\xd3\x56\x15\x2e\x5d\xa5\x8e\x22\x43\xfc\xf2\x68\x9b\x07\xfd\x9e\x90\xb6\x02\x33\x2e\x3f\x82\x48\x58\x58\xe2\xac\xc0\x59\x40\x11\xf5\xc9\xb9\x48\xf2\x14\x54\xbf\x10\x83\xac\x35\x80\xcf\x8d\x66\xa9\xf6\x4a\x50\x8b\xd9\x9c\xa9\x2e\xc2\x88\xd7\xc8\x69\xcc\x45\xe4\x8b\x5c\x67\xb9\x76\xf5\x66\x2a\x8d\xdd\x84\x42\xbb\x45\x51\x14\xa0\x46\xf6\x5f\x1f\xb4\x8f\x46\xa7\x5a\x83\xe4\x6f\xc8\xff\x1c\xfe\xfc\xd5\x6f\x83\xa3\xaf\x0f\x0f\x7f\x7a\x35\xf8\xeb\x2f\x5f\x1d\xfe\x3c\xc4\x7f\xfc\xfe\xe8\xeb\xa3\xdf\xfc\x1f\x5f\x1d\x1d\x1d\x1e\xfe\xf4\xfd\xbb\x6f\x6f\x46\xe7\xbf\xb0\xa3\xdf\x7e\xe2\x79\x7a\x6b\xff\xfa\xed\xf0\x27\x38\xff\x65\xcb\x49\x8e\x8e\xbe\xfe\xb2\xf5\xd2\x29\x5f\xbc\x6f\x49\x40\xed\x18\x74\x56\x2e\x68\x79\xc6\x8e\xe2\xac\xef\x07\xa5\xd2\x34\x60\x5c\x0f\x84\x1c\xd8\xa9\xdf\x10\x2d\xf3\x76\xc4\xa4\x64\x4a\x5d\x9f\x7f\xdf\xbd\xeb\x4d\xc9\x90\x0a\x76\xbd\x37\x07\x5c\x41\x24\x41\x7f\x0a\x4b\x8e\x7d\x93\x97\x53\x96\x62\x1e\x5f\x1a\x9f\xfb\x1c\x8c\x3b\x45\xc8\x20\xee\x6b\x29\x89\x4e\xa4\x48\x87\xa4\xe2\xde\x98\x63\xc2\x87\xbb\xef\x16\x5a\x58\x41\xfd\x08\xc6\xa0\x60\x0c\xda\x30\x1e\x35\x06\x5d\x5b\x3c\xdc\x5b\x4b\x10\xf0\x79\x53\x17\xc6\x5a\x0f\xba\xd7\x75\xb4\x20\x99\xc8\xf2\x84\xea\x0d\x9e\xb1\x35\xee\x74\x77\xd4\xcb\x78\xe4\x32\x98\xc6\x32\xb4\x74\xbd\x0f\x93\x9c\x24\x09\x61\xdc\x1e\x7c\x9c\xc0\x3b\xcc\x24\x58\xd5\x86\x50\xeb\xcf\x9e\x9b\x25\xdc\xb9\xb2\x72\xd5\xb8\x1c\x45\x94\xa6\x52\x63\xec\x31\x96\x9d\xb3\xac\xc4\x79\x9f\x18\x2f\x8b\xcf\x15\xc2\x61\x91\x0b\xb2\xb6\x33\x66\x42\x95\xf6\xcb\xc6\xd5\x68\x7a\x8b\xde\xc6\x08\x62\xe0\x11\x60\x62\x5a\x0e\xe5\xb7\x8e\x8d\xde\x46\xce\xf9\xdc\xce\x41\x49\x9c\xdb\x60\x10\x4b\xfe\xd6\xcf\xf1\xb2\x02\x10\x0c\x22\x5e\xfb\x06\xc6\x45\x1c\x02\x52\xfd\x42\xc3\x2e\xf2\xfb\x0a\x2b\xab\x7a\x9a\xc8\x83\xf6\x3c\xb3\xf0\x6c\xb5\x12\x86\x56\x98\x65\x69\x7e\xae\x33\xc9\x97\xe0\x0c\x6c\xcf\x3e\x3f\x3b\xd6\xd9\x11\xdb\xec\x86\x65\xee\xe0\x3b\xe9\x92\x4d\x76\xe1\x2c\xc9\x24\x4c\xd8\x7d\x47\xe7\xf4\x84\x97\x96\x18\x16\x03\xd7\x6c\xc2\x6c\xcf\xfb\x4c\x42\x06\x3c\x2e\x0a\x97\x62\x72\x38\xaf\xc3\x66\x2f\x83\x79\xac\xc0\xdd\x2d\x29\xbb\x5e\x27\xec\x07\x3a\x46\x02\x1d\x6b\x3c\x3e\x11\x1d\x73\x98\xbb\x3f\x44\x0c\x23\xcf\xdb\x47\xbf\x9f\xd6\x43\xd9\x11\x91\x77\x46\xb4\x32\xb3\xeb\x18\x67\x51\x36\x4b\xb2\x48\xc3\x2e\x48\xa3\x16\x36\x78\x8d\xcc\xd8\xd4\x40\x36\x81\x39\x24\x4e\x6e\x22\x29\xe5\x74\x6a\xf3\xbb\xb5\xf0\xa6\x5a\xa3\x68\x19\x3c\x96\x2c\x5e\x89\xbb\x47\x39\xde\xe0\x76\x22\x68\x8c\x17\xa5\x48\x12\x90\x8a\x24\xec\x16\xc8\x19\x64\x89\x58\xb8\x74\x6d\x1e\x93\x6b\x4d\xb5\xc1\xea\x6b\xd0\xcd\xdc\xbe\xad\x30\x16\x57\x3c\xca\x93\x64\x24\x12\x16\x35\x32\xaa\xd4\x77\xee\x02\xf7\x2b\xcb\x93\x84\x64\x38\xe5\x90\xbc\xe7\x48\x34\x4e\x92\x3b\xba\x50\x7d\x72\x09\x73\x90\x7d\x72\x31\xb9\x14\x7a\x64\xa5\xef\x7a\xc0\x9d\xbd\x91\xb0\x09\x79\x83\xd5\x6d\x34\xd1\x74\x8a\xba\x93\x77\x03\xf6\x0d\xfc\xab\x13\x58\xfa\x70\xc7\xd4\x5a\x65\xa5\x35\xe2\x7c\x81\x33\x19\x5a\x65\xff\xfe\xe4\xdb\x94\xb0\x09\x44\x8b\x28\x69\x7f\xb4\x4e\x22\x0c\x60\x28\x33\xce\x2b\xf8\xed\xaa\xa9\xbb\x1c\x4f\xd4\x02\x19\x27\xb6\xcc\xb9\xad\xdf\x5e\xa2\x7a\xb1\x22\xab\xed\xaa\x4e\x95\xc4\xc6\xcc\xb3\x2d\xdb\xcc\x84\xd2\xd7\x46\x43\xef\xa4\x18\x7a\x6f\xe4\xa7\x23\x58\xf2\x39\x49\x20\x26\x2c\x4d\x21\x36\x5a\x7c\xb2\x20\x74\xa2\x31\xd7\xb6\x66\x21\x88\x24\x58\xac\x75\x55\x4c\x66\x94\xc7\x09\x48\x32\xa1\x2c\x71\xf6\x80\xda\xfd\x1a\x64\xca\x38\x9a\x05\xac\x47\x16\x4d\x0c\xe6\xaf\x28\x12\xd2\x97\xa7\x67\x5a\xf9\x4b\xe5\xc1\x44\x3e\x52\x41\x80\x65\xd7\x32\x19\x27\x22\xba\x55\x24\xe7\x9a\x25\x76\x31\x42\xdc\x92\x48\xa4\x59\x82\x47\xa7\xc5\xc9\x2a\xfe\x39\x28\x50\x69\x60\x66\x57\xc7\x5f\x94\x97\xf0\x87\xa6\x0c\xbd\x03\x41\xac\x0b\x31\x0c\xee\x21\xea\x2c\xcf\xff\xfc\x1e\xa2\x4a\x61\x09\xec\xc7\x80\x27\x1a\xf3\x3c\xe9\x2d\xbc\xa0\x4a\x76\x2d\x72\xe9\xaa\xa3\x06\xbf\x53\x3b\xa7\x2f\x84\xe5\x5e\x41\x12\xc6\x91\xbe\xb9\xfc\x3a\xc2\xb8\x32\x9c\xbd\x76\x18\xec\xd1\x73\x42\x2b\x89\x99\xc4\x2a\x08\x8b\x22\x90\xda\xcf\x85\x05\x06\x84\xd0\xe4\xb0\x77\xdc\x3b\x5a\xb1\x3f\xf6\x8c\x04\x92\x80\xa5\xb5\x3e\x71\xaf\x58\x94\x62\x69\x96\x2c\x70\x1d\xbd\xb8\x4f\x98\xf6\x91\xd6\x32\xe7\x7e\x55\x2e\xe9\xaf\x4f\x94\x20\x5a\x52\x5f\x5d\xc5\xfe\x6a\x6e\xd2\x32\x77\x54\xfe\xb0\xf7\x5b\xaf\x4f\x40\x47\x47\xe4\x4e\xf0\x9e\xc6\xe5\x0f\xc9\x8d\x30\xa2\x74\x39\xd1\x42\xe4\x84\x83\x0d\xec\x87\xfb\x2c\x61\x11\xd3\xc9\x02\x29\x16\x11\xb9\xb6\x39\xc4\x54\xfb\x64\xc3\xf3\x7b\xa6\x5d\xbc\x9a\x21\x19\xaf\x10\x9a\x96\x6a\x11\x6a\xc4\x9c\x39\x1c\xcf\x80\x26\x7a\x66\x83\x44\xb8\xe0\x83\x7f\x83\x14\x98\x83\xc8\xdd\x95\x17\x57\xf5\xaf\x13\xcd\xc1\x10\xd1\x6f\xa1\xbb\x26\x3e\xdf\xdd\xdc\x8c\xbe\x05\xbd\x44\x32\xcc\x5b\x7c\xe8\x0e\x5a\x03\x40\x4e\x84\x4c\xf7\x80\x76\x74\xe3\xac\x1c\x90\x4c\xc8\x7d\x20\x61\x33\xa1\x5a\xed\x25\x59\xd9\x4f\xa1\x34\x6a\x43\x4e\x1a\xe3\x10\x99\x1d\xac\xc7\x90\xf8\x3e\x37\x17\xa3\x21\xf9\xbb\xc8\xcd\xd7\x8c\xe9\x38\x59\x14\x95\x18\x14\x68\x72\x60\xa6\x3a\x30\xe4\xc9\x60\xc3\x77\x40\x63\xa3\xa2\x18\xea\x01\x74\x3f\xfa\x59\x11\x77\x1e\xdc\xda\xba\xe5\x03\xb9\xd2\x22\x25\x33\xf7\xd9\xf5\xd4\x4b\x77\x32\x86\x78\x7a\x7c\x5e\x93\x84\xcc\x52\x38\xf7\xcc\x8b\xa3\x5f\x2b\x74\xc3\xc2\xdd\xfd\x3e\xc6\x32\x56\x51\x15\x6c\xae\xa1\x93\x4d\x0c\xe2\x16\x58\x06\xd5\xa0\x99\xab\xa4\x3a\xf6\xb8\xf6\x68\xe3\x44\xce\xe5\x89\xd0\xa9\xd7\x3e\xd6\xab\xd3\xca\xa3\xdd\xc4\x0d\x90\x75\x46\x56\x87\x33\xd6\xfa\xd2\x11\x10\x3f\x4e\xe9\xcb\x4f\x01\x80\x6e\x36\x9f\x74\x09\x81\xac\x83\xd0\xee\xd5\xc0\x6e\x2d\x8c\x1e\x8a\xa9\x97\x96\xb8\x22\x99\x50\x20\xe7\x4d\x93\xb9\xcb\xd1\xdd\xa7\x8b\xe6\x1a\xbf\x1f\x6b\xf2\xa4\x25\xe1\x79\x3a\x06\x59\x66\xa6\x48\xbd\x0a\x90\x4a\x64\xc2\xa5\xbd\xdd\x9b\x73\xeb\xed\x13\xcd\x93\x7f\xfe\xcf\xff\xfc\xe3\x7f\x0e\xed\xf4\x45\x94\x02\x27\x17\x27\x97\x27\xbf\x5e\x7f\x38\xc5\xe4\xd8\xb6\x50\xed\x28\x04\xb3\xeb\x00\xcc\x4e\xc3\x2f\x3f\x6a\xf0\x25\xa6\x7c\xb4\xa6\x22\x75\xdb\x3f\x4e\x69\x30\xc0\xe8\x6d\x46\xe3\x74\xb2\x5f\xa5\x58\x99\x91\x35\xeb\x86\x54\x73\xd4\xf6\xe2\x8c\xe9\x28\xbb\x16\xd1\x6d\x87\x7a\xcd\x19\x64\x12\x22\x6b\x27\xbb\x39\x1d\xd9\xd9\x8d\x7e\x79\xf9\xfe\xa6\x4c\x35\xc0\x78\x1c\xf2\xd6\xdb\x97\xbe\x73\x96\x34\xa3\x93\xde\x42\xa6\x0b\xd5\x7d\x4c\xa3\xdb\x3b\x2a\x63\xb4\x6c\x51\xcd\xc6\x2c\x61\xb6\xf8\xaf\x6f\x0a\xc9\x85\x0d\xf8\xb3\x45\xce\xc4\x64\xb9\xb4\x66\x69\x0e\x45\x93\x95\x8d\xa3\x99\x50\x96\xa0\x05\x35\xe7\x9a\xa5\xe0\x22\x82\xa2\xac\x30\xe9\x55\x6d\xda\x41\xf9\xf2\x63\x6f\x95\xaf\xde\x7b\xef\xd5\xdb\x59\x0f\x6b\x1b\x97\xb8\xc7\xac\xce\xb1\x38\x9b\x10\x12\x58\xdd\x67\xc1\xea\x32\x09\xd7\x5a\x64\x1d\x79\x49\xec\x64\x1b\x7c\x24\x63\x98\x08\x43\x84\x37\x3a\x3d\x7c\x8f\x60\x8e\xc9\x81\xde\xaa\x25\x6a\x8e\x0d\x1b\x91\xa9\xf2\x68\xe6\x0d\x94\x1c\x94\x3a\x46\x77\x48\x9e\x59\xad\x15\xc9\x75\x2e\xa1\x6f\xbe\x0e\x52\x5c\x5d\xbf\xcc\x72\x30\xaf\x07\x6e\x7f\x04\x1d\x59\xcb\x6d\x85\x90\x63\x61\x50\xb7\xfc\x65\x37\x4a\x24\xa9\x9a\x01\x96\x17\x81\x7b\xe6\xbb\xa1\x8c\x44\xdc\xeb\x95\x9f\x62\x18\xcb\x54\xd2\x08\x48\x06\x92\x09\xc3\x8c\x72\xae\x63\x71\xc7\xc9\x18\xa6\x8c\x2b\x0f\x0a\x33\xb7\x87\x19\xfa\x63\x98\x2a\x0a\xc3\x0d\xc9\x55\xad\xd8\x89\x4b\x43\x8a\x44\x79\x34\xdd\x9a\x97\x3d\x49\xc8\xb1\x2a\x2d\x93\x0b\x08\xfb\xf0\x58\xbd\xc5\x92\x0f\x73\x8e\x6f\x8e\x21\xa1\x0b\x1b\x6d\x3a\x61\x9c\x26\xec\xdf\x20\xd5\x51\x07\x1e\x27\x03\xc2\xf2\xda\xc6\x75\x60\xa9\x7e\x1a\xcd\xda\x39\x7f\x83\x8b\x6a\xcb\x11\x5c\x54\x6d\x26\x09\x2e\xaa\xe0\xa2\x7a\x64\x04\x17\x55\x70\x51\x2d\x8d\xbd\xd5\x92\x82\x8b\xaa\xf1\x08\x2e\xaa\x87\x47\x70\x51\x6d\x31\x82\x8b\x6a\xcb\x11\x5c\x54\xc1\x45\x15\x5c\x54\xc1\x45\xf5\x19\xd9\xed\xfc\x08\x2e\xaa\x95\x49\x82\x8b\x2a\xb8\xa8\xb6\x1e\x7b\xab\x7c\x05\x17\x95\x1d\xc1\x45\x55\x1f\x9f\x17\xab\xf3\x0e\x9e\x91\x51\xf5\xda\xe7\xb4\x8d\xd0\xa9\xc0\x22\xe7\x27\xaa\x36\x8d\x2b\x5e\x55\xe9\x13\x57\x29\x0b\xe2\x53\x71\x9c\x47\xa8\xf4\x33\xad\xcd\x97\xda\xd5\x55\xe1\x93\x0c\xd5\x71\x26\xec\xff\x95\x8e\x8a\x8a\x87\xc2\x2a\xbc\xcd\x73\xd6\x9e\x2c\x1b\xab\x8d\x5b\xe2\xd3\xb8\x24\xf6\xc4\x7f\xd3\x81\x1b\x22\xb8\x20\x5e\x9c\x0b\xe2\xe5\x74\xcd\x75\x9e\xf9\x9b\x99\x04\x35\x13\x49\x63\x44\xaf\x21\xf9\x3b\xc6\x59\x9a\xa7\x06\xe7\x94\xc1\x67\x36\x2f\x42\x00\x54\x81\xae\x96\x62\x5b\x2b\xa2\xb9\x91\xc5\x80\xc5\x4e\x29\x4b\xcc\x36\x62\xfe\xe6\x8c\xce\x0d\xae\xab\x3c\x8a\x00\xb0\x95\x5a\x55\xc3\xf9\xe3\xb0\x78\x53\xd1\x3a\xe3\x75\x3b\x7a\xd3\x8e\x89\xdb\x72\xa4\x38\xcb\x1f\xff\xd0\x68\x8e\xa9\xcc\xba\xa1\xcb\xdf\x5e\x8d\x4e\xab\x6d\xb2\xb9\x27\xcb\x8c\xcf\x45\x32\xb7\x1d\xf6\xf1\x26\x23\xac\xb9\x66\xfc\xd8\xcc\x7d\x0c\x9a\x56\x74\x1b\xa7\x16\x28\x02\x9c\x8e\x13\xf3\x9c\x79\xaa\xe0\xc8\x23\xcb\x77\x81\xea\x5c\x02\x99\x52\xfd\x94\x04\xbf\xbd\x0a\xd3\x4a\x7d\xe9\x82\xdf\xb4\x95\xd0\xeb\x36\x38\x23\x87\xd7\xad\x50\x53\xc4\x0b\x5b\x41\x7f\x6b\x39\xbc\x35\xa5\x6c\x2f\x1b\xb7\x3f\x5a\x04\x4b\xdc\xe0\x87\x77\x06\xe0\x03\xd7\xf2\xd9\xb3\xf3\xaa\x12\xe4\xbb\x4a\x69\x41\xb2\x84\x96\x7d\xa1\x70\x07\xbe\x43\x1e\x74\x3a\x83\xe8\xf6\xca\x79\x62\x0f\x15\x40\x21\x9b\x4e\x99\x9e\xe5\xe3\x61\x24\xd2\x63\x43\x12\xec\xff\x8d\x13\x31\x3e\x4e\xa9\xd2\x20\x8d\xb8\xea\x58\xdc\x20\x32\xb3\x30\x3e\x1d\xa6\xf1\xd1\x90\xfc\xcc\x6d\x76\x7b\xd9\x87\xb2\x52\xdb\xc1\xbc\xdf\xd7\xd9\x18\x83\xa1\xae\x42\x56\xdb\x87\x8f\x17\xb8\xbc\x61\x9b\x42\xc9\xad\x59\x52\x4b\x2f\xf8\xa7\xf7\x80\x07\xca\x45\x3a\x30\xb8\x3c\x37\x4f\x77\x67\x11\x1f\x1d\x78\xb8\xf7\xc8\xbb\xbd\x37\xa2\xf1\xbe\x78\xb4\xf7\xb0\xda\x74\x07\x0e\xd8\x2e\x3c\xd8\xdd\x79\xaf\x3f\x42\x51\xe6\x8f\xe3\xb5\xee\xd0\xb4\xd7\x91\xb7\xfa\x53\x78\xaa\x3b\xf9\xea\xb6\x1e\xea\x4f\xe7\x9d\xee\xe6\x73\xbb\x54\x04\x9e\xab\x47\xba\x03\x13\x7d\x97\xe6\xf9\xce\x4c\xf3\x1f\xcd\x03\xdd\xde\xfb\xbc\x07\x9e\xe7\xd6\x40\x66\x9c\x69\x46\x93\x33\x48\xe8\xe2\x1a\x22\xc1\xe3\xc6\x1c\x66\xa9\x4a\x67\x71\x7e\x94\x9d\xd6\xd9\xa9\xea\x89\x16\x33\xea\x8a\x91\x1b\x8d\xca\x26\x96\x78\x5f\x86\x13\x28\xd0\xab\x6c\x57\xb9\x97\xde\x09\xb2\x37\x06\x31\x9b\x75\xd2\xe5\x26\x7e\x27\xee\x88\x98\x68\xe0\xe4\x90\x71\xbf\x8f\x47\x15\x35\xb0\xb4\x4e\x16\x68\x6d\xae\xbe\x7e\xe5\x6f\x7e\x79\x66\x47\x34\xb0\x2a\xf5\xf1\xad\xc0\xee\x45\x8f\x9b\x81\xdd\x8d\x93\x3c\xa9\x9b\x82\xad\x79\xb8\x4e\x6f\x5e\x97\xe5\x94\x5f\xe3\xbc\xc5\x69\xa3\x3c\x26\x2e\x13\xed\xe5\x6d\x5a\xeb\xb8\x9a\xba\xe8\x57\xc4\xd1\x3c\x66\x35\xbe\x39\x1d\x59\xa3\x71\x30\x97\xec\x8b\xb9\xe4\x89\x62\x53\xf6\x50\xd0\x7d\xa6\xf1\x28\x41\xd0\xdd\x61\x54\x72\x53\xbf\x95\x34\x82\x51\xe7\x32\x82\x3f\x4e\x24\xce\x25\x75\x04\xb0\x10\xf9\xfc\xe1\xe1\x00\xb1\x3d\x4d\x45\x3e\x2f\x66\xca\x4e\xf2\x24\x59\x90\x3c\x13\xbc\x9e\xfd\x6c\x7d\xed\xcb\xc9\xb4\x68\x92\x5f\xf3\x96\x52\xb0\xcc\xa4\x70\x3c\x53\xe6\x9c\x1b\x1a\x5c\xf6\x44\x43\x41\x12\xcb\x34\xd3\x5a\xca\xae\x62\x53\xb3\x7c\xc3\xff\x30\x9b\xb7\x0c\x40\xac\x4d\x68\x9e\x9e\x08\x19\xb1\x71\xb2\x20\x33\x9a\x14\x0d\x70\x28\xb9\x65\x49\xe2\xa6\x19\x92\x6b\xd0\xd6\xa5\x60\x79\x67\x22\xf8\x14\x17\x47\xb9\x6f\xbc\x08\x91\x79\x36\x4a\x80\xf2\x3c\xb3\xef\x33\x9c\x78\x21\x72\xe9\xdf\x37\x2c\x1c\x13\x05\x07\xe6\x2c\xe9\x57\xda\xbb\x3d\xb8\xb1\x45\xec\x4f\xae\x8c\x00\xf0\xde\x97\xa5\xee\x57\xe7\xf4\x95\xc3\x55\xa5\xb9\x4f\x26\xc5\x9c\xc5\xd6\xbb\xe1\xc1\x86\x8d\xa4\x6d\x03\x9f\xe2\x3c\x73\xc1\x07\x1c\xa6\x14\x05\x15\x77\x8a\xec\x9e\xd9\x79\x6c\x04\x01\x8f\xb1\xa5\x8f\x91\xf0\x45\x56\x4b\xa7\x9f\x33\xdb\x8c\xb8\x02\x39\x72\xc8\x05\x11\x18\x8f\x9a\x73\xa6\x6d\x83\xfb\x59\xae\x49\x2c\xee\xf8\xd1\x4e\x5e\x57\x74\xb4\xde\xac\x05\x50\xdd\xfd\xba\x4e\xce\xb1\xdf\xfb\x30\x78\x99\x72\xa6\xcf\x09\xc9\xb9\x82\x96\xec\xbd\x33\xe1\xe8\xcf\x7f\x6a\x46\x23\x58\x0a\x22\xd7\x9f\x44\xfb\xbb\x9b\xb1\x68\x56\x15\x66\x59\x0a\x8a\x88\x7c\x49\x2d\x7e\xed\x1e\x5b\xbf\x43\x41\x05\x5c\x37\x9a\x1a\x76\xd7\x58\xbf\x96\xcb\x21\x94\x9d\xaf\x31\x4e\xfc\xec\xf2\xfa\xd7\xb7\x27\xff\x7d\xfe\x76\x48\xce\x69\x34\xab\xd6\xc4\xe0\x84\x22\xd1\x40\x42\x31\xa3\x73\x20\x94\xe4\x9c\xfd\x2b\x77\x0e\xdf\xc3\xe2\xd9\xa3\x4e\x6b\xb5\x37\xe4\xbe\xd8\x9d\xbf\xb3\x76\x70\xb6\xd7\xbf\x8d\xcb\x12\x0a\xb0\x81\xcb\xb2\xf8\x74\x6e\x2e\x59\xe5\x00\x45\x2d\x0c\x9c\x9f\xb2\xb9\x23\xc3\xae\xf8\x3d\x8d\x8b\x48\x31\x83\xe7\x06\x2d\x0c\xab\xa2\x63\x8c\xf0\x9a\x01\xe1\xa0\x0d\x5a\x17\x36\x26\xc1\x55\xad\x38\x49\xae\x40\xf5\xc9\x38\xc7\x98\xb4\x4c\xb2\x94\x4a\x96\x2c\xaa\x93\x19\x5e\x75\x59\xb8\xbc\x17\xcb\x4b\x3a\x7b\x7f\x7e\x8d\x39\x02\x99\xb4\x65\x4b\x30\xa8\x0c\xaf\xe3\x67\x8d\xc1\x3c\xe1\xda\x08\x0f\xc9\x09\x5f\xd8\x8b\xf6\x80\x33\x45\x12\xa6\x34\x20\x0b\x76\x32\xa4\x77\xa6\x1f\xbc\x1a\xe2\xff\x0e\xcc\x57\x4a\x23\x64\x16\xb1\x72\xd1\x4a\xf0\xaa\x15\x43\xd9\x38\xa9\x40\xd3\x7d\xfb\x8b\x6a\x08\x57\x06\x09\x19\x20\x56\x1a\xc2\xd1\x62\xab\x11\xbc\xb6\x41\x20\xe3\xd3\xa4\x8a\x55\xcd\xc8\x7e\x5b\xdd\xb2\xad\x66\x39\x28\xbf\x60\xd4\x54\xc1\xec\xa4\x31\x5d\xb9\x86\x8e\xda\x39\x95\xdc\xcf\xab\x53\x8e\x22\x88\x6a\x87\xde\x8b\x91\x3f\x01\x4e\xba\x49\x97\xda\xba\x66\x65\x4c\x52\x9f\xbc\x22\x7f\x23\xf7\xe4\x6f\xa8\x5e\xfd\xb9\x6d\xf3\xab\xb6\x8a\x4f\x17\x21\x46\x46\xab\xbf\x18\x75\x04\xf1\x1f\x0d\x75\x32\x33\x1a\xa8\x6a\x41\xc6\xcc\x89\xf3\x70\xaf\x41\x1a\x3a\xea\x76\xe2\x49\xdb\x86\x99\x05\x7e\x42\x34\xb3\xee\x86\x8b\x49\x3d\xac\x69\x37\x44\x33\x8f\x7f\x27\x94\xbe\x74\x54\xa8\xde\x00\xa7\x9c\x2d\xa5\x3a\x9a\xd5\xc9\x98\x11\xd4\x94\x2e\x0f\x98\x22\xb1\xc0\x28\x2b\x1b\xbe\x3c\x63\x2d\x82\x27\xf6\x07\x8d\xdb\xf9\xd3\x6b\xfb\xf9\xd0\x4e\x2d\x19\x50\x50\xf3\x71\x82\x55\xa5\x32\x56\x26\x62\x27\x93\x99\x65\xc5\x15\x9e\xf1\x80\x50\xe6\x6c\x35\x85\x95\x19\x71\xc9\x9c\xa7\x88\x72\x9b\x40\x32\x01\x29\x6d\xc4\xf9\x78\xe1\x83\xf5\x5a\x6f\x5e\xab\x93\x94\x49\xa1\x45\x24\x5a\x74\x36\xab\xfb\xb8\xdd\x74\x08\x04\x1b\xe5\xeb\xcd\xe4\x3f\x9c\x8d\xfa\xe4\xe6\x74\x84\xdd\x9e\xae\x4f\x6f\x46\x75\x4d\xe5\xe0\xe6\x74\x74\xf0\xa4\xa0\x20\x5e\xb2\x42\xc3\x74\x83\x49\x6a\x86\x27\x23\xb6\x0d\x52\x9a\x0d\x6e\x61\xd1\x90\xa7\x76\xc1\xd7\x07\xc5\x0e\x77\xf2\x41\x16\xcc\x29\xcd\x76\x9e\x4d\x02\x8d\xd9\x27\xca\xe2\xf2\x61\xb0\xc5\x3b\xd7\xa7\x73\xa5\x62\x0e\xb1\x15\x87\xfd\x13\xc0\xe3\x4c\x30\x23\x2f\x86\x1c\xaf\xdd\x9f\x0e\x39\x5e\x5b\x8f\x90\xe3\x15\x72\xbc\x56\xc7\xde\x04\xb2\x86\x1c\xaf\x97\xe5\xb7\x0f\x39\x5e\x9f\xb9\xeb\x3f\xe4\x78\xad\x1f\x21\xc7\x2b\xe4\x78\x6d\x37\x42\x8e\xd7\xee\x63\xef\x82\x96\x42\x8e\xd7\x4e\x23\xe4\x78\xad\x8e\x90\xe3\xb5\x61\x84\x1c\xaf\x0d\x23\xe4\x78\x85\x1c\xaf\x90\xe3\x15\x42\x5f\x1f\x9d\x6b\x3f\x43\x5f\x49\xc8\xf1\x72\x23\xe4\x78\xbd\x88\x00\x3f\x12\x72\xbc\xb6\x1a\x21\xc7\x2b\xe4\x78\x35\x19\x21\xc7\xeb\xa5\x98\x4b\x42\x8e\x57\xc8\xf1\xfa\x7c\x04\xdd\x90\xe3\x15\x72\xbc\x42\x8e\x57\xc8\xf1\x7a\x70\x15\x21\xc7\xeb\x25\xa8\x80\xbe\x0f\x70\xfb\x9c\xa5\xde\xa9\x48\xb3\x5c\x03\xb9\xf2\x53\x16\x52\xa4\x25\x0c\x4c\x55\x25\x82\xf6\x21\x84\x91\xe0\x13\x36\x75\x94\xfd\xd8\x36\xdf\x1d\x14\xdf\x33\xa8\x34\xbc\x7d\x86\xf1\x83\x09\x4b\x59\xb3\x44\x32\xb2\xb2\x31\x6f\x71\xae\x8a\x5f\xc6\x9c\xa4\x94\xde\xe3\x11\xa1\xa9\xc8\x6d\xc3\xe2\xc8\xed\x5f\x01\x42\xeb\xbd\xda\xbb\x9d\x21\xdd\xa8\x38\x65\x46\xdc\xa8\x8b\xb0\x12\xaa\x35\x48\xfe\x86\xfc\xcf\xe1\xcf\x5f\xfd\x36\x38\xfa\xfa\xf0\xf0\xa7\x57\x83\xbf\xfe\xf2\xd5\xe1\xcf\x43\xfc\xc7\xef\x8f\xbe\x3e\xfa\xcd\xff\xf1\xd5\xd1\xd1\xe1\xe1\x4f\xdf\xbf\xfb\xf6\x66\x74\xfe\x0b\x3b\xfa\xed\x27\x9e\xa7\xb7\xf6\xaf\xdf\x0e\x7f\x82\xf3\x5f\xb6\x9c\xe4\xe8\xe8\xeb\x2f\x1b\x2f\xb9\xb5\x48\xdc\x9d\x40\xdc\x91\x38\xfc\x51\x84\x61\xe7\xd0\xed\xe8\x2c\xba\x60\x94\x95\xd3\xe8\x18\xd6\x43\xa7\xd1\x53\x53\x14\xf3\x8a\x79\x98\x22\x22\x65\xda\x08\x87\x46\x1e\xa4\xd5\x70\x56\xa6\x6b\x4a\xa9\xa3\x03\x18\xd0\x4d\xb5\x6d\xaf\x5e\x84\x82\x56\x82\x58\x84\x97\xfc\x5c\xff\x79\x96\x66\x09\xb6\x35\xc7\xf3\x3c\xf0\xb1\x2c\xc8\x5c\x03\x6d\x78\x7c\x04\xda\xf0\x12\x69\x83\x82\x28\x97\x4c\x2f\x4e\x05\xd7\x70\xdf\xc8\xc2\x52\x27\x0d\xd7\xf5\x09\x5d\xcc\x98\xcb\xe2\x76\xd7\x88\xc8\x6c\xdc\xf7\x52\x3a\xfd\x4c\xe4\x49\x8c\xc9\x1c\x39\x47\x05\xd3\x66\xe9\x81\xb6\xda\x1f\xea\x3d\x18\xca\xbd\xfc\x12\xaf\xcf\x59\x35\xf3\x5f\x39\x9b\xd3\xc4\x68\xbb\xe5\x13\x23\xd4\x60\xaa\x0f\x6d\x7b\xe6\x35\x55\xb7\xe5\x81\x87\x81\x91\xa1\x8b\x35\x1f\xfb\x4f\xc2\x9f\xe0\x5e\x3f\x47\x29\x0d\x05\xa4\x91\x64\x73\x96\xc0\x14\xce\x55\x44\x13\xa4\x6b\xdd\xf0\x8a\x93\x0d\xb3\xe3\xc6\x4b\x91\x28\x72\x37\x03\x43\xab\x09\xf5\x26\x00\xcc\xb0\x9b\x52\xc6\x49\x6a\xb6\x28\xf3\x0f\x2b\x6b\x4b\x30\xe4\x3f\xa3\xd2\x6c\x70\x61\x33\x40\x15\x79\x2c\x44\xe2\x32\x1e\x92\x45\x39\xbf\xcb\xfd\xe1\xe2\x57\x0e\x77\xbf\x9a\xd9\x14\x99\x24\x74\x5a\x98\x0a\x14\xe8\x15\x6b\x5f\x39\xf5\xc6\x0f\xc0\x74\x82\x1c\x08\x4d\xee\xe8\x42\x95\x86\x93\x4a\xdd\x07\xf5\x86\xbc\x3e\x42\x74\xa6\x8a\x14\x73\xc4\xe4\x0f\x47\xe8\xfe\x3b\x3d\x19\xfd\x7a\xfd\xf7\xeb\x5f\x4f\xce\xde\x5d\x5c\x92\x4b\xa1\xc1\x32\xb5\x4a\x73\xc0\xa8\xd0\x30\xcc\x2a\xf1\x1d\xa8\xa5\x0b\x35\x44\xdb\x25\x53\xe4\x8e\xf1\x58\xdc\xa9\xc6\x36\x5a\x8b\x7e\x06\x78\x40\x79\xa3\x39\x22\x9a\x51\xec\x79\xd8\x82\xc3\xac\x44\x98\x54\x27\x45\x1e\x1e\xc7\xc7\xb1\x14\x99\x05\x82\x37\x72\x95\xac\xb6\xae\x46\x57\x63\x58\x71\x7f\x27\xf5\x09\xa7\x92\x72\x5d\x5a\x7b\xca\x3d\x73\xcd\x16\x87\xad\xb7\xe3\x79\x67\x34\xd1\xb8\xbb\x6c\xa6\x93\x38\x86\xb8\x06\xfe\x17\x17\x39\x78\xea\x3f\x6e\x51\x56\xa9\x20\xa3\xf7\xd7\x17\xff\x7b\x09\x8f\x17\x59\xbb\x40\xa9\x6e\x32\x63\xa5\xc8\x3a\xdb\xdd\x2b\x97\x79\x19\xf6\x77\x2f\xf6\xb7\xe0\x96\xdd\xb8\xe7\xaf\x72\x5e\x2f\x64\x54\xce\x4f\x52\x11\xc3\x90\x8c\x0a\x3f\x41\xfd\x6a\xa5\xc0\x01\x95\x40\xcc\x2d\x5c\x33\x9a\x24\x8b\xaa\x88\xa6\x85\xcd\x42\xac\xd5\x66\xa8\x12\xf2\x09\x4d\xd4\x53\x53\xe3\x36\xbc\xd1\xc8\x11\xef\x8c\x3e\xdc\xc9\x76\x14\xb3\x91\x18\xb8\xd0\x4e\xb0\x36\xab\xc4\x7a\x17\x52\x44\xc4\x2a\xdf\x95\x60\xac\x1a\x7f\x53\xd6\x57\xe1\x59\x23\x53\x1e\xd8\xa3\x62\x66\x6b\xa8\xce\x15\x2c\x0b\xe8\xbe\x0f\x71\xa1\x8e\x9b\xd9\x25\xd0\x58\xf0\x64\x81\x91\x97\x36\x96\x22\xa5\xea\x16\x62\xfb\x83\x13\xcd\x0a\x4f\x85\x99\xb1\x78\xd5\x8d\x59\xb7\x77\x4b\xa0\x48\x66\x23\x3c\xd0\x9d\x01\xf1\x13\xef\x7a\x8b\x43\x68\x80\xf2\x9e\x27\x8b\x2b\x21\xf4\x37\x45\x1a\x6d\x27\x18\xf0\xa3\x93\x96\xeb\xa6\x68\x14\x27\x29\xbe\x77\x80\xbb\x81\x87\xaa\x9a\xc1\x7b\x56\xee\xf8\x73\x3f\x52\x32\xe7\x27\xea\x5b\x29\xf2\xc6\x4c\x6c\x45\xd8\xfc\xf6\xe2\x0c\x49\x51\xee\x5c\x95\x5c\xcb\x05\x96\x0e\x58\xad\xfa\x56\x28\x06\x3f\x38\x67\x6b\xf5\x4c\x94\x7e\x31\xf2\x8e\x2e\x08\x4d\x94\xf0\xb0\x64\x7c\xad\x16\xea\x54\x5c\x73\x79\x2c\xf4\x6c\x45\xb7\x35\x07\x6a\xf5\xb9\x7e\xc5\x73\x59\x96\xa1\x63\x7c\xe5\x71\x4d\x6f\x41\x91\x4c\x42\x04\x31\xf0\xe8\xa9\xb7\xfd\xa9\x1d\x7e\x88\x3a\x97\x82\x9b\x83\xd9\x09\xf2\x5c\x14\x9e\x5e\x07\xd2\x2a\xaa\xa0\xcf\xd8\x69\x7f\x14\x3d\xc7\x78\x2c\x73\x05\xd2\xba\xb9\x65\x0e\x76\x27\xbf\xcf\xc7\x90\x18\xc8\x1b\x95\xd4\x75\x8a\xb7\xe6\x0c\x96\xd2\x29\x10\xaa\x0b\x4c\xd3\x82\x00\x57\x86\x62\x5a\x03\xa8\x26\xb1\x80\x32\xfb\x9e\x2a\xf2\xc3\xc5\x19\x79\x45\x0e\xcd\xbb\x8e\x10\x7f\xb0\x91\xbc\x16\x36\xc8\x6d\x59\x47\x9d\xf8\x29\x70\x49\x88\xbc\x44\x48\x4b\x24\xfa\x84\x0b\xa2\xf2\x68\x56\xed\x5e\xef\xd5\x66\x17\x08\x89\xae\x95\xfd\xc4\xf5\xa7\xa5\x50\x3f\x28\x90\x9d\x11\xa8\x1f\x1a\x10\xa8\xaa\x18\x65\x70\xae\x0e\x3d\x8b\x58\x29\x68\x1a\x53\x4d\x1d\xe1\xf2\x37\xec\xed\x96\x7e\xde\xe4\x4b\xc1\x5b\xc6\xf3\x7b\x1b\x78\xd4\x9d\xa9\xe5\xfa\x1c\xa7\x25\x91\x87\x3a\xee\x3a\xcd\xb2\x84\xd9\x6a\x1b\x4b\x81\x70\x17\x35\x5c\xe9\x6f\x10\x13\x91\x4e\xd0\x24\x11\x86\x3e\x1a\xe1\x84\xf2\x58\xa4\x2b\x2f\x33\x42\x24\xd4\xea\xa5\x0e\x49\xc0\xbe\xfa\xd8\x13\xa3\x50\x02\x73\x68\x51\x5b\x6c\xb9\x3e\xac\x99\xcd\x00\xc7\x63\x04\x4e\x4f\x12\x3a\x86\xc4\xc2\xd8\x62\xa0\x5a\xc5\xc0\xa7\x8e\x46\x95\x22\xe9\x2e\x7d\xe6\x4a\x24\x60\xc3\xbb\x3c\x20\xcc\xf4\xcf\x02\x0e\x38\x49\x57\x70\x40\x6d\xb0\x06\x07\xd4\x6b\x9f\x03\x1c\xf2\x16\xac\x9e\x2c\xc3\xc1\xc8\x0d\x75\x38\x20\xf3\xde\x77\x38\x28\x88\x22\x91\x66\x23\x29\x8c\xda\xd9\x19\x6f\x72\xd3\x96\x3e\x43\x6b\xd8\x58\x13\x8c\x85\xbc\xa0\x7e\x33\x95\x95\xc0\x4e\xaa\x2d\x93\xf0\xd1\x9d\xff\xab\xc2\xb3\x90\xf4\x2c\x33\x32\x3f\x4b\xcd\xbd\x68\x9e\x74\x17\x9e\x33\x3b\xe8\x22\x37\xa2\x85\xb1\xb3\x13\x6e\x24\x22\x9a\x60\xed\xd8\x76\x28\x47\x96\xd1\x6e\x79\xe2\x4a\x38\x2f\xfa\x28\xf1\x37\x1f\x40\x82\x65\x44\xf1\x17\x67\xc2\xe4\x22\x86\x8a\x2f\xdb\xc6\x21\xdf\xd8\xb0\x4f\xbc\xcf\x47\x12\x1b\xb9\xc2\xbb\x95\xe3\xda\xd3\x5a\xb8\x0a\x68\xef\x8a\x8a\xb4\x66\x81\xc0\x63\xc6\xa7\x68\x57\xeb\x13\x09\x89\x8d\x41\x76\x44\xe0\xd6\x6a\x90\x3d\x3c\x12\x7e\x52\x7f\x1e\xfc\xab\x51\x16\x63\x82\xbb\x99\xd1\x52\xe4\x25\xac\x89\x25\xb7\x4c\x91\x83\xb7\x1e\x00\x2d\x4a\x78\xee\x23\x87\x39\xb0\x5f\x58\xec\xa6\xb5\x74\xde\x32\x1e\xbb\x70\xdd\x1a\xb0\x8a\x62\xeb\x56\x0e\xc6\x40\x70\x16\x57\x69\xcb\x1b\xf2\x33\x27\x05\xb0\xc8\xa0\x31\x7a\x5c\x59\x91\xd9\xdb\xe8\x06\x0f\x1b\x5e\x8b\x97\x2c\x4f\xf3\x03\xc7\xbd\x37\xef\x1d\x18\xcd\x7d\xf5\x3e\xff\x2d\x4f\x5a\xba\xc7\x51\xbf\xae\xb5\x98\x1f\xed\xb4\x5e\xa4\x8f\x0c\x5a\x6b\xc6\xa7\xaa\xaa\xc9\xd0\x24\xa9\x19\xc3\xd7\xa9\x32\x7e\x87\x8b\xd2\xfa\xab\x2a\xc4\x52\x9a\xc1\x73\x51\x43\x12\x23\x4e\x3c\x73\x25\x64\x9a\x2a\x7a\x2a\x0d\x24\x34\xa3\xc9\x75\xd6\xbc\x44\x29\x59\x29\x87\xf7\xee\xfa\xa4\x3e\x35\x32\x6b\xec\xfc\x60\xf6\xca\x5c\x27\x34\x4e\x99\x52\x68\x08\x83\xf1\x4c\x88\x5b\x72\xb8\xa6\x1e\x57\x25\x4e\x4b\xb1\xa9\x3a\x76\x38\x3f\x30\xab\x3f\x22\x8c\x27\x45\x54\x14\xea\xc1\x5c\x2b\x6f\xc8\xc1\x97\x44\xc5\x2a\x70\x0f\x5d\xdd\x6a\x17\xac\xb0\xba\x4c\x5b\xa9\xda\x60\xc1\x93\x13\xec\xd5\xed\xb9\x6c\x59\x76\xe5\x91\x2d\xba\x74\xb8\xbd\x5c\x59\x6d\x2d\x1c\xad\xf4\xf8\xe4\x40\x72\xc2\x45\x04\xaa\xbb\x82\x4e\xdf\x95\x73\x92\x18\x6c\x16\x0f\x60\xf4\x13\xdd\x18\x64\x87\x76\xe9\x1e\x26\x83\xba\x47\x7b\x55\x89\xfa\xa6\x24\x2e\x46\x1f\x49\xb2\x19\x1d\x58\x25\xdd\x50\x34\x24\x81\x5e\x84\x98\x09\x2e\x5c\x92\x84\x61\xa2\x82\x23\x4a\x23\x89\xb2\xde\x3c\xdc\x13\x47\xa2\x2b\x4b\x3d\x2d\xbd\xc4\x55\x47\x20\x26\x93\xd9\xfa\x11\xe5\x1a\xee\x98\x9e\xf9\x4e\x2f\x35\xaf\x21\xae\x44\x82\x42\x07\x0c\x27\x20\xa5\x90\x2e\x20\xcb\xdb\xad\x71\x26\xa4\xe4\x18\xd1\x65\x90\x84\x9a\xbf\x7a\xaa\xea\xa8\x2e\x4b\xc1\x63\xbc\xa2\xc1\x26\x98\x4c\x20\x42\x41\xab\x0a\x60\x4b\xb5\x0f\xcb\xc2\xb7\x2e\xcb\xc0\x20\x98\x2b\x25\x9f\xb2\x7b\xf3\x96\xea\x53\x55\x97\xb8\x2b\x38\xbb\xfe\xf2\xd1\x90\x90\x0b\x5e\x44\xf0\xf6\xcd\x2e\x56\xef\xf4\xa1\x67\xda\x7c\x62\xb5\x0f\x01\x7e\x40\xd5\x70\x66\xa4\x43\x99\x77\x80\xf1\x6d\xcc\xe1\xa4\x6a\x12\xef\x94\x1c\xa0\x69\xdc\x4d\x6a\xb6\xde\xcb\x00\x6d\x4c\xe5\xe6\x96\x8f\x65\x2e\x7f\x1e\x0e\x10\xd2\x96\xce\xb9\x6a\x0a\x1d\x15\x87\xbf\xae\xcc\x56\x91\xde\x0b\x87\xdb\x48\xc4\xb6\x9a\x4a\x51\x0d\x02\x7b\x3a\x61\x75\x17\xf6\x6f\x2f\x9f\x95\x32\x1e\x17\x36\x3b\xa0\x5a\x66\xc5\x95\xd4\x8e\x89\x11\xb5\x13\x6f\x5b\x48\xb3\x04\x30\x8b\xb3\x32\x73\x99\xa0\x5a\xa9\x26\xdf\x2f\x16\x52\x16\xa4\x77\xc5\x5d\xfa\xe4\x9f\x78\x28\x8b\x40\x54\x5f\x77\x62\x54\x3c\x6e\x35\x44\xa6\x7c\x6b\x09\xcc\xb0\xd4\xc2\x9b\x2e\x48\xcc\x26\x13\xf0\x01\xaf\x46\x73\xa4\x92\xa6\x86\xc4\x2b\xe2\x40\x30\x86\x29\xb3\x01\x91\x05\x61\xeb\x19\x71\xcf\xe5\xfa\xf5\x2d\x31\x64\x9a\xa4\x6c\x3a\xb3\x88\x42\x28\x66\xe8\x12\xef\x54\x4c\x04\x8d\x09\xe2\xb6\x90\xe4\x8e\xca\xd4\xf0\x0d\x1a\xcd\xd0\x43\x49\x39\x89\x73\x89\x55\x96\x35\xd0\x78\x31\x50\x9a\x6a\x23\x29\x83\x74\x0a\xa5\x5f\x7f\x28\xa9\xff\xe0\x08\x25\xf5\xb7\x1c\xa1\xa4\x7e\x28\xa9\xbf\x3a\xf6\x26\x3a\x34\x94\xd4\x7f\x59\x65\x92\x42\x49\xfd\xa7\xf6\x26\x84\x92\xfa\xa1\xa4\xfe\x43\x23\x94\xd4\x7f\x64\x84\x92\xfa\x0d\xc6\x0b\xa0\x5c\xa1\xa4\x7e\x83\x11\x4a\xea\xaf\x1f\xa1\xa4\xfe\xea\x08\x25\xf5\x37\x8e\x50\x52\xbf\xf1\x08\x25\xf5\x43\x49\xfd\x50\x69\x74\xb7\xb9\xf6\xb3\xd2\x28\x09\x25\xf5\xdd\x08\x25\xf5\x5f\x44\x3d\x45\x12\x4a\xea\x6f\x35\x42\x49\xfd\x50\x52\xbf\xc9\x08\x25\xf5\x5f\x8a\xb9\x24\x94\xd4\x0f\x25\xf5\x3f\x1f\x41\x37\x94\xd4\x0f\x25\xf5\x43\x49\xfd\x50\x52\xff\xc1\x55\x84\x92\xfa\x2f\x41\x05\x54\x3a\x66\x8d\x2a\x80\x6e\x53\xac\xc8\x05\xa1\x57\x6a\x03\x8c\xf3\xc9\x04\x24\x52\x2e\x7c\xf3\x4a\xf0\x54\x59\x97\x71\xd9\xc9\x0a\xba\x8f\x75\x8f\x5c\xbe\xce\x86\xc7\x5d\x31\x02\xac\xd4\x59\x46\x8a\x9f\xbf\xff\x66\x4d\x65\xa4\xc6\x51\x85\x4d\x63\xa4\x71\xcd\xef\x79\x33\xff\xf8\x06\x80\xaf\xcb\x1f\x73\x70\x8f\x12\xa1\x5c\x84\x3b\x02\x2b\x9a\x51\xce\xc1\xeb\x7b\x4c\xa3\x1d\x65\x0c\xc0\x89\xc8\xc0\x79\xa7\x29\x51\x8c\x4f\x13\x20\x54\x6b\x1a\xcd\x86\xe6\x4d\xdc\x03\xbb\x8c\x46\x77\xbf\x28\x2d\x81\xa6\x3e\x2e\x3f\xa5\xcc\x4e\x45\x68\x24\x85\x52\x24\xcd\x13\xcd\xb2\x62\x32\xa2\x00\x13\x6a\x2c\xa3\x2a\x80\x81\x51\x71\x65\x08\x7b\xbf\x7c\x9b\x5b\x96\xa8\x96\xa6\x43\x6d\xb3\x8f\xf5\xc0\xd3\x4c\x2f\x8a\x38\x5e\x20\x13\x26\x95\x26\x51\xc2\x90\x5b\xe3\x1b\x6d\xee\x34\xce\xd7\xf7\xbc\x9a\xbb\x95\x2a\xb7\x54\x1e\xa3\xd8\x9a\x69\x65\xa3\x62\xcb\x09\xdd\x54\x31\x53\x4e\xcc\x57\x7d\x42\x7d\xdd\x34\x0b\x68\xbf\x52\x04\xb5\xe7\x2c\x76\x76\xf7\x53\x65\xba\x4a\xbd\xd8\x32\x6c\xb8\x44\x74\x4c\x71\xf0\xc8\xd9\xaf\x65\x73\x94\x02\x05\x46\xe9\xad\x1c\x03\xdc\x00\x0e\x73\x83\x03\x10\x81\xe1\xaf\x74\x03\xd6\x7f\x72\xa4\xaf\x30\xc5\x77\xa0\x14\x9d\xc2\xa8\xa1\xa3\x61\x93\x46\x86\xbe\x86\x72\x63\x10\x15\x12\x9b\x5d\x5b\xfc\x52\x46\x67\xd6\xc5\x20\x92\xda\x35\x15\xc2\xcf\x9d\x64\x5a\x03\x6e\x2a\x56\xd8\x43\x5f\xe5\x72\x02\x7e\x6f\x29\xc6\xf3\x9d\x9f\xa4\x7c\xd8\x10\x75\x1e\xdb\x88\xcb\x31\x90\xb1\x64\x30\x21\x13\x86\x61\x9c\x18\x58\xd9\xb7\x05\x97\xa8\xb5\x02\x28\x65\xf4\x5d\xc1\xbd\x2c\xeb\xd7\x35\x24\x3f\xba\x85\x69\x99\xf3\x88\x56\x6a\xd9\x62\x86\x29\x9b\x90\x29\x06\x66\x3a\x69\xf1\x4f\xaf\xfe\xfa\x67\x32\x5e\x18\x96\x86\x92\x95\x16\x9a\x26\xc5\x47\x26\xc0\xa7\x06\x56\xf6\x78\xd6\x73\x24\x0b\x08\x60\x37\x0f\xbb\xf0\xd7\x7f\xb8\x1d\xd7\x79\xec\x71\x0c\xf3\xe3\x0a\xfc\x06\x89\x98\xae\xeb\x8f\xd2\x3c\x64\xbb\xa1\x4a\xb4\x06\xcd\x44\xc2\xa2\x45\x6b\x44\xf3\x95\xbf\xc8\x4c\xdc\x59\x59\x7f\x0d\xf6\x94\xe9\x56\x99\xc8\xf2\xc4\x1a\x9d\xbf\x29\xb2\x8b\x73\x05\xab\x39\x80\x6b\xcf\x05\x9a\x49\xdd\x14\xcb\x75\xd3\x6d\x3c\xae\x7f\xa5\x70\xb9\x25\xce\x90\x57\x14\x00\x43\x45\xe8\x1b\x9a\x24\x63\x1a\xdd\xde\x88\xb7\x62\xaa\xde\xf3\x73\x29\x85\xac\xaf\x25\xa1\x86\x5a\xce\x72\x7e\x6b\x3b\x38\x14\x25\x12\xc4\xd4\x88\x56\x59\xae\x7d\x22\xc3\xba\x0f\xb6\xf9\xf2\x9e\x08\x7b\x35\xa8\x9c\x05\xee\x59\xa9\xeb\xb8\x54\x2d\x8b\x91\xd5\xf9\x55\x15\xd9\xfe\xf0\xea\x4f\x7f\xb1\xa8\x4b\x84\x24\x7f\x79\x85\x31\xdb\xaa\x6f\x0f\x31\xd2\x36\xc3\x28\x52\x9a\x24\x46\x6d\xa8\x22\xa5\x01\xf4\x3a\x24\xfc\xe4\x38\xa8\xdb\xa3\xdb\xd6\xa2\xd4\xcd\xcd\xdf\x51\x8e\x62\x5a\x41\x32\xe9\xdb\xac\xa4\x42\xad\xe9\x21\x63\xe8\x39\xea\x83\xa9\x61\x7b\x20\x00\xcd\x45\x92\xa7\x70\x06\x73\xd6\x45\x13\xa7\xda\x6c\x5e\xd5\x4f\x98\xc2\x04\xb0\x71\x22\xa2\x5b\x12\xbb\x8b\x95\xc8\x93\xe5\x4a\xe0\xcd\xa1\xd0\x34\x06\xa7\x45\xec\xcd\xc6\xef\xaf\x45\xdd\xa4\x34\xcb\x8a\x1c\x21\x49\xef\x6a\xc0\xc0\x33\x89\xe5\x0a\x5a\xd6\x93\x69\x6d\x66\x6e\x6b\x64\x1e\xb8\x2f\x32\x74\xb3\xf1\x14\x8d\xa3\x4e\xda\xdb\xa8\xcb\xd5\x37\x37\x4c\xd6\x10\xa2\x9c\xd0\x9f\x86\x0c\xff\x6d\xb3\x4a\x56\xb2\x22\x8b\xc4\xba\x02\x31\xac\x00\x60\xd0\x07\x49\x72\x73\x83\x6b\x07\xd6\xcd\x76\x21\x47\x35\xb8\xf0\xc2\xaa\x9c\x52\xed\x04\x42\x6f\xbe\xa6\x24\x03\xa9\x98\x32\x7c\xf9\x03\x1e\xa8\xd3\x84\xb2\xb4\x62\x02\x7c\x1a\x20\xd8\xc3\x8d\xe5\x93\xdb\x53\xca\x91\x88\xdd\x84\x48\x0a\x6d\xe9\xe8\x35\x62\x6d\x5d\xaa\xed\x90\xa1\x3e\x35\xa9\xfc\x50\x42\xb3\x4e\x29\xcd\x2f\x05\xa9\xb4\x77\xbd\x24\x02\x89\xdf\xf7\x5c\xe9\x63\xb1\xf8\x8e\xc8\x00\x12\x46\xb7\xb9\x75\x4a\x58\x53\x1e\xed\x41\xa9\x88\xf4\x4e\x0f\x1c\x12\xeb\x05\x37\x67\xc2\x3d\x4a\x7a\x6f\x7a\x4f\x4a\x24\x2d\x88\xa4\xc8\xe8\xb4\x55\x2f\x9f\x25\x48\x2d\x4f\x5b\x2d\x34\x61\xd4\x20\xbc\x5e\x94\x5d\xc3\xbb\x20\x2e\xeb\xe8\x60\x95\x24\xeb\x1d\xf5\x00\x76\x0a\x82\xcd\xc7\xbe\xa3\x0b\x42\xa5\xc8\x79\xec\xec\x4b\x85\x81\xef\xdd\xd2\x8b\x2f\x05\x07\x6f\x38\x5f\xae\x53\x81\x16\x7d\xc6\xc9\xeb\xe1\xeb\x57\x2f\x85\x53\xe1\x17\x2e\x71\xaa\xcb\x82\x53\x59\xfa\xf4\xa4\xdf\xea\x2b\xde\x77\xf4\xbd\xef\x9c\x89\xa5\x2c\x68\xcf\x7c\xb9\x6c\xfc\xe9\x4e\x32\x0d\x95\x1e\x7f\x87\xa8\xb8\x18\xfd\xb0\x52\x95\xe1\x68\x5d\x27\x89\x96\x40\x6a\x57\x06\x43\xe5\xe3\x8f\x48\xb7\x1c\x81\xc2\xe3\xb6\xce\xc2\xa5\x1e\x20\x61\x55\x40\x1d\x1c\x90\x43\x7b\x67\xcf\x26\x34\x1f\x3d\x29\x6a\x39\xa0\x9d\xdf\x67\x2d\x6a\x6c\x2e\xe5\xce\x67\x14\x6d\x70\x59\x87\x10\xfc\x6f\x98\xd1\x39\x60\x22\x37\x4b\xa8\x4c\xd0\xe7\x78\x6d\xd7\x4e\xc6\xb9\x26\xc0\xe7\x4c\x0a\x9e\x02\xd7\x64\x4e\x25\xc3\xaa\x38\x12\xb0\xb2\x83\xd1\x45\xbf\x3c\xfc\x70\x72\x85\x01\x0d\x47\xae\x24\x85\x5b\x65\xae\x7c\xf9\x9a\xea\x4a\x2a\xd3\x3d\xba\x7d\x7e\x1d\x06\x86\x48\x73\xfd\xba\xcc\x7b\xd2\x5c\xe7\xb6\x2d\xcb\x7d\x94\xe4\x8a\xcd\x9f\x8a\x92\xb8\x0c\xfb\x33\xd6\x68\x9f\x97\xb2\xfd\x4b\x40\xad\x24\xee\xa3\x69\x7d\x4d\x82\xde\x8a\xc3\xa4\xa7\x8a\xa4\xbd\xaa\x0f\xdc\x99\x9e\x5c\x2d\x0d\x1b\x3e\xe7\x2b\x2e\xae\x88\x10\x58\x37\xe6\x69\x8d\x50\x31\x57\xa7\xb8\xc2\xdd\xc0\x5a\x0f\x48\xae\xe5\xf1\x9d\x5d\x5e\x57\x8b\x90\x58\x75\x49\xc4\x43\x32\x2a\x7f\x2c\x2b\xd5\x60\xfd\xb4\x42\x89\x04\x39\x2d\x8b\x8a\x4f\x81\x83\x44\x21\xc1\x4c\x59\x6b\xab\x4a\xc6\x54\x59\x27\xcf\xd9\xe5\xb5\xb5\xd9\xee\x06\xb3\xc6\x62\x76\x73\x09\xd5\x70\x7c\x9b\xc6\xd0\x40\xb8\xad\xf7\x4c\x2b\x0c\x56\x06\x30\xa8\x94\xda\x89\xc9\xc5\x88\xd0\x38\x96\xe8\xf6\x71\xa2\x4f\xa5\x52\x65\xe1\x5b\xc0\xaa\x30\x54\x41\x75\x4d\x15\x70\x23\x89\x2b\x01\x4b\xce\xf2\x2c\x61\xd6\x8d\x50\x7d\xa0\xac\x66\x83\x4d\xbe\x76\x47\xda\x36\x6a\x5e\x63\x25\xaf\x05\x15\x12\x4d\x8b\x52\x3e\xb0\x7b\x12\x94\x48\xe6\x65\x41\xe1\xa5\x5d\x73\x27\x02\x4d\xe2\xc5\xae\xf9\x1a\x94\x5b\xed\x18\x70\x2d\xcd\xd1\x5c\xde\x2d\xec\x62\x9f\xe4\x78\x9a\x8a\x09\xd9\x1c\xd0\x3f\xee\xca\x6f\xba\x32\x6e\x65\x89\x63\xeb\x1b\xb6\x55\xa6\x81\x4a\x4f\xd1\x70\x55\x0d\x4f\x22\x79\x2a\x44\x58\x36\x76\x9c\x5d\x5e\x5b\x4a\x68\x3f\xbe\xe8\x4e\xbb\x6e\x97\x4a\xaa\xd6\x18\x03\x9f\xac\xca\x50\x1b\xcd\x63\xa9\xb9\x9f\x6b\xd7\xdd\x2a\x90\xa5\x85\xf8\xd7\x2a\xd9\xae\xc5\xdb\x15\x50\x19\xcd\x9a\xc0\xff\x01\x42\x60\x27\x25\xb1\xb0\x91\x00\x13\x21\x51\x25\x1e\x20\x79\x4f\x84\xb8\xcd\xb3\x6d\x28\xba\x9b\xc6\x36\x5c\xdb\x8a\x40\xd4\x9e\xf8\xac\x68\x7a\xcc\x55\x13\x7f\x6f\x5d\xf6\x01\x6d\x25\x1e\x9c\xa8\x4c\xa0\x10\xcb\x7a\xd3\x69\x92\x2b\x0d\xf2\x1b\x26\x95\x3e\xf0\xf5\xa2\x11\x83\xad\x4d\xa4\x57\xbd\xe1\x47\xa6\x67\xae\x74\x63\xaf\x5f\xbf\x64\xfe\x76\x13\xf7\x8c\x4e\xdb\xbb\x14\x1c\x7a\xc3\x65\xb1\xab\x20\xe5\x05\x59\xdb\xc8\x53\xdc\xd2\x15\x24\x36\x5e\x14\x2f\x54\x70\xe5\xc6\x95\xad\x34\x6f\xf0\xf4\x4f\x81\x26\x14\x4b\xc4\xe1\xdd\xb3\xb2\xcc\xa4\xad\x1b\x65\xeb\x64\x0a\x27\xe8\x2d\xaa\x20\xaa\x94\x92\xd2\x62\xf3\x67\x37\x91\xe7\x76\xc6\x00\x5b\x7e\xd4\xd5\x0b\x79\xcb\xf8\xed\x8e\xe8\x57\x8f\x2e\x39\x5f\x99\xad\x56\x4f\xdc\xfa\x68\x19\xb7\xc1\x77\x86\xc5\xd0\xb1\xc8\xb5\xaf\x49\xa2\x2a\x8a\x23\xe3\xff\xb4\x7b\x81\xf6\xf6\xcc\x56\xec\x5b\xa7\x23\xaa\xbe\x35\xfa\x78\x25\x50\x2d\xb8\xa6\x58\x5b\xf4\x4c\x44\xb7\x20\x49\x62\x96\x31\x24\x65\xe0\x4b\xad\x9a\xa5\xcc\x61\xc7\xa8\x8b\xa6\x96\x0e\xc8\x66\x90\x82\xa4\x49\x59\xd4\xb5\x05\xa8\xdf\x3a\xc2\x59\xcc\x5a\x8d\x49\xb1\x45\xd1\x5c\x19\x46\x73\x0e\xcf\xd7\xdd\x95\xd2\x85\xaf\x74\xcb\x38\x86\x1b\xdc\x33\x85\x66\xfd\x4c\xc4\xd5\xc4\xb3\x5c\x81\x1c\x14\x69\x81\x2e\xf7\x46\x15\x81\x38\x31\x8c\xf3\xe9\x94\xf1\xa9\xa3\xce\x48\xd3\x2b\xe5\xb6\x0b\x4d\x07\x23\xbd\x23\x09\xb6\xe0\x2c\x4a\x0f\x36\xbe\x8c\x55\xef\x4f\x45\x6c\x6f\x1f\x2f\xac\x36\xe8\x77\xb6\x0c\x90\xbe\xe0\x44\x48\x57\x1a\x81\xc6\x31\xae\x7d\xf5\x0b\xf1\x6a\xfd\xab\xfa\x45\x1c\x87\x8d\xec\x2e\x9e\xaa\x80\x45\xe5\x63\x23\xec\xe4\x32\x82\x75\xb6\xd3\x4a\x89\x5f\x3a\xa7\x2c\x41\x3b\x85\xe0\x24\xb2\xa7\xd8\xc5\x9a\x99\xd3\xcf\x7b\x18\x05\x87\xcd\x3a\xf1\x9d\xe7\xab\x18\xd0\xa2\x44\x55\x53\x3e\xd3\x88\xc7\xd4\xcb\x0b\x9d\xf0\x35\xdf\x62\x03\xc6\x35\xa4\x99\x90\x54\x2e\x96\x3d\xa6\x86\x26\x1a\x8c\x33\xfb\xb5\xb4\x31\x23\x11\x23\xdb\x58\x83\x67\x73\xdb\x38\x78\x0d\xaa\xad\x45\x69\x24\xba\x5c\x10\xbf\x81\x86\x3d\xa8\x68\x06\x71\x8e\xc1\xea\xd3\x9c\x62\x63\x73\x43\x34\x9c\x6d\x7d\xe1\xa2\x00\x2d\xee\x15\xf1\x85\x45\x56\xc2\x02\x63\x72\xb0\xe8\xa7\xf9\x05\x8b\x87\xda\x48\x44\xdb\xd7\x19\x7b\xbc\x16\x41\x89\x37\x65\xab\x09\xfc\x58\x98\xb3\x48\xfb\x87\x26\x9b\xf0\x34\xa2\x45\x3b\xd9\x91\x70\xc5\x06\x23\x30\xb4\x4f\xab\xf2\x53\x5c\x10\x0b\x96\x13\xfd\x99\x1b\x9e\xb4\x19\xf5\x4b\x3c\x7f\x04\xc3\x51\x8c\xaf\x6f\xc5\x03\xd4\xa2\x80\xd2\xba\x6f\x37\x6b\x5a\xca\x1b\x70\xb8\xdd\xf9\x39\xd9\xb5\x0e\x54\x0b\x7d\xa3\xb9\x33\xb1\x91\x13\xb0\x8d\x6a\x43\xe5\xb4\xbd\x1a\xd8\x3b\x91\xd3\x3c\xb5\xe5\xc9\xc5\x52\x85\x68\x8b\xdf\x68\xb2\x33\xdc\xf8\xf4\xdd\x59\x35\x3b\xa3\x1a\x76\xee\x73\x5b\x8c\x94\xd7\xd2\x94\xbb\x6c\xcb\xbd\x30\x7a\x67\x61\x20\x2e\xd9\x86\x53\x50\x9d\xb1\xb2\x78\x9b\x57\xd0\x19\xcf\x8c\xa0\x81\xe2\x51\x69\xae\xe4\xd1\x8c\xf2\x29\x5a\xf8\x45\x6e\xe6\xfb\xf2\x4b\x5c\x91\x84\x38\x8f\x5c\x4b\x0c\x1f\xda\xfd\xa5\x37\x6c\xba\xea\x44\xd8\x99\x4f\x45\x34\xf3\x6b\xae\x7e\x96\x95\x42\xde\x10\x36\x84\x21\x39\xf8\xb2\x72\xe9\xc0\xbe\x3d\x93\xc2\xbc\xc2\x45\x85\xe3\xaa\x12\xa6\xf1\xd0\x1d\x54\xef\x1e\x92\x73\xf3\x0e\x74\xf6\x14\x00\xac\x04\x2e\x8f\x4b\xf0\xf5\x89\x84\x29\x95\x71\x82\xc9\x84\x93\x42\xde\xb2\x29\x47\x0e\x60\x78\xd2\x31\x54\x90\x0b\xbd\xce\xf0\xba\x65\xc6\x87\xa6\xea\x56\x1d\x5b\x29\x6d\x10\x53\x4d\x07\xd8\x46\xc4\x12\xa8\x63\x6b\x39\x18\xb8\x02\xae\x03\xea\x70\x6a\x50\x6c\xeb\xf1\x17\x2e\x69\x6c\x40\x8b\xbb\x18\x1f\xd0\x01\x96\x52\x6d\x1e\x06\xfb\x04\x11\x13\xad\x94\xf8\x16\x75\x7c\x97\x25\xef\xa2\x8e\x3b\xc2\x00\xbb\xa0\x94\x75\xbb\x8b\xe0\x0c\x57\xaa\xb6\x76\x90\xcf\x2f\x6f\xae\xfe\x3e\x7a\x7f\x71\x79\x13\xce\x73\x38\xcf\xe1\x3c\xb7\x38\xcf\xc0\xe7\xad\xcf\x72\xa1\xda\xad\xd3\x76\x97\xea\xe6\x55\x92\xc5\x5f\x50\xdc\xd9\x39\x9f\x7f\xa0\x46\xb8\xcc\x24\x28\x94\x45\x8c\x8c\xba\xce\x41\xec\x6e\xb0\x8d\xc4\x4e\x9f\x7d\xe0\xd9\x13\x86\x8d\x75\x18\x8e\x73\x59\xa9\x71\xb0\x6e\xd7\xaa\x9d\xfb\x4e\x7f\xbd\x38\x3b\xbf\xbc\xb9\xf8\xe6\xe2\xfc\xea\x49\xe3\x28\x5a\xd6\xad\xab\x73\xe3\x86\x5c\x32\x93\x30\x67\x22\x57\xc9\xa2\x28\x7d\xbb\x9e\x08\xac\x86\xe2\x71\xa3\x0a\x2e\x8a\xea\xbe\x6b\x1f\x0b\xcc\xb6\x5b\x66\x5b\x0f\x2b\x69\x51\xb2\xa4\x2b\xf4\xfd\x46\x8a\xb4\x23\x14\xbe\xb6\xe6\x01\x6f\xcd\x5f\x87\x4f\x3d\x57\xdd\xa0\xc6\x7a\x9c\xf0\x58\x96\x52\x30\x52\x68\x9a\xe9\x16\x7d\x0d\x3a\xa9\x54\xda\x4d\x51\x4f\x1b\x82\xf1\x8e\x66\xdf\xc3\xe2\x0a\x5a\x56\x46\x59\xf2\xa2\x24\x10\x19\x46\x47\x6e\x61\x61\x9d\xab\xa7\xfe\x65\x6d\x2a\xb8\xec\x65\xa1\xd7\x5b\x68\x53\x84\xb7\xcb\x0a\xad\xb7\xd0\x22\x26\xd3\x8f\x95\x5a\xa5\x66\x0b\x51\x4e\x33\x7b\xda\x6e\xf7\x48\xb7\xd5\x59\x3f\x42\x45\xda\x5e\x95\xdd\x3b\x3a\xab\x77\x2e\x1c\x21\xe6\x86\x73\xc1\xdd\xb1\x8b\x47\x1b\x18\x8d\x75\x60\xb1\x56\x1d\x63\xd0\xcd\xf1\x17\xf8\x1f\x72\xf3\xfe\xec\xfd\x1b\x72\x12\xc7\x2e\x2e\x3a\x57\x30\xc9\x13\x6b\xa5\x57\x43\x42\x33\xf6\x01\xa4\xc2\xc6\x70\xb7\x8c\xc7\x7d\x92\xb3\xf8\xeb\x36\xf5\xa4\xec\xe8\x70\x17\x84\xf7\x45\x75\xbb\x13\xd7\xce\xd5\x58\xe5\x5d\x05\x11\x21\x36\xe9\x11\x71\xd3\x97\x96\x71\x42\x46\x47\xa0\x69\xdb\x03\x8f\xd8\x2d\xec\x96\xae\xf6\x4a\xc2\x6a\xdd\x38\x45\xed\xad\xf8\x0d\x51\x39\xd6\xc0\x51\x45\xe3\x3a\x6c\x05\xdb\xaf\xff\xa9\x32\x1a\x41\x9f\xfc\xa3\xf8\x11\x5b\xcd\xab\x9f\x7a\xbd\xbf\x7d\x7f\xfe\xf7\xff\xea\xf5\x7e\xf9\x47\xf5\x2a\xb2\x42\xd4\x9a\x97\x6e\x41\xd7\x15\x17\x31\x5c\xe2\x3b\xf0\x4f\x27\xae\x9d\x44\x91\xc8\xb9\x76\x17\x30\x61\x79\x38\x13\x4a\x5f\x8c\x8a\x3f\x33\x11\x2f\xff\xa5\x5a\x15\x49\xdb\x4b\xc6\x80\x5b\xd4\x22\xf1\xc6\x8e\xee\xd8\x43\x49\x4b\x3a\x3e\xaa\x6e\xd6\xa2\x29\x47\x34\x83\xd4\x96\x69\xfa\xc6\x83\x00\x9b\xeb\xfa\xca\x08\x1c\xd3\xc9\x8d\x64\x5a\xaf\x98\x77\x30\x7f\xdd\xaa\x0b\xb9\x1d\x1d\x92\xb6\x62\x07\x3b\x06\x18\x42\xc4\x41\xcb\x1e\xe4\x82\xc1\x7a\x2d\xa5\x74\x34\x9f\x8c\x2e\xc8\xdc\x42\x78\x6f\x80\xe3\x3d\x6e\xdf\x7c\x54\x1a\x57\xf5\xeb\xd5\x34\xc4\x37\xb6\x17\xad\xbf\xee\x4a\x08\xa8\xa2\xaa\x17\x18\xc5\xe6\xd0\xfe\x38\x8c\xb2\xbc\xef\x6e\x18\xa6\x90\x0a\xb9\x28\xfe\x2c\xfc\x89\x03\xa5\x85\xa4\x53\x4c\x39\xb1\x8f\xdb\xc7\x8a\xbf\xec\x83\xb5\x17\xac\x3e\x6d\x55\xe1\x28\x97\x46\x68\x48\x16\x9e\x22\x37\x2c\x85\x51\x8e\x3d\xa4\x6d\x1e\xf4\x7b\x42\xda\x0a\xcc\x68\xdb\x71\xd6\x8e\x3a\x42\x96\x41\x01\x28\x70\x16\x50\x44\x7d\xd2\xa5\xd4\xf6\x0b\x31\xc8\x5a\x03\xf8\xdc\x68\x96\x8d\x8b\x82\x95\xa3\x43\x6a\x16\xb3\x39\x53\xa2\x45\x62\x4d\x31\xd1\xe6\x6c\x01\x57\xd5\xc3\xc6\x44\x15\x66\xb3\xfb\x0c\xeb\x20\x15\xe7\x75\x89\xec\xbf\x6e\xd3\x0a\xc9\x8e\x8c\x6a\x0d\x92\xbf\x21\xff\x73\xf8\xf3\x57\xbf\x0d\x8e\xbe\x3e\x3c\xfc\xe9\xd5\xe0\xaf\xbf\x7c\x75\xf8\xf3\x10\xff\xf1\xfb\xa3\xaf\x8f\x7e\xf3\x7f\x7c\x75\x74\x74\x78\xf8\xd3\xf7\xef\xbe\xbd\x19\x9d\xff\xc2\x8e\x7e\xfb\x89\xe7\xe9\xad\xfd\xeb\xb7\xc3\x9f\xe0\xfc\x97\x2d\x27\x39\x3a\xfa\xfa\xcb\xd6\x4b\xef\xa0\x2c\xa9\x1d\x5d\x16\x27\xad\xcf\xd8\x09\xfa\x7d\xc4\x8a\xfc\x76\x78\xf4\xea\xfa\xfc\xfb\xc0\xe8\x37\x25\x43\x2a\xd8\xf5\xde\x1c\x70\x05\x91\x04\xfd\x29\x2c\x39\xf6\x4d\x95\xe2\x08\x3d\x45\x0a\xd5\xe2\xa5\xf1\xb9\xcf\xc1\xb8\x53\xf4\xd2\xc3\x7d\x2d\x25\xd1\x89\x14\xa9\x4f\x78\x47\xf7\x06\x36\xd8\xf7\xf7\xdd\x42\xab\xee\xae\x76\x04\x63\x50\x30\x06\x6d\x18\x8f\x1a\x83\xae\x2d\x1e\xee\xad\x25\x08\xf8\xbc\xa9\x0b\x63\xad\x07\xdd\xeb\x3a\xd5\xea\x70\xdb\x39\xd4\x86\xfe\xa8\x97\x4d\x28\xcb\x10\x1a\xcb\xd0\xd2\xf5\x3e\x4c\x72\x82\xcd\xa6\xed\xc1\xc7\x09\xca\x8c\x12\xab\xda\xb8\xe2\x85\x30\x37\x4b\x28\xaa\x5f\xd7\xea\x5c\x62\x50\x25\x86\xb9\xfe\x68\xa3\x4e\x6f\x6d\x20\xaa\x51\xd2\x18\x2f\x2b\x84\x16\xc2\x61\x59\x56\x9a\x2a\x25\x22\x1b\x40\x5b\xe4\x37\x60\xd1\x3a\xb7\x6c\x5c\x0d\x76\xb8\xcf\x24\x44\x10\x03\x8f\xc0\x95\x9c\xae\x35\xdc\xa4\x9c\x9c\xf3\xb9\x2f\xbb\x1d\xfb\x6c\x19\x5c\xc9\xfa\x39\x5e\x56\x00\x82\x41\x44\xe7\x04\xab\xc4\x21\x20\xd5\x2f\x23\x67\x31\x14\x43\x4c\x4a\x2b\x6b\xb3\x9e\x7c\xad\xb9\x78\x7b\x9e\x59\x78\xb6\x5a\x09\x43\x2b\xcc\xb2\x34\x3f\xd7\x99\xe4\x4b\x70\x06\xb6\x67\x9f\x9f\x1d\xeb\xec\x88\x6d\x76\xc3\x32\x77\xf0\x9d\x74\xc9\x26\xbb\x70\x96\x64\x12\x26\xec\xbe\xa3\x73\x7a\xc2\x4b\x4b\x0c\x8b\x81\x6b\x36\x61\x36\x7b\x26\x93\x90\x01\xb7\x19\x09\x34\x9a\x21\xed\x77\x9c\xb2\x74\x4e\xef\x63\x30\x8f\x15\xb8\xbb\x25\x65\xd7\xeb\x84\xfd\x40\xc7\x48\xa0\x63\x8d\xc7\x27\xa2\x63\x0e\x73\xf7\x87\x88\x61\xe4\x79\xfb\x98\xf7\xd3\x7a\x19\x19\x44\xe4\x9d\x11\xad\x4c\x71\x3a\xc6\x59\x1a\x19\xa0\x5b\xe1\x03\xbe\x76\x94\x27\x49\x47\xa5\xb7\x7b\x17\x08\x8d\x2c\x4f\x12\x97\x71\x3c\x24\xef\x39\x1e\xc9\x13\x6c\xf1\xd0\x27\x97\x30\x07\xd9\x27\x17\x93\x4b\xa1\x47\x56\xb6\xad\x87\xb3\xd9\x1b\x09\x9b\x90\x37\x46\x6b\x52\x9a\x68\x5b\x66\xbf\x52\x14\x48\xc8\xda\x04\x65\xbd\xb1\x16\x61\xe8\x9b\xb7\xe5\x0b\x9f\x0b\x3a\x78\xa2\x6d\x2a\xfa\x98\x74\xa0\x9e\xba\x99\x7c\x80\x1c\x06\x45\x3a\xef\xc8\xba\x84\xde\x67\x58\x63\x23\x13\x4a\x5f\x1b\x2d\xb6\x9b\x1e\x37\x23\x3f\x1d\xb6\x8d\xa0\x49\x02\x71\xad\xc9\x91\x6d\xce\x41\xeb\x5a\x34\xa6\x1a\x17\xbd\x22\x80\xcc\x28\x8f\x13\x90\x58\xef\x5d\x2d\x17\xb5\x62\x65\x83\x83\xa2\x25\x85\x4f\x06\xa5\x51\x24\x64\xec\x9a\xcb\xba\xa4\x4c\x5c\x4c\x71\xbc\x90\xd6\xa6\x94\xd3\x29\xa0\x65\x61\xa5\x6a\x30\xd6\x92\x56\x95\xbe\x16\x33\x21\x6e\x49\x24\xd2\x2c\xc1\x03\xd0\xe2\x7c\x94\x6d\x75\x0a\x14\x1d\x98\xd9\xd5\x71\xa5\xe3\x0e\xfe\xd0\xae\xe1\x4e\x2b\x61\xa5\x0b\x51\x05\xee\x21\xea\xac\x25\xdf\xf9\x3d\x44\x95\x9e\x92\x66\x4b\x5c\x53\x49\x2d\xd0\xb6\xd1\xbe\x55\x70\x6b\xb3\x7c\x57\xa6\xf0\x16\x59\x66\xd5\xb1\x54\x43\x0e\xe7\xf4\x25\xb3\xdd\x2b\xb0\xfb\x80\xcd\x60\xc6\xcc\x33\x5f\x45\xbb\x76\x18\xec\xd1\x5b\x29\x3c\x57\x04\x1b\xfb\xb9\x30\xcf\x5a\x08\x4d\x0e\x7b\xc7\xbd\xa3\x15\x1b\xdd\x52\xdd\xe5\x9b\xca\x93\x0c\x0b\x0d\x66\x58\xb5\x0f\xa2\x5e\xdc\x27\x4c\x7b\x62\x6b\xeb\x1d\xe0\xaa\x5c\x3a\x5c\x9f\x28\x41\xb4\xa4\x31\x73\x5a\x10\xfe\x6a\x6e\xd2\x32\x77\xc5\x0e\x0e\x7b\xbf\xf5\xfa\x04\x74\x74\x44\xee\x04\xef\x69\x5c\x3e\x56\x06\xc9\x55\x65\xa2\x85\xc8\xb1\x01\x9f\x05\x41\x51\xe6\xc3\x50\x2c\x22\x72\xdb\xad\x67\x46\xb5\x4f\xc3\x3b\xbf\x67\xda\x77\xa8\x10\x13\xf2\xca\x36\x0b\x02\xea\xac\x84\x09\x9b\xc3\xf1\x0c\x68\xa2\x67\x36\x90\x82\x0b\x3e\xb0\xfd\xde\x0c\x29\x71\x57\xda\xfa\x14\xda\x99\xdc\xaa\xa3\x85\xf9\x6d\x75\x41\x2d\xa5\x6b\x43\x44\xbf\x6d\xde\x84\x96\xac\xf4\x67\xbe\xb9\x19\x7d\x5b\x6b\x43\x8b\x54\x5c\xeb\xcc\x87\xb7\x54\x4a\x66\xec\x01\xed\xe8\xc6\xa1\xd7\xaa\x1f\x2d\xe9\x90\x84\xb5\xed\x4b\x4b\x56\xfb\x6d\xef\xd6\x90\x96\xfc\x5d\xe4\xd8\x48\x8f\x8e\x93\x05\xb9\xa3\x5c\xfb\x54\xbc\x03\x33\xd5\x81\x21\x4f\x06\x1b\xbe\x03\x1a\x83\x54\x48\x3d\x80\x36\x2e\x0d\xe6\x47\x67\x8e\xa6\xca\xda\xba\xe5\x03\xb9\xd2\x22\x25\x33\xf7\xd9\xf5\xf4\x44\x77\x32\x86\x78\x7a\x7c\xee\x8f\x84\xcc\x52\x38\xf7\xcc\x8b\xa3\x5f\x2b\x74\xc3\xc2\xbd\x56\x42\x3f\xaa\x82\xad\xda\x68\x85\x71\x0b\x2c\xdb\x22\xb1\x23\x5a\xda\x41\x80\x00\xe9\x30\x48\x80\xb4\x4b\x76\x5c\x9e\x08\x1d\x5f\xed\xe3\xa1\x3a\x8b\x3b\x20\x9d\xf9\xd6\xc9\x3a\x43\xa4\xc3\x19\x1b\x05\xdb\x11\x10\x3b\xf5\x68\x93\xf6\xe9\x94\xd5\xf1\x30\x00\xba\xd9\x7c\xd2\x25\x04\xb2\x0e\xc2\x9f\x57\x83\x9f\x57\x1a\x85\x23\x99\xb0\xa5\x68\xf7\x86\xcb\xb4\xed\x9a\x4e\xd6\xe7\x12\x4b\xc2\x8b\x26\xb7\xfa\x59\x74\x4e\x27\xdd\x85\x29\x76\x1d\xa4\xd8\x69\x88\xe2\x47\x0d\x50\xc4\xb4\x88\xd6\x54\xa4\x6e\x1f\xc7\x29\x0d\x06\x18\xbd\xcd\x68\x9c\x4e\xf6\x73\xd6\x1d\xdf\x88\xa3\x6e\x0e\x35\x47\x6d\x2f\xce\x98\x8e\xb2\x6b\x11\xdd\x76\xa8\xd7\x9c\x41\x26\x21\xb2\x76\xb2\x9b\xd3\x91\x9d\xdd\xe8\x97\x97\xef\x6f\xca\x70\x7c\x8c\x59\x29\x0d\x97\xdf\x39\x4b\x9a\xd1\x49\x6f\x21\xd3\x85\xea\x3e\xa6\xd1\xed\x1d\x95\x31\x5a\xb6\xa8\x66\x63\x96\x30\xbd\x40\xe5\x5c\x02\xc6\xfa\x73\x61\x83\xe2\x6c\xfd\x47\xe1\xbb\xb8\x16\x2d\xc6\x0b\x1b\x16\x5a\xc8\x5c\xf4\xcc\x84\x32\xa3\x8f\x17\xad\x7a\x6d\xd4\x4c\x94\x15\x26\xbd\xaa\x65\x3a\x28\x5f\x7e\xec\xad\xf2\x55\x69\x43\xbb\xab\x1e\xd6\x36\x76\x6f\x8f\x59\x9d\x63\x71\xb2\xe8\xb2\x16\x58\x5d\x47\xf3\xed\x2f\xab\xcb\x24\x5c\x6b\x91\x75\xe4\x25\xb1\x93\x6d\xf0\x91\x8c\x61\x22\x0c\x11\xde\xe8\xf4\x88\x73\x70\xa5\x39\x4f\x46\x17\x85\x55\x4b\xd4\x1c\x1b\x36\x6a\xd1\xd7\xe3\x4c\xd8\x1c\x38\x28\x75\x8c\xee\x90\x3c\xb3\x5a\xab\x6f\xa8\xdb\x37\x5f\x07\x29\xae\xae\x5f\x66\x02\xb8\x76\xbe\xf8\x23\xe8\xc8\x5a\x6e\x2b\x84\x1c\x3b\x85\xb9\xe5\x2f\xbb\x51\x22\x49\xd5\xcc\xb6\xba\x85\x7b\xa6\x5d\xbb\xe6\x91\x2d\x0f\x5c\xed\xb8\x3b\x95\x34\x02\x92\x81\x64\xc2\x30\xa3\x9c\xeb\x58\xdc\x71\x32\x86\x29\xe3\xca\x83\x02\x2b\x6e\x3a\x98\xa1\x3f\x86\xa9\xa2\x64\xda\x90\x5c\xd5\x0a\x82\xb8\x54\x9d\x48\x94\x47\xd3\xad\x79\xd9\x93\x84\x1c\x0b\xe1\x64\x1b\xc7\x14\x10\xae\xf6\xd2\x79\x6c\xc9\x87\x39\xc7\x37\xc7\x90\xd0\x85\x8d\xc8\xc4\x36\xd8\xec\xdf\x20\xd5\x51\x07\x1e\x27\xdb\x0d\xca\x5f\xdb\xb8\x0e\x2c\x75\x4a\xa3\x59\x3b\x17\x6e\x70\x51\x6d\x39\x82\x8b\xaa\xcd\x24\xc1\x45\x15\x5c\x54\x8f\x8c\xe0\xa2\x0a\x2e\xaa\xa5\xb1\xb7\x5a\x52\x70\x51\x35\x1e\xc1\x45\xf5\xf0\x08\x2e\xaa\x2d\x46\x70\x51\x6d\x39\x82\x8b\x2a\xb8\xa8\x82\x8b\x2a\xb8\xa8\x3e\x23\xbb\x9d\x1f\xc1\x45\xb5\x32\x49\x70\x51\x05\x17\xd5\xd6\x63\x6f\x95\xaf\xe0\xa2\xb2\x23\xb8\xa8\xea\xe3\xf3\x62\x75\xde\xc1\x33\x32\xaa\x5e\xfb\x1e\xc3\xa8\x30\x3a\x1a\xfb\x22\xd3\x9e\xda\xd8\xff\x3f\x8d\xed\x7f\x4f\x1c\x25\x1d\xd8\xfb\x83\xad\xff\xc5\xd9\xfa\xbb\xb1\x93\x75\x60\x23\x6b\x4d\x93\x9d\x0b\xfc\x66\x26\x41\xcd\x44\xd2\x18\xd1\x6b\x48\xfe\x8e\x71\x96\xe6\xa9\xc1\x39\x65\xf0\x99\xcd\x0b\x5f\xbb\x2a\x1b\x2f\xa3\x0b\xde\x9a\xeb\xcc\x8d\x2c\x06\xac\xbc\x49\x59\x62\xb6\x11\x13\x25\x67\x74\x6e\x70\x5d\xe5\x51\x04\x80\x7d\xbd\xaa\xaa\xc4\x1f\x87\xc5\x9b\x8a\x3e\x0e\xaf\xdb\xd1\x9b\x76\xdc\xd2\xd6\xc6\xc4\x59\xfe\xf8\x87\x46\x73\x4c\x65\xd6\x0d\x5d\xfe\xf6\x6a\x74\x5a\xa1\xcb\x94\x7b\xb2\xcc\xf8\x5c\x24\x73\xdb\xd8\x16\x6f\x32\x52\xd1\x70\xa5\x25\x66\xa1\x44\x38\xf9\x5b\xd9\x0e\xcc\xe6\x39\xf3\x54\x91\xd2\x3e\xb2\x81\x14\x8d\xbb\xc3\x96\xa3\x03\x82\xdf\x5e\x57\x68\xa5\x27\x74\xc1\x6f\xda\x8a\xc2\x75\x39\xc6\x08\xbc\x75\x73\xcf\x14\xf1\xc2\x96\x73\xdf\x5a\xe0\x6d\x4d\x29\xdb\x0b\xa1\xed\x8f\x16\xc1\x7a\x2b\xf8\xe1\x9d\x01\xf8\xc0\xb5\x10\xf7\xec\xbc\xaa\x6d\xf8\x16\x47\x5a\x90\x2c\xa1\x65\x93\x22\xdc\x81\xef\x90\x07\x9d\xce\x20\xba\xbd\x72\x2e\xcf\x43\x05\x50\xc4\xab\x4c\x99\x9e\xe5\xe3\x61\x24\xd2\x63\x43\x12\xec\xff\x8d\x13\x31\x3e\x4e\xa9\xd2\x20\x8f\x63\x11\x39\x16\x37\x88\xcc\x2c\x8c\x4f\x87\x69\x7c\x84\xed\x6d\x2f\xea\x4d\x11\x2b\xa5\x10\xcc\xfb\x9d\x32\x48\xc6\x60\xa8\xab\x40\x85\xbf\x52\x4f\xcd\x2c\x6f\xe7\xc6\xb5\xd5\xd1\x9a\x25\xb5\x74\x37\x7f\x7a\x57\x73\xa0\x5c\xa4\x03\xcb\xc6\x73\x73\x29\x77\x16\x5a\xd1\x81\x2b\x79\x8f\xdc\xc8\x7b\x23\x1a\xef\x8b\xeb\x78\x0f\x4b\x1f\x77\xe0\xe9\xec\xc2\x55\xdc\x9d\x9b\xf8\x23\x54\x08\xfe\x38\xee\xe1\x0e\x6d\x68\x1d\xb9\x85\x3f\x85\x4b\xb8\x93\xaf\x6e\xeb\x0a\xfe\x74\x6e\xe0\x6e\x3e\xb7\x4b\x45\xe0\xb9\xba\x7e\x3b\xb0\x85\x77\x69\x07\xef\xcc\x06\xfe\xd1\x5c\xbd\xed\xdd\xbc\x7b\xe0\xe2\x6d\x0d\x64\xc6\x99\x66\x34\x39\x83\x84\x2e\xae\x21\x12\x3c\x6e\xcc\x61\x96\x4a\x46\x16\xe7\x47\xd9\x69\x9d\x9d\xaa\x9e\xd1\x30\xa3\xae\x32\xb6\xd1\xa8\x6c\x06\x87\xf7\x4f\x38\x81\x02\x5d\x0b\x76\x95\x4d\x8a\xce\xdd\x09\x79\x9b\x08\x1a\xab\xe3\x4c\xd8\xff\x2b\xf3\x15\x2a\x89\x0a\xf6\x5d\xed\x32\x15\x9e\xda\x20\x66\xd3\x3b\xba\xdc\xc4\xef\xc4\x1d\x11\x13\x0d\x9c\x1c\x32\xee\xf7\xf1\xa8\xa2\x06\x96\xd6\xc9\x02\xad\xcd\xd5\xd7\xaf\xfc\xcd\x2f\xcf\xec\x88\x06\x56\xa5\x3e\xbe\x15\xd8\xbd\xe8\x71\x33\xb0\xbb\x71\x92\x27\x75\x53\xb0\x35\x0f\xd7\xe9\xcd\xeb\xb2\xb6\xef\x6b\x9c\xb7\x38\x6d\x94\xc7\xc4\xa5\x7c\xbd\xbc\x4d\x6b\x1d\xc0\x52\x17\xfd\x8a\x80\x95\xc7\xac\xc6\x37\xa7\x23\x6b\x34\x0e\xe6\x92\x7d\x31\x97\x3c\x51\x10\xc8\x1e\x0a\xba\xcf\x34\xf0\x23\x08\xba\x3b\x8c\x4a\x12\xe8\xb7\x92\x46\x30\xea\x5c\x46\xf0\xc7\x89\xc4\xb9\xa4\x8e\x00\x16\x22\x9f\x3f\x3c\x1c\x20\xb6\xa7\xa9\x48\x9c\xc5\x94\xd4\x49\x9e\x24\x0b\x92\x67\x82\xd7\xd3\x8c\xad\xaf\x7d\x39\x6b\x15\x4d\xf2\x6b\xde\x52\x0a\x96\x99\x14\x8e\x67\xca\x9c\x73\x43\x83\xcb\x06\x5d\x28\x48\x62\x55\x63\x5a\xcb\x8d\x55\x6c\x6a\x96\x6f\xf8\x1f\xa6\xcd\x96\x91\x7e\xb5\x09\xcd\xd3\x13\x21\x23\x36\x4e\x16\x64\x46\x93\xa2\x1b\x0b\x25\xb7\x2c\x49\xdc\x34\x43\x72\x0d\xda\xba\x14\x2c\xef\x4c\x04\x9f\xe2\xe2\x28\xf7\x5d\x00\x21\x32\xcf\x46\x09\x50\x9e\x67\xf6\x7d\x86\x13\x2f\x44\x2e\xfd\xfb\x86\x85\x63\xa2\xec\xba\xcf\x92\x7e\xa5\xd7\xd8\x83\x1b\x5b\xf4\xa7\xc9\x95\x11\x00\xde\xfb\x2a\xce\xfd\xea\x9c\x62\x0e\x52\xb2\xd8\xd9\xf9\xed\x6f\x99\x14\x73\x16\x5b\xef\x86\x07\x1b\x76\x35\xb6\xdd\x64\x8a\xf3\xcc\x05\x1f\x70\x98\x52\x14\x54\xdc\x29\xb2\x7b\x66\xe7\xb1\x11\x04\x3c\xc6\xfe\x32\x46\xc2\x17\x59\x2d\x6f\x7d\xce\x6c\x67\xdc\x0a\xe4\xc8\x21\x17\x44\x60\xe0\x67\xce\x99\xb6\xdd\xd6\x67\xb9\x26\xb1\xb8\xe3\x47\x3b\x79\x5d\xd1\xd1\x7a\xb3\x16\x40\x75\xf7\xeb\x3a\x39\xc7\x7e\xef\xc3\xe0\x65\xca\x99\x3e\x27\x24\xe7\x0a\x5a\xb2\xf7\xce\x84\xa3\x3f\xff\xa9\x19\x8d\x60\x29\x88\x5c\x7f\x12\xed\xef\x6e\xc6\xa2\x59\x55\x98\x65\x29\x28\x22\xf2\x25\xb5\xf8\xb5\x7b\x6c\xfd\x0e\x05\x15\x70\xdd\x68\x6a\xd8\x5d\x63\xfd\x72\x0d\x4b\x57\xe3\xf7\x2a\x0d\x99\x31\x34\xfb\xec\xf2\xfa\xd7\xb7\x27\xff\x7d\xfe\xd6\x9d\x4f\x5e\x65\xfa\x39\x67\xff\xca\x81\xd0\x54\x18\x59\x38\xa9\x86\x01\xf6\x51\xa3\xaf\xfc\x80\x27\xb9\xdb\x80\xc1\x86\x0c\x19\xbb\xc7\xb7\x0f\x8b\xc4\x1e\xf4\x1f\x3f\x2a\xf2\xa9\xbb\x6a\x95\xc1\x2d\x46\x6e\xac\x74\xd5\xa2\x84\x83\x36\x27\xcf\x4a\x94\xb6\xcb\x1a\xe3\xd3\xa4\x2a\x4c\x36\x23\x57\x6d\x75\xa2\xb6\x1a\xd1\xa0\xfc\x82\x51\x53\xc5\xa8\x93\xee\x5e\xe5\x1a\x3a\xea\x89\x53\x52\x6d\xaf\x06\xd8\xa6\xc5\x5e\x0d\xb0\xa2\xc7\xc5\x88\xd0\x38\x96\x28\xa6\xe0\xa9\x4f\x97\x7a\x63\x66\x65\x2c\x4d\x9f\xbc\x22\x7f\x23\xf7\xe4\x6f\xa8\x16\xfc\xb9\x6d\x07\xa1\xb6\x02\x7b\x17\xa1\x31\x46\x1b\xbd\x18\x75\x04\xf1\x1f\x67\x54\xe3\x8c\x06\xaa\x5a\x90\x31\x73\x62\x28\xdc\x6b\x90\x46\x2c\x72\x3b\xf1\xa4\xbd\x97\xcc\x02\x3f\x21\x9a\x59\x33\xf9\xc5\xa4\x1e\x8e\xb3\x1b\xa2\x99\xc7\x8d\x7e\x7f\xe9\xa8\x50\xbd\xcf\x49\x39\x5b\x4a\x75\x34\xab\x93\x31\x23\x60\xa8\x1a\x73\x8a\x05\x92\x71\x1b\x76\x3b\x63\x2d\x9c\xfe\xfb\x83\xc6\xed\xfc\xc0\xb5\xfd\x7c\x68\xa7\x96\x14\x7f\xe4\xf3\x4e\x30\xa8\x94\x4e\xca\x44\x3c\x24\xe7\x34\x9a\xe1\xb2\xe2\x0a\xcf\x30\x1a\x08\x4e\x36\xa3\x73\xb3\xf1\xee\x59\xdb\x17\x08\xa5\x95\xc2\x3a\x8a\xb8\x64\xce\x53\x44\xb9\x6d\xce\x39\x01\x29\x6d\xa4\xf4\x78\xe1\x83\xcc\x5a\x6f\x5e\xab\x93\x94\x49\xa1\x45\x24\x5a\xb4\x87\x5a\xce\xbe\xc0\xe9\x10\x08\x36\x3a\xd5\x9b\x77\x7f\x38\x1b\xf5\xc9\xcd\xe9\x08\x9b\xfa\x5c\x9f\xde\x8c\xea\x12\xf6\xc1\xcd\xe9\xe8\xe0\x49\x41\x41\xbc\x99\x0d\x0d\xaa\x0d\x26\xa9\x19\x4c\x12\xa6\xf4\x20\xa5\xd9\xe0\x16\x16\x0d\x79\x6a\x17\x7c\x7d\x50\xec\x70\x27\x1f\x64\xc1\x9c\xd2\x6c\xe7\xd9\x24\xd0\x98\x85\x34\x9f\xed\x47\x48\xf3\xd9\x72\x84\x34\x9f\x90\xe6\xb3\x3a\xf6\x26\x96\x31\xa4\xf9\xbc\x2c\xd7\x6d\x48\xf3\xf9\xcc\xbd\xbf\x21\xcd\x67\xfd\x08\x69\x3e\x21\xcd\x67\xbb\x11\xd2\x7c\x76\x1f\x7b\x17\xb7\x12\xd2\x7c\x76\x1a\x21\xcd\x67\x75\x84\x34\x9f\x0d\x23\xa4\xf9\x6c\x18\x21\xcd\x27\xa4\xf9\x84\x34\x9f\x10\xfd\xf8\xe8\x5c\xfb\x19\xfd\x48\x42\x9a\x8f\x1b\x21\xcd\xe7\x45\xc4\x78\x91\x90\xe6\xb3\xd5\x08\x69\x3e\x21\xcd\xa7\xc9\x08\x69\x3e\x2f\xc5\x5c\x12\xd2\x7c\x42\x9a\xcf\xe7\x23\xe8\x86\x34\x9f\x90\xe6\x13\xd2\x7c\x42\x9a\xcf\x83\xab\x08\x69\x3e\x2f\x41\x05\xf4\x3d\x57\xdb\xe7\xa8\x5c\xf9\x99\xb6\x0f\xeb\x23\xe7\x6b\x7e\x45\x4b\x88\xca\xcc\x24\xb2\x9c\x32\x91\x40\xe3\x05\x4e\x89\x7d\x1e\x2a\x42\xd6\x33\x8c\x0e\x4c\x58\xca\x9a\xa5\x05\x91\x95\x43\xf3\x16\xe7\xaa\x78\x5d\x0c\x58\x52\x7a\x8f\x07\x80\xa6\x22\xb7\xad\x5f\x23\x91\x66\xb9\xae\xc3\x14\xb7\xa7\x49\xd7\xd6\x09\x9b\x3a\x8e\x7a\x6c\x1b\xcc\x0e\x8a\x69\x07\x95\xa6\xae\x4f\xd8\xaa\x95\xc6\x3e\x6a\x6e\xd4\x45\xd0\x08\xd5\x1a\x24\x7f\x43\xfe\xe7\xf0\xe7\xaf\x7e\x1b\x1c\x7d\x7d\x78\xf8\xd3\xab\xc1\x5f\x7f\xf9\xea\xf0\xe7\x21\xfe\xe3\xf7\x47\x5f\x1f\xfd\xe6\xff\xf8\xea\xe8\xe8\xf0\xf0\xa7\xef\xdf\x7d\x7b\x33\x3a\xff\x85\x1d\xfd\xf6\x13\xcf\xd3\x5b\xfb\xd7\x6f\x87\x3f\xc1\xf9\x2f\x5b\x4e\x72\x74\xf4\xf5\x97\x8d\x97\xdc\x5a\xe0\xed\x4e\xdc\xed\x48\xd8\xfd\x28\xa2\xae\x73\xd7\x76\x74\x16\x5d\xa8\xc9\xca\x69\x74\xec\xe8\xa1\xd3\xe8\x35\x6e\x14\xe2\x8a\x79\x98\x22\x22\x65\x5a\x3b\x2a\x4a\xab\xc1\xaa\x4c\xd7\x54\x4e\x47\x07\xb0\x21\x36\xd5\xb6\x51\x75\x11\xe8\x59\x09\x51\x11\x5e\xae\x73\x9d\xbc\x59\x9a\x25\xd8\x20\x1a\xcf\xf3\xc0\x47\xaa\x20\xeb\x0c\xb4\xe1\xf1\x11\x68\xc3\x4b\xa4\x0d\x0a\xa2\x5c\x32\xbd\x38\x15\x5c\xc3\x7d\x23\xfb\xc9\x26\x03\xd2\x75\x7d\x6a\x17\x1b\xa6\x5c\x4c\x9b\xbd\x46\x44\x66\xe3\xbb\x37\x66\x4e\xcf\x44\x9e\xc4\x98\x97\x94\x73\x54\x29\x6d\x8a\x1b\x68\xab\xef\xa1\xa6\x83\xc1\xdb\xcb\xaf\xf3\x1a\x9c\x9d\xfa\x5f\x39\x9b\xd3\xc4\xe8\xb7\xe5\x13\x23\xd4\x59\xaa\x0f\x35\x32\x62\x3d\xb1\x8c\x85\xe2\xcd\x48\xb2\x39\x4b\x60\x0a\xe7\x2a\xa2\x09\x52\xa5\x6e\x28\xfd\xc9\x86\xd9\x71\x8b\xa4\x48\x14\xb9\x9b\x01\x76\xe0\xa7\x5e\x3d\xc7\x44\xb2\x29\x65\x9c\xa4\x86\xa8\x66\xfe\x61\x65\xf5\x7c\x43\xbc\x8d\xd4\xcb\x75\xa9\xcf\xa3\xfa\x3a\x16\x22\x71\xd9\x08\xc9\xa2\x9c\x9f\x59\xd3\x1b\x17\xbf\x72\xb8\xfb\xd5\xcc\xa6\xc8\x24\xa1\xd3\x42\x8d\x57\xa0\x57\x2c\x71\xe5\xd4\x1b\x3f\x00\x43\xfd\x73\x20\x34\xb9\xa3\x0b\x55\x1a\x35\xca\x39\x98\x7a\x43\x5e\x1f\x21\xe2\x51\x45\x8a\x39\x62\xf2\x87\x23\x74\xcd\x9d\x9e\x8c\x7e\xbd\xfe\xfb\xf5\xaf\x27\x67\xef\x2e\x2e\xc9\xa5\xd0\x60\x59\x52\xa5\x49\x5a\x44\xb9\xd1\x10\xdc\x2a\xf1\x1d\xa8\x41\x0b\x35\x44\xbb\x22\x53\xe4\x8e\xf1\x58\xdc\xa9\xc6\xf6\x53\x8b\x7e\x06\x78\x40\x79\xa3\x39\x22\x9a\x51\xec\xfd\xd6\x82\x3f\xac\x44\x7f\x54\x27\x45\x0e\x1c\xc7\xc7\xb1\x14\x99\x05\x82\x37\x40\x55\x95\xa4\xb3\x25\xbb\xb2\x8f\x2f\xc5\xfd\x9d\xd4\x27\x9c\x4a\xca\x75\x69\x89\x29\xf7\xcc\x35\x9d\x1b\xb6\xde\x8e\xe7\x9d\x6d\x44\xe3\xee\x32\x8d\x4e\xe2\x18\xe2\x1a\xf8\x5f\x5c\x54\xdf\xa9\xff\xb8\x45\x59\x8c\x81\x8c\xde\x5f\x5f\xfc\xef\x25\x3c\x5e\x64\xed\x82\x98\xba\x49\x00\x95\x22\xeb\x6c\x77\xaf\x20\x15\xf3\xb0\xbf\xfb\xb2\xbf\x05\xb7\xec\xc6\x75\x7e\x95\xf3\x2a\x43\xe3\x95\xf9\x49\x2a\x62\x18\x92\x51\x61\xc3\xaf\x5f\xad\x16\x99\x91\x40\xcc\x2d\x5c\x33\x9a\x24\x8b\xaa\x30\xa5\x85\xcd\x10\xac\x95\x20\xa8\x12\xf2\x09\x4d\xd4\x53\x53\xe3\x36\xbc\xd1\xc8\x11\xef\x8c\x36\xdb\xc9\x76\x14\xb3\x91\x18\xb8\xd0\x4e\x18\x36\xab\xc4\xb2\x0e\x52\x44\xc4\xaa\xce\x95\x40\xa9\x1a\x7f\x53\xd6\x8f\xe0\x59\x23\x53\x1e\xd8\xa3\x62\x66\x6b\x44\xce\x15\xa8\xf5\xac\xb1\x54\xa6\xcd\xec\x12\x68\x2c\x78\xb2\xc0\xa8\x48\x1b\xe7\x90\x52\x75\x0b\xb1\xfd\xc1\x89\x66\x85\x17\xc1\xcc\x58\xbc\xea\xc6\xac\xdb\xbb\x0c\x50\x24\xb3\xd1\x17\xe8\x6a\x30\x1a\xfe\x93\xee\x7a\x8b\x43\x68\x80\xf2\x9e\x27\x8b\x2b\x21\xf4\x37\x45\x8a\x6b\x27\x18\xf0\xa3\x93\x96\x11\x20\xf5\x48\x2f\x8a\xef\x1d\xe0\x6e\xe0\xa1\xaa\x66\xd7\x9e\x95\x3b\xfe\xdc\x8f\x94\xcc\xf9\x89\xfa\x56\x8a\xbc\x31\x13\x5b\x11\x36\xbf\xbd\x38\x43\x52\x94\x3b\x37\x22\xd7\x72\x91\x09\x66\x6d\x50\x1b\x14\x83\x1f\x9c\x23\xb4\x7a\x26\x4a\x9f\x15\x79\x47\x17\x84\x26\x4a\x78\x58\x32\xbe\x4e\x5f\x24\x4e\x19\x35\x97\xc7\x42\xcf\x56\xb4\x50\x73\xa0\x56\x9f\xeb\x57\xbc\x8a\x65\x6d\x30\xc6\x57\x1e\xd7\xf4\x16\x14\xc9\x24\x44\x10\x03\x8f\x9e\x7a\xdb\x9f\xda\x19\x87\xa8\x73\x29\xb8\x39\x98\x9d\x20\xcf\x45\xe1\x85\x75\x20\xad\xa2\x0a\xfa\x73\x9d\xf6\x47\xd1\xab\x8b\xc7\x32\x57\x20\xad\x0b\x5a\xe6\x60\x77\xf2\xfb\x7c\x0c\x89\x81\xbc\x51\x49\x5d\xc7\x6c\x6b\x78\x60\x29\x9d\x02\xa1\xba\xc0\x34\x2d\x08\x70\x65\x28\xa6\x35\x5f\x6a\x12\x0b\x28\x33\xe3\xa9\x22\x3f\x5c\x9c\x91\x57\xe4\xd0\xbc\xeb\x08\xf1\x07\x1b\x6a\x6b\x61\x03\xd0\x96\x75\xd4\x89\x9f\x02\x97\x84\xc8\x4b\x84\xb4\x44\xa2\x4f\xb8\x20\x2a\x8f\x66\xd5\x2e\xde\x5e\x6d\x76\x41\x8a\xe8\x18\xd9\x4f\x5c\x7f\x5a\x0a\xf5\x83\x02\xd9\x19\x81\xfa\xa1\x01\x81\xaa\x8a\x51\x06\xe7\xea\xd0\xb3\x88\x95\x82\xa6\x31\xd5\xd4\x11\xae\xa2\xab\xfa\xbe\x6e\xe9\xe7\x4d\xbe\x14\xbc\x65\x3c\xbf\xb7\x26\xd2\xee\x4c\x2d\xd7\xe7\x38\x2d\xe2\x10\x42\x1d\x77\x9d\x66\x59\xc2\x4a\x07\x72\x25\x48\xed\xa2\x86\x2b\xfd\x0d\x62\x22\xd2\x09\xef\x87\x36\xc2\x09\xe5\xb1\x48\x57\x5e\x86\x4e\x6f\x1a\xcd\xaa\x2f\x08\xd8\x57\x1f\x7b\x62\x14\x4a\x60\x0e\x2d\x4a\x68\x2d\x61\xde\x5b\x33\x9b\x01\x8e\xc7\x08\x9c\x9e\x24\x74\x0c\x89\x85\xb1\xc5\x40\xb5\x8a\x81\x4f\x1d\x29\x2a\x45\xd2\x5d\x6a\xcb\x95\x48\xc0\x86\x5e\x79\x40\x98\xe9\x9f\x05\x1c\x70\x92\xae\xe0\x80\xda\x60\x0d\x0e\xa8\xd7\x3e\x07\x38\xe4\x2d\x58\x3d\x59\x86\x83\x91\x1b\xea\x70\x40\xe6\xbd\xef\x70\x50\x10\x45\x22\xcd\x46\x52\x18\xb5\xb3\x33\xde\xe4\xa6\x2d\xfd\x7c\xd6\xb0\x81\x76\xfb\xaa\x06\xec\xbc\x7a\xf5\x9b\xa9\xac\x04\x5d\x52\x6d\x99\x84\x8f\xbc\xfc\x5f\x15\x9e\x85\xa4\x67\x99\x91\xf9\x59\x6a\x8e\x40\xf3\xa4\xbb\xf0\x9c\xd9\x41\x17\x79\x0b\x2d\x8c\x9d\x9d\x70\x23\x11\xd1\x04\x4b\xa4\xb6\x43\x39\xb2\x8c\x76\xcb\x13\x57\x42\x6d\xd1\x47\x89\xbf\xf9\xf0\x0f\xac\x96\x89\xbf\x38\x13\x26\x17\x31\x54\xbc\xce\x36\x46\xf8\xc6\x86\x64\xe2\x7d\x3e\xca\xd7\xc8\x15\x2e\x0a\x04\xe2\xda\xd3\x5a\xb8\xea\x64\xef\x8a\xc2\xab\x66\x81\xc0\x63\xc6\xa7\x68\x57\xeb\x13\x09\x89\x8d\x0f\x76\x44\xe0\xd6\x6a\x90\x3d\x3c\x12\x7e\x52\x7f\x1e\xfc\xab\x51\x16\x63\x82\xbb\x99\xd1\x52\xe4\x25\xac\x89\x25\xb7\x4c\x91\x83\xb7\x1e\x00\x2d\x2a\x55\xee\x23\x87\x39\xb0\x5f\x58\xec\xa6\xb5\x74\xde\x32\x1e\xbb\x50\xda\x1a\xb0\xbc\x9e\xeb\xe4\x60\x0c\xd2\x66\x71\x95\xb6\xbc\x21\x3f\x73\x52\x00\x8b\x0c\x1a\xa3\xc7\x95\x15\x99\xbd\x8d\x6e\xf0\xb0\xe1\xb5\x78\xc9\xf2\x34\x3f\x70\xdc\x7b\xf3\xde\x81\xd1\xdc\x57\xef\xf3\xdf\xf2\xa4\x65\x75\x1c\xf5\xeb\x5a\x8b\xf9\xd1\x4e\xeb\x45\xfa\xc8\xa0\xb5\x66\x7c\xaa\xaa\x9a\x4c\xbd\x1e\xfe\x7a\x55\xc6\xef\xf0\x44\x0a\x9b\x82\xb9\xaa\x42\x2c\xa5\x00\x3c\x17\x35\x24\x31\xe2\xc4\x33\x57\x42\xa6\xa9\xa2\xa7\xd2\x40\x42\x33\x9a\x5c\x67\xcd\xcb\x87\x92\x95\x52\x75\xef\xae\x4f\xea\x53\x23\xb3\x9e\x81\xb4\xbc\xdf\x5c\x27\x34\x4e\x99\x52\x68\x08\x83\xf1\x4c\x88\x5b\x72\xb8\xa6\x56\x56\x25\xca\x4a\xb1\xa9\x3a\x76\x38\x3f\x30\xab\x3f\x22\x8c\x27\x45\x24\x13\xea\xc1\x5c\x2b\x6f\xc8\xc1\x97\x44\xc5\x2a\x70\x0f\x5d\x79\x66\x17\xac\xb0\xba\x4c\x5b\x90\xd9\x60\xc1\x93\x13\xec\xd5\xed\xb9\x6c\x59\x12\xe5\x91\x2d\xba\x74\xb8\xbd\x5c\xf5\x6c\x2d\x1c\xad\xf4\xf8\xe4\x40\x72\xc2\x45\x04\xaa\xbb\x62\x4b\xdf\x95\x73\x92\x18\x6c\x86\x0d\x60\xf4\x13\xdd\x18\x0e\x87\x76\xe9\x1e\x26\x6a\xba\x47\x7b\x55\x89\xfa\xa6\x24\x2e\x46\x1f\x49\xb2\x19\x1d\x58\x25\xdd\x50\x34\x24\x81\x5e\x84\x98\x09\x2e\xa4\x45\x51\xc3\x44\x05\x47\x94\x46\x12\x65\xbd\x79\xb8\x27\x8e\x44\x57\x96\x7a\x5a\x7a\x89\xab\x8e\x40\x4c\xf4\xb2\xb5\x1d\xca\x35\xdc\x31\x3d\xc3\x1a\xac\xb3\x25\xaf\x21\xae\x44\x82\x42\x07\x0c\x27\x20\xa5\x90\x2e\x20\xcb\xdb\xad\x71\x26\xa4\xe4\x18\xd1\x65\x90\x84\x9a\xbf\x7a\xaa\xea\xa8\x2e\x2b\x9e\x63\x8c\xa1\xc1\x26\x98\x4c\x20\x42\x41\xab\x0a\x60\x4b\xb5\x0f\xcb\xa2\xb4\x3e\x85\x43\x0b\x5f\x31\x3d\x65\xf7\xe6\x2d\xd5\xa7\x96\xfa\xae\x70\xc1\x07\xeb\x2f\x1f\x0d\x09\xb9\xe0\x45\xfc\x6d\xdf\xec\x62\xf5\x4e\x1f\x7a\xa6\xcd\x27\x56\xcb\xed\xe3\x07\x54\x0d\x67\x46\x3a\x94\x79\x07\x18\xdf\xc6\x1c\x4e\xaa\x26\xf1\x4e\xc9\x01\x9a\xc6\xdd\xa4\x66\xeb\xbd\x0c\xd0\xc6\x54\x6e\x6e\xf9\x58\xe6\xf2\xe7\xe1\x00\x21\x6d\xe9\x9c\xab\x74\x10\x6a\xa0\x6f\x37\x42\x0d\xf4\x2d\x47\xa8\x81\x1e\x6a\xa0\xaf\x8e\xbd\x09\x19\x0c\x35\xd0\x5f\x56\x5d\x9b\x50\x03\xfd\xa9\x4d\xcc\xa1\x06\x7a\xa8\x81\xfe\xd0\x08\x35\xd0\x1f\x19\xa1\x06\x7a\x83\xf1\x02\x28\x57\xa8\x81\xde\x60\x84\x1a\xe8\xeb\x47\xa8\x81\xbe\x3a\x42\x0d\xf4\x8d\x23\xd4\x40\x6f\x3c\x42\x0d\xf4\x50\x03\x3d\x94\x86\xdc\x6d\xae\xfd\x2c\x0d\x49\x42\x0d\x74\x37\x42\x0d\xf4\x17\x51\x00\x8f\x84\x1a\xe8\x5b\x8d\x50\x03\x3d\xd4\x40\x6f\x32\x42\x0d\xf4\x97\x62\x2e\x09\x35\xd0\x43\x0d\xf4\xcf\x47\xd0\x0d\x35\xd0\x43\x0d\xf4\x50\x03\x3d\xd4\x40\x7f\x70\x15\xa1\x06\xfa\x4b\x50\x01\x95\x8e\x59\xa3\xb2\x90\xdb\x54\xb0\x71\x91\xc9\x95\x84\xf1\x71\x3e\x99\x80\x44\xca\x85\x6f\x5e\x09\x9e\x2a\x8b\xf5\x2d\x3b\x59\x41\xf7\xb1\x18\x8e\x4b\xe2\xd8\xf0\xb8\xcb\x50\xc7\xf2\x8d\x65\xf8\xf0\xf9\xfb\x6f\xd6\x94\xcb\x69\x1c\x55\xd8\x34\x70\x16\xd7\xfc\x9e\x37\xf3\x8f\x6f\x00\xf8\xba\xa4\x22\x07\xf7\x28\x11\xca\x85\x3d\x23\xb0\xa2\x19\xe5\x1c\xbc\xbe\xc7\x34\xda\x51\xc6\x00\x9c\x88\x0c\x9c\x77\x9a\x12\xc5\xf8\x34\x01\x42\xb5\xa6\xd1\x6c\x68\xde\xc4\x3d\xb0\xcb\x10\x65\xf7\x8b\xd2\x12\x68\xea\x83\xb5\x53\xca\xec\x54\x84\x46\x52\x28\x45\xd2\x3c\xd1\x2c\x2b\x26\x23\x0a\x30\xcb\xc2\x32\xaa\x02\x18\x18\x15\x57\xc6\x35\xf7\xcb\xb7\xb9\x65\x89\x6a\xbd\x32\xd4\x36\xfb\x58\xe2\x39\xcd\xf4\x82\x98\x4f\x4e\x5c\xd9\x57\xa9\x34\x89\x12\x86\xdc\x1a\xdf\x68\x13\x6a\x71\xbe\xbe\xe7\xd5\xdc\xad\x54\xb9\xa5\xf2\x18\xc5\xd6\x4c\x2b\x82\x61\xc0\xe5\x84\x6e\xaa\x98\x29\x27\xe6\xab\x3e\xa1\xbe\x98\x96\x05\xb4\x5f\x29\x82\xda\x73\x16\x3b\xbb\xfb\xa9\x32\x5d\xa5\x88\xa8\xc1\x4d\x6b\xc0\x2a\x11\x1d\xe3\xde\x3d\x72\xf6\x6b\x21\xfe\xa5\x40\x81\x51\x7a\x2b\xc7\x00\x37\x80\xc3\xdc\xe0\x00\x44\x60\xf8\x2b\xdd\x80\xf5\x9f\x1c\xe9\x35\x95\x53\xd0\x45\x3c\x53\xd3\x58\xf1\x7a\x58\x48\xb5\xdc\x6f\x55\x11\x29\x41\x86\xd0\x19\x89\x18\x53\x7e\xca\xbc\xaa\x75\xf5\x84\xed\x0a\x5d\x19\xb5\x75\x37\x78\xc1\xc8\x86\x68\x16\x2f\x55\x19\x8d\x40\x91\xc3\x8b\xd1\x69\x9f\x8c\x2e\xce\x5c\x1c\xa6\x98\xac\xcb\x63\x76\x34\xcc\x62\xe0\xa6\xca\xc6\x45\x85\xb6\xca\xf4\x95\xdc\x4f\xf7\xee\x51\x21\x5f\xfd\xcc\x5d\x78\xe9\x32\x05\x40\x91\xab\xa8\x6e\x4e\x54\x8e\x22\x92\xb3\x09\xb1\x22\x31\xc3\x21\x1f\x94\xe9\x88\xbe\xee\x90\x7f\xa2\x58\x88\x83\x92\xcb\xba\xf0\xbe\x6e\x24\xb0\xc8\xaf\x57\x52\x3b\x30\x14\xd4\xc5\xbd\x34\x8a\x77\x69\xa5\x21\x55\x44\xb1\x77\xa0\x14\x9d\xc2\xa8\xa1\x7b\x6b\x93\x1d\x00\x3d\x5c\x25\x39\x40\x02\x94\xd8\x44\xdf\xe2\x97\x32\x26\xb8\x2e\x7c\x93\xd4\xae\xa9\xc0\xac\x3b\xc9\xb4\x06\x24\x25\x58\xec\x0f\x37\x7b\xb9\x16\x40\x6f\x29\xb2\xf8\x9d\x9f\xa4\x7c\xd8\x88\x12\x3c\xb6\x71\xbe\x63\x20\x63\xc9\x60\x42\x26\x0c\x83\x87\x31\x9c\xb7\x6f\x6b\x3f\x51\x6b\x7b\x52\x0a\x24\xae\xc7\x69\x50\x7e\x5d\x43\xf2\xa3\x5b\x98\x96\x39\xb7\x4d\x47\x9c\x70\x8f\xc9\xae\x6c\x42\xa6\x18\x0e\xec\x74\x94\x3f\xbd\xfa\xeb\x9f\xc9\x78\x61\x04\x29\x44\x48\x2d\x34\x4d\x8a\x8f\x4c\x80\x4f\x0d\xac\x2c\x53\xa8\xa7\x6b\x16\x10\xc0\xb6\x20\x76\xe1\xaf\xff\x70\x3b\xae\x4b\x76\xc7\x31\xcc\x8f\x2b\xf0\x1b\x24\x62\x3a\x24\xa7\x45\x76\x64\x9e\xc5\x68\xe7\x6f\x5e\xaa\xbb\x3b\x34\x13\x09\x8b\x16\xad\x11\xcd\x17\x21\x23\x33\x71\x67\x35\xcc\x35\xd8\x53\x66\x7e\x65\x22\xcb\x13\xeb\xea\xf8\xa6\x48\x74\xce\x15\xac\xa6\x23\xae\x3d\x17\x68\x9c\x77\x53\x2c\xd1\x51\x17\x05\xee\x5f\x29\x5c\x9a\x8b\x33\x1f\x17\xb5\xc8\x90\x98\x7c\x43\x93\x64\x4c\xa3\xdb\x1b\xf1\x56\x4c\xd5\x7b\x7e\x2e\xa5\x90\xf5\xb5\x24\xd4\xf0\xe8\x59\xce\x6f\x6d\x2b\x88\xa2\x5a\x83\x98\x1a\x81\x3e\xcb\xb5\x2f\xee\xbd\xee\x83\x6d\xea\xbe\x67\xfd\x5e\xf9\x2e\x67\x81\x7b\x56\x6a\xd8\x2e\x6b\xcc\x62\x64\x75\x7e\x55\x45\xb6\x3f\xbc\xfa\xd3\x5f\x2c\xea\x12\x21\xc9\x5f\x5e\x61\xa6\x80\xea\xdb\x43\x8c\x1c\xd5\x88\x27\x29\x4d\x12\x43\xc8\xab\x48\x69\x00\xbd\x0e\x09\x3f\x39\x0e\xea\xf6\xe8\xb6\xb5\x00\x7f\x73\xf3\x77\xe4\x22\x4c\x2b\x48\x26\x7d\x9b\x20\x55\x28\xd3\x3d\x14\x47\x7a\x8e\xfa\x60\x96\xda\x1e\x88\xdd\x73\x91\xe4\x29\x9c\xc1\x9c\x75\xd1\xeb\xa9\x36\x9b\x37\x30\x25\x4c\x21\x1f\x1c\x27\x22\xba\x25\xb1\xbb\x58\x89\x77\x5a\x2e\x4a\xde\x1c\x0a\x4d\x23\xbf\x5a\x44\x7c\x6d\xfc\xfe\x5a\xac\x57\x4a\xb3\xcc\xc8\x00\x98\x87\x29\xe9\x5d\x0d\x18\x78\x26\xb1\x72\x42\xcb\xd2\x36\xad\x9d\x1b\x6d\x5d\x1b\x03\xf7\x45\x86\x6e\x36\x9e\xa2\x71\xac\x53\x7b\xcf\x48\xb9\xfa\xe6\xe6\xf0\x1a\x42\x94\x13\xfa\xd3\x90\xe1\xbf\x6d\x2e\xd3\x8a\x60\x5e\x14\xd5\x2c\x10\xc3\x0a\x00\x06\x7d\x90\x24\x37\x37\xf3\x77\x60\x53\x6f\x17\xe8\x56\x83\x0b\x2f\x7c\x19\x29\xd5\x4e\x20\xf4\xba\x0a\x25\x19\x48\xc5\x94\xe1\xcb\x1f\xf0\x40\x9d\x26\x94\xa5\x15\xc3\xf3\xd3\x00\xc1\x1e\x6e\xac\xe4\xdc\x9e\x52\x1a\x3d\xc5\x4e\x88\xa4\xd0\x56\xb1\x5e\x23\xd6\xd6\xa5\xda\xeb\x7c\x8c\xf8\x83\xb7\xef\xd2\x50\xaf\x43\x4e\xfc\xd4\x34\xf6\x43\xb9\x0d\x75\x12\x6b\x7e\x29\x68\xac\xbd\xeb\x25\x51\x56\xfc\xbe\xe7\x4a\x58\x8b\xc5\x77\x44\x3f\x90\xa2\xba\xcd\xad\x93\xd0\x9a\xd6\x69\x4f\x58\x45\x17\x70\x0a\xe4\x90\xd8\xa0\x0d\x73\x26\xdc\xa3\xa4\xf7\xa6\xf7\xa4\xd4\xd5\x82\x48\x8a\x8c\x4e\x5b\xf5\x23\x5a\x82\xd4\xf2\xb4\xd5\x62\x19\x46\x7f\xaa\x90\x92\xcc\xdd\x65\x28\x89\xaf\x05\x84\x95\x9e\xac\x33\xdf\x03\xd8\x69\x16\xd8\x2f\x8e\xdc\xd1\x05\xa1\x52\xe4\x3c\x76\xe6\xd0\xc2\x1e\xfd\x6e\xe9\xc5\x97\x82\x83\xf7\xf3\x2c\xd7\xda\x40\x07\x14\xe3\xe4\xf5\xf0\xf5\xab\x97\xc2\xe2\xf0\x0b\x97\x58\xdc\x65\xc1\xe2\x2c\x7d\x7a\xd2\x6f\xf5\x55\xfb\x3b\xfa\xde\x77\xce\x36\x53\x16\xe5\x67\xbe\xe4\x37\xfe\x74\x27\x99\x86\x4a\x97\xc1\x43\xd4\x78\x8c\x62\x59\xa9\x2c\x71\xb4\xae\x1b\x46\x4b\x20\xb5\x2b\xe5\xa1\xf2\xf1\x47\xa4\x5b\x8e\x40\xe1\x71\x5b\x67\x1a\x53\x0f\x90\xb0\x2a\xa0\x0e\x0e\xc8\xa1\xbd\xb3\x67\xf3\xef\x8f\x9e\x14\xb5\x1c\xd0\xce\xef\xb3\x16\x75\x42\x97\x4a\x3d\x64\x14\x8d\x77\x59\x87\x10\xfc\x6f\x98\xd1\x39\x60\xdd\x01\x96\x50\x99\xa0\x8b\xfc\xda\xae\x9d\x8c\x73\x4d\x80\xcf\x99\x14\x1c\xed\xc4\x73\x2a\x19\x56\xf6\x91\x30\x01\x09\xdc\x28\xb1\x5f\x1e\x7e\x38\xb9\xc2\xf8\x9b\x23\xdb\xf5\xc5\xaf\x32\x57\xbe\x04\x4f\x75\x25\x95\xe9\x1e\xdd\x3e\xbf\x0e\x03\x43\xa4\xb9\x7e\x5d\xe6\x3d\x69\xae\x73\xdb\x5a\xe6\x3e\x4a\x72\xc5\xe6\x4f\x45\x49\x5c\x41\x88\x33\xd6\x68\x9f\x97\x8a\x53\x94\x80\x5a\xa9\x33\x51\xba\x09\x1e\x29\xc3\xdd\x53\x45\x8e\x69\x35\x64\xc3\xd9\xac\x48\xca\xa6\x33\xed\xa2\x3d\x97\x3c\x07\x15\x17\x54\x8a\x66\xde\xa7\xb4\x5e\x19\xb6\x7b\x92\x30\xaa\x76\x15\xb9\x56\x12\x19\xdd\x2c\x18\xe8\xc1\x5d\xad\x3f\x9a\x14\x46\x19\xf3\x22\x6b\xa9\xbc\x18\x39\x0f\x9a\x87\x1b\xe3\xff\xb4\x81\x35\x85\x5a\x62\x03\x65\xec\x23\xd6\xdc\x38\x21\x95\xa2\x40\x3e\xa0\x04\x89\x3f\x56\xa2\x42\x8d\x84\x0b\x3e\x98\x55\x8a\x36\x65\x22\xde\x31\xc9\xaf\xa9\xe2\xd1\x48\xe5\x58\x0f\x41\x32\x13\x49\xec\x7b\x68\x5b\x5b\xce\x18\xf4\x1d\x00\x27\x17\x23\x84\x9f\xf9\x44\xf4\x08\x6d\x80\xa2\x75\x2b\x60\x79\xa6\x8a\x2a\x5b\x83\xe7\xae\x08\xd6\x42\x2b\x69\x23\xd2\x17\x5f\xda\xfa\xcc\x7f\x57\xc0\xcc\x47\x64\xd3\xb1\x98\x03\x82\x34\x8e\x25\xa8\x16\xe5\x8d\x9e\x40\x4f\x6d\x45\x4a\x59\xa3\xf6\x3e\x75\xc7\x48\x01\x36\x6f\x5a\x42\xf1\x1d\x8f\x2a\x22\xde\x27\xa6\x60\x17\xa3\xd3\x16\xd4\xab\xf7\x83\xf3\x8b\x98\xa9\x7a\x3d\x45\x58\x16\x95\x3e\xd7\x21\x29\xdd\x8d\x95\x44\x09\x2b\x31\xee\xe6\xeb\x6a\x2a\x26\x56\x88\x5a\x4b\x22\x4d\xb8\x9d\xc6\x90\x15\x97\x24\xed\xcc\x39\xe8\x74\xc8\x44\x8c\xfd\x97\x4a\x68\x28\xff\x44\x15\x20\x3e\x58\xc2\x12\x79\x17\x3a\xd2\x2f\x82\x90\x97\x08\x13\x9a\xde\x7d\xf8\x61\x85\x8a\xaf\x00\xf3\x93\xc1\x72\x74\x71\xd6\x25\xba\x64\x2c\xde\x3b\x74\xd9\x5d\xbf\xac\xa7\xc4\xd5\x2b\x49\xb8\x09\xfd\x61\x1f\x89\x78\x83\x98\x54\x32\x1a\xbc\xbf\xda\x09\x58\x0b\x42\x89\xb5\x2f\x2e\xf5\x78\x6f\x00\x94\x9d\xa9\x04\x8a\x5a\xa3\x3c\x49\xae\x21\x92\xb0\xab\x5d\xb5\xbe\xff\x17\x4b\x73\x6d\x12\x79\x2a\xf2\x3b\x96\x27\x70\x37\xf3\xb2\x08\x66\x25\xb0\xa3\x4c\x3e\xcc\xf2\x04\x63\x61\x29\x5f\x78\x80\xe3\xea\x55\xc5\x89\xc5\x94\x0f\xab\xb1\x61\x5c\xb5\x5d\x50\x50\xbc\xac\xe8\x29\x45\x95\xb2\xae\x56\xc6\x63\x36\x67\x71\x4e\x13\x7c\x11\x4a\xa1\xd5\xfe\xfb\x05\x87\x4c\x7d\x51\xd7\x06\x2d\xf8\x7d\x8f\x7d\xbb\xee\x2f\xec\xf2\x16\x8c\x4f\x07\xf8\x8b\x79\xb1\x5b\xe1\x40\xf0\x01\x1d\x18\xb4\x79\x26\x82\x1a\x96\x25\x7f\x8f\x92\xd0\x95\xdf\x5f\x2f\xd2\x1b\xc5\x4b\xe4\xd3\x19\x02\x4b\xa6\xd4\x57\x08\x4c\x40\x63\xf1\x37\xe7\xc0\xb5\x51\x3b\xee\xd9\xd8\x89\x55\xd5\x62\x78\x75\xdc\x78\x26\xc2\x5a\x53\x8b\xd6\x52\xf4\x71\x85\xcc\x38\x18\xe9\x9d\x31\x50\xcc\x41\xce\x19\xdc\x1d\x3b\x56\x37\x30\x6a\xfc\xc0\x42\x44\x1d\x23\x60\x8f\xbf\xb0\xe2\xe0\xcd\xfb\xb3\xf7\xd8\x49\xd9\x99\x19\x73\x05\x93\x3c\x71\xbd\xe8\x87\x84\x66\xec\x03\x48\x85\xb5\x62\x6f\x19\x8f\xfb\x24\x67\xf1\xd7\x9f\x30\xc2\x85\x71\x56\x86\xed\xb5\xa2\x5a\x6f\x1d\x55\x72\x69\xc3\xec\xdf\x65\xbb\x78\x17\x05\x34\x86\x44\xf0\x69\x25\xe9\x19\xc5\x81\x0b\xce\xf4\x4a\xd3\x59\x5b\xc0\x11\x55\x5a\x21\x63\x0c\x8e\x64\x42\xd6\xec\xb7\x66\x3e\x2c\x6b\x57\x09\xb1\x34\x24\x8d\xd5\xe6\xc3\xb8\x15\x55\x30\x0f\x62\x23\x1f\x7c\x7e\xa4\xaf\xfa\xeb\xcb\xe5\xd9\xea\x8d\x33\xca\x63\xfc\x33\x8a\x84\x8c\xdd\x7a\x99\x2e\xe2\x39\x6d\xf4\x8f\x0d\x39\x41\x36\x64\x28\x1a\xe5\xcb\x6f\x46\x8d\x51\xa6\xb5\xd8\x3f\x2f\xa6\xe4\x9c\xfd\x2b\x07\x42\x53\x61\x08\xf1\x72\x6d\xfb\x25\x88\xa4\x74\x81\xbc\x10\x97\xfa\xd6\xc7\xa7\xbb\xa4\x42\xd5\x27\x57\x40\x63\x56\xc9\x8b\xee\x93\xb7\xf5\x44\xe9\xbe\x59\xcb\xb5\xcd\xe0\x74\x3f\xd9\xd5\x4b\x50\x22\x97\x11\x5c\x59\xa7\x4e\xea\x03\x88\x56\x3f\xc6\xec\x8a\xa6\xb7\xc0\xad\x12\x6d\x40\x83\x7e\xab\x5c\xe2\x1e\x44\x33\x88\x73\xe4\x2a\xe3\x05\x99\x30\xdb\xf0\x02\x59\x3b\x9b\xce\x40\x69\x2f\x0c\x1e\x63\x50\x4e\xd9\x3b\xcc\x2f\x00\xd1\xb7\x12\xbd\x5b\x9a\x9d\x52\x8a\xe5\x98\xf1\xc8\x52\xed\x13\x54\xac\x8e\xa5\xf2\xd4\x9f\xe5\x65\x48\xab\x21\x79\x6b\x5e\x65\xf1\xa9\xd2\x48\x80\x2d\x01\x17\x9d\x6a\xce\x6e\x46\x26\x54\xcd\xb0\xcd\xc6\xf2\x16\xb8\x1a\xfd\x51\x2e\x0d\xc1\xb0\xa5\xb3\x29\xb6\x47\xc7\x56\xba\xd8\x49\x7b\x9d\xa1\xa5\x65\x42\x82\x59\xec\xa0\xc2\xef\x9e\x0b\x13\x3b\x29\x02\xcc\x0d\xe0\xa3\x25\x4a\x60\x77\xd2\x30\x2c\x5f\x62\x4a\xe6\xbc\xf4\x70\x1a\xaa\xf0\xe9\x58\x52\x73\x7f\x66\x23\x3f\x64\x1b\x0e\x48\xe5\xb4\xbd\xa5\xa2\x77\x22\xa7\xb9\x3d\xe8\x8e\x0a\x97\x85\xb6\x87\x4b\x81\xc6\x28\x4c\x19\x0d\xe4\xf4\xdd\x59\x35\xb3\xa9\x9a\xb2\xe1\xf3\xc2\x86\xe4\x43\x5b\xbb\xf2\xb2\x61\xd9\x10\xf4\xd2\x5a\x5d\xb6\xc9\x30\x44\x23\x99\x7b\x95\xa0\x78\x9b\x97\x7c\x19\xcf\x72\xed\x38\x61\xa9\x24\xf2\x68\x46\xf9\x14\xf5\x42\x91\x9b\xf9\xbe\xfc\x12\x57\x24\x21\xce\x23\xd7\x63\xc4\x63\xed\x97\xde\xca\xea\x2a\x7b\x21\xb9\x52\x11\xcd\xfc\x9a\xab\x9f\xf5\xff\xb1\xf7\x3f\xde\x71\xdb\x46\xbf\x30\xfe\xaf\xe0\xa8\x3d\x5f\x69\x93\xdd\xb5\x9d\xb4\x7d\x52\xdf\x7c\x9b\xa3\x48\x72\xaa\x1b\x5b\xd6\x23\xc9\xc9\xdb\x37\xce\xd3\x62\x49\xec\x2e\x2a\x12\x60\x08\x50\xf2\xf6\xfa\xfe\xef\xef\xc1\x0c\x00\x02\xdc\x95\x2c\x91\x94\x77\xa5\x2c\x7b\x4e\x63\x71\x49\x90\x1c\x0c\x06\xf3\xf3\x33\x6a\x21\x34\xfd\xf0\x92\xf0\x31\x1b\x93\x9d\x3f\x06\x3f\xed\xe0\xd3\x8b\x52\x9a\x47\xd8\x8a\x0a\x78\xab\x8c\x6b\xc8\x6c\xd8\x09\xaf\x1e\x93\x23\xf3\x0c\x88\x3c\x79\x02\x06\x49\xff\x93\x9a\x7c\x43\x52\xb2\x19\x2d\xd3\xcc\x7a\x48\xae\x83\x4a\x11\x4f\x30\xf6\x81\x2b\xad\x70\x1b\xd2\x1d\x84\x93\xa6\xea\xd2\x88\x22\xb3\xb8\x46\x29\xd5\x74\x14\xac\xea\x67\x68\x6a\x8d\x2c\xf8\xf1\x88\x5a\xee\xaa\xa5\xd6\xb3\x3f\xd8\x82\xcb\x11\xf5\x57\x71\xa3\x94\x03\x0c\x71\x7b\x55\xe7\xb1\xb9\xc5\x3a\x60\x60\xc7\x0b\xf8\xa8\x06\xc6\x07\x1a\x40\x5b\x99\x5a\x65\xf2\x72\xd4\xc2\x3c\xdf\xb0\xa4\x8f\x4e\x2e\xce\xfe\x71\xfa\xf6\xf8\xe4\x62\xbb\xb2\xb7\x2b\x7b\xbb\xb2\x3b\xac\x6c\x26\xae\x3a\xaf\x6a\x67\x3d\xad\x0a\xd4\x36\xd1\x27\x83\x9a\xa3\x27\x94\x0e\x77\x24\xae\x7e\xa2\x46\x99\x2e\x4a\xa6\x40\x3f\x81\x28\xd3\x8a\xb8\xb5\xbd\x00\x55\xf7\x83\x47\x9f\x0f\xb7\xc6\x6c\xb6\x1e\xb3\x84\x42\xc7\xca\xaa\x59\x0b\x9b\x22\x1e\xfc\xf3\xf8\xf0\xe8\xe4\xe2\xf8\xd5\xf1\xd1\xd9\x5a\xd3\x3b\x3a\xa2\x3f\xc6\xfb\x72\xcb\x5d\xb2\x28\xd9\x15\x97\x95\xca\x16\x1e\x40\x7a\xb5\x10\x58\xce\x10\x14\x29\x78\x3c\x1c\x46\xf6\xca\xdb\xb6\x9b\x6d\xbf\x9b\x6d\x9c\xed\xd2\x01\xf8\xa7\x2f\xf6\x7d\x55\xca\xbc\x27\x16\x3e\x47\x5f\x8c\x0b\x61\xaf\xe2\xa7\x5d\x8b\x11\x12\x6d\x3d\x56\x79\xac\x01\x49\x8c\x3e\x9a\x17\xba\x43\x77\x90\x5e\xf0\x7e\xfb\x81\xc6\xc5\x0c\x9b\x37\xb4\xf8\x91\x2d\xce\x58\x47\x7c\xa1\x98\xde\x2c\x63\x89\xd9\xe8\xc8\x25\x5b\x60\x3a\xe5\x81\x7b\x58\x17\x1c\xa4\x8d\x84\x4b\xbe\x64\x5d\xa0\xac\xfb\xc4\x39\xbe\x64\x1d\x52\x45\xdd\xb1\x84\xf8\x6b\xa6\x10\xf4\x34\x33\xa7\xdd\x66\x8f\xf4\x8b\x71\xfc\x00\xb8\xce\x4f\x37\x8e\x12\x1f\x3d\xce\x82\x0b\xdf\xf6\x3c\x13\x18\x49\x5f\x44\x7b\x97\x17\x22\x04\x8b\x38\x81\x37\x5d\xe8\xc1\x2a\x19\x3d\x91\xa6\x6b\x7b\x41\x82\x53\xd8\xaf\x5c\xdd\xad\x05\x2b\x66\xe6\x7b\x04\xbb\xf4\xa5\x03\x3d\x50\xbe\x27\x20\x74\xd9\x1d\xc6\x7f\x42\x60\x74\x48\xfe\xe5\x4f\x42\x17\x7f\xf5\xcb\xee\xee\xb7\x3f\x1e\xfd\xe3\x6f\xbb\xbb\xbf\xfe\x2b\xfc\x15\xb6\x42\x0c\x6f\xc7\x97\x00\x82\x83\x90\x29\x3b\x81\x67\xc0\x9f\x56\x5d\xdb\xc7\x10\x8a\xfd\x01\x0a\xb0\xc7\x98\x6b\xe4\xff\x2c\x64\xda\xfc\x4b\x75\x82\x1a\xdc\xc8\x8d\x01\xa6\xa8\x43\x3d\x10\x1e\xfd\x6d\x0f\xb5\x2c\xe9\x79\xa9\xda\x51\x7d\x6b\x9b\x64\xce\x72\x04\x3b\x7b\xe5\x48\x00\x7d\x8b\x1d\xd2\x83\x80\xf2\x78\xa3\x99\xc6\xb8\x93\x3b\x57\x2f\x3a\x35\x78\xc7\xa3\x47\xd1\xe6\x67\xb0\x67\x82\x01\x45\x2c\xb5\x70\x21\xfb\x0d\xd6\xa7\xb9\xf8\xbe\x9a\xfb\xa7\xc7\xe4\x0a\x29\xbc\x31\xc4\x71\xe1\xcd\x57\x0f\x2a\xe3\x7c\x10\xb5\x59\x86\xfb\x12\x33\x98\xdd\xef\x16\x12\x41\x79\x6c\x3c\x66\x0c\x9b\x3d\x3c\x39\x4e\x8a\x6a\x68\x2f\x18\xe7\x2c\x97\xe5\xc2\xff\xe9\x4b\x31\x47\x4a\xcb\x92\xce\xa0\x12\x06\x6f\xc7\xdb\xfc\x5f\x78\x63\xf4\x80\xe5\xbb\xd1\x14\xae\x63\xa9\x56\x22\xb7\x84\xf6\xa8\x8f\x0d\x94\x6d\x8e\xf4\x1b\x22\xda\x92\xae\x00\x4d\xf1\x11\x33\xa4\xf7\xc4\xa1\xc2\xe9\xa9\x08\xf6\xa4\x2d\x11\x1e\xd6\x59\x6c\xe0\x0d\x10\x57\xc6\xb2\x6c\x0d\xad\x57\x1f\x3d\x4a\xb3\x94\x5f\x71\x25\x3b\xd4\xfb\xf8\x81\x6e\xce\x78\xb4\x28\x25\x98\xc5\xe5\xdd\x66\x1f\x0a\x40\x13\xf3\xeb\xb5\x21\xf6\x5f\x74\x69\x28\x86\x47\x41\xb5\x66\xa5\x78\x49\xfe\x67\xef\xfd\x97\x1f\x47\x83\xef\xf6\xf6\x7e\x79\x3e\xfa\xeb\xaf\x5f\xee\xbd\x1f\xc3\x3f\xbe\x18\x7c\x37\xf8\xe8\xfe\xf8\x72\x30\xd8\xdb\xfb\xe5\xc7\x37\x3f\x5c\x9c\x1e\xfd\xca\x07\x1f\x7f\x11\x55\x7e\x89\x7f\x7d\xdc\xfb\x85\x1d\xfd\x7a\xc7\x41\x06\x83\xef\xfe\xd8\xf9\xd5\x7b\x00\xf7\xc5\xa3\x4f\x88\xdf\x78\xc4\x5e\xd8\xef\x01\xfb\x5a\xe0\xe1\xd8\xab\xef\xf5\x7f\xe6\xa4\x66\x90\xd5\xe3\xb6\xeb\x8d\x59\xe0\x98\x16\xfa\x39\x3c\x39\xf8\xa4\xb8\x42\xc6\x9b\x16\x4f\x6d\x9f\xfb\x3d\x38\x77\x7c\x47\x4a\x98\xd7\x5a\x13\x9d\x96\x32\x77\x75\xf8\x10\xde\xc0\x8a\x31\x7b\xdd\x25\xeb\xd4\x23\x19\x8f\xad\x33\x68\xeb\x0c\xba\xe1\xf8\xa4\x33\x08\x8b\x08\x36\xd7\x13\xc4\xc4\x55\xdb\x10\xc6\xca\x08\xba\xb3\x75\x42\xb4\xbb\xbb\x05\xd4\xc6\x6e\xa9\xd7\xad\x5c\xeb\x64\x1a\xdc\xd0\xf2\xd5\x31\x4c\xb2\x0f\x2d\xdb\x71\xe1\xc3\x00\x1e\x4d\x94\xa1\x69\xe3\xaa\x26\xaf\xcc\x2b\x78\x0c\xf9\x08\x2d\x16\x72\x8b\xb9\x98\x59\xfc\x09\xdc\x4a\x6c\xf4\x89\x8b\x1a\x67\xd7\x2b\x87\x35\x38\x3b\x55\x4a\x26\xd0\x05\x09\x61\xf1\x3c\x08\x9f\x7d\x6d\x78\x1b\x4d\x2f\x21\xda\x98\xb0\x94\x89\x84\x59\xe0\xf6\xa8\x6d\x2d\x15\xe4\x48\x5c\x39\xf0\xfa\xb4\xc2\x64\x10\x14\x7f\xab\xc7\x78\x5a\x09\x08\x86\x11\x6d\x10\x2c\xc8\x43\x00\xa9\xef\x2d\x6c\x0a\xa9\x18\x72\x5a\x7b\x59\xdb\x75\xb6\xec\xbc\x8b\x77\xdf\x33\x7d\x64\xab\x93\x32\xb4\xb4\x59\xd6\xee\xe7\x78\x93\x7c\x0a\xc1\xc0\xee\xdb\xe7\xef\x6e\xeb\xec\x69\xdb\xec\x67\xcb\xbc\x47\xec\xa4\xcf\x6d\xb2\x8f\x60\x49\x51\xb2\x29\xff\xd0\xd3\x3a\xdd\x0f\xea\x09\x79\xca\x84\xe6\x53\x8e\xcd\x7b\x8b\x92\x15\x4c\x80\xab\x15\x4a\x34\x8c\xec\xb7\x3b\x65\x1d\x9c\xde\xc4\x64\x1e\x54\xb8\xfb\x15\x65\xe7\xab\x94\xfd\xad\x1c\x23\x5b\x39\xd6\xfa\xf8\x4c\x72\xcc\x72\xee\xe6\x08\x31\xc8\x3c\xef\x9e\xfd\x7e\x10\xa7\xb2\x03\x23\x77\x2f\x21\x6e\xc0\xb8\x79\xd1\xa8\x25\x26\xaf\x61\x1d\x5b\x49\x32\x76\xc5\x32\xab\x37\x91\x9c\x0a\x3a\x43\xec\x7d\x2d\x3d\x5a\x8f\x2c\x7d\xff\xa4\x66\xde\x3d\xe8\xf1\xae\xc4\x0b\x7e\x2c\x65\x96\xb1\x52\x91\x8c\x5f\x32\x72\xc8\x8a\x4c\x2e\x72\x9b\xfb\x9a\x92\x73\x4d\xb5\xe1\xea\x73\xa6\xdb\x85\x7d\xbb\xc1\x78\xb8\x2a\xf4\x9e\xc0\xce\xb1\xac\x1d\x8a\xc2\x49\x61\x2b\x28\xdf\x0a\x10\x1a\xfb\xd0\xca\x65\x48\x4e\xd8\x15\x2b\x87\xe4\x78\x7a\x22\xf5\x29\x6a\xdf\x71\xc2\x1d\x5e\x48\xf8\x94\xbc\x34\x76\x9d\xd2\x44\x63\x3b\x8d\xa0\x40\x5d\x96\xd1\x00\x35\x50\x5b\x1f\xf5\x79\xcb\xb5\xe7\x30\x92\xaf\x3c\x6f\x15\xc9\xe8\x34\x4d\xbe\x5f\x51\xe7\x09\xda\xc7\x7a\xd2\x1a\xbb\x37\xe0\x6f\xc4\x55\x70\xd0\x63\x60\x05\x72\x41\x4a\xa6\x0a\x29\x14\x8b\x71\x15\xfd\x1b\xa1\xb5\xdb\x2f\x68\x6b\xeb\xcd\xb3\xeb\xb6\x59\x48\xa5\xa1\x84\xb6\x9f\x2e\x58\xa7\x6e\x38\xa8\x48\xa6\x59\xc6\xd2\xa8\x0d\x1a\xb6\xef\xa1\xb1\x87\x20\x81\x76\x0c\xa9\x6f\xe8\x81\x85\xca\x51\x8d\x73\x74\xbd\x6f\xa9\xe7\x9a\xd6\xb8\x7e\xca\x37\x55\x36\xd7\x0b\x13\xf6\x91\x80\x01\x96\x10\x9e\x01\xf7\x5b\x05\x9d\x6f\xe6\x52\x5e\x92\x44\xe6\x45\x06\x4b\xa7\xc3\xca\xaa\x1b\x6f\x79\x56\x1a\x99\xd1\xd5\xb3\xa0\x27\x17\x9c\xe8\xd6\x92\xab\x93\x22\xd6\x87\x1a\xc6\x3e\xb0\xa4\xb7\xa6\x9d\x47\x1f\x58\x12\x74\x9d\x05\x0c\xaa\xc4\x21\x44\x98\x15\xdb\xbd\x99\x78\xe7\x90\x43\x5f\x6e\xfe\x0e\xb5\x74\xe1\xd1\x80\xed\x83\x31\x1d\xbc\xb9\x7d\x04\x74\x8a\x00\x5b\x08\xeb\xeb\x42\x18\x0d\xcf\x8c\xb8\xf4\x96\xb0\xfe\x7c\x22\xb5\x1b\x0b\x7a\x42\x49\xa9\xc9\xde\xee\xb3\xdd\xc1\x92\xff\xb1\x81\x91\x7d\x11\xdc\xc9\x01\xdb\xb1\x00\xa0\x44\x96\xec\xa6\x43\xc2\xb5\xcb\xb4\xc6\x86\x45\xf0\x56\xb6\xe8\x6f\x48\x94\x24\xba\xa4\x29\xb7\x6a\x0c\x9c\x35\x17\xe9\xb2\xb2\x52\x7e\x6f\xf7\xe3\xae\xed\x65\x74\x2d\xc5\xae\x86\xd7\x1f\x93\x0b\xc4\x89\xf1\x03\x2d\x64\x05\x2d\x3a\x91\x04\x45\xc6\x13\xae\xb3\x05\x48\x2c\x22\x2b\xec\xe7\x65\xf6\x0b\x5b\x6c\x78\xf4\x81\x6b\xd7\x4d\x44\x4e\xc9\x73\x6c\x27\xc6\xa8\xf5\x80\x66\xfc\x8a\x3d\x9b\x33\x9a\xe9\x39\x26\x89\x08\x29\x46\xd8\x11\xd2\x88\x12\xfb\x4b\xd7\x78\x49\x37\x77\x62\x78\x74\x70\x2d\x2e\xbf\x50\x47\xcb\xc1\x08\xd1\x1f\xda\xb7\xa9\x26\x4b\x70\x5d\x17\x17\xa7\x3f\x44\x8d\xaa\x41\x8a\x6b\x5d\xb8\xd4\x9d\xa0\x9b\xfb\x06\xc8\x8e\x7e\x82\x95\x9d\x3a\x56\x93\x1e\x45\x58\xd7\xce\xd5\x64\x35\xfc\xda\xdd\x5b\x56\x93\x7f\xc8\x0a\xc0\x40\xe8\x24\x5b\x78\x24\x06\xc5\x34\xd9\x31\x43\xed\x18\xf1\x64\xb8\xe1\xef\x8c\xa6\x08\x94\xa1\x34\xa3\xad\x54\xb7\xf0\xe8\x2d\x88\x16\xbc\x5b\xbf\xfb\x40\xa5\xb4\xcc\xc9\xdc\x7e\x76\x5c\x7a\x69\x57\xc6\x18\x56\x8f\xab\x6b\x2a\x59\x81\x12\xce\xde\xf3\xe4\xe4\xd7\x92\xdc\x40\xba\x47\x5d\x0b\x92\x90\x6c\x61\x53\x1c\x2e\x90\x58\x88\x3b\xd3\x93\x2c\xed\x21\xf9\x81\xf4\x98\x00\x41\xba\x15\x72\x36\x07\x82\xa0\x5e\xf7\x5c\xaf\xde\x72\x2a\x48\x6f\x79\x03\x64\x95\x93\xd5\xf2\x0c\x7a\x5f\x7a\x22\x62\xaf\xd1\x7a\xd2\xbd\x54\x34\x3c\x6e\x27\x40\x3f\x93\x4f\xfa\xa4\x40\xd1\x43\x6a\xf7\x72\x62\x37\xc2\x48\x41\xe9\x25\x0a\x57\x10\x13\x8a\x95\x57\x6d\x8b\xb9\xeb\xa3\xbf\x4f\x97\xed\x2d\x7e\x77\xac\xa8\x93\x2e\x89\xf0\x6d\xb0\x1d\xac\xe9\x32\x41\x82\xcc\x04\xdb\x35\xdb\xb9\x73\xdd\x76\x44\xc5\x8c\x91\x17\xe6\xce\xbf\xfc\xf9\xcf\x5f\xff\x79\x8c\xc3\xfb\x2c\x05\x41\x8e\xf7\x4f\xf6\xff\x79\xfe\xd3\x01\x14\xc7\x76\xa5\x6a\x4f\x29\x98\x7d\x27\x60\xf6\x9a\x7e\xf9\xa0\xc9\x97\x50\xf2\xd1\x59\x8a\xc4\xbe\x7f\x18\x32\xc4\xf7\xb4\xba\x5f\x80\xb3\x67\x74\xcd\xd8\x91\x6a\x96\xda\x46\xac\x31\x9d\x14\xe7\x32\xb9\xec\xd1\xae\x39\x64\x45\xc9\x12\xf4\x93\x5d\x1c\x9c\xe2\xe8\xc6\xbe\x3c\x79\x7b\x51\x97\x1a\x40\x3e\x4e\x0d\xa6\xf7\x77\xeb\x49\x33\x36\xe9\x25\x2b\xb4\x37\xdd\x27\x34\xb9\xbc\xa6\x65\x0a\x9e\x2d\xaa\xf9\x84\x67\x5c\x23\xf6\x5f\xc9\x6c\xdf\x2a\x4c\xf8\x43\x90\x33\xd7\x17\x18\x65\x39\x3a\x10\x9c\x3b\x14\x5c\x56\x98\x47\x33\xa5\x3c\x03\x0f\xaa\x6d\xc9\x8b\x19\x41\x49\xe1\x5d\x7a\xa1\x4f\x7b\x6b\x7c\xb9\x63\x63\x8d\xaf\xa0\x65\xf0\x7d\xed\xb0\xae\x79\x89\x1b\xbc\xd5\xd9\x2d\xae\x8c\xba\x77\x6f\xb7\xba\x1e\xc6\xdb\xdc\xad\xae\x28\xd9\xb9\x96\xad\x5a\x00\x90\xe5\x28\x09\x0e\x76\x43\x8c\x64\xc2\xa6\xd2\x08\xe1\x1b\x83\x1e\x69\x05\x8b\x90\x0a\x28\x0e\x74\x5e\x2d\x19\x05\x36\x30\x23\xd3\xf5\xcb\xce\x2c\x70\xea\x33\x15\xa2\xa5\xba\xe6\xc7\x43\xf3\x75\x2c\x87\xb7\x1b\xd6\x55\x0e\xb6\xf5\x32\x9c\x64\x3a\x41\xcf\x6d\x20\xc8\x01\x39\xd4\xbe\x7e\x33\x8c\x92\x94\x54\xcd\xb1\x2d\x31\xfb\xc0\x5d\x7f\xfa\x53\x99\x36\x9b\x89\xcf\x4a\x9a\x30\x52\xb0\x92\x4b\xb3\x19\x55\x42\xa7\xf2\x5a\x90\x09\x9b\x71\xa1\x1c\x29\x00\x3c\xdd\xd2\x0c\xe2\x31\x5c\x79\x60\xb8\x31\x39\x8b\xc0\x4e\x6c\x19\x52\x22\xeb\xa5\x69\xdf\xb9\x19\x49\x82\x1d\x0b\xe8\x84\xbd\x7a\x3c\x85\xc3\xf6\x45\x9f\x7a\xe5\xbd\x4a\xc0\x93\x53\x96\xd1\x05\x66\x9b\x42\xcb\x72\xfe\x1f\x56\xaa\x41\x0f\x11\x27\x6c\xc0\xe5\x7e\xbb\xf1\x3d\xb8\x22\x25\xa3\xc9\xbc\x5b\xf0\x77\x1b\xa2\xba\xe3\xb1\x0d\x51\x75\x19\x64\x1b\xa2\xda\x86\xa8\x3e\x71\x6c\x43\x54\xdb\x10\x55\xe3\xd8\x58\x2b\x69\x1b\xa2\x6a\x7d\x6c\x43\x54\xb7\x1f\xdb\x10\xd5\x1d\x8e\x6d\x88\xea\x8e\xc7\x36\x44\xb5\x0d\x51\x6d\x43\x54\xdb\x10\xd5\xef\xc8\x6f\xe7\x8e\x6d\x88\x6a\x69\x90\x6d\x88\x6a\x1b\xa2\xba\xf3\xb1\xb1\xc6\xd7\x36\x44\x85\xc7\x36\x44\x15\x1f\xbf\xaf\xad\xce\x05\x78\x4e\x8d\xa9\xd7\xbd\xa6\xed\x14\x82\x0a\x3c\xb1\x71\x22\x39\x8d\xea\xa0\xf0\x51\xe3\xba\x47\x45\x00\x0b\xe2\x4a\x71\x6c\x44\xa8\x8e\x33\xad\xac\x97\xea\xd8\x47\xae\x90\x69\x1d\xa8\x08\x22\x14\x68\xf0\xb6\xaf\x59\x5b\x5b\x35\x56\x97\xb0\xc4\xe7\x09\x49\x6c\x48\xfc\xa6\x87\x30\xc4\x36\x04\xf1\xe4\x42\x10\xfd\xb8\xef\x7a\x70\xdd\x75\xde\x2a\x6c\x64\xfe\x62\x5e\x32\x35\x97\x59\x6b\x46\x8f\x98\xfc\x0d\x17\x3c\xaf\x72\xe8\x14\x6b\xf8\x99\x5f\xf9\x14\x00\xdf\xbe\xda\x4a\x6c\xf4\x22\x06\x2d\x65\x5d\x2b\x59\xa8\xdf\x9c\xd3\x2b\x68\x8f\x5a\x25\x09\x63\x69\xd0\x94\x1e\x34\xac\xaf\xc7\xfe\x49\xbe\x75\xc6\x8b\x6e\xf2\xa6\xdb\x26\x8e\x70\xa4\x30\xca\xd7\x5f\xb5\x1a\x63\x56\x16\xfd\xc8\xe5\x1f\xce\x4e\x0f\x02\xb9\x4c\x85\x13\xcb\x5c\x5c\xc9\x0c\xa8\x4a\xf1\x22\xa3\xac\x8d\xb1\x7e\x9f\x1b\x83\x69\xc2\x34\x0d\x6c\x1b\x6b\x16\x28\xc2\x04\x9d\x40\x87\x5a\x73\x97\xdf\x91\x4f\x71\xdf\x65\x54\x57\x25\x23\x33\xaa\xd7\x29\xf0\xbb\x9b\x30\x9d\xcc\x97\x3e\xf6\x9b\xae\x1a\x7a\xec\x83\x33\x7a\x78\xec\x85\x9a\x01\x5f\x20\x82\xfe\x9d\xf5\xf0\xce\x92\xb2\xbb\x6e\xdc\x7d\x69\x11\x80\xb8\x81\x0f\xef\x8d\xc0\x3b\xe7\xb6\x75\x94\xdd\xce\x43\x23\xc8\x75\x95\xd2\x92\x14\x19\xad\xfb\x42\xc1\x0c\xfc\x1d\xf6\xa0\x83\x39\x4b\x2e\xcf\x6c\x24\x76\x4f\x31\xe6\x75\xd3\x19\xd7\xf3\x6a\x32\x4e\x64\xfe\xcc\x88\x04\xfc\xbf\x49\x26\x27\xcf\x72\xaa\x34\x2b\x8d\xba\x6a\xb7\xb8\x51\x62\x46\xe1\x62\x36\xce\xd3\xc1\x98\xbc\x17\x58\xdd\x5e\xf7\xa1\x0c\xb0\x1d\xcc\xf3\x1d\xce\xc6\x84\x19\xe9\x2a\xc1\x0f\x11\x40\xd8\x99\xd7\x1b\x77\x01\x4a\xee\xbc\x25\x75\x8c\x82\x7f\xfe\x08\xf8\x56\x72\x91\x1e\x1c\x2e\x8f\x2d\xd2\xdd\x5b\xc6\x47\x0f\x11\xee\x0d\x8a\x6e\x6f\x8c\x6a\xbc\x29\x11\xed\x0d\x44\x9b\xee\x21\x00\xdb\x47\x04\xbb\xbf\xe8\xf5\x03\x80\x32\x3f\x4c\xd4\xba\x47\xd7\x5e\x4f\xd1\xea\xcf\x11\xa9\xee\xe5\xab\xbb\x46\xa8\x3f\x5f\x74\xba\x9f\xcf\xed\xd3\x10\x78\xac\x11\xe9\x1e\x5c\xf4\x7d\xba\xe7\x7b\x73\xcd\x3f\x58\x04\xba\x7b\xf4\x79\x03\x22\xcf\x9d\x89\xcc\x05\xd7\x9c\x66\x87\x2c\xa3\x8b\x73\x96\x48\x91\xb6\xde\x61\x1a\x28\x9d\x7e\xfd\x28\x1c\xd6\xfa\xa9\xe2\x42\x8b\x39\xb5\x60\xe4\xc6\xa2\xc2\xc2\x12\x17\xcb\xb0\x0a\x05\x44\x95\xf1\x2d\x37\x32\x3a\x41\x36\xc6\x21\x86\x55\x27\x7d\x4e\xe2\xdf\xe5\x35\x91\x53\xcd\x04\xd9\xe3\xc2\xcd\xe3\x20\x30\x03\x6b\xef\xa4\x67\x6b\xf3\xeb\x8b\xe7\xee\xe2\xa7\xe7\x76\x04\x07\xab\x52\x0f\xef\x05\xb6\x0f\xfa\xb4\x1b\xd8\x5e\x38\xad\xb2\xd8\x15\x8c\xee\xe1\x58\xde\xbc\xa8\xe1\x94\x5f\xc0\xb8\x7e\xb5\x51\x91\x12\x5b\x89\xf6\xf4\x26\xad\x73\x5e\x4d\xac\xfa\xf9\x3c\x9a\x4f\x79\x8d\x2f\x0e\x4e\xd1\x69\xbc\x75\x97\x6c\x8a\xbb\x64\x4d\xb9\x29\x1b\xa8\xe8\x3e\xd2\x7c\x94\xad\xa2\x7b\x8f\x23\xa8\x4d\xfd\xa1\xa4\x09\x3b\xed\x5d\x47\x70\xcb\x89\xa4\x55\x49\xad\x00\xf4\x2a\x9f\x5b\x3c\x82\xb1\x14\x57\x93\xaf\xe7\x85\x4a\xd9\x69\x95\x65\x0b\x52\x15\x52\xc4\xd5\xcf\x18\x6b\x6f\x16\xd3\x82\x4b\x7e\xc5\x53\x6a\xc5\xb2\x28\xa5\xdd\x33\xcb\x4a\x08\x23\x83\xeb\x9e\x68\xa0\x48\x02\x4c\x33\x8d\x4a\x76\x15\x9f\x99\xd7\x37\xfb\x1f\x54\xf3\xd6\x09\x88\xd1\x80\xe6\xee\xa9\x2c\x13\x3e\xc9\x16\x64\x4e\x33\xdf\x00\x87\x92\x4b\x9e\x65\x76\x98\x31\x39\x67\x1a\x43\x0a\xb8\x77\x66\x52\xcc\xe0\xe5\xa8\x70\x8d\x17\x59\x62\xee\x4d\x32\x46\x45\x55\xe0\xf3\xcc\x4e\xbc\x90\x55\xe9\x9e\x37\xf6\x81\x09\xbf\x03\x0b\x9e\x0d\x83\xf6\x6e\xb7\x4e\xac\xcf\xfd\xa9\x94\x51\x00\xde\x3a\x58\xea\x61\x38\xa6\x43\x0e\x57\x41\x73\x9f\xa2\x94\x57\x3c\xc5\xe8\x86\x23\x1b\x34\x92\xc6\x06\x3e\x7e\x3d\x0b\x29\x46\x82\xcd\x28\x28\x2a\x76\x15\xe1\x9c\xe1\x38\x98\x41\x20\x52\x68\xe9\x63\x34\x7c\x59\x44\xe5\xf4\x57\x1c\x9b\x11\x07\x94\x23\x7b\x42\x12\x09\xf9\xa8\x95\xe0\x1a\x1b\xdc\xcf\x2b\x4d\x52\x79\x2d\x06\xf7\x8a\xba\x42\xa0\xf5\x62\x25\x81\xe2\xf0\xeb\x2a\x3d\x07\xbf\xf7\x76\xf2\x72\x65\x5d\x9f\x53\x52\x09\xc5\x3a\x6e\xef\xbd\x29\x47\x7f\xf9\x53\x3b\x19\xc1\x73\x26\x2b\xfd\x59\xac\xbf\xeb\x39\x4f\xe6\xa1\x32\xcb\x73\xa6\x88\xac\x1a\x66\xf1\x0b\x7b\xdb\xea\x19\xda\x9a\x80\xab\x8e\xb6\x8e\xdd\x15\xde\xaf\x26\x1c\x42\xdd\xf9\x1a\xf2\xc4\x0f\x4f\xce\xff\xf9\x7a\xff\xfb\xa3\xd7\x63\x72\x44\x93\x79\x88\x89\x21\x08\x05\xa1\x01\x82\x62\x4e\xaf\x18\xa1\xa4\x12\xfc\xb7\xca\x06\x7c\xf7\xfc\xbd\x83\x5e\xb1\xda\x5b\xee\xbe\xd0\x9d\xbf\xb7\x76\x70\xd8\xeb\x1f\xf3\xb2\xa4\x62\xd0\xc0\xa5\xa9\x3e\x1d\x99\x9f\xd0\x38\x00\x55\x0b\x12\xe7\x67\xfc\xca\x8a\x61\x0b\x7e\x4f\x53\x9f\x29\x66\xf8\xdc\xb0\x85\xd9\xaa\xe8\x04\x32\xbc\xe6\x8c\x08\xa6\x0d\x5b\x7b\x1f\x93\x14\x2a\x02\x27\xa9\x14\x53\x43\x32\xa9\x20\x27\xad\x28\x79\x4e\x4b\x9e\x2d\xc2\xc1\xcc\x5e\x75\xe2\x43\xde\x8b\xe6\x2b\x1d\xbe\x3d\x3a\x87\x1a\x81\xa2\x44\xd8\x12\x48\x2a\x83\xdf\xe1\xb3\x26\xcc\xdc\x61\xdb\x08\x8f\xc9\xbe\x58\xe0\x8f\xb8\xc0\xb9\x22\x19\x57\x9a\xc1\x16\x6c\x75\x48\x17\x4c\xdf\x79\x3e\x86\xff\xed\x98\xaf\x2c\x8d\x92\xe9\x73\xe5\x92\xa5\xe4\x55\x54\x43\xf9\x24\x0b\xa8\x69\xbf\xfd\x49\x35\x84\xab\x93\x84\x0c\x11\x83\x86\x70\xd4\x4f\x35\x90\x17\x1b\x04\x72\x31\xcb\x42\xae\x6a\x27\xf6\xbb\xda\x96\x5d\x2d\xcb\x51\xfd\x05\xa7\x6d\x0d\xcc\x5e\x1a\xd3\xd5\xef\xd0\x53\x3b\xa7\x7a\xf7\x73\xe6\x94\x95\x08\x32\xec\xd0\x7b\x7c\xea\x56\x80\xd5\x6e\xf2\x46\x5b\xd7\xa2\xce\x49\x1a\x92\xe7\xe4\x5b\xf2\x81\x7c\x0b\xe6\xd5\x5f\xba\x36\xbf\xea\x6a\xf8\xf4\x91\x62\x64\xac\xfa\xe3\xd3\x9e\x28\xfe\xb3\x91\x4e\x66\x44\x43\x55\x2d\xc9\x84\x5b\x75\x9e\x7d\xd0\xac\x34\x72\xd4\xce\xc4\x5a\xdb\x86\x99\x17\xfc\x8c\x6c\x86\xe1\x86\xe3\x69\x9c\xd6\x74\x3f\x46\x33\xb7\xff\x5d\x2a\x7d\x62\xa5\x50\xdc\x00\xa7\x1e\x2d\xa7\x3a\x99\xc7\x62\xcc\x28\x6a\x4a\xd7\x0b\x4c\x91\x54\x42\x96\x15\xa6\x2f\xcf\x79\x87\xe4\x89\xcd\x61\xe3\x6e\xf1\xf4\x68\x3e\x6f\x9b\xa9\x86\x03\x05\x2c\x1f\xab\x58\x05\xc8\x58\x85\x4c\xad\x4e\x66\x5e\x2b\x0d\xf6\x8c\x5b\x94\x32\xeb\xab\xf1\x5e\x66\xe0\x25\xb3\x9e\x12\x2a\xb0\x80\x64\xca\xca\x12\x33\xce\x27\x0b\x97\xac\xd7\x79\xf2\x3a\xad\xa4\xa2\x94\x5a\x26\xb2\x43\x67\xb3\x38\xc6\x6d\x87\x03\x22\x60\x96\xaf\x73\x93\xbf\x3b\x3c\x1d\x92\x8b\x83\x53\xe8\xf6\x74\x7e\x70\x71\x1a\x5b\x2a\x3b\x17\x07\xa7\x3b\x6b\x25\x05\x71\x9a\x15\x38\xa6\x5b\x0c\x12\x39\x9e\x8c\xda\x36\xca\x69\x31\xba\x64\x8b\x96\x7b\x6a\x1f\xfb\xfa\xc8\xcf\x70\x2f\x1f\x84\x64\xce\x69\x71\xef\xd1\x4a\x46\x53\xfe\x99\xaa\xb8\x5c\x1a\xac\x7f\xe6\xea\x72\xae\x5c\x5e\xb1\x14\xd5\x61\x77\x07\x13\x69\x21\xb9\xd1\x17\xb7\x35\x5e\xf7\xbf\x7b\x5b\xe3\x75\xe7\x63\x5b\xe3\xb5\xad\xf1\x5a\x3e\x36\x26\x91\x75\x5b\xe3\xf5\xb4\xe2\xf6\xdb\x1a\xaf\xdf\x79\xe8\x7f\x5b\xe3\xb5\xfa\xd8\xd6\x78\x6d\x6b\xbc\xee\x76\x6c\x6b\xbc\xee\x7f\x6c\x5c\xd2\xd2\xb6\xc6\xeb\x5e\xc7\xb6\xc6\x6b\xf9\xd8\xd6\x78\xdd\x70\x6c\x6b\xbc\x6e\x38\xb6\x35\x5e\xdb\x1a\xaf\x6d\x8d\xd7\x36\xf5\xf5\x93\x63\x6d\x66\xea\x2b\xd9\xd6\x78\xd9\x63\x5b\xe3\xf5\x24\x12\xfc\xc8\xb6\xc6\xeb\x4e\xc7\xb6\xc6\x6b\x5b\xe3\xd5\xe6\xd8\xd6\x78\x3d\x15\x77\xc9\xb6\xc6\x6b\x5b\xe3\xf5\xfb\x51\x74\xb7\x35\x5e\xdb\x1a\xaf\x6d\x8d\xd7\xb6\xc6\xeb\xd6\xb7\xd8\xd6\x78\x3d\x05\x13\xd0\xf5\x01\xee\x5e\xb3\xb4\x7b\x20\xf3\xa2\xd2\x8c\x9c\xb9\x21\xbd\x16\x89\x82\x81\xab\x50\x23\xe8\x9e\x42\x98\x48\x31\xe5\x33\x2b\xd9\x9f\x61\xf3\xdd\x91\xff\x9e\x51\xd0\xf0\xf6\x11\xe6\x0f\x66\x3c\xe7\xed\x0a\xc9\xc8\xd2\xc4\xbc\x86\xb1\x82\xb8\x8c\x59\x49\x39\xfd\x00\x4b\x84\xe6\xb2\xc2\x86\xc5\x89\x9d\x3f\x4f\x42\x8c\x5e\x6d\xdc\xcc\x90\x7e\x4c\x9c\xba\x22\xee\xb4\x8f\xb4\x12\xaa\x35\x2b\xc5\x4b\xf2\x3f\x7b\xef\xbf\xfc\x38\x1a\x7c\xb7\xb7\xf7\xcb\xf3\xd1\x5f\x7f\xfd\x72\xef\xfd\x18\xfe\xf1\xc5\xe0\xbb\xc1\x47\xf7\xc7\x97\x83\xc1\xde\xde\x2f\x3f\xbe\xf9\xe1\xe2\xf4\xe8\x57\x3e\xf8\xf8\x8b\xa8\xf2\x4b\xfc\xeb\xe3\xde\x2f\xec\xe8\xd7\x3b\x0e\x32\x18\x7c\xf7\xc7\xd6\xaf\xdc\x59\x25\xee\x4f\x21\xee\x49\x1d\x7e\x10\x65\xd8\x06\x74\x7b\x5a\x8b\x36\x19\x65\x69\x35\xda\x0d\xeb\xb6\xd5\xe8\xa4\x29\xa8\x79\x7e\x1c\xae\x88\xcc\xb9\x36\xca\xa1\xd1\x07\x69\x98\xce\xca\x75\x64\x94\x5a\x39\x00\x09\xdd\x54\x63\x7b\x75\x9f\x0a\x1a\x24\xb1\x48\xa7\xf9\xd9\xfe\xf3\x3c\x2f\x32\x68\x6b\x0e\xeb\x79\xe4\x72\x59\x60\x73\xdd\xca\x86\x4f\x1f\x5b\xd9\xf0\x14\x65\x83\x62\x49\x55\x72\xbd\x38\x90\x42\xb3\x0f\xad\x3c\x2c\xb1\x68\x38\x8f\x07\xb4\x39\x63\xb6\x8a\xdb\xfe\x46\x64\x81\x79\xdf\x8d\x72\xfa\xb9\xac\xb2\x14\x8a\x39\x2a\x01\x06\x26\x56\xe9\x31\x8d\xd6\x1f\xd8\x3d\x90\xca\xdd\x7c\x88\xb3\xe7\xd0\xcc\xfc\xad\xe2\x57\x34\x33\xd6\x6e\x7d\xc7\x29\x58\x30\xe1\x4d\x77\x5d\xf3\x9a\xaa\xcb\x7a\xc1\xb3\x91\xd1\xa1\xfd\x3b\x3f\x73\x9f\x04\xa7\xd8\x07\xfd\x18\xb5\x34\x50\x90\x4e\x4b\x7e\xc5\x33\x36\x63\x47\x2a\xa1\x19\xc8\xb5\x7e\xf6\x8a\xfd\x1b\x46\x87\x89\x2f\x65\xa6\xc8\xf5\x9c\x19\x59\x4d\xa8\x73\x01\x40\x85\xdd\x8c\x72\x41\x72\x33\x45\x85\xbb\x59\xa1\x2f\xc1\x88\xff\x82\x96\x66\x82\xbd\xcf\x00\x4c\xe4\x89\x94\x99\xad\x78\xc8\x16\xf5\xf8\xb6\xf6\x47\xc8\x7f\x0a\x76\xfd\x4f\x33\x9a\x22\xd3\x8c\xce\xbc\xab\x40\x31\xbd\xe4\xed\xab\x87\xbe\xf1\x03\xa0\x9c\xa0\x62\x84\x66\xd7\x74\xa1\x6a\xc7\x49\x80\xfb\xa0\x5e\x92\x17\x03\x60\x67\xaa\x88\x1f\x23\x25\x5f\x0d\x20\xfc\x77\xb0\x7f\xfa\xcf\xf3\x7f\x9c\xff\x73\xff\xf0\xcd\xf1\x09\x39\x91\x9a\xe1\xa6\x16\x34\x07\x4c\xbc\x85\x61\xde\x12\x9e\x01\x56\xba\x54\x63\xf0\x5d\x72\x45\xae\xb9\x48\xe5\xb5\x6a\xed\xa3\x45\xf6\x33\xc4\x63\x54\xb4\x1a\x23\xa1\x05\x85\x9e\x87\x1d\x76\x98\xa5\x0c\x93\x70\x50\xd8\xc3\xd3\xf4\x59\x5a\xca\x02\x89\xe0\x9c\x5c\xf5\x56\x1b\x9b\xd1\x61\x0e\x2b\xcc\xef\x34\x1e\x70\x56\x52\xa1\x6b\x6f\x4f\x3d\x67\xb6\xd9\xe2\xb8\xf3\x74\x3c\xee\x8a\x26\x9a\xf6\x57\xcd\xb4\x9f\xa6\x2c\x8d\xc8\xff\xe4\x32\x07\x0f\xdc\xc7\x2d\x6a\x94\x0a\x72\xfa\xf6\xfc\xf8\xff\x69\xf0\xf1\xa2\xe8\x96\x28\xd5\x4f\x65\x6c\x29\x8b\xde\x66\xf7\xcc\x56\x5e\x6e\xe7\x77\x23\xe6\xd7\xef\x96\xfd\x84\xe7\xcf\x2a\x11\x03\x19\xd5\xe3\x93\x5c\xa6\x6c\x4c\x4e\x7d\x9c\x20\xfe\x35\x00\x38\xa0\x25\x23\xe6\x12\xa1\x39\xcd\xb2\x45\xa8\xa2\x69\x89\x55\x88\x11\x36\x43\x28\xc8\xa7\x34\x53\xeb\x96\xc6\x5d\xf6\x46\xa3\x47\xbc\x31\xf6\x70\x2f\xd3\xe1\x47\x23\x29\x13\x52\x5b\xc5\xda\xbc\x25\xe0\x5d\x94\x32\x21\x68\x7c\x07\xc9\x58\xd1\xfe\xa6\x30\x56\xe1\xb6\x46\xae\x1c\xb1\x4f\xfd\xc8\xe8\xa8\xae\x14\x6b\x2a\xe8\xae\x0f\xb1\x37\xc7\xcd\xe8\x25\xa3\xa9\x14\xd9\x02\x32\x2f\x31\x97\x22\xa7\xea\x92\xa5\x78\xc2\xaa\x66\x3e\x52\x61\x46\xf4\x8f\xba\x30\xef\xed\xc2\x12\xa0\x92\x61\x86\x07\x84\x33\x58\xba\xe6\x59\xef\xb0\x08\x0d\x51\xde\x8a\x6c\x71\x26\xa5\x7e\xe5\xcb\x68\x7b\xe1\x80\x9f\xad\xb6\x1c\xbb\xa2\x41\x9d\xa4\xf0\xdc\x11\xcc\x06\x2c\xaa\xb0\x82\xf7\xb0\x9e\xf1\xc7\xbe\xa4\xca\x4a\xec\xab\x1f\x4a\x59\xb5\xde\xc4\x96\x94\xcd\x1f\x8e\x0f\x41\x14\x55\x36\x54\x29\x74\xb9\x00\xe8\x80\x65\xd4\x37\x6f\x18\xbc\xb3\xc1\xd6\x70\x4d\xd4\x71\x31\xf2\x86\x2e\x08\xcd\x94\x74\xb4\xe4\x62\xa5\x15\x6a\x4d\x5c\xf3\xf3\x44\xea\xf9\x92\x6d\x6b\x16\xd4\xf2\x7d\xc3\x20\x72\x59\xc3\xd0\x71\xb1\x74\xbb\xa6\x97\x4c\x91\xa2\x64\x09\x4b\x99\x48\xd6\x3d\xed\xeb\x0e\xf8\x01\xeb\x9c\x48\x61\x16\x66\x2f\xcc\x73\xec\x23\xbd\x96\xa4\x21\xab\x40\xcc\xd8\x5a\x7f\x14\x22\xc7\xb0\x2c\x2b\xc5\x4a\x0c\x73\x97\x15\xc3\x99\xfc\xb1\x9a\xb0\xcc\x50\xde\x98\xa4\xb6\x53\x3c\xba\x33\x78\x4e\x67\x8c\x50\xed\x39\x4d\x4b\xc2\x84\x32\x12\x13\x1d\xa0\x9a\xa4\x92\xd5\xd5\xf7\x54\x91\x77\xc7\x87\xe4\x39\xd9\x33\xcf\x1a\x00\xff\x40\x23\x79\x2d\x31\xc9\xad\x69\xa3\x4e\xdd\x10\xf0\x4a\xc0\xbc\x44\x96\x28\x24\x86\x44\x48\xa2\xaa\x64\x1e\x76\xaf\x77\x66\xb3\x4d\x84\x84\xd0\xca\x66\xf2\xfa\x7a\x25\xd4\x3b\xc5\xca\xde\x04\xd4\xbb\x16\x02\x2a\x54\xa3\x0c\xcf\xc5\xd4\x43\xc6\xca\x99\xa6\x29\xd5\xd4\x0a\x2e\x77\xc1\xc6\x4e\xe9\xef\x5b\x7c\x29\xf6\x9a\x8b\xea\x03\x26\x1e\xf5\xe7\x6a\x39\x3f\x82\x61\x49\xe2\xa8\x0e\xb3\x4e\x8b\x22\xe3\x88\xb6\xd1\x48\x84\x3b\x8e\x78\x65\x78\x83\x9a\x08\x72\x82\x66\x99\x34\xf2\xd1\x28\x27\x54\xa4\x32\x5f\x7a\x98\x51\x22\x59\x84\x97\x3a\x26\x5b\xee\x8b\x8f\x0d\x71\x0a\x65\xec\x8a\x75\xc0\x16\x6b\xe2\xc3\x9a\xd1\x0c\x71\x1c\x47\xc0\xf0\x24\xa3\x13\x96\x21\x8d\x91\x03\xd5\x32\x07\xae\x3b\x1b\xb5\x94\x59\x7f\xe5\x33\x67\x32\x63\x98\xde\xe5\x08\x61\x86\x7f\x14\x74\x80\x41\xfa\xa2\x03\x58\x83\x11\x1d\xc0\xae\x7d\x0c\x74\xa8\x3a\x6c\xf5\xa4\x49\x07\xa3\x37\xc4\x74\x80\xcd\x7b\xd3\xe9\xa0\x58\x92\xc8\xbc\x38\x2d\xa5\x31\x3b\x7b\xdb\x9b\xec\xb0\x75\xcc\x10\x1d\x1b\x2b\x92\xb1\x60\x2f\x88\x2f\xa6\x65\x90\xd8\x49\x35\x6e\x12\x2e\xbb\xf3\xff\x17\xec\x59\x20\x7a\x9a\x1b\x99\x1b\x25\x0a\x2f\x9a\x3b\xed\x0f\x8f\x79\x3b\xe8\xa3\x36\xa2\x83\xb3\xb3\x97\xdd\x48\x26\x34\x03\xec\xd8\x6e\x2c\x47\x9a\x6c\xd7\x1c\x38\x48\xe7\x85\x18\x25\x9c\x73\x09\x24\x00\x23\x0a\x67\xac\x0b\x53\xc8\x94\x05\xb1\x6c\xcc\x43\xbe\xc0\xb4\x4f\xb8\xce\x65\x12\x1b\xbd\xc2\x85\x95\xd3\xe8\x6e\x2d\x2d\x02\xda\x1b\x8f\x48\x6b\x5e\x90\x89\x94\x8b\x19\xf8\xd5\x86\xa4\x64\x19\xe6\x20\x5b\x21\x70\x89\x16\xe4\x2e\x2c\x09\x37\xa8\x5b\x0f\xee\xd1\xa0\x8b\x71\x29\xec\xc8\xe0\x29\x72\x1a\xd6\x14\xc5\x2d\x57\x64\xe7\xb5\x23\x40\x07\x08\xcf\x4d\xdc\x61\x76\xf0\x0b\xfd\x6c\xa2\xa7\xf3\x92\x8b\xd4\xa6\xeb\x46\xc4\xf2\x60\xeb\xa8\x07\x43\x22\x38\x4f\x43\xd9\xf2\x92\xbc\x17\xc4\x13\x8b\x8c\x5a\xb3\xc7\x19\xaa\xcc\xce\x47\x37\xba\xdd\xf1\xea\x1f\xd2\x1c\xe6\x9d\x80\xb9\x37\xcf\x1d\x19\xcb\x7d\xf9\x3a\xf7\x2d\x6b\x85\xee\xb1\xd2\xaf\x6f\x2b\xe6\x67\x1c\xd6\xa9\xf4\x89\x61\x6b\xcd\xc5\x4c\x85\x96\x0c\xcd\xb2\xc8\x19\xbe\xca\x94\x71\x33\xec\xa1\xf5\x97\x4d\x88\x46\x99\xc1\x63\x31\x43\x32\xa3\x4e\x3c\x72\x23\x64\x96\x2b\x7a\x50\x1a\x4a\x68\x4e\xb3\xf3\xa2\x3d\x44\x29\x59\x82\xc3\x7b\x73\xbe\x1f\x0f\x0d\x9b\x35\x74\x7e\x30\x73\x65\x7e\x27\x34\xcd\xb9\x52\xe0\x08\x63\x93\xb9\x94\x97\x64\x6f\x05\x1e\x57\x90\xa7\xa5\xf8\x4c\x3d\xb3\x3c\x3f\x32\x6f\x3f\x20\x5c\x64\x3e\x2b\x0a\xec\x60\xa1\x95\x73\xe4\xc0\x43\x12\xff\x16\x30\x87\x16\xb7\xda\x26\x2b\x2c\xbf\x26\x22\x55\x1b\x2e\x58\xbb\xc0\x5e\x9e\x9e\x93\x8e\xb0\x2b\x9f\x98\xa2\x13\xcb\xdb\x4d\x64\xb5\x95\x74\x44\xed\x71\xed\x44\xb2\xca\x45\xc2\x54\x7f\x80\x4e\x7f\xaf\xc7\x24\x29\xc3\x2a\x1e\x06\xd9\x4f\xf4\xc6\x24\x3b\xf0\x4b\xef\x42\x31\xa8\xbd\x75\x37\xd4\xa8\x2f\x6a\xe1\x62\xec\x91\xac\x98\xd3\x11\x1a\xe9\x46\xa2\x81\x08\x74\x2a\xc4\x5c\x0a\x69\x8b\x24\xcc\x26\x2a\x05\xb0\x34\x88\x28\x8c\xe6\xc1\x9c\x58\x11\x1d\xbc\xea\x41\x1d\x25\x0e\x03\x81\x50\x4c\x86\xf8\x11\xf5\x3b\x5c\x73\x3d\x77\x9d\x5e\xa2\xa8\x21\xbc\x49\xc9\x14\x04\x60\x04\x61\x65\x29\x4b\x9b\x90\xe5\xfc\xd6\x30\x12\x48\x72\xc8\xe8\x32\x4c\x42\xcd\x5f\xbb\x2a\x0c\x54\xd7\x50\xf0\x90\xaf\x68\xb8\x89\x4d\xa7\x2c\x01\x45\x2b\x24\x30\x4a\xed\xbd\x1a\xf8\xd6\x56\x19\x18\x06\xb3\x50\xf2\x39\xff\x60\x9e\x12\xde\x15\x86\xc4\x2d\xe0\xec\xea\x9f\x07\x63\x42\x8e\x85\xcf\xe0\x1d\x9a\x59\x0c\xaf\x74\xa9\x67\xda\x7c\x62\xd8\x87\x00\x3e\x20\x74\x9c\x19\xed\xb0\xac\x7a\xe0\xf8\x2e\xee\x70\x12\xba\xc4\x7b\x15\x07\xe0\x1a\xb7\x83\x9a\xa9\x77\x3a\x40\x17\x57\xb9\xb9\xe4\xa1\xdc\xe5\x8f\x23\x00\x42\xba\xca\x39\x8b\xa6\xd0\x13\x38\xfc\x79\x30\x5a\xa0\xbd\xfb\x80\xdb\xa9\x4c\x11\x4d\xc5\xa3\x41\x40\x4f\x27\x40\x77\xe1\xff\x71\xfa\x59\xad\xe3\x09\x89\xd5\x01\x21\xcc\x8a\x85\xd4\x4e\x89\x51\xb5\x33\xe7\x5b\xc8\x8b\x8c\x41\x15\x67\x30\x72\x5d\xa0\x1a\xa0\xc9\x0f\xfd\x8b\xd4\x80\xf4\x16\xdc\x65\x48\xfe\x0d\x8b\xd2\x27\xa2\x3a\xdc\x89\x53\x7f\x3b\x5a\x88\x5c\xb9\xd6\x12\x50\x61\xa9\xa5\x73\x5d\x90\x94\x4f\xa7\xcc\x25\xbc\x1a\xcb\x91\x96\x34\x37\x22\x5e\x11\x4b\x82\x09\x9b\x71\x4c\x88\xf4\x82\x6d\xd7\xa8\x7b\xb6\xd6\x6f\x88\xc2\x90\x6b\x92\xf3\xd9\x1c\x19\x85\x50\xa8\xd0\x25\x2e\xa8\x98\x49\x9a\x12\xe0\x6d\x59\x92\x6b\x5a\xe6\x66\xdf\xa0\xc9\x1c\x22\x94\x54\x90\xb4\x2a\x01\x65\x59\x33\x9a\x2e\x46\x4a\x53\x6d\x34\x65\x56\x5a\x83\xd2\xbd\xff\x16\x52\xff\xd6\x63\x0b\xa9\x7f\xc7\x63\x0b\xa9\xbf\x85\xd4\x5f\x3e\x36\x26\x3b\x74\x0b\xa9\xff\xb4\x60\x92\xb6\x90\xfa\xeb\x8e\x26\x6c\x21\xf5\xb7\x90\xfa\xb7\x1d\x5b\x48\xfd\x4f\x1c\x5b\x48\xfd\x16\xc7\x13\x90\x5c\x5b\x48\xfd\x16\xc7\x16\x52\x7f\xf5\xb1\x85\xd4\x5f\x3e\xb6\x90\xfa\x37\x1e\x5b\x48\xfd\xd6\xc7\x16\x52\x7f\x0b\xa9\xbf\x45\x1a\xbd\xdf\x58\x9b\x89\x34\x4a\xb6\x90\xfa\xf6\xd8\x42\xea\x3f\x09\x3c\x45\xb2\x85\xd4\xbf\xd3\xb1\x85\xd4\xdf\x42\xea\xb7\x39\xb6\x90\xfa\x4f\xc5\x5d\xb2\x85\xd4\xdf\x42\xea\xff\x7e\x14\xdd\x2d\xa4\xfe\x16\x52\x7f\x0b\xa9\xbf\x85\xd4\xbf\xf5\x2d\xb6\x90\xfa\x4f\xc1\x04\x54\x3a\xe5\xad\x10\x40\xef\x02\x56\x64\x93\xd0\x03\x6c\x80\x49\x35\x9d\xb2\x12\x24\x17\x3c\x79\x29\x79\xaa\xc6\x65\x6c\x06\x59\x99\x1e\x02\xee\x91\xad\xd7\xb9\xe1\x76\x0b\x46\x00\x48\x9d\x75\xa6\xf8\xd1\xdb\x57\x2b\x90\x91\x5a\x67\x15\xb6\xcd\x91\x86\x77\x7e\x2b\xda\xc5\xc7\x6f\x20\xf8\xaa\xfa\x31\x4b\xf7\x24\x93\xca\x66\xb8\x03\xb1\x92\x39\x15\x82\x39\x7b\x8f\x6b\xf0\xa3\x4c\x18\x13\x44\x16\xcc\x46\xa7\x29\x51\x5c\xcc\x32\x46\xa8\xd6\x34\x99\x8f\xcd\x93\x84\x23\x76\x9d\x8d\x6e\xcf\x28\x5d\x32\x9a\xbb\xbc\xfc\x9c\x72\x1c\x8a\xd0\xa4\x94\x4a\x91\xbc\xca\x34\x2f\xfc\x60\x44\x31\x28\xa8\xc1\x8d\xca\x13\x03\xb2\xe2\xea\x14\xf6\x61\xfd\x34\xfb\x5a\x32\x84\xa6\x03\x6b\x73\x08\x78\xe0\x79\xa1\x17\x3e\x8f\x97\x91\x29\x2f\x95\x26\x49\xc6\x61\xb7\x86\x27\x62\xed\x34\x8c\x37\x74\x7b\xb5\xb0\x6f\xaa\xec\xab\x8a\x14\xd4\xd6\x42\x2b\xcc\x8a\xad\x07\xb4\x43\xa5\x5c\x59\x35\x5f\x0d\x09\x75\xb8\x69\x48\x68\xf7\xa6\x40\x6a\xb7\xb3\xe0\xe8\xf6\x54\x30\x5c\x80\x17\x5b\xa7\x0d\xd7\x8c\x0e\x25\x0e\x8e\x39\x87\x51\x35\x47\xad\x50\x40\x96\xde\xd2\x32\x80\x09\x10\xec\xca\xf0\x00\x4b\x98\xd9\x5f\xe9\x0d\x5c\xff\xd9\x99\x3e\xd8\x14\xdf\x30\xa5\xe8\x8c\x9d\xb6\x0c\x34\xdc\x64\x91\x41\xac\xa1\x9e\x18\x60\x85\x0c\xab\x6b\xfd\x99\x3a\x3b\x33\x56\x83\x48\x8e\xef\xe4\x95\x9f\xeb\x92\x6b\xcd\x60\x52\x01\x61\x0f\x62\x95\xcd\x02\xfc\xdd\x46\x8e\xe7\x1b\x37\x48\x7d\xb3\x11\xea\x22\xc5\x8c\xcb\x09\x23\x93\x92\xb3\x29\x99\x72\x48\xe3\x84\xc4\xca\x21\x02\x2e\x51\xf4\x02\x28\x65\xec\x5d\x29\x9c\x2e\xeb\xde\x6b\x4c\x7e\xb6\x2f\xa6\xcb\x4a\x24\x34\xc0\xb2\x85\x0a\x53\x3e\x25\x33\x48\xcc\xb4\xda\xe2\x9f\x9e\xff\xf5\x2f\x64\xb2\x30\x5b\x1a\x68\x56\x5a\x6a\x9a\xf9\x8f\xcc\x98\x98\x19\x5a\xe1\xf2\x8c\x6b\x24\x3d\x05\xa0\x9b\x07\xbe\xf8\x8b\xaf\x2e\x27\xf1\x1e\xfb\x2c\x65\x57\xcf\x02\xfa\x8d\x32\x39\x5b\xd5\x1f\xa5\x7d\xca\x76\x4b\x93\x68\x05\x9b\xc9\x8c\x27\x8b\xce\x8c\xe6\x90\xbf\xc8\x5c\x5e\xa3\xae\xbf\x82\x7b\xea\x72\xab\x42\x16\x55\x86\x4e\xe7\x57\xbe\xba\xb8\x52\x6c\xb9\x06\x70\xe5\xba\x00\x37\xa9\x1d\xa2\x89\x9b\x8e\xf9\xb8\xee\x91\xd2\xd6\x96\x58\x47\x9e\x07\x00\x03\x43\xe8\x15\xcd\xb2\x09\x4d\x2e\x2f\xe4\x6b\x39\x53\x6f\xc5\x51\x59\xca\x32\x7e\x97\x8c\x1a\x69\x39\xaf\xc4\x25\x76\x70\xf0\x10\x09\x72\x66\x54\xab\xa2\xd2\xae\x90\x61\xd5\x07\x63\xbd\xbc\x13\xc2\xce\x0c\xaa\x47\x61\x1f\x78\x6d\xeb\xd8\x52\x2d\xe4\xc8\x70\x7c\x15\x32\xdb\x57\xcf\xff\xf4\x0d\xb2\x2e\x91\x25\xf9\xe6\x39\xe4\x6c\xab\x21\x2e\x62\x90\x6d\x66\xa3\xc8\x69\x96\x19\xb3\x21\x64\x4a\x43\xe8\x55\x4c\xf8\xd9\x79\x50\x77\x67\xb7\x3b\xab\x52\x17\x17\xff\x00\x3d\x8a\x6b\xc5\xb2\xe9\x10\xab\x92\xbc\x59\xb3\x0b\x1b\xc3\xae\x95\x3e\x50\x1a\xb6\x01\x0a\xd0\x95\xcc\xaa\x9c\x1d\xb2\x2b\xde\x47\x13\xa7\x68\x34\x67\xea\x67\x5c\x41\x01\xd8\x24\x93\xc9\x25\x49\xed\x8f\x41\xe6\x49\x13\x09\xbc\x3d\x15\xda\xe6\xe0\x74\xc8\xbd\xb9\xf1\xfb\xa3\xac\x9b\x9c\x16\x85\xaf\x11\x2a\xe9\x75\x44\x0c\x58\x93\x00\x57\xd0\x11\x4f\xa6\xb3\x9b\xb9\xab\x93\x79\x64\xbf\xc8\xc8\xcd\xd6\x43\xb4\xce\x3a\xe9\xee\xa3\xae\xdf\xbe\xbd\x63\x32\x62\x88\x7a\x40\xb7\x1a\x0a\xf8\x37\x56\x95\x2c\x55\x45\xfa\xc2\x3a\xcf\x18\xa8\x00\x18\xf6\x01\x91\xdc\xde\xe1\xda\x83\x77\xb3\x5b\xca\x51\x44\x17\xe1\xbd\xca\x39\xd5\x56\x21\x74\xee\x6b\x4a\x0a\x56\x2a\xae\xcc\xbe\xfc\x13\x2c\xa8\x83\x8c\xf2\x3c\x70\x01\xae\x87\x08\xb8\xb8\x01\x3e\xb9\xbb\xa4\x3c\x95\xa9\x1d\x10\x44\x21\x42\x47\xaf\x50\x6b\x63\xad\xb6\xc7\x0d\x75\xdd\xa2\xf2\xa7\x9a\x9a\xb1\xa4\x34\x67\xbc\xa8\xc4\xab\x9e\x92\x80\x84\xef\x7b\xac\xf2\xd1\xbf\x7c\x4f\x62\x00\x04\xa3\x9d\xdc\x58\x12\x46\xc6\x23\x2e\x94\x40\xa5\xb7\x76\xe0\x98\x60\x14\xdc\xac\x09\x7b\x2b\xd9\x7d\xb9\xbb\x56\x21\x89\x24\x2a\x65\x41\x67\x9d\x7a\xf9\x34\x28\xd5\x1c\x36\x04\x9a\x30\x66\x10\xfc\xee\x61\xd7\xe0\x2a\x96\xd6\x38\x3a\x80\x92\x84\xd1\x51\x47\x60\x6b\x20\x60\x3d\xf6\x35\x5d\x10\x5a\xca\x4a\xa4\xd6\xbf\xe4\x1d\x7c\x6f\x1a\x0f\x3e\x91\x82\x39\xc7\x79\x13\xa7\x02\x3c\xfa\x5c\x90\x17\xe3\x17\xcf\x9f\xca\x4e\x05\x5f\xd8\xd8\xa9\x4e\xfc\x4e\x85\xf2\x69\xad\xdf\xea\x10\xef\x7b\xfa\xde\x37\xd6\xc5\x52\x03\xda\x73\x07\x97\x0d\xa7\xae\x4b\xae\x59\xd0\xe3\x6f\x0f\x0c\x17\x63\x1f\x06\xa8\x0c\x83\x55\x9d\x24\x3a\x12\xa9\x1b\x0c\x86\xaa\x26\x0f\x28\xb7\xac\x80\x82\xe5\xb6\xca\xc3\xa5\x6e\x11\x61\x21\xa1\x76\x76\xc8\x1e\x5e\xb9\x8b\x05\xcd\x83\xb5\xb2\x96\x25\xda\xd1\x87\xa2\x03\xc6\x66\xa3\x76\xbe\xa0\xe0\x83\x2b\x7a\xa4\xe0\xf7\x6c\x4e\xaf\x18\x14\x72\xf3\x8c\x96\x19\xc4\x1c\xcf\xf1\xdd\xc9\xa4\xd2\x84\x89\x2b\x5e\x4a\x91\x33\xa1\xc9\x15\x2d\x39\xa0\xe2\x94\x0c\x90\x1d\x8c\x2d\xfa\xc7\xbd\x9f\xf6\xcf\x20\xa1\x61\x60\x21\x29\xec\x5b\x56\xca\xc1\xd7\x84\x6f\x12\x0c\xf7\xc9\xe9\x73\xef\x61\x68\x08\x32\xd7\xbd\x97\x79\x4e\x5e\xe9\x0a\xdb\xb2\x7c\x48\xb2\x4a\xf1\xab\x75\x49\x12\x5b\x61\x7f\xc8\x5b\xcd\x73\xa3\xda\xbf\x26\xd4\x52\xe1\x3e\xb8\xd6\x57\x14\xe8\x2d\x05\x4c\x76\x95\x2f\xda\x0b\x63\xe0\xd6\xf5\x64\xb1\x34\x30\x7d\xce\x21\x2e\x2e\xa9\x10\x80\x1b\xb3\x5e\x27\x94\x90\x29\xbb\x3f\xea\x4e\x9c\xde\x63\x87\xc0\x98\x79\x50\xc1\xa7\x92\x39\x4b\x2b\x80\x77\xe2\x0a\xc1\x51\x8d\xf9\x40\x6b\x14\x3e\x01\x5d\x82\x8e\xa7\x1e\xd2\x40\x8c\xc0\x39\x88\x34\x77\xf7\x97\x0e\x00\xc1\x9d\x50\x8d\x11\xc1\x28\x35\x63\x0d\x09\x55\xaa\xca\x71\x49\x60\x03\x84\x29\xd7\xca\xf7\x98\x75\xda\xb1\x59\x18\xf7\x2c\xa8\xea\x40\xdf\x73\x96\x01\x73\x75\xa0\xf1\xee\x49\x30\x0e\x12\x5a\xb9\xbf\x2c\xc3\xd9\x84\x09\x88\xb6\xf9\x3c\x4e\x09\x5e\xd2\x29\x87\x26\x4a\xd4\xd2\xfb\x7c\xc5\x9d\xa8\x3a\xe0\x15\x00\x0f\x43\x27\x2c\x53\xcd\x81\x26\xf5\xa4\x58\x54\x52\x4b\xf8\x8e\x5d\x72\xa9\x52\x7c\x26\xa0\x7f\xa6\x19\xed\x9e\x9d\x32\x5b\xdb\x4c\x7d\x74\xc1\x6d\x2d\xd5\xa2\x2c\xac\x9c\x16\x23\x6b\xf5\x6a\x99\xf3\xe4\x1e\x23\xc9\x7b\xbe\x72\xa3\x56\x3a\xaa\xc1\x7d\x7b\xbe\xe4\xf1\x51\x81\x57\x63\x4c\xce\x65\x6e\x53\x9c\x44\xd0\xc5\xcb\x35\x53\x35\x3b\x46\xc9\x0c\x2d\x20\xf1\x88\xd7\xd1\x78\xe8\x7a\xe3\xaa\xa0\xe1\x39\x5e\x25\xb7\x61\x5c\x80\x9f\xb4\xcd\x5c\x65\x96\xc9\x6b\x48\x2c\xc6\x71\x1d\x6f\x43\x0a\xcc\x4b\x32\x6a\x74\xa6\x1d\xc7\xa0\xa1\xb7\x3f\xc7\x5e\x3b\xfc\xf4\x53\x30\x3f\x07\xe0\xf8\x8e\x0f\xc3\x3f\x8f\x4f\x0f\xdc\x9f\xcd\x37\x89\x9b\x30\xdc\x7c\x55\x08\x87\x7d\xd3\x55\x53\xec\x63\xf4\x89\x9f\x0f\xe6\x54\xb8\xb8\xd5\x8d\xcf\x5b\xa8\x44\x67\xf5\xeb\xcc\x69\xc9\x2c\x5c\x9c\x11\xdc\xaa\xa0\xc9\x8d\x6f\xe1\xb1\xd9\x6e\xbd\xe0\xd6\x37\x55\x55\xe1\xfa\x6b\x67\x70\xa1\x7f\x93\x9a\xcb\x7e\xf9\xe2\xd7\x3b\x12\xf3\x53\xf7\xac\x22\xed\xed\xf7\x44\x5d\xfa\xee\x74\xc7\xea\x1e\x5e\x77\xbb\x37\x68\x83\x77\xa7\xeb\x6f\x6a\xc1\x7b\xd7\xa7\xb9\xd6\x6d\x77\xfb\xb0\xe6\x6c\xdf\xe1\x72\x9c\xfb\x4f\x67\xcd\x99\x05\x79\x0c\x88\x9b\xd3\xc5\xa9\x4c\xcd\xda\xc4\x14\xb9\xfb\x01\x1b\xb4\x96\xf6\x6d\x3d\x63\x2d\xfc\x59\xed\xfd\x58\xed\xfc\x02\x0d\x5d\xe1\x06\xd4\x53\x8b\xc8\x26\x66\x24\xc2\x99\xaa\xca\x92\x09\xe8\x90\x5f\x41\x52\xa4\xeb\x7c\x8f\xf2\x1c\xe4\xb2\xc5\xf4\x44\x60\x7a\xb2\xef\xb7\x4d\x9b\x2c\x97\x53\xc0\xf9\x0c\x70\xad\xa7\x15\xe4\x3e\xc2\x2e\x81\xb8\x75\x52\x98\xf7\x78\xb9\x0a\x4c\x43\x16\x4c\x04\x6d\xf1\xad\x82\x3d\x32\xfc\x17\xc1\x6b\xa0\xce\x30\xce\xd3\x3f\x14\x19\xd5\x53\x59\xe6\x23\xa7\x49\x8e\x22\x7d\x82\x1c\x40\x16\x8e\x72\xa6\x18\xa6\xc2\x22\xfe\xa6\x48\x33\x16\x6c\xfc\xfe\x53\x45\x8a\x68\x55\xa4\x12\x25\x4b\xe4\x4c\xf0\xff\xd4\x84\x80\x2d\xd0\xfb\x91\xa8\x32\x9b\x2e\x11\x55\x96\xdd\x3f\x65\xa1\xa5\xbe\x20\xaf\x58\x39\x67\xf4\x9e\xcc\xdb\xc8\x7e\xb1\x63\xd4\x6d\x4a\x95\x85\x1f\xb0\xda\xb1\x7b\x88\xd1\xa2\x65\x02\x65\x70\x18\x8d\x77\x39\xce\x14\xf6\x7e\xa3\x14\x52\x32\xe3\x57\x4c\x38\x74\xf2\x83\x8c\xfa\x56\xdb\x0e\x90\xd5\x22\xa4\x57\x5a\xfa\xfc\x06\x42\x75\x80\x91\x0c\xe9\x50\x36\xb4\x1a\x8e\x13\x5c\x62\x1b\x75\x67\xae\x29\xda\x5d\xae\x84\x14\x03\xec\x12\x39\xac\x3f\x29\x77\x6e\xd8\x08\x84\x93\x24\x90\x08\xe3\xac\x16\x9b\x00\xf3\xe9\x47\xd8\xec\x35\x23\x83\x56\x0d\x63\x35\x6b\x8f\x16\x5b\x13\x36\x33\x5b\xc7\x02\xf5\xa1\xe3\x69\xfc\x24\x1e\xe1\xf3\x43\x99\x14\x68\xea\xb5\xe9\x78\x2a\x53\xa3\xb0\x0d\x89\x9f\xca\xb0\x4f\xb9\x0d\xcd\xe0\x9a\x0c\x16\x23\xea\x73\x65\xc9\x54\x21\xb1\x4d\x40\xf8\xd8\x61\xe0\x2a\xe3\x3a\xca\xcb\xc3\x86\x6f\x7e\x69\x20\x90\xdb\x7f\x58\x29\x57\xaa\xfb\x33\xae\xc7\x97\xdf\x80\xae\xcf\xc4\x9c\x8a\x04\xcd\xac\x67\x97\xac\x50\xcf\x14\x9f\xa1\x6a\xff\x97\x6f\xbe\x01\x3d\xdf\x91\xe4\xd9\xd9\xd1\xfe\xe1\x9b\xa3\x71\x9e\x3e\x22\xa5\xbf\xa0\x5a\xb3\x52\xbc\x24\xff\xb3\xf7\xfe\xcb\x8f\xa3\xc1\x77\x7b\x7b\xbf\x3c\x1f\xfd\xf5\xd7\x2f\xf7\xde\x8f\xe1\x1f\x5f\x0c\xbe\x1b\x7c\x74\x7f\x7c\x39\x18\xec\xed\xfd\xf2\xe3\x9b\x1f\x2e\x4e\x8f\x7e\xe5\x83\x8f\xbf\x88\x2a\xbf\xc4\xbf\x3e\xee\xfd\xc2\x8e\x7e\xbd\xe3\x20\x83\xc1\x77\x7f\xbc\xe7\x8b\xb6\x2c\x61\xe9\x5a\xb6\xd2\xa9\x54\xa5\xc7\xf2\x94\xa2\x64\x2c\x07\xf1\xd7\x26\xb1\x2b\x76\xa8\x36\x86\x72\x1b\xac\xfd\xcb\xc8\x44\xf7\x34\x31\x33\x62\x52\xa1\xe8\xcc\xe4\x35\x24\x63\x72\x69\x14\xa7\x31\x79\x0b\xfb\x20\x39\x61\x57\xac\x1c\xba\x51\x5f\x9b\x8b\x4e\xfd\x35\xa1\xc7\x6e\xd5\x15\x2d\xcb\x01\x5a\xce\x89\x7b\xf7\x0e\xc4\xc3\x16\x27\xf6\xe5\x41\x3e\x8d\xc9\x4f\xb4\xe4\xb2\x52\x56\x17\x09\x91\xc1\x31\xdb\xcc\xef\x24\xe0\xc0\xb0\xb1\x20\x3f\x88\x2f\x22\x73\xe1\x20\x4f\x9b\x7d\x2f\xaf\x0f\x56\x6f\x09\x5c\x9b\x99\xba\x72\x8f\x2a\x5d\x56\xec\x12\xa8\x38\x6e\x06\x2b\xe5\xbf\xdb\xd1\x54\xf8\xa2\x30\x8c\x7b\x0f\x90\xad\x46\x13\xc3\x51\xe6\x7c\xe6\x72\xaf\xe1\xfb\xd1\xd2\x0d\xce\x7a\x0e\x69\x31\xa5\x6d\x96\x69\xdb\x12\x80\xa2\xf9\x7d\x1d\xd8\x22\x86\x5e\x0e\xd1\x9b\x5d\xf1\x51\xbd\x6e\x76\x90\x4f\x60\x13\x19\x25\x25\xd7\x3c\xa1\xd9\x0e\x6c\x4e\xee\xa7\x24\xab\x8c\x9e\x18\xfe\x5a\x32\xa2\xaf\x25\x3e\x85\x66\xe4\x92\x2d\xae\x65\x99\xba\xfd\xd9\x3d\xb1\x9e\x0b\xa5\xdd\x23\x8d\x2d\x08\x0b\x18\x3d\x12\x65\xce\x4a\x32\x61\xce\xd9\xde\xb8\x78\x31\x26\xfb\x62\x61\x23\x95\x22\xac\x47\x0c\x40\xdc\x40\x47\x40\x2d\x2a\x62\x12\xbb\x89\xb9\xa7\x51\xac\x14\xbd\xc9\x11\x6d\x14\x30\xbf\x0a\xdc\xee\xef\x3c\xd1\xb2\xb4\x05\x51\xb0\x3a\x4a\x2c\xe7\x92\xee\xe7\xcf\x22\x2d\x8c\x7e\xc3\x05\x53\xea\x07\x33\x95\x5d\xd4\xd5\x98\x3b\x28\xa8\x25\x76\x6c\x28\xaa\xaa\xb3\x8f\x99\x59\x52\x18\x4e\x36\x62\x58\xa6\xf5\x95\x63\xb2\x0f\x27\x20\x7d\xde\x68\x5e\x50\x70\x67\x06\xe3\x5a\x35\xfb\xd0\xe3\x15\xfb\x27\x87\x2e\xcd\x19\x35\x05\x15\x23\xab\xa3\xca\x1c\xbf\x09\x68\x7a\x36\xd9\x96\xfd\x56\x51\x68\xa9\xbb\x73\x51\x56\x6c\xa7\x9d\xaa\x84\x98\xfd\xcf\xfe\xfc\xcd\x73\xd0\x96\xfc\xf3\x46\xf0\xbc\x36\xaa\xd2\xfd\xd3\x69\x5a\x25\xd2\x34\x73\x88\xce\x42\x7e\x70\x04\x77\x76\x87\x8d\x6f\x41\x19\x30\x4c\x93\xa7\x79\x2b\x2f\x6c\xab\xb4\x99\xf6\x09\x33\xa3\xfa\x75\x2f\xee\xdf\xee\xac\x4b\xae\x4b\xf4\xdc\x3e\x02\x62\xf5\x68\x38\x2b\x0a\xa7\xc4\x3f\x27\x70\x02\x63\x57\x0c\x7b\x1a\x32\x67\x41\x70\x41\x00\x01\xc4\xe3\xa2\xe8\x90\x25\xdc\x42\xde\x40\x51\x4c\x67\xfd\x6e\xf7\x0c\x07\x22\x45\xad\xd0\x2d\x15\x3b\xf8\x60\x30\xe8\x1d\x56\x95\xdb\x87\xca\xb1\x21\x79\x2b\x5e\x61\x2a\xfd\x10\xb5\xbb\x08\xa8\x04\x2f\xea\xb5\xa2\xf0\xd9\x1f\xec\xb7\x8f\xf0\x95\xdb\x08\x85\xfb\x93\x3b\xb0\x1c\x3b\xee\xfe\xbb\x67\x8d\xb1\x22\xd6\x8b\x2c\x63\xbb\x43\xf2\xba\x4d\x9a\x15\x9f\x64\x56\xca\xaa\x70\x41\xd7\xb8\xe7\x59\xdd\xe8\x03\x63\x85\xd8\x12\x58\xc8\x78\x68\xef\xfc\x00\x06\x66\xb5\xd7\x2c\x25\x09\x9a\xc7\x6e\xd7\xc5\x82\x29\xf4\x20\x94\x95\x88\x5b\xa2\x07\x61\xcb\x9d\x8c\xcd\x68\xb2\xd8\x89\x9f\xb3\x2a\x48\xcc\xa1\x8e\x87\xe7\x88\xad\x8e\xcf\xab\xcb\x1f\xa0\x4a\x02\xf4\x07\x5c\x6b\xa0\x1a\x54\xca\xbe\xa2\xdb\xf2\x5d\xfd\x1e\x7a\xb6\xca\x0e\x96\xf9\x9f\xbf\xf9\xf3\xc8\xf9\xde\xe0\x55\x3e\x0b\x43\xf9\x20\x6f\xaf\xba\x64\x34\x67\x46\x41\xe2\xaa\x80\xf9\x05\x4d\xac\xde\xce\xfd\xd3\x6f\x53\xb7\x56\x0f\xe2\x26\xa0\x1e\xe2\xb3\x90\x2b\xf6\xc0\x77\x59\x7e\xcd\x0e\x31\x73\x99\xa5\xb0\x50\x6c\x1f\x27\xf7\x28\x42\xb5\x2e\xf9\xa4\xd2\xd6\x4d\x9a\xc8\x3c\x8f\xcb\x2b\x6d\x2f\xbd\x31\xa9\xeb\xeb\x42\x13\x16\x38\x79\x4c\xc8\x39\x63\xd8\x47\x32\x78\x0f\x90\xb3\x8e\x94\xd6\xdb\x2a\xa7\xd8\xf4\x1b\x8d\xb0\xcf\xe4\x16\x6a\xbf\x1d\xdb\x40\x5c\x47\xaf\xfd\xce\xbe\xb7\x52\xc2\x78\x19\x0a\xb8\xa5\xd6\xbe\x8d\x9d\x09\x32\x8f\xeb\x00\xad\x4d\x44\x32\xb4\x50\x08\x27\x0b\xbc\xfc\x23\xb6\x01\x85\x2c\x4b\x88\x1a\xa2\x6f\xf2\xda\x0c\x31\xe7\x05\xda\xd4\x54\xfb\xdb\x21\xde\x6f\x7e\x0e\x51\x1a\xa0\xaf\xe5\x0b\x34\x6a\xe5\x35\x78\x85\x7f\x38\x3e\xf4\x6b\xc4\x5c\xf5\xea\x1c\x43\x42\x5f\x8d\x6d\x97\x5e\x3d\xe3\x29\x99\x60\x8e\x87\x91\x97\x7b\x82\x5d\x63\xd6\xb8\x75\x9c\x7a\xbd\xfa\xca\x65\x53\xe3\x68\xfe\xe1\x76\xc8\x01\xf9\xda\xf6\x4b\x65\xa5\xb3\xca\x27\xdc\x66\x95\xbe\x3d\xdb\x75\xee\xea\xeb\x51\x79\x3d\x1a\x8d\x46\x36\x14\x0c\x52\x7a\x18\xd1\xc0\x0b\xf3\x5c\xa6\x7c\xba\x68\x50\xc2\xb0\x79\xfd\x08\xe0\x48\x2a\x16\xf6\xed\xba\xb7\xf6\xbd\x3f\x92\x77\x37\x77\x5c\x17\xe4\x86\x15\x61\xe6\xae\xf1\xa9\x55\x91\x6b\xb4\x93\x55\x0d\x80\x2e\xa7\xc8\xa4\x90\x68\x7f\xc3\xc4\x38\x2f\x90\xe5\x1a\x0b\xeb\x87\x56\x3a\xfb\x50\x48\x04\x0d\x86\x42\x16\x68\xee\xd6\x0c\x4f\x40\xf2\xa8\x59\x55\x90\x8f\x17\xad\x1a\xab\x50\x60\x44\xcc\x11\x81\x4c\xa8\x19\xd2\xbf\xce\x5e\x83\x4f\x06\x63\x72\x6c\x59\x0b\x0c\x42\x21\x6d\x8b\x38\x22\x05\x61\xc5\x9c\xe5\xac\xa4\x59\xfc\x20\x5b\xd0\xfb\xd2\x88\xdb\xd2\x70\x29\x86\x00\x72\x5a\xa0\xb4\x05\xe1\x99\xf2\xd2\xb5\x98\x0d\x42\x73\x3b\x6f\xc5\x99\x94\xfa\x0d\x57\xa0\xbb\x58\x67\x08\x6a\x9a\x3b\xab\x36\x34\xf7\x5b\x9d\x1d\xdd\x95\x93\x3f\x5b\xfc\x8b\xb8\x36\x71\x7d\xc8\x5a\x23\x41\x8c\xd0\xba\x6f\x27\xb8\x77\x16\xef\x27\x6a\xb8\xeb\x7d\xb1\xab\xfa\xbc\x2d\x35\x79\xfb\xcc\x5d\xde\x6c\x02\x17\xd5\x11\xb0\xd6\xe7\xee\x4c\xbe\x3e\xe9\x05\x2c\x73\x22\x61\x9d\x74\x64\x9a\xe3\xe5\xe6\x72\x35\x8b\x80\xbb\xcf\x77\xcd\x14\x52\x8c\xa0\xd9\x53\xa5\x5c\xe0\xb2\x74\x2e\xdf\x68\x03\xb2\x1d\x28\x71\xdb\xc4\x2e\x82\xb4\x56\xe9\x8d\xea\x24\x54\x55\x32\x9f\xcc\x98\x4a\x56\x37\x7e\xa2\x8a\xbc\x3b\x3e\x24\xcf\xc9\x1e\x24\xf2\xfa\x62\x6e\x84\xaf\x30\xa6\x6c\x23\xdb\x74\xea\x86\x88\x4d\x17\x8b\x1d\x21\x24\xca\x22\xd7\x15\x53\x0a\xbf\x0d\x5b\x0c\xce\x1b\x7a\x19\xae\x9b\xc7\xdb\xf2\x63\xbb\x74\x7d\x9f\x21\xd3\x83\x0c\x7a\xd7\x42\x06\x85\x8a\x75\x1f\x9d\x28\xd7\x3d\x7b\xbf\x77\x09\x15\x27\xb9\xf5\xc0\x54\xe7\x47\x30\x20\xe2\x46\x7c\xd0\x56\x8d\xbf\x67\x9b\xf3\x65\x7c\x20\x0b\x92\xe4\xa1\x04\x4a\x2a\x52\x99\x2f\x3d\xcd\xcc\x26\x18\x6f\xc1\x6c\x6e\xd9\xee\xa6\xa3\x53\xb5\x67\xb7\x62\x49\xb0\xf1\x7b\xa8\x92\x7d\x0d\xbe\x02\xae\x3c\x27\xa0\xf3\x00\xf2\xc7\x97\xcc\xd6\xce\x20\x0a\x9d\x8b\x86\x4a\x99\xb5\xac\xbb\x8b\xbe\xfa\x4c\x66\xb6\xde\xc1\x7d\xb6\x19\x78\x63\xbf\x5a\xb7\x0c\x13\x34\xc5\xcb\xa2\x68\x7c\x35\xb8\x73\x36\xf5\xab\xab\x56\xbb\x34\x69\x7e\x35\xa4\xc3\x46\x5f\x0d\xfb\xee\x26\x7e\x75\x9c\xfd\xdc\xc3\x66\x62\x07\x24\xd2\xe6\x60\xdb\xa6\x03\x4d\x3c\x94\x3a\x43\x12\x9c\x50\x8f\x4b\x8e\x76\xa9\x98\xc7\x44\xa7\xcf\x2d\xba\x65\x42\xb3\x39\xb6\x7c\x6f\x37\xcf\xa4\x39\xd7\xcd\x21\x83\x64\x0c\x6a\xde\x16\xce\x05\x29\x85\x14\xc1\x9c\x64\x1d\x90\x69\x04\x5f\xac\x9b\xce\xde\xe9\xb2\x21\xcc\xfe\x5b\x67\x38\x86\x77\x6b\x69\xbb\xd0\x3a\xd0\x78\x0a\x2f\xc8\x30\x5f\xb1\xa0\x7a\x3e\x24\x25\xcb\x10\x07\xd6\xae\xb3\x4b\x34\xa5\x76\xa3\xb4\x49\xc7\xb1\xee\xd1\xa0\xb0\x40\x17\x6a\x18\x19\x5c\x3e\x4e\x0d\x99\xa2\xfc\xe2\x8a\xec\xbc\x76\x04\xd8\x79\xcc\x02\x7a\x07\xbf\xc7\xcf\x1d\x7a\xb1\x2e\xb9\x48\x2d\x40\x6a\x44\x1a\x9f\xa2\x8b\xba\xa1\xf3\x30\xb9\xb5\x4e\x4b\x06\xce\x5e\x4f\x1a\x32\x6a\xcd\x0c\x36\x14\xe6\x02\xa2\xa3\x1b\x94\x4c\xe7\x53\x71\x0f\x69\x0e\xf3\x4e\xc0\x4c\x0b\xa8\x9d\x10\x72\xc5\x75\xee\x5b\xda\x35\x4b\xec\x22\x7a\x97\x8a\x5c\x3a\x8a\xdf\x7d\x0f\x4b\x35\xc3\x9a\x99\x40\x85\xaf\xa1\x2b\xad\x5d\x68\x3b\x41\x37\x54\xef\x21\xcc\x8e\xcd\x77\x5d\xda\x9d\x30\xbd\x2a\xa7\xe5\x82\xfc\x70\x7c\x88\x1a\x78\x64\x08\x08\xe9\x1e\xed\x39\x25\xb5\xe8\x84\x54\x2c\x36\x40\x71\x6e\x87\x10\xd3\x1a\x1f\xa6\x2b\xf2\x6e\x27\x33\x11\x4b\xb8\x3a\xf2\xd4\xb9\x2d\x04\x9b\xcb\x2c\x25\xd4\x33\x98\x70\x45\x60\xa9\x7b\x0e\x06\xd0\x83\xea\xcf\xb1\x31\xbe\x6c\x70\xba\x12\x75\xa5\x88\xbb\x7e\xaf\xa9\x12\xb8\x35\x3d\xb0\xa5\xd0\xce\x33\x95\xd1\x4a\x24\xf3\xdf\x0b\xcb\xac\xa0\xbe\x0f\x75\x50\x72\xc9\x4a\xc1\x32\x52\xd0\x92\xe6\x4c\xfb\x66\x87\x8a\xb5\x81\xfe\xe9\x88\x1c\xd4\x0d\x37\xa8\x03\xe6\x4f\xfb\xa6\x85\x5d\xd1\x82\xba\x60\xb0\xac\xe8\xe4\x36\xc5\xdd\xd1\xbc\xd2\xc2\x36\xf8\x6c\x39\x78\x67\x60\x8c\x4e\x6d\x08\x63\x10\x2c\x44\xf0\xdf\x88\x6f\x8b\xcb\x7c\x7b\xb0\x6e\x7e\xc6\x01\x6b\x3c\x02\x97\xc9\x70\x5f\x77\x99\x53\x99\x96\x51\xc0\x76\xd5\x92\x2b\x2a\x6e\x99\xf0\x99\x7d\xe5\xad\xe5\x2e\xd4\x01\x3e\x2a\x0f\xd7\x2c\x57\xf4\xa0\x64\x50\x71\x4a\xb3\xf3\x82\xb5\x6c\xe2\x1f\xb7\xf0\x7f\x73\xbe\x1f\x0f\x0a\x9b\x12\x24\x5b\x9b\x39\x31\xbf\x07\x25\x03\xd7\x6c\x32\x97\xf2\x92\xec\xad\x28\x7b\x0c\xaa\x5c\x14\x9f\xa9\x67\x96\xbd\x47\xe6\xbd\x07\x84\x0b\x80\xb2\x5d\x86\x00\x76\x0f\x49\xfc\x5b\xc0\x5c\xd9\x9c\x35\xbb\x0d\x2f\xbf\x26\xc8\x28\xcc\xa8\x59\x87\x81\xb3\x3c\x19\xf7\xcf\xf7\x72\xc7\x27\x26\xe4\xa6\xf2\xd7\x95\x54\x43\x87\xc6\x5a\x48\x62\xcd\x6d\xa3\xbe\xf7\x40\x87\xbf\xd7\xa3\x85\xc8\x6b\x7c\x1a\x81\xc2\xd7\x86\x92\x0f\x56\xee\x42\x73\x2a\x7b\xeb\x6e\xa8\xd5\xc7\xd0\x69\x34\x2b\xe6\xd4\xa6\x86\x61\x39\xb0\xcb\xa0\x98\x30\x32\x97\x42\x96\xb6\xcc\xa1\x2e\xe4\x01\x31\x83\x75\x37\x30\x03\x56\xde\x06\xaf\x7a\x50\x7b\x90\x5c\xbf\x94\x69\x46\x67\xd0\xdc\xa6\x51\x8d\x03\xc2\x55\x56\x18\xd5\x0c\x2f\x76\x25\x8b\xae\x71\x03\xe0\x46\x2b\x94\x62\x2e\x98\x69\xcb\x36\x20\x0b\x64\xdf\xbc\xb7\x21\xcb\xa9\x4b\x66\x76\xaf\x00\x6e\x0a\x5f\xb4\xa9\x0c\xef\x60\xfe\x06\xbf\x62\x11\x81\x51\xf2\xee\x39\xd4\x1a\x8d\x49\x56\xb8\x5f\xc0\xfd\x94\xe4\xfc\x83\x79\x4a\x78\x57\x58\x6d\x20\x52\x88\x12\xaf\xfe\x79\x60\x8c\xb1\xda\x72\x1b\x9a\x59\x0c\xaf\x0c\x9a\x2a\x08\xf8\xe1\x04\xcb\x05\xf0\x03\xc2\x48\x8b\xed\x8f\xd0\x85\xbf\xdb\xa3\x9a\xf9\x50\x69\x4f\x4b\x1d\x42\xa6\x76\x38\x33\xd1\x6e\xfb\xee\x12\x42\x35\x97\xf4\x11\x46\x5d\xde\xa3\x3f\xfb\xd6\xfe\x39\x65\x98\x62\xe5\x15\x4f\xd8\x7e\x92\xc8\x4a\x74\xca\x42\x3d\x64\xe6\x13\xa8\x66\xe9\x79\x34\x26\x7a\xdc\x53\xf8\x15\x2b\xd1\x69\xc6\x29\x22\x12\xc5\x57\x62\x91\x5d\x3d\x0e\x78\xec\x1b\x6f\x68\x59\x46\x69\x46\xdb\x65\x94\x76\xa4\x50\xd7\x54\xf9\xe5\x2f\x5e\xb5\xc3\x35\x28\x68\x9d\xf5\x4b\x69\xf0\x77\xab\x41\xd0\x54\x5d\xd6\x38\x4d\x0c\xca\x90\xfc\x62\x0a\xce\xdb\x0f\x1d\x51\x7c\x6a\x2b\xec\xa6\x16\xd4\xd5\x46\xee\x99\x8f\xdf\x57\xaf\xfe\xfb\xf0\xa4\x5b\xe6\xb8\x6f\x51\x83\xf5\x2d\x73\x3b\xb4\x57\xd5\xc3\xb2\xfc\xb0\x3c\xd1\x3c\x79\x48\x4a\x6a\xd1\xf7\x6d\xe7\xb5\x8c\x51\xf4\xa9\x90\xbd\x20\x53\x7f\x30\x36\x32\xbd\x8e\x96\xa3\xa8\xb7\x8d\xd2\x72\x46\x85\x0a\x4a\x50\x19\x0c\xed\xb2\x62\xfd\xfb\xe0\x46\x68\x67\xdb\x7a\x0f\xf6\x9c\xd3\x35\xbe\x42\xe9\xb2\x4a\x34\xa9\xb4\x32\xe7\xf1\xe1\x4e\x60\xde\xe1\xf1\x25\x9b\x71\xa5\xcb\x85\x6b\xe1\x36\x0d\x5e\xc2\x7a\x85\xfc\x25\x97\x6c\x41\xfe\xfe\xe3\xd1\x3f\xfe\xf9\xfa\xed\xc1\xfe\xeb\x7f\xbe\xd9\x3f\xf8\xfb\xf1\xc9\xd1\xfb\xf7\xe7\xff\x38\xbf\x38\x7a\xf3\xfe\xfd\x01\x22\x8c\xd8\x72\xdc\x73\xa6\xdf\xbf\xb7\x9c\xaa\xde\xbf\xbf\x48\x0a\x5e\xbc\x7f\x7f\xea\x7c\x20\xd8\x9c\xe1\xbf\x0f\x4f\x40\x7e\x62\x55\x98\x4f\x7b\x82\xbd\x15\x89\x0e\xef\x3d\xa7\xaa\x4e\xb2\x8c\xea\x6d\x5a\x00\x7a\xb6\xdd\xee\x56\xc2\x29\x75\x5a\xec\x66\xc0\xba\xab\x92\x73\xf1\x7a\x2f\x1d\x99\x30\x7d\xcd\x6c\x19\xe3\x4a\xbc\x2e\x1a\x14\x46\x07\x10\x5c\xab\x3a\xb7\xa0\x72\x26\xc9\x15\x67\xd7\x88\x39\x81\x4d\xf2\xea\xf6\x41\x50\xd6\x8c\xa5\xad\xcb\xa8\x60\xa0\x24\x15\x32\xf5\xad\x92\x1a\x7e\xe9\x25\x9f\x74\x54\x46\x83\xb8\x6f\x2c\x25\xa7\xc7\x87\xe4\xc5\x18\x95\x9c\xe3\x43\x84\xa1\x5c\x89\x52\xe5\x2c\x55\xb3\xa1\xe2\xee\xbb\xa2\xea\xa0\x66\x80\x36\xc2\xa8\x05\x07\x54\x93\x54\xe6\xf4\xbe\x4d\xd1\x3e\x51\xbf\x82\x2d\x2b\x7f\xab\x68\x86\x3a\xc0\xa9\x4c\x97\x25\xd3\xce\xb7\xee\xd4\xdf\xc6\xdf\xfa\xf7\xf8\xdb\xf8\x5b\x68\x86\xe9\xc8\xf6\xb7\xb1\xba\x4a\xc6\xdf\xda\x02\x69\x62\x2f\x5a\x99\x23\xbc\x54\xed\x64\xf5\x59\xbc\x07\x9e\x4d\x41\xdf\xfd\x2c\xe5\x2e\x3d\x76\x15\xed\xb9\x97\x28\x6a\x81\x50\x7b\x9d\x94\x8c\x62\xaa\x39\x49\x59\xc6\x6a\x1c\x98\x0d\x68\x66\x79\x73\x77\x4f\x17\x6b\x8b\x7a\x9f\x86\xbe\x29\xaf\x2f\xfd\xee\x5b\xa4\x86\x06\xc3\xd7\x75\xc7\xf9\x16\x0b\xa0\x23\x52\xc3\xbd\xc2\x46\x5a\x66\x0c\xe7\xa7\xcb\x4a\x59\x59\x57\xb7\xab\xc2\xd1\xdb\x10\x62\x1d\xd5\xe8\x17\x0e\xc8\xd4\x70\xc4\x85\x7f\x7f\xb0\x34\xb0\xf5\x1f\x06\x57\xf1\x17\xa8\x76\x5b\x10\xb3\x6b\x69\xf4\x64\x84\x15\xa2\xba\x84\x26\x85\xdf\x5e\xb2\xc5\x10\x01\x3d\x50\x09\xf9\x5b\x80\xc8\xec\x4b\xa2\x11\x78\x4d\x96\xe4\x5b\xf7\xaf\xbf\xdd\xd7\x5a\xeb\xe0\x47\xed\xe2\x45\xc5\x8f\xea\x1c\xf9\x3a\xc2\x2a\x98\x18\xe1\x03\x29\x6b\x0b\x64\xb4\x44\x72\x8d\xc9\x11\xd4\xbd\xa2\x46\x6a\x51\x69\xb3\x2c\xba\x58\xb9\x0e\x93\x11\x3a\x04\xf8\x5f\x82\xea\x98\x13\x79\x6e\x2b\x33\x01\x66\x67\xca\xca\xfa\x0c\x08\x98\x13\x79\xf4\x81\x25\x95\xfe\x9c\xd5\xea\x78\x5c\xb2\xee\x3d\xbf\x7e\x64\x1e\x82\x08\x69\x63\xb4\x70\x5f\x99\x50\xaf\xce\x20\x39\xed\x76\xda\x5e\xb2\x85\xf2\x20\x6b\x97\x38\xba\xad\x6a\xf6\xfc\xeb\x36\xb2\xa3\x0f\x5c\x69\xf5\xbf\x5c\xc3\xb1\x7c\x52\xb7\x7a\xa3\x98\x25\x56\x8f\x1e\x00\xec\x99\x3f\xe1\x31\x9f\x9b\xe0\xee\x03\x3a\x53\xfd\xad\xa3\x44\x00\xa1\x47\xcd\x37\xed\x2a\x9b\x9e\x24\x05\x14\xaa\x85\x58\x6c\x75\x62\x0d\xde\x8c\xfc\x89\x34\x04\xba\x1c\x19\x25\x2f\xde\x66\xec\x29\x7b\x11\x07\x54\x11\x7e\x45\x33\x26\x2c\x8a\x6d\x96\x26\xb4\xc4\x10\xbd\x05\x14\x52\x16\x08\xdb\x22\x69\x98\x3d\xce\x4a\xb2\x7a\x96\x95\x0d\xe5\xd1\x52\xf3\xa4\xca\x68\x49\xcc\x7a\x9c\xc9\xf2\x9e\xb8\x43\x78\x74\x6b\x7c\xe7\x59\xb4\x43\x3f\xe8\x58\xbe\x37\x47\x6c\x02\x1d\x5a\xed\xc5\x98\x4c\x50\x5f\x13\x2f\x94\xbd\x18\x48\x5b\x4e\x9d\x6c\xf2\x82\x22\x84\xca\xd3\x91\x73\x9c\xcf\xc0\xff\x3d\x08\x36\x0f\xbf\x32\xc7\xe4\x7b\x5f\x2d\x3e\x24\xb5\xcf\x18\x6a\x52\xed\x33\xed\xb2\xb1\xd3\x55\x2f\xea\xa9\x2c\xa1\x8b\xe1\x5e\x2a\xe1\x1e\x76\xc5\x13\x3d\x18\x93\xff\xd7\x68\x8a\xe0\x44\x76\xea\xa4\x5d\x66\xbe\x0e\xb7\x06\xec\x7b\x4e\xf6\xe0\xb6\x50\x95\x1c\xb8\x40\x91\x45\x02\x7d\x64\xd9\x30\x1d\x22\xdc\x2b\xa2\xdb\x91\x18\x45\x4d\xb1\xc1\x1a\x7e\xe7\x97\x5e\x42\x7a\x99\xc8\x95\x5d\xa5\x91\xe7\xd6\xc7\x59\x9c\x08\xf5\x8c\xf3\x6f\xf0\xd1\x93\x92\xcd\x60\xfd\xe1\xea\xf9\x8c\xab\x4f\xcb\x42\x66\x72\xb6\x38\x2f\x4a\x46\xd3\x03\x29\x94\x2e\x41\x34\x74\xc1\x77\xbb\x69\xcc\xa0\x71\xd6\x5c\x5e\x13\x6a\xcb\xd9\xe5\x14\x11\xf2\x64\x35\x9b\x63\xab\x00\xb8\xd1\x35\x99\x75\xaf\x68\x8d\x4e\x35\x26\xe7\xbe\x15\x00\x30\xb8\xef\x2c\x00\xa3\x80\xc3\xe3\x9a\x2e\xec\x62\xa2\x13\x9e\x32\x15\xe4\x28\xbb\x97\xc1\xd0\xcf\x8d\xdf\x0f\x52\x79\xff\xe4\xf0\xbe\xfd\x17\xd6\xa8\xd0\xde\xf0\x29\x5e\x33\x42\xaa\xd7\xf4\xf5\x1a\x29\xd0\x8d\xe6\xd2\x6a\xaa\x88\xe5\xea\x28\xf3\x19\x75\xd3\x2e\xe0\x4b\x39\xfd\x70\x7e\xc9\xae\x5b\xdc\xe9\x3e\xf4\x47\x76\xff\x54\xb0\x11\xd8\xa3\xef\x84\xa2\x9a\xab\x29\x34\x6a\xf9\x8c\xfa\x38\x14\x1d\xb4\xeb\x27\x81\x47\x5c\xbb\x13\x8e\xe6\x8a\xc2\x3d\xde\x62\xc4\x2c\x36\xff\xaf\xb6\x83\x70\x03\xc4\x22\x08\xdf\x8a\xc2\xac\xa0\xc4\xb6\x67\xd2\xb2\x8e\x43\x63\xa4\xa2\xca\x27\xac\xf4\x6b\x1f\x9d\x01\xbc\x6c\x40\xd3\x36\xd6\x7e\x7b\xc1\xd8\x3a\x13\xae\x6b\x5a\x19\x90\xe7\xe8\x83\xd1\x3c\x54\xbb\x44\x25\x3c\xe2\xee\x6a\x8d\x41\x31\x3c\xe6\x12\x38\x1b\xd3\x10\x75\x39\x01\xb3\x37\x3c\xd3\x56\xce\xd5\x47\xb7\xfe\x8c\xa4\x5b\x8f\x46\xb2\x22\x51\xfa\xc6\xcf\x6f\xb4\x4a\x09\x0b\xfe\xac\x53\x48\x0d\x51\x81\x47\x07\x36\x15\xf5\xc6\x6e\xdb\xe6\x67\x5e\x9b\x33\x46\x91\xb9\x08\xef\xeb\xda\x08\xa9\x43\x8f\x47\xd2\x43\x9f\x47\x02\xb2\xec\xb2\x85\x04\x0c\xef\x77\xc4\x6a\x3d\x48\xf7\x8e\x8f\xa4\xbd\x41\x5d\x1f\x11\x43\x5d\xd6\xa6\x35\x72\x56\x64\x5a\xd7\xc2\xae\x36\xac\x3b\x3d\xbb\x87\x36\x68\xa4\xa3\x8d\x5b\x1f\x11\x21\xe4\x3d\xac\x5d\x0a\x01\x26\x39\x75\xab\x63\xa5\xcd\x7b\x2c\x86\xe4\x44\x6a\xf3\x9f\xc0\xfc\x3d\x94\x4c\x9d\x48\x0d\x67\x36\x82\x94\xf8\x09\x3d\x12\xd2\xb5\x11\x00\xbc\x37\x90\x9b\x36\x44\x6b\x76\x3c\x47\xb0\x15\x86\xc5\xb1\x20\xb2\x74\x14\xf3\xd6\x85\xb2\x43\x84\x61\x05\x8b\xb1\x75\xa3\x71\x62\xc6\x09\xe9\x7c\xcb\x70\x76\x28\xc8\xfe\xc2\x5f\x00\x3c\xb5\xc8\xa0\x40\x20\xad\x4a\xc4\xb0\x35\xba\xa6\x66\x33\x9e\x90\x9c\x95\x33\x68\x1b\x9d\xcc\xfb\x98\xbe\x2e\xfb\x0a\x1e\x1d\x77\x97\xf0\x65\x3a\xf0\x12\x6c\xd9\xa0\x62\xf5\xa8\x02\xe0\x78\xb8\xad\xe5\x14\x2c\xa9\xff\xe3\x7d\xd0\xff\x97\x14\x94\x97\x80\x79\x6b\x63\xc7\xe1\x6f\x36\xfa\x12\x0e\x63\x46\x58\xf2\x2d\x51\x41\x18\x56\x32\x99\xd1\x9b\x8a\xc7\x90\x5c\xcf\xa5\xc2\xcd\xd0\xbb\x3f\x76\x2e\xd9\x62\x67\xb8\xc4\x7a\x3b\xc7\x62\xa7\x0e\x0c\x47\xcc\xe6\x37\x61\xc8\x20\xdc\x81\xdf\x76\x1e\x4e\x57\xe9\xb4\xd9\xf6\xd1\x31\xa0\xf9\x42\x2d\xf9\xca\xda\x3c\x9d\x35\xff\xdd\x37\x38\x50\x60\x9f\x63\x4c\x70\x56\x32\x2c\xc6\x04\x53\x1a\x14\x75\xdb\xdd\xa5\x12\xec\x8a\x99\xc9\x4a\xb9\xb2\x78\x80\x2e\xc5\xe0\x5f\x4b\x26\xd1\xff\xff\x50\x9e\x48\xed\xac\xf6\x7f\x39\xb7\x17\xf2\xdf\x07\x9e\x57\x39\xe2\x66\x69\x63\x29\xa4\x7c\xea\x80\x80\x5d\x66\x43\x6c\x2f\xc4\x66\xab\xe5\x63\x4d\xcb\x19\x64\x38\x5a\x7b\xc1\xb1\xd9\x2c\x93\x13\x9a\x91\x9c\x0b\xf3\x18\x1b\xbc\x8c\xce\xf9\x37\xb1\x7f\xde\xf2\x20\x58\x0b\x7c\xc6\x27\x19\xb3\x06\x49\x03\x63\x3b\xb8\xb9\x71\x21\x2c\xd2\x8c\x29\x85\xf1\xc6\x37\x5c\x1c\x3a\x6f\xc6\x2b\x59\x12\xf6\x81\xe6\x45\xc6\xb0\x44\x8f\x7c\x3d\xfa\x8f\x14\x8c\xd8\x00\xfd\x90\xb8\xe9\xa9\xfb\x96\xbd\xc0\x85\x54\x37\x16\xf0\xd9\x17\x91\x4d\xe8\x3d\x29\x8a\x7c\xf5\xec\xab\x67\x2f\x5e\x9a\x3d\x04\xdd\xf4\x54\x59\x08\xa2\x65\x6a\xbc\x18\x93\x8f\xc4\xbc\xc1\x0b\xfb\xdf\xaf\xec\x7f\xbf\x26\x1f\xc9\x47\x42\x4e\xc9\x29\x09\xff\x6b\xfe\x43\x3e\x92\x91\x21\x42\xf0\xaa\x2f\xcc\xd7\x24\x32\xb7\x14\x04\x1f\xb4\x2f\xb8\xf5\x7d\x03\xb5\xb4\x43\x43\xb5\x53\x22\x73\x06\xaf\xfa\xd5\xff\x72\xd7\x40\xa8\x58\x63\x6b\x47\x78\xa9\x3d\x78\xa5\x01\xb9\x06\xa7\x5a\x4e\x2f\xd1\xa0\xdc\x4f\x74\x45\x33\xf3\xf0\xbd\xaf\x47\x2f\x06\x44\x8a\xf8\xf2\x2b\x2e\x8d\xf2\xee\xde\x70\xef\xc5\x60\xbc\xf4\xca\x5f\xad\x78\xe5\x46\x97\x43\x5b\xee\x68\x06\xbd\x99\xdf\x1d\xab\xef\x8b\xc5\x35\x5d\x78\x86\x77\x06\xf5\x8c\x5f\x79\xb4\xff\x00\x84\x04\xa2\x8d\xc0\xbf\xdc\xe1\x4a\xe1\xa0\x0b\xc2\xf5\x98\x1c\xeb\xdd\x5d\xd7\x53\xd3\xe8\xfa\xae\x2d\xc1\x61\x88\x97\x09\x84\x07\xde\x78\xde\xc8\x46\x6e\x81\xce\xd6\xab\x5b\xf7\x5e\x7d\x05\xf0\xc8\xfd\x2a\xe9\x2c\xe2\x76\xea\x15\x17\x55\xb3\x2f\xaf\xfa\xe6\xc2\xf5\x89\x53\xb7\xae\xee\x06\xea\xb5\x13\x43\x97\x6c\xd1\x58\xf9\xf5\x37\x0d\x21\x87\xc7\x79\xed\x08\xba\xed\xd0\x55\xaf\xc8\xfb\x9d\x78\x5d\xbe\xdf\x01\xe7\xbd\xdf\x3f\x6d\x1f\x1f\x9a\x25\x95\x6d\x00\x27\xa7\xc4\xb1\x71\x80\xd0\xb5\x2f\xd2\x3a\x65\xa2\xe5\xfb\x03\x84\x3d\xe8\x8c\x33\x88\x23\x94\xcb\x5f\x12\xa4\x55\x44\x59\x78\x66\x15\xd6\xeb\x78\x4c\xf6\x91\x81\x15\x04\x3f\xee\xf2\x5e\x37\xd2\xae\x6e\x07\x7b\x2d\xc5\x6e\x0d\xbc\x4b\x72\x89\x10\x69\xc2\x6d\x8f\xd6\x57\x25\x89\x06\x55\xc5\x4f\xeb\xf1\x74\x45\x1e\x4c\xed\x20\x46\xf0\x49\xc3\x24\x50\x37\x11\xf2\x4f\x80\xea\xff\x62\x05\x12\xa3\x5d\x2e\x2a\x26\xd7\x73\xcb\x48\xf5\x33\xa5\xc6\xe7\xfe\xdc\x94\x1f\x5e\xf9\x8e\xf6\x4d\x68\x99\xd9\x66\xb3\xf8\x6a\xd8\x78\x7b\x7b\xfe\xcf\x6d\xf6\x90\xaf\x5e\xde\x6f\x73\xb0\xff\xbd\x88\xa6\x79\xe5\xec\xfe\x79\xaf\x7e\xcb\x01\x04\x30\x57\x2c\x02\x28\x76\xa8\x83\x59\x63\xbf\xa1\x29\xae\x2b\x8a\xf5\x11\x82\x5d\xdb\xa4\xb5\x9b\x3f\x2a\xa8\x71\x73\xc2\x7d\x68\xf6\x1f\x5a\x29\x06\x45\x2b\x15\xd4\x33\x1b\x42\xba\x20\xda\xd7\x7b\x5f\x93\x11\x79\x3e\x30\xdc\x20\x90\xad\x80\x98\xe1\x56\x66\xb6\x06\x9b\x83\xa9\xe7\x46\x79\x32\x94\x51\x43\xdf\x4a\xab\xb1\x09\xc1\x94\xfa\x5e\x89\x02\xab\x6a\x56\x75\x4b\x84\xb2\x19\xb3\x32\x6b\x12\x1d\x8b\x53\x99\xc6\x3e\x7f\x5f\x08\x33\xa3\x9a\xb5\x02\x3d\x58\xaf\xbc\x0f\x3c\xf1\x3d\x84\x7f\xfd\x58\x4e\xc3\x33\x46\x8a\x9c\x22\x24\x05\x76\x34\x1e\x43\xbb\x6a\xbb\xd7\xda\xd4\x46\x74\xf2\x58\xde\xe1\xca\xfb\xf9\x38\x54\x8a\x25\x41\x93\xc0\x12\xc5\x05\x4f\x59\xc9\x5c\x43\xe4\x30\x11\xd6\x47\x50\xc8\xcf\xf5\x95\x98\x00\x0b\x99\x42\x38\xd0\xdf\xb0\xf0\x6a\x67\x52\x25\x97\x4c\x3b\x0b\xa9\x84\xdc\xbd\xa2\xd2\x64\x42\x33\x2a\x8c\xad\xbd\xe4\x31\xd7\x12\x07\xc3\x3b\xe1\x29\x58\x4d\xee\x13\x34\x71\xe8\x20\xbe\xcf\x85\xd2\x66\x34\x0c\xfc\xd7\x2f\xb8\x9f\x29\x39\x24\xd7\xf5\x00\xcb\x9a\x2e\x0c\x65\xff\x8d\x46\x9f\x00\xda\x39\xff\xbf\xc3\xfa\xb0\x2b\x6c\x4c\xd8\x78\x06\x42\xb6\x31\x13\x3b\x71\x75\x81\x4b\x58\xdd\x19\xe2\xc7\x98\x09\xb1\xd5\x1e\x56\xc3\xb6\x38\xd4\xc1\xcb\x8a\x14\x8a\xa0\x9a\x03\xfb\x2b\xe2\x27\x98\x25\xe8\x46\x07\x51\x79\xfb\xe8\xc7\x7a\x95\x96\xf5\xb9\xf3\x21\x96\x74\xca\xee\x46\xde\xf2\x36\x53\x2b\x42\x36\x30\x98\x32\x9a\xb9\xd4\x49\xe8\x93\xe3\x41\x42\xc5\xee\x6e\xad\x8d\x02\x87\xa3\xc4\xa9\xf7\x4b\xa3\x4d\x47\xfb\x15\xd9\x73\xb5\x0e\x44\xb3\x2c\xc3\x35\x58\x6f\xdb\x46\xfc\x86\x6d\xe1\x39\x8c\x10\x6b\xce\x2b\x6f\x8c\x7b\xc9\x63\x12\x1f\x18\x67\x0b\x0f\xef\x33\x24\x93\x4a\x1b\x35\xdb\x88\xcc\x3b\x29\xda\x68\x4c\xcc\x59\x56\x90\x92\xa5\x55\x62\x8b\xfe\x40\x46\xef\x87\x5a\x01\xb6\x65\x74\x8b\x7e\x27\x22\xe8\x0e\xf6\x09\x11\xb1\x11\xc1\xa7\xb0\xa4\xc1\xf4\xe1\x53\xc2\xae\x58\xb9\x20\x85\x54\x0a\x56\x17\x2c\x1a\xcc\x7c\x07\x27\x8b\x47\x22\x84\x1d\x0c\xde\xca\x6d\x1a\x3b\x76\xd7\xd8\x01\xad\x4a\x46\x12\xe6\xf3\x18\x91\x5f\x3f\x7b\x61\x8c\xc8\xdb\x14\x80\x53\xf8\x5f\x6d\x15\xba\xff\x1e\x4f\x57\xe8\x39\xf5\xbb\x44\x9c\x73\x1f\xc3\xf1\x2b\xb0\xef\xbe\x1e\x04\xf6\xe3\xd7\xc6\xd4\xdd\x33\xef\xfa\xd5\xc0\xbc\x75\x60\x19\x7e\x15\x58\x86\xfe\x4e\xfb\x46\x4c\x45\xb6\xe1\xb1\xb0\x65\x0e\xd0\x23\xcc\x6a\x87\x36\x65\xde\xbc\x91\xd2\x56\x2f\xe0\xb9\x13\xd1\xc8\x76\xb1\x66\xba\xab\xd1\x44\xe5\x9a\x7c\x61\x54\xd3\x2f\x82\xeb\x6f\xb4\xe9\xda\x9b\x6a\x5d\x5b\xcf\x67\x5c\x69\xe8\x3f\x6f\x34\xff\xfb\xf7\x46\x6e\x1f\x4b\xef\x1a\x49\x5f\xfe\x0a\x24\x48\x4e\x8b\x7b\x8c\x83\x60\xec\x9d\x1a\x95\xbd\xb6\x51\x58\x3b\x94\x8d\x32\xa2\x23\x21\xb7\xd1\xf0\xc9\x22\x2c\x9e\x99\xb0\x4c\x22\xb4\xbd\xcd\x13\xbc\x47\x5d\x9e\xef\x0d\xa4\xb4\x2c\xe9\x8c\x3d\xb3\x8f\x7d\x2c\x3d\xc1\x7e\x42\xf4\xfb\x28\xa4\x84\xd8\x05\x16\x17\xdf\xd5\x2f\xb9\x64\x03\x90\x02\x34\x81\xd4\x7f\x20\x64\x04\x3e\x15\x14\x15\x3c\x92\xbc\x95\x16\x48\x39\x5d\xa2\xa4\xf4\x5a\x1d\x65\x54\x69\x9e\x7c\x9f\xc9\xe4\xf2\x5c\xcb\xb2\x07\xd5\x62\xd5\xa8\xd1\x9c\x0a\xb2\xff\xf3\x39\x39\xe4\xea\xb2\x6e\xb1\x84\x30\xe6\x71\xb6\x3d\xf5\x30\x7e\xb6\xf0\x92\xe4\x34\x99\xa3\x46\x6a\xfd\x1e\xae\x95\x43\x7f\x6b\xe5\x0f\xf4\x5a\x31\x7c\xfd\x89\x79\x7d\xf3\x33\x6b\x2f\x82\xd7\x06\xba\x84\x9f\x73\x7c\xb8\x86\x2c\x97\xa9\x6a\xdb\x7b\x8e\xac\x68\x08\xe2\x90\x65\xb1\x80\x30\x63\xb6\x29\x2c\xc0\x19\xc6\x4d\x3e\x80\x87\x16\xb2\x22\xd7\x14\xc3\x55\x20\x61\xc7\xe4\x82\x17\x2f\xc9\x51\x00\x97\xbf\x6a\x28\xa3\x7d\x78\xe8\x32\x9b\x20\x08\x3c\xb7\xdc\x1a\xff\x08\x55\x2b\xf5\x92\xec\xb0\x0f\xfa\x4f\x3b\x43\xb2\xf3\x61\xaa\xcc\x7f\x84\x9e\x42\x7b\x0d\xdb\xb6\xcb\xe8\x78\x62\xca\xca\xda\x22\xc4\x1b\x96\x51\x03\xfa\x67\x59\x72\xf1\xf6\xf0\xed\x4b\xd0\xe5\x53\x69\x8c\x39\xdb\xd8\xd6\x61\x60\x58\xd9\x18\x90\x01\x8a\x39\x13\x99\x17\xa5\xcc\x79\x50\xa9\x02\x4b\xae\xcd\x0a\x20\x7d\x84\x4a\xc1\x5e\x05\x66\xe8\x85\x9f\xfc\x70\x8e\xa5\x82\x13\xe2\x2e\xcc\x74\x3c\x25\x12\x83\x53\x71\xad\x1c\x57\xfe\x22\xc3\x3e\x76\x14\x6c\xd7\x5a\x33\x8c\xd1\xcc\xed\x4f\xcf\x52\x76\xf5\x4c\xa5\xf4\xc5\x10\x1e\x83\xdc\xb0\x68\xbc\x13\x55\x64\xe7\xc5\xce\x98\x9c\xf3\x9c\x67\xb4\xcc\x6c\x1f\x39\x3b\x44\x7d\x9d\x31\x14\xdc\x80\x60\xfe\x3e\xdf\x21\x7b\x58\xac\x06\xea\x46\xc6\x1c\x74\x89\x87\xea\x82\x58\xfe\xa0\x95\x76\x49\x7a\x70\x0e\x91\xce\x0e\x22\x62\x5b\xca\xbe\x15\x59\xeb\x14\x9f\x98\x39\xdc\x68\x2e\xd3\xbb\xac\x6c\x35\xed\x54\x96\xd6\x08\xf4\x97\xb8\x8a\x78\x2e\xac\xda\xf2\xc6\x4c\xfd\xfd\xdb\x38\x3e\xd4\xf6\x43\x7a\x40\x69\x21\x7e\x17\xe9\x87\xbe\x6e\x34\x08\x7f\x09\xfe\x5b\xc5\xc8\xf1\xa1\xef\xd7\xcd\x4a\xc5\x95\x36\x22\x2a\x8d\x54\x03\x8e\xfa\xc2\xde\x7e\x4e\xff\x23\x05\x39\xfa\xfe\xdc\xbe\xd6\x60\x03\x89\xdd\x52\xd2\xd1\xff\x54\x25\x33\x1a\x51\x67\xf5\xcb\x8f\xd4\x54\xb9\xcc\x79\x72\x48\x35\x45\xcd\x0b\x25\x95\xac\x51\x24\x40\xa9\x9a\x40\x76\xaf\x83\x08\x69\xa9\x3c\x93\xf5\x6b\x3f\x86\x83\x4e\xda\xc3\x4e\x9a\xdb\xdf\x9d\x1d\xaf\x41\x77\x4a\x60\xbb\x9d\xbd\x91\x69\x4f\x0a\x54\x30\xa0\xdb\xf2\x00\xd5\xeb\x00\xcf\x93\xdc\x3c\x89\x9c\x48\xc1\x86\xe4\x8c\xd1\x94\x18\xe9\x66\xff\xf9\x73\xc9\xf5\x7d\x81\x12\xea\xa3\xf3\xd6\xef\x26\xb1\x17\x42\xb8\xc1\x1c\x11\x4e\x02\x70\x1c\x40\x72\x02\xa1\x63\x75\x80\x49\x26\x27\xc4\x0a\x8b\x75\x7e\xfd\xbb\xb3\xe3\xde\x3e\xfe\xdd\xd9\xb1\xfb\x76\xf3\x4f\x39\xdd\xcc\xcf\xee\xd1\x78\xa8\x6d\x87\x57\x0d\x65\xbf\x56\xe7\x6a\x4c\xf9\xa6\x41\x70\x77\x6b\x60\xdc\x97\x1d\xb0\x2e\x9a\x5f\x72\xd1\x3a\x59\x3c\x96\x36\x80\x27\xef\xb1\x13\x82\xd8\x18\x40\xb6\xa4\x2f\x49\x5e\x65\x1a\xca\xe3\x81\xd7\x0c\xf3\x41\x86\x82\xe3\x3a\x62\xa1\xa2\x08\x39\x64\x18\x8e\x48\x5f\xba\x84\x45\x7f\xc7\xea\x1b\xde\x50\x41\x67\xe6\x72\xd8\x01\x49\x8e\x7f\x06\x4c\xbe\x87\x4e\x77\xe1\x7f\xa2\x57\x94\x67\x74\xc2\x33\xae\x41\x9f\x1b\x8c\x9d\x36\xaf\x10\x2b\xc3\xbc\xf2\xda\xa4\x5f\xaf\xaa\xad\x57\x5b\xc3\x42\x62\xc0\xc1\x21\x7b\xe6\xb7\x67\xd7\x46\xd4\x0f\xc6\x20\xf7\xe1\x42\x80\x2d\x6d\x28\xbf\x67\x9f\x52\x7e\xd7\xa2\xa7\xc2\x7c\xbf\x6a\xd9\xec\x62\x59\x77\x32\x23\xad\xd4\x9d\xe0\x07\x8b\x4e\xf5\xc4\xd5\x27\x6c\x38\xda\x41\x81\x82\xb5\xd3\xf2\xfe\xae\x2a\xd4\xc3\x2c\x9c\xf4\xe9\x2d\x1c\x82\x6d\x81\xec\x4c\xf7\x42\xae\x7a\x38\xa7\x6b\x78\x14\x42\xfc\xa9\x51\x67\x85\x2b\xeb\xdc\xca\x72\x87\x4e\x08\xf7\x9b\xf5\xd4\xa6\x0a\x13\x8f\xce\xe2\xd7\x73\x70\x3f\x74\x71\xa3\x39\xb2\xe0\x26\x05\xa7\x49\xeb\x75\xd6\xf1\x33\x13\x56\xcc\xa7\xdd\xb3\x29\xcd\x30\xaf\xce\xe3\xa8\xcd\x01\x2b\xe6\xe4\xd5\xf9\x0a\x31\x89\x99\xac\xe6\xbb\x15\xc6\x72\x76\x15\xc9\xf8\x94\x69\xde\x8a\x08\x6b\x16\x94\xb9\x14\x5c\xcb\x52\xad\xa3\x96\xd4\x3e\xba\x1f\xc5\xcd\x8d\x66\xf8\xf3\xcc\x11\x85\xbc\x09\xce\x52\x92\xc8\x2c\x63\x89\xcb\x2f\x85\x29\xf6\xb7\xad\x70\xc4\xd8\x0c\x04\x35\xbe\xfc\x06\x5c\x31\xd6\xe9\xf2\x0c\xd9\xee\xd9\xd9\xd1\xfe\xe1\x9b\xa3\x71\x9e\xfe\x61\x2e\xaf\x47\x5a\x8e\x2a\xc5\x46\x5c\x77\xd3\xb7\xd6\x58\x78\xda\x83\xa7\x5b\xcf\xfb\x72\x72\xeb\xb9\x99\xb2\x1a\xfd\xf0\x9d\xaa\xf1\x49\x5d\xdc\xb9\x94\x52\x2f\x23\x94\x4e\xab\x2c\xc3\xb9\xd5\x25\x63\xc3\xd0\xbf\x7d\x4f\xfc\xd6\xfa\xd8\x2c\x5d\xb8\x76\xf3\x46\x24\x7a\x58\xcd\x78\x53\x16\x48\x77\x5d\xa1\xad\xa6\x4d\x96\xe6\xa1\x1e\x2f\x9e\x89\xf3\xe8\x3c\x06\x44\xf4\xdc\xcc\xcb\x25\x5b\x10\xa8\x31\x9c\xca\x12\xf0\xbe\x63\xfe\x64\x3a\x01\xe2\x3d\x83\xe6\xda\x56\xe1\xd8\x10\xc2\x77\x51\x45\xe0\x43\xce\xd8\xb4\x4f\xb2\x9f\xb1\xe9\x2a\xaa\xdb\xd3\x00\x8a\xe6\xd3\xe3\x8c\xbe\x52\xe9\x39\xa6\xbc\x22\x18\x23\xd2\x76\xe5\x34\xd8\x22\xd1\x0d\xa1\x7b\xa7\xf2\xbe\x3e\x4a\xd0\xbb\xb4\x12\x22\x4b\x93\x17\xba\x2d\xed\x24\xe9\x7b\x87\x41\xe4\x95\xb1\x62\xd9\xf5\xb3\x6b\x59\x5e\x72\x31\x1b\x5d\x73\x3d\x1f\x21\xa5\xd4\x33\x80\x86\x7d\xf6\x07\xf8\x8f\x8d\x22\xef\xa7\xa9\xcd\x7f\xab\x14\x9b\x56\x19\x66\xa6\xa9\x31\xa1\x05\xff\x89\x95\x0a\xb2\x2c\x2f\xb9\x48\x87\xa4\xe2\xe9\x77\x6d\x67\x8c\xf4\xb1\x5a\xda\xb7\x76\x6d\xd2\xba\xb2\xdd\x5d\x65\xb8\x8d\x96\x4e\x26\x95\x34\x95\x0a\x1b\x04\x18\x52\x45\x4b\x80\xa6\x39\x17\x9b\xb2\x02\xda\x5a\x07\x5c\xa4\xed\x28\xd9\x08\x40\xc0\x38\xb1\x79\x60\xcf\xd9\x30\xb6\xcf\xf9\xa1\xce\x7b\x82\x1d\x40\x6d\xf6\x4f\x9c\xfb\x73\x27\xc1\x92\x2f\xd4\x6f\xd9\x08\x9f\x32\x2a\xd2\x9a\xae\xdb\x44\x9e\xfb\x1c\x9f\x2f\x91\xa7\x5f\x87\xfc\x67\x48\xcf\x79\x50\x8e\x23\x1b\xac\x33\x3f\xac\x1f\x6c\x8d\xa4\xee\xae\x19\x3f\x8c\x86\x56\xef\x3e\xd0\xbc\x46\x39\x44\x15\x50\xc0\x50\x2a\x39\x7f\x1a\xf6\x43\xf6\xdd\x12\x5c\x85\x71\x22\x85\xb0\x40\xba\x6f\x0b\x26\xce\x35\x4d\x2e\x3b\x46\x75\xb7\x5a\xd5\xef\x4c\xab\x7a\xa0\x44\x20\xc7\xa2\x58\x4f\x67\xd3\xdf\xea\x64\x6f\x5c\xe4\x8f\x50\x00\x63\x57\x98\x37\xb4\xe8\xee\x5d\x75\x23\x35\x34\x28\x7f\xda\x3a\x54\xa1\x38\xa8\x90\x45\x95\x21\x4c\x2c\x57\x96\x8e\x9f\x5f\xe3\xe9\xba\xbe\xed\x16\xd3\x5f\x0e\x4c\x30\x60\x2c\x51\x73\x73\x66\xc2\x75\x2d\x2b\x15\xd3\x08\x3f\x62\xb1\xf4\xa4\x20\x89\x2d\x31\x06\x7d\xc4\xe8\x1e\x76\xb8\x40\x57\x11\x44\x26\xda\x15\x83\x7a\xa4\x92\xe7\xcf\x9f\x3f\x47\xf4\x85\xff\xfa\xaf\xff\x22\xb2\x84\xa6\x55\x09\xcf\x97\x2f\x84\xab\xfe\xfc\xe2\xc5\x98\xfc\x63\xff\xcd\x6b\xa8\x68\x28\xb4\xc2\x56\x26\x38\xb2\xb9\x20\xba\x59\x0d\xc9\xff\x3e\x7f\x7b\x52\x57\x05\xc7\xbf\x82\x69\xee\x3f\x2f\x06\x90\x7e\xfe\x97\x3f\xfd\x69\x4c\x0e\x79\x09\x15\x5d\x9c\xf9\xe6\xa4\xde\xd5\x42\x4b\x86\x68\x11\x50\xb7\xef\x34\x2e\xee\xfb\x00\x59\x08\x28\x6c\xdf\x8c\x85\xae\x86\x21\x33\x9e\x68\x2c\x1e\x43\xb1\xe6\x7a\x9f\x22\xf6\xb4\x45\x73\xb7\xda\x1f\xbc\xdc\x90\x64\xfc\x92\x91\xa9\x82\xb6\xe8\x35\x1e\x90\xed\xd8\x67\x0b\x65\x70\xb0\x7a\xae\x14\xd3\x8f\x3c\x6d\xb5\x93\xab\x39\xe2\x6d\x18\xa9\xa1\xb0\xda\xf2\xd6\x4b\xb6\x18\x21\x9f\x15\x94\xfb\x62\x18\xc8\x00\x8c\x9a\x45\x79\x5f\x4f\x4a\x0e\xbc\x54\x71\x75\xee\x45\x29\xff\x8d\x2c\x00\x25\xc6\x81\x78\x86\x12\x60\x98\x49\x5b\x00\x1c\x44\xb7\x5c\x99\xb4\xed\x4e\xea\x4e\x5b\xc8\xf3\xe5\xbe\x11\x19\x57\xe6\x11\x00\x30\x71\xcb\x93\xeb\xa6\x77\x86\x4b\x15\xf2\x4b\x25\x96\xee\xb6\xc5\xfc\x56\x5c\xda\x6e\x51\x16\xba\xaf\x1e\x03\x71\x8c\x2c\xf6\x82\xbd\xd6\x51\xc9\x13\x22\xca\xb7\x56\x4c\x57\x96\x34\x90\x45\x6f\x9e\x0d\x9d\x8c\xe0\x0b\x73\x5a\x5e\x1a\xc3\xd5\x4a\x97\x31\x39\x35\x2f\xe9\xe1\x1b\x10\x15\xef\x0a\x03\x9b\x39\x5d\xc0\x63\xad\xe2\x06\x0f\xd9\x1d\x8f\x77\x71\xf9\xc9\x92\x28\x4d\x4b\xbb\x96\xcc\xf9\xa7\x01\xc7\xf9\x86\x16\x0a\xe1\xe1\x8c\xa6\x0a\xd0\x89\x12\x4a\xd2\xf5\xbc\xee\x8f\x8c\xb4\xde\x42\x68\x92\x11\x10\xa6\xf5\x00\x1b\x0e\x9f\x69\x67\xdf\xae\xf2\x8d\xc0\x76\xcc\x3b\x28\x1c\x78\x34\x63\xaa\x69\x23\xb2\x71\x27\x7d\xc3\xb6\x0f\xc8\xd8\xa3\x52\x30\x56\xb7\x0b\xb3\x82\x33\x54\xc0\xe2\x1e\xe7\x8f\x55\x8f\xc0\xa3\x0f\x6d\x02\x8f\xee\x3a\x05\x1e\x5d\x82\xc8\x78\x44\x3c\xec\x22\xc9\x48\x4c\xbb\x81\xe1\x1e\x35\xad\xa7\x00\x9a\xba\x14\xc1\xb2\xc6\x0e\x68\xae\x93\x9f\x20\x74\xa2\x64\x56\x69\xbc\xb5\xfe\x31\xdc\xfd\x60\x50\x07\x2e\x09\x5b\x9e\xbf\x2c\xd8\x0b\x41\x0b\xc0\xed\xa3\xcb\xb6\x88\x47\x67\xb1\xd1\xc5\x09\xf1\x3b\x72\x40\x74\xa6\xb3\x37\xd8\xfa\xa0\xb5\x1b\xcc\x57\xdc\x5d\xcf\x99\x4d\x81\x08\xf4\x3e\x23\x4d\x8d\x8c\x00\xa5\xd2\xa9\x70\x88\x87\x93\xae\xc5\xcd\x98\x28\xde\xdd\x97\xa0\x38\xd9\xf3\x7d\xd5\x7d\xda\xdd\xb1\xd0\xac\x9c\xd2\x84\x0d\x42\x1f\x03\x2b\xe6\x2c\x67\xa5\x21\x94\xbd\xce\xd5\x68\xcf\xa9\x48\x33\x0b\x5c\xc0\x4a\x58\xc1\xec\x83\x66\xa5\x21\xea\xc1\xf9\x31\x49\x4b\x7e\xc5\x4a\x45\xf6\xbe\x67\xc6\xd6\x40\x18\xaa\xc1\x23\x4c\x83\xc5\x0f\x59\x87\x07\x04\x1e\xdc\x4f\xe9\x07\x0c\xb5\xaa\x25\x74\x3d\x55\x0e\xf2\xca\x4c\xab\x0a\x7d\x47\x63\xb3\x20\x60\x0b\x05\xe9\x0b\xad\x0f\x31\xb6\xe9\x3a\xfd\x42\x87\x86\x44\xe3\xc0\x54\xd9\xce\xbf\x00\x87\x63\x05\xbb\x85\x49\x59\x5b\x71\x43\xff\x05\x25\x75\xb0\xea\xb6\xda\x8f\xa9\xb5\x2b\xe5\x15\x4f\x9d\x3a\x04\xa9\x11\x35\xe8\x5f\x41\x55\x00\x5e\x40\x95\x92\xb6\x9f\x79\x30\x35\x68\xa5\x82\xd2\x14\xf7\xcc\x70\xe1\xe6\x30\x4c\x26\x01\x79\xbe\x55\xc3\x2e\xd2\xcb\x86\x28\x53\x76\x5a\x4d\x32\xae\xe6\xe7\xbd\x86\x44\x56\x0d\x8c\x49\x89\x4b\x99\x2a\x37\x46\x46\x14\x13\x8a\xdb\xfe\xaa\xa8\x6e\x71\xa3\x6d\x4b\x98\x06\x77\x77\xb8\x28\x24\x54\xc3\x43\xd7\x56\xf7\xd3\x49\xfd\x1e\x16\xac\x04\xdb\x05\xa6\xec\x9d\x28\xa2\xf3\x09\xcd\x32\x65\xf5\x5b\x0f\x86\xed\xf6\x1e\xd4\x50\x1d\x80\x09\x72\x05\x37\x0c\xe3\xde\x1e\x52\x70\x50\x78\x79\xe4\xf6\x95\x1f\xa6\x02\x88\x4b\x29\xdc\x45\xd0\xf5\xd0\xdd\xe0\x29\x84\x95\x38\xc8\x74\x6b\xc4\xcc\xde\x86\x7f\x1e\x5f\xf8\xe7\x61\x6a\x2a\xea\x5e\x54\x14\x4e\x8e\xa0\x42\xcb\x75\xd4\xa7\x1e\xd9\xa0\xb6\x24\xc7\x9f\x4a\xd3\x5c\x5b\x08\x18\xdf\x6f\x5f\x5b\xfc\xf3\x7e\xbc\xbb\xcd\x41\x41\x15\x33\xa6\x38\x48\xa8\x91\xa5\x5f\x12\x2c\x29\x6b\x23\xfb\x75\xbe\x2c\xd7\xea\x3d\x1d\xb6\x73\x3c\xb9\xab\x48\x2a\x93\xca\x18\x5f\x35\xd9\xeb\x84\x8b\x6e\x6d\x6d\x9e\x16\xce\x7e\x2a\xaf\xc5\x35\x2d\xd3\xfd\xd3\x56\xb5\xb9\xb1\x72\x56\x8f\x15\xaa\xde\xee\x34\x31\xe7\xe9\x44\x56\xda\x63\x1b\x6e\xa3\x7d\x2b\x87\x08\xa5\xf9\x2a\x77\x9b\x96\x46\xc8\xde\x31\x9a\x77\x5f\x87\xdd\x36\x40\xb8\x0d\x10\x46\xc7\x26\x05\x08\x8f\x31\x40\x18\xb6\x84\x8b\xc4\x8b\xf5\xd0\x1a\x8a\x3f\x89\x18\xd3\x61\x2d\x52\x51\x13\x6f\xd6\xf3\x36\x94\x7f\x5c\xbc\x35\xd7\x05\x06\x83\x93\xb9\xa0\x97\x3d\x85\x78\xd4\x06\xc4\x93\x80\x96\x1d\xac\x42\x3c\x62\x81\x5f\xd7\xab\x21\x4a\x2d\x06\xa6\x83\x08\x77\x21\xd3\x97\x08\x1a\x0b\x40\xef\xd8\x9c\x6c\x68\x61\xbf\x87\xd6\x77\x21\x52\xf8\x87\x2a\x68\xc2\x40\xbe\x79\xf5\xa7\x97\x20\x41\x47\x06\x20\x3d\x31\x01\x01\x46\x00\xea\x9c\x76\xe1\x06\xd2\x1b\x47\x98\xa3\xb6\x78\xba\x8e\xd4\x44\x14\xc5\x51\x1d\x23\xa8\x64\xce\x72\x0a\xff\x7c\xe5\x48\x60\x64\xa3\x31\x1e\x34\x43\x08\x38\x56\xe6\x8a\xc8\xe9\x30\xca\x74\xdd\xb9\x7a\xb1\xd3\x2d\xd8\x40\xfa\x8b\x53\x12\xb7\x8e\x4e\x3b\x07\x7b\x48\x93\x60\xa7\x51\x6c\xc7\xac\x21\xd0\x79\xcc\xb2\xf2\x70\xf6\x3e\x83\x02\xf6\x0f\xa4\xf0\xc6\x10\xa7\xef\x20\x6e\xdb\xe0\xed\xd0\x47\x0d\x1e\x81\xf2\xb7\x0d\xde\x3e\xc5\xe0\x6d\xb0\x31\x3a\x41\xb7\x22\x90\x1b\x86\x04\x5c\x34\x77\xc2\x9c\x51\x63\x6d\x18\x17\xca\x75\x71\x5c\x59\xc6\xa9\x4b\xbb\xe3\xf1\xee\xae\x8b\xee\x5a\xbe\xaf\xf4\x74\xf4\x0d\x61\x22\x91\x29\x32\x8b\x19\xbf\x54\x1a\xd4\xbd\xda\xdd\x16\xbe\x4b\xee\x9e\x15\xa6\x3f\xc1\xd8\x7d\x4c\x75\x67\xd9\xe2\x20\x09\x5f\x3d\x80\x12\x53\xab\x2e\x1e\xf8\xd0\x92\xc8\xe3\x59\x5b\x1d\xc6\xfd\xae\x48\xc6\x73\x6e\x1b\xa5\x9a\x85\xce\x94\x56\x64\x0f\x4f\x8e\x93\xa2\x1a\xda\x0b\xc6\x39\xcb\x65\xb9\x18\xfa\x8b\xcc\x8f\xd1\x5d\xf6\x8a\x01\xb6\x31\xa9\xca\x92\x09\x9d\x2d\x9e\xb2\x06\xe4\x88\xb8\x21\x0a\x90\x9f\xe3\x2e\x88\x23\xf5\x11\xb3\x56\x1d\xf1\x05\xb7\x79\xd0\x5f\xc0\xa3\xd1\xaa\x61\x1d\x17\x37\x67\x99\xb8\x22\x57\xb4\xbc\x27\x72\xfc\xaa\xa3\x47\x9d\x27\xe5\x57\x5c\x75\xed\x62\x4c\x9a\xe4\x39\xf7\x4e\x68\xb3\xd8\x64\xa5\x8b\x4a\x5b\x89\xee\x56\xa0\x43\x19\xf7\x2b\xaf\xa1\x1c\xbe\x68\xd3\x5d\x29\x3e\x0a\xaa\x35\x2b\xc5\x4b\xf2\x3f\x7b\xef\xbf\xfc\x38\x1a\x7c\xb7\xb7\xf7\xcb\xf3\xd1\x5f\x7f\xfd\x72\xef\xfd\x18\xfe\xf1\xc5\xe0\xbb\xc1\x47\xf7\xc7\x97\x83\xc1\xde\xde\x2f\x3f\xbe\xf9\xe1\xe2\xf4\xe8\x57\x3e\xf8\xf8\x8b\xa8\xf2\x4b\xfc\xeb\xe3\xde\x2f\xec\xe8\xd7\x3b\x0e\x32\x18\x7c\xf7\xc7\xce\xaf\x4e\xc5\xe2\x6d\x47\x51\x88\xc7\xa8\xc7\x2d\x39\x1e\xb1\x17\xf6\x6b\xb4\x95\xe0\x42\x8f\x64\x39\xc2\xa1\x5f\x02\x58\x70\xc7\x07\x38\xf6\xea\x7b\xfd\xd7\x6a\x40\x0d\xb7\xef\x94\xfa\x35\x2f\x70\x08\x7d\x1e\xf2\x1e\xca\x8c\xdd\x48\x71\x99\x8c\x66\x79\x21\x4b\x5a\x2e\x48\x6a\xbd\x99\x8b\x15\x08\x44\x01\x04\x51\x67\x48\x61\x78\x8f\x94\x97\x6b\xa8\x34\xee\x8c\x28\xc4\x52\x5e\xe5\x3d\xe1\x09\xc1\x58\xe1\x64\x5c\x03\xf2\xbe\x45\xed\x77\x29\x45\xf6\x32\x1b\xd0\x98\xd0\xe4\x12\x2d\x28\x3f\x5b\xa8\x37\x06\xa5\xf5\x3b\x3b\x36\x25\x22\x67\x54\x78\xc7\xbe\xeb\x38\x66\xa6\xd2\x5d\x8c\x63\x47\x4e\x78\x8c\xb4\xdb\x04\xc2\xba\x23\x95\x2c\xc9\x1b\x50\x80\xd6\x3a\xfb\xa4\x17\xac\x10\xfe\x1f\xf6\xda\x68\x7d\x3d\x55\xa2\xba\xe1\x5c\x02\x91\x96\x60\x6f\x5a\x5c\xaf\x29\x34\xd9\xaa\x33\xc4\x22\xcd\x02\x26\xf2\xc8\x2d\x4b\x17\xbf\x35\xd3\x69\x46\x45\xdd\x14\x1c\xd3\x99\xc2\xbc\x15\x9e\x40\x1f\x28\xb0\x4d\x61\x3a\xfc\x14\x5e\x04\xcd\xa1\x2b\x65\x9e\x24\x45\x7c\x4d\xfd\x20\x6c\x93\x35\x41\x9e\x70\x1d\x5d\x63\x8b\xda\xfc\x72\xee\xbf\xac\xf6\x67\x40\xc9\xb2\x33\x3f\x55\x05\x46\x8a\x7d\x8a\x55\xb5\xe5\x14\x32\x2b\x82\x7e\x3d\xae\x25\xcd\x12\xa3\x0a\x9e\xc5\x9c\xea\x3a\x4f\xf8\x0f\xaf\x84\x4d\x28\x5c\x62\xbb\xd5\x5c\x57\x29\x56\x8e\x66\x15\x4f\xfb\xe3\xb7\x47\xa7\x76\x74\x54\x36\xfa\x52\x31\x7a\x51\x2c\x7a\x57\x27\x7c\xca\x66\xf7\x0e\xc9\x75\xf6\x67\xb4\x9f\x86\xcd\x31\xe2\x4c\x50\xea\xfb\xa1\x39\x61\xe0\xd2\x0d\x2e\xbc\x2b\xc9\xee\xb3\xc9\x22\xb1\xd0\x4e\x3c\x6a\xdd\x83\xc3\xe2\x9a\x80\xa2\xaa\x91\x6f\x95\x5a\x3b\x24\xc8\x84\x4d\x31\xe3\x09\xef\x01\x4f\x81\x2d\x05\x4b\x59\xc6\x34\x0b\x7a\x1c\x17\xd8\x95\xb5\x64\xb9\xbc\x32\xcb\xec\xbd\x20\xef\x94\x8d\x97\xf3\xe9\x4b\x42\x07\x51\xc1\xb1\x42\x03\x5b\x30\x96\x62\x7d\x58\xd0\x54\xb0\xac\x84\x1a\x92\xc9\xc0\xe5\xb3\x2a\xec\x1e\x5a\x82\x53\xcd\x76\xf7\x02\x3f\x56\xc9\x0c\x01\x00\xa4\xaa\x94\x39\x51\x82\x16\x6a\x2e\x35\xb8\x4c\x68\x41\x13\xae\x17\x44\x97\x34\xb9\x34\x97\x40\x1c\x15\x1e\x37\x24\xc9\xc0\xa6\xb7\x87\xe4\x8b\x4b\xd6\xf4\xbc\x94\xd5\x6c\x0e\x35\x54\x78\x55\x92\x51\xe5\xbe\x7e\xe5\xfd\xd6\x86\x57\x24\x5d\x08\x9a\xf3\xc4\xf7\x0e\x29\xe5\x15\x57\x5c\xda\x48\x97\x1b\xf7\xd4\x77\x61\xc0\xe8\xd9\x41\x46\x79\x4e\xf6\x14\x63\xe4\xc8\xb1\x04\xfe\x72\x8e\x9a\x24\x7a\x12\xcb\x38\xa9\xce\x02\x3e\x5a\xe0\x01\x73\xa6\x16\xbd\x3e\x55\x01\x95\x01\xf3\xe6\x2b\x1f\x3a\xf0\xd3\xb5\xfa\x9d\x64\x09\x09\x6f\xae\x05\x10\x13\xa9\x0c\x32\x62\xf6\x4f\x8f\x55\x68\xdf\xda\x36\x8a\x38\x12\xfc\x90\x49\x31\x0b\x81\xef\x6a\xce\x34\x42\x5e\x40\x3f\xcc\x2b\x9e\x56\x34\x43\xf1\x6e\x5f\xe6\xe0\xfc\x18\x6f\xe7\xb3\xb9\x1e\x5d\x33\xf0\x7e\xe2\x2e\x58\xaf\x19\xf7\x50\xbe\x94\x69\xcb\x15\x6c\x07\xda\x7a\xd9\xd0\x93\x0c\x3d\x27\xe9\x02\x80\x77\x6d\x72\x67\x94\x8c\xe3\x60\xea\x71\x88\x55\x14\x87\xd7\xdb\xf7\x0d\x12\x8d\x4a\x04\xee\x61\x43\x62\xe0\xd4\xe5\x77\x83\x6e\x8f\x75\xcf\x0d\x7f\x5a\xd7\x9d\x1f\x41\x21\x6e\xdf\x39\x78\x6d\x8a\xec\x55\xcd\x26\x17\x2c\x2f\x32\xaa\xfb\x49\x2d\xd9\xf9\x39\x70\x7f\x07\xc1\x63\xb3\x1c\xa9\x48\x47\x34\x33\x1c\x79\xfa\xd3\x81\xad\x6c\xc3\x05\x16\xa5\xaf\x5d\xd4\x3d\x4a\x51\x39\x40\x2d\x69\xe5\xd2\x02\x2c\xb5\x09\x4b\x41\x18\xd9\x27\x83\x8f\xe2\x5a\x60\xeb\x5f\xf3\xc7\xe9\x4f\x07\x43\xc2\xc7\x6c\xec\xfe\xf2\x97\x3a\x69\xa8\xe5\x0c\x0b\x1c\x7c\x05\x0d\xf0\x33\x76\xe1\x0e\x9c\xbf\xe1\xbd\xff\xfa\xd6\xbc\xa4\xf9\xf5\x6f\xa3\x6f\x83\x5e\x46\x7f\xfb\x97\x11\xae\xa5\xb9\x20\x3e\x1b\xe6\x97\x83\xdc\x33\x7f\xfd\xeb\x54\xa6\xe7\x05\x4b\xc6\xf8\x59\xea\x5f\x98\x25\x40\x98\xd0\x46\xd7\x3e\x95\x90\x59\xc6\x53\xe4\x72\x78\x76\xc9\xfe\xed\x02\x04\xb6\x5d\xaa\x15\x24\x09\xd5\x4c\xc0\x06\xe0\x0a\x8d\x85\xd4\x78\x3b\x36\x5a\x85\xf7\xdf\x9b\x86\xad\x4f\xb5\x94\xb0\xcc\x51\x94\xec\x0b\xc2\x3e\x70\x05\xb8\x33\xf8\xad\x40\x0e\x6a\x93\xd7\xdd\x9e\x66\x86\x35\x14\xf6\x30\x43\xd8\x3d\x3c\xcb\xc8\x17\x42\xea\x2f\xfc\xf4\xbb\xc4\x44\xd8\xb8\x24\xa1\x57\x92\xa7\xa4\x82\xbe\x59\x66\x05\x0a\xf0\x6c\xd7\xad\x0b\x27\x0b\x92\x73\xa5\xe9\x25\x1b\x93\x73\xb3\x67\x85\x19\x06\x48\x3d\x41\xa0\x0b\x0d\x4b\x49\x25\x34\xcf\xe0\xd7\x7a\x1c\xf3\xca\xe1\x5e\x76\x3c\x25\xaa\x4a\xa0\x39\x6f\xc9\x46\x6e\x77\xb4\x57\x2d\xc9\x98\xfa\x5b\x86\x7e\xb2\xe7\x14\xed\xa7\x22\x85\x5b\xb1\xd5\xaf\xb0\xec\xb5\x94\x57\x6d\xde\x53\x8a\xa4\xde\x11\x81\x98\xd0\x35\xdb\x6c\x82\x99\x4b\x00\x42\x53\xce\x06\x0c\x04\x4b\x98\x52\xb4\x5c\x60\x37\x54\xee\x9b\x36\xda\x94\x57\xd8\xa9\x73\x2a\x2a\x18\xa0\x64\xd8\x5b\xb7\x4a\x80\x3a\x94\x4c\x4a\x79\xc9\x84\x2f\x21\xf0\x0d\xd2\x7d\x42\x75\x9d\x35\x0a\xf1\x7b\x49\x92\x39\x15\x33\x56\x57\x91\xe7\x34\x05\xda\xff\xe8\x35\x2d\xf7\x3d\x86\x02\x74\x6a\x14\x16\xae\x81\x14\x13\xb3\x3f\xf9\xb0\xc7\x7b\xe1\x71\x70\x87\x75\x5c\xc2\x7c\x12\xcf\x5a\xc9\x44\xd2\x8f\x23\xbc\xbb\x0b\x7c\x04\x0a\xc5\x1a\x93\xb7\x73\xa6\x69\x4a\x35\xed\x2d\x81\xfb\x0d\xf5\x5d\x3f\x6d\x52\x07\xb0\x43\x90\xec\x61\xf7\x58\xa7\x4a\xca\x82\x87\xb8\x02\x20\x0d\xe6\x6e\xf6\x01\x97\x4a\x1b\xbe\xb6\x41\x47\xcc\xcb\x06\x5d\x8d\x66\x99\xbc\xb6\x48\x75\x6e\x34\x14\x59\x2c\x25\x69\x05\x6a\x5f\x2d\xd2\xba\x04\xc5\x7b\x89\x99\x98\x89\xee\x8d\xca\x17\x75\xec\x3f\x89\x73\xb3\x57\x2a\x68\xb8\xd7\x31\xa1\x39\xb6\xc6\x77\x40\x10\x96\xf8\x95\xc0\xa5\xda\x98\x06\x98\xa7\x19\xd3\xaa\xce\xaa\xc4\xdd\xc4\x88\x48\xbb\x97\x5b\x27\x02\x6c\x35\x76\x6a\xac\x1d\xbe\x5a\x53\xc4\x89\x53\xd2\xee\x16\x66\xff\x5a\xfb\xcc\xf4\x17\x3c\xc2\xf6\xb7\x6f\x64\xda\x3d\x0a\xd5\xe8\xe3\x5a\x0f\x5c\x57\x9b\x60\xe5\x91\x02\x27\x0f\x5e\x00\x31\x79\x15\xc1\x64\xe0\x16\x30\xa7\x57\xed\xdd\xa9\xb5\x66\x3a\xf2\xcd\xda\xe0\x71\x23\x78\xdc\xe8\x45\x57\xc7\x75\xf7\xac\x45\x77\x74\xcc\x5e\x8c\x5f\xa8\x87\x48\x85\x11\xad\xe7\xbd\x04\x12\x1a\x28\x4a\x7e\x5c\xbb\xff\xda\xcc\x0c\x9f\x0d\x63\xeb\x69\x19\x37\x52\xf3\x25\xf9\x22\xd2\xb8\xac\x66\xeb\xad\x61\xac\x62\xda\x73\xe6\xf1\xd8\x4e\xbc\x83\xf3\x8a\x2f\x1f\x34\x06\x03\x55\x6f\xb5\xd5\xe8\xaa\xa5\xbc\xfa\x6d\x54\x65\xe8\xc3\xef\x6b\x54\x0d\x33\x97\x32\xcb\x5c\xef\x76\xb4\x90\x1b\xb9\x4d\xd0\x37\x08\xa3\x25\x43\xef\x86\xf0\xfa\xbe\x60\xd7\x5e\xb1\xa3\x0a\xe1\x4a\x5d\xac\x1e\x5c\x25\x2e\xe1\x6c\xd5\x78\xbe\xa2\x6b\x5f\x2c\xf0\xd5\x0f\x03\xd2\xa2\x7b\x81\xcc\xcc\x83\x8c\x05\x20\xe8\x24\xc3\x8c\x1c\xaf\xf8\xc0\xbb\xd0\xec\x9a\x2e\x14\xac\xb2\xda\x62\xf3\xcf\xb7\x58\xef\xf5\xc0\x67\x6c\xda\xa1\x9f\x7c\x78\xf4\x16\xcd\xef\x2f\x9e\x0f\x60\x2b\x5c\xb4\x4f\xd2\xad\x87\x69\xd1\x82\xbb\x79\xf4\x97\x16\x00\x99\x91\x90\x16\xd5\x47\x7c\x35\x5a\xce\xfb\xa7\xc7\x30\xb0\xb3\xdc\x66\xf0\x87\xdb\xd1\x7d\xa0\x70\xc2\xcc\x7a\xab\x21\xa2\x80\x77\xc3\x7b\x57\xe4\x8d\xd5\x4c\xff\x23\xf4\x43\xb2\xf1\x17\x57\x0f\x6c\x36\x84\xfd\xd3\x63\x7c\xe2\x18\x5a\xe2\x52\xb1\xb0\xba\x96\x9e\xf3\x32\x1d\x15\xb4\xd4\x0b\x74\x5e\x0c\xa3\xa7\xf9\xa2\xc8\x1e\xc8\xd1\x6b\x68\xb8\x4b\x0b\xb5\xf0\x88\xe6\x08\xc8\xe7\x02\x2f\x36\x72\x76\xe3\xcc\x6c\x1a\x45\xba\x96\x68\xba\x23\xa2\x48\xd8\x42\xc7\xf9\x2e\x1e\x05\x45\xd2\x50\x10\x3f\xd4\xbe\x6c\x64\xbc\x8a\xd3\x59\x70\x9b\x05\x1d\xda\xfa\x9b\x64\x58\x37\xe6\x75\x36\x30\xfe\xcd\x48\x43\xc2\xa7\x66\x83\x93\x62\x64\xab\xd5\xbd\x73\xdc\xea\x7d\x2e\xef\x13\x0d\x79\xb3\x74\xd1\xfd\x19\x3e\x2b\x1c\xc0\xaf\x75\xb2\x27\xa4\xc0\xf5\x8f\xd7\x0e\x30\xed\xf5\x06\xff\x2e\x5c\x32\x26\x3f\xcf\x99\x08\x37\xbf\xd0\x21\x3e\xf4\x9b\x30\x17\xa9\x99\x7c\xd8\x19\xc1\x1f\xa0\xaa\x24\x61\xcc\x7b\x90\xc2\x76\xf1\xb5\x7c\xb2\xaf\x9c\x53\x9d\xcc\x99\x22\x4a\x02\xec\xa8\xd2\x34\xcb\x6a\xcf\x8d\x25\x97\x04\x3d\xc2\x79\xd1\x03\xf5\x22\x2a\xf2\xb6\x4e\xac\x22\xa3\xd6\x53\x32\xad\x44\x82\x89\x55\x5c\x2f\xdc\x1b\x1c\x36\x55\x29\x30\x57\x15\x3a\x74\xf8\x14\x7d\xb7\x81\xd9\xe9\x89\x09\x02\x76\x81\x22\x35\xde\xf9\x2d\xb6\x9e\x91\xa6\x13\x9a\x5c\x5e\xd3\x32\x55\x50\xbf\x4e\x35\xc7\x16\x87\xc3\x68\xd8\xbd\xe0\x1d\xcc\xd3\x23\x4d\x61\xe0\x8d\x5b\xc5\x7c\x2b\xbb\xfa\x31\x84\x56\x5a\xe6\x54\xf3\x04\xdc\x36\x7c\x1a\x78\xe2\x73\xdf\x02\xc2\x47\x52\x51\xb2\xc3\x5e\x61\x3f\x03\x2c\xb8\x12\xcb\x2c\xf4\xb5\x24\x3c\x37\x1a\x18\x85\xd6\xcf\x53\x5f\xad\xee\x62\x06\xb7\xbd\xa9\x51\x33\x7f\x86\x40\x4d\x70\x15\x3a\x84\x8c\xa9\xae\x60\x78\x1f\x15\xf0\xee\x70\x5b\x96\x3d\x6c\x28\x48\xf6\x1e\xc3\xd3\xe6\x5d\x03\x56\x1d\x9a\xe9\xb9\x66\x46\xef\x52\xb7\x32\xac\x1a\xaf\x7a\x23\x3e\x13\x58\xb8\xcb\x95\x73\x21\xd8\x4c\xec\xbd\xb4\x94\x45\x61\x9d\x81\xf9\xa0\xf9\x46\x10\x7b\x2b\xaf\x98\x82\xb8\xb3\xcb\xed\x36\x64\x98\x31\xc1\x4a\xaa\xc1\x93\x6f\xe1\x08\x61\xe5\x36\x1f\x11\x2d\x98\x31\x82\xb2\x0c\xc8\x3b\xdb\xe0\xdf\x33\xae\xcf\x14\xbf\x93\x62\x8a\x9e\x45\xab\x9b\x6e\x35\xca\x5b\x87\xd9\x6a\x94\x5b\x8d\xb2\xc5\xb1\xd5\x28\x9b\xc7\x56\xa3\x0c\x0f\x9f\x8c\xdc\xaf\x36\x59\x57\x17\x04\x89\x1f\x61\x2a\x55\x7d\xc1\x4d\x2e\xbf\xe3\x29\x39\x63\x89\xbc\x62\x25\x6e\x22\x47\x1f\x0a\x2a\x8c\xae\xf4\x8a\xf2\xcc\x6c\x21\x6e\x2b\xa9\xdd\x1b\xd0\x47\x27\x76\xb1\x07\x1e\x25\x3f\x1f\x76\xb1\xe6\xf6\xa5\x2c\xd2\x85\xb9\xde\x06\xf2\x8b\x92\x5d\x71\x59\x29\x97\xf0\x55\x69\x14\x16\x4a\x5b\x7d\x66\xce\x67\xbe\xdd\x9d\x4f\xc7\x28\x59\x22\xcb\xb4\x86\xac\x52\x9a\xea\x4a\xc5\x35\xa4\x09\xfa\xb4\xfb\x73\x67\x7a\x3a\x6e\xd0\xee\xd9\xe7\x3e\x83\x19\x73\xbd\xaf\xd7\xdd\xd7\x98\x89\x87\x27\x27\x96\x0d\x5d\x72\x60\x9d\x98\x68\x54\xdf\x4a\xb3\x80\x5d\x2d\x63\xdd\x7b\x0e\x23\x3c\x9a\x67\xd8\x3c\x7c\xe4\x87\x1d\xd5\xb9\x80\xad\xfb\x23\x86\x47\x8f\xb3\x49\x7a\x07\x4e\x09\x8f\x47\x97\x3a\x18\x1f\xbd\x55\x2d\x90\x07\xa9\x5c\x20\xfd\x57\x2f\x90\x87\xaf\x60\x20\xbe\xa2\xac\xff\x75\x7f\xe6\x2a\xdc\x1a\x2b\xdf\x6e\x4b\xb7\xad\xfc\x08\x4a\xcd\x8f\xc3\x15\x91\x39\xd7\x9a\xb9\x04\x12\xbf\x92\xc1\xe1\x1f\x56\xf8\x58\x99\x03\xbe\x04\xcc\x12\x61\x1f\x7c\x0f\xa9\x40\x57\x05\x8d\xf3\x9a\x2b\x30\x90\xa8\x30\x76\x2d\x22\xda\x82\xec\x18\xd9\x74\x5f\x67\xab\x6f\xe5\x50\xf7\x71\xb7\x72\x28\x3c\xb6\x72\x88\x40\x37\xae\x0c\x8a\x47\x7a\x55\x8c\xdd\xa0\x16\x4a\x87\x4e\x58\x46\x7e\xab\x58\xb9\x20\x46\xd1\xad\xd3\x4c\xa1\xdd\x96\xe2\xa9\x4d\xd4\xb4\x8e\xc9\xae\xd6\xe5\x86\xea\x78\xe0\x38\x3d\xfa\x60\xec\x04\x40\x40\xe8\x5d\xea\x37\x1f\x10\x03\x19\xe1\x2c\xf8\x99\x09\xad\x03\xcc\x11\x89\xec\x05\x63\x2a\xec\x9f\x1c\xf6\x69\xea\xf7\x91\x3e\x40\xfa\x4b\x21\x20\x4b\x2e\x99\x5b\x48\x84\xa4\xf4\xbf\xc0\xc6\xe6\xd3\x3c\xbc\xa3\x91\x5c\xb2\xc5\xd0\x66\x53\xd9\x5e\x8b\xee\x62\x4c\x4c\x8c\x1b\xbe\x74\x03\x0a\x8c\x8f\x9e\x77\xa0\x3e\x7d\x83\x78\x74\x6d\xf0\x11\x8f\xe5\x88\xdb\xcf\xa6\xd8\xf3\x26\xdb\x43\x23\x90\xf0\xb8\xa9\x29\x08\x72\x2b\xf4\x10\x70\xd5\x52\x9e\x41\xa1\x42\x0c\x24\x6c\x3f\xec\x45\xfa\x76\x4f\xe1\xe1\xa6\xf1\x81\x88\xe5\x97\x60\x54\x96\x73\xc9\x16\xbb\xca\x62\x69\x48\xa1\xe6\xbc\x70\x5d\x22\x41\x4e\xda\x55\x49\x7e\x82\xfc\x37\x37\x04\x4a\xc4\x63\x31\x24\x27\x52\x9b\xff\x1c\x41\x42\x2f\xc6\x58\x24\x53\x27\x52\xc3\x99\x8d\x26\x37\x7e\xda\x03\x11\xdb\x86\x68\x38\x84\x58\x30\x75\x1d\x6a\x57\x5d\x9a\x27\x10\xd5\xe6\xf2\xf8\x89\xe1\x8a\x1c\x0b\x22\x4b\x47\x55\xed\x1a\x5f\x29\x3b\x84\xf3\x5e\x07\xd1\xb0\x15\x63\xd8\xc9\x90\x65\x34\x17\xb7\x0c\xe7\x03\x6b\xdc\xfd\x02\xde\x6d\x88\x44\xfa\xdc\x54\x68\xbe\x44\x35\x9b\xf1\x84\xe4\xac\x9c\x01\xee\x4a\x32\xef\x7b\x8a\xfb\xda\x17\xf1\xe8\x71\x77\xc4\xa3\x57\x3e\x04\x15\xe5\x35\x64\x1d\x3f\x8c\xfa\x83\x63\xe3\x76\x9d\xd3\xc2\xb0\xe0\xff\x31\xbb\x32\x70\xc1\xff\x85\xe6\x6e\x6a\x4c\xf6\x89\xe2\x62\x96\xb1\xe8\x37\xeb\xcf\x0c\x87\x31\x23\x18\xfb\xf5\xb7\x8a\x5f\xd1\x8c\x61\x95\x00\x15\xbe\xf5\x8a\x9c\x2e\x29\x5d\x43\xdb\xe1\xcd\xc8\x65\x1f\x83\xdf\xb9\x64\x8b\x9d\xe1\x12\xdb\xee\x1c\x8b\x9d\x1a\xc2\x29\x62\x54\xaf\x5c\x40\x78\x76\x07\x7e\xdb\xf9\x3c\x7a\xda\x23\x30\x63\x7b\xe3\x49\xeb\x72\x3e\xc8\xa8\x52\x7d\xa0\xc9\x34\x0a\xc2\x1b\xa3\xaf\x6a\x2c\x71\x1e\x5c\x53\x97\x84\xdb\x0a\x94\xde\xfd\xe8\x50\x01\xd9\x57\x3e\x70\x0f\xf4\xbf\xb2\xfd\xac\xbb\xc2\xd0\xad\x84\x02\x07\x10\x36\x57\x21\x1b\x21\x2a\xd4\x69\x3a\x37\x50\xfc\x27\x88\x88\xc8\x29\x79\x55\x37\x8c\xe0\x0a\x5c\x54\xdc\xd5\xcc\x0a\xa9\x09\x17\x49\x56\xd9\x60\x08\xdc\x0a\x0e\xae\x7e\x0c\xd8\xde\xc8\xdb\x3b\x63\xd7\xc3\x3a\x8e\x76\x29\x45\x4b\x85\x50\xcd\xec\x0f\xc8\xb7\xf1\xd9\x14\x48\xed\x75\x52\x6b\xda\xaa\xe4\x23\x6e\x74\x92\xc4\xfa\xe5\x2b\x3e\x29\x19\x39\x98\x53\x21\x58\x16\xa0\xc8\x58\x67\x28\xd5\x9a\x26\x73\x8c\xd9\x51\x62\xd6\x71\xc6\xf4\xae\xc2\x06\xfd\x39\x4d\xe6\x5c\x78\x5c\x05\xe1\xd1\x94\xea\xba\xb2\x35\xb4\x06\xea\x6a\x20\xf5\xd8\x55\x66\xd7\xb6\x95\xb1\x7c\x17\xf6\x73\x89\xbb\xcd\xd4\x00\xe5\xcd\x6b\x6a\xa4\x7e\xbb\xe6\x81\xf2\xb8\x2f\x43\xeb\x13\xb8\xf6\xf6\x7e\x35\xb9\x77\x68\x73\x31\x65\x65\x89\x33\x34\x61\xf6\x86\x46\x8f\xd9\xb1\x6d\x62\x31\x97\xd7\x24\x95\xe4\x1a\xba\xad\x5e\x19\x05\x02\x52\x91\x94\x53\x3d\x82\x37\x85\xc4\xc0\x44\xe6\x45\x29\x73\xae\x5c\xf9\xa3\x65\x8f\xb5\x01\xa6\x64\x55\x6b\xcc\xd9\x78\x16\xb3\x4a\xc4\xcd\x1e\x5f\x1d\x10\x4d\xcb\x19\xd3\xe6\x19\x44\x54\xf9\x84\x75\xc4\x85\x59\x37\x2a\x79\xaf\x5d\x40\x76\x7d\x1b\x90\x88\x6a\x9f\xe8\xef\x41\xce\xdc\x5d\x90\x40\x08\x69\x8a\x53\x59\xda\x64\x4b\xff\xa3\x85\xa1\x37\x5c\xf8\x93\xdd\x38\x2b\xa1\x55\x47\x54\xf8\x2e\xfd\x41\x90\x15\x7e\xfe\xf9\xa4\x1f\x58\xf7\xdd\x7a\xbc\x9b\xb8\xee\x5a\x96\x59\x7a\xcd\x53\x54\xce\x14\xd9\x33\x17\x0f\xba\x51\x60\x8d\x28\xef\x9d\x57\xfa\xf5\x35\x4f\x7b\x22\x3e\x0c\x15\x13\xdd\xe5\x51\x1b\xa2\x13\xa0\x3a\x4f\x99\xd0\x46\x58\x96\x8a\xec\xc1\x1d\x03\x72\xc4\xb1\x12\x1f\xee\x07\x10\xd5\x7c\xc2\x45\x8d\xf2\x50\x4f\xaa\xd9\x2e\x8d\xdc\x70\xe6\xbd\x62\x1a\x6b\xa8\xa1\x0c\x59\xea\x39\x51\x3c\xaf\x32\x4d\x05\x93\x95\xca\x16\x1d\x59\xfb\xb1\x4e\xec\x34\x63\x1f\x70\x85\x77\x57\x7a\xfc\x50\xb1\xf2\x03\x89\xb6\x35\x70\xca\x92\xf6\x53\xa7\x82\xa7\xcf\xbc\x26\xe4\x81\x00\xd8\x07\x96\xd8\x1a\xb1\x22\xab\x66\xbc\x55\x51\xf0\xb6\x0f\x62\xab\xbb\xef\xd6\x07\xb1\x6e\xf7\x56\x29\x56\x23\x97\x75\xeb\x43\xbe\x81\x6d\x0b\xd7\xab\x5f\x5e\xac\x6e\x59\x98\xb2\x82\x89\x14\xa0\xd3\x5f\xd5\xeb\x0f\x5f\x7e\x6d\xb4\xb7\x90\xe5\xfd\xec\x15\x0e\xff\x3c\xda\xa5\x83\xc4\xfb\xb9\xcc\x52\x45\xd8\x07\x5d\x52\xb3\x1d\xe4\x46\xf0\xfb\x7b\xa6\x84\x8a\xae\xa2\xfd\xa9\x34\xde\x22\x9f\x49\x03\x4d\x9f\xa8\x06\xaa\x7a\xed\xc8\xb9\xab\xc2\x3e\x9c\x35\xf5\xa2\xd3\x3d\x37\xe7\xc4\x0d\xd4\x4a\x07\x15\xd7\xa1\xad\x68\xa2\x69\x9f\x12\xd7\xbf\x74\x6b\xa6\xa9\x56\xb4\xd6\x6b\xbc\xd5\x1a\x17\xeb\xb6\xb3\xe6\xe3\xea\xac\x39\x05\xb8\xa7\xee\xe0\xc7\x76\x9c\x86\xcf\xce\x9e\xb4\x6a\xeb\x5d\x7c\x74\x76\x45\x05\x7b\x32\x74\xca\xb1\x03\x59\xd8\x04\xa2\xcc\x6c\xd4\xc5\x11\x95\x10\xed\xa4\xf9\xba\xfb\x0e\x52\x4d\x15\xd3\x5d\x3c\xc9\xb1\x82\x59\x8f\x67\x44\x4e\xc8\xf9\xf6\x27\xec\xde\x09\x85\x9e\x0e\x02\x89\x8c\xfe\x66\x75\x51\x11\x5d\x69\xb4\x50\x47\x77\x07\x8e\xcc\x7c\x66\x19\x8e\x91\x9a\xd9\x4e\xa8\xee\xd8\x90\xbe\xc3\x6e\x6c\xdf\xf6\xdd\xbb\xe3\xc3\x3e\x49\x68\xc6\x73\xda\x2a\xfc\x3b\x26\xa3\xe5\x52\x00\xd0\xe5\xbf\x55\xa1\xa1\x0d\xd0\x8d\x9e\x70\xf6\xfa\x75\x50\x67\x96\xb0\x3a\x4c\x70\xc8\xd5\x65\x77\x80\xf3\xa5\x21\xe3\xe5\xfe\xc3\xc1\x11\xb1\x67\xef\xe4\x9d\xbf\x8f\x7b\xbe\x2b\x2a\xf6\x2c\x61\x75\xe0\x2e\xe5\xea\x72\x0d\xe0\xe8\x5d\x6d\xe0\x22\x3d\x69\x57\xc7\xb9\x99\x91\x86\xa6\x85\xe7\x60\x54\x03\x7c\xdf\x85\xac\xc8\xb5\x85\x11\xb4\x16\xe2\x05\x2f\x5e\x92\x23\xa1\xaa\x92\xd5\x19\x5a\xcd\xa1\x8c\xbe\x75\x67\x7b\x11\x90\x1a\xd5\xcb\xde\xa2\x12\x7d\x73\xea\x53\x09\x73\x14\xb4\xd4\x60\xc8\xf5\xc3\x48\x7e\x38\x27\xa7\x83\x13\xe2\x2e\x9c\x74\x3c\x75\xc5\x17\x43\x8b\x29\xe6\x81\xd3\xdd\x45\x86\x77\x02\x90\xd1\x90\x5b\x5e\x79\x60\x5f\xf2\x2c\x65\x57\xcf\x54\x4a\x5f\x0c\xe1\x31\xae\x64\x30\x7e\x27\xaa\xc8\xce\x8b\x9d\x31\x39\xe7\x39\xcf\x68\x99\x2d\xa2\x06\x67\xf5\x75\x66\xdb\x75\x03\x42\x36\xcb\xf3\x1d\xb2\x27\x4b\x18\x39\xa1\x82\x64\xcc\x61\x2e\xd8\x55\xbd\x40\xbb\x63\xb0\x19\x22\x92\x6c\x4c\xa4\x08\xa5\x65\x4f\xbc\x96\x3a\x9d\xca\xee\xf7\x11\x68\xed\x61\xbd\xe1\x71\x61\x76\xc1\x31\x79\x67\xb7\x2f\xab\x17\x20\x33\xc0\x62\x76\x57\x6c\xd6\x64\x6d\x9e\x3f\xa4\x95\x67\x63\x39\x74\xb7\x69\x84\x6e\xeb\x3d\x99\x71\x7d\xc6\x0a\xd9\x83\x0e\x87\x03\x35\xe2\x0b\x5c\x9b\x13\x52\x71\x68\x4f\x43\x35\xa1\x28\x92\x92\x2a\xa3\xc6\xa8\xc3\xe8\xc2\x98\x1c\x1e\x9d\x9e\x1d\x1d\xec\x5f\x1c\x1d\xbe\x24\x3f\xd8\x91\x78\x68\x07\x8c\xc9\x45\x88\x3b\x1d\x54\xb4\x59\x70\x5f\xff\xac\xa1\x15\xb1\x54\xd4\x8d\x33\x00\x87\x93\x0a\x72\x2c\xb8\xae\x5b\x86\x61\x5d\x40\x26\x85\xcd\xf4\x37\x77\xdb\xe8\xc6\x8c\x63\x3e\xaa\xb0\x83\x99\x9f\xe3\xd1\x60\x85\x62\x83\x1d\xff\x2a\xad\x1c\x24\x6b\x56\xfe\xea\xe9\x59\x87\xa1\xea\x7a\xe1\xf4\x63\x63\xf9\x3e\x48\x0e\x06\x02\xa3\xc5\xf5\x79\xdc\x6c\x7d\xdb\x47\x07\xac\x2b\xcb\xa8\x2b\xe3\x78\xbc\x3b\x26\x66\x1b\xdf\x1d\xef\x3a\x95\x2f\x5b\x6a\x1d\xea\x07\x0d\xf1\xcb\x63\x86\x1f\x13\xf2\xd6\x95\x4d\x02\xf8\xd4\xea\x2e\xa4\x88\xbf\x18\xf4\x9c\x6c\x2c\x1b\x57\xba\x5f\x4d\xc2\x87\x5a\xc0\xf3\x19\xbf\x62\x02\x3f\x6c\x7d\x92\xda\xbd\x6a\x2f\xd3\x18\x7e\xb9\xb5\x94\xcf\x5e\xaf\xef\xdb\x50\xe2\xf4\xf4\x65\x56\x7c\xd9\xef\x4a\x64\x9e\x23\x42\xf7\xdc\x83\xc9\xd4\x78\x30\x5e\x3a\xae\xc5\xca\x47\x5c\xf2\x69\xab\x85\xdd\xd8\x19\xdc\x50\x0d\xab\xde\x9f\xb6\xe5\xcd\xa2\x36\xa7\xee\xdf\xc7\xcc\x02\xe3\x2b\x07\xb2\x6a\xb7\xd9\x67\xfe\xe1\xcf\xce\x8e\xf6\x0f\xdf\x1c\x8d\xf3\xf4\x11\x0a\x69\x26\xd2\x42\x72\xa1\x55\x5b\x0b\xbf\x5d\x3f\xf4\xae\xe2\xdd\xbf\x76\x3f\x3a\x9c\x1f\xce\xad\x1f\x77\x22\xe8\x72\x90\x32\x4d\x79\xa6\x02\xee\xd2\xb2\x90\x99\x9c\xad\x6e\x80\x76\x0f\xb6\xf9\x03\x22\xe4\x8e\xe8\xc8\xf0\xe3\xfa\x8c\xdd\xf6\x7d\x94\x9b\x76\x2e\xf6\x4d\x36\x84\xac\xa9\xe5\xed\x46\x68\x77\xfc\x04\x08\xf6\x19\xcd\x88\x25\x2a\xa2\x3b\x07\xc4\x9b\x6b\x42\x51\x77\x75\x08\xba\xab\xdf\xd5\xbe\x58\x0f\xf1\xdb\x9a\x16\x46\x92\xb7\x6d\xe3\x1f\x53\xdd\x8d\x14\x6f\x20\x45\xc9\x46\x1e\x36\x1b\xda\x7b\xcb\x32\x50\xcb\xc2\xfd\xc4\x79\x82\x9d\xdf\x18\xaf\xca\x16\x4d\x8f\x70\xad\xc9\x7b\x47\x3c\x62\x11\x66\xd9\xa2\x6e\x8d\x62\xbd\x61\x74\x86\x70\xd8\xa5\x0d\xc8\x15\x25\xbf\xe2\x19\x9b\x41\xdb\x23\x2e\x66\x01\x8c\x53\x08\xfc\x64\xdb\x20\xc5\xc1\xa9\x37\xe6\xaf\xa0\xf5\x1e\x70\xd6\xc9\xdb\x0b\xe8\xa0\x05\x29\x15\x9d\x0d\x4e\xf3\x40\x58\xf3\xa3\xd1\x08\x5c\x7f\x7b\xff\x36\x96\x4f\x9a\x0d\xc8\xcf\xcc\x3e\x47\x42\x8b\xaf\x12\xda\xdc\xcf\xa5\xef\xb7\x04\xef\x5a\x53\x16\x18\x1a\xd3\xf8\xec\x55\xcf\xcc\x95\x46\xa3\xc6\xad\x3c\xba\x9e\x33\x80\xec\xae\xf3\x0c\x1e\xa3\x95\xb4\xa6\x0d\xb4\x67\x69\xef\x82\x4d\xab\xd6\x88\x4f\x1f\x70\xfb\x02\x25\x6a\x91\x67\x5c\x5c\xd6\x18\xf1\x53\x69\xf8\x18\xcb\x99\xb9\xb8\x74\xab\xa6\x64\x34\xbb\x79\xc7\x68\xc3\xa3\x6b\xdb\x2d\x74\x6f\xf1\x08\x88\x17\x18\x69\xf1\x77\x27\xbc\x6c\x02\x58\x28\xea\x77\x76\x1e\x35\xc5\xb8\x4a\x14\xef\x2e\xde\x61\x98\x48\xb6\x0b\x72\x7c\x7e\x70\x7e\xfc\x59\xa3\x7e\x37\x6d\xae\xf0\x76\x8f\xda\x7a\xe0\xbf\xb5\xcb\xaa\x1a\x91\xac\x6a\x7b\x27\xba\x5e\x4e\x65\xa9\x69\xb6\x06\xc1\x99\xcc\x69\xb1\x5f\xe9\xf9\x21\x57\x80\xd6\xd8\x8f\xfa\xb7\x34\x6a\x50\xaf\x88\x7d\xe8\x5c\xc3\x0d\xee\xd8\xd7\x5e\x77\xf0\xf7\xfd\x53\x42\x2b\xc3\x8f\xda\xb6\x18\x5a\x5b\xb2\x9c\xfb\x8a\x73\xac\x81\xee\x95\x32\x76\xcc\x4f\xd0\xc5\x5d\xb5\x49\x54\xf9\x7c\x55\x6f\xdb\x78\x34\xec\x5c\x28\xf5\x9f\x48\x0c\x9a\x0b\xae\x39\xd5\xb2\xec\x2d\x36\x18\x8d\xe8\x1d\x86\x95\xd2\x32\xb7\xab\xe8\xd8\x5d\x01\x09\x59\xa0\xbf\x2d\xdd\x54\x7b\x13\xc1\xfa\x04\x9a\x1f\x0b\x63\x2b\xd2\x84\x35\xca\x6c\x86\xd0\xfa\x07\xc7\xe6\xfe\x9a\x6f\xad\x13\x1d\x50\xec\xb3\xbf\xbd\x8c\x9a\x63\x2e\x75\x30\x76\x5e\xcc\xba\x3d\xee\xda\xbc\xd2\xfc\xb7\x7e\x44\x1b\xff\x4d\x34\xe2\x09\x48\xa2\xff\xae\x68\x86\xa4\x3d\x59\xa7\xf3\x3d\x9e\xd2\x7e\xbe\x38\xe6\x12\xfb\xf1\x35\x4b\x9c\x78\x6f\x5b\xa5\x10\xa3\x1f\x29\xa2\x4b\x2a\x94\xe1\x93\xd8\x9f\xb1\x6b\x13\x20\x76\xc9\x9e\x4e\x8a\xc1\xda\x28\xd5\x57\x39\x6c\x56\x89\x50\x59\xc5\x6f\xbf\x40\xd6\x78\xed\xcb\x61\xbb\x7d\xe6\xda\x93\x1c\x60\xb5\xf7\xe3\xb7\xb5\x63\x79\x3e\x0a\xe9\x85\x0a\x22\x79\xcd\x95\x76\x0d\x84\xe1\x04\x57\xb6\xd7\x1a\xd8\x02\xa7\x44\x96\x84\x17\xff\xa4\x69\x5a\xbe\x44\x3d\xc2\xda\xaa\xf0\x6f\xe5\xe1\xf0\xa9\xf0\xd9\x36\x7b\x7a\x51\xd8\x26\x1e\x17\x07\xa7\x04\x1b\x85\x7f\xf3\x97\xe7\x60\x17\x7c\xfd\xd5\x5f\x9e\x77\x64\xc4\xc7\x5a\x55\x48\xfa\xf6\x89\xf6\x9e\x59\xf1\x44\xaa\x48\xa2\x6a\x11\x43\x0b\xd0\x76\xcf\xb1\x38\xc3\xec\x93\x56\x68\xe2\x42\x30\x5c\xe9\x77\xef\x3e\x75\xe2\x6d\xd5\xc5\xef\xa8\xea\x82\xf8\x6a\x7c\x14\xac\xbd\x30\x72\x38\x20\xc0\xea\x2c\x0b\x70\x94\xdd\xa7\x8f\x45\x76\xb7\xa4\x6e\x5b\x4e\x8e\x39\x38\x4c\xf1\x73\xad\xf3\xeb\xf2\xd4\xc3\x93\xf3\x7f\xbe\xde\xff\xfe\xe8\x35\x7c\xab\xcd\x0a\x34\xec\x69\x2d\xa1\x36\x39\xeb\x77\x67\xf7\xf6\xce\xad\xb6\x24\xed\x23\xc1\x40\x34\x52\x0b\x04\x39\x79\x75\x7e\xdf\xac\x82\xae\xe6\xac\x98\x76\xa0\xde\x63\x8b\x6b\x40\xa7\x75\x56\xae\xa7\x72\xbe\xe7\xa0\x48\x00\x7b\x1f\xf9\x51\x0c\x0f\xe1\x37\x76\x76\x75\xb4\xe4\x0d\xb2\x71\xba\xde\xed\xf1\x6f\x43\x31\xa4\x62\xef\x91\xef\xcf\x4a\xed\x6e\x3a\x64\xd9\x17\xac\xc3\x2e\x8e\xe5\xd4\x47\x23\xc2\x70\xef\x28\xcd\xae\x6a\xf6\x53\xa6\x7c\x37\xe6\x27\xc0\xad\xc5\xaa\xd6\x83\xdd\x77\x87\x95\xc3\xda\x1e\xdc\xae\xf5\x52\x90\x55\x10\xd5\x75\xdf\xd4\xc0\xd3\x65\x64\x52\xeb\x08\x53\x05\x4d\x7a\x6d\x08\x5f\x9f\xc2\x33\x00\xbd\xf7\x18\x37\x18\x78\xf1\x35\x95\x97\xf9\x67\xf7\xb3\x1c\xfd\x70\x4d\xa4\x95\x7b\x71\x89\x6b\x5f\x5e\x48\x87\xa4\x13\x42\xb2\x6c\x24\x0b\x91\x8d\xdb\x87\xfc\x36\xf4\x73\x4b\x77\xc3\x3a\x5d\x0d\xc5\x5c\x6a\x29\x7a\xae\xa1\x5d\x35\x68\x2c\xd8\x4e\xe1\x8a\x03\xac\x74\xcf\x58\x19\xc8\x5b\xac\x20\xf2\x61\x75\x63\x79\xb8\xad\x5b\x0a\x17\x60\x8f\xc3\xeb\x8f\x4f\x12\x15\xe9\xf1\xe1\x1a\x84\xd0\x53\x03\x3b\xba\x6f\x98\x70\x6d\x89\xb2\x69\x4f\x95\xfb\x66\x20\x47\xf3\xe3\x43\x6b\x2e\xb8\xb2\x7c\x65\x97\x15\xb9\x79\x5d\xad\x45\x95\x92\xa5\xbe\x96\x65\x5f\xf0\x71\xf1\x70\x8d\x2c\x4c\xfb\xdb\x12\x18\xc7\xd3\x94\x22\xf8\x95\x8f\x5e\x92\x9c\x83\x24\x69\xb4\x41\xbd\x49\xa2\x3c\x84\x40\x79\x3c\x82\xe4\x61\x14\x97\x87\x45\xe2\x5a\x9b\xf9\xeb\x96\x47\x2f\xc4\x72\x83\x59\x37\xa8\x61\x94\x5a\xee\x52\x70\x37\x07\x92\x67\x2d\x72\xb6\x94\x46\x0e\xb5\x13\x27\xb1\x88\x75\x23\x61\x70\x10\xdb\x36\x66\x99\x99\x59\x29\xc2\x86\x8f\x16\xac\x6b\x48\xb0\x67\x62\x4e\x0b\xdb\x34\x3f\x95\xd7\xe2\x9a\x96\x29\xd9\x3f\x3d\xfe\xfc\x72\xb5\x73\x25\x28\xae\x87\x2e\xbd\x05\xe2\x5a\xd0\x7a\x3c\xc8\xc0\x87\x24\x21\xf3\xc7\x84\x6b\x85\xa9\xfc\x90\x8c\xaf\x43\x6f\x94\xd9\xa7\x7c\x26\x8b\x91\x74\x46\xaa\xd9\x91\x02\xb5\x4a\x10\x99\x68\x9a\xb9\x46\xcc\x4c\x5f\x33\x26\xc8\xf3\xe7\xcf\x31\x40\xf1\xfc\xbf\xfe\xeb\xbf\x08\x74\xdd\x4c\x59\xc2\xf3\xe5\x0b\xe1\xaa\x3f\xbf\x78\x31\x26\xff\xd8\x7f\xf3\x9a\xd0\x04\x6c\x39\x44\xbe\xc5\x91\x61\x3e\xc3\x9b\xd5\x90\xfc\xef\xf3\xb7\x27\x6e\xfb\x52\x8d\x5f\x81\x5d\xfc\xe7\x8d\xc9\x61\x90\x7b\x1f\x06\x0f\xa8\x9e\x03\x35\x84\xd4\x84\x4e\xa7\xc8\x70\x20\xb9\xb9\x72\xc2\xc4\x61\xcf\xf1\xd9\xdc\x75\xa2\x37\xac\x96\x41\x51\x00\x37\xaf\x08\x01\x1b\x87\xe3\x88\x35\x0e\x30\x96\xdf\x44\xe0\x55\x86\x24\xe3\x97\x8c\x4c\x15\xf4\xa3\xaf\x1b\xa7\x94\x4c\x19\x03\x2c\xa1\xc2\x8c\x8e\x83\xd5\x33\xa3\x58\x47\x6c\xcc\x75\x67\x4e\x74\xec\x5c\x1e\x87\x90\xed\x9a\x77\x2d\xc4\x6c\x6f\x40\x57\xa3\x85\x22\xc3\xcc\xc2\x63\xcd\x64\x88\xbe\xf6\xd4\x7f\x0f\x32\x95\x45\x3f\xac\x25\x23\xcd\xa4\x98\x85\x3c\x58\x6b\x1f\x2e\x99\x72\x51\xb0\xb6\xc4\xe8\xa9\xa1\x4e\x3f\xed\xe9\x50\xb8\xbf\xa1\x45\xb7\x4e\x20\x71\x8e\xae\x1b\x33\xc2\xa1\xa4\x13\x59\x69\x97\xb3\x67\x7f\x07\xf8\x36\x2d\x1d\xe9\x3b\xbd\x42\x6f\x5d\x8a\xfa\xeb\xfb\xd7\x53\xd3\xad\x38\x67\x0e\x76\xed\x58\x65\x1d\x12\x46\x93\x39\xb9\x64\x8b\x11\xee\x00\x05\x05\xf4\x08\xa0\xf6\xa1\xa1\x71\xd4\x86\xdf\x7b\x9e\x53\x63\x4d\xda\xa9\x70\x09\x96\x81\x7e\xe0\xd0\x27\x9c\xc1\xa5\xac\x5e\x6e\x5b\x59\x89\xc0\x43\xe9\x7a\x57\x26\x52\x68\xdb\x17\xd3\xf7\xae\x82\x84\xd1\x06\x20\x81\x91\x30\x2c\x35\xb7\xa9\xdb\x9e\x5c\x67\x95\x9a\x1d\xc5\xea\x1f\x95\x58\xba\x1b\xf0\xdc\x21\xa7\x57\x31\x8b\x8c\x44\x5d\x4f\xc4\x20\x33\x75\xce\x13\xa8\x38\x32\x97\xdb\x6b\x1d\x95\x3c\x21\x22\xc0\x04\xc5\x74\x65\x49\x03\x79\xc2\xe6\xd9\x4c\x29\xc2\xe1\x0b\x73\x5a\x5e\x32\x07\x34\x4c\xb3\x31\x39\x35\x2f\xe9\xd1\xe6\xb1\x95\xe0\x15\x16\x88\x18\x19\x13\x22\x41\x98\x87\xec\x8e\xc7\xbb\xb8\x55\xae\xc0\x85\xe8\xcc\x35\x7d\x76\x91\xeb\xad\x7b\x5c\xc4\xca\x6f\x68\xa1\xb0\x9b\x9e\x31\x2d\xa0\x63\xa5\x04\xdc\x16\x3d\x77\xca\x04\xed\x08\x21\x1e\x1e\x3d\xb7\x31\xeb\xb7\x13\x6a\x7f\x7d\x50\x3b\xc4\xda\xe3\xa3\xef\xfe\xa7\x3d\x76\x3f\xbd\xa9\xf7\xa9\xe5\x21\x2b\x49\xfa\xea\xc8\xd8\x7b\xcb\xcd\xbc\x87\xc6\x66\xee\x88\x43\x47\xa0\xdf\x46\x58\xd2\x77\xb2\x45\x2c\x94\x7a\xc6\x1e\x95\xf1\x71\x3c\x05\x91\xba\x1a\xeb\x26\xb4\xcb\xdc\x0e\x63\x28\xb0\x7e\xab\xa3\x6b\x97\x3d\x77\x3c\x44\x9b\xfa\xee\x66\x49\xf3\xe8\x92\x44\xd3\x3c\x62\x47\x46\x00\x2b\xe1\xb7\xda\xb0\xfa\x18\xa6\x4a\x4b\xe8\xd6\x59\x0b\x87\x31\x79\x63\xb7\x62\x64\x72\x3a\x51\x32\xab\xb4\x47\xa2\x58\xb1\x4f\xc3\xa0\xae\xb7\x27\x82\x36\xb9\xcb\x82\x5d\x1b\xf4\x15\xdc\xca\xfa\xd9\xc0\xf1\xe8\x51\xf8\x74\x4d\x90\xc5\xe3\x77\x96\x26\x8b\x47\x8f\xb3\xe0\xd4\xc5\x9e\x67\xc2\x0d\xeb\xd1\x3b\x5d\x45\x64\xa4\xdd\x42\x8e\xac\x56\xa8\x3a\x3b\x45\x15\x6b\x28\xdb\x22\x60\xd7\x47\x77\xaf\xae\xfd\x2e\xeb\x60\xdc\x3f\x3d\xee\xd1\x2a\x0d\x46\xbd\xc1\x2e\x0d\xaf\xd8\x5a\xa6\x77\x39\x22\x02\x1f\xa3\x65\x6a\x54\x7a\xe7\x40\x3a\xac\x29\x6a\x43\x7a\x46\x28\xff\x0e\x4c\x9b\xa5\x0f\x7f\x65\x36\xa3\xb0\x98\x2b\xee\xd0\x81\xce\xe0\x7a\xdb\x0a\xba\x7a\xb8\x1c\x1e\x10\x71\x4f\xdf\x0c\xda\x50\xe3\x05\xa8\xdf\xa1\x62\xa7\x79\xc4\xbb\xe8\x99\x23\x22\x39\x67\x99\xd9\xf4\x48\xc3\x65\x53\xc8\xf4\x25\xf6\xfc\xa6\x42\x48\x0d\x7c\xa3\x86\x24\x83\x7e\xe4\x43\x74\xc5\x18\x0d\x34\xc8\xfe\x2a\x83\xa0\x69\xcf\x3a\x67\x6f\xcc\x43\x7a\x67\x20\x02\x4c\x04\xb4\x3b\xed\x87\x93\xc8\x03\x70\x93\x39\x6a\x55\xa5\xcf\xb6\xfc\x11\x5f\xd9\xf1\x1d\x13\xa9\x64\xce\x72\x8a\xfd\x48\x1c\x81\x8c\xbc\xbe\x2e\xb9\xd6\x0c\x51\xc7\x59\x99\x2b\x22\xa7\xc3\x28\x6e\xbc\x73\xf5\x62\xa7\x2f\x7d\x96\x3c\x84\x41\x4d\xdc\x0a\x6d\x0b\x03\x76\xd3\x11\xc7\x0d\x22\xe3\xc2\xac\x4e\xb0\xa6\x33\x68\x90\x24\x1a\x0e\x4b\xa3\x44\x5c\x21\xfd\x37\x9a\x74\x0f\xe7\x8b\x68\xeb\x83\x18\x7a\xc5\x74\xeb\x83\xd8\xfa\x20\xfa\x18\xf1\xc1\x7c\x10\xc1\xc6\xed\x84\xe9\x0a\x7f\x44\x58\x88\xe7\x9c\x12\x35\x94\x45\x00\x13\x6d\x58\xde\xb9\x23\x64\x19\xc7\x0a\x76\xc7\xe3\xdd\x5d\xe7\xa4\xb0\xeb\xa3\xd2\xd3\xd1\x37\x84\x89\x44\xa6\xc8\x54\x66\xfc\x52\x69\x50\x6a\x6b\xab\x3c\x7c\x97\xdc\x3d\x2b\x8c\x37\xc0\xd8\xfd\xb2\x44\x8f\x12\xca\xa5\xa4\xbc\x7a\x50\x15\xac\x56\xbc\x3c\x0c\x98\x25\xa0\x47\x4b\xb4\x1a\x58\x9d\x22\x93\xf1\x9c\x5b\x7c\x42\x23\x2e\x98\xd2\x8a\xec\xe1\xc9\x71\x52\x54\x43\x7b\xc1\x38\x67\xb9\x2c\x17\x43\x7f\x91\xf9\x31\xba\xcb\x5e\x31\x00\xad\x2d\xa9\xca\x92\x09\x9d\x2d\x7e\xbf\xfa\x9b\x23\xf1\x06\xab\x6f\x9e\x2b\xba\xd4\x7d\xac\x3a\x62\xb6\xac\x9b\x08\x80\xf7\xce\x53\x1b\xf6\x21\x5b\x81\x31\xac\x9d\x3f\xe6\x2c\x13\x57\xe4\x8a\x96\xad\x2b\x30\x56\x1d\x0f\xa2\xb1\xa5\xfc\x8a\x2b\xd9\xba\x86\x6d\xe5\x90\x21\xf1\xce\xed\xa6\x8c\x3e\x62\x59\xe9\xa2\xd2\x76\x77\x71\x6b\xdb\x41\xf6\xf9\x35\xdd\x50\x7c\x5f\xec\xf4\xf8\x72\x05\xd5\x9a\x95\xe2\x25\xf9\x9f\xbd\xf7\x5f\x7e\x1c\x0d\xbe\xdb\xdb\xfb\xe5\xf9\xe8\xaf\xbf\x7e\xb9\xf7\x7e\x0c\xff\xf8\x62\xf0\xdd\xe0\xa3\xfb\xe3\xcb\xc1\x60\x6f\xef\x97\x1f\xdf\xfc\x70\x71\x7a\xf4\x2b\x1f\x7c\xfc\x45\x54\xf9\x25\xfe\xf5\x71\xef\x17\x76\xf4\xeb\x1d\x07\x19\x0c\xbe\xfb\x63\x8f\x1f\x41\xc5\xe2\x6d\x6f\x22\x18\x8f\xd1\x83\xa8\x11\xf1\xd8\x3d\xb3\x2e\x21\x1f\x46\xb5\x47\x7b\xc4\x85\x1e\xc9\x72\x84\x0f\x79\x49\x74\x59\xf5\x25\xba\xea\xed\xef\xe1\x64\x4c\xad\xc4\xd4\x08\x98\xce\xb0\xd9\x40\x21\x82\x89\xa9\x3d\x7a\x86\x6d\x1f\xdb\xd5\x4e\x61\xfb\xe3\xd6\x1f\x7c\x97\xe3\x01\x33\x95\x2c\x9e\xcd\xef\x3c\x4d\xe9\xdc\x76\x53\xde\xe6\x28\x2d\x1d\xdb\x1c\xa5\xe5\x63\x9b\xa3\x74\xcf\x63\x9b\xa3\xe4\x8e\x6d\x8e\xd2\xd6\x3f\xd8\xfd\xf8\x9d\xfb\x07\xb7\x39\x4a\xf7\x3d\xb6\x39\x4a\xad\x8f\x47\x94\xa3\x84\x4a\xfe\xaa\x4c\x25\xab\xe6\xd7\x69\x4a\x1b\x9b\xa5\xa4\x0c\x3f\x24\x6c\x3f\x49\x64\x25\xf4\x85\xbc\x64\x1d\x03\xb9\x0d\x9b\x74\x69\x74\x80\x44\xbc\xc1\x46\x5d\xbe\x78\x23\x0d\xd6\xbe\xf4\xd1\x1e\xf4\xc7\xfe\x34\x47\x5a\xa5\xdc\xd8\xa8\x3d\x2f\x16\x37\x6c\x08\x8b\x2d\x52\x96\xd6\x3f\x58\x91\xa6\xcd\x7c\x8f\xc9\x3e\x29\x59\xc2\x0b\x6e\x36\x00\xc0\x0a\x82\xf3\xb8\x7c\x7c\x17\x67\xae\x15\xcb\xa6\xb6\x93\xad\xa8\xcb\x9c\xcb\xc0\xfe\xb4\x3b\xca\xca\xc7\xa0\x0e\x21\x5d\xaf\x51\xa2\xe6\xb2\xca\x52\x52\xb2\x7f\x3b\xe5\xc3\xbe\xcd\x45\x38\x42\xe8\x52\x85\x4f\xa9\x1f\x6b\x07\xa7\x05\xb7\xa0\x62\x9b\x24\x06\xd9\x87\x82\x97\xb0\xd8\xce\x59\x22\x45\xda\xb7\x87\x64\x69\xfc\x5a\x57\x80\xb8\x10\x4b\x49\x5a\xe1\x05\x50\x8e\x49\x33\x9e\x72\xbd\xf0\xf9\x1c\xb8\xec\x8d\xda\x8a\xbd\x83\x2d\x23\xa8\x7a\x22\x08\x2d\x8a\x52\xd2\x64\xce\x54\xf0\x34\x54\x42\x2d\x50\x86\xaf\xf2\xcc\xaa\x19\x17\xa8\x87\xc2\x3d\x46\x59\xc9\x16\xa4\x94\xda\xa5\xa6\xdd\xf0\xc0\x8b\x60\x30\xb8\x1d\x35\x0e\x5d\x2e\x20\x7f\x4d\x86\x43\xe0\x5b\xf1\x69\xf8\x87\x22\x32\x4b\x1d\x34\xeb\x37\xcf\x8d\xe2\x9f\x58\x2e\x36\x9b\x00\x80\x66\x6a\x49\x32\xa3\x3c\x99\x8d\xe1\xe6\x9b\xbf\xfa\x13\x99\xcb\xaa\x54\xe3\x10\xec\xef\x05\x9c\x43\x0f\x87\x33\x1c\x34\xc9\x18\x55\x9a\xbc\x78\x4e\x72\x2e\x2a\xb3\xe3\xf7\xc4\x78\x7d\xe9\xba\x81\x96\xfb\x97\x3f\x75\x1c\xad\x1f\xfd\xf6\x46\xcd\xb6\xc0\x8e\x79\x56\xbd\xb5\x6b\x1c\x01\x3d\xb0\x6b\x66\x43\xd9\xb5\x5b\x52\x38\x8b\x42\xcb\x35\xaf\xfc\xdf\x2a\x39\x59\xe8\xee\x10\x36\x76\x9c\x18\xbb\xe6\xbf\xed\xc9\xbb\x40\xc5\xd6\x48\xb1\x2d\x5e\x65\xed\x3d\xbe\x67\x5c\xe9\x56\x1d\xbe\x6b\xcc\x9b\x16\x37\x77\xdd\xcc\x67\xc6\x3e\xee\xa5\x92\x1e\x46\x72\x16\x9d\xf3\x48\x27\x09\x53\x20\x8a\x1c\x28\x1c\x38\x77\xf1\xda\x96\x0f\xdd\x50\xb4\x99\x55\x20\x32\x8e\xf9\x7b\xe8\x55\xda\x89\x58\x5d\x54\x7e\xc7\xd8\x3d\x51\x0b\x07\x8b\x65\x84\xe2\x62\x86\xad\x45\xf3\x2a\xd3\xbc\xc8\x6a\xca\x9d\xb9\x1b\xec\x06\x1c\x46\x0b\x68\xe0\x9e\xa6\x08\x7a\x85\xe8\xe7\x10\x59\xd9\xf3\x63\x31\xa1\xb1\x43\x66\x69\xf6\xf1\x82\x96\xd4\x93\x3f\x91\x79\x4e\xd5\xc0\x06\x1e\x28\x64\xc1\xd8\x36\x40\xe6\x2e\x9a\xd5\x6f\x1c\x64\x1d\xac\x8b\x71\x35\x13\x54\xb4\x0e\xff\xc5\x80\xf3\x30\x14\x91\xd7\x3e\xd1\x1e\x9b\xdc\x37\x38\xd6\x2a\xc4\xdf\xd3\xe4\x92\x89\x94\xbc\x53\x8e\x70\xe9\x42\xd0\xdc\xe2\xc7\x17\xa5\xc4\x2e\xea\x2c\x6d\xdc\xaf\x86\xd6\xed\x88\xd0\x27\x0e\xc0\x0a\xf5\xad\x75\x51\xb1\x52\x3d\x81\x07\x9b\x81\x3e\x25\xef\x14\xba\x74\x4b\x7e\x95\x30\xa7\x3b\x9a\xfb\xd6\xf5\xf1\x57\xad\xd1\xea\xc8\x6a\xe8\x28\xdb\xc6\x14\x57\x21\x6c\xe9\x3e\x72\x09\x30\xf1\x34\x33\x22\x6e\xe1\x31\x7f\x1a\x0c\x36\x59\x80\xdf\x6b\x2d\xc8\x63\xe5\xa4\x3b\xa6\xd4\x6e\x39\x49\x63\x61\x76\x46\x53\xa9\xc8\xf7\x99\x4c\x2e\xc9\x21\x03\xa3\xe1\x21\x9b\xef\x97\x93\xf4\x71\x37\xce\xcc\xe9\xac\x5d\xc6\xc8\x88\xe4\x52\x70\x2d\xcb\x36\xf2\x78\x83\x80\x02\xb7\xad\x0c\xef\x82\x98\x6e\xd6\xd9\x53\x69\x64\x68\x58\xbe\x1f\xd6\x81\xa1\xbc\xeb\x04\x24\x0f\x9e\x02\xa1\xda\x5a\x8e\xfc\x61\x2e\xaf\x47\x5a\x8e\x2a\xc5\x46\xbc\x75\x22\x54\x67\x42\x5d\xb2\x05\x64\x95\xf5\x42\x2a\x3b\x58\x64\xb9\x6b\x09\x7e\x76\x38\x6f\xf4\xbb\xb3\xef\x0f\xdf\x29\x56\x8e\x43\x6b\xe5\x19\xd3\xc9\xb3\x84\x15\xf3\x67\x76\x84\x47\x4f\x56\x27\x36\xfb\xa1\xab\x1b\x0d\x15\x81\x44\x66\x99\x05\x18\x93\x53\x72\xc0\x8a\xb9\x7f\xdc\x66\xd0\xed\x31\xf7\x94\x2b\xa4\xec\xa7\xdd\xd4\xae\x19\x29\x16\x1b\x70\x06\xa5\x46\xc0\xfc\xe5\xe4\x7e\x8d\xbc\x37\x91\xdd\x3f\x63\x77\x96\x36\xad\xf8\x36\x82\xbc\x9b\xd3\xd2\x6f\x37\xea\xe9\x17\xd6\x0f\xc5\x0d\xfb\x5c\x76\x6a\x24\xb6\x8f\xa7\x68\x8c\xa6\x2c\x25\xf2\x8a\x95\x25\x4f\x99\x22\x5e\x6e\x87\x3e\x28\x9e\x6d\x06\xe5\xb7\xbd\x03\x1f\x57\xc2\xc1\xe6\xb8\x1f\x76\xc1\xff\x10\x09\x71\x38\xb3\x24\xc4\x69\x9a\x73\xb1\x19\xdc\xde\x92\x6e\x2a\xa1\x19\x3b\x7e\xdb\xd9\x5a\xb7\xe3\xc4\x06\xfb\xb9\x3d\x19\xf4\x14\xf8\x04\xce\xfe\x8f\x9e\x77\x89\x90\x69\xbb\x00\xda\x9a\xcd\xee\x19\xd5\xec\xba\xa5\x22\x34\xaa\x45\x7e\xdb\xfb\xc1\x3c\x7b\xdc\x66\xfb\x46\x74\x0a\x09\x56\x39\x42\xfe\xaf\x4b\xc9\xb2\xfc\xd4\x4f\x20\x09\xc7\x0a\x9b\xb2\x35\x5b\xb1\xb9\x35\xbb\x7f\x7a\x4c\x7e\xc0\xcb\xd7\xd7\x05\xa5\x94\x1a\x4d\x9e\x43\x99\x53\xde\x4f\x03\xf4\xe6\xa0\xcd\x7e\x58\x21\x11\x4e\xfd\xb5\xc4\x5e\x6c\x94\xa2\x1a\x6e\xb8\x2a\x59\x4a\xac\x3f\xe5\x89\xb5\x78\x58\x52\xa7\x9f\x46\x8b\x87\x87\xea\x92\x1d\xb8\xe6\x5d\xfd\x4e\xad\x45\x3b\x76\x02\x25\xc2\xe7\x3a\x11\xc5\x84\xe2\x90\xde\x10\x64\xe0\x81\xaa\x0d\x69\xe9\xbe\x58\x07\xd5\xee\x21\x79\x2d\x67\x5c\x38\x29\x26\x6d\x56\xcd\x94\xf2\xac\x1b\x39\xb7\x7a\xf2\xef\x4c\x4f\x56\x2a\x3b\x12\x74\x92\xb5\x4f\x99\x8c\x17\x81\x1f\x8e\xbc\xca\xe8\x8c\x30\xf8\xe3\x59\xca\x95\xf9\x2f\x39\x3f\x7f\x0d\xc1\xe0\x4a\x38\xfb\x12\xc2\x9c\x76\x6f\xf1\xa5\xd1\x28\x64\xd6\x27\x17\x50\x88\xf7\xd6\xc1\x23\x18\x8f\x70\x91\x9a\x4f\x67\x2a\x4a\x4a\xb6\x57\x60\xaf\x14\x5f\x77\x87\xa9\x8f\x13\x46\x2e\xe6\x3c\xb9\x3c\x0d\xe2\xbf\xb2\x34\xe7\x44\x70\x2a\x52\x52\x9a\xbf\xad\x6b\x37\xb2\x9f\x75\xda\x97\x43\x2d\x18\xcf\xed\xd4\x4e\x9c\x9e\x5b\x0a\xc2\x6f\x54\x29\x99\xf0\x3a\xff\x00\x3c\xd1\xf5\xf6\x9d\xc2\xf6\xbd\x3e\xaa\x80\xc2\xd9\x0f\x41\x50\xcf\x5d\xa1\xb5\x38\x8e\xb2\x57\x50\x15\x6a\x29\x5c\x38\xba\xad\x8d\x08\xc8\xe3\xbd\xb5\x34\xad\x87\x5b\x6e\x69\xea\xcc\xcc\x46\x88\xdc\x15\xbc\x5a\x06\x72\x26\x83\xed\xa1\xbd\xcc\x42\xbe\xb5\xa9\x6d\x66\xb2\x16\xd2\xb5\x2f\x4d\x5f\xe5\xfe\x6b\xe4\x07\xe1\x39\x1b\x34\x07\xd9\x53\xc8\xa2\xca\x30\xb3\xb6\x7b\x67\x57\x17\x63\xc4\xe7\xac\x21\x88\xbe\x69\x9d\x9d\x76\xc3\xf2\xbc\xfb\xd7\x2b\x3e\x8d\xfe\x4e\x81\x69\xf1\xfc\x2f\x7f\xfa\xd3\x63\xef\xf8\xd4\xcd\x71\xb7\xee\x96\x4f\x9d\x42\x6f\x2b\xb0\x19\x8e\xb7\xd8\x0c\x5b\x6c\x86\xf8\x58\x7b\x7c\xf8\xf3\xa3\x2f\xf4\x52\xdd\xd6\x47\x65\x5b\x57\x7c\x85\x8e\x55\x71\xfd\x54\xc4\x75\x46\x50\xf8\x1c\xb8\x09\x3d\xd5\x88\x75\xc7\x48\xd8\x22\x23\xfc\xbe\x90\x11\xfa\xab\x11\xeb\x0b\x05\xa1\x7b\x6d\xd8\xef\x07\xf1\xa0\xb3\xd8\xe8\x5a\x57\xdf\xb9\x9a\xbe\xaf\xa6\x1f\x7d\x79\xf7\x7b\xf3\x30\xec\xd6\xe3\xad\xf4\xb7\x38\x88\x37\x87\xa6\xbf\xbb\xab\x02\xb0\x7c\x2d\x8d\x74\x59\xa3\xe9\x4c\x3a\x7b\x1e\xf0\x55\x64\xab\xbd\x7b\x95\x17\xef\xed\x79\x23\x41\xc0\x9f\xde\xfc\xbc\x80\x6d\x80\xbc\x5b\x9a\xfa\xd3\x0a\x8f\x3e\xd1\x0e\xf8\x0f\x15\x1e\x55\x11\x6a\xae\xf3\x3a\x82\x80\x04\x15\x4e\x4e\xc2\xce\x34\xb5\x58\xd8\x3f\x3d\x26\x49\xc9\x00\xda\x81\x66\x6a\x4c\x56\x68\x78\x2e\x80\x64\x35\x42\xa7\xd9\x51\xad\x59\x5e\xe8\xae\x9c\xb7\x8d\x8e\xfe\xce\xa2\xa3\x0f\x1e\xa5\x98\x57\x39\x15\x23\x23\x2d\x20\x3e\x1a\xe5\x9d\x34\xf6\xc3\x31\xb1\x72\x01\xd5\x0a\xf0\x85\x42\x49\x73\x25\xf8\x6f\x15\xab\xdd\x15\x5e\xeb\xd8\x80\xe0\x0e\xbc\x47\xcf\xb4\x43\x8d\xaa\x21\x45\x12\xb9\x54\xc4\x65\x09\xe2\xe9\xe8\x04\x46\xa0\x96\x45\xae\x37\x3d\x67\xa8\xbd\x9d\x02\x48\x42\x7d\x55\x6c\x1f\xa2\x81\x48\xb3\x4c\x5e\xe3\xb3\x43\x7d\xc4\xcc\x9f\x79\x17\x8b\x4b\x32\x61\x24\xe7\x65\x29\x4b\x1b\x46\x0a\x5f\x07\xd3\x87\x8c\x9d\xc9\x4a\x34\xd8\x4a\x9b\xf4\x71\xce\xb4\x9d\x6a\x60\x15\x2d\x09\x15\x58\xc0\x69\xfe\xed\x32\xae\xe1\xd9\x4e\xde\x4d\xd8\x9c\x5e\x71\x59\x95\x78\xb7\x96\x64\xc7\xfe\x04\x7b\xef\x42\x56\xde\x77\x5e\x41\x85\x96\xff\x3a\xb5\x82\x4e\x27\xf5\x8f\x60\xe0\xa6\xd2\xb9\x23\x47\xec\x03\x57\x7a\xf9\x5b\x1c\x89\x5c\xcb\x89\x75\x70\xde\x95\x2a\xcc\x06\xfb\x53\xeb\xda\xdb\x98\xdf\xc2\xd1\x62\x4d\xf5\xea\x1c\x7e\xfa\x94\x9e\x6a\x11\x6b\xb0\x64\xde\x95\xc3\x3d\xbe\x1c\x56\xfc\xca\x96\xbd\xae\x36\x52\x51\xde\x2a\xc9\xb7\x1e\x3e\xcb\x22\xe3\xc9\xe2\xf8\xb0\xdf\xcc\x0d\x1c\xd3\x6d\x7f\xca\x67\x6d\x98\xf3\xe4\x7b\xaa\x58\x4a\xde\x50\x41\x67\xe8\x75\xd9\x3b\x3f\xfd\xfe\xcd\xc0\x70\x11\x78\x75\x8e\x0f\x57\xa6\x76\x9c\x87\x83\x9f\xac\xab\xce\x9d\x34\x49\xd7\x9b\xda\xb0\x34\x6a\x4b\xf2\xad\x0d\x02\x80\x78\x9d\xa0\x4b\xfb\xb4\x15\xea\xc0\x69\x13\x24\x0a\xd3\x37\x1c\xfa\x9b\x6a\x8a\xea\xab\x3c\xbd\x7c\x48\x02\x04\x7e\xf3\xdb\xbe\xf2\x6e\x31\xb0\x3b\xc4\xb9\xe2\x6e\x24\xba\xa4\x9a\xcd\x16\x87\xac\xc8\xe4\xc2\x30\xc0\x69\xe0\xc6\xc7\x4b\x27\xa8\x36\x94\x13\x9a\x90\xb2\xca\x18\xf6\x16\x6a\xc2\xae\x09\xc6\xd2\x5a\xd2\x71\xa1\x34\x05\xd0\x35\x1c\xff\xd6\x37\xba\xf3\x66\x75\xd7\x6d\x69\x84\xef\xf9\xc9\xab\x62\x88\x4a\xb3\x4a\x6e\xbd\xe5\xee\x1b\x13\x3c\xfe\xd3\x3c\x7b\x9f\xb8\xe6\x9d\x23\x98\x71\x77\x40\x58\xe5\x67\x55\x66\x36\x9f\x2c\x6d\xb4\x78\x05\x3d\xcd\xce\x31\xa2\x5d\x80\x4c\x30\x6f\x3f\x24\x93\xca\x28\x71\x4c\x45\x3e\xee\x65\xa8\xcf\xeb\x39\x86\xb4\xcd\x4d\x84\x16\x45\xc6\x31\x85\x59\x96\x36\x2e\x1d\x38\x34\x97\x2f\xbb\x8b\x68\xb9\xa7\x2e\x73\x3f\xdd\x65\x44\xae\x58\x39\xb9\x0b\x4e\xc5\x7d\xd5\x12\x5a\x70\x88\xe3\xdc\x59\x8b\x89\x26\x6e\xff\xf4\x18\xef\x5e\xe5\x38\x76\x3f\xe2\x0c\xda\xb9\x71\xe1\x0d\xdb\x33\x08\x2d\x17\x8f\xb4\xb4\x7f\x7a\x8c\xd0\x5e\x16\x6c\xa9\x76\x7f\x18\x3b\x81\x62\x92\x63\x8d\xf0\x48\x67\x66\x44\x4d\xa4\xf0\x0f\x65\xa2\xca\x19\x02\x34\xd5\xcd\xc6\x8c\xf1\x28\x16\xf5\xe8\xb5\xf7\xc4\xd8\x3a\x77\x57\x48\xee\x1f\xe1\xbf\x67\x44\xff\xde\x7b\x91\x90\xe2\xcc\x7e\xe6\xbb\xb3\xd7\xed\x26\xf1\x24\x1e\xc3\x02\xf2\x30\xc0\x1e\x2c\x68\xa9\x39\xcd\x48\x55\x66\x2e\x24\x88\xf9\xfd\x36\x8d\x6e\x4e\xaf\x02\xd0\xa2\x31\x21\x5f\xe0\xcc\x59\xc2\xe2\xfa\xc4\xe6\xbb\xd6\x8d\x5b\x65\xd9\x90\x4c\x39\xb4\x5b\xd7\xac\x20\x61\x48\xea\x9c\x8b\xc4\x98\x72\x62\xe4\xbb\xe9\xc0\x1b\x39\x03\xcf\x2f\x52\x88\x78\x82\xbe\xcb\xb2\x14\x80\x2c\xe1\x11\x66\xc1\x26\xe0\x6e\x30\x16\xe8\x41\x56\x29\xcd\xca\x33\x69\x36\x83\x20\xe5\x06\x40\x3d\x68\xf8\xf3\xf7\x5c\xa4\x90\x63\x75\x06\x1b\x47\x42\x05\x61\x1c\x1c\x39\x66\x48\x88\x9d\x1b\xde\xa9\x19\x6a\x4f\x55\xc9\xdc\x7c\xd2\x4e\x21\x53\xb5\x63\xc4\xc8\x0e\xba\xfb\xd4\xce\xc0\xfc\xd5\xfc\x06\xcc\xa0\x09\xee\x7b\x46\x0b\xbe\x33\x18\x12\x20\x10\x04\xef\xa4\x9e\x3f\x5e\x3e\x74\xdf\x0a\xf6\x75\x2b\x2e\x3c\x0b\x47\x00\x1e\x14\x75\x98\xee\x7a\xce\x35\xf3\xad\xd1\xd1\x4b\xe4\x51\x6a\x9a\xc2\x9a\x90\x7d\x41\x58\x5e\x68\xf0\x3c\x93\x9c\x51\x17\xce\x66\x57\xac\x5c\x18\xfb\x1e\x50\x3c\x1e\xfd\xe2\xf7\xfc\xd8\x89\xe0\x8d\xbe\xf3\x35\x93\xc3\x0a\x5b\x22\xee\xee\x17\xbb\x91\xcf\x20\xcb\x02\x69\xfe\x68\x49\x09\xdb\x6b\x2b\x32\xfe\x64\xee\x8c\x49\x88\xa7\x50\x5a\x7a\xf9\xf1\xfa\xb5\x0d\x8a\x20\xad\x7e\xe4\x22\x55\xbe\x13\xa2\xcd\xd9\xb6\xf4\x5e\x49\x64\x78\xc3\xc7\x48\xe0\x65\xf5\xf5\xae\x2a\xe7\x2d\xc3\x3b\x8d\xfd\xa6\xa1\x6e\x1d\xc0\xaa\xfd\x6f\x64\xba\x7a\xe9\x44\xf3\x7b\x1c\x5c\xec\x13\x05\x6a\x9f\x89\x1d\xcb\xaa\xaa\x8b\x62\xa5\x3e\x7f\xfb\x74\xdc\x42\xfa\x9b\xde\xa4\x76\x16\x80\x9c\x0c\x7e\x01\x4f\x10\x62\x94\x93\x69\x46\x67\x35\x1b\x81\xd4\x43\x25\xe9\xe0\xfc\x27\xf7\x09\x8a\xf0\xd5\xea\xea\x27\xf5\xd9\x4f\x69\xb0\xa3\x9a\x4a\x37\x5e\x61\x1e\xb2\xf2\xc7\x4f\xab\xb1\x7e\xf0\x9b\xb9\xe9\x2e\x81\x42\x7d\xab\x13\xee\x26\xfa\x3b\x7f\x1b\x0d\x38\xc1\x81\xad\x39\xa3\x12\x72\x9f\x40\x0f\x39\xff\x29\x62\x93\x4f\xbc\xef\x0d\x4c\x7b\xc9\x16\xd7\xb2\x5c\x8d\xa3\xde\x9a\xbf\x6e\x7d\x62\x46\x27\x2c\xfb\xf4\x02\x79\x43\x0b\xf3\xd9\x75\xa2\x29\x5a\xde\x36\x4e\x89\xba\x3f\xe6\x84\xb9\x3c\x3c\x59\xce\xa8\xe0\xff\xc1\xec\xdc\xc4\xac\x63\x59\x9a\x3f\xf7\x30\xd6\x81\x76\x7b\xc6\x12\x3d\xb0\xfc\xb7\x52\xee\x7d\x82\x41\x69\x9a\x72\xd4\x1e\x4e\x3f\xc1\x4b\xb7\x13\x81\x8b\xcb\x87\xa0\xf9\x2d\x0b\xeb\xd3\xbc\x7f\x7b\xb0\xf4\x0e\xb2\xb9\x2a\x6f\xc9\xa3\xba\xf5\xfe\x9c\x72\xdb\x55\x77\xe3\xa8\xc2\x72\xca\xdb\x7e\x16\x1e\x1d\xe8\x9a\x53\x5d\x95\x5c\xaf\xdc\x90\x6e\xbf\x91\x8b\x1f\xab\x09\xb3\xf1\xe1\x7b\xdf\x2e\x20\x4d\x70\xff\xf4\xb8\xdf\xe9\x88\x56\x38\x58\xf1\xf6\x05\x8d\xde\x42\x2a\x41\xf3\x09\x9f\x55\xb2\x52\xd9\x22\x74\x4a\x52\x08\x6f\x1b\xa3\x1e\xbd\x32\xff\x1f\x7b\x57\xf3\xdb\xb8\x8d\xc5\xef\xfd\x2b\x08\x5f\x32\x13\xc4\x1e\x2c\xda\xd9\xc3\xdc\x82\x24\xc5\x06\x9b\x8f\x81\x9d\xb6\x97\x1e\xca\x48\xb4\x2d\x44\x22\xbd\xa4\x64\xc7\x2d\xfa\xbf\x2f\xf8\xf8\x48\x89\xb6\x44\x51\xb1\x93\xa6\xc5\xf8\x92\x19\x89\x7c\xe2\xe7\xe3\xfb\xfa\x3d\xf2\x93\x92\x50\x2e\xf8\xb6\xc0\xa2\x3c\xc9\xab\x94\x79\x14\xc1\x0b\xb8\x16\x59\x4a\x68\x55\x8a\x82\x96\x59\x42\x12\xc1\x64\x02\x1e\xc3\x26\xa5\x4a\x31\x42\x3b\xea\x26\x95\x2a\x45\x41\x0a\x2a\xd5\x92\xe6\x79\xd7\x1c\x1f\xe1\x54\x0b\xa5\x1e\x1f\x43\xff\x3b\x5f\xae\x4d\xab\x5f\xb8\xbe\x7b\x32\xad\x47\xac\x6f\xdd\xb8\x83\x08\xac\xbb\x57\x69\x04\x0d\xc4\xf8\xb7\x66\x2f\xea\x99\x98\xbe\xd1\x09\xed\xdc\xde\x7e\x05\xb8\x61\xb0\x2e\x04\xe9\xb2\xf4\xba\xa0\x8b\x08\x41\xf2\x46\x6b\x07\x94\x6f\x6d\x35\x93\x68\x53\x9d\x11\x21\x31\x6a\xc4\xdd\x8b\x8e\xaf\x5c\xb2\x56\x49\xee\xc1\x1d\x27\x24\x86\x6f\xe3\x2a\x85\xa0\x7e\x26\xe7\x42\x16\x5a\xae\xcb\x24\x99\x57\x1c\x8c\x64\x0a\xa3\xbd\x41\x25\x41\x5b\x0d\xcd\x95\x70\x3b\x10\xfc\x7b\xdc\x36\x82\x50\x45\x36\x2c\xcf\x27\xe4\x3c\xcf\x31\x03\x68\x23\xd7\x43\x8d\xd7\xae\x63\x0a\x1e\xb7\x24\xcd\x16\x4c\x95\xe4\xc3\xec\x3f\xe7\x1f\xe1\xd4\x06\x3b\xc6\x96\x94\xd4\xc2\xd5\x7c\xfb\x0c\x9c\xff\x69\x05\x72\x42\x42\x4b\x9a\x8b\x85\x71\xab\x83\x9d\x96\xa7\x64\x95\xd3\x2d\xa4\xf7\x5f\x51\x09\x11\xa7\x89\xb1\xd1\x10\x59\x71\x48\x6c\xfc\xa6\x27\x4e\x3f\x2b\x08\xe5\x1e\x1e\xc3\x9a\x7c\xe1\x56\xef\xc9\xf0\xfa\xba\x47\x99\x64\xab\x9c\x76\x58\x15\xbc\x15\xfd\xe0\x81\x91\xb5\x98\x0b\x2a\xac\xe0\xcc\xd1\x98\x90\x99\x59\x3b\x05\x2d\x13\xe3\xd3\xfc\xad\x60\x25\x4d\x69\x49\x27\x5a\x17\xfc\xcd\x47\xc6\x89\x3c\xd5\x84\xba\x27\xba\xa3\xcd\x46\x5e\x6c\xbf\x10\xdf\xdf\x85\x5a\xa8\x75\xc5\x41\x3e\xb7\xfb\x31\x68\xc6\x38\x90\x3f\x41\xf7\xaf\x9e\xb5\x2a\x16\xf4\xa1\x79\x6d\xdd\xad\xe4\x5b\x19\x72\xbf\x27\xb8\x5a\x0b\x06\x69\x22\x1f\xf0\x26\x24\xfb\x04\x4c\xa8\xe7\x77\x97\xdd\xe6\xae\x7e\x93\x41\x8f\x89\xc0\x77\x0c\x04\x9a\x67\x0d\xcc\xf8\xc6\xf7\x0e\x58\x38\x0c\x00\x08\x0d\xb8\x84\xda\x6c\x30\xb6\xb0\x99\x30\x1f\xfa\x68\xea\x75\xdb\x47\xa2\xdc\x33\x31\x4e\x99\x3e\xa4\xd9\xd8\x35\xb6\xb3\x50\x9c\x8f\xa6\x17\x0d\xd6\x85\xf6\x32\x23\x0f\xe0\x10\x6b\x22\x75\x83\x1d\xeb\xd3\x8a\xb4\xef\xd8\xae\x0e\x68\xa8\x9b\x4a\x2f\xf0\xe8\x89\x6d\x4f\x14\xa2\x5e\x04\x57\xcb\x6c\x65\xe0\x8a\xe8\x86\xc0\xd9\x25\x3f\xd3\x3c\x4b\x1d\x09\xb3\xaa\xaf\xf9\x19\xb9\x13\xa5\xfe\x73\xf5\x9c\xa9\xd2\xa8\x9f\x97\x82\xa9\x3b\x51\xc2\x93\xa3\x74\xd5\x34\x61\x40\x47\x51\x01\x36\x96\x6c\xd8\x57\x0d\x35\xd9\x76\xe8\x1a\xd9\x9e\x1d\x94\x4c\x91\x6b\xae\x25\x02\xec\x91\x83\xf1\x2a\x24\x61\x31\x28\x5c\xf0\x31\xd8\xb8\x5b\x69\xe0\x40\x08\xe9\x8d\x43\x80\x1c\x92\x32\x01\x80\xf0\x26\x53\x96\x89\xbb\x33\x9b\x5a\xb3\x5b\x96\x90\x82\xc9\x05\x78\x6d\x92\x1e\xaf\x45\xac\x29\x32\xca\x00\xd9\x3b\x57\xc0\x32\x6f\x3a\x0d\x17\x7b\x93\xd4\x28\x6f\xd8\x52\x61\xac\x19\x7f\x68\xee\x03\x23\xf5\x27\x60\xb9\xd5\x84\x9c\xdb\x6b\x66\x9a\xef\xd0\x7b\xd5\x24\xa3\x29\x64\x8a\x68\x56\xb2\xa6\x39\x33\x59\xf6\x29\x77\x78\x2b\x31\xdf\x63\xec\x67\x88\xe9\xd6\x7b\xd6\x89\x4c\xa3\x27\xb6\x1d\x9d\xed\x4d\xed\xe8\x9a\x8f\x6a\xd0\x9d\x37\x99\x8e\x89\x82\xb4\x35\x82\x77\xa3\x97\x9f\x05\x41\x66\x19\x6f\x5e\xe9\x9d\x37\xf5\x94\xb5\xbb\x9f\x5b\x85\x8d\x0f\xea\xa3\x1e\x42\x70\xf9\x4a\x52\x08\x09\xe6\x4c\xfd\xb4\x99\xde\x43\x8b\xaa\x4f\xd9\x6a\x55\x67\x43\xa9\x56\x0b\x49\x53\x46\x16\x92\xae\x96\x43\xc5\x12\x23\xdb\xb4\x91\xff\xdb\x08\xba\x1d\x83\x1f\xd0\xe8\x82\xf5\x36\xec\x71\x29\xc4\x13\x40\xe1\x60\x21\xbc\xa2\xfd\xe1\x17\xf3\xad\xcb\xfa\x99\x55\x25\x15\x49\x59\x49\xb3\x1c\x62\x39\xee\x6f\x6e\x31\xda\xc3\x9e\xe3\xb6\x95\xed\x81\x13\x47\x50\x00\x68\x8a\x51\x48\x53\xb6\xce\xd8\x06\xad\x12\x5d\x71\x1a\x63\xb2\x60\x1c\x82\x13\x02\x41\x3c\x63\xa2\xb2\x94\x5d\x01\xf0\xb6\x9b\xd0\x01\x86\xf3\x8e\x36\xf7\x6d\xde\x30\x07\xef\xe5\xde\x11\xa7\xac\x53\x7f\xbf\x0a\x19\x48\x04\x14\x87\x03\x8e\xc3\xf8\x62\x24\xf9\x17\xf2\xc3\x0f\xdf\x77\x16\x2a\xe8\x73\x56\x54\xc5\x17\xf2\xef\xcf\x9f\xbf\xff\xdc\x5d\x2c\xe3\xa6\xd8\xbf\xba\xfb\x87\xbb\xed\x62\x7a\xf9\x0e\xc6\x3b\x75\xd1\x74\x61\xa7\x5c\x04\xa9\x39\xcd\xf2\x4a\x62\x1c\x67\xa4\x8a\xf0\x63\xb3\x0e\x38\x54\x6a\xe0\x03\xb5\x14\x6d\xb0\x17\x06\x81\xcd\x33\xce\x14\x5c\xe0\x52\x71\xc9\x12\xb1\xe0\xd9\xef\x2c\xb5\xf7\xb7\x40\x60\x07\x64\x7a\xb7\x4b\x9c\x30\x9e\x9a\x7b\x34\xf5\x99\xb7\xa4\x3c\xcd\x43\x0e\xff\x88\x9e\x36\x77\xf0\x41\x43\x06\x27\xcf\xa0\x01\xbb\xad\x6b\xec\x0c\x17\xdc\x06\x8a\xee\x27\x73\xa2\x99\x61\x3b\xa8\xa7\x86\x31\xce\x02\x8a\x75\x4b\x1b\xf7\xf4\x3e\xa3\xb2\xc2\xb3\xff\x55\x4c\x6e\x01\xe4\x51\x0b\xf6\x8d\x40\xb0\x87\x3a\x87\x80\xed\x06\x4a\x54\x26\x89\xcb\x8e\x2e\x5c\x0b\x31\x75\xb8\xc7\xce\xb7\xa1\x0e\x33\xee\x73\xeb\x48\x22\xe7\x84\x57\x79\xde\x55\x94\x8b\x90\xcb\xa9\x39\x76\x3d\xaa\x64\x9c\x8e\x17\x6b\x16\x68\x19\xe9\x37\x35\x0e\x34\x3b\x7e\x24\x51\xfe\x7d\x9b\x0b\x9a\x1d\x8e\x8a\xe9\x8c\x8f\xe7\x8c\x4b\x55\x13\x61\x46\x30\xbf\x21\x01\x9f\x91\x09\x66\x5e\xd3\xb0\x60\x7e\x83\xe2\x73\xe2\x8c\x0c\x2d\x4d\x7f\x77\xa6\x86\x17\x74\x3e\xc6\xec\xd0\xd2\xf5\x6f\xc6\x87\xbd\x01\x8f\x8d\x86\x1a\x10\x09\x15\x39\x93\x11\x46\x09\xf3\xfb\x66\x9a\x18\x74\x12\x45\x30\xe6\x61\x66\x8a\xe8\x59\x95\x2c\xe3\x6b\x61\x12\x3d\x0f\x92\xe1\xa6\x7b\x15\x77\x44\xb9\x0d\x70\x56\x94\xe5\x9c\xf0\xdb\x14\x69\xb5\x42\x4b\x2a\xd5\x6f\xec\x0e\xf7\x20\x8c\xfd\x38\x8a\x0e\xe2\xf7\xbc\xca\xd9\x2f\x59\xb9\xbc\xb7\x89\xdd\x71\x55\x97\xd5\x2a\x87\xce\x36\x5e\xe8\x25\x34\xad\x25\xc3\x6b\x73\x95\x18\x4b\x44\x51\x30\x9e\x9a\x20\xa2\x82\x3e\x31\x52\x5f\x57\xa9\x65\x3c\x10\x83\x81\x1c\x7b\x5e\x51\x5e\xcb\x89\x6b\xcd\xcb\x43\x2b\x2a\x72\x3d\xc5\x9e\xb5\xd1\xa0\x8a\x30\x98\xa2\x81\x86\xf0\x40\x13\xe4\x91\xe5\x02\x60\xd8\x26\x52\xd4\xc4\x32\x63\x51\x60\xc9\xf8\x14\x4f\x3d\x4c\xfa\xc8\xf8\xa2\xce\x25\xa5\x72\xb8\x58\x16\x39\xb0\xe0\x6c\x42\xa6\x28\xc2\xc4\x49\x45\x31\xec\x34\x92\x95\x46\x1f\x88\x75\x1e\x85\xc1\x23\x6b\xeb\x35\xc7\x76\x6d\x9f\xc5\x8c\xae\x2d\xfc\x4f\x1e\x5f\x77\xe9\xc2\xb0\xe1\xf5\xb7\x74\x7d\x2a\xb8\xb1\xdd\x61\x5e\x89\xb9\xb6\x18\x4c\x75\x63\x72\x31\xbd\x3a\x7f\xb8\x3a\x23\x3f\x7d\xbd\x84\xbf\x97\x57\x37\x57\xfa\xef\xc5\xfd\xdd\xdd\xd5\xc5\x83\x96\x23\x4e\x4d\xfa\x78\xad\xc6\xe9\xd1\xd5\xe7\x91\xf0\xb9\x05\xe5\x5b\x32\xaf\x4a\xcd\x0e\xea\x8f\x79\xad\xa0\xc6\x06\x40\xd3\x54\xab\x8c\x7f\xbb\x39\x6c\x1f\xf0\x5d\xb3\x49\xf3\xde\x0c\x93\x71\x1f\xc1\x52\xfd\x62\x52\xf4\x22\x89\x46\x1d\x78\x4d\x1e\xbd\x10\x6e\xf0\x2b\x27\x3f\x0a\x49\xf0\xa2\x31\xb8\x79\x32\x55\x27\x08\xea\xd0\xff\x9e\x98\x47\x9f\x72\xb1\x38\x71\x58\x0f\x46\x72\xb1\x20\xaa\x7a\x74\x18\x1c\x38\x4d\xa1\xf4\xa9\x2d\xe6\x41\x17\xce\x1c\x10\xa7\x51\xcb\x11\xf7\xea\x34\x0b\x34\xe9\x7e\x82\xdb\xc1\xbc\x92\xfa\xc1\x2e\xc1\xd3\x4f\xed\x2d\xb0\x82\x53\x26\x77\x6a\xfc\xca\xf5\x72\xdd\x64\x79\x9a\x50\x99\xee\xad\x59\x38\xdc\xcc\x94\xc3\xe8\x99\x94\xb9\xe6\x26\xe7\x9a\x38\x26\xba\x10\x6b\x26\x73\xba\x32\x11\xe2\x90\xb3\x18\x42\x8f\xe0\x23\x97\x6c\xc5\x00\x07\x65\x6f\x1a\x67\x3c\xc9\x05\xe4\xd4\x30\x27\xe3\x99\xdf\x75\x13\x8a\x64\x13\x0f\x22\x98\xa6\xde\x21\xa3\x77\xcb\xe6\x20\xcc\x78\xd0\xea\x35\x81\xc9\x9d\x89\x59\x1c\x6e\xc3\x28\x8d\x4e\xf2\x65\x64\x84\x28\xb3\xd1\x19\x19\xb9\xdc\x23\x29\x4a\xc9\xa3\xd3\x51\x5d\xa0\x89\x53\x02\x21\x19\x5d\x42\x63\xf8\x4e\x13\xcd\x08\x13\x6c\x1d\x57\xee\xd3\x75\xfe\x18\x7d\xb4\xa1\x11\x0b\xda\xe0\x13\x9a\x78\x0d\xd9\xfb\x6a\x0d\xb1\xeb\xfd\xa2\x6e\x7e\xa3\x7a\x09\x70\x74\x03\xd5\xc3\xc1\x91\x4c\xcf\x86\x0d\x48\x9b\x79\x8b\xc7\x39\xde\x9a\x09\x6e\x32\x49\x56\x54\x6a\x55\xc4\x96\xf4\xaf\x28\x3b\xed\xbd\xa0\x2c\x62\x11\x34\xfc\x2b\x91\x52\xfb\xcc\xd5\xb8\xc8\xa9\x52\x2d\x96\x57\x60\x04\x9a\x30\x61\x86\x32\xa1\xd6\xf9\x04\xf9\xa7\x97\x74\x1d\x48\x50\x10\xd1\xe8\x92\xca\x05\x2b\xc3\x9e\x11\xca\xb7\xf7\xc1\x94\x66\xe3\xe8\x24\xaa\xe3\xb8\xdd\xf4\x3c\xae\x13\x68\x8d\x33\x5e\x8e\x85\x1c\x9b\x2a\x5f\x48\x29\xab\x2e\x1f\x57\x99\x15\x4c\x54\xe5\x8c\x25\x82\xb7\x23\x1a\xb0\xdc\xd1\x5c\x3d\x03\x60\x1e\xe8\x6d\x3c\xb7\x62\x44\x33\x09\xa1\x55\xcc\x6a\x19\xc3\x7a\x18\xfd\x34\x2a\xf7\x37\xb7\x87\x4c\x36\x01\x18\x73\x78\x26\x7f\x46\xb6\xcf\x17\xae\xa5\xd8\xf2\x60\xb5\xdb\xaa\x1c\x5e\xe9\xc2\x79\xae\xc2\xa5\x71\x30\xc2\xa9\x30\x3a\xfb\xaf\x4a\x5a\x56\x7b\xab\xc1\x9b\x1b\x64\x96\x33\x03\x29\x43\x99\x7e\x06\xf5\x9a\x46\xbe\x7d\xfc\xbf\xc9\x29\x02\xe5\x6c\xb0\xe2\x84\x60\x45\xbd\x3f\x4b\x49\x33\xa3\x40\xd2\xa4\xac\x00\x9b\x4c\x4b\x0c\x6c\xc4\x04\x38\xdf\xb5\x75\xa3\x55\x65\x0c\xa9\x89\x09\x93\xa5\xba\xa1\xaa\xfc\x69\x95\xd2\x0e\xf4\xd2\x4e\xc0\xa2\x2a\x61\xc3\x18\xc1\x7a\xc3\x59\xaa\x39\x3c\x0e\x81\xa1\x47\x36\x9a\xf5\x56\x86\xe2\x50\x4f\x7e\xbd\x81\x74\xf5\xb1\xfe\x54\x7b\xab\xa7\x42\x8f\xc9\x79\x2b\x03\xf2\x43\x35\xfa\x5a\xab\x8f\x13\x09\xd4\x08\x67\xcf\x6d\x1a\xf7\xe1\x2d\xce\x19\xe5\xed\xe1\xf2\x3b\x2b\x0a\xca\x0d\x5f\x43\xf8\x01\xb2\x59\x66\x5a\x64\x35\x28\x2f\x45\xac\x08\x95\xb2\x9c\x75\x80\xbd\x0e\x0c\x25\xc5\x2f\x5c\xe2\x07\xa2\xc2\x9c\xbe\xfa\x75\x9c\x41\x1f\x85\x70\x04\x4f\xd4\xc2\x32\x4a\x0f\x4e\x6b\xda\xed\x15\x88\x2f\x8f\xb9\x48\x9e\x4c\x42\x30\xc0\xf3\x67\xbf\x33\x69\xe3\xce\xeb\xcb\xc0\xf0\x86\xaa\x85\xbd\x7d\xd3\x8e\x9b\xbd\x8e\x08\xa8\x68\xda\x7a\x00\x1d\x7d\x21\x6b\xcb\x62\xc5\x11\x3d\xf7\x36\xa1\xab\x56\x51\x81\x78\x7d\xcf\x73\xb0\xaf\xb3\x98\xdc\x21\x90\xaf\x10\x55\x46\x5a\x20\xba\xe5\xd3\x7f\xbb\x91\x20\x47\x0d\x47\x0d\xe1\x51\x4c\x09\x18\x3e\x9e\x04\x53\xcd\x04\x91\x2b\xb1\x96\xaf\x1e\x84\x0a\x89\x17\xd2\x5d\x93\x63\xa8\x1d\x35\xb8\xf0\xe8\xde\xbe\x4e\x18\x40\xfd\x1b\xe2\xc3\x8b\x4d\x94\x3a\xc8\xcb\xc4\x87\x24\xb4\xf4\x93\x87\x38\xb5\x03\x41\x9e\xc6\x13\x3f\x17\xb2\x53\x81\x39\x5e\xe3\xc3\x78\xa6\x5e\x42\x5a\xfa\xec\x8e\x5d\xdb\x07\xef\x68\xee\xe5\xaa\x9c\x11\x4a\x96\x99\x2a\x85\x44\xd7\x1a\x5c\x26\x26\x29\x5c\x76\xda\x1e\x03\x76\x9c\x68\xb8\x0b\xd7\x04\x42\x57\x2b\x46\xdd\x3d\x43\x78\x36\xc1\x45\x41\x92\x25\x42\xa6\xad\x0d\xb3\xda\x7d\xab\x2c\xd5\xfa\xf9\x23\x60\x33\x73\xaa\xca\x07\xd7\x06\x2d\x20\x44\x72\x63\x5f\xfc\xc1\x2e\xd6\xbd\xb1\xe9\x5c\x04\xaf\x5f\x0a\x42\xb9\xb1\x6a\x1c\x26\x83\xf7\x0b\x19\x75\xdf\x8c\x34\xf7\xa2\x7e\x6d\x9c\xe4\xd6\xe8\xe2\xdb\xb4\xbc\x60\x4a\x05\x81\x46\x3b\x41\x1a\x90\xd3\x97\xb8\x9c\xbe\x58\xdd\x1e\xf6\x46\x40\x30\xe1\x98\x36\xeb\xd6\xb6\x7b\xa9\x11\x10\x13\x8c\x41\xc1\x6d\xab\x83\xa6\x6c\xb5\xa4\x2a\xb6\x33\x6e\x17\xb9\x10\xdf\xe8\xed\x10\xd9\x1a\xc9\xa8\x0a\x41\x25\x77\xc6\xf6\x51\x66\x6c\x4e\x2e\x68\xc1\xf2\x0b\xaa\x8e\x39\xb8\xc0\x01\x26\x84\x4d\x16\x13\x72\x32\x6d\x78\x5b\xef\x44\x79\x1b\xba\x73\xa1\x27\x3b\x40\xcc\x8e\x7e\xd5\xbd\x7c\xb0\x92\xd0\xbf\x73\x0f\xdc\xb3\x07\xb7\x30\xb0\x43\xdf\xc5\xde\x0c\xe3\x7d\xbb\xf6\xa3\xbf\x13\x2b\x09\x16\xbf\xe4\xa5\x3b\xb2\x07\xcc\xd8\xb5\x0b\xdf\xf3\xfe\xeb\xe9\x92\x23\x31\x6b\x35\x99\xec\xf5\xee\xc1\xd3\x5c\xc1\xec\xdf\x0c\xb0\x33\xb7\xfd\x67\x4a\xab\x60\xc7\x14\x5b\xfe\x5a\xb0\x3d\x4e\x60\xe7\xfb\x80\x5c\x3e\x0e\x9f\xc2\x87\x02\xf9\x53\x70\xb4\xe8\x15\xf0\x96\x01\x18\x97\xf6\xab\x68\xeb\x70\x99\x76\xe1\x7f\x73\xbc\xd1\x0c\xcb\x78\xeb\xe3\x03\xdc\x1d\xc7\xd6\xe6\xc2\x46\x00\x7c\x30\xc2\x99\xd2\x9b\xe2\x63\xe0\xf3\x91\x0a\x55\x9c\x32\xd5\xaf\xe8\xf6\x2a\xb1\xa4\x7f\x6a\x6d\xa1\xd0\x04\x9b\x5f\xac\xce\x16\xa1\x13\x0f\x50\xd6\xfa\x35\x9e\x01\xc4\x7a\xc5\xbf\x81\xf4\xda\x0d\xb8\xbb\xbf\x9d\xcc\xbe\xba\xca\x14\x98\xb4\x71\x0c\x27\x9a\x03\x27\x90\xef\xd9\xf0\x6e\x64\x4f\xbe\xfd\x76\xba\xcb\x03\x21\xdc\xd0\x5f\xe1\xc7\xea\x56\x55\x65\xc7\x1b\xf3\xde\x0c\x1a\xd1\xf4\xde\x41\x3a\x90\xde\x05\xf4\xba\x89\x0a\xcc\xaf\x6f\xd5\xfd\xf5\xeb\x2d\x26\x21\x53\x70\x8d\xbd\x52\x66\x16\xc5\xe4\x9a\xa5\x9e\xa7\x0e\xf3\xae\xfb\xcf\x1a\x7e\xdb\x9a\x3e\x0e\x3b\xf9\xe3\xcf\xef\xfe\x1f\x00\x00\xff\xff\x1b\xfd\x79\x5c\xe0\xce\x07\x00") +var _operatorsCoreosCom_clusterserviceversionsYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xfd\x7b\x73\xe3\x36\x96\x30\x8c\xff\x3f\x9f\x02\xe5\xc9\x3e\xb6\x67\x24\xb9\x7b\x6e\xbf\x99\xfe\xcd\xbb\x29\xaf\xed\x24\x7e\xd3\xed\x56\xd9\x4e\xe6\x99\x4a\xb2\x59\x88\x3c\x92\xb0\x26\x01\x2e\x00\xca\xd6\x3c\x79\xbe\xfb\x5b\x38\x00\x48\x50\x17\x5b\x12\xd9\x6d\xd9\x01\xa6\x2a\xd3\x16\x49\x10\x3c\x38\x38\xf7\x0b\x2d\xd8\xf7\x20\x15\x13\xfc\x1d\xa1\x05\x83\x07\x0d\xdc\xfc\xa5\x06\x77\x7f\x55\x03\x26\x4e\x66\x6f\x7f\x73\xc7\x78\xfa\x8e\x9c\x95\x4a\x8b\xfc\x1a\x94\x28\x65\x02\xe7\x30\x66\x9c\x69\x26\xf8\x6f\x72\xd0\x34\xa5\x9a\xbe\xfb\x0d\x21\x94\x73\xa1\xa9\xf9\x59\x99\x3f\x09\x49\x04\xd7\x52\x64\x19\xc8\xfe\x04\xf8\xe0\xae\x1c\xc1\xa8\x64\x59\x0a\x12\x27\xf7\xaf\x9e\xbd\x19\xfc\x6d\xf0\xe6\x37\x84\x24\x12\xf0\xf1\x5b\x96\x83\xd2\x34\x2f\xde\x11\x5e\x66\xd9\x6f\x08\xe1\x34\x87\x77\x24\xc9\x4a\xa5\x41\x2a\x90\x33\x96\x80\x7b\x5e\x0d\x44\x01\x92\x6a\x21\xd5\x20\x11\x12\x84\xf9\xbf\xfc\x37\xaa\x80\xc4\xac\x62\x22\x45\x59\xbc\x23\x2b\xef\xb1\xf3\xfa\xc5\x52\x0d\x13\x21\x99\xff\x9b\x90\x3e\x11\x59\x8e\xff\x76\x40\xb0\xaf\xbf\xb1\xaf\x77\x90\xc3\xeb\x19\x53\xfa\xdb\xf5\xf7\xbc\x67\x4a\xe3\x7d\x45\x56\x4a\x9a\xad\xfb\x10\xbc\x45\x4d\x85\xd4\x57\xf5\xb2\xcc\x32\x12\x35\x0b\xff\xed\x6e\x64\x7c\x52\x66\x54\xae\x99\xed\x37\x84\xa8\x44\x14\xf0\x8e\xe0\x64\x05\x4d\x20\xfd\x0d\x21\xfe\x5d\x76\xf2\x3e\xa1\x69\x8a\x1b\x49\xb3\xa1\x64\x5c\x83\x3c\x13\x59\x99\xf3\xea\xe5\xe6\x9e\x14\x54\x22\x59\xa1\x71\xb3\x6e\xa7\x80\x50\x23\x62\x4c\xf4\x14\xc8\xd9\xcd\xf7\xd5\xad\x84\xfc\xb7\x12\x7c\x48\xf5\xf4\x1d\x19\x98\x0d\x18\xa4\x4c\x15\x19\x9d\x9b\x25\x04\x77\xd9\xdd\x3c\xb7\xd7\x82\xdf\xf5\xdc\xac\x57\x69\xc9\xf8\xe4\xb1\xf7\xbb\x8f\xd8\x6c\x09\xb3\x60\x9f\xc2\xd7\x7f\xbf\xf4\xfb\xa6\xaf\xf7\x9f\x4f\xcd\x9b\x89\x9e\x52\x4d\xf4\x94\x29\x22\x38\x10\x09\x45\x46\x13\x50\x8f\x2c\x68\xc5\x2d\x76\x45\xd7\xcb\x17\xd6\x2c\x29\x9c\x52\x53\x5d\xaa\x41\x31\xa5\x6a\x19\xc4\xc3\x85\x5f\x57\x4c\x67\x6f\x9c\xbd\xa5\x59\x31\xa5\x6f\xdd\x8f\x2a\x99\x42\x4e\x6b\x1c\x10\x05\xf0\xd3\xe1\xe5\xf7\x7f\xbc\x59\xb8\x40\x9a\xd0\x59\x89\xfd\x84\x29\x03\x2a\xa4\x20\xc4\x93\x10\xdc\xbb\x79\x01\xe4\xbf\x56\x3e\x73\x53\x40\xf2\x5f\x83\xa5\x95\x8b\xd1\x7f\x43\xa2\x83\x9f\x25\xfc\x4f\xc9\x24\xa4\xe1\x8a\x0c\x80\x3c\x59\x5a\xf8\xd9\xc0\x3f\xf8\xa9\x90\x86\x2c\xe8\xe0\xc8\xdb\x11\xd0\xc5\xc6\xef\x0b\x5f\x7b\x68\x40\xe2\xbe\x31\x35\x24\x11\x14\xe2\xa3\xc3\x38\x48\x1d\x1c\x2d\x9e\x32\x65\x90\x43\x82\x02\x6e\x89\x24\xa2\x10\x77\xdf\x34\x20\x06\x00\x20\x95\x21\x00\x65\x96\x1a\xda\x39\x03\xa9\x89\x84\x44\x4c\x38\xfb\x57\x35\x9b\x22\x5a\xe0\x6b\x32\xaa\x41\x69\x82\xa7\x96\xd3\x8c\xcc\x68\x56\x42\x8f\x50\x9e\x92\x9c\xce\x89\x04\x33\x2f\x29\x79\x30\x03\xde\xa2\x06\xe4\x83\x90\x40\x18\x1f\x8b\x77\x64\xaa\x75\xa1\xde\x9d\x9c\x4c\x98\xf6\x54\x3f\x11\x79\x5e\x72\xa6\xe7\x27\x48\xc0\xd9\xa8\x34\x84\xf3\x24\x85\x19\x64\x27\x8a\x4d\xfa\x54\x26\x53\xa6\x21\xd1\xa5\x84\x13\x5a\xb0\x3e\x2e\x96\x23\xe5\x1f\xe4\xe9\x6f\xa5\xdb\x64\x75\xb8\x00\xbe\x95\xe8\x4c\x3c\x81\x7d\x14\xd6\x86\xbc\x5a\x4c\xb2\x8f\xdb\x6f\xa9\x41\x6a\x7e\x32\x50\xb9\xbe\xb8\xb9\x25\x7e\x01\xee\x5c\x22\x84\xeb\x5b\x55\x0d\x6c\x03\x28\xc6\xc7\x20\xed\x9d\x63\x29\x72\x9c\x05\x78\x5a\x08\xc6\x35\xfe\x91\x64\x0c\xb8\x26\xaa\x1c\xe5\x4c\x2b\xc4\x39\x50\xda\xec\xc3\x80\x9c\x21\xd3\x23\x23\x20\x65\x91\x52\x0d\xe9\x80\x5c\x72\x72\x46\x73\xc8\xce\xa8\x82\x4f\x0e\x6a\x03\x51\xd5\x37\xe0\xdb\x1c\xd8\x21\xcf\x5e\x7e\x60\xe9\x8c\x11\xe2\x79\xe9\xda\xdd\x59\x7b\x86\x49\x0a\x49\x46\xa5\x15\x0a\x88\x86\x2c\x23\x1f\xdf\x7f\x20\x53\x71\x6f\xb0\x98\x71\xa5\x69\x96\xe1\x29\x70\xfc\xd9\x92\xd3\x84\x72\x92\x53\x4e\x27\x40\x68\x51\x28\x32\x16\x92\x50\x32\x61\x33\xe0\xfe\x74\x0d\x36\x5d\xfc\x3a\x22\x41\x2c\x71\x5f\xc9\xa0\xfc\x55\xb7\xc0\x85\x2b\xeb\xc8\x86\x19\x4b\x32\xd0\x23\x50\x3b\xad\xef\x45\xcc\xe6\xa4\xe4\x4a\xcb\x12\x37\x3b\x25\x77\x30\x77\x48\x9e\xd3\x82\x28\x2d\xcc\x8f\xf7\x4c\x4f\x09\x0d\x11\x9c\x6a\xc4\xe2\x11\x10\x05\x9a\x8c\xe6\xc4\x88\x71\x48\x10\xb4\x10\x19\x52\x0b\x7c\x16\x09\x83\x04\x2d\x19\xcc\x80\x50\x39\x62\x5a\x52\x39\xaf\xb0\x61\x11\xa0\x4f\x00\x15\x3f\x36\x10\x1e\xd6\x83\x84\x3c\x86\x8b\xc4\x92\x5b\x27\xbb\xa4\x95\x60\xb9\x01\xf4\x86\x97\x0e\xdf\x6a\x71\x54\x39\x7c\x03\x45\x0c\x5e\x39\xf9\xa0\x92\x6b\xf1\x4d\x0e\xb1\x52\x22\x64\x85\x19\x06\x6c\x21\x12\x8e\xc0\x90\x13\x49\xb9\xb9\xb0\x12\xb9\x77\x80\xd6\x63\x68\x63\x86\xb8\xe7\xab\x70\x34\x9c\x9b\x4a\xd9\x10\x98\xc2\xc1\x34\xe4\x6b\x66\x7e\x14\x76\xd5\xcf\x66\x81\x33\x96\x82\x01\xa2\xa6\xcc\xa2\x8e\x39\xad\x74\x24\x4a\x6d\x61\xe7\x6e\x49\xc9\x8c\x51\x42\x27\x13\x09\x13\x44\xe0\xb5\xaf\x7d\x02\x26\x76\xac\x3f\xa0\xf5\xe8\x5b\x49\xfe\xd1\x3b\x0c\x19\x7c\xf4\x06\xbe\xea\x98\x87\x37\x2c\x0b\x8b\xcd\xf1\xd4\x1e\xda\x41\x13\x03\x13\x0f\x5a\x21\x1f\xbd\x79\x93\xbd\xb5\xe3\x89\x1d\xb6\xa3\xb9\xcf\x0b\x0b\x71\x57\x47\xe6\x7c\xd4\xa4\xd9\x90\x03\xbc\xb1\x26\xbe\x23\x20\x05\xc8\xb1\x90\xb9\x39\x28\x9c\x50\x92\x58\xf9\xad\x22\x3c\x48\x1a\x79\xf2\x18\x38\xc9\xa6\xfb\x6f\xc7\x26\x58\x60\x47\x9f\x14\x54\x4f\x9f\xb8\x6d\xb3\xad\xb2\x23\x04\xda\x93\x37\x3f\x41\xcd\x96\xe6\xae\x39\x4c\xe7\x73\x1b\x30\x74\x3e\x29\xf2\x9c\x4d\x66\x6d\xa0\xda\x35\xbd\xff\x00\x4a\x19\x96\x8d\x52\x9a\xa4\xf7\x04\x78\x22\x0c\xb1\xf8\x7f\x6f\x3e\x5e\xd9\x69\x07\xe4\x52\x13\x96\x17\x19\xe4\x46\x10\x23\x1f\xa8\x54\x53\x9a\x81\x44\xee\xf4\x1d\xcf\x1b\x7f\x3b\x4c\x2c\x15\xa4\x86\x16\xa5\x90\xd1\xb9\x9d\x2c\x85\x44\xa4\x86\x46\x0b\x49\x0a\x23\xe0\xe6\x45\xa9\x81\x50\x7b\x15\xdf\xcb\xf8\x64\x15\x91\x6e\x05\x1a\x62\x24\x91\x9c\xea\x77\x64\x34\xd7\x4f\xa1\x3e\x21\x0f\xfd\x74\x53\x1a\x10\x2e\xe6\x69\x4a\x60\xc7\x46\xf4\x20\x9c\xf8\xc9\xaf\x34\x42\x28\x65\x1c\xe4\x50\x48\xbd\x09\xd1\x32\xca\xc7\x04\xe4\xa3\x77\x7a\x90\x31\xae\xff\xf8\x87\x47\xee\x4c\xa1\xc8\xc4\xdc\xe0\xc5\xd3\x67\x65\xc3\xef\xd9\xf8\x5c\x6f\x3a\xdf\xa6\x67\x79\xc3\xf9\xac\x71\xaa\x8b\x99\x56\x29\x50\x3b\x4d\xc4\xbb\xfa\xb6\x4a\x09\x7c\x36\xe6\x37\xbc\xf4\xd6\x86\x6b\x18\x83\x04\x9e\x78\xda\x54\xfd\xa9\x05\xa1\xe4\xdb\x72\x04\x92\x83\x06\x15\xc8\xd5\xf3\x02\xbc\x69\x07\xec\x03\x12\x24\x29\x35\xcb\xd8\xbf\x40\x3d\x45\x59\x3e\x11\xdb\x7b\x42\xc0\xf1\xb7\x3d\x21\xe6\xf8\xdb\x9e\x12\x76\xec\xd8\x86\x8f\x3e\x8d\x85\x76\x34\xf6\x09\x35\x7b\x27\xaa\x57\x3b\x93\x36\xb7\xa2\x73\x4a\xfe\x34\x9a\xaf\x58\xe9\x10\xcd\xb7\x0d\xf3\xe7\xba\x05\x93\xa3\x75\x26\xf3\x81\xd1\x8b\x07\x68\x94\xfd\xe1\xa7\x81\x9d\xf2\x78\x40\x2e\xf2\x42\xcf\xbd\x6d\x83\x3d\x31\x39\x53\x84\x0b\xbd\x2c\x95\x75\x0e\xa6\xd9\x6a\x33\xd8\x93\x90\x3a\x1d\x5e\x7a\x03\xeb\x67\xdc\x5a\x55\x40\xb2\x07\x52\xf7\x4d\x63\x19\x0d\x99\x7b\xcc\x20\x4b\x09\x33\x02\xb5\x59\x2c\x19\x65\x22\xb9\x73\xb6\xe4\xeb\x73\xa2\x84\xa5\x39\x46\xeb\x32\xc2\x4f\x22\xb8\x2a\x73\x20\xec\x29\x22\x12\xc5\xec\x28\x66\x47\x31\xfb\xa5\x88\xd9\xd6\x67\xb3\x0f\x94\x6a\x61\x21\x6b\x69\x15\xde\x17\xa9\xd5\x63\x23\x52\x2b\x1c\x91\x5a\x3d\x31\x5e\x1c\xb5\xda\x48\x06\x7c\x72\xae\xa7\x0e\x72\x34\x70\x47\x03\x77\x34\x70\xbb\x11\x79\x99\x1b\x91\x97\x45\x5e\x16\x0d\xdc\x8f\x4d\x19\x0d\xdc\x5b\x4e\x14\x0d\xdc\xd1\xc0\xdd\x18\xd1\xc0\x1d\x0d\xdc\xd1\xc0\x1d\x0d\xdc\x6b\x46\x14\xb3\x77\x9c\x34\x8a\xd9\x8f\x8c\xd7\x2d\x66\x47\x03\x77\xa4\x56\x91\x5a\x45\x6a\xf5\x32\xa8\x55\x7b\x03\x77\x92\x01\xe5\xab\x15\xdd\x85\x3c\x09\xbc\x0f\x45\x23\x36\x66\x2e\x5f\xc8\x3d\x4d\x46\x30\xa5\x33\x26\x4a\x49\xee\xa7\xc0\x7d\x6a\x1b\x99\x80\x56\x06\x0b\x40\xc3\x2a\xdd\xe8\x09\x5a\xf3\x38\x7d\xe9\x13\xe0\x74\x94\xad\x9c\xf8\x29\x52\xe2\x9e\x7c\xdc\xa0\x3f\x12\xc2\x7c\xdd\x32\xc4\x50\xae\xf7\x72\xf2\x36\x71\xff\x07\xeb\xf4\x8e\xd5\xc1\xff\x67\xd7\xe7\x5d\x85\xfc\x93\x1f\x39\xb9\xac\x66\x25\xe8\x2d\xc0\x84\x22\xc3\x43\xcc\xaf\x1f\xef\x39\xa4\x98\x0c\xda\x23\x4c\x9b\x1b\xcc\xa1\x67\x09\xd3\xd9\xbc\x7a\xf1\xe0\x60\xfb\x4d\xdc\xa3\xd4\x81\xb3\xeb\xf3\xcd\x5d\x2a\x7e\x03\x3e\x87\xf7\x24\xfa\x46\xa2\x6f\xa4\x1a\x51\x0c\xda\x71\xd2\x28\x06\x3d\x32\x5e\xb7\x18\xb4\xef\xbe\x84\xe8\x01\x20\xd1\x03\xe0\x6f\x8b\x1e\x80\xe8\x01\xe8\x06\x4c\xd1\x03\x10\x3d\x00\x8f\xdf\x14\x85\xc9\x1d\x27\x8d\xc2\xe4\x23\xe3\x75\x0b\x93\xd1\x03\x10\xa9\x55\xa4\x56\x91\x5a\xbd\x0c\x6a\xf5\x12\x43\xdc\xa3\x21\x36\x1a\x62\xa3\x21\x36\x72\xa3\xc8\x8d\x9e\x18\x2f\x8e\x1b\x45\x43\xec\xb6\x13\x45\x43\x6c\x34\xc4\xae\x1b\xd1\x10\x1b\x0d\xb1\xd1\x10\x1b\x0d\xb1\x8f\x8f\x28\x4c\xe2\x88\xc2\xe4\x13\xe3\xc5\x09\x93\xd1\x10\x1b\xa9\x55\xa4\x56\x91\x5a\xbd\x0c\x6a\xd5\xde\x10\xfb\xc4\x49\x6a\xa0\x4c\x68\x3f\x75\x92\xa3\x8f\x07\xc6\xca\xfe\x84\xf1\x24\x2b\x53\xc0\x2b\x63\xa0\xba\x94\xa0\x7a\x24\x63\x39\xf3\x75\xdb\x85\x34\xd8\xd1\x4f\xa8\x02\xb5\x34\xc7\x8a\xf7\x3f\xbe\xf6\xc7\x4f\xea\xa3\x7d\x58\xaa\x40\x66\xc6\xfd\x3c\x0e\x57\xb6\x5e\x06\x4b\x36\x80\x9d\x79\xbf\xb9\x11\x6b\xf3\xdb\x36\x0b\x4f\x7e\xf6\x3a\xbc\x7a\x04\x8f\x9e\x24\xdf\x4f\x11\xed\x3e\x19\x51\x05\x7f\xf9\xd3\x52\x37\x90\xf0\x96\x1c\x52\x46\xcd\xab\x56\xde\xf1\x34\x21\xaf\x5f\xb1\x1e\x73\x37\x38\x01\xd5\x32\x76\x9c\xc5\xb5\x2b\x78\x72\xef\x0c\x82\xa5\x97\xf6\xe6\x1b\x2d\xa9\x86\xc9\x3c\x68\x8f\x81\xf8\x54\xf3\x5f\xbe\xa6\xad\x4b\xa5\x59\xdd\x4f\x41\xda\x33\xe2\x1b\x3a\x28\x3f\x29\x53\x55\xae\x43\xba\x43\xc9\xfc\xa7\x92\x17\xfc\x7b\x56\x5c\x7e\x6a\xd3\x56\xf5\xb4\x58\x09\x2c\x0f\xa0\x73\xeb\x57\x39\xaf\x8a\x38\x2c\x42\xac\xa0\xd2\xf0\x09\xef\x7f\x41\xd1\x25\xb8\x7b\x01\xde\xeb\x58\xc3\x06\xf2\xca\xd3\x72\x4a\x3f\xa8\x35\xb1\xce\xe7\xb3\x89\x78\xe2\x3a\x4b\x0d\x41\xe6\x4c\xa9\x75\xe9\x19\xcd\xa5\x3f\xc5\x3c\x36\x60\x1a\x6b\xe0\xef\xbf\x28\x58\x4e\x25\x44\x5a\xb5\x7f\x44\x13\x22\xcb\xcc\x88\x94\x3c\x25\xae\xa9\x04\xa1\x49\x22\x4a\xae\x09\x07\x48\x6d\xe2\xc7\x2a\x5c\xdd\x80\xe5\x6c\x20\x45\x6e\x2a\x43\xf6\xed\x3a\x9f\xbc\xcb\x7d\xc3\xa9\xfd\x84\x95\x6d\x4a\xc2\xb1\xb9\xcc\x89\xaf\x7f\x9a\x77\x6f\x23\x10\x6c\x2c\x0e\x34\x0d\x5d\x22\x63\xc9\xfc\xba\xcc\x80\x4c\x45\x96\x2a\x6c\x96\x63\xf8\x56\xe5\x0a\x0b\x15\x85\x02\xef\xc6\xd5\xf7\xc8\xa8\xd4\x24\x15\x60\x0d\x54\xae\xb4\x4b\xe3\x71\xeb\xfc\xbc\x9f\xda\x86\x49\xe6\x21\x42\x8b\x22\xc3\xc4\x2b\x61\x78\xf7\xfd\x94\x25\x53\xdb\x05\xae\xa0\x09\xac\xba\x6d\x73\x19\x6e\x23\x25\x83\x6c\xa5\x68\x10\x6f\x3c\x1d\x3d\x85\x2a\x64\x4b\x8d\x83\xd8\xc6\x2b\x5f\x4b\x51\x16\x1b\xde\xbe\x6c\x77\xb3\x4f\x1b\x2a\xaf\x17\xc4\x11\x7f\xd1\x39\x33\xed\xde\x28\x67\x9c\x73\xc6\xfa\x01\x21\x97\x63\x92\x97\x99\x66\x45\x86\x8f\xd8\x7a\x31\x8a\x50\x09\x35\xdf\xe8\x11\xca\xe7\xde\x37\xea\x9a\x2f\x41\x4a\xe8\xc4\xcc\xa8\xb1\xeb\x9a\x6f\xf4\xc2\xcb\xdc\xc8\x20\x81\xd9\x4f\xa1\x52\xc9\xe7\xf5\xec\xe4\x9e\x65\x99\x91\xea\x69\x96\x89\x7b\x48\x07\xe4\xe0\x60\x91\x94\x27\x42\x06\xeb\x41\x62\x72\xf0\xbb\xc6\x5d\x86\x72\xd4\x0b\xde\x04\x47\xc8\xd6\xe2\x35\xd9\x4e\xc4\x26\xdb\x2b\x13\x84\x70\xc1\xbd\xd9\xf8\xbb\xeb\xf7\xbb\x21\xc2\x55\x73\x0e\xd7\xa5\x0b\xb4\xd9\x96\x82\x4a\xcd\x68\x46\x4a\x99\x29\x8b\x0b\xd4\x08\xcc\xd2\xb7\x39\x9b\x52\xf4\x7b\x27\xa0\x6c\x3f\x2d\xf2\x3b\xbb\xfb\x6e\x73\xec\x19\x17\x3c\x9b\x13\x6a\xb7\x66\x5c\x66\x59\x8f\x8c\x19\xa7\x86\x74\x43\xe1\x73\xef\x8c\x26\x4a\x6e\x18\x4f\xc0\x7c\x53\xbf\x12\x4e\x70\x45\x66\x46\x43\x23\xaa\x83\x9e\xf6\x5c\xc3\x2f\x6b\x77\x50\xee\x15\xe6\xd0\x27\x74\x94\x01\x4a\xb5\x4e\xec\xb9\x16\x19\x7a\x6b\x2a\x93\x32\x76\x09\xa3\xe1\xe5\xff\x60\x1c\xd5\x3d\x72\x8d\xcc\xc7\xa8\x8d\xc0\xf4\xd4\x68\x91\x45\x91\xcd\x0d\xb1\x31\xc8\x52\x23\xe5\x91\x2a\x93\xa9\xf9\xa4\x83\x42\xa4\xea\xc0\x90\xa2\x03\x05\x89\x04\xad\x0e\x8e\xcd\x5f\x8b\xdf\x80\xdf\x17\x3e\x77\x42\x0b\x76\x70\xdc\x23\x08\x20\x6c\x41\x26\xf4\xf4\xe5\xe2\xa1\xff\xd6\x46\xe7\xcb\xa7\x46\x53\xff\x0f\x67\x70\xfd\xb4\x44\x61\xdb\x53\x19\x3a\xaf\x01\x33\x33\x0d\x52\x22\x1a\x04\x1e\xb7\x05\x82\x4f\xc8\x29\x27\x60\x7d\x24\xa0\x49\x0e\x94\xbb\xbb\x61\x06\x72\xae\xa7\xe8\x36\x51\x15\x01\x79\xf1\x40\x6f\x07\x70\x77\xe0\x3d\x70\x6b\x24\xb7\x3d\x0f\x17\x81\x7b\xf8\xbb\xc3\x45\x42\x5a\x73\x84\x17\x0b\x4a\x64\xd1\x3b\x81\xf1\x7b\xf3\x64\x13\x84\xf6\x27\x4b\x2d\x2b\xfa\xf1\xfe\xbd\xed\x6f\xe8\x60\xf5\x2d\xe3\xa9\xaa\xea\xd9\xa5\x96\x0c\x3a\x78\xaf\x04\x32\xae\xf0\x25\x02\x78\x59\x04\xde\x54\x6c\x7d\x62\xfa\x40\x47\xda\x07\xb5\x06\xfb\x25\x36\x24\x25\x43\xa7\x7a\xd6\x79\x67\x44\x90\x8c\x8e\x20\x53\xce\xe0\x02\xc1\xf2\xc9\xe9\xfb\x0f\x55\xdf\x50\x09\xf4\x09\xcb\xe0\x27\x50\x66\x36\x88\x02\x58\xea\xbe\xba\x3c\x36\x97\x5f\x11\x14\xdb\x99\xd5\xc9\x0d\x68\x7b\xcc\x72\x5a\x98\x53\x66\xe7\x58\x69\x15\x7e\x8f\x90\x7e\xfa\xb0\x6c\x25\xf7\x6f\xde\x2d\x71\xd5\x4b\x36\x3a\x2a\x9b\x45\x1a\x6c\x73\xf6\x1e\xb1\x92\xd4\x63\xc1\xa8\xda\x40\x68\xa7\x1b\x38\x69\x3e\xa1\xa1\xb1\x35\x05\x65\x4b\x31\xd8\xc2\x17\xd2\xff\x5e\x4f\xd1\xf1\x16\x6c\xa3\x78\x19\xdd\x3b\x83\x44\x8b\xc7\x8b\x7f\xfa\x9b\x35\xe4\x45\xf6\xd4\xc9\x23\x5b\x2b\x69\x39\xe3\xd7\x40\xd3\xf9\x0d\x24\x82\xa7\x1b\x12\xd8\xc6\x7e\x7c\x60\x9c\xe5\x65\x4e\x78\x99\x8f\x00\x41\xac\xec\x5c\x48\x48\xac\x02\x4c\x09\x87\xfb\x6c\xee\x88\x47\x4a\x0a\x91\x7a\x7a\x32\x32\x0a\x1b\x4d\xe7\xd8\x79\x14\xcb\x64\xf3\xb9\x99\x84\xe9\x9a\xfb\x48\x92\x48\xaa\x8c\x58\xd4\xc3\x49\x99\x36\x1c\x6b\x04\xe8\xa5\x63\x29\x98\x3d\xa6\x33\xca\x32\x23\x5a\x0f\xc8\x39\x8c\x69\x99\x61\x03\x5d\xf2\x86\x1c\x99\x97\x79\x9d\x6c\xd5\x03\x46\xdc\x55\xc2\x68\xf3\xca\x55\xd5\xc0\x05\x1d\x6f\xe1\x77\xd8\xa4\x8a\xab\x1f\x9b\x56\x73\xf5\xa3\xa0\xa5\xda\x54\x95\x6f\x6c\xcc\x25\x4f\xcd\x79\x08\x25\xd1\x80\xa4\x33\xe5\x66\xde\x8c\x65\x3f\x5e\x6d\x65\xc5\xaa\xa5\x98\x48\x50\xea\x1c\x68\x9a\x31\x0e\xbb\xe3\xd7\xed\x14\x48\x4e\x1f\x10\xc7\x34\xcb\xc1\x48\x22\x21\x86\xd1\xf0\xab\xb4\x20\x39\xbd\x83\xea\xf5\x64\x04\x63\x6c\x90\x8c\x1f\x1c\xec\xbe\xc5\x9f\x31\x65\x99\xd1\xd0\x6f\x9b\xb0\xc1\x5e\xc9\x22\xcb\x40\x5a\xc4\x31\x7f\x33\x5e\x62\x88\x5d\x21\x05\x2a\x93\xf6\xd1\x90\xc7\x23\x0f\xa5\xe6\x66\x4b\x87\x7d\x2f\xdd\xe1\x02\x28\x2e\x1e\x12\x6b\x28\x94\x40\x15\xde\x66\x71\x53\x95\x72\x6c\x54\x47\xaf\x71\x06\x0b\x72\x4d\xd8\xc9\x95\xd0\x2e\x92\xaf\xfa\x40\x7c\xda\xb5\x88\x06\xa5\x59\x8e\x07\x2c\x2d\xa5\x6f\x58\x8d\x30\xa3\xab\xb7\xbe\x71\x54\xfe\xf2\xe6\xcd\x86\xf2\xdb\xa7\x47\x7a\x09\xa8\x29\xef\x82\x2f\x57\x15\x1d\xf2\xe4\xdf\xa8\xc0\x66\x8f\x99\x13\x83\xb1\xf3\x36\x48\xf4\xb8\x32\xa5\x19\x9f\x94\x4c\x4d\xc9\x08\xf4\x3d\x00\x27\xf0\x60\x6b\xea\x90\x7f\x81\x14\xb8\xa9\x06\xbc\xb5\x9b\xa1\x01\xb4\xb7\xfb\x03\xb1\x19\x53\x4c\xf0\x6f\x98\xd2\x42\xce\xdf\xb3\x9c\x3d\x51\x80\xda\x8f\x65\xb7\x5f\x05\x41\x91\xa5\xe4\xda\x6e\xc5\x0d\xd8\x0f\x96\x80\x56\x50\x2d\xac\x7a\x4a\xcc\x39\x19\xd1\xe4\xee\x93\x01\xf8\xcd\xbe\x40\xd8\xb3\xeb\x1d\xa0\x8a\xf2\x5e\x35\x01\x92\x2d\x8b\x94\x17\x0f\x16\x3e\x0d\x28\xdf\x4f\x85\x02\xbc\xc1\x1a\x2a\xf1\x31\xef\x58\x60\xaa\x22\x18\xe8\x96\xe5\xa0\x08\x1d\x8f\x9b\x77\xd4\x87\x1d\x25\xcf\xbc\x54\x9a\xe4\x54\x27\x53\x6b\xca\x12\x69\x25\x4e\x1c\x2a\x27\xf6\x6f\x03\xe5\x8d\x0d\xd1\xdb\x9b\x8c\x89\x5d\xe7\xc5\x83\xd1\x2d\x9f\xf4\x08\x35\x47\x03\xe4\x8b\xd3\x34\x35\xe0\xac\xb9\x21\x4e\x6e\xcb\x6d\xf3\xfe\x5b\x34\x22\xd7\xbf\xe0\x2e\x9c\x5e\x9d\x6f\x6e\x8a\xd9\x45\xc1\xdd\x5a\xc5\x5d\x34\x97\x3f\xf2\x51\xde\x64\xea\xae\x34\x6d\xe6\xa8\xa1\xa8\x1e\xa1\xe4\x0e\xe6\x3d\xcb\xc5\x16\x1b\xe6\x4b\xc8\x9c\x24\x01\xd8\x37\xde\xdc\x64\x9f\xdb\x1c\x24\x3b\x60\x8f\x1d\xdb\xb9\x33\xfc\xe8\x9b\x85\x6e\xf9\x84\xff\xe8\x2d\x1e\xdb\x1e\xc1\xed\xb8\x83\xf9\x76\x0f\x2c\x6c\xb7\xd9\x05\xa7\xfb\xd8\x7d\x37\x3f\x54\x82\x5e\xb5\xd5\xdb\xf9\x99\xc2\xb1\xb5\x89\xca\x0f\x0f\xc4\x56\x9f\x57\xa1\x5f\x68\x65\x32\xdf\x78\xa8\x2c\x32\x9a\x33\x3d\x65\x85\xcd\x7a\x70\xce\x00\x87\x91\xe4\x7b\x9a\xb1\xb4\x9a\xc2\x9e\xdf\x4b\xde\x33\xe2\x93\xf9\x3f\x24\xba\x56\x5c\x3b\x17\xa0\xae\x84\xc6\x5f\x3e\x1b\x80\xec\x32\x5b\x81\xc7\x4e\xe1\xac\xd0\x48\x65\x50\xf1\xb2\x11\xf7\x1e\x0c\x97\x8b\x91\x3b\x8a\x5c\x72\x22\xa4\x87\x83\xb9\xe8\x26\xb2\x53\x20\x9f\x18\x59\x07\x07\xda\xa7\x57\xce\xe1\xc0\x27\x64\x03\x7a\x8f\x4c\xe7\xa6\x42\xf9\xc0\x5e\x41\x1d\xab\xc8\x50\xda\x75\xa2\x2a\xf5\x8e\x72\x96\x90\x1c\xe4\x04\x3d\x2e\xc9\xc6\x1e\x87\xe6\xa6\x6c\x47\x77\xed\xd8\x9a\xfa\x86\x2f\xdc\x0a\x0b\x90\x35\x59\x13\x50\x1b\xe6\x66\x67\x68\x98\x9c\xfe\x8f\xa1\xe0\xb8\x07\xff\x97\x14\x94\x49\x35\x20\xa7\x44\x31\x3e\xc9\xa0\x71\xcd\x69\x18\xe1\x34\x66\x06\xa6\x88\x21\xb5\x33\x9a\x39\x5d\x8a\x72\x02\xd6\x66\x65\x66\x5f\x64\xa9\x3d\x27\xa9\x18\xca\x53\x39\xba\x0e\xee\x60\x7e\xd0\x5b\x42\x9a\x83\x4b\x7e\x60\x79\xcb\x12\x9a\x54\x8c\x08\x7d\x64\x07\x78\xed\xa0\x4b\x2e\xbc\x25\xc3\xd9\xd5\x8e\xd6\x7c\xe9\xc6\x18\xe1\xe3\x43\x76\x14\xd6\x1b\x5a\xa2\x8b\x8a\xd2\x82\x94\x0a\xac\xb4\x8e\xa7\x8c\x80\x97\x33\x51\xaa\x44\xc5\x94\xc3\x3d\x4a\x8f\x7b\x23\xf8\x19\x4d\x82\xf1\xc9\x77\x45\x4a\xf5\x46\xe1\xb9\x76\x34\x20\x72\x78\x6d\x27\x21\x25\xce\x62\x70\x6b\xcc\x26\xa4\xa0\x92\xe6\x6a\x40\x86\xae\x9e\x2a\x62\x1a\x1b\x87\xb6\x44\x07\xbb\xdb\x79\x01\xe4\xff\x21\xd7\xe1\x5a\x06\xa4\xdf\xef\x93\xdb\x8f\xe7\x1f\xdf\x11\xfb\x8b\x95\xb2\xb5\x20\x63\x81\x4a\x90\x28\xa5\x79\xd5\x0c\x38\x2a\xfe\x46\xbe\x17\x1c\x3e\x8e\xcd\x09\xa1\x1a\x66\x20\xc9\xbd\xd9\xaa\x84\xa5\x50\x59\xaf\x06\x87\x9f\x16\x8f\x77\x93\x4c\x72\xfa\x70\x53\xca\xc9\x16\x1b\x40\x96\x36\x21\x34\xd9\xd4\xca\x24\xa2\x5e\x98\x7b\xae\x92\x29\xa4\x65\x06\x29\xa1\x23\x31\x83\x86\xc9\xb6\xf9\x18\xb2\xf4\x12\xfc\x83\x86\xe7\x8d\x94\xc8\x4a\x5d\x29\xab\x47\xf0\xf0\x8e\xfc\x19\x5d\xdb\x94\x14\x20\x13\xe0\x9a\x4e\x60\xd1\x0c\x60\xef\x7b\xfb\xe6\xdf\x8e\x1d\x3f\x32\x33\x3a\xeb\xc9\x1b\x83\x11\x1f\xe8\xc3\x77\xbc\x36\x0d\x32\x45\xde\x0c\xc8\xe9\xc2\xcb\xf0\xb9\x2c\x29\x33\xb4\xb5\xa0\xbb\x3e\x78\xe5\x68\x4e\xa4\x28\xd1\x61\x4f\xca\xa2\xa9\xcd\xfe\xe1\xcf\xff\x66\x94\x3e\x9a\x17\x19\xbc\xf3\x65\x98\xad\xda\x6c\x64\x18\x2d\xc8\x1f\xdf\xfc\x9b\xa5\x9e\xe6\x7c\xd6\x5a\x61\x0d\x33\x6a\x00\x56\x16\x84\xe5\x36\x9c\x13\xb2\x79\x5d\xcf\x59\x36\xd1\x5f\x69\x2a\xb5\xea\x11\xf4\xea\x57\xc2\xa1\x16\x9a\x66\x0b\x5a\x3e\x6a\xe1\x70\x6f\x81\x94\x0a\x84\x09\xa0\xa1\x8a\xbc\xfd\xe3\x9b\x7f\x5b\x36\xa7\x7c\xe4\x09\xe0\x93\xf8\x04\x86\x59\x8c\x8c\x72\x7f\xc7\xb2\x0c\xd2\xde\x93\xcb\x1f\x97\x52\x4f\x41\xf6\x08\x70\xe5\x8d\x55\x66\x7d\x0b\x6b\xc3\xd9\x65\xc9\x39\xca\x08\xd6\x3a\x8c\x16\xad\xc0\xc2\xe5\x3e\xd6\x30\x42\x4d\x72\xa1\xf4\xea\x25\x6f\x7e\xdc\xcc\xa0\x7c\xfe\x71\xbc\xad\x38\xd0\xdf\xc1\x0c\xb1\xfc\xf4\x0e\x22\xe5\x43\xff\xae\x4a\xfc\xed\x33\xae\xfb\x42\xf6\xed\x34\xef\x88\x96\xe5\xd3\x5e\x83\x7a\xe4\x8d\x13\xf0\x19\xc8\x40\x19\x9c\xb7\xa5\x5d\xfd\x24\x27\x7f\xf7\xf3\x9c\x8a\x7b\xbe\x9e\x72\x20\xe1\x74\x34\x63\xc7\x53\xdf\xb4\xb8\x2d\x1c\x1b\xf3\x76\x73\xf7\xff\x6f\x19\xbb\xb7\x20\x07\xee\xec\x56\xa7\xdd\xc8\x55\xe8\xf1\xe8\x6d\xf0\xf6\xea\xd8\x5a\xce\x67\x6d\x4e\xe6\x06\xfb\x9a\x15\x94\x6b\xe9\x84\xaf\xa0\x40\x76\x1d\xb5\x43\x46\x63\x44\x81\x39\xe7\x6a\xed\x41\xcf\x80\x2a\xbd\x0a\x14\xf1\xa0\x3f\x3d\x1e\x4f\x02\x58\x1c\x4d\xa1\xd3\x48\x48\x08\xf2\xda\xc6\x78\x66\x11\xe5\xe0\x1a\xac\x87\xcf\x06\x9c\x35\x84\xa8\x83\xea\x48\x98\xfd\x6b\xca\x57\x9f\x2a\x6c\xc6\x1b\x39\x77\x11\xad\xdd\xa3\x41\x70\xb0\x33\x9d\x3a\xe2\x55\x79\x14\xad\x4b\xd3\xea\x2b\x36\xca\xcf\x1d\x0c\xff\xf6\x81\x2a\x20\x19\x48\xc0\xd3\x67\xa3\x91\xad\x02\x84\x7a\xd1\x69\x76\x4f\xe7\xea\x60\x6f\xa4\xf0\x1c\x34\x7d\x3c\xd1\x64\x71\x34\x89\xfe\x8d\xa6\x3c\xa5\x32\x75\xab\x3c\x3c\x54\xd5\x94\x03\xf2\x01\x7d\x71\x7c\x2c\xde\x91\xa9\xd6\x85\x7a\x77\x72\x32\x61\x7a\x70\xf7\x57\x35\x60\xe2\x24\x11\x79\x5e\x72\xa6\xe7\x27\xe8\x80\x63\xa3\x52\x0b\xa9\x4e\x52\x98\x41\x76\xa2\xd8\xa4\x4f\x65\x32\x65\x1a\x12\x5d\x4a\x38\xa1\x05\xeb\xd7\x32\xb7\x1a\xe4\xe9\x6f\xfd\x8b\x3e\xb1\x60\xdd\x38\x83\x68\x9d\x92\x33\xe8\x97\xfc\x8e\x8b\x7b\xde\x47\x4d\x58\x6d\x75\x1a\x37\x8b\x82\xf0\x63\x01\xde\xdb\x04\x3e\x14\x22\xfd\xe4\x9b\x60\x3e\xa6\x4f\x79\xda\xb7\x4e\xcb\x4f\xbc\x17\xbb\xd8\x86\xfb\x75\x60\xc1\x26\x51\xef\x76\xec\xa6\x4d\xd1\x44\xb3\x19\xec\xe4\x04\xf7\xa3\xb1\xdd\x1f\x7d\xc0\x69\x5a\x4a\xbb\xe3\x81\x37\xdc\xfb\x76\x72\x3a\x47\x59\x09\xdf\x4d\x84\x15\x05\xb8\x48\xc1\x59\x4e\x67\x68\x1a\xb8\x31\xe4\xe8\xd6\x88\xd2\xce\x47\x8e\x76\xe3\xb9\xd2\x90\x5b\xe2\x66\x9f\xcf\xe6\x44\xcb\xb9\x75\xac\xcb\x3b\xa3\xbc\x3a\xcf\xb7\xd1\x18\xee\xf0\x3e\xa5\x44\xc2\x50\x74\xaa\xe1\xea\xe5\x36\x6f\x03\xa4\xa4\x10\x8a\xe1\xbb\x1d\xcf\xdc\xce\xb2\xb7\x3b\xbb\x0d\xdc\x7c\x7f\xf9\xd3\x36\x5b\x37\xc6\x2a\x27\x5b\x5a\xe9\x9b\x11\x18\xe3\x30\xcb\xc0\x6d\xcf\xa1\xf2\x8a\xaf\x11\x6b\x12\xc1\x95\x96\x94\xad\xcf\xa3\x5a\x3d\x76\x74\xa5\xec\xee\xaf\x20\x88\x41\xa7\x3b\x01\x85\xac\x4e\x8c\x1d\x61\x66\x4d\x0a\x15\xa8\x43\xc0\xd8\x34\x2b\x1f\x8b\x68\x08\xd7\x8e\xa6\xd9\x1d\x60\x44\x5a\xc1\xc9\x3e\x6d\xab\x2c\xa5\xe7\x28\xbd\xde\x54\xdf\x75\x39\xe1\xa2\xfa\xf9\xe2\x01\x92\x72\xd3\x9c\xfc\xe5\xb1\x64\x0b\xf4\x06\x15\x17\xb6\x62\x17\x61\x8e\xae\xbf\xe0\xe4\x17\x81\x60\x77\x82\x8c\xa2\x9a\xa9\xb1\xcd\x59\xab\x36\x02\x02\xc7\x69\x85\xc2\x95\x7b\x19\x59\x9c\x4d\x9d\x60\x1a\xc9\x4d\x32\x15\x42\x99\x53\x8e\xfb\x89\xf3\xce\x98\xb0\x3e\x43\x4c\xa0\x91\x24\x37\x34\xc6\x27\xd2\xd4\xd3\x5b\xc1\xa9\x7e\x8c\x29\xab\xc2\x57\x10\xf4\x5e\x2e\x33\x0d\x1a\x2e\xcd\x1f\x13\x94\xba\x94\x26\xaa\xcc\xcd\xa4\xf7\xc0\x26\x53\xad\x7a\x84\x0d\x60\x80\x58\x03\x34\x99\x06\xd3\xe6\x00\xba\xd1\xb7\x29\x44\xb5\xd0\xca\x7c\x54\x65\x45\xb8\x54\xa0\x5e\xc5\x63\x16\xf7\x72\x25\xb8\x7a\x04\x74\x32\x38\xee\x91\x3a\x65\xdf\xac\x71\x34\x27\x4c\x83\xa1\xd9\xa8\xcb\x48\x51\x4e\xec\x97\x80\x8f\x09\xc5\x75\x55\x29\x23\xe8\x85\x4d\x51\xe7\x3c\xb0\x1f\x77\x60\xf6\x0d\x57\x5e\xe6\xbe\xa8\x12\x7e\x1f\x9a\xe5\xa1\x4a\x2c\x92\xa0\x0a\x61\xb5\xd5\x45\x83\xfd\xff\xbf\x7a\xe8\x48\x1d\xd7\xc0\x9c\xb2\xc9\xd4\xc3\x92\x3a\x46\xd0\xdc\x83\xed\xcf\x1e\x69\xe5\x8b\xb1\x63\x47\x8f\x8c\x1d\x4d\xdf\xb8\xcf\xb7\xa8\xb1\x2a\xd8\x7f\x0d\x32\xaf\xa0\x88\x28\x82\x24\xc3\xd9\xc9\x7d\x8b\x2d\x87\x63\xe4\x0d\x39\x42\x24\x63\xfa\x50\x21\xc2\xf7\x45\x71\x3c\x20\xa7\x84\x97\xd5\x99\x7b\xec\x05\x5c\x54\xf3\xbb\x89\xcc\x4b\x95\xa8\xe7\xda\xf1\x8b\x5b\x91\x3b\x3b\x76\xf3\xb4\x87\xa3\xef\x20\x00\x4f\x17\x0d\x7d\x6c\x12\x0b\xeb\x1d\x27\x68\x47\xba\xfd\x1c\xfe\x2b\x76\x9f\x63\x29\x40\x03\x8f\x6b\x1d\x85\x01\x32\xef\x85\xd2\x53\x75\x20\x9b\xa7\xd8\xc2\x62\x57\xac\x20\xdd\x60\x06\xe9\x08\xae\xa4\x55\x84\xcf\xea\xb1\x18\x06\xe3\xb3\xb0\x1a\xd0\x6e\x10\xf9\xd1\x1c\xaf\x6e\x19\xfc\xb4\x7e\xb4\xa5\x74\xf5\x68\x45\xf3\xea\xf1\x28\xe2\xed\x5f\x60\xd0\xea\xd1\x11\xda\xda\xd1\x9e\xb4\xd5\x63\xfb\xd0\xa2\x75\xf3\xec\x10\x70\xb4\x7a\x74\x75\x36\xed\xd8\x21\x38\x69\xf5\x58\x12\x51\x3f\x4d\xac\xd2\xea\xb1\xb3\x91\x75\xf5\xd8\x35\xae\x69\xf5\x58\x48\x75\xfc\x44\x41\x4e\xbd\x66\x84\x13\xf9\x5a\xdb\x73\xfc\xbe\x15\x3f\xa9\x47\xc7\x20\xde\x2d\x32\x6a\xf5\x58\x14\x00\x5f\x48\x94\xd4\x8a\xa9\xbe\xd6\x66\x9a\xf7\x6b\x1f\xb6\x39\xee\x3e\xce\xc7\x29\x14\x3d\x97\x7a\xe3\xed\xd4\x18\x91\x5d\x48\xc0\xd2\x06\x18\x36\xe6\xed\x30\x9f\x27\x30\x6b\xf5\xe8\x8e\x71\xda\xd1\x11\xfb\xb4\xa3\x33\xe4\x46\x81\xe7\x2b\x6b\x17\x7e\x46\x59\xc7\x5a\xa6\xa3\xac\x13\x65\x9d\x2d\x46\x94\x75\x36\x1d\x51\xd6\x59\x37\xa2\xac\xb3\x62\x44\x59\x27\xca\x3a\xad\xc6\xfe\xc9\x3a\xd6\x52\xd5\x99\xc1\xec\x1f\xd6\xe0\xba\x68\x21\x43\x69\xca\x87\x04\x35\x4d\x65\x86\xf7\xdf\x38\x12\x7b\x8b\xe6\x35\x17\xe9\x2e\x29\x9f\x00\x79\xdb\x7f\xfb\x66\xc3\x74\xc2\xd5\xa3\x4d\xd0\x4f\x38\xb6\x4d\x3d\x5c\x1c\xeb\x3c\x12\x9f\xcc\xbb\xe4\x4e\x6a\xe5\xf0\x68\x48\x98\x6b\x1c\x44\x55\x55\xac\x1c\x34\xa1\xba\x61\x10\x67\x39\x54\x0e\xd1\x46\x0a\x73\x1d\x13\x2c\xb8\xf3\x77\x98\x4d\x1d\xec\xb6\x82\x04\xa8\x8d\x83\x1f\x41\xb5\x0a\x91\x83\x4d\x50\xf5\x87\xde\x2c\x01\x3c\xac\xc8\x11\x0c\x26\x03\x92\xda\x64\x6f\xca\x5d\xcc\xd9\x71\x2f\x74\x8f\xe7\x86\xb8\x4a\xfc\x3f\xb3\x6c\xe7\x1f\x87\x19\x70\x5d\xd2\x2c\x9b\x13\x98\xb1\x44\x57\xdf\x87\x01\x85\x4c\x5b\x67\x67\x1b\x57\x4a\x0b\xf1\xb0\xad\x48\xd8\x5f\x3a\x5b\xdb\xf9\xab\xfd\x68\x2f\xbb\x2d\xad\x63\x77\x7a\xb3\x20\x97\x58\x08\x0d\xd6\xaa\x55\xda\xbc\xcd\xfa\x2b\xf1\x9f\x88\xe0\x1f\xaf\x77\x75\x8f\x91\x8e\x78\x42\x6b\x3e\xb0\xa8\x40\x95\x59\x66\xd0\xdb\x7a\xcc\x96\x41\xb0\xc2\x93\xb5\x22\x5b\xc7\xba\x59\xf3\x20\x6b\x07\xef\xb9\x15\x85\xc8\xc4\x64\x1e\xee\xa0\xeb\x03\x53\x97\xc7\xa1\x44\x95\x23\x27\x02\x9a\x43\x74\xb5\xb0\xe5\xd1\x17\xb2\x76\x44\x5f\xc8\xd2\x88\xf6\x81\xc5\x11\xed\x03\x5b\x8c\x68\x1f\x58\x31\xa2\x7d\x60\x79\x44\xfb\x40\xb4\x0f\xb4\x19\xaf\xdf\x3e\x40\xa2\x2f\x64\xdd\x88\xb2\x4e\x3d\xa2\xac\xb3\xf9\x88\xb2\xce\xf2\x88\xb2\x4e\x94\x75\xa2\xac\x13\x65\x9d\x5d\x47\x0b\xe4\x2e\x44\xda\x79\x8a\x4c\x21\xd2\x47\x32\x64\xac\xbd\x3a\x11\xfd\x4c\x24\x55\x65\x12\xf3\x88\xf3\x7c\x28\x9a\x5b\x13\x7a\x8f\xfc\x4b\x70\xb0\xe9\x09\xb6\xe4\x6d\x0e\x44\x60\x13\x89\x42\xa4\x47\xea\x78\x87\xc0\xf3\x98\x61\x13\x33\x6c\x7e\x05\x19\x36\x53\xaa\x5c\xe1\x24\x24\xad\xeb\x13\x6e\x82\xe3\x7f\x0b\x32\xff\xd5\xe6\xdb\x18\x84\x73\x08\x83\x7d\xea\x6a\xa4\xb0\xb0\x4b\x9d\x6f\x17\xd2\x61\x13\x62\x4e\x2f\xb3\x2d\x7a\xd2\x14\x52\x52\x80\xec\x5b\x24\x13\x64\xcc\x5c\xfd\xb0\x05\xfc\x75\x10\x7e\xe1\x79\x33\x4d\x48\xbc\xe8\xe4\x99\xe6\xa7\x74\xe6\x9b\x0a\x5d\x74\x0d\xae\xf8\xe2\x52\x69\xba\xd1\x4a\xfb\x44\x3b\x77\xda\xb7\xad\xf4\xd2\xae\x94\x48\x54\xf2\x6e\xb6\x2a\x93\xbc\x7e\xac\x2c\x6e\xfb\x3f\x25\xc8\x39\x11\x33\x90\xb5\x62\x54\x75\xf7\xe9\x55\x4d\x6a\x12\xea\x0a\x28\x77\x63\xe0\xe9\xc4\x14\xd1\xa5\xa6\xde\xb5\xd7\x90\xec\x59\xf5\xe4\xf5\xa3\x5b\xc5\xa1\x43\xb5\xe1\xa5\xd5\x62\x5e\x3f\x3a\x35\xbf\x91\x8e\x4d\x70\xa4\x43\x33\x1c\xe9\xd6\x14\x47\x3a\x37\xc7\x91\x2e\x4d\x72\xe4\xb3\x57\x90\x5e\x3f\x3a\x36\x1f\x91\xce\xad\x74\xe4\x05\xd6\xa3\x5e\x3f\x3e\x01\xb8\xbb\xb4\xd8\x91\x58\xdd\xba\xf5\xe8\xda\xa0\x46\xba\x36\xaa\x91\xae\xf1\x70\xa7\x2a\xda\xeb\x47\xac\xaf\xfd\x09\xe4\xb4\xce\x84\x88\xb6\x35\xb9\x9f\x5a\x68\x07\x38\x59\xf5\xfe\xfd\x5c\x0a\x90\xe5\xd2\x75\xc3\x59\xf3\xee\xa0\xd7\x17\x86\x6a\x86\x8d\x51\x7d\xdc\x2a\x62\x34\xfe\x9e\x7a\x83\x57\xc9\x83\xe2\x71\xc1\x64\x4b\xad\x67\x6a\xd3\x59\xd5\x7c\xc6\x28\x05\x75\xd3\xaa\xe0\x61\xbc\x77\x60\xc3\x49\x6b\x69\x82\xa7\x8b\x01\xa6\xf5\x13\xa8\x5f\xd8\x76\xb8\x07\xde\x8e\x7d\xa8\xea\x3b\x0e\x06\x61\xe7\x5c\x37\xe3\xd1\xff\xf9\xbf\xc7\x8d\xea\x2d\xf5\x84\x51\xfb\xdb\x78\x44\xed\xaf\xd5\x88\xda\xdf\xda\x11\xb5\xbf\x16\x23\x6a\x7f\x9b\x8d\xa8\xfd\xad\x1f\x51\xfb\x8b\xda\xdf\x0e\x23\x6a\x7f\x51\xfb\xdb\x75\xfc\x8a\xb5\xbf\x6e\xa3\x9a\x43\x5d\xcc\x05\x89\xa0\xfc\xa8\xa9\x66\x49\x1d\xf1\xec\xef\xb2\xff\xea\x56\x07\x0c\xf5\xbb\xd5\x1a\x60\xa8\x25\x2e\x69\xc1\x83\x27\xd4\xbd\x4a\x21\x5c\x7a\xf2\x71\x4d\xf0\xb5\x45\x6e\x77\x86\x89\x81\x4b\xb8\x53\x54\xbc\xf5\x81\x65\x75\xe3\xf6\x2a\xea\x2c\x25\x47\xde\x17\x8f\x8d\x58\xb8\xd0\xcd\x8b\x5c\xb3\x7e\x7d\x47\xe5\x9d\xc7\xa0\x9a\x46\x3e\x7f\xc3\x85\x5c\xc5\xb0\x55\xf1\x51\x35\xf6\x18\xf2\x08\xb2\xb1\x06\x6c\x7c\x3b\x66\xdc\x46\x3a\xfa\xa6\x41\x82\xfb\xa0\x29\x4b\x4f\x6d\xeb\x05\x87\xe7\x56\xf4\xc5\xf5\xa0\xfc\x5b\xc3\x2e\x88\xf2\xa1\x78\xc8\x28\x77\xc9\xb0\x82\xfb\xae\xf6\xb6\x53\x7d\x2d\x2f\x57\xbd\x58\xaa\xb7\x0f\xc8\x05\x62\x7d\x38\x31\x53\x08\x1f\xd7\x26\xa2\x1b\x44\xde\xaf\xc2\x0d\xf7\x5b\x17\x6e\x58\x88\x18\x89\x75\x1b\x62\xdd\x86\x56\x75\x1b\xf0\xa2\x3d\xdc\x9d\x17\x70\x20\xff\x70\xed\x95\x24\x20\xa8\xf2\x32\xd3\xac\xa8\x23\xb0\x95\x7d\x55\x66\x35\x89\xb1\x8b\x04\x6d\xe2\xbb\x79\x1b\x4d\xa6\x8b\x78\x8f\xf3\x61\xc4\xb6\x42\x72\xe2\xa2\x2d\xb1\x19\x12\x56\x1c\xf0\x6a\x87\x0d\x29\x65\x2f\x3f\x52\xf0\x1c\x09\xb6\xaa\xb5\x66\xdb\xab\xcb\xd0\xf9\xcc\xa0\x84\xa1\xd8\x8f\x30\x88\xb0\xa1\x05\x46\xad\xb2\x19\xf0\x9a\x4b\x1c\xa9\xe3\x63\x2f\x0d\x75\xca\xbd\x3e\x09\xf7\xf9\x7b\xc0\x25\xfe\x7d\x13\xfe\x83\x1f\x54\x71\xa0\x1a\x7c\x35\xff\x79\xd9\x21\x91\xed\xa3\xdb\xba\xb0\xc8\x75\x16\xd5\xf6\xec\x11\x6d\xbf\xa6\xda\x17\x7b\xe9\xc3\xd8\x3b\xad\xe3\x75\xf8\x2d\x62\xc2\xe8\xe6\xe3\x25\x24\x8c\x3e\x93\x6f\xe2\xe5\xe4\x8d\xbe\x58\x7f\xc4\x4b\xc9\x1b\x8d\x3e\x88\xad\xc6\x6b\x4d\xe7\x6c\x8e\x0e\x7d\x0e\xd1\xdf\xd0\xb1\x4c\xd5\x09\xf3\xff\x34\x7e\x86\x4e\xf0\xaf\xd3\xe8\xb2\x18\x59\xf6\x9c\x91\x65\x51\x0b\x8b\x5a\x58\x73\x44\x2d\x6c\x69\x44\x2d\x6c\x8b\x11\xb5\xb0\xf5\x23\x6a\x61\xcb\x23\x6a\x61\x51\x0b\xdb\x60\x44\x2d\x2c\x6a\x61\x9b\x8e\x5f\x99\x16\xd6\x5d\xbd\xf5\x18\xe1\xf5\x09\x22\xbc\xba\xa1\x84\x1d\xd0\xbf\x4e\xb0\xae\xa3\x88\xae\x18\xcd\xb5\xdf\xd1\x5c\x2d\xcb\xce\x71\xcd\x3e\x4d\xe9\xb9\x70\xb7\xd7\xd5\x9f\xa3\x33\xc1\x52\x52\x94\xda\x55\xdf\x8a\x35\xe8\xf6\xb9\x06\x5d\x63\x47\x63\x21\xba\x8d\x0a\xd1\xad\x83\x59\xac\x46\xb7\x66\xec\x4f\x8c\x59\xac\x46\xb7\xed\x88\xd5\xe8\x56\x8f\x58\x8d\xee\x91\x11\xab\xd1\xc5\x6a\x74\xb1\x1e\x41\x8b\x11\xeb\x11\xac\x18\xb1\x1e\xc1\xee\x23\xd6\x23\xd8\x68\xc4\x7a\x04\xb1\x1e\x41\x73\x44\x2f\x54\xbb\x11\xeb\x11\xb4\x1c\xd1\x33\x15\xeb\x11\xb4\x9a\x30\x56\xa3\x7b\x55\x31\x83\x24\x6a\x7f\x51\xfb\xdb\x78\x44\xed\x6f\xed\x88\xda\x5f\x8b\x11\xb5\xbf\xcd\x46\xd4\xfe\xd6\x8f\xa8\xfd\x45\xed\x6f\x87\x11\xb5\xbf\xa8\xfd\xed\x3a\x7e\xc5\xda\x5f\xac\x46\xb7\xf7\xb1\x8a\x64\x1f\x33\x92\x62\x35\xba\x18\xbf\xb8\xd3\x76\xc7\x6a\x74\x4f\x8f\x5f\x7d\x35\xba\x46\x2c\xdd\xf3\x95\xa4\xdb\x7e\x19\xb1\x2e\x5d\xac\x4b\x17\xeb\xd2\xc5\xba\x74\xb1\x2e\x5d\xac\x4b\xb7\xf9\xd8\x7f\x6f\xc6\xde\xe9\x1f\xaf\xc3\x83\x11\x2b\x22\x6c\x3e\x62\x45\x84\xb5\x23\x56\x44\x88\x15\x11\xa2\x37\x62\x97\x11\x2b\x22\x6c\x39\xa2\xe7\x21\x56\x44\xd8\x6a\xc4\xba\x74\xaf\x26\xc6\x2c\x6a\x61\x51\x0b\x6b\x8e\xa8\x85\x2d\x8d\xa8\x85\x6d\x31\xa2\x16\xb6\x7e\x44\x2d\x6c\x79\x44\x2d\x2c\x6a\x61\x1b\x8c\xa8\x85\x45\x2d\x6c\xd3\xf1\x2b\xd3\xc2\x62\x5d\xba\xbd\x8e\xf5\x8a\x75\xe9\x56\x8c\x18\xd7\xb5\xdf\x71\x5d\x3b\xe2\x0a\x2d\xb5\xc8\x45\xc9\xf5\x0d\xc8\x19\x4b\xe0\x34\x49\xcc\x5f\xb7\xe2\x0e\xb6\x8c\x25\x6a\xaa\xa1\x8f\x4c\x4b\x18\x4f\x59\x82\x8a\xe4\xfd\x14\xb0\xac\x9c\x91\x6f\xf1\x3e\x42\xed\x8d\x44\xe3\x9d\x35\x7a\xe1\x3a\x0d\x51\xc3\x00\x1b\x9c\x7a\x5b\x78\x59\x08\x8d\x84\xc8\x80\xf2\x2d\x9e\x74\xdc\x10\xe4\x96\xa7\xb9\x01\x90\xf7\x8e\x14\xd7\x93\x91\x11\x64\x82\x4f\x5c\x3c\x8f\x3b\x01\x03\x72\x56\xdf\x90\x50\x8e\x87\xa7\x94\x12\xb8\xce\xe6\x08\x07\x2c\x70\x85\x5a\x43\x2e\x66\x90\x22\xc9\xc6\x30\x22\x2b\x47\x52\x4d\x32\xa0\xe6\x5d\x1c\xea\x97\x99\xc3\x43\xc9\x10\xe7\xb7\x93\x8e\xc0\x85\x36\xed\x04\xc4\xed\x69\xe3\x4e\xd4\x70\xc1\xb2\xe1\xc4\x26\xe4\x4b\x09\xea\x47\xc1\x17\xe2\xd1\x9c\x8b\x92\xdc\x53\x2b\x29\xc9\x92\xe3\x61\xc6\x4f\x37\xa0\xdd\xf2\xe5\x2d\x64\x92\xdd\xcd\x0f\x7d\xa4\x6a\x5b\x3e\xd6\xc6\x1c\x40\xe5\x64\x27\x26\xd5\xd8\x9a\xc3\x53\x39\x29\xad\x48\xe8\x50\x19\xb8\x96\x73\x8c\xb7\xb3\x32\x45\x80\x89\x39\x9d\xc0\xe1\xa1\x22\x67\x1f\xce\x0d\xf9\x2b\x95\xa1\xd6\xae\xca\x9e\x23\x87\x85\x14\x33\x96\x1a\xe4\xfe\x9e\x4a\x46\x47\x99\x91\x3b\xc7\x20\x81\x1b\xb1\xe0\x8b\xa3\xef\x4f\xaf\x7f\xbe\x3a\xfd\x70\x71\x8c\x12\x28\x3c\x14\x94\x9b\x53\x51\xaa\x3a\x50\xd4\xbd\xce\xbc\x08\xf8\x8c\x49\xc1\xcd\xfa\x50\x57\xa3\x64\xe6\x67\x4d\xaa\xc3\x20\x41\x89\x6c\x06\xa9\x95\x93\xab\xb7\x79\xae\xc3\x78\x51\x6a\xaf\x3b\x62\xf8\xa2\x39\x40\x3c\x99\x52\x3e\x31\xeb\x3c\x17\xa5\x99\xef\x8b\x2f\x70\x45\x12\xd2\x32\xb1\x92\x13\xf5\x58\xfb\x45\xcf\x73\x0a\x43\xeb\x95\x2d\x89\xa8\x12\x5a\xf8\x35\x87\x9f\xa5\xe6\x5c\xd3\x87\x77\x36\x7e\xef\xe0\x8b\xe0\xd2\x81\x2f\x27\x29\xcc\x2b\x2c\xbf\xb1\xab\xca\xb0\x92\x61\x46\x0e\xc2\xbb\x07\xe4\xc2\xbc\x03\xd2\x10\x80\x36\xfc\x12\x66\x20\x51\xf3\x74\xe0\xeb\x11\x09\x13\x2a\xd3\x0c\x14\x06\x1e\x7a\xda\x6c\xb5\x03\x07\x30\xa8\xf4\x5a\x2e\xf4\x2a\x62\x42\x3e\x08\x0c\x42\x1c\x8b\x77\x64\xaa\x75\xa1\xde\x9d\x9c\xdc\x95\x23\x90\x1c\x34\xa8\x01\x13\x27\xa9\x48\xd4\x89\xa6\xea\x4e\x9d\x30\x6e\x0e\x57\x3f\xa5\x9a\xf6\x83\x53\x7d\x62\x39\x77\x3f\x11\x79\x4e\x79\xda\xa7\x0e\xbb\xfa\xd5\xb6\x9e\xfc\xd6\xf1\xd4\x3e\xad\xee\x62\xbc\x4f\xfb\x6a\x0a\x59\x76\xb8\x03\x3e\xb7\x93\xf9\x5a\xc8\x7a\xad\x64\x3c\xf7\xed\xed\x0f\xf0\x45\x75\x5e\x2d\x0c\x06\xe4\x4a\x68\x17\x1f\xeb\x42\xb1\x91\x8e\x22\x7c\xd7\x1e\xe9\x8b\xab\xdb\xeb\x7f\x0e\x3f\x5e\x5e\xdd\xc6\x93\x1d\x4f\x76\x3c\xd9\x2d\x4e\x36\xf0\x59\xeb\x53\xed\x65\xce\xe0\x98\x54\xfb\x8d\x9c\x5a\x81\xf6\xc7\xa0\xda\x80\xd6\x12\xa2\x1d\xcf\x06\xf5\x06\x04\x2e\xf8\xec\x7b\xda\xb4\xb0\xf3\x95\xe0\x20\xee\x06\x2b\x28\x57\x32\x78\x9b\xf8\xf8\x16\xd6\xac\xb6\xee\xab\x9d\xa4\x48\x3b\xda\xbb\x96\xcc\xab\x77\x37\x34\x34\xb6\xef\x8a\xe6\x75\x85\xea\x15\xbb\x36\x20\x1f\xbc\xda\x43\xce\x7e\xbe\x3c\xbf\xb8\xba\xbd\xfc\xea\xf2\xe2\x7a\x77\x3d\xba\x03\x8b\x0b\xda\x14\x3a\x02\xc0\xe1\x8e\x5c\xb2\x90\x30\x63\xa2\x54\xd9\xbc\xb2\x82\xac\x26\x02\x8b\xa7\xdf\xf9\x7d\xe7\x95\x3e\xbe\xf2\xb1\xc8\x6c\xbb\x65\xb6\xe7\x30\xa6\x65\x66\xb5\xa7\x83\x83\xc1\x2e\x5c\xce\x8e\xae\xd0\xf7\x2b\x29\x5a\x54\x60\x6e\xa0\xf0\x8d\xad\xdd\x3e\x16\x72\xed\x31\x3e\x74\xd1\x07\x0d\xd6\xe3\x84\x47\x6b\xa1\x73\xd2\xa3\x75\x92\xb5\x84\x4e\x4b\x2f\x43\x37\xbe\xf7\x44\xf0\x31\x9b\x7c\xa0\xc5\xb7\x30\xbf\x86\x71\x3b\x33\x71\x13\xde\x68\x7d\x74\xae\x64\xb4\x55\x1a\x76\x66\x5f\xd6\xce\x4d\xd3\x99\x93\xa6\xab\xe8\x8c\xf6\x91\x19\xdd\x05\x52\x74\x12\x44\xb1\x54\x0f\xdf\xda\xa1\x9d\x45\xb9\xab\x18\x9b\x4e\x3c\xf7\xed\xb8\xbc\x1f\x4d\x66\x17\xb2\x7b\x47\x67\xf5\xa6\x6a\x47\x22\x78\x02\x85\x56\x27\x62\x66\x38\x17\xdc\x9f\xdc\x0b\x79\x67\xf4\x08\xa3\xbb\xf6\x2d\xd6\xaa\x13\xf4\x19\x9c\xfc\xd6\xba\xc1\x6e\x3f\x9e\x7f\x7c\x47\x4e\xd3\xd4\x35\x37\x29\x15\x8c\xcb\xcc\xb5\x13\x18\x10\x5a\xb0\xef\x41\x2a\x26\x78\x8f\xdc\x31\x9e\xf6\x48\xc9\xd2\x2f\x77\x27\xce\x7e\x74\xb8\x0b\xa2\xb0\xae\xce\x8e\x77\xe2\x06\x7d\x2c\xf3\x06\xef\xaa\x88\x88\xe1\x5a\x4c\x2b\xc4\x4d\x6f\x75\x76\x42\x46\x47\xa0\xd9\xde\x44\xbf\x38\x70\x0b\xbb\xa5\xab\x87\x35\x61\xb5\x2e\x4e\x87\xa8\x85\x48\xdf\x11\x55\x16\x85\x90\x5a\x91\x1c\x34\x35\x4a\xef\xc0\x60\x58\xaf\xf9\x27\xfa\xaa\x7a\xe4\xbf\xaa\x1f\xd1\xe1\xa4\x7e\x38\x3c\xfc\xfb\xb7\x17\xff\xfc\xf7\xc3\xc3\x9f\xfe\x2b\xbc\x8a\xac\xd0\x46\x01\x35\x6f\x51\x05\x24\x03\x2e\x52\xb8\xc2\x77\xe0\x9f\xaa\xe1\x66\x71\x17\x34\xd5\xa5\x1a\x4c\x85\xd2\x97\xc3\xea\xcf\x42\xa4\x8b\x7f\xa9\x16\x12\x07\xd9\x4f\xc6\x80\x5b\x34\xa4\x7a\xba\x27\xec\xa1\xa6\x25\x1d\x1f\x55\x37\x6b\xd8\x44\x27\xa7\xf8\xcf\xaf\x3c\x08\x8c\xf4\x74\x2f\x99\xd6\xe8\x7a\x73\xa9\xe0\x62\xdc\x33\xa7\xb6\x16\x3b\x67\x6f\x5b\xd7\x47\xe9\x94\xb4\x55\x3b\xd8\x31\xc0\x10\x22\x0e\x5a\xf6\x20\x57\x0c\x76\xd9\xc5\x7c\x3a\xbc\x24\x33\x0b\xe1\xbd\x01\x8e\x4f\xef\xfd\xea\x93\xd2\xb8\xaa\xe9\x92\x03\x55\xa5\x21\xbe\xb3\x41\x41\x55\x92\x31\xc9\x58\xce\x5c\xac\xa1\x6b\xd0\xa4\xc8\x91\xfd\x71\x90\x14\x65\xcf\xdd\x30\xc8\x21\x17\x72\x5e\xfd\x09\xc5\x14\x72\xa3\x69\xf5\x95\x16\x92\x4e\xa0\x57\x3d\x6e\x1f\xab\xfe\xb2\x0f\x36\x5e\xb0\xfc\xb4\x55\x85\x6b\x57\xa9\xa3\xc8\x90\xbe\x3e\xda\xe6\x41\xbf\x27\xa4\xad\xc2\x8c\xab\x4f\x20\x12\x56\x96\x38\x2b\x70\x56\x50\x44\x7d\x72\x26\xb2\x32\x07\xd5\xab\xc4\x20\x6b\x0d\xe0\x33\xa3\x59\xaa\xbd\x12\xd4\x52\x36\x63\xaa\x8b\x30\xe2\x15\x72\x1a\x73\x11\xf9\xa2\xd4\x45\xa9\x5d\xbd\x99\xa0\xb1\x9b\x50\x68\xb7\xa8\x8a\x02\x34\xc8\xfe\xdb\x83\xf6\xd1\xe8\x54\x6b\x90\xfc\x1d\xf9\xcf\xa3\x1f\x7f\xff\x4b\xff\xf8\xcb\xa3\xa3\x1f\xde\xf4\xff\xf6\xd3\xef\x8f\x7e\x1c\xe0\x3f\x7e\x77\xfc\xe5\xf1\x2f\xfe\x8f\xdf\x1f\x1f\x1f\x1d\xfd\xf0\xed\x87\xaf\x6f\x87\x17\x3f\xb1\xe3\x5f\x7e\xe0\x65\x7e\x67\xff\xfa\xe5\xe8\x07\xb8\xf8\x69\xc3\x49\x8e\x8f\xbf\xfc\xa2\xf5\xd2\x29\x9f\x7f\x6c\x49\x40\xed\xe8\x77\x56\x2e\x68\x71\xc6\x8e\xe2\xac\x1f\xfa\xb5\xd2\xd4\x67\x5c\xf7\x85\xec\xdb\xa9\xdf\x11\x2d\xcb\x76\xc4\xa4\x66\x4a\x5d\x9f\x7f\xdf\xbd\xeb\x5d\xcd\x90\x2a\x76\xbd\x37\x07\x5c\x41\x22\x41\x7f\x0e\x4b\x8e\x7d\x93\x97\x53\x16\x62\x1e\x5f\x1b\x9f\xfb\x35\x18\x77\xaa\x90\x41\xdc\xd7\x5a\x12\x1d\x4b\x91\x0f\x48\xe0\xde\x98\x61\xc2\x87\xbb\xef\x0e\x5a\x58\x41\xfd\x88\xc6\xa0\x68\x0c\x5a\x33\x9e\x34\x06\xdd\x58\x3c\xdc\x5b\x4b\x10\xf0\xd9\xae\x2e\x8c\x95\x1e\x74\xaf\xeb\x68\x41\x0a\x51\x94\x19\xd5\x6b\x3c\x63\x2b\xdc\xe9\xee\xa8\xd7\xf1\xc8\x75\x30\x8d\x65\x68\xf9\x6a\x1f\x26\x39\xcd\x32\xc2\xb8\x3d\xf8\x38\x81\x77\x98\x49\xb0\xaa\x0d\xa1\xd6\x9f\x3d\x33\x4b\xb8\x77\x65\xe5\xc2\xb8\x1c\x45\x94\xa6\x52\x63\xec\x31\x96\x9d\xb3\xac\xc4\x79\x9f\x18\xaf\x8b\xcf\x55\xc2\x61\x95\x0b\xb2\xb2\x33\x66\x46\x95\xf6\xcb\xc6\xd5\x68\x7a\x87\xde\xc6\x04\x52\xe0\x09\x60\x62\x5a\x09\xf5\xb7\x8e\x8c\xde\x46\x2e\xf8\xcc\xce\x41\x49\x5a\xda\x60\x10\x4b\xfe\x56\xcf\xf1\xba\x02\x10\x0c\x22\xde\xf8\x06\xc6\x55\x1c\x02\x52\xfd\x4a\xc3\xae\xf2\xfb\x2a\x2b\xab\x7a\x9e\xc8\x83\xf6\x3c\xb3\xf2\x6c\xb5\x12\x86\x96\x98\x65\x6d\x7e\x6e\x32\xc9\xd7\xe0\x0c\x6c\xcf\x3e\x7f\x75\xac\xb3\x23\xb6\xd9\x0d\xcb\xdc\xc2\x77\xd2\x25\x9b\xec\xc2\x59\x52\x48\x18\xb3\x87\x8e\xce\xe9\x29\xaf\x2d\x31\x2c\x05\xae\xd9\x98\xd9\x9e\xf7\x85\x84\x02\x78\x5a\x15\x2e\xc5\xe4\x70\xde\x84\xcd\x5e\x06\xf3\x58\x81\xbb\x5b\x52\x76\xb3\x4a\xd8\x8f\x74\x8c\x44\x3a\xb6\xf3\xf8\x4c\x74\xcc\x61\xee\xfe\x10\x31\x8c\x3c\x6f\x1f\xfd\x7e\xd6\x0c\x65\x47\x44\xde\x1a\xd1\xea\xcc\xae\x13\x9c\x45\xd9\x2c\xc9\x2a\x0d\xbb\x22\x8d\x5a\xd8\xe0\x35\x32\x65\x13\x03\xd9\x0c\x66\x90\x39\xb9\x89\xe4\x94\xd3\x89\xcd\xef\xd6\xc2\x9b\x6a\x8d\xa2\x65\xf0\x58\xb2\x74\x29\xee\x1e\xe5\x78\x83\xdb\x99\xa0\x29\x5e\x94\x22\xcb\x40\x2a\x92\xb1\x3b\x20\xe7\x50\x64\x62\xee\xd2\xb5\x79\x4a\x6e\x34\xd5\x06\xab\x6f\x40\xef\xe6\xf6\x6d\x85\xb1\xb8\xe2\x61\x99\x65\x43\x91\xb1\x64\x27\xa3\x4a\x73\xe7\x2e\x71\xbf\x8a\x32\xcb\x48\x81\x53\x0e\xc8\x47\x8e\x44\xe3\x34\xbb\xa7\x73\xd5\x23\x57\x30\x03\xd9\x23\x97\xe3\x2b\xa1\x87\x56\xfa\x6e\x06\xdc\xd9\x1b\x09\x1b\x93\x77\x58\xdd\x46\x13\x4d\x27\xa8\x3b\x79\x37\x60\xcf\xc0\x3f\x9c\xc0\xd2\x87\x7b\xa6\x56\x2a\x2b\xad\x11\xe7\xb7\x38\x93\xa1\x55\xf6\xef\xcf\xbe\x4d\x19\x1b\x43\x32\x4f\xb2\xf6\x47\xeb\x34\xc1\x00\x86\x3a\xe3\x3c\xc0\x6f\x57\x4d\xdd\xe5\x78\xa2\x16\xc8\x38\xb1\x65\xce\x6d\xfd\xf6\x1a\xd5\xab\x15\x59\x6d\x57\x75\xaa\x24\xee\xcc\x3c\xdb\xb2\xcd\x42\x28\x7d\x63\x34\xf4\x4e\x8a\xa1\x1f\x0e\xfd\x74\x04\x4b\x3e\x67\x19\xa4\x84\xe5\x39\xa4\x46\x8b\xcf\xe6\x84\x8e\x35\xe6\xda\x36\x2c\x04\x89\x04\x8b\xb5\xae\x8a\xc9\x94\xf2\x34\x03\x49\xc6\x94\x65\xce\x1e\xd0\xb8\x5f\x83\xcc\x19\x47\xb3\x80\xf5\xc8\xa2\x89\xc1\xfc\x95\x24\x42\xfa\xf2\xf4\x4c\x2b\x7f\xa9\x3e\x98\xc8\x47\x02\x04\x58\x74\x2d\x93\x51\x26\x92\x3b\x45\x4a\xae\x59\x66\x17\x23\xc4\x1d\x49\x44\x5e\x64\x78\x74\x5a\x9c\xac\xea\x9f\xfd\x0a\x95\xfa\x66\x76\x75\xf2\xdb\xfa\x12\xfe\xb0\x2b\x43\xef\x40\x10\xeb\x42\x0c\x83\x07\x48\x3a\xcb\xf3\xbf\x78\x80\x24\x28\x2c\x81\xfd\x18\xf0\x44\x63\x9e\x27\xbd\x83\x57\x54\xc9\xae\x45\x2e\x5d\x38\x1a\xf0\x3b\xb3\x73\xfa\x42\x58\xee\x15\x24\x63\x1c\xe9\x9b\xcb\xaf\x23\x8c\x2b\xc3\xd9\x1b\x87\xc1\x1e\x3d\x27\xb4\x92\x94\x49\xac\x82\x30\xaf\x02\xa9\xfd\x5c\x58\x60\x40\x08\x4d\x8e\x0e\x4f\x0e\x8f\x97\xec\x8f\x87\x46\x02\xc9\xc0\xd2\x5a\x9f\xb8\x57\x2d\x4a\xb1\xbc\xc8\xe6\xb8\x8e\xc3\xb4\x47\x98\xf6\x91\xd6\xb2\xe4\x7e\x55\x2e\xe9\xaf\x47\x94\x20\x5a\x52\x5f\x5d\xc5\xfe\x6a\x6e\xd2\xb2\x74\x54\xfe\xe8\xf0\x97\xc3\x1e\x01\x9d\x1c\x93\x7b\xc1\x0f\x35\x2e\x7f\x40\x6e\x85\x11\xa5\xeb\x89\xe6\xa2\x24\x1c\x6c\x60\x3f\x3c\x14\x19\x4b\x98\xce\xe6\x48\xb1\x88\x28\xb5\xcd\x21\xa6\xda\x27\x1b\x5e\x3c\x30\xed\xe2\xd5\x0c\xc9\x78\x83\xd0\xb4\x54\x8b\x50\x23\xe6\xcc\xe0\x64\x0a\x34\xd3\x53\x1b\x24\xc2\x05\xef\xff\x0b\xa4\xc0\x1c\x44\xee\xae\xbc\xba\xaa\x7f\x9d\x68\x0e\x86\x88\x7e\x0d\xdd\x35\xf1\xf9\xe6\xf6\x76\xf8\x35\xe8\x05\x92\x61\xde\xe2\x43\x77\xd0\x1a\x00\x72\x2c\x64\xbe\x07\xb4\xa3\x1b\x67\x65\x9f\x14\x42\xee\x03\x09\x9b\x0a\xd5\x6a\x2f\xc9\xd2\x7e\x0a\xa5\x51\x1b\x72\xd2\x18\x87\xc4\xec\x60\x33\x86\xc4\xf7\xb9\xb9\x1c\x0e\xc8\x3f\x45\x69\xbe\x66\x44\x47\xd9\xbc\xaa\xc4\xa0\x40\x93\x03\x33\xd5\x81\x21\x4f\x06\x1b\xbe\x01\x9a\x1a\x15\xc5\x50\x0f\xa0\xfb\xd1\xcf\x8a\xb8\xf3\xe0\xd6\xd6\x2d\x1f\x28\x95\x16\x39\x99\xba\xcf\x6e\xa6\x5e\xba\x93\x31\xc0\xd3\xe3\xf3\x9a\x24\x14\x96\xc2\xb9\x67\x5e\x1d\xfd\x5a\xa2\x1b\x16\xee\xee\xf7\x11\x96\xb1\x4a\x42\xb0\xb9\x86\x4e\x36\x31\x88\x5b\x60\x19\x54\x83\xdd\x5c\x25\xe1\xd8\xe3\xda\xa3\x3b\x27\x72\x2e\x4e\x84\x4e\xbd\xf6\xb1\x5e\x9d\x56\x1e\xed\x26\x6e\x80\xac\x32\xb2\x3a\x9c\xb1\xd6\x17\x6b\xcf\x41\x73\x8c\xf7\xa1\x26\x94\x0b\xce\x12\x9a\xb1\x7f\x41\x4a\xca\x42\x70\x17\x3f\x87\x72\x4e\x42\x15\xf4\xd1\xa9\xcb\xb5\xab\x99\x56\x67\x2b\x9a\xe3\xa8\x85\x40\xe1\x03\xdd\x78\x86\x3e\xda\xf7\xed\x6f\x81\xcd\xcf\x01\xe6\x6e\x50\x8c\x74\x09\x81\xa2\x83\x00\xf2\xe5\xf0\x71\x2d\x8c\xb6\x8b\x09\x9e\x96\x84\x23\x31\x52\x20\x67\xed\x51\xa0\xbb\x4f\x17\xbb\xdb\x15\xfc\x58\x91\x8d\x2d\x09\x2f\xf3\x11\xc8\x3a\xff\x45\xea\x65\x80\x04\xf1\x0f\x57\xf6\x76\x6f\x34\x6e\x36\x69\x34\x4f\xfe\xe5\xcf\x7f\xfe\xe3\x9f\x07\x76\xfa\x2a\x16\x82\x93\xcb\xd3\xab\xd3\x9f\x6f\xbe\x3f\xc3\x14\xdc\xb6\x50\xed\x28\xd0\xb3\xeb\x30\xcf\x4e\x83\x3c\x3f\x69\x88\x27\x26\x96\xb4\xa6\x22\x4d\x0f\x03\x4e\x69\x30\xc0\x68\x87\x46\xaf\x75\x12\x66\x50\x12\xcd\x48\xb4\x4d\x73\xad\x39\x6a\x7b\x71\xc6\x74\x52\xdc\x88\xe4\xae\x43\xed\xe9\x1c\x0a\x09\x89\xb5\xc6\xdd\x9e\x0d\xed\xec\x46\x8b\xbd\xfa\x78\x5b\x27\x34\x60\xd4\x0f\x79\xef\xad\x58\xdf\x38\x7b\x9d\xd1\x7c\xef\xa0\xd0\x95\x81\x60\x44\x93\xbb\x7b\x2a\x53\xb4\x9f\x51\xcd\x46\x2c\x63\xb6\xc4\xb0\x6f\x3d\xc9\x85\x0d\x2b\xb4\xa5\xd4\xc4\x78\xb1\x80\x67\x6d\x74\x45\xc3\x98\x65\x81\x63\xca\x32\xb4\xd3\x96\x5c\xb3\x1c\x5c\xdc\x51\x52\x54\x86\xc3\xd0\x72\x1e\x55\x3c\x3f\xf6\x56\xc5\x3b\xfc\xe8\x7d\x87\x5b\x6b\x7b\x6d\xa3\x1f\xf7\x98\xd5\x39\x16\x67\xd3\x4e\x22\xab\xfb\x55\xb0\xba\x42\xc2\x8d\x16\x45\x47\xbe\x18\x3b\xd9\x1a\x4f\xcc\x08\xc6\xc2\x10\xe1\xb5\xae\x15\xdf\x89\x98\x63\x0a\xa2\xb7\x9d\x89\x86\xfb\xc4\xc6\x7d\xaa\x32\x99\x7a\x33\x28\x07\xa5\x4e\xd0\xe9\x52\x16\x56\x37\x46\x72\x5d\x4a\xe8\x99\xaf\x83\x1c\x57\xd7\xab\x73\x29\xcc\xeb\x81\xdb\x1f\x41\x27\xd6\x3e\x1c\x10\x72\x2c\x3f\xea\x96\xbf\xe8\xac\x49\x24\x55\x53\xc0\x22\x26\xf0\xc0\x7c\xcf\x95\xa1\x48\x0f\x0f\xeb\x4f\x31\x8c\x65\x22\x69\x02\xa4\x00\xc9\x84\x61\x46\x25\xd7\xa9\xb8\xe7\x64\x04\x13\xc6\x95\x07\x85\x99\xdb\xc3\x0c\xbd\x3e\x4c\x55\xe5\xe7\x06\xe4\xba\x51\x52\xc5\x25\x3b\x25\xa2\x3e\x9a\x6e\xcd\x8b\xfe\x2a\xe4\x58\x41\x63\xe6\x0a\xc2\x3e\x08\x57\x6f\xb0\xe4\xa3\x92\xe3\x9b\x53\xc8\xe8\xdc\xc6\xb4\x8e\x19\x47\xcd\x51\xaa\xe3\x0e\xfc\x5a\x06\x84\xf5\xb5\xb5\xeb\xc0\x86\x00\x34\x99\xb6\x73\x31\x47\x47\xd8\x86\x23\x3a\xc2\xda\x4c\x12\x1d\x61\xd1\x11\xf6\xc4\x88\x8e\xb0\xe8\x08\x5b\x18\x7b\xab\x25\x45\x47\xd8\xce\x23\x3a\xc2\x1e\x1f\xd1\x11\xb6\xc1\x88\x8e\xb0\x0d\x47\x74\x84\xad\x1f\xd1\x11\xd6\x6e\x31\xd1\x11\x16\x1d\x61\x6e\xfc\xfa\xac\x83\x7e\x44\x47\xd8\xd2\x24\xd1\x11\x16\x1d\x61\x1b\x8f\xbd\x55\xf1\xa2\x23\xcc\x8e\xe8\x08\x6b\x8e\x5f\x17\xab\xf3\x6e\xa4\xa1\x51\x28\xdb\xe7\xe7\x0d\xd1\x75\xc1\x12\xe7\x8d\x0a\x1b\xe0\x55\xaf\x0a\x7a\xde\x05\x25\x4e\x7c\x5a\x91\xf3\x3b\xd5\xde\xac\x95\xb9\x5f\xdb\x3a\x44\x7c\xc2\xa4\x3a\x29\x84\xfd\x4f\xed\x0e\x09\xfc\x20\x56\xad\xde\x3d\xff\xee\xd9\x32\xcb\xda\x38\x3f\x3e\x8f\xe3\x63\x4f\xbc\x44\x1d\x38\x3b\xa2\xa3\xe3\xd5\x39\x3a\x5e\x4f\x07\x60\xe7\xff\xbf\x9d\x4a\x50\x53\x91\xed\x8c\xe8\x0d\x24\xff\xc0\x38\xcb\xcb\xdc\xe0\x9c\x32\xf8\xcc\x66\x55\xa0\x81\xaa\xd0\xd5\x52\x6c\x6b\xab\x34\x37\xb2\x14\xb0\x70\x2b\x65\x99\xd9\x46\xcc\x45\x9d\xd2\x99\xc1\x75\x55\x26\x09\x00\xb6\x85\x0b\x35\x9c\x3f\x0e\xaa\x37\x55\x6d\x40\xde\xb6\xa3\x37\xed\x98\xb8\x2d\xad\x8a\xb3\xfc\xf1\x0f\x3b\xcd\x31\x91\x45\x37\x74\xf9\xeb\xeb\xe1\x59\xd8\xf2\x9b\x7b\xb2\xcc\xf8\x4c\x64\x08\x55\x6a\x6f\x32\xc2\xda\x33\x12\xe9\xf6\x6a\x47\x2b\x95\xa3\x0b\x1e\xd1\x56\xaa\x6e\xda\xcd\x8c\xec\xdc\xb4\x1c\x4d\x70\x2f\x6d\x05\xff\x8d\x65\xe7\xd6\xd4\xad\xbd\x3c\xdb\xfe\x38\x10\x2c\xb1\x83\x1f\xde\x19\x80\x0f\x5c\xcb\x69\xcf\x82\x43\xc5\xc5\x77\xb5\xd2\x82\x14\x19\xad\xfb\x52\xe1\x0e\x7c\x83\x7c\xe3\x6c\x0a\xc9\xdd\xb5\xf3\xd1\x1e\x29\x80\x4a\x9e\x9c\x30\x3d\x2d\x47\x83\x44\xe4\x27\xe6\x18\xdb\xff\x8c\x32\x31\x3a\xc9\xa9\xd2\x20\x8d\x88\xe9\xd8\x52\x3f\x31\xb3\x30\x3e\x19\xe4\xe9\xf1\x80\xfc\xc8\x6d\x76\x7d\xdd\x07\x33\xa8\x2d\x61\xde\xef\xeb\x7c\x8c\xc0\x50\x44\x21\xc3\xf6\xe5\xa3\x39\x2e\x6f\xd0\xa6\x50\x73\x6b\x36\xd2\xd2\x3f\xfe\xf9\x7d\xe3\x91\x72\x91\x0e\x8c\x24\x2f\xcd\x07\xde\x59\x2c\x48\x07\xbe\xef\x3d\xf2\x7b\xef\x8d\x38\xbb\x2f\xbe\xee\x3d\xac\x76\xdd\x81\x7f\xbb\x0b\xdf\x76\x77\x7e\xed\x4f\x50\x14\xfa\x25\xfb\xb3\x3b\x34\xfa\x75\xe4\xc7\xfe\x1c\x3e\xec\x4e\xbe\xba\xad\xef\xfa\xf3\xf9\xad\xbb\xf9\xdc\x2e\xd5\x8d\x97\xea\xab\xee\xc0\x78\xdf\xa5\xe1\xbe\x33\xa3\xfd\x27\xf3\x4d\xb7\xf7\x4b\xef\x81\x4f\xba\x35\x90\x19\x67\x9a\xd1\xec\x1c\x32\x3a\xbf\x81\x44\xf0\x74\x67\x3e\xb6\x50\x8b\xb4\x3a\x3f\xca\x4e\xeb\x2c\x58\xcd\x44\x8f\x29\x75\x25\xd7\x8d\xde\x66\x13\x5b\xbc\x97\xc3\x89\x2d\xe8\x6f\xb6\xab\xdc\x4b\xbf\x05\xd9\x1b\x53\x99\xcd\x7a\xe9\x72\x13\xbf\x11\xf7\x44\x8c\x35\x70\x72\xc4\xb8\xdf\xc7\xe3\x40\xd9\xac\xed\x96\x15\x5a\x9b\xab\x6f\xdf\xf8\x9b\x5f\x9f\x41\x12\x4d\xaf\x4a\x7d\x7a\xfb\xb0\x7b\xd1\xd3\x06\x62\x77\xe3\xb8\xcc\x9a\x46\x62\x6b\x38\x6e\xd2\x9b\xb7\x75\xd1\xe8\xb7\x38\x6f\x75\xda\x28\x4f\x89\xcb\x84\x7b\x7d\x9b\xd6\x3a\xe2\xa6\x29\xfa\x55\x11\x36\x4f\xd9\x93\x6f\xcf\x86\xd1\x9c\xbc\x5f\x46\x99\x67\x8a\x5a\xd9\x43\x41\xf7\x85\x46\xaa\x44\x41\x77\x8b\x11\xe4\xc6\x7e\x2d\x69\x02\xc3\xce\x65\x04\x7f\x9c\x48\x5a\x4a\xea\x08\x60\x25\xf2\xf9\xc3\xc3\x01\x52\x7b\x9a\xaa\x7c\x62\xcc\xd4\x1d\x97\x59\x36\xb7\x36\x87\x46\xf6\xb5\xf5\xc2\x2f\x26\xf3\xa2\xe1\x7f\xc5\x5b\x6a\xc1\xb2\x90\xc2\xf1\x4c\x59\x72\x6e\x68\x70\xdd\xf9\x0d\x05\x49\x2c\x46\x4d\x1b\x29\xc3\x8a\x4d\xcc\xf2\x0d\xff\xc3\x6c\xe2\x3a\x34\xb1\x31\xa1\x79\x7a\x2c\x64\xc2\x46\xd9\x9c\x4c\x69\x56\xb5\xf9\xa1\xe4\x8e\x65\x99\x9b\x66\x40\x6e\x40\x5b\xc7\x85\xe5\x9d\x99\xe0\x13\x5c\x1c\xe5\xbe\xbd\x24\x24\xe6\xd9\x24\x03\xca\xcb\xc2\xbe\xcf\x70\xe2\xb9\x28\xa5\x7f\xdf\xa0\x72\x7f\x54\x1c\x98\xb3\xac\x17\x34\xb1\x7b\x74\x63\x6b\x13\x8d\x32\x02\xc0\x47\x5f\x7c\xbb\x17\xce\xe9\xeb\xa3\xab\xa0\x85\x51\x21\xc5\x8c\xa5\xd6\x87\xe2\xc1\x86\xed\xb2\x6d\x9b\xa2\xea\x3c\x73\xc1\xfb\x1c\x26\x14\x05\x15\x77\x8a\xec\x9e\xd9\x79\x6c\x6c\x01\x4f\xb1\x71\x91\x91\xf0\x45\xd1\x48\xe7\x9f\x31\xdb\x72\x39\x80\x1c\x39\xe2\x82\x08\x8c\x54\x2d\x39\xd3\xb6\x8d\xff\xb4\xd4\x24\x15\xf7\xfc\xd8\xd9\xac\x98\x22\x94\x8c\x40\xd3\x20\xd6\xd4\x31\x38\x45\x80\xd3\x51\x66\xf6\x1c\x43\xb1\x6e\x57\x02\x88\x8c\x81\xea\x52\x02\x99\x50\x0d\x2b\xe5\x1c\xfb\xbd\x8f\x83\x97\x29\x67\x60\x1d\x93\x92\x2b\x68\xc9\xde\x3b\x13\x8e\xfe\xf2\xa7\xdd\x68\x04\xcb\x41\x94\xfa\xb3\x68\x7f\xf7\x53\x96\x4c\x43\x61\x96\xe5\xa0\x88\x28\x17\xd4\xe2\xb7\xee\xb1\xd5\x3b\x14\x55\xc0\x55\x63\x57\xf3\xf1\x0a\xeb\xd7\x62\x39\x86\xba\xbf\x37\x46\x90\x9f\x5f\xdd\xfc\xfc\xfe\xf4\x3f\x2e\xde\x0f\xc8\x05\x4d\xa6\x61\x4d\x0e\x4e\x28\x12\x0d\x24\x14\x53\x3a\x03\x42\x49\xc9\xd9\xff\x94\xce\xad\x7c\x54\x3d\x7b\xdc\x69\x45\xfa\x1d\xb9\xaf\xa1\x36\x3b\x61\xfc\xca\xa6\x77\x38\x9b\x8b\xd8\x12\x0a\xb0\x4d\xcd\x92\xf8\x54\xf9\xb2\xe7\x56\x45\x40\x81\x0b\x03\xeb\xcf\x3f\x5e\xdc\x60\xc0\x7e\x21\x6d\xa5\x12\x8c\xf0\xc2\xeb\x38\xd3\x08\xcc\x13\xae\x3f\xf1\x80\x9c\xf2\xb9\xbd\x68\xcf\x14\x53\x24\x63\x4a\x03\x72\x3d\x27\xb6\x79\x2f\xf9\xc1\x9b\x01\xfe\xef\x80\xd0\x34\x95\x46\xae\xab\x02\xd7\x92\xa5\x48\x52\x2b\xf9\xb1\x51\x16\x7c\x00\x07\x6d\xe3\xd4\x3e\x88\xd4\xad\x1c\x39\x09\x7a\xc8\x2c\x1b\x54\x5a\x52\x0d\x13\x96\x90\x1c\xe4\x04\x48\x41\x75\x32\x25\x39\x9d\x93\x44\x48\x59\x16\xb6\x9b\x41\x4a\x35\x1d\x90\xaf\x84\x24\xb9\x3f\xc4\x06\xe7\x0d\x1f\xbe\x59\x1d\x39\x50\x9f\xec\xf0\x9f\x4c\xa9\x12\xd4\xc9\xdb\x37\x7f\xfd\xc3\x9f\xff\xfc\xaa\x1a\xe0\x55\xa1\xbd\x18\xf7\x12\x34\xc0\xa3\x7e\x17\xec\xae\xdb\x86\x88\x8c\x4f\xb2\x10\xbf\x76\x63\x00\x6d\xb5\xcc\xb6\x3a\x66\xbf\xfe\x82\xe1\xae\xaa\x66\x27\x8d\xf8\xea\x35\x74\xd4\xbe\xaa\xe6\x83\x5e\xb1\x72\xb4\x41\x84\x1d\x89\x2f\x87\xfe\x60\x3a\x39\x27\x5f\x68\x63\x5b\xd4\x31\x50\x3d\xf2\x86\xfc\x9d\x3c\x90\xbf\xa3\xa2\xf5\x97\xb6\xcd\xbe\xda\xaa\x40\x5d\x84\x34\x19\xfd\xfe\x72\xd8\x11\xc4\xff\x61\x88\xa6\x99\xd1\x40\x55\x0b\x32\x62\x4e\xb0\x87\x07\x0d\xd2\x08\x9a\x6e\x27\x9e\xb5\x4d\x9a\x59\xe0\x67\x44\x33\xeb\x78\xb8\x1c\x37\xc3\xa8\xb6\x43\x34\xf3\xf8\x37\x42\xe9\x2b\x47\x85\x9a\x0d\x7f\xea\xd9\x72\x24\xfc\x0d\x32\x66\xf8\x86\xd2\xf5\x01\x53\x24\x15\x18\xd5\x65\x43\x9c\xa7\xac\x45\xb0\xc6\xfe\xa0\x71\x3b\xff\x7d\x63\x3f\x1f\xdb\xa9\x05\x53\x0a\xea\x40\x4e\xc4\x0a\x6a\x74\x15\x22\x75\xd2\x99\x59\x56\x1a\xf0\x8c\x47\xc4\x33\x67\xb5\xa9\xec\xcd\x88\x4b\xe6\x3c\x25\x94\xdb\x24\x93\x31\x48\x69\xa3\xd2\x47\x73\x1f\x1c\xd8\x7a\xf3\x5a\x9d\xa4\x42\x0a\x2d\x12\xd1\xa2\x93\x5b\xd3\xdb\xed\xa6\x43\x20\x14\x16\x77\x1d\xe4\xbf\x3b\x1f\xf6\xc8\xed\xd9\x10\xbb\x5b\xdd\x9c\xdd\x0e\x9b\x3a\xcb\xc1\xed\xd9\xf0\xe0\x59\x41\x41\xbc\xc0\x87\x26\xea\x1d\x26\x69\x98\xa0\x8c\x34\xd9\xcf\x69\xd1\xbf\x83\xf9\x8e\x3c\xb5\x0b\xbe\xde\xaf\x76\xb8\x93\x0f\xb2\x60\xce\x69\xb1\xf5\x6c\x12\x68\xca\x3e\x53\xa6\x97\x0f\xbb\xad\xde\xb9\x3a\xe5\x2b\x17\x33\x48\xad\x94\xee\x9f\x00\x9e\x16\x82\x19\x79\x31\xe6\x81\x6d\xff\x74\xcc\x03\xdb\x78\xc4\x3c\xb0\x98\x07\xb6\x3c\xf6\x26\x70\x36\xe6\x81\xbd\x2e\x0f\x7e\xcc\x03\xdb\x7e\x3c\xbb\xe3\x3e\xe6\x81\xad\x1e\x31\x0f\x2c\xe6\x81\x6d\x36\x62\x1e\xd8\xf6\x63\xef\x42\x8e\x62\x1e\xd8\x56\x23\xe6\x81\x2d\x8f\x98\x07\xb6\x66\xc4\x3c\xb0\x35\x23\xe6\x81\x2d\x8f\x98\x07\xb6\xdd\x88\x79\x60\x31\x0f\xec\x55\x87\xc7\x92\x98\x07\xe6\x46\xcc\x03\x7b\x15\x41\x80\x24\xe6\x81\x6d\x34\x62\x1e\x58\xcc\x03\xdb\x65\xc4\x3c\xb0\xd7\x62\x94\x89\x79\x60\x31\x0f\xec\xd7\x23\xe8\xc6\x3c\xb0\x98\x07\x16\xf3\xc0\x62\x1e\xd8\xa3\xab\x88\x79\x60\xaf\x41\x05\x94\xa0\xd8\xbf\x60\x28\x32\x96\xcc\x5b\x47\x29\x5e\xbb\xc6\xc7\xca\x4d\x4b\x0a\x9c\x37\x08\xad\x6a\x91\x79\xb2\x67\x09\x37\xd7\x01\xe0\xc2\xc4\x9b\xaa\xf9\xf3\x27\x00\xc1\x5e\x24\xdf\xf8\x0f\xbc\xda\xdd\x93\xd2\xf7\x0d\x08\x2c\xf8\x76\xb3\x5b\xb4\x56\x11\xc2\x0f\xe9\x28\x1e\xfc\x30\xcc\x88\xac\x30\x41\x8b\x8a\x82\xb1\xb5\x08\x42\x8b\x22\x63\xa0\x06\xe4\xa6\x6a\xc0\x83\xd4\x4b\xbd\x23\x49\x51\xf6\x48\x0e\xb9\x90\xf3\x16\xda\x44\x07\x02\x67\x63\xd7\x3a\x02\xd9\xb5\x9d\xd3\x83\xc1\x28\x11\x45\x91\xcd\xad\x30\x55\xa7\x92\x56\x50\x63\x9e\xb8\xa4\x28\xee\x2c\x44\x79\x30\xdd\x50\xc3\xae\x84\xbe\x76\x08\xff\x6c\xb1\xf6\xeb\xa2\xca\xa9\x16\x39\x4b\x76\x21\xd8\x96\xc6\xb6\x8f\x29\x3f\x13\x79\x51\x6a\x68\x90\x6d\x0b\x2c\x2b\xc9\x31\x15\xaa\x70\xed\xa3\xc1\x13\xc1\xc7\x6c\xe2\x44\xf1\x13\xdb\xd1\xbd\x5f\x7d\x4f\x3f\xe8\xa2\xfe\x02\x43\xc1\x93\x8c\xb2\xdd\xfd\xf6\xcd\xd0\xaa\x33\x9c\x0b\x33\x74\xeb\xe0\x2a\x8c\xd1\xad\xa0\xd5\xab\x02\x97\x98\x3d\x26\x03\x7f\xc9\x3e\xdc\xb3\x91\xbe\x46\xff\x40\xa1\x73\xc5\x86\xfe\xc8\x6b\xf1\x98\x13\x9a\x15\xd3\xc7\x05\x64\xb3\x90\xf3\x39\xa7\x39\x4b\x3c\xc6\x9c\x66\x99\x48\xac\x42\xd4\x14\x91\xfd\xdc\x76\x3e\xf3\x92\x3c\x2f\x35\x1d\x65\x30\x20\x97\x36\x43\x48\xf0\x6c\x6e\xb0\x49\x81\xf6\x8e\x0f\xb7\xfd\x3b\xc7\x60\xb5\x0f\xc0\x68\x19\x7c\xb1\x52\x1a\xc2\x0d\xb1\xd9\x50\xc0\xcd\x29\x13\x1c\x08\x70\x2d\xe7\x66\xef\x86\x22\xbd\x31\xdb\xd7\xb8\xbb\x75\x92\x54\xcb\x98\x8b\x2e\xe2\x2d\x5a\xc6\x5a\x74\x13\x21\xd1\x3e\x3a\x62\xd9\xcd\x1b\xe4\x2d\x86\x81\x8f\x8d\x5d\x2d\x44\x3a\x58\x71\x2a\xbd\x68\x30\x14\xa9\x61\x70\x12\xc2\x56\x78\x4e\x3f\xc4\x03\x92\xd3\x3b\x54\xb1\xa9\xae\x39\x1f\x9d\x51\x96\x99\x23\xb4\x22\x1f\xbf\x5d\xe0\x44\x07\xa2\x41\xd7\xc9\x60\xa4\x2d\x06\x75\x99\xcc\x45\xb0\x73\x57\xce\x76\xab\xfe\x40\x96\x18\xef\x7b\x9c\x2b\x08\xc7\x32\x38\x91\xd3\x07\xd4\x59\x69\x2e\x4a\xae\x6d\x86\x97\xe5\xcf\x15\xd1\xb7\x41\x6b\x7b\xc7\x79\x49\x37\x64\x87\xa6\x3e\x05\x66\xd8\x45\x34\x39\xd5\x1a\x24\x7f\x47\xfe\xf3\xe8\xc7\xdf\xff\xd2\x3f\xfe\xf2\xe8\xe8\x87\x37\xfd\xbf\xfd\xf4\xfb\xa3\x1f\x07\xf8\x8f\xdf\x1d\x7f\x79\xfc\x8b\xff\xe3\xf7\xc7\xc7\x47\x47\x3f\x7c\xfb\xe1\xeb\xdb\xe1\xc5\x4f\xec\xf8\x97\x1f\x78\x99\xdf\xd9\xbf\x7e\x39\xfa\x01\x2e\x7e\xda\x70\x92\xe3\xe3\x2f\xbf\xd8\x79\xc9\xad\x6d\xd4\xdd\x59\xa8\x3b\xb2\x4f\x7f\x12\xeb\xb4\x8b\xe3\xec\xe8\x2c\xba\x18\xf4\xa5\xd3\xe8\x2c\x48\x8f\x9d\x46\xcf\x25\x51\x11\xa9\xe6\x61\x8a\x88\x9c\x69\xa3\xc0\x19\xb1\x86\x86\x99\x67\x0b\xea\x89\xa3\x03\x98\x7b\x49\x31\x45\x2c\xc8\xda\x0a\xb4\x1a\xe1\x4d\xb1\xa8\x1e\x71\xc2\xf2\x22\x83\x1c\xb8\xc6\xf3\xdc\xf7\x92\x20\xea\x8b\x83\x7a\x25\x89\x95\xd8\xe1\x21\x01\x48\xdd\xcb\x22\xe9\x78\x7a\x44\xd2\xf1\x1a\x49\x87\x82\xa4\x94\x4c\xcf\xcf\x04\xd7\xf0\xb0\x93\x47\xb4\x49\x39\x6e\x9a\x13\x3a\x85\xcc\xc5\xb4\xba\x6b\x44\x14\x36\x83\x73\xa1\x44\xd6\x54\x94\x59\x8a\x69\xd9\x25\x47\x87\x90\xad\xb7\x01\xda\x7a\x6b\x50\x20\x44\x69\x71\xf1\x25\xde\xff\x62\xdd\x42\xff\x53\xb2\x19\xcd\x80\xeb\xe0\x89\x21\x7a\x1c\xc2\x87\x36\x3d\xf3\x9a\xaa\xbb\xfa\xc0\x43\xbf\x10\x69\x7d\xbe\x4f\xfc\x27\xe1\x4f\xf0\xa0\x5f\xa2\x92\x8e\xf2\xd3\x50\xb2\x19\xcb\x60\x02\x17\x2a\xa1\x19\xd2\xb5\x6e\x58\xc9\xe9\x9a\xd9\x71\xe3\xa5\xc8\x94\x91\xf9\x0d\x29\x27\xd4\xbb\xec\x50\x13\x9e\x50\xc6\x6d\x85\xab\xc2\x3f\xac\xac\xef\xcf\x70\x87\x82\x4a\xb3\xc1\x95\x8f\x0f\xf5\xea\x91\x10\x99\xcb\x5d\xce\xe6\xf5\xfc\x2e\x8b\x9f\x8b\x9f\x39\xdc\xff\x6c\x66\x53\x64\x9c\xd1\x49\xe5\xda\x33\xca\xf6\xa2\x77\xbe\x9e\x7a\xed\x07\x60\x62\x70\x09\x84\x66\xf7\x74\xae\x6a\x47\x67\x50\xcb\x4d\xbd\x23\x6f\x8f\x11\x9d\xa9\x22\xd5\x1c\x29\xf9\xc3\x31\x86\xeb\x9d\x9d\x0e\x7f\xbe\xf9\xe7\xcd\xcf\xa7\xe7\x1f\x2e\xaf\xc8\x95\xd0\x60\x79\x5e\xa0\xff\x24\x95\x81\xc9\xac\xb2\xb2\xff\x0d\x84\x1a\xa0\x8e\x85\xd1\xe7\x3c\x15\xf7\x6a\x67\x2b\xa8\x45\x3f\x03\x3c\xa0\x7c\x37\x33\x0f\x2d\x28\x76\x38\x6f\xc1\x61\x96\x22\xc2\xc3\x49\x91\xc5\xa7\xe9\x49\x2a\x45\x61\x81\xe0\x9d\xd2\x81\x81\xa4\xe1\xf6\x0a\x33\xdb\x70\x7f\xc7\xcd\x09\x27\x92\x72\x5d\x7b\x67\xeb\x3d\x73\xad\xd5\x07\xad\xb7\xe3\xf9\x18\x7f\x17\x56\x02\x9a\x76\x57\x97\xe0\x34\x4d\x21\x6d\x80\xff\xd5\xe5\x13\x9d\xf9\x8f\x0b\xdc\x5e\x64\xf8\xf1\xe6\xf2\x7f\x2f\xe0\xf1\xbc\x68\x97\xd8\xd0\x4d\x8d\x1b\x29\x8a\xce\x76\xf7\xda\xd5\x50\x89\xfb\xbb\x17\xfb\x5b\x71\xcb\x6e\xc2\x69\xaf\x4b\xde\x2c\x4e\x5a\xcf\x4f\x72\x91\xc2\x80\x0c\xab\xb8\x9e\xe6\xd5\xa0\x54\x19\x95\x40\xcc\x2d\x5c\x33\x9a\x65\xf3\x50\x44\xd3\xc2\xd6\x13\x69\x54\x59\x0b\x09\xf9\x98\x66\xea\xb9\xa9\x71\x1b\xde\x68\xe4\x88\x0f\x46\x5d\xee\x64\x3b\xaa\xd9\x48\x0a\x5c\x68\x27\x58\x9b\x55\x62\xe5\x3a\x29\x12\x62\x75\xf3\x20\x79\xa2\xc1\xdf\x94\x8d\x2d\xf2\xac\x91\x29\x0f\xec\x61\x35\xb3\x75\xcb\x96\x0a\x16\x05\x74\xc7\x1a\x6b\x6d\xdd\xcc\x2e\x81\xa6\xe8\xb5\x28\xa8\x9e\xda\xd8\xe7\x9c\xaa\x3b\x48\xed\x0f\x4e\x34\xab\x1c\x27\x68\xe8\xf5\xaf\xba\x35\xeb\xf6\x3e\x12\x14\xc9\x6c\x44\x36\x7a\x57\x20\x7d\xe6\x5d\x6f\x71\x08\x0d\x50\x3e\xf2\x6c\x7e\x2d\x84\xfe\xaa\x2a\x88\xd3\x09\x06\xfc\xc3\x49\xcb\x4d\xc7\x15\x8a\x93\x14\xdf\xdb\xc7\xdd\xc0\x43\x15\xd6\xe2\x39\xaf\x77\xfc\xa5\x1f\x29\x59\xf2\x53\xf5\xb5\x14\xe5\xce\x4c\x6c\x49\xd8\xfc\xfa\xf2\x1c\x49\x51\xe9\x42\x0b\xb9\x96\x73\x2c\x02\xb6\x5c\xc9\xb9\x52\x0c\xbe\x73\xc1\x91\xe1\x99\xa8\xe3\xd8\xc8\x07\x3a\x27\x34\x53\xc2\xc3\xd2\xb9\xb5\x16\xb5\x50\xa7\xe2\x9a\xcb\x23\xa1\xa7\x4b\xba\xad\x39\x50\xcb\xcf\xf5\x82\x48\xc3\x3a\x1e\x80\xf1\xa5\xc7\x35\xfa\x4c\x0a\x09\x09\xa4\xc0\x93\xe7\xde\xf6\xe7\x0e\xd0\x43\xd4\xb9\x12\xdc\x1c\xcc\x4e\x90\xe7\xb2\x8a\xcc\x74\x20\x0d\x51\x05\x9d\x62\x4e\xfb\xa3\x18\xe9\x89\xc7\xb2\x54\x20\x6d\x58\xaa\x2c\xc1\xee\xe4\xb7\xe5\x08\x32\x03\x79\xa3\x92\x62\x1d\x51\xaa\xad\x39\x83\xe5\x74\x02\x84\xea\x0a\xd3\xb4\x20\xc0\x55\x29\xdd\x26\x32\x4d\x52\x01\x75\x1d\x2d\xaa\xc8\x77\x97\xe7\xe4\x0d\x39\x32\xef\x3a\x46\xfc\x19\x53\x96\x61\x10\x28\x06\x95\x2c\xe8\xa8\x63\x3f\x05\x2e\x09\x91\x97\x08\x69\x89\x44\x8f\x70\x41\x54\x99\x4c\xfd\x9a\x8c\xde\xeb\xd5\x66\x97\xb8\x84\x9e\x97\xfd\xc4\xf5\xe7\xa5\x50\xdf\x29\x90\x9d\x11\xa8\xef\x76\x20\x50\xa1\x18\x65\x70\xae\x09\x3d\x8b\x58\x39\x68\x9a\x52\x4d\x1d\xe1\xf2\x37\xec\xed\x96\xfe\xba\xc9\x97\x82\xf7\x8c\x97\x0f\x36\x51\xa0\x3b\x53\xcb\xcd\x05\x4e\x4b\x12\x0f\x75\xdc\x75\x1b\x7c\x97\x7a\x6b\x4a\x10\x24\x73\xd9\xc0\x95\xde\x1a\x31\x11\xe9\x04\xb5\xc1\x30\x60\x84\x13\xca\x53\x91\x2f\xbd\xcc\x08\x91\xd0\xe8\x81\x30\x20\x11\xfb\x9a\x63\x4f\x8c\x42\x19\xcc\xa0\x45\x95\xe0\xc5\x9e\x0f\x66\x36\x03\x1c\x8f\x11\x38\x3d\xc9\xe8\x08\x32\x17\xa8\x65\xc3\x3f\x97\x31\xf0\xb9\xb3\xc7\xa4\xc8\xba\x4b\x77\xbf\x16\x19\xd8\x74\x0c\x0f\x08\x33\xfd\x8b\x80\x03\x4e\xd2\x15\x1c\x50\x1b\x6c\xc0\x01\xf5\xda\x97\x00\x87\xb2\x05\xab\x27\x8b\x70\x30\x72\x43\x13\x0e\xc8\xbc\xf7\x1d\x0e\x0a\x92\x44\xe4\xc5\x50\x0a\xa3\x76\x76\xc6\x9b\xdc\xb4\xb5\xcf\xd0\x1a\x36\x56\x84\x6e\x22\x2f\x68\xde\x4c\x65\x90\x88\x45\xb5\x65\x12\x3e\x1b\xeb\x7f\x05\x3c\x0b\x49\xcf\x22\x23\xf3\xb3\x34\xdc\x8b\xe6\x49\x77\xe1\x25\xb3\x83\x2e\x72\x99\x5b\x18\x3b\x3b\xe1\x46\x22\xa1\x19\x76\x81\x68\x87\x72\x64\x11\xed\x16\x27\x0e\xd2\xef\xd0\x47\x89\xbf\x05\x91\xc6\x14\x0d\x2d\xde\x84\xc9\x45\x0a\x81\x2f\xdb\x46\x2f\xde\xda\x34\x2d\xbc\xcf\x67\xfe\x19\xb9\xc2\xbb\x95\xd3\xc6\xd3\x5a\xb8\x5a\xc6\x1f\xaa\xde\x12\x66\x81\xc0\x53\xc6\x27\x68\x57\xeb\x11\x09\x99\xcd\x19\x74\x44\xe0\xce\x6a\x90\x87\x78\x24\xfc\xa4\xfe\x3c\xf8\x57\xfb\xc0\x64\x37\x73\x18\x6d\xcc\xc6\x96\xdc\x32\x45\x0e\xde\x7b\x00\xb4\x28\xc6\xbf\x8f\x1c\xe6\xc0\x7e\x61\xb5\x9b\xd6\xd2\x79\xc7\x78\xea\xd2\xeb\x1a\xc0\xaa\xba\x39\x59\x39\x18\x13\x37\x59\x1a\xd2\x96\x77\xe4\x47\x4e\x2a\x60\x91\xfe\xce\xe8\x71\x6d\x45\x66\x6f\xa3\xeb\x3f\x6e\x78\xad\x5e\xb2\x38\xcd\x77\x1c\xf7\xde\xbc\xb7\x6f\x34\xf7\xe5\xfb\xfc\xb7\x3c\x6b\x41\x4f\x47\xfd\xba\xd6\x62\xfe\x61\xa7\xf5\x22\x7d\x62\xd0\x5a\x33\x3e\x51\xa1\x26\x43\xb3\xac\x61\x0c\x5f\xa5\xca\xf8\x1d\xae\x7a\x77\x2d\xab\x10\x0b\x69\xc1\x2f\x45\x0d\xc9\x8c\x38\xf1\xc2\x95\x90\x49\xae\xe8\x99\x34\x90\xd0\x8c\x66\x37\xc5\xee\xcd\x06\xc8\x52\x61\xeb\x0f\x37\xa7\xcd\xa9\x91\x59\xbb\x98\x74\xc0\xeb\x84\xa6\x39\x53\x0a\x0d\x61\x30\x9a\x0a\x71\x47\x8e\x1e\xed\xb9\xd6\x57\x6c\xa2\x4e\x1c\xce\xf7\xcd\xea\x8f\x09\xe3\x59\x15\x15\x85\x7a\x30\xd7\x55\x18\x3c\xbe\x24\xa9\x56\x81\x7b\xe8\x3a\xd0\xb8\x60\x85\xe5\x65\xda\x9e\x33\x06\x0b\x9e\x9d\x60\x2f\x6f\x4f\xbb\x54\xc2\x27\xb7\xe8\xca\xe1\xf6\x62\xbd\xe5\x95\x70\xb4\xd2\xe3\xb3\x03\xc9\x09\x17\x09\xa8\xee\xca\xbc\x7e\x53\xcf\x49\x52\xb0\x59\xf7\x80\xd1\x4f\x74\x6d\x90\x1d\xda\xa5\x0f\xb1\x78\x8b\x7b\xf4\x30\x94\xa8\x9b\xd9\x4a\x98\x0c\xd5\xb7\x4a\xba\xa1\x68\x48\x02\xbd\x08\x31\x15\x5c\xb8\x1c\x39\xc3\x44\x05\x47\x94\x46\x12\x65\xbd\x79\xb8\x27\x8e\x44\x07\x4b\x3d\xab\xbd\xc4\xa1\x23\x10\x8b\x3f\xe8\xaa\x49\xa2\x5d\xc3\x3d\xd3\x53\xec\xd8\x30\x5d\xf0\x1a\xe2\x4a\x24\x28\x74\xc0\x70\x02\x52\x0a\xe9\x02\xb2\xbc\xdd\xda\xa5\x6a\x0d\x45\x8a\x11\x5d\x06\x49\xa8\xf9\xeb\x50\x85\x8e\xea\xba\xa9\x53\x55\x83\x13\xc6\x63\x48\x50\xd0\x0a\x01\x6c\xa9\xf6\x51\xdd\xc2\xc2\x25\x21\x18\x04\x73\x4d\xa1\x72\xf6\x60\xde\x12\x3e\x15\xba\xc4\x5d\xeb\x88\xd5\x97\x8f\x07\x84\x5c\xf2\x2a\x82\xb7\x67\x76\x31\xbc\xd3\x87\x9e\x69\xf3\x89\x61\x47\x31\xfc\x80\xd0\x70\x66\xa4\x43\x59\x76\x80\xf1\x6d\xcc\xe1\x24\x34\x89\x77\x4a\x0e\xd0\x34\xee\x26\x35\x5b\xef\x65\x80\x36\xa6\x72\x73\xcb\xa7\x32\x97\xbf\x0c\x07\x08\x69\x4b\xe7\x5c\xf5\xb3\x8e\xda\x3c\xdd\x04\xb3\x05\xd2\x7b\xe5\x70\x1b\x8a\xd4\x56\x3f\xac\xaa\xb7\x65\x73\x5f\x8d\xb1\xca\x89\x0e\x64\x3c\x2e\x6c\xf2\x40\x58\x16\xd1\x35\xc7\x49\x89\x11\xb5\x33\x6f\x5b\xc8\x8b\x0c\xb0\xea\x4a\x30\x73\x5d\x50\x26\xe8\x0b\xd5\xab\x33\xd8\xaa\xd6\x52\xae\x18\x63\x8f\xfc\x37\x1e\xca\x2a\x10\xd5\xd7\x89\x1b\x56\x8f\x5b\x0d\x91\x29\xdf\x24\x0e\x93\x53\xb5\xf0\xa6\x0b\x92\xb2\x31\xe6\x49\x6a\xf7\xca\x82\x4a\x9a\x1b\x12\xaf\x88\x03\xc1\x08\x26\xcc\x06\x44\x56\x84\xed\xd0\x88\x7b\xae\x36\x47\xcf\x12\x43\xa6\x49\xce\x26\x53\x8b\x28\x84\x62\x45\x1d\xe2\x9d\x8a\x99\xa0\x29\x36\x97\x25\x42\x92\x7b\x2a\x73\xc3\x37\x68\x32\x45\x0f\x25\xe5\x24\x2d\x25\xf6\x4b\xd1\x40\xd3\x79\x5f\x69\xaa\x8d\xa4\x0c\xd2\x29\x94\x7e\xfd\xb1\x39\xd6\xa3\x23\x36\xc7\xda\x70\xc4\xe6\x58\xb1\x39\xd6\xf2\xd8\x9b\xe8\xd0\xd8\x1c\xeb\x75\x95\x35\x8d\xcd\xb1\xb6\x1f\xcf\x5e\xcd\x34\x36\xc7\x5a\x3d\x62\x73\xac\xd8\x1c\x6b\xb3\x11\x9b\x63\x6d\x3f\xf6\xae\x0e\x73\x6c\x8e\xb5\xd5\x88\xcd\xb1\x96\x47\x6c\x8e\xb5\x66\xc4\xe6\x58\x6b\x46\x6c\x8e\xb5\x3c\x62\x73\xac\xed\x46\x6c\x8e\x15\x9b\x63\xbd\xea\x9e\x01\x24\x36\xc7\x72\x23\x36\xc7\x7a\x15\x95\xd1\x49\x6c\x8e\xb5\xd1\x88\xcd\xb1\x62\x73\xac\x5d\x46\x6c\x8e\xf5\x5a\x8c\x32\xb1\x39\x56\x6c\x8e\xf5\xeb\x11\x74\x63\x73\xac\xd8\x1c\x2b\x36\xc7\x8a\xcd\xb1\x1e\x5d\x45\x6c\x8e\xf5\x1a\x54\x40\xa5\x53\xb6\x53\x6d\xd0\x4d\xca\x18\xb9\xf0\xf4\xa0\x6a\xc0\xa8\x1c\x8f\x41\x22\xe5\xc2\x37\x2f\x85\x55\xd5\x15\x1b\x17\x5d\xb9\xa0\x7b\x58\x11\xc9\x65\xf2\xac\x79\xdc\x95\x29\xc0\x1a\x9e\x75\x0c\xf9\xc5\xc7\xaf\x56\xd4\x4c\xda\x39\xde\x70\xd7\xe8\x69\x5c\xf3\x47\xbe\x9b\x17\x7e\x0d\xc0\x57\x65\x96\x39\xb8\x27\x99\x50\x2e\xf6\x1d\x81\x95\x4c\x29\xe7\xe0\xf5\x3d\xa6\xd1\x8e\x32\x02\xe0\x44\x14\xe0\x7c\xe0\x94\x28\xc6\x27\x19\x10\xaa\x35\x4d\xa6\x03\xf3\x26\xee\x81\x5d\xc7\xa9\xbb\x5f\x94\x96\x40\x73\x1f\xb1\x9f\x53\x66\xa7\x22\x34\x91\x42\x29\x92\x97\x99\x66\x45\x35\x19\x51\x80\xa9\x36\x96\x51\x55\xc0\xc0\x78\xb9\x3a\xb8\xbd\x57\xbf\xcd\x2d\x4b\x84\x45\xeb\x50\xdb\xec\x61\x21\xf1\xbc\xd0\xf3\x2a\xc2\x17\xc8\x98\x49\xa5\x49\x92\x31\xe4\xd6\xf8\x46\x9b\x55\x8d\xf3\xf5\x3c\xaf\xe6\x6e\xa5\xca\x2d\x95\xa7\x28\xb6\x16\x5a\xd9\x78\xd9\x7a\x42\x37\x55\xca\x94\x13\xf3\x55\x8f\x50\x5f\x51\xcd\x02\xda\xaf\x14\x41\xed\x39\x8b\x9d\xdd\xfd\x14\x4c\x17\x54\x92\xad\x03\x8a\x6b\x44\xc7\xe4\x07\x8f\x9c\xbd\x46\x9e\x47\x2d\x50\xb8\x7e\x19\x0b\xc7\x00\x37\x80\xc3\xcc\xe0\x00\x24\x60\xf8\x2b\x5d\x83\xf5\x9f\x1d\xe9\x03\xa6\xf8\x01\x94\xa2\x13\x18\xee\xe8\x68\x58\xa7\x91\xa1\xaf\xa1\xde\x18\x44\x85\xac\xd1\x93\x2c\x8c\xdb\x6c\x8a\x41\x24\xb7\x6b\xaa\x84\x9f\x7b\xc9\xb4\x06\xdc\x54\xac\xbd\x87\x1e\xd1\xc5\xd4\xfc\xc3\x85\xe8\xcf\x0f\x7e\x92\xfa\x61\x43\xd4\x79\x6a\x63\x31\x47\x40\x46\x92\xc1\x98\x8c\x19\x06\x78\x62\xc8\x65\xcf\x96\x62\xa2\xd6\x0a\xa0\x94\xd1\x77\x05\xf7\xb2\xac\x5f\xd7\x80\xfc\xc3\x2d\x4c\xcb\x92\x27\x34\xa8\x72\x8b\xb9\xa7\x6c\x4c\x26\x18\xb2\xe9\xa4\xc5\x3f\xbd\xf9\xdb\x5f\xc8\x68\x6e\x58\x1a\x4a\x56\x5a\x68\x9a\x55\x1f\x99\x01\x9f\x18\x58\xd9\xe3\xd9\xcc\x9e\xac\x20\x80\x6d\x40\xec\xc2\xdf\xfe\xe1\x6e\xd4\xe4\xb1\x27\x29\xcc\x4e\x02\xf8\xf5\x33\x31\x59\xd5\x38\x6b\xf7\x60\xee\x1d\x55\xa2\x15\x68\xd6\x4d\xc7\x47\x5f\x13\x8c\x4c\xc5\xbd\x95\xf5\x57\x60\x4f\x9d\x88\x55\x88\xa2\xcc\xac\xd1\xf9\xab\x2a\xef\xb8\x54\xb0\x9c\x1d\xb8\xf2\x5c\xa0\x99\xd4\x4d\xb1\x58\x51\xdd\x46\xea\xfa\x57\x0a\x97\x75\xe2\x0c\x79\x55\x69\x30\x54\x84\xbe\xa2\x59\x36\xa2\xc9\xdd\xad\x78\x2f\x26\xea\x23\xbf\x90\x52\xc8\xe6\x5a\x32\x6a\xa8\xe5\xb4\xe4\x77\xb6\xf5\x43\x55\x3c\x41\x4c\x9c\x2b\xd7\xa7\x38\xac\xfa\x60\x9b\x49\xef\x89\xb0\x57\x83\xea\x59\xe0\x81\xd5\xba\x8e\x4b\xe2\xb2\x18\x19\xce\xaf\x42\x64\xfb\xc3\x9b\x3f\xfd\xd5\xa2\x2e\x11\x92\xfc\xf5\x0d\x46\x73\xab\x9e\x3d\xc4\x48\xdb\x0c\xa3\xc8\x69\x96\x19\xb5\x21\x44\x4a\x03\xe8\x55\x48\xf8\xd9\x71\x50\xb7\x47\xb7\x8d\x45\xa9\xdb\xdb\x7f\xa2\x1c\xc5\xb4\x82\x6c\xdc\xb3\xf9\x4a\x95\x5a\x73\x88\x8c\xe1\xd0\x51\x1f\x4c\x1a\xdb\x03\x01\x68\x26\xb2\x32\x87\x73\x98\xb1\x2e\xba\xfb\x35\x66\xf3\xaa\x7e\xc6\x14\xa6\x86\x8d\x32\x91\xdc\x91\xd4\x5d\x0c\xe2\x5b\x16\x6b\x84\xbf\xdc\x46\xad\xe1\xf7\x37\x62\x7b\x72\x5a\x14\x55\xf6\x90\xa4\xf7\x0d\x60\xe0\x99\xc4\x42\x06\x2f\xbf\x51\xab\xfd\x22\x43\x37\x77\x9e\x62\xe7\x80\xa0\xf6\x36\xea\x7a\xf5\x1d\xb5\xe3\xab\x27\xf4\xa7\xa1\xc0\x7f\xdb\x7c\x93\xa5\x7c\xc9\x2a\xe5\xae\x42\x0c\x2b\x00\x18\xf4\x41\x92\xfc\x6c\x0d\x45\x49\xeb\xc0\xa6\x06\x5c\xf8\x23\x3d\xed\x28\x29\x40\x2a\xa6\x0c\x5f\xfe\x1e\x0f\x94\x6d\x66\x58\x9b\x00\x9f\x07\x08\xf6\x70\x63\x61\xe5\xf6\x94\x72\x28\x52\x37\x21\x92\x42\x5b\x54\x7a\x85\x58\xdb\x94\x6a\x3b\x64\xa8\xcf\x4d\x2a\xbf\xaf\xa1\xd9\xa4\x94\xe6\x97\x8a\x54\xda\xbb\x5e\x13\x81\xc4\xef\x7b\xa9\xf4\xb1\x5a\x7c\x47\x64\x00\x09\xa3\xdb\xdc\x26\x25\x6c\x28\x8f\xf6\xa0\x04\x22\xbd\xd3\x03\x07\xc4\x7a\xc1\xcd\x99\x70\x8f\x92\xc3\x77\x87\xcf\x4a\x24\x2d\x88\xa4\x28\xe8\xa4\x55\x97\x9f\x05\x48\x2d\x4e\x1b\x96\xa0\x30\x6a\x10\x5e\xaf\x0a\xb2\xe1\x5d\x90\xd6\x15\x76\xb0\x7e\x92\xf5\x8e\x7a\x00\x3b\x05\xc1\x66\x6a\xdf\xd3\x39\xa1\x52\x94\x3c\x75\xf6\xa5\xca\xc0\xf7\x61\xe1\xc5\x57\x82\x43\xdd\x35\xb4\x59\xc1\x02\x2d\xfa\x8c\x93\xb7\x83\xb7\x6f\x5e\x0b\xa7\xc2\x2f\x5c\xe0\x54\x57\x15\xa7\xb2\xf4\xe9\x59\xbf\xd5\xd7\xc2\xef\xe8\x7b\x3f\x38\x13\x4b\x5d\xea\x9e\xf9\x42\xda\xf8\xd3\xbd\x64\x1a\x82\xe6\x80\x47\xa8\xb8\x18\xfd\x30\xa8\xd7\x70\xbc\xaa\xc7\x44\x4b\x20\xb5\x2b\x90\xa1\xca\xd1\x27\xa4\x5b\x8e\x40\xe1\x71\x5b\x65\xe1\x52\x8f\x90\xb0\x10\x50\x07\x07\xe4\xc8\xde\x79\x68\x53\x9d\x8f\x9f\x15\xb5\x1c\xd0\x2e\x1e\x8a\x16\xd5\x37\x17\xb2\xea\x0b\x8a\x36\xb8\xa2\x43\x08\xfe\x07\x4c\xe9\x0c\x30\xc5\x9b\x65\x54\x66\xe8\x73\xbc\xb1\x6b\x27\xa3\x52\x13\xe0\x33\x26\x05\xcf\x81\x6b\x82\x31\xf0\xa3\x0c\xc2\xde\xd8\x5f\x1c\x7d\x7f\x7a\x8d\x01\x0d\xc7\xae\x58\x85\x5b\x65\xa9\x7c\x61\x9b\x70\x25\xc1\x74\x4f\x6e\x9f\x5f\x87\x81\x21\xd2\x5c\xbf\x2e\xf3\x9e\xbc\xd4\xa5\x6d\xd8\xf2\x90\x64\xa5\x62\xb3\xe7\xa2\x24\x2e\xf7\xfe\x9c\xed\xb4\xcf\x0b\x75\x00\x6a\x40\x2d\xa5\xf4\xa3\x69\x7d\x45\x1a\xe0\x92\xc3\xe4\x50\x55\xa9\x81\xa1\x0f\xdc\x99\x9e\x5c\x95\x0d\x1b\x3e\xe7\x6b\x31\x2e\x89\x10\x58\x51\xe6\x79\x8d\x50\x29\x57\x67\xb8\xc2\xed\xc0\xda\x0c\x48\x6e\x64\x0b\x9e\x5f\xdd\x84\xe5\x49\xac\xba\x24\xd2\x01\x19\xd6\x3f\xd6\x35\x6c\xb0\xb2\x5a\xa5\x44\x82\x9c\xd4\xe5\xc6\x27\xc0\x41\xa2\x90\x60\xa6\x6c\x34\x5c\x25\x23\xaa\xac\x93\xe7\xfc\xea\xc6\xda\x6c\xb7\x83\xd9\xce\x62\xf6\xee\x12\x2a\xa6\xb4\x60\x1a\xc3\x0e\xc2\x6d\xb3\x9b\x5a\x65\xb0\x32\x80\x41\xa5\xd4\x4e\x4c\x2e\x87\x84\xa6\xa9\x44\xb7\xcf\x42\xf2\x8d\xd1\xcf\xbd\x6f\x01\xeb\xc5\x50\x05\xe1\x9a\x02\x70\x23\x89\xab\x01\x4b\xce\xcb\x22\x63\xd6\x8d\x10\x3e\x50\xd7\xb9\xc1\xf6\x5f\xdb\x23\x6d\x1b\x35\x6f\x67\x25\xaf\x05\x15\x12\xbb\x96\xab\x7c\x64\xf7\x24\x28\x91\xcd\xea\x52\xc3\x0b\xbb\xe6\x4e\x04\x9a\xc4\xab\x5d\xf3\xd5\x29\x37\xda\x31\xe0\x5a\x32\x58\xde\x2d\x72\x6d\xde\x5c\xe2\x69\xaa\x26\x64\x33\x40\xff\xb8\x2b\xcc\xe9\x0a\xbc\xd5\xc5\x8f\xad\x6f\xd8\xd6\x9f\x06\x2a\x3d\x45\xc3\x55\xed\x78\x12\xc9\x73\x21\xc2\xa2\xb1\xe3\xfc\xea\xc6\x52\x42\xfb\xf1\x55\xdf\xda\x55\xbb\x54\x53\xb5\x9d\x31\xf0\xd9\xea\x0f\xb5\xd1\x3c\x16\xda\xfe\xb9\x3e\xdf\xad\x02\x59\x5a\x88\x7f\xad\x92\xed\x5a\xbc\x5d\x01\x95\xc9\x74\x17\xf8\x3f\x42\x08\xec\xa4\x24\x15\x36\x12\x60\x2c\x24\xaa\xc4\x7d\x24\xef\x99\x10\x77\x65\xb1\x09\x45\x77\xd3\xd8\x56\x6c\x1b\x11\x88\xc6\x13\xbf\x2a\x9a\x9e\x72\xb5\x8b\xbf\xb7\x29\xfb\x80\xb6\x12\x0f\x4e\x54\x27\x50\x88\x45\xbd\xe9\x2c\x2b\x95\x06\xf9\x15\x93\x4a\x1f\xf8\x4a\xd2\x88\xc1\xd6\x26\x72\x18\xde\xf0\x0f\xa6\xa7\xae\xa8\xe3\x61\xaf\x79\xc9\xfc\xed\x26\x3e\x34\x3a\xed\xe1\x95\xe0\x70\x38\x58\x14\xbb\x2a\x52\x5e\x91\xb5\xb5\x3c\xc5\x2d\x5d\x41\x66\xe3\x45\xf1\x42\x80\x2b\xb7\xae\xa0\xa5\x79\x83\xa7\x7f\x0a\x34\xa1\x58\x3c\x0e\xef\x9e\xd6\x05\x28\x6d\x45\x29\x5b\x41\x53\x38\x41\x6f\x1e\x82\x28\x28\x32\xa5\xc5\xfa\xcf\xde\x45\x9e\xdb\x1a\x03\x6c\x61\x52\x57\x95\xe4\x3d\xe3\x77\x5b\xa2\x5f\x33\xba\xe4\x62\x69\xb6\x46\xa5\x71\xeb\xa3\x65\xdc\x06\xdf\x19\x16\x43\x47\xa2\xd4\xbe\xf2\x89\x0a\x14\x47\xc6\xff\xdb\xee\x05\xda\xdb\x0b\x5b\xcb\x6f\x95\x8e\xa8\x7a\xd6\xe8\xe3\x95\x40\x35\xe7\x9a\x62\xd5\xd1\x73\x91\xdc\x81\x24\x99\x59\xc6\x80\xd4\x81\x2f\x8d\x3a\x97\xb2\x84\x2d\xa3\x2e\x76\xb5\x74\x40\x31\x85\x1c\x24\xcd\xea\x72\xaf\x2d\x40\xfd\xde\x11\xce\x6a\xd6\x30\x26\xc5\x96\x4b\x73\x05\x1a\xcd\x39\xbc\x58\x75\x57\x4e\xe7\xbe\x06\x2e\xe3\x18\x6e\xf0\xc0\x14\x9a\xf5\x0b\x91\x86\x89\x67\xa5\x02\xd9\xaf\xd2\x02\x5d\xee\x8d\xaa\x02\x71\x52\x18\x95\x93\x09\xe3\x13\x47\x9d\x91\xa6\x07\x85\xb8\x2b\x4d\x07\x23\xbd\x13\x09\xb6\x14\x2d\x4a\x0f\x36\xbe\x8c\x85\xf7\xe7\x22\xb5\xb7\x8f\xe6\x56\x1b\xf4\x3b\x5b\x07\x48\x5f\x72\x22\xa4\x2b\xc0\x40\xd3\x14\xd7\xbe\xfc\x85\x78\xb5\xf9\x55\xbd\x2a\x8e\xc3\x46\x76\x57\x4f\x05\x60\x51\xe5\xc8\x08\x3b\xa5\xdc\xb6\x76\xe8\xae\x84\x7f\x27\xa2\xdf\xac\x2a\x74\xca\xeb\x2d\x3e\x0b\x03\xe6\x28\xd1\x90\x17\x42\x52\x39\x5f\x74\x61\x1a\x22\x65\x50\xc0\x00\x70\x01\x52\x43\x91\x22\x1d\x5f\xb1\xf1\x33\xdb\xe3\x77\xc5\xde\xaf\xc4\x31\xa4\x82\x5c\x10\x0f\x51\x43\xaf\x55\x32\x85\xb4\xc4\xe8\xf1\x49\x49\xb1\x07\xb9\x39\xc5\xce\xd8\x3d\x77\x61\x79\x16\x19\xaa\x80\xbf\x2a\x4d\x60\x8e\x41\x32\x58\x9f\xd3\xfc\x82\x75\x3e\x6d\x68\xa0\x6d\xc1\x8c\xed\x58\xab\x28\xc1\xdb\xba\x2b\x04\x7e\x2c\xcc\x58\xa2\xfd\x43\xe3\x75\x88\x93\xd0\xaa\xf3\xeb\x50\xb8\xba\x80\x09\x18\x62\xa4\x55\xfd\x29\x2e\xaa\x04\x2b\x7f\xfe\xc8\x0d\x93\x58\x8f\x8b\x35\xe2\x3d\x81\x72\x28\x57\x37\xb7\xe2\x91\xe3\x5b\x41\x69\xc5\xb7\x6f\x5b\x92\xa9\x85\x50\xbe\xbb\xc7\x6d\x27\x4f\x59\x1b\xf9\x9f\xca\x49\x7b\x5d\xe9\xf0\x54\x4e\xca\xdc\x56\xf7\x16\x0b\x05\x96\x2d\xce\xa1\x5d\xcb\xb0\xac\xb3\x0f\xe7\x61\x0a\x43\x18\x9b\xed\x13\x40\x8c\x28\xd4\xd2\xde\xb9\x68\xf0\xbc\x34\xca\x59\x65\x45\xad\x69\xab\xd3\xe2\x9c\x45\xaf\x7a\x9b\xd7\x62\x19\x2f\x0c\x37\x46\x19\x22\x28\x3d\x92\x4c\x29\x9f\xa0\x19\x5c\x94\x66\xbe\x2f\xbe\xc0\x15\x49\x48\xcb\xc4\x75\x94\xf0\xf1\xcf\x5f\x78\xeb\x9f\x2b\x14\x84\x8d\xed\x54\x42\x0b\xbf\xe6\xf0\xb3\x2c\xab\x7e\x47\xd8\x00\x06\xe4\xe0\x8b\xe0\xd2\x81\x7d\x7b\x21\x85\x79\x85\x0b\x9d\xc6\x55\x65\x4c\xe3\x41\x38\x08\xef\x1e\x90\x0b\xf3\x0e\xf4\x88\x54\x00\x0c\xa2\x7b\x47\x35\xf8\x7a\x44\xc2\x84\xca\x34\xc3\x8c\xbb\x71\x25\x94\xd8\xbc\x1c\x07\x30\x3c\x7d\x18\x4f\xc7\x85\x5e\x65\x9d\xdc\x30\x2d\x42\x53\x75\xa7\x4e\xac\x28\xd3\x4f\xa9\xa6\x7d\xec\xc2\x61\x89\xc6\x89\x55\xaf\xfb\xae\xfe\x69\x9f\x3a\x9c\xea\x57\xdb\x7a\xf2\x5b\x97\x59\xd5\xa7\xd5\x5d\x8c\xf7\x69\x1f\x2b\x91\xee\x1e\x2b\xfa\x0c\x61\x05\xad\x34\xdd\x16\x65\x70\x17\xc5\xd3\xaa\x0c\x3a\xc2\x00\x9b\x88\xd4\x65\xaf\xab\x08\x06\x57\xe9\xb5\x71\x90\x2f\xae\x6e\xaf\xff\x39\xfc\x78\x79\x75\x1b\xcf\x73\x3c\xcf\xf1\x3c\xb7\x38\xcf\xc0\x67\xad\xcf\x72\xa5\xff\xac\x52\x09\x17\x4a\xd8\x05\x19\xd5\xaf\x28\x38\xeb\x82\xcf\xbe\xa7\x46\xe0\x2b\x24\x28\x94\x45\x8c\xdc\xb8\xca\x8b\xea\x6e\xb0\x7d\xb8\xce\x5e\x7c\x74\xd6\x33\xc6\x56\x75\x18\xb3\x72\x15\x14\x02\x58\xb5\x6b\x61\xe3\xbb\xb3\x9f\x2f\xcf\x2f\xae\x6e\x2f\xbf\xba\xbc\xb8\x7e\xd6\x60\x83\x96\xc5\xdd\x9a\xdc\x78\x47\x2e\x59\x48\x98\x31\x51\xaa\x6c\x5e\x55\xa1\x5d\x4d\x04\x96\xe3\xd5\xb8\x51\xcf\xe6\x55\xa1\xdd\x95\x8f\x45\x66\xdb\x2d\xb3\x6d\xc6\x5e\xb4\xa8\xeb\xd1\x15\xfa\x7e\x25\x45\xde\x11\x0a\xdf\x58\x95\xdd\x9b\xbc\x57\xe1\xd3\xa1\x2b\x01\xd0\x60\x3d\x4e\x78\xac\xeb\x0d\x18\x29\x34\x2f\x74\x8b\xb6\x00\x9d\x14\x0d\xed\xa6\xbe\xa6\x8d\x53\xf8\x40\x8b\x6f\x61\x7e\x0d\x2d\xcb\x87\x2c\xb8\x1a\x32\x48\x0c\xa3\x23\x77\x30\xb7\x1e\xc8\x33\xff\xb2\x76\x45\x30\xf7\xb0\xe6\xea\x1d\xb4\xa9\x87\xdb\x65\xb1\xd4\x3b\x68\x11\xb8\xe8\xc7\x52\x41\x4f\xb3\x85\x28\xa7\x99\x3d\xdd\xab\x12\xa6\x9f\xa0\x38\xec\x61\xc8\xee\x1d\x9d\xd5\x5b\x57\x57\x10\x33\xc3\xb9\xe0\xfe\xc4\x05\x6d\xf5\x8d\xc6\xda\xb7\x58\xab\x4e\x30\x32\xe5\xe4\xb7\xb6\x70\xec\xed\xc7\xf3\x8f\xef\xc8\x69\x9a\xba\xe0\xe1\x52\xc1\xb8\xcc\x6c\x18\xb0\x1a\x10\x5a\xb0\xef\x41\x2a\xec\xab\x76\xc7\x78\xda\x23\x25\x4b\xbf\x6c\x53\x74\xc9\x8e\x0e\x77\x41\x78\x87\x4d\xb7\x3b\x71\xe3\xfc\x71\x21\xef\xaa\x88\x08\xb1\x99\x81\x88\x9b\xbe\xfe\x8a\x13\x32\x3a\x02\x4d\xdb\x16\x72\xc4\x6e\x61\xb7\x74\xf5\xb0\x26\xac\x36\x4e\xbc\x2a\x50\x95\xbe\x23\xaa\xc4\x42\x31\xaa\xea\xfb\x86\x9d\x54\x7b\xcd\x3f\x55\x41\x13\xe8\x91\xff\xaa\x7e\xc4\x4e\xed\xea\x87\xc3\xc3\xbf\x7f\x7b\xf1\xcf\x7f\x3f\x3c\xfc\xe9\xbf\xc2\xab\xc8\x0a\x51\x6b\x5e\xb8\x05\xfd\x3b\x5c\xa4\x70\x85\xef\xc0\x3f\x9d\xb8\x76\x9a\x24\xa2\xe4\xda\x5d\xc0\xac\xde\xc1\x54\x28\x7d\x39\xac\xfe\x2c\x44\xba\xf8\x97\x6a\x55\x49\x6c\x2f\x19\x03\x6e\x51\x8b\xec\x14\x3b\xba\x63\x0f\x35\x2d\xe9\xf8\xa8\xba\x59\xab\xfe\x18\xc9\x14\x72\x5b\xcb\xe8\x2b\x0f\x02\xec\x4d\xeb\xcb\x07\x70\xcc\xb9\x36\x92\x69\xb3\xac\xdc\xc1\xec\x6d\xab\x26\xde\x76\x74\x48\xda\xaa\x1d\xec\x18\x60\x08\x11\x07\x2d\x7b\x90\x2b\x06\xeb\xb5\x94\xda\x1b\x7b\x3a\xbc\x24\x33\x0b\xe1\xbd\x01\x8e\xf7\x82\x7d\xf5\x49\x69\x5c\xe8\x6b\x6b\x68\x88\xef\x6c\x2b\x57\x7f\xdd\xe5\xd9\xab\xaa\xf4\x15\x18\xc5\xe6\xc8\xfe\x38\x48\x8a\xb2\xe7\x6e\x18\xe4\x90\x0b\x39\xaf\xfe\xac\x7c\x7c\x7d\xa5\x85\xa4\x13\xcc\xcb\xb0\x8f\xdb\xc7\xaa\xbf\xec\x83\x8d\x17\x2c\x3f\x6d\x55\xe1\xa4\x94\x46\x68\xc8\xe6\x9e\x22\xef\x58\x2f\xa2\x1e\x7b\x48\xdb\x3c\xe8\xf7\x84\xb4\x55\x98\xd1\xb6\x61\xab\x1d\x4d\x84\xac\x1d\xf5\x28\x70\x56\x50\x44\x7d\xd2\xe5\x9d\xf6\x2a\x31\xc8\x5a\x03\xf8\xcc\x68\x96\x3b\x57\xce\xaa\x47\x87\xd4\x2c\x65\x33\xa6\x44\x8b\xec\x93\x6a\xa2\xf5\x21\xf5\xae\xf4\x85\x0d\x1c\xaa\xcc\x66\x0f\x05\x16\x0b\xaa\xce\xeb\x02\xd9\x7f\xdb\xa6\x2b\x91\x1d\x05\xd5\x1a\x24\x7f\x47\xfe\xf3\xe8\xc7\xdf\xff\xd2\x3f\xfe\xf2\xe8\xe8\x87\x37\xfd\xbf\xfd\xf4\xfb\xa3\x1f\x07\xf8\x8f\xdf\x1d\x7f\x79\xfc\x8b\xff\xe3\xf7\xc7\xc7\x47\x47\x3f\x7c\xfb\xe1\xeb\xdb\xe1\xc5\x4f\xec\xf8\x97\x1f\x78\x99\xdf\xd9\xbf\x7e\x39\xfa\x01\x2e\x7e\xda\x70\x92\xe3\xe3\x2f\xbf\x68\xbd\xf4\x0e\x6a\x77\xda\xd1\x65\x05\xcf\xe6\x8c\x9d\xa0\xdf\x27\x2c\x5b\x6f\x87\x47\xaf\xae\xcf\xbf\x8f\x1e\x7e\x57\x33\xa4\x8a\x5d\xef\xcd\x01\x57\x90\x48\xd0\x9f\xc3\x92\x63\xdf\x14\x54\x10\x38\x54\xa4\x52\x2d\x5e\x1b\x9f\xfb\x35\x18\x77\xaa\xb6\x76\xb8\xaf\xb5\x24\x3a\x96\x22\xf7\x59\xe1\xe8\xde\xc0\xfe\xf4\xfe\xbe\x3b\x68\xd5\x1c\xd5\x8e\x68\x0c\x8a\xc6\xa0\x35\xe3\x49\x63\xd0\x8d\xc5\xc3\xbd\xb5\x04\x01\x9f\xed\xea\xc2\x58\xe9\x41\xf7\xba\x4e\x58\x42\x6d\x33\x87\xda\xc0\x1f\xf5\xba\x1f\x64\x1d\x42\x63\x19\x5a\xbe\xda\x87\x49\x4e\xb1\x57\xb3\x3d\xf8\x38\x41\x9d\x76\x61\x55\x1b\x57\xe1\x0f\x66\x66\x09\x55\x89\xe8\x46\x31\x48\x0c\x74\xc4\xd0\xd3\x7f\xd8\x48\xd0\x3b\x1b\x1c\x6a\x94\x34\xc6\xeb\x32\x9a\x95\x70\x58\xd7\x5e\xa6\x4a\x89\xc4\x06\xb5\x56\x49\x00\x58\xd9\xcd\x2d\x1b\x57\x83\x0d\xe2\x0b\x09\x09\xa4\xc0\x13\x70\x75\x99\x1b\xbd\x2f\x29\x27\x17\x7c\xe6\x6b\x53\xa7\x3e\xa5\x04\x57\xb2\x7a\x8e\xd7\x15\x80\x60\x10\xd1\x39\xc1\x82\x38\x04\xa4\xfa\x75\x34\x2b\x86\x62\x88\x71\x6d\x65\xdd\xad\x3d\x5e\x6b\x2e\xde\x9e\x67\x56\x9e\xad\x56\xc2\xd0\x12\xb3\xac\xcd\xcf\x4d\x26\xf9\x1a\x9c\x81\xed\xd9\xe7\xaf\x8e\x75\x76\xc4\x36\xbb\x61\x99\x5b\xf8\x4e\xba\x64\x93\x5d\x38\x4b\x0a\x09\x63\xf6\xd0\xd1\x39\x3d\xe5\xb5\x25\x86\xa5\xc0\x35\x1b\x33\x9b\x62\x52\x48\x28\x80\xdb\x2c\x01\x9a\x4c\x91\xf6\x3b\x4e\x59\x3b\xa7\xf7\x31\x98\xc7\x0a\xdc\xdd\x92\xb2\x9b\x55\xc2\x7e\xa4\x63\x24\xd2\xb1\x9d\xc7\x67\xa2\x63\x0e\x73\xf7\x87\x88\x61\xe4\x79\xfb\x98\xf7\xb3\x66\xad\x15\xd7\x95\x76\x4b\x44\xab\xd3\x8e\x4e\x70\x96\x9d\x0c\xd0\xad\xf0\x01\x5f\x3b\x2c\xb3\xac\xa3\xfa\xd4\x87\x97\x08\x8d\xa2\xcc\x32\x97\x96\x3b\x20\x1f\x39\x1e\xc9\x53\xec\x83\xd0\x23\x57\x30\x03\xd9\x23\x97\xe3\x2b\xa1\x87\x56\xb6\x6d\x86\xb3\xd9\x1b\x09\x1b\x93\x77\x46\x6b\x52\x9a\x68\x5b\x8b\x3e\xa8\x9c\x23\x64\x63\x82\xba\x28\x57\x8b\x30\xf4\xf5\xdb\xf2\x5b\x9f\x30\xd9\x7f\xa6\x6d\xaa\x9a\x7d\x74\xa0\x9e\xba\x99\x7c\x80\x1c\x06\x45\x3a\xef\xc8\xaa\xac\xd7\x17\x58\x88\xa2\x10\x4a\xdf\x18\x2d\xb6\x9b\x46\x30\x43\x3f\x1d\xf6\x56\xa0\x59\x06\x69\xa3\x13\x90\xed\x60\x41\x9b\x5a\x34\xe6\xe3\x56\x0d\x15\x80\x4c\x29\x4f\x33\x90\x58\x14\x5d\x2d\x56\x7e\x62\x75\x17\x80\xaa\x6f\x83\x4f\xd0\xa4\x49\x22\x64\xea\x3a\xb0\xba\x44\x49\x5c\x4c\x75\xbc\x90\xd6\xe6\x94\xd3\x09\xa0\x65\x61\xa9\xb4\x2e\x16\x5c\x56\x41\xf3\x87\xa9\x10\x77\x24\x11\x79\x91\xe1\x01\x68\x71\x3e\xea\xde\x33\x15\x8a\xf6\xcd\xec\xea\x24\x68\x4b\x83\x3f\xb4\xeb\x4a\xd3\x4a\x58\xe9\x42\x54\x81\x07\x48\x3a\xeb\x5b\x77\xf1\x00\x49\xd0\x78\xd1\x6c\x89\xeb\xbc\xa8\x05\xda\x36\xda\xf7\xd3\x6d\x6d\x96\xef\xca\x14\xde\x22\xcb\x2c\x1c\x0b\x85\xd6\x70\x4e\x5f\x57\xda\xbd\x02\x4b\xf4\xdb\xac\x62\xcc\x3c\xf3\xa5\xa6\x1b\x87\xc1\x1e\xbd\xa5\xea\x6c\x55\xb0\xb1\x9f\x0b\x73\x9f\x85\xd0\xe4\xe8\xf0\xe4\xf0\x78\xc9\x46\xb7\x50\x9c\xf8\x36\x78\x92\x61\x35\xbe\x02\x4b\xdb\x41\x72\x98\xf6\x08\xd3\x9e\xd8\xda\xa2\x00\xb8\x2a\x97\x0e\x87\x1d\xea\xb5\xa4\x29\x73\x5a\x10\xfe\x6a\x6e\xd2\xb2\x74\x15\x01\x8e\x0e\x7f\x39\xec\x11\xd0\xc9\x31\xb9\x17\xfc\x50\xe3\xf2\xb1\x7c\x46\xa9\x82\x89\xe6\xa2\xc4\x2e\x75\x16\x04\x55\x2d\x0c\x43\xb1\x88\x28\x6d\x4b\x9b\x29\xd5\x3e\x0d\xef\xe2\x81\x69\xdf\xc6\x41\x8c\xc9\x1b\xdb\x51\x07\xa8\xb3\x12\x66\x6c\x06\x27\x53\xa0\x99\x9e\xda\x40\x0a\x2e\x78\xdf\x36\x45\x33\xa4\xc4\x5d\x69\xeb\x53\x68\x67\x72\x0b\x47\x0b\xf3\xdb\xf2\x82\x5a\x4a\xd7\x86\x88\x7e\xbd\x7b\xa7\x56\xb2\xd4\xc4\xf8\xf6\x76\xf8\x75\xa3\x57\x2b\x52\x71\xad\x0b\x1f\xde\x12\xd4\x95\xd8\x03\xda\xd1\x8d\x43\xaf\x55\xd3\x56\xd2\x21\x09\x6b\xdb\xbc\x95\x2c\x37\xa5\xde\xae\x6b\x2b\xf9\xa7\x28\xb1\xdb\x1c\x1d\x65\x73\x72\x4f\xb9\xf6\xa9\x78\x07\x66\xaa\x03\x43\x9e\x0c\x36\x7c\x03\x34\x05\xa9\x90\x7a\x00\xdd\xb9\x7e\x96\x1f\x9d\x39\x9a\x82\xb5\x75\xcb\x07\x4a\xa5\x45\x4e\xa6\xee\xb3\x9b\xe9\x89\xee\x64\x0c\xf0\xf4\xf8\xdc\x1f\x09\x85\xa5\x70\xee\x99\x57\x47\xbf\x96\xe8\x86\x85\x7b\xa3\xce\x7c\x12\x82\x2d\xec\x46\xc2\xb8\x05\x96\xed\x23\xd8\x11\x2d\xed\x20\x40\x80\x74\x18\x24\x40\xda\x25\x3b\x2e\x4e\x84\x8e\xaf\xf6\xf1\x50\x9d\xc5\x1d\x90\xce\x7c\xeb\x64\x95\x21\xd2\xe1\x8c\x8d\x82\xb5\x36\x8f\x46\xe9\xb8\x84\x72\xc1\x59\x42\x33\xf6\x2f\x48\x6d\x57\x5c\x1b\x63\x86\x72\x4e\x42\x15\xf4\xd1\xf1\xc9\x2d\xfd\x0b\xda\xbc\x72\x73\x1c\xb5\x10\x28\x7c\xa0\xab\xcb\xd0\x47\xfb\xbe\xf6\x91\x0b\xa4\x5b\xbf\x39\x69\x9f\xb4\x19\x8e\xc7\xc1\xdc\x0d\x8a\x91\x2e\x21\x50\x74\x10\x64\xbd\x1c\x62\xbd\xd4\xb3\x1b\x89\x91\xad\x0a\xbb\x37\xbc\xac\x6d\x03\x73\xb2\x3a\x63\x59\x12\x5e\xf5\x9b\x7d\x19\x4d\xcc\x49\x77\xc1\x90\x5d\x87\x42\x76\x1a\x08\xf9\x49\xc3\x20\x31\xf9\xa2\x35\x15\x69\x5a\xe1\x71\x4a\x83\x01\x46\x3b\x34\x7a\xad\x93\x30\x9d\x0d\xc9\xf7\xc4\x68\x1a\x5d\xcd\x51\xdb\x8b\x33\xa6\x93\xe2\x46\x24\x77\x1d\x6a\x4f\xe7\x50\x48\x48\xac\x35\xee\xf6\x6c\x68\x67\x37\x5a\xec\xd5\xc7\xdb\x3a\xe8\x1f\x23\x63\x6a\xf3\xe8\x37\xce\x5e\x67\x34\xdf\x3b\x28\x74\x65\x20\x18\xd1\xe4\xee\x9e\xca\x14\xed\x67\x54\xb3\x11\xcb\x98\x9e\xa3\x09\x40\x02\x66\x14\x70\x61\x43\xef\x6c\x29\x46\xe1\x1b\xaa\x56\xdd\xbe\x2b\x4b\x19\xda\xe1\x1c\x0b\x1c\x53\x66\xb4\xfe\xaa\x6b\xae\x8d\xcd\x49\x8a\xca\x70\x18\xda\xbf\xa3\x8a\xe7\xc7\xde\xaa\x78\x41\x47\xd8\x6d\xb5\xbd\xb6\x11\x82\x7b\xcc\xea\x1c\x8b\x93\x55\xc3\xb3\xc8\xea\x3a\x9a\x6f\x7f\x59\x5d\x21\xe1\x46\x8b\xa2\x23\x5f\x8c\x9d\x6c\x8d\x27\x66\x04\x63\x61\x88\xf0\x5a\xd7\x4a\x5a\x82\x2b\xca\x79\x3a\xbc\xac\x6c\x67\xa2\xe1\x3e\xb1\xb1\x91\xbe\x12\x67\xc6\x66\xc0\x41\xa9\x13\x74\xba\x94\x85\x6b\xfa\xef\x7a\xdb\xf6\xcc\xd7\x41\x8e\xab\xeb\xd5\xf9\x06\xae\xb3\x2e\xfe\x08\x3a\xb1\xf6\xe1\x80\x90\x63\xd3\x2e\xb7\xfc\x45\x67\x4d\x22\xa9\x9a\xda\xae\xb3\xf0\xc0\xb4\xeb\x9c\x3c\xb4\x95\x7a\xc3\xe6\xb7\x13\x49\x13\x20\x05\x48\x26\x0c\x33\x2a\xb9\x4e\xc5\x3d\x27\x23\x98\x30\xae\x3c\x28\xb0\xd6\xa6\x83\x19\x7a\x7d\x98\xaa\x0a\xb3\x0d\xc8\x75\xa3\xec\x88\x4b\x08\x4a\x44\x7d\x34\xdd\x9a\x17\xfd\x55\xc8\xb1\x10\x4e\xb6\x87\x4b\x05\xe1\xb0\xad\xcd\x53\x4b\x3e\x2a\x39\xbe\x39\x85\x8c\xce\x6d\xdc\x27\x76\xa4\x66\xff\x02\xa9\x8e\x3b\xf0\x6b\xd9\xc6\x4c\xfe\xda\xda\x75\x60\x91\x53\x9a\x4c\xdb\x39\x8a\xa3\x23\x6c\xc3\x11\x1d\x61\x6d\x26\x89\x8e\xb0\xe8\x08\x7b\x62\x44\x47\x58\x74\x84\x2d\x8c\xbd\xd5\x92\xa2\x23\x6c\xe7\x11\x1d\x61\x8f\x8f\xe8\x08\xdb\x60\x44\x47\xd8\x86\x23\x3a\xc2\xd6\x8f\xe8\x08\x6b\xb7\x98\xe8\x08\x8b\x8e\x30\x37\x7e\x7d\xd6\x41\x3f\xa2\x23\x6c\x69\x92\xe8\x08\x8b\x8e\xb0\x8d\xc7\xde\xaa\x78\xd1\x11\x66\x47\x74\x84\x35\xc7\xaf\x8b\xd5\x79\x37\xd2\xd0\x28\x94\xed\x9b\x0a\xa3\x5a\xea\x68\xec\xab\x4c\xe1\x6a\xe3\x65\xf8\x3c\x1e\x86\x3d\x71\xc7\x74\xe0\x55\x88\x1e\x85\x57\xe7\x51\xe8\xc6\x1a\xd7\x81\x25\xae\x35\x4d\x76\x8e\xf6\xdb\xa9\x04\x35\x15\xd9\xce\x88\xde\x40\xf2\x0f\x8c\xb3\xbc\xcc\x0d\xce\x29\x83\xcf\x6c\x56\x79\xf4\x55\xdd\x69\x19\x1d\xfd\xd6\x28\x68\x6e\x64\x29\x60\x15\x51\xca\x32\xb3\x8d\x98\xf4\x39\xa5\x33\x83\xeb\xaa\x4c\x12\x00\xec\x51\x16\xaa\x12\x7f\x1c\x54\x6f\xaa\x7a\x52\xbc\x6d\x47\x6f\xda\x71\x4b\x5b\xe7\x13\x67\xf9\xe3\x1f\x76\x9a\x63\x22\x8b\x6e\xe8\xf2\xd7\xd7\xc3\xb3\x80\x2e\x53\xee\xc9\x32\xe3\x33\x91\xcd\x6c\x27\x5b\xbc\xc9\x48\x45\xcf\x48\xa4\xdb\xcb\xf7\xad\x64\xfb\x2e\x78\x44\x5b\xf1\xb5\x29\x7b\x18\x21\xb5\x69\xa2\x99\xe0\x5e\xda\x72\xf2\x1b\x0b\xa9\xad\xa9\x5b\x7b\xc1\xb1\xfd\x71\x20\x58\xef\x05\x3f\xbc\x33\x00\x1f\xb8\x3e\xdf\x9e\x05\x87\x1a\x82\x6f\xb1\xa4\x05\x29\x32\x5a\x37\x49\xc2\x1d\xf8\x06\xf9\xc6\xd9\x14\x92\xbb\x6b\xe7\x0c\x3d\x52\x00\x55\x24\xcb\x84\xe9\x69\x39\x1a\x24\x22\x3f\x31\xc7\xd8\xfe\x67\x94\x89\xd1\x49\x4e\x95\x06\x79\x92\x8a\xc4\xb1\xa5\x7e\x62\x66\x61\x7c\x32\xc8\xd3\x63\x6c\xc3\x7b\xd9\x6c\xca\x18\x94\x62\x30\xef\x77\x0a\x1c\x19\x81\xa1\x88\x02\x95\xf4\xa0\x9e\x9b\x59\xde\xd6\x8d\x73\xc3\xd1\x9a\x8d\xb4\x74\x44\x7f\x7e\x27\x74\xa4\x5c\xa4\x03\x6b\xc4\x4b\x73\x36\x77\x16\x74\xd1\x81\x93\x79\x8f\x1c\xcc\x7b\x23\xce\xee\x8b\x53\x79\x0f\x4b\x2f\x77\xe0\x48\xee\xc2\x89\xdc\x9d\x03\xf9\x13\x54\x28\x7e\xc9\x8e\xe3\x0e\xad\x6b\x1d\x39\x8c\x3f\x87\xb3\xb8\x93\xaf\x6e\xeb\x24\xfe\x7c\x0e\xe2\x6e\x3e\xb7\x4b\x75\xe3\xa5\x3a\x85\x3b\xb0\x92\x77\x69\x21\xef\xcc\x3a\xfe\xc9\x9c\xc0\xed\x1d\xc0\x7b\xe0\xfc\x6d\x0d\x64\xc6\x99\x66\x34\x3b\x87\x8c\xce\x6f\x20\x11\x3c\xdd\x99\x8f\x2d\x14\xc6\xac\xce\x8f\xb2\xd3\x3a\x0b\x56\x33\xa3\x62\x4a\x5d\xfd\x6f\xa3\xb7\xd9\x0c\x12\xef\xb9\x70\x62\x0b\x3a\x1d\xec\x2a\x77\x29\xad\x77\x2f\xe4\x5d\x26\x68\xaa\x4e\x0a\x61\xff\x53\xe7\x4b\x04\x89\x12\xf6\x5d\xed\x32\x25\x9e\xdb\x54\x66\xd3\x4b\xba\xdc\xc4\x6f\xc4\x3d\x11\x63\x0d\x9c\x1c\x31\xee\xf7\xf1\x38\x50\x36\x6b\xbb\x65\x85\xd6\xe6\xea\xdb\x37\xfe\xe6\xd7\x67\x90\x44\xd3\xab\x52\x9f\xde\x3e\xec\x5e\xf4\xb4\x81\xd8\xdd\x38\x2e\xb3\xa6\x91\xd8\x1a\x8e\x9b\xf4\xe6\x6d\x5d\xc1\xf8\x2d\xce\x5b\x9d\x36\xca\x53\xe2\x52\xce\x5e\xdf\xa6\xb5\x0e\x6d\x69\x8a\x7e\x55\x28\xcb\x53\xf6\xe4\xdb\xb3\x61\x34\x27\xef\x97\x51\xe6\x99\xc2\x43\xf6\x50\xd0\x7d\xa1\x21\x21\x51\xd0\xdd\x62\x04\x49\xa8\x5f\x4b\x9a\xc0\xb0\x73\x19\xc1\x1f\x27\x92\x96\x92\x3a\x02\x58\x89\x7c\xfe\xf0\x70\x80\xd4\x9e\xa6\x2a\x71\x17\x53\x62\xc7\x65\x96\xcd\xad\xcd\xa1\x91\xe6\x6c\xbd\xf0\x8b\x59\xb3\x68\xf8\x5f\xf1\x96\x5a\xb0\x2c\xa4\x70\x3c\x53\x96\x9c\x1b\x1a\x5c\xb7\x21\x43\x41\x12\x6b\x37\xd3\x46\x6e\xae\x62\x13\xb3\x7c\xc3\xff\x30\x6d\xb7\x8e\x01\x6c\x4c\x68\x9e\x1e\x0b\x99\xb0\x51\x36\x27\x53\x9a\x55\x3d\x67\x28\xb9\x63\x59\xe6\xa6\x19\x90\x1b\xd0\xd6\x71\x61\x79\x67\x26\xf8\x04\x17\x47\xb9\xef\x75\x08\x89\x79\x36\xc9\x80\xf2\xb2\xb0\xef\x33\x9c\x78\x2e\x4a\xe9\xdf\x37\xa8\xdc\x1f\x15\x07\xe6\x2c\xeb\x05\x1d\xd5\x1e\xdd\xd8\xda\x44\xa3\x8c\x00\xf0\xd1\xd7\xaa\xee\x85\x73\x8a\x19\x48\xc9\x52\xe7\x4d\xb0\xbf\x15\x52\xcc\x58\x6a\x7d\x28\x1e\x6c\xd8\xbb\xd9\xf6\xcc\xa9\xce\x33\x17\xbc\xcf\x61\x42\x51\x50\x71\xa7\xc8\xee\x99\x9d\xc7\xc6\x16\xf0\x14\xbb\xe8\x18\x09\x5f\x14\x8d\xbc\xf9\x19\xb3\xfd\x7f\x03\xc8\x91\x23\x2e\x88\xc0\x90\xd0\x92\x33\x6d\x7b\xca\x4f\x4b\x4d\x52\x71\xcf\x8f\x9d\xcd\x8a\x29\x42\xc9\x08\x34\x0d\x82\x3a\x1d\x83\x53\x04\x38\x1d\x65\x66\xcf\x31\x5a\xe9\x76\x25\x80\xc8\x18\xa8\x2e\x25\x90\x09\xd5\xb0\x52\xce\xb1\xdf\xfb\x38\x78\x99\x72\x06\xd6\x31\x29\xb9\x82\x96\xec\xbd\x33\xe1\xe8\x2f\x7f\xda\x8d\x46\xb0\x1c\x44\xa9\x3f\x8b\xf6\x77\x3f\x65\xc9\x34\x14\x66\x59\x0e\x8a\x88\x72\x41\x2d\x7e\xeb\x1e\x5b\xbd\x43\x51\x05\x5c\x35\x76\x35\x1f\xaf\xb0\x7e\xb9\xb6\xac\xcb\x91\x7d\x41\xdb\x69\x0c\xda\x3e\xbf\xba\xf9\xf9\xfd\xe9\x7f\x5c\xbc\x77\xe7\x93\x87\x4c\xbf\xe4\xec\x7f\x4a\x20\x34\x17\x46\x16\xce\xc2\x00\xc1\x1e\x6a\xf4\xc1\x0f\x78\x92\xbb\x0d\x25\xdc\x91\x21\x63\x8f\xfc\xf6\x01\x93\xd8\x69\xff\xd3\xc7\x4b\x3e\x77\xef\xb0\xaa\x2b\x05\x46\x69\x04\xbd\xc3\x28\xe1\xa0\xcd\xc9\xb3\x12\xa5\xed\x25\xc7\xf8\x24\x0b\x85\xc9\xdd\xc8\x55\x5b\x9d\xa8\xad\x46\xd4\xaf\xbf\x60\xb8\xab\x62\xd4\x49\x0f\xb3\x7a\x0d\x1d\x75\xfe\xa9\xa9\xb6\x57\x03\x6c\x6b\x66\xaf\x06\x58\xd1\xe3\x72\x48\x68\x9a\x4a\x14\x53\xf0\xd4\xe7\x0b\x1d\x40\x8b\x3a\x62\xa7\x47\xde\x90\xbf\x93\x07\xf2\x77\x54\x0b\xfe\xd2\xb6\x4f\x52\x5b\x81\xbd\x8b\x00\x1c\xa3\x8d\x5e\x0e\x3b\x82\xf8\x3f\xa6\x54\xe3\x8c\x06\xaa\x5a\x90\x11\x73\x62\x28\x3c\x68\x90\x46\x2c\x72\x3b\xf1\xac\x1d\xa6\xcc\x02\x3f\x23\x9a\x59\x33\xf9\xe5\xb8\x19\xf4\xb3\x1d\xa2\x99\xc7\x8d\x7e\x7f\xe5\xa8\x50\xb3\x9b\x4b\x3d\x5b\x4e\x75\x32\x6d\x92\x31\x23\x60\xa8\x06\x73\x4a\x05\x92\x71\x1b\x90\x3b\x65\x2d\x42\x0b\xf6\x07\x8d\xdb\x79\x9b\x1b\xfb\xf9\xd8\x4e\x2d\x28\xfe\xc8\xe7\x9d\x60\x10\x94\x6e\x2a\x44\x3a\x20\x17\x34\x99\xe2\xb2\xd2\x80\x67\x18\x0d\x04\x27\x9b\xd2\x99\xd9\x78\xf7\xac\xf5\x63\xa3\xb4\x52\x59\x47\x11\x97\xcc\x79\x4a\x28\xb7\x2d\x48\xc7\x20\xa5\x8d\xa1\x1e\xcd\x7d\x28\x5b\xeb\xcd\x6b\x75\x92\x0a\x29\xb4\x48\x44\x8b\x26\x58\x8b\x79\x19\x38\x1d\x02\xa1\xb0\xb8\xeb\x20\xff\xdd\xf9\xb0\x47\x6e\xcf\x86\xd8\xba\xe8\xe6\xec\x76\xd8\x94\xb0\x0f\x6e\xcf\x86\x07\xcf\x0a\x0a\xe2\xcd\x6c\x68\x50\xdd\x61\x92\x86\xc1\x24\x63\x4a\xf7\x73\x5a\xf4\xef\x60\xbe\x23\x4f\xed\x82\xaf\xf7\xab\x1d\xee\xe4\x83\x2c\x98\x73\x5a\x6c\x3d\x9b\x04\x9a\xb2\x98\x00\xb4\xf9\x88\x09\x40\x1b\x8e\x98\x00\x14\x13\x80\x96\xc7\xde\x44\x4c\xc6\x04\xa0\xd7\xe5\xba\x8d\x09\x40\xdb\x8f\x67\xf7\xd8\xc6\x04\xa0\xd5\x23\x26\x00\xc5\x04\xa0\xcd\x46\x4c\x00\xda\x7e\xec\x5d\xac\x49\x4c\x00\xda\x6a\xc4\x04\xa0\xe5\x11\x13\x80\xd6\x8c\x98\x00\xb4\x66\xc4\x04\xa0\xe5\x11\x13\x80\xb6\x1b\x31\x01\x28\x26\x00\xbd\xea\xb8\x48\x12\x13\x80\xdc\x88\x09\x40\xaf\x22\xfa\x8b\xc4\x04\xa0\x8d\x46\x4c\x00\x8a\x09\x40\xbb\x8c\x98\x00\xf4\x5a\x8c\x32\x31\x01\x28\x26\x00\xfd\x7a\x04\xdd\x98\x00\x14\x13\x80\x62\x02\x50\x4c\x00\x7a\x74\x15\x31\x01\xe8\x35\xa8\x80\x12\x14\xfb\x17\x0c\x45\xc6\x92\x79\xeb\x80\xbf\x6b\xd7\x5a\x56\xb9\x69\x49\x81\xf3\x06\xa1\x55\x2d\x92\x38\xf6\x2c\x77\xe5\x3a\x00\x5c\x98\xc3\x52\xb5\xd7\xfd\x04\x20\xd8\x8b\x3c\x16\xff\x81\x57\xbb\x7b\x52\x70\x12\xa3\x35\x5a\xf0\xed\x66\xb7\x68\xad\x22\x84\x1f\xd2\x51\x68\xf5\x61\x98\x0a\x57\x61\x82\x16\x15\x05\x63\x6b\x11\x84\x16\x45\xc6\x40\x0d\xc8\x4d\xd5\xe2\x04\xa9\x97\x7a\x47\x92\xa2\xec\x91\x1c\x72\x21\xe7\x2d\xb4\x89\x0e\x04\xce\xc6\xae\x75\x04\xb2\x6b\x3b\xa7\x07\x83\x51\x22\x8a\x22\x9b\x5b\x61\xaa\xce\x1c\xac\xa0\xc6\x3c\x71\x49\x51\xdc\x59\x88\xf2\x60\xba\xa1\x86\x5d\x09\x7d\xed\x10\xfe\xd9\xc2\xd6\xd7\x05\x68\x53\x2d\x72\x96\xec\x42\xb0\x2d\x8d\xed\x90\x5a\x6f\x1c\xa1\x4d\x2e\x56\xfc\x8a\xa6\x6b\x55\x98\x49\x64\x3d\x65\x26\x81\xa6\x73\x9c\x12\x9b\xf9\x04\x5a\xf1\x0b\x0c\xf4\x4e\x32\xca\x76\xf7\xca\x37\x03\xa7\xce\x70\x2e\x62\x50\xa1\x0e\x9d\xc2\x08\xdc\x0a\x7c\xbd\x2a\x2c\x89\xd9\x43\x30\xf0\x97\xec\xc3\x3d\x1b\xc7\x6b\x40\x8e\x22\x25\x0a\xde\x4c\x85\x1a\xf7\x8f\xbc\x16\x7e\x39\xa1\x59\x31\x7d\x5c\xfc\x35\x0b\x39\x9f\x73\x9a\xb3\xc4\x23\xc6\xa9\xdd\x3b\xa3\xee\x34\x05\x60\x3f\xb7\x9d\xcf\xbc\x24\xcf\x4b\x4d\x47\x19\x0c\xc8\xa5\x4d\xa5\x11\x1c\x3b\xdd\x63\xfc\x85\x73\x6b\x78\x24\xda\x35\xc2\xaa\x7d\x78\x45\xcb\xd0\x8a\x95\xa7\x07\x37\xc4\xa6\x0d\x01\x37\x98\x2f\x38\x10\xe0\x5a\xce\xcd\xde\x0d\x45\x7a\x63\xb6\xaf\x71\x77\xeb\x6c\xa2\x96\x11\x15\x5d\x44\x53\xb4\x8c\xa4\xe8\x26\xfe\xa1\x7d\xec\xc3\xb2\x13\x37\x48\xf0\x0b\xc3\x1a\x1b\xbb\x6a\x68\xd8\x8a\x53\xe9\x19\xff\x50\xa4\x86\x7d\x49\x08\x5b\x89\x39\xed\x0f\x0f\x48\x4e\xef\x50\x81\xa6\xba\xe6\x6b\x74\x46\x59\x66\x8e\x50\x9d\x1e\xd0\x52\x56\xf4\xa3\x03\xc6\xdf\x75\xd6\x14\x69\x8b\x41\x5d\x66\x3d\x11\xec\x7c\x94\xb3\xdd\x32\xf8\xc9\x92\x0c\xf8\x1e\xe7\x0a\x82\xad\x0c\x4e\xe4\xf4\x01\x35\x52\x9a\x8b\x92\x6b\x83\x29\x89\xc8\x8b\x52\x37\x79\x26\xb2\xdf\xad\x55\xd5\x44\xf0\x31\x9b\x38\x13\xd7\x49\x4e\x39\x9d\x40\xbf\x9a\xb6\x5f\x93\xde\x93\x76\x7a\x6a\x2b\xb2\x43\x53\x9f\xe0\x32\xec\x22\x56\x9c\x6a\x0d\x92\xbf\x23\xff\x79\xf4\xe3\xef\x7f\xe9\x1f\x7f\x79\x74\xf4\xc3\x9b\xfe\xdf\x7e\xfa\xfd\xd1\x8f\x03\xfc\xc7\xef\x8e\xbf\x3c\xfe\xc5\xff\xf1\xfb\xe3\xe3\xa3\xa3\x1f\xbe\xfd\xf0\xf5\xed\xf0\xe2\x27\x76\xfc\xcb\x0f\xbc\xcc\xef\xec\x5f\xbf\x1c\xfd\x00\x17\x3f\x6d\x38\xc9\xf1\xf1\x97\x5f\xec\xbc\xe4\xd6\x16\xe8\xee\xec\xcf\x1d\x59\x9f\x3f\x89\xed\xd9\x45\x69\x76\x74\x16\x5d\x84\xf9\xd2\x69\x74\xf6\xa1\xc7\x4e\xa3\xe7\x92\xa8\x66\x54\xf3\x30\x45\x44\xce\xb4\x76\x52\x32\x0d\xf3\xca\x16\x94\x0f\x47\x07\xd8\xd8\x52\x7a\xa6\xc2\x9c\xac\x40\x67\x11\xde\xd0\x8a\xca\x0f\x27\x2c\x2f\x32\xc8\x81\x6b\x3c\xcf\x7d\x2f\x09\xa2\x36\x38\xa8\x57\x92\x50\x6e\x64\x76\x78\x48\x00\x52\xf7\xb2\x48\x3a\x9e\x1e\x91\x74\xbc\x46\xd2\xa1\x20\x29\x25\xd3\xf3\x33\xc1\x35\x3c\xec\xe4\xef\x5c\xe7\xf0\xbd\x69\x4e\xed\x54\x33\x17\xbb\xea\xae\x11\x51\xd8\x4c\xcd\xb5\x35\x90\xa6\xa2\xcc\x52\xac\x30\x50\x72\x74\x01\xd9\x62\x15\xa0\xad\x7f\x06\x85\x44\x94\x20\x17\x5f\xe7\x3d\x2e\x76\xea\xff\x29\xd9\x8c\x66\xc0\x75\xf0\xc4\x10\x7d\x0c\xe1\x43\x3b\x99\x89\x9e\x59\xc5\x46\xe9\x67\x28\xd9\x8c\x65\x30\x81\x0b\x95\xd0\x0c\xa9\x52\x37\x8c\xe0\x74\xcd\xec\xb8\x45\x52\x64\xca\x48\xec\x86\x10\x13\xea\xdd\x69\xa8\xc7\x4e\x28\xe3\x24\x37\x44\xb5\xf0\x0f\x2b\xeb\x97\x33\xb4\xbd\xa0\xd2\x6c\x45\xe5\x7f\x43\xad\x78\x24\x44\xe6\xf2\x8a\xb3\x79\x3d\x3f\xb3\xca\x01\x17\x3f\x73\xb8\xff\xd9\xcc\xa6\xc8\x38\xa3\x93\xca\xed\x66\x54\xe5\x45\xcf\x79\x3d\xf5\xda\x0f\xc0\xa4\xdd\x12\x08\xcd\xee\xe9\x5c\xd5\x4e\xc8\x7a\x0e\xa6\xde\x91\xb7\xc7\x88\x78\x54\x91\x6a\x8e\x94\xfc\xe1\x18\x43\xe9\xce\x4e\x87\x3f\xdf\xfc\xf3\xe6\xe7\xd3\xf3\x0f\x97\x57\xe4\x4a\x68\xb0\x1c\x2b\xd0\x5e\x1c\xb3\x71\xab\xac\x6c\x73\x03\xa1\x06\xa8\x21\x61\x64\x38\x4f\xc5\xbd\xda\xd9\x42\x69\xd1\xcf\x00\x0f\x28\xdf\xcd\x48\x43\x0b\x8a\xfd\x9d\x5b\xf0\x87\xa5\x68\xed\x70\x52\x64\xd0\x69\x7a\x92\x4a\x51\x58\x20\x78\x87\x71\x68\x23\x3b\x5f\x88\x03\xf1\x59\x67\xb8\xbf\xe3\xe6\x84\x13\x49\xb9\xae\x3d\xa7\xf5\x9e\xb9\xc6\xd2\x83\xd6\xdb\xf1\x7c\x6c\xbb\x0b\x1d\x9f\xa6\xdd\xd5\x0c\x38\x4d\x53\x48\x1b\xe0\x7f\x75\xb9\x3e\x67\xfe\xe3\x02\x97\x14\x19\x7e\xbc\xb9\xfc\xdf\x0b\x78\x3c\x2f\xda\x25\x1d\x74\x53\xca\x45\x8a\xa2\xb3\xdd\xbd\x86\x5c\xcc\xe2\xfe\xee\xcb\xfe\x56\xdc\xb2\x9b\x50\xd7\xeb\x92\x87\x0c\x8d\x07\xf3\x93\x5c\xa4\x30\x20\xc3\x2a\xe6\xa6\x79\x35\x2c\x17\x29\x81\x98\x5b\xb8\x66\x34\xcb\xe6\xa1\x30\xa5\x85\xad\xf5\xd1\x28\x26\x16\x12\xf2\x31\xcd\xd4\x73\x53\xe3\x36\xbc\xd1\xc8\x11\x1f\x8c\xb2\xdb\xc9\x76\x54\xb3\x91\x14\xb8\xd0\x4e\x18\x36\xab\xc4\x02\x6d\x52\x24\xc4\x6a\xd6\x41\x62\x43\x83\xbf\x29\x1b\xf7\xe3\x59\x23\x53\x1e\xd8\xc3\x6a\x66\xeb\x32\x2d\x15\xa8\xd5\xac\xb1\xd6\xb5\xcd\xec\x12\x68\x8a\x3e\x87\x82\xea\xa9\x8d\x4b\xce\xa9\xba\x83\xd4\xfe\xe0\x44\xb3\xca\xed\x81\x66\x5a\xff\xaa\x5b\xb3\x6e\xef\xe1\x40\x91\xcc\x46\x4b\xa3\x6f\x04\xd2\x67\xde\xf5\x16\x87\xd0\x00\xe5\x23\xcf\xe6\xd7\x42\xe8\xaf\xaa\x62\x35\x9d\x60\xc0\x3f\x9c\xb4\xdc\x74\x3b\xa1\x38\x49\xf1\xbd\x7d\xdc\x0d\x3c\x54\x61\x9d\x9c\xf3\x7a\xc7\x5f\xfa\x91\x92\x25\x3f\x55\x5f\x4b\x51\xee\xcc\xc4\x96\x84\xcd\xaf\x2f\xcf\x91\x14\x95\x2e\xec\x8f\x6b\x39\x2f\x04\xb3\x26\xaa\x35\x8a\xc1\x77\x2e\x70\x31\x3c\x13\x75\x8c\x19\xf9\x40\xe7\x84\x66\x4a\x78\x58\x3a\xa7\xd4\x82\xbe\x48\x9c\x32\x6a\x2e\x8f\x84\x9e\x2e\x69\xa1\xe6\x40\x2d\x3f\xd7\x0b\xa2\x00\x6b\x5f\x3d\xe3\x4b\x8f\x6b\xf4\x78\x14\x12\x12\x48\x81\x27\xcf\xbd\xed\xcf\x1d\x3c\x87\xa8\x73\x25\xb8\x39\x98\x9d\x20\xcf\x65\x15\x35\xe9\x40\x1a\xa2\x0a\xba\xb4\x9c\xf6\x47\x31\x0a\x13\x8f\x65\xa9\x40\xda\x90\x51\x59\x82\xdd\xc9\x6f\xcb\x11\x64\x06\xf2\x46\x25\xc5\x72\x99\x54\x5b\xc3\x03\xcb\xe9\x04\x08\xd5\x15\xa6\x69\x41\x80\xab\x52\xba\x4d\x64\x9a\xa4\x02\xea\x1a\x57\x54\x91\xef\x2e\xcf\xc9\x1b\x72\x64\xde\x75\x8c\xf8\x33\xa6\x2c\xc3\x00\x4d\x0c\xf8\x58\xd0\x51\xc7\x7e\x0a\x5c\x12\x22\x2f\x11\xd2\x12\x89\x1e\xe1\x82\xa8\x32\x99\xfa\x35\x19\xbd\xd7\xab\xcd\x2e\xa9\x08\xfd\x26\xfb\x89\xeb\xcf\x4b\xa1\xbe\x53\x20\x3b\x23\x50\xdf\xed\x40\xa0\x42\x31\xca\xe0\x5c\x13\x7a\x16\xb1\x72\xd0\x34\xa5\x9a\x3a\xc2\xe5\x6f\xd8\xdb\x2d\xfd\x75\x93\x2f\x05\xef\x19\x2f\x1f\xac\x89\xb4\x3b\x53\xcb\xcd\x05\x4e\x8b\x38\x84\x50\xc7\x5d\xb7\x81\x71\x55\xfc\x50\x10\xe2\x72\xd9\xc0\x95\xde\x1a\x31\x11\xe9\x84\x0f\x43\x32\xc2\x09\xe5\xa9\xc8\x97\x5e\x86\x31\x4f\x34\x99\x86\x2f\x88\xd8\xd7\x1c\x7b\x62\x14\xca\x60\x06\x2d\x8a\xe1\x2e\x60\xde\x7b\x33\x9b\x01\x8e\xc7\x08\x9c\x9e\x64\x74\x04\x99\x0b\xb3\xb2\xa1\x99\xcb\x18\xf8\xdc\x99\x5d\x52\x64\xdd\xa5\xa2\x5f\x8b\x0c\x6c\xaa\x84\x07\x84\x99\xfe\x45\xc0\x01\x27\xe9\x0a\x0e\xa8\x0d\x36\xe0\x80\x7a\xed\x4b\x80\x43\xd9\x82\xd5\x93\x45\x38\x18\xb9\xa1\x09\x07\x64\xde\xfb\x0e\x07\x05\x49\x22\xf2\x62\x28\x85\x51\x3b\x3b\xe3\x4d\x6e\xda\xda\xcf\x67\x0d\x1b\x2b\x02\x2f\x91\x17\x34\x6f\xa6\x32\x48\x92\xa2\xda\x32\x09\x9f\x29\xf5\xbf\x02\x9e\x85\xa4\x67\x91\x91\xf9\x59\x1a\x8e\x40\xf3\xa4\xbb\xf0\x92\xd9\x41\x17\x79\xc6\x2d\x8c\x9d\x9d\x70\x23\x91\xd0\x0c\x9b\x1d\xb4\x43\x39\xb2\x88\x76\x8b\x13\x07\xa9\x71\xe8\xa3\xc4\xdf\x82\x38\x61\x8a\x86\x16\x6f\xc2\xe4\x22\x85\xc0\xeb\x6c\x63\x0f\x6f\x6d\x0a\x15\xde\xe7\xb3\xf2\x8c\x5c\xe1\xa2\x40\x20\x6d\x3c\xad\x85\xab\x33\xfc\xa1\x6a\xa1\x60\x16\x08\x3c\x65\x7c\x82\x76\xb5\x1e\x91\x90\xd9\x7c\x3e\x47\x04\xee\xac\x06\x79\x88\x47\xc2\x4f\xea\xcf\x83\x7f\xb5\x0f\x2b\x76\x33\x87\xb1\xc2\x6c\x6c\xc9\x2d\x53\xe4\xe0\xbd\x07\x40\x8b\x9a\xf3\xfb\xc8\x61\x0e\xec\x17\x56\xbb\x69\x2d\x9d\x77\x8c\xa7\x2e\xf5\xad\x01\x2c\xaf\xe7\x3a\x39\x18\x93\x2a\x59\x1a\xd2\x96\x77\xe4\x47\x4e\x2a\x60\x91\xfe\xce\xe8\x71\x6d\x45\x66\x6f\xa3\xeb\x3f\x6e\x78\xad\x5e\xb2\x38\xcd\x77\x1c\xf7\xde\xbc\xb7\x6f\x34\xf7\xe5\xfb\xfc\xb7\x3c\x6b\xb1\x4d\x47\xfd\xba\xd6\x62\xfe\x61\xa7\xf5\x22\x7d\x62\xd0\x5a\x33\x3e\x51\xa1\x26\xd3\xec\x6c\xb5\x5a\x95\xf1\x3b\x3c\x96\x22\xf7\x71\xc5\x8b\xaa\x41\x33\x65\xf7\xa5\xa8\x21\x99\x11\x27\x5e\xb8\x12\x32\xc9\x15\x3d\x93\x06\x12\x9a\xd1\xec\xa6\xd8\xbd\x11\x00\x59\x2a\x3a\xfd\xe1\xe6\xb4\x39\x35\x32\x6b\x17\x51\x0e\x78\x9d\xd0\x34\x67\x4a\xa1\x21\x0c\x46\x53\x21\xee\xc8\xd1\x8a\x0a\xba\x41\x94\x95\x62\x13\x75\xe2\x70\xbe\x6f\x56\x7f\x4c\x18\xcf\xaa\x48\x26\xd4\x83\xb9\xae\x82\xd8\xf1\x25\x49\xb5\x0a\xdc\x43\xd7\x68\xc5\x05\x2b\x2c\x2f\xd3\xb6\x56\x31\x58\xf0\xec\x04\x7b\x79\x7b\xda\xa5\xf9\x3d\xb9\x45\x57\x0e\xb7\x17\x6b\x21\xaf\x84\xa3\x95\x1e\x9f\x1d\x48\x4e\xb8\x48\x40\x75\x57\x82\xf5\x9b\x7a\x4e\x92\x82\xcd\x88\x07\x8c\x7e\xa2\x6b\xc3\xe1\xd0\x2e\x7d\x88\x85\x55\xdc\xa3\x87\xa1\x44\xdd\xcc\x35\xc2\x54\xa6\xbe\x55\xd2\x0d\x45\x43\x12\xe8\x45\x88\xa9\xe0\x42\x5a\x14\x35\x4c\x54\x70\x44\x69\x24\x51\xd6\x9b\x87\x7b\xe2\x48\x74\xb0\xd4\xb3\xda\x4b\x1c\x3a\x02\xb1\x30\x83\xad\xc5\x56\xaf\xe1\x9e\xe9\x29\x76\x53\x98\x2e\x78\x0d\x71\x25\x12\x14\x3a\x60\x38\x01\x29\x85\x74\x01\x59\xde\x6e\xed\x12\xad\x86\x22\xc5\x88\x2e\x83\x24\xd4\xfc\x75\xa8\x42\x47\x75\xdd\xbb\xa8\xaa\x8f\x09\xe3\x31\x24\x28\x68\x85\x00\xb6\x54\xfb\xa8\x6e\x2f\xe1\x33\xf8\xb4\xf0\xbd\x8f\x72\xf6\x60\xde\x12\x3e\xb5\xd0\x41\x91\x0b\xde\x5f\x7d\xf9\x78\x40\xc8\x25\xaf\xe2\x6f\x7b\x66\x17\xc3\x3b\x7d\xe8\x99\x36\x9f\x18\x36\xce\xc2\x0f\x08\x0d\x67\x46\x3a\x94\x65\x07\x18\xdf\xc6\x1c\x4e\x42\x93\x78\xa7\xe4\x00\x4d\xe3\x6e\x52\xb3\xf5\x5e\x06\x68\x63\x2a\x37\xb7\x7c\x2a\x73\xf9\xcb\x70\x80\x90\xb6\x74\xce\x55\x26\x8b\xdd\x8c\x36\x1b\xb1\x9b\xd1\x86\x23\x76\x33\x8a\xdd\x8c\x96\xc7\xde\x84\x0c\xc6\x6e\x46\xaf\xab\x0e\x65\xec\x66\xb4\xfd\x78\xf6\xf2\x93\xb1\x9b\xd1\xea\x11\xbb\x19\xc5\x6e\x46\x9b\x8d\xd8\xcd\x68\xfb\xb1\x77\x85\x73\x63\x37\xa3\xad\x46\xec\x66\xb4\x3c\x62\x37\xa3\x35\x23\x76\x33\x5a\x33\x62\x37\xa3\xe5\x11\xbb\x19\x6d\x37\x62\x37\xa3\xd8\xcd\xe8\x55\x17\x79\x27\xb1\x9b\x91\x1b\xb1\x9b\xd1\xab\x28\x65\x4d\x62\x37\xa3\x8d\x46\xec\x66\x14\xbb\x19\xed\x32\x62\x37\xa3\xd7\x62\x94\x89\xdd\x8c\x62\x37\xa3\x5f\x8f\xa0\x1b\xbb\x19\xc5\x6e\x46\xb1\x9b\x51\xec\x66\xf4\xe8\x2a\x62\x37\xa3\xd7\xa0\x02\x2a\x9d\xb2\x9d\x0a\x46\x6e\x52\xdb\xc6\xc5\x2c\x07\xa9\xe4\xa3\x72\x3c\x06\x89\x94\x0b\xdf\xbc\x14\x56\x55\x97\xf1\x5b\x74\xe5\x82\xee\x61\x99\x1c\x97\xde\xb1\xe6\x71\x97\xbb\x8e\x85\x1d\xeb\xc0\xe2\x8b\x8f\x5f\xad\x28\xa4\xb3\x73\xbc\xe1\xae\x21\xb5\xb8\xe6\x8f\x7c\x37\x2f\xfc\x1a\x80\xaf\x4a\x37\x72\x70\x4f\x32\xa1\x5c\x40\x34\x02\x2b\x99\x52\xce\xc1\xeb\x7b\x4c\xa3\x1d\x65\x04\xc0\x89\x28\xc0\xf9\xc0\x29\x51\x8c\x4f\x32\x20\x54\x6b\x9a\x4c\x07\xe6\x4d\xdc\x03\xbb\x0e\x5e\x76\xbf\x28\x2d\x81\xe6\x3e\x8c\x3b\xa7\xcc\x4e\x45\x68\x22\x85\x52\x24\x2f\x33\xcd\x8a\x6a\x32\xa2\x00\xf3\x2f\x2c\xa3\xaa\x80\x81\xf1\x72\x75\xc4\x73\xaf\x7e\x9b\x5b\x96\x08\x2b\x99\xa1\xb6\xd9\xc3\xda\xd0\x79\xa1\xe7\xc4\x7c\x72\xe6\x0a\xc2\x4a\xa5\x49\x92\x31\xe4\xd6\xf8\x46\x9b\x6a\x8b\xf3\xf5\x3c\xaf\xe6\x6e\xa5\xca\x2d\x95\xa7\x28\xb6\x16\x5a\x11\x0c\x10\xae\x27\x74\x53\xa5\x4c\x39\x31\x5f\xf5\x08\xf5\x65\xb6\x2c\xa0\xfd\x4a\x11\xd4\x9e\xb3\xd8\xd9\xdd\x4f\xc1\x74\x41\x79\x51\xdf\x18\xc8\xe5\x20\xd9\x58\xf9\x8c\x4e\x2a\xe4\xec\x35\x82\xff\x6b\x81\xc2\xb5\x40\x58\x38\x06\xb8\x01\x1c\x66\x06\x07\x20\x01\xc3\x5f\xe9\x1a\xac\xff\xec\x48\xaf\xa9\x9c\x80\xae\xd2\x05\x76\x8d\x22\x6f\x06\x9f\x84\x85\x80\x43\x45\xa4\x06\x19\x42\xc7\x35\x13\x09\x32\xae\x56\x55\x1a\xb6\x2b\x74\x05\xd6\x56\xdd\xe0\x05\x23\x1b\xbc\x59\x77\xa0\x29\x68\x02\x8a\x1c\x5d\x0e\xcf\x7a\x64\x78\x79\xee\x22\x34\xc5\x78\x55\x86\xb3\xa3\x61\x16\x03\xd7\xd5\x3c\xae\x6a\xb7\x05\xd3\x07\x59\xa1\xee\xdd\xc3\x4a\xbe\xc2\xb6\x32\xab\x28\x00\x8a\x5c\x55\x59\x74\xa2\x6c\x87\x2c\x67\x13\x62\x55\xca\x86\x43\x3e\xa8\x13\x15\x7d\x45\x22\xff\x44\xb5\x10\x07\x25\x97\x8f\xe1\x3d\xea\x48\x60\x91\x5f\x2f\x25\x7d\x60\x90\xa8\x8b\xae\xd9\x29\xaa\xa6\x95\x86\x14\x88\x62\x1f\x40\x29\x3a\x81\xe1\x8e\xee\xad\x75\x76\x00\xf4\x70\xd5\xe4\x00\x09\x50\xd6\x68\x5d\x16\x46\x0b\x37\x85\x6f\x92\xdb\x35\x55\x98\x75\x2f\x99\xd6\x80\xa4\x04\xcb\x00\xe2\x66\x2f\x56\x09\x38\x5c\x88\x39\xfe\xe0\x27\xa9\x1f\x36\xa2\x04\x4f\x6d\x04\xf0\x08\xc8\x48\x32\x18\x93\x31\xc3\xb0\x62\x0c\xf4\xed\xd9\xaa\x50\xd4\xda\x9e\x94\x02\x69\xbb\x15\x59\x0d\xca\xaf\x6b\x40\xfe\xe1\x16\xa6\x65\xc9\x6d\x37\x2a\x27\xdc\x63\x1a\x2c\x1b\x93\x09\x06\x0a\x3b\x1d\xe5\x4f\x6f\xfe\xf6\x17\x32\x9a\x1b\x41\x0a\x11\x52\x0b\x4d\xb3\xea\x23\x33\xe0\x13\x03\x2b\xcb\x14\x9a\x89\x9c\x15\x04\xb0\x9f\x88\x5d\xf8\xdb\x3f\xdc\x8d\x9a\x92\xdd\x49\x0a\xb3\x93\x00\x7e\xfd\x4c\x4c\x06\xe4\xac\xca\x9b\x2c\x8b\x14\xed\xfc\xbb\x17\xf1\xee\x0e\xcd\xba\x69\x0c\xe9\xcb\x93\x91\xa9\xb8\xb7\x1a\xe6\x0a\xec\xa9\x73\xc2\x0a\x51\x94\x99\x75\x75\x7c\x55\xa5\x40\x97\x0a\x96\x13\x15\x57\x9e\x0b\x34\xce\xbb\x29\x16\xe8\xa8\x8b\x0f\xf7\xaf\x14\x2e\x01\xc6\x99\x8f\xab\x2a\x65\x48\x4c\xbe\xa2\x59\x36\xa2\xc9\xdd\xad\x78\x2f\x26\xea\x23\xbf\x90\x52\xc8\xe6\x5a\x32\x6a\x78\xf4\xb4\xe4\x77\xb6\x87\x44\x55\xc7\x41\x4c\x5c\x00\x81\x2f\xfb\xbd\xea\x83\x6d\x52\xbf\x67\xfd\x5e\xf9\xae\x67\x81\x07\x56\x6b\xd8\x2e\x9f\xcc\x62\x64\x38\xbf\x0a\x91\xed\x0f\x6f\xfe\xf4\x57\x8b\xba\x44\x48\xf2\xd7\x37\x98\x43\xa0\x7a\xf6\x10\x23\x47\x35\xe2\x49\x4e\xb3\xcc\x10\xf2\x10\x29\x0d\xa0\x57\x21\xe1\x67\xc7\x41\xdd\x1e\xdd\x36\x16\xe0\x6f\x6f\xff\x89\x5c\x84\x69\x05\xd9\xb8\x67\x53\xa7\x2a\x65\xfa\x10\xc5\x91\x43\x47\x7d\x30\x7f\x6d\x0f\xc4\xee\x99\xc8\xca\x1c\xce\x61\xc6\xba\x68\x02\xd8\x98\xcd\x1b\x98\x32\xa6\x90\x0f\x8e\x32\x91\xdc\x91\xd4\x5d\x0c\xa2\xaa\x16\xcb\x95\xbf\xdc\x7e\xae\xe1\xf7\x37\x22\xca\x72\x5a\x14\x46\x06\xc0\x0c\x4d\x49\xef\x1b\xc0\xc0\x33\x89\x35\x15\x5e\x7e\x3f\x57\xfb\x45\x86\x6e\xee\x3c\xc5\xce\x61\x68\xed\x3d\x23\xf5\xea\x3b\xea\xeb\x57\x4f\xe8\x4f\x43\x81\xff\xb6\x59\x4e\x4b\x82\x79\x55\x6e\xb3\x42\x0c\x2b\x00\x18\xf4\x41\x92\xfc\x6c\x7d\x47\x49\xeb\x70\xba\x06\x5c\xf8\x23\xcd\xf1\x28\x29\x40\x2a\xa6\x0c\x5f\xfe\x1e\x0f\x94\xed\x8a\x58\x1b\x9e\x9f\x07\x08\xf6\x70\x63\x8d\xe7\xf6\x94\xd2\xe8\x29\x76\x42\x24\x85\xb6\xbe\xf5\x0a\xb1\xb6\x29\xd5\xde\x94\x23\xc4\x1f\xbc\x7d\x9b\x4e\xab\x1d\x72\xe2\xe7\xa6\xb1\xdf\xd7\xdb\xd0\x24\xb1\xe6\x97\x8a\xc6\xda\xbb\x5e\x13\x65\xc5\xef\x7b\xa9\x84\xb5\x5a\x7c\x47\xf4\x03\x29\xaa\xdb\xdc\x26\x09\x6d\x68\x9d\xf6\x84\x05\xba\x80\x53\x20\x07\xc4\x06\x6d\x98\x33\xe1\x1e\x25\x87\xef\x0e\x9f\x95\xba\x5a\x10\x49\x51\xd0\x49\xab\x4e\x45\x0b\x90\x5a\x9c\x36\x2c\xa3\x61\xf4\xa7\x80\x94\x14\xee\x2e\x43\x49\x7c\x95\x20\xac\x01\x65\x9d\xf9\x1e\xc0\x4e\xb3\xc0\x46\x73\xe4\x9e\xce\x09\x95\xa2\xe4\xa9\x33\x87\x56\xf6\xe8\x0f\x0b\x2f\xbe\x12\x1c\xea\xbe\xa5\xcd\x2a\x1c\xe8\x80\x62\x9c\xbc\x1d\xbc\x7d\xf3\x5a\x58\x1c\x7e\xe1\x02\x8b\xbb\xaa\x58\x9c\xa5\x4f\xcf\xfa\xad\xbe\x9e\x7f\x47\xdf\xfb\xc1\xd9\x66\xea\x72\xfd\xcc\x17\x03\xc7\x9f\xee\x25\xd3\x10\xb4\x27\x3c\x42\x8d\xc7\x28\x96\x41\xcd\x89\xe3\x55\x7d\x32\x5a\x02\xa9\x5d\x91\x0f\x55\x8e\x3e\x21\xdd\x72\x04\x0a\x8f\xdb\x2a\xd3\x98\x7a\x84\x84\x85\x80\x3a\x38\x20\x47\xf6\xce\x43\x9b\x99\x7f\xfc\xac\xa8\xe5\x80\x76\xf1\x50\xb4\xa8\x20\xba\x50\x04\xa2\xa0\x68\xbc\x2b\x3a\x84\xe0\x7f\xc0\x94\xce\x00\x2b\x12\xb0\x8c\xca\x0c\x5d\xe4\x37\x76\xed\x64\x54\x6a\x02\x7c\xc6\xa4\xe0\x68\x27\xc6\x94\x8d\x51\x06\x61\x77\xee\x2f\x8e\xbe\x3f\xbd\xc6\xf8\x9b\x63\xdb\x0f\xc6\xaf\xb2\x54\xbe\x38\x4f\xb8\x92\x60\xba\x27\xb7\xcf\xaf\xc3\xc0\x10\x69\xae\x5f\x97\x79\x4f\x5e\xea\xd2\x36\x9d\x79\x48\xb2\x52\xb1\xd9\x73\x51\x12\x57\x2a\xe2\x9c\xed\xb4\xcf\x0b\x65\x2b\x6a\x40\x2d\x55\xa0\xa8\xdd\x04\x4f\x14\xe8\x3e\xfc\xff\xd8\xfb\x1b\xee\x36\x6e\x6b\x5f\x18\xff\x2a\x58\x6a\xd7\x5f\x52\x4b\x52\x76\x72\xda\xd3\xe3\x9b\x7f\xb3\x54\x49\x4e\x74\x63\xcb\x3a\x96\x9c\x3c\x7d\xe2\x9c\x16\x9a\x01\x49\x54\x33\xc0\x64\x80\x91\xcc\xde\xdc\xef\xfe\x2c\xec\xbd\x81\x01\x86\x94\x63\x71\xc6\xa6\xe4\x70\xba\x56\x63\x91\x43\x0c\x06\x2f\x1b\xfb\xf5\xf7\x33\xa1\x92\x35\x4e\xd9\x20\x9f\x15\x2b\xe5\x6c\x6e\x29\xdb\xb3\x13\x39\x88\x42\x50\x25\xb8\x79\x37\xe9\xbd\x72\xc7\xee\x61\x21\xb9\xb9\xaf\xca\xb5\x54\x2e\x49\xad\x10\x73\xbf\xf6\xb9\x45\xde\x29\xe3\x1e\x84\x9e\xca\xd3\x73\x8a\xa0\xf9\x71\x93\xea\x5f\x98\x58\x13\xcc\x12\x4c\x94\xc1\x9f\xa0\xbb\x71\xca\x22\xb8\x20\x9f\x50\x02\xc2\x1f\x30\xaa\xc0\x22\x51\x5a\x8d\xe7\x11\x9c\x53\xa5\xf3\x7b\x96\x12\xae\x6b\x78\xac\x65\x72\xac\x1e\x41\x36\xd7\x45\xee\xc9\xb7\xd1\x97\x73\x25\xec\xad\x10\x8a\x9d\x9e\xc3\xf8\xb9\x57\xc4\x72\xae\xd5\xa3\x88\x61\x85\xc0\xfa\xbe\x6a\x3c\xef\xbb\xc0\x7a\x58\x25\x7d\x54\xfa\xf0\xa6\xbd\xf7\xfc\xb7\x61\xcc\x7c\x46\x36\xbf\xd2\x37\x02\x86\x34\xcf\x6b\x61\x7a\x00\x1f\x6d\xc0\x4e\xed\x25\x4a\xe5\x5a\xc4\x3f\x69\x60\x24\x0c\x9b\x77\x2d\x81\xfa\x0e\x5b\x15\x16\xde\x27\x96\x60\xa7\xe7\x47\x3d\xa4\xd7\xee\x1b\x8a\x8b\xb8\xa6\x76\x77\x0d\x93\x55\xd6\xc6\x5c\x27\xac\x0d\x37\x46\x85\x12\xa8\x31\xde\x2f\xd6\xb5\xae\x9a\x18\x09\xb5\x9e\x42\x9a\x29\x6c\xc6\x89\x15\x2a\xc5\x26\x77\x0e\x04\x1d\x2a\x9d\x03\x33\x53\x3b\x1a\xc6\xff\x22\x1e\x10\x9f\x2c\x81\x42\x9e\x52\x47\x46\x21\x09\xb9\x23\x98\xc0\xf5\xee\xd3\x0f\x23\x29\xbe\x34\x98\x9f\x6c\x2c\xcf\x4f\x8f\x87\x5c\x2e\x95\xcc\x1f\xdc\x72\x79\x63\xee\x5d\xd2\xff\xfe\x97\x04\x4c\xbf\x5f\x7b\x4b\x0c\x36\x11\x4c\x1f\xfd\x0d\x69\xea\xda\x32\xe2\x7d\x0c\x99\xb0\xab\x12\x3a\x40\x8a\xa4\x4f\x1a\xb9\xbf\xa7\x4d\x01\x8b\xb4\x4d\xee\x0d\x99\xc9\x3c\xe4\x85\x82\x36\xc0\x6f\xb8\x2c\x10\x31\x53\xdf\xdd\xa4\x0f\xbf\x17\x9a\xe7\x58\xee\x71\x2d\x6a\x25\x0a\x56\xea\xbc\x29\xd0\x9b\x17\xf8\x85\x5f\xbe\x3a\x7e\xf3\xe2\xc4\x27\x61\x89\x76\x3a\x47\x8c\x33\x25\x6e\xa1\x75\x05\x0a\x49\x46\xc0\x5d\xa1\xec\xc7\xed\x27\x8f\xc5\x89\x66\x28\x3a\x26\xfc\x0b\x95\xd2\xca\x19\x02\x6c\xb6\x6a\xe1\x55\x2d\xf8\xb5\x6e\x2c\xbb\x69\x0a\x25\xea\x96\x1f\x53\xdc\x08\x85\x3e\x58\xf7\x03\xf7\xd8\x18\xab\x51\xd6\x09\x44\x26\x01\xa7\x79\xd8\x4f\x9e\x91\x26\x4f\x25\x46\xf0\x65\x44\x0e\x9d\x50\x48\xbe\x1f\xba\xd4\x6b\x5e\x11\x6a\x29\x96\x13\x2f\x43\x96\x7a\x74\x49\x4c\xa3\xb9\xf0\x19\x30\x94\xf8\xf2\xe9\xb6\xc3\xfd\xdd\x2d\x69\x85\x68\x0a\xdf\x42\x0d\xfa\xb3\xef\x5c\xe7\x77\x58\x0d\xad\xde\x05\xf7\xc7\x94\xd9\x56\x33\xce\xd0\xdd\x3e\xf6\xf0\x37\x90\x29\xbb\x8e\x18\xbc\xf7\xa1\x09\x96\xc7\x79\x53\x14\x17\x22\xab\xc5\x7d\xc3\x0c\xa9\xa4\x38\xed\xb4\x75\x97\x05\x10\x99\xb3\x80\x09\x42\x37\xab\x16\x7f\x20\xca\x73\x6a\x6b\x71\xab\xa6\x80\xd4\x70\xae\x16\x7e\xc0\xa1\xf7\x26\x8a\xe9\x4a\xe3\xb3\xcc\x50\xfa\x24\xb3\x60\x44\x78\x58\x20\x5f\xe3\xc6\x60\xe6\x81\x54\xb9\xbc\x91\x79\xc3\x0b\x78\x10\x18\x65\x94\xb0\xc5\x09\xc7\x1c\xf7\x72\xe9\xd1\x8f\xef\x9b\xc3\xdc\xee\xc9\x03\xec\xf7\xef\xb0\x7b\x0b\xa9\x66\x63\xf8\xc4\x3d\x98\x7a\x38\xd6\x6a\xcc\xc7\x6e\xd9\x3c\x12\xbb\x05\xf0\xfb\x5f\x81\x61\xf0\xda\xcf\xaf\x17\x43\x86\x09\xa5\x9b\xd9\x1c\x06\xab\x2e\xb9\x87\xd2\x2c\x84\x05\x94\x44\xca\x67\xc0\x24\x36\xfa\x6d\x4e\x56\x46\x8c\x1a\x99\xae\x8d\x47\x62\xbb\xac\xeb\xe0\xed\x24\xe3\x47\x62\x86\xc6\xc8\xde\x7b\x05\xea\x1b\x51\xdf\x48\x71\x7b\x40\x9a\xdf\xd8\x9d\x09\x63\x1c\x11\x73\x00\x03\x7b\xf0\x3b\xb4\x8e\x2e\x5f\x1d\xbf\x02\xca\x71\xf2\xba\xfb\xa3\xca\x1d\x05\x66\xc2\x78\x25\xbf\x17\xb5\x01\x50\xe5\x6b\xa9\xf2\x11\x6b\x64\xfe\xf5\x27\x4c\xf8\x92\x4a\xb6\x59\xac\xbd\xa4\xd6\x0b\x92\x4a\x54\x45\x2f\xff\x8d\xcb\x33\x3a\x41\xaf\x44\xa1\xd5\x2c\xc2\x00\x80\xd3\xfc\x54\x49\xbb\xc4\xce\x8c\x48\xa7\xe0\xe1\xd1\x75\x0e\xb9\xc2\x52\xd7\x49\x38\xc3\xb5\x07\xf8\x8f\x51\xc6\xb1\x13\x69\x32\x69\x0f\xd2\xb8\x4c\xab\x23\x61\x22\x90\x2f\x17\xf6\xf0\xd8\x1e\x57\x12\xcf\xe2\x39\x57\x39\xfc\x99\x65\xba\xce\xa9\xbf\xd2\x86\xf4\x66\x4c\x86\xc3\x0c\x2c\x38\x86\x9c\x44\xe3\xaa\xfb\x64\x50\xd3\xea\x32\x49\x85\xf5\x5a\x7b\xa3\xe4\xcf\x8d\x60\xbc\xd4\x4e\x10\x77\x49\x20\x3a\x23\x52\xf2\x05\x9c\x85\xd0\xd5\x17\xbe\x5c\x83\x6a\x6c\xcd\x88\xbd\x16\x4e\xe9\x6a\x61\x02\x46\xec\x45\x8a\x1b\x30\x72\x7d\xb9\xc0\x82\x66\xfa\x08\x7b\x5f\x0b\xa3\x9b\x3a\x13\xaf\x31\xc6\x59\xfa\x7c\xba\xe5\x97\x71\xb3\x62\xf9\xb5\x50\xe8\x53\x72\x43\x03\x61\xdc\xa6\x86\x39\xc8\xe6\x22\x6f\xe0\x54\xb9\x5a\xb0\xa9\x44\x66\x18\x38\xda\xe5\x6c\x2e\x8c\xf5\xb6\xd1\x01\xe4\xa8\xb5\x24\x7b\xbe\x03\xb0\x7c\xa3\x64\xf6\xd6\x0b\x5b\x72\xc0\x2d\x87\x2d\xcb\xad\xaf\xd7\x42\x6d\xd0\x34\xa5\xdf\xcb\xdd\x91\x36\x13\xf6\xc2\x3d\x0a\xd7\x53\xc4\xb8\x21\x3b\x83\x0b\x31\x66\x72\x23\xb3\x29\x37\x73\xe0\xa3\xe9\x4e\x01\x91\x59\x64\x4d\xed\x04\x06\x62\xcc\xf3\x3c\x77\xd2\xb5\x66\x35\x52\xce\xaf\xf2\x3b\xf6\xac\xcf\x71\x9d\x1d\x47\xe7\xdd\x63\x39\xc4\x0e\x43\xbd\x85\x1b\xf8\xac\x23\x09\x70\x26\xdd\x81\xe5\x71\xdd\x9c\xc2\x1d\x02\xfe\x4e\x2a\x7c\xba\x23\x69\xfd\xf0\xfe\x5a\x61\xf9\x3e\x27\x20\xaf\x67\xfd\x1d\x77\xbb\x87\xf5\xac\xc1\x8d\x4e\x52\xb8\x45\xa4\x9f\x74\xf2\xee\x41\x99\x72\xb6\xea\xd1\xcb\xe3\xb8\xd0\x2f\xae\x60\xf2\x65\x92\x13\xf6\x7d\xdf\x30\x4b\x37\xce\xe2\x04\x7a\x1b\xbc\x69\xf9\x64\x9c\xd0\x28\x6e\xbc\x49\x10\x9e\xe6\x35\x5f\xa9\xaa\xc6\xd2\x49\x18\x01\x74\x65\x73\xae\x66\xe0\x26\xd1\x8d\x6b\xef\xf7\xbf\x87\x1e\xd5\x22\x6f\x32\x22\xe3\xf1\xab\xf6\xf7\x3e\xe8\x40\x70\x7a\x20\xae\x4c\xc6\x2b\xdf\xe7\xf8\xb5\xcc\x42\x59\xfe\xee\x19\x93\x13\x31\x61\x3b\xbf\x8f\xbe\xda\xc1\xa7\x57\xb5\x76\x8f\xa0\x02\x23\xe8\x55\x21\x2d\x24\xfa\xec\xc4\x77\x4f\xd8\x89\x7b\x06\x04\x62\xc3\x00\x46\x35\x30\x57\xed\xf0\x8d\x58\x2d\x66\xbc\xce\x0b\x72\x18\xde\x46\x85\x53\x61\xc0\xc4\x3b\x69\xac\x21\x6f\x41\x0f\xe1\x64\xb9\xb9\x76\xa2\xc8\x6d\xae\x71\xce\x2d\x1f\x47\xbb\xfa\x00\x4d\xad\x31\xa1\x84\x8f\x39\xad\xae\x56\x6a\x1d\xfc\x8e\xea\x8f\xc7\x3c\xdc\x25\x9d\x52\x0e\x78\xdd\xeb\xab\x3a\x8f\xcd\x4b\xdc\x03\x2c\x3e\xdd\xc0\x27\x2d\x83\x04\x8c\x01\xf0\x2f\xb5\x2a\x53\x90\xa3\x84\x87\x7e\xc7\x96\x3e\x39\xbb\x7c\xfd\xf7\xf3\x57\xa7\x67\x97\xdb\x9d\xbd\xdd\xd9\xdb\x9d\xdd\x63\x67\x0b\x75\xd3\x7b\x57\x7b\xeb\x69\x55\xde\x42\x17\xf2\x35\x2a\xc1\xfb\x8c\xb2\x43\x4f\xd4\xcd\xf7\xdc\x29\xd3\xe4\xd7\xa6\xa0\xeb\x8a\x34\x0e\xba\x01\x55\xf7\xa3\x47\x9f\x1e\xba\xc1\xe4\xce\x01\x93\xe6\x62\xc7\xca\xaa\x59\x8b\xd9\x43\x8f\xfe\x71\x7a\x7c\x72\x76\x79\xfa\xfc\xf4\xe4\xf5\x46\xb3\x9d\x7a\x82\xa1\xa6\xe7\xf2\x9a\xa7\x64\x55\x8b\x1b\xa9\x1b\x53\x2c\x02\x6a\xfb\x6a\x21\xb0\x9c\x30\xab\x72\xf0\x78\x78\x60\xfa\x95\x3f\xdb\x1e\xb6\xc3\x1e\xb6\x69\xf2\x57\x0f\x1c\xac\xa1\x96\xef\xf3\x5a\x97\x03\x2d\xe1\x0b\xf4\xc5\xf8\x60\xdb\xaa\xf5\xb4\x4b\x90\x39\xc9\xd1\x43\xca\x63\x8b\xcf\xe3\xf4\xd1\xb2\xb2\x3d\x68\x74\x06\x01\xd9\x1e\x06\x8f\x1a\x13\xce\x5e\xf2\xea\x3b\xb1\x78\x2d\x7a\xc2\x6d\xa5\xe3\x2d\x0a\x91\xb9\x83\x8e\x5d\x8b\x05\x66\x17\x1f\xf9\x87\xf5\x03\x8d\x7e\x80\x18\xe5\xd7\xa2\x0f\x7e\xfc\x90\xe0\xe2\xd7\xa2\x47\xe6\xb4\xbf\x96\x00\xb0\xdd\x14\x82\x9e\xe6\xe6\xf4\x41\x41\x7e\x7f\x04\x30\xf5\xcf\x37\x8e\x92\x5e\x03\xce\x82\x0f\xdf\x0e\x3c\x13\x18\x49\x5f\x24\x67\x57\x10\x22\x0c\x6b\x9a\x61\x6d\xfa\xd0\x03\x29\x19\x03\x0d\x4d\x5f\x1e\x4e\x86\x53\x38\xac\x5c\xdd\x6d\x05\x2b\xe6\x5c\x04\x40\xc7\xfc\x99\xc7\x00\x31\x81\x3c\x13\xe8\xa8\x47\xe9\x9f\x94\xd6\xf2\xcf\xf0\x61\xc1\xaf\x44\x61\x7e\xdc\xdd\xfd\xea\xbb\x93\xbf\xff\x75\x77\xf7\xa7\x7f\xc6\xdf\xc2\x51\x88\xe1\xed\xf4\x16\x00\x34\x51\x3a\x17\x67\xf0\x0c\xf8\x93\xd4\xb5\x43\x0c\xa1\xd0\x17\x80\x47\x30\xc1\xd4\xbb\xf0\x67\xa5\xf3\xee\x5f\xa6\x17\xf2\xe6\x83\x3c\x18\x60\x8a\x7a\x94\xc7\xe1\x35\xdc\xf1\xd0\xca\x92\x81\xb7\x2a\xb5\x1a\xf8\xa4\xb2\xb9\x28\x11\xfb\xef\xb9\x1f\x02\x20\xf8\xf6\xc0\x27\x0a\xd0\x22\x9c\x66\x9a\xc2\xb0\xee\xdc\x3c\xdd\x79\x50\x07\x4c\x98\xc1\x81\x07\x0c\x46\x84\x46\x0b\x37\x72\x38\x60\x43\x9a\x4b\x20\xa0\x3d\x3c\x3f\x65\x37\x38\xc2\x0f\x66\x70\x7c\x78\xf3\xf9\x47\x95\x71\x21\x88\xda\xad\x4a\x7f\x86\x69\x65\xfe\x7b\x42\x08\x31\x01\x2a\x52\x38\xc3\x66\x0f\x3f\x9c\x64\x55\x33\xa2\x1b\x26\xa5\x28\x75\xbd\x08\x7f\x86\xca\xe4\xb1\xb1\xba\xe6\x33\x28\x0c\xc3\x9f\xe3\xcf\xc2\x5f\xf8\xc3\xe4\x01\xcb\xbf\x46\x53\xb8\x8d\xa5\x92\x44\x5e\x13\xe9\xa6\xbd\x1e\xa0\x6c\xf3\x43\xff\x40\x44\x5b\xd6\x17\xaf\x2c\xbd\xd2\x05\x19\x3c\x71\xa8\x70\x86\x51\x04\x7b\x92\x2a\xe6\x47\x6d\x16\x1b\x78\x03\xd4\x8d\xb3\x2c\xd7\x46\x9a\x6c\xaf\x01\xa5\x59\x2e\x6f\xa4\xd1\x3d\xca\xdf\x42\x43\x77\x67\x3c\x12\x68\x0f\x66\x71\x05\xb7\xd9\xbb\x0a\xc0\xf5\xc2\x7e\xed\x88\xfd\xa7\x7d\x58\xfc\xf0\xaa\xb8\xb5\xa2\x56\xcf\xd8\xff\xec\xbd\xfd\xe3\x2f\xe3\xfd\xaf\xf7\xf6\x7e\x7c\x32\xfe\xaf\x9f\xfe\xb8\xf7\x76\x02\xff\xf8\xc3\xfe\xd7\xfb\xbf\xf8\x3f\xfe\xb8\xbf\xbf\xb7\xf7\xe3\x77\x2f\xbf\xb9\x3c\x3f\xf9\x49\xee\xff\xf2\xa3\x6a\xca\x6b\xfc\xeb\x97\xbd\x1f\xc5\xc9\x4f\x1f\xd8\xc8\xfe\xfe\xd7\xbf\xef\xdd\xf5\x01\xb0\xae\xf1\x1a\x12\xf1\x3a\x6d\x71\x90\xe5\xf7\x11\x69\x5e\xf0\xf2\xcb\x6b\xe8\xfd\xff\xda\x4b\xcd\x28\xab\xc7\x1f\xd7\x0f\x66\x83\x63\x5a\xe8\xa7\xf0\xe4\xe0\x93\xd2\x82\xb1\x60\x5a\x7c\x6e\xe7\xdc\x6f\xc1\xb9\x13\x68\x60\x61\x5e\x5b\x4d\x74\x5a\xeb\xd2\xc3\x52\x40\x78\x03\x0b\x28\xe9\xbe\x6b\xd1\x8b\x4c\x1c\xaf\xad\x33\x68\xeb\x0c\xba\xe3\xfa\x55\x67\x10\x16\x11\x3c\x5c\x4f\x90\x50\x37\xeb\x86\x30\x56\x46\xd0\xbd\xad\x13\x83\x3f\x7e\x58\x40\x6d\xe2\xb7\x7a\xcb\x9f\xdc\x26\xd3\xe0\x81\x56\xae\x8e\x61\xb2\xc3\xa2\x60\x52\xe1\xc6\x87\x06\x42\x2d\x96\x40\xd3\xc6\x17\x11\xdf\xb8\x2e\x84\xaa\xab\x04\x3c\x19\x72\x8b\xa5\x9a\x51\x61\x14\x1e\x25\x14\x7d\x92\xaa\x85\x9d\x0e\xca\x61\xcb\x55\xc0\x8d\xd1\x19\x90\x82\x61\xa5\x55\xc0\xa4\xa4\x6e\x43\x6f\x2c\xbf\x86\x68\x63\x26\x72\xa1\x32\x41\x3c\x06\x09\x57\x34\x57\xec\x44\xdd\x78\x2e\x87\xbc\xc1\x64\x10\x14\x7f\xab\xdb\xf8\xbc\x12\x10\xdc\x42\xa4\x20\x58\x94\x87\x00\x52\x3f\x58\xd8\x1c\x52\x31\xf4\xb4\xf5\xb2\xae\x47\x27\xdb\xfb\x14\xef\x7f\x66\x86\xc8\x56\x2f\x65\x68\xe9\xb0\x6c\xdd\xcf\xe9\x21\xf9\x39\x04\x03\xfb\x1f\x9f\xbf\xb9\xa3\x73\xa0\x63\x73\x98\x23\xf3\x1e\xb1\x93\x21\x8f\xc9\x21\x82\x25\x55\x2d\xa6\xf2\xdd\x40\xfb\xf4\x30\xaa\x27\x94\xb9\x50\x56\x4e\x25\x32\x66\x57\xb5\xa8\x84\x02\x57\x2b\x94\x68\x38\xd9\x4f\x27\x65\x1b\x9c\x7e\x88\xc9\x3c\xa8\x70\x0f\x2b\xca\x2e\x56\x29\xfb\x5b\x39\xc6\xb6\x72\x6c\xed\xeb\x13\xc9\x31\x5a\xb9\x0f\x47\x88\x41\xe6\x79\xff\xec\xf7\xa3\x34\x95\x9d\x58\xdc\xfb\x96\x10\x77\x0a\xf4\x83\x68\xb4\x1a\x93\xd7\xb0\x8e\xad\x66\x58\xb3\x8f\x7a\x13\x2b\xb9\xe2\x33\xa4\xa2\xb0\x3a\x80\x57\xe9\x3a\xd0\x89\x75\xf3\xee\x41\x8f\xf7\x25\x5e\xf0\x65\xad\x8b\x42\xd4\x86\x15\xf2\x5a\xb0\x63\x51\x15\x7a\x51\x52\xee\x6b\xce\x2e\x2c\xb7\x6e\x55\x5f\x08\xbb\x5e\xd8\xb7\x1f\xaa\x8d\xaf\x42\x1f\x08\xfb\x1f\xcb\xda\xa1\x28\x9c\x55\x54\x41\xf9\x4a\x81\xd0\x38\x04\x66\xa3\x11\x3b\x13\x37\xa2\x1e\xb1\xd3\xe9\x99\xb6\xe7\xa8\x7d\xa7\x09\x77\x78\x23\x93\x53\xf6\xcc\xd9\x75\xc6\x32\x8b\xec\x32\x51\x81\xba\xae\x93\x06\x5a\xdc\xc2\x21\xea\xf3\x96\x6b\xcf\xa1\xa5\x50\x79\xbe\x56\x24\xa3\xd7\x34\x05\xfa\xae\xde\x13\x74\x88\xf5\xa4\x2d\x94\x75\xb4\xbe\x11\x57\xc1\x23\xf1\x81\x15\x28\x15\xab\x85\xa9\xb4\x32\x22\x85\x19\x0d\x3d\x42\x6b\x77\x58\x0c\xe3\xb5\x0f\xcf\xbe\xc7\x66\xa5\x8d\x85\x12\xda\x61\x48\xe1\xce\x7d\x73\x50\x91\xcc\x8b\x42\xe4\x09\x2b\x20\xb2\x59\xf1\xd4\x43\x40\x68\x28\x81\xdf\x06\x0b\x95\x93\x1a\xe7\xe4\xfe\xc0\x30\xe9\x39\x9c\x3c\xbd\xf8\x5d\x95\xcd\xed\xc6\x84\x73\x24\x5a\x00\x4b\x80\xe7\x00\x83\x6f\x22\x22\xa8\xb9\xd6\xd7\x2c\xd3\x65\x55\xc0\xd6\xe9\xb1\xb3\x5a\x1e\xba\xb0\x94\xc6\xae\x75\x73\x10\x51\xd4\xc1\x07\xfd\x18\xea\x7a\x29\x62\x43\xa8\x61\xe2\x9d\xc8\x06\xe3\xb0\x3d\x79\x27\xb2\x88\x84\x19\x20\xd9\x32\x8f\x10\xe1\x76\x6c\x7f\x6e\xfd\xde\x21\x87\xa1\xdc\xfc\x3d\x6a\xe9\xe2\xab\x83\x62\x09\x6d\x7a\xb4\x7f\x7a\x04\x10\xa7\x80\x2d\x84\xf5\x75\x31\x8c\x46\x58\x8c\xb8\xf5\x96\xa0\x2f\x43\x22\xb5\x6f\x0b\x28\xd2\xb4\xb6\x6c\x6f\xf7\x60\x77\x7f\xc9\xff\xd8\x81\x8c\xbf\x8c\x7e\x29\x01\xea\xb4\x02\xdc\x50\x91\xed\xe6\x23\x26\xad\xcf\xb4\x46\xb8\x27\xe8\x15\x15\xfd\x8d\x98\xd1\xcc\xd6\x3c\x97\xa4\xc6\xc0\xa7\xee\x26\x5b\x37\x24\xe5\xf7\x76\x7f\xd9\x25\x6a\xaf\x5b\xad\x76\x2d\x74\x7f\xc2\x2e\x11\x27\x26\x34\xb4\xd0\x0d\xe0\x42\xe1\x10\x54\x85\xcc\xa4\x2d\x16\x20\xb1\x98\x6e\x10\x93\xca\x9d\x17\x54\x6c\x78\xf2\x4e\x5a\x4f\xae\xa3\xa7\xec\x09\xb2\xeb\x21\x86\x13\x37\xc0\xb0\x7e\x30\x17\xbc\xb0\x73\x4c\x12\x51\x5a\x8d\x91\x20\xd5\x89\x12\xfa\xa6\x6f\xbc\xa4\x9f\x3b\x31\xbe\x7a\xb8\x16\x97\x3b\xd4\xd3\x72\x70\x42\xf4\x9b\xf5\x59\xdb\xd9\x12\x7a\xdd\xe5\xe5\xf9\x37\x09\x6f\x3b\x48\x71\x6b\x2b\x9f\xba\x03\xde\x00\x51\x4f\x75\x5d\x3e\x00\xd9\x31\x4c\xb0\xb2\x17\x81\x3b\x1b\x50\x84\xf5\x25\x72\x67\xab\xd1\x08\x3f\x9c\xc1\x9d\xfd\x5d\x37\x00\x06\xc2\xaf\x8a\x45\x40\x62\x30\xc2\xb2\x1d\xd7\xd4\x8e\x13\x4f\x6e\x35\x7c\x2b\x78\x8e\x40\x19\xc6\x0a\xbe\x96\xea\x16\x5f\x83\x05\xd1\xa2\xbe\x0d\x7b\x0e\x34\xc6\xea\x92\xcd\xe9\xb5\xd3\xd2\x4b\xda\x19\x13\xd8\x3d\xbe\xae\xa9\x16\x15\x4a\x38\xfa\xcd\x67\x27\xbf\x96\xe4\x06\x8e\x7b\x42\xe2\x91\xc5\xc3\x16\x73\x44\x49\x85\x83\x85\xb8\x33\x03\xc9\xd2\x01\x92\x1f\xd8\x80\x09\x10\xac\x5f\x21\x67\xb7\x21\x08\xea\xf5\xcf\xf5\x1a\x2c\xa7\x82\x0d\x96\x37\xc0\x56\x39\x59\x69\xcd\xa0\xf7\x05\xfd\x39\xe0\x8e\xf1\x31\xd4\x8c\x2b\xad\x64\xc6\x0b\xf9\x6f\x91\x23\x43\x3e\xe6\xcf\x81\x9e\x93\x71\x23\xc6\x10\xd4\x55\x44\xec\x19\x55\x2b\xba\xed\x68\xb5\x06\xe5\x23\x20\x9f\xe1\xf3\xfa\x67\x65\xb0\x61\x73\x02\x58\xff\x82\xd4\xf8\x7a\xff\x30\x0f\xb3\xc4\xd8\x90\x23\x50\x0d\x90\x40\xbe\x9c\x3e\x8e\x60\x55\x50\xe0\x89\x22\x1c\x84\x11\xc2\x6b\x3e\x98\xb3\xcc\xe9\x24\x83\xbe\x3a\xba\xe3\x6b\xa6\x02\xf7\xbc\xc7\x12\x5e\x1e\x90\x28\xff\x81\xa8\xea\xbd\xd3\xd8\x1f\x7a\x5c\xcd\x04\x7b\xea\x7e\xf9\xe7\x3f\xfd\xe9\xcb\x3f\x4d\xb0\xf9\x90\x0b\xa1\xd8\xe9\xe1\xd9\xe1\x3f\x2e\xbe\x3f\x82\x12\xdc\xbe\xa3\x3a\x50\xa2\xe7\xd0\x69\x9e\x83\x26\x79\x7e\xd4\x14\x4f\x28\x2c\xe9\x2d\x45\xd2\x08\x03\x34\x19\xa3\x88\x92\x86\x19\xa1\xf9\x21\xd2\x6d\xec\xae\x75\x5b\xed\x41\xec\x31\x9b\x55\x17\x3a\xbb\x1e\xd0\x7a\x3a\x16\x55\x2d\x32\xf4\xc6\x5d\x1e\x9d\x63\xeb\xce\x8a\x3d\x7b\x75\xd9\x16\x34\x40\xd6\x4f\x0b\xd9\xf7\x2d\xf9\xeb\x9c\xe5\x7b\x2d\x2a\x1b\x1c\x04\x57\x3c\xbb\xbe\xe5\x75\x0e\xfe\x33\x6e\x25\x00\x14\x23\xc2\x60\x2d\x88\x2c\x0e\xd3\x0a\x11\x4a\xcd\x93\x71\xa3\x2c\x47\x37\x85\x77\xba\x82\x63\x0c\x8f\xc0\x29\x97\x05\xf8\x69\x89\x07\x1b\xf3\x8e\xb2\x2a\x38\x0e\x63\xcf\xf9\xd6\xc4\xf3\xd7\x83\x35\xf1\x22\x9e\xee\xfb\x5a\x7b\x7d\xb3\x1f\x1f\xf0\x51\x47\x47\x5c\x9d\x50\xe6\x6f\x8f\xba\x01\xda\x7b\xb8\x47\x5d\x55\x8b\x0b\xab\xd7\xe2\xdd\x60\xcb\xb1\x18\x6c\xec\x8e\x48\xcc\x95\x98\x6a\x27\x84\xef\x0c\xad\xe4\x0d\x6c\x42\xae\xa0\x04\xd1\xfb\xce\x74\x12\x3e\xc1\xbc\xcf\x80\x92\x4f\xf0\xac\x07\x26\xc6\x64\xf5\x8c\xe3\x23\xf7\x76\xa2\x84\xde\x8d\xda\x5a\x0a\xe2\x3b\x87\x0f\x85\xcd\xd0\x3f\x1c\x09\x72\xc0\x27\xa5\xee\x77\x83\x35\x59\xcd\xcd\x1c\xb9\xc0\xc5\x3b\x69\x09\xfd\xf5\x5c\xe7\x5d\x06\xff\x59\xcd\x33\xc1\x2a\x51\x4b\xed\x0e\xa3\x46\xd9\x5c\xdf\x2a\x76\x25\x66\x52\x19\x3f\x14\x00\xd1\x4e\x63\x06\x51\x1f\x69\x02\xfc\xdc\x84\xbd\x4e\x20\x55\xa8\xd8\x29\xd3\xed\xd6\xa4\x3e\x77\xe3\x55\x70\x62\xc1\x38\x21\xac\x7e\x18\xe1\x98\x33\xec\xd7\xba\xbc\xd7\x28\x78\x72\x2e\x0a\xbe\xc0\x9c\xd6\xa9\x54\x60\x39\xd6\x66\x7f\x80\xb8\x16\xb2\xde\xf9\xef\xee\xec\x87\x34\xac\x16\x3c\x9b\xf7\x0b\x31\x6f\x03\x61\x1f\x78\x6d\x03\x61\x7d\x1a\xd9\x06\xc2\xb6\x81\xb0\x5f\xb9\xb6\x81\xb0\x6d\x20\xac\x73\x3d\x58\x2b\x69\x1b\x08\x5b\xfb\xda\x06\xc2\xde\x7f\x6d\x03\x61\x1f\x70\x6d\x03\x61\x1f\x78\x6d\x03\x61\x77\x5f\xdb\x40\x58\xbf\xce\x6c\x03\x61\xdb\x40\x18\x5d\xbf\x3d\xef\xa0\xbf\xb6\x81\xb0\xa5\x46\xb6\x81\xb0\x6d\x20\xec\x83\xaf\x07\x6b\xe2\x6d\x03\x61\x78\x6d\x03\x61\xe9\xf5\xdb\x3a\xea\x7c\x18\xe9\xdc\x19\x94\xfd\xeb\xf3\xce\x21\x74\x21\x33\x8a\x46\xe9\x69\x52\xd3\x85\x8f\x9a\xb4\x7c\x1b\x11\xc4\x89\x2f\x2b\xa2\xb8\x53\x1b\xcd\x5a\x59\xfb\xd5\x93\x13\xaf\xd2\x79\x1b\x0e\x89\xe2\x20\x68\x56\xaf\x5f\x7f\xb7\xb1\xca\xb2\x3e\xc1\x8f\x4f\x13\xf8\x78\x20\x51\xa2\x01\x82\x1d\xdb\x40\xc7\x67\x17\xe8\x18\xc6\x49\x38\x80\x83\xb0\xf7\x51\x41\xf1\xff\xcb\x79\x2d\xcc\x5c\x17\x6b\x2f\xf4\x64\x91\xbf\x94\x4a\x96\x4d\x09\xac\xb7\x6e\x3d\xcb\x9b\x90\x68\x60\x5a\x5a\x7d\x90\xd8\xe8\xab\x8c\xe8\x71\x3d\x2d\x2e\xd4\xa2\x12\xcd\xbd\x69\xb2\x4c\x08\xa0\x85\x8b\x2d\x9c\x2f\x27\xe1\x49\x81\x06\xe4\x69\x3f\x79\xd3\xef\x10\x47\x68\x55\x68\xe5\xcb\x2f\xd6\x6a\x63\x56\x57\xc3\xc8\xe5\x6f\x5e\x9f\x1f\x45\x72\x99\x2b\x2f\x96\xa5\xba\xd1\x05\x8c\x2a\xc7\x9b\x9c\xb2\xb6\x41\x21\xdd\xdf\xec\xe8\x65\x72\x0c\x71\x46\xf4\xd5\xaa\x53\xbf\x99\xd3\x9d\x53\xcf\xd1\x0c\xe6\x12\x11\xfc\x3f\x58\x77\xee\x2d\xdd\xfa\xeb\xb3\xfd\xb7\x03\x03\x88\x1d\x78\xf1\xc1\x06\x78\xe7\x82\xa8\xab\xe8\x08\x8e\x0d\x17\xcf\x6a\x65\x35\xab\x0a\xde\xf2\x52\xc1\x0c\x7c\x0b\xe7\xc6\xd1\x5c\x64\xd7\xaf\x29\x46\xbb\x67\x84\x08\xfa\xe4\x4c\xda\x79\x73\x35\xc9\x74\x79\xe0\xb6\x31\xfe\xdf\x55\xa1\xaf\x0e\x4a\x6e\xac\xa8\x9d\x8a\x49\xc7\xd2\x38\x73\xad\x48\x35\x9b\x94\xf9\xfe\x84\xbd\x55\x58\x5d\xdf\xf2\x60\x46\xd8\x12\xee\xf9\x1e\xe7\xe3\x4a\x38\x89\xa8\xc1\x77\x10\x41\xe8\xb9\xee\x4d\xfa\x00\x35\xf7\x3e\x46\x7a\xc6\xc7\x3f\x7d\x6c\x7c\x2b\xb9\xd8\x00\x4e\x92\xc7\x16\x03\x1f\x2c\x17\x64\x80\xd8\xf7\x03\x8a\x7b\x3f\x18\x75\xf6\xa1\xc4\xba\x1f\x20\xda\xf5\x00\xf1\xed\x21\x62\xdb\xc3\xc5\xb5\x3f\x02\x28\xf4\x63\x8e\x67\x0f\xe8\xf4\x1b\x28\x8e\xfd\x29\x62\xd8\x83\xbc\x75\xdf\xd8\xf5\xa7\x8b\x5b\x0f\xf3\xba\x43\x9a\x1b\x8f\x35\x56\x3d\x80\xf3\x7e\x48\xc7\xfd\x60\x4e\xfb\x8f\x16\x9b\xee\x1f\x97\x7e\x00\x31\xe9\xde\x83\x2c\x95\xb4\x92\x17\xc7\xa2\xe0\x8b\x0b\x91\x69\x95\xaf\x7d\x8e\x75\xb0\x48\xc3\xfe\x31\xd8\x2c\x79\xb0\xd2\x42\x8f\x39\x27\xc8\x75\x67\xb7\x61\x61\x8b\x8f\x72\x90\xda\x02\xf1\x66\xec\xe5\x83\x8c\x5b\xb0\x07\xe3\x2a\xc3\xaa\x97\x21\x27\xf1\x5b\x7d\xcb\xf4\xd4\x0a\xc5\xf6\xa4\xf2\xf3\xb8\x1f\x19\x9b\xad\xdf\x32\x2c\x6b\xf7\xed\xd3\x27\xfe\xe6\xcf\xcf\x21\x09\xae\x57\x63\x3e\xbe\x7f\x98\x1e\xf4\xeb\x0e\x62\xba\x71\xda\x14\xa9\x93\x18\x1d\xc7\xa9\xbc\x79\xda\x82\x46\x3f\x85\x76\xc3\x6e\xe3\x2a\x67\x54\x09\xf7\xf9\x4d\x5a\xef\x8c\x9b\x54\xf5\x0b\x19\x36\xbf\xe6\x4f\xbe\x3c\x3a\xdf\xba\x93\x1f\x96\x53\x66\x43\x59\x2b\x0f\x50\xd1\x7d\xa4\x99\x2a\x5b\x45\xf7\x1e\x57\x54\x1b\xfb\x4d\xcd\x33\x71\x3e\xb8\x8e\xe0\xb7\x13\xcb\x9b\x9a\x93\x00\x0c\x2a\x9f\xdf\x3c\x4a\x88\x1c\x77\x53\xa8\x27\x86\x4a\xdd\x69\x53\x14\x0b\xf4\x39\x24\xd5\xd7\x18\x85\xef\x16\xf3\x82\xe3\x7f\xc5\x53\x5a\xc5\xb2\xaa\x35\x9d\x99\x75\xa3\x94\x93\xc1\x2d\xf3\x1b\x28\x92\x00\x46\xcd\x93\x92\x61\x23\x67\xae\xfb\xee\xfc\x83\x6a\xe2\x36\x35\x31\x69\xd0\xfd\x7a\xaa\xeb\x4c\x5e\x15\x0b\x36\xe7\x45\xa0\xf9\xe1\xec\x5a\x16\x05\x35\x33\x61\x17\xc2\x62\xe0\x02\xcf\xce\x42\xab\x19\x74\x8e\x2b\x4f\x2f\x29\x32\xf7\xdb\xac\x10\x5c\x35\x15\x3e\xcf\x9d\xc4\x0b\xdd\xd4\xfe\x79\x93\x10\xfe\x08\x27\xb0\x92\xc5\x28\x22\xb1\x7b\xef\xc4\xb6\x2e\x1a\xe3\x14\x80\x57\x1e\x7c\x7b\x14\xb7\xe9\xf1\xd1\x4d\x44\x61\x54\xd5\xfa\x46\xe6\x18\x43\xf1\xc3\x06\x74\xd9\x48\x53\x14\xf6\xb3\xd2\x6a\xac\xc4\x8c\x83\xa2\x42\xbb\x08\xe7\x0c\xdb\xc1\xdc\x02\x95\x03\x71\x91\xd3\xf0\x75\x95\x94\xf3\xdf\x48\xa4\x5c\x8e\x46\x8e\xed\x29\xcd\x34\x64\xaa\x36\x4a\x5a\xa4\xf1\x9f\x37\x96\xe5\xfa\x56\xed\x93\xcf\x4a\x1a\xc6\xd9\x95\xb0\x3c\xca\x35\xa5\x03\xce\x30\xa1\xf8\x55\xe1\xe6\x1c\x52\xb1\x2e\x57\x0e\x10\x9b\x0a\x6e\x9b\x5a\xb0\x19\xb7\x62\xa5\x9e\x83\xef\xfb\xfe\xe1\x95\x86\x1c\xac\x53\xd6\x28\x23\x7a\x1e\xef\x83\x29\x47\x7f\xfe\x8f\xf5\x64\x84\x2c\x85\x6e\xec\x27\xb1\xfe\x6e\xe7\x32\x9b\xc7\xca\xac\x2c\x85\x61\xba\xe9\x98\xc5\x4f\xe9\x67\xab\x67\x68\x6b\x02\xae\xba\xd6\x75\x1f\xaf\xf0\x7e\x75\xe1\x18\x5a\x7e\x6f\xc8\x20\x3f\x3e\xbb\xf8\xc7\x8b\xc3\xbf\x9d\xbc\x98\xb0\x13\x9e\xcd\x63\x4c\x0e\xc5\x38\x08\x0d\x10\x14\x73\x7e\x23\x18\x67\x8d\x92\x3f\x37\x14\x56\xde\x0b\xbf\xdd\x1f\x14\x91\x7e\xcd\xd3\xd7\x49\x9b\xb5\x56\xfc\x4a\xd2\x3b\x68\x8d\x32\xb6\xb4\x11\x40\x53\xb3\xa4\x3e\x85\x58\xf6\x02\x4d\x04\x50\xb8\x20\xb1\xfe\xf8\xd5\xc9\x05\x24\xec\x57\x35\x22\x95\x40\x86\x17\x7c\x0f\x2d\x5d\x09\xf7\x0b\xe2\x27\x9e\xb0\x43\xb5\xc0\x2f\x71\x4f\x49\xc3\x0a\x69\xac\x80\x53\x8f\xd4\x36\x1f\x25\xdf\x79\x32\x81\xff\xed\x30\x9e\xe7\xb5\xd3\xeb\x42\xe2\x5a\xb6\x94\x49\x8a\x9a\x9f\xbc\x2a\xa2\x17\x50\xc2\x62\x9e\xda\x4b\x9d\x53\xcf\xe1\x24\x81\x08\x19\x1e\x83\xc6\xd6\xdc\x8a\x99\xcc\x58\x29\xea\x99\x60\x15\xb7\xd9\x9c\x95\x7c\xc1\x32\x5d\xd7\x4d\x85\x6c\x06\x39\xb7\x7c\xc2\x9e\xeb\x9a\x95\x7e\x13\xbb\x35\xef\xce\xe1\x8b\xd5\x99\x03\xed\xce\x8e\xff\x29\x8d\x69\x84\x39\x78\xfa\xe4\x2f\x5f\xfc\xe9\x4f\x9f\x15\x01\x5e\x48\xed\x85\xbc\x97\x88\x00\x8f\xfb\x59\xc0\x59\x47\x42\x44\xa9\x66\x45\xbc\xbe\xd6\x3b\x00\xfa\x5a\x99\x7d\x6d\xcc\x71\xfb\x06\xe7\xeb\x9a\x9a\x83\x10\xf1\xb5\x7d\x18\x88\xbe\xaa\x3d\x07\xbd\x61\x45\xb2\x41\xc7\x8c\xc4\xa7\xe7\x7e\x63\x92\x9e\x53\x76\x68\x6c\xab\x36\x07\x6a\xc4\x9e\xb0\xaf\xd8\x3b\xf6\x15\x18\x5a\x7f\xee\x4b\xf6\xd5\xd7\x04\x1a\x22\xa5\xc9\xd9\xf7\xa7\xe7\x03\x8d\xf8\x0f\x4e\x68\xba\x16\xdd\xa8\x5a\xcd\xae\x24\x29\xf6\xe2\x9d\x15\xb5\x53\x34\x69\x26\x36\x4a\x93\xe6\x3a\xf8\x09\x97\x19\x06\x1e\x4e\xa7\x69\x1a\xd5\xfd\x16\x9a\xfb\xf9\xb7\xda\xd8\x33\x92\x42\x29\xe1\x4f\xdb\x5a\x09\x82\x3f\x11\x63\xee\xdc\x30\xb6\xdd\x60\x86\xe5\x1a\xb2\xba\x30\xc5\x79\x2e\x7b\x24\x6b\x3c\x9c\x65\xdc\x2f\x7e\x9f\xcc\xe7\xfb\x66\xaa\xe3\x4a\x01\x1b\x88\x54\xac\x08\xa3\xab\xd2\x39\x69\x67\xae\x5b\x79\x74\x66\xbc\x47\x3d\x23\xaf\x4d\xf0\x37\xc3\x5a\x72\xfb\x29\xe3\x0a\x8b\x4c\xa6\xa2\xae\x31\x2b\xfd\x6a\xe1\x93\x03\x7b\x4f\x5e\xaf\x9d\x54\xd5\xda\xea\x4c\xf7\x60\x72\x4b\xa3\xdd\xd4\x1c\x0c\x42\x85\x6b\x97\x46\xfe\xcd\xf1\xf9\x88\x5d\x1e\x9d\x03\xbb\xd5\xc5\xd1\xe5\x79\x6a\xb3\xec\x5c\x1e\x9d\xef\x6c\x74\x28\x98\x57\xf8\xc0\x45\xbd\x46\x23\x89\x0b\xca\x69\x93\xe3\x92\x57\xe3\x6b\xb1\x58\xf3\x4c\x1d\xe2\x5c\x1f\x87\x19\x1e\xe4\x85\x70\x98\x4b\x5e\xdd\xbb\xb5\x5a\xf0\x5c\x7e\xa2\x4a\x2f\x9f\x76\x1b\x9e\xb9\xba\xe4\xab\xd4\x37\x22\x47\x2d\xdd\xff\x42\xa8\xbc\xd2\xd2\xe9\x8b\xdb\x3a\xb0\xfb\xff\x7a\x5b\x07\xf6\xc1\xd7\xb6\x0e\x6c\x5b\x07\xb6\x7c\x3d\x98\xc4\xd9\x6d\x1d\xd8\xe7\x15\xc1\xdf\xd6\x81\xdd\xff\xda\x78\xe0\x7e\x5b\x07\xb6\xfa\xda\xd6\x81\x6d\xeb\xc0\x3e\xec\xda\xd6\x81\xdd\xff\x7a\x70\x29\x47\xdb\x3a\xb0\x7b\x5d\xdb\x3a\xb0\xe5\x6b\x5b\x07\x76\xc7\xb5\xad\x03\xbb\xe3\xda\xd6\x81\x2d\x5f\xdb\x3a\xb0\xfb\x5d\xdb\x3a\xb0\x6d\x1d\xd8\x67\x9d\x1e\xcb\xb6\x75\x60\x74\x6d\xeb\xc0\x3e\x8b\x24\x40\xb6\xad\x03\xfb\xa0\x6b\x5b\x07\xb6\xad\x03\x5b\xe7\xda\xd6\x81\x7d\x2e\x4e\x99\x6d\x1d\xd8\xb6\x0e\xec\xb7\xa3\xe8\x6e\xeb\xc0\xb6\x75\x60\xdb\x3a\xb0\x6d\x1d\xd8\x7b\x7b\xb1\xad\x03\xfb\x1c\x4c\xc0\x5a\x18\xf9\x6f\x71\xae\x0b\x99\x2d\x7a\x67\x29\xbe\x26\xe2\x63\x43\xcd\xb2\x0a\xda\x8d\x52\xab\x7a\x54\x9e\x3c\xb0\x82\x9b\xd7\xd1\xc0\xc5\x85\x37\x81\xfc\xf9\x23\x0c\xc1\x83\x28\xbe\xf1\x2f\x78\xb6\x7e\x24\x65\xec\x09\x08\x70\xf8\xd6\xf3\x5b\xf4\x36\x11\xe2\x17\x19\x28\x1f\x7c\x37\xae\x88\x0c\x2b\xc1\xea\x20\xc1\xe4\x9d\x0b\x84\x57\x55\x21\x85\x99\xb0\x8b\x40\xc0\x03\xd2\xcb\x3c\x63\x59\xd5\x8c\x58\x29\x4a\x5d\x2f\x7a\x58\x13\x03\x28\x9c\xc9\xac\x0d\x34\x64\xaf\xb1\x4d\x3f\x0c\xce\x88\xa8\xaa\x62\x81\xca\x54\x5b\x4a\x1a\x46\x4d\x7a\xe1\x92\x83\xba\xd3\xc9\xf2\x90\x36\x31\xc3\xce\xb4\x7d\x4d\x0b\x7e\x63\xb9\xf6\x77\x65\x95\x73\xab\x4b\x99\xad\x23\xb0\x51\xc6\xf6\xcf\x29\x3f\xd2\x65\xd5\x58\x91\x88\x6d\x1c\x2c\xd4\xe4\xa4\x89\x4d\xb8\xfe\xd9\xe0\x99\x56\x53\x39\x23\x55\xfc\x00\x19\xdd\xc7\xe1\x7d\xc6\x11\x8b\xfa\x23\x4c\x05\xcf\x0a\x2e\xd7\x8f\xdb\xa7\xa9\x55\x47\xd0\x16\x54\xe8\xb6\xc9\x55\x90\xa3\x1b\x46\x6b\x14\x12\x97\x24\x6e\x93\x89\xff\x0a\x7f\x3c\xc2\x4c\x5f\x67\x7f\x80\xd2\xb9\x62\x42\xdf\xaa\x56\x3d\x56\x8c\x17\xd5\xfc\xfd\x0a\xb2\xeb\xc8\xf1\x42\xf1\x52\x66\x7e\xc5\x1c\x16\x85\xce\xd0\x20\x4a\x55\x64\xdf\x36\xb6\xe7\x1e\x52\x96\x8d\xe5\x57\x85\x98\xb0\x53\xac\x10\xd2\xaa\x58\xb8\xd5\x64\x84\xf5\x81\x0f\x9a\xfe\xb5\x73\xb0\xfa\x27\x60\xf4\x4c\xbe\x58\xa9\x0d\xc1\x84\x60\x35\x94\x50\x6e\x97\x69\x25\x98\x50\xb6\x5e\xb8\xb9\x3b\xd7\xf9\x85\x9b\xbe\xe4\xee\xde\x45\x52\x3d\x73\x2e\x86\xc8\xb7\xe8\x99\x6b\x31\x4c\x86\x44\xff\xec\x88\xe5\x30\x6f\x54\xb7\x18\x27\x3e\x26\xb3\x5a\xe9\x7c\xb2\x62\x57\x7a\xd5\xe0\x5c\xe7\xee\x80\xab\x45\x4c\x85\x47\xf6\x21\x6c\x90\x92\x5f\x83\x89\xcd\x6d\x7b\xf2\xf1\x1b\x2e\x0b\xb7\x85\x56\xd4\xe3\xf7\x4b\x9c\x18\x40\x35\x18\xba\x18\x8c\xf5\x5d\x41\x43\x16\x73\x31\x60\xee\x2a\xe5\x7a\xe8\x0f\x6c\xe9\xe0\x7d\x01\x6d\x45\xe9\x58\x6e\x4d\x94\xfc\x1d\xd8\xac\xbc\xd4\x8d\xb2\x58\xe1\x85\xe7\x73\x10\xfa\x98\xb4\xf6\xe0\x4e\x5e\x36\x8c\xd8\xe1\xb9\x2f\x81\x39\x1f\x22\x9b\x9c\x5b\x2b\x6a\xf5\x8c\xfd\xcf\xde\xdb\x3f\xfe\x32\xde\xff\x7a\x6f\xef\xc7\x27\xe3\xff\xfa\xe9\x8f\x7b\x6f\x27\xf0\x8f\x3f\xec\x7f\xbd\xff\x8b\xff\xe3\x8f\xfb\xfb\x7b\x7b\x3f\x7e\xf7\xf2\x9b\xcb\xf3\x93\x9f\xe4\xfe\x2f\x3f\xaa\xa6\xbc\xc6\xbf\x7e\xd9\xfb\x51\x9c\xfc\xf4\x81\x8d\xec\xef\x7f\xfd\xfb\xb5\xbb\xdc\xdb\x47\x3d\x9c\x87\x7a\x20\xff\xf4\x47\xf1\x4e\x53\x1e\xe7\x40\x7b\x91\x72\xd0\x97\x76\x23\x79\x90\xde\xb7\x1b\xfd\x29\x09\x86\x48\x68\x47\x1a\xa6\x4b\x69\x9d\x01\xe7\xd4\x1a\x1e\x57\x9e\x75\xcc\x13\x92\x03\x50\x7b\xc9\xa1\x44\x2c\xaa\xda\x8a\xac\x1a\xed\x5d\xb1\x60\x1e\x29\x26\xcb\xaa\x10\xa5\x50\x16\xf6\xf3\xd8\x6b\x82\x60\x2f\x4e\xda\x9e\x64\xa8\xb1\x8b\x77\x99\x10\x39\x3d\x6c\x2b\x3a\x7e\xfd\xda\x8a\x8e\xcf\x51\x74\x18\x91\x35\xb5\xb4\x8b\x23\xad\xac\x78\xb7\x56\x44\x34\x95\x1c\x17\x69\x83\x64\x90\x51\x4e\x2b\x7d\xc7\x74\x85\x15\x9c\x1d\x88\xac\xb9\x6e\x8a\x1c\xca\xb2\x1b\x05\x01\x21\xc4\xdb\x10\x16\xa3\x35\xa0\x10\x82\xb6\xd8\x7d\x88\x8f\xbf\x60\x58\xe8\xe7\x46\xde\xf0\x42\x28\x1b\xfd\xe2\x1c\x22\x0e\xf1\x8f\x3e\x74\xcf\x5b\x6e\xae\xdb\x0d\x2f\xc6\x95\xce\xdb\xfd\x7d\xe0\x5f\x09\x3e\x12\xef\xec\x63\x34\xd2\x41\x7f\x3a\xaf\xe5\x8d\x2c\xc4\x4c\x9c\x98\x8c\x17\x20\xd7\x86\x39\x4a\x0e\xef\x68\x1d\x26\xbe\xd6\x85\x71\x3a\xbf\x13\xe5\x8c\xfb\x90\x1d\x58\xc2\x33\x2e\x15\x22\x5c\x55\xfe\xc7\x06\x63\x7f\xee\x74\xa8\x78\xed\x26\x38\xc4\xf8\xc0\xae\xbe\xd2\xba\xa0\xda\xe5\x62\xd1\xb6\x4f\x55\xfc\x4a\xff\x43\x89\xdb\x7f\xb8\xd6\x0c\x9b\x16\x7c\x16\x42\x7b\xce\xd8\xee\x46\xe7\xdb\xa6\xef\x7c\x01\x28\x0c\x6e\x04\xe3\xc5\x2d\x5f\x98\x36\xd0\x19\x61\xb9\x99\x67\xec\xe9\x3e\x2c\x67\x6e\x58\x68\x23\x67\x5f\xec\x43\xba\xde\xd1\xe1\xf9\x3f\x2e\xfe\x7e\xf1\x8f\xc3\xe3\x97\xa7\x67\xec\x4c\x5b\x81\x67\x5e\x64\xff\x64\xc1\xc1\xe4\x7a\x19\xfc\x7f\x13\x6d\x26\x60\x63\x41\xf6\xb9\xca\xf5\xad\x59\xdb\x0b\x8a\xcb\xcf\x0d\x9e\xe0\x6a\x3d\x37\x0f\xaf\x38\x30\x9c\xf7\x38\x61\x96\x32\xc2\xe3\x46\xe1\x88\xcf\xf3\x83\xbc\xd6\x15\x0e\x82\x0f\x4a\x47\x0e\x92\x24\xec\x15\x57\xb6\xc1\xfc\x4e\xd3\x06\x67\x35\x57\xb6\x8d\xce\xb6\x73\x46\xd4\xea\x93\xde\xd3\xb1\xb9\x83\x7f\x08\x2f\x01\xcf\x87\xc3\x25\x38\xcc\x73\x91\x27\xc3\xff\xd9\xd5\x13\x1d\xf9\x97\x8b\xc2\x5e\xec\xfc\xd5\xc5\xe9\xff\xd3\x59\xc7\x8b\xaa\x5f\x61\xc3\x30\x18\x37\xb5\xae\x06\x9b\xdd\xd7\x84\xa1\xb2\x9d\xdf\x07\x31\xbf\xe1\xb4\x1c\x26\x9d\xf6\x75\xa3\x52\x70\xd2\xb6\x7d\x56\xea\x5c\x4c\xd8\x79\xc8\xeb\x49\xbf\x8d\xa0\xca\x78\x2d\x98\xbb\x45\x59\xc9\x8b\x62\x11\xab\x68\x56\x23\x9e\x48\x82\xb2\x16\x0b\xf2\x29\x2f\xcc\xa6\xa5\x71\x9f\xb3\xd1\xe9\x11\x2f\x9d\xb9\x3c\xc8\x74\x84\xd6\x58\x2e\x94\xb6\xa4\x58\xbb\x5e\x02\x72\x5d\xad\x33\x86\xb6\x79\x54\x3c\x91\x9c\x6f\x06\x73\x8b\xfc\xd1\x28\x8d\x1f\xec\xf3\xd0\x32\x86\x65\x1b\x23\xba\x0a\x3a\x1d\x8d\xad\xb5\xee\x5a\xaf\x05\xcf\x21\x6a\x51\x71\x3b\xc7\xdc\xe7\x92\x9b\x6b\x91\xe3\x07\xa4\x9a\x85\xc0\x09\x38\x7a\xfd\xa3\x2e\x5d\xbf\x7d\x8c\x04\x54\x32\xcc\xc8\x86\xe8\x8a\xc8\x37\x3c\xeb\x3d\x36\xa1\x1b\x94\x57\xaa\x58\xbc\xd6\xda\x3e\x0f\x80\x38\x83\xac\x80\x1f\x48\x5b\x4e\x03\x57\xa0\x4e\x72\x78\xee\x18\x66\x03\x36\x55\x8c\xc5\x73\xdc\xce\xf8\x63\xdf\x52\x75\xa3\x0e\xcd\x37\xb5\x6e\xd6\x3e\xc4\x96\x94\xcd\x6f\x4e\x8f\x41\x14\x35\x94\x5a\xa8\x6c\xbd\x00\x10\xb0\x65\x24\xe7\x60\x18\xbc\xa1\xe4\xc8\x78\x4f\xb4\x79\x6c\xec\x25\x5f\x30\x5e\x18\xed\xc7\x92\xc2\x5a\x5d\x2b\x94\x4c\x5c\xf7\xf5\x95\xb6\xf3\x25\xdb\xd6\x6d\xa8\xe5\xdf\x8d\xa2\x4c\xc3\x36\x1f\x40\xaa\xa5\x9f\x5b\x88\x99\x54\xb5\xc8\x44\x2e\x54\xb6\xe9\x69\xdf\x74\x82\x1e\x2c\x9d\x33\xad\xdc\xc6\x1c\x64\xf1\x9c\x86\xcc\x4c\x1a\xd2\x78\xa9\x40\x50\x8c\xac\x3f\x0e\x99\x9e\xb0\x2d\x1b\x23\x6a\x4c\x4b\xad\x1b\x81\x33\xf9\x5d\x73\x25\x0a\x37\xf2\xce\x24\x05\x1c\x51\x6e\xd1\x9d\x21\x4b\x3e\x13\x8c\xdb\xb0\xd2\xac\x66\x42\x99\xa6\xa6\x49\x94\x96\xe5\x5a\xb4\x38\x5a\xdc\xb0\x37\xa7\xc7\xec\x09\xdb\x73\xcf\xda\x87\xf5\x33\xe5\xb2\x80\x24\x50\x48\x2a\xe9\xd8\xa8\x53\xdf\x04\x74\x09\x16\x2f\xd3\x35\x0a\x89\x11\x53\x9a\x99\x26\x9b\xfb\x3e\x39\xbb\xd7\x9b\xcd\x54\xb8\x04\x91\x97\x87\xb9\xd6\x37\x2b\xa1\xde\x18\x51\x0f\x26\xa0\xde\xac\x21\xa0\x62\x35\xca\xad\xb9\x74\xf4\x70\x61\x95\xc2\xf2\x9c\x5b\x4e\x82\xcb\xdf\xf0\x60\xa7\xf4\xb7\x2d\xbe\x8c\x78\x21\x55\xf3\x0e\x0b\x05\x86\x73\xb5\x5c\x9c\x40\xb3\x2c\xf3\xa3\x0e\xb3\x8e\xc9\x77\xb9\xf7\xa6\x44\x49\x32\xa7\xc9\x5a\x19\xdd\xa1\x26\x82\x9c\xe0\x98\x0c\x23\x9c\x72\xc2\x55\xae\xcb\xa5\x87\x39\x25\x52\x24\x1c\x08\x13\xb6\x5d\x7d\xe9\xf5\x40\x9c\x42\x85\xb8\x11\x3d\x50\x82\xbb\x9c\x0f\xae\x35\x37\x38\x7e\x45\x40\xf3\xac\xe0\x57\xa2\xa0\x44\x2d\x4c\xff\x5c\x5e\x81\x9b\xae\x1e\xab\x75\x31\x5c\xb9\xfb\x6b\x5d\x08\x2c\xc7\xf0\x03\xe1\x9a\x7f\x14\xe3\x00\x8d\x0c\x35\x0e\x60\x0d\x26\xe3\x00\x76\xed\x63\x18\x87\xa6\xc7\x51\xcf\xba\xe3\xe0\xf4\x86\x74\x1c\xe0\xf0\x7e\xe8\xe3\x60\x44\x96\xe9\xb2\x3a\xaf\xb5\x33\x3b\x07\x3b\x9b\xa8\xd9\x36\x66\x88\x8e\x8d\x15\xa9\x9b\x70\x16\xa4\x37\xf3\x3a\x2a\xc4\xe2\x16\x0f\x09\x5f\x8d\xf5\xff\x8b\xce\x2c\x10\x3d\xdd\x83\xcc\xb7\x92\x84\x17\xdd\x2f\xe9\x8b\xc7\x7c\x1c\x0c\x51\xcb\xdc\xc3\xd9\x39\xc8\x69\xa4\x33\x5e\x00\x0b\x44\xbf\x25\xc7\xba\xcb\xae\xdb\x70\x54\x7e\x07\x31\x4a\xf8\x2c\xca\x34\xe6\xe0\x68\xf1\x2e\x4c\xa5\x73\x11\xc5\xb2\x31\x7b\xf1\x12\xcb\xb4\xe0\x3e\x5f\xf9\xe7\xf4\x0a\x1f\x56\xce\x93\x5f\x5b\x4d\x58\xc6\x2f\x03\xb7\x84\xeb\xa0\x50\xb9\x54\x33\xf0\xab\x8d\x58\x2d\x0a\xac\x19\x24\x21\x70\x8d\x16\xe4\x2e\x6c\x09\xdf\xa8\xdf\x0f\xfe\xd1\x3e\x31\x99\x5a\x8e\xb3\x8d\xe5\x14\xc5\xad\x34\x6c\xe7\x85\x1f\x80\x1e\x60\xfc\x0f\xf1\x84\xd9\xc1\x37\x0c\xb3\x89\x9e\xce\x6b\xa9\x72\x2a\xaf\x4b\x06\x2b\xb0\x39\xa1\x1e\x0c\x85\x9b\x32\x8f\x65\xcb\x33\xf6\x56\xb1\x30\x58\x6c\xbc\xf6\xf2\x78\x8d\x2a\xb3\xf7\xd1\x8d\xdf\xef\x78\x0d\x0f\xe9\x36\xf3\x46\xc1\xdc\xbb\xe7\x8e\x9d\xe5\xbe\x7c\x9f\x7f\x97\x8d\x02\x7a\x92\xf4\x1b\xda\x8a\xf9\x01\x9b\xf5\x2a\x7d\xe6\x96\xb5\x95\x6a\x66\x62\x4b\x86\x17\x45\xe2\x0c\x5f\x65\xca\xf8\x19\x0e\xdc\x5d\xcb\x26\x44\xa7\x2c\xf8\xb1\x98\x21\x85\x53\x27\x1e\xb9\x11\x32\x2b\x0d\x3f\xaa\xdd\x48\x58\xc9\x8b\x8b\x6a\x7d\xb2\x01\xb6\x04\x6c\xfd\xf2\xe2\x30\x6d\x1a\x0e\x6b\xca\x49\x17\xf0\x3d\xe3\x79\x29\x8d\x01\x47\x98\xb8\x9a\x6b\x7d\xcd\xf6\xde\xcb\xb9\x36\x36\x72\x66\x0e\x68\xcd\x8f\x5d\xef\xf7\x99\x54\x45\xc8\x8a\x02\x3b\x58\xd9\x90\x06\x0f\x0f\xc9\x42\x2f\x60\x0e\x89\x81\x86\x92\x15\x96\xbb\x89\x9c\x33\x6e\x15\x6c\x5c\x60\x2f\x4f\x4f\xbf\x52\xc2\x5f\x9d\xa2\x33\x5a\xdb\x5d\xbc\xe5\x95\xe3\x88\xda\xe3\xc6\x07\x89\x94\x8b\x4c\x98\xe1\x60\x5e\xbf\x6d\xdb\x64\xb9\xc0\xaa\x7b\x01\xd9\x4f\xfc\xce\x24\x3b\xf0\x4b\xef\x02\x78\x0b\xfd\x74\x37\xd6\xa8\xd3\x6a\x25\x28\x86\x1a\xa3\x91\xee\x24\x1a\x88\x40\xaf\x42\xcc\xb5\xd2\x54\x23\xe7\x0e\x51\xad\x60\x49\x83\x88\xc2\x68\x1e\xcc\x09\x89\xe8\xa8\xab\x47\x6d\x94\x38\x0e\x04\x02\xf8\x83\x0d\x24\x89\xd8\x87\x5b\x69\xe7\xc0\xd8\x30\xef\x44\x0d\xa1\x27\xb5\x30\x10\x80\x51\x4c\xd4\xb5\xae\x29\x21\xcb\xfb\xad\xa9\x54\xeb\x5c\xe7\x90\xd1\xe5\x16\x09\x77\x7f\xed\x9a\x38\x50\xdd\x92\x3a\x05\x0c\x4e\x31\x9d\x8a\x0c\x14\xad\x78\x80\x51\x6a\xef\xb5\x14\x16\x54\x84\xe0\x16\x18\x91\x42\x95\xf2\x9d\x7b\x4a\xfc\xab\x38\x24\x4e\xd4\x11\xab\xbf\xde\x9f\x30\x76\xaa\x42\x06\xef\xc8\xcd\x62\x7c\xa7\x4f\x3d\xb3\xee\x15\x63\x46\x31\x78\x81\xd8\x71\xe6\xb4\xc3\xba\x19\x60\xc5\xf7\x71\x87\xb3\xd8\x25\x3e\xa8\x38\x00\xd7\x38\x35\xea\xa6\xde\xeb\x00\x7d\x5c\xe5\xee\x96\x8f\xe5\x2e\x7f\x1c\x01\x10\xd6\x57\xce\x11\xfa\xd9\x40\x34\x4f\x17\x51\x6b\x91\xf6\x1e\x02\x6e\xe7\x3a\x47\xf4\xc3\x80\xde\x56\x2c\x3c\x1a\x63\xa8\x89\x8e\x74\x3c\xa5\xb1\x78\x20\x86\x45\x24\x72\x9c\x9c\x39\x55\xbb\xf0\xbe\x85\xb2\x2a\x04\xa0\xae\x44\x2d\xb7\x80\x32\x11\x2f\xd4\xa8\xad\x60\x0b\xd4\x52\x04\xc6\x38\x62\xff\x82\x4d\x19\x12\x51\x3d\x4e\xdc\x79\xf8\x39\x5a\x88\xd2\x78\x92\x38\x28\x4e\xb5\xda\xbb\x2e\x58\x2e\xa7\x50\x27\x69\xe9\x91\x15\xaf\x79\xe9\x44\xbc\x61\x34\x04\x57\x62\x26\x31\x21\x32\x08\xb6\x5d\xa7\xee\x11\x36\xc7\x08\x85\xa1\xb4\xac\x94\xb3\x39\x2e\x14\xc6\x01\x51\x87\xf9\xa0\x62\xa1\x79\x0e\xe4\xb2\x4c\xd7\xec\x96\xd7\xa5\x3b\x37\x78\x36\x87\x08\x25\x57\x2c\x6f\x6a\xe0\x4b\xb1\x82\xe7\x8b\xb1\xb1\xdc\x3a\x4d\x59\xd4\x64\x50\xfa\xfe\x6f\xc9\xb1\xde\x7b\x6d\xc9\xb1\x3e\xf0\xda\x92\x63\x6d\xc9\xb1\x96\xaf\x07\x93\x1d\xba\x25\xc7\xfa\xbc\x60\x4d\xb7\xe4\x58\xf7\xbf\x36\x8e\x66\xba\x25\xc7\x5a\x7d\x6d\xc9\xb1\xb6\xe4\x58\x1f\x76\x6d\xc9\xb1\xee\x7f\x3d\x38\x1c\xe6\x2d\x39\xd6\xbd\xae\x2d\x39\xd6\xf2\xb5\x25\xc7\xba\xe3\xda\x92\x63\xdd\x71\x6d\xc9\xb1\x96\xaf\x2d\x39\xd6\xfd\xae\x2d\x39\xd6\x96\x1c\xeb\xb3\xe6\x0c\x60\x5b\x72\x2c\xba\xb6\xe4\x58\x9f\x05\x32\x3a\xdb\x92\x63\x7d\xd0\xb5\x25\xc7\xda\x92\x63\xad\x73\x6d\xc9\xb1\x3e\x17\xa7\xcc\x96\x1c\x6b\x4b\x8e\xf5\xdb\x51\x74\xb7\xe4\x58\x5b\x72\xac\x2d\x39\xd6\x96\x1c\xeb\xbd\xbd\xd8\x92\x63\x7d\x0e\x26\xa0\xb1\xb9\x5c\x0b\x1b\xf4\x43\x60\x8c\x28\x3d\x3d\x42\x0d\xb8\x6a\xa6\x53\x51\x83\xe4\x82\x27\x2f\xa5\x55\xb5\x88\x8d\xdd\x50\xae\xb0\x23\x40\x44\xa2\x4a\x9e\x3b\x7e\x4e\x30\x05\x80\xe1\xd9\xe6\x90\x9f\xbc\x7a\xbe\x02\x33\x69\xed\x7c\xc3\x75\xb3\xa7\xa1\xcf\xaf\xd4\x7a\x51\xf8\x3b\x06\x7c\x55\x65\x19\x8d\x7b\x56\x68\x43\xb9\xef\x30\x58\xd9\x9c\x2b\x25\xbc\xbd\x27\x2d\xf8\x51\xae\x84\x50\x4c\x57\x82\x62\xe0\x9c\x19\xa9\x66\x85\x60\xdc\x5a\x9e\xcd\x27\xee\x49\xca\x0f\x76\x9b\xa7\x4e\x9f\x18\x5b\x0b\x5e\xfa\x8c\xfd\x92\x4b\x6c\x8a\xf1\xac\xd6\xc6\xb0\xb2\x29\xac\xac\x42\x63\xcc\x08\x28\xb5\xc1\x83\x2a\x0c\x06\xe4\xcb\xb5\xc9\xed\xa3\xf6\x69\xd4\x2d\x1d\x83\xd6\x81\xb5\x39\x02\x20\xf1\xb2\xb2\x8b\x90\xe1\x2b\xd8\x54\xd6\xc6\xb2\xac\x90\x70\x5a\xc3\x13\xb1\xaa\x1a\xda\x1b\xf9\xb3\x5a\x51\x4f\x0d\x75\x55\xe5\xa0\xb6\x56\xd6\x60\xbe\x6c\xdb\x20\x35\x95\x4b\x43\x6a\xbe\x19\x31\xee\x11\xd5\x70\xa0\x7d\x4f\x61\xa8\xfd\xc9\x82\xad\xd3\x47\x51\x73\x11\x92\x6c\x9b\x50\xdc\x2e\x74\x28\x7e\xf0\x8b\x73\x94\xd4\x79\xb4\x0a\x05\xf1\x65\x74\xb6\x01\x4c\x80\x12\x37\x6e\x0d\x88\x4c\xb8\xf3\x95\xdf\xb1\xea\x3f\xf9\xa2\x8f\x0e\xc5\x97\xc2\x18\x3e\x13\xe7\x6b\x06\x1a\xee\xb2\xc8\x20\xd6\xd0\x4e\x0c\x2c\x85\x22\xe1\x24\x8b\xf3\x36\x53\x35\x88\x95\xd8\xa7\xa0\xfc\xdc\xd6\xd2\x5a\x01\x93\x0a\xd8\x7b\x10\x11\xed\x96\xe6\xef\x76\xb2\x3f\x5f\xfa\x46\xda\x1f\x3b\xa1\xae\x72\xcc\xc5\xbc\x12\xec\xaa\x96\x62\xca\xa6\x12\x12\x3c\x21\xe5\x72\x84\x50\x4c\x1c\xbd\x00\xc6\x38\x7b\x57\x2b\xaf\xcb\xfa\x7e\x4d\xd8\x0f\xd4\x31\x5b\x37\x2a\xe3\x11\xca\x2d\xd4\x9e\xca\x29\x9b\x41\xca\x26\x69\x8b\xff\xf1\xe4\xbf\xfe\xcc\xae\x16\xee\x48\x03\xcd\xca\x6a\xcb\x8b\xf0\x92\x85\x50\x33\x37\x56\xb8\x3d\xd3\xea\xc9\x30\x02\x40\x03\x82\x1d\x7f\xfa\xc5\xf5\x55\x7a\xc6\x1e\xe4\xe2\xe6\x20\x1a\xbf\x71\xa1\x67\xab\x88\xb3\xd6\x4f\xe6\x5e\xd3\x24\x5a\xb1\xcc\x86\x61\x7c\xf4\x98\x60\x6c\xae\x6f\x51\xd7\x5f\xb1\x7a\xda\x42\xac\x4a\x57\x4d\x81\x4e\xe7\xe7\xa1\xee\xb8\x31\x62\xb9\x3a\x70\xe5\xbe\x00\x37\x29\x35\xd1\x45\x54\xc7\x4c\x5d\xff\x48\x4d\x55\x27\xe4\xc8\x0b\xd0\x60\x60\x08\x3d\xe7\x45\x71\xc5\xb3\xeb\x4b\xfd\x42\xcf\xcc\x2b\x75\x52\xd7\xba\x4e\xfb\x52\x70\x27\x2d\xe7\x8d\xba\x46\xea\x87\x00\x9e\xa0\x67\x14\xca\xf5\x25\x0e\xab\x5e\x18\x2b\xe9\xbd\x10\xf6\x66\x50\xdb\x8a\x78\x27\x5b\x5b\x87\x8a\xb8\x70\x45\xc6\xed\x9b\x78\xb1\x7d\xf1\xe4\x3f\xfe\x82\x4b\x97\xe9\x9a\xfd\xe5\x09\x64\x73\x9b\x11\x6e\x62\x90\x6d\xee\xa0\x28\x79\x51\x38\xb3\x21\x5e\x94\x6e\xa0\x57\x2d\xc2\x4f\xbe\x06\x6d\xff\xe5\xf6\xc1\xaa\xd4\xe5\xe5\xdf\x41\x8f\x92\xd6\x88\x62\x3a\xc2\x7a\xa5\x60\xd6\xec\xc2\xc1\xb0\x4b\xd2\x07\x8a\xc6\x1e\x80\x02\x74\xa3\x8b\xa6\x14\xc7\xe2\x46\x0e\xc1\xee\x97\xb4\xe6\x4d\xfd\x42\x1a\x28\x0d\xbb\x2a\x74\x76\xcd\x72\xfa\x32\xca\x6f\xe9\x62\x84\x3f\x5e\xa2\xd6\xf8\xfd\x93\xdc\x9e\x92\x57\x55\xa8\x1e\xaa\xf9\x6d\x32\x18\xb0\x27\x01\xc8\xe0\xf1\x13\xb5\xe2\x1b\x39\xb9\xb9\x76\x13\x6b\x27\x04\xf5\xf7\x51\xb7\xbd\x1f\x88\x8e\xaf\x6d\xd0\xef\x86\x0a\xfe\x8d\xf5\x26\x4b\xf5\x92\xa1\xe4\x2e\x2c\x0c\x54\x00\xdc\xf2\x01\x91\xbc\x31\x42\x51\xd6\x3b\xb1\x29\x19\x17\xf5\x1e\x4e\x3b\xce\x2a\x51\x1b\x69\xdc\xb9\xfc\x3d\x6c\x28\x24\x33\x6c\x5d\x80\x9b\x19\x04\xdc\xdc\x00\xac\xdc\x5f\x52\x9e\xeb\x9c\x1a\x04\x51\x88\xa0\xd2\x2b\xd4\xda\x54\xab\x1d\xf0\x40\xdd\xb4\xa8\xfc\xbe\x1d\xcd\x54\x52\xba\x4f\x82\xa8\xc4\xbb\x3e\x27\x01\x09\xef\xf7\x58\xe5\x63\xe8\xfc\x40\x62\x00\x04\x23\x4d\x6e\x2a\x09\x13\xe3\x11\x37\x4a\xa4\xd2\x93\x1d\x38\x61\x18\x05\x77\x7b\x82\x7e\xca\x76\x9f\xed\x6e\x54\x48\xe2\x10\xd5\xba\xe2\xb3\x5e\x2c\x3f\x9d\x91\xea\x36\x1b\x43\x50\x38\x33\x08\xbe\x0f\x80\x6c\x70\x97\xc8\x5b\x84\x1d\xc0\x4f\xc2\xe8\xa8\x1f\x60\x32\x10\xb0\x52\xfb\x96\x2f\x18\xaf\x75\xa3\x72\xf2\x2f\x05\x07\xdf\xcb\xce\x83\xcf\xb4\x12\x2d\x6b\x68\x8a\x60\x01\x1e\x7d\xa9\xd8\xd3\xc9\xd3\x27\x9f\xcb\x49\x05\x6f\xd8\x39\xa9\xce\xc2\x49\x85\xf2\x69\xa3\xef\xea\xb1\xf0\x07\x7a\xdf\x97\xe4\x62\x69\xa1\xee\xa5\x07\xd2\x86\x8f\x6e\x6b\x69\x45\x44\x0e\xb8\x07\x86\x8b\xb3\x0f\x23\xbc\x86\xfd\x55\x1c\x13\x3d\x07\xa9\x1f\x40\x86\x69\xae\x3e\xa2\xdc\x22\x01\x05\xdb\x6d\x95\x87\xcb\xbc\x47\x84\xc5\x03\xb5\xb3\xc3\xf6\xf0\xce\x5d\x2c\x75\xde\xdf\xe8\xd2\xa2\x41\x3b\x79\x57\xf5\x40\xdf\xec\x54\xd5\x57\x1c\x7c\x70\xd5\x80\x23\xf8\x37\x31\xe7\x37\x02\x4a\xbc\x65\xc1\xeb\x02\x62\x8e\x17\xd8\x77\x76\xd5\x58\x26\xd4\x8d\xac\xb5\x2a\x85\xb2\x0c\x72\xe0\xaf\x0a\x11\x73\x63\xff\x7e\xef\xfb\xc3\xd7\x90\xd0\xb0\x4f\x60\x15\xd4\xcb\xc6\x78\x60\x9b\xb8\x27\x51\x73\xbf\x3a\x7d\xbe\x1f\x6e\x0c\x41\xe6\xfa\x7e\xb9\xe7\x94\x8d\x6d\x90\xb0\xe5\x5d\x56\x34\x46\xde\x6c\x4a\x92\x50\xed\xfd\xb1\x5c\x6b\x9e\x3b\x38\x00\xed\x40\x2d\x95\xf4\x83\x6b\x7d\x45\x19\xe0\x52\xc0\x64\xd7\x84\xd2\xc0\x38\x06\x4e\xae\x27\x42\xd9\xc0\xf4\x39\x8f\xc5\xb8\xa4\x42\x00\xa2\xcc\x66\x9d\x50\x4a\xe7\xe2\xfe\x78\x3c\x69\x7a\x0f\x35\x81\x31\xf3\xa8\x4e\xd0\x64\x73\x91\x37\x05\xb1\x79\x03\x6c\xaa\x33\x1f\x78\x8b\xcf\xa7\x80\x3f\xe8\x74\x1a\xc0\x0e\xd4\x18\x9c\x83\x38\xe6\xfe\xf7\xb5\x87\x46\xf0\x1f\x98\x4e\x8b\x60\x94\xba\xb6\x46\x8c\x1b\xd3\x94\xb8\x25\x90\x1a\x61\x2a\xad\x69\xc9\xc2\x49\x3b\x76\x1b\xe3\x9e\x65\x5b\x3d\xc6\xf7\x42\x14\xb0\xb8\x7a\x8c\xf1\xee\x59\xd4\x0e\x0e\xb4\xf1\x7f\xd1\x82\xa3\x84\x09\x88\xb6\x85\x3c\x4e\x0d\x5e\xd2\xa9\x04\x7a\x25\x4e\xe3\x7d\xb1\xe2\x97\xa8\x3a\xe0\x1d\x00\x1c\xc3\xaf\x44\x61\xba\x0d\x5d\xb5\x93\x42\x78\xa5\x34\xf0\x3d\xf9\x73\xb9\x31\x72\xa6\x80\x59\xd3\xb5\x76\x4f\x0e\xcd\xb5\x6d\xa6\x21\xf8\x71\xd7\x96\x6a\x49\x16\x56\xc9\x2b\x22\x62\xe7\x56\x97\x32\xbb\x47\x4b\xfa\x9e\x5d\xee\x54\x64\x27\x95\xbe\xaf\x2e\x96\x3c\x3e\x26\xf2\x6a\x4c\xd8\x85\x2e\x29\xc5\x49\x45\xfc\x5e\x9e\x66\xd5\x9d\x18\xb5\x70\x63\x01\x89\x47\xb2\x8d\xc6\x03\x1f\x8e\xaf\xb5\x86\xe7\x04\x95\x9c\xc2\xb8\x00\x4c\x49\x34\xaf\xba\x28\xf4\x2d\x24\x16\x63\xbb\x7e\x6d\x43\x0a\xcc\x33\x36\xee\x70\xd6\x4e\x52\x38\xd1\xf7\x3f\x87\xee\x1d\xfd\xfa\x53\x30\x3f\x07\x80\xfa\x4e\x8f\xe3\x3f\x4f\xcf\x8f\xe2\x3f\xdf\x18\x37\x4a\xf4\x41\xb7\x6b\x29\x5f\xc3\xdd\x77\xc5\xc8\xd9\x77\xdd\x35\x45\xca\xa3\x5f\xf9\xfa\x68\xce\x95\x0f\x64\xdd\xf9\xbc\x85\xc9\x6c\xd1\x76\x67\xce\x6b\x41\xc8\x72\x4e\x92\x9b\x8a\x67\x77\xf6\x22\xc0\xb8\xbd\xf7\x86\xf7\xf6\xd4\x34\x95\x67\xea\x2e\xe0\xc6\xd0\x93\x76\xd9\xfd\xf8\x87\x9f\x3e\x70\x30\x7f\xed\x37\xab\x86\xf6\xfd\xbf\x49\x08\xfd\x3e\xe8\x17\xab\xe9\xbe\x3e\xec\xb7\x11\x63\xde\x07\xdd\x7f\x17\x5b\xef\x87\x3e\xcd\xb3\xbc\x7d\xd8\x8b\x75\x67\xfb\x03\x6e\x87\x29\xbd\x1f\x26\xc2\xda\x22\x7c\x5d\x77\xd7\x1a\x4e\xaa\xf5\x9d\x53\xeb\x19\xfb\x1d\x05\xe0\x0e\x90\x53\x02\x60\x53\x33\x96\xc0\x4a\x35\x75\x2d\x14\xf0\xe5\x37\x90\xe9\xe8\x79\xf0\x51\x48\x83\xb0\x25\x08\x4f\xc4\xa1\x67\x87\xe1\x2c\xa4\x0c\xb8\x92\x03\xac\x67\x04\x63\x3d\x6d\x20\xa1\x11\x44\x3f\xc2\xd4\x69\xe5\xfa\xf1\x6c\x15\x0e\x87\xae\x84\x8a\x58\xf0\x49\x6b\x1e\xbb\x35\x94\x20\x73\xa0\x22\x30\x29\xf3\xdf\x55\x05\xb7\x53\x5d\x97\x63\xaf\x1e\x8e\x13\x25\x81\x1d\x41\x6a\x8d\xf1\xf6\x15\xe6\xb7\x22\xdc\xa6\xca\x0b\x11\x9d\xe6\xe1\x55\x55\x8e\xe0\x54\xac\x51\xb5\xc8\xf4\x4c\x41\xe5\x31\x7d\x0b\xe7\x5a\x70\x0e\x71\xe3\x4e\x52\xa6\x9a\xa2\xb8\x7f\x1e\xc2\x9a\x4a\x80\xbe\x11\xf5\x5c\xf0\x7b\x2e\xde\x4e\x4a\x0b\xb5\xd1\xb2\x92\x1a\x42\x2e\x20\x95\xd7\x3f\xc4\xa9\xc6\x3a\x83\xda\x36\x0c\xb1\xfb\xc4\x65\x0e\x07\xba\xd3\xf4\x38\x9b\xc9\x1b\xa1\x3c\x18\xf9\x51\xc1\x03\xb3\xb6\xc7\x5f\x25\x40\xf4\xc6\xea\x90\xb4\xc0\xb8\x8d\x20\x91\x21\xc7\x89\xe2\xa5\x71\x3b\xd1\x2d\xc4\xcb\x5d\x78\x0e\xb4\x0f\xb9\x13\xf2\x06\x90\x14\x72\xd4\xbe\x52\xe9\x7d\xab\x09\xe6\x26\xcb\x20\xbb\xc5\x9b\x22\x94\xd5\xf2\xeb\x8f\xa0\x94\x34\x27\x83\x56\x35\x43\xea\x72\x00\x87\x6d\x07\xb6\x70\xe2\x7f\x81\x4a\xce\xe9\x34\x7d\x92\x4c\xe0\xf8\xa1\xf6\x09\xd4\xef\xd6\x1e\x3c\xd7\xb9\xd3\xc2\x46\x2c\x4c\x65\x4c\x4b\x4e\xf1\x16\xdc\x93\xd1\x66\x44\x25\xad\xae\x85\xa9\x34\xb2\x02\xc4\x8f\x1d\x45\xfe\x2f\x69\x93\x64\x3b\xe4\x77\x0b\x5b\x03\x71\xdb\xfe\x2d\x6a\xbd\x52\x87\x9f\x49\x3b\xb9\xfe\x0b\x28\xf0\x42\xcd\xb9\xca\xd0\x76\x3a\xb8\x16\x95\x39\x30\x72\x86\xfa\xfa\x9f\xff\xf2\x17\x50\xde\xfd\x90\x1c\xbc\x3e\x39\x3c\x7e\x79\x32\x29\xf3\x47\xa4\xc9\x57\xdc\x5a\x51\xab\x67\xec\x7f\xf6\xde\xfe\xf1\x97\xf1\xfe\xd7\x7b\x7b\x3f\x3e\x19\xff\xd7\x4f\x7f\xdc\x7b\x3b\x81\x7f\xfc\x61\xff\xeb\xfd\x5f\xfc\x1f\x7f\xdc\xdf\xdf\xdb\xfb\xf1\xbb\x97\xdf\x5c\x9e\x9f\xfc\x24\xf7\x7f\xf9\x51\x35\xe5\x35\xfe\xf5\xcb\xde\x8f\xe2\xe4\xa7\x0f\x6c\x64\x7f\xff\xeb\xdf\xdf\xb3\xa3\x6b\xd6\xa5\xf4\xad\x45\xe9\x55\x7f\x32\x60\xcd\x49\x55\x0b\x51\x82\xf8\x5b\x27\x5b\x2b\xf5\x92\x76\x9a\xf2\x07\x2c\xfd\xe5\x64\xa2\x7f\x9a\x9a\x39\x31\x69\x50\x74\x16\xfa\x16\x32\x2c\xa5\x76\xca\xcf\x84\xbd\x82\x73\x90\x9d\x89\x1b\x51\x8f\x7c\xab\x2f\xdc\x4d\xe7\xe1\x9e\xd8\x0d\xb7\xea\x8e\x35\x73\xfc\xd7\x9c\x13\xdf\xf7\x1e\x83\x87\x8c\x26\xd4\x79\x90\x4f\x13\xf6\x3d\xaf\xa5\x6e\x0c\xe9\x22\x31\x10\x38\xa6\x90\x85\x93\x04\xbc\x12\x14\xe0\x09\x8d\x84\xca\x30\x1f\xe3\x09\x63\x73\x18\xe4\xf5\xd1\xea\x23\x41\x5a\x37\x53\x37\xfe\x51\xb5\x4f\x75\x5d\xc2\x10\xc7\xc3\x60\xa5\xfc\xf7\x27\x9a\x89\x3b\x0a\xcd\xf8\x7e\x80\x6c\x3d\x23\x64\x13\xc1\xe6\x72\xe6\x13\xaa\xe1\xfd\xd1\x7c\x8d\x3e\x0d\x2b\x64\x8d\x29\x5d\x67\x9b\xae\x9b\xd7\x5f\x75\xdf\xaf\xc7\xb2\x48\x91\x96\x63\xb0\x66\x5f\x51\xd4\xee\x9b\x1d\x5c\x27\x70\x88\x8c\xb3\x5a\x5a\x99\xf1\x62\x07\x0e\x27\xff\x55\x56\x34\x4e\x4f\x8c\xbf\xad\x05\xb3\xb7\x1a\x9f\xc2\x0b\x76\x2d\x16\xb7\xba\xce\xfd\xf9\xec\x9f\xd8\xce\x85\xb1\xfe\x91\x52\xd0\x06\x46\x37\x43\x5d\x8a\x9a\x5d\x09\xef\x41\xef\xdc\xbc\x98\xb0\x43\xb5\xa0\xf0\xa3\x8a\x8b\x0c\x23\xfc\x37\xd0\x11\x50\x8b\x4a\x16\x09\x1d\x62\xfe\x69\xdc\x12\x20\xce\x6a\xef\xb2\x53\xc0\xc2\x2e\xf0\xa7\xbf\x77\x2f\xeb\x9a\xaa\x9c\x60\x77\xd4\x58\xa3\xa5\xfd\xd7\x9f\x44\x5a\x38\xfd\x46\x2a\x61\xcc\x37\x6e\x2a\xfb\xa8\xab\xe9\xea\xe0\xa0\x96\x50\xdb\x50\x29\xd5\xa6\x14\x0b\xb7\xa5\x30\x46\xec\xc4\xb0\xce\xdb\x3b\x27\xec\x10\x3e\x80\x9c\x78\xa7\x79\x41\x15\x9d\x6b\x4c\x5a\xd3\xa5\x9d\xc7\x3b\x0e\xcf\x8e\x7d\xee\x32\x6a\x0a\x26\x05\x52\x47\x95\x39\xed\x09\x68\x7a\x94\x41\x2b\x7e\x6e\x38\x30\xe8\xee\x5c\xd6\x8d\xd8\x59\x4f\x55\x42\x88\xfe\x83\x3f\xfd\xe5\x09\x68\x4b\xe1\x79\x63\x78\xde\x3a\xaa\xd2\xfd\x73\x64\xd6\xca\x8e\xe9\x26\x06\xbd\x8e\xd7\x83\x1f\x70\x6f\x77\x50\xd0\x0a\x6a\x7b\x61\x9a\xc2\x98\xaf\xe5\x5a\x5d\x2b\x17\x66\xfd\x2c\x98\x71\xdb\xdd\xcb\xfb\xb3\x9b\xf5\x49\x60\x49\x9e\x3b\x44\x94\xab\x6d\x0d\x67\xc5\xe0\x94\x84\xe7\x44\x9e\x5d\x24\xc1\xa0\x8f\x21\x1d\x16\x04\x17\x44\x05\x40\x3c\x2e\xaa\x1e\xa9\xbf\x6b\xc8\x1b\x34\x5e\x21\xad\xae\x97\x7f\xfb\x75\xd2\x12\x49\x6e\x7f\x54\x74\xbe\x0c\x35\xe4\x94\x30\xed\x6b\x73\x00\x7c\x2a\xa0\xc6\x78\x98\x7f\xe0\x43\x09\x94\x1f\x50\x99\x83\x5a\x81\xef\xbc\x89\x92\x23\x73\xc1\xf8\x0d\x97\x05\xf2\xa0\x38\x93\x4e\x9b\xc4\xc9\x8e\x1d\xca\xb4\x32\x4d\x09\xcf\x28\xdd\xe9\x82\x67\xc6\x5b\xd5\xd6\xa4\x2a\x24\x61\x79\x6f\x55\xaa\xeb\xe1\xf1\x42\xf1\x52\x66\xfe\x0d\x0f\x0b\x4f\xfc\xd6\xa9\x4b\xf5\x6d\x07\x37\xb9\x2c\xcb\xc6\xba\x6e\xde\x13\xd5\x74\xc3\xf2\x28\x9a\xc8\x38\x6e\x2e\xde\xf1\xcc\x16\x0b\x70\x54\xa5\x37\xd9\x79\xad\x9b\xd9\x9c\x71\x06\x7f\x5f\xc0\x57\x13\x76\x6a\x9d\x2d\x09\x64\xed\x04\xd7\x20\x2d\x9e\xdf\x8d\x92\x3f\x37\xa2\x58\x30\x09\x7c\x42\x21\x66\x92\x36\x1b\xa1\xc7\x03\xd3\x4c\xc4\x6e\x83\x5a\x80\x10\xb9\x87\x3c\x20\xd3\xfe\x8e\xce\xa3\xdd\x0e\xda\x83\x3b\xf0\xf9\xfd\x93\x78\x36\x24\x3f\xd7\xc8\xfe\xeb\x23\x36\xd7\xcd\xa4\x5a\xc6\x62\x5b\x3d\xc3\x32\x0a\x1f\x67\xdd\x39\x06\x53\xa5\x4d\xc0\x02\xa2\xc6\xe3\xb3\x8b\x7f\xbc\x38\xfc\xdb\xc9\x8b\x4f\x5e\x4b\x82\xbd\xec\x3d\x18\xb8\x17\xa2\x9c\x57\xe2\x3f\x8b\x4c\xb6\x64\xcd\xae\xff\x9e\x1b\x23\xe1\x48\x0e\x98\x3e\x7c\x44\x29\x8f\x73\xb7\xd5\xae\xc3\x9e\x77\x36\x3b\x19\x09\x74\x0e\x03\xa8\xa5\x0a\xf1\x37\xde\xa6\x39\xf4\x2b\xfb\xef\x91\x61\x95\x8c\xd3\xa5\x28\x2b\x67\x1f\x0f\x36\x5e\xe9\xe9\x1c\x37\xff\x2b\x03\xe7\x6f\xfd\xf0\x01\xc4\x83\x4e\x30\xeb\x7f\x19\x27\xed\x40\xde\x29\x3a\x7b\x39\x53\xe2\x36\x7d\x98\x4f\xe9\xf1\xbf\xb8\xd2\x8d\x22\x4e\x7c\xdf\xf8\x0f\x88\xe2\x41\x39\x29\x80\x10\x5e\x08\xeb\xad\xbb\x74\xce\xa9\xda\x1c\x89\xa2\xe8\x3e\x54\x1c\xe2\xb0\xce\x8a\xdf\x5c\x09\xf6\x15\x40\x9c\xf0\x52\xfc\x75\xfc\x55\x10\x4a\xf0\xf7\x88\x36\x69\xe7\xe3\xd6\xa1\x95\x9e\x91\x13\x74\x62\x40\x8e\x3f\xf1\xa3\x69\x95\x38\xc0\xbd\x59\x2a\x43\x3e\x80\x53\x89\x14\xa8\x45\x9e\x4c\xd2\x59\xb2\xf0\x73\x8a\x1e\xa4\x9d\xde\x13\x93\xd9\x84\x59\xad\x01\x9a\x04\xb1\xd6\x0f\x15\x13\xef\xa4\x01\x8b\xb9\xfb\x8a\xb1\xa1\x4c\xe9\x3b\xf8\x08\x7d\xab\x52\xa0\x10\x2c\x5d\xa6\x94\x29\x43\x16\x62\x94\xa6\xc2\x6f\xb4\xf4\xa9\x71\x5c\x41\xf0\x07\x23\x15\x61\x70\xae\x16\xac\x94\x06\x48\x72\x00\x4f\x31\x6f\x0a\xbc\x39\x47\x24\x12\x84\x27\x43\x57\x83\x9b\x5b\x28\x86\x4a\x2a\xb3\xdb\x46\x3b\x0a\x80\x3b\x2e\x4a\x7d\x23\xf2\xf7\x29\x57\xc4\x8d\x02\xe5\xf5\xb3\xae\xa6\x18\x4a\x2c\x12\xef\x7e\xf2\x94\xa8\x20\xad\xd6\x05\xab\x0a\xae\x04\xd5\xe8\x07\x8f\xc4\xb2\x9c\x5e\x17\xa7\x7e\x98\x1c\x17\x67\x56\x40\xa2\xcb\xb5\x58\xdc\x5b\x6c\xaf\xa1\x56\x2c\x3f\x1c\xdf\xa3\xe4\xd5\xfd\x4c\x11\xb7\x18\x7a\xbb\x9a\x77\x5f\x63\x43\xac\x6a\x7d\xcb\x4b\xc5\xd4\x21\xd9\x14\xa4\x0a\x79\x95\x0f\x01\x99\x62\xc4\x5e\xa9\xe7\x58\xaa\x3b\x42\x47\xf3\x84\x9d\x2a\x66\x74\x49\x25\xc2\xef\xac\x19\x21\x19\x23\x67\xa6\xb9\x32\x82\xd8\xee\x9c\xa1\x41\x11\x4f\x0a\xe9\x56\xa2\x2e\xa5\x8d\x53\x7b\xdd\x92\xc3\xc7\x0c\x8a\x79\x72\xf0\x3b\x1a\xbd\x31\xbe\xf4\x3a\x1e\x8e\xfb\xdb\x8e\x51\x18\xac\xa7\x2b\x73\xf7\x75\xa7\xad\xc4\x8e\x4e\xc2\x7c\xe9\x41\x04\x29\x71\xe8\x0b\x62\xb3\x5a\x37\x95\x3f\x43\x52\xbe\xe6\x96\xa4\xd0\x1f\x24\xe8\x1f\x4c\x9b\x0e\x42\x0b\xac\x71\xd1\x1e\x8c\xb9\xd3\x47\x8d\x19\xad\x94\x8b\x75\xa3\x3c\xb7\xb1\x00\x1f\x62\x94\x58\xb9\x53\x88\x19\xcf\x16\x3b\xe9\x73\x56\xa5\xb1\xa2\xc9\x29\x4b\xe4\x85\xc2\xe7\xb5\x05\xda\x50\xc7\x0d\x26\x35\x3a\x0e\xd0\x4e\x32\xd4\x45\xef\xbf\xf4\x08\x23\x18\xa6\xaf\x7b\x84\x19\xff\xf4\x97\x3f\x8d\x7d\x22\x01\x74\xe5\x93\x2c\xa8\x90\x86\x3a\xa8\x63\x3c\x99\x33\xa7\x09\x48\x53\xc1\xfc\xc2\x49\xd7\xfa\x26\xc3\xd3\xdf\xe7\x3b\x5e\xdd\x88\x9f\x80\xb6\x89\x4f\x38\x5c\x52\xcd\xfa\x3a\x8b\x77\x2e\xd2\xa6\x68\x35\xea\x8a\xff\xdc\xb4\x45\xdb\x24\xdb\x50\x61\x88\x86\x98\x06\x05\xaa\x98\xdb\x3e\xb5\xd2\xd5\x4d\xc7\x72\xfb\x6e\x80\xa3\x9d\x12\x06\xd7\x58\xbe\xf0\xbb\x3b\xed\x16\x68\x0b\x56\x84\x72\xa5\x36\x6b\x39\x6c\x47\x6e\x9d\xda\xd9\xcd\x89\x16\x41\x31\xed\xbe\x67\xe6\xde\x32\x62\xe6\xe7\x16\xfd\xa8\x70\xb2\x53\x8e\x05\x62\xd3\x00\xcd\x24\x68\x1b\x24\xfa\x9d\x0a\x70\xcb\xeb\xdc\xa4\x6e\x23\x82\x32\x23\xd7\x0f\x45\xcd\xbc\x16\x71\xae\xf3\xb6\x07\xc1\xb5\x9b\x3a\x8a\x1e\x91\x33\x28\x1d\x4d\x78\xfd\x36\xf3\x05\x24\xf7\x39\xaa\x89\xb3\x86\xd7\x39\x84\x0c\xda\x85\xb0\xf5\xb1\xac\xba\x86\xf3\xb1\x78\xb6\xa7\x76\x43\xa2\x1f\xf2\x04\xb0\x9e\xd2\x4f\x23\x32\x66\x4e\xce\x19\x34\x0e\xd6\xe6\x39\xff\x2d\x2b\xb2\x9d\x54\xcd\x3e\x6a\x51\x97\x75\x78\xae\x8b\x1c\x14\x18\xe2\x06\xf7\x8f\x72\x82\xaf\x96\x57\x8d\xa5\x5c\xbc\x4c\x97\x65\x0a\xcc\x85\xe1\x79\x33\x61\x2d\x32\x53\x9c\x27\x01\x92\x78\xc2\xd8\x85\x10\x30\x77\x71\x3f\x40\x83\xf6\x47\x1c\x1d\x02\x7a\xca\x84\x5b\x48\xb8\x40\x3e\x51\xee\xd1\xfa\x1b\x8b\x32\xb6\x7b\xa6\x86\xee\x1c\x86\x50\x78\x9c\x58\x8d\x8a\x27\x9e\x8b\xbc\xaa\x0a\x89\x75\xfc\x1d\x9b\x03\x6a\xd6\xdb\xd4\x7e\x2a\x61\x73\x63\x41\xe1\x0d\xd8\xae\xdf\x35\x57\xa2\xc0\x64\x34\xb4\x58\x31\x01\xee\xd6\x35\x31\x97\x15\xee\x6a\x6e\xc3\xcf\xc1\xb7\xd1\x35\xdb\x9f\xb9\x13\xe9\x29\xba\x3a\xf4\x2d\xa4\x1e\x7e\x73\x7a\x1c\x74\x17\x77\xd7\xf3\x0b\xcc\x1b\xff\x02\xef\x32\xc2\xce\x64\xce\xae\xb0\x3a\xc8\x9d\x84\x7b\x4a\xdc\x22\xde\x00\x39\x6c\x42\xf0\xf6\xc6\xd7\xe1\x63\x6b\xe1\xe1\xd4\xe4\x3e\xfb\x12\xdb\x04\xe3\x07\x53\x3f\xae\x24\xd5\x23\xbf\x7a\xbd\xeb\x73\x22\x6f\xc7\xf5\xed\x78\x3c\x1e\x53\x11\x01\x68\xcf\xa3\x64\x0c\xc2\xa9\x5e\xea\x5c\x4e\x17\x9d\x91\x00\x0f\x42\x78\x04\xac\x48\xae\x16\xd4\xbb\x09\x3b\xd3\x56\x78\x0c\x8d\xe0\x18\x68\x39\x93\xdd\x2b\x42\x2c\x1b\x52\xad\xb5\x99\x78\x4f\x8b\x4f\xd3\xbd\xbf\x05\xdf\x2f\xe7\xab\x0f\xe6\xe7\x8a\x7a\x84\xbe\x49\xd0\xab\x4a\x1c\x7c\x48\x2f\x10\xf4\xe9\x29\x2e\x52\x80\x68\xb8\x63\x62\xfc\x39\x44\xab\x86\x42\x7b\x98\x0a\x22\xde\x55\x1a\x49\xad\xc0\xcd\x7f\xae\xf3\xe5\x1c\x58\x54\xb6\xaa\x0a\x2b\x39\x93\x5d\x43\x86\x1e\xa6\x5d\xfb\x41\x60\x57\xdc\x35\x19\xba\xb3\xd7\x59\x27\xfb\x10\x79\x82\xa6\xe1\xbc\x53\x9a\x89\xe9\xd4\x59\x94\x5a\x31\x51\xcd\x45\x29\x6a\x5e\xa4\x0f\x22\x28\xb8\x67\x4e\xdc\xd6\x6e\x95\x62\x9e\x69\xc9\x2b\x94\xb6\x20\x3c\x73\x59\x03\xa4\xae\x4c\xf2\xbf\x77\x5e\xa9\xd7\x5a\xdb\x97\xd2\x80\x4d\x49\x19\x37\xe8\x01\xd8\x59\x65\x68\xf8\xef\xda\xba\xfa\xbe\x2b\xf9\x93\x25\x59\x33\xf4\x09\x1c\x0e\x22\x6b\x9d\x04\x71\x42\x2b\x18\xee\x4e\x99\xb6\xf5\xa2\xd2\x52\xd9\x65\xb4\x9c\x00\xb2\xfc\x86\x90\xa2\xc1\x10\xf6\x87\x56\x48\xf8\x63\x2f\xf9\x22\xb8\x84\x29\x8f\xb9\x73\xc6\xa2\x6b\x80\xbe\x03\x0c\xb7\xee\x21\xec\xa6\xf0\x1c\x90\x83\xe3\x8f\x47\x51\xf6\x70\x92\xf0\xd2\xfd\xb9\xe5\xd7\xc2\xb0\xaa\x16\x99\xc8\x21\xfc\x88\x3e\x55\x6e\x13\x48\xf6\x9e\x93\xfe\x88\xa4\x17\x2c\x99\x33\x0d\xfb\xa4\xe7\xa2\x39\x8d\x72\xe0\x08\x3d\xa9\x5d\x22\xa0\xe3\xba\xb5\xc4\x21\xe8\xac\xd5\x18\x08\xc4\x1b\xe3\xb3\xe3\x6b\x9f\x57\x98\x1c\x40\xe4\xb5\xc7\x63\x13\xea\x88\x9d\x95\xe8\x57\x98\x53\x9d\x94\x69\x6a\x11\xca\x60\x73\x2d\x5a\x32\x71\x6e\xd8\x9b\xd3\x63\xf6\x84\xed\x41\x09\x78\x80\x01\x0c\x89\x0c\xdd\x3a\xe5\xa9\x6f\x22\x75\x29\x11\xea\xa8\xd2\x28\x8b\xba\x91\x04\x74\x35\x42\x9a\x5d\xfe\x20\xd7\xf8\xba\xeb\x71\x3d\xa0\x87\x50\x4a\x35\x80\x0c\x7a\xb3\x86\x0c\x8a\x15\x6b\xb7\xbc\xd2\xb1\xc2\x35\x54\x0a\xcb\x01\xd1\x16\x65\x93\xbf\xe1\x41\xce\xde\x6f\x5d\x42\xa5\xd5\x90\x03\x2c\xaa\x8b\x13\x68\xd0\x87\x13\x48\x8d\x47\xdb\x21\x5f\xb6\x1d\xbc\x2c\xf8\x15\xa0\x04\x1f\xf0\x0c\x20\x94\x35\x57\xb9\x2e\x97\x9e\xe6\x66\x13\x8c\xb7\x68\x36\xb7\xcb\xee\xae\xab\x57\xfe\x44\xbf\xec\x09\xb0\xf1\x07\xc0\x57\x7b\x01\xbe\x02\x69\xc2\x4a\x40\xe7\x01\x20\x0f\x2c\x99\xad\xbd\xe1\x37\x7b\x27\x43\xd4\xba\x58\x33\xeb\x21\xcd\x11\xd1\x05\x21\x65\xf8\xd7\x76\x0d\x3f\xd8\xb7\xb6\x6b\xe6\xa2\x76\xc5\xcb\xa2\xea\xbc\x35\xb8\x73\x1e\xea\x5b\x37\x6b\x9d\xd2\xac\xfb\xd6\x50\x37\x9d\xbc\x35\x9c\xbb\x0f\xf1\xad\xd3\x32\xf9\x01\x0e\x13\x6a\x90\x69\x2a\xd6\x27\xba\xca\x2e\x92\x6e\x5b\x86\x0b\x4e\xa8\xc7\x25\x47\xfb\x60\x2d\x62\x35\xdd\xa7\x16\xdd\x3a\xe3\x05\x20\x5a\xac\x3b\xcf\xac\x3b\xd7\xdd\x26\xa3\x8a\x1f\xee\x7a\x0b\x9f\x45\x75\xab\x1c\x61\xc0\x75\x1b\x28\xef\x04\xc5\xc9\x4d\x47\xbf\xf4\x69\x95\xee\xfc\x6d\xcb\x68\xe3\x5f\x5b\x0d\x28\x4e\x2d\xdd\x20\x87\x0e\x0a\x4c\x9b\xa9\xb8\x9d\x8f\x18\xa4\xea\xc8\x9b\x90\x5a\x73\x8d\xa6\xd4\x6e\x52\x9b\xeb\x57\xac\x7f\xb4\xcf\x98\xa6\x96\xe3\x80\x9c\x9c\xa2\xfc\x92\x86\xed\xbc\xf0\x03\xb0\xf3\x98\x05\xf4\x0e\xbe\x4f\x98\x3b\xf4\x62\x5d\x4b\x95\x13\xb5\x4e\x32\x34\xa1\x0e\x1c\x75\x43\xef\x61\xf2\x7b\x9d\xd7\x02\x9c\xbd\x61\x68\xd8\x78\xed\xc5\x40\x29\x0a\x3e\x51\x65\x7c\x87\x92\xe9\x7d\x2a\xfe\x21\xdd\x66\xde\x28\x98\x69\x05\x20\x1b\x4a\xaf\xb8\xcf\xbf\xcb\x7a\x49\x52\x7d\x44\xef\x12\x1a\x4a\x4f\xf1\x7b\x18\x62\xe3\x33\x04\x57\x89\x54\x78\x1b\x48\x4f\xc8\x2e\x04\x1b\x52\xaa\x8e\xea\x3d\x82\xd9\xa1\xa2\xea\xa5\xd3\x09\x6b\xf8\x4a\x5e\x2f\xd8\x37\xa7\xc7\x04\xda\x43\x8e\xce\xbd\x38\x06\xbf\x8f\x51\x6a\x8c\x44\x94\xa2\xbc\x42\xef\xa7\x59\x2e\x64\x4f\x20\xd1\x42\x3e\x5f\x23\xf3\xf7\x18\xb4\x5d\xf3\x43\xe9\x18\x03\xc2\xbf\x7b\x0d\xc8\x10\x64\xc0\xa8\xc5\x6a\xad\xfd\xa3\xf4\x10\x79\xe0\xac\xdb\x2b\xe8\xcc\x95\x37\x62\xc4\xc4\x8d\x50\x94\x55\xb9\x80\x3b\xdc\xd9\x26\x55\x56\x34\xb9\x7f\x1c\x70\x1c\x18\xbb\xb1\xe3\x70\x3d\xe4\xe5\xb5\x71\x97\xfb\x32\x5a\xf5\x32\xa2\x11\x09\xa9\xe7\x8e\xbb\x20\x3c\xa5\xb9\x2e\x72\xc6\xc3\xf6\x0b\xa9\xc8\xb9\x7f\xce\x52\xba\x2a\xe4\xe0\x52\x4a\x55\xa3\x5a\xb0\x16\x7f\xff\x5e\x57\x61\xf2\x12\x6f\x9f\x20\x06\xbd\xdf\xae\xe0\x8d\xca\xe6\xbf\x95\x25\xb3\x62\xf4\x43\x20\x88\xb3\x6b\x51\x2b\x51\xb0\x8a\xd7\xbc\x14\x40\x73\xe3\x1d\x08\x9f\xbe\x52\xa1\x1f\x1e\x77\x0f\x2c\xed\x31\x3a\x37\x36\x50\x5c\xd1\x07\xdb\x78\x65\xc6\x08\xf7\x5d\x42\xae\xc6\xb5\xa6\x91\x0d\x51\x0e\x01\x23\x3a\xc8\xab\x21\xcb\xe5\xc3\x78\xb7\x14\x3e\x6f\x00\xdb\xef\x07\x6c\xb0\xc5\xf9\xf4\x79\x1e\xf7\x75\x26\x7a\x85\x72\x19\x5d\x7f\xd7\x2c\x39\xea\x52\x2a\xd2\x4f\x1c\x49\x58\x5b\xee\x02\x14\xd7\xa3\xf2\xff\xcd\x4a\xc3\x8f\x6a\x01\x35\x72\xbc\xb8\xa8\x44\x36\x80\xfd\xf1\xcd\xcb\x8b\xc3\xb4\x51\x38\x94\xb0\xf0\x6c\x2e\xe0\xfb\x08\xb5\xe3\x56\x5c\xcd\xb5\xbe\x66\x7b\x2b\x90\xc7\xa2\x64\x29\x23\x67\xe6\x80\x96\xf7\xd8\xf5\x7b\x9f\x49\x05\x14\x51\xe1\x50\x0d\xd4\x5a\xfe\x21\x59\xe8\x05\xcc\x15\x65\x5a\xd3\x31\xbc\xdc\xcd\xb3\x5e\x09\x69\xbd\x65\xd2\xf2\x64\xac\x5f\x9d\xf5\x2b\x13\x72\x17\x02\xdd\xca\x51\x43\x77\xcf\x46\x86\x84\x9c\x11\x4e\x03\x1f\x60\x1c\xbe\x6d\x5b\x8b\x19\x0d\xe4\x34\x21\x5b\x6c\xcd\xc8\x10\xca\xdd\x05\xd2\x77\xfa\xe9\x6e\x6c\x76\xa4\x35\x41\x50\xcf\x4d\x89\x73\x88\xc8\xe7\xf3\x4b\xae\x04\x9b\x6b\xa5\x6b\x42\x1a\x69\xb1\x74\x40\xcc\x60\x12\x2f\xcc\x00\xc9\xdb\xa8\xab\x51\xd9\xb1\x4f\xe3\x9d\x16\x7c\x06\xa4\xd1\x1d\x40\x1c\x10\xae\xba\xc1\x98\x6f\x7c\xb3\x2f\x07\xf3\x84\xa8\xc0\xc7\x66\x50\x8a\xf9\x50\x2f\x25\x54\x43\x8e\xcc\xa1\xeb\xf7\x14\xd3\x6b\x77\x13\x18\x8e\x36\x8f\x33\x54\xe9\x05\x83\x28\x19\x60\x94\xbc\x7b\x32\x94\x7e\x45\x15\xf6\x94\x07\x5a\xca\x77\xee\x29\xf1\xaf\x62\xc0\x0f\x28\xab\x52\xe3\xd5\x5f\xef\x4f\x18\x3b\x6d\xed\xda\x91\x9b\xc5\xf8\xce\x88\xac\x54\xc1\x17\x67\x88\xd8\x81\x2f\x10\xc7\xa1\x88\x77\xb4\xcf\xfa\x5e\x9f\x2d\x20\x04\x92\x07\xda\xea\x10\x50\xa6\xe6\xdc\x44\xfb\xe3\xbb\x4f\x80\x19\x6c\xe3\x01\x82\xcc\xcb\x67\xf4\x27\x3f\xda\x3f\xa5\x0c\x33\xa2\xbe\x91\x99\x38\xcc\x32\xdd\xa8\x5e\x39\xba\xc7\xc2\xbd\x02\xb7\x22\xbf\x48\xda\xc4\x78\x44\x0e\xdf\x62\x4a\x3c\x2f\x24\x47\xa4\xef\xf4\x4e\x2c\x11\x6d\xdb\x81\x78\x46\xa7\x87\xb4\x64\x8c\x15\x7c\xbd\x7c\xdb\x9e\x23\xd4\xb7\xc0\x6b\xf9\x8d\x57\x9d\x70\x9d\x11\xa4\x50\xc6\x52\xf1\xd6\x87\x55\xce\x59\x6e\xae\x5b\xfc\x73\x01\x48\x40\x61\x33\x45\x9f\xd3\x8b\x8e\x39\x3e\x75\x2d\x4c\xf4\x35\x46\xd7\x3a\xb9\xe7\x5e\xfe\xd0\x3c\xff\xef\xe3\xb3\x7e\xf5\x4e\x81\xfa\x19\x21\x66\xe6\xd4\x74\x50\xd5\x63\x64\xcc\x18\x21\xcc\x3d\x79\xc4\x6a\x4e\xac\x96\x1c\x85\x50\x21\x38\xfa\x54\xd8\x5e\x54\x5f\xb6\x0f\x75\x90\x6d\x2e\x01\x8a\xfa\x11\xce\x4b\x29\xb8\x32\x11\x0a\x9c\x80\xa6\xbd\x53\x2f\xf4\x07\x0f\x42\x9a\x6d\xf2\x1e\xec\x79\x97\x74\x7a\x87\xb1\x75\x93\x59\xd6\x58\xe3\x3e\xc7\x87\x7b\x81\xf9\x01\x8f\xaf\xc5\x4c\x1a\x5b\x13\x60\x9e\x6b\xb0\xed\x04\x79\x85\xc2\x2d\xd7\x62\xc1\xbe\xfd\xee\xe4\xef\xff\x78\xf1\xea\xe8\xf0\xc5\x3f\x5e\x1e\x1e\x7d\x7b\x7a\x76\xf2\xf6\xed\xc5\xdf\x2f\x2e\x4f\x5e\xbe\x7d\x7b\x84\x20\xbf\x84\x88\x77\x21\xec\xdb\xb7\xb4\x52\xcd\xdb\xb7\x97\x59\x25\xab\xb7\x6f\xcf\xbd\x0f\x04\x49\x4f\xff\xfb\xf8\x0c\xe4\x27\x02\x33\x85\xa4\x30\x38\x5b\x71\xd0\xa1\xdf\x73\x6e\xda\x14\xd4\xa4\x4a\x74\x0d\xa2\x9c\x75\x8f\xbb\x95\xa8\xe4\xbd\x36\xfb\x1c\x9c\xc1\x9e\xad\xdc\x7b\x69\x5b\xc0\x80\x2b\x61\x6f\x05\x21\x89\xad\xc4\xc1\xe7\xdd\x72\x7f\x4a\x4b\x5f\xc1\x88\xec\x91\x7e\x6e\xa4\xb8\x45\xd8\x57\x39\x53\xbc\x88\x68\xb9\x01\x59\x10\xd1\xe5\x96\xd1\xf6\x41\x49\xaa\x74\x1e\x28\xc8\x3b\x5e\xfb\x25\x8f\x7d\x52\xfc\x89\x7c\x0a\x22\x67\xe7\xa7\xc7\xec\xe9\x04\x95\x9c\xd3\x63\xa4\x77\x59\x09\xf6\xee\x2d\x55\x77\xa0\xe2\xe9\xbb\xa2\x26\xa3\x5d\x00\xeb\x08\xa3\x35\x56\x40\x73\x95\xeb\x92\xcb\x7b\x52\x94\xfd\x4a\xd5\xe5\xb4\x29\x8a\x05\xfb\xb9\xe1\x05\xea\x00\xe7\x3a\x5f\x96\x4c\x3b\x5f\xf9\x8f\xfe\x3a\xf9\x2a\xf4\xe3\xaf\x93\x80\xc0\x00\xc3\xf6\xd7\x89\xb9\xc9\x26\x5f\x11\x46\x21\xa3\x9b\x56\x66\x50\x2f\xd5\xe8\x92\x3e\x8b\xbf\x81\x67\x73\xd0\x77\x3f\x49\x91\x66\x44\xcf\xfc\x4d\xcd\x33\x71\x2e\x6a\x09\x2a\x93\x56\x79\x9f\x92\x4d\xbf\x64\x58\xee\x51\xbb\xa5\x62\x06\x9b\x0d\x43\xa0\x84\xc8\x51\x49\xa4\x5e\x08\x36\x73\x9d\x80\x89\x41\x2d\x10\xa0\x31\xb2\x5a\x70\x4c\xc4\x27\x9c\x0c\x0f\xc5\x3c\x21\xf7\x99\x0f\x0e\x3b\x8d\x5f\x89\x19\x86\x78\x29\x8e\x80\x61\x64\x94\xb2\x08\x9f\x18\x62\x9b\xc6\xea\x8a\xc9\xb2\x14\xb9\x53\x80\x8a\x05\xbb\x91\x1c\x25\x3f\x54\x7a\xe2\x3e\xdd\x53\x9a\x69\xf0\xc6\x37\x4a\x92\x73\x6e\xde\x58\x96\xeb\x5b\xb5\xdf\x12\xf0\xe3\x03\x9c\xb5\x22\x8b\x51\x52\xf6\x0c\xaf\xc4\x2a\x18\xd8\x14\x6d\xc4\xeb\x4b\xd0\xc3\xe4\x36\xd2\x3d\x56\x0d\x1e\x82\x3b\x20\xa8\xa8\x97\x20\x1e\xc1\xbb\x05\x0d\xc0\x90\x93\x50\x96\xf1\x84\x82\x9b\x5e\xca\xcb\x12\xcc\xcb\x43\x29\x16\x37\xe8\x7e\x3d\xd5\x75\x26\xaf\x8a\x05\x9b\xf3\xa2\xa5\xe3\x8e\xc7\x06\xac\xc8\xf8\xf5\x0b\xad\x66\xf1\x41\x8d\xd0\xec\x50\x9f\x2e\xb8\x6a\x2a\x7c\x9e\x3b\xdf\x16\xba\xb9\xc3\x60\xf8\xf2\x89\x7f\xd5\x0d\x80\xa5\xde\x2b\x6c\x64\x75\x21\x70\x7e\xfa\xec\x94\x95\xd5\xe0\xbb\x26\x6e\x7d\x9d\x81\xd8\x44\xcd\xed\xa5\x47\x5e\x71\x2b\xe2\x32\xf4\x1f\x2c\x0d\x6b\x39\x94\xa3\xbb\xdd\x8e\xdf\x40\x2d\xe0\x82\xb9\x53\x8b\x90\xd5\x62\x5c\x03\x5b\xcb\xaa\x10\xec\xab\x6b\xb1\x18\x21\xa6\x2e\x2a\x21\x7f\x8d\x98\xce\x02\x2a\x21\x72\x1f\xe8\x9a\x7d\xe5\xff\xf5\xd7\x4f\x58\xbf\xdb\xc7\x8b\x8a\x2f\xd5\x3b\xf2\x75\x82\x35\x42\x29\xc8\x2e\x8e\x2c\x95\x0f\x59\x8d\xc3\x35\x61\x27\x80\xd6\x80\x1a\x29\xb1\x3d\x15\x45\x72\xb3\x21\xcd\x26\x05\x68\x05\xff\x4b\x54\x3b\x74\xa6\xa9\xc0\x5a\x00\xd2\xf5\x54\xd4\xed\x27\x20\x60\xce\xf4\xc9\x3b\x91\x35\xf6\x53\x02\x46\xe2\x75\x2d\xfa\x73\xe9\x7f\x27\x02\x0a\x38\x8e\x8d\xd3\xc2\x43\xdd\x46\xbb\x3b\xa3\xd4\xbd\xf7\x8f\xed\xb5\x58\x98\xc0\x73\x70\x8d\xad\x13\xc2\x40\x58\xbf\xfe\x20\x3b\x79\x27\x8d\x35\xff\xcb\x13\xf9\x97\x57\x5e\x7e\x63\xd3\x7e\x32\xa1\xf5\x88\xe3\xc2\xfd\x09\x8f\xf9\xd4\x03\xee\x5f\xa0\xf7\xa8\xbf\xf2\x23\x11\xb1\x58\x70\xf7\x4e\xbb\x86\x92\xb7\xb4\x82\x32\xbe\x98\x0e\xa1\x4d\x3b\xc2\x1f\xe3\xfa\xc4\x31\x84\x71\x39\x71\x4a\x5e\x7a\xcc\xd0\x47\x74\x93\x04\x60\x5f\x79\xc3\x0b\xa1\x88\x1d\xaa\xc8\x33\x5e\x63\x88\x9e\x30\xbd\x0d\x11\xcc\x11\x98\xad\x3b\xe3\x48\x92\xb5\xb3\x6c\x28\x94\xc7\x6b\x2b\xb3\xa6\xe0\x35\x73\xfb\x71\xa6\xeb\x7b\x42\x7f\xe3\xd5\x6b\x4e\xda\x25\xba\x96\x3a\x87\x57\x2a\xdf\xbb\x2d\x76\xb9\x46\x48\x7b\x71\x26\x93\x44\xf4\xd2\x78\xa3\xec\xa5\x04\x75\x7a\xea\x65\x53\x10\x14\x31\x5b\x85\x4d\x01\xb3\x66\xe0\xff\xde\x8f\x0e\x8f\xb0\x33\x27\xec\x6f\x01\xe3\x64\xc4\x5a\x9f\x31\x54\xec\xd2\x33\x69\xdb\xd0\x74\xb5\x9b\x7a\xaa\x6b\x71\x23\x6a\xb6\x97\x6b\x84\xfc\xb8\x91\x99\xdd\x9f\xb0\xff\xd7\x69\x8a\xe0\x44\xf6\xea\x24\x6d\xb3\x50\xa5\xdc\x72\x66\x3c\x61\x7b\xf0\xb3\x58\x95\xdc\xf7\x81\x22\x22\xe3\x79\x64\xd9\x30\x3d\x22\xdc\x2b\xa2\xdb\x89\x18\x45\x4d\xb1\xb3\x34\xc2\xc9\xaf\x83\x84\x0c\x32\x51\x1a\xda\xa5\x89\xe7\x36\xc4\x59\xbc\x08\x0d\x0b\xe7\x5f\xe0\xa3\x67\xb5\x98\xc1\xfe\xc3\xdd\xf3\x09\x77\x9f\xd5\x95\x2e\xf4\x6c\x71\x51\xd5\x82\xe7\x47\x5a\x19\x5b\x83\x68\xe8\x43\xb1\x70\x57\x9b\x11\x38\xe7\x5c\xdf\x32\x4e\x09\x6c\x7a\x8a\x24\x15\xba\x99\xcd\x11\x6e\x06\x7e\xc8\x78\x56\x6b\x00\x9c\xc5\xe6\xc8\xe8\x34\x01\xfb\xce\xbb\x0f\x02\x3a\x0d\xb4\x02\x0e\x8f\x5b\xbe\xa0\xcd\xc4\xaf\x64\x2e\x4c\x94\xc1\xed\x3b\x83\xa1\x9f\x3b\xdf\x1f\xa4\xf2\xe1\xd9\xf1\x7d\x79\x4d\x37\xa8\xd0\xde\xf1\x2a\x41\x33\xc2\x51\x6f\xc7\x37\x68\xa4\x30\x6e\xbc\xd4\xa4\xa9\x22\x9d\x92\x1f\x99\x47\x82\x2d\x53\xf2\x77\x17\xd7\xe2\x76\x8d\x5f\xfa\x17\xfd\x4e\xdc\x3f\x15\x6c\x0c\xf6\xe8\x1b\x65\xb8\x95\x66\x0a\x04\xc8\x9f\x50\x1f\x87\x92\x8c\xf5\x78\x5a\xf1\x4a\x2b\x9b\xe2\xd6\x7c\xc9\x7c\xc0\xcf\x4d\x16\x0b\xe5\xff\xb5\x76\x10\xa5\x7f\x42\x89\x48\xa0\x78\x75\x3b\x28\x23\xda\x73\xab\xdb\x38\x34\x46\x2a\x9a\xf2\x4a\xd4\x61\xef\xa3\x33\x40\xd6\x1d\xfc\xc8\xce\xde\x7f\x84\x98\xbd\x30\x3c\x27\xef\x9c\xe6\x61\xd6\x4b\x54\xc2\x2b\x99\xaa\x6e\xa3\x18\x1e\xf3\x09\x9c\x9d\x69\x48\xd8\x83\x09\xeb\xbd\xfd\x64\x5d\x39\xd7\x5e\x7d\x52\x29\xf1\x5a\x3b\xa1\x12\xaf\x6e\x1a\xf9\x9d\xaf\xdf\xa1\x20\x8e\xcb\x21\xc9\x29\x64\x46\xa8\xc0\xa3\x03\x1b\x60\xdb\xe8\x60\x87\x9b\x11\x3c\xd5\x04\xa3\xc8\xdd\x84\xbf\xeb\x4b\x30\xbe\xf6\xfa\xc4\xab\x5f\xbe\x26\x5e\x63\xf7\x4a\xbd\x7e\xef\x07\x6b\xed\x46\xfa\x6e\x36\xbc\xd6\x34\xa8\xdb\x2b\x59\x50\xd7\xad\x69\x8d\x2b\x2b\x31\xad\x5b\x61\xd7\x1a\xd6\xbd\x9e\xdd\x3b\xdb\x13\xaf\x3e\x36\x6e\x7b\x25\x03\xa1\xef\x61\xed\x72\x46\x48\xae\xb4\x3b\x56\xda\xbc\xa7\x6a\xc4\xce\xb4\x75\xff\x89\xcc\xdf\x63\x2d\xcc\x99\xb6\xf0\xc9\x83\x18\x4a\x7c\x85\x01\x07\xd2\x33\x79\x22\x31\x86\x93\x9b\x14\xa2\x75\x27\x9e\x1f\xb0\x15\x86\xc5\xa9\x62\xba\xf6\x23\x16\xac\x0b\x43\x4d\xc4\x61\x05\x42\x20\xbb\xd3\x38\x71\xed\xc4\xe3\xfc\x9e\xe6\xa8\x29\xc8\xfe\xc2\x6f\x00\x2b\xba\x2a\xa0\x40\x20\x6f\x6a\xa4\x91\x72\xba\xa6\x15\x33\x99\xb1\x52\xd4\x33\xc1\x00\xd0\x73\x88\xe9\xeb\x73\xae\xe0\xd5\xf3\x74\x89\x3b\xd3\x63\x2d\xc1\x91\x0d\x2a\xd6\x80\x2a\x00\xb6\x87\xc7\x5a\xc9\xc1\x92\xfa\x3f\xc1\x07\xfd\x7f\x59\xc5\x65\x0d\xb4\x53\x14\x3b\x8e\xbf\xa3\xe8\x4b\xdc\x8c\x6b\x61\xc9\xb7\xc4\x15\x13\x58\xe7\xe5\x5a\xef\x2a\x1e\x23\x76\x0b\x50\xcd\x4e\x26\x06\xf7\xc7\xce\xb5\x58\xec\x8c\x96\x96\xde\xce\xa9\xda\x69\x03\xc3\xc9\x62\x0b\x87\x30\x64\x10\xee\xc0\x77\x3b\x1f\x4f\x57\xe9\x75\xd8\x0e\x41\xda\xd9\xed\xd0\x9a\xeb\xaa\x9d\xbc\xef\xd6\xc0\x74\x64\x4b\xd5\x94\x2f\x93\xf6\xbc\xb6\x64\x49\x49\x6f\x8f\x3f\x83\x49\xff\x45\x84\xb8\x6f\x80\x58\xd6\xc3\x88\x55\x48\x12\x36\x6b\x53\x66\x78\x91\x21\xef\x2e\xce\x2a\x34\xe2\x66\xd3\xdb\x18\x85\xd6\xd7\x4d\xe5\x57\x05\x24\x19\x00\x46\x90\xca\x74\x49\x56\x07\x3e\x1f\x1c\x2b\xb4\xe4\xc6\x14\xc8\xc3\xe5\x1b\x16\x07\xb1\x5d\x26\xe6\x4c\xda\xe1\xe0\x77\x08\xb0\xfe\xf7\x79\x85\x90\xf3\x12\xf7\x8e\xb0\xff\x78\x19\xdc\xe5\x53\x5d\x5f\xc9\x3c\x07\x53\x1a\x1f\x14\x92\xff\x3a\x03\xed\xf6\x44\x62\x7d\x4d\xba\x77\xac\x48\xc9\xef\x9a\x6b\x6a\xd7\x62\x02\x04\xfc\x00\x14\x94\x5c\xbb\x0f\xc3\xa3\xef\x18\xd0\xf0\x86\xe4\xb6\x74\x02\x43\x35\x45\x11\xe0\xb7\xd1\xb0\x40\xaf\x24\x6c\x50\x72\xe7\xcf\xdc\x96\xb5\xe9\x40\xaf\x04\xf0\x5d\x66\x7d\x72\x5d\x49\x5f\xf1\x54\x9d\xeb\x3c\x75\x61\x24\x58\xbe\x54\x0d\xe5\x41\x80\xf7\x22\x34\xe0\x90\x52\xb5\x4e\x11\x6c\xbf\x53\xa6\xc7\xd9\xd2\xf3\x44\xb9\x0b\x5e\x95\x5b\x5d\xca\x6c\x0d\x51\x02\xee\x93\xde\x32\x64\xf7\x25\x36\x14\xb9\xfa\x30\xbd\x60\x56\x0b\xac\x7a\x87\xed\x05\xdb\x8d\x80\xfd\x1b\x25\x6e\x84\x5b\x56\xb9\x34\x04\xbc\xea\xb3\x95\xfe\xb9\xe4\x5d\xf9\xff\x1f\xeb\x33\x6d\xbd\x03\xf0\x9f\xde\x83\x8e\x47\xd9\x3b\x59\x36\x65\x4b\x14\xc0\x72\x39\xf5\xb4\x54\x3e\x49\x2a\x75\x3d\xa4\x1e\x30\xda\x22\x96\xd7\x33\x48\x96\x26\xd7\x83\x3f\xb1\x66\x85\xbe\xe2\x05\x2b\xa5\x72\x8f\xa1\x3c\x88\xe4\xb3\xd0\x13\xfa\xf3\x3d\x0f\x82\x63\x55\xce\xe4\x55\x21\xc8\xb7\xd1\x61\xcc\x8c\x7e\xdc\xb9\x11\xb6\x56\x01\x54\x5c\x73\xae\xd8\x4b\xa9\x8e\xbd\x63\xf4\xb9\xdb\xb2\xef\x78\x59\x15\x02\x6b\xa1\xd9\x97\xe3\x7f\x6b\x25\x18\xe5\xfa\x8c\x98\x9f\x1e\x4a\x01\xb3\x9a\x3d\x1d\x79\x02\x91\x88\x65\x14\xe4\x58\x2a\x41\xbd\x53\xd6\xb0\x2f\x0e\xbe\x38\x78\xfa\xcc\xa9\xa3\x18\xf1\xe3\x86\xb0\xde\x96\x47\xe3\xe9\x84\xfd\xc2\x5c\x0f\x9e\xd2\x7f\xbf\xa0\xff\x7e\xc9\x7e\x61\xbf\x30\x76\xce\xce\x59\xfc\x5f\xf7\x1f\xf6\x0b\x1b\xbb\x41\x88\xba\xfa\x74\x94\x0a\xae\x04\x6a\x9c\xd6\x02\x1c\x23\xd8\x34\x88\x8a\x4c\x97\x02\xba\xfa\xc5\xff\x8a\x21\x9a\xa5\x65\x5a\xd1\x9d\x4f\xf7\xa0\x4b\xfb\xec\x16\xfc\xf3\x25\xbf\x46\xdf\xd4\x61\x66\x1b\x5e\xb8\x87\xef\x7d\x39\x7e\xba\xcf\xb4\x4a\x6f\xbf\x91\x1a\xd8\x78\xa8\x87\x7b\x4f\xf7\x27\x4b\x5d\xfe\x62\x45\x97\x93\xde\x42\x2f\xb8\x5a\x40\xd3\x77\xaf\x77\xbf\xd4\x0f\xd5\xe2\x96\x2f\xc2\x82\xf7\xe7\xe6\x4c\xde\x04\xee\xde\x08\xed\x09\x12\x17\x60\xfd\x4a\x0f\xe0\x87\x8d\x2e\x98\xb4\x13\x76\x6a\x77\x77\x0d\x84\x1d\xd0\x6d\xe0\x49\x86\x8f\x63\x60\x62\x18\x78\x58\x1b\x4f\x3a\x85\x0d\x6b\xc0\x60\x0e\x1a\x21\xba\x17\x4b\x30\x5e\x65\xd8\x25\x03\xa8\x49\xa1\xad\x04\x36\x64\x79\xd7\x77\x37\x6e\xc8\xc1\x7c\xef\xee\xee\x70\x58\x7a\x31\x74\x4d\x2a\x59\xbb\xf3\xdb\x77\x1a\x41\x3a\xa0\x3f\x3d\x19\x1d\x9f\x10\xf5\x33\xec\xed\x4e\xba\x2f\xdf\xee\x40\x1c\x30\xa8\xe2\x04\x15\x40\xea\x0d\xc1\xcc\xfa\x65\x1c\x41\x21\x1e\xaa\xbc\xcd\xbe\x5a\xb3\xff\x40\x48\x0b\xe6\xe7\x0c\x42\x92\xf5\xf2\x9b\x44\x19\x5a\x49\x42\xaf\xdb\x85\x11\xe2\x3d\x3b\xc4\x05\x6c\x20\x8e\xfa\x21\xfd\xba\x73\xec\x22\xee\x03\x50\x98\x42\x3c\xa9\x44\xe6\x4c\x77\x3b\x6d\x6c\x74\x7b\x7b\x26\xcc\x30\xad\xa7\xd3\x15\x29\x75\x6d\xac\x09\x51\x7e\xdd\x22\x81\x12\xac\x78\xfd\x44\x1c\xbd\x4f\x57\x40\xde\xd2\x76\x31\xe9\x70\x3d\xa1\x85\xd4\x3e\x53\x5b\x7c\xee\x0f\x5d\xf9\x11\xec\xf8\xe4\xdc\x04\x2d\x6d\x9d\xc3\xe2\x8b\x51\xa7\xf7\xf4\xf9\x9f\xd6\x39\x43\xbe\x78\x76\xbf\xc3\x81\xfe\x7b\x99\x4c\xf3\xca\xd9\xfd\xd3\x5e\xdb\xcb\x7d\xc8\x85\x58\xb1\x09\xa0\x6e\xaa\x8d\x8b\x4f\xc2\x81\x66\xa4\x6d\x38\x96\x5a\x29\x71\x4b\xf9\xaf\x77\xbf\x54\xa4\x9b\x7b\xe1\x3e\x72\xe7\x0f\x6f\x80\x2c\xb5\xac\x1a\x80\x46\x70\x03\xe9\x35\xed\x2f\xf7\xbe\x64\x63\xf6\x64\xdf\xad\x06\x85\xcb\x0a\x06\x33\x3e\xca\xdc\xd1\x40\xe9\xdc\x76\xee\x94\x27\x37\x32\x66\x84\x04\x9b\x45\xd1\x3d\x84\xee\xa3\x78\x87\xb1\xd9\xac\xd2\xbd\xa9\xb3\x40\xe9\x5c\x1c\x4e\x81\xff\x67\xb1\x2e\xc2\x77\xf7\x4c\x38\x5b\x6a\x33\x3a\x1b\xe6\xfa\x96\xdd\x52\x96\x36\x2c\x39\x2a\x36\x8c\x3b\x72\xe0\xfe\x08\x6b\x0a\xe4\x59\x10\xc9\xa4\x42\x04\x51\x4a\xdb\xc8\xc0\xb4\xbf\x8a\xe1\x8b\xc6\xec\x5b\xad\x74\xfd\x0c\xb5\x23\xd7\xa4\x69\x45\xf1\xdd\x8f\x43\x51\x13\x83\xb9\x24\x07\x82\x71\xea\xcd\x29\x58\x87\xcf\x7e\xad\x95\x60\x43\x42\xc2\x78\x1e\xe4\xd8\xfb\x1a\x47\xd4\xfa\x3b\x32\x93\x03\x42\xfa\x92\x6b\xca\x7d\x0b\xaf\x4b\xec\x64\x93\xce\xfa\xa7\xf2\x54\xbf\xa0\x7d\x8a\x73\x87\x47\xc6\xcd\xdc\xa9\xeb\x9e\x91\x5a\xe1\xd4\xbd\x6f\x5b\x40\x41\xea\xfa\x6b\x7e\x4d\x7b\xcf\x8d\xe4\x25\xe4\x25\x0c\xb9\x60\xe3\x16\xdf\xbb\x5c\x11\xb2\x0c\xf3\x22\x7a\x2f\x4d\x5c\x15\xa1\x7e\x17\x5a\x1d\x31\x5e\x68\x70\xb6\x38\x39\xeb\x3e\x12\x39\xdd\x38\xd5\xde\x27\xb3\xe4\xbf\x98\x43\xc9\x72\x9b\x99\x33\x4a\xd6\x5a\x77\xd1\xfa\x17\xf8\x80\x65\xda\x6b\x49\xe2\x33\x3f\xff\x35\x19\xe5\x4d\x0c\x90\xac\x17\xda\xf2\x46\xf4\xb5\x80\xf3\x0f\x66\x0e\x1d\x55\x13\x18\x17\x32\x67\xa8\x10\x05\x7d\x92\x2d\xe3\xb4\x8f\xca\x22\x19\x72\xc6\x8b\x58\x9b\x72\x1a\x99\xcc\x45\x8d\x07\xec\x95\x48\xca\x96\x42\xbe\x0b\xfb\xa1\xbd\x13\xcb\x95\x20\xaf\x1b\x1b\xfa\x2b\x96\xc9\xef\x5c\x35\xd9\xb5\xb0\xde\x9f\x5d\x43\xa5\x45\xd5\x58\x76\xc5\x0b\xae\x32\xb7\x78\xbb\xf9\x0d\x56\x63\x63\xf8\x4b\x78\x0a\x62\xff\x84\x72\x1a\x6c\x3a\xca\xc6\x94\xca\x58\xd7\x1a\xa6\x69\xb6\x1d\x3c\x2c\x8c\x1e\xb9\x2d\xea\x1b\x58\x76\x26\x40\x53\xf4\x6f\x74\xd1\xd3\x61\x20\x84\xa5\x7a\xbd\xc8\xaf\x4e\xe3\xdc\x39\xc0\xb0\x2c\x3d\x15\x13\x13\x06\xfc\xa8\xa7\xd3\xee\x94\xed\xa4\x45\xa3\xbe\x0e\x69\x67\x84\x6f\xed\x66\x8e\x8a\x78\xc9\xdb\x41\xe4\x2b\xd1\x5b\xa9\x1c\x6a\xdb\xbb\x0d\x87\x3b\xd2\x27\x38\x75\xc8\xb7\x0e\x6a\xeb\xfb\x5b\x3f\xb5\xab\x2c\xde\x4f\xbd\x67\x96\xec\xfb\xfe\x0e\xb7\x65\x95\x3f\x95\xe4\x90\x79\xc3\x0b\x5f\x11\x43\xec\xb8\x84\x8c\xaf\x76\x77\x5b\xcf\x00\x6c\x05\x94\x2c\xad\xed\xe2\xa4\x68\x62\x3b\xb0\x3d\xaf\xfa\x31\x2b\x8a\x02\x37\x6b\x6b\x42\x39\x55\x38\x66\x8c\x93\xd0\x42\xea\xc5\x58\xf9\xc3\x15\x34\x73\xe8\x28\x5b\x04\x4c\xcb\x11\xbb\x6a\x2c\x9b\xc9\x1b\x77\x00\x7c\x90\xd3\x03\x1d\x3b\x73\x51\x54\xac\x16\x79\x93\x11\x96\x03\x9c\x4e\x87\xb1\x85\x06\x99\xeb\x41\x3a\xec\x24\x03\xba\x83\xb4\xa7\x2a\x3d\x7c\xe4\x14\x36\x08\x28\x5a\x72\xca\xc4\x8d\xa8\x17\xac\xd2\xc6\xc0\x36\x04\xb1\x85\x05\x8d\x10\x3b\x0b\xf0\xdb\x60\x4d\x40\xaf\xbc\x02\xbf\x43\x1a\xfc\x0e\x58\xb8\x3a\x11\x45\x9f\xc6\xa1\xf7\xe5\xc1\xd3\x83\xa7\xef\x37\xc6\xce\xe1\x7f\xad\x87\xce\xff\xf7\x74\xba\xc2\xe6\x6c\xfb\x92\xac\x9c\xfb\x38\xf1\xbe\x00\x5f\xdb\x97\xfb\x91\x2f\xef\xcb\x83\x2f\x0e\x9e\xee\xb9\xbe\x7e\xb1\xef\x7a\x1d\x79\xe9\xbe\x88\xbc\x74\xe1\x97\xd4\x23\x61\x12\x3f\xdd\xa9\xa2\xea\xd5\x5b\x5d\xe7\x94\xa5\xeb\x2b\x21\x5d\x8f\x10\xf9\xd0\x9d\x0d\xa5\x97\xe5\xb8\xec\x52\x2f\xc1\xae\x45\x77\xa1\xb4\xec\x0f\xa5\xae\xc5\x1f\xa2\xfb\xef\xf4\xaf\xad\xef\x36\xdb\x30\xf9\xdb\xfa\x29\x92\x7d\x13\x24\x87\x61\x91\x43\x06\xa2\x3e\x39\xcd\xbb\x2f\x3c\x71\x27\x36\x45\xc9\x63\xe8\xd4\x2d\x29\xc9\xf1\x6a\x11\xd7\x44\x5f\x09\xa7\xd2\xa2\x0f\xac\x05\x4e\xbc\x27\x51\xb1\xb1\xba\xe6\x33\x71\x40\x8f\x5d\xa7\x82\x79\x13\xb9\xc8\xdf\x23\xe5\x53\x92\x29\x84\x90\x54\x44\x06\xe5\xcb\xd2\x7d\x0e\x29\x48\x01\x9e\x41\x45\x27\x0c\x64\x02\x7a\x1a\xd5\x8a\x3e\x92\x74\xe4\x4f\x4c\x75\xc9\x6f\xcd\x49\xc1\x8d\x95\xd9\xdf\x0a\x9d\x5d\x5f\x58\x67\xf5\xf4\x56\x2d\x56\xb5\x9a\xcc\xa9\x62\x87\x3f\x5c\xb0\x63\x69\xae\x5b\xbe\x67\xcf\x81\x1f\x17\x51\xf2\x80\x5d\x4d\x78\x1a\xac\xe4\xd9\x1c\x55\x57\xf2\x41\x7b\xfe\xb2\xe1\xf6\xca\xef\xf8\xad\x11\xd8\x7d\xe0\xd3\x75\x5f\x8b\xf5\x45\xf0\xc6\xb0\x34\xf1\x75\x4e\x8f\x37\x90\xbc\x3c\x35\x97\x6b\x03\x75\x2f\xb3\xe0\x79\x3a\x05\xc4\x85\x28\x04\x56\x1b\x21\x26\x79\xca\x6c\x07\x6b\x68\xa1\x1b\x76\xcb\xd1\xae\x06\x09\x3b\x61\x97\xb2\x7a\xc6\x4e\x22\x8e\xa8\x55\x4d\x39\xed\x23\x20\xd2\x92\x41\x0d\x6b\x0e\x93\x91\x9c\x40\xa6\x3a\x27\x76\x82\xaa\x95\x79\xc6\x76\xc4\x3b\xfb\x1f\x3b\x23\xb6\xf3\x6e\x6a\xdc\x7f\x94\x9d\x02\xa7\x1c\x71\x88\x3b\x1d\x4f\x4d\x45\xdd\x9a\x8e\xf8\x83\x65\x30\xa8\xe1\x97\x2c\xbb\x7c\x75\xfc\xea\x19\xe8\xf2\xb9\x76\x56\x5f\x55\x8b\x1b\xa7\x53\x12\xb4\x19\xc9\xc6\x68\x18\x20\x7d\x26\xd3\x65\x55\xeb\x52\x46\x05\xc8\xb0\xe5\xd6\xd9\x01\x6c\x88\x0c\x38\x30\x6c\x61\x31\x0c\xb2\x9e\x42\x73\x7e\x49\x45\x1f\xa8\x0f\x59\x4c\xa7\x53\xa6\x31\x51\x20\x85\x40\x90\x26\xdc\xe4\x96\x0f\xb5\xa2\x00\x57\xaa\x5d\x30\x4e\x33\xa7\xaf\x0e\x72\x71\x73\x60\x72\xfe\x74\x04\x8f\xc1\xd5\xb0\xe8\xf4\x89\x1b\xb6\xf3\x74\x67\xc2\x2e\x64\x29\x0b\x5e\x17\x44\xd5\x4d\x4d\xb4\xf7\x39\x43\xc1\x37\x08\xe6\xef\x93\x1d\xb6\x87\x18\x04\xa0\x6e\x14\xc2\x23\xd2\x05\x04\x56\x48\xd2\xd9\x5f\x4b\xbb\x64\x03\x38\xe3\x59\x6f\x87\x3c\x03\x29\xc9\xf3\x57\xaa\x58\x3b\x73\x3b\x5d\x1c\xbe\x35\x5f\xc0\x57\x37\xe4\xcf\x9c\xea\x9a\x8c\xc0\x70\x8b\x07\x3a\x92\x8a\xd4\x96\x97\x6e\xea\xcd\x83\x39\x7e\xd8\x00\xe0\x7b\x2c\x9c\x22\xc3\x8c\xaf\x6f\x0d\x52\x11\x90\xe3\xfa\xf4\xd8\x0b\xf1\x4a\xd4\x46\x1a\xeb\x44\x54\x9e\xa8\x06\x12\xf5\x85\xbd\xc3\x92\xff\x5b\x2b\x76\xf2\xb7\x0b\xea\xd6\xfe\x03\x1c\xec\x35\x25\x1d\xff\x77\x53\x0b\xa7\x11\xf5\x56\xbf\x42\x4b\x5d\x95\xcb\x7d\xce\x8e\xb9\xe5\xa8\x79\xa1\xa4\xd2\x2d\x38\x18\x72\xec\x43\xd1\x96\x47\x7e\x5b\x53\x79\x66\x9b\xd7\x7e\xdc\x0a\x3a\x5b\x1f\x4d\xdc\xfd\xfc\xcd\xeb\xd3\x0d\xe8\x4e\x19\x1c\xb7\xb3\x97\x3a\x1f\x48\x81\x8a\x1a\xf4\x47\x1e\x80\xb5\x1e\xe1\xe7\xac\x74\x4f\x62\x67\x5a\x89\x11\x7b\x2d\x78\xce\x9c\x74\xa3\x7f\xfe\x50\x4b\x7b\x5f\xfc\xab\xf6\xea\x7d\xf4\xfb\x49\x1c\x64\x20\x7c\x63\x7e\x10\x62\x86\x7e\x00\xe8\x04\xa1\x43\x3a\xc0\x55\xa1\xaf\x18\x09\x8b\x4d\xbe\xfd\x9b\xd7\xa7\x83\xbd\xfc\x9b\xd7\xa7\xfe\xdd\xdd\x3f\xf5\xf4\x61\xbe\xf6\x80\xc6\x43\x6b\x3b\x3c\xef\x28\xfb\xad\x3a\xd7\x12\x29\x75\x0d\x82\x0f\xb7\x06\x26\x43\xd9\x01\x9b\x1a\xf3\x6b\xa9\xd6\xae\x01\x4c\xa5\x0d\x90\x28\x05\x48\xac\x28\x88\x06\x48\x7c\xf9\x33\x56\x36\x85\x05\xd4\x23\x58\x6b\x6e\xf1\x41\xb6\x98\x5f\x75\x8c\x10\x40\x19\x3b\x16\x18\x8e\xc8\x9f\xf9\x3a\x94\xf0\x8b\xd5\x3f\x78\xc9\x15\x9f\xb9\xdb\xe1\x04\x64\x25\xfe\x19\x2d\xf2\x3d\x74\xba\xab\xf0\x15\xbf\xe1\xb2\xe0\x57\xb2\x90\x16\xf4\xb9\xfd\x89\xd7\xe6\xb1\x54\x01\xba\xbc\x31\xe9\x37\xa8\x6a\x1b\xd4\xd6\x18\x1f\x06\xe0\x0d\xd9\x9e\xfb\xee\xe0\xd6\x89\xfa\xfd\x09\xc8\x7d\xb8\x11\xd0\xe8\x3b\xca\xef\xeb\x5f\x53\x7e\x37\xa2\xa7\xc2\x7c\x3f\x5f\x93\xe1\x6d\x59\x77\x72\x2d\xad\xd4\x9d\xe0\x0b\x02\x1d\xfd\xcc\xd5\x27\x64\xd9\xef\xa1\x40\xc1\xde\x59\xf3\xf7\x7d\x55\xa8\x8f\xb3\x71\xf2\xcf\x6f\xe3\x30\xe4\xc2\xa4\x99\x1e\x64\xb8\xda\xe6\xbc\xae\x11\xc0\xa5\xf1\xab\x4e\xf9\x3c\xee\xac\x0b\x92\xe5\x1e\x74\x1a\x7e\xef\xf6\xd3\x3a\xe0\x1a\x78\xf5\x16\xbf\x61\x05\x0f\x33\x2e\xbe\x35\x3f\x2c\x78\x48\xc1\xc7\x6c\xed\x7d\xd6\xf3\x35\x33\x51\xcd\xa7\xfd\x33\xdb\x5d\x33\xcf\x2f\xd2\xa8\xcd\x91\xa8\xe6\xec\xf9\xc5\x0a\x31\x89\x55\x05\xee\xbd\x0d\xc6\x72\x76\x0d\x2b\xe4\x54\x58\xb9\xd6\x20\x6c\x58\x50\x96\x5a\x49\xab\x6b\xb3\x01\x31\xe7\x1f\x3d\x8c\xe2\xe6\x5b\x73\xeb\xf3\xb5\x1f\x14\xf6\x32\xfa\x94\xb3\x4c\x17\x85\xc8\x7c\xae\x3f\x4c\x71\xf8\xd9\x0a\x47\x0c\x65\x20\x98\xc9\xf5\x5f\xc0\x15\x43\x4e\x97\x03\x5c\x76\x07\xaf\x4f\x0e\x8f\x5f\x9e\x4c\xca\xfc\x77\x73\x7d\x3b\xb6\x7a\xdc\x18\x31\x96\xb6\x9f\xbe\xb5\x41\x3c\x91\x01\x3c\xdd\x76\x3e\x94\x93\xdb\xce\xdd\x94\xb5\xa0\xd6\x6f\x4c\x0b\x3b\xef\xe3\xce\xb5\xd6\x76\x19\x78\x7e\xda\x14\x05\xce\xad\xad\x85\x18\xc5\xfe\xed\x7b\xc2\xf2\xb7\xd7\xc3\xd2\x85\x5b\x37\x6f\x32\x44\x1f\x57\x33\x7e\x28\x1b\xa4\xbf\xae\xb0\xae\xa6\xcd\x96\xe6\xa1\x6d\x2f\x9d\x89\x8b\xe4\x73\x0c\x88\xd8\xb9\x9b\x97\x6b\xb1\x60\x00\x1d\x31\xd5\x35\xd0\xb8\xa4\xeb\x53\xd8\x0c\x06\xef\xa0\x31\xa2\x9e\x90\xc2\xf1\x40\x06\xbe\x8f\x2a\x02\x2f\xf2\x5a\x4c\x87\x1c\xf6\xd7\x62\xba\x6a\xd4\xe9\x63\xc0\xba\x0d\xe9\x71\x4e\x5f\x69\xec\x1c\x73\x63\x11\x63\x1b\xc7\x76\xe5\x34\x10\xf6\xc7\x03\x19\xf7\x5e\xa8\x0d\x43\x20\x0b\xf5\x61\x88\x64\x4b\x93\x17\xbb\x2d\x69\x92\xec\xbd\xc3\x20\xfa\xc6\x59\xb1\xe2\xf6\xe0\x56\xd7\xd7\x52\xcd\xc6\xb7\xd2\xce\xc7\x38\x52\xe6\x00\x10\xff\x0f\x7e\x07\xff\xa1\x28\xf2\x61\x9e\x53\xfe\x5b\x63\xc4\xb4\x29\x30\x33\xcd\x4c\x18\xaf\xe4\xf7\xa2\x36\x90\x65\x79\x2d\x55\x3e\x62\x8d\xcc\xbf\x5e\x77\xc6\xd8\x10\xbb\xc5\xed\xfd\x61\x36\x0a\x70\x3a\x49\x43\xcc\x8c\x74\x8c\xd6\x5e\x26\xd5\x3c\xd7\x06\x79\x9f\xdc\x50\x25\x5b\x80\xe7\xa5\x54\x0f\x65\x07\xac\x6b\x1d\x48\x95\xaf\x37\x92\x9d\x00\x04\xb4\x93\x9a\x07\xf4\x19\x85\xb1\x43\xce\x0f\xf7\xde\x13\xa4\xbd\xa7\xec\x9f\x34\xf7\xe7\x83\x04\x4b\xb9\x30\x3f\x17\x63\x7c\xca\xb8\xca\xdb\x71\xdd\x26\xf2\xdc\xe7\xfa\x74\x89\x3c\xc3\x3a\xe4\x3f\x41\x7a\xce\x47\x5d\x71\xec\x01\xeb\xcc\x1f\xd7\x0f\xb6\xc1\xa1\xee\xaf\x19\x7f\x1c\x0d\xad\x3d\x7d\x80\x93\xd0\x78\xa0\x3c\x50\xc0\x50\x2a\x79\x7f\x1a\xe4\xc8\xb7\x24\x58\x1e\xed\x21\xd3\x4a\x11\x3f\xc2\xab\x4a\xa8\x0b\xcb\xb3\xeb\x9e\x51\xdd\xad\x56\xf5\x1b\xd3\xaa\x3e\x52\x22\x90\x5f\xa2\x58\x78\x47\xe9\x6f\x6d\xb2\x37\x6e\xf2\x47\x28\x80\x91\xec\xef\x25\xaf\xfa\x7b\x57\x7d\x4b\x1d\x0d\x2a\x7c\x4c\x0e\x55\x28\x0e\xaa\x74\x05\x60\x63\x54\x82\x0a\xe3\xf8\xe9\x35\x9e\xbe\xfb\x9b\x8e\x98\xe1\x72\x60\xa2\x06\x53\x89\x5a\xba\x4f\xae\xa4\x6d\x65\xa5\x11\x16\xa1\xa0\x08\x22\x59\x2b\x96\x11\xdc\x03\xe8\x23\x11\x88\x41\xa4\xab\x28\xa6\x33\xeb\xab\x46\x03\x6a\xd4\x93\x27\x4f\x9e\x20\x12\xce\x7f\xfe\xe7\x7f\x32\x5d\x03\x17\x69\x26\xcb\xe5\x1b\xe1\xae\x3f\x3d\x7d\x3a\x61\x7f\x3f\x7c\xf9\x02\x2a\x1a\x2a\x6b\x10\xf5\x0d\x5b\x76\x37\x24\x3f\x36\x23\xf6\xbf\x2f\x5e\x9d\xb5\x18\x0d\xe9\xb7\x60\x9a\x87\xd7\x4b\x79\x41\x9e\xfc\xf9\x3f\xfe\x63\xc2\x8e\x65\x0d\x15\x5d\x52\x04\xce\xf9\xe0\x6a\xe1\xb5\x40\xe4\x1e\xc0\x50\xf1\x1a\x97\x0c\xf4\x8e\x54\x9f\x5c\xca\xd9\xdc\x52\x45\xac\x5b\x90\x85\xcc\x2c\x16\x8f\xa1\x58\xf3\x94\xf6\x48\x29\x42\x24\x3d\xa4\xfd\x41\xe7\x46\xac\x90\xd7\x82\x4d\xcd\x37\xb5\x6e\xaa\x16\xe6\x91\x88\x98\xa9\x50\x06\x1b\x6b\xe7\xca\x08\xfb\xc8\xd3\x56\x7b\xb9\x9a\x93\xb5\x0d\x2d\x75\x14\x56\x2a\x6f\x6d\xa1\x0e\x2b\x2e\x43\x31\x0c\x64\x00\x26\x1c\xa0\xc1\xd7\x93\xb3\xa3\x20\x55\x3c\xe6\x48\x55\xeb\x7f\xe1\x12\x80\x5a\xe4\x48\x3c\x43\xad\x30\xcc\x24\x55\x0a\x47\xd1\x2d\x5f\x4f\x4d\xa4\xf3\xfe\x63\x62\xb2\x59\xa6\x03\x2b\xa4\x71\x8f\x00\xb0\x9f\xf7\x3c\xb9\xe5\x32\x76\xab\xd4\xe0\x7a\x69\xd4\xd2\xaf\x09\x58\x85\xc4\x25\x91\x80\x12\xbe\x62\xdb\x06\xc2\x03\x10\x0e\x0e\xdd\xeb\x47\x29\x0c\x44\x92\x6f\x6d\x84\x6d\x68\x68\x20\x8b\xde\x3d\x1b\x08\x2a\xe1\x0d\x4b\x5e\x5f\x3b\xc3\x95\xa4\xcb\x84\x9d\xbb\x4e\x06\x28\x1d\x04\x3b\xbe\xc1\xc0\x66\xc9\x17\xf0\x58\x52\xdc\xe0\x21\xbb\x93\xc9\x2e\x6e\x3f\x5d\x33\x63\x79\x4d\x7b\xc9\x7d\xfe\x79\xa0\xac\xbf\xe4\x95\x41\xd4\x5f\xa7\xa9\x02\x22\xb6\x86\xda\x75\x3b\xf7\x22\x88\xd3\x58\x6f\x91\xd1\xd9\x18\x06\x66\xed\x06\x1e\x38\x2a\x3a\xcd\x3e\xed\xf2\x07\x01\xd9\x5d\xf6\x50\x38\xf0\xea\xc6\x54\xf3\x4e\x64\xe3\x83\xf4\x0d\x62\x85\x2a\xc4\xa3\x52\x30\x56\xb3\xc0\x92\xe0\x8c\x15\xb0\x98\x1e\xf4\xf1\xea\x11\x78\x0d\xa1\x4d\xe0\xd5\x5f\xa7\xc0\xab\x4f\x10\x19\xaf\x64\x0d\xfb\x48\x32\x0e\x26\x1d\x60\x78\x46\x4d\xdb\x29\x00\xae\xbe\x2a\xda\xd6\x48\x6c\xeb\x09\x9a\x15\xe3\x57\x46\x17\x8d\xc5\x9f\xb6\x5f\xc6\xa7\x1f\x34\xea\x31\xc3\xe1\xc8\x0b\xb7\x45\x67\x21\x68\x01\x78\x7c\xf4\x39\x16\xf1\xea\x2d\x36\xfa\x38\x21\x7e\x43\x0e\x88\xde\xe3\x1c\x0c\xb6\x21\xc6\xda\x37\x16\x2a\xee\x6e\xe7\x82\x52\x20\x22\xbd\xcf\x49\x53\x27\x23\x40\xa9\xf4\x2a\x1c\x02\xe7\xe4\x1b\x71\x33\x66\x46\xf6\xf7\x25\x18\xc9\xf6\x8e\x42\x79\xbc\x4f\xbb\x3b\x55\x56\xd4\x53\x9e\x89\xfd\xd8\xc7\x20\xaa\xb9\x28\x45\xed\x06\x8a\xee\xf3\x35\xda\x73\xae\x72\x82\x9d\xca\x44\x0d\x3b\x58\xbc\xb3\xa2\x76\x83\x7a\x74\x71\xca\xf2\x5a\xde\x88\xda\xb0\xbd\xbf\x01\x9c\x20\xc2\x4d\xed\x3f\xc2\x34\x58\x7c\x91\x4d\x78\x40\xe0\xc1\xc3\x94\x7e\x40\x53\x5e\x86\xab\x48\xce\xb4\x53\xe5\xb1\xb1\xdc\xb4\x9a\xd8\x77\x34\x71\x1b\x02\x8e\x50\x90\xbe\xc0\x68\x8d\xb1\x4d\x0f\x66\x0f\xc4\x5b\x99\xc5\x86\xb9\x61\xb5\x98\x39\x6b\xac\x8e\x40\xfb\x10\x26\x65\x63\xc5\x0d\xc3\x17\x94\xb4\xc1\xaa\xf7\xd5\x7e\x4c\xc9\xae\xd4\x37\x32\xf7\xea\x10\x02\xe3\x07\x68\xb8\x8a\x9b\x08\xbc\x80\x1b\xa3\x33\x09\xae\xa6\x68\x6a\xd0\x4a\x05\xa5\x29\xa5\x42\xf3\xe1\xe6\x38\x4c\xa6\x81\x50\x68\x2d\x1e\x56\x36\xc8\x81\xa8\x73\x71\xde\x5c\x15\xd2\xcc\x2f\x06\x0d\x89\xac\x6a\x18\x93\x12\x97\x32\x55\xee\x8c\x8c\x18\xa1\x8c\x24\xda\x7c\x54\xb7\xa4\x06\x96\x05\x37\x0d\xfe\xd7\xf1\xa6\xd0\x50\x0d\x0f\x64\xfc\xfe\xab\xb3\xb6\x1f\x04\x56\x82\x2c\xd0\xb9\x78\xa3\xaa\xe4\xf3\x8c\x17\x85\x21\xfd\x36\x70\x9c\xf8\xb3\x07\x35\x54\x0f\x60\x82\xab\x42\xba\x05\xe3\x7b\x0f\x29\x38\x28\xbc\x02\x21\xcf\xca\x17\x33\x11\xdc\xb0\x56\xfe\x26\x20\xb3\xf6\x3f\x08\x23\x84\x95\x38\xb8\xe8\x36\x48\x85\xb2\x0d\xff\x3c\xbe\xf0\xcf\xc7\xa9\xa9\x68\x29\x46\x39\x7c\x38\x86\x0a\x2d\x0c\x6d\x34\x44\x9b\xeb\x0f\x1a\x7f\x20\xfd\x4a\x9a\xe6\xc6\x42\xc0\xd8\xbf\x43\x4b\x5c\x14\xc3\x78\x77\xbb\x8d\x82\x2a\xe6\x4c\x71\x90\x50\x63\x1a\xbf\x2c\xda\x52\x64\x23\x87\x7d\xbe\x2c\xd7\xda\x33\x1d\x8e\x73\xfc\x70\xd7\xb0\x5c\x67\x8d\x33\xbe\xda\x61\x6f\x13\x2e\xfa\xb1\x15\x7e\x5e\xf4\x49\xb9\xbe\x55\xb7\xbc\xce\x0f\xcf\xd7\xaa\xcd\x4d\x95\xb3\xb6\xad\x58\xf5\xf6\x1f\x33\xf7\x39\xbf\x02\xc0\x5b\xc2\x36\xdc\x46\xfb\x56\x36\x11\x4b\xf3\x55\xee\x36\xab\x9d\x90\xfd\xc0\x68\xde\x7d\x1d\x76\xdb\x00\xe1\x36\x40\x98\x5c\x0f\x29\x40\x78\x8a\x01\xc2\x98\xe9\x37\x11\x2f\xe4\xa1\x75\x23\xfe\x59\xc4\x98\x8e\x5b\x91\x8a\x9a\x78\xb7\x9e\xb7\xa3\xfc\xe3\xe6\x6d\x57\x5d\x64\x30\x78\x99\x0b\x7a\xd9\xe7\x10\x8f\x7a\x00\xf1\x24\x18\xcb\x1e\x56\x21\x5e\xa9\xc0\x6f\xeb\xd5\x10\xa5\x16\x03\xd3\x51\x84\xbb\xd2\x39\x71\x1b\x00\xe9\x06\x12\x08\x8c\x02\x33\xa0\xf2\xe5\xa6\xa0\x9d\x57\x3c\x13\x20\xdf\x82\xfa\x33\x48\x90\xa0\xe7\x02\x60\x03\x2d\x02\x06\x0b\x01\x46\xe7\xbc\xcf\x6a\x60\x83\xad\x08\x77\xb5\x16\x4f\xdf\x96\xba\x88\xa2\xd8\xaa\x5f\x08\x26\x9b\x8b\x92\xc3\x3f\x9f\xfb\x21\x70\xb2\xd1\x19\x0f\x56\x20\x04\x9c\xa8\x4b\xc3\xf4\x74\x94\x64\xba\xee\xdc\x3c\xdd\xe9\x17\x6c\x60\xc3\xc5\x29\x99\xdf\x47\xe7\xbd\x83\x3d\xac\x3b\x60\xe7\x49\x6c\xc7\xed\xa1\x96\x03\xd3\xe3\xde\x87\x0c\x0a\x38\x3f\x70\x84\x1f\xcc\xe0\x0c\x1d\xc4\x5d\x37\x78\x3b\x0a\x51\x83\x47\xa0\xfc\x6d\x83\xb7\x9f\x63\xf0\x36\x3a\x18\xbd\xa0\x5b\x11\xc8\x8d\x43\x02\x3e\x9a\x7b\x25\xbc\x51\x43\x36\x8c\x0f\xe5\xfa\x38\xae\xae\xd3\xd4\xa5\xdd\xc9\x64\x77\xd7\x47\x77\x69\xdd\x37\x76\x3a\xfe\x0b\x13\x2a\xd3\xb9\x27\xf0\x9d\xca\xda\x58\x50\xf7\x5a\x77\x5b\xdc\x97\xd2\x3f\x2b\x4e\x7f\x82\xb6\x87\x98\xea\xde\xb2\xc5\x43\x12\x3e\xff\x08\x4a\x4c\xab\xba\x04\xe0\x43\x1a\xa2\x80\x67\x4d\x3a\x8c\xff\xde\xb0\x42\x96\x92\xf8\xef\xdd\x46\x17\xc6\x1a\xb6\x87\x1f\x4e\xb2\xaa\x19\xd1\x0d\x93\x52\x94\xba\x5e\x8c\xc2\x4d\xee\xcb\xe4\x57\x74\xc7\x3e\xf2\x9d\x34\x75\x2d\x94\x2d\x16\x9f\xb3\x06\xe4\x07\xf1\x81\x28\x40\x61\x8e\xfb\x20\x8e\xb4\x57\xba\xb4\xda\x88\x2f\xb8\xcd\x23\x7e\x81\x80\x46\x6b\x46\x6d\x5c\xdc\x7d\x2a\xd4\x0d\xbb\xe1\xf5\x3d\x91\xe3\x57\x5d\x03\xea\x3c\xb9\xbc\x91\x46\xaf\x1d\x16\x8d\x1a\x8a\x87\xe7\x22\x38\xa1\xdd\x66\xd3\x8d\xad\x1a\x4b\x12\xdd\xef\x40\x8f\x32\x1e\x76\x5e\x47\x39\x7c\xba\x0e\x8b\x52\x7a\x55\xdc\x5a\x51\xab\x67\xec\x7f\xf6\xde\xfe\xf1\x97\xf1\xfe\xd7\x7b\x7b\x3f\x3e\x19\xff\xd7\x4f\x7f\xdc\x7b\x3b\x81\x7f\xfc\x61\xff\xeb\xfd\x5f\xfc\x1f\x7f\xdc\xdf\xdf\xdb\xfb\xf1\xbb\x97\xdf\x5c\x9e\x9f\xfc\x24\xf7\x7f\xf9\x51\x35\xe5\x35\xfe\xf5\xcb\xde\x8f\xe2\xe4\xa7\x0f\x6c\x64\x7f\xff\xeb\xdf\xf7\xee\x3a\x57\x8b\x57\x3d\x45\x21\x5e\xe3\x01\x8f\xe4\xb4\xc5\x41\x96\x5f\x87\x56\x42\x2a\x3b\xd6\xf5\x18\x9b\x7e\x06\x60\xc1\x3d\x1f\xe0\x97\xd7\xd0\xfb\xbf\x55\x03\x5a\xb8\x7d\xaf\xd4\x6f\x78\x83\x43\xe8\xf3\x58\x0e\x50\x66\xec\x5b\x4a\xcb\x64\xac\x28\x2b\x5d\xf3\x7a\xc1\x72\xf2\x66\x2e\x56\x20\x10\x45\x10\x44\xbd\x21\x85\xa1\x1f\xb9\xac\x37\x50\x69\xdc\x1b\x51\x48\xe4\xb2\x29\x07\xc2\x13\x82\xb6\xe2\xc9\xb8\x05\xe4\x7d\x42\xed\xf7\x29\x45\x74\x1b\x05\x34\xae\x78\x76\x8d\x16\x54\x98\x2d\xd4\x1b\xa3\xd2\xfa\x9d\x1d\x4a\x89\x28\x05\x57\xc1\xb1\x0f\xb9\x2d\x3a\x17\x6e\x2a\xfd\xcd\xd8\x76\xe2\x84\xc7\x48\x3b\x25\x10\xb6\x8c\x54\xba\x66\x2f\x41\x01\xda\xe8\xec\xb3\x41\xb0\x42\xe4\xbf\xc5\x0b\xa7\xf5\x0d\x54\x89\xea\x9b\xf3\x09\x44\x56\x83\xbd\x49\xb8\x5e\x53\x20\xd9\x6a\x33\xc4\x12\xcd\x02\x26\xf2\xc4\x6f\x4b\x1f\xbf\x75\xd3\xe9\x5a\x45\xdd\x14\x1c\xd3\x85\xc1\xbc\x15\x99\x01\x0f\x14\xd8\xa6\x30\x1d\x61\x0a\x2f\x23\xa2\xfe\xc6\xb8\x27\x69\x95\xde\xd3\x3e\x08\x69\xb2\xae\x70\x4d\x78\x76\xed\xd4\xa2\x76\xdf\x5c\x84\x37\x6b\xfd\x19\x50\xb2\xec\xcd\x4f\xd3\x80\x91\x42\x4f\x21\x55\x5b\x4f\x21\xb3\x22\xe2\xeb\xf1\x94\x34\x4b\x0b\x55\xc9\x22\x5d\xa9\x9e\x79\x22\xbc\x78\xa3\x28\xa1\x70\xe3\xcb\xee\xd1\x69\x1f\x3d\x75\x8e\xa1\x34\x8d\x41\xf4\x8b\xc1\xb5\x8a\x90\xb9\xd9\x9f\xef\xb5\x4d\x02\x4d\x8e\xd5\x98\x23\x23\x4d\x08\xe5\x81\x16\xcd\xcb\x04\x9f\x75\x70\x19\x3c\x4a\x74\xdc\x66\x8b\x8c\x10\x9e\x64\xc2\xe0\x83\xcd\xe2\xd6\x80\xda\xaa\x71\x60\xaf\x6e\xfd\x12\xec\x4a\x4c\x31\xf1\x09\x7f\x03\x0e\x03\xaa\x08\xcb\x45\x21\xac\x88\x68\xe7\x2b\x24\xca\xae\x45\xa9\x6f\x88\xa6\xf5\x8d\xa1\xb0\xb9\x9c\x3e\x63\x7c\x3f\xa9\x3b\x36\xc4\x83\x2c\x44\x8e\x65\x62\x11\xb7\x60\xdd\x28\x33\x62\x57\xfb\x3e\xad\x95\x58\x30\x6b\xf0\xad\x11\xc9\x17\xb8\xb3\x6a\xe1\x06\x00\xb0\xaa\x6a\x5d\x32\xa3\x78\x65\xe6\xda\x82\xe7\x84\x57\x3c\x93\x76\xc1\x6c\xcd\xb3\x6b\x77\x0b\x84\x53\xe1\x71\x23\x96\xed\x53\x96\x7b\x3c\x7c\x69\xe5\x9a\x9d\xd7\xba\x99\xcd\xa1\x94\x0a\xef\xca\x0a\x6e\xfc\xdb\xaf\xfc\x3d\x99\xf2\x86\xe5\x0b\xc5\x4b\x99\x05\x0a\x91\x5a\xdf\x48\x23\x35\x05\xbc\x7c\xbb\xe7\x81\x8c\x01\x83\x68\x47\x05\x97\x25\xdb\x33\x42\xb0\x13\xbf\x24\xf0\x9b\x0b\x54\x28\xd1\xa1\x58\xa7\xb9\x75\x84\xfb\x48\xf8\x03\xee\x93\x56\x02\x87\x8c\x05\xd4\x09\x5c\xcf\x57\x3e\x74\x3f\x4c\xd7\xea\x3e\xe9\x1a\xf2\xde\x3c\x13\x90\x50\xb9\x8e\x12\x63\x0e\xcf\x4f\x4d\x6c\xe6\x12\x9b\x22\xb6\x04\x5f\x14\x5a\xcd\x62\xfc\xbb\x76\x65\x3a\x59\xaf\x80\x16\xf3\x46\xe6\x0d\x2f\x50\xca\x53\x67\x8e\x2e\x4e\xf1\xe7\x72\x36\xb7\xe3\x5b\x01\x4e\x50\x3c\x0c\xdb\x3d\xe3\x1f\x2a\x97\x12\x6e\xa5\x81\x53\xc1\x92\xb3\x0d\x1d\xca\x40\x3d\xc9\x17\x80\xbf\x4b\x39\x9e\x49\x4e\x8e\x47\xab\xc7\x26\x56\x8d\x38\x74\xef\x30\xf0\x24\x3a\xcd\x08\xbc\xc4\x6e\x88\x61\xa5\x2e\xf7\x0d\x48\x1f\x5b\xea\x8d\xf0\xb1\x6d\x09\x20\x41\x2f\x5e\x9f\x28\x78\x63\xfa\xec\x4d\xbb\x4c\x2e\x45\x59\x15\xdc\x0e\x93\x61\xb2\xf3\x43\xe4\x05\x8f\x62\xc8\x6e\x3b\x72\x95\x8f\x79\xe1\x56\xe4\xf9\xf7\x47\x54\xe0\x86\x1b\x2c\xc9\x62\xbb\x6c\xa9\x4a\x3d\x4b\xb5\x53\x96\x56\x6e\x2d\x80\x54\xbb\x12\x39\x08\x23\x7a\x32\xb8\x2a\x6e\x15\x52\x05\xbb\x3f\xce\xbf\x3f\x1a\x31\x39\x11\x13\xff\x57\xb8\xd5\x4b\x43\xab\x67\x58\xe7\x10\x0a\x69\x60\x3d\x43\x57\x62\x1f\x70\xfc\xdb\x7f\x7e\xe5\x3a\xe9\xbe\xfd\xeb\xf8\xab\x88\xd2\xe8\xaf\xff\x74\xc2\xb5\x76\x37\xa4\x9f\xc6\x69\xe6\x20\xf7\xdc\x5f\xff\x3c\xd7\xf9\x45\x25\xb2\x09\xbe\x96\xf9\x27\x26\x0b\x30\xa1\xac\x53\xb9\xcf\x35\x24\x98\xc9\x1c\x57\x39\x3c\xbb\x16\xff\xf2\x71\x02\x62\x4d\x25\x41\x92\x71\x2b\x14\x1c\x00\xbe\xde\x58\x69\x8b\x3f\x47\xbe\x55\xe8\xff\xde\x34\x66\x40\xb5\x5a\xc3\x36\x47\x51\x72\xa8\x98\x78\x27\x0d\xc0\xcf\xe0\xbb\xc2\x70\x70\xca\x61\xf7\x67\x9a\x6b\xd6\x8d\x70\x40\x1b\x02\x0a\x56\xd7\xb7\x3f\x28\x6d\xff\x10\xa6\xdf\xe7\x27\x22\x9f\x39\xe3\x37\x5a\xe6\xac\x01\xfa\x2c\xb7\x03\x15\x38\xb8\x5b\x06\xc3\xab\x05\x2b\xa5\xb1\xfc\x5a\x4c\xd8\x85\x3b\xb3\xe2\x44\x03\x1c\x3d\xc5\x80\x8c\x46\xe4\xac\x51\x56\x16\xf0\x6d\xdb\x8e\xeb\x72\x7c\x96\x9d\x4e\x99\x69\x32\xe0\xe8\xad\xc5\xd8\x9f\x8e\x74\xd7\x92\x8c\x69\xdf\x65\x14\x26\x7b\xce\xd1\x8c\xaa\x72\xf8\x29\x32\xfe\x2a\x5a\x5e\x4b\xe9\xd5\xae\x9f\x5a\x65\xed\x89\x08\x83\x09\x2c\xdb\xee\x10\x2c\x7c\x1e\x10\x5a\x74\x14\x37\x50\x22\x13\xc6\xf0\x7a\x81\xa4\xa8\x32\x70\x37\x52\xe6\x2b\x9c\xd4\x25\x57\x0d\x34\x50\x0b\xa4\xd8\x6d\x32\x18\x1d\xce\xae\x6a\x7d\x2d\x54\xa8\x24\x70\xb3\x98\xe6\x55\xb7\xc9\xa3\xc8\x3e\xcd\xb2\x39\x57\x33\xd1\x16\x93\x97\x3c\x87\xb1\xff\x2e\x68\x5a\xfe\x7d\xdc\x08\xf0\xa9\x53\x58\xa4\x85\xa1\xb8\x72\xe7\x53\x88\x7e\xbc\x55\x01\x0e\x77\xd4\x86\x27\xdc\x2b\xc9\x62\x2d\x99\xc8\x86\xf1\x87\xf7\xf7\x84\x8f\x41\xa1\xd8\x60\x0e\x77\x29\x2c\xcf\xb9\xe5\x83\xe5\x71\xbf\xe4\x81\xfc\x93\x72\x3b\x60\x39\x44\x39\x1f\x74\xc6\x7a\x55\x52\x57\x32\x86\x17\x00\x69\x30\xf7\xb3\x0f\xf0\x54\xd6\xad\x6b\x8a\x3d\x62\x7a\x36\xe8\x6a\xbc\x28\xf4\x2d\x01\xd6\xf9\xd6\x50\x64\x89\x9c\xe5\x0d\xa8\x7d\xad\x48\xeb\x13\x1b\x1f\x24\x74\xe2\x26\x7a\xb0\x51\xbe\x6c\x53\x00\xb2\x34\x45\x7b\xa5\x82\x86\x67\x9d\x50\x56\x22\x95\xbe\xc7\x83\xa0\xc1\x6f\x14\x6e\xd5\xce\x34\xc0\x3c\xcd\x84\x35\x6d\x72\x25\x9e\x26\x4e\x44\xd2\x59\x4e\xbe\x04\x38\x6a\x68\x6a\xc8\x1c\x5f\xad\x29\xe2\xc4\x19\x4d\xa7\x85\x3b\xbf\x36\x3e\x33\xc3\xc5\x90\x90\x05\xf7\xa5\xce\xfb\x07\xa3\x3a\x74\xae\x6d\xc3\x6d\xd1\x09\x16\x20\x19\xf0\xf5\xe0\x0d\x10\x9a\x37\x09\x5a\x06\x1e\x01\x73\x7e\xb3\xbe\x57\xb5\xd5\x4c\xc7\x81\xb3\x0d\x1e\x37\x86\xc7\x8d\x9f\xf6\xf5\x5f\xf7\x4f\x5e\xf4\x57\xcf\x24\xc6\xb4\x43\x03\x04\x2c\x9c\x68\xbd\x18\x24\x9e\xd0\x01\x53\x0a\xed\xd2\xf9\x4b\x09\x1a\x21\x29\x86\xca\x6a\x85\x74\x52\xf3\x19\xfb\x43\xa2\x71\x91\x66\x1b\xac\x61\x2c\x66\xda\xf3\xe6\xf1\x84\x26\xde\xa3\x7a\xa5\xb7\xef\x77\x1a\x03\x55\x6f\xb5\xd5\xe8\x8b\xa6\x82\xfa\xed\x54\x65\xa0\xe3\x0f\xa5\xaa\x6e\x31\xd7\xba\x28\x3c\x85\x3b\x5a\xc8\x9d\x14\x27\xa0\x0f\xc2\xa0\xc9\x28\xb8\x21\x82\xbe\xaf\xc4\x6d\x50\xec\xb8\x41\xd4\x52\x1f\xb2\x07\x57\x89\xcf\x3b\x5b\xd5\xde\x04\x38\xf0\xe1\xfb\x43\xb5\xc0\xce\x1f\x47\x83\x8b\x0e\x06\x36\x73\x8f\x72\x36\x80\xe2\x57\x85\xd3\x42\xa2\x09\x08\xcf\xe9\x1c\x69\x56\x47\x77\xbd\x16\x53\xf2\x0c\xc4\x1f\x7d\xd8\x6f\xf1\x3c\x4c\x7e\x38\x69\xb3\x24\x49\x4d\x8e\x90\x32\x69\xd4\x93\x5b\xd2\xac\xa2\x4e\x6b\x09\x60\xcf\xaa\x1e\xf4\x4c\x3d\x18\x30\xf9\x60\xb8\xf4\x03\xc0\x86\x91\x6a\xfd\x9c\xe2\xb6\x99\x35\x18\xc3\xbb\xd7\x70\x59\x0c\x90\xc8\x09\x59\x5c\x43\x84\x83\x13\xb1\x73\x78\x7e\x0a\x0d\x7b\x0b\x73\x06\x7f\x78\xcd\x23\xc4\x35\xaf\x84\x93\x0b\x2d\xa2\x15\xac\xc8\xf8\xb7\x2b\xd2\xdc\xda\xcd\xf9\x1d\xd0\x37\x51\xb8\xc8\x97\x2f\xbb\x83\xeb\xf0\xfc\x14\x9f\x38\x01\x06\x5f\xae\x16\xa4\x13\xda\xb9\xac\xf3\x71\xc5\x6b\xbb\x40\x27\xcb\x28\x79\x5a\xa8\xe1\x1c\x60\x38\x06\x8d\x64\xf7\x61\x7c\x8b\xaf\x64\x8e\x60\xf8\x7c\x9c\x88\x02\x7d\x77\xce\xcc\x43\x1b\x91\xbe\x15\xa5\xfe\x4a\x46\x24\x66\xfc\xf1\x3e\x96\x47\x31\x22\x89\x8c\xfe\x58\xfa\x83\x13\xff\x26\xcd\xbe\x41\x75\x00\x74\x7d\xf2\x8b\xe9\xb8\xcc\x2d\xe8\x96\xe0\xa4\x70\x2d\x8d\x98\x9c\xba\x83\x58\xab\x31\x15\xd7\x07\x27\x3e\xe9\xa7\x3e\x4d\x15\x1d\x0e\xb0\x75\xa3\xa7\xc4\x3f\x0d\xbb\x9c\xed\x29\xad\x70\xe7\xe3\xbd\xfb\x98\x9f\x7b\x87\x07\x1a\x6e\x09\xa7\x79\xec\x97\x88\x24\x8d\x57\x13\xa4\xca\xdd\xb4\xc3\xb1\x07\x1e\x0b\xd3\x64\x99\x10\xc1\xc7\x15\xf3\xda\xb7\x92\x89\xba\x5c\x72\x9b\xcd\x85\x61\x46\x03\x3e\xaa\xb1\xbc\x28\x5a\xdf\x12\x0d\x94\x06\x4d\xc7\xfb\xf9\x23\x05\x28\xa9\x46\x27\x37\x5b\x55\x70\xf2\xe5\x4c\x1b\x95\x61\x06\x98\xb4\x8b\x98\x19\x35\x51\xf6\xc0\xa0\x36\xe8\x72\x92\x53\xf4\x2e\x47\x86\x71\x18\x4c\x10\xad\x0b\x14\xa6\x73\xcf\x3d\x0e\xb6\x1a\x81\x00\x3a\x39\x7a\xc5\xb3\xeb\x5b\x5e\xe7\x06\x0a\xed\xb9\x95\xc8\xc5\x38\x42\xad\x23\x56\x22\xd4\xee\x6e\x1c\xa8\x95\xaa\xab\xdf\xc4\x1d\xd9\x8b\x7a\xbd\xa4\xf7\xec\x07\x7d\xc7\x88\xc0\xd2\xd7\x76\x8c\xf1\xc6\xea\x92\x5b\x99\x81\x2b\x4a\x4e\xa3\xe8\x42\x19\xd8\x2d\x42\x90\x18\x4f\x01\x38\x57\xe8\xc5\x69\x1d\xac\xd6\x80\x56\x74\x3c\xea\xab\x7f\xcd\xd5\xfd\x8a\x8e\x26\x7a\xd0\x25\xc6\xab\x21\x0a\x56\x0b\xc1\x64\xe9\x14\x58\x0e\x04\xda\xd3\x50\xf3\xef\x43\x2e\xef\x1b\x14\xa7\xa5\xff\x00\x71\xae\xe8\x2e\xf4\xa7\x15\x85\xbe\x35\xcc\xde\xea\x60\xf4\xb7\xd1\x04\x2a\x6e\x1f\x75\x54\x3a\xfa\x8d\xdb\x6a\x6e\x58\xa2\x7d\x34\x72\x6b\xe7\x56\x14\x85\xfb\xef\xfb\x76\x93\x99\xac\xea\x91\x9c\x29\x2c\x7f\x96\xc6\x7b\x60\x28\x9f\x7d\x2f\xaf\x75\x55\x91\x2f\xb5\xdc\xef\xf6\x08\x42\x97\xf5\x8d\x30\x10\xbd\xf7\x19\xf2\x6e\x18\x66\x42\x89\x9a\x5b\x08\x84\x10\xa8\x23\x08\x94\xee\x23\x92\x69\x5c\xd9\xb9\x78\xb8\x30\x10\xf4\xfe\xe1\xa1\x6f\xc1\x63\xe1\x46\xca\x2f\x18\x33\x41\xe0\x9c\x7d\xf6\xc6\xe0\x0b\x85\x3d\x1b\xb2\xf9\x3f\xc8\x66\x40\xb7\x2f\x99\x0d\x13\xb6\x77\x58\x54\xf3\xa8\xd5\x58\x4b\x0f\xd5\x52\x69\x4f\x93\xe7\x1d\xd5\xda\x98\x33\xff\x93\xfb\x3c\x7a\xab\xc1\xbf\xaf\x99\xad\x06\xbf\xd5\xe0\xd7\xb8\xb6\x1a\x7c\xf7\xda\x6a\xf0\xdd\x2b\x08\xf8\x8f\x32\x2c\x41\xbd\x49\xcf\x92\xf7\x0d\x10\x3b\xd3\x96\x42\xac\xa0\xe2\xf1\x3b\x3d\x45\x1c\x0e\x92\x5b\xbe\x98\x28\x61\x09\x51\xc7\x3b\x05\x5f\xfb\xf6\xbe\xa9\x9d\xb2\x43\xba\x71\xb4\x59\xfd\xce\xf7\x58\x3e\xd1\x53\xac\xc6\xf3\xb7\x8d\xf8\xc2\xe7\xbb\x86\xe2\x9d\xee\x7b\xa8\xaf\x8b\x1b\xc8\xc4\x84\x5d\x08\x4f\x61\x92\x3c\x7c\x19\x35\x25\x17\x96\xcb\xc2\xb4\x07\xee\xe5\x1d\x07\xf8\xfa\x07\xea\x43\x5a\x67\xa1\x26\x62\x58\x2b\xb1\x2d\x72\x8a\x12\xcf\xe2\x8c\xce\xf6\x86\xbb\x42\x0e\xa7\x53\xf6\x5a\x64\xfa\x46\xd4\x38\xb6\x27\xef\x2a\xae\x9c\x25\xf4\x9c\xcb\xc2\x8d\xac\x1f\xe1\xd6\xb9\x0a\x74\x5e\x69\x88\x2f\xf2\x68\x87\x65\x4d\xd3\x58\x52\xa7\x08\x70\xc7\xdd\x4f\x89\x44\x55\x2d\x6e\xa4\x6e\x8c\xcf\x3b\x6d\x2c\x1e\x4a\xc6\x92\xed\x31\x97\xb3\xc0\xba\x19\xd2\xc1\x6a\x91\xe9\x3a\x6f\x97\xaf\xb1\xdc\x36\x26\x2d\x65\xcf\x30\xa6\x36\x5c\x38\x25\x8c\xe3\x03\xd2\xd2\x86\xd4\x67\x60\xc0\x06\x68\xa7\x9b\x03\x04\xd6\x8a\x01\x4c\x8d\x48\x02\xc6\xd2\x0f\xab\x84\xa4\xc2\x09\x75\x8b\x68\xe2\xbf\xc2\x1f\x8f\xda\xb5\xd3\x26\x67\x48\xd3\x66\x17\xb7\x99\x0e\x12\xec\x13\xee\x04\x4a\x64\x88\x07\x71\x02\xcb\xd7\xab\xf5\xc7\x68\xf9\xbf\xa6\x67\x1d\x16\xce\x1a\x41\xf1\x14\x89\x94\x15\x59\x14\xb2\x2c\x1b\xeb\xf6\xc1\x84\x9d\x62\xdd\x2d\xd8\x34\x64\x2a\x4f\xdb\x9a\x4f\x51\x9b\xb5\x73\x1f\xe2\x6b\xb8\xe0\x1b\x1b\x2e\x00\xc7\xba\x53\xfd\x3a\x9e\xb4\x18\x4d\x4f\x2b\x81\x39\x4c\x6e\x7e\x7d\x8e\x53\x72\xf7\xda\x90\x59\xe9\x35\xe0\xd6\xc2\x6b\x38\x33\x08\xaf\x41\xac\x18\xbc\x86\xdc\xfb\x78\x0d\xa5\x17\xe2\xb5\xac\x1d\x82\x64\x07\xcf\x5c\xa2\x25\x26\xab\xa3\xd2\xf9\x64\x85\x04\x08\x39\x77\x3a\xa7\x84\xba\xd4\x7f\x88\x65\xf6\xa7\xae\xf9\x6b\x9f\xbc\x1a\x4e\x21\x7e\xc3\x65\x01\x15\x13\x52\x19\x99\x0b\x64\x05\x22\xc9\x31\xd8\xfb\x0e\xaa\x90\x76\x92\xdd\x9d\xf0\x1c\x97\xbc\x1a\x5f\x8b\xc5\x40\xd3\x3d\xd8\x4a\x5c\xee\x28\x8e\x44\xc9\xab\xde\xad\x63\x31\xc9\xe0\x67\xd2\xee\x0b\x2c\x52\xc1\x0f\xaf\x48\x35\xf2\x75\x33\x6d\xcd\x4e\xa6\xcb\xaa\xb1\x22\x52\xa1\x48\xd9\xb9\xb7\x5e\x91\x40\x35\x1e\x94\x5c\xf1\x99\x18\x87\x66\xc7\xed\x71\xb1\x36\x75\x78\x7c\x0d\x2c\x06\x87\xc5\x14\x8c\xaf\x47\x57\x4e\x93\x5e\x83\x15\xf4\xb2\x8f\x52\xd4\xcb\x86\x2f\xec\x65\x1f\xbf\xb8\x97\x05\xb0\x85\xe1\xf7\xfd\x6b\x0f\xfe\xd0\xd9\xf9\x64\x2a\xbd\x6f\xe7\x27\x28\xc3\xa1\x1d\x69\x98\x2e\xa5\xb5\xc2\x27\x55\x87\x9d\x0c\x49\x30\x71\xf1\x3b\xc9\x1c\x88\x5e\x61\xe6\xb4\x78\x17\xe8\x55\x23\x83\x1e\xbc\x6d\xb7\xd2\xa0\x09\xae\x98\x2c\x2b\x24\x7b\x00\xd9\x31\xf6\x9a\x32\x45\x87\x42\x4f\x32\xc8\xde\x64\xe2\x1d\xc4\xc8\xf0\x61\x5b\x31\xb5\x15\x53\x5b\x31\xf5\x31\xc4\x14\x62\x02\xf4\x87\xd8\x48\xc4\x93\x6f\x94\x40\x28\xf9\x95\x28\xd8\xcf\x8d\xa8\x17\x4c\xdf\x88\xa8\x32\x0b\x88\x6a\x9d\x22\x8b\xb5\x4d\x14\x29\xef\xab\xc9\x3e\x50\xb7\x04\xd8\x0b\x27\xef\xaa\x5a\x20\x76\xd8\xe0\x87\x42\xf7\x01\x29\x04\x28\xce\x42\x98\x99\xd8\xa1\x85\x69\xd5\x89\x8b\x8b\xd7\x82\x1d\x9e\x1d\x0f\xe9\x79\x7c\xe8\x46\xff\xe1\x7b\x86\x08\x87\x32\x7c\x03\xe7\x5e\xc8\x8c\x0e\xc1\x65\x76\x2d\x16\x23\x2a\x40\x20\x96\x72\x7f\x33\xd6\xf2\xa4\x54\x89\xfd\x20\xb6\xd3\xeb\x11\xf8\x0b\xfa\x51\xe3\xa5\x6d\xf9\xc1\x7d\xa0\xfe\x87\xde\x14\x7a\xf1\x75\x17\x9d\x1e\xae\x56\x60\xdf\xf2\x38\x03\x61\x81\x02\xb6\x02\x48\xd8\x07\xeb\x16\x60\xc0\xf2\x84\xd3\xf8\x91\x06\x2b\x6c\xc1\xa4\x92\xfd\x5a\x2c\x76\x0d\xa1\xd0\x69\x65\xe6\xb2\xf2\xfc\xea\x20\x27\x69\x57\xb2\xef\xa1\x64\xc4\x37\x81\x12\xf1\x54\x8d\xd8\x99\xb6\xee\x3f\x27\x50\x03\x07\xfb\xf8\x58\x0b\x73\xa6\x2d\x7c\xf2\xa0\x87\x1b\x5f\xed\x23\x0d\x36\xa5\xe5\x90\xdb\x1a\xaa\x3d\x01\xf5\xc5\x57\x46\xc1\xa0\x52\xb2\x78\x98\x18\x69\xd8\xa9\x62\xba\xf6\xa3\x6a\x3d\x65\xac\xa1\x26\x7c\x60\x3f\x4a\xb6\x5a\xd1\x06\x4d\x86\xae\x93\xb9\x78\x4f\x73\x21\x9d\x4a\xfa\x6f\x20\x96\x08\xa9\x71\xa1\x9c\x0b\x68\x4b\xb9\x15\x33\x99\xb1\x52\xd4\x33\x40\x2c\xcc\xe6\x43\x4f\xf1\x50\xe7\x22\x5e\x03\x9e\x8e\x78\x0d\xba\x0e\x41\x45\x79\x01\x85\x7a\x1f\x47\xfd\xc1\xb6\xf1\xb8\x2e\x79\xe5\x96\xe0\xff\x71\xa7\x32\xac\x82\xff\x0b\xb4\xc8\x66\xc2\x0e\x99\x91\x6a\x56\x88\xe4\x3b\x0a\xc1\xc5\xcd\xb8\x16\x9c\x79\xfb\x73\x23\x6f\x78\x21\xb0\xb0\x96\xab\x40\x5a\xa8\xa7\x4b\x4a\xd7\x88\xb8\x91\x9d\x5c\x0e\x4e\xdd\x9d\x6b\xb1\xd8\x19\x2d\x2d\xdb\x9d\x53\xb5\xd3\x82\x9f\x26\x0b\x35\x28\x17\x10\x8f\xd9\x81\xef\x76\x3e\x8d\x9e\xf6\x08\xcc\xd8\xc1\xd6\x24\x45\x49\x8f\x0a\x8e\x71\xf9\x61\x23\xda\xdd\xd6\x57\x51\xb2\x5d\x44\xf7\xb4\xd9\x0c\x54\xb4\x3d\x78\xe8\x17\x40\x43\x86\x2a\xa1\x1b\x60\xfc\xb1\x5f\x7d\x88\x40\xfc\xb5\x82\x44\x07\xe0\x8b\x3d\xa8\x4c\x82\x45\xd6\x66\x8c\xdf\x31\xe2\xdf\x43\x10\x5f\x4f\xd9\xf3\x96\x6a\x0d\xc2\xa5\x4e\xad\x22\x98\x19\xa5\x2d\x93\x2a\x2b\x1a\x8a\xdf\xc3\x4f\x31\xe8\xfb\xb0\x86\x77\xf0\x85\xdd\x36\xeb\x57\xb4\xcf\x71\x5f\xc2\x0e\xe8\x66\xfc\x42\x02\x78\xc8\x71\xc5\xd1\xde\xe4\x68\x4d\xd7\xaa\x92\x4e\x29\x02\xb3\x54\xbf\x7c\x2e\xaf\x6a\xc1\x8e\xe6\x5c\x29\x51\x44\xf8\x8b\xe4\x2b\xe5\xd6\xf2\x6c\x8e\x69\x26\x9c\xb9\x7d\x5c\x08\xbb\x6b\xd8\x5c\x43\x4c\x31\x9b\x4b\x15\x10\xc9\x54\xc0\x21\x6d\xa1\x18\x36\x40\xaa\xd9\xd7\x40\x1a\x90\x8f\x71\x97\x08\x19\x69\xdd\xc5\x4c\x88\x29\x4f\x63\x4b\xed\xd3\xbd\xa7\xe5\xb8\xa2\x3d\x0f\x23\x8f\xe7\x32\x90\x06\xc2\xbd\xef\x67\x7a\x2c\x83\xbf\x5b\xaa\xa9\xa8\x6b\x9c\xa1\x2b\x41\x3f\x60\x72\xca\x1a\x15\x25\x8f\x23\xfd\xdb\x5c\xdf\xb2\x5c\xb3\x5b\x01\xd9\x42\x4e\x81\x80\xf4\x73\xe3\x55\x8f\xa8\xa7\x50\xa9\x92\xe9\xb2\xaa\x75\x29\x43\xfa\x36\x2d\x8f\x8d\x41\x0d\x16\xcd\xda\x6c\x0d\xe9\x2c\x16\x8d\x4a\x69\xd2\x9f\x1f\x31\xcb\xeb\x99\xb0\xee\x19\x4c\x35\xe5\x95\xe8\x89\xa8\xb8\x69\x3e\x9f\x41\xf9\xf3\x76\x03\x81\x5e\x32\x6a\xbf\xc2\x8c\xc7\x5e\xfb\x5f\x41\xa2\x01\x54\xc1\x4c\x75\x9d\xf9\xb4\x46\xcf\xc9\x87\x04\x4e\x6e\x15\x7e\x4f\x07\x67\xa3\xac\xe9\xc9\xa7\xd4\x87\x59\x0f\x97\xc2\x0f\x3f\x9c\x0d\x43\x88\xb4\xdb\xb6\x77\xd7\xaa\xbb\xd5\x75\x91\xdf\xca\xdc\x27\x75\xed\xb9\x9b\xf7\xfb\x8d\xc0\x06\xf9\x91\x7a\xef\xf4\xdb\x5b\x99\x0f\x34\xf8\xd0\x54\x3a\xe8\xbe\xa4\xcf\x0d\x3a\x83\x51\x97\xb9\x50\xd6\x09\xcb\xda\xb0\x3d\xf8\xc5\x3e\x3b\x91\x08\x5e\x05\xbf\x87\x54\xb4\xf2\x4a\xaa\x16\x18\xad\x9d\x54\x77\x5c\x3a\xb9\xe1\xcd\x7b\x23\x2c\xc2\x0e\x41\x95\xb9\xb6\x73\x66\x64\xd9\x14\x96\x2b\xa1\x1b\x53\x2c\x7a\x2e\xed\xc7\x3a\xb1\xd3\x42\xbc\xc3\x1d\xde\x5f\xe9\x09\x4d\xa5\xca\x0f\x14\x57\xb5\x58\x83\x4b\xda\x4f\x5b\x9b\x98\x1f\x04\x4d\x28\x60\x67\x89\x77\x22\x23\x58\x85\xaa\x68\x66\x72\x2d\x1c\x9d\x2d\x83\xf8\x5a\xbf\xfe\x30\x06\xf1\x96\x28\xb9\x31\xa2\xc5\xfc\x25\x90\xbb\x4d\xe9\x25\xc3\x13\x7e\x6f\x56\xbf\xbc\x5c\x4d\xf6\x9d\x8b\x4a\xa8\x1c\x48\x87\x9e\xb7\xfb\x0f\x3b\xbf\xb1\xb1\x27\xb2\x9f\x61\xce\x0a\xcf\x1c\x94\x9c\xd2\x51\x82\xe4\x5c\x17\xb9\x61\xe2\x9d\xad\xb9\x3b\x0e\x4a\x27\xf8\xc3\x6f\xa6\x8c\xab\xbe\xa2\xfd\x73\xa1\xac\x65\x9f\x48\x03\xcd\x3f\x53\x0d\xd4\x0c\xca\x65\xbf\x6b\x62\x06\xfb\x76\xf4\x92\x8f\x07\xa6\xb5\xc7\x03\x94\xa4\x83\x49\x21\x11\x56\xd0\xcf\xb7\x25\x55\xcb\xd8\x3e\x6b\xd2\xd0\x9b\x15\xa4\xd4\x9d\x5e\x6d\x70\xb3\x6e\x39\xe9\x1f\x17\x27\xfd\x14\x10\x52\xfb\xd3\x86\x50\x3b\x1d\x9f\x1d\x7d\x48\x6a\xeb\x87\xf8\xe8\x68\x47\x45\x67\xb2\x9b\x37\xdf\x10\x21\x8d\x31\xe3\x66\xa3\x2d\x8b\x6c\x94\x5a\x4f\x9a\x6f\x9a\xb1\x9b\x5b\x6e\x84\xed\xe3\x49\x4e\x15\xcc\xb6\x3d\x27\x72\xe2\x95\x4f\x5f\x21\xef\x3d\x20\x8f\x78\xd4\x50\x36\xfe\x2b\xe9\xa2\x2a\xb9\xd3\x69\xa1\x7e\xdc\x3d\xad\x88\x08\x99\x65\xd8\x46\xee\x66\x3b\xe3\x76\xed\x8a\xdd\xde\xa7\x31\xf5\xf6\xcd\x9b\xd3\xe3\x21\x87\xd0\xb5\xe7\xb5\x55\xf8\x77\x3a\x8c\x93\x50\x4c\xd6\x28\xf9\x73\x13\x1b\xda\x80\x76\x1e\x06\x8e\xee\xdf\xc4\xe8\xcc\x32\xd1\x86\x09\x8e\xa5\xb9\xee\x4f\x0d\xb4\xd4\x64\xba\xdd\xbf\x39\x3a\x61\xf4\xe9\x07\x79\xe7\xef\xe3\x9e\xef\x4b\xec\x31\xcb\x44\x1b\xb8\xcb\xa5\xb9\xde\x00\xad\x50\x5f\x1b\xb8\xca\xcf\xd6\x2b\xc9\x79\x98\x91\x86\xae\x85\xe7\x99\x07\x22\x4a\x8c\x85\x6e\xd8\x2d\x21\x6f\x93\x85\x78\x29\xab\x67\xec\x44\x99\xa6\x16\x6d\x86\x56\xb7\x29\xa7\x6f\x7d\xb0\xbd\x08\xe0\xe6\xe6\xd9\x60\x51\x89\xa1\x57\xea\xe7\x12\xe6\xa8\x78\x6d\xc1\x90\x1b\x66\x21\x85\xe6\xbc\x9c\x8e\x3e\x50\x1f\xb2\x92\x4e\xa7\xbe\x36\x63\x44\x30\xbc\x81\x72\xc8\xdf\xe4\xd6\x4e\x84\xcb\x1f\xaf\x96\xe7\x81\x0b\x83\x1d\xe4\xe2\xe6\xc0\xe4\xfc\xe9\x08\x1e\xe3\xab\xdc\xd3\x3e\x71\xc3\x76\x9e\xee\x4c\xd8\x85\x2c\x65\xc1\xeb\x62\x91\x50\x03\xb7\xf7\xb9\x63\xd7\x37\x08\xd9\x2c\x4f\x76\xd8\x9e\xae\xa1\xe5\x8c\x2b\x56\x08\x0f\x02\x46\xbb\x7a\x81\x76\xc7\xfe\xc3\x10\x91\xec\xc1\x44\x8a\x50\x5a\x0e\xb4\xd6\x72\xaf\x53\xd1\x79\x9f\xf0\x3c\x1c\xb7\x07\x9e\x54\xee\x14\x9c\xb0\x37\x74\x7c\x91\x5e\x80\x8b\x01\x36\xb3\xbf\xe3\x61\x4d\xd6\xc3\xf3\x87\xac\xe5\xd9\x58\x0e\xdd\x3d\xb4\x81\x5e\xd7\x7b\x32\x93\xf6\xb5\xa8\xf4\x00\x3a\x1c\x36\xd4\x89\x2f\x48\xeb\x3e\xd0\x46\x02\xb1\x23\xb7\x8c\xa3\x48\xca\x9a\x82\x3b\xa3\x0e\xa3\x0b\x13\x76\x7c\x72\xfe\xfa\xe4\xe8\xf0\xf2\xe4\xf8\x19\xfb\x86\x5a\x92\xb1\x1d\x30\x61\x97\x31\x55\x4b\x54\xf0\x46\x7c\x18\xe1\x59\x23\x12\xb1\x5c\xb5\x94\x73\x00\x5d\xcf\x15\x3b\x55\xd2\xb6\x64\xbb\x58\x17\x50\x68\x45\x99\xfe\xee\xd7\x14\xdd\x98\x49\x4b\x60\xc8\xd8\x98\xfb\x3a\x6d\x8d\xaa\xc2\x9d\xb2\xd9\x16\x75\x3f\x42\xe5\xaf\x9d\x9e\x4d\x18\xaa\x9e\x45\x72\x18\x1b\x2b\x30\x88\x7a\x84\x2c\x8c\x16\xb7\x9f\xe3\x61\x1b\x08\xd3\x3d\x17\x85\xae\x13\x3e\xf3\xc9\x64\x77\xc2\xdc\x31\xbe\x3b\xd9\xf5\x2a\x5f\xb1\x44\xba\x1f\x1a\x8d\x29\x7f\xd2\x05\x3f\x61\xec\x95\xaf\xaa\x04\x1c\xd4\xd5\xfc\xfd\x08\x59\x1e\xb1\xb5\x77\xb6\x8d\x47\x9b\x69\xae\xe2\x87\x12\x47\xd0\x4c\xde\x10\x9a\xe5\xc6\x62\x0a\x6d\x57\x07\x99\xc6\xf8\xcd\xc9\x52\x7e\xfd\x62\x73\xef\x86\x12\x67\xa0\x37\x23\xf1\x45\xef\x95\xe9\xb2\x44\x52\x9b\x79\xc0\xd9\x6b\xa1\xf2\x82\x74\xdc\x88\x95\x8f\x54\x3e\xd3\xb5\x36\x76\xe7\x64\xf0\x4d\x75\xac\xfa\xf0\x31\x55\x3f\xab\xd6\x9c\xba\x3f\x03\x30\x71\x49\x19\x0f\x41\x46\xc7\xec\x41\x78\xf8\xc1\xeb\x93\xc3\xe3\x97\x27\x93\x32\x7f\x84\x42\x5a\xa8\xbc\xd2\x52\x59\xb3\xae\x85\xcf\xed\x7c\x03\xe2\x3d\x74\x7b\x18\x1d\x2e\x34\xe7\xf7\x8f\xff\x20\x22\x06\x23\x70\xb7\x68\x75\x59\x5d\xe9\x42\xcf\x56\x53\x07\xdf\x63\xd9\xfc\x0e\x49\x25\xc6\x7c\xec\xd6\xe3\xe6\x8c\x5d\x3b\x1f\xca\xce\xb5\x73\x3f\x90\xed\x68\x05\xbb\xd1\xce\x3f\x8f\x01\xfb\x84\x66\xc4\xd2\x28\xa2\x3b\x07\xc4\x9b\xe7\x6d\x6b\x89\xd0\x2a\x51\x97\x12\xab\x50\x3e\xd4\xbe\xd8\xcc\xe0\xaf\x6b\x5a\x38\x49\x7e\xbe\xe6\x72\x4d\x47\xdd\xb7\x94\x1e\x20\x55\x2d\xc6\x81\x69\x66\x2a\x0b\x01\xa8\xea\x41\x43\x8a\xcf\x13\xef\x09\xf6\x7e\x63\xbc\xab\x58\x74\x3d\xc2\x11\xb0\x9b\x77\xc4\x23\xfe\x74\x51\x2c\x5a\x36\x41\xf2\x86\xf1\x19\x32\xc8\xd4\x14\x90\xab\x6a\x79\x23\x0b\x31\x03\xa6\x50\xa9\x66\x11\xf2\x60\x8c\x55\x48\x30\x95\x69\x70\xea\xa5\xfb\x2b\x22\xad\x86\x95\x75\xf6\xea\x12\x48\x67\x21\xa5\xa2\xb7\xc1\xe9\x1e\x08\x7b\x7e\x3c\x1e\x83\xeb\x6f\xef\x5f\xce\xf2\xc9\x8b\x7d\xf6\x83\xa0\xe7\x68\x60\xc5\xad\x65\x66\xd9\xed\x5c\x07\x8a\x52\xe8\x6b\x3b\xb2\xb0\xa0\x31\x8d\x8f\xee\x3a\x70\x77\x3a\x8d\x1a\x8f\xf2\xe4\x7e\x29\x80\xf7\xab\xcd\x33\x78\x8c\x56\xd2\x86\x0e\xd0\x81\xa5\xbd\x0f\x36\xad\xda\x23\x21\x7d\xc0\x9f\x0b\x9c\x99\x45\x59\x48\x75\xdd\xd2\x2a\x4d\x35\x21\xb3\x0a\xe6\xbe\xf0\xbb\xa6\x16\xbc\xb8\xfb\xc4\x58\x67\x8d\x6e\xec\xb4\xb0\x83\xc5\x23\x20\x5e\xe0\xa4\xc5\xb7\x5e\x78\x51\x02\x58\x2c\xea\x77\x76\x1e\xf5\x88\x49\x93\x19\xd9\x5f\xbc\x43\x33\x89\x6c\x57\xec\xf4\xe2\xe8\xe2\xf4\x93\x46\xfd\xee\x3a\x5c\xa1\x77\x8f\xda\x7a\x90\x3f\xaf\x97\x55\x35\x66\x45\xb3\xee\x2f\xd1\xf5\x72\xae\x6b\xcb\x8b\x0d\x08\xce\x6c\xce\xab\xc3\xc6\xce\x8f\xa5\x01\x80\xe1\x61\xd4\xbf\xa5\x56\xa3\x7a\x45\xa4\x6e\xf6\x1c\x75\xd2\x2f\x5f\xba\xef\xe8\xdb\xc3\x73\xc6\x1b\xb7\x1e\x2d\xb1\x72\x6e\x2c\x59\xce\xbf\xc5\x05\xd6\x40\x0f\x3a\x32\xd4\xe6\xaf\x8c\x8b\xbf\xeb\x21\x8d\xca\xa7\xab\x7a\xdb\xc6\xa3\xe1\xe4\x42\xa9\xff\x99\xc4\xa0\xa5\x92\x56\x72\xab\xeb\xc1\x62\x83\x49\x8b\xc1\x61\xd8\x18\xab\x4b\xda\x45\xa7\xfe\x0e\x48\xc8\x02\xfd\x6d\xe9\x47\xad\x37\x11\xac\x4f\x18\xf3\x53\xe5\x6c\x45\x9e\x89\x4e\x99\xcd\x08\xd8\x32\xb1\x6d\x19\xee\xf9\x8a\x9c\xe8\xc0\x5c\x54\xfc\xf5\x59\xc2\x27\xdf\x52\x53\x7a\x12\x60\xf2\x62\x66\x5a\x29\x91\xf5\xe1\x56\xee\x3f\x25\x3f\x0f\x23\xda\xe4\xcf\xaa\x13\x4f\xc0\x21\xfa\xef\x86\x17\x38\xb4\x67\x9b\x74\xbe\xa7\x53\x3a\xcc\x1b\xa7\xab\x84\x5e\xbe\x5d\x12\x67\xc1\xdb\xd6\x18\xe4\x65\xc2\x11\xb1\x35\x57\xc6\xad\x93\xd4\x9f\xb1\x4b\x09\x10\xbb\x6c\xcf\x66\xd5\xfe\xc6\x46\x6a\xa8\x72\xd8\xa2\x51\xb1\xb2\x8a\xef\x7e\x89\x4b\xe3\x45\x28\x87\xed\xf7\x9a\x1b\x4f\x72\x80\xdd\x3e\x8c\xdf\x96\xda\x0a\xeb\x28\x1e\x2f\x54\x10\xd9\x0b\x69\x2c\xd6\xd1\xe0\xcd\x00\xe3\x82\xf5\x84\xce\x16\x38\x67\xba\x66\xb2\xfa\x07\xcf\xf3\xfa\x19\xea\x11\x64\xab\xc2\xbf\x4d\x60\x0a\xe2\x2a\x64\xdb\xec\xd9\x45\x45\x1c\x71\x97\x47\xe7\x70\xa7\x61\x7f\xf9\xf3\x13\xb0\x0b\xbe\xfc\xe2\xcf\x4f\x7a\x2e\xc4\xc7\x5a\x55\xc8\x86\xf6\x89\x0e\x9e\x59\xf1\x99\x54\x91\x24\xd5\x22\x40\x27\xe3\xb4\xdd\x0b\x2c\xce\x70\xe7\x24\x09\x4d\xdc\x08\x6e\x55\x86\xd3\x7b\x48\x9d\x78\x5b\x75\xf1\x1b\xaa\xba\x60\xa1\x1a\x1f\x05\xeb\x20\x0b\x39\x6e\x10\x60\x75\x96\x05\x38\xca\xee\xf3\xc7\x22\xbb\xd7\x1c\xdd\x75\x57\x72\xba\x82\xe3\x14\x3f\x2a\xc4\x8d\xca\x53\x8f\xcf\x2e\xfe\xf1\xe2\xf0\x6f\x27\x2f\xe0\x5d\x29\x2b\xd0\x2d\x4f\xb2\x84\xd6\xc9\x59\xff\xf0\xe5\xbe\xbe\x73\x6b\xdd\x21\x1d\x22\xc1\x40\x75\x52\x0b\x14\x3b\x7b\x7e\x71\xdf\xac\x82\xbe\xe6\xac\x9a\xf6\x18\xbd\xc7\x16\xd7\x70\x3f\x05\xbe\xd6\x4d\x54\xce\x0f\x1c\x14\x89\x50\xf1\x13\x3f\x8a\x5b\x43\xf8\x8e\xbd\x5d\x1d\x6b\xae\x0d\xf6\xe0\x74\xbd\xf7\xc7\xbf\xdd\x88\xe1\x28\x0e\x1e\xf9\xfe\xa4\xa3\xdd\x4f\x87\xac\x87\x82\x75\xd8\xc5\xb6\xbc\xfa\xe8\x44\x18\x9e\x1d\xb5\x3b\x55\xdd\x79\x2a\x4c\x20\x28\xfa\x0c\x56\x6b\xb5\x8a\x6e\xba\xff\xe9\xb0\xb2\x59\xfc\xe7\x85\x67\x0b\x8c\xb2\x0a\x92\xba\xee\xbb\x18\xe5\x7d\x46\x26\x2f\x23\x62\xcd\x21\x91\x1f\xdb\x8f\xf0\x13\x24\xc9\x7b\x84\x07\x0c\x74\x7c\x43\xe5\x65\xe1\xd9\xc3\x6c\xc7\xd0\x5c\x17\x69\xe5\x5e\xab\x84\x71\xe3\x15\x39\xca\x35\x8f\x21\x59\x1e\xe4\x12\x62\x0f\xee\x1c\x0a\xc7\xd0\x0f\x6b\xba\x1b\x36\xe9\x6a\xa8\xe6\xda\x6a\x35\x70\x0d\xed\xaa\x46\x53\xc1\x76\x0e\x77\x1c\x61\xa5\x7b\x21\xea\x48\xde\x62\x05\x51\x08\xab\x3b\xcb\xc3\x1f\xdd\x5a\xf9\x00\x7b\x1a\x5e\x7f\x7c\x92\xa8\xca\x4f\x8f\x37\x20\x84\x3e\x37\xb0\xa3\xfb\x86\x09\x37\x96\x28\x9b\x0f\x54\xb9\xef\x1a\xf2\x63\x7e\x7a\x4c\xe6\x82\x2f\xcb\x37\xb4\xad\xd8\xdd\xfb\x6a\x23\xaa\x94\xae\xed\xad\xae\x87\x82\x8f\x4b\x9b\xeb\x64\x61\xd2\x77\x4b\x60\x1c\x9f\xa7\x14\xc1\xb7\x7c\xf4\x92\xe4\x02\x24\x49\x87\xb9\xfb\x2e\x89\xf2\x31\x04\xca\xe3\x11\x24\x1f\x47\x71\xf9\xb8\x48\x5c\x1b\x33\x7f\xfd\xf6\x18\x64\xb0\x7c\x63\xe4\x06\x75\x0b\xa5\x95\xbb\x1c\xdc\xcd\x91\xe4\xd9\x88\x9c\xad\xb5\x93\x43\xeb\x89\x93\x54\xc4\xfa\x96\x30\x38\x88\xac\x8e\x45\xe1\x66\x56\xab\x98\x0f\x92\xc0\xba\x46\x0c\x39\x13\x4b\x5e\x19\x24\xa5\xc8\xf5\xad\xba\xe5\x75\xce\x0e\xcf\x4f\x3f\xbd\x5c\xed\x5d\x09\x8a\xfb\xa1\x0f\xb7\x40\x5a\x0b\xda\xb6\x07\x19\xf8\x90\x24\xe4\xfe\xb8\x92\x16\x69\x9b\x31\x19\xdf\xc6\xde\x28\x77\x4e\x85\x4c\x16\x27\xe9\x9c\x54\xa3\x96\x22\xb5\x4a\x31\x9d\x59\x5e\x20\x05\x08\xbb\x12\xf6\x56\x08\xc5\x9e\x3c\x79\x82\x01\x8a\x27\xff\xf9\x9f\xff\xc9\x80\x94\x33\x17\x99\x2c\x97\x6f\x84\xbb\xfe\xf4\xf4\xe9\x84\xfd\xfd\xf0\xe5\x0b\xc6\x33\xb0\xe5\x10\xf9\x16\x5b\x86\xf9\x8c\x7f\x6c\x46\xec\x7f\x5f\xbc\x3a\x6b\x09\xe5\xd3\x6f\x61\xb9\x84\xd7\x9b\xb0\xe3\x28\xf7\x3e\x0e\x1e\x70\x3b\x87\xd1\x50\xda\x32\x3e\x9d\xe2\x82\xf3\xac\xf6\x24\x4c\x3c\xf6\x9c\x9c\xcd\xe1\x75\xa5\x82\xa5\x56\x40\x51\x80\x74\x5d\x84\x80\x8d\xc7\x71\xc4\x1a\x07\x68\x2b\x1c\x22\xd0\x95\x11\x2b\xe4\xb5\x60\x53\xf3\x4d\xad\x9b\xaa\x25\x4e\xa9\x85\x71\x06\x58\xc6\x95\x6b\x1d\x1b\x6b\x67\xc6\x88\x9e\xd8\x98\x9b\xce\x9c\xa0\x7d\x3a\x4c\x08\x99\xf6\xbc\xa7\x10\x23\x6e\x40\x5f\xa3\x85\x22\xc3\xcd\xc2\x63\xcd\x64\x48\xde\xf6\x3c\xbc\x0f\x2e\x2a\x42\x3f\x6c\x25\x23\x2f\xb4\x9a\xc5\x6b\xb0\xd5\x3e\x7c\x32\xe5\xa2\x12\xeb\x0e\xc6\x40\x84\x3a\xc3\xd0\xd3\xa1\x70\x7f\xc9\xab\x7e\x4c\x20\x69\x8e\xae\x6f\x33\xc1\xa1\xe4\x57\xba\xb1\x3e\x67\x8f\xbe\x07\xf8\x36\xab\xfd\xd0\xf7\xea\xc2\x60\x2c\x45\xc3\xf1\xfe\x0d\x44\xba\x95\xe6\xcc\xc1\xa9\x9d\xaa\xac\x23\x26\x78\x36\x67\xd7\x62\x31\xc6\x13\xa0\xe2\x80\x1e\x01\xa3\x7d\xec\xc6\x18\x61\x72\xd3\x74\x86\x4c\xe4\xce\x9a\xa4\xa9\xf0\x09\x96\x91\x7e\xe0\xd1\x27\xbc\xc1\x65\x48\x2f\x27\x2a\x2b\x15\x79\x28\x3d\x77\x65\xa6\x95\x25\x5e\xcc\xc0\x5d\x05\x09\xa3\x1d\x40\x02\x27\x61\x44\xee\x7e\x66\xde\xf7\xe4\x36\xab\xd4\x9d\x28\xff\x1f\x7b\x5f\xf7\xdc\x38\x6e\x24\xfe\x9e\xbf\x02\xe5\xdf\xaf\xca\xf6\xc4\xd2\xec\x5e\x36\xa9\xdc\xbe\xa4\x3c\xf6\x6c\xce\xb5\xf3\xe1\xb3\x66\x27\x0f\xbb\xb9\x0a\x44\xc2\x12\xcf\x24\xc0\x00\xa0\x3c\xda\x6c\xfe\xf7\x2b\x74\x03\x20\x28\xf1\x4b\x22\x3d\x96\x67\xcc\x97\x19\x53\x00\x08\x34\x1a\x8d\xfe\x6e\xcb\x7f\x14\x7c\xab\x37\xe4\x73\x07\x9f\x5e\xc5\x6c\x66\x24\xea\x6a\x22\x06\x9e\xa9\xcb\x24\x82\x88\x23\xd3\xdc\xb6\x75\x50\xf2\x80\xa8\x24\x4c\x50\x4c\x17\x16\x34\xe0\x27\x6c\xbe\xcd\x94\x22\x09\xac\x30\xa3\xf2\x8e\xb9\x44\xc3\x34\x9d\x92\x6b\x33\x49\x9f\x6d\x1e\x4b\x09\xae\x30\x40\xc4\xd0\x98\x30\x13\x84\xf9\xc8\xf1\x74\x7a\x8c\x57\x65\x4d\x5e\x88\xc1\x58\x33\x66\x15\xb9\xd1\xaa\xc7\x55\x50\xf9\x2d\xcd\x15\x56\xd3\x33\xa2\x05\x54\xac\x14\x90\xb7\x45\x2f\x1d\x33\x41\x07\xa6\x10\x0f\x9f\x91\xcb\x98\x8d\x5b\x09\x75\xbc\x3a\xa8\x03\x6c\xed\xd5\x67\xec\xfa\xa7\x23\x56\x3f\x6d\xaa\x7d\x6a\x71\xc8\x52\x92\xb1\x2a\x32\x8e\x5e\x72\x33\x1b\xa1\xb0\x99\x7b\xaa\xa6\x23\xe0\x6f\x2b\xb9\xa4\x7b\xc9\x22\x36\x95\x7a\xca\x9e\x94\xf0\x71\x75\x0b\x24\xb5\x3e\xd7\x4d\x28\x97\xb9\x1b\xc6\x40\xe0\xf1\xa5\x8e\xa1\x55\xf6\xdc\xf3\x10\x65\xea\x87\x8b\x25\x9b\xcf\x10\x27\x9a\xcd\xa7\xaa\xc8\x08\xd2\x4a\xf8\xab\x36\x8c\x3e\x86\xad\xd2\x02\xaa\x75\x96\xc4\x61\x4a\xde\xda\xab\x18\x91\x9c\xce\x95\x48\x0b\xed\x33\x51\xd4\xdc\xd3\x30\xa8\xab\xed\x89\x49\x9b\x5c\xb3\xe0\xd6\x06\x7e\x05\xaf\xb2\x71\x2e\x70\x7c\x46\x24\x3e\x43\x1d\x64\xf1\xf9\xca\xdc\x64\xf1\x19\x71\x17\x1c\xbb\x38\xf2\x4e\xb8\x61\x7d\xf6\x4e\x17\x11\x59\xe1\x6e\xc1\x47\x56\x2b\x64\x9d\x1d\xa3\x8a\x31\x94\xfb\x66\xc0\x2e\x9f\xe1\x5a\x5d\xbb\x2e\xab\x60\x3c\xbf\xbe\x1a\x51\x2a\x0d\x46\x6d\x90\x4b\xc3\x16\xcf\x92\x69\x9f\xa7\x02\xe0\x2b\x94\x4c\x0d\x4b\xef\x14\x48\x97\x25\x44\xad\x49\xcf\x10\xe5\xaf\x40\xb4\xd9\x5a\xf8\x0f\xe6\x32\x0a\x83\xb9\xaa\x15\x3a\x50\x19\x5c\x5e\x5b\x41\x55\x0f\xe7\xc3\x03\x24\xee\xcb\x17\x83\x0e\x54\x78\x01\xe8\x0f\x88\xd8\xd9\x7c\xaa\xb7\xe8\x8d\x03\x22\x99\xb1\xd4\x5c\x7a\x64\x43\x65\x93\x8b\xf8\x7b\xac\xf9\x4d\x39\x17\x1a\xf0\x46\x9d\x91\x14\xea\x91\x9f\xa1\x2a\xc6\x70\xa0\x81\xf7\x97\x0c\x8c\xa6\x23\xf3\x9c\xa3\x21\x0f\x19\x1d\x81\x08\x20\x11\xc0\xee\x7a\x1c\x4c\x22\x0f\x80\x4d\xe6\x29\x59\x95\x31\xcb\xf2\x57\xf0\xca\x8e\xef\x90\x48\x45\x4b\x96\x51\xac\x47\xe2\x00\x64\xe8\xf5\xbd\x4c\xb4\x66\x98\x75\x9c\xc9\x4c\x11\x71\x7b\x56\xb1\x1b\x1f\xad\xbe\x3d\x1a\x8b\x9f\x25\x0f\x21\x50\x13\x77\x42\xf7\x4d\x03\xd6\xf4\x54\xed\x06\x15\xe1\xc2\x9c\x4e\x90\xa6\x53\x28\x90\xc4\x37\x14\x96\x86\x89\x58\x21\xfc\x0f\x1a\x74\x0f\xa7\x8b\xd8\x57\x07\x71\xe6\x19\xd3\x67\x1d\xc4\xb3\x0e\x62\x8c\x11\x1f\x4c\x07\x11\x5c\xdc\x8e\x98\xd6\xe8\x23\xc2\x40\x3c\xa7\x94\x28\x53\x59\x04\x69\xa2\x0d\xca\x3b\x75\x84\x90\x55\x5b\xc1\xf1\x74\x7a\x7c\xec\x94\x14\xf6\x7c\x14\xfa\x76\xf2\x67\xc2\x78\x24\x62\x44\x2a\x33\xbe\x54\x1a\x98\xda\x52\x2a\x0f\xe7\x92\xb9\x6f\x85\xf6\x06\x18\x7b\x5c\x94\x18\x91\x42\x39\x97\x94\x1f\x1e\x94\x05\x2b\x19\x2f\x9f\x06\xcc\x02\xd0\x67\x4b\xb4\x1c\x58\xe9\x22\x93\x26\x59\x62\xf3\x13\x1a\x72\xc1\x94\x56\xe4\x04\x5f\x4e\xa3\xbc\x38\xb3\x0d\xa6\x19\xcb\x84\x5c\x9f\xf9\x46\xe6\xc7\x4a\x2f\xdb\xe2\x14\xb8\xb6\xa8\x90\x92\x71\x9d\xae\xbf\x5e\xfe\xcd\x81\xf8\x80\xd9\x37\x8f\x15\x43\xe2\x3e\xea\x9e\x2a\x5a\x96\x45\x04\x40\x7b\xe7\xa1\x0d\xf7\x90\x8d\xc0\x38\x2b\x95\x3f\xe6\x2d\xe3\x2b\xb2\xa2\x72\xef\x08\x8c\xba\xe7\x41\x38\xb6\x38\x59\x25\x4a\xec\x1d\xc3\x56\x3b\x64\x08\xbc\x99\xbd\x94\x51\x47\x2c\x0a\x9d\x17\xda\xde\x2e\xee\x6c\xbb\x94\x7d\xfe\x4c\x6f\x30\xbe\xdf\x1e\x8d\x38\xb9\x9c\x6a\xcd\x24\xff\x9e\xfc\xcf\xc9\x2f\xbf\xff\x6d\x72\xfa\x97\x93\x93\x9f\xbf\x99\xfc\xe7\xdf\x7f\x7f\xf2\xcb\x14\xfe\xf3\xe2\xf4\x2f\xa7\xbf\xb9\x3f\x7e\x7f\x7a\x7a\x72\xf2\xf3\x8f\x6f\xff\xfa\xe1\xfa\xf5\xdf\x93\xd3\xdf\x7e\xe6\x45\x76\x87\x7f\xfd\x76\xf2\x33\x7b\xfd\xf7\x9e\x83\x9c\x9e\xfe\xe5\xff\x8f\xb8\x08\xca\xd7\xef\x47\x23\xc1\xf8\x4c\x1e\x84\x8d\xa8\x8e\x3d\x32\xea\x12\xf2\x69\x52\x6a\xb4\x27\x09\xd7\x13\x21\x27\xf8\x91\xef\x89\x96\xc5\x58\xa4\xab\xbc\xfe\x1e\x8e\xc6\x94\x4c\x4c\x99\x01\xd3\x09\x36\x07\x48\x44\xd0\x31\x75\x44\xcd\xb0\xad\x63\x5b\xaf\x14\xb6\x3f\x3e\xeb\x83\xfb\x3c\x0f\xe8\xa9\x64\xf3\xd9\x7c\xe5\x6e\x4a\x33\x5b\x4d\xf9\xd9\x47\x69\xeb\x79\xf6\x51\xda\x7e\x9e\x7d\x94\x76\x7c\x9e\x7d\x94\xdc\xf3\xec\xa3\xf4\xac\x1f\x1c\xfe\x7c\xe5\xfa\xc1\x67\x1f\xa5\x5d\x9f\x67\x1f\xa5\xbd\x9f\x27\xe4\xa3\x84\x4c\x7e\x9d\xa7\x92\x65\xf3\x4b\x37\xa5\x83\xf5\x52\x52\x06\x1f\x22\x76\x1e\x45\xa2\xe0\xfa\x83\xb8\x63\x03\x0d\xb9\x1b\x32\xe9\xd6\xe8\x90\x12\xb1\x41\x46\xdd\x6e\x7c\x90\x02\xeb\x58\xfc\xe8\x08\xfc\xe3\x78\x9c\x23\x2d\xe2\xc4\xc8\xa8\x23\x1f\x16\x37\x6c\x98\x16\x9b\xc7\x2c\x2e\x7f\xb0\x24\x4d\x9b\xfd\x9e\x92\x73\x22\x59\x94\xe4\x89\xb9\x00\x20\x57\x10\xbc\xc7\xe3\xe3\xab\x38\x27\x5a\xb1\xf4\xd6\x56\xb2\xe5\x65\x98\xb3\x0c\xe4\x4f\x7b\xa3\xd4\x7e\x06\x79\x08\xe1\x6a\x8d\x12\xb5\x14\x45\x1a\x13\xc9\xfe\xd7\x31\x1f\x76\x36\x1f\xc2\x11\x42\x95\x2a\x2c\xa5\xfc\xac\x1d\x9c\xe6\x89\x4d\x2a\x76\x48\x64\x90\x7d\xca\x13\x09\x87\x6d\xc6\x22\xc1\xe3\xb1\x35\x24\x5b\xe3\x97\xbc\x02\xd8\x85\x58\x4c\xe2\x02\x1b\x40\x38\x26\x4d\x93\x38\xd1\x6b\xef\xcf\x81\xc7\xde\xb0\xad\x58\x3b\xd8\x22\x82\x2a\x37\x82\xd0\x3c\x97\x82\x46\x4b\xa6\x82\xaf\x21\x13\x6a\x13\x65\xf8\x28\xcf\xb4\x58\x24\x1c\xf9\x50\xe8\x63\x98\x95\x74\x4d\xa4\xd0\xce\x35\xad\xe1\x83\x1f\x82\xc1\xa0\x3b\x72\x1c\x5a\xae\xc1\x7f\x4d\x84\x43\xe0\xac\x92\xdb\xf0\x0f\x45\x44\x1a\xbb\xd4\xac\x7f\xfe\xc6\x30\xfe\x91\xc5\x62\x73\x09\x40\xd2\x4c\x2d\x48\x6a\x98\x27\x73\x31\x34\x77\xfe\x8f\xef\xc8\x52\x14\x52\x4d\xc3\x64\x7f\xdf\xc2\x3b\xd4\x70\x38\xc1\x41\x93\x94\x51\xa5\xc9\xb7\xdf\x90\x2c\xe1\x85\xb9\xf1\x47\x42\xbc\xb1\x78\xdd\x80\xcb\xfd\xd3\x77\x03\x47\x1b\x87\xbf\x6d\xe4\x6c\x73\xac\x98\x67\xd9\x5b\x7b\xc6\x31\xa1\x07\x56\xcd\xdc\x60\x76\xed\x95\x14\xee\x22\xd7\xe2\x91\x4f\xfe\x3f\x0b\x31\x5f\xeb\xe1\x29\x6c\xec\x38\xd5\xdc\x35\xff\x6d\x5f\xf6\x49\x15\x5b\x66\x8a\xdd\x63\x2a\x8f\x5e\xe3\x7b\x91\x28\xbd\x57\x85\xef\x32\xe7\xcd\x1e\x9d\x87\x5e\xe6\x0b\x23\x1f\x8f\x12\x49\x0f\x23\x39\x89\xce\x69\xa4\xa3\x88\x29\x20\x45\x2e\x29\x1c\x28\x77\xb1\xed\x9e\x1f\x3d\xd0\x6c\x33\x75\x49\x64\x1c\xf2\x8f\x50\xab\x74\x10\xb0\x86\xb0\xfc\x0e\xb1\x47\x82\x16\x0e\x56\xa5\x11\x2a\xe1\x0b\x2c\x2d\x9a\x15\xa9\x4e\xf2\xb4\x84\xdc\x8d\xeb\x60\x2f\xe0\xd0\x5a\x40\x03\xf5\x34\xc5\xa4\x57\x98\xfd\x1c\x2c\x2b\x27\x7e\x2c\xc6\x35\x56\xc8\x94\xe6\x1e\xcf\xa9\xa4\x1e\xfc\x91\xc8\x32\xaa\x4e\xad\xe1\x81\x82\x17\x8c\x2d\x03\x64\x7a\xd1\xb4\x9c\x71\xe0\x75\xf0\x58\x88\xab\x19\xa7\x7c\x6f\xf3\x5f\x35\xe1\x3c\x0c\x45\xc4\xbd\x77\xb4\xc7\x22\xf7\x1b\x18\x6b\x19\xe2\x57\x34\xba\x63\x3c\x26\x3f\x29\x07\xb8\x78\xcd\x69\x66\xf3\xc7\xe7\x52\x60\x15\x75\x16\x6f\xf4\x57\x67\x56\xed\x88\xa9\x4f\x5c\x02\x2b\xe4\xb7\x1e\x0b\x8a\x85\x1a\x29\x79\xb0\x19\xa8\x8b\xde\x29\x54\xe9\xca\x64\x15\x31\xc7\x3b\x9a\x7e\x8f\xb5\xf8\xd5\xde\xd9\xea\x48\x7d\xea\x28\x5b\xc6\x14\x4f\x21\x5c\xe9\xde\x72\x09\x69\xe2\x69\x6a\x48\xdc\xda\xe7\xfc\xd9\x40\xb0\xf9\x1a\xf4\x5e\x8f\x92\x79\x4c\xce\x87\xe7\x94\x3a\x96\xf3\xb8\x4a\xcc\x6e\x68\x2c\x14\x79\x95\x8a\xe8\x8e\x5c\x32\x10\x1a\x1e\xb2\xf8\xbe\x9c\xc7\x4f\xbb\x70\x66\x46\x17\xfb\x79\x8c\x4c\x48\x26\x78\xa2\x85\xdc\x87\x1e\x1f\x50\xa2\xc0\xe7\x52\x86\x7d\x32\xa6\x9b\x73\xf6\xa5\x14\x32\x34\x28\x3f\x0e\xea\xc0\x50\x5e\x75\x02\x94\x07\x5f\x01\x51\xdd\x9b\x8e\xfc\xbf\xa5\xb8\x9f\x68\x31\x29\x14\x9b\x24\x7b\x3b\x42\x0d\x06\xd4\x1d\x5b\x83\x57\xd9\x28\xa0\xb2\x83\x55\x24\x77\x2d\x40\xcf\x0e\xef\x0d\x7f\x77\xf3\xea\xf2\x27\xc5\xe4\x34\x94\x56\x5e\x32\x1d\xbd\x8c\x58\xbe\x7c\x69\x47\x78\xf2\x60\x75\x64\x73\x1c\xb8\xba\xd1\x90\x11\x88\x44\x9a\xda\x04\x63\xe2\x96\x5c\xb0\x7c\xe9\x3f\x77\x18\x70\x7b\xca\x35\xe5\x72\x21\xc6\x29\x37\x75\x6c\x46\xaa\x92\x0d\x78\x83\x54\x23\x40\x7e\x39\xdf\xad\x90\xf7\x21\xa2\xfb\x67\xac\xce\xb2\x4f\x29\xbe\x83\x00\xef\xe1\x94\xf4\x3b\xae\xd4\xf4\x0b\xe3\x87\xaa\x05\xfb\x9c\x77\x6a\x85\x6c\x5f\xdd\xa2\x30\x1a\xb3\x98\x88\x15\x93\x32\x89\x99\x22\x9e\x6e\x87\x3a\xa8\x24\x3d\x0c\xc8\x3f\xd7\x0e\x7c\x5a\x0e\x07\x87\xa3\x7e\x38\x06\xfd\x43\x85\x88\xc3\x9b\x2d\x22\x4e\xe3\x2c\xe1\x87\x81\xed\x7b\xc2\x4d\x45\x34\x65\x57\xef\x07\x4b\xeb\x76\x9c\xaa\xc0\x3e\xb3\x2f\x83\x9a\x02\x1d\x79\xf6\x7f\xf4\xb8\x4b\xb8\x88\xf7\x33\xa0\x3d\xb2\xd8\xbd\xa0\x9a\xdd\xef\xc9\x08\x4d\x4a\x92\xbf\x6f\x7f\x10\xcf\x9e\xb6\xd8\x7e\x10\x95\x42\x82\x53\x8e\x29\xff\x1f\x8b\xc9\xb2\xf8\x34\x8e\x21\x09\xc7\x0a\x8b\xb2\x6d\x96\x62\x73\x67\xf6\xfc\xfa\x8a\xfc\x15\x9b\x3f\x5e\x15\x14\x29\x34\x8a\x3c\x97\x22\xa3\xc9\x38\x05\xd0\x37\x07\xdd\xac\x87\x15\x02\xe1\xda\xb7\x25\xb6\xb1\x61\x8a\xca\x74\xc3\x85\x64\x31\xb1\xfa\x94\x2f\xac\xc4\xc3\x16\x3b\xfd\x65\x94\x78\x78\xa8\x2a\xd9\x81\x6a\xde\xc5\xef\x94\x5c\xb4\x43\x27\x60\x22\xbc\xaf\x13\x51\x8c\xab\x04\xdc\x1b\x02\x0f\x3c\x60\xb5\xc1\x2d\xdd\x07\xeb\x20\xdb\x7d\x46\xde\x88\x45\xc2\x1d\x15\x13\xd6\xab\xe6\x96\x26\xe9\x30\x70\x3e\xf3\xc9\x5f\x19\x9f\xac\x54\xfa\x9a\xd3\x79\xba\xbf\xcb\x64\xf5\x10\xf8\xe1\xc8\x0f\x29\x5d\x10\x06\x7f\xbc\x8c\x13\x65\xfe\x25\xb3\xd9\x1b\x30\x06\x17\xdc\xc9\x97\x60\xe6\xb4\x77\x8b\x0f\x8d\x46\x22\xf3\x78\x74\x01\x89\xf8\x68\x15\x3c\x82\xf1\x48\xc2\x63\xb3\x74\xa6\x2a\x4e\xc9\xb6\x05\xd6\x4a\xf1\x71\x77\xe8\xfa\x38\x67\xe4\xc3\x32\x89\xee\xae\x03\xfb\xaf\x90\xe6\x1d\x0f\x5e\x55\x98\x94\xcd\xdf\x1e\xeb\x36\xb2\xcb\xba\x1e\x4b\xa1\x16\x8c\xe7\x6e\x6a\x47\x4e\x67\x16\x82\xf0\x1b\x55\x4a\x44\x49\xe9\x7f\x00\x9a\xe8\xf2\xfa\x8e\xe1\xfa\x7e\x3c\xa8\x00\xc3\x39\x0e\x40\x90\xcf\xad\xe1\x5a\x1c\x46\xd9\x16\x54\x85\x5c\x4a\xc2\x1d\xdc\x1e\x0d\x08\x88\xe3\xa3\x95\x34\x2d\x87\xdb\x2e\x69\xea\xc4\xcc\x0d\x13\xb9\x0b\x78\xb5\x08\xe4\x44\x06\x5b\x43\x7b\x1b\x85\x7c\x69\x53\x5b\xcc\xe4\x51\x40\xb7\x7f\x68\x7a\x9d\xfa\x6f\xc3\x3f\x08\xdf\x59\xa3\x39\xd0\x9e\x5c\xe4\x45\x8a\x9e\xb5\xc3\x2b\xbb\x3a\x1b\x23\x7e\xe7\x11\x8c\xe8\x87\x56\xd9\xe9\x38\x0c\xcf\xdb\x3d\x5e\xf1\xcb\xa8\xef\x14\x88\x16\xdf\xfc\xe9\xbb\xef\x9e\x7a\xc5\xa7\x61\x8a\xbb\xc7\x2e\xf9\x34\xc8\xf4\x56\x93\x9b\xe1\xea\x39\x37\xc3\x73\x6e\x86\xea\xf3\xe8\xf6\xe1\xcf\x9f\x7d\x61\x94\xe8\xb6\x31\x22\xdb\x86\xe6\x57\x18\x18\x15\x37\x4e\x44\xdc\xe0\x0c\x0a\x9f\x23\x6f\xc2\x48\x31\x62\xc3\x73\x24\x3c\x67\x46\xf8\xba\x32\x23\x8c\x17\x23\x36\x56\x16\x84\xe1\xb1\x61\x5f\x4f\xc6\x83\xc1\x64\x63\x68\x5c\xfd\xe0\x68\xfa\xb1\x8a\x7e\x8c\xa5\xdd\x1f\x4d\xc3\x70\x5c\x8e\x57\xab\x6f\x71\x29\xde\x5c\x36\xfd\xe3\x63\x15\x24\xcb\xd7\xc2\x50\x97\x47\x14\x9d\xc9\x60\xcd\x03\x4e\x45\xec\x75\x77\xd7\x69\xf1\xde\xcf\x36\x1c\x04\xfc\xeb\xc3\xf7\x0b\x78\x36\x90\x0f\x73\x53\xff\xb2\xcc\xa3\x5f\x68\x05\xfc\x87\x32\x8f\xaa\x4a\xd6\x5c\xa7\x75\x04\x02\x09\x2c\x9c\x98\x87\x95\x69\x4a\xb2\x70\x7e\x7d\x45\x22\xc9\x20\xb5\x03\x4d\xd5\x94\xd4\x70\x78\xce\x80\x64\x39\x42\xc7\xd9\x51\xad\x59\x96\xeb\xa1\x98\xf7\x6c\x1d\xfd\xca\xac\xa3\x0f\x6e\xa5\x58\x16\x19\xe5\x13\x43\x2d\xc0\x3e\x5a\xf1\x3b\xd9\xb8\x0f\xa7\xc4\xd2\x05\x64\x2b\x40\x17\x0a\x21\xcd\x05\x4f\xfe\x59\xb0\x52\x5d\xe1\xb9\x8e\x03\x30\xee\xc0\x3c\x46\x86\x1d\x72\x54\x1b\x54\x24\x12\x5b\x41\x5c\x16\x20\x1e\x8e\x8e\x60\x04\x6c\x59\x45\xf5\xa6\x97\x0c\xb9\xb7\x6b\x48\x92\x50\xb6\xaa\xca\x87\x28\x20\xd2\x34\x15\xf7\xf8\xed\x90\x1f\x31\xfb\x67\xe6\x62\xf3\x92\xcc\x19\xc9\x12\x29\x85\xb4\x66\xa4\x70\x3a\xe8\x3e\x64\xe4\x4c\x26\x51\x60\x93\xd6\xe9\x63\xc6\xb4\xdd\x6a\x40\x15\x2d\x08\xe5\x18\xc0\x69\xfe\xef\x3c\xae\xe1\xdb\x8e\xde\xcd\xd9\x92\xae\x12\x51\x48\xec\xad\x05\x39\xb2\x3f\xc1\xdd\xbb\x16\x85\xd7\x9d\x17\x10\xa1\xe5\x57\xa7\x6a\xe0\xf4\xae\xfc\x11\x04\xdc\x58\x38\x75\xe4\x84\x7d\x4a\x94\xde\x5e\x8b\x03\x91\x2b\x39\xf1\x18\x98\xb7\x52\xb9\xb9\x60\x3f\xee\x1d\x7b\x5b\xc5\xb7\x70\xb4\x2a\xa7\xba\x9a\xc1\x4f\x5d\x7c\xaa\xcd\x58\x83\x21\xf3\x2e\x1c\xee\xe9\xf9\xb0\xe2\x2a\xf7\xac\x75\x75\x90\x8c\xf2\x33\x93\xdc\xfa\x78\x2f\x8b\x34\x89\xd6\x57\x97\xe3\x7a\x6e\xe0\x98\xee\xfa\x53\xde\x6b\xc3\xbc\x27\xaf\xa8\x62\x31\x79\x4b\x39\x5d\xa0\xd6\xe5\x64\x76\xfd\xea\xed\xa9\xc1\x22\xd0\xea\x5c\x5d\xd6\xba\x76\xcc\xc2\xc1\xdf\x3d\x56\x9c\x3b\xd9\x04\xdd\x68\x6c\xc3\xd6\xa8\x7b\x82\xef\xd1\x52\x00\x10\xcf\x13\x0c\x29\x9f\x56\xc3\x0e\x5c\x6f\x26\x89\x42\xf7\x0d\x97\xfd\x4d\x6d\x92\xea\x55\x16\xdf\x3d\x24\x00\x02\xbd\x79\xdb\x2a\xfb\xd9\xc0\x7a\xd8\xb9\xaa\xd5\x48\xb4\xa4\x9a\x2d\xd6\x97\x2c\x4f\xc5\xda\x20\xc0\x75\xa0\xc6\xc7\xa6\x73\x64\x1b\xe4\x9c\x46\x44\x16\x29\xc3\xda\x42\x9b\x69\xd7\x38\x63\x71\x49\xe9\x12\xae\x34\x85\xa4\x6b\x38\x7e\xeb\x8c\x7a\x5f\x56\x7d\xaf\xa5\x09\xce\xb3\xb3\x55\x35\x45\xa5\x39\x25\xad\x5d\xfa\x5f\x4c\xf0\xf9\x6e\x9c\xdd\xc5\xae\xd9\xdb\x82\x59\xad\x0e\x08\xa7\xfc\xa6\x48\xcd\xe5\x93\xc6\x1b\x25\x5e\x81\x4f\xb3\x7b\x8c\xd9\x2e\x80\x26\x98\xd9\x9f\x91\x79\x61\x98\x38\xa6\x2a\x3a\xee\xed\x54\x9f\xf7\x4b\x34\x69\x9b\x4e\x84\xe6\x79\x9a\xa0\x0b\xb3\x90\xd6\x2e\x1d\x28\x34\xb7\x9b\xf5\x21\x2d\x3b\xf2\x32\xbb\xf1\x2e\x13\xb2\x62\x72\xde\x27\x4f\xc5\xae\x6c\x09\xcd\x13\xb0\xe3\xf4\xe6\x62\x2a\x1b\x77\x7e\x7d\x85\xbd\xeb\x14\xc7\xee\x47\xdc\x41\xbb\x37\xce\xbc\x61\x6b\x06\xa1\xe4\xe2\x33\x2d\x9d\x5f\x5f\x61\x6a\x2f\x9b\x6c\xa9\x54\x7f\x18\x39\x81\xa2\x93\x63\x99\xe1\x91\x2e\xcc\x88\x9a\x08\xee\x3f\xca\x78\x91\x31\x4c\xd0\x54\x16\x1b\x33\xc2\x23\x5f\x97\xa3\x97\xda\x13\x23\xeb\x18\xd1\xe7\xe8\x28\x64\x84\x31\xf4\x41\x06\xf3\x01\x62\x72\xf4\xa2\xd2\xca\x50\x8e\x72\xc2\x7d\xaf\x9f\xdd\xbd\x04\x76\xf4\x0a\xd8\xf9\x3e\xe3\x82\xdf\x58\x50\xfd\x74\xf3\x66\x3f\x44\x78\x57\x1d\xc3\x26\xf5\x61\x90\xbf\x30\xa7\x52\x27\x34\x25\x85\x4c\x9d\x59\x11\x63\x04\xac\x2b\xde\x92\xae\x82\xc4\x47\x53\x42\x5e\xe0\xee\xdb\xcd\xc1\x33\x8e\x05\x7c\xad\x2a\xb8\x48\xd3\x33\x72\x9b\x40\xc9\x76\xcd\x72\x12\x9a\xb5\x66\x09\x8f\x8c\x38\xc8\x27\xbe\x22\x0f\xcc\xc8\x09\x89\xfe\xa0\x83\xd5\x14\x78\x66\x96\xc6\x90\x0c\x13\x3e\x61\x0e\x7d\x04\x2a\x0b\x23\xc5\x5e\xa4\x85\xd2\x4c\xde\x08\x73\xa1\x04\x6e\x3b\x90\x18\x84\x86\x3f\xbf\x4a\x78\x0c\x7e\x5a\x37\x70\xf9\x44\x94\x13\x96\x80\x32\xc8\x0c\x09\xf6\x77\x83\x2c\x25\x52\x9e\xa8\x22\x5a\x9a\x25\x1d\xe5\x22\x56\x47\x86\x14\x1d\xa1\xca\x50\x1d\x9d\x9a\xbf\x36\xd7\x80\x5e\x38\x41\xbf\x97\x34\x4f\x8e\x4e\xcf\x08\x00\x08\x0c\x80\x42\x2f\x9f\x2e\x1e\xba\xb5\x82\x8c\xbe\x17\x16\xde\x84\x23\x00\x0e\xf2\xd2\xd4\x77\xbf\x4c\x34\xf3\xe5\xd5\x51\xd3\xe4\x33\xdd\x6c\x12\x7c\x42\xce\x39\x61\x59\xae\x41\x7b\x4d\x32\x46\x9d\x49\x9c\xad\x98\x5c\xeb\xa5\xcd\x04\xe2\x08\xc8\x93\x07\xfa\x30\x80\x6f\xd4\xae\x2f\x91\x1c\x4e\xd8\x16\x70\x8f\x5f\x1c\x6f\x12\xd2\xf2\x46\x78\xb2\xa0\x84\x2b\x7a\x2f\x30\x7e\x34\x3d\xab\x20\xc4\x57\x48\x2d\x3d\xfd\x78\xf3\xc6\x1a\x56\x10\x56\x3f\x26\x3c\x56\xbe\x9a\xa2\xf5\xfb\xb6\xf0\xae\x05\x32\xcc\xf0\x29\x02\x78\x9b\x05\xee\xcb\xb6\xb6\x0c\xef\xb8\xfe\xa6\xa1\x5a\x07\xb0\xa2\xc3\x5b\x11\xd7\x1f\x9d\xca\xfe\x5e\x05\x8d\xbd\xb3\x41\xa9\x77\xb1\x63\x59\x76\x77\x9d\xd7\xca\x04\xed\xdb\xd1\x02\xfa\xa6\x99\x94\x0a\x07\xa0\x93\xc1\x2f\xa0\x4d\xc2\x3c\xe7\xe4\x36\xa5\x8b\x12\x8d\x80\xea\x21\xa3\x75\x31\xfb\xe8\x96\xa0\x48\x52\xcf\xf2\x76\xf2\xc4\x5d\x5c\xf0\xa4\x84\x52\x63\x0b\xf3\x91\xda\x1f\xbb\x59\x61\x3f\x78\x33\x36\xf5\x31\x36\xea\x56\x45\x5e\x13\xfc\x9d\xce\x8e\x06\x98\xe0\x12\xb6\x39\xc1\x14\xfc\xa7\x80\x0f\x99\x7d\xac\xa0\x49\xc7\x7c\x1b\x90\xf6\x8e\xad\xef\x85\xac\xcf\xc5\x5e\xe5\xeb\x3d\x1d\x72\x5d\x9c\x04\xe6\x8c\x97\xa8\x1f\x14\xb5\x49\xe7\xf7\x46\xd5\xd6\xc9\xa7\x74\xce\xd2\xee\xa9\xbf\xa5\xb9\x99\x77\xe9\xf7\x8a\x8a\x00\x6b\x36\x45\x51\x04\x5d\xd4\x9c\x5b\xa0\x90\x0b\xca\x93\x5f\xd1\x59\x38\x32\x24\x41\x48\xf3\xe7\x09\x9a\x5e\x50\x8d\x90\xb2\x48\x9f\x5a\x54\xae\x25\xa1\x1d\xb8\x4e\xe3\x38\x41\x46\xe4\xba\x03\x2d\xdb\x81\x90\xf0\xbb\x5d\xb6\x0f\xda\xa3\x37\x19\x2e\xf6\x81\xf7\xae\xe5\xac\x77\x1f\xc7\x76\x1b\x70\x8f\xeb\xa2\x90\x2d\xee\x61\xad\xfd\x33\x9a\xd8\x62\xc1\xbb\x40\xd7\x62\x0e\xb5\x1c\xa6\x21\x90\x66\x7d\x7e\xb4\xcf\x70\x58\x06\x01\x9c\x65\x34\xd9\x17\x62\xf8\x0c\xd8\xb2\x8c\xea\x42\x26\xba\xf6\xfa\x6d\xef\x98\xf0\x1f\x8b\x39\xb3\x16\xf5\x9d\xbb\x73\x70\xac\x3c\xbf\xbe\xaa\x05\xcb\x38\xd7\x2c\xe8\x3d\xec\x04\x0d\x97\x46\x0a\x4e\xb3\x79\xb2\x28\x44\xa1\xd2\x75\xa8\xc6\xa5\xe0\x10\x30\x25\xe4\x0a\xf5\x58\xfc\x58\x13\xca\x05\x5f\x67\xb6\x29\x8f\xd2\x22\x66\x95\x11\xc1\x6e\xba\x12\x49\x4c\x68\xa1\x45\x46\x75\x12\x91\x48\x30\x19\x81\x8d\x35\x1c\xa9\x50\x8c\xd0\x86\xbe\x51\xa1\xb4\xc8\x48\x46\xa5\x5a\xd2\x34\x6d\xda\xe3\x11\xee\xf0\xb6\x64\xed\x13\x58\x7f\xe3\x8f\x2b\x9c\xf5\x9e\xf8\xdd\x91\x9b\xbe\x07\x7e\x9b\xc9\x0d\x1a\x60\xd5\x8c\xa5\x3d\xc6\xb0\x59\x11\x6a\xf3\x3d\x55\x10\xee\xc3\x92\x91\xbc\x98\xa7\x89\x02\xc9\x14\x28\xd1\x9a\xcc\xd9\x32\xb1\xde\xd9\xdd\x24\xa8\x71\x8b\xbb\xe0\xdc\x46\x03\x3a\x21\xd4\x42\xb2\x5b\xfb\xda\x2b\xed\x2a\xa3\x8b\x1e\x0c\xf8\x1b\x43\xb0\x29\x5f\xfb\x9b\x10\x92\x9c\xaa\x33\x22\xa4\xf5\xd8\xf1\x35\xe9\xed\x4f\x3e\x51\xae\x24\xef\x2d\xe8\xac\xeb\xbc\xc5\x77\x08\xa8\x60\xf2\x56\xc8\xcc\x00\x38\x91\xe4\xb6\xe0\xa0\xa0\x54\xd6\xd3\x1e\x6e\x09\xab\xe3\xa2\xa9\x12\xfe\x2c\xc3\x5e\x70\x37\x09\x42\x15\xb9\x67\x69\x3a\x25\xe7\x69\x6a\xb3\xaf\x06\x79\x36\xca\x58\xf9\xd2\x9f\x63\xbe\x26\x71\xb2\x60\x4a\x93\x93\xd9\x7f\x9d\x9f\x02\x8b\x02\xfa\x9f\x35\xd1\xd4\x85\x0a\x56\xf5\x5a\xc0\xec\xc4\x05\x30\x45\x11\xd5\x34\x15\x0b\x74\x69\x00\x1d\x39\x8f\x49\x9e\xd2\x35\x94\x56\xc8\xa9\x04\x6f\xdf\x08\x75\x5b\x44\x16\x1c\x92\x4a\x7f\xd6\xbb\xab\x9b\xa8\xb4\xe5\x7d\x9e\x00\x4e\xee\x49\x34\x3a\xb2\xeb\x3e\xec\xa5\x28\x59\x9e\xd2\x06\x6d\xcc\xd6\x81\x2f\x03\xc1\x8d\x78\x00\xa2\xbf\xe0\xcc\x8f\x31\x25\x33\xc4\x9d\x8c\xea\x08\xed\xc9\xff\xc8\x98\xa6\x31\xd5\x74\x6a\x64\xe8\x7f\x54\xa3\x12\x45\x1a\x9b\x81\x9a\x37\xba\x61\xce\xc8\x1c\x8b\x6e\x22\xf5\xc6\x70\xf0\xbe\x39\xc8\x35\xee\x3c\xb6\xaa\x7f\x06\xd2\x27\x58\xfe\xeb\x4f\x46\x84\x6d\xb5\x5f\x56\xe6\xba\xd9\xa9\xaa\x9d\x49\xab\x2b\xb1\xd8\x9a\x31\x48\xd1\xf9\xc1\x56\xa1\x72\x6f\x40\xf5\x7c\xfe\xee\xb2\x59\x4d\xd8\xad\x6a\xe9\x50\xad\x6c\xf2\xa7\x8d\xd3\x73\x8a\x79\xfb\x4b\xd5\x32\xe3\x42\x91\x20\x78\x13\x03\x7b\x28\xf7\x37\x87\x4b\xce\x9f\x82\xc6\x20\x0c\x3b\xc5\x7e\xcd\x7a\xa5\x5e\xa6\xb1\x3e\x06\xb1\xae\x28\xbf\x89\x9f\x6c\x63\xa3\x7e\xf6\xb1\xce\x48\xbc\xa6\x48\x3b\x84\x3c\x04\xe6\x38\xd5\xb2\x07\x76\x5f\x7b\x62\x4f\xbd\x98\x5b\xea\x0e\x13\xf5\x5b\x59\x71\xfa\xba\x63\xeb\x63\x2b\x23\x1a\x4c\x5f\x26\x39\x86\x8a\x5a\xf3\x8d\xdd\x5d\xf2\x91\xa6\x49\xec\x87\x40\xac\xbe\xe2\x67\xe4\x9d\xd0\xe6\x9f\xd7\x9f\x12\xa5\x51\xd6\xbe\x14\x4c\xbd\x13\x1a\xde\x8c\xb2\x54\x9c\xc2\x0e\x0b\xb5\xd2\x3e\x5a\x00\xe0\x5c\x05\x3a\x01\xb7\xa0\xab\xdb\x0a\x67\x64\x5a\x5f\x71\xc3\x11\xd8\x15\xf9\x10\x6a\x65\x87\x70\xf1\x3f\x5c\xf0\x09\xd8\x06\x6a\xc7\xb0\x80\x10\xb2\x02\x87\x96\xe1\xec\x50\xe8\x7c\x09\xbf\x24\xca\x11\x71\x7f\x67\x53\xa7\xae\x4c\x22\x92\x31\xb9\x00\x6b\x57\xd4\x61\xed\xe9\xab\xc2\xed\xa5\xb8\xed\xdc\x2b\x20\x99\x6f\x1a\xb5\x34\x5b\x9b\x14\xb4\x47\xb2\x94\xa1\xea\xe6\x5f\x86\xfa\x00\xa4\xfe\x0d\x71\xf4\x6a\x4a\xce\x5d\x89\x9f\xf0\x37\x6b\xf5\x0b\x87\x31\x23\x24\x8a\x18\x52\xb2\xa2\x29\xc3\x0a\x07\x94\xfb\x58\x37\x71\xbb\x45\xd8\xcf\x6c\x3c\xbd\x39\xb3\x9e\x65\x3a\xba\x63\xeb\xa3\xb3\xad\xad\x3d\xba\xe2\x47\x65\xc0\x63\x65\x33\x3d\x11\x05\x6e\xeb\x08\x7e\x3b\xda\xff\x2e\x68\x25\x96\xfd\x75\x49\x9d\xfb\xa6\xee\x92\x7a\xd3\x7f\x2d\xb3\x71\xa2\x4e\x41\xed\xc1\xb1\xd6\x92\x90\xa0\x06\x36\x6f\xc3\xd4\x2a\x86\x55\xbd\x4b\xf2\xbc\xcc\x44\x53\xe4\x0b\x49\x63\x46\x16\x92\xe6\xcb\x5d\xd9\x12\xe4\x6d\xea\x86\x7f\x32\x8c\x6e\x03\xf0\x5b\x64\xc3\xd6\x7e\xf7\x6c\xbe\x14\xe2\x0e\xc2\x10\x01\x11\x1e\x50\x93\xf1\x37\xfc\xd6\x65\xf9\xce\x09\xa5\x8a\xc4\x4c\xd3\x24\x05\x3f\x9a\xf7\x6f\xde\x5a\x4f\x1b\x77\x8f\xbb\x59\xd6\x3b\xad\x8c\x20\x00\xd0\xd8\x7a\x80\xdd\xb0\x55\xc2\xee\xad\x7e\xa3\xc9\x47\x66\x42\x16\x8c\x83\x63\x48\x8b\x03\xd5\x84\xa8\x24\x66\xaf\x21\xe8\xb9\x79\xa0\x01\x06\x87\x86\x39\x77\x1d\xde\x76\x0a\xde\x49\xbd\x7b\xdc\xb2\x5e\xfc\xbd\x16\xb2\x25\x09\x53\xbf\x18\xec\x7e\xf1\xd5\xd6\x8b\xff\x7b\xf2\xdd\x77\x7f\x68\x6c\x94\xd1\x4f\x49\x56\x64\xdf\x93\x3f\xfd\xf1\x8f\x7f\xf8\x63\x73\xb3\x84\x63\xb3\x6f\x9b\xd7\x67\x4f\xdb\xc5\xcd\xe5\x01\xc0\x3b\xf6\x9e\x8c\xed\xc6\xcc\x1e\x43\xdd\xd2\x24\x2d\xa4\xf5\xa1\xed\x29\x22\xfc\x10\xf6\x01\x43\x54\x19\x74\x42\xdd\x88\xce\xd1\xce\x3a\xe0\xdd\x26\x9c\x29\x28\x9e\x53\x70\xc9\x22\xb1\xe0\xc9\xaf\x2c\x76\xb5\x73\xc0\x21\x06\xb2\xec\x3b\x14\x27\x8c\xc7\x58\xc3\xd4\xdc\x79\x4b\xca\xe3\xb4\xcd\x51\xa2\xc7\x4a\xc3\x13\x3c\x08\x64\x70\xf3\xec\x04\xb0\xb7\x65\x8f\x0d\x70\x41\x25\x56\x6b\xb6\xc3\x1b\x0d\xc1\x36\x68\xa5\x48\x18\x67\x2d\x82\x75\xcd\x1c\xb7\xe4\x3e\x14\x59\xe1\xdd\x3f\x0b\x26\xd7\x10\x60\x53\x32\xf6\x81\x13\xde\x87\x32\x7f\x83\x5b\x86\xe5\xa8\x30\x81\xce\x86\x2c\x5c\x32\x31\xa5\x9b\xcc\xc6\xb7\xa1\x0f\x43\xb7\x03\x67\x35\x23\xe7\x84\x17\x69\xda\xd4\x94\x8b\x36\xfb\x5a\x08\xbb\x0e\x51\xb2\x9f\x8c\xd7\x57\x2d\x50\x03\xe9\xcf\xaa\x1c\x08\x17\x3e\x12\x2b\x7f\xd8\xea\x82\x70\xc1\xbd\xfc\x69\xfb\xfb\xd2\xf6\x4b\x13\xd4\x43\x8d\x80\xcf\x2e\xce\xb6\x3d\x93\xfb\x3c\xa4\x62\x01\x9f\x9d\xfc\x9a\xfa\x29\x19\x6a\xa6\x7e\x70\xaa\x86\x3d\x16\xdf\x47\xed\x50\xb3\xf4\x67\xe5\xc3\x16\xc0\xfb\x7a\x91\xed\xe0\x41\xd6\x73\x27\x7b\x28\x25\xf0\x79\x56\x4d\xec\x74\x13\xf5\x20\xcc\xbb\xa9\x29\x7a\xef\xaa\x64\x09\x5f\x09\x4c\xb2\xbd\x13\x0f\x77\xb3\xd5\x71\x83\x95\xbb\x07\xca\x6a\x79\x39\xcf\xfc\x86\x2c\xad\x11\x68\x49\xa1\xba\x95\xdd\xed\x2b\x68\x8f\xbb\x19\x45\x06\xa9\xae\xbc\x48\xd9\xdf\x12\xbd\x7c\xef\x92\xea\x5b\xac\xd6\x45\x9e\xc2\x62\x83\x1f\x0c\x0a\xdd\x94\x9c\xe1\x15\x96\x71\x63\x91\xc8\x32\xc6\x63\x74\x22\xca\xe8\x1d\x23\x65\xa9\x50\xc3\xe3\x01\x1b\x0c\xc3\xb1\x4f\x39\xe5\x25\x9f\xb8\x32\xb4\xbc\x0d\xa3\x7a\xe2\x53\xdf\xbb\xb6\x77\x40\x4b\x7b\x20\x4b\x10\x89\x52\x09\x58\x21\x73\x96\x0a\x08\x81\x47\x0f\x5b\xf4\x01\x77\x31\x20\x86\x24\xdb\xb7\xf6\xd6\xb3\x09\x37\x19\x5f\x94\x79\xbc\x54\x0a\x45\x7d\x2d\x05\x16\x9c\x4d\xc9\x8d\x65\x61\xfa\x71\x45\x7d\xc8\x69\x4f\x52\xba\xc3\x85\xf8\x69\x52\x66\xcb\x98\x18\x66\x77\x62\x67\xa3\x45\x96\x44\x5d\x9b\xd2\xad\xeb\xc0\x67\x73\x5b\x5c\xbf\x70\x63\x56\xee\x5d\x9f\xad\x71\x8d\x9f\x37\xa7\xe1\xf1\xa5\x36\x76\xdb\x9b\x2a\x31\x29\xef\x23\xbf\x31\x1b\x64\x33\xc2\x62\xd5\xa0\x24\x9c\x90\x8b\x9b\xd7\xe7\x1f\x5e\x9f\x91\x9f\xae\x2f\xe1\xdf\xcb\xd7\x6f\x5e\x9b\x7f\x2f\xde\xbf\x7b\xf7\xfa\xe2\x83\xe1\x60\x5e\x60\xd1\x00\x23\x40\x9a\xad\x31\x37\xa1\xa8\xd2\x29\xca\xd7\xe4\xb6\xd0\x86\x10\x95\x1f\xab\xcc\x82\xa2\xf6\x81\xc6\xb1\x11\x56\x9f\x1c\x02\xd4\x03\x7c\x53\x61\x13\x56\x4b\xc1\x3a\x0b\x36\x44\xae\x9b\x41\xfb\x3c\x18\xd6\x3b\xc8\xa4\xb2\xde\xa3\x3d\xa3\x4b\x7e\xe1\xe4\x07\x21\x89\xad\x4d\x07\xc5\x4a\x63\x75\x6c\x63\x78\xcc\xff\xa7\xf8\xea\x65\x2a\x16\xc7\x3e\xb4\x87\x91\x54\x2c\x88\x2a\xe6\x3e\xe4\x0a\x98\x00\x68\xfd\xc2\x35\xab\x44\xaa\x9c\xf9\xb8\xab\xa0\x97\x1f\xbc\xd2\x27\x6c\x10\x8e\xfb\x12\x0a\xca\x55\x5a\x9a\x17\x9b\x03\xbe\x78\x59\x3f\x03\xc7\xef\x25\x72\xa3\xc7\x2f\xdc\xe0\xfa\x7d\x92\xc6\x11\x95\xf1\x16\xc2\xc3\x9d\x8c\xf8\x02\xd0\xc3\x2c\xcb\x58\xfc\xbb\x1c\xdc\xe6\x46\x11\x2b\x26\x53\x9a\x63\x40\x00\xa4\xb9\x06\x8f\x29\xf8\xc8\x25\xcb\x19\x84\xbd\xb9\xe2\xf4\x8c\x47\xa9\x80\x34\x2c\x78\xa1\x9f\x55\x97\x8e\x1e\x54\x2e\x57\xa5\x0b\xbe\xf4\xc7\xeb\xe8\xcb\x24\xb0\xe0\x47\xbe\x13\xea\xa3\xe7\x79\x63\x22\x20\x1f\xe3\x83\x82\xb2\xe7\xf6\x19\x39\xb2\x11\x89\x47\x67\xe4\xc8\xe7\xba\x89\xad\x64\x70\xf4\xe2\xa8\x6c\x10\xc6\xb4\x81\x60\x60\xcd\x60\x13\xf8\x4e\x18\x3d\x0b\xd8\xe1\x8c\x75\xfe\xd3\x65\xbe\x22\x73\x23\x5b\xc5\x1d\xcc\xa1\x3a\xd0\xb4\x32\x91\xad\xaf\x96\xe1\x98\x9d\x5f\x34\xd3\x0f\xba\x6b\x48\x7f\x80\x61\x9d\x16\x38\x92\x99\xad\x74\x4e\x78\xb3\x0a\xe6\x79\x63\x63\x98\x50\x29\x91\x24\xa7\xd2\x88\x5f\xae\x65\xb5\x24\xde\x8b\xce\x82\x78\x3d\x30\x28\xb0\x29\xf5\x94\x54\x66\xbe\xc7\x45\x4a\x95\xaa\xd1\x36\x03\x15\x31\x03\x13\x86\x23\x13\xea\x0c\x6e\x90\xef\x7c\x49\x57\x2d\x09\x31\x7a\x4c\x5a\x53\xb9\x60\xba\xdd\x1a\x44\xf9\xfa\x7d\x6b\x0a\xbd\x49\xef\xa4\xbd\x93\x7e\x47\xb1\x72\x08\x13\xae\x27\x42\x4e\xb0\xcb\xf7\x44\xcb\xa2\xc9\xae\xa7\x93\x8c\x89\x42\xcf\x58\x24\x78\x7d\xf4\x8b\x6d\x37\x9a\x79\x6b\x87\x90\x20\x6b\x61\x3d\x77\x0c\x4c\x98\xf4\xd2\x09\xa3\x25\x77\xe3\xac\xaa\xd5\xb4\x3d\xef\xdf\xbc\x1d\xb2\xd9\x04\xc2\xe6\xdb\x77\xf2\xa3\xbd\x33\xf8\xc2\xcf\xd4\xce\xbc\xb5\xdb\xdb\x42\xef\xde\xe9\xc2\x5b\xeb\xda\x5b\x5b\x60\xb4\xa7\x5e\x69\x5c\xbf\xd2\x54\x17\x5b\xd8\x50\xd9\x1b\x4b\x2c\x67\x18\x7e\x68\x45\x91\x19\xf4\x0b\x15\x9b\xdb\xf9\x26\x30\x87\x0d\xb4\x73\x0e\x9a\x53\x62\x3b\x9a\xf3\xa9\x25\x4d\x50\x68\xa6\x91\x2e\x20\x8e\x9d\x6a\xeb\xcc\x69\x13\x2e\xfd\xae\x6e\x19\xb5\x62\x72\x9b\x68\x1c\x31\xa9\xd5\x1b\xaa\xf4\x4f\x79\x4c\x1b\x22\xdd\x36\x9c\x34\x95\x86\x03\x83\x2c\xfd\x3d\x67\xb1\xa1\xf0\x16\x04\x38\x1e\xb9\x37\xa4\xb7\xc0\x11\x1b\x5d\x0f\x1a\x51\xce\x1d\x20\xd3\x7d\x62\x3e\x55\x3f\xeb\x1b\x61\x60\x72\x5e\x4b\x80\xaa\xee\x29\x5d\xb3\x35\xd7\x89\x84\xd1\x08\x67\x9f\xea\xb4\x0c\xc3\x67\x9c\x32\xca\xeb\x83\x0d\x36\x30\x0a\xda\xed\x8e\x43\xf6\x03\xe4\x7e\x99\x18\x7e\x17\x23\x02\x15\x71\xfc\x57\xcc\x52\xd6\x10\x18\x38\xd0\x7d\xd6\x7e\xe1\xd2\x7e\xa0\x97\x6b\xd7\x75\xb5\x8f\x37\x62\x58\x0e\xde\x86\x9e\x94\x9c\xb6\xe5\x1e\xbc\xbc\xb6\xb9\x2a\x60\x5f\xe6\xa9\x88\xee\x30\x01\x1d\xe4\x7e\x48\x7e\x65\xd2\xf9\xda\x97\xc5\xe7\x6c\x45\xb4\x85\xab\xf6\xea\xe0\xe6\xca\x5f\xc1\x28\x66\x6c\x03\x40\x3f\xbe\x90\xa5\x36\xb5\xe0\x36\xd2\xf2\xf3\xb8\xeb\x3a\x29\x07\x62\x14\x2a\xd6\x92\x6d\x81\x07\x73\xd5\x40\x7e\x4c\x2b\xac\xd2\xcc\xc6\x06\xbd\xfc\xb1\x39\x8e\x66\x54\x17\xdc\xb6\x68\x1e\x6c\x01\xe0\xe3\x51\x6b\x6a\xa3\xd6\xb8\x9f\xbe\xda\xbe\x8e\xf8\x1e\xd2\x9f\xc3\xf7\x53\xee\x33\xda\xa8\x0e\x95\xa3\x5b\x38\x1b\x43\x1f\xca\x67\x17\xbb\x65\xdf\xc4\xbc\x3b\x59\xd6\xf8\x2e\x09\x54\xab\x89\x66\xbc\xd8\x61\xa3\x78\xd1\xfb\xe0\x56\xc8\x46\x01\x66\xbc\xc9\xb7\x47\x83\x75\x0e\x64\xb8\xcf\x66\x7f\xbd\xed\x80\x25\x43\xbd\x7c\x97\x33\x42\xc9\x32\x51\x5a\x48\x6b\x4e\x84\xe2\x75\x92\x42\x71\xdd\x7a\xbf\xb7\x71\x3c\x00\x2f\xfc\x14\x08\xcd\x73\x46\x7d\x5d\x2b\x7b\x37\x41\x61\x2a\xc9\x22\x21\xe3\xda\x89\x39\xd5\x40\x2d\x2f\x55\xfb\xf9\x11\x22\x5b\x53\xaa\xf4\x07\x3f\x07\xc3\x20\xf4\xa4\xc6\x55\xf6\xc7\x2e\xb1\x5c\x8d\x4b\xfd\x23\x78\xf9\xa3\x20\x94\xa3\x4a\x64\x18\x0f\xde\xcd\x64\x94\x6b\x43\x6e\x6e\xaf\x75\xdd\x7b\xce\x2d\x58\xe2\xe7\x99\x79\xc6\x94\x6a\x0d\xae\xda\x70\x4c\x81\x1c\xd2\xc4\xe7\x90\xb6\xdd\xdd\x65\x8f\x0c\x02\xba\xa0\xba\x2c\x6f\xeb\x66\x54\x23\xc0\x26\xa0\x42\xc1\x1f\xab\x41\x5b\x96\x2f\xa9\xea\xbb\x18\x7f\x8a\xbc\x5b\x73\xef\xe3\xd0\x73\x36\x92\x51\xd5\x16\x68\xba\x01\xdb\xb9\x4c\xd8\x2d\xb9\xa0\x19\x4b\x2f\xa8\x1a\x13\xb8\x40\x01\xa6\x84\x4d\x17\x53\x72\x7c\x13\x58\x98\xdf\x09\xfd\xb6\xad\xc6\x47\x47\xfa\x87\x3e\x27\xfa\x41\xcf\xf2\x60\x21\xa1\xfb\xe4\x0e\x3c\xb3\x83\x67\xd8\x72\x42\x0f\xe2\x6c\xb6\x47\x4b\x37\x9d\xc7\xea\x49\x2c\x24\x68\xfc\xa2\x7d\x4f\x64\x47\x00\x67\xd3\x29\x3c\xe4\xf3\xd7\xb1\x24\x3f\xc4\xac\x56\x65\xb2\xb5\xba\x0f\x15\xc9\x15\x6c\x06\xa1\x53\x21\xa4\x87\x37\x33\xbd\x98\x7d\x1c\x93\x6d\x79\xdc\x54\x05\x76\x03\x1b\x7f\x6f\xe1\xcb\x27\xed\xb7\xf0\xd0\x34\x08\x31\x58\x69\x0c\x06\x7c\x4e\xa7\x93\x4b\xf7\x55\xab\xeb\xf0\x99\x9d\xe1\xaf\x5b\x5b\x41\xcf\xb6\xa9\xe0\xc7\x09\xd4\x2a\x64\x2b\x2c\x10\x0a\x41\x2e\x8c\x70\xa6\xcc\xa1\x38\x6d\xf9\x7c\x4f\x81\xaa\x9f\x30\xd5\x2d\xe8\x76\x0a\xb1\xa4\x7b\x6b\x5d\xa3\xb6\x0d\xc6\xa7\xaf\xcc\xd6\x43\x26\xde\x41\x58\xeb\x96\x78\x76\x18\xac\x93\xfd\xdb\x71\xbc\x7a\x05\xee\xe6\xb3\x91\x49\xda\x74\xb9\x01\x22\x8d\x56\xe5\xc8\x50\xe0\x08\xf2\x8b\x23\xed\xb6\xe4\xa9\xaa\xbf\xbd\xd9\xa4\x81\xe0\x62\x59\xc5\xf0\xb1\x96\x55\x14\xc9\x78\x30\xef\xcc\x3f\xd2\x7b\xbc\x03\x48\xa6\xd2\x89\x40\x0f\x9b\x9c\x01\x9f\x2e\xac\x7b\x7c\x7c\xeb\x93\x29\xab\x15\xc7\x1e\x28\xaf\x8d\x62\x72\xc5\xe2\x8a\xa5\xce\xe6\xf9\xaf\xbe\x0b\xec\xb6\xe5\xf8\x16\xec\xe4\x5f\xff\xfe\xdd\xff\x05\x00\x00\xff\xff\x96\x44\x81\xaa\x39\x2a\x08\x00") func operatorsCoreosCom_clusterserviceversionsYamlBytes() ([]byte, error) { return bindataRead( @@ -125,7 +125,7 @@ func operatorsCoreosCom_clusterserviceversionsYaml() (*asset, error) { return a, nil } -var _operatorsCoreosCom_installplansYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5b\x4b\x93\xdb\x36\x12\xbe\xcf\xaf\xe8\x9a\x1c\x9c\x54\x59\x9a\x24\x7b\x49\xe9\xe6\x9d\x6c\xb6\x66\x37\x0f\x97\x67\xe2\x4b\x36\x87\x16\xd9\x12\x91\x01\x01\x04\x0f\xc9\xda\x54\xfe\xfb\x56\x03\x7c\x4a\x24\x45\x8d\x27\x8e\x6b\x2b\xbc\xd8\x43\x36\x80\x7e\xf7\xd7\x00\x84\x46\xbc\x25\xeb\x84\x56\x2b\x40\x23\xe8\x9d\x27\xc5\x7f\xb9\xe5\xe3\x57\x6e\x29\xf4\xcd\xee\x8b\xab\x47\xa1\xf2\x15\xdc\x06\xe7\x75\xf9\x86\x9c\x0e\x36\xa3\xaf\x69\x23\x94\xf0\x42\xab\xab\x92\x3c\xe6\xe8\x71\x75\x05\x80\x4a\x69\x8f\xfc\xda\xf1\x9f\x00\x99\x56\xde\x6a\x29\xc9\x2e\xb6\xa4\x96\x8f\x61\x4d\xeb\x20\x64\x4e\x36\x4e\x5e\x2f\xbd\xfb\x7c\xf9\xd5\xf2\xf3\x2b\x80\xcc\x52\x1c\xfe\x20\x4a\x72\x1e\x4b\xb3\x02\x15\xa4\xbc\x02\x50\x58\xd2\x0a\x84\x72\x1e\xa5\x34\x12\x95\x5b\x6a\x43\x16\xbd\xb6\x6e\x99\x69\x4b\x9a\xff\x29\xaf\x9c\xa1\x8c\xd7\xde\x5a\x1d\xcc\x0a\x06\x69\xd2\x6c\x35\x8b\xe8\x69\xab\xad\xa8\xff\x06\x58\x80\x96\x65\xfc\x7f\x12\xfd\x2e\x2d\xfa\x5a\xa2\x8a\x6f\xa5\x70\xfe\xdf\xc7\x5f\xbe\x15\xce\xc7\xaf\x46\x06\x8b\xb2\xcf\x6a\xfc\xe0\x0a\x6d\xfd\xf7\xed\xc2\xbc\x90\x30\xe9\x93\x50\xdb\x20\xd1\xf6\x46\x5d\x01\xb8\x4c\x1b\x5a\x41\x1c\x64\x30\xa3\xfc\x0a\xa0\x52\x5a\x35\xc9\x02\x30\xcf\xa3\x21\x50\xbe\xb6\x42\x79\xb2\xb7\x5a\x86\x52\x35\x8b\x30\x4d\x4e\x2e\xb3\xc2\xf8\xa8\xec\x87\x82\x60\x23\xac\xf3\x70\x7b\xff\x16\x84\x02\x5f\x50\x94\x09\xf4\x06\x32\x19\x9c\x27\x7b\x4f\x76\x27\x32\xaa\x7c\x23\xae\xdf\x4c\x07\xf0\x8b\xd3\xea\x35\xfa\x62\x05\x4b\x56\xf7\x72\x7c\xd0\x4f\x9f\xff\xdc\x19\x97\x6c\x78\x7b\xff\xb6\xf3\xce\x1f\x58\x42\xe7\xad\x50\xdb\x29\x8e\xd1\x18\xab\x77\x28\xa1\xd4\x39\x4d\xf0\x52\xd3\x9d\x2c\xfb\xea\xf4\xc3\xc8\xda\xc3\x53\x46\xe5\x0f\x4d\xd9\xfb\x90\xa6\x5c\x6b\x2d\xa9\xf2\x96\x9a\x78\xf7\x05\x4a\x53\xe0\x17\xd5\x4b\x97\x15\x54\x62\x6b\x24\x6d\x48\xbd\x7a\x7d\xf7\xf6\x6f\xf7\x47\x1f\xa0\xaf\x8b\x8e\xcb\x41\xce\x51\x48\x2e\x1a\xb0\x72\x9c\x18\x3d\x6c\x48\x04\x47\xd1\xa2\x6d\x04\x9c\xb0\xa9\xd7\xbf\x50\xe6\x3b\xaf\x2d\xfd\x1a\x84\xa5\xbc\xbb\x3a\x6b\xa4\x8e\xf1\xa3\xd7\xac\x9d\xce\x2b\x63\x79\x2d\xdf\x89\xa4\xf4\x74\x92\x4c\xef\xfd\x91\x64\x2f\x58\xfc\x44\xd7\x93\xac\x72\x78\xca\x2b\x9d\xb1\x50\xbe\x10\x0e\x2c\x19\x4b\x8e\x94\x6f\x85\x56\x95\x4c\x4b\x60\x67\x24\xeb\x38\xea\x82\xcc\x39\x11\xed\xc8\x7a\xb0\x94\xe9\xad\x12\xff\x6d\x66\x73\xe0\x75\x8a\x00\xf4\xe4\x3c\xc4\x10\x52\x28\x61\x87\x32\xd0\x4b\x40\x95\x43\x89\x07\xb0\xc4\xf3\x42\x50\x9d\x19\x22\x89\x5b\xc2\x77\xda\xb2\x01\x36\x7a\x05\x85\xf7\xc6\xad\x6e\x6e\xb6\xc2\xd7\x29\x34\xd3\x65\x19\x94\xf0\x87\x9b\x98\x0d\xc5\x3a\xb0\x35\x6e\x72\xda\x91\xbc\x71\x62\xbb\x40\x9b\x15\xc2\x53\xe6\x83\xa5\x1b\x34\x62\x11\x99\x55\x31\x8d\x2e\xcb\xfc\x13\x5b\x25\x5d\xf7\xe2\x48\x7d\x83\xfe\x0b\x75\xde\x9a\xd4\x35\xe7\x2f\x10\x8e\xdd\x24\x0e\x4f\xb2\xb4\x2a\xe5\x57\xac\x95\x37\xff\xb8\x7f\x80\x9a\x81\xa4\xf6\xa4\xe1\x96\xd4\xb5\xca\x66\x45\x09\xb5\x21\x9b\x28\x37\x56\x97\x71\x16\x52\xb9\xd1\x42\xf9\xf8\x47\x26\x05\x29\x0f\x2e\xac\x4b\xe1\x5d\xf4\x39\x72\x9e\xed\xb0\x84\xdb\x58\x41\x60\x4d\x10\x4c\x8e\x9e\xf2\x25\xdc\x29\xb8\xc5\x92\xe4\x2d\x3a\xfa\xc3\x55\xcd\x1a\x75\x0b\x56\xdf\x7c\x65\x77\x0b\xe0\xe9\x80\x93\x18\x03\xa8\x4b\xd4\xa8\x75\x3a\x31\x7e\x6f\x28\x6b\xa2\xa1\x89\xe9\x57\xc6\x48\x91\x25\xb7\x6f\xbc\x83\x1d\x79\xdd\x24\x82\x5e\x56\x9a\x64\x67\x2c\xec\x21\x95\x97\xd3\xb4\xd9\xff\x74\xb2\x10\x7f\x9a\x55\x46\x60\x22\x67\x40\xcc\x1b\x69\xe9\xd3\x2f\x47\xfa\xaa\x53\x3b\x3b\x34\x7b\x58\x70\x64\xdb\x82\x61\xb4\x14\xd9\x01\x36\xda\x72\x7e\xe8\xe8\x76\x09\x77\x1e\xca\xe0\xa2\xbf\x69\x45\xac\xd9\xeb\x57\xc1\xeb\x12\xbd\xc8\xae\x41\x5b\xb8\xfe\x0e\x55\x40\x79\xbd\x1c\x60\x61\xd4\x21\x5a\xde\x87\x54\x3a\x5c\x23\xda\x67\x5c\x75\xe3\x73\xa1\xb5\x78\x18\xf8\x2a\x3c\x95\x83\xc3\xce\x70\xbf\x25\xc5\x45\x63\x20\x63\xb7\x43\x39\x51\x6e\xc9\x9e\x7c\x4f\xde\x38\x3e\x6e\x64\xc9\x34\xac\x41\x3a\x17\x8d\x77\x1e\x7d\x38\x91\xb3\xe7\x22\xd7\xdd\x98\x8a\xe4\x9d\x04\x56\x15\xd0\x8d\xb6\x65\x8a\x29\x5c\xeb\x90\x92\x55\x9a\x9a\x3d\xc3\x79\x32\xae\x09\x15\x0e\xb6\x4c\x97\x46\x92\xef\xd7\xde\x25\xfc\x47\x41\xb5\x02\xa7\x43\x6f\x51\xc8\x38\x15\x66\x3e\xa0\x8c\x33\x52\x55\xa1\x0f\xce\x53\xb9\xbc\x7e\x9e\x48\xcd\xd0\xa3\xd4\xdb\xfb\x94\x0d\x06\x08\x4c\x81\x8e\x2e\x89\x3f\xef\x49\x05\xce\xc2\x95\x33\xbe\xca\x32\x1d\x94\x7f\x43\x9b\xf3\x21\x39\x3e\x16\x2c\x6d\xc8\x92\xca\xaa\xfa\xee\x12\x01\x60\xa2\x00\x5f\xa0\xe7\x48\x0e\x2e\xa9\x39\xd7\x09\x07\xe7\x0d\x94\xa9\x15\x3e\x1e\x95\x83\xca\x3b\x27\x2f\x4c\x62\x95\x61\x31\x5f\xdf\xd5\xf8\x24\xc1\x12\xaa\xa5\xf3\x43\xcc\xc1\xb9\x28\xe0\x67\x23\x48\xe6\x11\x7f\xce\xe1\xe0\xc5\x5d\xa5\xd0\x58\xc5\xbd\x06\x04\x23\x28\xa3\x1e\x1c\x8a\x0a\x23\xcc\xab\x97\x5c\xf0\x2c\x55\xdf\x5e\xa6\x5a\x5d\xc1\x80\x16\x2e\x79\x14\x0a\x90\x71\x81\xc8\xe1\x5f\xf7\x3f\x7c\x7f\xf3\x4f\x9d\x78\x63\x4b\x91\x73\xc9\x93\x4b\x52\xfe\x25\xb8\x90\x15\x80\x8e\x59\x63\xf7\x64\xff\xa7\x65\x89\x4a\x6c\xc8\xf9\x65\x35\x1b\x59\xf7\xd3\x97\x3f\x2f\xe1\x1b\x6d\x81\xde\x21\x07\xcf\x4b\x10\x49\x6b\x0d\xa8\xa8\x5c\x23\xa6\x72\x16\xa6\x19\x0b\x7b\xe1\x8b\xc8\x92\xd1\x79\xc5\xf4\x3e\x32\xeb\xf1\x91\xf3\x77\x62\x36\x70\x2f\xf3\x48\x2b\xb8\x4e\xad\x49\xb3\xf4\x6f\x0c\xc3\x7f\xbf\x86\x4f\xf7\x05\x59\x82\x6b\xfe\xf3\x3a\x2d\xd8\x60\x40\x7e\x57\xdb\xb1\x5d\x38\x3a\xa4\xb7\x62\xbb\xa5\x18\xf9\x0c\x68\x18\x34\x7c\xc6\x15\x42\x6c\x40\xe9\x0e\x71\x9c\x82\xf5\x69\x28\x13\x1b\x41\xf9\x09\x23\x3f\x7d\xf9\xf3\x35\x7c\xda\x97\x0b\x84\xca\xe9\x1d\x7c\x99\xda\x31\xe1\x58\xc6\xcf\x96\xf0\x10\x2d\x73\x50\x1e\xdf\xf1\x9c\x59\xa1\x1d\x29\xd0\x4a\x1e\x98\xe3\x02\x77\x04\x4e\x97\x04\x7b\x92\x72\x91\x50\x42\x0e\x7b\x3c\xb0\x0c\xb5\x2a\xd9\xaa\x08\x06\xad\x3f\x42\xc8\x0f\x3f\x7c\xfd\xc3\x2a\xad\xc6\x66\xdb\x2a\x5e\x82\xd1\xd7\x46\x30\xfe\x65\xe0\x9b\x50\x5c\xb4\x39\x33\x12\x92\x91\x38\xf5\x15\xa8\xb6\x54\x37\x8f\x9b\xc0\x78\x6a\x79\x8c\x98\x66\x7b\xfc\x10\x5c\x1d\x76\xf6\x08\x5b\x8f\x03\xed\x4f\x04\x85\xb3\x45\x8c\x3d\xe0\x2c\x11\xbf\xef\xf8\xe0\xa4\x88\x8f\x61\x4d\x56\x91\xa7\x28\x65\xae\x33\xc7\x02\x66\x64\xbc\xbb\xd1\x3b\x4e\xaa\xb4\xbf\xd9\x6b\xfb\x28\xd4\x76\xc1\x4e\xb6\x48\x96\x77\x37\x71\xf7\xe3\xe6\x93\xf8\xcf\x7b\x49\x34\x5a\xaa\x87\xc5\x8a\xe4\x1f\x42\x36\x5e\xc7\xdd\x3c\x59\xb4\x1a\x52\x5f\x52\x09\x5e\xdc\xa7\x80\xcf\x8e\x47\x73\xb8\xec\x0b\x91\x15\x75\xd3\xda\xc9\x70\x25\xe6\x29\x05\xa2\x3a\xfc\xe1\x6e\xcc\x0a\x0c\x96\xd7\x3e\x2c\xaa\x7d\xb9\x05\xaa\x9c\xff\xef\x84\xf3\xfc\xfe\xc9\x1a\x0b\x62\x66\x00\xff\x78\xf7\xf5\x87\x71\xee\x20\x9e\x18\xad\xeb\xa0\x72\x49\xdf\x6a\xfd\x18\xcc\x20\x48\xe8\x09\xf4\xf7\x2e\x75\xdd\x7f\x54\x5d\x9a\x50\x0b\x63\xf5\xd6\x72\xad\xec\x74\xb9\x60\x82\x4c\xe9\x35\x28\x83\xd9\x23\x6e\xa9\x5a\x34\x96\x11\xee\x8d\xab\x72\x54\xb5\x02\xe3\x30\xe7\x09\xb8\x7f\x94\xfb\xb4\x1b\x50\xf1\x39\xc2\x66\x5d\x17\x99\xc7\x88\x60\x2b\xbe\xcf\xf3\x7b\x16\x98\x4d\x61\xdb\xf4\x1c\x21\xdc\x37\xb4\x19\x25\x14\x39\xfb\xfd\x46\x0c\xb4\x27\x35\x89\x41\x5f\x8c\x7e\xb4\x64\x24\x0e\x81\x68\x98\x01\x21\xe1\x84\xcf\x31\xba\x23\x6b\xdc\x1e\x0d\xab\x2d\x52\x27\x8c\x4a\xcb\x3d\xb2\xf8\xa6\xb2\x02\x8b\x04\x7b\x74\x31\x03\xc9\x1d\xe5\x71\x03\x66\x0c\x87\xce\xb0\xc8\x3c\x69\x61\x16\x6c\x1e\x90\xf7\x09\xe0\xb9\xcb\xf8\x44\x3a\x4a\xcf\x59\x20\x3d\xc0\xd3\x5f\x70\xfa\x2f\x38\xfd\x91\xc3\xe9\x8b\x62\x60\x0a\x5a\x0f\xb9\xff\xc7\x0a\xb0\x2f\x12\x7a\x0a\x6c\x0f\x09\xfd\x91\x40\xee\x8b\x65\x9c\x84\xdf\x63\x82\x7e\x24\x20\xfc\x22\x61\x67\x02\xf2\x21\x91\xff\x9f\x61\xf9\x45\x3a\x9c\x80\xe8\x43\x7a\xfb\x28\x80\xfa\x6c\x01\x33\xad\xd2\x29\xf8\x04\x4a\xe9\x63\xad\x66\xc0\xf1\x3e\x30\x33\x8d\xb2\xb7\x4f\xdb\x85\xc9\xe7\xe0\xd4\x18\x24\x4f\xcf\x04\x30\xef\x4e\x72\x06\x93\x9d\xc7\xca\xe9\x59\x54\xdb\xd7\x67\x88\x78\xcd\x09\x92\x79\x08\x10\x40\xa2\xf3\x0f\x16\x95\x13\xf5\x0d\x8e\x69\xfa\x23\x8b\x7c\x8b\xdc\x76\x88\xb2\xe9\x32\x92\x7d\xc0\x37\x53\x56\x80\x36\x1e\xd5\x54\xfb\xf2\x8c\x69\x94\xf6\xc5\x58\xd3\xd1\x3e\x33\xa3\x84\x9f\x74\x0e\xb0\x82\x1c\x3d\x2d\x98\xa3\xb3\x62\xff\x18\x0f\x2b\x9f\x4d\x64\xc6\xf0\xc6\xea\x35\xe5\x7f\x9a\x54\x25\x39\x87\xdb\xcb\xc4\x79\x05\x45\x28\x51\x81\x25\xcc\x71\x2d\xa9\x9e\x84\xd1\x58\x3c\xad\x54\x5b\xc8\xc9\xa3\x90\xae\x73\xc2\xd2\xda\xf7\xd9\x84\xb5\x84\xee\x5c\x95\x80\xd3\x2b\x26\x69\x58\x3c\x28\xec\xd9\xe3\x85\x8b\x46\xfe\x23\x38\x1d\x3e\xb9\x9a\xe4\xf4\xbe\x39\x91\xea\x31\xf9\xb2\x3e\xc1\x7c\xb0\x81\x5e\xc2\x37\x28\x1d\xbd\x84\x1f\xd5\xa3\xd2\xfb\xe7\xe3\x37\x12\x5e\xa4\xd7\x83\x89\x5c\x35\x7c\x3e\x03\x2b\x6d\x77\x3f\x33\xd9\xdf\x35\x03\xea\x1d\x9a\xaa\x43\x5f\x04\x25\x7e\x0d\xfd\x46\xa5\x39\x64\xfa\xf4\xb8\x85\xb9\xbd\x7f\x1b\x9d\x23\xb5\xdb\x2e\x35\x32\x75\x6b\x77\x7b\xff\xd6\x7d\x76\xa6\x36\x4c\x4a\x65\x26\x1b\xd5\x9e\x3c\xdc\xd3\x1e\xb5\x5a\x52\x67\x9d\xab\x3f\xed\xb6\x8c\x09\x52\x2e\xe1\xce\xbf\x70\xcc\x83\xc8\x50\xca\x03\x77\x2d\xa2\xe4\xc0\x6c\x50\xcf\xb9\xaa\x36\xcd\xf9\x8c\x02\x71\x12\x6c\xb4\xd9\x50\xe6\xc5\x8e\x3a\xc3\x6b\x45\xa7\x0d\x27\xca\x2b\x39\xde\x8b\xb9\x7a\x2b\x67\x26\x6b\x6f\x2a\xf2\xda\x51\xba\xf6\x6f\xb5\x5a\x4d\x9a\x7a\xcd\xe8\x34\x8a\x60\xa3\x83\xca\x01\x7d\x34\xcf\x13\x79\xee\x9f\xe1\x7e\xb8\x03\xff\x69\xfc\xf4\x3c\x9b\x8d\x9d\x13\xf8\x06\x7d\x4d\x81\xaf\x36\xc9\xd1\x3b\xca\x42\xe7\x8e\x57\xf7\x0e\xc7\xd3\xf6\x1a\xcf\xbb\xec\x25\x68\x66\x56\xfa\x9c\x5b\x7f\xe7\xe2\x89\x67\x5d\xf4\x6c\xb9\x9f\x15\x69\xd3\x55\x77\x18\x7f\xbf\x49\x45\x37\x6e\x75\x66\x58\x92\xcc\xd0\x51\x7e\x5c\x8b\x13\x18\x9f\x53\x80\x67\x30\x7a\xae\xe8\xce\x98\x62\xba\x0e\x9e\x75\xfb\x58\x15\x13\xd5\xba\xbe\x05\xd1\xb4\x1b\x3d\xff\xe6\x7c\x82\x90\x91\x8d\x45\x26\x5d\xa2\x43\xd6\xd5\xbe\xd0\x4f\xce\x8c\x13\xd6\xee\xb1\xfe\x5d\x8d\xdf\x78\xc1\x88\xed\x16\x27\xd8\xae\xaa\x7f\x2d\xb6\xa3\xbc\x77\x95\x26\x16\xc9\x12\x0f\xf1\x6a\x5a\x69\xb4\xf5\x98\x0e\x38\x82\xca\xc9\x3a\x8f\x2a\xe7\xb1\xfb\xe2\x10\xd5\x60\x58\xe6\x02\x1d\x08\xef\x20\xf5\xc5\xbe\x32\xd8\xc5\x77\xb0\xe2\x7d\x97\xb3\x42\x76\x94\xfd\x9a\x07\x34\x10\xa1\xb7\x78\xaa\xab\x3d\xc3\x4c\x5a\x61\x9a\x31\x89\x13\x17\xab\xde\x37\xcf\xde\x7b\x32\xc7\x79\xb5\x23\x84\x8a\x70\x7c\x27\xf2\x74\x19\x89\x0c\x08\xf5\x3c\x49\xf5\xfc\x01\x4e\x3a\x98\x18\x0f\xab\x45\xb3\x4b\x33\x4a\x30\xd1\xd1\x9e\x4f\xea\xda\xa4\x9b\xf2\xe7\x62\x7f\xec\x6e\x5e\x7a\x1a\x29\xde\x33\x5d\x8e\xdf\x94\x4b\xcf\x89\x55\xeb\x5f\x5f\x4c\x58\xb7\x73\x57\x37\xde\x06\xf5\xb6\x42\x52\x87\x59\x36\x86\xb9\x5b\x10\x73\x36\x20\x16\xe9\x47\x18\x93\x14\x8f\x42\x9d\xde\x1f\xed\x12\x30\x00\x9b\x24\x68\x2f\x0e\xce\x24\x8b\x1b\x93\x93\xb4\xd5\xa1\xd4\x7b\x9e\x89\xa5\x5f\xa0\x7c\x98\x4d\xfc\x99\x13\xd5\x47\x48\xcf\x32\xd9\xf9\x5d\xf6\x99\x13\xb5\xa6\x79\xe6\xe9\x66\xec\x8f\xcf\x9c\x73\x37\x67\xe3\xf9\x19\xa0\xc7\x49\xc8\x57\xdd\xfe\x44\x4d\x32\x68\xbd\xc8\x82\x44\xdb\xc6\x7e\x4c\xf2\x27\xbf\x5b\xba\x98\x67\xe7\xd1\xfa\x31\x14\x7a\xbc\x29\x91\x28\x6b\x4e\xe3\xae\xd6\xbe\x20\xd5\x1c\xfe\xa5\x9f\x81\xc1\x9a\xb6\x5c\x3c\x8d\x91\x87\xfa\x37\x06\xed\x0d\x76\x29\x9c\x8f\xf8\xa1\xc5\x02\x73\xaf\x42\x8c\xaa\x7d\x0c\x02\x3b\xb2\x3b\xca\x57\xe0\x6d\x68\x5e\x79\x6d\x19\x17\xf5\xde\x85\x75\xc3\x5f\xab\x86\xca\x8e\xf0\xdb\xef\x57\xff\x0b\x00\x00\xff\xff\xae\xb2\xfa\x2c\x43\x37\x00\x00") +var _operatorsCoreosCom_installplansYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5b\x4b\x93\x1b\xb7\x11\xbe\xef\xaf\xe8\x5a\x1f\x64\x57\x89\x5c\xdb\xb9\x24\xbc\x29\xeb\x38\xb5\x89\x1f\x2a\xed\x5a\x17\xc7\x87\xe6\x4c\x93\x03\x2f\x06\x80\xf1\x20\xc5\xb8\xfc\xdf\x53\x0d\xcc\x93\x9c\x19\x0e\x57\x6b\x59\x95\xf2\x5c\xa4\x9d\x69\x00\xfd\xee\xaf\x01\x10\x8d\x78\x4b\xd6\x09\xad\x56\x80\x46\xd0\x3b\x4f\x8a\xff\x72\xcb\xc7\xbf\xba\xa5\xd0\x37\xbb\x2f\xae\x1e\x85\xca\x57\x70\x1b\x9c\xd7\xe5\x1b\x72\x3a\xd8\x8c\xbe\xa2\x8d\x50\xc2\x0b\xad\xae\x4a\xf2\x98\xa3\xc7\xd5\x15\x00\x2a\xa5\x3d\xf2\x6b\xc7\x7f\x02\x64\x5a\x79\xab\xa5\x24\xbb\xd8\x92\x5a\x3e\x86\x35\xad\x83\x90\x39\xd9\x38\x79\xbd\xf4\xee\xf3\xe5\xdf\x96\x9f\x5f\x01\x64\x96\xe2\xf0\x07\x51\x92\xf3\x58\x9a\x15\xa8\x20\xe5\x15\x80\xc2\x92\x56\x20\x94\xf3\x28\xa5\x91\xa8\xdc\x52\x1b\xb2\xe8\xb5\x75\xcb\x4c\x5b\xd2\xfc\x4f\x79\xe5\x0c\x65\xbc\xf6\xd6\xea\x60\x56\x30\x48\x93\x66\xab\x59\x44\x4f\x5b\x6d\x45\xfd\x37\xc0\x02\xb4\x2c\xe3\xff\x93\xe8\x77\x69\xd1\xd7\x12\x55\x7c\x2b\x85\xf3\xff\x3e\xfe\xf2\x8d\x70\x3e\x7e\x35\x32\x58\x94\x7d\x56\xe3\x07\x57\x68\xeb\xbf\x6b\x17\xe6\x85\x84\x49\x9f\x84\xda\x06\x89\xb6\x37\xea\x0a\xc0\x65\xda\xd0\x0a\xe2\x20\x83\x19\xe5\x57\x00\x95\xd2\xaa\x49\x16\x80\x79\x1e\x0d\x81\xf2\xb5\x15\xca\x93\xbd\xd5\x32\x94\xaa\x59\x84\x69\x72\x72\x99\x15\xc6\x47\x65\x3f\x14\x04\x1b\x61\x9d\x87\xdb\xfb\xb7\x20\x14\xf8\x82\xa2\x4c\xa0\x37\x90\xc9\xe0\x3c\xd9\x7b\xb2\x3b\x91\x51\xe5\x1b\x71\xfd\x66\x3a\x80\x9f\x9d\x56\xaf\xd1\x17\x2b\x58\xb2\xba\x97\xe3\x83\x7e\xfc\xfc\xa7\xce\xb8\x64\xc3\xdb\xfb\xb7\x9d\x77\xfe\xc0\x12\x3a\x6f\x85\xda\x4e\x71\x8c\xc6\x58\xbd\x43\x09\xa5\xce\x69\x82\x97\x9a\xee\x64\xd9\x57\xa7\x1f\x46\xd6\x1e\x9e\x32\x2a\x7f\x68\xca\xde\x87\x34\xe5\x5a\x6b\x49\x95\xb7\xd4\xc4\xbb\x2f\x50\x9a\x02\xbf\xa8\x5e\xba\xac\xa0\x12\x5b\x23\x69\x43\xea\xd5\xeb\xbb\xb7\x7f\xb9\x3f\xfa\x00\x7d\x5d\x74\x5c\x0e\x72\x8e\x42\x72\xd1\x80\x95\xe3\xc4\xe8\x61\x43\x22\x38\x8a\x16\x6d\x23\xe0\x84\x4d\xbd\xfe\x99\x32\xdf\x79\x6d\xe9\x97\x20\x2c\xe5\xdd\xd5\x59\x23\x75\x8c\x1f\xbd\x66\xed\x74\x5e\x19\xcb\x6b\xf9\x4e\x24\xa5\xa7\x93\x64\x7a\xef\x8f\x24\x7b\xc1\xe2\x27\xba\x9e\x64\x95\xc3\x53\x5e\xe9\x8c\x85\xf2\x85\x70\x60\xc9\x58\x72\xa4\x7c\x2b\xb4\xaa\x64\x5a\x02\x3b\x23\x59\xc7\x51\x17\x64\xce\x89\x68\x47\xd6\x83\xa5\x4c\x6f\x95\xf8\x6f\x33\x9b\x03\xaf\x53\x04\xa0\x27\xe7\x21\x86\x90\x42\x09\x3b\x94\x81\x5e\x02\xaa\x1c\x4a\x3c\x80\x25\x9e\x17\x82\xea\xcc\x10\x49\xdc\x12\xbe\xd5\x96\x0d\xb0\xd1\x2b\x28\xbc\x37\x6e\x75\x73\xb3\x15\xbe\x4e\xa1\x99\x2e\xcb\xa0\x84\x3f\xdc\xc4\x6c\x28\xd6\x81\xad\x71\x93\xd3\x8e\xe4\x8d\x13\xdb\x05\xda\xac\x10\x9e\x32\x1f\x2c\xdd\xa0\x11\x8b\xc8\xac\x8a\x69\x74\x59\xe6\x9f\xd8\x2a\xe9\xba\x17\x47\xea\x1b\xf4\x5f\xa8\xf3\xd6\xa4\xae\x39\x7f\x81\x70\xec\x26\x71\x78\x92\xa5\x55\x29\xbf\x62\xad\xbc\xf9\xc7\xfd\x03\xd4\x0c\x24\xb5\x27\x0d\xb7\xa4\xae\x55\x36\x2b\x4a\xa8\x0d\xd9\x44\xb9\xb1\xba\x8c\xb3\x90\xca\x8d\x16\xca\xc7\x3f\x32\x29\x48\x79\x70\x61\x5d\x0a\xef\xa2\xcf\x91\xf3\x6c\x87\x25\xdc\xc6\x0a\x02\x6b\x82\x60\x72\xf4\x94\x2f\xe1\x4e\xc1\x2d\x96\x24\x6f\xd1\xd1\xef\xae\x6a\xd6\xa8\x5b\xb0\xfa\xe6\x2b\xbb\x5b\x00\x4f\x07\x9c\xc4\x18\x40\x5d\xa2\x46\xad\xd3\x89\xf1\x7b\x43\x59\x13\x0d\x4d\x4c\xbf\x32\x46\x8a\x2c\xb9\x7d\xe3\x1d\xec\xc8\xeb\x26\x11\xf4\xb2\xd2\x24\x3b\x63\x61\x0f\xa9\xbc\x9c\xa6\xcd\xfe\xa7\x93\x85\xf8\xd3\xac\x32\x02\x13\x39\x03\x62\xde\x48\x4b\x9f\x7e\x39\xd2\x57\x9d\xda\xd9\xa1\xd9\xc3\x82\x23\xdb\x16\x0c\xa3\xa5\xc8\x0e\xb0\xd1\x96\xf3\x43\x47\xb7\x4b\xb8\xf3\x50\x06\x17\xfd\x4d\x2b\x62\xcd\x5e\xbf\x0a\x5e\x97\xe8\x45\x76\x0d\xda\xc2\xf5\xb7\xa8\x02\xca\xeb\xe5\x00\x0b\xa3\x0e\xd1\xf2\x3e\xa4\xd2\xe1\x1a\xd1\x3e\xe3\xaa\x1b\x9f\x0b\xad\xc5\xc3\xc0\x57\xe1\xa9\x1c\x1c\x76\x86\xfb\x2d\x29\x2e\x1a\x03\x19\xbb\x1d\xca\x89\x72\x4b\xf6\xe4\x7b\xf2\xc6\xf1\x71\x23\x4b\xa6\x61\x0d\xd2\xb9\x68\xbc\xf3\xe8\xc3\x89\x9c\x3d\x17\xb9\xee\xc6\x54\x24\xef\x24\xb0\xaa\x80\x6e\xb4\x2d\x53\x4c\xe1\x5a\x87\x94\xac\xd2\xd4\xec\x19\xce\x93\x71\x4d\xa8\x70\xb0\x65\xba\x34\x92\x7c\xbf\xf6\x2e\xe1\x3f\x0a\xaa\x15\x38\x1d\x7a\x8b\x42\xc6\xa9\x30\xf3\x01\x65\x9c\x91\xaa\x0a\x7d\x70\x9e\xca\xe5\xf5\xf3\x44\x6a\x86\x1e\xa5\xde\xde\xa7\x6c\x30\x40\x60\x0a\x74\x74\x49\xfc\x79\x4f\x2a\x70\x16\xae\x9c\xf1\x55\x96\xe9\xa0\xfc\x1b\xda\x9c\x0f\xc9\xf1\xb1\x60\x69\x43\x96\x54\x56\xd5\x77\x97\x08\x00\x13\x05\xf8\x02\x3d\x47\x72\x70\x49\xcd\xb9\x4e\x38\x38\x6f\xa0\x4c\xad\xf0\xf1\xa8\x1c\x54\xde\x39\x79\x61\x12\xab\x0c\x8b\xf9\xfa\xae\xc6\x27\x09\x96\x50\x2d\x9d\x1f\x62\x0e\xce\x45\x01\x3f\x1b\x41\x32\x8f\xf8\x73\x0e\x07\x2f\xee\x2a\x85\xc6\x2a\xee\x35\x20\x18\x41\x19\xf5\xe0\x50\x54\x18\x61\x5e\xbd\xe4\x82\x67\xa9\xfa\xf6\x32\xd5\xea\x0a\x06\xb4\x70\xc9\xa3\x50\x80\x8c\x0b\x44\x0e\xff\xba\xff\xfe\xbb\x9b\x7f\xea\xc4\x1b\x5b\x8a\x9c\x4b\x9e\x5c\x92\xf2\x2f\xc1\x85\xac\x00\x74\xcc\x1a\xbb\x27\xfb\x3f\x2d\x4b\x54\x62\x43\xce\x2f\xab\xd9\xc8\xba\x1f\xbf\xfc\x69\x09\x5f\x6b\x0b\xf4\x0e\x39\x78\x5e\x82\x48\x5a\x6b\x40\x45\xe5\x1a\x31\x95\xb3\x30\xcd\x58\xd8\x0b\x5f\x44\x96\x8c\xce\x2b\xa6\xf7\x91\x59\x8f\x8f\x9c\xbf\x13\xb3\x81\x7b\x99\x47\x5a\xc1\x75\x6a\x4d\x9a\xa5\x7f\x65\x18\xfe\xdb\x35\x7c\xba\x2f\xc8\x12\x5c\xf3\x9f\xd7\x69\xc1\x06\x03\xf2\xbb\xda\x8e\xed\xc2\xd1\x21\xbd\x15\xdb\x2d\xc5\xc8\x67\x40\xc3\xa0\xe1\x33\xae\x10\x62\x03\x4a\x77\x88\xe3\x14\xac\x4f\x43\x99\xd8\x08\xca\x4f\x18\xf9\xf1\xcb\x9f\xae\xe1\xd3\xbe\x5c\x20\x54\x4e\xef\xe0\xcb\xd4\x8e\x09\xc7\x32\x7e\xb6\x84\x87\x68\x99\x83\xf2\xf8\x8e\xe7\xcc\x0a\xed\x48\x81\x56\xf2\xc0\x1c\x17\xb8\x23\x70\xba\x24\xd8\x93\x94\x8b\x84\x12\x72\xd8\xe3\x81\x65\xa8\x55\xc9\x56\x45\x30\x68\xfd\x11\x42\x7e\xf8\xfe\xab\xef\x57\x69\x35\x36\xdb\x56\xf1\x12\x8c\xbe\x36\x82\xf1\x2f\x03\xdf\x84\xe2\xa2\xcd\x99\x91\x90\x8c\xc4\xa9\xaf\x40\xb5\xa5\xba\x79\xdc\x04\xc6\x53\xcb\x63\xc4\x34\xdb\xe3\x87\xe0\xea\xb0\xb3\x47\xd8\x7a\x1c\x68\x7f\x20\x28\x9c\x2d\x62\xec\x01\x67\x89\xf8\x5d\xc7\x07\x27\x45\x7c\x0c\x6b\xb2\x8a\x3c\x45\x29\x73\x9d\x39\x16\x30\x23\xe3\xdd\x8d\xde\x71\x52\xa5\xfd\xcd\x5e\xdb\x47\xa1\xb6\x0b\x76\xb2\x45\xb2\xbc\xbb\x89\xbb\x1f\x37\x9f\xc4\x7f\xde\x4b\xa2\xd1\x52\x3d\x2c\x56\x24\xff\x10\xb2\xf1\x3a\xee\xe6\xc9\xa2\xd5\x90\xfa\x92\x4a\xf0\xe2\x3e\x05\x7c\x76\x3c\x9a\xc3\x65\x5f\x88\xac\xa8\x9b\xd6\x4e\x86\x2b\x31\x4f\x29\x10\xd5\xe1\x77\x77\x63\x56\x60\xb0\xbc\xf6\x61\x51\xed\xcb\x2d\x50\xe5\xfc\x7f\x27\x9c\xe7\xf7\x4f\xd6\x58\x10\x33\x03\xf8\x87\xbb\xaf\x3e\x8c\x73\x07\xf1\xc4\x68\x5d\x07\x95\x4b\xfa\x46\xeb\xc7\x60\x06\x41\x42\x4f\xa0\xbf\x77\xa9\xeb\xfe\xa3\xea\xd2\x84\x5a\x18\xab\xb7\x96\x6b\x65\xa7\xcb\x05\x13\x64\x4a\xaf\x41\x19\xcc\x1e\x71\x4b\xd5\xa2\xb1\x8c\x70\x6f\x5c\x95\xa3\xaa\x15\x18\x87\x39\x4f\xc0\xfd\xa3\xdc\xa7\xdd\x80\x8a\xcf\x11\x36\xeb\xba\xc8\x3c\x46\x04\x5b\xf1\x7d\x9e\xdf\xb3\xc0\x6c\x0a\xdb\xa6\xe7\x08\xe1\xbe\xa1\xcd\x28\xa1\xc8\xd9\xef\x37\x62\xa0\x3d\xa9\x49\x0c\xfa\x62\xf4\xa3\x25\x23\x71\x08\x44\xc3\x0c\x08\x09\x27\x7c\x8e\xd1\x1d\x59\xe3\xf6\x68\x58\x6d\x91\x3a\x61\x54\x5a\xee\x91\xc5\x37\x95\x15\x58\x24\xd8\xa3\x8b\x19\x48\xee\x28\x8f\x1b\x30\x63\x38\x74\x86\x45\xe6\x49\x0b\xb3\x60\xf3\x80\xbc\x4f\x00\xcf\x5d\xc6\x27\xd2\x51\x7a\xce\x02\xe9\x01\x9e\xfe\x84\xd3\x7f\xc2\xe9\x8f\x1c\x4e\x5f\x14\x03\x53\xd0\x7a\xc8\xfd\x3f\x56\x80\x7d\x91\xd0\x53\x60\x7b\x48\xe8\x8f\x04\x72\x5f\x2c\xe3\x24\xfc\x1e\x13\xf4\x23\x01\xe1\x17\x09\x3b\x13\x90\x0f\x89\xfc\xff\x0c\xcb\x2f\xd2\xe1\x04\x44\x1f\xd2\xdb\x47\x01\xd4\x67\x0b\x98\x69\x95\x4e\xc1\x27\x50\x4a\x1f\x6b\x35\x03\x8e\xf7\x81\x99\x69\x94\xbd\x7d\xda\x2e\x4c\x3e\x07\xa7\xc6\x20\x79\x7a\x26\x80\x79\x77\x92\x33\x98\xec\x3c\x56\x4e\xcf\xa2\xda\xbe\x3e\x43\xc4\x6b\x4e\x90\xcc\x43\x80\x00\x12\x9d\x7f\xb0\xa8\x9c\xa8\x6f\x70\x4c\xd3\x1f\x59\xe4\x1b\xe4\xb6\x43\x94\x4d\x97\x91\xec\x03\xbe\x99\xb2\x02\xb4\xf1\xa8\xa6\xda\x97\x67\x4c\xa3\xb4\x2f\xc6\x9a\x8e\xf6\x99\x19\x25\xfc\xa4\x73\x80\x15\xe4\xe8\x69\xc1\x1c\x9d\x15\xfb\x87\x78\x58\xf9\x6c\x22\x33\x86\x37\x56\xaf\x29\xff\xc3\xa4\x2a\xc9\x39\xdc\x5e\x26\xce\x2b\x28\x42\x89\x0a\x2c\x61\x8e\x6b\x49\xf5\x24\x8c\xc6\xe2\x69\xa5\xda\x42\x4e\x1e\x85\x74\x9d\x13\x96\xd6\xbe\xcf\x26\xac\x25\x74\xe7\xaa\x04\x9c\x5e\x31\x49\xc3\xe2\x41\x61\xcf\x1e\x2f\x5c\x34\xf2\xef\xc1\xe9\xf0\xc9\xd5\x24\xa7\xf7\xcd\x89\x54\x8f\xc9\x97\xf5\x09\xe6\x83\x0d\xf4\x12\xbe\x46\xe9\xe8\x25\xfc\xa0\x1e\x95\xde\x3f\x1f\xbf\x91\xf0\x22\xbd\x1e\x4c\xe4\xaa\xe1\xf3\x19\x58\x69\xbb\xfb\x99\xc9\xfe\xae\x19\x50\xef\xd0\x54\x1d\xfa\x22\x28\xf1\x4b\xe8\x37\x2a\xcd\x21\xd3\xa7\xc7\x2d\xcc\xed\xfd\xdb\xe8\x1c\xa9\xdd\x76\xa9\x91\xa9\x5b\xbb\xdb\xfb\xb7\xee\xb3\x33\xb5\x61\x52\x2a\x33\xd9\xa8\xf6\xe4\xe1\x9e\xf6\xa8\xd5\x92\x3a\xeb\x5c\xfd\x69\xb7\x65\x4c\x90\x72\x09\x77\xfe\x85\x63\x1e\x44\x86\x52\x1e\xb8\x6b\x11\x25\x07\x66\x83\x7a\xce\x55\xb5\x69\xce\x67\x14\x88\x93\x60\xa3\xcd\x86\x32\x2f\x76\xd4\x19\x5e\x2b\x3a\x6d\x38\x51\x5e\xc9\xf1\x5e\xcc\xd5\x5b\x39\x33\x59\x7b\x53\x91\xd7\x8e\xd2\xb5\x7f\xab\xd5\x6a\xd2\xd4\x6b\x46\xa7\x51\x04\x1b\x1d\x54\x0e\xe8\xa3\x79\x9e\xc8\x73\xff\x0c\xf7\xc3\x1d\xf8\x4f\xe3\xa7\xe7\xd9\x6c\xec\x9c\xc0\x37\xe8\x6b\x0a\x7c\xb5\x49\x8e\xde\x51\x16\x3a\x77\xbc\xba\x77\x38\x9e\xb6\xd7\x78\xde\x65\x2f\x41\x33\xb3\xd2\xe7\xdc\xfa\x3b\x17\x4f\x3c\xeb\xa2\x67\xcb\xfd\xac\x48\x9b\xae\xba\xc3\xf8\xfb\x4d\x2a\xba\x71\xab\x33\xc3\x92\x64\x86\x8e\xf2\xe3\x5a\x9c\xc0\xf8\x9c\x02\x3c\x83\xd1\x73\x45\x77\xc6\x14\xd3\x75\xf0\xac\xdb\xc7\xaa\x98\xa8\xd6\xf5\x2d\x88\xa6\xdd\xe8\xf9\x37\xe7\x13\x84\x8c\x6c\x2c\x32\xe9\x12\x1d\xb2\xae\xf6\x85\x7e\x72\x66\x9c\xb0\x76\x8f\xf5\x6f\x6b\xfc\xc6\x0b\x46\x6c\xb7\x38\xc1\x76\x55\xfd\x6b\xb1\x1d\xe5\xbd\xab\x34\xb1\x48\x96\x78\x88\x57\xd3\x4a\xa3\xad\xc7\x74\xc0\x11\x54\x4e\xd6\x79\x54\x39\x8f\xdd\x17\x87\xa8\x06\xc3\x32\x17\xe8\x40\x78\x07\xa9\x2f\xf6\x95\xc1\x2e\xbe\x83\x15\xef\xbb\x9c\x15\xb2\xa3\xec\xd7\x3c\xa0\x81\x08\xbd\xc5\x53\x5d\xed\x19\x66\xd2\x0a\xd3\x8c\x49\x9c\xb8\x58\xf5\xbe\x79\xf6\xde\x93\x39\xce\xab\x1d\x21\x54\x84\xe3\x3b\x91\xa7\xcb\x48\x64\x40\xa8\xe7\x49\xaa\xe7\x0f\x70\xd2\xc1\xc4\x78\x58\x2d\x9a\x5d\x9a\x51\x82\x89\x8e\xf6\x7c\x52\xd7\x26\xdd\x94\x3f\x17\xfb\x63\x77\xf3\xd2\xd3\x48\xf1\x9e\xe9\x72\xfc\xa6\x5c\x7a\x4e\xac\x5a\xff\xfa\x62\xc2\xba\x9d\xbb\xba\xf1\x36\xa8\xb7\x15\x92\x3a\xcc\xb2\x31\xcc\xdd\x82\x98\xb3\x01\xb1\x48\x3f\xc2\x98\xa4\x78\x14\xea\xf4\xfe\x68\x97\x80\x01\xd8\x24\x41\x7b\x71\x70\x26\x59\xdc\x98\x9c\xa4\xad\x0e\xa5\xde\xf3\x4c\x2c\xfd\x02\xe5\xc3\x6c\xe2\xcf\x9c\xa8\x3e\x42\x7a\x96\xc9\xce\xef\xb2\xcf\x9c\xa8\x35\xcd\x33\x4f\x37\x63\x7f\x7c\xe6\x9c\xbb\x39\x1b\xcf\xcf\x00\x3d\x4e\x42\xbe\xea\xf6\x27\x6a\x92\x41\xeb\x45\x16\x24\xda\x36\xf6\x63\x92\x3f\xf9\xdd\xd2\xc5\x3c\x3b\x8f\xd6\x8f\xa1\xd0\xe3\x4d\x89\x44\x59\x73\x1a\x77\xb5\xf6\x05\xa9\xe6\xf0\x2f\xfd\x0c\x0c\xd6\xb4\xe5\xe2\x69\x8c\x3c\xd4\xbf\x31\x68\x6f\xb0\x4b\xe1\x7c\xc4\x0f\x2d\x16\x98\x7b\x15\x62\x54\xed\x63\x10\xd8\x91\xdd\x51\xbe\x02\x6f\x43\xf3\xca\x6b\xcb\xb8\xa8\xf7\x2e\xac\x1b\xfe\x5a\x35\x54\x76\x84\x5f\x7f\xbb\xfa\x5f\x00\x00\x00\xff\xff\xa9\xc5\x05\x0b\x43\x37\x00\x00") func operatorsCoreosCom_installplansYamlBytes() ([]byte, error) { return bindataRead( @@ -145,7 +145,7 @@ func operatorsCoreosCom_installplansYaml() (*asset, error) { return a, nil } -var _operatorsCoreosCom_olmconfigsYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb4\x58\x6f\x6f\xdb\x46\xd2\x7f\xef\x4f\x31\xd0\xf3\x00\xb1\x73\x12\x15\x27\x87\x5c\x4a\x20\x08\x02\xe5\x5c\x04\x89\xaf\x41\xec\xcb\x01\x67\xf9\xae\x43\x72\x44\x6d\x43\xee\xb2\xbb\xb3\xb6\xd5\xa2\xdf\xfd\x30\xbb\x24\x45\xc9\xa2\x63\xa0\xad\xde\x58\x9a\x9d\x9d\x9d\xbf\xbf\x99\x31\x36\xea\x0b\x59\xa7\x8c\x4e\x01\x1b\x45\x77\x4c\x5a\x7e\xb9\xe4\xeb\x2b\x97\x28\x33\xbf\x39\x3d\xfa\xaa\x74\x91\xc2\xc2\x3b\x36\xf5\x67\x72\xc6\xdb\x9c\xde\xd1\x4a\x69\xc5\xca\xe8\xa3\x9a\x18\x0b\x64\x4c\x8f\x00\x50\x6b\xc3\x28\x64\x27\x3f\x01\x72\xa3\xd9\x9a\xaa\x22\x3b\x2b\x49\x27\x5f\x7d\x46\x99\x57\x55\x41\x36\x08\xef\x9e\xbe\x79\x96\xbc\x4a\x9e\x1d\x01\xe4\x96\xc2\xf5\x4b\x55\x93\x63\xac\x9b\x14\xb4\xaf\xaa\x23\x00\x8d\x35\xa5\x60\xaa\x3a\x37\x7a\xa5\x4a\x97\x98\x86\x2c\xb2\xb1\x2e\xc9\x8d\x25\x23\x7f\xea\x23\xd7\x50\x2e\x2f\x97\xd6\xf8\x26\x85\x83\x3c\x51\x56\xa7\x20\x32\x95\xc6\xaa\xee\x37\xc0\x4c\x1e\x09\xdf\xa3\xe1\x3f\x7c\x3c\x5f\x84\x27\x03\xad\x52\x8e\x3f\xec\xd2\x3f\x2a\xc7\xe1\xac\xa9\xbc\xc5\x6a\xa8\x64\x20\x3b\xa5\x4b\x5f\xa1\x1d\x1c\x1c\x01\xb8\xdc\x34\x94\xc2\xa2\xf2\x8e\xc9\x1e\x01\xb4\xce\x68\xf5\x98\xb5\x06\xdf\x9c\xb6\x6a\xb9\x7c\x4d\x35\x76\x4a\x82\x98\xa6\xdf\x7e\x7a\xff\xe5\xc5\xc5\xde\x01\x40\x41\x2e\xb7\xaa\xe1\xe0\xda\x5e\x4d\x50\x0e\x10\x6c\x1b\x40\xf9\xd2\x18\xed\x54\x56\x11\xac\x8c\x85\xa8\x98\xb7\x4a\x97\x72\x27\x19\xc8\xe3\x8d\x68\x6a\xb2\x9f\x28\xe7\x01\xd9\xd2\xcf\x5e\x59\x2a\x86\x4f\x8b\xe2\x5d\x42\x0c\xc8\x8d\x95\x48\xf0\xc0\xcb\xf1\x33\x48\xbf\x1d\xfa\x9e\x0d\x4f\xc4\xd0\xc8\x07\x85\x64\x1e\x39\xe0\x35\x75\x2e\xa3\xa2\xf5\x0e\x98\x15\xf0\x5a\x39\xb0\xd4\x58\x72\xa4\x63\x2e\x0a\x19\x75\x6b\x40\x02\x17\x64\xe5\x22\xb8\xb5\xf1\x55\x21\x86\xdf\x90\x65\xb0\x94\x9b\x52\xab\x5f\x7a\x69\x0e\xd8\x84\x67\x2a\x64\x72\x0c\x4a\x33\x59\x8d\x15\xdc\x60\xe5\x69\x0a\xa8\x0b\xa8\x71\x03\x96\x44\x2e\x78\x3d\x90\x10\x58\x5c\x02\xe7\xc6\x12\x28\xbd\x32\x29\xac\x99\x1b\x97\xce\xe7\xa5\xe2\xae\xb8\x72\x53\xd7\x5e\x2b\xde\xcc\x43\x9d\xa8\xcc\x4b\xae\xce\x0b\xba\xa1\x6a\xee\x54\x39\x43\x9b\xaf\x15\x53\xce\xde\xd2\x1c\x1b\x35\x0b\xca\xea\x50\x60\x49\x5d\xfc\x5f\x17\x4d\xf7\x64\xcf\x7d\x31\x64\x8e\x25\x9c\x3b\x47\x21\xa7\x1f\xf4\xb5\x64\x77\xcc\x95\x78\x3d\xda\xb2\x75\xa9\x90\xc4\x2b\x9f\xff\x7e\x71\xb9\x4d\xa7\xe0\xf6\xe8\xe1\x2d\xab\xdb\x3a\x5b\x1c\xa5\xf4\x8a\x6c\xe4\x5c\x59\x53\x07\x29\xa4\x8b\xc6\x28\xcd\xe1\x47\x5e\x29\xd2\x0c\xce\x67\xb5\x62\x17\x12\x8c\x1c\x4b\x1c\x12\x58\x04\x6c\x81\x8c\xc0\x37\x05\x32\x15\x09\xbc\xd7\xb0\xc0\x9a\xaa\x05\x3a\xfa\xd3\x5d\x2d\x1e\x75\x33\x71\xdf\xe3\x9d\x3d\x84\xc6\xfb\x17\xee\x15\x14\x40\x07\x5f\xa3\xd1\xe9\xab\xf9\xa2\xa1\x5c\xa2\x24\x6e\x93\x5b\xa1\x86\x51\x0f\xca\xbd\x0b\x4d\xf2\xd8\xc7\xc7\xcb\x54\x3e\x2b\x42\x71\xcd\x81\x93\x3d\x15\xcf\x5a\xc6\x80\xfd\xa8\x74\xd4\x51\x70\x53\xea\xb0\x83\x19\x14\xdc\xf9\xe1\xe3\x79\x2f\x77\x5f\xcd\x6f\xa8\xfa\x2d\x75\x83\x5a\xca\xc9\x33\x0b\xd3\x28\x2a\x16\x17\x5f\x46\xd8\xf6\xf4\x7f\xb7\x7f\x4b\xdc\xec\x1d\x15\x02\x07\xad\x48\xd1\xfc\x89\x83\x49\x64\x82\xc5\xc5\x97\x49\x67\x48\x08\x44\xdf\x77\x40\x69\xc7\x58\x55\x54\x00\x76\x39\x1e\x00\x3f\xe2\xff\x14\x6e\xd7\x64\x09\x70\x97\x5c\xf4\x02\xe4\x6d\xa3\xa5\xbc\x90\x61\x8d\x0e\x32\x22\x3d\x10\xaa\x74\x08\x7a\xcb\xfd\xbd\x74\xbd\xc8\xcb\x68\x4b\x62\x07\x58\x55\xb1\xdd\x35\x98\x0b\x20\xfd\x6b\x4d\x1a\x2c\x91\x16\x33\x8a\x69\x08\xc1\xad\xaa\x2a\x81\x3f\xe9\xbd\x14\x94\x1c\x18\xe6\x26\xc1\x22\xc2\x7c\x3d\xa6\xe4\xa1\xd0\x6d\xc3\x97\x19\x53\x11\xea\xdd\x3c\x67\x64\x7f\x2f\x1c\x23\x99\x1e\x78\xfb\x5c\x8f\xbf\xfe\xec\x6c\xcf\x8d\x2e\xd4\x60\x8e\x39\x24\x14\xad\xc5\xcd\x81\x53\xc5\x54\x8f\x65\xe4\xd0\xc2\xc9\xa2\x7b\x64\x5b\x2a\x05\x31\xaa\x2a\xda\x27\x71\x47\xa9\x6d\x8e\x7d\x8d\x20\xf7\xd6\x06\x80\x64\x09\x54\xd7\xec\xde\x7e\x7a\x0f\xdd\x5c\x96\xc0\x6c\x36\x83\x4b\x21\x3b\xb6\x3e\x67\xf1\x9b\x34\x2e\x5d\x50\x11\xa4\x16\xca\x86\x6e\xe5\x44\xb8\xf8\x30\x98\xd1\x65\xe7\x4a\x51\x55\x40\x83\xbc\x86\x24\xba\x3a\xd9\xba\x22\x01\x38\x93\x54\xb8\xc3\xba\xa9\x68\x1a\xdc\x00\x67\xc6\xb4\x11\x8a\x0f\xfe\x0a\xf3\x39\x7c\xee\x3b\x40\x90\x6a\x32\x47\xf6\x26\xce\x85\xa1\x19\xc3\xca\x98\x27\x6e\xd7\x9e\x44\x2e\x7e\xd0\xe6\x56\x1f\x7a\x3a\xbc\x85\x96\x52\x58\x4e\xde\xde\xa0\xaa\x24\x7f\x97\x93\x29\x2c\x27\x9f\xac\x29\x2d\x39\x19\xb3\x84\x20\x6d\x79\x39\x79\x47\xa5\xc5\x82\x8a\xe5\x44\xc4\xfe\xa5\x41\xce\xd7\xe7\x64\x4b\xfa\x40\x9b\xd7\x41\x58\x4f\xbe\x60\x2b\x43\xe0\xe6\x75\x2d\xe7\x81\x2e\x68\x75\xb9\x69\xe8\x75\x8d\x4d\x4f\x38\xc7\xa6\xbf\xdc\x87\xce\xc1\xd5\xb5\xc0\xfc\xcd\x69\xb2\x0d\xe7\x8f\x3f\x39\xa3\xd3\xe5\x64\xab\xff\xd4\xd4\x92\x16\x0d\x6f\x96\x13\xd8\x79\x35\x5d\x4e\xc2\xbb\x1d\xbd\x53\x32\x5d\x4e\xe4\x25\x21\x5b\xc3\x26\xf3\xab\x74\x39\xc9\x36\x4c\x6e\x7a\x3a\xb5\xd4\x4c\xa5\xaa\x5f\x6f\x5f\x58\x4e\x7e\x84\xa5\x16\x65\x0d\xaf\xc9\xc6\x48\x3a\xf8\x6d\x72\x30\x11\xbf\x81\xac\x63\xc3\xdd\xf6\x33\x83\x0a\x1d\x5f\x5a\xd4\x4e\x75\x03\xfb\x28\x6b\x4d\xce\x61\x39\x7e\x6e\x09\x9d\xd1\xa3\xc7\x31\x1b\x46\x8f\xc5\x96\x83\x87\xdf\xea\x0f\x70\xc0\x86\x31\xce\xbd\xda\xbd\x7f\xb1\x03\x28\x39\x01\x16\x42\xa8\xd8\x3e\x27\xb8\xe7\x96\x42\x94\xf1\x47\xea\xbb\x85\x33\x36\x80\x3a\xc4\x2d\x69\x8b\x37\xce\xa6\x19\x49\x83\xd0\x41\x94\xd7\x05\xd9\x6a\x23\xe3\xd7\x56\x6a\xbe\x46\x5d\xca\x2c\x04\xef\x57\x11\xf8\x95\x03\x99\x93\xbe\x4a\x21\x4d\xe5\xa2\x06\xef\xba\x99\x2d\xe8\xd5\x4b\x14\xe0\x88\x05\xdf\x8a\x09\x63\x5f\x9e\x53\xc3\x52\x5d\x63\xb0\xfe\xc0\xc0\x33\xfc\xac\x8c\xad\x91\x53\x90\x61\x6d\xc6\xe3\xe9\xd1\x26\xc7\x23\x1d\xdf\x72\xc7\x01\x75\xed\x6b\x94\x6e\x86\x45\x68\xca\xfd\x99\x2e\x54\x8e\x61\x50\xed\xf0\x14\x33\xe3\x23\xc2\x6d\xe3\xd0\xba\x5a\x26\xd3\x8c\x04\x09\x43\x7d\xb6\x66\xfd\x4e\xe3\x6b\xbc\xfb\x48\xba\xe4\x75\x0a\x2f\x9e\xff\xed\xe5\xab\x11\xc6\x08\x8c\x54\x7c\x4f\x5a\x5a\xe9\x81\x3d\x68\xc4\x0d\xf7\x2f\x0e\xa6\xee\x60\x67\xd2\x0d\x9f\x49\xb9\xe5\x89\xa3\xc1\x4e\x5e\xde\xa2\x03\x47\x0c\x19\xca\x88\xe3\x1b\xf1\x8b\xa0\x7c\x98\x31\x74\x4e\x53\x50\xab\xc3\xc2\x54\x0f\xe0\xd5\x06\x4e\x9f\x4f\x21\x6b\x5d\x7c\x1f\xbe\xaf\xee\xae\x93\x03\x2a\x2b\x07\xdf\x4d\xf7\xf4\x91\x81\xc7\x87\x8e\x27\x89\x03\xb7\x8a\xd7\x61\x57\x95\xa6\xd5\xee\x63\x07\xda\x20\xf5\xfa\x7e\x2b\x70\xd2\x0c\xcb\xb0\x70\x1f\xfe\x74\x69\xab\x34\xbf\xfc\xeb\x78\x7c\x95\x56\xb5\xaf\x53\x78\x36\xc2\x12\x21\xed\x91\xd1\x8c\xcc\xdb\x29\x00\x05\xba\x4a\x8b\x75\x8d\xac\x72\x50\x85\xec\x21\x2b\x45\x76\x98\xda\x62\x74\x7b\x51\xfa\xfa\x8e\x17\x9f\xb8\x16\x87\x06\xc9\xfe\xc9\x9a\xc2\xe7\xb2\x8b\x99\x55\x58\x19\xd4\x4a\xe5\x43\x80\x92\x05\x27\x54\x43\x5c\xb1\x81\xee\xc4\xe9\xfd\x32\x1b\xf7\x5d\x42\xad\x74\xe9\xda\x27\x65\x93\x13\x00\x89\x5d\xf7\x76\x4d\xa1\xf5\x84\xd5\xbc\xbd\x63\x83\x56\x4e\x15\x64\x65\x06\x86\xd2\xa3\x45\xcd\x44\x85\xc0\x8f\x94\x60\xcb\x3b\x80\x3c\xdc\xae\x75\x5d\x35\xc6\x52\x8d\x60\x25\x2a\xb6\xab\x60\xa8\xd8\x3f\xae\x54\x4f\x9f\x3d\x7f\x30\xe4\x3d\xdf\x28\x53\x83\xcc\x64\x75\x0a\xff\xb9\x7a\x3b\xfb\x37\xce\x7e\xb9\x3e\x6e\xbf\x3c\x9b\x7d\xf7\xdf\x69\x7a\xfd\x74\xf0\xf3\xfa\xe4\xcd\xff\x8f\x48\x3a\x3c\x20\x8f\xa4\x4f\xdb\x44\xba\x21\xb1\x8b\xe8\x34\x74\x18\xb3\x82\x4b\xeb\x69\x0a\x67\x58\x39\x9a\xc2\x3f\x75\x68\x0d\xbf\xd3\x69\xa4\x7d\x3d\xae\x9d\x74\xe5\x89\xbc\x7a\x78\xf8\xe8\x59\x82\x4a\x0f\xf3\xb4\xea\x3e\xb4\x61\x3c\xce\x49\x61\x6c\x8b\x0b\x68\x87\x34\x83\x7f\x1f\x40\x40\x3c\x19\x4b\x93\x76\xbc\x4d\x72\x53\xcf\x07\xff\x5e\x90\xb9\xfa\x1c\xf5\x06\xb6\xb0\x16\x87\xd2\xfd\x4c\x77\x2c\xd8\x84\xb9\x35\xce\xf5\x6b\x89\x83\x4a\x7d\x25\xe8\x27\xd7\x08\x96\x19\xe5\x18\x06\x71\x9b\x29\xb6\x68\x37\x83\xbd\x03\x72\xd4\xe1\xbf\x1d\x8e\x56\xbe\x82\x63\x47\x04\x89\x36\x05\xdd\x47\xd7\x93\x88\xa1\x98\xa9\x4a\xf1\x26\xac\xa9\x24\x7b\x76\xa5\xda\xf9\xbf\x6e\x8c\x65\xd4\x1c\xcb\xcd\x52\x49\x77\xa0\x18\x6a\x99\x37\x29\xac\x56\xc7\x85\x76\xa7\xa7\xcf\x5f\x5c\xf8\xac\x30\x35\x2a\x7d\x56\xf3\xfc\xe4\xcd\xf1\xcf\x1e\x2b\x41\x9e\xe2\x1f\x58\xd3\x59\xcd\x27\x7f\x5c\x5b\x3c\x7d\xf9\x88\x2a\x3a\xbe\x8a\xb5\x72\x7d\x7c\x35\x6b\xbf\x3d\xed\x48\x27\x6f\x8e\x97\xc9\x83\xe7\x27\x4f\xc5\x86\x41\x05\x5e\x5f\xcd\xb6\xe5\x97\x5c\x3f\x3d\x79\x33\x38\x3b\xe9\x8a\x31\xf6\xa9\x14\xd8\xfa\x6e\x68\x71\x6c\xac\x0c\x29\x3b\x34\x9f\xf5\xe1\xdd\x26\x61\x5b\xb9\xf0\xeb\x6f\x47\xff\x0b\x00\x00\xff\xff\x65\x57\xc7\x70\x5d\x17\x00\x00") +var _operatorsCoreosCom_olmconfigsYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb4\x58\x6f\x6f\xdb\x46\xd2\x7f\xef\x4f\x31\xd0\xf3\x00\xb1\x73\x12\x15\x27\x87\x5c\x43\x20\x08\x02\xe5\x5c\x04\x89\xaf\x41\xec\xcb\x01\x67\xf9\xae\x43\x72\x44\x6d\x43\xee\xb2\xbb\xb3\xb6\xd5\xa2\xdf\xfd\x30\xbb\x24\x45\xc9\xa2\x63\xa0\xad\xde\x58\x9a\x9d\x9d\x9d\xbf\xbf\x99\x31\x36\xea\x0b\x59\xa7\x8c\x4e\x01\x1b\x45\x77\x4c\x5a\x7e\xb9\xe4\xeb\x77\x2e\x51\x66\x7e\x73\x7a\xf4\x55\xe9\x22\x85\x85\x77\x6c\xea\xcf\xe4\x8c\xb7\x39\xbd\xa3\x95\xd2\x8a\x95\xd1\x47\x35\x31\x16\xc8\x98\x1e\x01\xa0\xd6\x86\x51\xc8\x4e\x7e\x02\xe4\x46\xb3\x35\x55\x45\x76\x56\x92\x4e\xbe\xfa\x8c\x32\xaf\xaa\x82\x6c\x10\xde\x3d\x7d\xf3\x2c\x79\x95\x3c\x3b\x02\xc8\x2d\x85\xeb\x97\xaa\x26\xc7\x58\x37\x29\x68\x5f\x55\x47\x00\x1a\x6b\x4a\xc1\x54\x75\x6e\xf4\x4a\x95\x2e\x31\x0d\x59\x64\x63\x5d\x92\x1b\x4b\x46\xfe\xd4\x47\xae\xa1\x5c\x5e\x2e\xad\xf1\x4d\x0a\x07\x79\xa2\xac\x4e\x41\x64\x2a\x8d\x55\xdd\x6f\x80\x99\x3c\x12\xbe\x47\xc3\x7f\xf8\x78\xbe\x08\x4f\x06\x5a\xa5\x1c\x7f\xd8\xa5\x7f\x54\x8e\xc3\x59\x53\x79\x8b\xd5\x50\xc9\x40\x76\x4a\x97\xbe\x42\x3b\x38\x38\x02\x70\xb9\x69\x28\x85\x45\xe5\x1d\x93\x3d\x02\x68\x9d\xd1\xea\x31\x6b\x0d\xbe\x39\x6d\xd5\x72\xf9\x9a\x6a\xec\x94\x04\x31\x4d\xbf\xfd\xf4\xfe\xcb\x8b\x8b\xbd\x03\x80\x82\x5c\x6e\x55\xc3\xc1\xb5\xbd\x9a\xa0\x1c\x20\xd8\x36\x80\xf2\xa5\x31\xda\xa9\xac\x22\x58\x19\x0b\x51\x31\x6f\x95\x2e\xe5\x4e\x32\x90\xc7\x1b\xd1\xd4\x64\x3f\x51\xce\x03\xb2\xa5\x9f\xbd\xb2\x54\x0c\x9f\x16\xc5\xbb\x84\x18\x90\x1b\x2b\x91\xe0\x81\x97\xe3\x67\x90\x7e\x3b\xf4\x3d\x1b\x9e\x88\xa1\x91\x0f\x0a\xc9\x3c\x72\xc0\x6b\xea\x5c\x46\x45\xeb\x1d\x30\x2b\xe0\xb5\x72\x60\xa9\xb1\xe4\x48\xc7\x5c\x14\x32\xea\xd6\x80\x04\x2e\xc8\xca\x45\x70\x6b\xe3\xab\x42\x0c\xbf\x21\xcb\x60\x29\x37\xa5\x56\xbf\xf4\xd2\x1c\xb0\x09\xcf\x54\xc8\xe4\x18\x94\x66\xb2\x1a\x2b\xb8\xc1\xca\xd3\x14\x50\x17\x50\xe3\x06\x2c\x89\x5c\xf0\x7a\x20\x21\xb0\xb8\x04\xce\x8d\x25\x50\x7a\x65\x52\x58\x33\x37\x2e\x9d\xcf\x4b\xc5\x5d\x71\xe5\xa6\xae\xbd\x56\xbc\x99\x87\x3a\x51\x99\x97\x5c\x9d\x17\x74\x43\xd5\xdc\xa9\x72\x86\x36\x5f\x2b\xa6\x9c\xbd\xa5\x39\x36\x6a\x16\x94\xd5\xa1\xc0\x92\xba\xf8\xbf\x2e\x9a\xee\xc9\x9e\xfb\x62\xc8\x1c\x4b\x38\x77\x8e\x42\x4e\x3f\xe8\x6b\xc9\xee\x98\x2b\xf1\x7a\xb4\x65\xeb\x52\x21\x89\x57\x3e\xff\xfd\xe2\x72\x9b\x4e\xc1\xed\xd1\xc3\x5b\x56\xb7\x75\xb6\x38\x4a\xe9\x15\xd9\xc8\xb9\xb2\xa6\x0e\x52\x48\x17\x8d\x51\x9a\xc3\x8f\xbc\x52\xa4\x19\x9c\xcf\x6a\xc5\x2e\x24\x18\x39\x96\x38\x24\xb0\x08\xd8\x02\x19\x81\x6f\x0a\x64\x2a\x12\x78\xaf\x61\x81\x35\x55\x0b\x74\xf4\xa7\xbb\x5a\x3c\xea\x66\xe2\xbe\xc7\x3b\x7b\x08\x8d\xf7\x2f\xdc\x2b\x28\x80\x0e\xbe\x46\xa3\xd3\x57\xf3\x45\x43\xb9\x44\x49\xdc\x26\xb7\x42\x0d\xa3\x1e\x94\x7b\x17\x9a\xe4\xb1\x8f\x8f\x97\xa9\x7c\x56\x84\xe2\x9a\x03\x27\x7b\x2a\x9e\xb5\x8c\x01\xfb\x51\xe9\xa8\xa3\xe0\xa6\xd4\x61\x07\x33\x28\xb8\xf3\xc3\xc7\xf3\x5e\xee\xbe\x9a\xdf\x50\xf5\x5b\xea\x06\xb5\x94\x93\x67\x16\xa6\x51\x54\x2c\x2e\xbe\x8c\xb0\xed\xe9\xff\x6e\xff\x96\xb8\xd9\x3b\x2a\x04\x0e\x5a\x91\xa2\xf9\x13\x07\x93\xc8\x04\x8b\x8b\x2f\x93\xce\x90\x10\x88\xbe\xef\x80\xd2\x8e\xb1\xaa\xa8\x00\xec\x72\x3c\x00\x7e\xc4\xff\x29\xdc\xae\xc9\x12\xe0\x2e\xb9\xe8\x05\xc8\xdb\x46\x4b\x79\x21\xc3\x1a\x1d\x64\x44\x7a\x20\x54\xe9\x10\xf4\x96\xfb\x7b\xe9\x7a\x91\x97\xd1\x96\xc4\x0e\xb0\xaa\x62\xbb\x6b\x30\x17\x40\xfa\xd7\x9a\x34\x58\x22\x2d\x66\x14\xd3\x10\x82\x5b\x55\x55\x02\x7f\xd2\x7b\x29\x28\x39\x30\xcc\x4d\x82\x45\x84\xf9\x7a\x4c\xc9\x43\xa1\xdb\x86\x2f\x33\xa6\x22\xd4\xbb\x79\xce\xc8\xfe\x5e\x38\x46\x32\x3d\xf0\xf6\xb9\x1e\x7f\xfd\xd9\xd9\x9e\x1b\x5d\xa8\xc1\x1c\x73\x48\x28\x5a\x8b\x9b\x03\xa7\x8a\xa9\x1e\xcb\xc8\xa1\x85\x93\x45\xf7\xc8\xb6\x54\x0a\x62\x54\x55\xb4\x4f\xe2\x8e\x52\xdb\x1c\xfb\x1a\x41\xee\xad\x0d\x00\xc9\x12\xa8\xae\xd9\xbd\xfd\xf4\x1e\xba\xb9\x2c\x81\xd9\x6c\x06\x97\x42\x76\x6c\x7d\xce\xe2\x37\x69\x5c\xba\xa0\x22\x48\x2d\x94\x0d\xdd\xca\x89\x70\xf1\x61\x30\xa3\xcb\xce\x95\xa2\xaa\x80\x06\x79\x0d\x49\x74\x75\xb2\x75\x45\x02\x70\x26\xa9\x70\x87\x75\x53\xd1\x14\x96\x3a\x78\x02\xce\x8c\x69\x83\x14\xdf\xfc\x15\xe6\x73\xf8\xdc\x37\x81\x20\xd8\x64\x8e\xec\x4d\x1c\x0d\x43\x3f\x86\x95\x31\x4f\xdc\xae\x49\x89\x5c\xfc\xa0\xcd\xad\x3e\xf4\x7a\x78\x0b\x2d\xa5\xb0\x9c\xbc\xbd\x41\x55\x49\x0a\x2f\x27\x53\x58\x4e\x3e\x59\x53\x5a\x72\x32\x69\x09\x41\x3a\xf3\x72\xf2\x8e\x4a\x8b\x05\x15\xcb\x89\x88\xfd\x4b\x83\x9c\xaf\xcf\xc9\x96\xf4\x81\x36\xaf\x83\xb0\x9e\x7c\xc1\x56\xe6\xc0\xcd\xeb\x5a\xce\x03\x5d\x00\xeb\x72\xd3\xd0\xeb\x1a\x9b\x9e\x70\x8e\x4d\x7f\xb9\x8f\x9e\x83\xab\x6b\x41\xfa\x9b\xd3\x64\x1b\xd1\x1f\x7f\x72\x46\xa7\xcb\xc9\x56\xff\xa9\xa9\x25\x33\x1a\xde\x2c\x27\xb0\xf3\x6a\xba\x9c\x84\x77\x3b\x7a\xa7\x64\xba\x9c\xc8\x4b\x42\xb6\x86\x4d\xe6\x57\xe9\x72\x92\x6d\x98\xdc\xf4\x74\x6a\xa9\x99\x4a\x61\xbf\xde\xbe\xb0\x9c\xfc\x28\x31\x99\xcf\xc1\xf0\x9a\x6c\x0c\xa6\x83\xdf\x26\x07\x73\xf1\x1b\xe0\x3a\x36\xdf\x6d\x3f\x33\xa8\xd0\xf1\xa5\x45\xed\x54\x37\xb3\x8f\xb2\xd6\xe4\x1c\x96\xe3\xe7\x96\xd0\x19\x3d\x7a\x1c\xb3\x61\xf4\x58\x6c\x39\x78\xf8\xad\x16\x01\x07\x6c\x18\xe3\xdc\x2b\xdf\xfb\x17\x3b\x8c\x92\x13\x60\x21\x84\xa2\xed\x73\x82\x7b\x6e\xa9\x45\x99\x80\xa4\xc4\x5b\x44\x63\x03\xa8\x43\xdc\x92\xb6\x7e\xe3\x78\x9a\x91\xf4\x08\x1d\x44\x79\x5d\x90\xad\x36\x32\x81\x6d\xa5\xe6\x6b\xd4\xa5\x8c\x43\xf0\x7e\x15\xb1\x5f\x39\x90\x51\xe9\xab\x14\xd2\x54\x2e\x6a\xf0\xae\x1b\xdb\x82\x5e\xbd\x44\xc1\x8e\x58\xf3\xad\x98\x30\xf9\xe5\x39\x35\x2c\xd5\x35\x86\xec\x0f\xcc\x3c\xc3\xcf\xca\xd8\x1a\x39\x05\x99\xd7\x66\x3c\x9e\x1e\x6d\x72\x3c\xd2\xf1\x2d\x77\x9c\x51\xd7\xbe\x46\x69\x68\x58\x84\xbe\xdc\x9f\xe9\x42\xe5\x18\x66\xd5\x0e\x52\x31\x33\x3e\x82\xdc\x36\x0e\xad\xab\x65\x38\xcd\x48\xc0\x30\xd4\x67\x6b\xd6\xef\x34\xbe\xc6\xbb\x8f\xa4\x4b\x5e\xa7\xf0\xe2\xf9\xdf\x5e\x7e\x37\xc2\x18\x81\x91\x8a\xef\x49\x4b\x37\x3d\xb0\x0a\x8d\xb8\xe1\xfe\xc5\xc1\xe0\x1d\xec\x4c\xba\xf9\x33\x29\xb7\x3c\x71\x3a\xd8\xc9\xcb\x5b\x74\xe0\x88\x21\x43\x99\x72\x7c\x23\x7e\x11\xa0\x0f\x63\x86\xce\x69\x0a\x6a\x75\x58\x98\xea\x01\xbc\xda\xc0\xe9\xf3\x29\x64\xad\x8b\xef\xc3\xf7\xd5\xdd\x75\x72\x40\x65\xe5\xe0\xd5\x74\x4f\x1f\x99\x79\x7c\x68\x7a\x92\x38\x70\xab\x78\x1d\xd6\x55\xe9\x5b\xed\x4a\x76\xa0\x13\x52\xaf\xef\xb7\x02\x27\xfd\xb0\x0c\x3b\xf7\xe1\x4f\x97\xb6\x4a\xf3\xcb\xbf\x8e\xc7\x57\x69\x55\xfb\x3a\x85\x67\x23\x2c\x11\xd2\x1e\x19\xcd\xc8\xbc\x1d\x04\x50\xa0\xab\xb4\x58\xd7\xc8\x2a\x07\x55\xc8\x2a\xb2\x52\x64\x87\xa9\x2d\x46\xb7\x17\xa5\xb5\xef\x78\xf1\x89\x6b\x71\x68\x90\xec\x9f\xac\x29\x7c\x2e\xeb\x98\x59\x85\xad\x41\xad\x54\x3e\x04\x28\xd9\x71\x42\x35\xc4\x2d\x1b\xe8\x4e\x9c\xde\xef\xb3\x71\xe5\x25\xd4\x4a\x97\xae\x7d\x52\x96\x39\x01\x90\xd8\x75\x6f\xd7\x14\x5a\x4f\xd8\xce\xdb\x3b\x36\x68\xe5\x54\x41\x56\xc6\x60\x28\x3d\x5a\xd4\x4c\x54\x08\xfc\x48\x09\xb6\xbc\x03\xc8\xc3\xed\x66\xd7\x55\x63\x2c\xd5\x08\x56\xa2\x62\xbb\x0d\x86\x8a\xfd\xe3\x4a\xf5\xf4\xd9\xf3\x07\x43\xde\xf3\x8d\x32\x35\xc8\x4c\x56\xa7\xf0\x9f\xab\xb7\xb3\x7f\xe3\xec\x97\xeb\xe3\xf6\xcb\xb3\xd9\xab\xff\x4e\xd3\xeb\xa7\x83\x9f\xd7\x27\x6f\xfe\x7f\x44\xd2\xe1\x19\x79\x24\x7d\xda\x26\xd2\xcd\x89\x5d\x44\xa7\xa1\xc3\x98\x15\x5c\x5a\x4f\x53\x38\xc3\xca\xd1\x14\xfe\xa9\x43\x6b\xf8\x9d\x4e\x23\xed\xeb\x71\xed\xa4\x2b\x4f\xe4\xd5\xc3\xc3\x47\xcf\x12\x54\x7a\x98\xa7\x55\xf7\xa1\x25\xe3\x71\x4e\x0a\x63\x5b\xdc\x41\x3b\xa4\x19\xfc\x07\x01\x02\xe2\xc9\x58\x9a\xb4\x13\x6e\x92\x9b\x7a\x3e\xf8\x0f\x83\x8c\xd6\xe7\xa8\x37\xb0\x85\xb5\x38\x94\xee\x67\xba\x63\xc1\x26\xcc\xad\x71\xae\xdf\x4c\x1c\x54\xea\x2b\x41\x3f\xb9\x46\xb0\xcc\x28\xc7\x30\x8b\xdb\x4c\xb1\x45\xbb\x19\xac\x1e\x90\xa3\x0e\xff\xf0\x70\xb4\xf2\x15\x1c\x3b\x22\x48\xb4\x29\xe8\x3e\xba\x9e\x44\x0c\xc5\x4c\x55\x8a\x37\x61\x53\x25\x59\xb5\x2b\xd5\xae\x00\x75\x63\x2c\xa3\xe6\x58\x6e\x96\x4a\xba\x03\xc5\x50\xcb\xbc\x49\x61\xbb\x3a\x2e\xb4\x3b\x3d\x7d\xfe\xe2\xc2\x67\x85\xa9\x51\xe9\xb3\x9a\xe7\x27\x6f\x8e\x7f\xf6\x58\x09\xf2\x14\xff\xc0\x9a\xce\x6a\x3e\xf9\xe3\xda\xe2\xe9\xcb\x47\x54\xd1\xf1\x55\xac\x95\xeb\xe3\xab\x59\xfb\xed\x69\x47\x3a\x79\x73\xbc\x4c\x1e\x3c\x3f\x79\x2a\x36\x0c\x2a\xf0\xfa\x6a\xb6\x2d\xbf\xe4\xfa\xe9\xc9\x9b\xc1\xd9\x49\x57\x8c\xb1\x4f\xa5\xc0\xd6\x77\x43\x8b\x63\x63\x65\x48\xd9\xa1\xf9\xac\x0f\xef\x36\x09\xdb\xca\x85\x5f\x7f\x3b\xfa\x5f\x00\x00\x00\xff\xff\x1e\x16\x84\x1b\x60\x17\x00\x00") func operatorsCoreosCom_olmconfigsYamlBytes() ([]byte, error) { return bindataRead( @@ -165,7 +165,7 @@ func operatorsCoreosCom_olmconfigsYaml() (*asset, error) { return a, nil } -var _operatorsCoreosCom_operatorconditionsYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5b\xdd\x6f\x1b\xb9\x11\x7f\xf7\x5f\x31\x50\x0b\xc4\x4e\xa5\x55\x9c\x2b\xae\x39\x01\x41\x10\xe4\x9a\x22\x48\x7c\x09\x62\xf7\x1e\x6a\xb9\xcd\xec\x72\x24\xf1\xb2\x4b\xee\x91\x5c\xd9\xba\xc3\xfd\xef\xc5\x90\xfb\x25\x69\xa5\xf8\x90\x34\x68\x0b\xf2\xc5\x12\x3f\x86\xc3\xf9\xfe\xd1\x14\x96\xf2\x47\x32\x56\x6a\x35\x03\x2c\x25\xdd\x39\x52\xfc\xcd\x26\x1f\x9f\xd8\x44\xea\xe9\xfa\xfc\xe4\xa3\x54\x62\x06\x2f\x2a\xeb\x74\xf1\x9e\xac\xae\x4c\x46\xdf\xd3\x42\x2a\xe9\xa4\x56\x27\x05\x39\x14\xe8\x70\x76\x02\x80\x4a\x69\x87\xdc\x6d\xf9\x2b\x40\xa6\x95\x33\x3a\xcf\xc9\x4c\x96\xa4\x92\x8f\x55\x4a\x69\x25\x73\x41\xc6\x13\x6f\xb6\x5e\x3f\x4a\x9e\x24\x8f\x4e\x00\x32\x43\x7e\xf9\x95\x2c\xc8\x3a\x2c\xca\x19\xa8\x2a\xcf\x4f\x00\x14\x16\x34\x03\x5d\x92\x41\xa7\x4d\xa6\x95\xf0\xdb\xdb\xa4\xe9\xb2\x49\xa6\x0d\x69\xfe\x53\x9c\xd8\x92\x32\xe6\x60\x69\x74\x55\x76\xcb\xb6\xe6\x04\x9a\x0d\xa3\xe8\x68\xa9\x8d\x6c\xbe\x03\x4c\x40\xe7\x85\xff\x1c\x04\xf0\xb6\xa6\xf1\xa2\xd9\xda\x8f\xe5\xd2\xba\xd7\xc3\xe3\x6f\xa4\x75\x7e\x4e\x99\x57\x06\xf3\x21\xe6\xfd\xb0\x5d\x69\xe3\x7e\xe8\x58\xe1\xad\xb3\xad\x4d\xac\x54\xcb\x2a\x47\x33\x40\xe2\x04\xc0\x66\xba\xa4\x19\x78\x0a\x25\x66\x24\x4e\x00\x6a\xc9\xd6\x14\x27\xb5\xf4\xd6\xe7\xf5\x06\x36\x5b\x51\x81\xcd\x76\xc0\x64\xd5\xf3\x77\xaf\x7e\xfc\xe6\x72\x67\x00\x40\x90\xcd\x8c\x2c\x9d\xd7\xd3\xde\x19\x41\x5a\xc0\xda\x36\xa0\x31\x0e\xd0\x0b\x70\x9b\x92\xe0\xc3\xde\xfc\x0f\x70\xbb\x92\xd9\x8a\x97\x55\x96\x04\x38\xcd\x47\x5d\xd3\x06\xa4\x5a\x68\x53\x78\xe5\x73\xef\xdb\x37\x17\x80\xa9\xae\x1c\xb8\x15\x81\x75\xe8\x3c\x59\x54\xad\x08\x92\x1e\x93\xbc\xdb\x0c\x74\xfa\x13\x65\xae\xd7\x6d\xe8\xe7\x4a\x1a\x12\xfd\xf3\xb0\x34\x1a\x93\xed\x75\x97\x86\xe9\xba\x9e\xfe\x43\xeb\x39\xc8\x56\xff\x8e\x60\x1e\xb0\xf4\xc2\x3c\x10\xec\x1b\x64\x3d\xe3\xb5\x1e\x48\xd4\x22\xf7\xa2\x59\x49\x0b\x86\x4a\x43\x96\x54\xf0\x96\xe6\x68\xfe\x00\x09\x5c\x92\xe1\x85\x6c\x19\x55\x2e\x82\x84\x8c\x03\x43\x99\x5e\x2a\xf9\x4b\x4b\xcd\xb2\xa4\x78\x9b\x1c\x1d\x59\x07\x52\x39\x32\x0a\x73\x58\x63\x5e\xd1\x18\x50\x09\x28\x70\x03\x86\x98\x2e\x54\xaa\x47\xc1\x4f\xb1\x09\x5c\x68\x43\x5e\xf8\x33\x58\x39\x57\xda\xd9\x74\xba\x94\xae\x71\xff\x4c\x17\x45\xa5\xa4\xdb\x4c\xbd\x27\xcb\xb4\x62\x2f\x9a\x0a\x5a\x53\x3e\xb5\x72\x39\x41\x93\xad\xa4\xa3\xcc\x55\x86\xa6\x58\xca\x89\x67\x56\x05\xd7\x2c\xc4\x1f\x4c\x6d\x13\xf6\xc1\x8e\xf8\x82\xca\xac\x33\x52\x2d\xb7\x86\xbc\xb7\x1d\x95\x35\xfb\x5b\x30\xbc\xb0\x3c\x9c\xa5\x13\x29\x77\xb1\x54\xde\xff\xf5\xf2\x0a\x1a\x06\x82\xd8\x83\x84\xbb\xa9\xb6\x13\x36\x0b\x4a\xaa\x05\x99\x30\x73\x61\x74\xe1\xa9\x90\x12\xa5\x96\x2a\x18\x62\x96\x4b\x52\x0e\x6c\x95\x16\xd2\x59\x6f\x60\x64\x1d\xeb\x21\x81\x17\x3e\xfa\x41\x4a\x50\x95\x02\x1d\x89\x04\x5e\x29\x78\x81\x05\xe5\x2f\xd0\xd2\x7f\x5c\xd4\x2c\x51\x3b\x61\xf1\xdd\x5f\xd8\xfd\xe0\xbd\xbf\x60\xcf\xa1\x00\x9a\xc0\x7a\x50\x3b\x7b\x2e\x7f\x59\x52\x06\x98\xe7\xfa\x96\x35\x96\xe5\x95\x75\x64\x00\x45\x21\xd5\x01\xf7\x3f\xee\xf7\x75\x74\x18\x43\xa9\x1d\x9f\x1e\xf3\x7c\x03\x7a\x4d\xc6\x48\xc1\x9a\x0f\x6b\x0c\x95\xda\x38\x12\x90\x6e\x3c\xa5\xa1\xa8\x71\xf4\xa0\x87\x43\x42\x38\x72\x99\xeb\x4d\xc1\x16\xb4\x3f\xd8\x50\x45\x63\x70\x33\x30\x2a\x1d\x15\x83\xcb\x8e\x28\x8a\x5b\x7d\xc8\x21\x7e\x3e\x63\xcb\x2d\xed\x8d\xba\xc8\xce\x56\x88\x52\x59\x10\xe4\x50\xe6\x16\x16\xda\x80\x56\x04\xc8\x36\xe0\x42\x24\x23\xc8\x2a\x63\xbc\x4b\x34\xaa\xf2\xde\xf3\xfc\xdd\xab\x36\x1d\x24\x30\x99\x4c\xe0\x8a\xbb\xad\x33\x55\xe6\xd8\x77\x39\x54\x29\x41\xc2\x53\x15\xd2\xf8\xf8\x64\x99\x38\xeb\xda\x1f\x03\x30\x18\xc1\x42\x52\x2e\xa0\x44\xb7\x82\x84\x77\xa9\x38\x7d\xb7\xe9\x1f\xe0\xa5\x36\x40\x77\x58\x94\x39\x8d\x43\xde\x79\xa9\xf5\xa5\x9f\x58\x6f\xf8\x2b\x4c\xa7\xf0\xbe\xf5\xf9\x60\x10\xa9\x25\xb3\x0e\xb5\x8a\xb7\x30\x58\x68\xfd\xc0\x6e\x9f\x27\xe1\x85\xaf\x95\xbe\x55\x43\x5b\xfb\xbd\xd0\xd0\x0c\xe6\xa3\xe7\x6b\x94\x39\xa6\x39\xcd\x47\x63\x98\x8f\xde\x19\xbd\x34\x64\x39\x71\x73\x07\x07\xe2\xf9\xe8\x7b\x5a\x1a\x14\x24\xe6\x23\x26\xfb\xa7\x12\x5d\xb6\xba\x20\xb3\xa4\xd7\xb4\x79\xea\x89\xb5\xdd\x97\xce\x70\x41\xb2\x79\x5a\xf0\xb8\xef\xe7\x4a\xe3\x6a\x53\xd2\xd3\x02\xcb\xb6\xe3\x02\xcb\x76\x71\xab\x3a\x0b\xd7\x37\xec\xd8\xeb\xf3\xa4\x53\xe7\x87\x9f\xac\x56\xb3\xf9\xa8\xe3\x7f\xac\x0b\x36\x8b\xd2\x6d\xe6\x23\xd8\xda\x75\x36\x1f\xf9\x7d\x9b\xfe\x86\xc9\xd9\x7c\xc4\x3b\x71\xb7\xd1\x4e\xa7\xd5\x62\x36\x1f\xa5\x1b\x47\x76\x7c\x3e\x36\x54\x8e\xb9\xcc\x78\xda\xed\x30\x1f\x7d\x80\xb9\x62\x66\xb5\x5b\x91\x09\x9a\xb4\xf0\xdb\xe8\x88\xed\x0f\xba\x62\x68\xc3\xe9\xbc\x6b\x9c\xd8\xad\xc5\x25\x1d\x1c\x37\x84\xb6\xae\xa9\x86\x86\x83\x8a\x0f\x0e\x33\x83\x83\x83\xc7\x22\x45\x68\x39\x5a\x77\x65\x50\x59\xd9\x54\xb7\x87\x66\xee\x38\xe4\xfe\x42\xf6\x9e\x90\xf3\xad\x03\xc7\x1d\xde\x0d\x5b\x45\xbb\x76\x36\x7b\x17\x67\x31\x76\xda\x70\x34\x8e\x9d\xa8\xbc\x32\x92\xda\x23\x43\x89\x91\x12\xdc\xae\x48\x79\x52\x95\x12\x64\xf2\x0d\xc7\xd2\x8e\x6a\xb6\x42\xb5\xe4\x94\x06\xaf\xd8\xc5\xd1\x3b\x31\xa7\xbb\x8f\xec\x1d\x63\x5e\xa8\xa0\xb2\x4d\xea\xf5\x7c\xb5\x14\x39\x1a\x04\x2f\xae\xc9\xf8\xec\x9d\x65\x54\x3a\x76\x99\xdd\x98\xdc\xb5\xa3\xe1\xb0\x69\x21\x71\xcc\x80\x73\xee\x84\x37\x3e\x30\xb3\x36\x8e\x7b\x0a\xbe\x9e\x1d\xea\x8c\x55\x55\xa0\x62\xeb\x11\xcc\x6f\x37\xa6\x84\xcc\xd0\xd7\x1b\x4d\x90\xec\x72\x57\xa7\x87\x5a\xd4\x5c\x60\xa4\xc4\xe1\xcd\x3b\x5d\x7d\xac\xcf\x3c\x7c\x81\x77\x6f\x48\x2d\xdd\x6a\x06\xdf\x3c\xfe\xcb\xb7\x4f\x0e\x4c\x0c\xd1\x8e\xc4\xdf\x48\x71\x1e\x1c\x28\x67\x0f\x88\x61\x7f\x61\xaf\x78\xf2\xe7\x4c\x9a\x1a\x22\x59\x76\x73\xbc\x85\x6c\xdb\xe5\x2d\x5a\xb0\xe4\x20\x45\x2e\xfc\xab\x92\xe5\xc2\xa1\x5b\x2a\xeb\x50\x65\x34\x06\xb9\x18\x26\x26\xdb\xa8\x9c\x6f\xe0\xfc\xf1\x18\xd2\x5a\xc4\xfb\x31\xf9\xfa\xee\x26\x19\x60\x59\x5a\xf8\x6e\xbc\xc3\x0f\x57\x83\x95\x4f\x63\x6c\x38\x70\x2b\xdd\x8a\x8b\x45\x9f\xdb\xea\xb2\x7a\x20\xb7\x51\xcb\xef\xa7\x14\xc7\x19\x6e\x49\xe6\x93\x66\x2b\x95\xfb\xf6\xcf\x87\xf5\x2b\x95\x2c\xaa\x62\x06\x8f\x0e\x4c\x09\x21\xed\x9e\xda\x0c\x93\xbb\xd4\x8e\x1c\xba\x96\x06\x0b\xae\xbc\x32\x90\x82\x0b\xaa\x85\x24\xd3\x37\x6d\x3e\x74\xbd\x90\x93\xf5\x96\x14\x1f\xd8\x3a\x0e\xf5\x8c\xfd\x9d\xd1\xa2\xca\xb8\xa4\xd6\x0b\x5f\x2f\xca\x85\xcc\xfa\x01\x8a\xeb\x54\xef\x0d\x01\x29\x01\xdd\xb1\xd0\x5b\x4c\x12\x60\x0b\xa1\x92\x6a\x69\xeb\x2d\xb9\x20\xe7\x00\x12\x52\xe9\xed\x8a\x7c\x3e\xf1\x08\xab\x5e\x63\x3c\x57\x56\x0a\x32\x24\x00\x61\x59\xa1\x41\xe5\x88\x04\x87\x1f\x76\xc1\x7a\x6e\x2f\xe4\x61\x57\x9d\x37\xde\x18\x5c\x35\x04\x2b\x66\xb1\xae\xe8\xbd\xc7\x7e\x39\x57\x3d\x7f\xf4\xf8\xa8\xca\xdb\x79\x07\x27\x95\xe8\x18\xeb\xcd\xe0\x9f\xd7\xcf\x27\xff\xc0\xc9\x2f\x37\xa7\xf5\x87\x47\x93\xef\xfe\x35\x9e\xdd\x3c\xec\x7d\xbd\x39\x7b\xf6\xc7\x03\x94\x82\x07\xdd\xd3\x7c\xea\x24\xd2\x54\x7e\x8d\x46\xc7\x3e\xc3\xe8\x05\x5c\x19\x46\x9d\x2f\x31\xb7\x34\x86\xbf\x2b\x9f\x1a\x3e\x53\x68\xa4\xaa\xe2\x30\x77\x9c\x95\x47\xbc\xeb\x70\x45\xd1\x4e\xf1\x2c\x1d\x9f\x53\xb3\x7b\x60\x8e\xe7\xf5\x7e\x42\xf2\xb5\x98\x5e\xf4\x23\x4d\x0f\x05\x82\x8f\x78\x5c\x6b\x26\x75\xcd\x9a\x64\xba\x98\xf6\x50\x22\x17\xcb\x17\xa8\x36\xd0\x85\xb5\x50\x69\xee\x5a\xba\x65\xf8\x03\x98\x19\x6d\x6d\x0b\x73\x2d\xe4\xf2\x23\x41\x5b\x8e\x86\x60\x99\x52\x86\xbe\xba\x36\xa9\x74\x06\xcd\xa6\xe3\xce\x42\x86\xca\x83\x56\x4b\x8b\x2a\x87\x53\x4b\x04\x89\xd2\x82\xf6\xa3\xeb\x59\x88\xa1\x98\xca\x5c\xba\x0d\x47\x49\x41\x99\x56\x8b\x5c\xd6\x45\x7d\xc1\xa0\x0b\x95\x0b\xee\x66\x68\x49\x77\x20\x1d\x14\x5c\x44\x92\xe5\x29\xa7\x42\xd9\xf3\xf3\xc7\xdf\x5c\x56\xa9\xd0\x05\x4a\xf5\xb2\x70\xd3\xb3\x67\xa7\x3f\x57\x98\x73\xe4\x11\x3f\x60\x41\x2f\x0b\x77\xf6\xe5\xd2\xe2\xf9\xb7\xf7\xf0\xa2\xd3\xeb\xe0\x2b\x37\xa7\xd7\x93\xfa\xd3\xc3\xa6\xeb\xec\xd9\xe9\x3c\x39\x3a\x7e\xf6\x90\xcf\xd0\xf3\xc0\x9b\xeb\x49\xe7\x7e\xc9\xcd\xc3\xb3\x67\xbd\xb1\xb3\x7d\x67\xe4\x8c\x25\x33\x7a\x9e\x65\xba\xfa\x6a\x98\x72\xd8\xf7\x3f\x81\xe6\x43\x08\x68\xf0\xfc\x36\x2c\x1f\xc0\xf2\xd2\xd9\x3a\x7d\x06\xd8\x1e\x2c\xa3\x0e\x24\x1c\x60\x9d\x41\x99\x07\xb3\xca\x5c\x85\x79\x0f\xf3\x83\xdd\x58\x47\xc5\x17\x82\xec\x9d\x19\x47\xf8\x1c\xe1\x73\x84\xcf\x7b\x6d\x32\x00\x36\x23\xd2\x8e\x48\xbb\x6b\x11\x69\x47\xa4\x1d\x91\xf6\xbd\xb4\x19\x91\x76\x44\xda\xdb\x2d\x22\xed\x7a\x4e\x44\xda\x11\x69\x7f\x6d\xa4\x1d\xf2\xd4\x0c\x9c\xa9\x9a\xa2\xc5\x3a\x6d\xb8\x48\x81\x05\x9b\x6c\xd3\x59\xa5\xad\x7e\x3b\x2b\xac\x5d\x17\x7e\xfd\x6d\xfb\x39\xcd\xe3\xf8\x9c\x26\x3e\xa7\x89\xcf\x69\xe2\x73\x9a\xa6\x7d\xed\xe7\x34\xdb\xd7\x6f\xe1\xcd\xcb\xd6\x75\x9b\xb7\xd9\xd2\xe8\xb5\x14\x64\x77\x1e\xdf\xf8\x3a\x7c\x27\xcb\x14\xa8\xaa\xfe\x83\x1a\xfa\x3a\xcf\x69\xe2\xdd\x5c\xbc\x9b\x8b\x77\x73\xf1\x6e\xae\xd7\xe2\xdd\x5c\xdb\xe2\xdd\x5c\xbc\x9b\x8b\x77\x73\xf1\x6e\x2e\xde\xcd\xed\xb6\x78\x37\x17\x5a\xbc\x9b\x8b\x77\x73\x03\xed\x7f\xe3\x6e\xae\x6f\x41\xf1\x57\x15\x11\x7a\x46\xe8\xf9\x5f\x06\x3d\x23\x9e\x8c\x78\x32\xe2\xc9\x81\x16\xf1\x64\xc4\x93\x11\x4f\x46\x3c\xb9\xd7\x22\x9e\xac\xe7\x44\x3c\x19\xf1\x64\xfc\x55\xc5\xef\xfc\x55\xc5\xdb\x37\x17\xbd\x97\x1c\xe1\x85\x47\xcf\xb2\x56\xb8\x26\x48\x89\x54\x5b\x46\xc4\xff\xc2\x46\x28\x1c\xa1\x70\xfc\x2f\x2c\x44\xd4\x1c\x51\x73\x44\xcd\x11\x35\xef\x2a\x2e\xa2\xe6\x88\x9a\xb7\x55\x19\x51\xf3\xef\x17\x5a\x44\xcd\x11\x35\x0f\xa8\xe2\xff\x03\x35\x1f\xfb\x85\x44\xbf\xef\x53\x3f\x90\xf8\x77\x00\x00\x00\xff\xff\x79\xf0\xdc\xa4\x52\x56\x00\x00") +var _operatorsCoreosCom_operatorconditionsYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5b\x5f\x6f\x1b\xb9\x11\x7f\xf7\xa7\x18\xa8\x05\x62\xa7\xd2\x2a\x4e\x8a\xf4\x22\x20\x08\x82\x5c\x53\x04\x89\x2f\x41\xec\xde\x43\x2d\xb7\x99\x5d\x8e\x24\x9e\x77\xc9\x3d\x92\x2b\x5b\x77\xb8\xef\x5e\x0c\xb9\xff\x64\xad\x14\x1f\x92\x06\x6d\x41\xbe\x58\x22\x87\x43\x72\xfe\xff\x68\x0a\x4b\xf9\x23\x19\x2b\xb5\x9a\x01\x96\x92\x6e\x1d\x29\xfe\x66\x93\xeb\xef\x6c\x22\xf5\x74\x7d\x7a\x74\x2d\x95\x98\xc1\xab\xca\x3a\x5d\x7c\x24\xab\x2b\x93\xd1\xf7\xb4\x90\x4a\x3a\xa9\xd5\x51\x41\x0e\x05\x3a\x9c\x1d\x01\xa0\x52\xda\x21\x77\x5b\xfe\x0a\x90\x69\xe5\x8c\xce\x73\x32\x93\x25\xa9\xe4\xba\x4a\x29\xad\x64\x2e\xc8\x78\xe6\xcd\xd2\xeb\x47\xc9\xb3\xe4\xd1\x11\x40\x66\xc8\x4f\xbf\x90\x05\x59\x87\x45\x39\x03\x55\xe5\xf9\x11\x80\xc2\x82\x66\xa0\x4b\x32\xe8\xb4\xc9\xb4\x12\x7e\x79\x9b\x34\x5d\x36\xc9\xb4\x21\xcd\x7f\x8a\x23\x5b\x52\xc6\x3b\x58\x1a\x5d\x95\xdd\xb4\x2d\x9a\xc0\xb3\xd9\x28\x3a\x5a\x6a\x23\x9b\xef\x00\x13\xd0\x79\xe1\x3f\x07\x01\xbc\xaf\x79\xbc\x6a\x96\xf6\x63\xb9\xb4\xee\xed\xf0\xf8\x3b\x69\x9d\xa7\x29\xf3\xca\x60\x3e\xb4\x79\x3f\x6c\x57\xda\xb8\x1f\xba\xad\xf0\xd2\xd9\xd6\x22\x56\xaa\x65\x95\xa3\x19\x60\x71\x04\x60\x33\x5d\xd2\x0c\x3c\x87\x12\x33\x12\x47\x00\xb5\x64\x6b\x8e\x93\x5a\x7a\xeb\xd3\x7a\x01\x9b\xad\xa8\xc0\x66\x39\x60\xb6\xea\xe5\x87\x37\x3f\x3e\x39\xbf\x33\x00\x20\xc8\x66\x46\x96\xce\xeb\x69\xe7\x8c\x20\x2d\x60\x6d\x1b\xd0\x18\x07\xe8\x05\xb8\x4d\x49\xf0\x69\x87\xfe\x13\xdc\xac\x64\xb6\xe2\x69\x95\x25\x01\x4e\xf3\x51\xd7\xb4\x01\xa9\x16\xda\x14\x5e\xf9\xdc\xfb\xfe\xdd\x19\x60\xaa\x2b\x07\x6e\x45\x60\x1d\x3a\xcf\x16\x55\x2b\x82\xa4\xb7\x49\x5e\x6d\x06\x3a\xfd\x89\x32\xd7\xeb\x36\xf4\x73\x25\x0d\x89\xfe\x79\x58\x1a\x8d\xc9\xf6\xba\x4b\xc3\x7c\x5d\x4f\xff\xa1\xf5\x1c\x64\xab\xff\x8e\x60\x1e\xb0\xf4\x02\x1d\x08\xf6\x0d\xb2\x7e\xe3\xb5\x1e\x48\xd4\x22\xf7\xa2\x59\x49\x0b\x86\x4a\x43\x96\x54\xf0\x96\xe6\x68\xfe\x00\x09\x9c\x93\xe1\x89\x6c\x19\x55\x2e\x82\x84\x8c\x03\x43\x99\x5e\x2a\xf9\x4b\xcb\xcd\xb2\xa4\x78\x99\x1c\x1d\x59\x07\x52\x39\x32\x0a\x73\x58\x63\x5e\xd1\x18\x50\x09\x28\x70\x03\x86\x98\x2f\x54\xaa\xc7\xc1\x93\xd8\x04\xce\xb4\x21\x2f\xfc\x19\xac\x9c\x2b\xed\x6c\x3a\x5d\x4a\xd7\xb8\x7f\xa6\x8b\xa2\x52\xd2\x6d\xa6\xde\x93\x65\x5a\xb1\x17\x4d\x05\xad\x29\x9f\x5a\xb9\x9c\xa0\xc9\x56\xd2\x51\xe6\x2a\x43\x53\x2c\xe5\xc4\x6f\x56\x05\xd7\x2c\xc4\x1f\x4c\x6d\x13\xf6\xc1\x1d\xf1\x05\x95\x59\x67\xa4\x5a\x6e\x0d\x79\x6f\x3b\x28\x6b\xf6\xb7\x60\x78\x61\x7a\x38\x4b\x27\x52\xee\x62\xa9\x7c\xfc\xeb\xf9\x05\x34\x1b\x08\x62\x0f\x12\xee\x48\x6d\x27\x6c\x16\x94\x54\x0b\x32\x81\x72\x61\x74\xe1\xb9\x90\x12\xa5\x96\x2a\x18\x62\x96\x4b\x52\x0e\x6c\x95\x16\xd2\x59\x6f\x60\x64\x1d\xeb\x21\x81\x57\x3e\xfa\x41\x4a\x50\x95\x02\x1d\x89\x04\xde\x28\x78\x85\x05\xe5\xaf\xd0\xd2\x7f\x5c\xd4\x2c\x51\x3b\x61\xf1\xdd\x5f\xd8\xfd\xe0\xbd\x3b\x61\xc7\xa1\x00\x9a\xc0\xba\x57\x3b\x3b\x2e\x7f\x5e\x52\x06\x98\xe7\xfa\x86\x35\x96\xe5\x95\x75\x64\x00\x45\x21\xd5\x1e\xf7\x3f\xec\xf7\x75\x74\x18\x43\xa9\x1d\x9f\x1e\xf3\x7c\x03\x7a\x4d\xc6\x48\xc1\x9a\x0f\x73\x0c\x95\xda\x38\x12\x90\x6e\x3c\xa7\xa1\xa8\x71\xf0\xa0\xfb\x43\x42\x38\x72\x99\xeb\x4d\xc1\x16\xb4\x3b\xd8\x70\x45\x63\x70\x33\x30\x2a\x1d\x15\x83\xd3\x0e\x28\x8a\x5b\x7d\xc8\xa1\xfd\x7c\xc1\x92\x5b\xda\x1b\x75\x91\x9d\xad\x10\xa5\xb2\x20\xc8\xa1\xcc\x2d\x2c\xb4\x01\xad\x08\x90\x6d\xc0\x85\x48\x46\x90\x55\xc6\x78\x97\x68\x54\xe5\xbd\xe7\xe5\x87\x37\x6d\x3a\x48\x60\x32\x99\xc0\x05\x77\x5b\x67\xaa\xcc\xb1\xef\x72\xa8\x52\x82\x84\xe7\x2a\xa4\xf1\xf1\xc9\x32\x73\xd6\xb5\x3f\x06\x60\x30\x82\x85\xa4\x5c\x40\x89\x6e\x05\x09\xaf\x52\x71\xfa\x6e\xd3\x3f\xc0\x6b\x6d\x80\x6e\xb1\x28\x73\x1a\xc3\x5c\x85\xd4\xf3\x5a\xeb\x73\x4f\x5b\xaf\xf9\x2b\x4c\xa7\xf0\xb1\x75\xfb\x60\x13\xa9\x25\xb3\x0e\xe5\x8a\x37\x32\x58\x68\xfd\xc0\x6e\x1f\x29\xe1\x89\x6f\x95\xbe\x51\x43\xab\xfb\xb5\xd0\xd0\x0c\xe6\xa3\x97\x6b\x94\x39\xa6\x39\xcd\x47\x63\x98\x8f\x3e\x18\xbd\x34\x64\x39\x77\x73\x07\xc7\xe2\xf9\xe8\x7b\x5a\x1a\x14\x24\xe6\x23\x66\xfb\xa7\x12\x5d\xb6\x3a\x23\xb3\xa4\xb7\xb4\x79\xee\x99\xb5\xdd\xe7\xce\x70\x4d\xb2\x79\x5e\xf0\xb8\xef\xe7\x62\xe3\x62\x53\xd2\xf3\x02\xcb\xb6\xe3\x0c\xcb\x76\x72\xab\x3d\x0b\x97\x57\xec\xdb\xeb\xd3\xa4\xd3\xe8\xa7\x9f\xac\x56\xb3\xf9\xa8\xdb\xff\x58\x17\x6c\x19\xa5\xdb\xcc\x47\xb0\xb5\xea\x6c\x3e\xf2\xeb\x36\xfd\xcd\x26\x67\xf3\x11\xaf\xc4\xdd\x46\x3b\x9d\x56\x8b\xd9\x7c\x94\x6e\x1c\xd9\xf1\xe9\xd8\x50\x39\xe6\x4a\xe3\x79\xb7\xc2\x7c\xf4\x89\x75\x32\x9d\x82\x76\x2b\x32\x41\x99\x16\x7e\x1b\x1d\x30\xff\x41\x6f\x0c\x6d\x38\xa3\x77\x8d\x73\xbb\xb5\xb8\xa4\xbd\xe3\x86\xd0\xd6\x65\xd5\xd0\x70\x50\xf1\xde\x61\xde\xe0\xe0\xe0\xa1\x60\x11\x5a\x8e\xd6\x5d\x18\x54\x56\x36\x05\xee\x3e\xca\x3b\x3e\xb9\x3b\x91\x1d\x28\xa4\x7d\xeb\xc0\x71\x87\xf7\xc4\x56\xd1\xae\xa5\x66\x07\xe3\x44\xc6\x7e\x1b\x8e\xc6\xe1\x13\x95\x57\x46\x52\x3b\x65\xa8\x32\x52\x82\x9b\x15\x29\xcf\xaa\x52\x82\x4c\xbe\xe1\x70\xda\x71\xcd\x56\xa8\x96\x9c\xd5\xe0\x0d\x7b\x39\x7a\x3f\xe6\x8c\x77\xcd\xde\x31\xe6\x89\x0a\x2a\xdb\x64\x5f\xbf\xaf\x96\x23\x07\x84\xe0\xc8\x35\x1b\x9f\xc0\xb3\x8c\x4a\xc7\x2e\x73\x37\x2c\x77\xed\x60\x44\x6c\x5a\xc8\x1d\x33\xe0\xb4\x3b\xe1\x85\xf7\x50\xd6\xc6\x71\x4f\xc1\xd7\xd4\xa1\xd4\x58\x55\x05\x2a\xb6\x1e\xc1\xfb\xed\xc6\x94\x90\x19\xfa\x92\xa3\x89\x93\x5d\xfa\xea\xf4\x50\x8b\x9a\x6b\x8c\x94\x38\xc2\x79\xa7\xab\x8f\xf5\x85\x87\x2f\xf0\xf6\x1d\xa9\xa5\x5b\xcd\xe0\xc9\xe3\xbf\x3c\xfd\x6e\x0f\x61\x88\x76\x24\xfe\x46\x8a\x53\xe1\x40\x45\xbb\x47\x0c\xbb\x13\x7b\xf5\x93\x3f\x67\xd2\x94\x11\xc9\xb2\xa3\xf1\x16\xb2\x6d\x97\x37\x68\xc1\x92\x83\x14\xb9\xf6\xaf\x4a\x96\x0b\x47\x6f\xa9\xac\x43\x95\xd1\x18\xe4\x62\x98\x99\x6c\xa3\x72\xbe\x81\xd3\xc7\x63\x48\x6b\x11\xef\xc6\xe4\xcb\xdb\xab\x64\x60\xcb\xd2\xc2\xb3\xf1\x9d\xfd\x70\x41\x58\xf9\x4c\xc6\x86\x03\x37\xd2\xad\xb8\x5e\xf4\xe9\xad\xae\xac\x07\xd2\x1b\xb5\xfb\xfd\x9c\xe2\x38\xc9\x2d\xc9\x7c\xd6\x6c\xa5\x72\x4f\xff\xbc\x5f\xbf\x52\xc9\xa2\x2a\x66\xf0\x68\x0f\x49\x08\x69\xf7\xd4\x66\x20\xee\xb2\x3b\x72\xe8\x5a\x1a\x2c\xb8\xf8\xca\x40\x0a\xae\xa9\x16\x92\x4c\xdf\xb4\xf9\xd0\xf5\x44\xce\xd7\x5b\x52\x7c\x60\xeb\x38\xd4\x33\xf6\x0f\x46\x8b\x2a\xe3\xaa\x5a\x2f\x7c\xc9\x28\x17\x32\xeb\x07\x28\x2e\x55\xbd\x37\x04\xb0\x04\x74\xcb\x42\x6f\x61\x49\x40\x2e\x84\x4a\xaa\xa5\xad\x97\xe4\x9a\x9c\x03\x48\x48\xa5\x37\x2b\xf2\xf9\xc4\x83\xac\x7a\x8e\xf1\xbb\xb2\x52\x90\x21\x01\x08\xcb\x0a\x0d\x2a\x47\x24\x38\xfc\xb0\x0b\xd6\xb4\xbd\x90\x87\x5d\x81\xde\x78\x63\x70\xd5\x10\xac\x78\x8b\x75\x51\xef\x3d\xf6\xeb\xb9\xea\xe9\xa3\xc7\x07\x55\xde\xd2\xed\x25\x2a\xd1\x31\xdc\x9b\xc1\x3f\x2f\x5f\x4e\xfe\x81\x93\x5f\xae\x8e\xeb\x0f\x8f\x26\xcf\xfe\x35\x9e\x5d\x3d\xec\x7d\xbd\x3a\x79\xf1\xc7\x3d\x9c\x82\x07\xdd\xd3\x7c\xea\x24\xd2\x14\x7f\x8d\x46\xc7\x3e\xc3\xe8\x05\x5c\x18\x06\x9e\xaf\x31\xb7\x34\x86\xbf\x2b\x9f\x1a\xbe\x50\x68\xa4\xaa\x62\xff\xee\x38\x2b\x8f\x78\xd5\xe1\x8a\xa2\x25\xf1\x5b\x3a\x4c\x53\x6f\x77\x0f\x8d\xdf\xeb\xfd\x84\xe4\x6b\x31\xbd\xe8\x47\x9a\x1e\x10\x04\x1f\xf1\xb8\xd6\x4c\xea\xb2\x35\xc9\x74\x31\xed\x01\x45\xae\x97\xcf\x50\x6d\xa0\x0b\x6b\xa1\xd2\xbc\x6b\xe9\x96\x11\x10\x60\x66\xb4\xb5\x2d\xd2\xb5\x90\xcb\x6b\x82\xb6\x1c\x0d\xc1\x32\xa5\x0c\x7d\x81\x6d\x52\xe9\x0c\x9a\x4d\xb7\x3b\x0b\x19\x2a\x8f\x5b\x2d\x2d\xaa\x1c\x8e\x2d\x11\x24\x4a\x0b\xda\x8d\xae\x27\x21\x86\x62\x2a\x73\xe9\x36\x1c\x25\x05\x65\x5a\x2d\x72\x59\xd7\xf5\x05\xe3\x2e\x54\x2e\xb8\x9b\xa1\x25\xdd\x82\x74\x50\x70\x11\x49\x96\x49\x8e\x85\xb2\xa7\xa7\x8f\x9f\x9c\x57\xa9\xd0\x05\x4a\xf5\xba\x70\xd3\x93\x17\xc7\x3f\x57\x98\x73\xe4\x11\x3f\x60\x41\xaf\x0b\x77\xf2\xf5\xd2\xe2\xe9\xd3\x7b\x78\xd1\xf1\x65\xf0\x95\xab\xe3\xcb\x49\xfd\xe9\x61\xd3\x75\xf2\xe2\x78\x9e\x1c\x1c\x3f\x79\xc8\x67\xe8\x79\xe0\xd5\xe5\xa4\x73\xbf\xe4\xea\xe1\xc9\x8b\xde\xd8\xc9\xae\x33\x72\xc6\x92\x19\xbd\xcc\x32\x5d\x7d\x33\x58\x39\xec\xfb\x9f\x01\xf4\x21\x04\x34\x90\x7e\x1b\x99\x0f\xc0\x79\xe9\x6c\x9d\x3e\x03\x72\x0f\x96\x51\x07\x12\x0e\xb0\xce\xa0\xcc\x83\x59\x65\xae\xc2\xbc\x07\xfb\xc1\x6e\xac\xa3\xe2\x2b\xa1\xf6\xce\x8c\x23\x82\x8e\x08\x3a\x22\xe8\xa1\x36\x19\xc0\x9b\x11\x6c\x47\xb0\xdd\xb5\x08\xb6\x23\xd8\x8e\x60\xfb\x5e\xda\x8c\x60\x3b\x82\xed\xed\x16\xc1\x76\x4d\x13\xc1\x76\x04\xdb\xdf\x1a\x6c\x87\x3c\x35\x03\x67\xaa\xa6\x68\xb1\x4e\x1b\x2e\x52\x60\xc1\x26\xdb\x74\x56\x69\xab\xdf\xce\x0a\x6b\xd7\x85\x5f\x7f\xdb\x7e\x54\xf3\x38\x3e\xaa\x89\x8f\x6a\xe2\xa3\x9a\xf8\xa8\xa6\x69\xdf\xfa\x51\xcd\xf6\x0d\x5c\x78\xf9\xb2\x75\xe3\xe6\x6d\xb6\x34\x7a\x2d\x05\xd9\x3b\x4f\x70\x7c\x1d\x7e\x27\xcb\x14\xa8\xaa\xfe\xb3\x1a\xfa\x36\x8f\x6a\xe2\xf5\x5c\xbc\x9e\x8b\xd7\x73\xf1\x7a\x6e\xbb\xc5\xeb\xb9\xb6\xc5\xeb\xb9\x78\x3d\x17\xaf\xe7\xe2\xf5\x5c\xbc\x9e\xbb\xdb\xe2\xf5\x5c\x68\xf1\x7a\x2e\x5e\xcf\x0d\xb4\xff\x8d\xeb\xb9\xbe\x05\xc5\x9f\x57\x44\xf4\x19\xd1\xe7\x7f\x1f\xfa\x8c\x90\x32\x42\xca\x08\x29\x07\x5a\x84\x94\x11\x52\x46\x48\x19\x21\xe5\x4e\x8b\x90\xb2\xa6\x89\x90\x32\x42\xca\xf8\xf3\x8a\xdf\xf9\xf3\x8a\xf7\xef\xce\x7a\xef\x39\xc2\x3b\x8f\x9e\x65\xad\x70\x4d\x90\x12\xa9\xb6\x8c\x88\xff\x8b\x8d\x68\x38\xa2\xe1\xf8\xbf\xd8\xba\x45\xe0\x1c\x81\x73\x04\xce\x11\x38\x6f\x29\x2e\x02\xe7\x08\x9c\xb7\x55\x19\x81\xf3\xef\x17\x5a\x04\xce\x11\x38\x0f\xa8\xe2\xff\x03\x38\x1f\xfa\xa9\x44\xbf\xef\x73\xbf\x94\xf8\x77\x00\x00\x00\xff\xff\x0a\x10\x91\x5e\x61\x56\x00\x00") func operatorsCoreosCom_operatorconditionsYamlBytes() ([]byte, error) { return bindataRead( @@ -185,7 +185,7 @@ func operatorsCoreosCom_operatorconditionsYaml() (*asset, error) { return a, nil } -var _operatorsCoreosCom_operatorgroupsYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5a\x79\x6f\x23\x37\x96\xff\xbf\x3f\xc5\x83\x66\x81\xb6\xb3\x3a\xda\x9d\x45\x36\x23\x20\x08\x8c\xee\x74\xe0\x4d\xb7\xdb\x68\xbb\xb3\xc0\x5a\xde\x1d\xaa\xea\x55\x89\x63\x16\x59\x43\xb2\x24\x6b\x82\x7c\xf7\xc5\x7b\x64\x1d\xba\xe5\x1c\xb3\x93\x85\xea\x1f\x5b\x3c\xdf\xc1\xf7\x7b\x07\x29\x4a\xf9\x23\x5a\x27\x8d\x1e\x83\x28\x25\x3e\x79\xd4\xf4\xcb\x0d\x1f\xbf\x76\x43\x69\x46\xf3\x8b\x17\x8f\x52\xa7\x63\x78\x53\x39\x6f\x8a\x4f\xe8\x4c\x65\x13\x7c\x8b\x99\xd4\xd2\x4b\xa3\x5f\x14\xe8\x45\x2a\xbc\x18\xbf\x00\x10\x5a\x1b\x2f\xa8\xd9\xd1\x4f\x80\xc4\x68\x6f\x8d\x52\x68\x07\x39\xea\xe1\x63\x35\xc5\x69\x25\x55\x8a\x96\x17\xaf\xb7\x9e\xbf\x1a\x7e\x3d\x7c\xf5\x02\x20\xb1\xc8\xd3\xef\x64\x81\xce\x8b\xa2\x1c\x83\xae\x94\x7a\x01\xa0\x45\x81\x63\x30\x25\x5a\xe1\x8d\xcd\xad\xa9\x4a\x37\xac\x7f\xba\x61\x62\x2c\x1a\xfa\x53\xbc\x70\x25\x26\xb4\x3b\x8f\x69\xa7\xac\x8c\x09\xeb\xd5\x44\x0a\x8f\xb9\xb1\xb2\xfe\x0d\x30\x00\xa3\x0a\xfe\x3f\x30\xff\x31\xae\xf1\x3d\x2d\xc9\xed\x4a\x3a\xff\xc3\x66\xdf\x7b\xe9\x3c\xf7\x97\xaa\xb2\x42\xad\x13\xcc\x5d\x6e\x66\xac\xbf\x6e\xb7\xe7\xed\xf2\xd0\x25\x75\x5e\x29\x61\xd7\xe6\xbd\x00\x70\x89\x29\x71\x0c\x3c\xad\x14\x09\xa6\x2f\x00\xa2\xf8\xe2\x32\x83\x28\xa2\xf9\x45\x5c\xd5\x25\x33\x2c\x44\xbd\x07\xd0\x92\xfa\xf2\xe6\xea\xc7\x2f\x6f\xd7\x3a\x00\x52\x74\x89\x95\xa5\x67\x65\xac\x30\x04\xd2\x81\x9f\x21\x54\x5a\x7a\x30\x19\x14\x95\xf2\xd2\xa3\x16\x3a\x59\x42\x66\x2c\x7c\x7c\xff\x01\x0a\xa1\x45\x8e\x69\x47\xd4\x70\xe5\x49\xf7\xce\x5b\x21\x75\x58\x41\x6a\xe7\x85\x52\xac\x5e\x5a\xa9\x19\x0c\x52\x83\xf4\x2e\x68\x84\x78\x03\x6f\x40\x00\xa9\x51\x66\x12\x53\x70\xc8\x5b\x7b\x61\x73\xf4\xed\x30\x37\xec\x70\xe0\x97\x24\x1e\x33\xfd\x2b\x26\xbe\xd3\x6c\xf1\x6f\x95\xb4\x98\x76\x99\x25\x51\xd5\x87\xb6\xd3\x5c\x5a\xa2\xc8\x77\x4e\x41\xf8\x3a\x26\xb2\xd2\xbe\x26\xb5\x97\x24\xda\x30\x0e\x52\xb2\x0e\x0c\x6c\x47\x25\x11\x1b\x2c\x76\xe6\x64\x26\x1d\x58\x2c\x2d\x3a\xd4\xbe\x91\x88\xd0\x91\x81\x21\xdc\xa2\xa5\x89\x74\x56\x2a\x95\x92\x28\xe7\x68\x3d\x58\x4c\x4c\xae\xe5\xdf\x9b\xd5\x1c\xc9\x8a\xb6\x51\xc2\xa3\xf3\x20\xb5\x47\xab\x85\x82\xb9\x50\x15\xf6\x41\xe8\x14\x0a\xb1\x04\x8b\xb4\x2e\x54\xba\xb3\x02\x0f\x71\x43\xf8\x60\x2c\x69\x27\x33\x63\x98\x79\x5f\xba\xf1\x68\x94\x4b\x5f\x03\x40\x62\x8a\x82\x94\xbf\x1c\xb1\x2d\xcb\x69\x45\x3a\x1b\xa5\x38\x47\x35\x72\x32\x1f\x08\x9b\xcc\xa4\xc7\xc4\x57\x16\x47\xa2\x94\x03\x26\x56\x33\x08\x0c\x8b\xf4\x4f\x36\x42\x86\x7b\xb9\x26\xbe\xa0\x32\xe7\xad\xd4\xf9\x4a\x17\xdb\xdc\x5e\x59\x93\xe5\xd1\xc9\x14\x71\x7a\xe0\xa5\x15\x29\x35\x91\x54\x3e\x7d\x77\x7b\x07\x35\x01\x41\xec\x41\xc2\xed\x50\xd7\x0a\x9b\x04\x25\x75\x86\x36\x8c\xcc\xac\x29\x78\x15\xd4\x69\x69\xa4\xf6\xfc\x23\x51\x12\xb5\x07\x57\x4d\x0b\x3a\xb4\x74\xc0\xd0\x79\xd2\xc3\x10\xde\x30\xfe\xc1\x14\xa1\x2a\x53\xe1\x31\x1d\xc2\x95\x86\x37\xa2\x40\xf5\x46\x38\xfc\xdd\x45\x4d\x12\x75\x03\x12\xdf\xf1\xc2\xee\xc2\xf7\xe6\x84\x0d\x83\x02\xa8\xe1\x75\xa7\x76\x56\xf0\xe3\xb6\xc4\xa4\xc6\x10\x9a\xc9\x98\x21\xf4\x1a\xc8\xd4\x2a\x1a\x1e\x4b\x04\x6d\x99\x89\x4a\xf9\x75\x4a\x00\xaa\x32\xb7\x22\xc5\x5b\x6f\x09\xd6\x97\x63\x78\x1b\x46\xae\x0d\xdc\x65\xee\xcc\x22\x2a\x4c\xbc\xb1\x9b\x3d\x6b\xac\xde\xc6\x81\x71\x46\x60\x73\x85\xb5\x97\x6e\x3f\x6e\x1d\xc1\xe9\x21\x6a\xe9\x2b\x84\x4f\x66\xdf\x3d\xd1\x99\xee\xb8\x84\x03\xd4\xaf\x4f\x0a\x16\x45\x9e\x8d\xd0\x48\x89\x29\xaa\x46\x14\x35\x92\x16\xc1\x64\xee\x66\xb8\xd2\x02\xc2\x22\x5c\x5e\xbf\xc5\x74\x1b\x73\x2d\x83\xc2\x5a\xb1\xdc\x31\x42\x7a\x2c\x76\x12\xbe\x46\xfa\xe5\x1e\xf2\x22\x30\xd4\x3d\x7e\x26\xd8\x17\x79\xf6\x44\x01\xf4\xfa\x20\xe0\x11\x97\x01\x1f\x09\x76\xa3\xca\xc2\x60\x8b\x8c\xa6\xac\xcc\x47\x5c\xf2\xa0\x08\x96\x3b\xa9\x3b\xa0\xbf\xf0\x6d\xf7\x46\xab\xdf\x80\xb6\xdc\xdb\x5f\x13\xbb\x73\xd0\xa1\xc3\x12\xbe\x47\x5c\xee\xeb\x5e\x13\x38\xc9\x21\x9a\x71\x90\x3c\x35\xb0\xb4\xd8\xb2\x6b\x61\x8b\xb2\x54\x12\x19\x0d\xf7\xae\xbd\x13\x8e\x56\xbf\x9a\xd5\x67\x10\xda\xa8\xb2\x45\xf8\xa0\xec\x97\x2e\x28\x96\x4e\xfa\x4c\x96\x31\xc8\x08\xa1\x45\xed\x0a\x7f\x14\x4a\x76\xc2\x18\x3e\xd5\x57\xba\x0f\xd7\xc6\xd3\x9f\xef\x9e\x24\x41\x3d\x9d\x87\xb7\x06\xdd\xb5\xf1\xdc\xf2\x9b\xb0\x1a\x48\x78\x06\xa3\x61\x02\x1f\x76\x1d\xec\x8a\x38\xe9\xfa\x43\x0a\xc3\x32\xd6\x4f\x23\x14\xe9\xc8\x23\x19\x5b\x73\xc4\x11\x4a\x58\x28\x2c\x51\x54\x8e\x1d\x98\x36\x7a\x80\x45\xe9\x97\x5b\xd7\x88\x82\x30\x76\x45\x0e\x7b\x96\x8b\x4b\xdd\x91\x5f\x0d\x3d\x21\x02\x52\x14\xca\x42\x5a\x31\xd1\xec\xcd\x09\xb4\x65\x02\x05\xda\x1c\xa1\x24\x84\x3a\x46\xbc\xfb\x70\x25\x7c\x07\xd0\xe5\x48\x5d\x31\x64\xbe\x27\x03\x78\x06\xc4\x86\xf1\x01\x96\x0a\x51\x92\x9a\x7e\x22\xf4\x61\x49\xfd\x0c\xa5\x90\x14\x31\x5f\x72\xf4\xaf\x70\xa5\x4f\x6a\x96\x69\x77\x19\x5a\x41\x3a\x20\x28\x99\x0b\x45\x78\x47\x27\x59\x03\xaa\x80\x7e\x14\xa4\xaf\x01\x7b\x1f\x16\x33\xe3\x02\x98\x65\x12\x15\xc7\x4e\xbd\x47\x5c\xf6\xfa\x1b\xaa\xed\x5d\xe9\x5e\xc0\xc5\x0d\x65\x36\x20\x6a\xb4\x5a\x42\x8f\xfb\x7a\xbf\xdc\x17\xec\x05\x4b\x91\xa6\x9c\x5e\x0a\x75\x73\x04\x9a\xed\xd5\x9b\x43\x3b\x97\x09\x5e\x26\x89\xa9\x34\x27\x5e\x47\xf8\xf5\xf5\x29\x35\xf8\x89\xb4\x90\x7a\x25\x37\xe1\x91\x20\xc2\x50\x58\xcc\x64\x32\x83\x85\x54\x8a\xc3\x40\x87\x29\xa9\x27\xc5\x52\x99\x65\x23\xe7\x33\x77\x1e\x34\x4b\xf1\x68\x2d\x7b\xce\xf4\x76\x87\x06\xbb\x98\xa3\xf4\x21\xb9\xb1\x66\x2e\x53\x4c\x2f\x6f\xae\xb6\x4a\x69\x95\x39\x9e\x02\x1e\x95\x72\x9c\xbe\x51\xcc\xea\x4d\x8c\x59\xb7\x86\x30\x65\x67\xfd\x4e\x92\xbf\x93\xd8\xa9\x31\x0a\xc5\x66\x7f\x08\x85\x9a\x24\xf6\x30\xad\x77\x6b\x13\x22\xdc\xe1\x53\xa9\x64\x22\x7d\x8d\xdf\x6d\x6c\xc5\xf9\x10\x4f\x62\xe0\x92\x1c\x0d\x38\xf4\xfd\x36\x56\x93\x0e\x64\xae\x8d\xdd\x7e\x3e\xf7\xe3\xc9\x1e\x14\x39\x80\x1d\x4f\x83\xc7\x6a\x8a\x56\xa3\x47\x37\xa0\x18\x6b\x10\x27\xe0\xa6\x09\xac\x87\xb0\x87\xa4\xd4\xfb\xbc\x3a\x61\x25\x01\x8d\x8b\xd5\xd8\x1a\xb2\xf6\x95\xe4\x9b\x46\x35\x12\x64\x7b\xb6\xc8\x46\x9c\x54\xd6\xa2\xf6\x6a\x09\x7e\x61\xc0\x55\x65\x69\xac\xc7\x74\x7d\x49\x32\x4d\x98\xe8\x3a\xd0\x1e\xf3\xa1\x62\x13\x60\xa0\x10\x4a\x99\x05\x24\xaa\x72\x1e\x6d\xb4\xac\x98\x29\xb3\xba\x0a\x33\xc7\x3a\x8d\x0d\x2e\x81\x9c\x41\x39\x13\x0e\xdb\x1c\xcc\x55\x49\x82\x98\x62\x1a\x3a\xa2\x2b\xc1\x2c\xc3\xc4\xcb\x39\xaa\x25\x14\x28\xb8\xd2\x20\x7c\xbb\x3f\x9d\xec\xb0\x7d\xcb\xf0\xda\x8e\x1a\x9f\x7c\x9d\xa4\x83\xe4\x24\x7c\xb5\x52\x61\x1b\x76\x67\xc2\x41\x26\xa4\xa2\xbc\x6e\xa2\xe1\x0e\x93\xd9\x8d\xc5\xb9\xc4\xc5\x67\xed\x44\x86\xef\x84\x54\xef\x8c\x5d\x08\x9b\x76\x64\xf0\x7b\xb0\x4f\x54\x35\x7d\x81\xa4\x5a\x2e\x97\x0d\x70\xaa\x65\xbf\xa5\x22\x47\x4d\x02\x20\x7e\x17\x35\x83\x37\x8a\x24\xb6\x98\xa1\x26\xd7\x5b\x4d\x9b\x13\x05\x16\x33\xb4\xa8\xc9\x9e\x44\xbd\x7e\x67\x52\xe3\x1e\x12\xe1\x85\x32\x39\x4b\x66\x8a\xa8\xeb\xbc\x17\x16\xd2\xcf\x40\xf0\x66\xb5\xf4\x32\x0e\xaf\x11\x90\x42\x05\x62\x31\xda\x6e\xa7\x68\x34\xd1\xf0\x9f\x97\x9f\xae\xaf\xae\xbf\x1f\xb3\x57\xd9\x27\xe1\xcd\x73\x2d\x1d\x54\x3c\xaa\x53\xf5\x70\x95\xf2\x74\xc4\x2b\x8d\x4f\x25\x26\x44\xda\x14\x67\x62\x2e\xc9\x06\x6c\xac\x87\xcc\xd1\x8a\xa9\x42\xa0\x34\x18\x94\x71\xb4\x8e\x42\xe7\x60\x69\x2a\x98\x89\x39\x42\x8a\x58\x42\xa5\x53\xb4\xce\x0b\x9d\x12\xf5\x26\x8b\x91\xef\x2a\x13\x30\x45\xea\xad\x2b\x62\x1b\xd6\xd5\x7b\x2e\xc0\xb7\x99\xee\x8e\x44\x96\x3e\xd4\x55\xb1\x1d\x95\x06\x7b\x66\x51\xef\x3e\x11\xaf\xa6\xfd\x5e\xf8\x6a\x03\xfa\xf6\x24\xfe\x3c\xbe\x49\xfd\xc3\xaf\x6d\xc9\xff\xa7\xe7\xe7\xfe\xbb\xf3\xa8\x01\x28\xe1\xfc\xe7\x70\x0a\x9f\x91\xf1\x27\x46\x07\xb3\x39\xec\x92\xde\x34\x43\xd7\x63\xef\x6d\x9e\xb3\x5d\xf8\x37\x75\x36\xab\xf0\xdf\x90\xd4\x86\x68\x29\x7a\x21\x55\x90\xb8\xd1\x08\x82\x42\x16\x5f\x53\x19\x81\x9d\xd5\x82\x4d\x45\xf2\xf2\xe6\x0a\x1a\x6d\xc0\x60\x30\x08\x20\xeb\xbc\xad\x12\xf6\xa3\x52\x7b\xd4\x04\x42\xb4\x6a\x2a\x2d\x97\x14\x1d\x2d\xde\xca\x21\x66\x84\x21\xcc\x2c\x85\x9f\xc1\x30\x28\x7f\xd8\x11\x05\xc0\x3b\x63\x01\x9f\x44\x51\x2a\xec\xb3\x18\xe0\x9d\x31\xf1\xcc\x84\x0d\x7f\x82\xd1\x08\x3e\xb5\x49\x1c\x07\xaa\x53\x8a\xb7\x42\x0e\xc7\x15\x53\xc8\x8c\x21\x29\x77\xf9\x19\xd2\xc4\x1f\xb4\x59\xe8\x6d\x5b\xf3\x5e\xc2\xe2\x18\x26\xbd\xcb\xb9\x90\x8a\x4c\x7f\xd2\xeb\xc3\xa4\x77\x63\x4d\xce\x21\xb3\xce\x27\x31\x06\x9e\xf4\xde\x22\xc3\x4c\x3a\xe9\xd1\xb2\xff\xca\x19\xc9\x07\x4a\x4e\x7e\xc0\xe5\x37\xbc\x58\xd3\x5c\xbb\xdf\x6f\x42\xf2\x42\xed\xe4\xe8\xef\x96\x25\x7e\x43\x51\x7b\xdd\xf0\x41\x94\xcd\xe4\xce\x69\xba\x7f\x28\xd0\x8b\xf9\xc5\xb0\x55\xe7\x5f\xfe\xea\x8c\x1e\x4f\x7a\x2d\xfd\x7d\x53\xd0\xb1\x28\xfd\x72\xd2\x83\x95\x5d\xc7\x93\x1e\xef\x5b\xb7\xd7\x44\x8e\x27\x3d\xda\x89\x9a\xad\xf1\x66\x5a\x65\xe3\x49\x6f\xba\xf4\xe8\xfa\x17\x7d\x8b\x65\x9f\xc0\xe9\x9b\x76\x87\x49\xef\x2f\x04\xc4\xa3\x11\x18\x3f\x43\x1b\x34\xe9\xe0\xe7\x6d\xc8\x75\x44\x28\x7f\xa8\xe6\x11\x2c\xf6\xce\x0a\xed\x64\x7d\xf3\xb3\x73\x68\x81\xce\x89\x7c\x77\xbf\x45\xe1\xb6\x86\xa5\xa1\x3b\x9c\x86\x9d\xdd\xc4\xcb\xd6\xce\xc3\x05\x95\x4d\x1e\x8e\x2c\x64\x6d\x4e\x6c\xcb\x2c\xce\x83\xa7\x06\xb6\xd8\xe6\x4c\xf8\x66\x34\x19\x22\x05\x01\x64\xdf\x11\x60\x39\x15\x64\xbd\xc5\x08\x29\x5e\x20\x4c\x31\xf8\xf9\x70\x95\x93\xa2\x55\x4b\x72\x53\xed\xaa\xc9\x4c\xe8\x9c\x02\x9b\x90\xee\x0b\xb6\x77\x0a\x9f\x1e\xc9\x90\x38\x4d\xd4\x50\xb9\xba\xb0\xce\x74\x35\x2b\x12\x70\x04\x83\x8f\xcb\x30\x32\x26\x09\x96\x9e\xac\xeb\x50\xd5\xec\x40\x6d\x24\x33\xb6\x10\x7e\x4c\xee\x19\x07\x7e\xf7\xf1\x88\x87\xe3\x48\xc1\xc7\xd1\x21\x2b\x9f\x55\x85\xa0\xa8\x47\xa4\x1c\x08\x34\x7d\x3a\x95\x89\xe0\x60\xa5\xc6\x53\x31\x35\x55\x40\xb8\x56\x0f\x51\xd4\x14\x71\x4c\x91\xd3\x13\xb2\xcf\xc8\xd6\xaf\x64\xbe\x10\x4f\xef\x51\xe7\x7e\x36\x86\x2f\x5f\xff\xfb\x57\x5f\xef\x18\x18\x80\x11\xd3\xef\x43\x98\xb7\xe5\xb2\x6a\x87\x18\x36\x27\x76\x0b\x67\xc4\xe7\xb0\xbe\x21\x18\xe6\xed\x98\xa6\xf2\xd7\x9e\xa0\x85\xe0\x44\x0b\xa6\xc2\x71\x8a\x40\x72\x21\x94\xe7\xb8\x51\x27\xd8\xa7\xe8\x7a\xeb\x62\xd2\x75\x32\x8d\x8b\xd7\x7d\x98\x46\x11\x6f\xc2\xf7\xfd\xd3\xc3\x70\x0b\xc9\xd2\xc1\x9f\xfb\x6b\xf4\x50\x6e\x5d\xb1\xc7\xe3\xb4\x96\x23\x52\x8b\xc1\x0d\xc6\x70\x7b\x8b\x1b\xc4\x86\xde\x43\x8a\x23\x67\x98\xe3\xee\x2a\x6c\x7d\x6c\xa5\xf6\x5f\xfd\xdb\x6e\xfd\x4a\x2d\x8b\xaa\x18\xc3\xab\x1d\x43\x02\xa4\x1d\xa9\xcd\x30\xb8\x8d\x02\x04\x41\x57\x6e\x45\x51\x70\xca\x2f\x53\xd4\x5e\x66\x12\x6d\xf7\x68\x87\xc4\x83\x27\xd6\x31\x7a\x23\xc5\x97\x2e\xe2\x50\xe7\xb0\xdf\x58\x93\x56\x09\x5a\xf6\xc0\xb1\x12\x92\x74\x01\x6a\x59\x62\xb0\x86\x90\x86\x42\x13\x7a\xd7\xd5\x24\x0a\xcf\x51\x68\xa9\x73\x17\xb7\x94\x2e\x00\x48\xf0\xba\x8b\x19\xb2\xeb\x59\xa9\x40\x31\x55\x4e\xa6\x68\x31\x05\x01\x79\x25\xac\xd0\x1e\x31\x25\xf8\x09\x55\xa8\x70\x0b\xd8\x42\x9e\x68\xef\xde\x6a\x6b\x0c\xa6\x1a\xc0\x8a\x48\x8c\xf7\x75\xa1\x3e\xf9\x9b\x99\xea\xc5\xab\xd7\x7b\x55\xde\x8c\xdb\x5d\xc3\x17\xde\xa3\xd5\x63\xf8\xef\xfb\xcb\xc1\x7f\x89\xc1\xdf\x1f\xce\xe2\x3f\xaf\x06\x7f\xfe\x9f\xfe\xf8\xe1\x8b\xce\xcf\x87\xf3\x6f\xff\x65\xc7\x4a\xdb\xc3\xf6\x1d\xc7\x27\x3a\x91\x3a\x48\xac\x35\xda\x67\x0f\x63\x32\xb8\xb3\x15\xf6\xe1\x9d\x50\x0e\xfb\xf0\x59\xb3\x6b\xf8\x95\x42\xdb\x9d\xb9\x84\x6f\x00\x3d\xda\x75\x7b\xf0\xd1\x0c\x61\x92\xf6\x8f\x89\xe4\xee\xab\x48\x1e\x27\x24\x0e\xdb\x4c\xd6\x45\x9a\xce\x1d\x2f\x30\xe2\x51\x58\x3a\x8c\xe1\xed\x30\x31\xc5\xa8\x73\x07\x4c\x71\xf5\x07\xa1\x97\xd0\xc2\x5a\x08\x4a\xd7\x4f\xba\xf3\x84\x4d\x22\xb1\x94\x91\x36\xb7\xe8\xa0\xe4\x23\x42\x13\xb9\x06\xb0\x9c\x62\x22\x38\x10\xb7\x53\xe9\xad\xb0\xcb\x4e\xde\x01\x89\xd0\xb1\x16\x99\x55\x0a\xce\x1c\x22\x0c\xb5\x49\x71\x13\x5d\xcf\x03\x86\x8a\xa9\x54\xd2\x2f\x43\xe1\x32\x31\x3a\x53\x32\xc6\xff\x45\x69\xac\x17\xda\xd7\x45\xdf\x1c\x9f\x40\xfa\x50\x6f\x0e\xc5\xb9\xb3\x54\xbb\x8b\x8b\xd7\x5f\xde\x56\xd3\xd4\x14\x42\xea\x77\x85\x1f\x9d\x7f\x7b\xf6\xb7\x4a\x28\xae\x98\x5e\x8b\x02\xdf\x15\xfe\xfc\xb7\x73\x8b\x17\x5f\x1d\x61\x45\x67\xf7\xc1\x56\x1e\xce\xee\x07\xf1\xbf\x2f\xea\xa6\xf3\x6f\xcf\x26\xc3\xbd\xfd\xe7\x5f\x10\x0f\x1d\x0b\x7c\xb8\x1f\xb4\xe6\x37\x7c\xf8\xe2\xfc\xdb\x4e\xdf\xf9\xa6\x31\x76\xb2\xd2\x83\x09\xe6\xfb\x76\x6c\x88\x4e\x7c\xfd\x18\xaa\xb6\xcc\xd5\xd0\x70\x3d\xe5\x8c\x56\x4c\xfe\x38\x2e\xf3\xec\xaa\xf2\x31\x41\x97\x3e\xbe\x8a\xbb\x5a\xbf\xed\x94\x4d\x36\xae\xc6\x1b\x0f\xb4\xc2\xd4\x3f\x6b\x9d\x76\xf5\x66\xe1\x13\x66\xcf\xbc\x58\xf8\x84\x59\xb7\xd4\x16\x04\xb3\x7a\x9f\x10\x9f\xab\x34\x17\x0e\xbf\xc3\xdb\x81\xdd\x0f\x9c\xb6\xb2\x40\xc1\x7e\x5d\x2f\x8d\xe7\x31\xf2\xb0\xf3\x22\xf4\xa0\x49\xb3\x3f\xbe\x11\x7e\x76\x14\x05\x2f\xaf\xa2\xd8\xf8\xd6\x90\xef\x71\x4b\x89\x09\xae\xbc\xa1\xe2\x38\x0e\x45\x1a\x1b\x29\xf0\xb1\x18\xfb\xfa\x21\xe2\x88\x77\xa5\xed\x1b\x2b\x0a\x9a\x40\x10\x10\xcb\x14\xfe\xe3\xf6\xe3\xf5\xe8\x7b\x13\x63\x05\xca\x66\x5c\xb0\x2d\xbe\xe5\xea\x83\xab\x92\x19\x08\x47\xa4\x51\x7e\x7b\xcb\xa5\x87\x42\x68\x99\xa1\xf3\xc3\xb8\x1a\x5a\x77\xff\xfa\x61\xb8\x5a\xee\x90\xf1\x42\xb5\x7e\x89\x14\x0f\x00\xdb\x06\x31\xd3\xcc\xe5\xa0\x95\x49\x2a\x4d\x1a\x89\x5e\x30\xb1\x5e\x3c\x22\x98\x48\x6c\x85\xec\x14\xc6\xd0\xa3\x63\xd2\xd9\xfa\x27\x32\xac\x9f\x7b\x70\xb6\xe0\x92\x7e\x8f\x7e\xf6\xc2\x86\xcd\xc3\x31\x6a\xeb\x78\xfc\xb8\x71\x88\xef\xad\xcc\x73\x0e\xb7\xb8\x6e\x3b\x47\xed\xcf\xd9\xbf\x65\xa0\x4d\x67\xb0\x8e\xf7\x63\xed\xad\xd8\x3a\x21\xf7\xaf\x1f\x7a\x70\xb6\xca\x17\x85\xa0\xf8\x04\xaf\x9b\x9b\xb0\xd2\xa4\xe7\x75\xd6\xba\xd4\x5e\x3c\x71\x62\x30\x33\x0e\x75\xb8\x48\xf0\x26\x54\x63\x9d\xa1\xe4\x13\x95\x1a\x84\x00\x33\x85\x45\x28\xc0\xd5\xa2\x0c\x97\xc9\xa5\xb0\x7e\xed\x59\xdd\xdd\xc7\xb7\x1f\xc7\x61\x37\x52\x5b\xae\xeb\x2c\x37\x93\x5a\xa8\x58\xd6\x6e\xe2\x43\x22\xa4\x0a\x4a\xf2\x26\xa6\xb6\x75\x45\x37\xab\x7c\x65\x71\xb8\xfe\xcc\xea\xe8\x13\xbf\xed\x8d\xdb\xf6\xc3\xce\x6f\xdd\xd6\x0d\xed\xff\xf0\x25\xd9\xd1\x2c\xea\x1d\x37\xad\x9b\x2c\x5e\x77\xce\xe0\x5e\x16\x5b\x68\x26\x2e\x53\x93\x38\x62\x30\xc1\xd2\xbb\x91\x99\x13\x74\xe2\x62\xb4\x30\xf6\x51\xea\x7c\x40\x87\x6c\x10\x34\xef\x46\xec\x62\x46\x7f\xe2\x3f\xbf\x8a\x23\xf6\x53\xc7\xb3\x15\x1e\xb4\xfe\x03\x78\x63\xf7\x39\xfa\xc5\xac\xd5\xf1\xe5\x73\x3c\xc1\xcb\xdb\x3a\xf9\x5b\x9b\x4d\xe6\x12\x2e\xc2\xe3\x4b\xd7\x0e\xc2\x15\x22\x0d\x10\x28\xf4\xf2\x77\x3f\xc6\x24\x40\xce\xf1\x93\xe5\x20\x3e\x45\x1f\x08\x9d\x0e\x9a\xf8\x3a\x59\xfe\x62\x89\x55\xf2\x48\x03\xfe\x7c\xf5\xf6\x1f\x73\xb8\x2b\xf9\x2c\x6b\x0d\x55\x94\x31\x78\x5b\xd5\xd1\x9d\xf3\xc6\x8a\x1c\x57\xdb\xaa\x69\x93\x7c\xb4\x0c\xc7\xbc\x12\x7e\xfa\x99\x9b\xda\xc7\xe7\x42\x95\x33\xf1\xba\x9e\x7b\x7a\x82\x7e\x7a\x82\x7e\x7a\x82\x7e\x7a\x82\xbe\x57\xd8\x7f\xd4\x27\xe8\xa7\x27\xe4\xa7\x27\xe4\xa7\x27\xe4\xbb\xbb\x4f\x4f\xc8\x4f\x4f\xc8\x4f\x4f\xc8\xd7\xbf\xd3\x13\xf2\xd3\x13\xf2\xd3\x13\xf2\xd3\x13\xf2\x2d\xdf\x4e\x35\xfd\xff\x7e\x7c\x79\xba\x1c\xfb\x63\x5c\x8e\x9d\xae\xbb\x4e\xd7\x5d\xa7\xeb\xae\xd3\x75\xd7\x2f\x38\xf1\xa7\xeb\xae\xd3\x75\xd7\xe9\xba\xeb\x74\xdd\xf5\x4f\x7a\xdd\x95\x09\xe5\x8e\xbe\xef\xfa\xdf\x00\x00\x00\xff\xff\x25\xf1\x04\x48\x34\x4b\x00\x00") +var _operatorsCoreosCom_operatorgroupsYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5a\x79\x6f\x23\x37\x96\xff\xbf\x3f\xc5\x83\x66\x81\xb6\xb3\x3a\xda\x9d\x45\x76\x22\x20\x08\x8c\xee\x74\xe0\x4d\xb7\xdb\x68\xbb\xb3\xc0\x5a\xde\x1d\xaa\xea\x55\x89\x63\x16\x59\x43\xb2\x24\x6b\x82\x7c\xf7\xc5\x7b\x64\x1d\xba\xe5\x1c\xb3\x93\x85\xea\x1f\x5b\x3c\xdf\xc1\xf7\x7b\x07\x29\x4a\xf9\x23\x5a\x27\x8d\x1e\x83\x28\x25\x3e\x79\xd4\xf4\xcb\x0d\x1f\xff\xec\x86\xd2\x8c\xe6\x17\x2f\x1e\xa5\x4e\xc7\xf0\xa6\x72\xde\x14\x9f\xd0\x99\xca\x26\xf8\x16\x33\xa9\xa5\x97\x46\xbf\x28\xd0\x8b\x54\x78\x31\x7e\x01\x20\xb4\x36\x5e\x50\xb3\xa3\x9f\x00\x89\xd1\xde\x1a\xa5\xd0\x0e\x72\xd4\xc3\xc7\x6a\x8a\xd3\x4a\xaa\x14\x2d\x2f\x5e\x6f\x3d\x7f\x35\xfc\x7a\xf8\xea\x05\x40\x62\x91\xa7\xdf\xc9\x02\x9d\x17\x45\x39\x06\x5d\x29\xf5\x02\x40\x8b\x02\xc7\x60\x4a\xb4\xc2\x1b\x9b\x5b\x53\x95\x6e\x58\xff\x74\xc3\xc4\x58\x34\xf4\xa7\x78\xe1\x4a\x4c\x68\x77\x1e\xd3\x4e\x59\x19\x13\xd6\xab\x89\x14\x1e\x73\x63\x65\xfd\x1b\x60\x00\x46\x15\xfc\x7f\x60\xfe\x63\x5c\xe3\x7b\x5a\x92\xdb\x95\x74\xfe\x87\xcd\xbe\xf7\xd2\x79\xee\x2f\x55\x65\x85\x5a\x27\x98\xbb\xdc\xcc\x58\x7f\xdd\x6e\xcf\xdb\xe5\xa1\x4b\xea\xbc\x52\xc2\xae\xcd\x7b\x01\xe0\x12\x53\xe2\x18\x78\x5a\x29\x12\x4c\x5f\x00\x44\xf1\xc5\x65\x06\x51\x44\xf3\x8b\xb8\xaa\x4b\x66\x58\x88\x7a\x0f\xa0\x25\xf5\xe5\xcd\xd5\x8f\x5f\xde\xae\x75\x00\xa4\xe8\x12\x2b\x4b\xcf\xca\x58\x61\x08\xa4\x03\x3f\x43\xa8\xb4\xf4\x60\x32\x28\x2a\xe5\xa5\x47\x2d\x74\xb2\x84\xcc\x58\xf8\xf8\xfe\x03\x14\x42\x8b\x1c\xd3\x8e\xa8\xe1\xca\x93\xee\x9d\xb7\x42\xea\xb0\x82\xd4\xce\x0b\xa5\x58\xbd\xb4\x52\x33\x18\xa4\x06\xe9\x5d\xd0\x08\xf1\x06\xde\x80\x00\x52\xa3\xcc\x24\xa6\xe0\x90\xb7\xf6\xc2\xe6\xe8\xdb\x61\x6e\xd8\xe1\xc0\x2f\x49\x3c\x66\xfa\x57\x4c\x7c\xa7\xd9\xe2\xdf\x2a\x69\x31\xed\x32\x4b\xa2\xaa\x0f\x6d\xa7\xb9\xb4\x44\x91\xef\x9c\x82\xf0\x75\x4c\x64\xa5\x7d\x4d\x6a\x2f\x49\xb4\x61\x1c\xa4\x64\x1d\x18\xd8\x8e\x4a\x22\x36\x58\xec\xcc\xc9\x4c\x3a\xb0\x58\x5a\x74\xa8\x7d\x23\x11\xa1\x23\x03\x43\xb8\x45\x4b\x13\xe9\xac\x54\x2a\x25\x51\xce\xd1\x7a\xb0\x98\x98\x5c\xcb\xbf\x37\xab\x39\x92\x15\x6d\xa3\x84\x47\xe7\x41\x6a\x8f\x56\x0b\x05\x73\xa1\x2a\xec\x83\xd0\x29\x14\x62\x09\x16\x69\x5d\xa8\x74\x67\x05\x1e\xe2\x86\xf0\xc1\x58\xd2\x4e\x66\xc6\x30\xf3\xbe\x74\xe3\xd1\x28\x97\xbe\x06\x80\xc4\x14\x05\x29\x7f\x39\x62\x5b\x96\xd3\x8a\x74\x36\x4a\x71\x8e\x6a\xe4\x64\x3e\x10\x36\x99\x49\x8f\x89\xaf\x2c\x8e\x44\x29\x07\x4c\xac\x66\x10\x18\x16\xe9\x9f\x6c\x84\x0c\xf7\x72\x4d\x7c\x41\x65\xce\x5b\xa9\xf3\x95\x2e\xb6\xb9\xbd\xb2\x26\xcb\xa3\x93\x29\xe2\xf4\xc0\x4b\x2b\x52\x6a\x22\xa9\x7c\xfa\xee\xf6\x0e\x6a\x02\x82\xd8\x83\x84\xdb\xa1\xae\x15\x36\x09\x4a\xea\x0c\x6d\x18\x99\x59\x53\xf0\x2a\xa8\xd3\xd2\x48\xed\xf9\x47\xa2\x24\x6a\x0f\xae\x9a\x16\x74\x68\xe9\x80\xa1\xf3\xa4\x87\x21\xbc\x61\xfc\x83\x29\x42\x55\xa6\xc2\x63\x3a\x84\x2b\x0d\x6f\x44\x81\xea\x8d\x70\xf8\xbb\x8b\x9a\x24\xea\x06\x24\xbe\xe3\x85\xdd\x85\xef\xcd\x09\x1b\x06\x05\x50\xc3\xeb\x4e\xed\xac\xe0\xc7\x6d\x89\x49\x8d\x21\x34\x93\x31\x43\xe8\x35\x90\xa9\x55\x34\x3c\x96\x08\xda\x32\x13\x95\xf2\xeb\x94\x00\x54\x65\x6e\x45\x8a\xb7\xde\x12\xac\x2f\xc7\xf0\x36\x8c\x5c\x1b\xb8\xcb\xdc\x99\x45\x54\x98\x78\x63\x37\x7b\xd6\x58\xbd\x8d\x03\xe3\x8c\xc0\xe6\x0a\x6b\x2f\xdd\x7e\xdc\x3a\x82\xd3\x43\xd4\xd2\x57\x08\x9f\xcc\xbe\x7b\xa2\x33\xdd\x71\x09\x07\xa8\x5f\x9f\x14\x2c\x8a\x3c\x1b\xa1\x91\x12\x53\x54\x8d\x28\x6a\x24\x2d\x82\xc9\xdc\xcd\x70\xa5\x05\x84\x45\xb8\xbc\x7e\x8b\xe9\x36\xe6\x5a\x06\x85\xb5\x62\xb9\x63\x84\xf4\x58\xec\x24\x7c\x8d\xf4\xcb\x3d\xe4\x45\x60\xa8\x7b\xfc\x4c\xb0\x2f\xf2\xec\x89\x02\xe8\xf5\x41\xc0\x23\x2e\x03\x3e\x12\xec\x46\x95\x85\xc1\x16\x19\x4d\x59\x99\x8f\xb8\xe4\x41\x11\x2c\x77\x52\x77\x40\x7f\xe1\xdb\xee\x8d\x56\xbf\x01\x6d\xb9\xb7\xbf\x26\x76\xe7\xa0\x43\x87\x25\x7c\x8f\xb8\xdc\xd7\xbd\x26\x70\x92\x43\x34\xe3\x20\x79\x6a\x60\x69\xb1\x65\xd7\xc2\x16\x65\xa9\x24\x32\x1a\xee\x5d\x7b\x27\x1c\xad\x7e\x35\xab\xcf\x20\xb4\x51\x65\x8b\xf0\x41\xd9\x2f\x5d\x50\x2c\x9d\xf4\x99\x2c\x63\x90\x11\x42\x8b\xda\x15\xfe\x28\x94\xec\x84\x31\x7c\xaa\xaf\x74\x1f\xae\x8d\xa7\x3f\xdf\x3d\x49\x82\x7a\x3a\x0f\x6f\x0d\xba\x6b\xe3\xb9\xe5\x37\x61\x35\x90\xf0\x0c\x46\xc3\x04\x3e\xec\x3a\xd8\x15\x71\xd2\xf5\x87\x14\x86\x65\xac\x9f\x46\x28\xd2\x91\x47\x32\xb6\xe6\x88\x23\x94\xb0\x50\x58\xa2\xa8\x1c\x3b\x30\x6d\xf4\x00\x8b\xd2\x2f\xb7\xae\x11\x05\x61\xec\x8a\x1c\xf6\x2c\x17\x97\xba\x23\xbf\x1a\x7a\x42\x04\xa4\x28\x94\x85\xb4\x62\xa2\xd9\x9b\x13\x68\xcb\x04\x0a\xb4\x39\x42\x49\x08\x75\x8c\x78\xf7\xe1\x4a\xf8\x0e\xa0\xcb\x91\xba\x62\xc8\x7c\x4f\x06\xf0\x0c\x88\x0d\xe3\x03\x2c\x15\xa2\x24\x35\xfd\x44\xe8\xc3\x92\xfa\x19\x4a\x21\x29\x62\xbe\xe4\xe8\x5f\xe1\x4a\x9f\xd4\x2c\xd3\xee\x32\xb4\x82\x74\x40\x50\x32\x17\x8a\xf0\x8e\x4e\xb2\x06\x54\x01\xfd\x28\x48\x5f\x03\xf6\x3e\x2c\x66\xc6\x05\x30\xcb\x24\x2a\x8e\x9d\x7a\x8f\xb8\xec\xf5\x37\x54\xdb\xbb\xd2\xbd\x80\x8b\x1b\xca\x6c\x40\xd4\x68\xb5\x84\x1e\xf7\xf5\x7e\xb9\x2f\xd8\x0b\x96\x22\x4d\x39\xbd\x14\xea\xe6\x08\x34\xdb\xab\x37\x87\x76\x2e\x13\xbc\x4c\x12\x53\x69\x4e\xbc\x8e\xf0\xeb\xeb\x53\x6a\xf0\x13\x69\x21\xf5\x4a\x6e\xc2\x23\x41\x84\xa1\xb0\x98\xc9\x64\x06\x0b\xa9\x14\x87\x81\x0e\x53\x52\x4f\x8a\xa5\x32\xcb\x46\xce\x67\xee\x3c\x68\x96\xe2\xd1\x5a\xf6\x9c\xe9\xed\x0e\x0d\x76\x31\x47\xe9\x43\x72\x63\xcd\x5c\xa6\x98\x5e\xde\x5c\x6d\x95\xd2\x2a\x73\x3c\x05\x3c\x2a\xe5\x38\x7d\xa3\x98\xd5\x9b\x18\xb3\x6e\x0d\x61\xca\xce\xfa\x9d\x24\x7f\x27\xb1\x53\x63\x14\x8a\xcd\xfe\x10\x0a\x35\x49\xec\x61\x5a\xef\xd6\x26\x44\xb8\xc3\xa7\x52\xc9\x44\xfa\x1a\xbf\xdb\xd8\x8a\xf3\x21\x9e\xc4\xc0\x25\x39\x1a\x70\xe8\xfb\x6d\xac\x26\x1d\xc8\x5c\x1b\xbb\xfd\x7c\xee\xc7\x93\x3d\x28\x72\x00\x3b\x9e\x06\x8f\xd5\x14\xad\x46\x8f\x6e\x40\x31\xd6\x20\x4e\xc0\x4d\x13\x58\x0f\x61\x0f\x49\xa9\xf7\x79\x75\xc2\x4a\x02\x1a\x17\xab\xb1\x35\x64\xed\x2b\xc9\x37\x8d\x6a\x24\xc8\xf6\x6c\x91\x8d\x38\xa9\xac\x45\xed\xd5\x12\xfc\xc2\x80\xab\xca\xd2\x58\x8f\xe9\xfa\x92\x64\x9a\x30\xd1\x75\xa0\x3d\xe6\x43\xc5\x26\xc0\x40\x21\x94\x32\x0b\x48\x54\xe5\x3c\xda\x68\x59\x31\x53\x66\x75\x15\x66\x8e\x75\x1a\x1b\x5c\x02\x39\x83\x72\x26\x1c\xb6\x39\x98\xab\x92\x04\x31\xc5\x34\x74\x44\x57\x82\x59\x86\x89\x97\x73\x54\x4b\x28\x50\x70\xa5\x41\xf8\x76\x7f\x3a\xd9\x61\xfb\x96\xe1\xb5\x1d\x35\x3e\xf9\x3a\x49\x07\xc9\x49\xf8\x6a\xa5\xc2\x36\xec\xce\x84\x83\x4c\x48\x45\x79\xdd\x44\xc3\x1d\x26\xb3\x1b\x8b\x73\x89\x8b\xcf\xda\x89\x0c\xdf\x09\xa9\xde\x19\xbb\x10\x36\xed\xc8\xe0\xf7\x60\x9f\xa8\x6a\xfa\x02\x49\xb5\x5c\x2e\x1b\xe0\x54\xcb\x7e\x4b\x45\x8e\x9a\x04\x40\xfc\x2e\x6a\x06\x6f\x14\x49\x6c\x31\x43\x4d\xae\xb7\x9a\x36\x27\x0a\x2c\x66\x68\x51\x93\x3d\x89\x7a\xfd\xce\xa4\xc6\x3d\x24\xc2\x0b\x65\x72\x96\xcc\x14\x51\xd7\x79\x2f\x2c\xa4\x9f\x81\xe0\xcd\x6a\xe9\x65\x1c\x5e\x23\x20\x85\x0a\xc4\x62\xb4\xdd\x4e\xd1\x68\xa2\xe1\x3f\x2f\x3f\x5d\x5f\x5d\x7f\x3f\x66\xaf\xb2\x4f\xc2\x9b\xe7\x5a\x3a\xa8\x78\x54\xa7\xea\xe1\x2a\xe5\xe9\x88\x57\x1a\x9f\x4a\x4c\x88\xb4\x29\xce\xc4\x5c\x92\x0d\xd8\x58\x0f\x99\xa3\x15\x53\x85\x40\x69\x30\x28\xe3\x68\x1d\x85\xce\xc1\xd2\x54\x30\x13\x73\x84\x14\xb1\x84\x4a\xa7\x68\x9d\x17\x3a\x25\xea\x4d\x16\x23\xdf\x55\x26\x60\x8a\xd4\x5b\x57\xc4\x36\xac\xab\xf7\x5c\x80\x6f\x33\xdd\x1d\x89\x2c\x7d\xa8\xab\x62\x3b\x2a\x0d\xf6\xcc\xa2\xde\x7d\x22\x5e\x4d\xfb\xbd\xf0\xd5\x06\xf4\xed\x49\xfc\x79\x7c\x93\xfa\x87\x5f\xdb\x92\xff\x4f\xcf\xcf\xfd\x77\xe7\x51\x03\x50\xc2\xf9\xcf\xe1\x14\x3e\x23\xe3\x4f\x8c\x0e\x66\x73\xd8\x25\xbd\x69\x86\xae\xc7\xde\xdb\x3c\x67\xbb\xf0\x6f\xea\x6c\x56\xe1\xbf\x21\xa9\x0d\xd1\x52\xf4\x42\xaa\x20\x71\xa3\x11\x04\x85\x2c\xbe\xa6\x32\x02\x3b\xab\x05\x9b\x8a\xe4\xe5\xcd\x15\x34\xda\x80\xc1\x60\x10\x40\xd6\x79\x5b\x25\xec\x47\xa5\xf6\xa8\x09\x84\x68\xd5\x54\x5a\x2e\x29\x3a\x5a\xbc\x95\x43\xcc\x08\x43\x98\x59\x0a\x3f\x83\x61\x50\xfe\xb0\x23\x0a\x80\x77\xc6\x02\x3e\x89\xa2\x54\xd8\x27\xbb\x27\x49\xc0\x3b\x63\xe2\xb1\x09\x7b\xfe\x04\xa3\x11\x7c\x6a\xf3\x38\x8e\x55\xa7\x14\x72\x85\x34\x8e\x8b\xa6\x90\x19\x43\x82\xee\xb2\x34\xa4\x89\x3f\x68\xb3\xd0\xdb\x76\xe7\xbd\x84\xc5\x31\x4c\x7a\x97\x73\x21\x15\x59\xff\xa4\xd7\x87\x49\xef\xc6\x9a\x9c\xa3\x66\x9d\x4f\x62\x18\x3c\xe9\xbd\x45\x46\x9a\x74\xd2\xa3\x65\xff\x95\x93\x92\x0f\x94\x9f\xfc\x80\xcb\x6f\x78\xb1\xa6\xb9\xf6\xc0\xdf\x84\xfc\x85\xda\xc9\xd7\xdf\x2d\x4b\xfc\x86\x02\xf7\xba\xe1\x83\x28\x9b\xc9\x9d\x03\x75\xff\x50\xa0\x17\xf3\x8b\x61\xab\xd1\xbf\xfc\xd5\x19\x3d\x9e\xf4\x5a\xfa\xfb\xa6\xa0\x93\x51\xfa\xe5\xa4\x07\x2b\xbb\x8e\x27\x3d\xde\xb7\x6e\xaf\x89\x1c\x4f\x7a\xb4\x13\x35\x5b\xe3\xcd\xb4\xca\xc6\x93\xde\x74\xe9\xd1\xf5\x2f\xfa\x16\xcb\x3e\xe1\xd3\x37\xed\x0e\x93\xde\x5f\x48\x27\xa3\x11\x18\x3f\x43\x1b\x94\xe9\xe0\xe7\x6d\xe0\x75\x44\x34\x7f\xa8\xec\x11\x8c\xf6\xce\x0a\xed\x64\x7d\xf9\xb3\x73\x68\x81\xce\x89\x7c\x77\xbf\x45\xe1\xb6\x46\xa6\xa1\x3b\x9c\x86\x9d\xdd\xc4\xcb\xd6\xce\xc3\x35\x95\x4d\x1e\x8e\xac\x65\x6d\x4e\x6c\x2b\x2d\xce\x83\xa7\x06\x36\xda\xe6\x4c\xf8\x66\x34\xd9\x22\xc5\x01\x64\xe2\x11\x63\x39\x1b\x64\xbd\xc5\x20\x29\xde\x21\x4c\x31\xb8\xfa\x70\x9b\x93\xa2\x55\x4b\xf2\x54\xed\xaa\xc9\x4c\xe8\x9c\x62\x9b\x90\xf1\x0b\x36\x79\x8a\xa0\x1e\xc9\x90\x38\x53\xd4\x50\xb9\xba\xb6\xce\x74\x35\x2b\x12\x76\x04\x9b\x8f\xcb\x30\x38\x26\x09\x96\x9e\xac\xeb\x50\xe1\xec\x40\x79\x24\x33\xb6\x10\x7e\x4c\x1e\x1a\x07\x7e\xf7\xf1\x88\x87\xe3\x48\xc1\xc7\xd1\x21\x31\x9f\x55\x85\xa0\xc0\x47\xa4\x1c\x0b\x34\x7d\x3a\x95\x89\xe0\x78\xa5\x86\x54\x31\x35\x55\x00\xb9\x56\x0f\x51\xd4\x14\x74\x4c\x91\x33\x14\xb2\xcf\xc8\xd6\xaf\x64\xbe\x10\x4f\xef\x51\xe7\x7e\x36\x86\x2f\x5f\xff\xfb\x57\x7f\xde\x31\x30\x00\x23\xa6\xdf\x87\x48\x6f\xcb\x7d\xd5\x0e\x31\x6c\x4e\xec\xd6\xce\x88\xcf\x61\x7d\x49\x30\xcc\xdb\x31\x4d\xf1\xaf\x3d\x41\x0b\xc1\xb9\x16\x4c\x85\xe3\x2c\x81\xe4\x42\x40\xcf\xa1\xa3\x4e\xb0\x4f\x01\xf6\xd6\xc5\xa4\xeb\x24\x1b\x17\xaf\xfb\x30\x8d\x22\xde\x84\xef\xfb\xa7\x87\xe1\x16\x92\xa5\x83\xaf\xfb\x6b\xf4\x50\x7a\x5d\xb1\xd3\xe3\xcc\x96\x83\x52\x8b\xc1\x13\xc6\x88\x7b\x8b\x27\xc4\x86\xde\x43\x8a\x23\x7f\x98\xe3\xee\x42\x6c\x7d\x6c\xa5\xf6\x5f\xfd\xdb\x6e\xfd\x4a\x2d\x8b\xaa\x18\xc3\xab\x1d\x43\x02\xa4\x1d\xa9\xcd\x30\xb8\x0d\x04\x04\x41\x57\x6e\x45\x51\x70\xd6\x2f\x53\xd4\x5e\x66\x12\x6d\xf7\x68\x87\xdc\x83\x27\xd6\x61\x7a\x23\xc5\x97\x2e\xe2\x50\xe7\xb0\xdf\x58\x93\x56\x09\x5a\xf6\xc0\xb1\x18\x92\x74\x01\x6a\x59\x62\xb0\x86\x90\x89\x42\x13\x7d\xd7\x05\x25\x8a\xd0\x51\x68\xa9\x73\x17\xb7\x94\x2e\x00\x48\xf0\xba\x8b\x19\xb2\xeb\x59\x29\x42\x31\x55\x4e\xa6\x68\x31\x05\x01\x79\x25\xac\xd0\x1e\x31\x25\xf8\x09\x85\xa8\x70\x11\xd8\x42\x9e\x68\xaf\xdf\x6a\x6b\x0c\xa6\x1a\xc0\x8a\x48\x8c\x57\x76\xa1\x44\xf9\x9b\x99\xea\xc5\xab\xd7\x7b\x55\xde\x8c\xdb\x5d\xc6\x17\xde\xa3\xd5\x63\xf8\xef\xfb\xcb\xc1\x7f\x89\xc1\xdf\x1f\xce\xe2\x3f\xaf\x06\x5f\xff\x4f\x7f\xfc\xf0\x45\xe7\xe7\xc3\xf9\xb7\xff\xb2\x63\xa5\xed\x91\xfb\x8e\xe3\x13\x9d\x48\x1d\x27\xd6\x1a\xed\xb3\x87\x31\x19\xdc\xd9\x0a\xfb\xf0\x4e\x28\x87\x7d\xf8\xac\xd9\x35\xfc\x4a\xa1\xed\x4e\x5e\xc2\x37\x80\x1e\xed\xba\x3d\xf8\x68\x86\x30\x49\xfb\xc7\x44\x72\xf7\x15\x25\x8f\x13\x12\x87\x6d\x26\xeb\x22\x4d\xe7\x9a\x17\x18\xf1\x28\x2c\x1d\xc6\x08\x77\x98\x98\x62\xd4\xb9\x06\xa6\xd0\xfa\x83\xd0\x4b\x68\x61\x2d\x04\xa5\xeb\x27\xdd\x79\xc2\x26\x91\x58\x4a\x4a\x9b\x8b\x74\x50\xf2\x11\xa1\x89\x5c\x03\x58\x4e\x31\x11\x1c\x8b\xdb\xa9\xf4\x56\xd8\x65\x27\xf5\x80\x44\xe8\x58\x8e\xcc\x2a\x05\x67\x0e\x11\x86\xda\xa4\xb8\x89\xae\xe7\x01\x43\xc5\x54\x2a\xe9\x97\xa1\x76\x99\x18\x9d\x29\x19\x53\x80\xa2\x34\xd6\x0b\xed\xeb\xba\x6f\x8e\x4f\x20\x7d\x28\x39\x87\xfa\xdc\x59\xaa\xdd\xc5\xc5\xeb\x2f\x6f\xab\x69\x6a\x0a\x21\xf5\xbb\xc2\x8f\xce\xbf\x3d\xfb\x5b\x25\x14\x17\x4d\xaf\x45\x81\xef\x0a\x7f\xfe\xdb\xb9\xc5\x8b\xaf\x8e\xb0\xa2\xb3\xfb\x60\x2b\x0f\x67\xf7\x83\xf8\xdf\x17\x75\xd3\xf9\xb7\x67\x93\xe1\xde\xfe\xf3\x2f\x88\x87\x8e\x05\x3e\xdc\x0f\x5a\xf3\x1b\x3e\x7c\x71\xfe\x6d\xa7\xef\x7c\xd3\x18\x3b\x89\xe9\xc1\x1c\xf3\x7d\x3b\x36\x44\x27\xbe\x7e\x0f\x55\x5b\xe6\x6a\x68\xb8\x9e\x75\x46\x2b\x26\x7f\x1c\x97\x79\x76\x61\xf9\x98\xa0\x4b\x1f\x5f\xc8\x5d\x2d\xe1\x76\x2a\x27\x1b\xb7\xe3\x8d\x07\x5a\x61\xea\x9f\xb5\x54\xbb\x7a\xb9\xf0\x09\xb3\x67\xde\x2d\x7c\xc2\xac\x5b\x6d\x0b\x82\x59\xbd\x52\x88\x2f\x56\x9a\x3b\x87\xdf\xe1\xf9\xc0\xee\x37\x4e\x5b\x59\xa0\x60\xbf\x2e\x99\xc6\xf3\x18\x79\xd8\x79\x17\x7a\xd0\xa4\xd9\x1f\xdf\x08\x3f\x3b\x8a\x82\x97\x57\x51\x6c\x7c\x71\xc8\x57\xb9\xa5\xc4\x04\x57\x9e\x51\x71\x1c\x87\x22\x8d\x8d\x14\xf8\x58\x8c\x7d\xfd\x10\x71\xc4\xeb\xd2\xf6\x99\x15\x05\x4d\x20\x08\x88\x65\x0a\xff\x71\xfb\xf1\x7a\xf4\xbd\x89\xb1\x02\x65\x33\x2e\xd8\x16\x5f\x74\xf5\xc1\x55\xc9\x0c\x84\x23\xd2\x28\xbf\xbd\xe5\xd2\x43\x21\xb4\xcc\xd0\xf9\x61\x5c\x0d\xad\xbb\x7f\xfd\x30\x5c\xad\x78\xc8\x78\xa7\x5a\x3f\x46\x8a\x07\x80\x6d\x83\x98\x69\xe6\x72\xd0\xca\x24\x95\x26\x8d\x44\x2f\x98\x58\x2f\x1e\x11\x4c\x24\xb6\x42\x76\x0a\x63\xe8\xd1\x31\xe9\x6c\xfd\x13\x19\xd6\xcf\x3d\x38\x5b\x70\x55\xbf\x47\x3f\x7b\x61\xc3\xe6\xed\x18\xb5\x75\x3c\x7e\xdc\x38\xc4\xf7\x56\xe6\x39\x87\x5b\x5c\xba\x9d\xa3\xf6\xe7\xec\xdf\x32\xd0\xa6\x33\x58\xc7\x2b\xb2\xf6\x62\x6c\x9d\x90\xfb\xd7\x0f\x3d\x38\x5b\xe5\x8b\x42\x50\x7c\x82\xd7\xcd\x65\x58\x69\xd2\xf3\x3a\x6b\x5d\x6a\x2f\x9e\x38\x31\x98\x19\x87\x3a\xdc\x25\x78\x13\x0a\xb2\xce\x50\xf2\x89\x4a\x0d\x42\x80\x99\xc2\x22\xd4\xe0\x6a\x51\x86\xfb\xe4\x52\x58\xbf\xf6\xb2\xee\xee\xe3\xdb\x8f\xe3\xb0\x1b\xa9\x2d\xd7\x75\x96\x9b\x49\x2d\x54\xac\x6c\x37\xf1\x21\x11\x52\x05\x25\x79\x13\x53\xdb\xba\xa8\x9b\x55\xbe\xb2\x38\x5c\x7f\x69\x75\xf4\x89\xdf\xf6\xcc\x6d\xfb\x61\xe7\xe7\x6e\xeb\x86\xf6\x7f\xf8\x98\xec\x68\x16\xf5\x8e\xcb\xd6\x4d\x16\xaf\x3b\x67\x70\x2f\x8b\x2d\x34\x13\x97\xa9\x49\x1c\x31\x98\x60\xe9\xdd\xc8\xcc\x09\x3a\x71\x31\x5a\x18\xfb\x28\x75\x3e\xa0\x43\x36\x08\x9a\x77\x23\x76\x31\xa3\x3f\xf1\x9f\x5f\xc5\x11\xfb\xa9\xe3\xd9\x0a\x6f\x5a\xff\x01\xbc\xb1\xfb\x1c\xfd\x62\xd6\xea\xf8\xf2\x39\x9e\xe0\xe5\x6d\x9d\xfc\xad\xcd\x26\x73\x09\x77\xe1\xf1\xb1\x6b\x07\xe1\x0a\x91\x06\x08\x14\x7a\xf9\xbb\x1f\x63\x12\x20\xe7\xf8\xc9\x72\x10\x5f\xa3\x0f\x84\x4e\x07\x4d\x7c\x9d\x2c\x7f\xb1\xc4\x2a\x79\xa4\x01\x7f\xbe\x7a\xfb\x8f\x39\xdc\x95\x7c\x96\xb5\x86\x2a\xca\x18\xbc\xad\xea\xe8\xce\x79\x63\x45\x8e\xab\x6d\xd5\xb4\x49\x3e\x5a\x86\x63\x5e\x09\x3f\xfd\xcc\x4d\xed\xfb\x73\xa1\xca\x99\x78\x5d\xcf\x3d\xbd\x42\x3f\xbd\x42\x3f\xbd\x42\x3f\xbd\x42\xdf\x2b\xec\x3f\xea\x2b\xf4\xd3\x2b\xf2\xd3\x2b\xf2\xd3\x2b\xf2\xdd\xdd\xa7\x57\xe4\xa7\x57\xe4\xa7\x57\xe4\xeb\xdf\xe9\x15\xf9\xe9\x15\xf9\xe9\x15\xf9\xe9\x15\xf9\x96\x6f\xa7\x9a\xfe\x7f\xbf\xbf\x3c\x5d\x8e\xfd\x31\x2e\xc7\x4e\xd7\x5d\xa7\xeb\xae\xd3\x75\xd7\xe9\xba\xeb\x17\x9c\xf8\xd3\x75\xd7\xe9\xba\xeb\x74\xdd\x75\xba\xee\xfa\x27\xbd\xee\xca\x84\x72\x47\xdf\x77\xfd\x6f\x00\x00\x00\xff\xff\x43\xb0\x74\xb5\x37\x4b\x00\x00") func operatorsCoreosCom_operatorgroupsYamlBytes() ([]byte, error) { return bindataRead( @@ -205,7 +205,7 @@ func operatorsCoreosCom_operatorgroupsYaml() (*asset, error) { return a, nil } -var _operatorsCoreosCom_operatorsYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\x59\xcd\x72\xe3\x36\x12\xbe\xfb\x29\xba\x94\x83\x93\x2a\xfd\x24\xb3\x97\x94\x6e\x2e\x7b\xb2\xe5\xdd\xac\x67\x6a\xec\x99\x4b\x2a\x87\x16\xd9\x12\xb1\x02\x01\x06\x0d\x4a\xd6\x4e\xcd\xbb\x6f\x35\x00\x4a\xa4\x24\x4b\xd4\xac\x27\x1b\x5c\x24\x82\x40\xa3\x7f\xbf\xee\x06\xb1\x52\x9f\xc8\xb1\xb2\x66\x0a\x58\x29\x7a\xf6\x64\xe4\x89\xc7\xcb\x9f\x79\xac\xec\x64\xf5\xd3\xd5\x52\x99\x7c\x0a\xb7\x35\x7b\x5b\x7e\x20\xb6\xb5\xcb\xe8\x8e\xe6\xca\x28\xaf\xac\xb9\x2a\xc9\x63\x8e\x1e\xa7\x57\x00\x68\x8c\xf5\x28\xd3\x2c\x8f\x00\x99\x35\xde\x59\xad\xc9\x8d\x16\x64\xc6\xcb\x7a\x46\xb3\x5a\xe9\x9c\x5c\x20\xde\x1c\xbd\xfa\x71\xfc\xf3\xf8\xc7\x2b\x80\xcc\x51\xd8\xfe\xa4\x4a\x62\x8f\x65\x35\x05\x53\x6b\x7d\x05\x60\xb0\xa4\x29\xd8\x8a\x1c\x7a\xeb\x78\xbc\xfb\x97\x59\x47\x56\x7e\xca\x2b\xae\x28\x93\x83\x17\xce\xd6\x55\x7b\x75\x6b\x4d\x24\xd5\xf0\x87\x9e\x16\xd6\xa9\xe6\x19\x60\x04\x56\x97\xe1\x7f\x94\xfb\x5d\xa2\x11\xa6\xb4\x62\xff\xcf\xce\xf4\xaf\x8a\x7d\x78\x55\xe9\xda\xa1\x6e\x9d\x19\x66\x59\x99\x45\xad\xd1\xed\xe6\xaf\x00\x38\xb3\x15\x4d\xe1\x56\xd7\xec\x49\x26\x92\x1e\x12\x0f\xa3\x24\xeb\xea\xa7\xc4\x12\x67\x05\x95\xd8\x30\x08\x42\xca\xdc\xbc\xbf\xff\xf4\xb7\xc7\xbd\x17\x00\x39\x71\xe6\x54\xe5\x83\x56\x1b\x1e\xc1\x51\xe5\x88\xc9\x78\x06\x84\x2c\x1e\xbb\x65\x68\xdc\xda\xee\x37\xc2\x98\x9d\xfd\x9b\x32\xdf\x9a\xae\x9c\x2c\xf6\x2d\x2d\xc5\xd1\xf2\x9e\xce\xfc\x1e\x1f\xd7\xc2\x6c\x5c\x07\xb9\x38\x0e\x31\xf8\x82\x1a\xb1\x29\x4f\x12\x82\x9d\x83\x2f\x14\xef\xf8\x0d\xbe\x20\xd3\x68\x12\x57\x63\x78\x24\x27\x1b\x81\x0b\x5b\xeb\x5c\x3c\x6c\x45\xce\x83\xa3\xcc\x2e\x8c\xfa\xcf\x96\x1a\x83\xb7\xe1\x18\x8d\x9e\xd8\x83\x32\x9e\x9c\x41\x0d\x2b\xd4\x35\x0d\x01\x4d\x0e\x25\x6e\xc0\x91\xd0\x85\xda\xb4\x28\x84\x25\x3c\x86\x7f\x59\x47\xa0\xcc\xdc\x4e\xa1\xf0\xbe\xe2\xe9\x64\xb2\x50\xbe\x89\x8d\xcc\x96\x65\x6d\x94\xdf\x4c\x82\x9b\xab\x59\x2d\x76\x9f\xe4\xb4\x22\x3d\x61\xb5\x18\xa1\xcb\x0a\xe5\x29\xf3\xb5\xa3\x09\x56\x6a\x14\x98\x35\x21\x3e\xc6\x65\xfe\x9d\x4b\xd1\xc4\xd7\x7b\xea\x8b\x76\x60\xef\x94\x59\x74\x5e\x05\x9f\x3c\xa9\x6b\x71\x4f\x50\x62\xe8\xb8\x3d\xca\xb2\x53\xa9\x4c\x89\x56\x3e\xbc\x7d\x7c\x82\x86\x81\xa8\xf6\xa8\xe1\x96\xb7\xec\x94\x2d\x8a\x52\x66\x4e\x2e\xae\x9c\x3b\x5b\x06\x2a\x64\xf2\xca\x2a\xe3\xc3\x43\xa6\x15\x19\x0f\x5c\xcf\x4a\xe5\xc5\x8a\x7f\xd4\xc4\x5e\xec\x30\x86\xdb\x00\x0d\x30\x23\xa8\xab\x1c\x3d\xe5\x63\xb8\x37\x70\x8b\x25\xe9\x5b\x64\xfa\xe6\xaa\x16\x8d\xf2\x48\xd4\xd7\x5f\xd9\x6d\x64\x3b\xdc\x70\x10\x25\x00\x0d\xfc\xbc\x68\x9d\x26\x22\x1f\x2b\xca\x3a\xa1\x90\x13\x2b\x27\xae\xeb\xd1\x93\x38\x7c\x07\x76\xfa\x1c\xed\xd1\xd7\xdc\xef\xf0\xb0\xb4\x73\xbc\x9d\xb1\x18\xba\x75\x3e\x9a\x1d\x7c\x48\xa4\x88\x41\x33\x5b\x56\xd6\x88\x63\xf4\xe5\xea\x65\xe8\x80\x90\x1c\x1a\x7a\x87\xef\xf6\x78\xbf\xdd\x2e\x4d\xf3\x33\xe2\xad\xf7\x8a\x0c\xe8\x23\x39\xa6\x28\xd0\x11\x70\xeb\xc1\xad\x0c\x71\x5b\xb1\xc5\x31\x9e\x04\x9c\x35\xce\x48\x3f\x92\xa6\xec\xd0\x3c\xe7\x24\x96\xd1\xd9\x7f\x7c\xc9\x9e\xf0\xbf\xb6\x77\xc4\xd8\x0e\x44\xe0\x8f\x9a\xdc\x06\xec\x8a\x9c\x84\x3b\x79\x31\xdc\x4e\x29\x35\x53\x2e\x18\xc8\x61\x67\x47\x2d\xd7\x27\x8c\xd9\x53\x4d\x7d\x44\x95\x51\xa2\xcf\x8a\xb7\xcf\x02\x29\xad\x1c\xd7\x43\xea\xfd\x8d\x49\x70\xc5\x41\xcc\xa8\x00\x6e\x94\x92\x8c\x56\x46\xd4\x7a\x2a\xa8\x33\x03\xe8\x08\x6e\x1e\xee\x28\x3f\xe6\x0f\x5d\x81\xd1\x39\xdc\x9c\x58\xa5\x3c\x95\x27\x85\xd8\x13\xe3\xe6\x04\xab\x09\xa7\x9b\x37\xc9\x8b\x8d\x47\x65\x38\xe5\xa0\x21\x20\x2c\x69\x13\xd3\x95\x64\xc1\x26\x28\xc3\x62\x47\x21\xb9\x05\xdb\x2e\x69\x13\x16\xa5\xdc\x75\x92\xc3\x1e\xb6\x8d\xe3\x74\x30\xec\xc6\x48\x8e\x3f\xbb\xc6\x1e\x07\xb5\xee\xe8\xe3\x54\x71\x2c\x69\x73\x6e\xc9\x9e\x31\x44\x47\x8a\x53\x55\x20\x56\x91\x89\xa0\x49\x99\xda\x1a\x02\xab\x4a\x2b\x0a\x89\xeb\x2c\xfd\x17\xb3\xc7\xe1\x68\xc4\xbf\x90\x69\x7b\xb4\x8c\x5b\xd2\xe6\x9a\xa3\x03\x48\x74\x14\xaa\x92\x58\xdf\xc2\x40\x53\xc1\x7c\x42\xad\xf2\x5d\x51\x1a\x22\xe1\xde\x0c\xe1\xc1\x7a\xf9\x79\xfb\xac\x24\x43\x8b\xdf\xdc\x59\xe2\x07\xeb\xc3\xcc\xab\x8a\x1d\x59\xb9\x50\xe8\xb8\x29\x04\x88\x89\x31\x29\x52\xb5\x4b\x1a\x1e\xc3\xfd\xbc\x83\x6a\xb2\xfa\xde\x80\x75\x8d\x74\xa1\xc8\x8c\x84\x22\x89\xb2\xe6\x50\x83\x18\x6b\x46\x54\x56\x7e\x73\x94\x46\x52\x8a\x75\x1d\x9d\x9c\x20\x97\x48\x3d\x49\x69\x14\xdf\xc4\x22\x56\x63\x46\x39\xe4\x75\x60\x3a\x14\x64\xd2\x6e\xa8\x0c\x4a\x72\x0b\x82\x4a\x10\xae\xaf\xaa\xcf\xe1\x52\x1c\x3d\xd0\xa9\x4d\xf4\x8c\xfd\x02\x04\x87\xec\x73\x21\x6c\xc7\x3d\x11\xde\x4a\xac\xc4\x74\x9f\x05\xc5\x82\xf6\xbe\x40\x85\xca\xf1\x18\x6e\x42\x7b\xa4\xa9\xf3\x4e\x99\xa0\xe7\x36\x19\xa1\xa0\x18\x04\x8a\x56\xa8\x05\x37\xc5\xd3\x0d\x90\x8e\x28\x6a\xe7\x07\xc9\x62\x08\xeb\x42\x6a\x01\x89\xef\xb9\x22\x1d\x4a\xe2\xc1\x92\x36\x83\xe1\x81\xb9\x07\xf7\x66\x10\xf1\xf5\xc0\xc0\x5b\x30\xb6\x46\x6f\x60\x10\xde\x0d\xfe\xb7\xfc\x72\x16\x74\x31\xcf\x43\x63\x8d\xfa\x7d\x4f\x24\x3c\x6b\x4b\x47\xf3\x17\x49\x74\x8c\xf7\x81\xe6\x51\x98\x56\x39\x31\x27\x47\x26\x14\x59\xf6\xc5\x1a\x62\x57\x75\x0c\x13\x8a\x52\x0e\x6b\xe5\x8b\x6e\xed\xf2\x92\x76\xce\x7b\xf8\x19\xbf\xee\x0a\xa1\xb2\xe2\x43\xc3\x76\xf4\xc1\xad\x14\x11\x23\x1b\x6e\x87\x40\xc6\xa9\xac\x68\x98\x95\x22\x37\x16\xd2\x62\xf9\x68\x86\x13\x99\xb4\x97\x41\xfb\xa5\xb3\x97\x3b\xe9\x13\x82\xde\xbc\xbf\x6f\x7a\xe8\xd8\x3a\x53\x23\xe8\x19\x00\xef\x09\xde\x3b\x1d\x5c\xc0\xd4\xed\x76\x53\x3b\x5f\xb5\xfa\xf0\x6d\x8b\x11\x5a\xc6\xc6\x83\xfa\x30\x7c\x1e\x02\x7b\xc1\xdf\x71\x76\x77\xdc\xb6\x99\xc5\x15\x2a\x8d\x33\xdd\xb4\x48\x31\xd9\xa6\x06\x69\xcb\xfc\x75\x74\x1b\x3a\x87\xe5\xbd\xcb\xae\xfe\x85\x97\x94\x55\xd1\x65\x7b\x2c\x94\xf3\xcf\x2c\xeb\x5f\x7d\x49\x27\xc3\xfe\xc9\xa1\x61\xd5\x5c\xd9\xf5\xc9\x3c\x7b\xad\x0d\x7b\xf0\xaa\xa4\xe4\x0d\x8d\x31\xfc\x96\x2c\xe5\xf1\xb6\xc1\x1a\x6a\x62\x33\xa0\xbf\xf5\x05\xbd\x08\x28\xed\x71\x41\xa5\x22\x63\x6e\x5d\x89\x7e\x0a\x39\x7a\x1a\x09\x67\xbd\xd4\xf0\x31\x5c\x6a\xbc\xaa\x0a\xd6\xc8\x62\x8d\x19\xe5\x7f\x05\x21\x4b\x62\xc6\xc5\xe5\xd2\xdd\x40\x51\x97\x28\xd1\x85\x79\x88\xa3\x44\x08\x94\xc9\x55\x86\xe1\x3a\x2a\x27\x8f\x4a\x33\xe0\xcc\xd6\x31\xfa\x76\xe6\x7f\x75\x0b\x3b\x42\x3e\x87\xb2\x47\xe4\x88\x29\x5f\xb6\x8a\xf2\xba\xa6\xba\xe6\xe0\x03\xdf\x92\xeb\xe3\xd7\x3b\x67\xb9\x4e\x57\x3d\x5b\xb0\x4d\x0c\x0f\x43\x34\xd9\x39\x3c\xb9\x9a\x86\xf0\x0b\x6a\xa6\x21\x7c\x34\x4b\x63\xd7\xaf\xcf\x7b\x58\x7c\xb1\xbe\x37\x55\xe0\x70\xcb\xf3\x2b\xb2\x15\x0a\xc2\xf7\xe8\x8b\x0b\xd2\xda\xf5\x7d\xaa\x85\x42\x2d\x1f\xaa\x88\x4a\x51\x46\x9d\xcb\x69\x50\x86\x3d\x61\x9e\x26\xc9\x78\xe5\x28\xbd\x1b\xc6\x9b\xd3\xd4\xc1\xec\x2e\xaf\xa5\xbe\x04\x94\xb2\x53\xe5\xf0\x8f\xc7\x77\x0f\x93\xbf\xdb\x54\xb2\x62\x96\x11\xa7\xd4\x22\x75\xe6\x10\xb8\xce\x0a\x40\x6e\xae\x0b\x1f\x43\xd2\x29\xd1\xa8\x39\xb1\x1f\x27\x6a\xe4\xf8\xb7\x37\xbf\x8f\xe1\x17\xeb\x80\x9e\xb1\xac\x34\x0d\x41\xa5\x36\xa7\xb9\xe2\x6d\x95\x47\x41\x98\xed\xde\x50\x09\x05\x96\x2a\x9b\x27\xa6\xd7\x81\x59\x8f\x4b\x02\x9b\x98\xad\x09\xb4\x5a\xd2\x14\x06\x5c\x51\xd6\x3a\xfa\xb3\xc1\x92\xbe\x0c\xe0\xfb\x75\x41\x8e\x60\x20\x8f\x83\x78\xe0\xb6\x84\x94\xb9\x96\x53\xa6\x83\x63\x1f\xee\xd4\x62\x41\x8e\x62\x31\x4e\x2b\x32\xfe\x07\xe9\xc4\xd4\x1c\x8c\x6d\x2d\x0e\x24\x44\x9f\x15\x65\x6a\xae\x28\x3f\x60\xe4\xb7\x37\xbf\x0f\xe0\xfb\xae\x5c\x82\x3a\xf4\x0c\x6f\x62\x97\xa1\x58\x64\xfc\x21\x35\x6e\xbc\x31\x1e\x9f\x85\x66\x26\xad\x83\x89\x35\xbf\xb7\x50\xe0\x8a\x80\x6d\x49\xb0\x26\xad\x47\xf1\xde\x34\x87\x75\x6c\x49\x1b\x55\xc6\x16\xaf\x42\xe7\xf7\xbe\x57\x3c\xbd\xbb\x7b\x37\x8d\xa7\x89\xd9\x16\x46\x8e\x30\xd6\xc3\x5c\x19\xd4\xa9\xef\x50\xbc\x6b\x53\xb8\x8e\x46\xf2\x16\xb2\x02\x4d\xc0\xca\xa0\x8d\x79\xed\x6b\x47\xe3\xfd\xfb\xeb\xaf\x8a\x81\x63\x1f\x12\x4e\xb9\x7f\xf8\xac\xb0\x5f\x64\xfe\x1f\x2f\xed\xbf\x4a\xe8\xf0\x5d\xed\x02\xa1\x1f\x5a\x7e\x7a\x52\xe8\x65\x3d\x23\x67\xc8\x53\x90\x3b\xb7\x19\x8b\xc8\x19\x55\x9e\x27\x76\x45\x6e\xa5\x68\x3d\x59\x5b\xb7\x54\x66\x31\x12\x47\x1c\x45\xef\xe0\x49\xf8\x16\x39\xf9\x2e\xfc\xbc\x9a\x8c\x5c\x61\x76\xb1\xa0\x61\xd3\x9f\x21\xad\x9c\xc3\x93\x57\x11\xb6\x69\xe4\x2e\xef\x9d\xae\x1f\x23\x70\x64\xfb\x34\x24\xec\xd6\x85\xca\x8a\xe6\x53\x64\x0b\x29\x4b\xcc\x23\x94\xa2\xd9\x7c\x73\xe7\x17\x95\xd6\x4e\xce\xde\x8c\xd2\x67\xf4\x11\x9a\x5c\xfe\xb3\x62\x2f\xf3\xaf\xa2\xc3\x5a\x5d\x04\x04\x1f\xef\xef\xfe\x9c\x90\xa8\xd5\x57\x44\x7d\xfc\x8c\x35\x05\xef\xea\xa6\xa6\x65\x6f\x9d\x54\xae\x9d\xb9\x7a\xb6\xbd\xb1\xd8\x09\x9f\x8a\x2c\xf8\xfc\xe5\xea\xbf\x01\x00\x00\xff\xff\x7e\x2b\xf8\xdd\x18\x21\x00\x00") +var _operatorsCoreosCom_operatorsYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\x59\x5f\x73\xe3\xb6\x11\x7f\xf7\xa7\xd8\x51\x1e\x9c\xcc\xe8\x4f\x72\x7d\x69\xf5\xe6\xb1\x2f\x1d\xb7\xa9\xef\xe6\xec\xbb\x97\x4c\x1e\x56\xe4\x4a\x44\x05\x02\x0c\x16\x94\xac\xde\xdc\x77\xef\x2c\x00\x4a\xa4\x24\x4b\xd4\xd5\x97\x06\x2f\x12\x41\x60\xb1\x7f\x7f\xbb\x0b\x62\xa5\x3e\x91\x63\x65\xcd\x14\xb0\x52\xf4\xec\xc9\xc8\x13\x8f\x97\x7f\xe5\xb1\xb2\x93\xd5\x4f\x57\x4b\x65\xf2\x29\xdc\xd6\xec\x6d\xf9\x81\xd8\xd6\x2e\xa3\x3b\x9a\x2b\xa3\xbc\xb2\xe6\xaa\x24\x8f\x39\x7a\x9c\x5e\x01\xa0\x31\xd6\xa3\x4c\xb3\x3c\x02\x64\xd6\x78\x67\xb5\x26\x37\x5a\x90\x19\x2f\xeb\x19\xcd\x6a\xa5\x73\x72\x81\x78\x73\xf4\xea\xc7\xf1\xdf\xc6\x3f\x5e\x01\x64\x8e\xc2\xf6\x27\x55\x12\x7b\x2c\xab\x29\x98\x5a\xeb\x2b\x00\x83\x25\x4d\xc1\x56\xe4\xd0\x5b\xc7\xe3\xdd\xbf\xcc\x3a\xb2\xf2\x53\x5e\x71\x45\x99\x1c\xbc\x70\xb6\xae\xda\xab\x5b\x6b\x22\xa9\x86\x3f\xf4\xb4\xb0\x4e\x35\xcf\x00\x23\xb0\xba\x0c\xff\xa3\xdc\xef\x12\x8d\x30\xa5\x15\xfb\x7f\x76\xa6\x7f\x51\xec\xc3\xab\x4a\xd7\x0e\x75\xeb\xcc\x30\xcb\xca\x2c\x6a\x8d\x6e\x37\x7f\x05\xc0\x99\xad\x68\x0a\xb7\xba\x66\x4f\x32\x91\xf4\x90\x78\x18\x25\x59\x57\x3f\x25\x96\x38\x2b\xa8\xc4\x86\x41\x10\x52\xe6\xe6\xfd\xfd\xa7\xbf\x3c\xee\xbd\x00\xc8\x89\x33\xa7\x2a\x1f\xb4\xda\xf0\x08\x8e\x2a\x47\x4c\xc6\x33\x20\x64\xf1\xd8\x2d\x43\xe3\xd6\x76\xbf\x11\xc6\xec\xec\xdf\x94\xf9\xd6\x74\xe5\x64\xb1\x6f\x69\x29\x8e\x96\xf7\x74\xe6\xf7\xf8\xb8\x16\x66\xe3\x3a\xc8\xc5\x71\x88\xc1\x17\xd4\x88\x4d\x79\x92\x10\xec\x1c\x7c\xa1\x78\xc7\x6f\xf0\x05\x99\x46\x93\xb8\x1a\xc3\x23\x39\xd9\x08\x5c\xd8\x5a\xe7\xe2\x61\x2b\x72\x1e\x1c\x65\x76\x61\xd4\x7f\xb6\xd4\x18\xbc\x0d\xc7\x68\xf4\xc4\x1e\x94\xf1\xe4\x0c\x6a\x58\xa1\xae\x69\x08\x68\x72\x28\x71\x03\x8e\x84\x2e\xd4\xa6\x45\x21\x2c\xe1\x31\xfc\xcb\x3a\x02\x65\xe6\x76\x0a\x85\xf7\x15\x4f\x27\x93\x85\xf2\x4d\x6c\x64\xb6\x2c\x6b\xa3\xfc\x66\x12\xdc\x5c\xcd\x6a\xb1\xfb\x24\xa7\x15\xe9\x09\xab\xc5\x08\x5d\x56\x28\x4f\x99\xaf\x1d\x4d\xb0\x52\xa3\xc0\xac\x09\xf1\x31\x2e\xf3\xef\x5c\x8a\x26\xbe\xde\x53\x5f\xb4\x03\x7b\xa7\xcc\xa2\xf3\x2a\xf8\xe4\x49\x5d\x8b\x7b\x82\x12\x43\xc7\xed\x51\x96\x9d\x4a\x65\x4a\xb4\xf2\xe1\xed\xe3\x13\x34\x0c\x44\xb5\x47\x0d\xb7\xbc\x65\xa7\x6c\x51\x94\x32\x73\x72\x71\xe5\xdc\xd9\x32\x50\x21\x93\x57\x56\x19\x1f\x1e\x32\xad\xc8\x78\xe0\x7a\x56\x2a\x2f\x56\xfc\xbd\x26\xf6\x62\x87\x31\xdc\x06\x68\x80\x19\x41\x5d\xe5\xe8\x29\x1f\xc3\xbd\x81\x5b\x2c\x49\xdf\x22\xd3\x37\x57\xb5\x68\x94\x47\xa2\xbe\xfe\xca\x6e\x23\xdb\xe1\x86\x83\x28\x01\x68\xe0\xe7\x45\xeb\x34\x11\xf9\x58\x51\xd6\x09\x85\x9c\x58\x39\x71\x5d\x8f\x9e\xc4\xe1\x3b\xb0\xd3\xe7\x68\x8f\xbe\xe6\x7e\x87\x87\xa5\x9d\xe3\xed\x8c\xc5\xd0\xad\xf3\xd1\xec\xe0\x43\x22\x45\x0c\x9a\xd9\xb2\xb2\x46\x1c\xa3\x2f\x57\x2f\x43\x07\x84\xe4\xd0\xd0\x3b\x7c\xb7\xc7\xfb\xed\x76\x69\x9a\x9f\x11\x6f\xbd\x57\x64\x40\x1f\xc9\x31\x45\x81\x8e\x80\x5b\x0f\x6e\x65\x88\xdb\x8a\x2d\x8e\xf1\x24\xe0\xac\x71\x46\xfa\x91\x34\x65\x87\xe6\x39\x27\xb1\x8c\xce\xfe\xe3\x4b\xf6\x84\xff\xa5\xbd\x23\xc6\x76\x20\x02\xbf\xd7\xe4\x36\x60\x57\xe4\x24\xdc\xc9\x8b\xe1\x76\x4a\xa9\x99\x72\xc1\x40\x0e\x3b\x3b\x6a\xb9\x3e\x61\xcc\x9e\x6a\xea\x23\xaa\x8c\x12\x7d\x56\xbc\x7d\x16\x48\x69\xe5\xb8\x1e\x52\xef\x6f\x4c\x82\x2b\x0e\x62\x46\x05\x70\xa3\x94\x64\xb4\x32\xa2\xd6\x53\x41\x9d\x19\x40\x47\x70\xf3\x70\x47\xf9\x31\x7f\xe8\x0a\x8c\xce\xe1\xe6\xc4\x2a\xe5\xa9\x3c\x29\xc4\x9e\x18\x37\x27\x58\x4d\x38\xdd\xbc\x49\x5e\x6c\x3c\x2a\xc3\x29\x07\x0d\x01\x61\x49\x9b\x98\xae\x24\x0b\x36\x41\x19\x16\x3b\x0a\xc9\x2d\xd8\x76\x49\x9b\xb0\x28\xe5\xae\x93\x1c\xf6\xb0\x6d\x1c\xa7\x83\x61\x37\x46\x72\xfc\xd9\x35\xf6\x38\xa8\x75\x47\x1f\xa7\x8a\x63\x49\x9b\x73\x4b\xf6\x8c\x21\x3a\x52\x9c\xaa\x02\xb1\x8a\x4c\x04\x4d\xca\xd4\xd6\x10\x58\x55\x5a\x51\x48\x5c\x67\xe9\xbf\x98\x3d\x0e\x47\x23\xfe\x85\x4c\xdb\xa3\x65\xdc\x92\x36\xd7\x1c\x1d\x40\xa2\xa3\x50\x95\xc4\xfa\x16\x06\x9a\x0a\xe6\x13\x6a\x95\xef\x8a\xd2\x10\x09\xf7\x66\x08\x0f\xd6\xcb\xcf\xdb\x67\x25\x19\x5a\xfc\xe6\xce\x12\x3f\x58\x1f\x66\x5e\x55\xec\xc8\xca\x85\x42\xc7\x4d\x21\x40\x4c\x8c\x49\x91\xaa\x5d\xd2\xf0\x18\xee\xe7\x1d\x54\x93\xd5\xf7\x06\xac\x6b\xa4\x0b\x45\x66\x24\x14\x49\x94\x35\x87\x1a\xc4\x58\x33\xa2\xb2\xf2\x9b\xa3\x34\x92\x52\xac\xeb\xe8\xe4\x04\xb9\x44\xea\x49\x4a\xa3\xf8\x26\x16\xb1\x1a\x33\xca\x21\xaf\x03\xd3\xa1\x20\x93\x76\x43\x65\x50\x92\x5b\x10\x54\x82\x70\x7d\x55\x7d\x0e\x97\xe2\xe8\x81\x4e\x6d\xa2\x67\xec\x17\x20\x38\x64\x9f\x0b\x61\x3b\xee\x89\xf0\x56\x62\x25\xa6\xfb\x2c\x28\x16\xb4\xf7\x05\x2a\x54\x8e\xc7\x70\x13\xda\x23\x4d\x9d\x77\xca\x04\x3d\xb7\xc9\x08\x05\xc5\x20\x50\xb4\x42\x2d\xb8\x29\x9e\x6e\x80\x74\x44\x51\x3b\x3f\x48\x16\x43\x58\x17\x52\x0b\x48\x7c\xcf\x15\xe9\x50\x12\x0f\x96\xb4\x19\x0c\x0f\xcc\x3d\xb8\x37\x83\x88\xaf\x07\x06\xde\x82\xb1\x35\x7a\x03\x83\xf0\x6e\xf0\xbf\xe5\x97\xb3\xa0\x8b\x79\x1e\x1a\x6b\xd4\xef\x7b\x22\xe1\x59\x5b\x3a\x9a\xbf\x48\xa2\x63\xbc\x0f\x34\x8f\xc2\xb4\xca\x89\x39\x39\x32\xa1\xc8\xb2\x2f\xd6\x10\xbb\xaa\x63\x98\x50\x94\x72\x58\x2b\x5f\x74\x6b\x97\x97\xb4\x73\xde\xc3\xcf\xf8\x75\x57\x08\x95\x15\x1f\x1a\xb6\xa3\x0f\x6e\xa5\x88\x18\xd9\x70\x3b\x04\x32\x4e\x65\x45\xc3\xac\x14\xb9\xb1\x90\x16\xcb\x47\x33\x9c\xc8\xa4\xbd\x0c\xda\x2f\x9d\xbd\xdc\x49\x9f\x10\xf4\xe6\xfd\x7d\xd3\x43\xc7\xd6\x99\x1a\x41\xcf\x00\x78\x4f\xf0\xde\xe9\xe0\x02\xa6\x6e\xb7\x9b\xda\xf9\xaa\xd5\x87\x6f\x5b\x8c\xd0\x32\x36\x1e\xd4\x87\xe1\xf3\x10\xd8\x0b\xfe\x8e\xb3\xbb\xe3\xb6\xcd\x2c\xae\x50\x69\x9c\xe9\xa6\x45\x8a\xc9\x36\x35\x48\x5b\xe6\xaf\xa3\xdb\xd0\x39\x2c\xef\x5d\x76\xf5\x2f\xbc\xa4\xac\x8a\x2e\xdb\x63\xa1\x9c\x7f\x66\x59\xff\xea\x4b\x3a\x19\xf6\x4f\x0e\x0d\xab\xe6\xca\xae\x4f\xe6\xd9\x6b\x6d\xd8\x83\x57\x25\x25\x6f\x68\x8c\xe1\xb7\x64\x29\x8f\xb7\x0d\xd6\x50\x13\x9b\x01\xfd\xad\x2f\xe8\x45\x40\x69\x8f\x0b\x2a\x15\x19\x73\xeb\x4a\xf4\x53\xc8\xd1\xd3\x48\x38\xeb\xa5\x86\x8f\xe1\x52\xe3\x55\x55\xb0\x46\x16\x6b\xcc\x28\xff\x33\x08\x59\x12\x33\x2e\x2e\x97\xee\x06\x8a\xba\x44\x89\x2e\xcc\x43\x1c\x25\x42\xa0\x4c\xae\x32\x0c\xd7\x51\x39\x79\x54\x9a\x01\x67\xb6\x8e\xd1\xb7\x33\xff\xab\x5b\xd8\x11\xf2\x39\x94\x3d\x22\x47\x4c\xf9\xb2\x55\x94\xd7\x35\xd5\x35\x07\x1f\xf8\x96\x5c\x1f\xbf\xde\x39\xcb\x75\xba\xea\xd9\x82\x6d\x62\x78\x18\xa2\xc9\xce\xe1\xc9\xd5\x34\x84\x9f\x51\x33\x0d\xe1\xa3\x59\x1a\xbb\x7e\x7d\xde\xc3\xe2\x8b\xf5\xbd\xa9\x02\x87\x5b\x9e\x5f\x91\xad\x50\x10\xbe\x47\x5f\x5c\x90\xd6\xae\xef\x53\x2d\x14\x6a\xf9\x50\x45\x54\x8a\x32\xea\x5c\x4e\x83\x32\xec\x09\xf3\x34\x49\xc6\x2b\x47\xe9\xdd\x30\xde\x9c\xa6\x0e\x66\x77\x79\x2d\xf5\x25\xa0\x94\x9d\x2a\x87\x7f\x3c\xbe\x7b\x98\xfc\xdd\xa6\x92\x15\xb3\x8c\x38\xa5\x16\xa9\x33\x87\xc0\x75\x56\x00\x72\x73\x5d\xf8\x18\x92\x4e\x89\x46\xcd\x89\xfd\x38\x51\x23\xc7\xbf\xbe\xf9\x6d\x0c\x3f\x5b\x07\xf4\x8c\x65\xa5\x69\x08\x2a\xb5\x39\xcd\x15\x6f\xab\x3c\x0a\xc2\x6c\xf7\x86\x4a\x28\xb0\x54\xd9\x3c\x31\xbd\x0e\xcc\x7a\x5c\x12\xd8\xc4\x6c\x4d\xa0\xd5\x92\xa6\x30\xe0\x8a\xb2\xd6\xd1\x9f\x0d\x96\xf4\x65\x00\xdf\xaf\x0b\x72\x04\x03\x79\x1c\xc4\x03\xb7\x25\xa4\xcc\xb5\x9c\x32\x1d\x1c\xfb\x70\xa7\x16\x0b\x72\x14\x8b\x71\x5a\x91\xf1\x3f\x48\x27\xa6\xe6\x60\x6c\x6b\x71\x20\x21\xfa\xac\x28\x53\x73\x45\xf9\x01\x23\xbf\xbe\xf9\x6d\x00\xdf\x77\xe5\x12\xd4\xa1\x67\x78\x13\xbb\x0c\xc5\x22\xe3\x0f\xa9\x71\xe3\x8d\xf1\xf8\x2c\x34\x33\x69\x1d\x4c\xac\xf9\xbd\x85\x02\x57\x04\x6c\x4b\x82\x35\x69\x3d\x8a\xf7\xa6\x39\xac\x63\x4b\xda\xa8\x32\xb6\x78\x15\x3a\xbf\xf7\xbd\xe2\xe9\xdd\xdd\xbb\x69\x3c\x4d\xcc\xb6\x30\x72\x84\xb1\x1e\xe6\xca\xa0\x4e\x7d\x87\xe2\x5d\x9b\xc2\x75\x34\x92\xb7\x90\x15\x68\x02\x56\x06\x6d\xcc\x6b\x5f\x3b\x1a\xef\xdf\x5f\x7f\x55\x0c\x1c\xfb\x90\x70\xca\xfd\xc3\x67\x85\xfd\x22\xf3\xff\x78\x69\xff\x55\x42\x87\xef\x6a\x17\x08\xfd\xd0\xf2\xd3\x93\x42\x2f\xeb\x19\x39\x43\x9e\x82\xdc\xb9\xcd\x58\x44\xce\xa8\xf2\x3c\xb1\x2b\x72\x2b\x45\xeb\xc9\xda\xba\xa5\x32\x8b\x91\x38\xe2\x28\x7a\x07\x4f\xc2\xb7\xc8\xc9\x77\xe1\xe7\xd5\x64\xe4\x0a\xb3\x8b\x05\x0d\x9b\xfe\x08\x69\xe5\x1c\x9e\xbc\x8a\xb0\x4d\x23\x77\x79\xef\x74\xfd\x18\x81\x23\xdb\xa7\x21\x61\xb7\x2e\x54\x56\x34\x9f\x22\x5b\x48\x59\x62\x1e\xa1\x14\xcd\xe6\x9b\x3b\xbf\xa8\xb4\x76\x72\xf6\x66\x94\x3e\xa3\x8f\xd0\xe4\xf2\x9f\x15\x7b\x99\x7f\x15\x1d\xd6\xea\x22\x20\xf8\x78\x7f\xf7\xc7\x84\x44\xad\xbe\x22\xea\xe3\x67\xac\x29\x78\x57\x37\x35\x2d\x7b\xeb\xa4\x72\xed\xcc\xd5\xb3\xed\x8d\xc5\x4e\xf8\x54\x64\xc1\xe7\x2f\x57\xff\x0d\x00\x00\xff\xff\x08\x9c\x4f\xa3\x18\x21\x00\x00") func operatorsCoreosCom_operatorsYamlBytes() ([]byte, error) { return bindataRead( @@ -225,7 +225,7 @@ func operatorsCoreosCom_operatorsYaml() (*asset, error) { return a, nil } -var _operatorsCoreosCom_subscriptionsYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xbd\x7b\x73\xe3\xb8\x95\x38\xfa\xff\x7c\x0a\x94\x93\x2a\xdb\x59\x49\xee\xce\xe6\x97\xe4\xf6\xa6\xb2\xe5\xb1\xdd\x13\xff\xa6\xbb\xc7\xdb\x76\xcf\xd4\xde\x6c\xee\x06\x22\x21\x09\x31\x09\x70\x00\x50\x6e\xe5\xf1\xdd\x6f\xe1\x1c\x00\x04\xa9\x17\x29\xc9\x8f\x9e\x21\xff\x98\x69\x53\x00\x08\x1c\x1c\x9c\x17\xce\x83\x16\xfc\x7b\xa6\x34\x97\xe2\x0d\xa1\x05\x67\x9f\x0d\x13\xf6\x2f\x3d\xba\xff\xbd\x1e\x71\x79\x36\x7f\xfd\xd5\x3d\x17\xe9\x1b\x72\x51\x6a\x23\xf3\x8f\x4c\xcb\x52\x25\xec\x92\x4d\xb8\xe0\x86\x4b\xf1\x55\xce\x0c\x4d\xa9\xa1\x6f\xbe\x22\x84\x0a\x21\x0d\xb5\xaf\xb5\xfd\x93\x90\x44\x0a\xa3\x64\x96\x31\x35\x9c\x32\x31\xba\x2f\xc7\x6c\x5c\xf2\x2c\x65\x0a\x06\xf7\x9f\x9e\xbf\x1a\xfd\x7e\xf4\xea\x2b\x42\x12\xc5\xa0\xfb\x1d\xcf\x99\x36\x34\x2f\xde\x10\x51\x66\xd9\x57\x84\x08\x9a\xb3\x37\x44\x97\x63\x9d\x28\x5e\xc0\x27\x46\xb2\x60\x8a\x1a\xa9\xf4\x28\x91\x8a\x49\xfb\xbf\xfc\x2b\x5d\xb0\xc4\x7e\x7c\xaa\x64\x59\xbc\x21\x2b\xdb\xe0\x70\x7e\x8e\xd4\xb0\xa9\x54\xdc\xff\x4d\xc8\x90\xc8\x2c\x87\x7f\xe3\xda\x6f\xa3\xaf\xc2\xeb\x8c\x6b\xf3\xed\xd2\x4f\xef\xb8\x36\xf0\x73\x91\x95\x8a\x66\x8d\xd9\xc2\x2f\x7a\x26\x95\xf9\x50\x7d\xdb\x7e\x4b\x97\xe3\xf8\xdf\xae\x21\x17\xd3\x32\xa3\xaa\x3e\xc8\x57\x84\xe8\x44\x16\xec\x0d\x81\x31\x0a\x9a\xb0\xf4\x2b\x42\x1c\x1c\xdd\x98\x43\x42\xd3\x14\xf6\x86\x66\x37\x8a\x0b\xc3\xd4\x85\xcc\xca\x5c\x84\x6f\xda\x36\x29\x0b\xa3\xbe\x21\x77\x33\x46\x0a\x9a\xdc\xd3\x29\xf3\xdf\x1b\xb3\x94\x18\x19\x3a\x10\xf2\x37\x2d\xc5\x0d\x35\xb3\x37\x64\x64\x41\x3c\xb2\x10\x8c\x7e\xc6\xfd\xb9\xc1\x41\xa2\xf7\x66\x61\xa7\xab\x8d\xe2\x62\xba\xe9\xf3\x09\x35\x34\x93\x53\x82\xf8\x45\x26\x52\x11\x33\x63\xc4\x7e\x8a\x4f\x38\x4b\xfd\xfc\x36\xcc\x08\xbb\x2e\xcd\xe9\xb6\xf9\xba\xf5\x94\x66\x54\x08\x96\x11\x39\x21\x65\x91\x52\xc3\x34\x31\xb2\x82\xcf\x66\xf0\xb8\xce\x4b\xb3\xb9\x58\x7a\xbf\x62\x3a\xd8\x74\xfe\x9a\x66\xc5\x8c\xbe\x76\x2f\x75\x32\x63\x39\xad\xf6\x50\x16\x4c\x9c\xdf\x5c\x7f\xff\xef\xb7\x8d\x1f\x48\x7d\x29\x31\x8a\x92\x7b\xc6\x0a\x5d\x1d\x0a\x52\x16\x76\x4d\x76\x71\x64\xbc\x20\x46\xd1\xe4\x9e\x8b\x29\x2c\x7d\x8a\xeb\xbd\xc0\x8d\xd1\xa3\xa5\x29\xcb\xf1\xdf\x58\x62\xa2\xd7\x8a\xfd\x58\x72\xc5\xd2\x78\x2a\x16\xb2\x9e\x44\x34\x5e\x5b\x38\x45\xaf\x0a\x65\xa7\x65\xa2\x73\x88\x4f\x44\xa3\x6a\xef\x1b\xcb\x3c\xb6\xb0\xc0\x76\x24\xb5\xe4\xc9\x4e\x7f\xc6\xfc\xe1\x60\xa9\x03\xa0\xdd\x4e\x33\xe3\x9a\x28\x56\x28\xa6\x99\x40\x82\x65\x5f\x53\xe1\xd6\x34\x22\xb7\x4c\xd9\x8e\xf6\xc0\x96\x59\x6a\xe9\xd8\x9c\x29\x43\x14\x4b\xe4\x54\xf0\xbf\x87\xd1\x00\x44\xf6\x33\x99\xc5\x0f\x43\xe0\xb8\x09\x9a\x91\x39\xcd\x4a\x36\x20\x54\xa4\x24\xa7\x0b\xa2\x98\x1d\x97\x94\x22\x1a\x01\x9a\xe8\x11\x79\x2f\x15\x23\x5c\x4c\xe4\x1b\x32\x33\xa6\xd0\x6f\xce\xce\xa6\xdc\x78\x0a\x9c\xc8\x3c\x2f\x05\x37\x8b\x33\x20\xa6\x7c\x5c\xda\x8d\x3b\x4b\xd9\x9c\x65\x67\x9a\x4f\x87\x54\x25\x33\x6e\x58\x62\x4a\xc5\xce\x68\xc1\x87\x30\x59\x81\x24\x32\x4f\x7f\xa1\x1c\xcd\xd6\xc7\x0d\xf0\xad\x3c\x07\xc4\x53\xbd\x8d\xb0\xb6\xc4\x8f\x70\x4d\xa8\xeb\x8e\x6b\xa9\x40\x6a\x5f\x59\xa8\x7c\xbc\xba\xbd\x23\x7e\x02\x08\x76\x84\x70\xd5\x54\x57\xc0\xb6\x80\xe2\x62\xc2\x14\xb6\x9c\x28\x99\xc3\x28\x4c\xa4\x85\xe4\xc2\xc0\x1f\x49\xc6\x99\x30\xf6\x18\xe6\xdc\x68\xc0\x39\xa6\x8d\xdd\x87\x11\xb9\x00\x06\x44\xc6\xcc\x1d\xd8\x74\x44\xae\x05\xb9\xa0\x39\xcb\x2e\xa8\x66\x8f\x0e\x6a\x0b\x51\x3d\xb4\xe0\x6b\x0f\xec\x98\x7f\x2e\x77\x58\x3a\x63\x84\x78\x06\xb7\x76\x77\xe2\x03\x7f\x5b\xb0\x24\x1c\x07\x2a\xc8\x79\x51\x64\x3c\x41\x8c\x37\x33\x6a\x48\x42\x85\x85\x17\x17\xda\xd0\x2c\x03\x76\xd2\x6a\x16\xeb\x4e\x3b\x81\xa3\xdd\x60\x0e\xfe\xf5\x12\x85\xae\xff\x10\x98\x5a\xa3\xc5\x3a\xca\x60\x1f\x47\x67\x97\x7f\xd8\x00\x72\x82\x92\xc9\x84\x4f\x57\x75\x5b\x0b\xcb\x0b\xe8\x02\x32\x0d\xe5\x42\xbb\x21\x4a\x85\xd0\xac\x38\x95\xe5\x5d\xb4\xc6\xb7\x47\x6b\x67\xb7\x12\xb2\xdb\xd6\x6c\x1f\x3a\x01\x09\x6c\xb1\xfa\xd7\xc6\x2a\xae\x27\xd5\xf4\x06\x44\xce\x99\x52\x3c\x75\xf4\xb1\x90\xe9\xb1\x06\x6a\x96\x96\x19\xd0\x7e\x29\xb4\x51\x94\xc3\xd1\x14\x3c\xb3\x2b\x19\x52\x83\xe7\x81\x69\xf2\xc0\xb3\x8c\xfc\x4a\x48\xf3\xab\x30\x12\x0c\x24\x15\x9f\xf2\x40\xfa\x34\xe1\xc2\x8f\x0f\x1c\xd1\xb1\x74\xa9\x59\x63\xc0\x11\xf9\xa4\x19\x61\x79\x61\x16\x9e\x38\x9c\xfc\xe3\x5f\xa7\x96\xb0\x32\x45\x75\x34\x70\xad\x9f\x27\x9f\x6b\xd6\xbf\x05\xbc\x6d\x40\x6c\x1f\x21\x53\x76\xbe\x05\xd4\x4b\xe0\xbe\x64\x28\x21\x68\xe8\x1e\xb6\x2a\x06\xb2\x2a\x33\xa6\x83\x94\x63\x61\xb4\x61\xf0\x16\x6b\x69\xbb\x1e\x6c\xc7\x26\x4c\x29\x96\x5e\x96\xf6\x68\xdc\x86\x59\x5d\x4f\x85\x0c\xaf\xaf\x3e\xb3\xa4\x34\x2b\xb8\xee\xc6\xa5\x5b\xb9\xc9\x2d\x93\x29\x44\x15\xfc\x1c\x88\x4e\xee\x07\xbb\x5e\x60\x9c\x16\x3c\x1a\xe9\x90\xa6\x86\xeb\xc9\x02\xc0\x11\x00\xc6\x3e\x5b\x26\x01\xb2\x6d\x74\xbe\xac\xa0\x02\xfc\x81\xb3\x2c\x1d\x90\x71\x69\x08\x37\xc0\x3c\x92\x99\xb4\xf8\x45\x11\xee\x30\xee\x9c\x4b\x60\xcd\x44\x0a\x8b\x49\x24\xb7\x1c\x00\x44\x00\x16\x0f\x3f\x82\x99\x57\xdd\xb8\x26\xb9\xd4\xa6\x82\x95\x7d\x03\x58\x2e\x18\x79\xe0\x66\x06\x7f\x4c\xad\xba\x62\xd9\xbe\x2e\x73\x3b\xe8\x03\xe3\xd3\x99\xd1\x03\xc2\x47\x6c\x04\xbb\xcb\x68\x32\x8b\x86\xcd\x19\x33\x9a\xd0\x2c\xf3\x53\x88\x51\x02\xe9\x69\x6e\x79\x22\x39\x09\x4c\xd3\x31\xb8\x41\xa0\xb7\xcd\x5d\x5b\x09\xae\x01\x61\x26\x19\x9d\x0e\x48\x22\xf3\xc2\x9e\x16\x0a\x73\x1c\x2f\x08\x37\x56\xf6\x43\x06\xad\x64\x39\xc5\x95\xb0\xcc\x7d\xd8\x4b\x47\x00\x5c\x10\x5f\xac\x36\x21\xa6\xe4\x08\x17\x77\xe4\x05\x1e\x3b\x1c\xc7\x45\xc0\xfa\x72\x6a\x92\x99\xa3\x29\x89\x54\x8a\xe9\x42\x0a\xe8\x09\xbf\x5c\x55\x73\xfb\x8f\xd0\xe9\x44\x9f\x56\xc0\x9c\xf1\xe9\xcc\xc3\x92\x2a\xa4\x29\xf5\x3d\xd8\x74\x46\xaa\x73\x42\x95\xa2\x8b\x2d\x2d\xb9\x61\xf9\x96\x53\xb2\x84\xda\xe7\xc2\x11\xa9\x0a\x27\xa2\xdd\x33\x4c\xe5\x01\x06\xb0\xc1\x70\x5c\x35\xae\x8f\xe7\x96\xed\x72\xe3\x30\x84\xbc\x22\x27\x80\x22\xdc\x1c\x6b\x40\xd7\xa1\x2c\x4e\x47\xe4\x1c\xb4\xdd\x16\x1f\x10\x32\x8c\xef\x06\xb2\x1f\xd5\xb2\x1a\x6b\xeb\xda\x5a\x12\x15\x7c\xd6\xf3\xfa\xe5\x67\xe8\xe6\xcf\xc4\x0a\x56\xbf\xaa\x39\xc2\x64\x6b\xd3\xb6\xe4\xcd\xb7\xf6\x73\x68\xd3\xba\xb9\xd5\x88\xd2\x9a\x65\x2c\x31\x96\x46\x33\x95\x0f\x08\xd5\x5a\x26\xdc\x8a\x95\x15\xd2\xd6\x31\x1d\x57\xb2\x1d\xf6\xa4\x2b\xfc\x49\xe7\xf5\xdb\xa7\x79\xf0\xda\xf6\x5b\x82\x46\xc6\xb5\xb1\x94\xa1\x0e\x95\x1a\xc1\x1a\x2f\xe0\xd7\x63\x4d\x32\x3a\x66\xd9\x5a\xbe\xbc\xfc\xb4\x3f\xb5\xd5\xd3\xf2\xfc\xae\x5d\xd0\xda\x85\x38\xa5\x26\x6c\x3c\x88\xc8\x5e\xe0\x43\x89\x63\x40\x28\xb9\x67\x0b\xd4\xed\xac\xca\xe8\x94\x69\x6c\xac\x18\xb2\x1b\x8b\x1c\xf7\x6c\x01\x8d\x36\x4b\x2a\xeb\x61\xd2\x01\x39\xf0\xe9\x72\x4c\xab\x67\x68\x27\xda\xb1\x87\x5f\x74\x87\x6e\xdd\xf1\x17\x9f\x7b\xb6\x51\xf2\x5a\xf5\x2c\x89\x24\x80\x93\xb0\x1f\xb0\x49\xc0\xbf\xfc\x1e\x53\xab\x12\x81\xad\xa3\xcb\x0e\x91\x6d\x0a\xc6\xa6\xc7\x43\x6f\xaf\x75\x7d\x0c\x1a\x34\x22\xe4\xb1\x46\xe4\xb3\x27\x7d\xc6\xc1\xae\x63\x31\x19\x0e\xae\x37\x35\x7c\x4f\x33\x9e\x46\xe6\x1f\xcb\x67\xaf\xc5\x80\x7c\x90\xc6\xfe\xef\xea\x33\xd7\x56\x7c\xb9\x94\x4c\x7f\x90\x06\xfe\x1c\x91\x6f\x0c\xe2\xfa\xbb\x96\x94\xed\x00\x00\xc2\xf9\xee\x05\x9e\x73\x81\x34\xc5\x2e\x3f\x36\x52\xe8\x91\x55\x87\x40\x94\xf3\x07\x97\x6b\x72\x2d\xac\x70\xe8\xc0\x00\x66\x23\x54\x62\x70\x88\xbc\xd4\x60\x55\x10\x52\x0c\x41\x06\x58\x39\x06\x42\xcf\x8e\x13\xc3\x6f\xc3\x70\xeb\x87\xfa\xc6\xd8\x61\xde\xad\xed\x3c\xa3\x73\x10\xe9\xb8\x98\x66\x41\x78\x1b\x90\x87\x19\x4f\x66\x28\x75\x83\x4e\x6f\x98\x2a\x14\xb3\x0c\x8b\x82\xf6\x6f\xdf\x4c\x99\xb2\xc2\x2e\xf7\xe3\xa1\x25\x2c\xa3\x09\x4b\x49\x0a\xa2\x25\x5a\x75\xa8\x61\x53\x9e\x90\x9c\xa9\x29\x23\x85\xe5\x24\xbb\xed\x7e\x37\xc2\x8e\x4f\x67\xf2\x1e\x7f\xb0\x13\xba\x01\x8b\x7c\x6b\x65\xdd\x27\xe2\x8e\x20\x57\xf7\xdc\xb1\xe7\x8e\x8d\xa7\xe7\x8e\xe1\xe9\xb9\xe3\x96\xa7\xe7\x8e\x3d\x77\x7c\x74\xee\x88\xba\xec\x0e\xca\xf3\x0f\x68\xe2\x68\x6a\xcb\xc0\x69\xfd\xbd\x50\x5d\x6d\xb6\xfc\xe6\xd6\x11\x9c\x3b\x50\xb5\x9d\xed\x58\x51\x31\x65\xe4\xf5\xf0\xf5\xab\x57\x5d\x94\x6a\xb7\x91\xad\x7a\x4c\xa4\xca\xa9\x81\x3e\xff\xfe\xeb\x8d\x3d\xd6\xd9\xdf\x0e\x60\x35\x75\x38\x1e\x0c\x79\x35\xd9\x61\x8d\xe1\x13\xa8\x93\x90\x86\xe4\xcc\x10\x6a\x6a\xa6\x22\x9e\xb3\x81\x37\x2c\x23\xc2\xbb\x6b\x31\x6f\x81\x4d\x89\x14\xce\x8e\x67\x81\x3f\xda\x6d\x06\x09\xa3\x9a\x59\x4a\x3a\x66\x61\x16\x32\xb7\x5f\xe5\xc2\xf8\xe3\x62\xa7\xc0\x3c\x54\xc8\x09\x1b\x4d\x47\x24\x2d\xa1\x1b\x15\xee\x9e\xee\x14\x67\xab\x17\xda\xb0\x1c\x2c\xb9\x52\xc1\xff\xec\xb4\x8d\x5a\xc0\x5d\xc0\x9c\x09\x53\xd2\x2c\x5b\x10\x36\xe7\x89\x09\xeb\x83\x6b\x42\x6e\xd0\xd8\xde\xce\x44\xd8\x4a\x74\x68\x2f\x2e\x0c\x97\x30\x58\x6f\xe9\xd3\x85\xdb\x2f\x8d\xdd\xe6\x4c\x36\x78\x21\xae\x64\xb4\x56\x58\x35\x76\x5c\xb4\x81\xc3\x3f\x01\xb9\xbe\xfb\xb8\xdd\xe4\x4a\x3a\x53\xb2\x0e\xd4\xab\x29\x96\x96\x59\x66\x11\x03\xad\xb0\xcb\x0b\x58\x61\x1d\xc5\x25\xd5\x90\x19\x0d\xef\x68\x62\x3e\xff\x70\x69\xa1\x62\xdb\xdc\xc9\x42\x66\x72\xba\x88\x21\x0d\x2b\x03\xdb\xad\xeb\x8b\xb7\x7a\x28\x34\x58\xf4\xfb\xd0\xd8\x9a\xde\xf2\xd7\x5b\xfe\x7a\xdd\x66\xe9\xe9\x75\x9b\xf0\xf4\xba\xcd\x96\xa7\xd7\x6d\x7a\xdd\xa6\xb7\xfc\x91\x9e\x3b\x6e\x80\x49\xcf\x1d\x49\xcf\x1d\xd7\xae\xab\xe7\x8e\x1b\xc1\xd3\x73\xc7\x9e\x3b\xae\x7a\x0a\x99\xee\xe1\xe8\x58\xc8\x74\x83\x9f\x23\x5a\x7d\x12\x39\xcc\x64\x42\x8d\x73\x04\xb7\x5d\x9c\x9d\x4f\xd3\x1c\x0d\x51\x03\xf2\x77\x29\x18\x3a\xaf\xd9\xbd\x01\x73\x92\x34\x33\xa6\x6c\xf3\x13\x7d\xba\xd1\xb1\xa9\xf7\x93\xec\xfd\x24\x5f\xbc\x9f\xe4\x8c\x6a\xdc\x57\x24\x4a\xeb\xdd\x26\xa3\x03\x79\xc7\x54\xfe\x85\x7a\x4d\x5a\x74\x71\xdb\x0d\x21\x36\xd5\x96\xe2\xca\x53\x77\x5f\xc0\xd2\x9b\xfa\x7a\x9d\xbc\x0c\x8b\xa2\x69\xca\x52\x52\x30\x35\x44\x14\x91\x64\xc2\x45\xba\x62\xad\x1e\x3e\xcf\xea\xfd\x58\x5f\xc7\x33\xba\x40\xd6\x27\xb2\x83\xcd\x35\x36\x1c\xd7\x28\xfc\x8b\x70\x88\xec\x2a\xd5\x0f\x89\x71\x46\xde\x6f\x5b\xca\xf5\xdd\x45\x73\x10\xa8\xbd\x49\x78\x77\xbd\x12\xc4\xf2\x1f\x4b\xa6\x16\x10\x63\x51\x09\xac\x21\x98\xcb\xdd\x91\x71\x4d\x12\xaa\x91\x53\x74\x55\x2d\x3b\xaa\x51\xbb\xe9\x29\xbb\x5b\xa2\x49\x13\x2e\xcd\xa1\x50\x27\xf5\x3a\x38\xc2\x6c\xa5\x12\xbe\xe2\x16\xa0\xb2\xfe\x77\x9a\xcf\xae\xa2\xdb\x4e\x82\xdb\x4a\xa4\x78\xc1\xca\x39\xd9\x5d\x41\x27\x3b\x2b\xe9\x64\x27\x45\x9d\xec\xaa\xac\x93\x3d\x14\x76\xb2\x9b\xd2\x4e\x9a\xa8\x60\x77\xc8\x49\x59\x8f\xa3\xbf\x93\x7d\x54\x54\xb2\x87\x1e\x4f\x9a\x4b\x0d\x68\xaa\x1e\x4b\xa9\x07\x5c\xaf\xe9\xf5\x4f\x0d\xac\xdd\x74\x7a\xd2\x04\x95\x8f\xba\x03\x85\xf6\x0b\xd1\xf0\x9f\x44\xdd\x26\x7b\xa9\xdc\x64\x77\xb5\x9b\xec\x8e\x19\xc0\xea\xde\xc1\x75\xea\xbe\x0c\x13\x47\x41\x16\x91\xd3\xc2\x22\xc5\x3f\x2c\x27\x80\x7d\xf9\x17\x29\x28\x57\xda\xca\x77\xce\x66\x12\xff\xe6\xb4\xf3\x78\x18\x3b\x02\xd7\xc4\x92\xea\x39\xcd\x2c\xef\x41\x3f\x0e\xa7\x17\xd9\xd1\x9b\x6c\x7a\x40\x1e\x20\xea\xd3\x52\x29\xd4\x96\xb8\x26\x47\xf7\x6c\x71\x34\x58\x42\xa4\xa3\x6b\x71\x84\x3c\x6a\x09\x75\x02\x43\x93\x22\x5b\x90\x23\xf8\xed\xe8\xd0\x9c\x7d\x07\xc6\x15\x27\xdb\xd8\x95\x2f\xec\x80\x25\xc2\xc7\x4a\x1f\x5e\xd8\x44\x2e\x82\x17\x1b\xfe\x2b\xba\x62\x30\xe0\x6a\x11\x31\x97\xe0\x35\x02\x38\x06\xef\x53\xaf\xfc\x96\xc2\xa5\x56\x00\xdd\xb5\x1a\x0c\x99\xd4\xb2\x4b\x93\xdb\x78\x29\x98\x06\xc1\x8e\x05\x13\x51\xd4\x19\xda\x8e\xd0\x1d\xa4\xe2\x76\x22\x6d\x3a\x88\x54\x3d\x40\x46\xcc\x19\x15\x9a\x1c\x79\xdb\xd3\xb1\xae\x5a\x1c\x8d\xaa\xe8\xbe\x30\x22\x04\x21\xc7\x11\x7d\xd5\x80\xbd\xa4\xdd\x4b\xda\xbd\xa4\xdd\xa1\x57\x2f\x69\xaf\x7f\x7a\x49\xbb\xc3\xd3\x4b\xda\xbd\xa4\xbd\xe9\xc3\xbd\xa4\xdd\x4b\xda\xdb\x3f\xbe\x9b\xa4\xbd\xab\x9f\x50\x2c\xf7\xba\xcb\x39\xcc\x9c\x45\x0d\x4f\x2a\x1f\x22\xdf\x0a\xff\x75\x58\x79\x3b\x96\xa5\x57\x4b\xdb\xb1\x44\xbe\xa4\x5b\x8c\xb6\x88\xd6\x41\xf8\x5e\xea\xb9\x59\xea\x7e\x59\xbe\x50\x3b\xe0\x46\x74\xa1\xb0\x23\x72\xdc\xf9\xab\x70\x97\x69\x6e\xcc\xaa\x7b\xf2\x94\x9c\xf8\x1b\x97\x53\x0b\x7c\x21\x4d\xfd\x47\x61\xf8\xb0\x6a\x11\xee\x60\xe0\x7a\xb1\x16\x6f\x53\xbb\x96\x08\xb7\xee\xe1\xa6\xb8\xda\x4f\x4b\x42\x98\xaa\xcd\x81\x6b\x97\x40\x0c\xbc\x25\x54\x29\x84\x1d\x55\x0a\x7f\x7d\x8c\x34\x07\x13\xc0\x39\xcc\x43\x61\x09\xe6\x03\x12\x53\x05\xa5\xe8\xbe\x93\x1a\xcc\xb9\xe7\x5c\xf9\xa5\x70\x37\xa2\xf6\x8d\xbf\xf5\xf5\x48\x09\x2b\xe2\xe1\xeb\x23\x72\x05\x78\x18\x0f\xcc\x35\xc0\x87\x66\x99\x7c\xe8\x42\x92\x9e\x2a\x2c\xea\xa1\x73\x58\x54\xe3\xfe\xae\x8f\x8a\xfa\x99\x44\x45\xc1\x8f\x78\x84\x0e\x1e\x1e\x45\x7e\x98\x31\xc0\x22\xc5\x00\x54\x79\x99\x19\x5e\x54\xbe\x52\x1a\x3f\x95\xa1\x94\x39\x71\x9e\x27\x75\xbc\xb4\x5f\xa3\xc9\xac\x89\x9f\x30\x1e\xf8\x56\x69\x38\xb4\xce\xbb\x83\x66\x99\x8b\x29\xf2\x22\x29\xba\xb0\xf0\xe7\xf6\x4c\xb8\xf4\x59\x11\xbd\x36\x03\x44\xe6\xc4\xd2\xc2\x6c\xe1\x32\xd5\x6d\x20\xa2\xa8\x14\xcd\x99\x67\xbd\x53\x3e\x67\xa2\xa2\xa4\x27\xfa\xf4\xd4\xf3\xf0\x83\x52\xf8\x47\xa1\xd0\x7f\x88\x28\xe9\x1f\xdb\xd0\x68\x58\x50\xa0\xd2\x15\xf8\x2a\x1a\xfd\x9c\x2e\x18\x5d\xee\xf9\xbb\xd9\x18\x76\xb8\xdf\x7f\xc2\xbb\xfd\x2f\x27\xb2\xec\x99\x2d\x8c\xcf\xe1\x5b\xff\xe2\xad\x8a\xbd\x73\x7d\xf5\xec\xeb\x5c\xff\xe8\x96\xc3\xe7\xf5\xb1\xff\x02\xac\x85\xcf\xe9\x63\xdf\x5b\x08\x37\x6e\xca\x4b\x73\x7d\xaf\x3f\x3b\x59\x04\x7b\x6b\xe0\xce\x5c\xb8\x23\xc3\xd9\xd7\x0a\xd8\x11\x23\x76\xbc\x67\xef\xef\xd8\x9f\xe6\x8e\xbd\x97\x78\x5b\x3e\xbd\xc4\xbb\x16\x28\xbd\xc4\x4b\x7a\x89\x77\xdb\xf2\x7a\x89\x77\x23\x78\x7a\x89\x77\xe3\xa6\xf4\x12\x6f\x2f\xf1\x92\x2f\x4d\xe2\xdd\x25\x4b\x57\x7f\xd7\xbd\xd7\x5d\x77\x57\x6a\xd1\x89\x46\x74\xc4\x83\xce\x77\xdb\xfd\xbd\xf6\x4b\xb9\xd7\x6e\x1d\xf0\x2f\x0c\xdf\x37\xe8\x3f\xde\xab\x75\x91\xff\x74\x2e\x79\x4a\x8a\xd2\xb8\x78\xea\x3e\xfa\xff\x10\xd1\xff\x35\xc8\xf7\x29\x00\x5a\xa5\x00\x58\x07\xb3\x3e\x0f\x40\x9f\x07\xe0\xc0\x97\xd0\x7d\x1e\x80\x3e\x0f\x40\x9f\x07\xc0\x3f\x7d\x74\x12\xe9\xa3\x93\x5a\x3d\x7d\x74\xd2\xfa\xa7\x8f\x4e\x7a\xb1\xd6\x57\xd2\x47\x27\xbd\x6c\x4b\x2c\xe9\xa3\x93\x7a\xeb\x6c\xcb\x8d\xfa\x02\xa3\x93\xfa\x3c\x00\x2f\xd5\x47\x81\xf4\x92\x76\x2f\x69\xf7\x92\x76\x2f\x69\x6f\x7e\x7a\x49\xbb\xc3\xd3\x4b\xda\xbd\xa4\xbd\xe9\xc3\xbd\xa4\xdd\x4b\xda\xdb\x3f\xde\xe7\x01\xf8\x82\x7c\x23\x48\x9f\x07\xa0\xf7\x97\xe8\xf3\x00\xfc\x7c\xf3\x00\xd4\xee\xee\x9f\x2f\x19\x40\xf7\x69\xf4\x19\x01\xfa\x8c\x00\x7d\x46\x80\x3e\x23\x80\x7f\xfa\x8c\x00\xf8\xbc\x24\x5b\x63\x1f\x1f\xb5\x16\x28\x7d\x7c\x14\xe9\xe3\xa3\xb6\x2d\xef\x0b\xb0\x1b\xf6\xf1\x51\x2f\xd0\x56\xd8\xc7\x47\xf5\x76\xc1\xe6\xe6\x7c\x21\xf1\x51\x7d\x46\x80\x97\x78\xdb\xde\x4b\xbc\x2d\x9f\x5e\xe2\x5d\x0b\x94\x5e\xe2\x25\xbd\xc4\xbb\x6d\x79\xbd\xc4\xbb\x11\x3c\xbd\xc4\xbb\x71\x53\x7a\x89\xb7\x97\x78\xc9\x97\x26\xf1\xf6\x19\x01\xfa\x8c\x00\x7d\x46\x80\x2f\xf1\x86\x7b\xeb\x4e\x33\x31\x5f\xb7\xa7\xb5\x5d\xbc\x12\xf3\xba\x9e\xc2\xc4\x9c\x2b\x29\x80\x02\xcf\xa9\xe2\x74\x9c\xc1\x49\x05\x89\xc7\xc1\xdf\xd1\x4f\xa6\x46\xe4\x82\x0a\x77\xd1\x8a\x37\x99\x6b\xe7\xbf\x1d\xf1\xb7\xa0\x7a\x73\xda\xdf\xd3\xba\xa8\x26\x56\x4e\x9d\xb8\x06\x76\xea\x94\x5c\x84\x89\xaf\xfd\x4c\x2b\x02\xde\x46\x3f\x18\x02\x72\xae\x6d\xd0\x4e\x8a\xb7\x43\x6c\x3e\x9b\x35\xb0\x7c\xa0\x79\x15\xe2\xbf\x02\x1a\x23\xf2\xde\x49\x48\x94\x5c\xfc\xef\xf5\xe5\xd5\x87\xbb\xeb\xb7\xd7\x57\x1f\x37\x23\x5d\x4b\xb2\x02\x07\xa9\xc3\x64\x8f\xbf\xf7\x7b\x04\x61\xde\x4c\x58\x0a\xfc\xcb\x93\xef\xcf\x3f\xfe\xef\x87\xf3\xf7\x57\xa7\xc0\x7e\xd9\xe7\x82\x8a\x94\xa5\xa4\xd4\x9e\x24\x14\x8a\xcd\xb9\x2c\x75\xb6\x08\xc7\x7b\x35\xd2\x36\xb1\xd5\x29\x9a\x0b\xa2\x99\x9a\xf3\x64\x35\x88\x50\x8a\xa5\x15\x02\x25\x01\xc3\x15\xd3\x32\x9b\xb3\x14\x65\x8d\x30\x69\xff\x1d\x2e\x8a\xd2\x78\x89\x18\x5c\x10\xec\xa9\x10\xc9\x8c\x8a\x29\x4b\x47\xe4\x52\x96\x76\xbc\x5f\xfe\x12\x16\xa6\x58\x5a\x26\xc8\xeb\xa8\x17\x98\x7e\x39\xf0\x94\xc4\xd2\x02\x8d\x69\x14\x74\x42\x0b\xbf\xf4\x18\x3a\x7a\x21\x0c\xfd\xfc\x06\xef\xe0\x8f\x7e\x19\xfd\x74\xe4\x53\x50\x48\xfb\x09\xa4\x47\x38\xab\x0c\xb2\x1f\x64\xe4\x28\x6e\x3d\x22\x57\xf6\x1b\x2c\x8d\xf7\x01\x5d\x28\xd8\x9c\x29\x90\xa7\xdd\x2e\x0c\x88\x62\x53\xaa\xd2\x8c\x69\x70\x1e\x78\x98\x31\x48\xe7\x81\x12\x96\x03\x18\x0b\xd2\xba\x90\x66\x44\x2e\xd9\x84\x96\x99\x01\x1a\x72\x74\x34\x3a\x3e\x18\xaa\xbd\x55\x72\x4b\xf0\x7b\x0d\xdd\x6e\x31\xa9\xc4\x44\xaa\xb5\xc7\xe3\xd8\x99\x26\x6a\x64\x4d\x5b\x4e\xe2\x34\x3d\x4f\xab\x51\xbf\x68\xb1\x92\x16\x82\x60\x7b\x75\x3e\x91\x62\xc2\xa7\xef\x69\xf1\x2d\x5b\x7c\x64\x93\x8e\xde\x10\xc8\x44\x9d\x4e\x0b\x0c\xcc\x92\x43\x1c\x70\x3b\xd3\x79\xc4\xbb\xfc\x36\x46\x93\x6e\x36\x8f\xd6\x96\x8e\xa5\x94\x16\xc8\xf4\x1d\xfb\x3e\x60\x72\x9e\xea\xd9\x4e\xd1\x57\x4e\xee\x38\x26\xed\xee\x9c\x9a\x11\x79\x2f\xc1\x25\x67\x22\xdf\x90\x99\x31\x85\x7e\x73\x76\x76\x5f\x8e\x99\x12\xcc\x30\x3d\xe2\xf2\x2c\x95\x89\x3e\x4b\xa4\x48\x58\x61\xf4\x99\x9c\x5b\xca\xc7\x1e\xce\x1e\xa4\xba\xe7\x62\x3a\xb4\x92\xce\x10\x77\x55\x9f\x81\x30\x75\xf6\x0b\x94\xd8\xef\xbe\xbb\xfc\xee\x0d\x39\x4f\x53\x97\xb1\xa7\xd4\x6c\x52\x66\x2e\x7b\xc7\x88\xd0\x82\x7f\xcf\x94\x55\xca\x06\xe4\x9e\x8b\x74\x40\x4a\x9e\xfe\xe7\xe6\xc3\xbd\x23\xc4\x64\x81\xba\xd1\x0e\x50\xbb\x05\x41\x71\x51\xa3\x53\x01\xe9\x2d\x85\xe2\x46\xc3\x9e\x7b\xc3\x81\x63\x28\x1d\x96\x31\x96\x32\x63\x54\x6c\xe9\x01\x60\xeb\x7e\x66\x8f\xab\x43\x8b\x5a\x8e\x43\x80\x42\xa6\x6f\x88\x2e\x8b\x42\x2a\xa3\x49\xce\x0c\x4d\xa9\xa1\x23\xbb\x73\x83\xfa\x9f\x20\x1c\x0f\xc8\x5f\xc3\x4b\x90\x70\xf5\x9f\x8f\x8f\xff\xf0\xed\xd5\x7f\xff\xf1\xf8\xf8\x2f\x7f\x8d\x7f\x05\xb2\x87\xa6\xae\x7a\x13\x2b\x72\x8f\xac\xb8\xfb\x01\xbe\x01\x7f\x3a\x36\x7a\x9e\x24\xb2\x14\xc6\xfd\x60\xa8\x29\xf5\x68\x26\xb5\xb9\xbe\x09\x7f\x16\x32\x6d\xfe\xa5\xb7\x70\x02\xf2\xb8\x44\x07\xc0\x79\x43\xcd\xec\xc0\xa4\xa7\x3a\x17\x3b\xa0\xab\xeb\x19\x67\x48\xca\x29\xfc\xf3\xad\x9f\xae\xe5\x40\x0f\x8a\x1b\xc3\x04\xc8\x1d\xe0\x77\x27\x27\x03\x8b\xb9\x15\x9b\x9d\xbf\xee\xa4\x8e\xb6\x3e\x8a\x01\x6a\x3b\x2c\x0e\x66\xef\x56\x86\xc8\x1c\x08\xed\xb2\x5e\x77\x7e\x73\x4d\xe6\x08\x8d\x83\x2f\xc4\x7b\x61\xbd\xdd\xfb\x4c\x86\x4c\x55\x6e\x59\x41\xd2\x7c\x83\x96\xa5\xe0\xef\x45\x32\x9e\x73\x67\x00\x76\x59\xad\x34\x39\xc1\x97\xa3\xa4\x28\x07\xae\xc1\x28\x67\xb9\x54\x8b\xf0\x27\x2b\x66\x2c\xb7\x12\xdb\x50\x1b\xa9\xe8\x94\x0d\x42\x77\xec\x16\xfe\xc2\x8e\xb5\x0f\x2c\xf7\x46\x91\x3a\x29\x95\x65\x1e\xd9\xc2\x53\x10\x96\x3e\xef\x59\xf4\x60\x3a\xf0\x51\x0c\xbb\xf1\x61\x47\x96\x1b\xb4\x45\x64\xda\x61\x55\x20\x43\xce\x65\x56\xe6\x4c\x0f\x02\x7b\x42\x69\x5d\xcc\xad\x34\xa9\x1f\x85\x11\xa6\x7c\xce\xf5\x4e\xf7\xd3\xb7\xc1\x52\x07\x26\xb2\xd2\x58\x4d\x05\x9d\xc1\xa3\x8c\x70\x52\x83\x0e\x10\x7c\x14\x6b\x24\xe5\xf5\x51\xbb\xdb\x57\x6a\x0c\x53\xe2\x0d\xf9\xff\x4e\xfe\xe7\xdf\xfe\x39\x3c\xfd\xcf\x93\x93\x3f\xbf\x1a\xfe\x3f\x7f\xf9\xb7\x93\xff\x19\xc1\x3f\x7e\x75\xfa\x9f\xa7\xff\xf4\x7f\xfc\xdb\xe9\xe9\xc9\xc9\x9f\xbf\x7d\xff\xcd\xdd\xcd\xd5\x5f\xf8\xe9\x3f\xff\x2c\xca\xfc\x1e\xff\xfa\xe7\xc9\x9f\xd9\xd5\x5f\x5a\x0e\x72\x7a\xfa\x9f\xbf\x6c\x35\x3d\x2a\x16\xdf\xb5\x38\xf0\xf8\x0c\x77\xf0\xb0\xaf\x7a\x75\x30\xd0\x7f\x1e\x56\x42\xdb\x90\x0b\x33\x94\x6a\x88\xdd\xdf\x10\xa3\xca\xed\x07\xa3\x22\x6a\xbb\xe0\xb9\x4f\x07\xf6\xa6\x22\x68\x81\x34\x1f\x1c\x91\x35\x4b\x14\x33\x87\xd2\x60\x70\x34\xcf\x3f\x1a\x26\xd9\x5e\xa9\xa9\x94\x9a\x60\x97\x04\x78\x55\x9c\x77\xa2\x64\x3e\x22\x91\x59\x68\x0e\x37\x99\xae\xdd\x3d\xdb\xa2\xe5\xfa\xa7\x57\x82\xbe\x2c\x25\xe8\x16\xf7\xf7\xd1\x35\x20\x26\xe6\x9b\xcc\x34\x4d\x9b\xee\x5b\x08\x65\x89\xcd\xd1\x5e\x80\x32\x92\x14\xb2\x28\x33\x6a\xd6\x98\xed\x56\xd8\xa6\x1d\xee\x57\xb7\x00\x76\xa3\xc1\x0e\xec\xa8\x5c\xbe\xda\x18\x4a\xce\xb3\x8c\x70\x81\x27\x01\x06\xf0\xd6\x3c\xc5\x50\x5e\x22\x14\x0d\xce\x73\x3b\x85\x07\x17\x70\x13\x19\x1a\xb9\xb6\xba\x8e\x32\x60\xf1\x87\x80\x1c\xa4\x59\xce\x34\xc6\x45\x15\x96\x13\xb8\x6d\xb8\xa5\x5c\x99\x7f\x31\xa3\xda\xf8\x69\xc3\x6c\x0c\xbd\x07\x53\x68\xc2\x52\x26\x12\x06\x2e\x08\x25\xab\xd6\x3a\xb6\xc2\x20\x98\xf7\x61\x0c\x4a\xd2\xb2\xc8\x78\x62\xe1\x67\x67\xb2\x7a\x8c\xeb\x3c\x2f\x0d\x18\x8a\x9f\xca\x8a\x6f\x77\xfc\xd6\xa7\x7b\x0d\xc6\x7c\x20\x55\x41\xb4\x0e\xde\x16\x41\x75\xd7\xfb\x99\xef\xdb\x11\xde\x60\x6e\xdb\xca\xa9\x96\x28\x6e\x65\x63\xa8\x53\xda\xa7\xb6\x18\xb6\xa3\xb3\x3f\x49\x1a\xdb\x81\xbe\xb6\xa7\xad\x1d\x8c\x4b\x5d\xe9\x69\x5b\x6b\x52\xa1\xd8\x84\x7f\xee\x80\x8f\xe7\xa2\x52\x51\x78\xca\x84\xb1\x8a\x00\x64\xa6\x2e\x14\x2b\x98\x48\x43\xb8\x1f\x38\x78\x89\xfa\x3a\x1e\xf5\xc6\x08\xa5\x8c\xee\xc7\xeb\x76\x95\x14\xd3\x9f\xad\x9f\xf8\xd9\x72\xbb\x7e\xf8\x83\x25\x64\xba\xd5\xf9\xbb\xb1\x8f\x51\x8f\x86\xa7\xab\x4b\xff\xed\x26\x69\xb5\xb7\x70\xe5\x54\xc8\x14\x73\x5c\x9b\xca\x09\x61\x44\x6e\x57\xf4\x04\x5f\x03\xd7\xe2\xf8\x58\xa3\x5b\x82\x6e\x0e\xd4\x88\x6e\x46\xcf\x04\x1c\xb4\x23\x4a\x21\xab\x2b\x15\x58\x7e\xcf\xa8\xd6\x7c\x2a\x86\x85\x4c\x21\x2f\xf7\xd9\x3a\x84\x68\x71\xa8\xba\x79\x36\x6d\xc5\xab\x60\x9c\x68\xb7\x4d\x1f\x83\xfd\x2d\x92\x2d\x7c\x46\x78\x15\xfd\xe8\xec\x3a\xde\x8f\x3e\x92\x21\x2b\x89\x68\x3f\x98\xe6\x54\xd0\x29\x1b\xba\x8f\x0f\xc3\xc7\x87\xe1\x5b\xfb\x80\xb9\x0d\xd5\x42\x93\x62\xeb\xb2\x10\xc7\xef\xd0\x64\x99\x86\xf2\x10\xe8\xbf\xf7\x99\xe7\x65\x4e\x68\x2e\x4b\x74\xd1\x5b\x06\xa7\x77\x64\x39\x08\xc0\x56\x00\x4a\xaf\x85\x54\x4b\x68\x91\x9d\x5c\xee\x5e\xa8\x65\xab\x95\x45\xab\x9b\x25\xab\x83\x05\x6b\x67\xcb\x95\x37\x52\xb7\xc7\xc7\x8f\xde\x6e\xde\xc0\x48\x2e\xb6\x62\xa4\x0a\xf9\xee\xaf\x27\x24\x8c\xc3\x35\x91\x39\x37\xc6\x19\x74\x69\x75\xec\x07\x84\x9b\x9a\xf5\xd3\x9d\x05\xa8\xf7\x80\x25\x32\xd8\x67\xab\x4d\x71\xb0\xa2\xfb\x5b\x8b\x01\x72\xd9\x07\x8e\xd9\x21\xa8\x20\x3c\x2f\xd0\x99\x15\x70\x7a\xe8\x75\x33\xe7\x64\xd0\x9f\x8f\xfe\x7c\xac\xea\xa4\xbb\xc8\x22\xb1\x18\x52\x79\x30\x06\x71\xc4\x62\xb6\x2f\x3c\x03\x1e\x9a\x88\x43\xf6\x2c\x80\x13\x3d\x17\x53\xf2\x91\x81\x65\xe0\x96\x19\xed\x7c\x22\xa1\x07\x55\x6c\x39\xc4\xcc\x5b\x42\x82\xab\x2d\x9d\x4c\xea\x2d\x52\x56\x64\x72\x91\x83\x64\x7b\x6d\x62\x79\x26\x88\x2e\x2c\x2f\x32\x6a\x58\x10\x6c\x36\x5b\x1b\xf6\xe6\x7c\x5d\xe2\xbb\x9e\x37\xa2\xab\x9d\x77\x70\x0b\x9f\xe0\x97\x1f\xa7\xd5\x5a\x23\x6b\x6b\x77\x6f\x63\x73\x6f\x19\x6f\xd5\x5e\x09\x6c\x65\x94\x7f\xec\x28\xaa\x4e\xea\x58\xdb\x48\xa9\x97\x1f\x1b\xd5\x61\xd9\x6d\xe3\x9f\xfa\x88\xa7\x4d\xa0\x6e\x17\xb5\xd0\x3a\x62\xa1\xd5\xfe\xb5\x8c\x5c\xea\x63\x95\x3a\xf0\x97\x47\x10\xfe\xb6\xee\xa5\x91\x19\x43\xc9\xb5\x9d\xee\x7e\x57\xb5\x0f\xf5\xcf\xf0\x7a\x37\x1a\xe9\x69\x6e\x29\xee\xbc\xd8\x62\xcf\x56\x35\x2f\x40\x2d\x63\x28\x14\x3b\x33\xd2\xcf\xcb\x6e\x9c\x58\x10\xbb\x67\xc6\x55\xbe\x8b\x4a\xc1\x19\x05\x97\x3e\x7f\x08\xd8\x36\x60\x20\x3f\xfd\x31\xf2\x6f\x0f\xf1\x2f\x01\x43\xfe\xe0\xff\xf5\xc7\x3d\xe3\x16\xda\x31\x36\x9c\x52\x07\x01\xe3\x0a\x3a\x10\x2e\x52\xb8\x60\x72\x4b\x05\x08\xe0\x58\x16\x3e\xb0\x2c\x1f\xff\x82\x81\x54\xce\xcc\x05\x37\x51\x55\x63\xed\xae\xcc\x22\xbd\xca\x99\x14\xaa\x93\xc1\xc8\x07\xe9\x92\x12\xb2\x01\xb9\x01\x5b\x6a\xf5\x06\x4e\xd2\x07\x89\xe9\x09\xd7\xde\x65\xc5\x70\xdb\xca\x45\xb6\x32\xfa\x1a\x40\xbe\xad\x98\x3c\xae\xac\xc6\xe4\x2b\x0c\xae\x45\xc2\x6d\x82\xcc\x3d\x5b\x54\xcc\xc6\x89\x10\x40\xf2\x07\x15\x96\x78\x56\x80\xbc\xe3\x3f\xbc\x29\x2b\x1f\x73\x81\x1f\xc3\xa1\xfd\x56\xc0\xe8\x1e\xa0\x56\xb2\xcb\x32\xfc\xcc\x21\xc0\xd5\x4e\xce\xa8\xc1\xec\xbb\x0e\x32\x46\xa0\x92\xab\xa5\x8b\x48\xa4\xb8\xfa\xb1\xa4\x59\x3d\x08\xc1\xbd\x72\x8d\x96\xa8\xfa\x03\xcf\xd2\x84\x2a\xe7\xe5\x05\x67\x94\x68\x89\xbb\x87\x59\xf1\x12\x2a\xc2\x69\xaf\xf6\x08\xeb\x20\x92\x82\x2a\xc3\x93\x32\xa3\x8a\xd8\xb3\x30\x95\xaa\x55\xa0\xc0\x56\x88\x56\x48\x73\xcb\x12\x29\xd2\x2e\x0a\xc0\x5d\xb3\x6f\xf3\xae\xb5\x60\x8a\xbb\x74\x7f\x3c\x67\x4d\x24\x3d\xa9\xdb\xb4\xe5\xc4\x9f\xea\x70\xc4\x6a\x96\x8f\x2a\x26\x93\x6b\xc2\x31\x5f\xe8\x69\x44\x1e\xc3\xa9\x18\x91\xaf\x17\xde\xcc\x02\x26\x17\x17\x5d\xa1\x99\xf1\x81\x30\x1e\x65\x1d\xb0\xab\x03\x35\x91\x0a\x82\x53\x4e\x52\x89\x11\x19\x73\x9e\x98\xd3\x11\xf9\x7f\x99\x92\x18\xc1\xc9\xa6\x98\xbd\xd1\xa1\x78\x50\x5c\xa1\x70\x29\xdc\xe0\xbf\x22\x27\x98\x49\x93\xe7\x39\x4b\x39\x35\x2c\x5b\x9c\xa2\x1e\xeb\x73\x71\xb6\xd9\xba\x36\x46\x83\x28\xf1\xea\x6f\x7f\xb3\xa1\x65\xd7\x18\xaa\xef\x7d\x54\x4a\x05\x19\xf4\x21\x68\x6c\x61\xe0\x41\x72\x83\xb8\x19\xfb\x20\x54\x41\x9d\x9e\xcc\x84\x0d\xfe\x9b\xc5\x03\x4a\x14\x9b\x02\x96\x23\xe6\xee\x89\xe3\xe8\x4d\xf9\x5e\x96\x62\xbd\x49\xb0\xb6\xf0\x77\x4e\x09\xff\x3e\xea\xb8\x36\x4a\xf1\x49\xc4\x84\x68\x26\x91\x89\x92\x12\xb0\x4b\x02\x3b\xb7\xe4\x01\x5b\x55\x9e\x28\x5b\x27\x79\xd0\x88\x44\x98\xcb\x16\xaf\xf7\x83\xc4\x2d\x86\x0f\x75\xc0\x65\x70\x10\x77\x80\x69\xc4\xed\x19\x47\x0e\x00\x3f\x11\x82\x15\x82\xc2\xb7\x58\xea\xbd\xd8\x30\xd6\x18\xba\x92\xe3\x37\xc7\x07\x21\xbe\xb8\x1c\x25\x0b\x3a\xa5\xdb\xf3\x1d\xd7\x95\x91\x46\x57\x92\x32\xc3\x54\x0e\x89\x69\x67\xf2\x01\x7f\x47\xb6\x55\xb8\x56\xcc\xe5\xf4\xb5\xab\x9d\x49\x0d\x5c\xa9\x1e\xc4\x08\xe7\x17\x2e\x46\x1f\xe8\x82\x50\x25\x4b\x91\x3a\xa9\x29\x10\xd0\xf7\x8d\x0f\x7f\x90\x02\x28\x45\xa9\x2d\xac\xee\x6a\x54\x7a\xcc\x0c\xb5\xc7\xe6\xf5\xe8\xf5\x96\xdc\xd3\x2d\x01\xd6\x31\x6e\x15\x66\xd3\xb0\x14\xfa\xbb\x72\x7f\x66\x0e\x32\x2f\xc5\x68\xfa\x9d\xc8\xba\xc8\x72\xef\x11\xbd\xa0\xeb\x10\x94\x30\x3e\x01\xdb\xed\x00\x5f\x3d\x28\x6e\x58\x44\x1e\x4f\x26\x34\xd3\x50\x70\xbb\x14\x41\x84\x3d\xad\x8b\x20\xd0\xa4\xcd\x82\xb6\xfb\x83\xe8\x72\xbc\xe7\x39\x73\x07\x0a\x50\xae\x3a\x66\x01\xe1\x8e\xf5\x86\x23\x57\x0f\xee\x24\x27\xd8\xd2\x4a\x6c\x52\x9a\x8d\xe5\xdd\xdb\x3b\x89\xe0\x02\xad\x66\xdd\x45\x25\xf1\x71\xc3\xc5\x01\x57\xfb\x35\x9b\xd1\x39\xd3\x44\xf3\x9c\x67\x54\x65\x10\x2b\x78\x8b\xf3\x83\x62\xec\x2b\x23\xd0\xbb\x45\x37\xc7\x33\x89\x86\xdb\x0a\x6a\x3f\x0f\x0b\x27\xa0\x11\x7e\x5e\x98\x04\xdc\x67\x0e\xff\x9c\x64\xa5\xe6\xf3\x7d\x4f\x93\x8b\x7e\xd8\x81\x55\x37\xb9\x74\x21\xd3\xdb\x82\x25\x4f\xc9\xa3\xeb\x1a\x86\x25\x55\xa9\xdf\x74\xe0\xc9\xa8\xec\x53\x2c\xac\x3f\x66\x84\x26\x09\xd3\xda\xfb\x54\x2e\x62\x3f\xcf\xb0\x86\x2f\x25\xa1\x00\x7d\xd0\x57\x19\xd5\x86\x27\x5f\x67\x32\xb9\xbf\x35\x52\x75\x8a\xd9\x5f\xd5\xbf\x91\x86\xe1\xfc\x87\x5b\x72\xc9\xf5\x7d\x14\x4d\xe0\x2e\x4d\x63\x73\x09\x25\xf7\xe5\x98\x65\xcc\x1c\x1f\x6b\xe4\x72\x39\x4d\x66\x5c\x30\xcf\xe0\x44\x08\x49\x71\x0a\x9f\x85\x72\xd7\x3b\x53\x17\xf8\x74\xe6\xf0\xf5\x17\xf4\x41\x33\x9c\xfe\xd8\x4e\xdf\xfe\xcc\xda\x44\xa4\x1f\xf4\x9e\x02\x27\x73\x7d\x79\xa0\x3b\x88\x89\xbe\xb3\x73\xec\x66\xdc\x3e\xc6\x5e\x5e\x75\x98\xf0\x8c\xb9\xea\x03\x76\xc1\xde\x47\xcd\x9d\x0a\xd8\xbf\x85\x2c\xc9\x03\x45\x1d\x19\x28\xe2\x88\xdc\xf1\xe2\x0d\xb9\x12\xba\x54\xac\xb2\x6e\x34\x87\xe2\xba\x8a\x33\xf3\xca\x15\xec\x37\x2a\x20\x96\xee\x39\x5d\x8b\x5c\x7d\xa6\x79\x91\x31\xfd\x86\x1c\xb1\xcf\xe6\x37\x47\x03\x72\xf4\x79\xa2\xed\xff\x84\x99\xe8\xa3\x11\xb9\xce\xc3\xad\x3b\x17\x13\xa6\x14\xf3\x8e\x50\xd8\xc1\xb2\xe6\x88\xeb\x3e\x0a\xba\x38\xa7\x3a\x2b\xbb\xa5\x92\x3c\x60\x3e\x0a\x4b\xf0\x99\x52\x52\x05\x3f\xf4\x08\x0c\xc0\x6b\x12\x99\x17\x4a\xe6\x3c\x32\xf3\x01\xba\x1f\xd4\xdb\x0e\x8c\x0f\x6d\x0a\x72\x34\xb1\x21\x74\xf4\x08\x11\xbd\x10\x6d\x50\xe1\x7a\xe2\x9d\x29\x50\x8b\x74\x6a\x3d\x0c\xe7\x1a\xd9\xcd\x77\xa3\x58\x42\x16\x6f\xf7\xdb\x10\x50\x47\xce\x52\x36\x3f\xd3\x29\x7d\x3d\x80\xcf\x68\xe7\x08\x58\x9f\x13\xd5\xe4\xe8\xf5\xd1\x88\xdc\x7a\x46\x3c\x88\xe7\x58\xb5\x9b\x48\x15\x06\x04\x3b\xfb\xab\x23\x72\x22\x15\x8c\x9c\x50\x41\x32\x46\xe7\xce\xb6\x8c\xc7\x6d\x81\xea\xee\x69\xeb\x80\xc8\xb6\xb1\x61\xed\x2b\xaf\xb4\x15\x52\x97\x37\xd1\xf7\xf3\x26\x00\x55\xba\x58\x81\x89\x54\x2e\x0f\x48\x68\xa2\x99\x81\xa3\xc7\x45\x4d\x85\x7e\x06\x02\x4b\x3a\x86\xd2\x7b\xea\xd9\x15\x3a\xbe\x1f\xe8\x40\x82\xff\x58\x32\x72\x7d\x19\x02\xea\x99\xd2\x5c\x1b\x7b\x8c\xd3\x1a\xeb\xe2\xc8\xcf\x4e\xce\x73\xfa\x77\x29\xc8\xd5\xd7\xb7\x6e\x02\xa7\xcf\x0a\xaa\xad\xd4\x80\xfe\xbd\x54\xcc\x72\xe1\x0e\xcc\x3d\xf4\x69\x32\x74\xfb\x9e\x5c\x52\x43\x91\xaf\x3b\x4f\x2b\x51\x91\x72\xcb\xb2\xc7\x5c\xa4\xee\xa7\x88\x61\x3f\x35\x6f\xb5\xbb\xf7\x61\x93\x98\x14\x37\xfc\xf4\xf1\xfa\x40\x3c\x38\x01\x62\x3e\x7d\x2f\xd3\xce\x8c\x38\xea\xea\x89\xef\x9f\x2c\x4c\x2f\xf0\x3d\xc9\xed\x98\xc4\x6a\xef\x03\xf2\x91\xd1\x94\xd8\xf3\xeb\xfe\xf9\x83\xd5\x3d\x5b\xd3\xaa\x56\x2c\xc4\x03\xb0\xe3\x32\x7c\x37\xbf\x84\xd8\xd3\x3d\xb5\x98\x03\xc7\xca\xf1\x92\x71\x26\xc7\xc4\x1d\x87\x43\xcf\xfd\xd3\xc7\xeb\x1d\xa6\xfe\xe9\xe3\xb5\x9f\xb9\xfd\xa7\x9c\x3c\xdd\xa4\x77\x12\xdf\x2a\xe9\xed\x6d\x43\xdc\xaa\x58\x72\x15\xb8\xd1\x14\xc9\xda\xcb\x63\xa3\x43\x49\x62\x87\x84\xd8\x3d\x17\x2d\xa2\x70\xeb\xa7\xcc\xf6\xb1\x0a\x05\xfa\xaa\x45\xf7\x88\xb7\x33\x0a\xa1\xcf\x21\x20\x0f\xf6\xd9\x6e\xbc\xb6\x5c\xc1\xef\xb8\x55\x02\x81\xb6\x91\x4b\x86\xb7\x9c\xe9\x1b\xef\x3b\x10\x7a\xac\xee\xf0\x1e\x3c\x35\x53\x47\x5f\x09\x3a\x6e\xa6\x11\x82\x9d\xa0\x55\x49\x84\x9f\xe8\x9c\xf2\x8c\x8e\x79\xc6\x21\x95\xba\xd5\xee\x63\x6f\x54\x0d\x53\x3e\xe8\xa9\xdf\x51\xe4\x08\xe2\xc4\x92\x71\x8b\x9c\xd8\xdf\xce\xc0\x38\x76\x3a\x02\x6a\x05\x0d\x21\x47\x63\x43\x28\xf9\xb8\x4d\x28\x39\x98\xfc\x00\x3b\x60\x4f\x4c\x57\xae\x68\xfb\xac\xe4\x8a\xf0\xc3\xad\xcb\x27\xf7\x92\x19\x23\xc6\x5a\xb5\x62\x8d\x80\x5f\x5b\x5b\xb6\x67\x8e\xfb\x22\x57\xfa\x65\x20\x17\x09\x11\x6d\x3b\xf0\xcf\xaa\xa3\xe7\x43\xa0\x24\x81\xc7\x99\x8b\x76\xab\xb9\x66\x22\xf6\xdd\x3a\x5a\xe3\x52\x30\x21\xd7\xb5\x38\xd7\xa6\x2e\x5a\x97\xa4\x0d\x1e\x23\xba\xae\xca\xf7\xf3\x8b\x42\x12\x08\xaf\x49\x0b\x5c\x6c\x3d\xc9\x84\x15\xb3\x49\x97\x2b\x71\xdb\xe1\xed\x6d\xdd\x12\x78\xc1\x8a\x19\x79\x7b\xbb\xe2\x18\x03\xec\x61\xd6\x1a\xed\x83\xc7\x9a\x64\x7c\xc2\x0c\xdf\xb2\x84\x47\x38\xc8\xb9\x14\xdc\x48\xb5\x3e\x04\x9a\x74\x3a\x9c\x7e\xb8\xae\x0c\xd5\xf7\xb3\x3b\x5b\x25\x10\x79\x1f\xbd\xa5\x24\x91\x59\xc6\x12\xe3\x52\x5a\x01\x78\x43\xb7\x15\xca\x13\x73\xf6\x80\xd1\xfd\xef\x41\x7d\x72\x8a\xd2\x19\x6e\xee\xd9\xc7\xab\xf3\xcb\xf7\x57\xa3\x3c\xfd\xc5\x4c\x3e\x0c\x8d\x1c\x96\x9a\x0d\x79\x8b\x0c\x25\xcf\xe7\xbd\x88\x4f\xd1\x2a\x61\x56\xd3\x20\x83\xb9\xbe\xbe\xf3\xf1\x93\xe4\x93\x46\xaf\x05\xb0\x1d\xf9\x3b\x29\x29\xcd\x80\x28\xea\x62\x24\xa9\x33\x3d\x95\x59\x86\xd0\x36\x8a\xb1\x41\x6c\x8b\xd9\x18\x1a\xd2\x79\x61\x7b\x1b\x2a\x6a\x0b\x7c\x5c\x19\xe2\xe9\x11\xae\x0b\xc7\xd8\x2e\x93\x2c\x43\xb1\xea\x59\x87\xe3\x6d\xed\x3d\x1a\xce\xcc\xcc\x42\xf5\x9e\x2d\x08\x38\x02\x4f\xa4\xb2\xf8\xa4\xea\xb8\xc1\x4c\x02\x4b\x3f\x2b\x35\x53\x23\xc7\x76\x9e\x1c\x6c\x1d\xb2\x08\xed\x90\xbc\x2d\x74\x5c\x05\x33\xf7\xba\xca\xec\xeb\xe4\x35\x5a\x9a\x19\x13\xc6\x8a\xfd\x96\x96\x39\xc8\xac\x04\xa2\xf3\xc3\x7e\x72\xa8\xb5\x4c\x62\xd4\x2d\xe5\x50\x9f\xa6\xa7\x0b\x4e\xda\x53\xd3\x15\x1d\x6d\x1f\x08\x44\x8c\xc9\x7c\x88\xe5\x52\x34\x95\xe0\xb0\x81\x19\xe8\x6a\x88\x46\xd3\x9c\x8b\x17\x78\x3a\x13\x2e\xd2\x6d\x70\x68\x18\xc0\xa0\x47\x5d\x14\x73\xef\x9c\x41\x3f\xdc\x1b\x52\xaf\x49\x61\xc0\xbb\xbb\x41\xac\xdf\x1f\xb6\x3a\x7c\xf9\x42\xff\x98\x0d\xf1\x2b\xc3\x22\xad\xa0\xd2\x5f\x06\x2e\xdf\xe0\x1d\xd6\xa4\xf4\x04\x57\x7c\x07\xda\x6d\xf2\xc4\xd2\xd0\xe3\xea\xb9\x4f\x02\xa8\x2e\x32\xcf\xbe\xdc\xbb\xa2\x99\x50\x78\x5f\xfb\xe0\x33\xcc\x6c\x06\x67\xd4\xeb\xcb\x50\x90\x9f\x2a\x9a\x33\xc3\x14\xba\xc0\x39\xa7\x3a\xe1\xa2\x13\xbe\x2b\x98\xb8\x35\x34\xb9\x3f\x74\x2a\xd4\x9e\xe3\x3e\x1e\xc7\xdd\xfb\x2a\xd0\x23\x82\xcb\x8b\xb4\x88\x6f\x91\xb9\x70\x5c\xe8\x85\x90\x98\x90\x8e\xac\x8b\x95\x23\xa4\xa3\xaa\x73\xd7\x2a\x3d\x19\x1a\x36\xc0\xd3\x2d\xe4\xd7\x03\x0f\x7e\x84\xc2\x61\xb8\x61\xfb\x33\xe0\x48\xe0\x2e\xf7\x68\x51\xd7\x3a\x75\xc8\xed\x9b\x31\x37\xd5\xb9\xd7\xcc\x90\x82\xa9\x9c\xbb\xb0\x6e\x29\x48\xe2\xc2\x02\x80\xaf\x59\x1e\xe6\x86\x8b\x78\x9e\x20\x32\x31\xd4\xc5\xcc\x90\x31\x33\x0f\x8c\x09\xf2\xea\xd5\xab\x57\x20\x97\xbc\xfa\xdd\xef\x7e\x47\x20\x8f\x44\xca\x12\x9e\x2f\x37\x84\x56\xff\xe7\xf5\xeb\x11\xf9\xef\xf3\xf7\xef\xc0\xab\xac\x30\x9a\x8c\xa5\x99\xb9\x91\x6d\x83\x5a\x67\x3d\x20\xff\xf7\xf6\xbb\x0f\x5e\x9c\xd0\x8d\x5f\x41\x05\x09\xcb\xab\xbb\x08\xbe\xfa\xed\x6f\x7e\x33\x22\x97\x5c\x41\x3c\x31\x87\x08\x88\xe0\x04\x59\x78\xc7\x40\x28\x3c\xd4\x8c\xe0\x77\x1c\xc4\x39\x09\xe7\x7c\x3a\x03\x00\xd8\x03\x21\xc5\x24\xe3\x89\xc1\x9c\x82\x78\xf4\x11\xd0\xae\x2e\x12\x75\xe1\x5e\x4e\x8a\x80\xc9\x0d\x48\xc6\xef\x19\x99\xe8\x6f\x94\x2c\x8b\x2a\xcc\x51\x31\x6d\x65\xd9\x84\x0a\x88\x2a\x81\xc1\xaa\xbd\xd2\xcc\x3c\xab\x13\x46\x4b\x43\x50\x0d\x07\xa1\x4f\x43\x40\x19\x84\xdc\x6a\x43\xc4\x87\x82\xf2\xe0\x38\x08\x77\xea\xb5\xcc\xfe\x41\xf7\x4c\xa3\x5c\x72\x3e\x76\xa5\x50\xf2\x6f\xb8\x55\x5c\xf8\x28\x28\x27\x21\x6b\x27\x93\xb9\xa0\x53\x11\xd9\x5c\x7d\x54\xbe\xe5\x85\x2e\xe2\x3f\x8a\x9f\xba\x9e\xc4\x81\x76\x10\x96\x8e\xe5\xd5\x6a\x89\x2f\x57\x7c\xb9\x4a\xd6\x6e\xb1\x49\xe3\xbe\x96\x62\xa9\xb7\xab\xa3\xe2\xc8\x8f\xab\xae\xe3\x42\xd8\xaa\x31\xd0\x15\xd7\x05\x00\x45\x35\x9b\x6a\xc9\xe8\x6a\x5e\x3e\x9a\x99\xd2\x81\x06\x3c\xaf\xec\xb7\x99\xd6\x2e\x8e\x28\xa7\xea\xde\x2a\x09\x8e\x0a\x8c\xc0\xeb\x59\x87\x18\x26\x0c\x28\x9b\xa3\xb1\x3c\xa7\x8b\x5a\xd4\x80\xfd\xc8\xf1\x68\x74\x8c\xc7\x44\x2a\xcc\xe5\x89\x38\x6f\xdf\x3f\x53\xbc\x74\xdd\x2b\x9d\x16\x58\x76\x0f\xec\x39\xae\x6c\x09\xad\x79\x3b\x53\x07\xa9\x36\x19\x7c\x3b\x96\x2d\xec\x56\x1f\xb7\x7d\x5d\xdc\x21\x2c\xa0\x45\xd3\xae\x35\x70\x3b\xd4\xbe\x5d\x97\xad\xc1\xc1\xd8\x9d\x84\xb6\x15\x21\x3b\xe7\x02\xcf\x5b\xb1\xbe\x15\x53\x3d\xce\x1d\xe7\xfb\xae\x1b\xe7\x73\xf1\x7a\xb5\xe2\x60\x2f\x9f\xd5\x5d\x4f\x30\xd2\xa5\x4e\xba\x1c\x69\x88\x45\x81\x50\x88\xab\x0a\x7b\x79\xd1\x1c\x2d\x46\x9b\x6e\x89\xe7\xbb\x70\x37\x7c\xda\x5d\x4c\xe0\x53\xc3\x35\x7f\x3b\x81\x8b\x76\xa4\xb4\xa8\x15\xf8\xc8\xd0\x6e\x00\x32\xa6\x3f\x3c\x23\xf2\xde\x91\x5a\x44\x32\x3a\xd6\x32\x2b\x0d\x76\xad\x7e\x8c\xe9\x30\x0c\xea\xb3\x2c\x00\xf1\x0d\xcd\x22\xaa\x6c\xaa\x12\x67\xed\x08\x34\x3e\x1d\x0e\x67\x9f\xed\xf3\x11\xb3\x7d\x86\xfc\xb4\xba\x65\xbd\x26\xfd\x68\xe9\x75\x13\xcd\xbb\xe8\x57\x9a\x93\x93\xaa\x4c\x88\xbf\x8e\xbf\x16\x86\xa9\x09\x4d\xd8\x69\xac\x77\x85\x72\x2c\xc1\x45\xc8\xc7\x45\xcc\xa8\x48\x33\x14\xc0\x13\xa6\x00\xf7\xd9\x67\xc3\x94\x05\xc9\xc5\xed\x35\x49\x15\x9f\x33\xa5\xc9\xc9\xd7\xcc\xca\x8b\x8c\x9a\x52\xb1\x56\xd1\x55\x87\xf5\xad\x84\x69\x1c\x4a\xd3\x83\xc1\xba\xba\xea\x41\x27\x4f\x79\x44\x74\xbe\x2a\x30\x21\x54\x11\xa4\x3a\xd6\x65\x47\x16\x95\x80\x40\x03\xcd\x58\xc8\x52\x39\x2b\xba\xcf\xab\x9a\x48\x65\xd5\x25\x1c\x98\x6a\xa2\xd8\xd4\x4a\xb3\xca\x17\x1b\x66\x24\xc9\x4a\xfb\xe2\xa0\xee\x6c\xfb\x38\x00\x56\xa6\xd9\x4d\xbe\x7a\x13\x27\x55\xcb\x39\x4f\x3d\xab\xc4\xda\xc7\xa1\xaa\x61\x41\x75\x14\x6a\x13\x65\xa0\x8f\x00\x8b\x32\x3a\x30\xd4\x10\xc4\x5a\x73\xf6\x8f\x8d\xc2\x12\x72\x5b\xb4\x28\x1f\xd1\x85\x08\xcb\x94\xdd\x94\xe3\x8c\xeb\xd9\xed\x8e\x26\xc4\x55\x43\xa0\xb3\xc2\xd2\xad\xdf\x5a\x4b\xa2\x66\x42\x73\x60\x79\x96\x8c\x5b\xa6\xcb\xad\x1c\x25\x01\x88\xbe\x77\x8c\x90\x12\xa2\x3f\x32\xe6\x32\x18\xd8\x9f\x3e\x54\xf3\x70\x41\x69\x98\xb3\x24\x65\x9f\x44\x51\x7b\x9f\xd0\x2c\xd3\xcd\x80\x5d\x4f\x31\x51\xf6\xf0\x81\x6a\xb8\xa7\xdc\x6e\x77\xa8\x8c\xd2\xc8\x7e\xb9\x76\x61\x9a\xe4\x12\xc3\x78\x04\x91\xc2\x37\x82\xd4\x2b\xbe\x43\x14\xc8\x08\xe1\xca\x80\x32\x07\x2e\x1d\xd9\x9b\x4b\x1f\xcf\x5c\xba\xaf\x1f\x5e\x5c\xef\xbd\x8a\x86\xae\xa5\x25\x0d\xa4\xd4\x93\xdc\x2d\x4e\x1d\x07\xbd\x56\xc0\x6f\x9e\x1b\xa3\xf8\xb8\x34\xdd\xf3\xbd\x35\xba\x03\x9b\xb6\x8a\x08\x9c\xe2\xa1\x5b\x7d\x12\xa1\xa8\xd3\x10\xc2\x59\x58\x3e\xfb\x15\xcf\x01\x76\x83\x2f\x8f\x35\x49\x65\x52\x86\xbc\xb0\x00\xb4\xea\x02\xad\x4d\xf6\x44\xd2\xf5\x5c\x75\x4f\xe9\x15\x7f\x64\x2b\x7a\xa5\xf2\x41\x3c\x50\x95\x9e\xdf\x6c\xf1\xbe\xaf\xb3\xf3\xaa\x57\x2c\x28\xf9\xd7\x50\x05\x90\x8e\x65\x69\xaa\xd4\xa1\x3f\x1d\x7b\xf5\x2a\x35\xdd\x48\x4b\x1a\x5a\xda\xa3\xbb\x2a\xfa\xbd\x89\xbb\x37\x71\xd7\x9e\x5d\x4c\xdc\xd7\x68\xe2\x8e\xf3\xe0\xd6\x8e\xab\x4f\xaf\xc0\xb3\xb6\xbe\xbd\x8f\x69\x25\xbd\xac\x08\x0c\x4a\x53\x4d\x3f\xfe\x86\x00\x87\x47\xa4\xda\xdb\x48\xe8\xf3\x14\x08\x78\xf6\xf3\x5b\x54\x1f\xc9\x4e\xda\xbe\x4e\x31\x3e\xeb\x0a\x09\x6e\xaa\x5b\x0c\x52\x43\x54\x68\x78\xe0\xb2\x40\x0f\x9c\xde\x25\xd2\xaa\x84\x1f\x26\xa1\xee\x50\xa6\x14\x9f\x8e\xc0\x27\x9d\x37\x80\x74\x2c\x22\x8c\x4f\xd7\xdd\x20\x3b\x14\x14\xc6\xe7\x99\xcb\x0a\xe3\xd3\xd9\xf6\x4d\xba\x97\x18\x5e\xb1\xdc\xc7\x2d\x34\xbc\xe3\xd2\x76\x37\xeb\xef\x6a\xce\x1f\x54\xe5\xed\x5e\x3e\x5b\xef\xcd\xf9\x4b\xcf\x13\x9a\xf3\x23\xc2\xed\x89\xc1\x0a\xd3\x7e\x6c\x6e\xf3\xf6\xfd\x31\xf3\x62\xe5\xa8\xca\xbe\x66\x51\xce\x5b\xf6\xa5\xaa\x5f\xab\x1e\x8f\x46\xc7\xc7\xde\xde\xef\xf0\xb3\x34\x93\xe1\xef\x09\x13\x89\x4c\x71\x53\xed\xf8\x4a\x1b\x60\xfa\x95\x9a\x1e\xcf\x25\xf7\xdf\x8a\xaf\x66\x61\xec\x6e\x5b\xd2\xe1\x04\x77\x2f\x1b\xbe\x0a\xd2\x4f\x51\x3c\x3c\x2e\x11\x5e\xaf\x08\x8e\x2d\xf6\x29\x03\x1e\x03\xef\xd1\xf9\x6b\xeb\xc2\xe0\xf8\xec\xc2\x5e\x77\x28\x12\x8e\xcf\x13\x97\x0a\xc7\x67\x27\x8e\xda\xa9\x6c\xf8\x8a\xc5\x3d\x5d\xf1\x70\x7c\x5e\x68\x21\x99\xfa\xd3\xa9\x90\x38\x3e\xbb\x95\x13\xaf\xf7\xed\xb8\xf5\x07\x29\x2d\x8e\x4f\xb7\x02\xe3\xf8\x1c\xba\xcc\x38\x3e\x2d\x21\x01\xc6\xf0\x4b\xde\x29\x14\xc1\xf7\xa9\xbb\x4b\x1a\x96\x17\x52\x51\xb5\x20\xa9\xb3\x35\x2c\x56\x44\x84\x46\x21\xa1\x7b\xa7\x86\x81\x79\xa4\x5c\x1d\x28\x1a\xa1\x43\x34\x28\x4b\x79\xb9\xb6\x5c\xf3\x3a\xb0\x61\xaf\x18\x68\x0f\x90\x0d\xcc\x65\x12\xf3\xd7\x9d\xae\x99\x4f\xac\x48\x93\x7b\x57\x31\xc8\x43\x15\x79\x7f\x14\xe4\x72\x74\xd4\xc8\x03\x0d\xe6\x31\xb8\xfb\x73\x95\x11\x7d\x63\x1c\xbb\x66\xca\xc2\xdb\x10\xe7\x16\x70\xe2\x1a\x9e\x5a\x89\xe4\x3d\xb0\xc1\x27\xda\x25\xd2\x31\xb2\x8d\xff\x9d\x41\xb9\xb1\xce\xbe\xf1\xbe\x63\x48\x07\x2d\x41\x32\x0f\x75\xd1\x32\x99\x44\x77\xcf\x35\x0e\x05\xdb\x70\xe5\x91\xdf\xdb\xee\xed\x66\xd8\x51\x51\xbe\x00\xa3\x4f\xa6\xf1\x5e\x8f\x27\x90\xda\x12\xa4\x78\x00\x66\xd8\x80\xbb\xa8\x4a\x60\xa9\xed\x97\x20\xf3\x7c\xd4\xa6\xfa\xd0\x83\xcf\xb0\x69\xa2\x42\x6e\x75\xdd\xc3\xfe\x72\x1b\x56\x56\xe9\x6d\x10\x02\xe1\x05\x75\x5d\x82\x98\xe8\xbe\xe2\xc4\x25\x39\x81\xbb\xab\xaa\x2c\x5a\x48\xee\xb8\x84\x66\x82\x67\x75\x3c\xf3\xb9\xec\xc2\xc2\x4b\xe1\x1c\x0d\x96\x90\x66\x35\xce\x94\x9a\xa9\xe1\xb4\xe4\xe9\x2e\xd8\xf2\x82\x19\x60\x6b\xb6\xd7\x9d\xd9\x75\x64\x71\x7b\x30\xb6\xe0\x88\xd1\x81\x35\x1c\x55\xde\x1b\x35\xde\x10\xa7\xc5\xab\x7b\x72\x50\xef\x2c\x10\x8e\x9c\xbf\x12\xba\x0b\xaa\xad\xe3\x19\xc9\x22\x71\xc1\xba\xbc\x96\xee\x12\x87\x45\xcc\x03\xc7\xd6\xa1\xfd\x8f\x57\x81\xbd\x3d\x7f\xcc\x26\xb2\xaa\x90\x82\x1a\x91\x73\xc7\x4d\x59\xc6\xa0\x8c\xbc\x2f\x51\x6f\x1b\xc0\x95\x70\x2e\xe7\x16\x99\xff\x47\x90\x4f\x3e\x67\x3f\x9f\xbc\x21\xf4\xb4\x16\x02\xe1\xaa\xce\x08\xc6\x52\xf4\xd1\xcd\xaa\xef\xa8\x52\xe8\x01\x19\x9f\x7a\x7f\x14\x38\x71\xc2\x8a\x85\x99\x97\x78\x51\xaf\x56\xcc\x02\x00\xc2\x8e\x95\xcc\x89\x16\xb4\xd0\x33\x69\x40\x35\xa4\x05\x4d\xb8\x59\x10\xa3\x68\x72\x0f\x25\x8a\x14\x73\x9f\x1b\x90\xe4\xd4\x39\x76\xc5\xe0\xab\xbb\x0d\x9b\x99\x92\xe5\x74\x06\x9e\xb0\xd8\x2a\xc9\xa8\xf6\xab\x5f\xd9\xdf\x69\x3b\x9a\xa4\x0b\x41\x73\x9e\x84\xac\x81\x4a\xce\xb9\xe6\xd2\x59\x7b\xfd\xb8\x37\x21\x33\x1c\x5a\x90\x2f\x32\xca\x73\x72\xa2\x19\x23\x57\x1e\x25\xf0\x17\x57\xc6\x1e\x2d\x1b\xaa\xee\x1c\x20\x43\x4a\x73\xe1\x12\x22\x54\x04\x2e\x5c\x5e\x21\xc3\xb4\x33\x5f\xf9\xd1\xd3\xb0\x5d\xab\xe7\x24\x15\x5c\xdc\xfb\xd4\x9d\x4c\xa4\x32\xba\xb5\x3c\xbf\xb9\xd6\xb1\x36\x82\xb8\xe5\xf2\xde\xc1\x0f\x99\x14\xd3\x38\x8d\x40\x85\x99\x96\x94\x0a\x28\xef\x32\xe7\x69\x49\x33\x24\xa2\x6e\x32\x17\xb7\xd7\xd8\x9d\x4f\x67\x66\xf8\xc0\xc0\x1a\x83\xbc\xa6\x3a\x33\xfe\xa3\x7c\xc9\x5b\x87\x6b\x20\xba\xc6\x59\x13\xd0\xb2\x65\xa7\xf6\x40\x17\x90\xb6\xc6\xb9\x98\xd4\x2e\x4c\x7d\x62\x31\x1c\x62\x15\xc4\x61\x7a\xe7\xa1\x5c\x87\x15\x1b\xc0\x5c\x65\x41\x0c\x98\xba\x3c\x37\x0b\xf8\x28\x0f\x60\x78\xed\x2a\xb3\x51\xbb\x41\x56\xb8\xdb\xac\xcb\x3c\x82\x50\x36\xaf\x36\xf9\xce\x95\x4e\xec\x28\x1c\x1c\xfd\x10\x99\xcd\xa2\x8b\x0e\x7b\x6c\xa8\x48\x87\x34\xb3\x98\x73\xf3\xfd\x85\xf3\x70\xc6\x83\x50\xbb\xc8\xf7\x55\x90\xb8\x08\x69\xb3\xad\xcc\xb0\xf2\x08\x40\x1c\xfc\x98\xa5\x40\x34\xe2\x82\x91\x0f\x56\x43\x76\x9b\x77\xf3\xfd\xc5\x80\xf0\x11\x1b\xf9\xbf\x42\x53\x4f\xb5\x8c\x9c\xa2\x1b\x60\xf0\xf1\x04\xbc\x83\xa9\xc4\xc6\xa8\xb8\xef\x5f\xff\x60\x27\x69\x7f\xfd\xe3\xf0\x0f\x51\xb6\xd1\x3f\xfe\xd5\x12\x41\x65\x1b\xd4\xdf\xc6\xbe\x64\x21\xeb\xfe\x5f\x6f\x5c\x56\x6a\x97\xb3\xfa\xaf\xae\x18\x17\x13\xc6\xca\x8d\x37\x12\x6e\xe9\x79\x8a\xd8\x08\xdf\x56\xec\x6f\xde\xb0\x08\x60\x0a\x46\x9d\x84\x1a\x26\x80\x50\xfb\xa0\x0c\x21\x0d\x76\x77\x75\x67\xed\xfc\x4f\xc0\x24\x80\x41\x65\x03\x62\xa4\x84\xe3\x88\x47\xfe\x5c\x10\xe6\x6b\x75\xe2\x5a\x01\x1c\xd4\x39\xaa\x79\xde\x63\x87\xb5\x10\x0e\x21\xb8\x76\x1e\x30\xb7\x5f\x09\x69\x7e\x15\xb6\xbf\x51\x45\x9c\xce\x25\xf7\x09\xc8\xed\x49\x11\x58\xd1\x31\xa4\xc4\x1e\x2f\x48\xce\xb5\xa1\xf7\x6c\x44\x6e\x2d\x6f\x89\x6f\xc3\x10\x7a\x82\x40\x06\x4b\x96\x92\x52\x18\x9e\xc1\xaf\xd5\x38\x76\xca\x31\xcf\xb9\x9e\x10\x5d\x42\x79\xf3\x42\xb1\xa1\xe7\x62\xae\xd5\x12\x2d\xa8\xd6\x32\x08\x9b\x3d\xa3\xa8\x0b\x14\x29\x74\x05\x78\x50\xe1\xd0\x6b\xc9\x8f\xcb\xce\x53\x8a\xa4\xe2\x5c\x00\x4c\x3d\x22\x1f\x80\x59\x65\xfe\x4a\x18\xd5\x12\x67\xc0\x14\x2c\x61\x5a\x53\xb5\x18\x40\x62\x77\x1e\x92\x81\x3b\xd7\x1d\xe0\xa8\x39\x15\x98\x56\x5d\xb1\x44\x0a\x6d\x54\x99\x18\xac\xb3\x37\x56\xf2\x9e\x89\xe0\x2e\x68\x77\xb1\xee\xc0\x55\xf9\xcf\xc0\x7d\x97\x24\xc9\x8c\x8a\x69\x54\xa7\x26\xa7\x29\xc0\xfe\xdb\x20\xe5\xf8\xf5\x58\x08\xd0\x89\x15\x2c\xb8\x01\x50\x8c\x2d\x1f\x09\x66\xd8\xff\x11\x21\x1f\xcf\xa0\xb2\x93\xda\x25\xf1\x6c\x0b\xed\xea\x44\xbf\x48\x47\xa3\xde\x10\xd8\xf6\x81\x1d\xc0\x72\x66\x68\x4a\x0d\xdd\xc1\x09\xec\x7d\x55\x5c\xcf\xd7\xd7\xc7\x02\xa7\xe1\x62\xd2\xf1\x21\x2f\x6e\xc9\x82\xc7\xf1\x4f\x70\x12\x67\x1e\xf2\x10\x71\x6d\x2c\x4e\xb9\x8b\x02\xf4\xed\x02\x79\xc6\x57\x2f\xb3\xc3\xfb\xd1\x90\x5c\x54\xa5\x19\x2b\x72\xd2\xee\x1a\xaa\xa3\x05\xd6\x82\x7e\x07\x18\xdd\x55\x77\x65\x49\xdd\xbf\x6b\xa5\x08\x82\x5c\x82\x09\xc3\x15\x8b\xc3\xcd\x1c\xe8\x4a\x81\x48\xde\x00\x22\x40\x79\xca\x8c\xae\x3c\x54\x90\x0e\x5b\xe2\xe2\xf8\x9d\x53\x46\x81\x48\x3b\xc0\x3a\x7d\x6e\xb5\x2c\x84\x60\xd7\xd2\xd1\x59\x4b\xf9\x1f\x05\xae\xbb\x18\x9d\xb1\x9c\xc0\x7b\x99\x76\xb1\x53\x37\xb2\xf0\x57\x43\x54\xfe\x9b\xe8\x89\xab\x41\xa9\xc7\x06\x70\x5b\xa5\x6b\x41\x73\x48\xe4\x66\x74\xbe\xbb\x91\xaa\x92\x91\x86\x21\x95\x31\x7c\x6e\x08\x9f\x1b\xbe\x6e\x6f\xcc\xeb\xe2\x01\xe2\x9f\xd6\x9e\x20\xf5\x8f\x74\xb2\x9c\x5a\x92\x72\xdb\xd1\xdc\xd9\x88\x46\x0e\x23\x38\x9a\xef\x6e\x11\xc3\xcd\xad\x8b\x74\x60\xdc\x52\x8b\x37\xe4\x57\x35\x2e\xef\xa4\xa9\xa0\x29\xa1\xa7\xee\x89\x57\x9d\x46\x6e\x2b\x7c\xf0\x79\xbd\xf9\x69\x63\x30\x10\x2f\x56\x6b\x14\xde\x23\x38\x88\x7c\x56\x3c\x53\x60\x3c\xf3\xf1\x07\x16\xbd\x94\xcc\x32\xa6\x60\x09\x4e\x7b\x6a\xdc\xa2\x43\x2e\x53\xb4\xe9\x0e\x82\x8a\x1a\x64\x4c\xc1\x1e\x82\x30\x41\x35\xa6\x6e\xf1\x37\x5e\xcc\x15\xce\x5b\x3b\x5e\xf0\x5a\x3e\x17\x0b\x9c\xfa\x65\x04\x5a\x54\x3d\xc9\xd4\x7e\xc8\x4a\x9d\x82\x8e\x33\xbc\x3d\x0e\xcc\x16\xe6\x42\xb3\x07\xba\xd0\x80\xf7\x95\x34\x1f\xbe\xef\xb2\xaa\x55\x03\x7f\x64\x13\xec\xdd\xfa\x46\x6c\xa7\x3b\xb1\x5d\x6e\xc5\x20\x9c\x92\x8b\x36\x2e\x48\x55\x87\x8d\x85\x43\x9a\xcf\x2e\xd7\x68\xe0\xa7\x02\xd7\xe7\xdd\xee\x44\xea\x75\xca\x6f\xae\x61\x08\x2f\x93\x4f\xe1\x0f\xcf\x71\xc2\xa5\xc1\x98\x59\xac\xae\x02\xa5\x01\x43\xe2\xbe\x2b\x3c\x09\x2a\xd4\xfa\x16\xb2\xb1\x3a\x2b\x71\xa8\x34\xa6\x18\x78\x82\xc0\x17\x47\x50\x8e\x80\x8a\x85\xe3\xe4\x66\xc6\x55\x3a\x2c\xa8\x32\x0b\x54\x1f\x07\xb5\xaf\x05\xf7\xfa\x4e\x0b\xdf\xf1\x3a\xa7\x5d\xea\xe3\xb5\x10\x86\xc5\x7b\xf3\xb0\xb3\xce\xaf\x85\xeb\x53\xac\xa7\xbd\x03\xff\xca\xf5\xc4\xa9\x45\xbd\x46\xf8\x6c\xeb\x49\x63\xf2\xb1\x3f\xdf\xb0\x34\x48\xd7\xaf\x5e\x91\x0d\xc4\xa5\xab\x64\xec\x05\x1d\xb8\x3c\x28\x44\x76\xa4\x81\xd5\x43\x69\x55\x6b\x3c\x32\xec\x39\x49\xc1\xfb\xd0\xb8\x4a\x47\x62\xe1\x4c\x37\xf1\xb7\xe2\x01\xc2\x29\x21\x27\x42\x0a\x3c\x39\xd8\xf6\x14\x5d\x88\xd6\xd8\xa6\xa0\x89\x2b\x51\x57\xaf\x10\x1a\x9d\x54\xcf\x24\xb8\x48\xed\xd6\x01\xe5\x06\x1d\x49\x97\x49\xc2\x58\xd0\xaa\xe3\x12\x35\xd5\xc9\x76\x53\xf6\xa5\x2e\xb5\x84\x24\x2e\xda\xd0\x2c\xab\xb4\x59\x07\x2e\x09\x7c\xce\x5b\x00\x23\xf6\x57\x0b\xb4\x71\x8a\x3d\x14\x51\x47\xb7\x97\x52\x24\x78\x85\xcf\xcd\xc2\xcf\xe0\xb2\xc9\xea\x41\x8d\xd0\xa8\xe4\xf2\x09\xda\x9d\x22\x75\x20\x00\x13\x48\x93\x2b\xe1\x5e\xe7\x4c\x2e\x37\x83\xa5\x43\x63\x9a\xdc\x3f\x50\x95\x42\x29\xdf\x82\x1a\x8e\x69\xc1\x07\xb5\x61\x4f\xa2\x39\x40\x21\xfd\x18\x8b\x4e\x83\xd2\xa1\x59\x48\x41\x5d\x7d\x86\xd0\xd2\xc8\x9c\x1a\x9e\x80\x2a\xcb\x27\x91\x15\x31\x0f\x29\x0d\x1b\x65\x07\x81\xca\x86\x02\xf6\x77\x78\x1b\xa3\x18\x31\x0f\x92\xf0\xdc\x4a\x08\x14\x4a\x69\x4c\x42\xc4\x90\xb7\x77\x6e\x9a\xa9\x15\x83\x7e\x00\x23\x73\xd4\x0a\x95\x64\xab\x42\x69\x18\x3e\x58\x34\x83\x29\xcf\x85\xdc\x0c\x1a\x0c\xdc\xf5\xb1\x38\x6d\xe7\x1a\xa1\xea\xc0\x6e\xcf\x03\xb3\x72\x81\xde\x88\xb0\x7a\xb4\x6a\x46\x58\xd3\x56\x93\x94\xeb\x46\x61\xea\x93\x54\xc9\xa2\x70\x06\x92\xfc\xb4\x39\x23\xb8\x37\x50\x73\xa6\xa3\xda\xcb\x68\xaa\x9e\x32\x11\x8a\x87\xbb\x74\x16\x70\x72\x9b\x9f\xa8\x1d\x98\x11\x06\x84\x9e\x92\x4f\xae\xa8\x50\x40\xdc\xe0\x75\xd7\x4a\x70\x42\x6b\x8b\x93\x9d\x7a\x89\xa7\xed\xd3\x4b\x3c\xbd\xc4\xf3\xf3\x96\x78\x82\xbb\xd7\xae\xd2\x4e\xe5\xe3\xd8\x28\x48\xee\x9d\x01\xaa\x06\xeb\x8c\x18\xd7\x13\xf2\x91\x25\x72\xce\x14\x12\x39\x28\xfc\x69\x79\xf9\x5b\xca\x33\x4b\xe2\x3c\xa9\xab\xd4\x43\xc8\xa8\x5a\x37\xcd\x45\x1a\x79\x80\xa6\x43\xf3\xdc\x4d\xca\x45\xfa\xd9\xf6\xee\x92\xac\x50\x6c\xce\x65\xa9\xbd\xcb\x42\x69\xf0\x98\x69\xe3\xf8\xed\x8c\x4f\x43\x62\xee\x70\xd5\xa9\x58\x22\x55\x5a\x85\x94\x6b\x43\x4d\xa9\xeb\x71\x12\x09\x5a\xd3\x0e\x67\xa0\x09\x70\x7c\x64\xea\xbe\x1b\x25\x45\x8f\x8d\x3d\x4e\xc5\xf1\x3b\xf4\xf9\xa8\xea\x6e\x9b\xc8\x0d\xa5\x72\x81\xb1\x22\x54\x69\x58\x84\x56\x0e\x01\x3a\xc3\xba\x16\xf5\x7a\x86\x85\x5b\x86\x61\xd8\x61\xe5\x75\xd2\x22\xe3\x7a\xfc\xec\x04\x75\xb2\x47\x80\x67\xfc\xbc\x60\xc7\x93\xc6\x62\xbb\x7b\x5f\x92\x3d\x3d\x30\xc9\x3e\x5e\x98\xe4\x90\x9e\x98\x24\xf8\x73\xef\x73\x62\x3e\x7a\x4f\xf2\xc6\x99\x71\x84\x77\xd3\x99\xa9\x25\x14\x08\xe3\x70\xed\x2b\x40\xba\x6b\xcd\x70\x06\xc0\x24\x18\xfb\x03\xbb\xd3\x0a\xda\x1c\xde\x5d\xb2\xcf\x21\xeb\x6f\x24\xc7\x54\x45\xb5\x8d\x04\x0f\x84\xbc\xc0\x4c\x40\x70\xea\x86\xce\x25\xcb\x6b\x4b\xfd\x09\xee\x4f\x70\xdb\xfe\xcf\x79\x82\xd1\xe3\xb9\x8b\x43\x7e\xa3\x52\x10\x76\x77\x41\xb8\x74\xcc\x32\xf2\x63\xc9\xd4\x82\x58\x21\xa8\x72\xef\x81\xf4\xc6\x9a\xa7\xce\x41\xc6\x19\x55\xda\xcb\xec\x4f\xc8\xff\xc1\x64\x73\xf5\xd9\x4a\x80\x10\xc7\xb6\x07\x5d\x6b\x0e\x55\x0f\x55\x46\x68\x05\x08\xc6\x12\x1e\xde\x30\xd6\x64\x3e\x2b\xee\x9d\x7f\xb8\xdc\x4d\xd1\xe9\x76\xa9\x45\x76\xb9\xd8\x5a\x5a\xfc\xf9\x86\x05\x22\x20\xc2\x2f\xf5\x6a\x52\xc1\x14\x41\xee\xd9\x62\xe0\xee\xc1\x5d\xf6\x76\xdf\x18\xdd\x39\xea\x29\x45\xdb\xa6\xaa\x58\x05\xa0\x1d\x28\xe4\x6e\xd6\x03\x7c\xda\x27\xa1\xac\xf7\xf2\x40\xe8\x4a\x88\x77\x26\xe1\x9d\x92\x55\xc6\xcf\xba\xc4\x95\x88\x13\x90\x81\xcf\xfb\x35\x07\x34\x00\x5f\x6e\xa0\x16\x5d\x37\x91\xec\xae\x02\xe3\xe3\x01\xbb\xf7\x52\x03\x9a\xd6\x1c\x73\xef\xd9\xe2\x58\xbb\xa8\x41\x29\xf4\x8c\x17\x3e\x3f\x3c\x50\x02\x87\xb9\xe4\x7b\xf0\x0f\xf0\x43\xe0\x99\xbf\x16\x03\xf2\x41\x1a\xfb\xbf\x2b\x70\x15\x42\x4b\xa5\x64\xfa\x83\x34\xf0\xe6\xc9\x81\x85\xd3\xdd\x1b\x54\xce\x4c\xc9\xc1\xcc\x88\x2e\x6d\x10\x9f\xe1\x5d\x50\x00\x24\xee\xbe\x35\x80\x95\x6b\x72\x2d\x88\x54\x1e\x26\xc6\x27\x0f\xd6\x6e\x08\x6f\x5b\x8a\x2c\xc2\x2b\xc6\x70\xa0\x94\xaa\x06\xc9\x0d\xc3\x05\xe3\x32\xf7\xbf\x80\xed\x09\xac\xf1\xc1\x6f\x06\x52\xe0\x52\xc3\xa6\x3c\x21\x39\x53\x53\x88\x0f\x4d\x66\xbb\x6f\x50\x77\xba\x8d\xcf\x4e\xd4\x3b\xfe\x70\x67\xcc\x00\x56\xf7\x0e\x3c\x97\xf6\x65\x98\x38\x0a\xb2\x88\x9c\x16\x16\x29\xfe\x61\x39\x01\xec\xcb\xbf\x20\x65\xb5\x1e\x91\x73\x5f\xf0\x34\xfe\xcd\x59\x31\xe2\x61\xec\x08\x56\xa6\xff\xb1\xe4\x73\x9a\x31\xf4\xe7\xa3\x22\xa4\xf1\x94\x93\x25\x36\x3d\x70\x79\xab\x2d\x95\x0a\x37\x43\x47\xf7\x6c\x71\x34\x58\x42\xa4\xa3\x6b\x71\x54\x05\x69\xd7\x50\x27\x30\x34\xb8\x34\x38\x82\xdf\x8e\x0e\xcd\xd9\x9f\x49\xb4\xdf\x01\x4b\x9c\x41\xe8\x22\xa3\x5a\x77\x8b\x6f\x6d\x84\x16\x35\xc6\x59\x95\x80\xf1\x36\x6a\x53\x05\x17\x39\xef\xcd\x83\xdb\xb3\xc0\xcb\xbf\xbb\xa7\x51\x27\xe8\xcd\x5d\xf5\x94\xf6\x89\x1b\x56\x26\x14\x83\xb4\x05\x3e\x86\xa3\x16\x17\x57\x5d\xc6\xae\x81\xd7\xf7\x60\x57\x94\x93\xb8\xc8\x33\xd7\xa0\x06\x73\x1f\xd5\x21\xa4\x21\x5c\x24\x59\xe9\x4c\x8a\xd0\x15\x94\xe8\xae\xa2\xfe\x0e\xc0\xd9\x03\xa9\xaa\x01\x3c\x36\xf9\x6b\xdf\x25\x07\xde\xe6\x0d\x1d\xdc\x89\x86\x1b\x2f\x84\xd5\xa1\xd7\x3a\xd9\xe2\x2e\x59\x4f\xc6\x99\xd4\x65\x8f\xb7\x7c\xac\x18\xb9\x98\x51\x21\x58\x16\x45\xbb\x3a\x63\x47\x28\x67\x05\x02\x89\x2b\x62\x75\x5c\xaf\x62\xe5\xe9\x9b\x08\xb1\xd5\x07\xaf\x1d\xfc\x53\x2a\x2a\x75\xb0\x3a\xe5\x2e\x55\xe3\x4c\x3e\x90\x54\x92\x07\xa8\x5b\x30\xb7\x4c\x0b\x2e\x65\xb5\x67\x77\xd1\x4c\xc1\x45\x22\x91\x79\xa1\x64\xce\xb5\x77\x8e\x77\xdb\x78\xd0\xd0\xd0\xac\x6c\x91\x03\xa8\xbe\x07\x59\x29\xea\x29\xe1\xdf\x5e\x10\x43\xd5\x94\x19\x3b\x1a\x11\x65\x3e\x66\xad\xe3\x57\x1f\x23\x07\xd9\x97\x54\x42\xf4\xb0\x45\xb0\x70\x1b\x7e\xf8\xe1\x43\xe7\xd2\xbb\x55\xcf\x75\x7b\xfb\x20\x55\x96\x3e\xf0\x14\x59\xb4\x26\x27\xb6\xf1\xe9\xcb\xaf\x94\xfb\xf0\xc0\xd3\xce\xe0\x80\x4e\x75\x30\x78\x3f\x28\x0b\x06\x02\x70\x70\x15\x9e\x38\xa4\xd1\x86\x1e\xa7\xe4\x8a\x63\x74\x11\xf4\x87\x44\x35\xf9\x98\x8b\x2a\xc2\xac\x02\xb3\x25\xc6\xf6\xbc\x78\xd5\x44\x33\x83\x71\x21\x10\x5a\x21\xcd\x8c\x68\x9e\x97\x99\xa1\x82\xc9\x52\x67\x8b\xd6\xa8\xf2\x3c\xa0\x9e\x64\xec\x33\x62\x76\x17\x26\x17\x3a\xd5\x99\x1d\xb8\xae\x54\x61\x94\x4b\xdc\xae\x72\xae\x4a\xcf\x02\xe7\x0b\xe1\x46\xec\x33\x4b\x9c\x57\x70\x91\x95\x53\xbe\x25\xfc\xe1\x67\x96\xd5\xbc\x4a\x20\x5d\x6a\x56\x45\xea\xb7\xad\xeb\xf2\x44\x49\xc8\x9f\x97\xc3\xdf\xad\x4e\x40\x9e\xb2\x82\x89\x14\x52\xa2\xbd\xad\x30\x17\x27\x7f\x50\xc8\xb9\xf4\x62\x5d\xa9\x96\xcf\x4a\x56\xa3\xe0\x91\x0b\xd7\x4c\x66\xa9\x26\xec\xb3\x51\xd4\x12\xa6\xdc\x92\xa0\xd0\x67\x42\xa8\x68\x4f\x64\x5e\x46\x8a\x60\x72\x70\x6e\xff\xb8\xf5\x32\x5f\x62\xc9\xcb\x6a\xed\x7a\x63\xc1\xea\xfd\x52\xd7\x23\x21\x76\x67\x45\xd7\x3d\x84\x57\xa4\x98\x77\x5f\xa9\x7b\x26\xee\x97\x6a\x5e\xaf\x48\xaa\xdd\x98\x55\x5f\xa6\xf3\x8b\xc8\x3b\x3f\x81\xc0\xe0\x2e\x49\x98\x5c\x8f\x86\x46\xed\x5e\x36\x0b\x42\x6f\xd0\xa0\x1d\xde\x46\x7c\x00\x32\x9e\xba\x81\x5c\x58\x13\xd1\x16\x96\x95\xeb\x5c\x29\xc4\x36\x2a\xf6\x18\x59\xc4\xa9\xa1\x9a\x99\x76\xd6\x94\xba\xe8\x50\xf5\xb4\x07\x30\xc6\x2f\xf7\x13\x66\xb1\x07\x87\x74\x1f\x2c\x4b\x86\x7f\x74\x52\x86\xa8\xb5\xb4\xf2\x85\x87\x8f\x4f\xd2\xc4\xc2\x2d\x32\x8e\x91\xda\x5d\x49\xa8\x69\x5d\x72\xa7\x15\x5f\x70\x33\xf8\xf4\xa9\x73\x2d\xd7\xa8\xa7\x97\x43\xe0\xdf\x75\x20\x38\x5c\x80\x44\x3e\xfc\xc7\x32\x56\x07\x20\xb9\x45\x58\xb6\x6b\x7f\xa8\xb5\x4d\x13\x56\x19\xaf\x2e\xb9\xbe\xef\x92\x8c\x6c\xa9\x73\xfd\x48\x7c\x73\x71\x45\xdc\xdb\x56\xf6\xa5\x2e\x06\xa6\x7d\x33\x63\x4d\x13\x56\x19\x6d\x53\xae\xef\x9f\xbc\xac\x7a\x91\x7e\xd8\xe6\x01\xfe\x74\xf6\xaf\xa6\xd4\xeb\x53\xb4\x44\xb9\x83\x16\xb2\x24\x0f\x2e\xf5\x81\x93\x9a\xef\x78\xf1\x86\x5c\x09\x5d\x2a\x56\xdd\xdc\x36\x87\xb2\x5c\xf7\x25\x95\x5e\xdf\x0b\x4b\x5e\xb2\xf1\xad\xa0\xca\x80\x78\xdc\x15\x0d\x42\x47\x4f\x9f\xa2\x17\xa2\x0d\x1e\x5c\x4f\xbc\x63\xdd\xc0\xc5\x78\x87\xc4\x65\xbe\x91\xdd\xf9\x28\xad\x49\xbc\xd7\x6f\x43\xca\x1f\x72\x96\xb2\xf9\x99\x4e\xe9\xeb\x01\x7c\xc6\x3b\x3c\xd7\xe7\x44\x35\x39\x7a\x7d\x34\x22\xb7\x3c\xe7\x19\x55\xd9\xa2\x96\x8a\xb9\x6a\x67\x99\x85\x1f\x10\x6e\xe5\x5e\x1d\x91\x13\xa9\x60\xe4\x84\x0a\x92\x31\x1f\xd1\xe4\xce\xd9\x02\x65\xc7\xd3\xa7\x26\x2e\xe4\x51\xed\x97\x48\x67\x3a\xe3\x44\xea\x39\xb6\xe3\x47\xb5\x74\x36\x97\x15\x49\xe7\xc2\xd2\xf9\x11\xf9\xb4\xaa\x50\x39\x1c\x19\xdf\xe2\xb9\x80\xfa\x34\x7a\xdf\x4e\x1a\xdc\xb2\x39\xf8\xf9\xc0\xb4\x5d\x4b\x9c\x72\xf3\x91\x15\xb2\x93\x84\x80\x5d\x1a\xf6\x38\x6e\xec\x0b\xa9\x39\x24\x2a\xa5\x06\xca\x02\x2b\xc3\x93\x32\xa3\x56\xac\x46\x6b\xdc\x88\x5c\x5e\xdd\x7c\xbc\xba\x38\xbf\xbb\xba\x7c\x43\xbe\x71\x23\xf1\x58\xc2\x1b\x91\xbb\x38\x1b\x54\xe4\xd1\xeb\x52\xee\x84\x6f\x0d\x1c\x19\xa2\xa2\x4a\xee\x08\x39\x3e\xa8\x20\xd7\x82\x9b\x2a\x3d\x32\xfa\x9d\x65\x52\x30\x5f\x3d\xb4\x90\xce\x1a\x38\xe5\xe8\x0d\x22\xdc\x60\xf6\xe7\xfa\x68\x70\x3a\x30\xd5\x6a\x98\xca\x16\x45\xf0\x11\x44\x8b\x0a\xb8\x87\x12\xff\x7d\xfe\xd3\xae\xb2\x6f\xc8\x46\xeb\x03\x9c\xd0\xfa\x5f\xbd\x47\x66\x10\x12\xb3\xfb\x74\x37\x2b\x4a\x5a\x13\xcb\x66\x8e\x47\xc7\x5e\xa0\xc8\x96\x92\xf0\x87\x41\xe3\x8c\x5e\x75\x64\x1b\x11\xf2\x9d\x77\xd9\x86\xd0\xe3\xd5\xf9\xfc\x31\x3b\x44\x94\x15\xbe\x81\xb2\x3e\x30\xa6\x1c\xc7\x1f\x75\x29\xc0\xa6\x7c\xce\x04\x2e\xec\xb0\x14\xca\x7f\xbe\x73\x75\xb4\x6a\xde\x4e\xff\xf8\xf8\xee\xb0\x33\xc3\xf3\xd7\x79\x5e\xee\xd8\xba\x59\x25\x32\xcf\x31\x5f\xd4\x2c\x04\x18\x56\x31\x82\x81\x2a\x1c\x4c\xf3\xc1\xcc\x57\x93\x2d\xc8\xdf\xa0\x67\xbe\x53\x43\xd3\x09\xaf\x5d\x50\x82\xa8\xc4\xdc\xee\x79\x98\x5d\x92\x35\xed\x93\xa7\x38\xd2\x7e\x16\x3e\x7e\xf6\xf1\xea\xfc\xf2\xfd\xd5\x28\x4f\x9f\x9c\xb4\x30\x91\x16\x92\x0b\xa3\xb7\xeb\x37\xdb\xaa\xce\xb4\x27\x3f\xe1\xa3\x5d\xb9\x73\xe8\xe8\x71\xcc\xbf\x88\xf2\xd2\xa5\xcc\x50\x9e\xe9\x68\x0f\x8d\x2c\x64\x26\xa7\xab\xd3\x2f\x77\xd8\x9c\x5f\x60\x7e\x99\x21\x1d\xda\x5d\x3f\xac\xa8\xdf\xa6\x8e\x46\x53\xca\xaf\x2a\x62\x57\x6b\x0d\x52\x33\x94\xbb\x78\xa1\xcb\x7d\x14\xe1\x6c\x09\x06\xa8\x48\xc2\x01\xf6\x29\xfb\xaa\x1c\x78\x51\x0d\x9b\xb6\x52\xdb\x63\x83\x6e\xbb\xc0\x66\xe9\xcf\xf6\x42\x45\x75\x98\xf9\x3e\x75\x02\x57\x28\x36\x0c\xe9\x9a\xa0\xb4\x8a\x54\x11\xc3\x8d\xe9\x9d\xb7\xde\x78\x5b\x0f\xb6\xca\x16\x4d\x2b\x4e\x25\x1f\x05\xd3\x17\xe6\x18\xc8\xb2\x45\x95\x06\xd2\x69\xd1\x74\x8a\x69\x98\x94\x33\x13\x17\x8a\xcf\x79\xc6\xa6\x90\x8a\x95\x8b\x69\x14\xfe\x1a\x07\xcc\xba\xd4\xac\x75\xa3\xeb\x7b\xfb\x57\x94\x74\x1b\xf0\xe2\xc3\x77\x77\x90\xd5\x17\x2e\xb8\xf6\x16\xc2\xed\x07\xe1\xbc\x0d\x87\x43\x30\x19\x9c\xfc\xcd\xca\x93\x69\x76\x4a\x7e\x60\xee\x3b\x12\xd2\x0e\x2b\x28\x05\x34\x93\x21\x07\x2c\xcc\xb5\x82\x2c\xa0\x23\x5e\xef\xbb\x56\x67\xb6\xa5\x95\x95\x90\xd5\xd4\xda\x43\xe5\x53\x4c\xdd\x88\x77\x4c\x4f\x2f\x7b\x1e\x90\xec\xef\x4c\xe5\xbc\x69\x75\x15\x7e\x86\x8b\x1f\x4f\x0f\x29\xd1\x8b\x3c\xe3\xe2\xbe\xca\x0b\x36\x91\x16\x87\x30\x34\x81\x8b\x7b\x8f\xb1\x8a\xd1\x6c\x3d\xa5\xdc\x05\x3f\x0e\x4a\x25\xcd\x0e\x16\x40\xb0\xd0\xd9\x73\xf6\x27\x7f\xec\xdd\x35\x74\x4c\xe2\x8e\x8e\x5e\xdc\x7a\xb9\xee\x56\x06\xff\x18\x3a\xd4\x68\x9a\x20\xd7\xb7\x17\xb7\xd7\x4f\x6a\xa1\x5e\xc7\x12\x60\x76\xcf\x28\xd5\xf1\x1f\xb7\xdd\x0e\x0f\x49\x56\x6e\x6f\x83\xea\xdd\x8d\x54\x86\x66\x07\x22\x02\xc9\x8c\x16\xe7\xa5\x99\x5d\x72\x0d\x39\x14\xba\x0a\x01\x4b\xfd\x23\x4f\x67\xcc\xdd\xec\x13\x06\x72\x8f\x0e\xae\xdd\xc5\x9f\xce\x6f\x08\x2d\xed\xfe\x1a\x97\x5c\xf4\xa0\x17\xee\x7e\x66\xb7\x18\x61\xb0\xe3\xba\x5c\xef\x2d\xab\xf2\xad\x1e\x7b\x4d\x8f\xe1\x87\xdb\xdf\x45\x00\x0d\x45\x0a\xf6\x82\xef\x1f\xb8\xe0\x86\x53\x23\x5b\x16\x2a\xab\xa1\x40\xad\x6f\x30\x08\x94\xda\xc8\xdc\x61\xf0\xb5\x6f\x01\x57\xc8\xc0\xc5\x97\x3a\x55\xd6\x02\x90\xde\x01\x62\xd7\xc2\xca\xda\x34\x61\x0d\x07\xc8\x01\x24\xfd\xc4\xb1\x79\x68\xf3\x07\x67\xa0\x82\xfc\x60\xd9\x1f\xdf\xd4\x52\xb1\x2f\xd5\xb5\xf0\x56\x8a\xaa\x68\xc2\x41\x2d\x3e\xfc\xc7\xae\x44\x81\xff\x28\x1a\x96\x36\x5c\xe0\x7f\x95\x34\x43\xc0\x7c\x38\xb4\x59\xaa\x0e\xe4\xae\xf3\xad\xef\x90\x9b\x7a\xb5\x1d\x1f\x82\x96\x5e\x6a\xcc\x3c\x86\xeb\x31\x8a\x0a\x6d\xf7\xa8\xae\x8b\x1d\xbb\x8b\xa7\x63\x72\x62\x92\xa2\x75\xed\xfe\x47\x72\x6d\xcf\x4a\x51\x2b\xe4\x0c\x33\xbf\xc3\x6d\x79\x17\x5c\xdb\xdb\x4e\xf2\x51\xae\x86\x00\xcb\xbb\x5a\x55\x5c\xaf\xb0\x5b\xf1\xba\x90\xf5\x93\x77\x5c\x1b\x5f\x90\x01\x5e\x70\xed\xf2\x08\x83\xdc\x75\x63\x15\x39\x5e\xfc\x2f\x4d\x53\xf5\x06\xb9\x94\xaf\xbe\xac\x40\xfa\xf2\x49\xbe\xa8\x08\x77\x89\x27\x66\x51\xb8\x04\x80\x77\x17\x37\x04\x0b\xa4\xfc\xfe\xb7\x58\xf9\xf5\xdf\x7f\xfd\xdb\x57\xad\xb7\xfb\xf9\x9c\xc7\x77\xb4\x63\x1c\xfc\x8e\xe9\x45\xf8\x0d\xd6\xfc\x03\xed\x4a\x40\x36\xb9\x45\x77\x3c\x4b\x59\xdd\x51\x47\xc4\xb2\xbb\x1c\xe8\xfd\x6e\x12\x4c\xef\x67\xf7\xac\x7e\x76\x24\x44\x94\x20\x91\xe8\x88\x2e\x71\x57\x08\x31\x5c\x26\x3b\x48\x71\x6e\x5e\x1e\xc5\xd9\x0a\x9b\xed\x58\x54\xc7\x9e\xf8\x32\xde\x97\xbf\xa9\x5c\xd8\x2f\x3f\xdc\xfe\xef\xbb\xf3\xaf\xaf\xde\xc1\x4c\xdd\xfd\xbd\x45\x0d\x2e\x76\xf6\x9f\x6a\x8f\x6a\x6d\x94\xd7\xed\x00\xe9\x76\x2d\x23\x1a\x17\x32\x82\x7c\x78\x7b\xdb\xf5\x2e\x66\x5f\x01\x5d\x4c\x5a\xad\xfd\x69\xad\x6d\x50\xd5\x84\xa9\xc3\xc5\x8f\xec\x6c\x94\x8b\x12\x69\xd5\xf4\x2f\xbb\x53\x38\xc3\xbd\x55\xa4\xad\x3b\x40\x5e\xc0\xbd\x83\x5d\x2f\xc2\xe0\xe0\x37\x0e\x8f\x04\xab\xb6\x72\x80\xea\x1e\x58\x74\x8c\xbd\xbc\x08\x60\x0f\x29\xd2\x36\x65\x69\xb6\xa5\xd6\x4c\x87\xea\x0b\x2f\x14\x53\x8a\x55\xe9\x99\xbb\x50\xaf\x95\x03\xd4\xca\x95\xd5\xee\x62\x6a\xb1\x14\xeb\xd2\x99\x7b\x0f\x05\xea\x94\x57\x5d\xd0\xe4\xa0\x05\x55\xaa\x57\xf8\x06\x82\xdc\x9f\x9e\x00\xc2\x67\x0f\xe8\x48\x1b\xc6\xeb\x8a\xc8\xa1\x63\x33\x4a\xae\xd3\x0e\xf9\x42\x1f\x85\xf4\x11\x88\x71\x38\xdd\x33\x6f\x1f\x79\x5a\x6d\xe7\x87\x1d\x15\x9d\x43\x2b\x39\xc5\x4c\x1a\x29\x76\xf6\x92\x5f\xd5\xbd\x7e\xa0\x6f\xa0\xc5\x45\x55\xc6\x26\xaa\xf1\x08\x1e\x94\xe1\x32\xc2\xca\x73\x9e\x5d\x48\xe1\xaf\x25\xea\x97\x12\x4f\x2e\x82\xa4\xd7\x97\x07\x3a\x7c\x5f\x6e\x88\x67\x57\x63\xf0\x41\x9d\x41\xd2\xce\x31\x29\xb6\x8b\x87\xd8\xf5\xa5\x13\xcd\x7c\xc0\x89\x76\x08\x49\xd6\x63\xe4\xc1\x58\xa7\x54\xe6\x41\xaa\xee\xa1\xde\xf5\x8e\x0d\x5f\x05\xf7\xdb\x52\x28\xd6\x4b\x3c\x3d\x38\xc7\x67\x3e\x41\xb7\x70\x82\x1a\x09\xce\xd7\x9d\xa4\xc7\x38\x48\xcf\x7b\x80\xf6\x65\x54\x8f\x1b\xe5\x7b\x50\x21\xdd\xa3\x5b\xc7\xa5\xfa\x6e\xce\x98\x60\x37\xa9\xa2\x16\x14\x4c\x2e\xd1\x89\x3b\x18\x75\x50\x12\x4b\x50\x76\x21\x0c\xbe\x0f\x1a\x70\x31\xd1\x73\x96\x59\xa8\x4a\x11\xa7\x88\x76\x61\xbc\x03\x82\x59\x96\x73\x5a\xf8\x9a\xdc\xf2\x41\x3c\x50\x95\x92\xf3\x9b\xeb\xc3\x50\x83\x0e\x7e\xd6\x88\x49\xed\x32\x7a\xd5\x3d\xad\xab\x9e\x58\xe6\x66\xc6\xa0\xb6\x22\x19\x73\xa3\xab\x9a\x7e\xcc\xc4\x7a\xa5\xa5\x82\xe1\x2e\xcb\x9e\x65\x7b\x6e\xdd\x48\x11\xc3\x14\x44\x26\x86\x66\xbe\x88\x80\x2b\x93\xf3\xea\xd5\x2b\x34\x85\xbd\xfa\xdd\xef\x7e\x87\x95\x95\x52\x96\xf0\x7c\xb9\x21\xb4\xfa\x3f\xaf\x5f\x8f\xc8\x7f\x9f\xbf\x7f\x07\x95\x1f\x0b\xa3\x31\x2b\x09\x8e\x8c\x95\xe0\xa3\xce\x7a\x40\xfe\xef\xed\x77\x1f\xaa\x32\x31\xf5\x5f\x5d\x41\x6d\xb7\xbc\x11\xb9\x8c\xfc\x9f\x62\x43\x17\x35\x33\x57\xd0\xc8\x10\x3a\x99\x20\x62\x8c\x7d\x39\x5d\x3c\x70\x3e\x7a\x1c\xaa\x82\x63\xfd\x11\x8b\x12\x19\x38\x66\x59\x95\x1c\x4d\x83\x3e\xb3\x01\xfa\x99\xc1\x58\x81\x4c\xc2\x54\x06\x58\x4b\x7e\xa2\xa1\x0a\x49\x95\xfe\x4f\x31\x6d\x85\x52\x57\x5d\x11\x07\xab\x76\x46\xb3\xd6\xb9\x1e\x1e\xe3\x06\xa8\x75\x75\x8c\xba\xe9\xde\x9d\x21\x9f\xbe\xd5\xe5\x2e\xae\xca\xd4\xff\x0d\x6f\x43\xb7\x39\x09\x3f\xd2\x8d\x4c\x6d\xae\x37\x61\x36\xb8\x75\x2e\x4b\x40\x45\x27\x68\x26\xa1\x92\x57\xd8\xe9\x8a\x8b\x45\x45\xef\xb7\x2f\xa5\x73\xf2\xc5\xae\x09\x78\x91\x50\xbd\xa7\xad\xcb\xf9\xd4\xfd\x45\x7c\xef\x5a\x5e\x05\x3a\x96\xa5\xf1\x77\xd8\xee\x77\x08\xc0\xc6\x2a\xeb\x1d\xd2\x48\xee\x90\x79\x72\x97\x0c\xc4\x9d\x93\x98\xd6\xef\x9b\x81\x27\xd4\x45\x89\x01\x61\x34\x99\x91\x7b\xb6\x18\x22\xdd\x2a\x28\x44\xf3\x00\x54\x2e\x2d\x2c\x6a\x85\x4f\xaa\xda\x35\x56\x3e\x76\x20\xf3\x8e\x01\x11\xf7\xf1\xd1\x40\x5e\x08\xd5\x4e\x5e\x72\x69\x44\x45\x64\x29\xf0\xb9\xaa\xa3\x7a\xc4\x21\x6f\x28\x16\x23\xaf\x07\xa9\xd8\xf3\xc6\x52\xdb\x4d\x6f\xfa\x72\xe5\x0d\x61\xe9\xa0\xe3\x6e\xa5\x58\xea\xed\x8a\x6f\x3b\xe1\x0f\x3e\x48\x7d\x76\xe6\xc8\xa3\x02\xca\xf9\xb9\x4a\x4e\xae\xad\x87\x52\x00\x44\x2d\x88\x46\x33\x53\x3a\xd0\x60\xbd\xb0\x52\x64\x4c\x6b\xc2\x61\x85\x39\x55\xf7\xcc\x27\x8c\xa1\xd9\x88\xdc\xd8\x49\x86\xfc\x55\x98\x16\x79\x8e\x2e\x76\xf6\xcc\xc6\xd1\x41\xf6\x23\xc7\xa3\xd1\x31\x12\xf8\x15\xb1\x42\x1d\xf0\x63\xb7\x9c\xba\x3b\xe4\xd2\x6d\x94\xf6\x2e\x34\x66\x06\xb6\x22\x1f\x64\xbe\x96\x10\x05\x67\x66\x9e\x81\xd1\xd6\x49\x94\x96\x97\xb3\x43\x02\xd8\x5d\xf3\x96\xef\x92\xb5\xbc\xd5\xbd\x45\xfd\xd9\x3d\x5b\xf9\x4e\xb9\xca\xd7\x65\x2a\x77\x3b\xe5\x4e\x5b\xf7\x1c\xce\x7b\xa4\xd8\xce\x3b\xa5\x79\xf5\x4f\xdd\x48\x09\x72\x47\x2d\x4b\x4f\x2b\x19\xd1\x25\x7d\xca\xd8\x17\x25\x14\x5e\x4f\x56\x55\x9d\xf3\xc1\x82\x91\xbc\xec\x69\xa8\x85\xc0\xf3\x4b\x83\xdd\x6a\xb9\x90\xce\xe2\x61\xf3\xe9\x22\x2e\x36\x9f\x76\x97\x81\xcd\xa7\xae\xb0\x45\x61\x49\x81\xe8\xc7\x5e\xfc\x00\x52\x23\x21\x67\x77\x75\x04\x47\xe4\xbd\x63\x0a\x88\x8c\x74\xac\x65\x56\x9a\x10\xc9\xb4\x82\x63\xc0\xa0\x3e\xc3\x37\x86\x94\xfa\x66\x11\xff\x00\xce\x89\x64\xb9\x2b\x2b\xc1\x67\xa7\x23\xde\xb5\xe6\xde\x4f\xd6\x99\x64\x0f\x18\x7a\x51\x62\x67\x38\xfa\x01\x42\xde\x09\xef\x4b\x5d\x93\x71\xc0\x93\xc4\x68\x14\xa0\xbc\xb8\xe2\x0a\x3d\x75\x5e\x62\x3b\xab\x8d\x9b\xab\x33\x4c\x9c\xdf\x5c\xef\xa4\x01\x44\xfd\xd7\xe8\x00\x71\x8b\x9f\xb0\x16\x70\x8d\x5a\x40\x5c\x76\xe7\xb2\x5a\xb9\x33\x29\x5b\xb2\xf3\xe2\xc5\xc8\xa5\x69\xbf\xb5\xc4\x32\x76\x3a\xad\xe7\xd0\x43\x63\x4f\x45\x56\xa3\xbc\x7b\xfe\xd6\x11\x0e\xf1\x4b\x17\x39\x9f\x50\x7c\x04\x78\x74\x2a\x97\xee\x9f\xe5\x6a\x76\xb0\x58\x72\x0b\xa5\x6d\x50\x1f\x8c\x14\xcb\x42\xa6\x6f\x5c\x29\x69\x21\x24\x16\x90\xd3\x03\xac\x8d\xa3\x07\xa8\x30\x5a\x29\x22\xba\x2b\x56\x91\xc9\x7d\x67\xb9\x61\xa7\x2a\x47\xfb\xd4\x39\xb2\x1b\x08\x2b\xbf\xe9\xba\x8b\x64\xcf\xb2\x45\x24\x62\x4d\xbb\x15\x42\xa9\xed\xa9\x1b\x29\xd4\x79\x4f\x66\x2c\xa7\x98\xc3\xcf\x2f\xcf\x52\x99\x07\xc5\x8d\x61\x98\x4b\x89\xa9\x5c\x13\x39\x19\xd4\xee\x0c\x8e\xe6\xaf\x8f\x76\x29\x07\xb3\x67\xc5\x1e\x52\xed\xc2\x01\x80\x71\x53\x13\xd9\x2c\x5e\x83\x2e\x91\x41\xe2\x4d\xd1\x30\x48\x58\x06\x33\x47\xe8\x3d\xf9\xc2\x0f\xa1\x47\xed\xaa\x3f\x0d\x82\xc0\xd0\xeb\x4f\xbd\xfe\x74\x10\xfd\x29\x62\x2c\x9e\xe0\xac\xd0\xa5\x62\x87\x61\xaf\x50\x55\x81\x4c\x51\x02\x1e\x8b\x9a\x5e\x95\x92\xaa\x6e\x71\xb3\xfa\xd0\xb1\x57\xb0\x1c\x1e\x97\x66\x32\xfc\x3d\x61\x22\x91\x29\x6e\xbe\x1d\x5f\x69\x03\xa2\x4d\xa5\x93\xc4\x73\xc9\xfd\xb7\x62\xab\x1d\x8c\xbd\xeb\xd6\xed\x44\x07\xfc\x55\xe0\xdb\x03\x31\xf8\x8a\xad\x87\x60\x62\x5f\x2b\xdb\xe7\x1a\x70\xfc\xbd\xba\x84\xc4\xb2\xd2\x80\xdc\xbe\x62\x2e\x39\xc1\x97\xa3\xa4\x28\x07\xae\xc1\x28\x67\xb9\x54\x8b\x41\x68\x64\x7f\xac\xf5\x72\x2d\x4e\x41\x26\x48\x4a\x65\x35\xc0\x6c\xf1\xa5\x4a\x07\x1e\x40\x4f\x2c\x1c\x84\x7d\xea\x56\x34\x28\x7e\xea\x28\x51\x25\x15\x03\xfd\xbe\x2a\xa2\x34\x09\x29\x0f\xf5\xa0\x52\x3b\xed\x5b\x26\xe6\x64\x4e\x55\x87\x2a\xe8\xf1\xb3\xa7\x3c\x90\xf2\x39\xd7\xbb\xd5\x3b\x6c\x2c\xfd\xd6\x31\x0d\xb4\xeb\xc8\xd2\x14\xa5\x71\x94\xd2\x9f\x0a\x1f\x32\x1f\x4e\x43\x43\x28\x7a\x7d\xb4\xd3\x34\xbe\x98\xfa\xc2\xf8\xec\x58\x65\x18\x9f\x7d\x6b\x0d\xd7\x47\xd9\x19\x6d\x0e\x5a\x39\xdc\x3f\x1e\x2d\x0e\x71\x0e\x2b\x16\x59\xe5\x79\xf0\xc2\xe9\x13\x1d\x34\x74\x37\xd9\xc9\x6e\xe3\x32\xd4\xaf\x36\xd9\xb8\x1f\x7f\xc2\xd6\x9a\xc3\xde\xd9\xba\xf8\xc2\x9f\xf9\x85\xed\xad\xab\x67\xd0\xdf\xd6\xb6\x42\xc1\xfe\xb6\xb6\xbf\xad\xed\x6f\x6b\x7b\x6b\x43\x6f\x6d\xe8\x6f\x6b\x49\x7f\x5b\x7b\x10\x18\x1e\xee\xb6\x16\x45\xbd\x55\x77\xb6\x4e\xd8\xab\x2e\x6c\x9f\xf4\xbe\xd6\x15\xee\x39\x4f\x12\x59\x0a\x73\x27\xef\x59\xeb\x4b\x87\x86\xfc\xbf\x34\x0e\x24\x40\x58\xa3\x0f\x2c\x37\x7e\x32\xe5\xa0\xbb\x54\xd2\x49\xb6\xd8\x45\xaa\xa0\x65\xca\xad\xe4\xbf\x33\x9a\xf9\x01\xe2\xe4\x44\x22\x65\x69\xf5\x83\x3b\xca\xc6\xc2\x7a\x44\xce\x89\x62\x09\x2f\xb8\x2b\x23\x4f\xf1\x3d\x22\x5e\xa8\x8d\xc0\x8d\x66\xd9\xc4\xe5\xa8\x17\x71\xad\x9f\x4a\x7e\x77\x74\x70\xe5\x67\x90\x43\x49\x9f\xc9\xdc\xd7\x42\x52\xec\x6f\x9e\xb5\xb9\xd9\xdc\xc5\x23\xc4\xe6\x15\x58\x4a\xad\xc4\x10\x7c\xac\xe0\x2e\xc0\xfa\xb1\x8f\x3f\xfb\x5c\x70\x05\xc8\x7b\xcb\x12\x29\xda\xd4\x54\x5d\xb3\x41\x4b\x23\x55\xfc\x09\x6c\xa3\x2c\x25\x69\xa9\x42\xcd\xd4\x39\xcd\x78\xca\xcd\x22\xdc\xda\xb9\xf2\x5a\x14\x4f\x4c\xd8\x46\x5d\x81\x91\xd0\xa2\x50\x92\x26\x33\xa6\xa3\xaf\xa1\x80\xe2\x82\xc8\x82\xef\x3b\x96\x80\x03\x19\x05\xfa\x58\x06\x99\x2d\x88\x92\xc6\x5f\xbc\xaf\xf9\xe0\x5d\x34\x18\x74\x47\x2e\x67\xd4\x02\x6e\xe7\x65\x3c\x04\xce\x8a\x4f\xe2\x3f\x34\x91\x59\xea\x53\x98\xfc\xfe\x95\x15\x0a\x13\x87\x83\x96\xf8\x41\x82\x0b\x23\x49\x66\x19\xb6\x25\x88\xeb\x3b\xff\xfa\x37\x64\x26\x4b\xa5\x47\x71\xd2\x81\xd7\xf0\x0e\xf5\x3b\x2f\x54\x1a\x92\x31\xaa\x0d\x79\xfd\x8a\xe4\x5c\x94\x96\x4f\x75\x46\x9b\xee\x72\x50\x24\x01\xfd\xf6\x37\xad\xfb\x75\x95\x7d\xd6\x4a\x3d\x05\xe6\x46\x76\xa2\x8f\x3b\x49\x18\x18\x87\x99\xc5\x1b\x82\x90\x23\xba\x31\xb4\x85\x91\x8f\x70\xbe\x7e\x2c\xe5\x78\x61\xba\x04\x51\xba\x1e\xf5\xe8\xc9\xff\x72\x2f\xdb\x24\x4f\xa9\x72\xa7\x6c\xfc\xe8\xa3\x54\xb8\x98\x72\x6d\xb6\xd4\xb7\xa8\xe2\x2b\x37\x36\x6b\xcf\x56\xa6\x56\x3b\xe8\x18\x2b\x03\x7d\xbc\x44\xec\x6d\x4b\x49\xc2\xb0\x98\xe5\x65\x55\x29\x49\x48\x6c\xbb\x75\xf8\x67\x4e\x38\xe6\x11\xe4\x00\x59\xd3\x5b\x2e\xb5\x9d\xd0\xe5\x51\xa2\xf3\x5a\xb1\x5b\xfd\x14\x68\x2e\xa6\x98\xe4\x3c\x2f\x33\xc3\x8b\xac\x5a\xf7\x47\xdf\xc1\x11\xf2\xd8\xe6\x46\x23\x33\x11\xc5\xc0\x62\xcc\x36\x05\xf6\xc9\x93\x30\x16\x13\x06\x73\x75\x2b\xcb\x0f\x0a\xaa\x68\x00\x1e\x54\xd2\xd5\xa7\xce\x7c\x47\xe1\x46\xd1\xa5\xc3\xb4\xbd\x68\x56\xcd\x38\xba\x45\x3a\x24\xd2\x18\x26\xa8\x68\x61\xaa\xae\xa7\xe7\x82\x4e\x44\x3e\x04\x67\x32\x2c\x83\xd2\xc0\x16\x27\xd4\x7c\x4d\x93\x7b\x26\x52\x2c\x1a\x05\xcb\x4e\x17\x82\xe6\x2e\xdb\x56\x54\x8f\xbb\xd1\x5f\x0f\x9c\x61\x02\xc3\xf7\x7c\x98\x31\x72\xdd\x43\xc2\xa0\xd4\x9d\x53\xd9\xd8\x2e\xdb\xce\xb9\x46\x93\x8d\xe2\xf3\x84\x79\xfe\x6f\xfb\x1d\x72\xea\xf3\x16\xb1\xf4\x4b\x93\xf7\xdb\x13\xe1\x2f\x90\xfb\x60\x39\x87\xa4\x5a\x34\xb3\x47\x7b\x11\x62\x46\x1b\x9b\x3b\x5e\x1c\xb6\xea\x8d\x1a\x77\x89\xfc\x3d\x56\xe3\xb4\x7e\x88\x3f\xd2\x54\x6a\xf2\x75\x26\x93\x7b\x72\xc9\x40\xe8\x7a\xcc\xf2\x2c\x6a\x9c\x3e\x67\x0a\xef\x9c\x4e\xb7\xdd\xb3\x0d\x49\x2e\x05\x37\x52\x6d\xa6\x17\x4f\x57\x76\xb2\x4f\xf7\xbc\x36\x43\x95\xc5\xe6\x97\x9c\xec\xd9\xa2\x5b\xd7\x8d\x87\x4e\x41\x3d\x83\xd3\x89\xaf\x5c\x15\xb0\x1d\xcf\xda\x2f\x66\xf2\x61\x68\xe4\xb0\xd4\x6c\xc8\x5b\x5c\xe8\x76\x58\xe6\x3d\x5b\xc0\x2d\x76\xc7\x85\xba\x6e\x35\x9d\xc1\x48\xb0\x40\xc1\x7b\xcb\xb9\x3f\x7e\x7d\xf9\x49\x33\x35\x8a\x65\xc0\x33\x66\x92\xb3\x84\x15\xb3\x33\x37\xc2\x8b\x04\x8a\x27\x22\x5d\xa1\xe2\xfb\x21\x9b\x49\x64\x96\xb9\xc0\x6c\x39\x21\x17\xac\x98\x85\x81\x9f\x7a\xd5\xcf\x97\x11\xb8\x90\xb2\x6b\x22\xd4\x63\xdb\xa7\x7e\x88\xe0\x0d\x9e\xa1\x08\x99\xd4\xb8\x5b\x11\x8a\xa7\x42\x9f\x17\x5d\x6a\xf3\x11\x81\xf3\xb8\xe9\x94\x8f\x6b\xf9\x94\x63\x7f\xcf\x7a\xb2\x64\xef\x31\x52\x23\x41\xd7\x13\x14\xba\x53\x96\x12\x39\x67\x4a\xf1\x94\x69\x12\x68\x50\xac\xa5\xf2\xec\xa9\xe1\xd6\xe7\x6d\x7e\xf6\xbc\xcd\x3b\xa8\x43\xc7\xa0\x0f\xd5\xc8\x14\xbc\x59\x22\x53\x34\xcd\xb9\x78\x71\x84\x4a\x27\x34\x63\xd7\xdf\x75\xd0\x3f\x5c\x8f\xba\x0a\x72\xeb\x5e\x46\xf9\xd3\xb6\x64\x25\xfb\x36\xe0\x0d\x11\x32\xdd\x66\x52\x7d\x04\x45\x62\x4a\x0d\x7b\xd8\xca\x0e\x87\x15\xa1\xda\xde\x12\x84\xd3\xe7\x54\x39\x5e\x44\x8e\xc0\x08\xe7\x31\xe9\xd9\x21\x99\xaa\xdb\xb5\xae\xc6\x49\xec\x15\xa7\xdf\x6d\x26\xdd\xf5\x18\x7c\x7e\x73\x4d\xbe\xc1\xe6\x87\xcd\x5e\xa8\xa4\x41\x31\xf0\x52\xe6\x94\x77\x2d\xb2\xd1\xec\xde\xcc\xbe\x1a\x2f\xe1\x26\xb4\x25\xae\x71\x54\xc0\x65\xc2\xa7\xa5\xd5\xe9\x9c\x1e\xf6\xa2\x12\xcc\x2d\x89\x2e\x2f\x37\xc1\xdc\xfe\xd5\x20\x22\x93\x93\xf7\x8b\xac\x24\x16\xbf\x95\xc0\x4a\xc2\x1d\x28\xd1\x4c\x68\x0e\x17\x32\xd1\xad\xb8\xab\xf4\x87\xa5\x25\xd1\x09\x12\x45\x9c\x01\x79\x27\xa7\x5c\xf8\xd3\x2b\xdd\x7d\xdd\x84\xf2\xac\x2d\x30\x7a\x99\xe4\xd9\x65\x12\xad\xb3\x2b\x41\xc7\x59\x1b\x77\x83\x3a\xaa\x85\x8e\xe4\x6d\x46\xa7\x84\xc1\x1f\x67\x29\xd7\xf6\xff\xe4\xf6\xf6\x1d\x18\xe1\x4b\xe1\x25\x66\x30\x50\x3b\xda\x17\x82\x14\xf0\x20\x1e\xf6\xec\x20\xe9\xd9\x21\xfb\x5f\xd4\x93\x70\x91\xda\x89\x47\xa5\xe0\xd0\x49\x0a\x5a\x60\x3e\xc4\xe0\xf3\x8b\x6e\x03\x63\x46\xee\x66\x3c\xb9\xbf\x89\xec\xee\x52\xd9\x77\x22\x7a\x55\x63\x60\xcd\xdf\x0e\x49\x2d\xdd\x54\x6f\xba\xab\xc6\x51\x4f\xcf\x07\x3c\xc1\xb8\x75\xeb\x87\xdf\xa8\xd6\x32\xe1\xd5\x9d\x0b\xd8\x68\x2a\xe6\x90\x02\x73\x38\xec\x9a\x40\x3c\xe8\xba\x1c\x94\x3f\x56\x70\x34\xbf\x9b\xbe\x3a\xae\x8e\x39\x18\x17\x7e\xd5\x07\x5d\x02\xe2\xcc\x0e\xa9\xd1\xab\x8e\xcb\xa9\xd1\xbd\x30\xdc\xb8\x58\xf0\x6e\xea\x6e\xf3\xbc\x20\xe6\x6b\x73\x2e\x6d\x5f\x48\x91\xee\x52\x13\x1e\x6c\xe1\x6d\xc2\x36\x56\xa9\xe1\x8d\xdb\x44\x7c\xe7\xae\x1a\xe0\xcc\x15\xb2\x28\x33\xf4\xe7\xd8\x3f\xbf\xbb\xb7\x19\xe3\x77\x0e\x74\xf5\xf0\x14\x59\x4b\x8f\x63\xc7\xde\xee\x9e\xce\x3f\x8d\xdc\xa5\x91\x70\xf7\xea\xb7\xbf\xf9\xcd\x97\x9e\xcd\xb4\xad\x0a\xfe\x18\xe9\x4c\x5b\x9a\x68\x57\xc4\x17\x5d\xf7\xf1\x45\x3f\xdf\xf8\xa2\xc7\xcf\x42\x7b\xe0\x08\xa2\x8e\xbe\xb9\xdd\xfc\x72\xdb\xc7\x08\xb5\xf6\xde\xed\xea\xb9\xdb\x21\x0a\xe8\xb0\xb1\x3f\x9d\x7d\x59\xbb\xc4\xf9\xf4\xd1\x3d\x3f\xd5\xe8\x9e\x5d\x7c\x59\xbb\x47\xf2\x74\xf1\x61\xfd\x29\x46\xed\x74\x38\x9c\xed\xa3\x4b\xf6\x8e\x29\xe9\x9e\x04\xb0\xbb\x3d\x6d\x97\x82\x54\x55\xcf\x95\x1a\xa4\x0f\x2a\xf7\xb9\xc7\x8e\x8f\x75\x94\x5a\xcc\x48\x7b\x02\x9f\x44\x21\x21\x1d\xb4\x31\x1c\x5e\x76\xa9\x0d\xe9\xfa\x7c\x77\xdb\xb8\x98\x09\xaf\x9f\xe7\x3e\xe6\xe7\x70\xe1\xd1\xd7\x74\xf9\x42\x4c\xee\xba\x96\xad\xc5\x5b\x2b\x80\x04\x00\x23\x97\xe3\x38\x4b\x64\x75\x74\xce\x6f\xae\xad\x0e\x0e\x61\x44\x34\xd3\x23\xb2\x82\xcf\x7b\x73\xa9\x93\x0b\x3c\x7f\xa7\xc6\xb0\xbc\x30\xed\x77\xbd\xb7\xb8\x3f\xbb\xc5\xfd\x80\x16\xc0\x59\x99\x53\x31\xb4\x27\x0a\x6c\xee\xb5\xdb\xba\x06\x65\x1e\x11\x77\x76\x90\x3d\x81\x05\x04\x82\x0b\xea\x85\x8d\x69\x54\xe6\xf2\x71\xcc\x9e\x30\xf6\xce\x2b\x47\xbe\xda\x38\x69\x89\x5c\x72\x78\x75\xcb\x09\x50\xf0\x87\x2a\x62\xce\x35\x35\xdc\xcc\x18\xf2\xf0\x1b\x08\xc8\xa9\x5a\xd5\x25\x69\x14\xa5\x69\x96\xc9\x07\xfc\x76\xcc\xd7\x2c\xf4\xed\x5c\x5c\xa4\xd9\x98\x91\x9c\x5b\x1d\xdd\x19\x58\xe3\xe9\xe0\x95\xa9\x95\xc8\x99\x42\x81\x57\xb9\xcb\xb6\x5b\x66\xdc\x46\xc1\x46\x5b\xfd\x56\xa0\x43\xb8\xfd\xb7\xf7\x2a\x82\x6f\x7b\x9a\x30\x66\x33\x3a\xe7\xb2\x54\xd8\xdb\x48\x72\xe4\x7e\x02\xde\xb0\x90\x65\xb0\x77\x61\x31\xcc\xb0\x3a\xbd\x02\x4e\x1f\xaa\x1f\x41\x15\x48\xa5\x37\x4d\x0c\xd9\x67\xae\xcd\xf2\x5a\x3c\x88\x7c\x1a\xbc\x43\xe1\xcd\x5c\x17\x96\x2d\x74\xae\x6a\x57\xeb\x57\x97\x57\xe6\xb7\xf0\xd3\x17\x54\xd3\x6e\x6b\x76\xd7\x27\x13\x81\x7e\x86\xe2\x4f\xb8\x09\xcb\x78\xb2\xe8\x5c\xee\xad\xd1\xdb\x13\x6d\x1d\xee\xd0\xec\x7b\xf2\x35\xd5\x2c\x25\xef\xa9\xa0\x53\xd4\xf7\x4e\x6e\x6f\xbe\x7e\x7f\x6a\xf7\x15\xf4\xc9\xeb\xcb\x95\x17\x6d\xb7\xf1\xe0\x1f\x0e\x19\x2f\xb2\xb4\xf0\x1d\x58\xd5\x52\xff\x1d\x17\x7f\xd0\x40\x18\x12\xf8\x50\xbb\x64\xbd\x2b\x58\xd0\x4d\x33\x84\xb5\x59\xf3\xb3\x41\x60\xe6\x79\xba\x67\x95\x4f\x2e\xb4\xa1\x59\x76\x93\x51\x71\x5e\x14\x4a\xce\x57\x6b\xe3\xb5\xb9\xfa\x86\x7e\xa6\xe8\xe6\xe1\x5f\x16\x08\x7a\xb8\xc2\x16\xe4\xba\x1a\x7f\x44\xae\x4d\xd0\xc2\xa5\x00\x96\x7a\x74\x5e\x1a\x99\x53\xc3\x93\x23\xab\xac\x1f\xbd\xa7\xa2\xa4\xd9\x4a\xa7\xab\x8d\xcb\x58\x27\x22\x6e\xec\xb4\x3e\x75\x5d\x8b\x6e\x1b\x65\x8d\xcd\xfd\x0d\x55\x96\x3a\x5d\xdc\x7e\xdf\xa9\xaf\x36\xd4\x94\x4b\x54\x78\x03\x67\x58\xcf\x0b\x86\x24\xa3\xda\x7c\x2a\x52\x7b\xe8\x1b\xbf\x6e\x22\xf8\x09\x35\x34\x93\xd3\x3f\x31\x9a\xad\xc6\xf0\x1a\x9e\x5c\xc4\xad\xbd\x01\xca\x5d\xf8\x97\xe3\xd0\xf0\x58\x13\x2b\x60\xfb\x18\x78\xc5\x32\x36\xa7\xc2\xf8\xee\x58\x5c\x5d\x1f\xbb\xf5\x03\x16\xf1\xca\xf8\x9a\x32\xc3\x54\xce\x45\x7d\xcc\x5b\x68\x7b\x21\x45\xca\xd1\xec\x08\x06\x35\xec\x51\x1f\x77\x3d\xaa\xad\xbb\x69\xd8\x70\xb7\x50\xcf\xae\x19\xcd\xa7\x0e\x0a\x6c\x36\x76\xf2\xe5\x0c\x5f\xc2\x4d\x7b\x6d\x6e\x4b\x90\x22\xf7\xc2\x0a\x86\x90\x47\x64\x35\xd9\xda\x2a\x27\x6c\x93\x0f\x86\x7e\x8f\x71\x0a\xeb\x1d\x47\x87\x6e\xde\xeb\xee\x20\x36\xa1\x18\x3e\xdb\x25\x8b\xe6\x54\xd6\xd3\xd4\x55\x78\x17\xba\x61\x24\x4b\xa3\x20\x7f\xad\xd1\x7a\x1e\xd0\x4a\xf0\x6a\x27\x23\xb5\xcd\x6a\x5f\xa7\xb5\x55\x0e\xf6\x25\x55\xb6\x85\xc4\xb8\x95\x69\xb5\x4c\x2e\x5f\x57\xac\xaf\x9d\xff\x9f\x72\xaa\x08\x25\x05\x67\x98\xfc\x84\x0a\x07\x2c\xe0\x2c\x8c\xa6\xee\xa5\xe5\x60\x56\x25\x84\xdf\x06\xee\x32\x1c\x8d\xcb\xce\xd7\xc2\x1b\xa8\x29\x26\xff\x80\x8b\x8b\xb3\x6f\xa4\x33\xf2\xba\x20\x5d\x4b\x03\x80\x93\x0f\x88\x2e\x93\x19\xa1\xda\x4e\xcd\x22\xb4\x3d\xf1\x6c\x94\x53\xc1\x27\x4c\x9b\x51\xc8\x12\xac\xff\xfc\xeb\xbf\x8c\xc8\x5b\xa9\x88\x73\x54\x1f\xf8\xac\x1a\x6e\x9e\x15\x5e\x70\x8d\x8b\x09\x7d\x2b\xad\xb5\x90\xa9\x9b\xf4\x03\x4c\xd6\xd0\x7b\xcb\xc3\x70\xb2\x25\x83\xab\x8b\x37\xe4\xc8\x8a\x89\xd1\xa7\xff\x61\xd9\xd2\xbf\x8e\xc8\xc9\x03\x30\xed\x23\xfb\xe7\x11\x7e\x30\xb8\x4d\xc6\x4a\x75\xf5\x61\x0c\x96\x54\x7c\x3a\x65\x0a\xd5\x47\x02\x41\x85\xa7\x2e\x2b\x88\x90\x51\x63\x7f\x29\x5d\xa9\x9b\xcd\x89\xfc\xf9\xd7\x7f\x39\x22\x27\xf5\x75\x11\x2e\x52\xf6\x99\xfc\x1a\xad\xcb\x5c\xdb\x35\x9e\xba\xcb\x1c\xbd\x10\x86\x7e\xb6\x63\x26\x33\xa9\x99\x40\x55\xde\x48\x32\xa3\x73\x46\xb4\xb4\x1a\x30\xcb\xb2\xa1\xb3\xa5\x93\x07\x0a\x99\x5a\x3c\x28\x21\xb0\x9e\x14\x54\x99\x1a\x4a\x8c\x9c\x85\x04\xbe\x66\xb7\x6d\x2a\xfc\xcd\xf4\x84\x0b\x77\x7f\xe5\x6e\xce\xec\x9e\x43\x60\x28\x6e\x92\x91\x24\x99\x51\x31\x0d\xb1\xe9\x93\xd2\x94\x8a\x6d\xb9\xfa\x69\x79\x06\xee\xb9\xe8\x14\xc2\xfc\x2d\x17\x4d\xa7\x82\xd5\x76\xa5\x29\x37\x3e\x2a\xc2\xf9\x2a\x9a\xc5\x99\xdd\x05\xc5\xc7\xa5\x91\x4a\x9f\xa5\x6c\xce\xb2\x33\xcd\xa7\x43\xaa\x92\x19\x37\x2c\xb1\xcb\x3a\xa3\x05\x1f\x26\x52\xd8\x1d\x87\xac\x0c\x79\xfa\x0b\x28\x6f\x3a\xb4\x53\xdd\x92\x75\xba\xe5\xa2\xb7\x1b\xd5\x9e\xd5\x98\x76\xb0\x35\xb6\xb0\x07\x2d\x2f\x14\x6d\x33\x4f\xb0\x5a\x30\x84\x9c\x1d\x64\xb1\x3e\x69\x72\x77\x1e\x73\xec\xf2\x80\x27\xcd\x31\xec\xb1\x43\x07\x12\x38\x95\x35\x4a\x99\xd3\x14\x49\x29\x15\x8b\x47\x47\x7e\x0b\x52\x48\x97\x9f\x2c\x86\x30\x84\xcc\x86\x54\xa4\xf6\xdf\x18\xb0\x93\x2c\x0e\x02\xc3\x92\x77\x22\x04\x9f\xae\x2f\x9f\xe6\x48\x94\xfc\x00\xa7\xde\xc9\x6b\x2d\x85\x28\x14\x55\xd1\x51\x43\x95\xcc\x33\xcd\xba\x80\xca\xb5\x1f\xf5\x3f\xdc\xfd\x4b\xc8\x76\xb6\x4d\xa4\xda\x7c\x6b\x12\xc9\x8e\x2d\xe7\xfb\xae\xea\x11\xdb\xe4\xc0\xf1\x8a\x6a\xe3\x52\x6b\xf9\x1c\x04\xb5\x65\x78\x05\x05\x18\xcc\xfa\x8b\xe1\x56\x38\xe4\xfd\x05\xec\x44\x86\x2b\x73\x2e\x25\x41\x29\xd9\xae\x40\x55\xfa\x4b\xad\x0e\x1a\x2e\xca\x30\x6d\x08\x9d\x53\x9e\x81\x75\x5e\x8e\x35\x53\x73\x2c\x48\xe5\x52\x0d\xd2\xa6\x9e\xe5\x6a\x4e\xa0\x18\xf5\x44\x9a\x8f\x5f\xc3\xf2\xae\x6c\x5a\x00\x68\x43\x8d\xd9\xaf\x9d\xf5\x41\xf4\x1e\x54\x2f\xd7\xfe\x6c\xbf\xb0\xa3\x1a\x63\xf1\xef\x4f\x8c\x2a\x33\x66\xd4\xdc\xf1\x4d\x7c\x77\x09\xa5\x6b\xfd\x42\x29\xf7\x80\xd0\x0f\x8c\x4c\xa5\xb1\x22\x56\x09\xb8\x8f\x32\x29\x26\xf5\x09\x88\xf6\xd8\x18\x5d\xad\xf2\x4e\x51\x08\xf1\x91\xa2\xe3\x32\xeb\x1d\x97\xd7\xe9\xa4\x63\x87\x49\x06\x5b\x63\x22\x0d\x29\x98\xdb\x3b\xbc\xcd\x00\x0a\xf4\x34\x4b\xce\x99\xd6\x1b\x13\x6c\xd4\xbd\x0b\xb1\x35\x1e\xe5\xc6\xd5\x5a\xee\x7f\xc3\xb0\x10\x2b\x40\xa7\xcc\x50\x9e\xf9\xa3\x8c\xa0\x08\x50\xda\x46\x5d\x37\x2e\x50\x31\xaa\x37\x09\x08\xb5\x59\x7f\x84\xc6\x38\x69\x29\xd8\xf0\x41\xaa\x94\x5c\xd0\x9c\x65\x17\x54\x33\x37\x56\x1c\xa2\x87\x7b\x74\xac\x0f\x3a\xe5\xd5\xb6\xaf\x35\x53\x46\xe3\x4f\x65\x12\x86\xbf\x2a\x15\x0b\x27\x38\xf0\x26\xc8\x3b\x55\xb2\x01\x79\x6b\xb9\xd7\x80\x7c\x12\xf7\x42\x3e\xec\x37\x57\xb3\xf1\x16\xa4\x36\xd3\xd8\xfd\xc3\xa7\xd5\xa9\x19\x7c\xc2\x74\x77\x9c\x91\x23\xf8\x6b\x4c\x8d\x75\x66\x13\x9a\xfa\x19\xd9\x7f\x2e\x99\xa0\xac\xa2\xa8\xe4\x54\x31\x8d\x99\x6b\x56\x26\x49\x6c\x6b\x72\xfe\x86\x09\x17\xdc\xb7\x75\x7a\xd7\xab\x7a\xf9\x99\x7a\xbe\x36\xad\x7e\x71\xfb\xed\x3e\x56\x64\x2b\x45\x8d\xcd\x1e\x81\xd1\x44\xd7\x18\x9f\xd6\xcd\x70\xb5\xd1\x29\xe2\x7a\x51\x5b\x14\x4a\x36\x59\x47\xfd\xea\x2e\x6e\xbf\x5f\x0f\xec\xb5\xbc\x6f\x1b\x7f\xda\x6e\x96\xda\xd7\x20\xb5\xf5\xcc\x6c\x35\x42\xf5\xe6\xa7\xde\xfc\xf4\x25\x99\x9f\xb6\x62\xfc\x26\x93\xd3\x97\x61\x6c\xda\xba\xc4\x4d\x06\xa6\x17\x69\x5a\x6a\xb5\xa2\x8d\xe6\xa4\x17\x6b\x48\xda\xba\xb4\x96\xc6\xa3\x9f\x8f\xd9\x68\x2b\xc4\x36\x98\x8a\x5e\xa0\x91\xa8\x8d\x40\xc6\xd2\x36\x62\xe2\x75\xd4\x38\x16\x14\xab\x72\x96\x61\x38\xef\x94\x13\x8b\x33\xbb\x4a\x8b\x56\x80\xdb\x3a\xb7\x63\x37\xb9\xf6\xb2\x97\x13\x18\x5d\xb1\xc7\xa5\xc9\x92\xcb\xab\x9b\x8f\x57\x17\xe7\x77\x57\x97\x4d\xf9\x6e\x15\xa4\xb7\x48\x62\x9b\x6d\x10\xc3\x48\x12\x5b\xd3\xc0\x12\xe4\x35\x3f\x59\x1c\x58\xf3\x53\x59\xf2\x55\xbd\xf6\x97\x0b\xf7\xe2\x72\x7b\xf1\x8f\xed\xa7\xb3\xed\xf1\xfc\x84\x8e\x53\xd4\xf9\x9c\x59\xb9\x67\x26\xb3\x54\x7b\xbf\xd5\xeb\xcb\x10\x49\xc5\x45\x92\x95\xa9\x15\x2e\x3e\x7d\xba\xbe\xd4\x23\x42\xbe\x66\x09\x2d\x35\x58\x61\x52\x29\x8e\x0d\xf9\xee\xc3\xbb\xff\x06\x7f\x6c\x68\x31\x08\x79\x4d\x20\x2b\x2f\xa7\x98\x58\xd8\x60\xba\x36\xf2\x35\x43\x41\x05\xbe\x9c\xd0\xc2\x52\x31\x8d\x95\x2b\x0c\xc8\x22\x33\x96\x15\x96\x62\xde\x33\x52\x65\x50\xb5\x03\x57\x15\xe6\xbd\xfb\xe4\x94\x19\x8c\xba\xda\xe4\x21\xb9\x11\x6a\x5b\x2c\xae\x7b\xd8\x5a\x6b\xea\xa3\xd3\xc6\x1f\xa8\x76\x16\xab\x95\xb3\xdd\xb2\xbf\xdb\xed\x33\xeb\x4d\x1c\x6b\x8c\x1b\x48\x9e\xe1\xaf\xa5\x39\xdb\xc9\x56\x76\x0c\x74\x22\xe1\xa6\xb5\x35\x75\xbd\x1b\xd0\xea\x3a\x00\x4b\xb6\x0c\xd6\x04\x72\xed\xc3\xc1\x23\x3b\x9a\x72\xbb\xb9\x40\x11\x91\xb4\x56\xfb\xd3\xf9\xcf\xd5\xdf\x95\xe3\x50\xfd\xb5\x9a\xaf\xb3\xc8\x90\x7f\xfc\xeb\xab\xff\x3f\x00\x00\xff\xff\x01\xa8\x18\xd1\x2e\x5c\x02\x00") +var _operatorsCoreosCom_subscriptionsYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\xbd\x7b\x73\xe3\xb8\x95\x28\xfe\x7f\x3e\x05\xca\x49\x95\xed\xac\x24\x77\x67\x73\x93\xdc\xde\x54\xb6\x3c\xb6\x7b\xe2\x3b\xdd\x3d\xbe\xed\x9e\x99\xda\x5f\x92\xdf\x06\x22\x21\x09\x31\x09\x70\x00\x50\x6e\x25\x9b\xef\x7e\x0b\xe7\xe0\x45\xea\x45\xca\xf2\xa3\x27\xe2\x1f\x33\x6d\x0a\x00\x81\x83\x83\xf3\xc2\x79\xd0\x8a\x7f\xcf\x94\xe6\x52\xbc\x21\xb4\xe2\xec\xb3\x61\xc2\xfe\xa5\x47\x77\xbf\xd3\x23\x2e\xcf\xe6\xaf\x7f\x76\xc7\x45\xfe\x86\x5c\xd4\xda\xc8\xf2\x23\xd3\xb2\x56\x19\xbb\x64\x13\x2e\xb8\xe1\x52\xfc\xac\x64\x86\xe6\xd4\xd0\x37\x3f\x23\x84\x0a\x21\x0d\xb5\xaf\xb5\xfd\x93\x90\x4c\x0a\xa3\x64\x51\x30\x35\x9c\x32\x31\xba\xab\xc7\x6c\x5c\xf3\x22\x67\x0a\x06\xf7\x9f\x9e\xbf\x1a\xfd\xef\xd1\xab\x9f\x11\x92\x29\x06\xdd\x3f\xf1\x92\x69\x43\xcb\xea\x0d\x11\x75\x51\xfc\x8c\x10\x41\x4b\xf6\x86\xe8\x7a\xac\x33\xc5\x2b\xf8\xc4\x48\x56\x4c\x51\x23\x95\x1e\x65\x52\x31\x69\xff\x57\xfe\x4c\x57\x2c\xb3\x1f\x9f\x2a\x59\x57\x6f\xc8\xca\x36\x38\x9c\x9f\x23\x35\x6c\x2a\x15\xf7\x7f\x13\x32\x24\xb2\x28\xe1\xdf\xb8\xf6\xdb\xe4\xab\xf0\xba\xe0\xda\x7c\xb3\xf4\xd3\x3b\xae\x0d\xfc\x5c\x15\xb5\xa2\x45\x6b\xb6\xf0\x8b\x9e\x49\x65\x3e\xc4\x6f\xdb\x6f\xe9\x7a\x9c\xfe\xdb\x35\xe4\x62\x5a\x17\x54\x35\x07\xf9\x19\x21\x3a\x93\x15\x7b\x43\x60\x8c\x8a\x66\x2c\xff\x19\x21\x0e\x8e\x6e\xcc\x21\xa1\x79\x0e\x7b\x43\x8b\x1b\xc5\x85\x61\xea\x42\x16\x75\x29\xc2\x37\x6d\x9b\x9c\x85\x51\xdf\x90\x4f\x33\x46\x2a\x9a\xdd\xd1\x29\xf3\xdf\x1b\xb3\x9c\x18\x19\x3a\x10\xf2\x37\x2d\xc5\x0d\x35\xb3\x37\x64\x64\x41\x3c\xb2\x10\x4c\x7e\xc6\xfd\xb9\xc1\x41\x92\xf7\x66\x61\xa7\xab\x8d\xe2\x62\xba\xe9\xf3\x19\x35\xb4\x90\x53\x82\xf8\x45\x26\x52\x11\x33\x63\xc4\x7e\x8a\x4f\x38\xcb\xfd\xfc\x36\xcc\x08\xbb\x2e\xcd\xe9\xb6\xfd\xba\xf3\x94\x66\x54\x08\x56\x10\x39\x21\x75\x95\x53\xc3\x34\x31\x32\xc2\x67\x33\x78\x5c\xe7\xa5\xd9\x5c\x2c\xbd\x5f\x31\x1d\x6c\x3a\x7f\x4d\x8b\x6a\x46\x5f\xbb\x97\x3a\x9b\xb1\x92\xc6\x3d\x94\x15\x13\xe7\x37\xd7\xdf\xff\xfb\x6d\xeb\x07\xd2\x5c\x4a\x8a\xa2\xe4\x8e\xb1\x4a\xc7\x43\x41\xea\xca\xae\xc9\x2e\x8e\x8c\x17\xc4\x28\x9a\xdd\x71\x31\x85\xa5\x4f\x71\xbd\x17\xb8\x31\x7a\xb4\x34\x65\x39\xfe\x1b\xcb\x4c\xf2\x5a\xb1\x1f\x6b\xae\x58\x9e\x4e\xc5\x42\xd6\x93\x88\xd6\x6b\x0b\xa7\xe4\x55\xa5\xec\xb4\x4c\x72\x0e\xf1\x49\x68\x54\xe3\x7d\x6b\x99\xc7\x16\x16\xd8\x8e\xe4\x96\x3c\xd9\xe9\xcf\x98\x3f\x1c\x2c\x77\x00\xb4\xdb\x69\x66\x5c\x13\xc5\x2a\xc5\x34\x13\x48\xb0\xec\x6b\x2a\xdc\x9a\x46\xe4\x96\x29\xdb\xd1\x1e\xd8\xba\xc8\x2d\x1d\x9b\x33\x65\x88\x62\x99\x9c\x0a\xfe\xf7\x30\x1a\x80\xc8\x7e\xa6\xb0\xf8\x61\x08\x1c\x37\x41\x0b\x32\xa7\x45\xcd\x06\x84\x8a\x9c\x94\x74\x41\x14\xb3\xe3\x92\x5a\x24\x23\x40\x13\x3d\x22\xef\xa5\x62\x84\x8b\x89\x7c\x43\x66\xc6\x54\xfa\xcd\xd9\xd9\x94\x1b\x4f\x81\x33\x59\x96\xb5\xe0\x66\x71\x06\xc4\x94\x8f\x6b\xbb\x71\x67\x39\x9b\xb3\xe2\x4c\xf3\xe9\x90\xaa\x6c\xc6\x0d\xcb\x4c\xad\xd8\x19\xad\xf8\x10\x26\x2b\x90\x44\x96\xf9\xcf\x95\xa3\xd9\xfa\xb8\x05\xbe\x95\xe7\x80\x78\xaa\xb7\x11\xd6\x96\xf8\x11\xae\x09\x75\xdd\x71\x2d\x11\xa4\xf6\x95\x85\xca\xc7\xab\xdb\x4f\xc4\x4f\x00\xc1\x8e\x10\x8e\x4d\x75\x04\xb6\x05\x14\x17\x13\xa6\xb0\xe5\x44\xc9\x12\x46\x61\x22\xaf\x24\x17\x06\xfe\xc8\x0a\xce\x84\xb1\xc7\xb0\xe4\x46\x03\xce\x31\x6d\xec\x3e\x8c\xc8\x05\x30\x20\x32\x66\xee\xc0\xe6\x23\x72\x2d\xc8\x05\x2d\x59\x71\x41\x35\x7b\x74\x50\x5b\x88\xea\xa1\x05\x5f\x77\x60\xa7\xfc\x73\xb9\xc3\xd2\x19\x23\xc4\x33\xb8\xb5\xbb\x93\x1e\xf8\xdb\x8a\x65\xe1\x38\x50\x41\xce\xab\xaa\xe0\x19\x62\xbc\x99\x51\x43\x32\x2a\x2c\xbc\xb8\xd0\x86\x16\x05\xb0\x93\x4e\xb3\x58\x77\xda\x09\x1c\xed\x16\x73\xf0\xaf\x97\x28\x74\xf3\x87\xc0\xd4\x5a\x2d\xd6\x51\x06\xfb\x38\x3a\xbb\xfc\xc3\x06\x90\x13\x94\x4c\x26\x7c\xba\xaa\xdb\x5a\x58\x5e\x40\x17\x90\x69\x28\x17\xda\x0d\x51\x2b\x84\x66\xe4\x54\x96\x77\xd1\x06\xdf\x1e\xad\x9d\xdd\x4a\xc8\x6e\x5b\xb3\x7d\xe8\x04\x24\xb0\xc5\xea\x5f\x5b\xab\xb8\x9e\xc4\xe9\x0d\x88\x9c\x33\xa5\x78\xee\xe8\x63\x25\xf3\x63\x0d\xd4\x2c\xaf\x0b\xa0\xfd\x52\x68\xa3\x28\x87\xa3\x29\x78\x61\x57\x32\xa4\x06\xcf\x03\xd3\xe4\x9e\x17\x05\xf9\xa5\x90\xe6\x97\x61\x24\x18\x48\x2a\x3e\xe5\x81\xf4\x69\xc2\x85\x1f\x1f\x38\xa2\x63\xe9\x52\xb3\xd6\x80\x23\xf2\x9d\x66\x84\x95\x95\x59\x78\xe2\x70\xf2\x8f\x7f\x9e\x5a\xc2\xca\x14\xd5\xc9\xc0\x8d\x7e\x9e\x7c\xae\x59\xff\x16\xf0\x76\x01\xb1\x7d\x84\xcc\xd9\xf9\x16\x50\x2f\x81\xfb\x92\xa1\x84\xa0\xa1\x7b\xd8\xaa\x14\xc8\xaa\x2e\x98\x0e\x52\x8e\x85\xd1\x86\xc1\x3b\xac\xa5\xeb\x7a\xb0\x1d\x9b\x30\xa5\x58\x7e\x59\xdb\xa3\x71\x1b\x66\x75\x3d\x15\x32\xbc\xbe\xfa\xcc\xb2\xda\xac\xe0\xba\x1b\x97\x6e\xe5\x26\xb7\x4c\xa6\x10\x55\xf0\x73\x20\x3a\xb9\x1f\xec\x7a\x81\x71\x5a\xf0\x68\xa4\x43\x9a\x1a\xae\x27\x0b\x00\x47\x00\x18\xfb\x6c\x99\x04\xc8\xb6\xc9\xf9\xb2\x82\x0a\xf0\x07\xce\x8a\x7c\x40\xc6\xb5\x21\xdc\x00\xf3\xc8\x66\xd2\xe2\x17\x45\xb8\xc3\xb8\x73\x2e\x81\x35\x13\x29\x2c\x26\x91\xd2\x72\x00\x10\x01\x58\x3a\xfc\x08\x66\x1e\xbb\x71\x4d\x4a\xa9\x4d\x84\x95\x7d\x03\x58\x2e\x18\xb9\xe7\x66\x06\x7f\x4c\xad\xba\x62\xd9\xbe\xae\x4b\x3b\xe8\x3d\xe3\xd3\x99\xd1\x03\xc2\x47\x6c\x04\xbb\xcb\x68\x36\x4b\x86\x2d\x19\x33\x9a\xd0\xa2\xf0\x53\x48\x51\x02\xe9\x69\x69\x79\x22\x39\x09\x4c\xd3\x31\xb8\x41\xa0\xb7\xed\x5d\x5b\x09\xae\x01\x61\x26\x1b\x9d\x0e\x48\x26\xcb\xca\x9e\x16\x0a\x73\x1c\x2f\x08\x37\x56\xf6\x43\x06\xad\x64\x3d\xc5\x95\xb0\xc2\x7d\xd8\x4b\x47\x00\x5c\x10\x5f\xac\x36\x21\xa6\xe4\x08\x17\x77\xe4\x05\x1e\x3b\x1c\xc7\x45\xc0\xfa\x4a\x6a\xb2\x99\xa3\x29\x99\x54\x8a\xe9\x4a\x0a\xe8\x09\xbf\x5c\xc5\xb9\xfd\x47\xe8\x74\xa2\x4f\x23\x30\x67\x7c\x3a\xf3\xb0\xa4\x0a\x69\x4a\x73\x0f\x36\x9d\x91\x78\x4e\xa8\x52\x74\xb1\xa5\x25\x37\xac\xdc\x72\x4a\x96\x50\xfb\x5c\x38\x22\x15\x71\x22\xd9\x3d\xc3\x54\x19\x60\x00\x1b\x0c\xc7\x55\xe3\xfa\x78\x69\xd9\x2e\x37\x0e\x43\xc8\x2b\x72\x02\x28\xc2\xcd\xb1\x06\x74\x1d\xca\xea\x74\x44\xce\x41\xdb\xed\xf0\x01\x21\xc3\xf8\x6e\x20\xfb\x51\x2d\xe3\x58\x5b\xd7\xd6\x91\xa8\xe0\xb3\x9e\xd7\x2f\x3f\x43\x37\x7f\x26\x56\xb0\xfa\x55\xcd\x11\x26\x5b\x9b\x76\x25\x6f\xbe\xb5\x9f\x43\x97\xd6\xed\xad\x46\x94\xd6\xac\x60\x99\xb1\x34\x9a\xa9\x72\x40\xa8\xd6\x32\xe3\x56\xac\x8c\x48\xdb\xc4\x74\x5c\xc9\x76\xd8\x93\xbe\xf0\x27\xbd\xd7\x6f\x9f\xf6\xc1\xeb\xda\x6f\x09\x1a\x05\xd7\xc6\x52\x86\x26\x54\x1a\x04\x6b\xbc\x80\x5f\x8f\x35\x29\xe8\x98\x15\x6b\xf9\xf2\xf2\xd3\xfd\xd4\xc6\xa7\xe3\xf9\x5d\xbb\xa0\xb5\x0b\x71\x4a\x4d\xd8\x78\x10\x91\xbd\xc0\x87\x12\xc7\x80\x50\x72\xc7\x16\xa8\xdb\x59\x95\xd1\x29\xd3\xd8\x58\x31\x64\x37\x16\x39\xee\xd8\x02\x1a\x6d\x96\x54\xd6\xc3\xa4\x07\x72\xe0\xd3\xe7\x98\xc6\x67\x68\x27\xda\xb3\x87\x5f\x74\x8f\x6e\xfd\xf1\x17\x9f\x3b\xb6\x51\xf2\x5a\xf5\x2c\x89\x24\x80\x93\xb0\x1f\xb0\x49\xc0\xbf\xfc\x1e\x53\xab\x12\x81\xad\xa3\xcf\x0e\x91\x6d\x0a\xc6\xa6\xc7\x43\xef\x41\xeb\xfa\x18\x34\x68\x44\xc8\x63\x8d\xc8\x67\x4f\xfa\x8c\x83\x5d\xc7\x62\x32\x1c\x5c\x6f\x6a\xf8\x9e\x16\x3c\x4f\xcc\x3f\x96\xcf\x5e\x8b\x01\xf9\x20\x8d\xfd\xdf\xd5\x67\xae\xad\xf8\x72\x29\x99\xfe\x20\x0d\xfc\x39\x22\x5f\x1b\xc4\xf5\x77\x1d\x29\xdb\x1e\x00\x84\xf3\x7d\x10\x78\xce\x05\xd2\x14\xbb\xfc\xd4\x48\xa1\x47\x56\x1d\x02\x51\xce\x1f\x5c\xae\xc9\xb5\xb0\xc2\xa1\x03\x03\x98\x8d\x50\x89\xc1\x21\xca\x5a\x83\x55\x41\x48\x31\x04\x19\x60\xe5\x18\x08\x3d\x3b\x4e\x0a\xbf\x0d\xc3\xad\x1f\xea\x6b\x63\x87\x79\xb7\xb6\xf3\x8c\xce\x41\xa4\xe3\x62\x5a\x04\xe1\x6d\x40\xee\x67\x3c\x9b\xa1\xd4\x0d\x3a\xbd\x61\xaa\x52\xcc\x32\x2c\x0a\xda\xbf\x7d\x33\x65\xca\x0a\xbb\xdc\x8f\x87\x96\xb0\x82\x66\x2c\x27\x39\x88\x96\x68\xd5\xa1\x86\x4d\x79\x46\x4a\xa6\xa6\x8c\x54\x96\x93\xec\xb6\xfb\xfd\x08\x3b\x3e\xbd\xc9\x7b\xfa\xc1\x5e\xe8\x06\x2c\xf2\xad\x95\x75\x9f\x88\x3b\x82\x5c\x7d\xe0\x8e\x07\xee\xd8\x7a\x0e\xdc\x31\x3c\x07\xee\xb8\xe5\x39\x70\xc7\x03\x77\x7c\x74\xee\x88\xba\xec\x0e\xca\xf3\x0f\x68\xe2\x68\x6b\xcb\xc0\x69\xfd\xbd\x50\x53\x6d\xb6\xfc\xe6\xd6\x11\x9c\x4f\xa0\x6a\x3b\xdb\xb1\xa2\x62\xca\xc8\xeb\xe1\xeb\x57\xaf\xfa\x28\xd5\x6e\x23\x3b\xf5\x98\x48\x55\x52\x03\x7d\xfe\xfd\x57\x1b\x7b\xac\xb3\xbf\xed\xc1\x6a\xea\x70\x3c\x18\xf2\x1a\xb2\xc3\x1a\xc3\x27\x50\x27\x21\x0d\x29\x99\x21\xd4\x34\x4c\x45\xbc\x64\x03\x6f\x58\x46\x84\x77\xd7\x62\xde\x02\x9b\x13\x29\x9c\x1d\xcf\x02\x7f\xb4\xdb\x0c\x32\x46\x35\xb3\x94\x74\xcc\xc2\x2c\x64\x69\xbf\xca\x85\xf1\xc7\xc5\x4e\x81\x79\xa8\x90\x13\x36\x9a\x8e\x48\x5e\x43\x37\x2a\xdc\x3d\xdd\x29\xce\x56\x2f\xb4\x61\x25\x58\x72\xa5\x82\xff\xd9\x69\x1b\xb5\x80\xbb\x80\x39\x13\xa6\xa6\x45\xb1\x20\x6c\xce\x33\x13\xd6\x07\xd7\x84\xdc\xa0\xb1\xbd\x9b\x89\xb0\x93\xe8\xd0\x5d\x5c\x18\x2e\x61\xb0\xde\xd2\xa7\x0f\xb7\x5f\x1a\xbb\xcb\x99\x6c\xf1\x42\x5c\xc9\x68\xad\xb0\x6a\xec\xb8\x68\x03\x87\x7f\x02\x72\x7d\xfb\x71\xbb\xc9\x95\xf4\xa6\x64\x3d\xa8\x57\x5b\x2c\xad\x8b\xc2\x22\x06\x5a\x61\x97\x17\xb0\xc2\x3a\x8a\x4b\x6a\x20\x33\x1a\xde\xd1\xc4\x7c\xfe\xe1\xd2\x42\xc5\xb6\xf9\x24\x2b\x59\xc8\xe9\x22\x85\x34\xac\x0c\x6c\xb7\xae\x2f\xde\xea\xa1\xd0\x60\xd1\xef\x43\x6b\x6b\x0e\x96\xbf\x83\xe5\xef\xa0\xdb\x2c\x3d\x07\xdd\x26\x3c\x07\xdd\x66\xcb\x73\xd0\x6d\x0e\xba\xcd\xc1\xf2\x47\x0e\xdc\x71\x03\x4c\x0e\xdc\x91\x1c\xb8\xe3\xda\x75\x1d\xb8\xe3\x46\xf0\x1c\xb8\xe3\x81\x3b\xae\x7a\x2a\x99\x3f\xc0\xd1\xb1\x92\xf9\x06\x3f\x47\xb4\xfa\x64\x72\x58\xc8\x8c\x1a\xe7\x08\x6e\xbb\x38\x3b\x9f\xa6\x25\x1a\xa2\x06\xe4\xef\x52\x30\x74\x5e\xb3\x7b\x03\xe6\x24\x69\x66\x4c\xd9\xe6\x27\xfa\x74\xa3\x63\xd3\xc1\x4f\xf2\xe0\x27\xf9\xe2\xfd\x24\x67\x54\xe3\xbe\x22\x51\x5a\xef\x36\x99\x1c\xc8\x4f\x4c\x95\x5f\xa8\xd7\xa4\x45\x17\xb7\xdd\x10\x62\x13\xb7\x14\x57\x9e\xbb\xfb\x02\x96\xdf\x34\xd7\xeb\xe4\x65\x58\x14\xcd\x73\x96\x93\x8a\xa9\x21\xa2\x88\x24\x13\x2e\xf2\x15\x6b\xf5\xf0\x79\x56\xef\xc7\xe6\x3a\x9e\xd1\x05\xb2\x39\x91\x1d\x6c\xae\xa9\xe1\xb8\x41\xe1\x5f\x84\x43\x64\x5f\xa9\x7e\x48\x8c\x33\xf2\x7e\xd3\x51\xae\xef\x2f\x9a\x83\x40\xed\x4d\xc2\xbb\xeb\x95\x20\x96\xff\x58\x33\xb5\x80\x18\x8b\x28\xb0\x86\x60\x2e\x77\x47\xc6\x35\xc9\xa8\x46\x4e\xd1\x57\xb5\xec\xa9\x46\xed\xa6\xa7\xec\x6e\x89\x26\x6d\xb8\xb4\x87\x42\x9d\xd4\xeb\xe0\x08\xb3\x95\x4a\xf8\x8a\x5b\x80\x68\xfd\xef\x35\x9f\x5d\x45\xb7\x9d\x04\xb7\x95\x48\xf1\x82\x95\x73\xb2\xbb\x82\x4e\x76\x56\xd2\xc9\x4e\x8a\x3a\xd9\x55\x59\x27\x0f\x50\xd8\xc9\x6e\x4a\x3b\x69\xa3\x82\xdd\x21\x27\x65\x3d\x8e\xfe\x4e\x1e\xa2\xa2\x92\x07\xe8\xf1\xa4\xbd\xd4\x80\xa6\xea\xb1\x94\x7a\xc0\xf5\x86\x5e\xff\xd4\xc0\xda\x4d\xa7\x27\x6d\x50\xf9\xa8\x3b\x50\x68\xbf\x10\x0d\xff\x49\xd4\x6d\xf2\x20\x95\x9b\xec\xae\x76\x93\xdd\x31\x03\x58\xdd\x3b\xb8\x4e\x7d\x28\xc3\xc4\x51\x90\x45\x94\xb4\xb2\x48\xf1\x0f\xcb\x09\x60\x5f\xfe\x49\x2a\xca\x95\xb6\xf2\x9d\xb3\x99\xa4\xbf\x39\xed\x3c\x1d\xc6\x8e\xc0\x35\xb1\xa4\x7a\x4e\x0b\xcb\x7b\xd0\x8f\xc3\xe9\x45\x76\xf4\x36\x9b\x1e\x90\x7b\x88\xfa\xb4\x54\x0a\xb5\x25\xae\xc9\xd1\x1d\x5b\x1c\x0d\x96\x10\xe9\xe8\x5a\x1c\x21\x8f\x5a\x42\x9d\xc0\xd0\xa4\x28\x16\xe4\x08\x7e\x3b\xda\x37\x67\xdf\x81\x71\xa5\xc9\x36\x76\xe5\x0b\x3b\x60\x89\xf0\xb1\xd2\xfb\x17\x36\x91\x8b\xe0\xc5\x86\xff\x8a\x8e\x0c\x06\x5c\x2d\x12\xe6\x12\xbc\x46\x00\xc7\xe0\x7d\xee\x95\xdf\x5a\xb8\xd4\x0a\xa0\xbb\xc6\xc1\x90\x49\x2d\xbb\x34\xb9\x8d\x97\x82\x69\x10\xec\x58\x30\x11\x25\x9d\xa1\xed\x08\xdd\x41\x22\xb7\x13\x79\xdb\x41\x24\xf6\x00\x19\xb1\x64\x54\x68\x72\xe4\x6d\x4f\xc7\x3a\xb6\x38\x1a\xc5\xe8\xbe\x30\x22\x04\x21\xa7\x11\x7d\x71\xc0\x83\xa4\x7d\x90\xb4\x0f\x92\x76\x8f\x5e\x07\x49\x7b\xfd\x73\x90\xb4\x7b\x3c\x07\x49\xfb\x20\x69\x6f\xfa\xf0\x41\xd2\x3e\x48\xda\xdb\x3f\xbe\x9b\xa4\xbd\xab\x9f\x50\x2a\xf7\xba\xcb\x39\xcc\x9c\x45\x0d\xcf\xa2\x0f\x91\x6f\x85\xff\xda\xaf\xbc\x9d\xca\xd2\xab\xa5\xed\x54\x22\x5f\xd2\x2d\x46\x5b\x44\xeb\x20\x7c\x2f\xf5\xdc\x2c\x75\xbf\x2c\x5f\xa8\x1d\x70\x23\xb9\x50\xd8\x11\x39\x3e\xf9\xab\x70\x97\x69\x6e\xcc\xe2\x3d\x79\x4e\x4e\xfc\x8d\xcb\xa9\x05\xbe\x90\xa6\xf9\xa3\x30\x7c\x18\x5b\x84\x3b\x18\xb8\x5e\x6c\xc4\xdb\x34\xae\x25\xc2\xad\x7b\xb8\x29\x8e\xfb\x69\x49\x08\x53\x8d\x39\x70\xed\x12\x88\x81\xb7\x84\xaa\x85\xb0\xa3\x4a\xe1\xaf\x8f\x91\xe6\x60\x02\x38\x87\x79\x28\x2c\xc1\x7c\x40\x62\x8a\x50\x4a\xee\x3b\xa9\xc1\x9c\x7b\xce\x95\x5f\x0a\x77\x23\x6a\xdf\xf8\x5b\x5f\x8f\x94\xb0\x22\x1e\xbe\x3e\x22\x57\x80\x87\xe9\xc0\x5c\x03\x7c\x68\x51\xc8\xfb\x3e\x24\xe9\xa9\xc2\xa2\xee\x7b\x87\x45\xb5\xee\xef\x0e\x51\x51\xff\x22\x51\x51\xf0\x23\x1e\xa1\xbd\x87\x47\x91\x1f\x66\x0c\xb0\x48\x31\x00\x55\x59\x17\x86\x57\xd1\x57\x4a\xe3\xa7\x0a\x94\x32\x27\xce\xf3\xa4\x89\x97\xf6\x6b\x34\x9b\xb5\xf1\x13\xc6\x03\xdf\x2a\x0d\x87\xd6\x79\x77\xd0\xa2\x70\x31\x45\x5e\x24\x45\x17\x16\xfe\xdc\x9e\x09\x97\x3e\x2b\xa2\xd7\x66\x80\xc8\x9c\x58\x5a\x58\x2c\x5c\xa6\xba\x0d\x44\x14\x95\xa2\x39\xf3\xac\x77\xca\xe7\x4c\x44\x4a\x7a\xa2\x4f\x4f\x3d\x0f\xdf\x2b\x85\x7f\x14\x0a\xfd\xfb\x84\x92\xfe\xa1\x0b\x8d\x86\x05\x05\x2a\x1d\xc1\x17\x69\xf4\x73\xba\x60\xf4\xb9\xe7\xef\x67\x63\xd8\xe1\x7e\xff\x09\xef\xf6\xbf\x9c\xc8\xb2\x67\xb6\x30\x3e\x87\x6f\xfd\x8b\xb7\x2a\x1e\x9c\xeb\xe3\xf3\x50\xe7\xfa\x47\xb7\x1c\x3e\xaf\x8f\xfd\x17\x60\x2d\x7c\x4e\x1f\xfb\x83\x85\x70\xe3\xa6\xbc\x34\xd7\xf7\xe6\xb3\x93\x45\xf0\x60\x0d\xdc\x99\x0b\xf7\x64\x38\x0f\xb5\x02\xf6\xc4\x88\x1d\xef\xd9\x0f\x77\xec\x4f\x73\xc7\x7e\x90\x78\x3b\x3e\x07\x89\x77\x2d\x50\x0e\x12\x2f\x39\x48\xbc\xdb\x96\x77\x90\x78\x37\x82\xe7\x20\xf1\x6e\xdc\x94\x83\xc4\x7b\x90\x78\xc9\x97\x26\xf1\xee\x92\xa5\xeb\x70\xd7\xfd\xa0\xbb\xee\xbe\xd4\xa2\x17\x8d\xe8\x89\x07\xbd\xef\xb6\x0f\xf7\xda\x2f\xe5\x5e\xbb\x73\xc0\xbf\x30\xfc\xa1\x41\xff\xe9\x5e\xad\x8b\xfc\xa7\x73\xc9\x73\x52\xd5\xc6\xc5\x53\x1f\xa2\xff\xf7\x11\xfd\xdf\x80\xfc\x21\x05\x40\xa7\x14\x00\xeb\x60\x76\xc8\x03\x70\xc8\x03\xb0\xe7\x4b\xe8\x43\x1e\x80\x43\x1e\x80\x43\x1e\x00\xff\x1c\xa2\x93\xc8\x21\x3a\xa9\xd3\x73\x88\x4e\x5a\xff\x1c\xa2\x93\x5e\xac\xf5\x95\x1c\xa2\x93\x5e\xb6\x25\x96\x1c\xa2\x93\x0e\xd6\xd9\x8e\x1b\xf5\x05\x46\x27\x1d\xf2\x00\xbc\x54\x1f\x05\x72\x90\xb4\x0f\x92\xf6\x41\xd2\x3e\x48\xda\x9b\x9f\x83\xa4\xdd\xe3\x39\x48\xda\x07\x49\x7b\xd3\x87\x0f\x92\xf6\x41\xd2\xde\xfe\xf1\x43\x1e\x80\x2f\xc8\x37\x82\x1c\xf2\x00\x1c\xfc\x25\x0e\x79\x00\xfe\x75\xf3\x00\x34\xee\xee\x9f\x2f\x19\x40\xff\x69\x1c\x32\x02\x1c\x32\x02\x1c\x32\x02\x1c\x32\x02\xf8\xe7\x90\x11\x00\x9f\x97\x64\x6b\x3c\xc4\x47\xad\x05\xca\x21\x3e\x8a\x1c\xe2\xa3\xb6\x2d\xef\x0b\xb0\x1b\x1e\xe2\xa3\x5e\xa0\xad\xf0\x10\x1f\x75\xb0\x0b\xb6\x37\xe7\x0b\x89\x8f\x3a\x64\x04\x78\x89\xb7\xed\x07\x89\xb7\xe3\x73\x90\x78\xd7\x02\xe5\x20\xf1\x92\x83\xc4\xbb\x6d\x79\x07\x89\x77\x23\x78\x0e\x12\xef\xc6\x4d\x39\x48\xbc\x07\x89\x97\x7c\x69\x12\xef\x21\x23\xc0\x21\x23\xc0\x21\x23\xc0\x97\x78\xc3\xbd\x75\xa7\x99\x98\xaf\xdb\xd3\xc6\x2e\x5e\x89\x79\x53\x4f\x61\x62\xce\x95\x14\x40\x81\xe7\x54\x71\x3a\x2e\xe0\xa4\x82\xc4\xe3\xe0\xef\xe8\x27\x53\x23\x72\x41\x85\xbb\x68\xc5\x9b\xcc\xb5\xf3\xdf\x8e\xf8\x5b\x50\xbd\x3d\xed\xef\x69\x53\x54\x13\x2b\xa7\x4e\x5c\x03\x3b\x75\x4a\x2e\xc2\xc4\xd7\x7e\xa6\x13\x01\xef\xa2\x1f\x0c\x01\x39\xd7\x36\xe8\x26\xc5\xdb\x21\x36\x9f\xcd\x06\x58\x3e\xd0\x32\x86\xf8\xaf\x80\xc6\x88\xbc\x77\x12\x12\x25\x17\xff\x7d\x7d\x79\xf5\xe1\xd3\xf5\xdb\xeb\xab\x8f\x9b\x91\xae\x23\x59\x81\x83\xd4\x63\xb2\xc7\xdf\xfb\x3d\x82\x30\x6f\x26\x2c\x05\xfe\xc5\xc9\xf7\xe7\x1f\xff\xfb\xc3\xf9\xfb\xab\x53\x60\xbf\xec\x73\x45\x45\xce\x72\x52\x6b\x4f\x12\x2a\xc5\xe6\x5c\xd6\xba\x58\x84\xe3\xbd\x1a\x69\xdb\xd8\xea\x14\xcd\x05\xd1\x4c\xcd\x79\xb6\x1a\x44\x28\xc5\xd2\x88\x40\x59\xc0\x70\xc5\xb4\x2c\xe6\x2c\x47\x59\x23\x4c\xda\x7f\x87\x8b\xaa\x36\x5e\x22\x06\x17\x04\x7b\x2a\x44\x36\xa3\x62\xca\xf2\x11\xb9\x94\xb5\x1d\xef\x17\xbf\x80\x85\x29\x96\xd7\x19\xf2\x3a\xea\x05\xa6\x5f\x0c\x3c\x25\xb1\xb4\x40\x63\x1a\x05\x9d\xd1\xca\x2f\x3d\x85\x8e\x5e\x08\x43\x3f\xbf\xc1\x3b\xf8\xa3\x5f\x24\x3f\x1d\xf9\x14\x14\xd2\x7e\x02\xe9\x11\xce\xaa\x80\xec\x07\x05\x39\x4a\x5b\x8f\xc8\x95\xfd\x06\xcb\xd3\x7d\x40\x17\x0a\x36\x67\x0a\xe4\x69\xb7\x0b\x03\xa2\xd8\x94\xaa\xbc\x60\x1a\x9c\x07\xee\x67\x0c\xd2\x79\xa0\x84\xe5\x00\xc6\x82\xb4\x2e\xa4\x19\x91\x4b\x36\xa1\x75\x61\x80\x86\x1c\x1d\x8d\x8e\xf7\x86\x6a\x6f\x95\xdc\x12\xfc\xde\x40\xb7\x5b\x4c\x2a\x31\x91\x6a\xed\xf1\x38\x76\xa6\x89\x06\x59\xd3\x96\x93\x38\x4d\xcf\xd3\x6a\xd4\x2f\x3a\xac\xa4\x83\x20\xd8\x5d\x9d\xcf\xa4\x98\xf0\xe9\x7b\x5a\x7d\xc3\x16\x1f\xd9\xa4\xa7\x37\x04\x32\x51\xa7\xd3\x02\x03\xb3\xe4\x10\x07\xdc\xce\x74\x1e\xf1\x2e\xbf\x8b\xd1\xa4\x9f\xcd\xa3\xb3\xa5\x63\x29\xa5\x05\x32\x7d\xc7\xbe\xf7\x98\x9c\x27\x3e\xdb\x29\xfa\xca\xc9\x1d\xa7\xa4\xdd\x9d\x53\x33\x22\xef\x25\xb8\xe4\x4c\xe4\x1b\x32\x33\xa6\xd2\x6f\xce\xce\xee\xea\x31\x53\x82\x19\xa6\x47\x5c\x9e\xe5\x32\xd3\x67\x99\x14\x19\xab\x8c\x3e\x93\x73\x4b\xf9\xd8\xfd\xd9\xbd\x54\x77\x5c\x4c\x87\x56\xd2\x19\xe2\xae\xea\x33\x10\xa6\xce\x7e\x8e\x12\xfb\xa7\x6f\x2f\xbf\x7d\x43\xce\xf3\xdc\x65\xec\xa9\x35\x9b\xd4\x85\xcb\xde\x31\x22\xb4\xe2\xdf\x33\x65\x95\xb2\x01\xb9\xe3\x22\x1f\x90\x9a\xe7\xff\xb9\xf9\x70\xef\x08\x31\x59\xa1\x6e\xb4\x03\xd4\x6e\x41\x50\x5c\x34\xe8\x54\x40\x7a\x4b\xa1\xb8\xd1\xb0\xe7\xde\x70\xe0\x18\x4a\x8f\x65\x8c\xa5\x2c\x18\x15\x5b\x7a\x00\xd8\xfa\x9f\xd9\xe3\x78\x68\x51\xcb\x71\x08\x50\xc9\xfc\x0d\xd1\x75\x55\x49\x65\x34\x29\x99\xa1\x39\x35\x74\x64\x77\x6e\xd0\xfc\x13\x84\xe3\x01\xf9\x6b\x78\x09\x12\xae\xfe\xd3\xf1\xf1\xef\xbf\xb9\xfa\xaf\x3f\x1c\x1f\xff\xe5\xaf\xe9\xaf\x40\xf6\xd0\xd4\xd5\x6c\x62\x45\xee\x91\x15\x77\x3f\xc0\x37\xe0\x4f\xc7\x46\xcf\xb3\x4c\xd6\xc2\xb8\x1f\x0c\x35\xb5\x1e\xcd\xa4\x36\xd7\x37\xe1\xcf\x4a\xe6\xed\xbf\xf4\x16\x4e\x40\x1e\x97\xe8\x00\x38\x6f\xa8\x99\xed\x99\xf4\xc4\x73\xb1\x03\xba\xba\x9e\x69\x86\xa4\x92\xc2\x3f\xdf\xfa\xe9\x5a\x0e\x74\xaf\xb8\x31\x4c\x80\xdc\x01\x7e\x77\x72\x32\xb0\x98\x1b\xd9\xec\xfc\x75\x2f\x75\xb4\xf3\x51\x0c\x50\xdb\x61\x71\x30\x7b\xb7\x32\x44\xe6\x40\x68\x97\xf5\xba\xf3\x9b\x6b\x32\x47\x68\xec\x7d\x21\xde\x0b\xeb\xed\x83\xcf\x64\xc8\x54\xe5\x96\x15\x24\xcd\x37\x68\x59\x0a\xfe\x5e\xa4\xe0\x25\x77\x06\x60\x97\xd5\x4a\x93\x13\x7c\x39\xca\xaa\x7a\xe0\x1a\x8c\x4a\x56\x4a\xb5\x08\x7f\xb2\x6a\xc6\x4a\x2b\xb1\x0d\xb5\x91\x8a\x4e\xd9\x20\x74\xc7\x6e\xe1\x2f\xec\xd8\xf8\xc0\x72\x6f\x14\xa9\xb3\x5a\x59\xe6\x51\x2c\x3c\x05\x61\xf9\xf3\x9e\x45\x0f\xa6\x3d\x1f\xc5\xb0\x1b\x1f\x76\x64\xb9\x41\x5b\x44\xa6\x1d\x56\x05\x32\xe4\x5c\x16\x75\xc9\xf4\x20\xb0\x27\x94\xd6\xc5\xdc\x4a\x93\xfa\x51\x18\x61\xce\xe7\x5c\xef\x74\x3f\x7d\x1b\x2c\x75\x60\x22\xab\x8d\xd5\x54\xd0\x19\x3c\xc9\x08\x27\x35\xe8\x00\xc1\x47\xb1\x41\x52\x5e\x1f\x75\xbb\x7d\xa5\xc6\x30\x25\xde\x90\xff\xff\xe4\xcf\xff\xf6\x3f\xc3\xd3\xff\x3c\x39\xf9\xd3\xab\xe1\xff\xfe\xcb\xbf\x9d\xfc\x79\x04\xff\xf8\xe5\xe9\x7f\x9e\xfe\x8f\xff\xe3\xdf\x4e\x4f\x4f\x4e\xfe\xf4\xcd\xfb\xaf\x3f\xdd\x5c\xfd\x85\x9f\xfe\xcf\x9f\x44\x5d\xde\xe1\x5f\xff\x73\xf2\x27\x76\xf5\x97\x8e\x83\x9c\x9e\xfe\xe7\x2f\x3a\x4d\x8f\x8a\xc5\xb7\x1d\x0e\x3c\x3e\xc3\x1d\x3c\xec\x63\xaf\x1e\x06\xfa\xcf\xc3\x28\xb4\x0d\xb9\x30\x43\xa9\x86\xd8\xfd\x0d\x31\xaa\xde\x7e\x30\x22\x51\xdb\x05\xcf\x7d\x3a\xb0\x37\x91\xa0\x05\xd2\xbc\x77\x44\xd6\x2c\x53\xcc\xec\x4b\x83\xc1\xd1\x3c\xff\x68\x99\x64\x0f\x4a\x4d\x54\x6a\x82\x5d\x12\xe0\x15\x39\xef\x44\xc9\x72\x44\x12\xb3\xd0\x1c\x6e\x32\x5d\xbb\x3b\xb6\x45\xcb\xf5\xcf\x41\x09\xfa\xb2\x94\xa0\x5b\xdc\xdf\x47\xd7\x80\x98\x98\x6f\x32\xd3\xb4\x6d\xba\x6f\x21\x94\x25\x35\x47\x7b\x01\xca\x48\x52\xc9\xaa\x2e\xa8\x59\x63\xb6\x5b\x61\x9b\x76\xb8\x1f\x6f\x01\xec\x46\x83\x1d\xd8\x51\xb9\x72\xb5\x31\x94\x9c\x17\x05\xe1\x02\x4f\x02\x0c\xe0\xad\x79\x8a\xa1\xbc\x44\x28\x1a\x9c\xe7\x76\x0a\xf7\x2e\xe0\x26\x31\x34\x72\x6d\x75\x1d\x65\xc0\xe2\x0f\x01\x39\x48\xb3\x9c\x69\x8c\x8b\x18\x96\x13\xb8\x6d\xb8\xa5\x5c\x99\x7f\xb1\xa0\xda\xf8\x69\xc3\x6c\x0c\xbd\x03\x53\x68\xc6\x72\x26\x32\x06\x2e\x08\x35\x8b\x6b\x1d\x5b\x61\x10\xcc\xfb\x30\x06\x25\x79\x5d\x15\x3c\xb3\xf0\xb3\x33\x59\x3d\xc6\x75\x59\xd6\x06\x0c\xc5\x4f\x65\xc5\xb7\x3b\x7e\xeb\xd3\xbd\x06\x63\x3e\x90\xaa\x20\x5a\x07\x6f\x8b\xa0\xba\xeb\x87\x99\xef\xbb\x11\xde\x60\x6e\xdb\xca\xa9\x96\x28\x6e\xb4\x31\x34\x29\xed\x53\x5b\x0c\xbb\xd1\xd9\x9f\x24\x8d\xed\x41\x5f\xbb\xd3\xd6\x1e\xc6\xa5\xbe\xf4\xb4\xab\x35\xa9\x52\x6c\xc2\x3f\xf7\xc0\xc7\x73\x11\x55\x14\x9e\x33\x61\xac\x22\x00\x99\xa9\x2b\xc5\x2a\x26\xf2\x10\xee\x07\x0e\x5e\xa2\xb9\x8e\x47\xbd\x31\x42\x29\xa3\xff\xf1\xba\x5d\x25\xc5\x1c\xce\xd6\x4f\xfc\x6c\xb9\x5d\xdf\xff\xc1\x12\x32\xdf\xea\xfc\xdd\xda\xc7\xa4\x47\xcb\xd3\xd5\xa5\xff\x76\x93\xb4\xda\x5b\xb8\x72\xaa\x64\x8e\x39\xae\x4d\x74\x42\x18\x91\xdb\x15\x3d\xc1\xd7\xc0\xb5\x38\x3e\xd6\xe8\x96\xa0\xdb\x03\xb5\xa2\x9b\xd1\x33\x01\x07\xed\x89\x52\xc8\xea\x6a\x05\x96\xdf\x33\xaa\x35\x9f\x8a\x61\x25\x73\xc8\xcb\x7d\xb6\x0e\x21\x3a\x1c\xaa\x7e\x9e\x4d\x5b\xf1\x2a\x18\x27\xba\x6d\xd3\xc7\x60\x7f\x4b\x64\x0b\x9f\x11\x5e\x25\x3f\x3a\xbb\x8e\xf7\xa3\x4f\x64\xc8\x28\x11\x3d\x0c\xa6\x25\x15\x74\xca\x86\xee\xe3\xc3\xf0\xf1\x61\xf8\xd6\x43\xc0\xdc\x85\x6a\x65\x05\xe5\x9b\x5d\x89\x1a\xc0\x3b\xba\x80\xf6\x2e\x50\x3c\x78\x60\xb5\xc2\x58\xbd\xb4\xc9\x05\x5e\x09\xf8\x9f\xb0\xf3\x00\x51\x92\x2a\x77\x8d\xba\x02\xbe\x7f\x16\xe8\x48\xe4\xfc\x4a\x8b\x6a\x46\x13\x87\x2e\xb7\x33\x9a\x30\x41\xc7\x85\xbf\x05\xbf\x5c\x08\x5a\xf2\xcc\xef\xee\x79\x01\x0e\x3f\x5c\x0a\x32\x61\xd4\xd4\x8a\x91\x29\x35\x2c\x8e\x1d\x3c\x05\x79\xdc\xcc\x6b\x43\x32\x2a\xd0\x4c\x3b\xc6\x48\x0d\x7b\xba\xc2\xcc\xf4\x68\x93\xbd\xab\x9b\x17\x57\x07\xdf\xad\x56\x5a\xf6\x04\x78\xe9\x65\xbc\x14\x56\xe9\x31\x0a\xd8\xf3\x8d\xcc\x2d\x75\x1c\x35\x5a\x6f\x71\x8a\xef\xcc\xfe\xba\x1a\x39\xb6\x38\xb7\x90\xc7\xe6\xa4\xc0\x48\x13\x52\xe9\xf1\xd3\xa2\x67\x03\x5a\x95\xcc\x47\x2b\x30\xd3\x33\xe1\x1b\x99\x3b\xbf\x31\xd3\xc0\x14\x8b\xae\x80\x24\x25\xbd\xf3\x3e\x5f\xc1\x38\x46\xe7\x94\x17\xe0\xea\xc0\x85\xe6\xb9\x15\x8d\xb2\xed\x8e\x45\xfe\xe9\xc8\x3c\x1b\x36\x41\x7b\x08\x87\x25\xad\x86\x56\x1b\xdd\x0c\xaa\xad\x3b\xb3\x3c\x30\xce\xa8\xa4\xd5\xda\x5e\x78\x1d\xd1\x99\x76\x1c\xbf\xc3\xeb\x8e\x3c\x94\x96\x41\xdf\xdf\xcf\xbc\xac\x4b\x42\x4b\x59\xa3\x7b\xef\x32\x29\xf6\x4e\x70\x7b\x21\xb6\x2b\x88\xac\x5e\x4b\x65\x49\xf7\x63\xd2\xdf\x5d\xf7\x85\x5a\xc5\x3b\x59\xc3\xfb\x59\xc1\x7b\x58\xbf\x77\xb6\x7a\xfb\x0b\xae\xee\xf8\xf8\xd1\xdf\xb9\xb5\x30\x92\x8b\xad\x18\xa9\x42\xad\x8c\xeb\x09\x09\xe3\x70\x4d\x64\xc9\x8d\x71\x97\x41\x09\x01\x18\x10\x6e\x1a\x37\x27\xee\x2c\x40\xad\x18\x2c\xaf\xc3\x3e\x57\x05\xcf\x38\xdc\xc0\xf9\x1b\xcf\x01\x4a\xe8\xf7\x1c\x33\xcb\x50\x41\x78\x59\xa1\x23\x3c\xe0\xf4\xd0\x73\x5a\xe7\xa0\x14\x66\xe2\xdc\xd3\xd8\xe7\x8c\xb1\xdc\x7d\xec\x70\x7c\x0e\xc7\x67\xf5\xf1\xd1\x7d\xd4\x9c\x54\xc3\x89\xce\xd1\x41\xd3\xb1\x88\xef\x6b\x5a\x81\xf3\x37\xe2\x90\x3d\x2a\x10\x9f\x63\xc5\xb5\x8f\x0c\x8c\x8e\xb7\xcc\x68\xe7\x6e\x0d\x3d\xac\x44\xb8\x14\xbd\xea\x8d\xac\xc1\x8b\x9f\x4e\x26\xcd\x16\x39\xab\x0a\xb9\x28\x41\x69\xbe\x36\x6d\xfe\x0f\x5a\x11\x2b\xab\x82\x1a\x16\x74\xa6\xcd\x86\xcc\x07\x0b\xd5\x7d\x42\x47\x9f\x37\x58\xf4\x71\x44\xd6\x17\x19\x02\xfa\x08\xd2\xee\xf6\xeb\xbc\x8e\xa1\x9c\xdd\xa5\xe2\x4e\xf7\x7d\x8f\x1d\xa0\xd9\xcb\xd2\xd3\x35\x08\xf3\xe5\x87\x5d\xf6\x58\x76\xd7\xd0\xca\x43\x30\xe5\x26\x50\x77\x0b\x88\xea\x1c\x0c\xd5\x69\xff\x3a\x06\x45\x1e\xc2\x20\x7b\xf0\x97\x47\x10\xfe\xb6\xee\xa5\x91\x05\x43\xc9\xb5\x9b\x59\xf0\x53\x6c\x1f\x4a\x2b\xa2\xe7\x48\x32\xd2\xd3\x5c\x80\x7e\xf2\x62\x8b\x3d\x5b\x71\x5e\x80\x5a\xc6\x50\xa8\xa3\x68\xa4\x9f\x97\xdd\x38\xb1\x20\x76\xcf\x8c\x2b\xaa\x99\x54\x99\x34\x0a\xee\x93\x7f\x1f\xb0\x6d\xc0\x40\x7e\xfa\x43\x12\x3a\x13\x42\xeb\x02\x86\xfc\xde\xff\xeb\x0f\x0f\x0c\x89\xea\xc6\xd8\x70\x4a\x3d\x04\x8c\x2b\xe8\x40\xb8\xc8\xe1\xee\xda\x2d\x15\x20\x80\x63\x59\xf8\xc0\xb2\x7c\x68\x1d\xc6\x68\x3a\x0b\x3a\x5c\x72\xc7\xc6\xda\xdd\xc6\x27\x6a\x97\xb3\x38\xc4\x93\xc1\xc8\x07\xe9\xf2\x9d\xb2\x01\xb9\x01\x33\x5c\x7c\x03\x27\xe9\x83\xc4\xcc\xa7\x6b\xaf\xc9\x53\xb8\x6d\xe5\x22\x5b\x19\x7d\x03\x20\xdf\x44\x26\x8f\x2b\x6b\x30\xf9\x88\xc1\x8d\x20\xdb\x4d\x90\xb9\x63\x8b\xc8\x6c\x9c\x08\x01\x24\x7f\x10\xb1\xc4\xb3\x02\xe4\x1d\xff\xe1\xad\xb8\xe5\x98\x0b\xfc\x18\x0e\xed\xb7\x02\x46\xf7\x00\xb5\x92\x5d\x51\xe0\x67\xf6\x01\xae\x6e\x72\x46\x03\x66\xdf\xf6\x90\x31\x02\x95\x5c\x2d\x5d\x24\x22\xc5\xd5\x8f\x35\x2d\x9a\xf1\x4d\xee\x95\x6b\xb4\x44\xd5\xef\x79\x91\x67\x54\x39\x07\x52\x38\xa3\x44\x4b\x67\x24\x07\x42\x90\x51\x11\x4e\x7b\xdc\x23\x2c\xb1\x4a\x2a\xaa\x0c\xcf\xea\x82\x2a\x62\xcf\xc2\x54\xaa\x4e\x31\x48\x5b\x21\x1a\x91\xe6\x96\x65\x52\xe4\x7d\x14\x80\x4f\xed\xbe\x6d\x37\x8e\x8a\x29\xee\x32\x89\xf2\x92\xb5\x91\xf4\xa4\x79\x5d\x26\x27\xfe\x54\x87\x23\xd6\x30\x8c\x34\xad\xf9\x98\x8a\xf8\x34\x21\x8f\xe1\x54\x8c\xc8\x57\x0b\x6f\x85\x01\x8b\x8c\x0b\xdc\xd2\xcc\xf8\x18\x3b\x8f\xb2\x0e\xd8\xf1\x40\x4d\xa4\x82\xb8\xb7\x93\x5c\x62\xb0\xd7\x9c\x67\xe6\x74\x44\xfe\x3f\xa6\x24\x06\x87\xb3\x29\x26\x86\x75\x28\x1e\x14\x57\xa8\x89\x0c\xce\x41\xaf\xc8\x09\x26\xe9\xe5\x65\xc9\x72\x4e\x0d\x2b\x16\xa7\xa8\xc7\xfa\x34\xbf\x5d\xb6\xae\x8b\xd1\x20\xc9\xe9\xfc\x9b\x5f\x6f\x68\xd9\x37\x3c\xf3\x7b\x1f\xf0\x16\x21\x83\xee\x49\xad\x2d\x0c\x3c\x48\x6e\x10\x37\x53\xf7\xa6\x18\x2f\xee\xc9\x4c\xd8\xe0\xbf\x59\x3c\xa0\x44\xb1\x29\x60\x39\x62\xee\x03\x71\x1c\x1d\xb5\xdf\xcb\x5a\xac\xb7\x18\x36\x16\xfe\xce\x29\xe1\xdf\x27\x1d\xd7\x06\x40\x3f\x89\x98\x90\xcc\x24\xb1\x60\x52\x02\x66\x4b\x60\xe7\x96\x3c\x60\xab\xe8\xe4\xd6\xe1\x4e\x62\x8f\xc1\xce\x30\x97\x2d\x01\x35\x7b\x09\x89\x0e\x1f\xea\x81\xcb\x10\x7b\xe2\x00\xd3\x0a\x09\x36\x8e\x1c\x00\x7e\x22\x04\x23\x82\xc2\xb7\x58\xee\x1d\x64\x31\x8d\x01\x74\x25\xc7\x6f\x8e\xf7\x42\x7c\x71\x39\x4a\x56\x74\x4a\xb7\xa7\x52\x6f\x2a\x23\xad\xae\x24\x67\x86\xa9\x12\x72\x5e\xcf\xe4\x3d\xfe\x8e\x6c\xab\x72\xad\x98\x4b\x17\x6e\x57\x3b\x93\x1a\xb8\x52\x33\x3e\x1a\xce\x2f\xf8\x5c\xdc\xd3\x05\xa1\x4a\xd6\x22\x77\x52\x53\x20\xa0\xef\x5b\x1f\xfe\x20\x05\x8b\xb7\x66\xcd\x3b\xd7\x31\x33\xd4\x1e\x9b\xd7\xa3\xd7\x5b\xd2\xda\x77\x04\x58\xcf\x90\x78\x98\x4d\xcb\x52\xe8\xdd\x70\xfc\x99\xd9\xcb\xbc\x14\xa3\xf9\xb7\xa2\xe8\x23\xcb\xbd\x47\xf4\x82\xae\x43\x50\xc2\xf8\x04\x6c\xb7\x03\x7c\x75\xaf\xb8\x61\x09\x79\x3c\x99\xd0\x42\x43\x2d\xff\x5a\x04\x11\xf6\xb4\x29\x82\x40\x93\x2e\x0b\xda\xee\x6a\xa6\xeb\xf1\x03\xcf\x99\x3b\x50\x80\x72\xf1\x98\x05\x84\x3b\xd6\x1b\x8e\x5c\x33\x6e\x9c\x9c\x60\x4b\x2b\xb1\x49\x69\x4e\xf7\xe3\x7f\x86\x0b\xb4\x9a\x75\x1f\x95\xc4\xa7\x24\xa8\xf6\xb8\xda\xaf\xd8\x8c\xce\x99\x26\x9a\x97\xbc\xa0\xaa\x80\x30\xe4\x5b\x9c\x1f\x19\xd7\x66\x75\x72\x8b\x7e\x89\x13\xd2\x99\x24\xc3\x6d\x05\xb5\x9f\x87\x85\x13\xd0\x08\x3f\x2f\xac\x2f\xe0\x8b\x12\x7c\xce\x8a\x5a\xf3\xf9\x43\x4f\x93\x0b\xac\xda\x81\x55\xb7\xb9\x74\xe5\x3c\x25\x9e\x90\x47\x37\x35\x0c\x4b\xaa\x72\xbf\xe9\xc0\x93\x51\xd9\x07\xcd\x1d\xfc\x4e\x68\x96\x31\xad\xbd\xbb\xf6\x22\x75\x21\x0f\x6b\xf8\x52\x72\x95\xd0\x7b\x7d\x55\x50\x6d\x78\xf6\x55\x21\xb3\xbb\x5b\x23\x55\xaf\x74\x20\xab\xfa\xb7\x32\xbc\x9c\xff\x70\x4b\x2e\xb9\xbe\x4b\x02\x95\xdc\x9d\x6a\x6a\x2e\xa1\xe4\xae\x1e\xb3\x82\x99\xe3\x63\x8d\x5c\xae\xa4\xd9\x8c\x0b\xe6\x19\x9c\x08\xd1\x6e\x4e\xe1\xb3\x50\xee\x7b\x67\xea\x62\x2a\xcf\x1c\xbe\xfe\x9c\xde\x6b\x86\xd3\x1f\xdb\xe9\xdb\x9f\x59\x97\x64\x17\x7b\xbd\xa7\xc0\xc9\x5c\x5f\xee\xe9\x0e\x62\xa2\x3f\xd9\x39\xf6\x33\x6e\x1f\x63\x2f\xaf\x3a\x4c\x78\xc1\x5c\x61\x13\xbb\x60\xef\x79\xe3\x4e\x05\xec\xdf\x42\xd6\xe4\x9e\xa2\x8e\x0c\x14\x71\x44\x3e\xf1\xea\x0d\xb9\x12\xba\x56\x2c\x5a\x37\xda\x43\x71\x1d\x43\x58\xbd\x72\x05\xfb\x8d\x0a\x88\xa5\x7b\x4e\xd7\x22\x57\x9f\x69\x59\x15\x4c\xbf\x21\x47\xec\xb3\xf9\xf5\xd1\x80\x1c\x7d\x9e\x68\xfb\x3f\x61\x26\xfa\x68\x44\xae\xcb\x70\x29\xcf\xc5\x84\x29\xc5\xbc\x8f\x25\x76\xb0\xac\x39\xe1\xba\x8f\x82\x2e\xce\x5f\xd7\xca\x6e\xb9\x24\xf7\x98\xea\xc6\x12\x7c\xa6\x94\x54\x21\xc4\x25\x01\x03\xf0\x9a\x4c\x96\x95\x92\x25\x4f\xcc\x7c\x80\xee\x7b\x75\xe4\x05\xe3\x43\x97\x5a\x3f\x6d\x6c\x08\x1d\x3d\x42\x24\x2f\x44\x17\x54\xb8\x9e\x78\x5f\x0b\xd4\x22\x9d\x5a\x0f\xc3\xb9\x46\x76\xf3\xdd\x28\x96\x90\xa5\xdb\xfd\x36\xc4\xea\x92\xb3\x9c\xcd\xcf\x74\x4e\x5f\x0f\xe0\x33\xda\xf9\x18\x37\xe7\x44\x35\x39\x7a\x7d\x34\x22\xb7\x9e\x11\x0f\xd2\x39\xc6\x76\x13\xa9\xc2\x80\x60\x67\x7f\x75\x44\x4e\xa4\x82\x91\x33\x2a\x48\xc1\xe8\xdc\xd9\x96\xf1\xb8\x2d\x50\xdd\x3d\xed\x1c\x6b\xdd\x35\xec\xb4\x7b\x51\xa7\xae\x42\xea\xf2\x26\xfa\x7e\xde\x04\xa0\x6a\x17\x86\x34\x91\xca\xa5\x18\x0a\x4d\x34\x33\x70\xf4\xb8\x68\xa8\xd0\xcf\x40\x60\x49\xcf\x2c\x1d\x9e\x7a\xf6\x85\x8e\xef\x07\x3a\x90\xe0\x3f\xd6\x8c\x5c\x5f\x86\x5c\x1d\x4c\x69\xae\x8d\x3d\xc6\x79\x83\x75\x71\xe4\x67\x27\xe7\x25\xfd\xbb\x14\xe4\xea\xab\x5b\x37\x81\xd3\x67\x05\xd5\x56\x6a\x40\xff\x5e\x2b\x66\xb9\x70\x0f\xe6\x1e\xfa\xb4\x19\xba\x7d\x4f\x2e\xa9\xa1\xc8\xd7\x9d\x23\x96\x88\xa4\xdc\xb2\xec\x31\x17\xb9\xfb\x29\x61\xd8\x4f\xcd\x5b\xed\xee\x7d\xd8\xe6\xf5\xea\x1b\x7e\xf7\xf1\x7a\x4f\x3c\x38\x03\x62\x3e\x7d\x2f\xf3\xde\x8c\x38\xe9\xea\x89\xef\x1f\x2d\x4c\x2f\xf0\x3d\x29\xed\x98\xc4\x6a\xef\x03\xf2\x91\xd1\x9c\xd8\xf3\xeb\xfe\xf9\x83\xd5\x3d\x3b\xd3\xaa\x4e\x2c\xc4\x03\xb0\xe7\x32\x7c\x37\xbf\x84\x34\x88\x26\xb7\x98\x03\xc7\xca\xf1\x92\x71\x21\xc7\xc4\x1d\x87\x7d\xcf\xfd\xbb\x8f\xd7\x3b\x4c\xfd\xbb\x8f\xd7\x7e\xe6\xf6\x9f\x72\xf2\x74\x93\xde\x49\x7c\x8b\xd2\xdb\xdb\x96\xb8\x15\x59\x72\x8c\x09\x6b\x8b\x64\xdd\xe5\xb1\xd1\xbe\x24\xb1\x7d\x42\xec\x8e\x8b\x0e\x01\xfe\xcd\x53\x66\xfb\x58\x85\x02\x7d\xd5\x92\x7b\xc4\xdb\x19\x85\xac\x0a\x21\xd6\x17\xf6\xd9\x6e\xbc\xb6\x5c\xc1\xef\xb8\x55\x02\x81\xb6\x91\x4b\x86\xb7\x9c\xf9\x1b\xef\x3b\x10\x7a\xac\xee\xf0\x1e\x3c\x35\x73\x47\x5f\x09\x3a\x6e\xe6\x09\x82\x9d\xa0\x55\x49\x84\x9f\x9c\xef\x3a\x2f\x38\x54\x69\xb0\xda\x7d\xea\xac\xaa\x61\xca\x7b\x3d\xf5\x3b\x8a\x1c\x41\x9c\x58\x32\x6e\x91\x13\xfb\xdb\x19\x18\xc7\x4e\x47\x40\xad\xa0\x21\xb8\xf1\xb7\x84\x92\x8f\xdb\x84\x92\xbd\xc9\x0f\xb0\x03\xf6\xc4\xf4\xe5\x8a\xb6\xcf\x4a\xae\x08\x3f\xdc\xba\x54\x95\x2f\x99\x31\x62\x18\x67\x27\xd6\x08\xf8\xb5\xb5\x65\x77\xe6\xf8\x50\xe4\xca\xbf\x0c\xe4\x22\x21\x58\x76\x07\xfe\x19\x3b\x7a\x3e\x14\x42\x65\x7c\x3a\x90\x86\x6b\x26\x62\xdf\xad\xa3\x35\x2e\xbb\x1b\x72\x5d\x8b\x73\x5d\x4a\x2e\xf6\xc9\x07\xe3\x31\xa2\xef\xaa\x7c\x3f\xbf\x28\x24\x81\xf0\x9a\x74\xc0\xc5\xce\x93\xcc\x58\x35\x9b\xf4\xb9\x12\xb7\x1d\xde\xde\x36\x2d\x81\x17\xac\x9a\x91\xb7\xb7\x2b\x8e\x31\xc0\x1e\x66\xad\xd1\x3e\x78\xac\x49\xc1\x27\xcc\xf0\x2d\x4b\x78\x84\x83\x5c\x4a\xc1\x8d\x54\xeb\xb3\x2b\x90\x5e\x87\xd3\x0f\xd7\x97\xa1\xfa\x7e\x76\x67\x63\x6e\xa2\xf7\xc9\x5b\x4a\x32\x59\x14\x2c\x33\x2e\x5b\x1e\x80\x37\x74\x5b\xa1\x3c\x31\x67\x0f\x18\xdd\xfd\x0e\xd4\x27\xa7\x28\x9d\xe1\xe6\x9e\x7d\xbc\x3a\xbf\x7c\x7f\x35\x2a\xf3\x9f\xcf\xe4\xfd\xd0\xc8\x61\xad\xd9\x90\x77\x48\x7e\xf4\x7c\xde\x8b\xf8\x54\x9d\x72\xf1\xb5\x0d\x32\x98\x46\xf0\x5b\x1f\x9a\x4d\xbe\xd3\xe8\xb5\x00\xb6\x23\x7f\x27\x25\xa5\x19\x10\x45\x5d\xf8\x35\x75\xa6\xa7\xba\x28\x10\xda\x46\x31\x36\x48\x6d\x31\x1b\x43\x43\x7a\x2f\xec\xc1\x86\x8a\xc6\x02\x1f\x57\x86\x78\x7a\x84\xeb\xc3\x31\xb6\xcb\x24\xcb\x50\x8c\x3d\x9b\x70\xbc\x6d\xbc\x47\xc3\x99\x99\x59\xa8\xde\xb1\x05\x01\x47\xe0\x89\x54\x16\x9f\x54\x13\x37\x98\xc9\x60\xe9\x67\xb5\x66\x6a\xe4\xd8\xce\x93\x83\xad\x47\x82\xb2\x1d\xf2\x42\x86\x8e\xab\x60\xe6\x5e\xc7\xa4\xe1\x4e\x5e\xa3\xb5\x99\x31\x61\xb8\x0b\x60\x76\x90\x59\x09\x44\xe7\x87\xfd\xe4\x50\xeb\x98\x1f\xad\x5f\x36\xb3\x43\x06\xb0\x3e\x38\x69\x4f\x4d\x5f\x74\xb4\x7d\x20\x4e\x31\x25\xf3\x21\x96\x4b\xd1\x5c\x82\xc3\x06\x26\xb7\x6c\x20\x1a\xcd\x4b\x2e\x5e\xe0\xe9\xcc\xb8\xc8\xb7\xc1\xa1\x65\x00\x83\x1e\x4d\x51\xcc\xbd\x73\x06\xfd\x70\x6f\x48\xbd\x26\x85\xb9\x34\xdc\x0d\x62\xf3\xfe\xb0\xd3\xe1\x2b\x17\xfa\xc7\x62\x88\x5f\x19\x56\x79\x84\xca\xe1\x32\x70\xf9\x06\x6f\xbf\x26\xa5\x27\xb8\xe2\xdb\xd3\x6e\x93\x27\x96\x86\x1e\x57\xcf\x7d\x12\x40\xf5\x91\x79\x1e\xca\xbd\x23\xcd\xac\x24\x77\xee\x9f\x21\xd9\x28\x9e\x51\xaf\x2f\x5b\x78\x54\x54\xd1\x92\x19\xa6\xd0\x05\xce\x39\xd5\x09\x17\x9d\xf0\x6d\xc5\xc4\xad\xa1\xd9\xdd\xbe\xb3\x2c\x1f\x38\xee\xe3\x71\xdc\x07\x5f\x05\x7a\x44\x70\x29\xd7\x16\xe9\x2d\x32\x17\x8e\x0b\xbd\x10\x12\x13\x32\x1d\xf6\xb1\x72\x84\x4c\x77\x4d\xee\x1a\x33\x1f\xa2\x61\x03\x3c\xdd\x42\xea\x4e\xf0\xe0\x47\x28\xec\x87\x1b\x76\x3f\x03\x8e\x04\xee\x72\x8f\x96\x74\x6d\x52\x87\xd2\xbe\x19\x73\x13\xcf\xbd\x66\x86\x54\x4c\x95\xdc\x85\x75\x4b\x41\x32\x17\x16\x00\x7c\xcd\xf2\x30\x37\x5c\xc2\xf3\x04\x91\x99\xa1\x2e\x66\x86\x8c\x99\xb9\x67\x4c\x90\x57\xaf\x5e\xbd\x02\xb9\xe4\xd5\x6f\x7f\xfb\x5b\x02\x69\x26\x72\x96\xf1\x72\xb9\x21\xb4\xfa\x5f\xaf\x5f\x8f\xc8\x7f\x9d\xbf\x7f\x07\x5e\x65\x95\xd1\x64\x2c\xcd\xcc\x8d\x6c\x1b\x34\x3a\xeb\x01\xf9\x3f\xb7\xdf\x7e\x88\x29\x96\x9a\xbf\x82\x0a\x12\x96\xd7\x74\x11\x7c\xf5\x9b\x5f\xff\x7a\x44\x2e\xb9\x82\x78\x62\x0e\x11\x10\xc1\x09\xb2\xf2\x8e\x81\x50\xd3\xac\x1d\xc1\xef\x38\x88\x73\x12\x2e\xf9\x74\x06\x00\xb0\x07\x42\x8a\x49\xc1\x33\x83\xe9\x4a\xf1\xe8\x23\xa0\x5d\xfa\x1d\xea\xc2\xbd\x9c\x14\x01\x93\x1b\x90\x82\xdf\x31\x32\xd1\x5f\x2b\x59\x57\x31\xcc\x51\x31\x6d\x65\xd9\x8c\x0a\x88\x2a\x81\xc1\xe2\x5e\x69\x66\x9e\xd5\x09\xa3\xa3\x21\xa8\x81\x83\xd0\xa7\x25\xa0\x0c\x42\xda\xc6\x21\xe2\x43\x45\x79\x70\x1c\x84\x3b\xf5\x46\xd1\x90\xa0\x7b\xe6\x49\x9a\x4a\x1f\xbb\x52\x29\xf9\x37\xdc\x2a\x2e\x7c\x14\x94\x93\x90\xb5\x93\xc9\x5c\xd0\xa9\x48\x6c\xae\x3e\x2a\xdf\xf2\x42\x17\xf1\x9f\xc4\x4f\x5d\x4f\xd2\x40\x3b\x08\x4b\xc7\xca\x8d\x8d\x9c\xba\x2b\xbe\x1c\xeb\x40\x58\x6c\xd2\xb8\xaf\xb5\x58\xea\xed\x4a\x34\x39\xf2\xe3\x0a\x77\xb9\x10\xb6\x38\x06\xba\xe2\xba\x00\xa0\xa4\x1c\x5c\x23\xcf\x65\xc3\xcb\x47\x33\x53\x3b\xd0\x80\xe7\x95\xfd\x36\xd3\xda\xc5\x11\x95\x54\xdd\x59\x25\xc1\x51\x81\x11\x78\x3d\xeb\x10\xc3\x84\x01\x65\x73\x34\x96\x97\x74\xd1\x88\x1a\xb0\x1f\x39\x1e\x8d\x8e\xf1\x98\x48\x85\x69\x82\x11\xe7\xed\xfb\x67\x8a\x97\x6e\x7a\xa5\xd3\x0a\x2b\x7a\x82\x3d\xc7\x55\x44\xa2\x0d\x6f\x67\xea\x20\xd5\x25\x39\x78\xcf\x8a\xa8\xfd\x4a\x6f\x77\x2f\xb9\x3d\x84\x05\x74\x68\xda\xb7\xbc\x76\x8f\xb2\xda\xeb\xb2\x35\x38\x18\xbb\x93\xd0\xb5\xd8\x6c\xef\x32\x03\x65\x27\xd6\xb7\x62\xaa\xc7\xa5\xe3\x7c\xdf\xf6\xe3\x7c\x2e\x5e\xaf\x51\x77\xf0\xe5\xb3\xba\xeb\x09\x46\xba\x34\x49\x97\x23\x0d\xa9\x28\x10\x6a\xfc\xc5\xb0\x97\x17\xcd\xd1\x52\xb4\xe9\x57\xd3\xa2\x0f\x77\xc3\xa7\xdb\xc5\x04\x3e\x0d\x5c\xf3\xb7\x13\xb8\x68\x47\x4a\xab\x46\xed\xa0\x02\xed\x06\x20\x63\xfa\xc3\x33\x22\xef\x1d\xa9\x45\x24\xa3\x63\x2d\x8b\xda\x60\xd7\xf8\x63\x4a\x87\x61\x50\x9f\x65\x01\x88\x6f\x68\x96\x50\x65\x13\xab\x27\x76\x23\xd0\xf8\xf4\x38\x9c\x87\x44\xc2\x8f\x98\x48\x38\xa4\xbe\xd6\x1d\x4b\xc1\xe9\x47\xcb\xdc\x9d\x69\xde\x47\xbf\xd2\x9c\x9c\xc4\x0a\x44\xfe\x3a\xfe\x5a\x18\xa6\x26\x34\x63\xa7\xa9\xde\x15\x2a\x3d\x05\x17\x21\x1f\x17\x31\xa3\x22\x2f\x50\x00\xcf\x98\x02\xdc\x67\x9f\x0d\x53\x16\x24\x17\xb7\xd7\x24\x57\x7c\xce\x94\x26\x27\x5f\x31\x2b\x2f\x62\xfe\xd4\x4e\xd1\x55\xfb\xf5\xad\x84\x69\xec\x4b\xd3\x83\xc1\xfa\xba\xea\x41\x27\x4f\x79\x44\x72\xbe\x22\x98\x10\xaa\x08\x52\x9d\xea\xb2\x23\x8b\x4a\x40\xa0\x81\x66\x2c\x64\xad\x9c\x15\xdd\xa7\x6c\xce\xa4\xb2\xea\x12\x0e\x4c\x35\x51\x6c\x6a\xa5\x59\xe5\xeb\x98\x33\x92\x15\xb5\x7d\xb1\x57\x77\xb6\x87\x38\x00\x46\xd3\xec\x26\x5f\xbd\x89\x93\xaa\xe5\x9c\xe7\x9e\x55\x62\x59\xf5\x50\x30\xb5\xa2\x3a\x09\xb5\x49\x8a\x5b\x24\x80\x45\x19\x1d\x18\x6a\x08\x62\x6d\x38\xfb\xa7\x46\x61\x09\xb9\x2d\x3a\x54\xa6\xe9\x43\x84\x65\xce\x6e\xea\x71\xc1\xf5\xec\x76\x47\x13\xe2\xaa\x21\xd0\x59\x61\xe9\xd6\x6f\xad\x25\x51\x33\xa1\x39\xb0\x3c\x4b\xc6\x2d\xd3\xe5\x56\x8e\x92\x00\x44\xdf\x3b\x45\x48\x09\xd1\x1f\x05\x73\x19\x0c\xec\x4f\x1f\xe2\x3c\x5c\x50\x1a\xe6\x2c\xc9\xd9\x77\xa2\x6a\xbc\xcf\x68\x51\xe8\x76\xc0\xae\xa7\x98\x28\x7b\xf8\x40\x35\xdc\x53\x6e\xb7\x3b\x14\x5d\x6a\x25\xc7\x5c\xbb\x30\x4d\x4a\x89\x61\x3c\x02\x92\xf3\x62\x23\x48\xbd\xe2\x3b\x24\x81\x8c\x10\xae\x0c\x28\xb3\xe7\xaa\xb4\x07\x73\xe9\xe3\x99\x4b\x1f\xea\x87\xa7\x43\x81\x3a\x9a\x44\x43\x37\xd2\x92\x06\x52\xea\x49\xee\x16\xa7\x8e\xbd\x5e\x2b\xe0\x37\xcf\x8d\x51\x7c\x5c\x9b\xfe\xf9\xde\x5a\xdd\x81\x4d\x5b\x45\x04\x4e\xf1\xd0\xad\x3e\x4b\x50\x34\x66\x4e\x6f\x92\xcf\x78\xf6\x23\xcf\x01\x76\x83\x2f\x8f\x35\xc9\x65\x56\x87\xb4\xb1\x00\xb4\x78\x81\xd6\x25\x7b\x22\xe9\x7b\xae\xfa\xa7\xf4\x4a\x3f\xb2\x15\xbd\x72\x79\x2f\xee\xa9\xca\xcf\x6f\xb6\x78\xdf\x37\xd9\x79\xec\x95\x0a\x4a\xfe\x35\x14\x18\xa5\x63\x59\x9b\x98\x3a\xf4\xa7\x63\xaf\x5e\xa5\xa6\x1b\x69\x49\x43\x47\x7b\x74\x5f\x45\xff\x60\xe2\x3e\x98\xb8\x1b\xcf\x2e\x26\xee\x6b\x34\x71\xa7\x79\x70\x1b\xc7\xd5\xa7\x57\xe0\x45\x57\xdf\xde\xc7\xb4\x92\x5e\x46\x02\x83\xd2\x54\xdb\x8f\xbf\x25\xc0\xe1\x11\x89\x7b\x9b\x08\x7d\x9e\x02\x01\xcf\x7e\x7e\x8b\xea\x23\xd9\x49\xbb\x97\x40\xc7\x67\x5d\x8d\xd2\x4d\x25\xd1\x41\x6a\x48\x6a\x98\x0f\x5c\x16\xe8\x81\xd3\xbb\x44\x1e\xab\x83\x62\x12\xea\x1e\x15\x90\xf1\xe9\x09\x7c\xd2\x7b\x03\x48\xcf\xfa\xe4\xf8\xf4\xdd\x0d\xb2\x43\xad\x72\x7c\x9e\xb9\x62\x39\x3e\xbd\x6d\xdf\xa4\x7f\xf5\xf2\x15\xcb\x7d\xdc\x1a\xe6\x3b\x2e\x6d\x77\xb3\xfe\xae\xe6\xfc\x41\xac\x9c\xf9\xf2\xd9\xfa\xc1\x9c\xbf\xf4\x3c\xa1\x39\x3f\x21\xdc\x9e\x18\xac\x30\xed\xa7\xe6\x36\x6f\xdf\x1f\x33\x2f\x56\x8e\x62\xf6\x35\x8b\x72\xde\xb2\x1f\xcb\x35\xe1\xb5\xea\xf1\x68\x74\x7c\xec\xed\xfd\x0e\x3f\x6b\x33\x19\xfe\x8e\x30\x91\xc9\x1c\x37\xd5\x8e\xaf\xb4\x01\xa6\x1f\xd5\xf4\x74\x2e\xa5\xff\x56\x7a\x35\x0b\x63\xf7\xdb\x92\x1e\x27\xd8\xa7\x04\x78\xfb\x20\x16\x19\x19\x63\x48\x31\xe0\x16\x18\xb2\x0a\x39\x0e\x19\xab\x9b\x60\x61\x9f\x50\x6b\x0b\x2a\x8a\x9c\xe0\xcb\x51\x56\xd5\x03\xd7\x60\x54\xb2\x52\xaa\xc5\x20\x34\xb2\x3f\x36\x7a\xb9\x16\x98\x7b\x2a\xab\x95\x62\x02\xea\x9b\xbc\x54\xfe\xea\x41\xf0\x88\xec\x35\x40\xbd\x5b\x74\x5b\x7c\x9a\xdb\x1a\xef\x00\xc0\x24\x15\xab\xd5\x4d\x42\x66\x13\x3d\x88\xf7\x1c\xf6\x2d\x13\x73\x32\xa7\x4a\x77\x85\x39\xd9\x95\xa3\xe6\x7c\xce\x75\x97\x94\xff\x6b\x16\x77\x1b\xcc\x3e\x90\x76\xb0\x36\x55\x6d\x1c\x75\xf2\xb8\xeb\x33\x35\x35\x8b\xce\x45\xc1\xe1\xf5\xa6\x3a\x6d\xed\xe7\x85\x16\x92\x69\x3e\x9d\xca\xca\x34\x9f\x7e\x45\x66\x56\xf7\xed\xb9\xf5\x0f\xa8\xdf\xd4\x7e\xfc\xd6\xee\x7e\x46\x22\x93\x89\x89\xc1\xbc\x60\xf6\x08\x87\x00\x8c\xe1\x97\xbc\x57\x28\x82\xef\xd3\x74\x97\x34\xac\xac\xa4\xa2\x6a\x41\x72\x67\x6b\x58\xac\x88\x08\x4d\x42\x42\x1f\x9c\x1a\x06\xe6\x91\x73\xb5\xa7\x68\x84\x1e\xd1\xa0\x2c\xe7\xf5\xda\x4a\xf0\xeb\xc0\x86\xbd\x52\xa0\xdd\x43\x36\x30\x97\x49\xcc\x5f\x77\xba\x66\x3e\xb1\x22\xcd\xee\x5c\xc5\x20\x0f\x55\xe4\xfd\x49\x90\xcb\xd1\x51\x2b\x0f\x34\x98\xc7\xe0\xee\xcf\x15\x5d\xf5\x8d\x71\xec\x86\x29\x0b\x6f\x43\x9c\x5b\xc0\x89\x6b\x78\x6a\x25\x92\xf7\xc0\x06\x9f\x68\x97\x48\xcf\xc8\x36\xfe\x77\x06\x05\xc2\x7a\xfb\xc6\xfb\x8e\x21\x1d\xb4\x04\xc9\x3c\x94\x4d\x2b\x64\x96\xdc\x3d\x37\x38\x14\x6c\xc3\x95\x47\x7e\x6f\xbb\xb7\x9b\x61\x47\x45\xf9\x02\x8c\x3e\x85\xc6\x7b\x3d\x9e\x41\x6a\x4b\x90\xe2\x01\x98\x61\x03\x3e\x25\x45\x04\x6b\x6d\xbf\x04\x99\xe7\x93\x36\xf1\x43\xf7\x3e\xc3\xa6\x49\xea\xbc\x35\x75\x0f\xfb\xcb\x6d\x58\x59\xd4\xdb\x20\x04\xc2\x0b\xea\xba\x06\x31\xd1\x7d\xc5\x89\x4b\x72\x02\x77\x57\xb1\x2c\x5a\x48\xee\xb8\x84\x66\x82\x17\x4d\x3c\xf3\xb9\xec\xc2\xc2\x6b\xe1\x1c\x0d\x9e\x10\x69\x5e\x30\x1f\xec\xcc\xfd\xfa\xf3\xbc\x9e\x9c\xee\x01\xfc\x2d\xf8\x63\xf4\xe0\x10\x47\xd1\x89\xa3\xc1\x22\xd2\xec\x78\x4d\x87\x0e\xea\x7d\x06\xc2\xc9\xf3\x37\x43\x9f\x82\x86\xeb\x58\x47\xb6\xc8\x5c\xcc\x2e\x6f\x64\xbd\xc4\x61\x11\x01\xc1\xbf\x75\x68\xff\xe3\x35\x61\x6f\xd6\x1f\xb3\x89\x8c\x85\x52\x50\x31\x72\x5e\xb9\x39\x2b\x98\x01\x27\x5b\x16\x12\x96\xe2\xcd\x70\x29\xe7\x16\xa7\xff\x2c\xc8\x77\x3e\x75\x3f\x9f\xbc\x21\xf4\xb4\x11\x09\xe1\x8a\xcf\x08\xc6\x72\x74\xd5\x2d\xe2\x77\x54\x2d\xf4\x80\x8c\x4f\xbd\x5b\x0a\x1c\x3c\x61\xa5\xc3\xc2\x0b\xbe\xa8\x5e\x2b\x66\x01\x00\xd1\xc7\x4a\x96\x44\x0b\x5a\xe9\x99\x34\xa0\x21\xd2\x8a\x66\xdc\x2c\x88\x51\x34\xbb\x83\x4a\x45\x8a\xb9\xcf\x0d\x48\x76\xea\xfc\xbb\x52\xf0\x35\xbd\x87\xcd\x4c\xc9\x7a\x3a\x03\x87\x58\x6c\x95\x15\x54\xfb\xd5\xaf\xec\xef\x94\x1e\x4d\x72\x2c\x54\x1c\x92\x07\x2a\x39\xe7\x9a\x4b\x67\xf4\xf5\xe3\xde\x84\x04\x71\x68\x48\xc6\xf2\xbf\x27\x9a\x31\x72\xe5\x51\x02\x7f\xb9\x45\xd1\x06\x0d\x1c\xaa\xe9\x23\x20\x43\x66\x73\xe1\xf2\x22\x44\x3a\x17\xee\xb0\x90\x6f\xda\x99\xaf\xfc\xe8\x69\xd8\xae\xd5\x73\x92\x0a\xee\xef\x7d\x06\x4f\x26\x72\x99\x5c\x5e\x9e\xdf\x5c\xeb\x54\x29\x41\xdc\x72\xe9\xef\xe0\x87\x42\x8a\x69\x9a\x4d\x20\x62\xa6\xa5\xa8\x02\xaa\xbc\xcc\x79\x5e\xd3\x02\x69\xa9\x9b\xcc\xc5\xed\x35\x76\xe7\xd3\x99\x19\xde\x33\x30\xca\x20\xcb\x89\x67\xc6\x7f\x94\x2f\x39\xed\x70\x0d\xb4\xd7\x38\xa3\x02\x1a\xb8\xec\xd4\xee\xe9\x02\xb2\xd7\x38\x4f\x93\xc6\xbd\xa9\xcf\x2f\x86\x43\xac\x82\x38\x4c\xef\x3c\x54\xed\xb0\xd2\x03\x58\xad\x2c\x88\x01\x53\x97\xe7\x66\x01\x9f\xa4\x03\x0c\xaf\x5d\x81\x36\x6a\x37\xc8\xca\x78\x9b\x55\x9a\x47\x90\xcd\xe6\x71\x93\x3f\xb9\x0a\x8a\x3d\x65\x84\xa3\x1f\x12\xeb\x59\x72\xdf\x61\x8f\x0d\x15\xf9\x90\x16\x16\x73\x6e\xbe\xbf\x70\x8e\xce\x78\x10\x1a\xf7\xf9\xbe\x18\x12\x17\x21\x7b\xb6\x15\x1d\x56\x1e\x01\x08\x87\x1f\xb3\x1c\x88\x46\x5a\x37\xf2\xde\x2a\xca\xbe\xb8\xf3\xf7\x17\x03\xc2\x47\x6c\xe4\xff\x0a\x4d\x3d\xd5\x32\x72\x8a\xde\x80\xc1\xd5\x13\xf0\x0e\xa6\x92\xda\xa4\xd2\xbe\x7f\xfd\xbd\x9d\xa4\xfd\xf5\x0f\xc3\xdf\x27\x49\x47\xff\xf0\x57\x57\x49\xfa\xaf\xad\xb7\xa9\x4b\x59\x48\xbe\xff\x57\x5f\xc6\xdb\xa5\xae\xfe\xab\xab\xc9\x05\x85\xab\x47\x50\x97\x7a\x4e\x0b\x9e\x23\x36\xc2\xb7\x15\xfb\x9b\xb7\x2f\x02\x98\x82\x6d\x27\xa3\x86\x09\x20\xd4\x3e\x36\x43\x48\x83\xdd\x5d\x75\x5a\x3b\xff\x13\xb0\x0c\x60\x6c\xd9\x80\x18\x29\xe1\x38\xe2\x91\x3f\x17\x84\xf9\x92\x9d\xb8\x56\x00\x07\x75\xfe\x6a\x9e\xf7\xd8\x61\x2d\x84\x43\x24\xae\x9d\x07\xcc\xed\x97\x42\x9a\x5f\x86\xed\xf7\x9e\x1a\xc0\x60\x24\xa1\x73\xc9\x7d\x1e\x72\x7b\x52\x04\x16\x76\x0c\x99\xb1\xc7\x0b\x52\x72\x6d\xe8\x1d\x1b\x91\x5b\xcb\x5b\xd2\x4b\x31\x84\x9e\x20\x90\xc8\x92\xe5\xa4\x16\x86\x17\xf0\x6b\x1c\xc7\x4e\x39\xe5\x39\xd7\x13\xa2\xeb\xcc\xd2\xd6\x4a\xb1\xa1\xe7\x62\xae\xd5\x12\x2d\x88\x6b\x19\x84\xcd\x9e\x51\x54\x09\xaa\x1c\xba\x02\x3c\xa8\x70\xe8\xb5\xe4\xce\x65\xe7\x29\x45\x16\x39\x17\x00\x53\x8f\xc8\x07\x60\x56\x85\xbf\x19\x46\xed\xc4\xd9\x31\x05\xcb\x98\xd6\x54\x2d\x06\x90\xdf\x9d\x87\x9c\xe0\xce\x83\x07\x38\x6a\x49\x05\x66\x57\x57\x2c\x93\x42\x1b\x55\x67\x06\xcb\xed\x8d\x95\xbc\x63\x22\x78\x0d\x2e\x17\xbb\x8f\x6e\x34\x70\xed\x25\x49\x36\xa3\x62\x9a\x94\xab\x29\x69\x0e\xb0\xff\x26\x48\x39\x7e\x3d\x16\x02\x74\x62\x05\x0b\x6e\x00\x14\x63\xcb\x47\x82\x35\xf6\xcf\x22\xa4\xe5\x19\x44\x73\xa9\x5d\x12\x2f\xb6\xd0\xae\x5e\xf4\x8b\xf4\xb4\xed\x0d\x81\x6d\xef\xd9\x0f\xac\x64\x86\xe6\xd4\xd0\x1d\x7c\xc1\xde\xc7\x1a\x7b\xee\x1e\xd2\xd5\x39\x0d\xf7\x93\x8e\x0f\x79\x71\x4b\x56\x3c\x0d\x83\x82\x93\x38\xf3\x90\x87\xc0\x6b\x63\x71\xca\xdd\x17\xa0\x8b\x17\xc8\x33\xbe\x88\x99\x1d\xde\x8f\x86\xe4\x22\x56\x68\x8c\xe4\xa4\xdb\x6d\x54\x4f\x43\xac\x05\xfd\x0e\x30\xfa\x14\xaf\xcc\xb2\xa6\x9b\xd7\x4a\x11\x04\xb9\x04\x13\x86\x2b\x96\x46\x9d\x39\xd0\xd5\x02\x91\xbc\x05\x44\x80\xf2\x94\x19\x1d\x1d\x55\x90\x0e\x5b\xe2\xe2\xf8\x9d\xd3\x49\x81\x48\x3b\xc0\x3a\xb5\x6e\xb5\x2c\x84\x60\xd7\xd2\xd1\x59\x4b\xf9\x1f\x05\xae\xbb\xd8\x9e\xb1\xaa\xc0\x7b\x99\xf7\x31\x57\xb7\x92\xf1\xc7\x21\xa2\x1b\x27\x3a\xe4\x6a\xd0\xed\xb1\x01\x5c\x5a\xe9\x46\xec\x1c\x12\xb9\x19\x9d\xef\x6e\xab\x8a\x32\xd2\x30\x64\x34\x86\xcf\x0d\xe1\x73\xc3\xd7\xdd\x6d\x7a\x7d\x1c\x41\xfc\xd3\xd9\x21\xa4\xf9\x91\x5e\x06\x54\x4b\x52\x6e\x7b\x5a\x3d\x5b\x41\xc9\x61\x04\x47\xf3\xdd\x65\x62\xb8\xc0\x75\x01\x0f\x8c\x5b\x6a\xf1\x86\xfc\xb2\xc1\xe5\x9d\x34\x15\x34\x25\x74\xd8\x3d\xf1\xaa\xd3\xc8\x6d\x85\x8f\x41\x6f\x36\x3f\x6d\x0d\x06\xe2\xc5\x6a\x8d\xc2\x3b\x06\x07\x91\xcf\x8a\x67\x0a\x6c\x68\x3e\x0c\xc1\xa2\x97\x92\x45\xc1\x14\x2c\xc1\x69\x4f\xad\xcb\x74\x48\x69\x8a\xa6\xdd\x41\x50\x51\x83\x8c\x29\xd8\x7d\x10\x26\xa8\xc6\x0c\x2e\xfe\xe2\x8b\xb9\xfa\x79\x6b\xc7\x73\xd5\x8d\xec\xef\xe7\x62\x81\x93\xbf\x4c\x80\x8b\xca\x27\x99\xda\x4f\x59\xb9\x53\xd0\x71\x61\x39\x5f\xb2\x01\xe1\x3b\x2d\x52\x6e\x64\xd2\xea\x23\x9b\x38\xad\x31\x7d\xd5\xad\x2f\xf2\x81\x46\xc7\x51\xf4\x64\xf1\xc5\xed\x62\xe6\x12\x07\xf5\x46\x93\xe6\x0d\x78\x6b\xb4\x46\x40\xed\xaa\x19\x74\xbe\xc0\xdb\xe9\x0a\x6f\x97\x4b\x3c\x88\xfe\xe4\xa2\x8b\xc7\x54\xec\xb0\xb1\xce\x49\xfb\xd9\xe5\xd6\x0f\xdc\x6a\xe0\xb6\xbf\xdf\x15\x4e\xb3\xac\xfa\xcd\x35\x0c\xe1\x75\x87\x29\xfc\xe1\x39\x63\xb8\xe3\x18\x33\x7b\xfa\x62\x5c\x37\xec\x7b\xda\x77\x85\xe3\x43\x3c\x02\xdf\x40\xf2\x58\x67\xd4\x0e\x85\xd1\x14\x03\xc7\x15\xf8\xe2\x08\xaa\x27\x50\xb1\x70\x12\x87\x99\x71\x95\x0f\x2b\xaa\xcc\x02\xd5\xdc\x41\xe3\x6b\x21\x1a\xa0\xd7\xc2\x77\xbc\x7d\xea\x96\xa9\x79\x2d\x84\x61\xf1\xde\x9a\xed\x2e\x13\xd6\xc2\xf5\x29\xd6\xd3\x3d\xde\x60\xe5\x7a\xd2\x4c\xa8\x5e\x73\x7d\xb6\xf5\x34\x28\xcb\xc3\xf9\x9b\x25\x4f\xba\x79\x53\x8c\xec\x2a\xad\xb4\x25\x53\xa7\xed\x20\x8d\x80\xe2\x66\x47\x1a\x58\x7d\x99\xc6\xd2\xe8\x89\x01\xd2\x49\x34\xde\xe5\xc7\x15\x66\xb2\x48\x9f\x7c\x25\xed\x1a\xce\x07\x39\x11\x52\xe0\x99\xc1\xb6\xa7\xe8\xeb\xb4\xc6\x7a\x06\x4d\x02\xb7\x49\x75\xb5\xe4\x8c\x7a\x36\xc6\x45\x6e\x37\x0d\xc8\x32\x68\x71\xba\xce\x32\xc6\x82\xde\x9f\xd6\xd2\x89\x67\xda\x4d\xd9\xd7\xe4\xd4\x12\xb2\xcd\x68\x43\x8b\x22\xea\xdb\x0e\x50\x12\x38\xb1\xb7\x51\x26\x0c\xba\x11\x11\xe4\x4c\x0f\x50\xed\x1d\xfd\x73\x6a\x91\xa1\xaf\x01\x37\x8b\x34\x0f\x7f\x43\x18\x01\x45\x47\xa3\x1a\xce\x27\x68\x19\x4b\x14\x96\x00\x4c\x20\x4a\xae\xd6\xfc\xcc\x57\x4c\x01\x29\xdc\x25\x91\xb0\x14\x68\x4c\xb3\xbb\x7b\xaa\x72\xa8\x39\x5c\x51\xc3\x31\x7f\xf9\x00\xb9\x62\xca\xe4\xc4\xf1\x71\x7a\x95\xc3\x45\x9b\xff\xa6\x13\x39\x49\x66\xbd\xc4\x97\x4f\x03\x3f\xd6\x2c\x64\xd7\x8e\x13\x23\xb4\x36\xb2\xa4\x86\x67\xa0\x9e\xf3\x49\x62\x19\x2d\x43\xb6\xc6\x56\x45\x45\xa0\xc8\xa1\x36\xff\x0f\xed\xc9\x6f\x9c\x78\x32\x57\xbf\xcc\xd5\xf3\x4a\x88\x7a\xa8\xdc\x0f\x37\x5a\x60\xc1\x57\x8c\x11\x5e\x5a\x01\x8b\x42\x41\x92\x49\x88\xbb\xf2\xe6\xe2\x4d\x40\xb1\x52\xe4\x0f\x60\xa3\x4f\x5a\xa1\x8d\xc1\x6a\xa0\x9a\x98\x7b\x19\xd4\xb9\x68\x09\x75\x81\x4b\x83\x96\xc8\xe1\xfa\xd8\xa3\x66\xc1\x92\x9c\xa3\x81\xc5\x9d\x7b\x56\x14\xf6\xff\x9b\x4e\x93\x1e\xad\x9a\x11\x56\x06\xd6\x24\xe7\xba\x55\xde\xfb\x24\x57\xb2\xaa\x9c\x7d\xa9\x3c\x6d\xcf\x08\xae\x5d\xd4\x9c\xe9\xa4\x82\x35\xca\x6c\x53\x26\x42\x09\x76\x97\x14\x04\x08\x4a\xfb\x13\x8d\x6d\x5c\x39\xb9\x14\x5c\x68\xc4\xde\x0c\x1e\xf7\x2b\xe8\xa2\x16\x52\x1e\x61\xf4\x08\x83\x76\x4f\xc9\x77\xae\xf0\x53\x38\xb3\xc1\x33\xb2\x93\x4c\x8b\xa6\x30\x27\xd6\x8e\xc8\xc9\x79\x51\xcd\x92\x51\x53\x29\x32\x78\x5c\x37\x67\xda\xf8\xde\x85\x92\x5a\x7f\xf0\x5d\xfa\x7c\xfa\x20\x61\x76\x7c\x0e\x12\xe6\x41\xc2\xfc\xd7\x96\x30\xfd\x7a\x80\xc6\x3c\x70\x51\x81\xfd\x36\x69\xdd\xa6\xe5\x91\x0f\xd2\xb8\x6b\x11\x10\x41\xe8\x5a\x4d\x9b\x02\xa1\xbb\xa7\x8b\x91\x60\xc6\x45\xf3\x7a\xa3\xca\x47\x3f\xde\xd7\xca\x32\x63\x27\xbb\x25\x68\xee\xcf\x8c\x8f\x23\x4e\xbe\x62\x24\xf2\x87\x78\x4b\x03\xef\x8f\xb5\xbb\xa3\xb0\xbf\x83\x2f\x7d\x3a\x40\xc6\x46\xe4\x96\xf9\xa4\x9e\x8d\x8f\x2f\x47\x8d\xe6\xcc\x50\x5e\xe8\xc8\x10\x3e\xad\x61\x30\xbb\x13\xfc\xc7\xc6\x92\xe0\x33\xba\xab\x0e\x12\x1d\xa5\x13\x97\x8c\xd4\xa3\x28\x36\x58\x67\x02\xbd\x9e\x90\x8f\x2c\x93\x73\xa6\x10\x32\x50\x3d\xd8\xca\xd9\x6f\x29\x2f\x2c\x5c\x3c\x7c\xa2\x69\x09\xd2\x32\x37\x0d\xfb\x89\x3d\x2f\x20\xa5\xdb\x84\xd2\x4d\xca\x85\x0b\xdb\xf6\xee\x8a\xbd\x52\x6c\xce\x65\xad\xbd\xdf\x53\x6d\x90\x18\x6b\xe3\x24\xdb\x19\x9f\x86\xec\xfe\xc1\x51\x42\xb1\x4c\xaa\x3c\x22\x9f\x36\xd4\xd4\xba\x19\x6c\x95\xa1\x2d\x7e\x7f\xe6\xdd\x00\xc7\x47\x96\x01\x76\xe3\xb7\xb0\xdc\x5e\x3d\xda\xb7\xe3\x20\xb3\x6a\x88\x6b\x4c\xe8\x4c\x4a\x63\xd0\xaf\x99\x0b\x04\xbc\xdd\xec\x91\xff\x09\x3b\x0f\xe2\x1e\xc7\x6b\x4b\xae\x93\x32\xff\xe1\x0e\x90\x83\x94\x4a\xed\xb1\x4d\xd4\xb1\x70\x68\x01\xcd\xbc\x70\x77\x89\xfa\xdf\x47\xf7\xad\xf3\xc2\xca\xa4\x48\x04\x92\x83\xbb\xe2\x7e\x91\x97\x65\x6d\x2c\xbe\x8e\xc8\x35\x46\xb2\x80\x64\xeb\x14\xa6\x49\x8c\xce\x60\x4a\x77\xb8\x15\x4c\x9f\x5d\x8c\xf6\x64\x17\xc3\xfd\xd2\x46\x7d\x4c\x41\x9e\x66\xa5\xb0\xda\x1d\xdc\xcd\xdb\xdd\xf1\x77\xf7\x8d\xd6\x1d\xc2\xea\x57\xad\xb2\x27\x02\xe3\xb3\x8b\x28\x8b\x4f\x4f\xf9\x14\x9f\xdd\x4e\x0d\x3e\xfd\xa5\x0e\x7c\x96\x65\x8f\x56\x11\x7f\x2f\x83\x34\x76\xa6\x92\xf9\x68\xc5\xd9\x09\x7e\x1c\x32\x77\x4e\x1a\x4d\xfb\x0b\x86\x7c\x5d\xdb\xe1\xef\xbc\xe3\x52\xa0\xb3\xae\x64\x5a\x01\x96\x14\x9e\x33\xcc\x72\xeb\xce\xdc\x0e\x2b\xdb\x51\xdc\x69\x39\x24\x5a\x52\x32\x2c\x69\x35\xbc\x63\x8b\xde\xdb\xb2\x03\x16\x2c\x7f\x1c\xd7\x51\xd2\xaa\xc7\x38\xe8\x40\xfb\x00\x4a\x7a\xfc\x0e\x5d\x70\xf1\xe5\xd8\x31\x5e\xef\x15\x1c\x3d\x92\x33\x59\x56\xb5\x61\x09\x83\x76\xac\xb4\x37\xd7\x6a\x24\x21\x39\xc3\x3a\x7a\xc3\x30\xec\x30\x12\xb9\x0e\x05\x70\xd2\x67\xe7\xe3\xbf\x6b\xbe\x8d\xf4\x79\xc1\x0e\xc0\xad\xc5\xf6\x0f\x86\x21\x0f\x0c\x88\x21\x0f\x09\x8a\x21\xfb\x0c\x8c\x21\x21\xbc\xee\x21\x27\xe6\xa3\x0f\xec\x6b\x9d\x19\x27\xc2\x6e\x3a\x33\x8d\xfc\x4e\x61\x1c\xae\x7d\x41\x6e\xe7\x5e\x16\xce\x00\x5c\xcd\xa6\xe1\x59\xee\xb4\x82\xcd\x1a\x7d\xc8\xd8\xe7\x50\x84\x21\x51\x93\x40\xfb\xbf\xe7\x1a\x15\x1b\x41\x78\x59\x61\x62\x46\x38\x75\x43\x2f\x19\x39\x9b\x70\x98\x49\x06\xbe\x34\x84\x7d\x06\xcb\x38\x7e\xec\x70\xc0\xc9\xe1\x80\x77\xee\xff\x9c\x07\x1c\xe3\xd3\xfa\x84\x4f\xb6\xea\x3a\x62\x77\x97\x32\x85\x8e\x59\x41\x7e\xac\x99\x5a\x10\xab\x6d\x46\x2f\x6c\x28\x46\x61\x05\x17\xf4\x63\x76\x37\x4b\xdd\x25\x97\x27\x54\xb4\x40\xba\xbb\xfa\x6c\x55\x6d\xc8\x3a\xf0\x00\xb2\xd7\x1e\xaa\x99\x58\x06\xa1\x15\x20\x98\xaa\xd2\xe8\x08\xd6\x50\xae\xad\xce\x75\xfe\xe1\x72\x37\x8b\xc5\x73\xa8\x31\xe7\x1b\x16\x88\x80\x08\xbf\x34\x6b\x7f\x86\x2b\x0f\x72\xc7\x16\x03\xe7\xae\xe8\x6a\xed\xf8\xc6\xe8\x75\xdb\x4c\x00\xdf\x35\xb1\xd8\x2a\x00\x3d\xb9\x06\xd4\x35\x65\x78\xb3\x97\x07\xc2\x13\xea\x4e\x3d\x52\x8b\xa7\xcf\xba\x34\xe3\x88\x13\x90\x2f\xd9\x47\xa1\x05\x34\x80\xc8\x3b\xa0\x16\x4f\xaa\xd2\x10\xc8\xec\x8b\x80\x7d\xf0\x52\x03\x9a\x36\xe2\xa7\xee\xd8\xe2\x58\xbb\x1c\x0f\x52\xe8\x19\xaf\x7c\x35\x1f\xa0\x04\x0e\x73\xc9\xf7\xe0\xc6\xe9\x87\xc0\x33\x7f\x2d\x06\xe4\x83\x34\xf6\x7f\x57\xe0\xd1\x0d\xb8\x7e\x29\x99\xfe\x20\x0d\xbc\x79\x72\x60\xe1\x74\x1f\x0c\x2a\x77\x1d\xea\x0c\x45\x10\x79\x00\xd1\xb4\xde\x53\x18\x40\xe2\x9c\xc8\x02\x58\xb9\x26\xd7\x82\x48\xe5\x61\x62\x7c\xa9\x07\xed\x86\xf0\x57\x3d\xc9\x25\xf7\x8a\x31\x1c\x28\xa5\x6a\x40\x72\xc3\x70\xe1\x1a\x9b\xfb\x5f\xc0\x46\x0e\x2e\x09\xc1\xbd\x19\x0a\x16\x50\xc3\xa6\x3c\x23\x25\x53\x53\xc8\xe6\x91\xcd\x76\xdf\xa0\xfe\x74\x1b\x9f\x9d\xa8\x77\xfa\xe1\xde\x98\x01\xac\xee\x1d\x38\x98\x3f\x94\x61\xe2\x28\xc8\x22\x4a\x5a\x59\xa4\xf8\x87\xe5\x04\xb0\x2f\xff\x84\x02\x23\x7a\x44\xce\x7d\x79\xfa\xf4\x37\x67\x2e\x4e\x87\xb1\x23\x58\x91\xff\xc7\x9a\xcf\x69\xc1\x30\xec\x82\x8a\x90\x74\x5d\x4e\x96\xd8\xf4\xc0\x55\x19\xb1\x54\x2a\x98\x67\x8e\xee\xd8\xe2\x68\xb0\x84\x48\x47\xd7\xe2\x28\xa6\xd4\x69\xa0\x4e\x60\x68\x60\x93\x3c\x82\xdf\x8e\xf6\xcd\xd9\x9f\x49\xb4\xdf\x01\x4b\x9c\xe5\xfd\xa2\xa0\x78\x53\xb3\xeb\x7d\x48\x7b\x9c\x55\xe9\xb2\x6f\x93\x36\xf1\x26\xcb\x05\xd9\xec\xfd\xe2\x00\x82\x31\xfb\x3b\x84\xf7\x82\xde\xdc\xd5\xba\xeb\x9e\x66\x6b\x65\xfa\x57\x48\x32\xe5\x43\x6d\x1b\x59\x0c\xa2\x2f\xda\x1a\x78\x7d\x0f\x17\x38\x72\x42\xde\xc6\x34\xd8\x60\x82\xb7\x4c\xdb\x05\xdf\x5a\x45\x98\x8b\xac\xa8\xdd\xdd\x0d\x74\xc5\x8b\x84\xc7\x07\xce\x03\x90\x2a\x0e\xe0\xb1\xc9\xfb\xbe\x2d\xc5\x59\xb5\x3d\x81\xc0\x31\x2c\xf8\xbe\x20\xac\xf6\xbd\xd6\xc9\x96\xa8\x96\x66\xea\xf4\xac\x29\x7b\xbc\xe5\x63\xc5\xc8\xc5\x8c\x0a\xc1\x8a\x24\x37\x89\xb3\x85\x84\xe2\xa3\x20\x90\xb8\x92\xa3\xc7\xcd\x9a\xa3\x9e\xbe\x89\x90\x09\x27\x06\x9d\xed\x29\x4d\xff\x4f\xa9\x04\xe8\xfa\x4c\xf5\x7d\x8b\x7f\x62\x62\xed\x99\xbc\x27\xb9\x24\xf7\x50\x65\x6a\x6e\x99\x16\x38\x7f\x69\xcf\xee\x92\x99\x82\x9f\x68\x26\xcb\x4a\xc9\x92\x07\xe7\x29\xb7\x8d\x7b\x4d\xe4\x51\xd4\x1d\x32\x36\x36\xf7\xa0\xa8\x45\xb3\x80\xcf\xdb\x0b\x62\xa8\x9a\x32\x63\x47\x23\xa2\x2e\xc7\xac\x73\xb6\x91\xc7\xc8\x18\xfb\x25\x15\x7c\xdf\x6f\xc9\x52\xdc\x86\x1f\x7e\xf8\xd0\x37\x61\xee\x71\xec\xb9\x6e\x6f\xef\xa5\x2a\xf2\x7b\x9e\xfb\x0b\xe7\x13\xdb\xf8\xb4\xeb\xfc\xf7\x9c\x3f\xb7\x07\x86\xdf\xdf\xf3\xbc\x37\x38\xa0\x53\x13\x0c\xde\x0d\xdc\x82\x81\x00\x1c\x5c\x3d\x4e\x0e\x45\x4f\xa0\xc7\x29\xb9\xe2\x18\x04\x0e\xfd\xe1\xe2\xba\x1c\x73\x11\x13\x01\x44\x30\x5b\x62\x6c\xcf\x8b\x57\x4d\x34\x33\x18\xbe\x0b\x91\x33\xd2\xcc\x88\xe6\x65\x5d\x18\x2a\x98\xac\x75\xb1\xe8\x8c\x2a\xcf\x03\xea\x49\xc1\x3e\x23\x66\xf7\x61\x72\xa1\x53\x93\xd9\x81\x8b\x6c\xcc\x76\xb1\xc4\xed\xa2\x87\x79\x7e\x16\x38\x5f\x88\x0a\x67\x9f\x59\xe6\x82\xb7\xaa\xa2\x9e\xf2\x2d\x51\xaa\xff\x62\x35\x68\x62\xb9\x8f\x5a\xb3\x98\x57\xa9\x6b\x15\xbe\x27\x2a\x19\xf3\xbc\x1c\xfe\xd3\xea\x72\x31\x39\xab\x98\xc8\x21\x81\xed\xdb\x88\xb9\x38\xf9\xbd\x42\xce\x25\x83\xed\x4b\xb5\x7c\x0e\xd9\x06\x05\x4f\xdc\x13\x66\xb2\xc8\x35\x61\x9f\x8d\xa2\x96\x30\x95\x96\x04\x85\x3e\x13\x42\x45\x77\x22\xf3\x32\x0a\x3a\x90\xbd\x73\xfb\xc7\xad\x6e\xfe\x12\x0b\x94\xc7\xb5\x37\x5e\xef\xb9\xd0\x10\x12\x62\x77\x56\x74\x33\x40\x6a\x45\x41\xa0\xe8\xc0\xba\x1c\x89\xba\x63\x61\x20\xbd\xa2\x04\x4a\x6b\x56\x87\xa2\xea\x5f\x44\x95\xa0\x09\xe4\x6f\xe9\x93\x32\xd3\xf5\x68\x69\xd4\xee\xa5\x2f\x4e\xdc\x41\x83\x76\x78\x9b\xf0\x01\x0b\x75\x3f\x90\x8b\x3e\x27\xda\xc2\x32\xba\x7a\xd7\x42\x6c\xa3\x62\x8f\x51\xf3\x85\x1a\xaa\x99\xe9\x66\x4d\x69\x8a\x0e\xb1\xa7\x3d\x80\x29\x7e\xb9\x9f\xb0\xe6\x10\x44\xe5\xf9\x9c\x26\x64\xf8\x07\x27\x65\x88\x46\x4b\x2b\x5f\x78\xf8\xf8\x94\x9a\x2c\xdc\x22\xe3\x18\xb9\xdd\x95\x8c\x9a\xce\x05\x12\x3b\xf1\x05\x37\x83\xef\xbe\xeb\x5d\x79\x3f\xe9\xe9\xe5\x10\xf8\x77\x13\x08\xa3\xe0\x20\x5b\x0b\xfe\x63\x9d\xaa\x03\x90\x83\x2c\x2c\xdb\xb5\xdf\xd7\xda\xa6\x19\x8b\xc6\xab\x4b\xae\xef\xfa\xa4\x8e\x5d\xea\xdc\x3c\x12\x5f\x5f\x5c\x11\xf7\xb6\x93\x7d\xa9\x8f\x81\xe9\xa1\x29\x29\xa7\x19\x8b\x46\xdb\x9c\xeb\xbb\x3d\xa5\x9d\xed\x2e\xd5\x57\xf9\x87\x6d\xae\x8e\x4f\x67\xff\x6a\x4b\xbd\x3e\x93\x5e\x92\xe2\x71\x21\x6b\x72\xef\x32\x54\x39\xa9\xf9\x13\xaf\xde\x90\x2b\xa1\x6b\xc5\xe2\xcd\x6d\x7b\x28\xcb\x75\x3b\xcb\xd0\x90\x04\x4c\xbf\xd9\x9b\xad\x6c\xdf\x58\xf2\x92\x8d\x6f\x15\x55\x06\xc4\xe3\xbe\x68\x10\x3a\x7a\xfa\x94\xbc\x10\x5d\xf0\xe0\x7a\xe2\xfd\xee\x06\x2e\x15\x4f\x48\x33\xeb\x1b\xd9\x9d\x4f\xb2\xcf\xa5\x7b\xfd\x36\x64\x66\x24\x67\x39\x9b\x9f\xe9\x9c\xbe\x1e\xc0\x67\x7c\x64\x49\x73\x4e\x54\x93\xa3\xd7\x47\x23\x72\xcb\x4b\x5e\x50\x55\x2c\x1a\x85\x33\x62\x3b\xcb\x2c\xfc\x80\x70\x2b\xf7\xea\x88\x9c\x48\x05\x23\x67\x54\x90\x82\xf9\xb0\x6e\x77\xce\x16\x28\x3b\x9e\x3e\x35\x71\x21\x8f\x6a\xbf\x44\x3a\xd3\x1b\x27\x72\xcf\xb1\x1d\x3f\x6a\x64\x1d\xbc\x8c\x24\x9d\x0b\x4b\xe7\x47\xe4\x3b\x47\xa0\x1d\xdf\xc2\x4d\x83\x23\xe3\x5b\x3c\x17\x50\x9f\x46\xef\xdb\x49\x83\x5b\x36\x07\x3f\x1f\x98\xb6\x6b\x89\x53\x6e\x3e\xb2\x4a\xf6\x92\x10\xb0\x4b\xcb\x1e\xc7\x8d\x7d\x21\x35\x87\xb4\xf2\xd4\x10\x8a\xc7\x36\xab\x0b\x6a\xc5\x6a\xb4\xc6\x8d\xc8\xe5\xd5\xcd\xc7\xab\x8b\xf3\x4f\x57\x97\x6f\xc8\xd7\x6e\x24\x9e\x4a\x78\x23\xf2\x29\x4d\xda\x99\x38\xfc\xba\xcc\x88\xe1\x5b\x03\x47\x86\xa8\x88\xa9\xb8\x21\x15\x1b\x15\xe4\x5a\x70\x13\x8b\x59\xa0\xdf\x59\x21\x05\xf3\xb5\xde\x2b\xe9\xac\x81\x53\x6e\x5c\x8a\x22\x1c\xcc\xfe\xdc\x1c\xcd\xc5\x72\x58\x51\x26\x86\x62\x3c\xb9\x68\x11\x81\xbb\x2f\xf1\xdf\x67\xab\xef\x2b\xfb\x86\xda\x01\x3e\xde\x18\xad\xff\xf1\x3d\x32\x83\x50\x46\xc7\x67\x25\x94\xaa\x51\xe5\x06\x6a\xe0\x5b\x36\x73\x3c\x3a\xf6\x02\x45\xb1\x54\x32\x29\x0c\x9a\x26\x5e\x6d\x22\xdb\x88\x90\x6f\xbd\x47\x37\x64\x5e\x59\x5d\x7d\x09\x93\x78\x25\x35\x7c\x5a\x28\xeb\x23\x10\xeb\x71\xfa\x51\x97\xa9\x75\xca\xe7\x2e\x7f\xc6\x5e\xad\x78\xf1\xf3\xbd\x6b\xd9\xc6\x79\x3b\xfd\xe3\xe3\xbb\xfd\xce\x0c\xcf\x5f\xef\x79\xb9\x63\xeb\x66\x95\xc9\xb2\xc4\xb4\x9e\xb3\x10\xef\x1f\x43\xf6\x03\x55\xd8\x9b\xe6\x83\x09\x4a\x27\x5b\x90\xbf\x45\xcf\x7c\xa7\x96\xa6\x13\x5e\xbb\x98\x05\x11\xc5\xdc\xfe\x55\x33\x5c\x2e\x5c\xed\xc3\xb1\x1d\x69\x3f\x0b\x1f\x3f\xfb\x78\x75\x7e\xf9\xfe\x6a\x54\xe6\x4f\x4e\x5a\x98\xc8\x2b\xc9\x85\xd1\xdb\xf5\x9b\x6d\x35\x02\xbb\x93\x9f\xf0\xd1\xbe\xdc\x39\x74\xf4\x38\xe6\x5f\x24\xe9\x83\x5d\x38\x79\xb2\x87\x46\x56\xb2\x90\xd3\xd5\xc5\x32\x7a\x6c\xce\xcf\x31\x0d\xe0\x90\x0e\xed\xae\xef\x57\xd4\xef\x52\xf5\xac\x2d\xe5\x63\x95\x33\x0b\x86\xb8\xd6\x20\x35\x43\x71\xb2\x17\xba\xdc\x47\x11\xce\x96\x60\x80\x8a\x24\x1c\x60\x9f\x59\x39\xa6\x2a\x4e\x2a\x0e\x76\x95\xda\x1e\x1b\x74\xdb\x05\x36\x4b\x7f\xb6\x97\x95\x6c\xc2\xcc\xf7\x69\x12\xb8\x4a\xb1\x61\xc8\xaa\x09\x85\xf0\xa4\x4a\x18\x6e\x4a\xef\xbc\xf5\xc6\xdb\x7a\xb0\x55\xb1\x68\x5b\x71\x92\xf0\x70\x6f\xfa\xc2\x5c\x46\x45\xb1\x88\xd9\xba\x9d\x16\x4d\xa7\x98\x2d\x53\x39\x33\x71\xa5\xf8\x9c\x17\x6c\x0a\x19\xf3\xb9\x98\x26\x79\x06\xd2\xcc\x04\x2e\xa5\x44\xd3\xe8\xfa\xde\xfe\x95\x94\x48\x01\xbc\xf8\xf0\xed\x27\x28\xbe\x00\x17\x5c\x0f\x16\xc2\xed\x07\xe1\xbc\x0d\x87\x43\x30\x19\x9c\xfc\xcd\xca\x93\x79\x71\x4a\x7e\x60\xee\x3b\x12\xaa\x43\x28\x28\xdc\x38\x93\x21\x55\x3f\xcc\x35\x42\x16\xd0\x11\xaf\xf7\x5d\xab\x33\xdb\xd2\xca\x4a\xc8\x6a\x1a\xed\xa1\x4e\x3d\x66\xd8\xc6\x3b\xa6\xa7\x97\x3d\xf7\x48\xf6\x77\xa6\x72\xde\xb4\xba\x0a\x3f\xc3\xc5\x8f\xa7\x87\x94\xe8\x45\x59\x70\x71\x17\xd3\xb7\x4e\xa4\xcb\x60\xc2\x88\xfd\xc1\x63\xac\x62\xb4\x58\x4f\x29\x77\xc1\x8f\xbd\x52\x49\xb3\x83\x05\x10\x2c\x74\xf6\x9c\xfd\xd1\x1f\x7b\x77\x0d\x9d\x92\xb8\xa3\xa3\x17\xb7\x5e\xae\x33\xcd\xfb\x90\x35\xe8\xd0\xa0\x69\x82\x5c\xdf\x5e\xdc\x5e\x3f\xa9\x85\x7a\x1d\x4b\x80\xd9\x3d\xa3\x54\xc7\x7f\xdc\x76\x3b\x3c\x24\x45\xbd\xbd\x0d\xaa\x77\x37\x52\x19\x5a\xec\x89\x08\x64\x33\x5a\x9d\xd7\x66\x76\xc9\x35\x24\xab\xe9\x2b\x04\x2c\xf5\x4f\x3c\x9d\xb1\xc4\x86\xcf\xeb\xcc\x3d\x3a\xb8\x76\x17\x7f\x3c\xbf\x21\xb4\xb6\xfb\x6b\x5c\x0e\xf8\xbd\x5e\xb8\xfb\x99\xdd\x62\x84\xc1\x8e\xeb\x72\xbd\xb7\xac\xca\xb7\x7a\xec\x35\x3d\x86\x1f\xee\xe1\x2e\x02\x68\x28\x52\xb0\x17\x7c\xff\xc0\x05\x37\x9c\x1a\xd9\xb1\xac\x6c\x03\x05\x1a\x7d\x83\x41\xa0\xd6\x46\x96\x0e\x83\xaf\x7d\x0b\xb8\x42\x06\x2e\xbe\xd4\x29\x5a\x0b\x40\x7a\x07\x88\x5d\x0b\x2b\x6b\xd3\x8c\xb5\x1c\x20\x07\x90\x9b\x1d\xc7\xe6\xa1\xcd\xef\x9d\x81\x0a\xf2\x90\x16\x7f\x78\xd3\xa8\x98\xb3\x54\x7e\xcc\x5b\x29\x62\x6d\xab\xbd\x5a\x7c\xf8\x8f\x7d\x89\x02\xff\x51\xb4\x2c\x6d\xb8\xc0\xff\x5b\xd3\x02\x01\xf3\x61\xdf\x66\xa9\x26\x90\xfb\xce\xb7\xb9\x43\x6e\xea\x71\x3b\x3e\x04\x2d\xbd\xd6\x98\xe1\x14\xd7\x63\x14\x15\xda\xee\x51\x53\x17\x3b\x76\x17\x4f\xc7\xe4\xc4\x64\xd5\xe9\x5e\xd7\xd9\xdf\xb5\xbd\xa8\x45\x2a\x70\xe0\xcc\x3f\xe1\xb6\xbc\x0b\xae\xed\x5d\x27\xf9\x28\x57\x43\x80\xe5\x7d\xad\x2a\xae\x57\xd8\xad\x74\x5d\xc8\xfa\xc9\x3b\xae\x8d\xaf\x9b\x05\x2f\xb8\x76\xe5\x1e\x40\xee\xba\xb1\x8a\x1c\xaf\xfe\x9b\xe6\xb9\x7a\x83\x5c\xca\xc9\xe4\xf0\x6f\x1d\x72\x6e\x52\x11\xee\x12\x4f\xcc\xa2\x72\x39\x8d\x3f\x5d\xdc\x10\xac\x63\xf7\xbb\xdf\x60\x9d\xfe\x7f\xff\xd5\x6f\x5e\x75\xde\xee\xe7\x73\x1e\xdf\xd1\x8e\xb1\xf7\x3b\xa6\x17\xe1\x37\xd8\xf0\x0f\x84\x74\x8d\x56\x36\xb9\x45\x77\x3c\x4b\x59\xdd\x51\x47\xc4\xb2\xbb\x1c\xe8\xfd\x6e\x12\xcc\xc1\xcf\xee\x59\xfd\xec\x48\x88\x28\x41\x22\xd1\x13\x5d\xd2\xae\x10\x62\xb8\x4c\x76\x90\xe2\xdc\xbc\x3c\x8a\xb3\x15\x36\xdb\xb1\xa8\x89\x3d\xe9\x65\xbc\xaf\x52\x18\x5d\xd8\x2f\x3f\xdc\xfe\xf7\xbb\xf3\xaf\xae\xde\xc1\x4c\xdd\xfd\xbd\x45\x0d\x2e\x76\xf6\x9f\xea\x8e\x6a\x5d\x94\xd7\xed\x00\xe9\x77\x2d\x23\x5a\x17\x32\x82\x7c\x78\x7b\xdb\xf7\x2e\xe6\xa1\x02\xba\x98\x74\x5a\xfb\xd3\x5a\xdb\xa0\xf8\x1c\x53\xfb\x8b\x1f\xd9\xd9\x28\x97\xe4\xd9\x6a\xe8\x5f\x76\xa7\x70\x86\x0f\x56\x91\xb6\xee\x00\x79\x01\xf7\x0e\x76\xbd\x08\x83\xbd\xdf\x38\x3c\x12\xac\xba\xca\x01\xaa\x7f\x60\xd1\x31\xf6\xf2\x22\x80\x3d\xa4\x48\xdb\x94\xa5\xd9\x96\x5a\x33\x1d\x92\x64\xbe\x50\x4c\xa9\x56\x95\x81\xe8\x43\xbd\x56\x0e\xd0\xa8\x2a\xdb\xb8\x8b\x69\xc4\x52\xac\xab\xe9\xe2\x3d\x14\x68\x99\xa4\x0e\xdf\x67\x7e\x83\xf8\x0a\xdf\x60\x2a\xe2\x27\x27\x80\xf0\xd9\x3d\x3a\xd2\x86\xf1\xfa\x22\x72\xe8\xd8\x8e\x92\xeb\xb5\x43\x84\x6a\xcf\xa2\x9d\xcf\x51\x1a\x4e\xf7\xcc\xdb\x47\x9e\x56\xdb\xf9\x61\x47\x45\x67\xdf\x4a\x4e\x35\x93\x46\x8a\x9d\xbd\xe4\x57\x75\x6f\x1e\xe8\x1b\x68\x71\x11\xab\x0d\x26\xa5\xb8\xc1\x83\x32\x5c\x46\x40\x0d\x1d\xc7\x2e\xa4\xf0\xd7\x12\xcd\x4b\x89\x27\x17\x41\xf2\xeb\xcb\x3d\x1d\xbe\x2f\x37\xc4\xb3\xaf\x31\x78\xaf\xce\x20\x79\xef\x98\x14\xdb\xc5\x43\xec\xfa\xd2\x89\x66\x3e\xe0\x44\x3b\x84\x24\xeb\x31\x72\x6f\xac\x53\x2a\x73\x2f\x55\xff\x50\xef\x66\xc7\x96\xaf\x82\xfb\x6d\x29\x14\xeb\x25\x9e\x1e\x9c\xe3\x33\x9f\xa0\x5b\x38\x41\xad\x4a\x12\xeb\x4e\xd2\x63\x1c\xa4\xe7\x3d\x40\x0f\x65\x54\x8f\x1b\xe5\xbb\x57\x21\xdd\xa3\x5b\xcf\xa5\xfa\x6e\xce\x98\x60\x37\x29\x52\x0b\x0a\x26\x97\xe4\xc4\xed\x8d\x3a\x28\x89\x95\xc2\xfb\x10\x06\xdf\x07\x0d\xb8\x98\x07\xba\x28\x2c\x54\xa5\x48\x33\x48\xbb\x30\xde\x01\xc1\x2c\xcb\x25\xad\x5c\x41\xb5\x5c\xde\x8b\x7b\xaa\x72\x72\x7e\x73\xbd\x1f\x6a\xd0\xc3\xcf\x1a\x31\xa9\x5b\x46\xaf\xa6\xa7\x75\xec\xe9\x0a\xea\x31\x28\x81\x4d\xc6\xdc\xe8\x58\x7a\x99\x99\x54\xaf\xb4\x54\x30\xdc\x65\xd9\xb3\x6c\xcf\xad\x1b\x29\x61\x98\x82\xc8\xcc\xd0\xc2\x57\x6b\x71\xe5\xf8\x5e\xbd\x7a\x85\xa6\xb0\x57\xbf\xfd\xed\x6f\xb1\xbc\x64\xce\x32\x5e\x2e\x37\x84\x56\xff\xeb\xf5\xeb\x11\xf9\xaf\xf3\xf7\xef\x5c\xf9\x1f\x8d\x59\x49\x70\x64\x80\x7b\xda\x59\x0f\xc8\xff\xb9\xfd\xf6\x43\x2c\x0d\xd2\xfc\x15\xb6\x35\x2c\x6f\x44\x2e\x13\xff\xa7\xd4\xd0\x45\xcd\xcc\x55\x75\x34\x84\x4e\x26\x88\x18\xbe\x3e\x89\x3b\x70\x3e\x7a\x9c\x4f\x67\xbe\x1c\x98\x45\x89\x02\x1c\xb3\xac\x4a\x8e\xa6\x41\x9f\xd9\x00\xfd\xcc\x60\xac\x40\x26\x61\x2a\x03\x52\xf0\x3b\x46\x26\x1a\x8a\x82\xc5\xf4\x7f\x8a\x69\x2b\x94\xba\x22\xd8\x38\x58\xdc\x19\xcd\x3a\xe7\x7a\x78\x8c\x1b\xa0\xce\x65\x88\x9a\xa6\x7b\x77\x86\x7c\xfa\x56\x97\xbb\xd8\xfb\x92\xe2\x11\xb4\xd0\x7a\x9e\x1b\x99\xc6\x5c\x6f\xc2\x6c\x70\xeb\x5c\x96\x80\x48\x27\x68\x21\xa1\x9c\x69\xd8\xe9\xc8\xc5\xbc\xcb\xc1\xa2\x62\xdb\x97\xd2\x3b\xf9\x62\xdf\x04\xbc\x48\xa8\xde\xd3\xce\xd5\xf5\x9a\xfe\x22\xbe\x77\x23\xaf\x02\x1d\xcb\xda\xf8\x3b\x6c\xf7\x3b\x04\x60\x1b\xe9\x41\xd4\xf1\x63\x3b\x64\x9e\xdc\x25\x03\x71\xef\x24\xa6\xcd\xfb\x66\xe0\x09\x4d\x51\x62\x40\x18\xcd\x66\xe4\x8e\x2d\x86\x48\xb7\x2a\x0a\xd1\x3c\x58\x84\xc8\xc2\xa2\x51\x61\x2a\xa9\xb5\x76\x11\x40\xe6\x1d\x03\x12\xee\xe3\xa3\x81\xbc\x10\xaa\x9d\xbc\xe4\xd2\x88\x8a\xc4\x52\xe0\x73\x55\xbb\x82\xeb\xfe\xb5\xab\x29\x70\xbd\x14\xa4\x62\xcf\x1b\xcb\x6d\x37\xbd\xe9\xcb\xd1\x1b\xc2\xd2\x41\xc7\xdd\x6a\xb1\xd4\xdb\xd5\x56\x77\xc2\x1f\x7c\x90\xfa\xec\xcc\x89\x47\x05\x54\x33\x76\x85\x15\x5d\x5b\x0f\xa5\x00\x88\x46\x10\x8d\x66\xa6\x76\xa0\xc1\xba\xa4\xb5\x28\x98\xd6\x84\xc3\x0a\x4b\xaa\xee\x98\x4f\x18\x43\x8b\x11\xb9\xb1\x93\x0c\xf9\xab\x30\x2d\xf2\xdc\x95\x8d\xa5\x8b\x46\x74\x90\xfd\xc8\xf1\x68\x74\x8c\x04\x7e\x45\xac\x50\x0f\xfc\xd8\x2d\xa7\xee\x0e\xb9\x74\x1b\x88\xf8\x9e\x56\x1a\x33\x03\x5b\x91\x0f\x32\x5f\x4b\x88\x82\x33\x33\xcf\xc0\x68\xe7\x24\x4a\xcb\xcb\xd9\x21\x01\xec\xae\x79\xcb\x77\xc9\x5a\xde\xe9\xde\xa2\xf9\xec\x9e\xad\x7c\xa7\x5c\xe5\xeb\x32\x95\xbb\x9d\x72\xa7\xad\x7f\x0e\xe7\x07\xa4\xd8\x2e\x7b\xa5\x79\xf5\x4f\xd3\x48\x09\x72\x47\x23\x4b\x4f\x27\x19\xd1\x25\x7d\x2a\xd8\x17\x25\x14\x5e\x4f\x56\x15\x81\xf5\xc1\x82\x89\xbc\xec\x69\x28\x16\xdb\x7a\x6e\x69\xb0\x5f\x2d\x17\xd2\x5b\x3c\x6c\x3f\x7d\xc4\xc5\xf6\xd3\xed\x32\xb0\xfd\x34\x15\xb6\x24\x2c\x29\x10\xfd\xd4\x8b\x1f\x40\x6a\x24\xe4\xec\x8e\x47\x70\x44\xde\x3b\xa6\x80\xc8\x48\xc7\x5a\x16\xb5\x09\x91\x4c\x2b\x38\x06\x0c\xea\x33\x7c\x63\x48\xa9\x6f\x96\xf0\x0f\xe0\x9c\x48\x96\xfb\xb2\x12\x7c\x76\x3a\xe2\x7d\x8b\xd1\xfd\x64\x9d\x49\x1e\x00\x43\x2f\x4a\xec\x0c\x47\x3f\x40\xc8\x3b\xe1\x7d\xa9\x1b\x32\x0e\x78\x92\x18\x8d\x02\x94\x17\x57\x5c\x1d\xa8\xde\x4b\xec\x66\xb5\x71\x73\x75\x86\x89\xf3\x9b\xeb\x9d\x34\x80\xa4\xff\x1a\x1d\x20\x6d\xf1\x13\xd6\x02\xae\x51\x0b\x48\xcb\xee\x5c\xc6\x95\x3b\x93\xb2\x25\x3b\x2f\x5e\x8c\x5c\x9a\xf6\x5b\x4b\x2c\x53\xa7\xd3\x66\x0e\x3d\x34\xf6\x44\xb2\x9a\xe4\xdd\xf3\xb7\x8e\x70\x88\x5f\xba\xc8\xf9\x84\xe2\x23\xc0\xa3\x93\x77\x63\xfb\x59\x2e\x76\x07\x8b\x25\xb7\x50\xda\x06\xf5\xc1\x44\xb1\xac\x64\xfe\x06\xab\x42\x40\xed\x38\x2c\x0a\x33\xc0\xda\x38\x7a\x80\x0a\xa3\x95\x22\x92\xbb\x62\x95\x98\xdc\x77\x96\x1b\x76\xaa\x72\xf4\x90\x3a\x47\x76\x03\x61\xe5\x37\x7d\x77\x91\x3c\xb0\x6c\x11\x49\x58\xd3\x6e\x85\x50\x1a\x7b\xea\x46\xf2\x1b\xa8\xb3\x19\x2b\x29\xe6\xf0\xf3\xcb\xb3\x54\xe6\x5e\x71\x63\x18\xe6\x52\x62\x0a\x6a\xbe\x0e\x1a\x77\x06\x47\xf3\xd7\x47\xbb\x94\x83\x79\x60\xc5\x1e\x12\x77\x61\x0f\xc0\xb8\x69\x88\x6c\x16\xaf\x41\x97\x28\x20\xf1\xa6\x68\x19\x24\x2c\x83\x99\x23\xf4\x9e\x7c\xe1\xfb\xd0\xa3\x76\xd5\x9f\x06\x41\x60\x38\xe8\x4f\x07\xfd\x69\x2f\xfa\x53\xc2\x58\x3c\xc1\x59\xa1\x4b\xa5\x0e\xc3\x5e\xa1\x8a\x81\x4c\x49\x02\x1e\x8b\x9a\x5e\x95\x8a\x95\xd2\xd1\xe2\x66\xf5\xa1\x63\xaf\x60\x39\x3c\xae\xcd\x64\xf8\x3b\xc2\x44\x26\x73\xdc\x7c\x3b\xbe\xd2\x06\x44\x9b\xa8\x93\xa4\x73\x29\xfd\xb7\x52\xab\x1d\x8c\xbd\xeb\xd6\xed\x44\x07\xfc\x55\xe0\xdb\x3d\x31\xf8\xc8\xd6\x43\x30\xb1\x5b\x7e\xc8\x35\xe0\xf8\x7b\xbc\x84\xc4\xaa\xd3\xa1\x08\x3e\x94\x8e\x3d\xc1\x97\xa3\xac\xaa\x07\xae\xc1\xa8\x64\xa5\x54\x8b\x41\x68\x64\x7f\x6c\xf4\x72\x2d\x4e\x41\x26\xc8\x6a\x65\x35\xc0\x62\xf1\xa5\x4a\x07\x1e\x40\x4f\x2c\x1c\x84\x7d\xea\x57\x34\x28\x7d\x9a\x28\x11\x93\x8a\x81\x7e\x1f\x8b\x28\x4d\x42\xca\x43\x3d\x88\x6a\xa7\x7d\xcb\xc4\x9c\xcc\xa9\xea\xe0\x89\xb7\xea\x79\xa0\x3c\x90\xf3\x39\xd7\xbb\xd5\x3b\x6c\x2d\xfd\xd6\x31\x0d\xb4\xeb\xc8\xda\x54\xb5\x71\x94\xd2\x9f\x0a\x1f\x32\x1f\x4e\x43\x4b\x28\x7a\x7d\xb4\xd3\x34\xbe\x98\xfa\xc2\xf8\xec\x58\x65\x18\x9f\x87\xd6\x1a\x6e\x8e\xb2\x33\xda\xec\xb5\xb0\xb8\x7f\x3c\x5a\xec\xe3\x1c\x46\x16\x19\xf3\x3c\x78\xe1\xf4\x89\x0e\x1a\xba\x9b\xec\x64\xb7\x71\x19\xea\x57\x9b\x6c\xdc\x8f\x3f\x61\x6b\xcd\x7e\xef\x6c\x5d\x7c\xe1\xbf\xf8\x85\xed\xad\xab\x67\x70\xb8\xad\xed\x84\x82\x87\xdb\xda\xc3\x6d\xed\xe1\xb6\xf6\x60\x6d\x38\x58\x1b\x0e\xb7\xb5\xe4\x70\x5b\xbb\x17\x18\xee\xef\xb6\x16\x45\xbd\x55\x77\xb6\x4e\xd8\x8b\x17\xb6\x4f\x7a\x5f\xeb\x0a\xf7\x9c\x67\x99\xac\x85\xf9\x24\xef\x58\xe7\x4b\x87\x96\xfc\xbf\x34\x0e\x24\x40\x58\xa3\x0f\x2c\x37\x7e\x32\xe5\xa0\xbf\x54\xd2\x4b\xb6\xd8\x45\xaa\xa0\x75\xce\xad\xe4\xbf\x33\x9a\xf9\x01\xd2\xe4\x44\x22\x67\x79\xfc\xc1\x1d\x65\x63\x61\x3d\x22\xe7\x44\xb1\x8c\x57\xdc\x95\x91\xa7\xf8\x1e\x11\x2f\xd4\x46\xe0\x46\xb3\x62\xe2\x72\xd4\x8b\xb4\xd6\x4f\x94\xdf\x1d\x1d\x5c\xf9\x19\xe4\x50\xd2\x67\x32\xf7\xb5\x90\x14\xfb\x9b\x67\x6d\x6e\x36\x9f\xd2\x11\x52\xf3\x0a\x2c\xa5\x51\x62\x08\x3e\x56\x71\x17\x60\xfd\xd8\xc7\x9f\x7d\xae\xb8\x02\xe4\xbd\x65\x99\x14\x5d\x6a\xaa\xae\xd9\xa0\xa5\x91\x22\x7f\x02\xdb\x28\xcb\x49\x5e\xab\x50\x33\x75\x4e\x0b\x9e\x73\xb3\x08\xb7\x76\xae\xbc\x16\xc5\x13\x13\xb6\x51\x47\x30\x12\x5a\x55\x4a\xd2\x6c\xc6\x74\xf2\x35\x14\x50\x5c\x10\x59\xf0\x7d\xc7\x12\x70\x20\xa3\x40\x1f\xcb\x20\x8b\x05\x51\xd2\xf8\x8b\xf7\x35\x1f\xfc\x94\x0c\x06\xdd\x91\xcb\x19\xb5\x80\xdb\x79\x99\x0e\x81\xb3\xe2\x93\xf4\x0f\x4d\x64\x91\xfb\x14\x26\xbf\x7b\x65\x85\xc2\xcc\xe1\xa0\x25\x7e\x90\xe0\xc2\x48\x52\x58\x86\x6d\x09\xe2\xfa\xce\xbf\xfa\x35\x99\xc9\x5a\xe9\x51\x9a\x74\xe0\x35\xbc\x43\xfd\xce\x0b\x95\x86\x14\x8c\x6a\x43\x5e\xbf\x22\x25\x17\xb5\xe5\x53\xbd\xd1\xa6\xbf\x1c\x94\x48\x40\xbf\xf9\x75\xe7\x7e\x7d\x65\x9f\xb5\x52\x4f\x85\xb9\x91\x9d\xe8\xe3\x4e\x12\x06\xc6\x61\x66\xf1\x96\x20\xe4\x88\x6e\x0a\x6d\x61\xe4\x23\x9c\xaf\x1f\x6b\x39\x5e\x98\x3e\x41\x94\xae\x47\x33\x7a\xf2\xff\xba\x97\x5d\x92\xa7\xc4\xdc\x29\x1b\x3f\xfa\x28\x15\x2e\xa6\x5c\x9b\x2d\xf5\x2d\x62\x7c\xe5\xc6\x66\xdd\xd9\xca\xd4\x6a\x07\x3d\x63\x65\xa0\x8f\x97\x88\xbd\x6d\x29\xcb\x18\x16\xb3\xbc\x8c\x95\x92\x84\xc4\xb6\x5b\x87\x7f\xe6\x84\x63\x1e\x41\xf6\x90\x35\xbd\xe3\x52\xbb\x09\x5d\x1e\x25\x7a\xaf\x15\xbb\x35\x4f\x81\xe6\x62\x8a\x49\xce\xcb\xba\x30\xbc\x2a\xe2\xba\x3f\xfa\x0e\x8e\x90\xa7\x36\x37\x9a\x98\x89\x28\x06\x16\x63\xb6\x29\xb0\x4f\x9e\x84\xb1\x98\x30\x98\xab\x5b\x59\x7e\x50\x51\x45\x03\xf0\xa0\x92\xae\x3e\x75\xe6\x3b\x0a\x37\x8a\x2e\x1d\xa6\xed\x45\x8b\x38\xe3\xe4\x16\x69\x9f\x48\x63\x98\xa0\xa2\x83\xa9\xba\x99\x9e\x0b\x3a\x11\x79\x1f\x9c\xc9\xb0\x0c\x4a\x0b\x5b\x9c\x50\xf3\x15\xcd\xee\x98\xc8\xb1\x68\x14\x2c\x3b\x5f\x08\x5a\xba\x6c\x5b\x49\x3d\xee\x56\x7f\x3d\x70\x86\x09\x0c\xdf\xf3\x61\xc6\xc8\x75\xf7\x09\x83\x5a\xf7\x4e\x65\x63\xbb\x6c\x3b\xe7\x1a\x4d\x36\x8a\xcf\x33\xe6\xf9\xbf\xed\xb7\xcf\xa9\xcf\x3b\xc4\xd2\x2f\x4d\xde\x6f\x4f\x82\xbf\x40\xee\x83\xe5\x1c\x92\x6a\xd1\xc2\x1e\xed\x45\x88\x19\x6d\x6d\xee\x78\xb1\xdf\xaa\x37\x6a\xdc\x27\xf2\xf7\x58\x8d\xf3\xe6\x21\xfe\x48\x73\xa9\xc9\x57\x85\xcc\xee\xc8\x25\x03\xa1\xeb\x31\xcb\xb3\xa8\x71\xfe\x9c\x29\xbc\x4b\x3a\xdd\x76\xcf\x36\x24\xa5\x14\xdc\x48\xb5\x99\x5e\x3c\x5d\xd9\xc9\x43\xba\xe7\xb5\x19\xaa\x2c\x36\xbf\xe4\x64\xcf\x16\xdd\xfa\x6e\x3c\x74\x0a\xea\x19\x9c\x4e\x7c\xe5\xaa\x80\xed\x78\xd6\x7e\x3e\x93\xf7\x43\x23\x87\xb5\x66\x43\xde\xe1\x42\xb7\xc7\x32\xef\xd8\x02\x6e\xb1\x7b\x2e\xd4\x75\x6b\xe8\x0c\x46\x82\x05\x0a\xde\x5b\xce\xfd\xf1\xab\xcb\xef\x34\x53\xa3\x54\x06\x3c\x63\x26\x3b\xcb\x58\x35\x3b\x73\x23\xbc\x48\xa0\x78\x22\xd2\x17\x2a\xbe\x1f\xb2\x99\x4c\x16\x85\x0b\xcc\x96\x13\x72\xc1\xaa\x59\x18\xf8\xa9\x57\xfd\x7c\x19\x81\x2b\x29\xfb\x26\x42\x3d\xb6\x7d\x9a\x87\x08\xde\xe0\x19\x4a\x90\x49\x8d\xfb\x15\xa1\x78\x2a\xf4\x79\xd1\xa5\x36\x1f\x11\x38\x8f\x9b\x4e\xf9\xb8\x91\x4f\x39\xf5\xf7\x6c\x26\x4b\xf6\x1e\x23\x0d\x12\x74\x3d\x41\xa1\x3b\x67\x39\x91\x73\xa6\x14\xcf\x99\x26\x81\x06\xa5\x5a\x2a\x2f\x9e\x1a\x6e\x87\xbc\xcd\xcf\x9e\xb7\x79\x07\x75\xe8\x18\xf4\xa1\x06\x99\x82\x37\x4b\x64\x8a\xe6\x25\x17\x2f\x8e\x50\xe9\x8c\x16\xec\xfa\xdb\x1e\xfa\x87\xeb\xd1\x54\x41\x6e\xdd\xcb\x24\x7f\xda\x96\xac\x64\xdf\x04\xbc\x21\x42\xe6\xdb\x4c\xaa\x8f\xa0\x48\x4c\xa9\x61\xf7\x5b\xd9\xe1\x30\x12\xaa\xed\x2d\x41\x38\x7d\x4e\x95\xe3\x45\xe4\x08\x4c\x70\x1e\x93\x9e\xed\x93\xa9\xba\x5d\xeb\x6b\x9c\xc4\x5e\x69\xfa\xdd\x76\xd2\x5d\x8f\xc1\xe7\x37\xd7\xe4\x6b\x6c\xbe\xdf\xec\x85\x4a\x1a\x14\x03\x2f\x65\x49\x79\xdf\x22\x1b\xed\xee\xed\xec\xab\xe9\x12\x6e\x42\x5b\xe2\x1a\x27\x05\x5c\x26\x7c\x5a\x5b\x9d\xce\xe9\x61\x2f\x2a\xc1\xdc\x92\xe8\xf2\x72\x13\xcc\x3d\xbc\x1a\x44\x62\x72\xf2\x7e\x91\x51\x62\xf1\x5b\x09\xac\x24\xdc\x81\x12\xcd\x84\xe6\x70\x21\x93\xdc\x8a\xbb\x4a\x7f\x58\x5a\x12\x9d\x20\x51\xc4\x19\x90\x77\x72\xca\x85\x3f\xbd\xd2\xdd\xd7\x4d\x28\x2f\xba\x02\xe3\x20\x93\x3c\xbb\x4c\xa2\x75\x71\x25\xe8\xb8\xe8\xe2\x6e\xd0\x44\xb5\xd0\x91\xbc\x2d\xe8\x94\x30\xf8\xe3\x2c\xe7\xda\xfe\x9f\xdc\xde\xbe\x03\x23\x7c\x2d\xbc\xc4\x0c\x06\x6a\x47\xfb\x42\x90\x02\x1e\xc4\xfd\x9e\x1d\x24\x3d\x3b\x64\xff\x4b\x7a\x12\x2e\x72\x3b\xf1\xa4\x14\x1c\x3a\x49\x41\x0b\xcc\x87\x18\x7c\x7e\xd1\x6d\x60\xcc\xc8\xa7\x19\xcf\xee\x6e\x12\xbb\xbb\x54\xf6\x9d\x48\x5e\x35\x18\x58\xfb\xb7\x7d\x52\x4b\x37\xd5\x9b\xfe\xaa\x71\xd2\xd3\xf3\x01\x4f\x30\x6e\xdd\xfa\xe1\x37\xaa\xb5\xcc\x78\xbc\x73\x01\x1b\x4d\x64\x0e\x39\x30\x87\xfd\xae\x09\xc4\x83\xbe\xcb\x41\xf9\x63\x05\x47\xf3\xbb\xe9\xab\xe3\xea\x94\x83\x71\xe1\x57\xbd\xd7\x25\x20\xce\xec\x90\x1a\x3d\x76\x5c\x4e\x8d\xee\x85\xe1\xd6\xc5\x82\x77\x53\x77\x9b\xe7\x05\x31\x5f\x9b\x73\x69\xfb\x42\x8a\x74\x97\x9a\x70\x6f\x0b\xef\x12\xb6\xb1\x4a\x0d\x6f\xdd\x26\xe2\x3b\x77\xd5\x00\x67\xae\x92\x55\x5d\xa0\x3f\xc7\xc3\xf3\xbb\x7b\x9b\x31\x7e\x67\x4f\x57\x0f\x4f\x91\xb5\xf4\x38\x75\xec\xed\xef\xe9\xfc\xd3\xc8\x5d\x9a\x08\x77\xaf\x7e\xf3\xeb\x5f\x7f\xe9\xd9\x4c\xbb\xaa\xe0\x8f\x91\xce\xb4\xa3\x89\x76\x45\x7c\xd1\xf5\x21\xbe\xe8\x5f\x37\xbe\xe8\xf1\xb3\xd0\xee\x39\x82\xa8\xa7\x6f\x6e\x3f\xbf\xdc\xee\x31\x42\x9d\xbd\x77\xfb\x7a\xee\xf6\x88\x02\xda\x6f\xec\x4f\x6f\x5f\xd6\x3e\x71\x3e\x87\xe8\x9e\x9f\x6a\x74\xcf\x2e\xbe\xac\xfd\x23\x79\xfa\xf8\xb0\xfe\x14\xa3\x76\x7a\x1c\xce\xee\xd1\x25\x0f\x8e\x29\xe9\x9f\x04\xb0\xbf\x3d\x6d\x97\x82\x54\xb1\xe7\x4a\x0d\xd2\x07\x95\xfb\xdc\x63\xc7\xc7\x3a\x49\x2d\x66\xa4\x3d\x81\x4f\xa2\x90\x90\x1e\xda\x18\x0e\x2f\xfb\xd4\x86\x74\x7d\xbe\xbd\x6d\x5d\xcc\x84\xd7\xcf\x73\x1f\xf3\xaf\x70\xe1\x71\xa8\xe9\xf2\x85\x98\xdc\x75\x23\x5b\x8b\xb7\x56\x00\x09\x00\x46\x2e\xc7\x69\x96\xc8\x78\x74\xce\x6f\xae\xad\x0e\x0e\x61\x44\xb4\xd0\x23\xb2\x82\xcf\x7b\x73\xa9\x93\x0b\x3c\x7f\xa7\xc6\xb0\xb2\x32\xdd\x77\xfd\x60\x71\x7f\x76\x8b\xfb\x1e\x2d\x80\xb3\xba\xa4\x62\x68\x4f\x14\xd8\xdc\x1b\xb7\x75\x2d\xca\x3c\x22\xee\xec\x20\x7b\x02\x0b\x08\x04\x17\x34\x0b\x1b\xd3\xa4\xcc\xe5\xe3\x98\x3d\x61\xec\x9d\x57\x8e\x7c\xb5\x75\xd2\x32\xb9\xe4\xf0\xea\x96\x13\xa0\xe0\x0f\x55\xc2\x9c\x1b\x6a\xb8\x99\x31\xe4\xe1\x37\x10\x90\x13\x5b\x35\x25\x69\x14\xa5\x69\x51\xc8\x7b\xfc\x76\xca\xd7\x2c\xf4\xed\x5c\x5c\xa4\xd9\x98\x91\x92\x5b\x1d\xdd\x19\x58\xd3\xe9\xe0\x95\xa9\x95\xc8\x99\x42\x81\x57\xb9\xcb\xb6\x5b\x66\xdc\x46\xc1\x46\x5b\xfd\x56\xa0\x43\xb8\xfd\xb7\xf7\x2a\x82\x6f\x7b\x9a\x30\x66\x33\x3a\xe7\xb2\x56\xd8\xdb\x48\x72\xe4\x7e\x02\xde\xb0\x90\x75\xb0\x77\x61\x31\xcc\xb0\x3a\xbd\x02\x4e\x1f\xe2\x8f\xa0\x0a\xe4\xd2\x9b\x26\x86\xec\x33\xd7\x66\x79\x2d\x1e\x44\x3e\x0d\xde\xbe\xf0\x66\xae\x2b\xcb\x16\x7a\x57\xb5\x6b\xf4\x6b\xca\x2b\xf3\x5b\xf8\xe9\x0b\xaa\x69\xb7\x35\xbb\xeb\x93\x89\x40\xff\x82\xe2\x4f\xb8\x09\x2b\x78\xb6\xe8\x5d\xee\xad\xd5\xdb\x13\x6d\x1d\xee\xd0\xec\x7b\xf2\x15\xd5\x2c\x27\xef\xa9\xa0\x53\xd4\xf7\x4e\x6e\x6f\xbe\x7a\x7f\x6a\xf7\x15\xf4\xc9\xeb\xcb\x95\x17\x6d\xb7\xe9\xe0\x1f\xf6\x19\x2f\xb2\xb4\xf0\x1d\x58\xd5\x52\xff\x1d\x17\xbf\xd7\x40\x18\x12\xf8\x50\xb7\x64\xbd\x2b\x58\xd0\x4d\x3b\x84\xb5\x5d\xf3\xb3\x45\x60\xe6\x65\xfe\xc0\x2a\x9f\x5c\x68\x43\x8b\xe2\xa6\xa0\xe2\xbc\xaa\x94\x9c\xaf\xd6\xc6\x1b\x73\xf5\x0d\xfd\x4c\xd1\xcd\xc3\xbf\xac\x10\xf4\x70\x85\x2d\xc8\x75\x1c\x7f\x44\xae\x4d\xd0\xc2\xa5\x00\x96\x7a\x74\x5e\x1b\x59\x52\xc3\xb3\x23\xab\xac\x1f\xbd\xa7\xa2\xa6\xc5\x4a\xa7\xab\x8d\xcb\x58\x27\x22\x6e\xec\xb4\x3e\x75\x5d\x87\x6e\x1b\x65\x8d\xcd\xfd\x0d\x55\x96\x3a\x5d\xdc\x7e\xdf\xab\xaf\x36\xd4\xd4\x4b\x54\x78\x03\x67\x58\xcf\x0b\x86\xa4\xa0\xda\x7c\x57\xe5\xf6\xd0\xb7\x7e\xdd\x44\xf0\x33\x6a\x68\x21\xa7\x7f\x64\xb4\x58\x8d\xe1\x0d\x3c\xb9\x48\x5b\x7b\x03\x94\xbb\xf0\xaf\xc7\xa1\xe1\xb1\x26\x56\xc0\xf6\x31\xf0\x8a\x15\x6c\x4e\x85\xf1\xdd\xb1\xb8\xba\x3e\x76\xeb\x07\x2c\xe2\xd1\xf8\x9a\x33\xc3\x54\xc9\x45\x73\xcc\x5b\x68\x7b\x21\x45\xce\xd1\xec\x08\x06\x35\xec\xd1\x1c\x77\x3d\xaa\xad\xbb\x69\xd8\x70\xb7\xd0\xcc\xae\x99\xcc\xa7\x09\x0a\x6c\x36\x76\xf2\xe5\x0c\x5f\xc2\x4d\x7b\x63\x6e\x4b\x90\x22\x77\xc2\x0a\x86\x90\x47\x64\x35\xd9\xda\x2a\x27\x6c\x93\x0f\x86\x7e\x8f\x71\x0a\xeb\x1d\x47\x87\x6e\xde\xeb\xee\x20\x36\xa1\x18\x3e\xdb\x25\x8b\xf6\x54\xd6\xd3\xd4\x55\x78\x17\xba\x61\x24\x4b\xab\x20\x7f\xa3\xd1\x7a\x1e\xd0\x49\xf0\xea\x26\x23\x75\xcd\x6a\xdf\xa4\xb5\x31\x07\xfb\x92\x2a\xdb\x41\x62\xdc\xca\xb4\x3a\x26\x97\x6f\x2a\xd6\xd7\xce\xff\x4f\x39\x55\x84\x92\x8a\x33\x4c\x7e\x42\x85\x03\x16\x70\x16\x46\x73\xf7\xd2\x72\x30\xab\x12\xc2\x6f\x03\x77\x19\x8e\xc6\x65\xe7\x6b\xe1\x0d\xd4\x14\x93\x7f\xc0\xc5\xc5\xd9\xd7\xd2\x19\x79\x5d\x90\xae\xa5\x01\xc0\xc9\x07\x44\xd7\xd9\x8c\x50\x6d\xa7\x66\x11\xda\x9e\x78\x36\x2a\xa9\xe0\x13\xa6\xcd\x28\x64\x09\xd6\x7f\xfa\xd5\x5f\x46\xe4\xad\x54\xc4\x39\xaa\x0f\x7c\x56\x0d\x37\xcf\x88\x17\x5c\xe3\x62\x42\xdf\xa8\xb5\x56\x32\x77\x93\xbe\x87\xc9\x1a\x7a\x67\x79\x18\x4e\xb6\x66\x70\x75\xf1\x86\x1c\x59\x31\x31\xf9\xf4\x3f\x2c\x5b\xfa\xe7\x11\x39\xb9\x07\xa6\x7d\x64\xff\x3c\xc2\x0f\x06\xb7\xc9\x54\xa9\x8e\x1f\xc6\x60\x49\xc5\xa7\x53\xa6\x50\x7d\x24\x10\x54\x78\xea\xb2\x82\x08\x99\x34\xf6\x97\xd2\x51\xdd\x6c\x4f\xe4\x4f\xbf\xfa\xcb\x11\x39\x69\xae\x8b\x70\x91\xb3\xcf\xe4\x57\x68\x5d\xe6\xda\xae\xf1\xd4\x5d\xe6\xe8\x85\x30\xf4\xb3\x1d\x33\x9b\x49\xcd\x04\xaa\xf2\x46\x92\x19\x9d\x33\xa2\xa5\xd5\x80\x59\x51\x0c\x9d\x2d\x9d\xdc\x53\xc8\xd4\xe2\x41\x09\x81\xf5\xa4\xa2\xca\x34\x50\x62\xe4\x2c\x24\xf0\x35\xbb\x6d\x53\xe1\x6f\xa6\x27\x5c\xb8\xfb\x2b\x77\x73\x66\xf7\x1c\x02\x43\x71\x93\x8c\x24\xd9\x8c\x8a\x69\x88\x4d\x9f\xd4\xa6\x56\x6c\xcb\xd5\x4f\xc7\x33\x70\xc7\x45\xaf\x10\xe6\x6f\xb8\x68\x3b\x15\xac\xb6\x2b\x4d\xb9\xf1\x51\x11\xce\x57\xd1\x2c\xce\xec\x2e\x28\x3e\xae\x8d\x54\xfa\x2c\x67\x73\x56\x9c\x69\x3e\x1d\x52\x95\xcd\xb8\x61\x99\x5d\xd6\x19\xad\xf8\x30\x93\xc2\xee\x38\x64\x65\x28\xf3\x9f\x43\x79\xd3\xa1\x9d\xea\x96\xac\xd3\x1d\x17\xbd\xdd\xa8\xf6\xac\xc6\xb4\xbd\xad\xb1\x83\x3d\x68\x79\xa1\x68\x9b\x79\x82\xd5\x82\x21\xe4\x6c\x2f\x8b\xf5\x49\x93\xfb\xf3\x98\x63\x97\x07\x3c\x6b\x8f\x61\x8f\x1d\x3a\x90\xc0\xa9\x6c\x50\xca\x92\xe6\x48\x4a\xa9\x58\x3c\x3a\xf2\x5b\x90\x42\xba\xfc\x6c\x31\x84\x21\x64\x31\xa4\x22\xb7\xff\xc6\x80\x9d\x6c\xb1\x17\x18\xd6\xbc\x17\x21\xf8\xee\xfa\xf2\x69\x8e\x44\xcd\xf7\x70\xea\x9d\xbc\xd6\x51\x88\x42\x51\x15\x1d\x35\x54\xcd\x3c\xd3\x6c\x0a\xa8\x5c\xfb\x51\xff\xc3\xdd\xbf\x84\x6c\x67\xdb\x44\xaa\xcd\xb7\x26\x89\xec\xd8\x71\xbe\xef\x62\x8f\xd4\x26\x07\x8e\x57\x54\x1b\x97\x5a\xcb\xe7\x20\x68\x2c\xc3\x2b\x28\xc0\x60\xd6\x5f\x0c\x77\xc2\x21\xef\x2f\x60\x27\x32\x5c\x99\x73\x29\x0b\x4a\xc9\x76\x05\x2a\xea\x2f\x8d\x3a\x68\xb8\x28\xc3\xb4\x21\x74\x4e\x79\x01\xd6\x79\x39\xd6\x4c\xcd\xb1\x20\x95\x4b\x35\x48\xdb\x7a\x96\xab\x39\x81\x62\xd4\x13\x69\x3e\x7e\x0d\xcb\xbb\xb2\x69\x01\xa0\x0d\xb5\x66\xbf\x76\xd6\x7b\xd1\x7b\x50\xbd\x5c\xfb\xb3\xfd\xc2\x8e\x6a\x8c\xc5\xbf\x3f\x32\xaa\xcc\x98\x51\xf3\x89\x6f\xe2\xbb\x4b\x28\xdd\xe8\x17\x4a\xb9\x07\x84\xbe\x67\x64\x2a\x8d\x15\xb1\x6a\xc0\x7d\x94\x49\x31\xa9\x4f\x40\xb4\xc7\xc6\xe8\xb8\xca\x4f\x8a\x42\x88\x8f\x14\x3d\x97\xd9\xec\xb8\xbc\x4e\x27\x1d\x3b\x4c\x32\xd8\x1a\x13\x69\x48\xc1\xdc\xde\xe1\x6d\x06\x50\xa0\xa7\x59\x72\xc9\xb4\xde\x98\x60\xa3\xe9\x5d\x88\xad\xf1\x28\xb7\xae\xd6\x4a\xff\x1b\x86\x85\x58\x01\x3a\x67\x86\xf2\xc2\x1f\x65\x04\x45\x80\xd2\x36\xea\xba\x71\x81\x8a\x51\xbd\x49\x40\x68\xcc\xfa\x23\x34\xc6\x49\x4b\xc1\x86\xf7\x52\xe5\xe4\x82\x96\xac\xb8\xa0\x9a\xb9\xb1\xd2\x10\x3d\xdc\xa3\x63\xbd\xd7\x29\xaf\xb6\x7d\xad\x99\x32\x1a\x7f\xa2\x49\x18\xfe\x8a\x2a\x16\x4e\x70\xe0\x4d\x90\x9f\x54\xcd\x06\xe4\xad\xe5\x5e\x03\xf2\x9d\xb8\x13\xf2\xfe\x61\x73\x35\x1b\x6f\x41\x1a\x33\x4d\xdd\x3f\x7c\x5a\x9d\x86\xc1\x27\x4c\x77\xc7\x19\x39\x82\xbf\xc6\xd4\xd8\x64\x36\xa1\xa9\x9f\x91\xfd\xe7\x92\x09\xca\x2a\x8a\x4a\x4e\x15\xd3\x98\xb9\x66\x65\x92\xc4\xae\x26\xe7\xaf\x99\x70\xc1\x7d\x5b\xa7\x77\xbd\xaa\x97\x9f\xa9\xe7\x6b\xd3\xf8\x8b\xdb\x6f\xf7\xb1\xaa\x58\x29\x6a\x6c\xf6\x08\x4c\x26\xba\xc6\xf8\xb4\x6e\x86\xab\x8d\x4e\x09\xd7\x4b\xda\xa2\x50\xb2\xc9\x3a\xea\x57\x77\x71\xfb\xfd\x7a\x60\xaf\xe5\x7d\xdb\xf8\xd3\x76\xb3\xd4\x43\x0d\x52\x5b\xcf\xcc\x56\x23\xd4\xc1\xfc\x74\x30\x3f\x7d\x49\xe6\xa7\xad\x18\xbf\xc9\xe4\xf4\x65\x18\x9b\xb6\x2e\x71\x93\x81\xe9\x45\x9a\x96\x3a\xad\x68\xa3\x39\xe9\xc5\x1a\x92\xb6\x2e\xad\xa3\xf1\xe8\x5f\xc7\x6c\xb4\x15\x62\x1b\x4c\x45\x2f\xd0\x48\xd4\x45\x20\x63\x79\x17\x31\xf1\x3a\x69\x9c\x0a\x8a\xb1\x9c\x65\x18\xce\x3b\xe5\xa4\xe2\xcc\xae\xd2\xa2\x15\xe0\xb6\xce\xed\xd8\x4d\xae\xbb\xec\xe5\x04\x46\x57\xec\x71\x69\xb2\xe4\xf2\xea\xe6\xe3\xd5\xc5\xf9\xa7\xab\xcb\xb6\x7c\xb7\x0a\xd2\x5b\x24\xb1\xcd\x36\x88\x61\x22\x89\xad\x69\x60\x09\xf2\x9a\x9f\x2c\x0e\xac\xf9\xa9\xae\xf9\xaa\x5e\x0f\x97\x0b\x1f\xc4\xe5\x1e\xc4\x3f\xb6\x9f\xce\xae\xc7\xf3\x3b\x74\x9c\xa2\xce\xe7\xcc\xca\x3d\x33\x59\xe4\xda\xfb\xad\x5e\x5f\x86\x48\x2a\x2e\xb2\xa2\xce\xad\x70\xf1\xdd\x77\xd7\x97\x7a\x44\xc8\x57\x2c\xa3\xb5\x06\x2b\x4c\x2e\xc5\xb1\x21\xdf\x7e\x78\xf7\x5f\xe0\x8f\x0d\x2d\x06\x21\xaf\x09\x64\xe5\xe5\x14\x13\x0b\x1b\x4c\xd7\x46\xbe\x62\x28\xa8\xc0\x97\x33\x5a\x59\x2a\xa6\xb1\x72\x85\x01\x59\x64\xc6\x8a\xca\x52\xcc\x3b\x46\x62\x06\x55\x3b\x70\xac\x30\xef\xdd\x27\xa7\xcc\x60\xd4\xd5\x26\x0f\xc9\x8d\x50\xdb\x62\x71\x7d\x80\xad\xb5\xa1\x3e\x3a\x6d\xfc\x9e\x6a\x67\xb1\x5a\x39\xdb\x2d\xfb\xbb\xdd\x3e\xb3\xde\xc4\xb1\xc6\xb8\x81\xe4\x19\xfe\x5a\x9a\xb3\x9d\x6c\xb4\x63\xa0\x13\x09\x37\x9d\xad\xa9\xeb\xdd\x80\x56\xd7\x01\x58\xb2\x65\xb0\x36\x90\x1b\x1f\x0e\x1e\xd9\xc9\x94\xbb\xcd\x05\x8a\x88\xe4\x8d\xda\x9f\xce\x7f\xae\xf9\xae\x1e\x87\xea\xaf\x71\xbe\xce\x22\x43\xfe\xf1\xcf\x9f\xfd\xbf\x00\x00\x00\xff\xff\xab\xf2\x0f\xc7\x37\x6a\x02\x00") func operatorsCoreosCom_subscriptionsYamlBytes() ([]byte, error) { return bindataRead( @@ -311,11 +311,13 @@ var _bindata = map[string]func() (*asset, error){ // directory embedded in the file by go-bindata. // For example if you run go-bindata on data/... and data contains the // following hierarchy: -// data/ -// foo.txt -// img/ -// a.png -// b.png +// +// data/ +// foo.txt +// img/ +// a.png +// b.png +// // then AssetDir("data") would return []string{"foo.txt", "img"} // AssetDir("data/img") would return []string{"a.png", "b.png"} // AssetDir("foo.txt") and AssetDir("notexist") would return an error diff --git a/vendor/github.com/operator-framework/api/pkg/manifests/bundleloader.go b/vendor/github.com/operator-framework/api/pkg/manifests/bundleloader.go index 5d5bf2dc1a..94f14a22ac 100644 --- a/vendor/github.com/operator-framework/api/pkg/manifests/bundleloader.go +++ b/vendor/github.com/operator-framework/api/pkg/manifests/bundleloader.go @@ -51,6 +51,10 @@ func (b *bundleLoader) LoadBundle() error { // Add values from the annotations when the values are not loaded func (b *bundleLoader) addChannelsFromAnnotationsFile() { + if b.bundle == nil { + // None of this is relevant if the bundle was not found + return + } // Note that they will not get load for Bundle Format directories // and PackageManifest should not have the annotationsFile. However, // the following check to ensure that channels and default channels diff --git a/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/catalogsource_types.go b/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/catalogsource_types.go index 020fecc0ec..c4c7662d37 100644 --- a/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/catalogsource_types.go +++ b/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/catalogsource_types.go @@ -89,6 +89,11 @@ type CatalogSourceSpec struct { // +optional Secrets []string `json:"secrets,omitempty"` + // RunAsRoot allows admins to indicate that they wish to run the CatalogSource pod in a privileged + // pod as root. This should only be enabled when running older catalog images which could not be run as non-root. + // +optional + RunAsRoot bool `json:"runAsRoot,omitempty"` + // Metadata DisplayName string `json:"displayName,omitempty"` Description string `json:"description,omitempty"` @@ -114,6 +119,10 @@ type GrpcPodConfig struct { // +optional Tolerations []corev1.Toleration `json:"tolerations,omitempty"` + // Affinity is the catalog source's pod's affinity. + // +optional + Affinity *corev1.Affinity `json:"affinity,omitempty"` + // If specified, indicates the pod's priority. // If not specified, the pod priority will be default or zero if there is no // default. diff --git a/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/clusterserviceversion_types.go b/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/clusterserviceversion_types.go index eb4d1635ea..3e6d324803 100644 --- a/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/clusterserviceversion_types.go +++ b/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/clusterserviceversion_types.go @@ -145,11 +145,14 @@ type APIServiceDescription struct { ActionDescriptor []ActionDescriptor `json:"actionDescriptors,omitempty"` } -// APIResourceReference is a Kubernetes resource type used by a custom resource +// APIResourceReference is a reference to a Kubernetes resource type that the referrer utilizes. // +k8s:openapi-gen=true type APIResourceReference struct { - Name string `json:"name"` - Kind string `json:"kind"` + // Plural name of the referenced resource type (CustomResourceDefinition.Spec.Names[].Plural). Empty string if the referenced resource type is not a custom resource. + Name string `json:"name"` + // Kind of the referenced resource type. + Kind string `json:"kind"` + // API Version of the referenced resource type. Version string `json:"version"` } @@ -279,13 +282,34 @@ type ClusterServiceVersionSpec struct { WebhookDefinitions []WebhookDescription `json:"webhookdefinitions,omitempty"` NativeAPIs []metav1.GroupVersionKind `json:"nativeAPIs,omitempty"` MinKubeVersion string `json:"minKubeVersion,omitempty"` - DisplayName string `json:"displayName"` - Description string `json:"description,omitempty"` - Keywords []string `json:"keywords,omitempty"` - Maintainers []Maintainer `json:"maintainers,omitempty"` - Provider AppLink `json:"provider,omitempty"` - Links []AppLink `json:"links,omitempty"` - Icon []Icon `json:"icon,omitempty"` + + // The name of the operator in display format. + DisplayName string `json:"displayName"` + + // Description of the operator. Can include the features, limitations or use-cases of the + // operator. + // +optional + Description string `json:"description,omitempty"` + + // A list of keywords describing the operator. + // +optional + Keywords []string `json:"keywords,omitempty"` + + // A list of organizational entities maintaining the operator. + // +optional + Maintainers []Maintainer `json:"maintainers,omitempty"` + + // The publishing entity behind the operator. + // +optional + Provider AppLink `json:"provider,omitempty"` + + // A list of links related to the operator. + // +optional + Links []AppLink `json:"links,omitempty"` + + // The icon for this operator. + // +optional + Icon []Icon `json:"icon,omitempty"` // InstallModes specify supported installation types // +optional diff --git a/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/installplan_types.go b/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/installplan_types.go index 5210436d98..09deba525b 100644 --- a/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/installplan_types.go +++ b/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/installplan_types.go @@ -239,6 +239,9 @@ const ( // BundleLookupPending describes BundleLookups that are not complete. BundleLookupPending BundleLookupConditionType = "BundleLookupPending" + // BundleLookupFailed describes conditions types for when BundleLookups fail + BundleLookupFailed BundleLookupConditionType = "BundleLookupFailed" + crdKind = "CustomResourceDefinition" ) diff --git a/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/subscription_types.go b/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/subscription_types.go index 900cc46577..2452f9a1cf 100644 --- a/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/subscription_types.go +++ b/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/subscription_types.go @@ -111,6 +111,12 @@ const ( // SubscriptionResolutionFailed indicates that the dependency resolution in the namespace in which the subscription is created has failed SubscriptionResolutionFailed SubscriptionConditionType = "ResolutionFailed" + + // SubscriptionBundleUnpacking indicates that the unpack job is currently running + SubscriptionBundleUnpacking SubscriptionConditionType = "BundleUnpacking" + + // SubscriptionBundleUnpackFailed indicates that the unpack job failed + SubscriptionBundleUnpackFailed SubscriptionConditionType = "BundleUnpackFailed" ) const ( diff --git a/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/zz_generated.deepcopy.go b/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/zz_generated.deepcopy.go index e26ddea616..cf01001f5c 100644 --- a/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/github.com/operator-framework/api/pkg/operators/v1alpha1/zz_generated.deepcopy.go @@ -723,6 +723,11 @@ func (in *GrpcPodConfig) DeepCopyInto(out *GrpcPodConfig) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.Affinity != nil { + in, out := &in.Affinity, &out.Affinity + *out = new(v1.Affinity) + (*in).DeepCopyInto(*out) + } if in.PriorityClassName != nil { in, out := &in.PriorityClassName, &out.PriorityClassName *out = new(string) diff --git a/vendor/github.com/operator-framework/api/pkg/validation/internal/annotations.go b/vendor/github.com/operator-framework/api/pkg/validation/internal/annotations.go index 2ab63aa9fb..715b04171f 100644 --- a/vendor/github.com/operator-framework/api/pkg/validation/internal/annotations.go +++ b/vendor/github.com/operator-framework/api/pkg/validation/internal/annotations.go @@ -30,13 +30,13 @@ which are known to be case sensitive. It also checks to see if the olm.propertie annotation is defined in order to add a warning if present. This function can be used anywhere annotations need to be checked for case sensitivity. -Arguments +# Arguments • annotations: annotations map usually obtained from ObjectMeta.GetAnnotations() • value: is the field or file that caused an error or warning -Returns +# Returns • errs: Any errors that may have been detected with the annotation keys provided */ diff --git a/vendor/github.com/operator-framework/api/pkg/validation/internal/community.go b/vendor/github.com/operator-framework/api/pkg/validation/internal/community.go index dfc7c4aabe..debaae2bab 100644 --- a/vendor/github.com/operator-framework/api/pkg/validation/internal/community.go +++ b/vendor/github.com/operator-framework/api/pkg/validation/internal/community.go @@ -7,7 +7,7 @@ import ( "os" "strings" - "github.com/blang/semver" + "github.com/blang/semver/v4" "github.com/operator-framework/api/pkg/manifests" "github.com/operator-framework/api/pkg/validation/errors" diff --git a/vendor/github.com/operator-framework/api/pkg/validation/internal/operatorhub.go b/vendor/github.com/operator-framework/api/pkg/validation/internal/operatorhub.go index ac9fd0cf53..f5da37a274 100644 --- a/vendor/github.com/operator-framework/api/pkg/validation/internal/operatorhub.go +++ b/vendor/github.com/operator-framework/api/pkg/validation/internal/operatorhub.go @@ -71,15 +71,15 @@ import ( // containing a list of categories will enable those categories to be used when comparing CSV categories for // OperatorHub validation. The json file should be in the following format: // -// ```json -// { -// "categories":[ -// "Cloud Pak", -// "Registry", -// "MyCoolThing", -// ] -// } -// ``` +// ```json +// { +// "categories":[ +// "Cloud Pak", +// "Registry", +// "MyCoolThing", +// ] +// } +// ``` // // - The `csv.Spec.Provider.Name` was provided // diff --git a/vendor/github.com/operator-framework/api/pkg/validation/internal/removed_apis.go b/vendor/github.com/operator-framework/api/pkg/validation/internal/removed_apis.go index 44dee85d06..13feafb5d2 100644 --- a/vendor/github.com/operator-framework/api/pkg/validation/internal/removed_apis.go +++ b/vendor/github.com/operator-framework/api/pkg/validation/internal/removed_apis.go @@ -2,12 +2,17 @@ package internal import ( "fmt" - "github.com/blang/semver" + "sort" + "strings" + + "github.com/blang/semver/v4" "github.com/operator-framework/api/pkg/manifests" + "github.com/operator-framework/api/pkg/operators/v1alpha1" "github.com/operator-framework/api/pkg/validation/errors" interfaces "github.com/operator-framework/api/pkg/validation/interfaces" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "sort" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" ) // k8sVersionKey defines the key which can be used by its consumers @@ -147,11 +152,12 @@ func checkRemovedAPIsForVersion( errs []error, warns []error) ([]error, []error) { found := map[string][]string{} + warnsFound := map[string][]string{} switch k8sVersionToCheck.String() { case "1.22.0": found = getRemovedAPIsOn1_22From(bundle) case "1.25.0": - found = getRemovedAPIsOn1_25From(bundle) + found, warnsFound = getRemovedAPIsOn1_25From(bundle) case "1.26.0": found = getRemovedAPIsOn1_26From(bundle) default: @@ -172,6 +178,16 @@ func checkRemovedAPIsForVersion( warns = append(warns, msg) } } + + if len(warnsFound) > 0 { + deprecatedAPIsMessage := generateMessageWithDeprecatedAPIs(warnsFound) + msg := fmt.Errorf(DeprecateMessage, + k8sVersionToCheck.Major, k8sVersionToCheck.Minor, + k8sVersionToCheck.Major, k8sVersionToCheck.Minor, + deprecatedAPIsMessage) + warns = append(warns, msg) + } + return errs, warns } @@ -287,40 +303,115 @@ func getRemovedAPIsOn1_22From(bundle *manifests.Bundle) map[string][]string { // add manifests on the bundle using these APIs. On top of that some Kinds such as the CronJob // are not currently a valid/supported by OLM and never would to be added to bundle. // See: https://github.com/operator-framework/operator-registry/blob/v1.19.5/pkg/lib/bundle/supported_resources.go#L3-L23 -func getRemovedAPIsOn1_25From(bundle *manifests.Bundle) map[string][]string { +func getRemovedAPIsOn1_25From(bundle *manifests.Bundle) (map[string][]string, map[string][]string) { deprecatedAPIs := make(map[string][]string) + warnDeprecatedAPIs := make(map[string][]string) + + deprecatedGvk := map[schema.GroupVersionKind]struct{}{ + {Group: "batch", Version: "v1beta1", Kind: "CronJob"}: {}, + {Group: "discovery.k8s.io", Version: "v1beta1", Kind: "EndpointSlice"}: {}, + {Group: "events.k8s.io", Version: "v1beta1", Kind: "Event"}: {}, + {Group: "autoscaling", Version: "v2beta1", Kind: "HorizontalPodAutoscaler"}: {}, + {Group: "policy", Version: "v1beta1", Kind: "PodDisruptionBudget"}: {}, + {Group: "policy", Version: "v1beta1", Kind: "PodSecurityPolicy"}: {}, + {Group: "node.k8s.io", Version: "v1beta1", Kind: "RuntimeClass"}: {}, + } + + addIfDeprecated := func(u *unstructured.Unstructured) { + if _, ok := deprecatedGvk[u.GetObjectKind().GroupVersionKind()]; ok { + deprecatedAPIs[u.GetKind()] = append(deprecatedAPIs[u.GetKind()], u.GetName()) + } + } + + deprecatedGroupResource := map[schema.GroupResource]struct{}{ + {Group: "batch", Resource: "cronjobs"}: {}, + {Group: "discovery.k8s.io", Resource: "endpointslices"}: {}, + {Group: "events.k8s.io", Resource: "events"}: {}, + {Group: "autoscaling", Resource: "horizontalpodautoscalers"}: {}, + {Group: "policy", Resource: "poddisruptionbudgets"}: {}, + {Group: "policy", Resource: "podsecuritypolicies"}: {}, + {Group: "node.k8s.io", Resource: "runtimeclasses"}: {}, + } + + warnIfDeprecated := func(gr schema.GroupResource, msg string) { + if _, ok := deprecatedGroupResource[gr]; ok { + warnDeprecatedAPIs[gr.Resource] = append(warnDeprecatedAPIs[gr.Resource], msg) + } + } + for _, obj := range bundle.Objects { switch u := obj.GetObjectKind().(type) { case *unstructured.Unstructured: switch u.GetAPIVersion() { - case "batch/v1beta1": - if u.GetKind() == "CronJob" { - deprecatedAPIs[u.GetKind()] = append(deprecatedAPIs[u.GetKind()], obj.GetName()) - } - case "discovery.k8s.io/v1beta1": - if u.GetKind() == "EndpointSlice" { - deprecatedAPIs[u.GetKind()] = append(deprecatedAPIs[u.GetKind()], obj.GetName()) - } - case "events.k8s.io/v1beta1": - if u.GetKind() == "Event" { - deprecatedAPIs[u.GetKind()] = append(deprecatedAPIs[u.GetKind()], obj.GetName()) - } - case "autoscaling/v2beta1": - if u.GetKind() == "HorizontalPodAutoscaler" { - deprecatedAPIs[u.GetKind()] = append(deprecatedAPIs[u.GetKind()], obj.GetName()) - } - case "policy/v1beta1": - if u.GetKind() == "PodDisruptionBudget" || u.GetKind() == "PodSecurityPolicy" { - deprecatedAPIs[u.GetKind()] = append(deprecatedAPIs[u.GetKind()], obj.GetName()) - } - case "node.k8s.io/v1beta1": - if u.GetKind() == "RuntimeClass" { - deprecatedAPIs[u.GetKind()] = append(deprecatedAPIs[u.GetKind()], obj.GetName()) + case "operators.coreos.com/v1alpha1": + // Check a couple CSV fields for references to deprecated APIs + if u.GetKind() == "ClusterServiceVersion" { + resInCsvCrds := make(map[string]struct{}) + csv := &v1alpha1.ClusterServiceVersion{} + err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.Object, csv) + if err != nil { + fmt.Println("failed to convert unstructured.Unstructed to v1alpha1.ClusterServiceVersion:", err) + } + + // Loop through all the CRDDescriptions to see + // if there is any with an API Version & Kind that is deprecated + crdCheck := func(crdsField string, crdDescriptions []v1alpha1.CRDDescription) { + for i, desc := range crdDescriptions { + for j, res := range desc.Resources { + resFromKind := fmt.Sprintf("%ss", strings.ToLower(res.Kind)) + resInCsvCrds[resFromKind] = struct{}{} + unstruct := &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": res.Version, + "kind": res.Kind, + "metadata": map[string]interface{}{ + "name": fmt.Sprintf("ClusterServiceVersion.Spec.CustomResourceDefinitions.%s[%d].Resource[%d]", crdsField, i, j), + }, + }, + } + addIfDeprecated(unstruct) + } + } + } + + // Check the Owned Resources + crdCheck("Owned", csv.Spec.CustomResourceDefinitions.Owned) + + // Check the Required Resources + crdCheck("Required", csv.Spec.CustomResourceDefinitions.Required) + + // Loop through all the StrategyDeploymentPermissions to see + // if the rbacv1.PolicyRule that is defined specifies a resource that + // *may* have a deprecated API then add it to the warnings. + // Only present a warning if the resource was NOT found as a resource + // in the ClusterServiceVersion.Spec.CustomResourceDefinitions fields + permCheck := func(permField string, perms []v1alpha1.StrategyDeploymentPermissions) { + for i, perm := range perms { + for j, rule := range perm.Rules { + for _, apiGroup := range rule.APIGroups { + for _, res := range rule.Resources { + if _, ok := resInCsvCrds[res]; ok { + continue + } + warnIfDeprecated(schema.GroupResource{Group: apiGroup, Resource: res}, fmt.Sprintf("ClusterServiceVersion.Spec.InstallStrategy.StrategySpec.%s[%d].Rules[%d]", permField, i, j)) + } + } + } + } + } + + // Check the ClusterPermissions + permCheck("ClusterPermissions", csv.Spec.InstallStrategy.StrategySpec.ClusterPermissions) + + // Check the Permissions + permCheck("Permissions", csv.Spec.InstallStrategy.StrategySpec.Permissions) } + default: + addIfDeprecated(u) } } } - return deprecatedAPIs + return deprecatedAPIs, warnDeprecatedAPIs } // getRemovedAPIsOn1_26From return the list of resources which were deprecated diff --git a/vendor/github.com/operator-framework/operator-lifecycle-manager/cmd/catalog/main.go b/vendor/github.com/operator-framework/operator-lifecycle-manager/cmd/catalog/main.go index 20134d71d2..d282dfebb3 100644 --- a/vendor/github.com/operator-framework/operator-lifecycle-manager/cmd/catalog/main.go +++ b/vendor/github.com/operator-framework/operator-lifecycle-manager/cmd/catalog/main.go @@ -27,7 +27,7 @@ const ( defaultWakeupInterval = 15 * time.Minute defaultCatalogNamespace = "olm" defaultConfigMapServerImage = "quay.io/operator-framework/configmap-operator-registry:latest" - defaultOPMImage = "quay.io/operator-framework/upstream-opm-builder:latest" + defaultOPMImage = "quay.io/operator-framework/opm:latest" defaultUtilImage = "quay.io/operator-framework/olm:latest" defaultOperatorName = "" defaultWorkLoadUserID = int64(1001) diff --git a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/clientset/versioned/clientset.go b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/clientset/versioned/clientset.go index aa24543eef..6d1cbfb097 100644 --- a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/clientset/versioned/clientset.go +++ b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/clientset/versioned/clientset.go @@ -39,8 +39,7 @@ type Interface interface { OperatorsV2() operatorsv2.OperatorsV2Interface } -// Clientset contains the clients for groups. Each group has exactly one -// version included in a Clientset. +// Clientset contains the clients for groups. type Clientset struct { *discovery.DiscoveryClient operatorsV1alpha1 *operatorsv1alpha1.OperatorsV1alpha1Client diff --git a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/informers/externalversions/factory.go b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/informers/externalversions/factory.go index f037340b49..3a265e8e4c 100644 --- a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/informers/externalversions/factory.go +++ b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/informers/externalversions/factory.go @@ -47,6 +47,11 @@ type sharedInformerFactory struct { // startedInformers is used for tracking which informers have been started. // This allows Start() to be called multiple times safely. startedInformers map[reflect.Type]bool + // wg tracks how many goroutines were started. + wg sync.WaitGroup + // shuttingDown is true when Shutdown has been called. It may still be running + // because it needs to wait for goroutines. + shuttingDown bool } // WithCustomResyncConfig sets a custom resync period for the specified informer types. @@ -107,20 +112,39 @@ func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResy return factory } -// Start initializes all requested informers. func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { f.lock.Lock() defer f.lock.Unlock() + if f.shuttingDown { + return + } + for informerType, informer := range f.informers { if !f.startedInformers[informerType] { - go informer.Run(stopCh) + f.wg.Add(1) + // We need a new variable in each loop iteration, + // otherwise the goroutine would use the loop variable + // and that keeps changing. + informer := informer + go func() { + defer f.wg.Done() + informer.Run(stopCh) + }() f.startedInformers[informerType] = true } } } -// WaitForCacheSync waits for all started informers' cache were synced. +func (f *sharedInformerFactory) Shutdown() { + f.lock.Lock() + f.shuttingDown = true + f.lock.Unlock() + + // Will return immediately if there is nothing to wait for. + f.wg.Wait() +} + func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool { informers := func() map[reflect.Type]cache.SharedIndexInformer { f.lock.Lock() @@ -167,11 +191,58 @@ func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internal // SharedInformerFactory provides shared informers for resources in all known // API group versions. +// +// It is typically used like this: +// +// ctx, cancel := context.Background() +// defer cancel() +// factory := NewSharedInformerFactory(client, resyncPeriod) +// defer factory.WaitForStop() // Returns immediately if nothing was started. +// genericInformer := factory.ForResource(resource) +// typedInformer := factory.SomeAPIGroup().V1().SomeType() +// factory.Start(ctx.Done()) // Start processing these informers. +// synced := factory.WaitForCacheSync(ctx.Done()) +// for v, ok := range synced { +// if !ok { +// fmt.Fprintf(os.Stderr, "caches failed to sync: %v", v) +// return +// } +// } +// +// // Creating informers can also be created after Start, but then +// // Start must be called again: +// anotherGenericInformer := factory.ForResource(resource) +// factory.Start(ctx.Done()) type SharedInformerFactory interface { internalinterfaces.SharedInformerFactory - ForResource(resource schema.GroupVersionResource) (GenericInformer, error) + + // Start initializes all requested informers. They are handled in goroutines + // which run until the stop channel gets closed. + Start(stopCh <-chan struct{}) + + // Shutdown marks a factory as shutting down. At that point no new + // informers can be started anymore and Start will return without + // doing anything. + // + // In addition, Shutdown blocks until all goroutines have terminated. For that + // to happen, the close channel(s) that they were started with must be closed, + // either before Shutdown gets called or while it is waiting. + // + // Shutdown may be called multiple times, even concurrently. All such calls will + // block until all goroutines have terminated. + Shutdown() + + // WaitForCacheSync blocks until all started informers' caches were synced + // or the stop channel gets closed. WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool + // ForResource gives generic access to a shared informer of the matching type. + ForResource(resource schema.GroupVersionResource) (GenericInformer, error) + + // InternalInformerFor returns the SharedIndexInformer for obj using an internal + // client. + InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer + Operators() operators.Interface } diff --git a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/bundle/bundle_unpacker.go b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/bundle/bundle_unpacker.go index 6abfc808ac..c7b71c0670 100644 --- a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/bundle/bundle_unpacker.go +++ b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/bundle/bundle_unpacker.go @@ -26,6 +26,7 @@ import ( "github.com/operator-framework/api/pkg/operators/reference" operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" + v1listers "github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/listers/operators/v1" listersoperatorsv1alpha1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/listers/operators/v1alpha1" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/install" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/projection" @@ -33,12 +34,8 @@ import ( ) const ( - // TODO: Move to operator-framework/api/pkg/operators/v1alpha1 - // BundleLookupFailed describes conditions types for when BundleLookups fail - BundleLookupFailed operatorsv1alpha1.BundleLookupConditionType = "BundleLookupFailed" - // TODO: This can be a spec field - // BundleUnpackTimeoutAnnotationKey allows setting a bundle unpack timeout per InstallPlan + // BundleUnpackTimeoutAnnotationKey allows setting a bundle unpack timeout per OperatorGroup // and overrides the default specified by the --bundle-unpack-timeout flag // The time duration should be in the same format as accepted by time.ParseDuration() // e.g 1m30s @@ -211,6 +208,9 @@ func (c *ConfigMapUnpacker) job(cmRef *corev1.ObjectReference, bundlePath string }, }, }, + NodeSelector: map[string]string{ + "kubernetes.io/os": "linux", + }, }, }, }, @@ -422,7 +422,7 @@ func (c *ConfigMapUnpacker) UnpackBundle(lookup *operatorsv1alpha1.BundleLookup, result = newBundleUnpackResult(lookup) // if bundle lookup failed condition already present, then there is nothing more to do - failedCond := result.GetCondition(BundleLookupFailed) + failedCond := result.GetCondition(operatorsv1alpha1.BundleLookupFailed) if failedCond.Status == corev1.ConditionTrue { return result, nil } @@ -768,3 +768,30 @@ func getCondition(job *batchv1.Job, conditionType batchv1.JobConditionType) (con } return } + +// OperatorGroupBundleUnpackTimeout returns bundle timeout from annotation if specified. +// If the timeout annotation is not set, return timeout < 0 which is subsequently ignored. +// This is to overrides the --bundle-unpack-timeout flag value on per-OperatorGroup basis. +func OperatorGroupBundleUnpackTimeout(ogLister v1listers.OperatorGroupNamespaceLister) (time.Duration, error) { + ignoreTimeout := -1 * time.Minute + + ogs, err := ogLister.List(k8slabels.Everything()) + if err != nil { + return ignoreTimeout, err + } + if len(ogs) != 1 { + return ignoreTimeout, fmt.Errorf("found %d operatorGroups, expected 1", len(ogs)) + } + + timeoutStr, ok := ogs[0].GetAnnotations()[BundleUnpackTimeoutAnnotationKey] + if !ok { + return ignoreTimeout, nil + } + + d, err := time.ParseDuration(timeoutStr) + if err != nil { + return ignoreTimeout, fmt.Errorf("failed to parse unpack timeout annotation(%s: %s): %w", BundleUnpackTimeoutAnnotationKey, timeoutStr, err) + } + + return d, nil +} diff --git a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/install/deployment.go b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/install/deployment.go index 559520aad7..43aab8e1ce 100644 --- a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/install/deployment.go +++ b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/install/deployment.go @@ -175,7 +175,7 @@ func (i *StrategyDeploymentInstaller) deploymentForSpec(name string, spec appsv1 // By default, each deployment created by OLM could spawn up to 10 replicaSets. // By setting the deployments revisionHistoryLimit to 1, OLM will only create up // to 2 ReplicaSets per deployment it manages, saving memory. - dep.Spec.RevisionHistoryLimit = pointer.Int32Ptr(1) + dep.Spec.RevisionHistoryLimit = pointer.Int32(1) hash = HashDeploymentSpec(dep.Spec) dep.Labels[DeploymentSpecHashLabelKey] = hash diff --git a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/operators/catalog/operator.go b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/operators/catalog/operator.go index 0c3531e780..0d24b363d3 100644 --- a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/operators/catalog/operator.go +++ b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/operators/catalog/operator.go @@ -934,7 +934,13 @@ func (o *Operator) syncResolvingNamespace(obj interface{}) error { return err } - failForwardEnabled, err := resolver.IsFailForwardEnabled(o.lister.OperatorsV1().OperatorGroupLister().OperatorGroups(namespace)) + ogLister := o.lister.OperatorsV1().OperatorGroupLister().OperatorGroups(namespace) + failForwardEnabled, err := resolver.IsFailForwardEnabled(ogLister) + if err != nil { + return err + } + + unpackTimeout, err := bundle.OperatorGroupBundleUnpackTimeout(ogLister) if err != nil { return err } @@ -1028,6 +1034,80 @@ func (o *Operator) syncResolvingNamespace(obj interface{}) error { return err } + // Attempt to unpack bundles before installing + // Note: This should probably use the attenuated client to prevent users from resolving resources they otherwise don't have access to. + if len(bundleLookups) > 0 { + logger.Debug("unpacking bundles") + + var unpacked bool + unpacked, steps, bundleLookups, err = o.unpackBundles(namespace, steps, bundleLookups, unpackTimeout) + if err != nil { + // If the error was fatal capture and fail + if olmerrors.IsFatal(err) { + _, updateErr := o.updateSubscriptionStatuses( + o.setSubsCond(subs, v1alpha1.SubscriptionCondition{ + Type: v1alpha1.SubscriptionBundleUnpackFailed, + Reason: "ErrorPreventedUnpacking", + Message: err.Error(), + Status: corev1.ConditionTrue, + })) + if updateErr != nil { + logger.WithError(updateErr).Debug("failed to update subs conditions") + return updateErr + } + return nil + } + // Retry sync if non-fatal error + return fmt.Errorf("bundle unpacking failed with an error: %w", err) + } + + // Check BundleLookup status conditions to see if the BundleLookupFailed condtion is true + // which means bundle lookup has failed and subscriptions need to be updated + // with a condition indicating the failure. + isFailed, cond := hasBundleLookupFailureCondition(bundleLookups) + if isFailed { + err := fmt.Errorf("bundle unpacking failed. Reason: %v, and Message: %v", cond.Reason, cond.Message) + logger.Infof("%v", err) + + _, updateErr := o.updateSubscriptionStatuses( + o.setSubsCond(subs, v1alpha1.SubscriptionCondition{ + Type: v1alpha1.SubscriptionBundleUnpackFailed, + Reason: "BundleUnpackFailed", + Message: err.Error(), + Status: corev1.ConditionTrue, + })) + if updateErr != nil { + logger.WithError(updateErr).Debug("failed to update subs conditions") + return updateErr + } + // Since this is likely requires intervention we do not want to + // requeue too often. We return no error here and rely on a + // periodic resync which will help to automatically resolve + // some issues such as unreachable bundle images caused by + // bad catalog updates. + return nil + } + + // This means that the unpack job is still running (most likely) or + // there was some issue which we did not handle above. + if !unpacked { + _, updateErr := o.updateSubscriptionStatuses( + o.setSubsCond(subs, v1alpha1.SubscriptionCondition{ + Type: v1alpha1.SubscriptionBundleUnpacking, + Reason: "UnpackingInProgress", + Status: corev1.ConditionTrue, + })) + if updateErr != nil { + logger.WithError(updateErr).Debug("failed to update subs conditions") + return updateErr + } + + logger.Debug("unpacking is not complete yet, requeueing") + o.nsResolveQueue.AddAfter(namespace, 5*time.Second) + return nil + } + } + // create installplan if anything updated if len(updatedSubs) > 0 { logger.Debug("resolution caused subscription changes, creating installplan") @@ -1062,8 +1142,17 @@ func (o *Operator) syncResolvingNamespace(obj interface{}) error { logger.Debugf("no subscriptions were updated") } + // Make sure that we no longer indicate unpacking progress + subs = o.setSubsCond(subs, v1alpha1.SubscriptionCondition{ + Type: v1alpha1.SubscriptionBundleUnpacking, + Status: corev1.ConditionFalse, + }) + + // Remove BundleUnpackFailed condition from subscriptions + o.removeSubsCond(subs, v1alpha1.SubscriptionBundleUnpackFailed) + // Remove resolutionfailed condition from subscriptions - subs = o.removeSubsCond(subs, v1alpha1.SubscriptionResolutionFailed) + o.removeSubsCond(subs, v1alpha1.SubscriptionResolutionFailed) newSub := true for _, updatedSub := range updatedSubs { updatedSub.Status.RemoveConditions(v1alpha1.SubscriptionResolutionFailed) @@ -1408,35 +1497,30 @@ type UnpackedBundleReference struct { Properties string `json:"properties"` } -func (o *Operator) unpackBundles(plan *v1alpha1.InstallPlan) (bool, *v1alpha1.InstallPlan, error) { - out := plan.DeepCopy() +func (o *Operator) unpackBundles(namespace string, installPlanSteps []*v1alpha1.Step, bundleLookups []v1alpha1.BundleLookup, unpackTimeout time.Duration) (bool, []*v1alpha1.Step, []v1alpha1.BundleLookup, error) { unpacked := true - // The bundle timeout annotation if specified overrides the --bundle-unpack-timeout flag value - // If the timeout cannot be parsed it's set to < 0 and subsequently ignored - unpackTimeout := -1 * time.Minute - timeoutStr, ok := plan.GetAnnotations()[bundle.BundleUnpackTimeoutAnnotationKey] - if ok { - d, err := time.ParseDuration(timeoutStr) - if err != nil { - o.logger.Errorf("failed to parse unpack timeout annotation(%s: %s): %v", bundle.BundleUnpackTimeoutAnnotationKey, timeoutStr, err) - } else { - unpackTimeout = d - } + outBundleLookups := make([]v1alpha1.BundleLookup, len(bundleLookups)) + for i := range bundleLookups { + bundleLookups[i].DeepCopyInto(&outBundleLookups[i]) + } + outInstallPlanSteps := make([]*v1alpha1.Step, len(installPlanSteps)) + for i := range installPlanSteps { + outInstallPlanSteps[i] = installPlanSteps[i].DeepCopy() } var errs []error - for i := 0; i < len(out.Status.BundleLookups); i++ { - lookup := out.Status.BundleLookups[i] + for i := 0; i < len(outBundleLookups); i++ { + lookup := outBundleLookups[i] res, err := o.bundleUnpacker.UnpackBundle(&lookup, unpackTimeout) if err != nil { errs = append(errs, err) continue } - out.Status.BundleLookups[i] = *res.BundleLookup + outBundleLookups[i] = *res.BundleLookup // if the failed condition is present it means the bundle unpacking has failed - failedCondition := res.GetCondition(bundle.BundleLookupFailed) + failedCondition := res.GetCondition(v1alpha1.BundleLookupFailed) if failedCondition.Status == corev1.ConditionTrue { unpacked = false continue @@ -1455,11 +1539,11 @@ func (o *Operator) unpackBundles(plan *v1alpha1.InstallPlan) (bool, *v1alpha1.In continue } - // Ensure that bundle can be applied by the current version of OLM by converting to steps - steps, err := resolver.NewStepsFromBundle(res.Bundle(), out.GetNamespace(), res.Replaces, res.CatalogSourceRef.Name, res.CatalogSourceRef.Namespace) + // Ensure that bundle can be applied by the current version of OLM by converting to bundleSteps + bundleSteps, err := resolver.NewStepsFromBundle(res.Bundle(), namespace, res.Replaces, res.CatalogSourceRef.Name, res.CatalogSourceRef.Namespace) if err != nil { if fatal := olmerrors.IsFatal(err); fatal { - return false, nil, err + return false, nil, nil, err } errs = append(errs, fmt.Errorf("failed to turn bundle into steps: %v", err)) @@ -1468,7 +1552,7 @@ func (o *Operator) unpackBundles(plan *v1alpha1.InstallPlan) (bool, *v1alpha1.In } // step manifests are replaced with references to the configmap containing them - for i, s := range steps { + for i, s := range bundleSteps { ref := UnpackedBundleReference{ Kind: "ConfigMap", Namespace: res.CatalogSourceRef.Namespace, @@ -1485,19 +1569,19 @@ func (o *Operator) unpackBundles(plan *v1alpha1.InstallPlan) (bool, *v1alpha1.In continue } s.Resource.Manifest = string(r) - steps[i] = s + bundleSteps[i] = s } res.RemoveCondition(resolver.BundleLookupConditionPacked) - out.Status.BundleLookups[i] = *res.BundleLookup - out.Status.Plan = append(out.Status.Plan, steps...) + outBundleLookups[i] = *res.BundleLookup + outInstallPlanSteps = append(outInstallPlanSteps, bundleSteps...) } if err := utilerrors.NewAggregate(errs); err != nil { o.logger.Debugf("failed to unpack bundles: %v", err) - return false, nil, err + return false, nil, nil, err } - return unpacked, out, nil + return unpacked, outInstallPlanSteps, outBundleLookups, nil } // gcInstallPlans garbage collects installplans that are too old @@ -1599,7 +1683,6 @@ func (o *Operator) syncInstallPlans(obj interface{}) (syncError error) { querier := o.serviceAccountQuerier.NamespaceQuerier(plan.GetNamespace()) ref, err := querier() - out := plan.DeepCopy() if err != nil { // Set status condition/message and retry sync if any error @@ -1645,65 +1728,6 @@ func (o *Operator) syncInstallPlans(obj interface{}) (syncError error) { } } - // Attempt to unpack bundles before installing - // Note: This should probably use the attenuated client to prevent users from resolving resources they otherwise don't have access to. - if len(plan.Status.BundleLookups) > 0 { - unpacked, out, err := o.unpackBundles(plan) - if err != nil { - // If the error was fatal capture and fail - if fatal := olmerrors.IsFatal(err); fatal { - if err := o.transitionInstallPlanToFailed(plan, logger, v1alpha1.InstallPlanReasonInstallCheckFailed, err.Error()); err != nil { - // retry for failure to update status - syncError = err - return - } - } - // Retry sync if non-fatal error - syncError = fmt.Errorf("bundle unpacking failed: %v", err) - return - } - - if !reflect.DeepEqual(plan.Status, out.Status) { - logger.Warnf("status not equal, updating...") - if _, err := o.client.OperatorsV1alpha1().InstallPlans(out.GetNamespace()).UpdateStatus(context.TODO(), out, metav1.UpdateOptions{}); err != nil { - syncError = fmt.Errorf("failed to update installplan bundle lookups: %v", err) - } - - return - } - - // Check BundleLookup status conditions to see if the BundleLookupPending condtion is false - // which means bundle lookup has failed and the InstallPlan should be failed as well - isFailed, cond := hasBundleLookupFailureCondition(plan) - if isFailed { - err := fmt.Errorf("bundle unpacking failed. Reason: %v, and Message: %v", cond.Reason, cond.Message) - // Mark the InstallPlan as failed for a fatal bundle unpack error - logger.Infof("%v", err) - - if err := o.transitionInstallPlanToFailed(plan, logger, v1alpha1.InstallPlanReasonInstallCheckFailed, err.Error()); err != nil { - // retry for failure to update status - syncError = err - return - } - - // Requeue subscription to propagate SubscriptionInstallPlanFailed condtion to subscription - o.requeueSubscriptionForInstallPlan(plan, logger) - return - } - - // TODO: Remove in favor of job and configmap informer requeuing - if !unpacked { - err := o.ipQueueSet.RequeueAfter(plan.GetNamespace(), plan.GetName(), 5*time.Second) - if err != nil { - syncError = err - return - } - logger.Debug("install plan not yet populated from bundle image, requeueing") - - return - } - } - outInstallPlan, syncError := transitionInstallPlanState(logger.Logger, o, *plan, o.now(), o.installPlanTimeout) if syncError != nil { @@ -1731,10 +1755,10 @@ func (o *Operator) syncInstallPlans(obj interface{}) (syncError error) { return } -func hasBundleLookupFailureCondition(plan *v1alpha1.InstallPlan) (bool, *v1alpha1.BundleLookupCondition) { - for _, bundleLookup := range plan.Status.BundleLookups { +func hasBundleLookupFailureCondition(bundleLookups []v1alpha1.BundleLookup) (bool, *v1alpha1.BundleLookupCondition) { + for _, bundleLookup := range bundleLookups { for _, cond := range bundleLookup.Conditions { - if cond.Type == bundle.BundleLookupFailed && cond.Status == corev1.ConditionTrue { + if cond.Type == v1alpha1.BundleLookupFailed && cond.Status == corev1.ConditionTrue { return true, &cond } } @@ -1742,27 +1766,6 @@ func hasBundleLookupFailureCondition(plan *v1alpha1.InstallPlan) (bool, *v1alpha return false, nil } -func (o *Operator) transitionInstallPlanToFailed(plan *v1alpha1.InstallPlan, logger logrus.FieldLogger, reason v1alpha1.InstallPlanConditionReason, message string) error { - now := o.now() - out := plan.DeepCopy() - out.Status.SetCondition(v1alpha1.ConditionFailed(v1alpha1.InstallPlanInstalled, - reason, message, &now)) - out.Status.Phase = v1alpha1.InstallPlanPhaseFailed - - logger.Info("transitioning InstallPlan to failed") - _, err := o.client.OperatorsV1alpha1().InstallPlans(plan.GetNamespace()).UpdateStatus(context.TODO(), out, metav1.UpdateOptions{}) - if err == nil { - return nil - } - - updateErr := errors.New("error updating InstallPlan status: " + err.Error()) - logger = logger.WithField("updateError", updateErr) - logger.Errorf("error transitioning InstallPlan to failed") - - // retry sync with error to update InstallPlan status - return fmt.Errorf("installplan failed: %s and error updating InstallPlan status as failed: %s", message, updateErr) -} - func (o *Operator) requeueSubscriptionForInstallPlan(plan *v1alpha1.InstallPlan, logger *logrus.Entry) { // Notify subscription loop of installplan changes owners := ownerutil.GetOwnersByKind(plan, v1alpha1.SubscriptionKind) diff --git a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/operators/olm/operator.go b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/operators/olm/operator.go index 6964fe9917..18de7df998 100644 --- a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/operators/olm/operator.go +++ b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/operators/olm/operator.go @@ -1246,7 +1246,7 @@ func (a *Operator) removeDanglingChildCSVs(csv *v1alpha1.ClusterServiceVersion) func (a *Operator) deleteChild(csv *v1alpha1.ClusterServiceVersion, logger *logrus.Entry) error { logger.Debug("gcing csv") - return a.client.OperatorsV1alpha1().ClusterServiceVersions(csv.GetNamespace()).Delete(context.TODO(), csv.GetName(), *metav1.NewDeleteOptions(0)) + return a.client.OperatorsV1alpha1().ClusterServiceVersions(csv.GetNamespace()).Delete(context.TODO(), csv.GetName(), metav1.DeleteOptions{}) } // syncClusterServiceVersion is the method that gets called when we see a CSV event in the cluster @@ -2287,7 +2287,7 @@ func (a *Operator) transitionCSVState(in v1alpha1.ClusterServiceVersion) (out *v syncError = fmt.Errorf("marked as replacement, but no replacement CSV found in cluster") } case v1alpha1.CSVPhaseDeleting: - syncError = a.client.OperatorsV1alpha1().ClusterServiceVersions(out.GetNamespace()).Delete(context.TODO(), out.GetName(), *metav1.NewDeleteOptions(0)) + syncError = a.client.OperatorsV1alpha1().ClusterServiceVersions(out.GetNamespace()).Delete(context.TODO(), out.GetName(), metav1.DeleteOptions{}) if syncError != nil { logger.Debugf("unable to get delete csv marked for deletion: %s", syncError.Error()) } diff --git a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/operators/olm/overrides/inject/inject.go b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/operators/olm/overrides/inject/inject.go index 50432767c9..8d105fbfa5 100644 --- a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/operators/olm/overrides/inject/inject.go +++ b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/operators/olm/overrides/inject/inject.go @@ -235,10 +235,12 @@ func InjectNodeSelectorIntoDeployment(podSpec *corev1.PodSpec, nodeSelector map[ // with the given corev1.Affinity. Any nil top-level sub-attributes (e.g. NodeAffinity, PodAffinity, and PodAntiAffinity) // will be ignored. Hint: to overwrite those top-level attributes, empty them out. I.e. use the empty/default object ({}) // e.g. NodeAffinity{}. In yaml: -// affinity: -// nodeAffinity: {} -// podAffinity: {} -// podAntiAffinity: {} +// +// affinity: +// nodeAffinity: {} +// podAffinity: {} +// podAntiAffinity: {} +// // will completely remove the deployment podSpec.affinity and is equivalent to // affinity: {} func OverrideDeploymentAffinity(podSpec *corev1.PodSpec, affinity *corev1.Affinity) error { diff --git a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/reconciler/reconciler.go b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/reconciler/reconciler.go index ebcbd86849..dfb7b87049 100644 --- a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/reconciler/reconciler.go +++ b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/reconciler/reconciler.go @@ -214,6 +214,11 @@ func Pod(source *operatorsv1alpha1.CatalogSource, name string, img string, saNam pod.Spec.Tolerations[index] = *toleration.DeepCopy() } } + + // Override affinity + if grpcPodConfig.Affinity != nil { + pod.Spec.Affinity = grpcPodConfig.Affinity.DeepCopy() + } } // Set priorityclass if its annotation exists diff --git a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/fail_forward.go b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/fail_forward.go index ba522ba9c3..fe1575c647 100644 --- a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/fail_forward.go +++ b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/fail_forward.go @@ -17,8 +17,8 @@ import ( // backwards compatible. func IsFailForwardEnabled(ogLister v1listers.OperatorGroupNamespaceLister) (bool, error) { ogs, err := ogLister.List(labels.Everything()) - if err != nil || len(ogs) == 0 { - return false, nil + if err != nil { + return false, err } if len(ogs) != 1 { return false, fmt.Errorf("found %d operatorGroups, expected 1", len(ogs)) diff --git a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/catalogsource/catalogsource_update.go b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/catalogsource/catalogsource_update.go index c8a58caaea..821ed00b96 100644 --- a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/catalogsource/catalogsource_update.go +++ b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/catalogsource/catalogsource_update.go @@ -12,7 +12,8 @@ import ( "github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/clientset/versioned" ) -/* UpdateStatus can be used to update the status of the provided catalog source. Note that +/* +UpdateStatus can be used to update the status of the provided catalog source. Note that the caller is responsible for ensuring accurate status values in the catsrc argument (i.e. the status is used as-is). @@ -34,7 +35,8 @@ func UpdateStatus(logger *logrus.Entry, client versioned.Interface, catsrc *v1al return nil } -/* UpdateStatusWithConditions can be used to update the status conditions for the provided catalog source. +/* +UpdateStatusWithConditions can be used to update the status conditions for the provided catalog source. This function will make no changes to the other status fields (those fields will be used as-is). If the provided conditions do not result in any status condition changes, then the API server will not be updated. Note that the caller is responsible for ensuring accurate status values for all other fields. @@ -71,7 +73,8 @@ func UpdateStatusWithConditions(logger *logrus.Entry, client versioned.Interface return nil } -/* UpdateSpecAndStatusConditions can be used to update the catalog source with the provided status conditions. +/* +UpdateSpecAndStatusConditions can be used to update the catalog source with the provided status conditions. This will update the spec and status portions of the catalog source. Calls to the API server will occur even if the provided conditions result in no changes. @@ -98,7 +101,8 @@ func UpdateSpecAndStatusConditions(logger *logrus.Entry, client versioned.Interf return nil } -/* RemoveStatusConditions can be used to remove the status conditions for the provided catalog source. +/* +RemoveStatusConditions can be used to remove the status conditions for the provided catalog source. This function will make no changes to the other status fields (those fields will be used as-is). If the provided conditions do not result in any status condition changes, then the API server will not be updated. Note that the caller is responsible for ensuring accurate status values for all other fields. diff --git a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/controller-runtime/client/fake_ssa.go b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/controller-runtime/client/fake_ssa.go index a7e04cb873..3044cd6d9b 100644 --- a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/controller-runtime/client/fake_ssa.go +++ b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/controller-runtime/client/fake_ssa.go @@ -35,8 +35,7 @@ type fakeStatusWriter struct { k8scontrollerclient.StatusWriter } -func (c fakeStatusWriter) Patch(ctx context.Context, obj k8scontrollerclient.Object, patch k8scontrollerclient.Patch, opts ...k8scontrollerclient.PatchOption) error { - patch, opts = convertApplyToMergePatch(patch, opts...) +func (c fakeStatusWriter) Patch(ctx context.Context, obj k8scontrollerclient.Object, patch k8scontrollerclient.Patch, opts ...k8scontrollerclient.SubResourcePatchOption) error { return c.StatusWriter.Patch(ctx, obj, patch, opts...) } diff --git a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/controller-runtime/client/ssa.go b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/controller-runtime/client/ssa.go index b13f923b3d..74eb4784e2 100644 --- a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/controller-runtime/client/ssa.go +++ b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/controller-runtime/client/ssa.go @@ -87,13 +87,13 @@ type ServerSideApplier struct { // The underlying value of the given resource pointer is updated to reflect the latest cluster state each time the closure is successfully invoked. // Ex. Change the spec of an existing InstallPlan // -// plan := &InstallPlan{} -// plan.SetNamespace("ns") -// plan.SetName("install-123def") -// Eventually(c.Apply(plan, func(p *v1alpha1.InstallPlan) error { +// plan := &InstallPlan{} +// plan.SetNamespace("ns") +// plan.SetName("install-123def") +// Eventually(c.Apply(plan, func(p *v1alpha1.InstallPlan) error { // p.Spec.Approved = true // return nil -// })).Should(Succeed()) +// })).Should(Succeed()) func (c *ServerSideApplier) Apply(ctx context.Context, obj Object, changeFunc interface{}) func() error { // Ensure given object is a pointer objType := reflect.TypeOf(obj) @@ -182,7 +182,10 @@ func (c *ServerSideApplier) Apply(ctx context.Context, obj Object, changeFunc in return err } - if err := c.client.Status().Patch(ctx, cp, k8scontrollerclient.Apply, k8scontrollerclient.ForceOwnership, c.Owner); err != nil { + pos := &k8scontrollerclient.SubResourcePatchOptions{} + k8scontrollerclient.ForceOwnership.ApplyToPatch(&pos.PatchOptions) + + if err := c.client.Status().Patch(ctx, cp, k8scontrollerclient.Apply, pos, c.Owner); err != nil { fmt.Printf("second patch error: %s\n", err) return err } diff --git a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/filemonitor/cabundle_updater.go b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/filemonitor/cabundle_updater.go index 4fcee4e457..58f577ef45 100644 --- a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/filemonitor/cabundle_updater.go +++ b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/filemonitor/cabundle_updater.go @@ -2,7 +2,7 @@ package filemonitor import ( "crypto/x509" - "io/ioutil" + "os" "sync" "github.com/fsnotify/fsnotify" @@ -16,7 +16,7 @@ type certPoolStore struct { } func NewCertPoolStore(clientCAPath string) (*certPoolStore, error) { - pem, err := ioutil.ReadFile(clientCAPath) + pem, err := os.ReadFile(clientCAPath) if err != nil { return nil, err } @@ -31,7 +31,7 @@ func NewCertPoolStore(clientCAPath string) (*certPoolStore, error) { } func (c *certPoolStore) storeCABundle(clientCAPath string) error { - pem, err := ioutil.ReadFile(clientCAPath) + pem, err := os.ReadFile(clientCAPath) if err == nil { c.mutex.Lock() defer c.mutex.Unlock() diff --git a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac/v1/zz_generated.conversion.go b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac/v1/zz_generated.conversion.go index b3d5891bb7..04e9556e17 100644 --- a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac/v1/zz_generated.conversion.go +++ b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac/v1/zz_generated.conversion.go @@ -1,3 +1,4 @@ +//go:build !ignore_autogenerated // +build !ignore_autogenerated /* diff --git a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac/v1/zz_generated.deepcopy.go b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac/v1/zz_generated.deepcopy.go index 7bf8d13745..a4ff45d659 100644 --- a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac/v1/zz_generated.deepcopy.go +++ b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac/v1/zz_generated.deepcopy.go @@ -1,3 +1,4 @@ +//go:build !ignore_autogenerated // +build !ignore_autogenerated /* diff --git a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac/v1/zz_generated.defaults.go b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac/v1/zz_generated.defaults.go index f0d53c1721..ba7fdabd85 100644 --- a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac/v1/zz_generated.defaults.go +++ b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac/v1/zz_generated.defaults.go @@ -1,3 +1,4 @@ +//go:build !ignore_autogenerated // +build !ignore_autogenerated /* diff --git a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac/zz_generated.deepcopy.go b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac/zz_generated.deepcopy.go index 33518a9868..0f7023a2db 100644 --- a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac/zz_generated.deepcopy.go +++ b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/apis/rbac/zz_generated.deepcopy.go @@ -1,3 +1,4 @@ +//go:build !ignore_autogenerated // +build !ignore_autogenerated /* diff --git a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/printers/tablegenerator.go b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/printers/tablegenerator.go index add7c3896e..f96239dc0d 100644 --- a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/printers/tablegenerator.go +++ b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/printers/tablegenerator.go @@ -150,7 +150,9 @@ func (h *HumanReadableGenerator) TableHandler(columnDefinitions []metav1beta1.Ta // ValidateRowPrintHandlerFunc validates print handler signature. // printFunc is the function that will be called to print an object. // It must be of the following type: -// func printFunc(object ObjectType, options GenerateOptions) ([]metav1beta1.TableRow, error) +// +// func printFunc(object ObjectType, options GenerateOptions) ([]metav1beta1.TableRow, error) +// // where ObjectType is the type of the object that will be printed, and the first // return value is an array of rows, with each row containing a number of cells that // match the number of columns defined for that printer function. diff --git a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorlister/lister.go b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorlister/lister.go index 99e41817da..0bf77a89e4 100644 --- a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorlister/lister.go +++ b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorlister/lister.go @@ -28,6 +28,7 @@ import ( //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -o ./operatorlisterfakes/fake_clusterserviceversion_v1alpha1_namespace_lister.go ../../api/client/listers/operators/v1alpha1.ClusterServiceVersionNamespaceLister // OperatorLister is a union of versioned informer listers +// //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . OperatorLister type OperatorLister interface { AppsV1() AppsV1Lister diff --git a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorstatus/csv_handler.go b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorstatus/csv_handler.go index eb8c57ab20..bf2b9b51b7 100644 --- a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorstatus/csv_handler.go +++ b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorstatus/csv_handler.go @@ -86,8 +86,8 @@ type handler struct { // OnAddOrUpdate is invoked when a CSV has been added or edited. We tap into // this notification and do the following: // -// a. Make sure this is the CSV related to the cluster operator resource we are -// tracking. Otherwise, do nothing. +// a. Make sure this is the CSV related to the cluster operator resource we are tracking. Otherwise, do nothing. +// // b. If this is the right CSV then send it to the monitor. func (h *handler) OnAddOrUpdate(in *v1alpha1.ClusterServiceVersion) { h.onNotification(in, false) @@ -96,8 +96,8 @@ func (h *handler) OnAddOrUpdate(in *v1alpha1.ClusterServiceVersion) { // OnDelete is invoked when a CSV has been deleted. We tap into // this notification and do the following: // -// a. Make sure this is the CSV related to the cluster operator resource we are -// tracking. Otherwise, do nothing. +// a. Make sure this is the CSV related to the cluster operator resource we are tracking. Otherwise, do nothing. +// // b. If this is the right CSV then send it to the monitor. func (h *handler) OnDelete(in *v1alpha1.ClusterServiceVersion) { h.onNotification(in, true) diff --git a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/proxy/overridden.go b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/proxy/overridden.go index 8ad45f1a78..42eec7acd6 100644 --- a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/proxy/overridden.go +++ b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/proxy/overridden.go @@ -6,8 +6,9 @@ import ( // IsOverridden returns true if the given container overrides proxy env variable(s). // We apply the following rule: -// If a container already defines any of the proxy env variable then it -// overrides all of these. +// +// If a container already defines any of the proxy env variable then it +// overrides all of these. func IsOverridden(envVar []corev1.EnvVar) (overrides bool) { for _, envVarName := range allProxyEnvVarNames { _, found := find(envVar, envVarName) diff --git a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/package-server/client/openapi/zz_generated.openapi.go b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/package-server/client/openapi/zz_generated.openapi.go index e4fcd10386..2ef8406a65 100644 --- a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/package-server/client/openapi/zz_generated.openapi.go +++ b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/package-server/client/openapi/zz_generated.openapi.go @@ -141,28 +141,31 @@ func schema_api_pkg_operators_v1alpha1_APIResourceReference(ref common.Reference return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ - Description: "APIResourceReference is a Kubernetes resource type used by a custom resource", + Description: "APIResourceReference is a reference to a Kubernetes resource type that the referrer utilizes.", Type: []string{"object"}, Properties: map[string]spec.Schema{ "name": { SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", + Description: "Plural name of the referenced resource type (CustomResourceDefinition.Spec.Names[].Plural). Empty string if the referenced resource type is not a custom resource.", + Default: "", + Type: []string{"string"}, + Format: "", }, }, "kind": { SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", + Description: "Kind of the referenced resource type.", + Default: "", + Type: []string{"string"}, + Format: "", }, }, "version": { SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", + Description: "API Version of the referenced resource type.", + Default: "", + Type: []string{"string"}, + Format: "", }, }, }, @@ -679,20 +682,23 @@ func schema_api_pkg_operators_v1alpha1_ClusterServiceVersionSpec(ref common.Refe }, "displayName": { SchemaProps: spec.SchemaProps{ - Default: "", - Type: []string{"string"}, - Format: "", + Description: "The name of the operator in display format.", + Default: "", + Type: []string{"string"}, + Format: "", }, }, "description": { SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, - Format: "", + Description: "Description of the operator. Can include the features, limitations or use-cases of the operator.", + Type: []string{"string"}, + Format: "", }, }, "keywords": { SchemaProps: spec.SchemaProps{ - Type: []string{"array"}, + Description: "A list of keywords describing the operator.", + Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -706,7 +712,8 @@ func schema_api_pkg_operators_v1alpha1_ClusterServiceVersionSpec(ref common.Refe }, "maintainers": { SchemaProps: spec.SchemaProps{ - Type: []string{"array"}, + Description: "A list of organizational entities maintaining the operator.", + Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -719,13 +726,15 @@ func schema_api_pkg_operators_v1alpha1_ClusterServiceVersionSpec(ref common.Refe }, "provider": { SchemaProps: spec.SchemaProps{ - Default: map[string]interface{}{}, - Ref: ref("github.com/operator-framework/api/pkg/operators/v1alpha1.AppLink"), + Description: "The publishing entity behind the operator.", + Default: map[string]interface{}{}, + Ref: ref("github.com/operator-framework/api/pkg/operators/v1alpha1.AppLink"), }, }, "links": { SchemaProps: spec.SchemaProps{ - Type: []string{"array"}, + Description: "A list of links related to the operator.", + Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -738,7 +747,8 @@ func schema_api_pkg_operators_v1alpha1_ClusterServiceVersionSpec(ref common.Refe }, "icon": { SchemaProps: spec.SchemaProps{ - Type: []string{"array"}, + Description: "The icon for this operator.", + Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ diff --git a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/package-server/storage/subresources.go b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/package-server/storage/subresources.go index a851ee215a..24bc799e69 100644 --- a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/package-server/storage/subresources.go +++ b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/package-server/storage/subresources.go @@ -3,7 +3,7 @@ package storage import ( "context" "encoding/base64" - "io/ioutil" + "io" "net/http" "strconv" "strings" @@ -72,7 +72,7 @@ func (s *LogoStorage) Connect(ctx context.Context, name string, options runtime. etag := `"` + strings.Join([]string{name, pkgChannel.Name, pkgChannel.CurrentCSV}, ".") + `"` reader := base64.NewDecoder(base64.StdEncoding, strings.NewReader(data)) - imgBytes, _ := ioutil.ReadAll(reader) + imgBytes, _ := io.ReadAll(reader) return imgBytes, mimeType, etag } diff --git a/vendor/github.com/operator-framework/operator-lifecycle-manager/util/cpb/main.go b/vendor/github.com/operator-framework/operator-lifecycle-manager/util/cpb/main.go index ae9912bf97..5b1769bb37 100644 --- a/vendor/github.com/operator-framework/operator-lifecycle-manager/util/cpb/main.go +++ b/vendor/github.com/operator-framework/operator-lifecycle-manager/util/cpb/main.go @@ -2,7 +2,6 @@ package main import ( "fmt" - "io/ioutil" "os" "path/filepath" @@ -118,7 +117,7 @@ func getMetadata() (m *metadata, err error) { m.annotationsFile = path // Unmarshal metadata - content, err := ioutil.ReadFile(path) + content, err := os.ReadFile(path) if err != nil { return fmt.Errorf("couldn't get content of annotations.yaml file: %s", path) } diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/action/migrate.go b/vendor/github.com/operator-framework/operator-registry/alpha/action/migrate.go index 8cca8b8974..c5880f0006 100644 --- a/vendor/github.com/operator-framework/operator-registry/alpha/action/migrate.go +++ b/vendor/github.com/operator-framework/operator-registry/alpha/action/migrate.go @@ -1,13 +1,10 @@ package action import ( - "bytes" "context" "fmt" - "io" "io/ioutil" "os" - "path/filepath" "github.com/operator-framework/operator-registry/alpha/declcfg" "github.com/operator-framework/operator-registry/pkg/image" @@ -17,13 +14,11 @@ type Migrate struct { CatalogRef string OutputDir string - WriteFunc WriteFunc + WriteFunc declcfg.WriteFunc FileExt string Registry image.Registry } -type WriteFunc func(config declcfg.DeclarativeConfig, w io.Writer) error - func (m Migrate) Run(ctx context.Context) error { entries, err := ioutil.ReadDir(m.OutputDir) if err != nil && !os.IsNotExist(err) { @@ -52,48 +47,5 @@ func (m Migrate) Run(ctx context.Context) error { return fmt.Errorf("render catalog image: %w", err) } - return writeToFS(*cfg, m.OutputDir, m.WriteFunc, m.FileExt) -} - -func writeToFS(cfg declcfg.DeclarativeConfig, rootDir string, writeFunc WriteFunc, fileExt string) error { - channelsByPackage := map[string][]declcfg.Channel{} - for _, c := range cfg.Channels { - channelsByPackage[c.Package] = append(channelsByPackage[c.Package], c) - } - bundlesByPackage := map[string][]declcfg.Bundle{} - for _, b := range cfg.Bundles { - bundlesByPackage[b.Package] = append(bundlesByPackage[b.Package], b) - } - - if err := os.MkdirAll(rootDir, 0777); err != nil { - return err - } - - for _, p := range cfg.Packages { - fcfg := declcfg.DeclarativeConfig{ - Packages: []declcfg.Package{p}, - Channels: channelsByPackage[p.Name], - Bundles: bundlesByPackage[p.Name], - } - pkgDir := filepath.Join(rootDir, p.Name) - if err := os.MkdirAll(pkgDir, 0777); err != nil { - return err - } - filename := filepath.Join(pkgDir, fmt.Sprintf("catalog%s", fileExt)) - if err := writeFile(fcfg, filename, writeFunc); err != nil { - return err - } - } - return nil -} - -func writeFile(cfg declcfg.DeclarativeConfig, filename string, writeFunc WriteFunc) error { - buf := &bytes.Buffer{} - if err := writeFunc(cfg, buf); err != nil { - return fmt.Errorf("write to buffer for %q: %v", filename, err) - } - if err := ioutil.WriteFile(filename, buf.Bytes(), 0666); err != nil { - return fmt.Errorf("write file %q: %v", filename, err) - } - return nil + return declcfg.WriteFS(*cfg, m.OutputDir, m.WriteFunc, m.FileExt) } diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/action/render.go b/vendor/github.com/operator-framework/operator-registry/alpha/action/render.go index 3f38390a0e..b1e5bd7541 100644 --- a/vendor/github.com/operator-framework/operator-registry/alpha/action/render.go +++ b/vendor/github.com/operator-framework/operator-registry/alpha/action/render.go @@ -82,7 +82,7 @@ func (r Render) Run(ctx context.Context) (*declcfg.DeclarativeConfig, error) { if err != nil { return nil, fmt.Errorf("render reference %q: %w", ref, err) } - renderBundleObjects(cfg) + moveBundleObjectsToEndOfPropertySlices(cfg) for _, b := range cfg.Bundles { sort.Slice(b.RelatedImages, func(i, j int) bool { @@ -122,7 +122,7 @@ func (r Render) renderReference(ctx context.Context, ref string) (*declcfg.Decla if !r.AllowedRefMask.Allowed(RefDCDir) { return nil, fmt.Errorf("cannot render declarative config directory: %w", ErrNotAllowed) } - return declcfg.LoadFS(os.DirFS(ref)) + return declcfg.LoadFS(ctx, os.DirFS(ref)) } else { // The only supported file type is an sqlite DB file, // since declarative configs will be in a directory. @@ -169,7 +169,7 @@ func (r Render) imageToDeclcfg(ctx context.Context, imageRef string) (*declcfg.D if !r.AllowedRefMask.Allowed(RefDCImage) { return nil, fmt.Errorf("cannot render declarative config image: %w", ErrNotAllowed) } - cfg, err = declcfg.LoadFS(os.DirFS(filepath.Join(tmpDir, configsDir))) + cfg, err = declcfg.LoadFS(ctx, os.DirFS(filepath.Join(tmpDir, configsDir))) if err != nil { return nil, err } @@ -304,6 +304,7 @@ func bundleToDeclcfg(bundle *registry.Bundle) (*declcfg.DeclarativeConfig, error if err != nil { return nil, fmt.Errorf("get related images for bundle %q: %v", bundle.Name, err) } + var csvJson []byte for _, obj := range bundle.Objects { if obj.GetKind() == "ClusterServiceVersion" { @@ -376,19 +377,21 @@ func getRelatedImages(b *registry.Bundle) ([]declcfg.RelatedImage, error) { return relatedImages, nil } -func renderBundleObjects(cfg *declcfg.DeclarativeConfig) { +func moveBundleObjectsToEndOfPropertySlices(cfg *declcfg.DeclarativeConfig) { for bi, b := range cfg.Bundles { - props := b.Properties[:0] + var ( + others []property.Property + objs []property.Property + ) for _, p := range b.Properties { - if p.Type != property.TypeBundleObject { - props = append(props, p) + switch p.Type { + case property.TypeBundleObject, property.TypeCSVMetadata: + objs = append(objs, p) + default: + others = append(others, p) } } - - for _, obj := range b.Objects { - props = append(props, property.MustBuildBundleObjectData([]byte(obj))) - } - cfg.Bundles[bi].Properties = props + cfg.Bundles[bi].Properties = append(others, objs...) } } diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/declcfg/declcfg.go b/vendor/github.com/operator-framework/operator-registry/alpha/declcfg/declcfg.go index a4169c28c5..994d47a0b7 100644 --- a/vendor/github.com/operator-framework/operator-registry/alpha/declcfg/declcfg.go +++ b/vendor/github.com/operator-framework/operator-registry/alpha/declcfg/declcfg.go @@ -1,7 +1,14 @@ package declcfg import ( + "bytes" "encoding/json" + "errors" + "fmt" + + "golang.org/x/text/cases" + utilerrors "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/apimachinery/pkg/util/sets" "github.com/operator-framework/operator-registry/alpha/property" ) @@ -52,11 +59,11 @@ type ChannelEntry struct { // Top-level fields are the source of truth, i.e. not CSV values. // // Notes: -// - Any field slice type field or type containing a slice somewhere -// where two types/fields are equal if their contents are equal regardless -// of order must have a `hash:"set"` field tag for bundle comparison. -// - Any fields that have a `json:"-"` tag must be included in the equality -// evaluation in bundlesEqual(). +// - Any field slice type field or type containing a slice somewhere +// where two types/fields are equal if their contents are equal regardless +// of order must have a `hash:"set"` field tag for bundle comparison. +// - Any fields that have a `json:"-"` tag must be included in the equality +// evaluation in bundlesEqual(). type Bundle struct { Schema string `json:"schema"` Name string `json:"name"` @@ -84,6 +91,7 @@ type RelatedImage struct { type Meta struct { Schema string Package string + Name string Blob json.RawMessage } @@ -93,17 +101,81 @@ func (m Meta) MarshalJSON() ([]byte, error) { } func (m *Meta) UnmarshalJSON(blob []byte) error { - type tmp struct { - Schema string `json:"schema"` - Package string `json:"package,omitempty"` - Properties []property.Property `json:"properties,omitempty"` + blobMap := map[string]interface{}{} + if err := json.Unmarshal(blob, &blobMap); err != nil { + // TODO: unfortunately, there are libraries between here and the original caller + // that eat our error type and return a generic error, such that we lose the + // ability to errors.As to get this error on the other side. For now, just return + // a string error that includes the pretty printed message. + return errors.New(newJSONUnmarshalError(blob, err).Pretty()) } - var t tmp - if err := json.Unmarshal(blob, &t); err != nil { + + // TODO: this function ensures we do not break backwards compatibility with + // the documented examples of FBC templates, which use upper camel case + // for JSON field names. We need to decide if we want to continue supporting + // case insensitive JSON field names, or if we want to enforce a specific + // case-sensitive key value for each field. + if err := extractUniqueMetaKeys(blobMap, m); err != nil { + return err + } + + buf := bytes.Buffer{} + enc := json.NewEncoder(&buf) + enc.SetEscapeHTML(false) + if err := enc.Encode(blobMap); err != nil { return err } - m.Schema = t.Schema - m.Package = t.Package - m.Blob = blob + m.Blob = buf.Bytes() + return nil +} + +// extractUniqueMetaKeys enables a case-insensitive key lookup for the schema, package, and name +// fields of the Meta struct. If the blobMap contains duplicate keys (that is, keys have the same folded value), +// an error is returned. +func extractUniqueMetaKeys(blobMap map[string]any, m *Meta) error { + keySets := map[string]sets.Set[string]{} + folder := cases.Fold() + for key := range blobMap { + foldKey := folder.String(key) + if _, ok := keySets[foldKey]; !ok { + keySets[foldKey] = sets.New[string]() + } + keySets[foldKey].Insert(key) + } + + dupErrs := []error{} + for foldedKey, keys := range keySets { + if len(keys) != 1 { + dupErrs = append(dupErrs, fmt.Errorf("duplicate keys for key %q: %v", foldedKey, sets.List(keys))) + } + } + if len(dupErrs) > 0 { + return utilerrors.NewAggregate(dupErrs) + } + + metaMap := map[string]*string{ + folder.String("schema"): &m.Schema, + folder.String("package"): &m.Package, + folder.String("name"): &m.Name, + } + + for foldedKey, ptr := range metaMap { + // if the folded key doesn't exist in the key set derived from the blobMap, that means + // the key doesn't exist in the blobMap, so we can skip it + if _, ok := keySets[foldedKey]; !ok { + continue + } + + // reset key to the unfolded key, which we know is the one that appears in the blobMap + key := keySets[foldedKey].UnsortedList()[0] + if _, ok := blobMap[key]; !ok { + continue + } + v, ok := blobMap[key].(string) + if !ok { + return fmt.Errorf("expected value for key %q to be a string, got %t: %v", key, blobMap[key], blobMap[key]) + } + *ptr = v + } return nil } diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/declcfg/errors.go b/vendor/github.com/operator-framework/operator-registry/alpha/declcfg/errors.go new file mode 100644 index 0000000000..f5ef115233 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/alpha/declcfg/errors.go @@ -0,0 +1,93 @@ +package declcfg + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "strings" +) + +type jsonUnmarshalError struct { + data []byte + offset int64 + err error +} + +func newJSONUnmarshalError(data []byte, err error) *jsonUnmarshalError { + var te *json.UnmarshalTypeError + if errors.As(err, &te) { + return &jsonUnmarshalError{data: data, offset: te.Offset, err: te} + } + var se *json.SyntaxError + if errors.As(err, &se) { + return &jsonUnmarshalError{data: data, offset: se.Offset, err: se} + } + return &jsonUnmarshalError{data: data, offset: -1, err: err} +} + +func (e *jsonUnmarshalError) Error() string { + return e.err.Error() +} + +func (e *jsonUnmarshalError) Pretty() string { + if len(e.data) == 0 || e.offset < 0 || e.offset > int64(len(e.data)) { + return e.err.Error() + } + + const marker = " <==" + + var sb strings.Builder + _, _ = sb.WriteString(fmt.Sprintf("%s at offset %d (indicated by%s)\n", e.err.Error(), e.offset, marker)) + + prettyBuf := bytes.NewBuffer(make([]byte, 0, len(e.data))) + err := json.Indent(prettyBuf, e.data, "", " ") + + // If there was an error indenting the JSON, just treat the original data as the pretty data. + if err != nil { + prettyBuf = bytes.NewBuffer(e.data) + } + + // If the offset is at the end of the data, just print the pretty data and the marker at the end. + if int(e.offset) == len(e.data) { + _, _ = sb.WriteString(prettyBuf.String()) + _, _ = sb.WriteString(marker) + return sb.String() + } + + // If the offset is within the data, find the corresponding offset in the pretty data. + var ( + pIndex int + pOffset int + ) + pretty := prettyBuf.Bytes() + for dIndex, b := range e.data { + // If we've reached the offset, record it and break out of the loop + if dIndex == int(e.offset) { + pOffset = pIndex + break + } + + // Fast-forward the pretty index until we find the byte in the pretty data + // that matches the byte in the original data. + for pretty[pIndex] != b { + pIndex++ + if pIndex >= len(pretty) { + // Something went wrong. For example, if the pretty data somehow reordered + // the bytes or is missing a byte + return e.err.Error() + } + } + + // We found the byte in the pretty data that matches the byte in the original data, + // so increment the pretty index. + pIndex++ + + } + + _, _ = sb.Write(pretty[:pOffset]) + _, _ = sb.WriteString(fmt.Sprintf("%s ", marker)) + _, _ = sb.Write(pretty[pOffset:]) + + return sb.String() +} diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/declcfg/load.go b/vendor/github.com/operator-framework/operator-registry/alpha/declcfg/load.go index 98b25da02a..43864f7921 100644 --- a/vendor/github.com/operator-framework/operator-registry/alpha/declcfg/load.go +++ b/vendor/github.com/operator-framework/operator-registry/alpha/declcfg/load.go @@ -1,17 +1,19 @@ package declcfg import ( - "bytes" + "context" "encoding/json" "errors" "fmt" "io" "io/fs" "path/filepath" - "strings" + "runtime" + "sync" "github.com/joelanford/ignore" "github.com/operator-framework/api/pkg/operators" + "golang.org/x/sync/errgroup" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/util/yaml" @@ -22,6 +24,46 @@ const ( indexIgnoreFilename = ".indexignore" ) +type WalkMetasFSFunc func(path string, meta *Meta, err error) error + +func WalkMetasFS(root fs.FS, walkFn WalkMetasFSFunc) error { + return walkFiles(root, func(root fs.FS, path string, err error) error { + if err != nil { + return walkFn(path, nil, err) + } + + f, err := root.Open(path) + if err != nil { + return walkFn(path, nil, err) + } + defer f.Close() + + return WalkMetasReader(f, func(meta *Meta, err error) error { + return walkFn(path, meta, err) + }) + }) +} + +type WalkMetasReaderFunc func(meta *Meta, err error) error + +func WalkMetasReader(r io.Reader, walkFn WalkMetasReaderFunc) error { + dec := yaml.NewYAMLOrJSONDecoder(r, 4096) + for { + var in Meta + if err := dec.Decode(&in); err != nil { + if errors.Is(err, io.EOF) { + break + } + return walkFn(nil, err) + } + + if err := walkFn(&in, nil); err != nil { + return err + } + } + return nil +} + type WalkFunc func(path string, cfg *DeclarativeConfig, err error) error // WalkFS walks root using a gitignore-style filename matcher to skip files @@ -29,6 +71,21 @@ type WalkFunc func(path string, cfg *DeclarativeConfig, err error) error // It calls walkFn for each declarative config file it finds. If WalkFS encounters // an error loading or parsing any file, the error will be immediately returned. func WalkFS(root fs.FS, walkFn WalkFunc) error { + return walkFiles(root, func(root fs.FS, path string, err error) error { + if err != nil { + return walkFn(path, nil, err) + } + + cfg, err := LoadFile(root, path) + if err != nil { + return walkFn(path, cfg, err) + } + + return walkFn(path, cfg, nil) + }) +} + +func walkFiles(root fs.FS, fn func(root fs.FS, path string, err error) error) error { if root == nil { return fmt.Errorf("no declarative config filesystem provided") } @@ -40,7 +97,7 @@ func WalkFS(root fs.FS, walkFn WalkFunc) error { return fs.WalkDir(root, ".", func(path string, info fs.DirEntry, err error) error { if err != nil { - return walkFn(path, nil, err) + return fn(root, path, err) } // avoid validating a directory, an .indexignore file, or any file that matches // an ignore pattern outlined in a .indexignore file. @@ -48,35 +105,136 @@ func WalkFS(root fs.FS, walkFn WalkFunc) error { return nil } - cfg, err := LoadFile(root, path) - if err != nil { - return walkFn(path, cfg, err) - } - - return walkFn(path, cfg, err) + return fn(root, path, nil) }) } +type LoadOptions struct { + concurrency int +} + +type LoadOption func(*LoadOptions) + +func WithConcurrency(concurrency int) LoadOption { + return func(opts *LoadOptions) { + opts.concurrency = concurrency + } +} + // LoadFS loads a declarative config from the provided root FS. LoadFS walks the // filesystem from root and uses a gitignore-style filename matcher to skip files // that match patterns found in .indexignore files found throughout the filesystem. // If LoadFS encounters an error loading or parsing any file, the error will be // immediately returned. -func LoadFS(root fs.FS) (*DeclarativeConfig, error) { - cfg := &DeclarativeConfig{} - if err := WalkFS(root, func(path string, fcfg *DeclarativeConfig, err error) error { +func LoadFS(ctx context.Context, root fs.FS, opts ...LoadOption) (*DeclarativeConfig, error) { + if root == nil { + return nil, fmt.Errorf("no declarative config filesystem provided") + } + + options := LoadOptions{ + concurrency: runtime.NumCPU(), + } + for _, opt := range opts { + opt(&options) + } + + var ( + fcfg = &DeclarativeConfig{} + pathChan = make(chan string, options.concurrency) + cfgChan = make(chan *DeclarativeConfig, options.concurrency) + ) + + // Create an errgroup to manage goroutines. The context is closed when any + // goroutine returns an error. Goroutines should check the context + // to see if they should return early (in the case of another goroutine + // returning an error). + eg, ctx := errgroup.WithContext(ctx) + + // Walk the FS and send paths to a channel for parsing. + eg.Go(func() error { + return sendPaths(ctx, root, pathChan) + }) + + // Parse paths concurrently. The waitgroup ensures that all paths are parsed + // before the cfgChan is closed. + var wg sync.WaitGroup + for i := 0; i < options.concurrency; i++ { + wg.Add(1) + eg.Go(func() error { + defer wg.Done() + return parsePaths(ctx, root, pathChan, cfgChan) + }) + } + + // Merge parsed configs into a single config. + eg.Go(func() error { + return mergeCfgs(ctx, cfgChan, fcfg) + }) + + // Wait for all path parsing goroutines to finish before closing cfgChan. + wg.Wait() + close(cfgChan) + + // Wait for all goroutines to finish. + if err := eg.Wait(); err != nil { + return nil, err + } + return fcfg, nil +} + +func sendPaths(ctx context.Context, root fs.FS, pathChan chan<- string) error { + defer close(pathChan) + return walkFiles(root, func(_ fs.FS, path string, err error) error { if err != nil { return err } - cfg.Packages = append(cfg.Packages, fcfg.Packages...) - cfg.Channels = append(cfg.Channels, fcfg.Channels...) - cfg.Bundles = append(cfg.Bundles, fcfg.Bundles...) - cfg.Others = append(cfg.Others, fcfg.Others...) + select { + case pathChan <- path: + case <-ctx.Done(): // don't block on sending to pathChan + return ctx.Err() + } return nil - }); err != nil { - return nil, err + }) +} + +func parsePaths(ctx context.Context, root fs.FS, pathChan <-chan string, cfgChan chan<- *DeclarativeConfig) error { + for { + select { + case <-ctx.Done(): // don't block on receiving from pathChan + return ctx.Err() + case path, ok := <-pathChan: + if !ok { + return nil + } + cfg, err := LoadFile(root, path) + if err != nil { + return err + } + select { + case cfgChan <- cfg: + case <-ctx.Done(): // don't block on sending to cfgChan + return ctx.Err() + } + } + } +} + +func mergeCfgs(ctx context.Context, cfgChan <-chan *DeclarativeConfig, fcfg *DeclarativeConfig) error { + for { + select { + case <-ctx.Done(): // don't block on receiving from cfgChan + return ctx.Err() + case cfg, ok := <-cfgChan: + if !ok { + return nil + } + fcfg.Packages = append(fcfg.Packages, cfg.Packages...) + fcfg.Channels = append(fcfg.Channels, cfg.Channels...) + fcfg.Bundles = append(fcfg.Bundles, cfg.Bundles...) + fcfg.Others = append(fcfg.Others, cfg.Others...) + } + } - return cfg, nil } func readBundleObjects(bundles []Bundle, root fs.FS, path string) error { @@ -123,46 +281,38 @@ func extractCSV(objs []string) string { // Path references will not be de-referenced so callers are responsible for de-referencing if necessary. func LoadReader(r io.Reader) (*DeclarativeConfig, error) { cfg := &DeclarativeConfig{} - dec := yaml.NewYAMLOrJSONDecoder(r, 4096) - for { - doc := json.RawMessage{} - if err := dec.Decode(&doc); err != nil { - if errors.Is(err, io.EOF) { - break - } - return nil, err - } - doc = []byte(strings.NewReplacer(`\u003c`, "<", `\u003e`, ">", `\u0026`, "&").Replace(string(doc))) - var in Meta - if err := json.Unmarshal(doc, &in); err != nil { - return nil, fmt.Errorf("unmarshal error: %s", resolveUnmarshalErr(doc, err)) + if err := WalkMetasReader(r, func(in *Meta, err error) error { + if err != nil { + return err } - switch in.Schema { case SchemaPackage: var p Package - if err := json.Unmarshal(doc, &p); err != nil { - return nil, fmt.Errorf("parse package: %v", err) + if err := json.Unmarshal(in.Blob, &p); err != nil { + return fmt.Errorf("parse package: %v", err) } cfg.Packages = append(cfg.Packages, p) case SchemaChannel: var c Channel - if err := json.Unmarshal(doc, &c); err != nil { - return nil, fmt.Errorf("parse channel: %v", err) + if err := json.Unmarshal(in.Blob, &c); err != nil { + return fmt.Errorf("parse channel: %v", err) } cfg.Channels = append(cfg.Channels, c) case SchemaBundle: var b Bundle - if err := json.Unmarshal(doc, &b); err != nil { - return nil, fmt.Errorf("parse bundle: %v", err) + if err := json.Unmarshal(in.Blob, &b); err != nil { + return fmt.Errorf("parse bundle: %v", err) } cfg.Bundles = append(cfg.Bundles, b) case "": - return nil, fmt.Errorf("object '%s' is missing root schema field", string(doc)) + return fmt.Errorf("object '%s' is missing root schema field", string(in.Blob)) default: - cfg.Others = append(cfg.Others, in) + cfg.Others = append(cfg.Others, *in) } + return nil + }); err != nil { + return nil, err } return cfg, nil } @@ -187,47 +337,3 @@ func LoadFile(root fs.FS, path string) (*DeclarativeConfig, error) { return cfg, nil } - -func resolveUnmarshalErr(data []byte, err error) string { - var te *json.UnmarshalTypeError - if errors.As(err, &te) { - return formatUnmarshallErrorString(data, te.Error(), te.Offset) - } - var se *json.SyntaxError - if errors.As(err, &se) { - return formatUnmarshallErrorString(data, se.Error(), se.Offset) - } - return err.Error() -} - -func formatUnmarshallErrorString(data []byte, errmsg string, offset int64) string { - sb := new(strings.Builder) - _, _ = sb.WriteString(fmt.Sprintf("%s at offset %d (indicated by <==)\n ", errmsg, offset)) - // attempt to present the erroneous JSON in indented, human-readable format - // errors result in presenting the original, unformatted output - var pretty bytes.Buffer - err := json.Indent(&pretty, data, "", " ") - if err == nil { - pString := pretty.String() - // calc the prettified string offset which correlates to the original string offset - var pOffset, origOffset int64 - origOffset = 0 - for origOffset = 0; origOffset < offset; { - pOffset++ - if pString[pOffset] != '\n' && pString[pOffset] != ' ' { - origOffset++ - } - } - _, _ = sb.WriteString(pString[:pOffset]) - _, _ = sb.WriteString(" <== ") - _, _ = sb.WriteString(pString[pOffset:]) - } else { - for i := int64(0); i < offset; i++ { - _ = sb.WriteByte(data[i]) - } - _, _ = sb.WriteString(" <== ") - _, _ = sb.Write(data[offset:]) - } - - return sb.String() -} diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/declcfg/write.go b/vendor/github.com/operator-framework/operator-registry/alpha/declcfg/write.go index 96e132bc29..2f149e5afd 100644 --- a/vendor/github.com/operator-framework/operator-registry/alpha/declcfg/write.go +++ b/vendor/github.com/operator-framework/operator-registry/alpha/declcfg/write.go @@ -6,13 +6,15 @@ import ( "fmt" "io" "os" + "path/filepath" "sort" "strings" "github.com/blang/semver/v4" - "github.com/operator-framework/operator-registry/alpha/property" "k8s.io/apimachinery/pkg/util/sets" "sigs.k8s.io/yaml" + + "github.com/operator-framework/operator-registry/alpha/property" ) type MermaidWriter struct { @@ -124,12 +126,12 @@ func (writer *MermaidWriter) WriteChannels(cfg DeclarativeConfig, out io.Writer) if len(ce.Replaces) > 0 { replacesId := fmt.Sprintf("%s-%s", channelID, ce.Replaces) - pkgBuilder.WriteString(fmt.Sprintf(" %s[%q]-- %s --> %s[%q]\n", entryId, ce.Name, "replaces", replacesId, ce.Replaces)) + pkgBuilder.WriteString(fmt.Sprintf(" %s[%q]-- %s --> %s[%q]\n", replacesId, ce.Replaces, "replace", entryId, ce.Name)) } if len(ce.Skips) > 0 { for _, s := range ce.Skips { skipsId := fmt.Sprintf("%s-%s", channelID, s) - pkgBuilder.WriteString(fmt.Sprintf(" %s[%q]-- %s --> %s[%q]\n", entryId, ce.Name, "skips", skipsId, s)) + pkgBuilder.WriteString(fmt.Sprintf(" %s[%q]-- %s --> %s[%q]\n", skipsId, s, "skip", entryId, ce.Name)) } } if len(ce.SkipRange) > 0 { @@ -138,7 +140,7 @@ func (writer *MermaidWriter) WriteChannels(cfg DeclarativeConfig, out io.Writer) for _, edgeName := range filteredChannel.Entries { if skipRange(versionMap[edgeName.Name]) { skipRangeId := fmt.Sprintf("%s-%s", channelID, edgeName.Name) - pkgBuilder.WriteString(fmt.Sprintf(" %s[%q]-- \"%s(%s)\" --> %s[%q]\n", entryId, ce.Name, "skipRange", ce.SkipRange, skipRangeId, edgeName.Name)) + pkgBuilder.WriteString(fmt.Sprintf(" %s[%q]-- \"%s(%s)\" --> %s[%q]\n", skipRangeId, edgeName.Name, "skipRange", ce.SkipRange, entryId, ce.Name)) } } } else { @@ -425,3 +427,48 @@ func writeToEncoder(cfg DeclarativeConfig, enc encoder) error { } return nil } + +type WriteFunc func(config DeclarativeConfig, w io.Writer) error + +func WriteFS(cfg DeclarativeConfig, rootDir string, writeFunc WriteFunc, fileExt string) error { + channelsByPackage := map[string][]Channel{} + for _, c := range cfg.Channels { + channelsByPackage[c.Package] = append(channelsByPackage[c.Package], c) + } + bundlesByPackage := map[string][]Bundle{} + for _, b := range cfg.Bundles { + bundlesByPackage[b.Package] = append(bundlesByPackage[b.Package], b) + } + + if err := os.MkdirAll(rootDir, 0777); err != nil { + return err + } + + for _, p := range cfg.Packages { + fcfg := DeclarativeConfig{ + Packages: []Package{p}, + Channels: channelsByPackage[p.Name], + Bundles: bundlesByPackage[p.Name], + } + pkgDir := filepath.Join(rootDir, p.Name) + if err := os.MkdirAll(pkgDir, 0777); err != nil { + return err + } + filename := filepath.Join(pkgDir, fmt.Sprintf("catalog%s", fileExt)) + if err := writeFile(fcfg, filename, writeFunc); err != nil { + return err + } + } + return nil +} + +func writeFile(cfg DeclarativeConfig, filename string, writeFunc WriteFunc) error { + buf := &bytes.Buffer{} + if err := writeFunc(cfg, buf); err != nil { + return fmt.Errorf("write to buffer for %q: %v", filename, err) + } + if err := os.WriteFile(filename, buf.Bytes(), 0666); err != nil { + return fmt.Errorf("write file %q: %v", filename, err) + } + return nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/model/model.go b/vendor/github.com/operator-framework/operator-registry/alpha/model/model.go index a6ca060420..48861e49cd 100644 --- a/vendor/github.com/operator-framework/operator-registry/alpha/model/model.go +++ b/vendor/github.com/operator-framework/operator-registry/alpha/model/model.go @@ -141,8 +141,9 @@ type Channel struct { } // TODO(joelanford): This function determines the channel head by finding the bundle that has 0 -// incoming edges, based on replaces and skips. It also expects to find exactly one such bundle. -// Is this the correct algorithm? +// +// incoming edges, based on replaces and skips. It also expects to find exactly one such bundle. +// Is this the correct algorithm? func (c Channel) Head() (*Bundle, error) { incoming := map[string]int{} for _, b := range c.Bundles { @@ -210,11 +211,11 @@ func (c *Channel) Validate() error { // validateReplacesChain checks the replaces chain of a channel. // Specifically the following rules must be followed: -// 1. There must be exactly 1 channel head. -// 2. Beginning at the head, the replaces chain must reach all non-skipped entries. -// Non-skipped entries are defined as entries that are not skipped by any other entry in the channel. -// 3. There must be no cycles in the replaces chain. -// 4. The tail entry in the replaces chain is permitted to replace a non-existent entry. +// 1. There must be exactly 1 channel head. +// 2. Beginning at the head, the replaces chain must reach all non-skipped entries. +// Non-skipped entries are defined as entries that are not skipped by any other entry in the channel. +// 3. There must be no cycles in the replaces chain. +// 4. The tail entry in the replaces chain is permitted to replace a non-existent entry. func (c *Channel) validateReplacesChain() error { head, err := c.Head() if err != nil { diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/property/property.go b/vendor/github.com/operator-framework/operator-registry/alpha/property/property.go index 695bfd6da8..5cb876846b 100644 --- a/vendor/github.com/operator-framework/operator-registry/alpha/property/property.go +++ b/vendor/github.com/operator-framework/operator-registry/alpha/property/property.go @@ -9,6 +9,9 @@ import ( "io/ioutil" "path/filepath" "reflect" + + "github.com/operator-framework/api/pkg/operators/v1alpha1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) type Property struct { @@ -40,8 +43,9 @@ type Package struct { } // NOTICE: The Channel properties are for internal use only. -// DO NOT use it for any public-facing functionalities. -// This API is in alpha stage and it is subject to change. +// +// DO NOT use it for any public-facing functionalities. +// This API is in alpha stage and it is subject to change. type Channel struct { ChannelName string `json:"channelName"` //Priority string `json:"priority"` @@ -69,6 +73,23 @@ type BundleObject struct { File `json:",inline"` } +type CSVMetadata struct { + Annotations map[string]string `json:"annotations,omitempty"` + APIServiceDefinitions v1alpha1.APIServiceDefinitions `json:"apiServiceDefinitions,omitempty"` + CustomResourceDefinitions v1alpha1.CustomResourceDefinitions `json:"crdDescriptions,omitempty"` + Description string `json:"description,omitempty"` + DisplayName string `json:"displayName,omitempty"` + InstallModes []v1alpha1.InstallMode `json:"installModes,omitempty"` + Keywords []string `json:"keywords,omitempty"` + Labels map[string]string `json:"labels,omitempty"` + Links []v1alpha1.AppLink `json:"links,omitempty"` + Maintainers []v1alpha1.Maintainer `json:"maintainers,omitempty"` + Maturity string `json:"maturity,omitempty"` + MinKubeVersion string `json:"minKubeVersion,omitempty"` + NativeAPIs []metav1.GroupVersionKind `json:"nativeAPIs,omitempty"` + Provider v1alpha1.AppLink `json:"provider,omitempty"` +} + type File struct { ref string data []byte @@ -128,6 +149,7 @@ type Properties struct { GVKsRequired []GVKRequired `hash:"set"` BundleObjects []BundleObject `hash:"set"` Channels []Channel `hash:"set"` + CSVMetadatas []CSVMetadata `hash:"set"` Others []Property `hash:"set"` } @@ -138,6 +160,7 @@ const ( TypeGVK = "olm.gvk" TypeGVKRequired = "olm.gvk.required" TypeBundleObject = "olm.bundle.object" + TypeCSVMetadata = "olm.csv.metadata" TypeChannel = "olm.channel" ) @@ -175,6 +198,12 @@ func Parse(in []Property) (*Properties, error) { return nil, ParseError{Idx: i, Typ: prop.Type, Err: err} } out.BundleObjects = append(out.BundleObjects, p) + case TypeCSVMetadata: + var p CSVMetadata + if err := json.Unmarshal(prop.Value, &p); err != nil { + return nil, ParseError{Idx: i, Typ: prop.Type, Err: err} + } + out.CSVMetadatas = append(out.CSVMetadatas, p) // NOTICE: The Channel properties are for internal use only. // DO NOT use it for any public-facing functionalities. // This API is in alpha stage and it is subject to change. @@ -286,9 +315,29 @@ func MustBuildBundleObjectData(data []byte) Property { return MustBuild(&BundleObject{File: File{data: data}}) } +func MustBuildCSVMetadata(csv v1alpha1.ClusterServiceVersion) Property { + return MustBuild(&CSVMetadata{ + Annotations: csv.GetAnnotations(), + APIServiceDefinitions: csv.Spec.APIServiceDefinitions, + CustomResourceDefinitions: csv.Spec.CustomResourceDefinitions, + Description: csv.Spec.Description, + DisplayName: csv.Spec.DisplayName, + InstallModes: csv.Spec.InstallModes, + Keywords: csv.Spec.Keywords, + Labels: csv.GetLabels(), + Links: csv.Spec.Links, + Maintainers: csv.Spec.Maintainers, + Maturity: csv.Spec.Maturity, + MinKubeVersion: csv.Spec.MinKubeVersion, + NativeAPIs: csv.Spec.NativeAPIs, + Provider: csv.Spec.Provider, + }) +} + // NOTICE: The Channel properties are for internal use only. -// DO NOT use it for any public-facing functionalities. -// This API is in alpha stage and it is subject to change. +// +// DO NOT use it for any public-facing functionalities. +// This API is in alpha stage and it is subject to change. func MustBuildChannelPriority(name string, priority int) Property { return MustBuild(&Channel{ChannelName: name, Priority: priority}) } diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/property/scheme.go b/vendor/github.com/operator-framework/operator-registry/alpha/property/scheme.go index 28d8a5d147..ab176856fa 100644 --- a/vendor/github.com/operator-framework/operator-registry/alpha/property/scheme.go +++ b/vendor/github.com/operator-framework/operator-registry/alpha/property/scheme.go @@ -12,6 +12,7 @@ func init() { reflect.TypeOf(&GVK{}): TypeGVK, reflect.TypeOf(&GVKRequired{}): TypeGVKRequired, reflect.TypeOf(&BundleObject{}): TypeBundleObject, + reflect.TypeOf(&CSVMetadata{}): TypeCSVMetadata, // NOTICE: The Channel properties are for internal use only. // DO NOT use it for any public-facing functionalities. // This API is in alpha stage and it is subject to change. diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/template/composite/builder.go b/vendor/github.com/operator-framework/operator-registry/alpha/template/composite/builder.go index 3d1f7af95d..953868f3e7 100644 --- a/vendor/github.com/operator-framework/operator-registry/alpha/template/composite/builder.go +++ b/vendor/github.com/operator-framework/operator-registry/alpha/template/composite/builder.go @@ -27,21 +27,14 @@ const ( CustomBuilderSchema = "olm.builder.custom" ) -type ContainerConfig struct { - ContainerTool string - BaseImage string - WorkingDir string -} - type BuilderConfig struct { - ContainerCfg ContainerConfig - OutputType string - InputDirectory string + WorkingDir string + OutputType string } type Builder interface { Build(ctx context.Context, reg image.Registry, dir string, td TemplateDefinition) error - Validate(dir string) error + Validate(ctx context.Context, dir string) error } type BasicBuilder struct { @@ -96,13 +89,13 @@ func (bb *BasicBuilder) Build(ctx context.Context, reg image.Registry, dir strin return fmt.Errorf("error rendering basic template: %v", err) } - destPath := path.Join(bb.builderCfg.ContainerCfg.WorkingDir, dir, basicConfig.Output) + destPath := path.Join(bb.builderCfg.WorkingDir, dir, basicConfig.Output) return build(dcfg, destPath, bb.builderCfg.OutputType) } -func (bb *BasicBuilder) Validate(dir string) error { - return validate(bb.builderCfg.ContainerCfg, dir) +func (bb *BasicBuilder) Validate(ctx context.Context, dir string) error { + return validate(ctx, bb.builderCfg, dir) } type SemverBuilder struct { @@ -158,13 +151,13 @@ func (sb *SemverBuilder) Build(ctx context.Context, reg image.Registry, dir stri return fmt.Errorf("error rendering semver template: %v", err) } - destPath := path.Join(sb.builderCfg.ContainerCfg.WorkingDir, dir, semverConfig.Output) + destPath := path.Join(sb.builderCfg.WorkingDir, dir, semverConfig.Output) return build(dcfg, destPath, sb.builderCfg.OutputType) } -func (sb *SemverBuilder) Validate(dir string) error { - return validate(sb.builderCfg.ContainerCfg, dir) +func (sb *SemverBuilder) Validate(ctx context.Context, dir string) error { + return validate(ctx, sb.builderCfg, dir) } type RawBuilder struct { @@ -218,13 +211,13 @@ func (rb *RawBuilder) Build(ctx context.Context, _ image.Registry, dir string, t return fmt.Errorf("error parsing raw input file: %s, %v", rawConfig.Input, err) } - destPath := path.Join(rb.builderCfg.ContainerCfg.WorkingDir, dir, rawConfig.Output) + destPath := path.Join(rb.builderCfg.WorkingDir, dir, rawConfig.Output) return build(dcfg, destPath, rb.builderCfg.OutputType) } -func (rb *RawBuilder) Validate(dir string) error { - return validate(rb.builderCfg.ContainerCfg, dir) +func (rb *RawBuilder) Validate(ctx context.Context, dir string) error { + return validate(ctx, rb.builderCfg, dir) } type CustomBuilder struct { @@ -268,13 +261,12 @@ func (cb *CustomBuilder) Build(ctx context.Context, reg image.Registry, dir stri } // build the command to execute cmd := exec.Command(customConfig.Command, customConfig.Args...) - cmd.Dir = cb.builderCfg.ContainerCfg.WorkingDir // custom template should output a valid FBC to STDOUT so we can // build the FBC just like all the other templates. v, err := cmd.Output() if err != nil { - return fmt.Errorf("running command %q: %v", cmd.String(), err) + return fmt.Errorf("running command %q: %v: %v", cmd.String(), err, v) } reader := bytes.NewReader(v) @@ -286,15 +278,15 @@ func (cb *CustomBuilder) Build(ctx context.Context, reg image.Registry, dir stri return fmt.Errorf("error parsing custom command output: %s, %v", strings.Join(cmdString, "'"), err) } - destPath := path.Join(cb.builderCfg.ContainerCfg.WorkingDir, dir, customConfig.Output) + destPath := path.Join(cb.builderCfg.WorkingDir, dir, customConfig.Output) // custom template should output a valid FBC to STDOUT so we can // build the FBC just like all the other templates. return build(dcfg, destPath, cb.builderCfg.OutputType) } -func (cb *CustomBuilder) Validate(dir string) error { - return validate(cb.builderCfg.ContainerCfg, dir) +func (cb *CustomBuilder) Validate(ctx context.Context, dir string) error { + return validate(ctx, cb.builderCfg, dir) } func writeDeclCfg(dcfg declcfg.DeclarativeConfig, w io.Writer, output string) error { @@ -308,18 +300,18 @@ func writeDeclCfg(dcfg declcfg.DeclarativeConfig, w io.Writer, output string) er } } -func validate(containerCfg ContainerConfig, dir string) error { +func validate(ctx context.Context, builderCfg BuilderConfig, dir string) error { - path := path.Join(containerCfg.WorkingDir, dir) + path := path.Join(builderCfg.WorkingDir, dir) s, err := os.Stat(path) if err != nil { - return fmt.Errorf("directory not found. validation path needs to be composed of ContainerConfig.WorkingDir+Component[].Destination.Path: %q: %v", path, err) + return fmt.Errorf("directory not found. validation path needs to be composed of BuilderConfig.WorkingDir+Component[].Destination.Path: %q: %v", path, err) } if !s.IsDir() { return fmt.Errorf("%q is not a directory", path) } - if err := config.Validate(os.DirFS(path)); err != nil { + if err := config.Validate(ctx, os.DirFS(path)); err != nil { return fmt.Errorf("validation failure in path %q: %v", path, err) } return nil diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/template/composite/composite.go b/vendor/github.com/operator-framework/operator-registry/alpha/template/composite/composite.go index 422017c974..68d261994b 100644 --- a/vendor/github.com/operator-framework/operator-registry/alpha/template/composite/composite.go +++ b/vendor/github.com/operator-framework/operator-registry/alpha/template/composite/composite.go @@ -2,35 +2,139 @@ package composite import ( "context" + "encoding/json" "fmt" + "io" + "net/http" + "net/url" + "os" "github.com/operator-framework/operator-registry/pkg/image" + "k8s.io/apimachinery/pkg/util/yaml" ) type BuilderMap map[string]Builder type CatalogBuilderMap map[string]BuilderMap +type builderFunc func(BuilderConfig) Builder + type Template struct { - CatalogBuilders CatalogBuilderMap - Registry image.Registry + catalogFile io.Reader + contributionFile io.Reader + validate bool + outputType string + registry image.Registry + registeredBuilders map[string]builderFunc +} + +type TemplateOption func(t *Template) + +func WithCatalogFile(catalogFile io.Reader) TemplateOption { + return func(t *Template) { + t.catalogFile = catalogFile + } +} + +func WithContributionFile(contribFile io.Reader) TemplateOption { + return func(t *Template) { + t.contributionFile = contribFile + } +} + +func WithOutputType(outputType string) TemplateOption { + return func(t *Template) { + t.outputType = outputType + } +} + +func WithRegistry(reg image.Registry) TemplateOption { + return func(t *Template) { + t.registry = reg + } +} + +func WithValidate(validate bool) TemplateOption { + return func(t *Template) { + t.validate = validate + } +} + +func NewTemplate(opts ...TemplateOption) *Template { + temp := &Template{ + // Default registered builders when creating a new Template + registeredBuilders: map[string]builderFunc{ + BasicBuilderSchema: func(bc BuilderConfig) Builder { return NewBasicBuilder(bc) }, + SemverBuilderSchema: func(bc BuilderConfig) Builder { return NewSemverBuilder(bc) }, + RawBuilderSchema: func(bc BuilderConfig) Builder { return NewRawBuilder(bc) }, + CustomBuilderSchema: func(bc BuilderConfig) Builder { return NewCustomBuilder(bc) }, + }, + } + + for _, opt := range opts { + opt(temp) + } + + return temp +} + +type HttpGetter interface { + Get(url string) (*http.Response, error) +} + +// FetchCatalogConfig will fetch the catalog configuration file from the given path. +// The path can be a local file path OR a URL that returns the raw contents of the catalog +// configuration file. +func FetchCatalogConfig(path string, httpGetter HttpGetter) (io.ReadCloser, error) { + var tempCatalog io.ReadCloser + catalogURI, err := url.ParseRequestURI(path) + if err != nil { + tempCatalog, err = os.Open(path) + if err != nil { + return nil, fmt.Errorf("opening catalog config file %q: %v", path, err) + } + } else { + tempResp, err := httpGetter.Get(catalogURI.String()) + if err != nil { + return nil, fmt.Errorf("fetching remote catalog config file %q: %v", path, err) + } + tempCatalog = tempResp.Body + } + + return tempCatalog, nil } // TODO(everettraven): do we need the context here? If so, how should it be used? -func (t *Template) Render(ctx context.Context, config *CompositeConfig, validate bool) error { +func (t *Template) Render(ctx context.Context, validate bool) error { + + catalogFile, err := t.parseCatalogsSpec() + if err != nil { + return err + } + + contributionFile, err := t.parseContributionSpec() + if err != nil { + return err + } + + catalogBuilderMap, err := t.newCatalogBuilderMap(catalogFile.Catalogs, t.outputType) + if err != nil { + return err + } + // TODO(everettraven): should we return aggregated errors? - for _, component := range config.Components { - if builderMap, ok := t.CatalogBuilders[component.Name]; ok { + for _, component := range contributionFile.Components { + if builderMap, ok := (*catalogBuilderMap)[component.Name]; ok { if builder, ok := builderMap[component.Strategy.Template.Schema]; ok { // run the builder corresponding to the schema - err := builder.Build(ctx, t.Registry, component.Destination.Path, component.Strategy.Template) + err := builder.Build(ctx, t.registry, component.Destination.Path, component.Strategy.Template) if err != nil { return fmt.Errorf("building component %q: %w", component.Name, err) } if validate { // run the validation for the builder - err = builder.Validate(component.Destination.Path) + err = builder.Validate(ctx, component.Destination.Path) if err != nil { return fmt.Errorf("validating component %q: %w", component.Name, err) } @@ -40,7 +144,7 @@ func (t *Template) Render(ctx context.Context, config *CompositeConfig, validate } } else { allowedComponents := []string{} - for k := range t.CatalogBuilders { + for k := range *catalogBuilderMap { allowedComponents = append(allowedComponents, k) } return fmt.Errorf("building component %q: component does not exist in the catalog configuration. Available components are: %s", component.Name, allowedComponents) @@ -48,3 +152,111 @@ func (t *Template) Render(ctx context.Context, config *CompositeConfig, validate } return nil } + +func (t *Template) builderForSchema(schema string, builderCfg BuilderConfig) (Builder, error) { + builderFunc, ok := t.registeredBuilders[schema] + if !ok { + return nil, fmt.Errorf("unknown schema %q", schema) + } + + return builderFunc(builderCfg), nil +} + +func (t *Template) parseCatalogsSpec() (*CatalogConfig, error) { + + // get catalog configurations + catalogConfig := &CatalogConfig{} + catalogDoc := json.RawMessage{} + catalogDecoder := yaml.NewYAMLOrJSONDecoder(t.catalogFile, 4096) + err := catalogDecoder.Decode(&catalogDoc) + if err != nil { + return nil, fmt.Errorf("decoding catalog config: %v", err) + } + err = json.Unmarshal(catalogDoc, catalogConfig) + if err != nil { + return nil, fmt.Errorf("unmarshalling catalog config: %v", err) + } + + if catalogConfig.Schema != CatalogSchema { + return nil, fmt.Errorf("catalog configuration file has unknown schema, should be %q", CatalogSchema) + } + + return catalogConfig, nil +} + +func (t *Template) parseContributionSpec() (*CompositeConfig, error) { + + // parse data to composite config + compositeConfig := &CompositeConfig{} + compositeDoc := json.RawMessage{} + compositeDecoder := yaml.NewYAMLOrJSONDecoder(t.contributionFile, 4096) + err := compositeDecoder.Decode(&compositeDoc) + if err != nil { + return nil, fmt.Errorf("decoding composite config: %v", err) + } + err = json.Unmarshal(compositeDoc, compositeConfig) + if err != nil { + return nil, fmt.Errorf("unmarshalling composite config: %v", err) + } + + if compositeConfig.Schema != CompositeSchema { + return nil, fmt.Errorf("composite configuration file has unknown schema, should be %q", CompositeSchema) + } + + return compositeConfig, nil +} + +func (t *Template) newCatalogBuilderMap(catalogs []Catalog, outputType string) (*CatalogBuilderMap, error) { + + catalogBuilderMap := make(CatalogBuilderMap) + + // setup the builders for each catalog + setupFailed := false + setupErrors := map[string][]string{} + for _, catalog := range catalogs { + errs := []string{} + // if catalog.Destination.BaseImage == "" { + // errs = append(errs, "destination.baseImage must not be an empty string") + // } + + if catalog.Destination.WorkingDir == "" { + errs = append(errs, "destination.workingDir must not be an empty string") + } + + // check for validation errors and skip builder creation if there are any errors + if len(errs) > 0 { + setupFailed = true + setupErrors[catalog.Name] = errs + continue + } + + if _, ok := catalogBuilderMap[catalog.Name]; !ok { + builderMap := make(BuilderMap) + for _, schema := range catalog.Builders { + builder, err := t.builderForSchema(schema, BuilderConfig{ + OutputType: outputType, + }) + if err != nil { + return nil, fmt.Errorf("getting builder %q for catalog %q: %v", schema, catalog.Name, err) + } + builderMap[schema] = builder + } + catalogBuilderMap[catalog.Name] = builderMap + } + } + + // if there were errors validating the catalog configuration then exit + if setupFailed { + //build the error message + var errMsg string + for cat, errs := range setupErrors { + errMsg += fmt.Sprintf("\nCatalog %v:\n", cat) + for _, err := range errs { + errMsg += fmt.Sprintf(" - %v\n", err) + } + } + return nil, fmt.Errorf("catalog configuration file field validation failed: %s", errMsg) + } + + return &catalogBuilderMap, nil +} diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/template/composite/config.go b/vendor/github.com/operator-framework/operator-registry/alpha/template/composite/config.go index 70a480d4e8..21d4ac5ee0 100644 --- a/vendor/github.com/operator-framework/operator-registry/alpha/template/composite/config.go +++ b/vendor/github.com/operator-framework/operator-registry/alpha/template/composite/config.go @@ -37,6 +37,6 @@ type Catalog struct { } type CatalogDestination struct { - BaseImage string + // BaseImage string WorkingDir string } diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/template/semver/semver.go b/vendor/github.com/operator-framework/operator-registry/alpha/template/semver/semver.go index 8cf2412874..ec6b6829e7 100644 --- a/vendor/github.com/operator-framework/operator-registry/alpha/template/semver/semver.go +++ b/vendor/github.com/operator-framework/operator-registry/alpha/template/semver/semver.go @@ -74,17 +74,42 @@ func readFile(reader io.Reader) (*semverTemplate, error) { return nil, err } - // default behavior is to generate only minor channels - sv := semverTemplate{ - GenerateMajorChannels: false, - GenerateMinorChannels: true, - } + sv := semverTemplate{} if err := yaml.UnmarshalStrict(data, &sv); err != nil { return nil, err } + if sv.Schema != schema { return nil, fmt.Errorf("readFile: input file has unknown schema, should be %q", schema) } + + // if no generate option is selected, default to GenerateMinorChannels + if !sv.GenerateMajorChannels && !sv.GenerateMinorChannels { + sv.GenerateMinorChannels = true + } + + // for default channel preference, + // if un-set, default to align to the selected generate option + // if set, error out if we mismatch the two + switch sv.DefaultChannelTypePreference { + case defaultStreamType: + if sv.GenerateMinorChannels { + sv.DefaultChannelTypePreference = minorStreamType + } else if sv.GenerateMajorChannels { + sv.DefaultChannelTypePreference = majorStreamType + } + case minorStreamType: + if !sv.GenerateMinorChannels { + return nil, fmt.Errorf("schema attribute mismatch: DefaultChannelTypePreference set to 'minor' doesn't make sense if not generating minor-version channels") + } + case majorStreamType: + if !sv.GenerateMajorChannels { + return nil, fmt.Errorf("schema attribute mismatch: DefaultChannelTypePreference set to 'major' doesn't make sense if not generating major-version channels") + } + default: + return nil, fmt.Errorf("unknown DefaultChannelTypePreference: %q\nValid values are 'major' or 'minor'", sv.DefaultChannelTypePreference) + } + return &sv, nil } @@ -240,8 +265,8 @@ func (sv *semverTemplate) generateChannels(semverChannels *bundleVersions) []dec unlinkedChannels[cName] = ch - hwcCandidate := highwaterChannel{archetype: archetype, version: bundles[bundleName], name: cName} - if hwcCandidate.gt(&hwc) { + hwcCandidate := highwaterChannel{archetype: archetype, kind: cKey, version: bundles[bundleName], name: cName} + if hwcCandidate.gt(&hwc, sv.DefaultChannelTypePreference) { hwc = hwcCandidate } } @@ -419,3 +444,31 @@ func stripBuildMetadata(v semver.Version) string { v.Build = nil return v.String() } + +// prefer (in descending order of preference): +// - higher-rank archetype, +// - semver version, +// - a channel type matching the set preference, or +// - a 'better' (higher value) channel type +func (h *highwaterChannel) gt(ih *highwaterChannel, pref streamType) bool { + if channelPriorities[h.archetype] != channelPriorities[ih.archetype] { + return channelPriorities[h.archetype] > channelPriorities[ih.archetype] + } + if h.version.NE(ih.version) { + return h.version.GT(ih.version) + } + if h.kind != ih.kind { + if h.kind == pref { + return true + } + if ih.kind == pref { + return false + } + return h.kind.gt((*ih).kind) + } + return false +} + +func (t streamType) gt(in streamType) bool { + return streamTypePriorities[t] > streamTypePriorities[in] +} diff --git a/vendor/github.com/operator-framework/operator-registry/alpha/template/semver/types.go b/vendor/github.com/operator-framework/operator-registry/alpha/template/semver/types.go index de948f3723..de68504c65 100644 --- a/vendor/github.com/operator-framework/operator-registry/alpha/template/semver/types.go +++ b/vendor/github.com/operator-framework/operator-registry/alpha/template/semver/types.go @@ -24,12 +24,13 @@ type semverTemplateChannelBundles struct { } type semverTemplate struct { - Schema string `json:"schema"` - GenerateMajorChannels bool `json:"generateMajorChannels,omitempty"` - GenerateMinorChannels bool `json:"generateMinorChannels,omitempty"` - Candidate semverTemplateChannelBundles `json:"candidate,omitempty"` - Fast semverTemplateChannelBundles `json:"fast,omitempty"` - Stable semverTemplateChannelBundles `json:"stable,omitempty"` + Schema string `json:"schema"` + GenerateMajorChannels bool `json:"generateMajorChannels,omitempty"` + GenerateMinorChannels bool `json:"generateMinorChannels,omitempty"` + DefaultChannelTypePreference streamType `json:"defaultChannelTypePreference,omitempty"` + Candidate semverTemplateChannelBundles `json:"candidate,omitempty"` + Fast semverTemplateChannelBundles `json:"fast,omitempty"` + Stable semverTemplateChannelBundles `json:"stable,omitempty"` pkg string `json:"-"` // the derived package name defaultChannel string `json:"-"` // detected "most stable" channel head @@ -62,10 +63,12 @@ func (b byChannelPriority) Swap(i, j int) { b[i], b[j] = b[j], b[i] } type streamType string +const defaultStreamType streamType = "" const minorStreamType streamType = "minor" const majorStreamType streamType = "major" -var streamTypePriorities = map[streamType]int{minorStreamType: 0, majorStreamType: 1} +// general preference for minor channels +var streamTypePriorities = map[streamType]int{minorStreamType: 2, majorStreamType: 1, defaultStreamType: 0} // map of archetypes --> bundles --> bundle-version from the input file type bundleVersions map[channelArchetype]map[string]semver.Version // e.g. srcv["stable"]["example-operator.v1.0.0"] = 1.0.0 @@ -74,14 +77,11 @@ type bundleVersions map[channelArchetype]map[string]semver.Version // e.g. srcv[ // later as the package's defaultChannel attribute type highwaterChannel struct { archetype channelArchetype + kind streamType version semver.Version name string } -func (h *highwaterChannel) gt(ih *highwaterChannel) bool { - return (channelPriorities[h.archetype] > channelPriorities[ih.archetype]) || (h.version.GT(ih.version)) -} - type entryTuple struct { arch channelArchetype kind streamType diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/template/composite.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/template/composite.go index 1d8b9df0cb..df44998766 100644 --- a/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/template/composite.go +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/alpha/template/composite.go @@ -1,13 +1,11 @@ package template import ( - "encoding/json" - "fmt" "log" + "net/http" "os" "github.com/spf13/cobra" - "k8s.io/apimachinery/pkg/util/yaml" "github.com/operator-framework/operator-registry/alpha/template/composite" "github.com/operator-framework/operator-registry/cmd/opm/internal/util" @@ -15,9 +13,7 @@ import ( func newCompositeTemplateCmd() *cobra.Command { var ( - template composite.Template output string - containerTool string validate bool compositeFile string catalogFile string @@ -30,154 +26,52 @@ and a 'composite template' file`, and a 'composite template' file`, Args: cobra.MaximumNArgs(0), Run: func(cmd *cobra.Command, args []string) { - containerTool = "docker" - catalogData, err := os.Open(catalogFile) - if err != nil { - log.Fatalf("opening catalog config file %q: %s", catalogFile, err) - } - defer catalogData.Close() - - // get catalog configurations - catalogConfig := &composite.CatalogConfig{} - catalogDoc := json.RawMessage{} - catalogDecoder := yaml.NewYAMLOrJSONDecoder(catalogData, 4096) - err = catalogDecoder.Decode(&catalogDoc) - if err != nil { - log.Fatalf("decoding catalog config: %s", err) - } - err = json.Unmarshal(catalogDoc, catalogConfig) - if err != nil { - log.Fatalf("unmarshalling catalog config: %s", err) - } - if catalogConfig.Schema != composite.CatalogSchema { - log.Fatalf("catalog configuration file has unknown schema, should be %q", composite.CatalogSchema) + switch output { + case "yaml": + // do nothing + case "json": + // do nothing + default: + log.Fatalf("invalid --output value %q, expected (json|yaml)", output) } - catalogBuilderMap := make(composite.CatalogBuilderMap) - - wd, err := os.Getwd() - if err != nil { - log.Fatalf("getting current working directory: %s", err) - } - - // setup the builders for each catalog - setupFailed := false - setupErrors := map[string][]string{} - for _, catalog := range catalogConfig.Catalogs { - errs := []string{} - if catalog.Destination.BaseImage == "" { - errs = append(errs, "destination.baseImage must not be an empty string") - } - - if catalog.Destination.WorkingDir == "" { - errs = append(errs, "destination.workingDir must not be an empty string") - } - - // check for validation errors and skip builder creation if there are any errors - if len(errs) > 0 { - setupFailed = true - setupErrors[catalog.Name] = errs - continue - } - - if _, ok := catalogBuilderMap[catalog.Name]; !ok { - builderMap := make(composite.BuilderMap) - for _, schema := range catalog.Builders { - builder, err := builderForSchema(schema, composite.BuilderConfig{ - ContainerCfg: composite.ContainerConfig{ - ContainerTool: containerTool, - BaseImage: catalog.Destination.BaseImage, - WorkingDir: catalog.Destination.WorkingDir, - }, - OutputType: output, - // BUGBUG: JEK: This is a strong assumption that input is always local to execution which we need to eliminate in a later PR - InputDirectory: wd, - }) - if err != nil { - log.Fatalf("getting builder %q for catalog %q: %s", schema, catalog.Name, err) - } - builderMap[schema] = builder - } - catalogBuilderMap[catalog.Name] = builderMap - } - } - - // if there were errors validating the catalog configuration then exit - if setupFailed { - //build the error message - var errMsg string - for cat, errs := range setupErrors { - errMsg += fmt.Sprintf("\nCatalog %s:\n", cat) - for _, err := range errs { - errMsg += fmt.Sprintf(" - %s\n", err) - } - } - log.Fatalf("catalog configuration file field validation failed: %s", errMsg) - } - - template.CatalogBuilders = catalogBuilderMap - reg, err := util.CreateCLIRegistry(cmd) if err != nil { log.Fatalf("creating containerd registry: %v", err) } defer reg.Destroy() - template.Registry = reg - - compositeData, err := os.Open(compositeFile) + // operator author's 'composite.yaml' file + compositeReader, err := os.Open(compositeFile) if err != nil { - log.Fatalf("opening composite config file %q: %s", compositeFile, err) + log.Fatalf("opening composite config file %q: %v", compositeFile, err) } - defer compositeData.Close() + defer compositeReader.Close() - // parse data to composite config - compositeConfig := &composite.CompositeConfig{} - compositeDoc := json.RawMessage{} - compositeDecoder := yaml.NewYAMLOrJSONDecoder(compositeData, 4096) - err = compositeDecoder.Decode(&compositeDoc) + // catalog maintainer's 'catalogs.yaml' file + tempCatalog, err := composite.FetchCatalogConfig(catalogFile, http.DefaultClient) if err != nil { - log.Fatalf("decoding composite config: %s", err) - } - err = json.Unmarshal(compositeDoc, compositeConfig) - if err != nil { - log.Fatalf("unmarshalling composite config: %s", err) + log.Fatalf(err.Error()) } + defer tempCatalog.Close() - if compositeConfig.Schema != composite.CompositeSchema { - log.Fatalf("%q has unknown schema, should be %q", compositeFile, composite.CompositeSchema) - } + template := composite.NewTemplate( + composite.WithCatalogFile(tempCatalog), + composite.WithContributionFile(compositeReader), + composite.WithOutputType(output), + composite.WithRegistry(reg), + ) - err = template.Render(cmd.Context(), compositeConfig, validate) + err = template.Render(cmd.Context(), validate) if err != nil { - log.Fatalf("rendering the composite template: %s", err) + log.Fatalf("rendering the composite template: %v", err) } }, } cmd.Flags().StringVarP(&output, "output", "o", "json", "Output format (json|yaml)") - // TODO: Investigate ways to do this without using a cli tool like docker/podman - // cmd.Flags().StringVar(&containerTool, "container-tool", "docker", "container tool to be used when rendering templates (should be an equivalent replacement to docker - similar to podman)") cmd.Flags().BoolVar(&validate, "validate", true, "whether or not the created FBC should be validated (i.e 'opm validate')") - cmd.Flags().StringVarP(&compositeFile, "composite-config", "c", "catalog/config.yaml", "File to use as the composite configuration file") + cmd.Flags().StringVarP(&compositeFile, "composite-config", "c", "composite.yaml", "File to use as the composite configuration file") cmd.Flags().StringVarP(&catalogFile, "catalog-config", "f", "catalogs.yaml", "File to use as the catalog configuration file") return cmd } - -func builderForSchema(schema string, builderCfg composite.BuilderConfig) (composite.Builder, error) { - var builder composite.Builder - switch schema { - case composite.BasicBuilderSchema: - builder = composite.NewBasicBuilder(builderCfg) - case composite.SemverBuilderSchema: - builder = composite.NewSemverBuilder(builderCfg) - case composite.RawBuilderSchema: - builder = composite.NewRawBuilder(builderCfg) - case composite.CustomBuilderSchema: - builder = composite.NewCustomBuilder(builderCfg) - default: - return nil, fmt.Errorf("unknown schema %q", schema) - } - - return builder, nil -} diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/migrate/cmd.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/migrate/cmd.go index 6405060b0a..36c73abc7a 100644 --- a/vendor/github.com/operator-framework/operator-registry/cmd/opm/migrate/cmd.go +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/migrate/cmd.go @@ -21,6 +21,10 @@ func NewCmd() *cobra.Command { Short: "Migrate a sqlite-based index image or database file to a file-based catalog", Long: `Migrate a sqlite-based index image or database file to a file-based catalog. +NOTE: the --output=json format produces streamable, concatenated JSON files. +These are suitable to opm and jq, but may not be supported by arbitrary JSON +parsers that assume that a file contains exactly one valid JSON object. + ` + sqlite.DeprecationMessage, Args: cobra.ExactArgs(2), PersistentPreRun: func(_ *cobra.Command, _ []string) { diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/render/cmd.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/render/cmd.go index 448097a73a..03cdbcbd3e 100644 --- a/vendor/github.com/operator-framework/operator-registry/cmd/opm/render/cmd.go +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/render/cmd.go @@ -22,8 +22,10 @@ func NewCmd() *cobra.Command { ) cmd := &cobra.Command{ Use: "render [index-image | bundle-image | sqlite-file]...", - Short: "Generate a declarative config blob from catalogs and bundles", - Long: `Generate a declarative config blob from the provided index images, bundle images, and sqlite database files + Short: "Generate a stream of file-based catalog objects from catalogs and bundles", + Long: `Generate a stream of file-based catalog objects to stdout from the provided +catalog images, file-based catalog directories, bundle images, and sqlite +database files. ` + sqlite.DeprecationMessage, Args: cobra.MinimumNArgs(1), @@ -63,7 +65,7 @@ func NewCmd() *cobra.Command { } }, } - cmd.Flags().StringVarP(&output, "output", "o", "json", "Output format (json|yaml)") + cmd.Flags().StringVarP(&output, "output", "o", "json", "Output format of the streamed file-based catalog objects (json|yaml)") return cmd } diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/serve/serve.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/serve/serve.go index 8b7d280764..fc3c482ff8 100644 --- a/vendor/github.com/operator-framework/operator-registry/cmd/opm/serve/serve.go +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/serve/serve.go @@ -136,7 +136,7 @@ func (s *serve) run(ctx context.Context) error { return err } } else { - if err := cache.LoadOrRebuild(store, os.DirFS(s.configDir)); err != nil { + if err := cache.LoadOrRebuild(ctx, store, os.DirFS(s.configDir)); err != nil { return err } } diff --git a/vendor/github.com/operator-framework/operator-registry/cmd/opm/validate/validate.go b/vendor/github.com/operator-framework/operator-registry/cmd/opm/validate/validate.go index 9132ce578e..4579f5e120 100644 --- a/vendor/github.com/operator-framework/operator-registry/cmd/opm/validate/validate.go +++ b/vendor/github.com/operator-framework/operator-registry/cmd/opm/validate/validate.go @@ -17,7 +17,7 @@ func NewCmd() *cobra.Command { Short: "Validate the declarative index config", Long: "Validate the declarative config JSON file(s) in a given directory", Args: cobra.ExactArgs(1), - RunE: func(_ *cobra.Command, args []string) error { + RunE: func(c *cobra.Command, args []string) error { directory := args[0] s, err := os.Stat(directory) if err != nil { @@ -27,7 +27,7 @@ func NewCmd() *cobra.Command { return fmt.Errorf("%q is not a directory", directory) } - if err := config.Validate(os.DirFS(directory)); err != nil { + if err := config.Validate(c.Context(), os.DirFS(directory)); err != nil { logger.Fatal(err) } return nil diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/api/api_to_model.go b/vendor/github.com/operator-framework/operator-registry/pkg/api/api_to_model.go index d203f40b4a..06645f7c6b 100644 --- a/vendor/github.com/operator-framework/operator-registry/pkg/api/api_to_model.go +++ b/vendor/github.com/operator-framework/operator-registry/pkg/api/api_to_model.go @@ -5,6 +5,8 @@ import ( "fmt" "sort" + "github.com/operator-framework/api/pkg/operators/v1alpha1" + "github.com/operator-framework/operator-registry/alpha/model" "github.com/operator-framework/operator-registry/alpha/property" ) @@ -106,8 +108,17 @@ func convertAPIBundleToModelProperties(b *Bundle) ([]property.Property, error) { out = append(out, property.MustBuildGVKRequired(p.Group, p.Version, p.Kind)) } - for _, obj := range b.Object { - out = append(out, property.MustBuildBundleObjectData([]byte(obj))) + // If there is a bundle image reference and a valid CSV, create an + // olm.csv.metadata property. Otherwise, create a bundle object property for + // each object in the bundle. + var csv v1alpha1.ClusterServiceVersion + csvErr := json.Unmarshal([]byte(b.CsvJson), &csv) + if csvErr == nil && b.BundlePath != "" { + out = append(out, property.MustBuildCSVMetadata(csv)) + } else { + for _, obj := range b.Object { + out = append(out, property.MustBuildBundleObjectData([]byte(obj))) + } } sort.Slice(out, func(i, j int) bool { diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/api/model_to_api.go b/vendor/github.com/operator-framework/operator-registry/pkg/api/model_to_api.go index 26f8b745c3..1abe1cf6be 100644 --- a/vendor/github.com/operator-framework/operator-registry/pkg/api/model_to_api.go +++ b/vendor/github.com/operator-framework/operator-registry/pkg/api/model_to_api.go @@ -1,9 +1,15 @@ package api import ( + "encoding/base64" "encoding/json" "fmt" + "github.com/operator-framework/api/pkg/lib/version" + "github.com/operator-framework/api/pkg/operators" + "github.com/operator-framework/api/pkg/operators/v1alpha1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/operator-framework/operator-registry/alpha/model" "github.com/operator-framework/operator-registry/alpha/property" ) @@ -14,6 +20,38 @@ func ConvertModelBundleToAPIBundle(b model.Bundle) (*Bundle, error) { return nil, fmt.Errorf("parse properties: %v", err) } + csvJson := b.CsvJSON + if csvJson == "" && len(props.CSVMetadatas) == 1 { + var icons []v1alpha1.Icon + if b.Package.Icon != nil { + icons = []v1alpha1.Icon{{ + Data: base64.StdEncoding.EncodeToString(b.Package.Icon.Data), + MediaType: b.Package.Icon.MediaType, + }} + } + csv := csvMetadataToCsv(props.CSVMetadatas[0]) + csv.Name = b.Name + csv.Spec.Icon = icons + csv.Spec.InstallStrategy = v1alpha1.NamedInstallStrategy{ + // This stub is required to avoid a panic in OLM's package server that results in + // attemptint to write to a nil map. + StrategyName: "deployment", + } + csv.Spec.Version = version.OperatorVersion{b.Version} + csv.Spec.RelatedImages = convertModelRelatedImagesToCSVRelatedImages(b.RelatedImages) + if csv.Spec.Description == "" { + csv.Spec.Description = b.Package.Description + } + csvData, err := json.Marshal(csv) + if err != nil { + return nil, err + } + csvJson = string(csvData) + if len(b.Objects) == 0 { + b.Objects = []string{csvJson} + } + } + apiDeps, err := convertModelPropertiesToAPIDependencies(b.Properties) if err != nil { return nil, fmt.Errorf("convert model properties to api dependencies: %v", err) @@ -31,7 +69,7 @@ func ConvertModelBundleToAPIBundle(b model.Bundle) (*Bundle, error) { Properties: convertModelPropertiesToAPIProperties(b.Properties), Replaces: b.Replaces, Skips: b.Skips, - CsvJson: b.CsvJSON, + CsvJson: csvJson, Object: b.Objects, }, nil } @@ -46,9 +84,40 @@ func parseProperties(in []property.Property) (*property.Properties, error) { return nil, fmt.Errorf("expected exactly 1 property of type %q, found %d", property.TypePackage, len(props.Packages)) } + if len(props.CSVMetadatas) > 1 { + return nil, fmt.Errorf("expected at most 1 property of type %q, found %d", property.TypeCSVMetadata, len(props.CSVMetadatas)) + } + return props, nil } +func csvMetadataToCsv(m property.CSVMetadata) v1alpha1.ClusterServiceVersion { + return v1alpha1.ClusterServiceVersion{ + TypeMeta: metav1.TypeMeta{ + Kind: operators.ClusterServiceVersionKind, + APIVersion: v1alpha1.ClusterServiceVersionAPIVersion, + }, + ObjectMeta: metav1.ObjectMeta{ + Annotations: m.Annotations, + Labels: m.Labels, + }, + Spec: v1alpha1.ClusterServiceVersionSpec{ + APIServiceDefinitions: m.APIServiceDefinitions, + CustomResourceDefinitions: m.CustomResourceDefinitions, + Description: m.Description, + DisplayName: m.DisplayName, + InstallModes: m.InstallModes, + Keywords: m.Keywords, + Links: m.Links, + Maintainers: m.Maintainers, + Maturity: m.Maturity, + MinKubeVersion: m.MinKubeVersion, + NativeAPIs: m.NativeAPIs, + Provider: m.Provider, + }, + } +} + func gvksProvidedtoAPIGVKs(in []property.GVK) []*GroupVersionKind { var out []*GroupVersionKind for _, gvk := range in { @@ -82,7 +151,7 @@ func convertModelPropertiesToAPIProperties(props []property.Property) []*Propert // in its `Data` field, this CSV annotation projection would cause the size of the on-cluster // CSV to at least double, which is untenable since CSVs already have known issues running up // against etcd size constraints. - if prop.Type == property.TypeBundleObject { + if prop.Type == property.TypeBundleObject || prop.Type == property.TypeCSVMetadata { continue } @@ -117,3 +186,14 @@ func convertModelPropertiesToAPIDependencies(props []property.Property) ([]*Depe } return out, nil } + +func convertModelRelatedImagesToCSVRelatedImages(in []model.RelatedImage) []v1alpha1.RelatedImage { + var out []v1alpha1.RelatedImage + for _, ri := range in { + out = append(out, v1alpha1.RelatedImage{ + Name: ri.Name, + Image: ri.Image, + }) + } + return out +} diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/cache/cache.go b/vendor/github.com/operator-framework/operator-registry/pkg/cache/cache.go index 7df08d6f50..faf65d9934 100644 --- a/vendor/github.com/operator-framework/operator-registry/pkg/cache/cache.go +++ b/vendor/github.com/operator-framework/operator-registry/pkg/cache/cache.go @@ -18,13 +18,13 @@ type Cache interface { registry.GRPCQuery CheckIntegrity(fbc fs.FS) error - Build(fbc fs.FS) error + Build(ctx context.Context, fbc fs.FS) error Load() error } -func LoadOrRebuild(c Cache, fbc fs.FS) error { +func LoadOrRebuild(ctx context.Context, c Cache, fbc fs.FS) error { if err := c.CheckIntegrity(fbc); err != nil { - if err := c.Build(fbc); err != nil { + if err := c.Build(ctx, fbc); err != nil { return err } } diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/cache/json.go b/vendor/github.com/operator-framework/operator-registry/pkg/cache/json.go index 47a54952ba..0899a6f4f8 100644 --- a/vendor/github.com/operator-framework/operator-registry/pkg/cache/json.go +++ b/vendor/github.com/operator-framework/operator-registry/pkg/cache/json.go @@ -14,6 +14,7 @@ import ( "github.com/operator-framework/operator-registry/alpha/declcfg" "github.com/operator-framework/operator-registry/pkg/api" "github.com/operator-framework/operator-registry/pkg/registry" + "k8s.io/apimachinery/pkg/util/sets" ) var _ Cache = &JSON{} @@ -58,8 +59,13 @@ func (q *JSON) ListBundles(ctx context.Context) ([]*api.Bundle, error) { func (q *JSON) SendBundles(_ context.Context, s registry.BundleSender) error { for _, pkg := range q.packageIndex { - for _, ch := range pkg.Channels { - for _, b := range ch.Bundles { + channels := sets.KeySet(pkg.Channels) + for _, chName := range sets.List(channels) { + ch := pkg.Channels[chName] + + bundles := sets.KeySet(ch.Bundles) + for _, bName := range sets.List(bundles) { + b := ch.Bundles[bName] apiBundle, err := q.loadAPIBundle(apiBundleKey{pkg.Name, ch.Name, b.Name}) if err != nil { return fmt.Errorf("convert bundle %q: %v", b.Name, err) @@ -172,7 +178,7 @@ func (q *JSON) computeDigest(fbcFsys fs.FS) (string, error) { return fmt.Sprintf("%x", computedHasher.Sum(nil)), nil } -func (q *JSON) Build(fbcFsys fs.FS) error { +func (q *JSON) Build(ctx context.Context, fbcFsys fs.FS) error { // ensure that generated cache is available to all future users oldUmask := umask(000) defer umask(oldUmask) @@ -184,7 +190,7 @@ func (q *JSON) Build(fbcFsys fs.FS) error { return fmt.Errorf("ensure clean base directory: %v", err) } - fbc, err := declcfg.LoadFS(fbcFsys) + fbc, err := declcfg.LoadFS(ctx, fbcFsys) if err != nil { return err } diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/cache/pkgs.go b/vendor/github.com/operator-framework/operator-registry/pkg/cache/pkgs.go index d387ddbd09..af24c397c9 100644 --- a/vendor/github.com/operator-framework/operator-registry/pkg/cache/pkgs.go +++ b/vendor/github.com/operator-framework/operator-registry/pkg/cache/pkgs.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "sort" + "strings" "github.com/operator-framework/operator-registry/alpha/declcfg" "github.com/operator-framework/operator-registry/alpha/model" @@ -34,6 +35,7 @@ func (pkgs packageIndex) GetPackage(_ context.Context, name string) (*registry.P CurrentCSVName: ch.Head, }) } + sort.Slice(channels, func(i, j int) bool { return strings.Compare(channels[i].Name, channels[j].Name) < 0 }) return ®istry.PackageManifest{ PackageName: pkg.Name, Channels: channels, diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/lib/config/validate.go b/vendor/github.com/operator-framework/operator-registry/pkg/lib/config/validate.go index 5017d3da71..34f2bf0411 100644 --- a/vendor/github.com/operator-framework/operator-registry/pkg/lib/config/validate.go +++ b/vendor/github.com/operator-framework/operator-registry/pkg/lib/config/validate.go @@ -1,6 +1,7 @@ package config import ( + "context" "io/fs" "github.com/operator-framework/operator-registry/alpha/declcfg" @@ -13,9 +14,9 @@ import ( // directory: a filesystem where declarative config file(s) exist // Outputs: // error: a wrapped error that contains a tree of error strings -func Validate(root fs.FS) error { +func Validate(ctx context.Context, root fs.FS) error { // Load config files and convert them to declcfg objects - cfg, err := declcfg.LoadFS(root) + cfg, err := declcfg.LoadFS(ctx, root) if err != nil { return err } diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/lib/indexer/interfaces.go b/vendor/github.com/operator-framework/operator-registry/pkg/lib/indexer/interfaces.go index df9e6e47a2..5ebefdd1e3 100644 --- a/vendor/github.com/operator-framework/operator-registry/pkg/lib/indexer/interfaces.go +++ b/vendor/github.com/operator-framework/operator-registry/pkg/lib/indexer/interfaces.go @@ -9,6 +9,7 @@ import ( // IndexAdder allows the creation of index container images from scratch or // based on previous index images +// //counterfeiter:generate . IndexAdder type IndexAdder interface { AddToIndex(AddToIndexRequest) error @@ -29,6 +30,7 @@ func NewIndexAdder(buildTool, pullTool containertools.ContainerTool, logger *log // IndexDeleter takes indexes and deletes all references to an operator // from them +// //counterfeiter:generate . IndexDeleter type IndexDeleter interface { DeleteFromIndex(DeleteFromIndexRequest) error diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/lib/log/writerhook.go b/vendor/github.com/operator-framework/operator-registry/pkg/lib/log/writerhook.go index aa51229bc6..7609ae27f7 100644 --- a/vendor/github.com/operator-framework/operator-registry/pkg/lib/log/writerhook.go +++ b/vendor/github.com/operator-framework/operator-registry/pkg/lib/log/writerhook.go @@ -44,7 +44,7 @@ func AddHooks(hooks ...*WriterHook) { } func AddDefaultWriterHooks(terminationLogPath string) error { - terminationLogFile, err := os.OpenFile(terminationLogPath, os.O_WRONLY|os.O_CREATE, 0755) + terminationLogFile, err := os.OpenFile(terminationLogPath, os.O_WRONLY|os.O_CREATE, 0644) if err != nil { return err } diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/registry/registry_to_model.go b/vendor/github.com/operator-framework/operator-registry/pkg/registry/registry_to_model.go index 14b6e7b004..869b8a5c7a 100644 --- a/vendor/github.com/operator-framework/operator-registry/pkg/registry/registry_to_model.go +++ b/vendor/github.com/operator-framework/operator-registry/pkg/registry/registry_to_model.go @@ -5,6 +5,9 @@ import ( "fmt" "sort" + "github.com/operator-framework/api/pkg/operators" + "github.com/operator-framework/api/pkg/operators/v1alpha1" + "github.com/operator-framework/operator-registry/alpha/property" ) @@ -99,8 +102,21 @@ func ObjectsAndPropertiesFromBundle(b *Bundle) ([]string, []property.Property, e if err != nil { return nil, nil, fmt.Errorf("marshal object %s/%s (%s) to json: %v", obj.GetName(), obj.GetNamespace(), obj.GroupVersionKind(), err) } - props = append(props, property.MustBuildBundleObjectData(objData)) objects = append(objects, string(objData)) + + // Make an olm.bundle.object property if there is no bundle image set. + // Otherwise, make a olm.csv.metadata property if the object is a CSV + // (and fallback to olm.bundle.object if parsing the CSV fails). + if b.BundleImage == "" { + props = append(props, property.MustBuildBundleObjectData(objData)) + } else if obj.GetKind() == operators.ClusterServiceVersionKind { + var csv v1alpha1.ClusterServiceVersion + if err := json.Unmarshal(objData, &csv); err != nil { + props = append(props, property.MustBuildBundleObjectData(objData)) + } else { + props = append(props, property.MustBuildCSVMetadata(csv)) + } + } } if packageProvidedProperty == nil { diff --git a/vendor/github.com/operator-framework/operator-registry/pkg/registry/tar.go b/vendor/github.com/operator-framework/operator-registry/pkg/registry/tar.go new file mode 100644 index 0000000000..f62a15da85 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-registry/pkg/registry/tar.go @@ -0,0 +1,66 @@ +package registry + +import ( + "archive/tar" + "fmt" + "io" + "io/fs" + "os" + "time" +) + +// fsToTar writes the filesystem represented by fsys to w as a tar archive. +// This function unsets user and group information in the tar archive so that readers +// of archives produced by this function do not need to account for differences in +// permissions between source and destination filesystems. +func fsToTar(w io.Writer, fsys fs.FS) error { + tw := tar.NewWriter(w) + if err := fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + + if d.Type()&os.ModeSymlink != 0 { + return nil + } + info, err := d.Info() + if err != nil { + return fmt.Errorf("get file info for %q: %v", path, err) + } + + h, err := tar.FileInfoHeader(info, "") + if err != nil { + return fmt.Errorf("build tar file info header for %q: %v", path, err) + } + h.Uid = 0 + h.Gid = 0 + h.Uname = "" + h.Gname = "" + h.AccessTime = time.Time{} + h.ChangeTime = time.Time{} + h.ModTime = time.Time{} + h.Name = path + + if err := tw.WriteHeader(h); err != nil { + return fmt.Errorf("write tar header for %q: %v", path, err) + } + if d.IsDir() { + return nil + } + f, err := fsys.Open(path) + if err != nil { + return fmt.Errorf("open file %q: %v", path, err) + } + defer f.Close() + if _, err := io.Copy(tw, f); err != nil { + return fmt.Errorf("write tar data for %q: %v", path, err) + } + return nil + }); err != nil { + return fmt.Errorf("write tar: %w", err) + } + if err := tw.Close(); err != nil { + return err + } + return nil +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/collector.go b/vendor/github.com/prometheus/client_golang/prometheus/collector.go index ac1ca3cf5f..cf05079fb8 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/collector.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/collector.go @@ -69,9 +69,9 @@ type Collector interface { // If a Collector collects the same metrics throughout its lifetime, its // Describe method can simply be implemented as: // -// func (c customCollector) Describe(ch chan<- *Desc) { -// DescribeByCollect(c, ch) -// } +// func (c customCollector) Describe(ch chan<- *Desc) { +// DescribeByCollect(c, ch) +// } // // However, this will not work if the metrics collected change dynamically over // the lifetime of the Collector in a way that their combined set of descriptors diff --git a/vendor/github.com/prometheus/client_golang/prometheus/collectors/dbstats_collector.go b/vendor/github.com/prometheus/client_golang/prometheus/collectors/dbstats_collector.go index e09f149d76..d5a7279fb9 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/collectors/dbstats_collector.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/collectors/dbstats_collector.go @@ -101,7 +101,7 @@ func (c *dbStatsCollector) Describe(ch chan<- *prometheus.Desc) { ch <- c.waitDuration ch <- c.maxIdleClosed ch <- c.maxLifetimeClosed - c.describeNewInGo115(ch) + ch <- c.maxIdleTimeClosed } // Collect implements Collector. @@ -115,5 +115,5 @@ func (c *dbStatsCollector) Collect(ch chan<- prometheus.Metric) { ch <- prometheus.MustNewConstMetric(c.waitDuration, prometheus.CounterValue, stats.WaitDuration.Seconds()) ch <- prometheus.MustNewConstMetric(c.maxIdleClosed, prometheus.CounterValue, float64(stats.MaxIdleClosed)) ch <- prometheus.MustNewConstMetric(c.maxLifetimeClosed, prometheus.CounterValue, float64(stats.MaxLifetimeClosed)) - c.collectNewInGo115(ch, stats) + ch <- prometheus.MustNewConstMetric(c.maxIdleTimeClosed, prometheus.CounterValue, float64(stats.MaxIdleTimeClosed)) } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/collectors/dbstats_collector_go115.go b/vendor/github.com/prometheus/client_golang/prometheus/collectors/dbstats_collector_go115.go deleted file mode 100644 index 6d152fbf19..0000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/collectors/dbstats_collector_go115.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2021 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//go:build go1.15 -// +build go1.15 - -package collectors - -import ( - "database/sql" - - "github.com/prometheus/client_golang/prometheus" -) - -func (c *dbStatsCollector) describeNewInGo115(ch chan<- *prometheus.Desc) { - ch <- c.maxIdleTimeClosed -} - -func (c *dbStatsCollector) collectNewInGo115(ch chan<- prometheus.Metric, stats sql.DBStats) { - ch <- prometheus.MustNewConstMetric(c.maxIdleTimeClosed, prometheus.CounterValue, float64(stats.MaxIdleTimeClosed)) -} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/collectors/dbstats_collector_pre_go115.go b/vendor/github.com/prometheus/client_golang/prometheus/collectors/dbstats_collector_pre_go115.go deleted file mode 100644 index 65235069d6..0000000000 --- a/vendor/github.com/prometheus/client_golang/prometheus/collectors/dbstats_collector_pre_go115.go +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2021 The Prometheus Authors -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//go:build !go1.15 -// +build !go1.15 - -package collectors - -import ( - "database/sql" - - "github.com/prometheus/client_golang/prometheus" -) - -func (c *dbStatsCollector) describeNewInGo115(ch chan<- *prometheus.Desc) {} - -func (c *dbStatsCollector) collectNewInGo115(ch chan<- prometheus.Metric, stats sql.DBStats) {} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/collectors/go_collector_latest.go b/vendor/github.com/prometheus/client_golang/prometheus/collectors/go_collector_latest.go index 01790e885d..2f5616894e 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/collectors/go_collector_latest.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/collectors/go_collector_latest.go @@ -16,76 +16,147 @@ package collectors -import "github.com/prometheus/client_golang/prometheus" +import ( + "regexp" -//nolint:staticcheck // Ignore SA1019 until v2. -type goOptions = prometheus.GoCollectorOptions -type goOption func(o *goOptions) + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/internal" +) + +var ( + // MetricsAll allows all the metrics to be collected from Go runtime. + MetricsAll = GoRuntimeMetricsRule{regexp.MustCompile("/.*")} + // MetricsGC allows only GC metrics to be collected from Go runtime. + // e.g. go_gc_cycles_automatic_gc_cycles_total + // NOTE: This does not include new class of "/cpu/classes/gc/..." metrics. + // Use custom metric rule to access those. + MetricsGC = GoRuntimeMetricsRule{regexp.MustCompile(`^/gc/.*`)} + // MetricsMemory allows only memory metrics to be collected from Go runtime. + // e.g. go_memory_classes_heap_free_bytes + MetricsMemory = GoRuntimeMetricsRule{regexp.MustCompile(`^/memory/.*`)} + // MetricsScheduler allows only scheduler metrics to be collected from Go runtime. + // e.g. go_sched_goroutines_goroutines + MetricsScheduler = GoRuntimeMetricsRule{regexp.MustCompile(`^/sched/.*`)} +) +// WithGoCollectorMemStatsMetricsDisabled disables metrics that is gathered in runtime.MemStats structure such as: +// +// go_memstats_alloc_bytes +// go_memstats_alloc_bytes_total +// go_memstats_sys_bytes +// go_memstats_lookups_total +// go_memstats_mallocs_total +// go_memstats_frees_total +// go_memstats_heap_alloc_bytes +// go_memstats_heap_sys_bytes +// go_memstats_heap_idle_bytes +// go_memstats_heap_inuse_bytes +// go_memstats_heap_released_bytes +// go_memstats_heap_objects +// go_memstats_stack_inuse_bytes +// go_memstats_stack_sys_bytes +// go_memstats_mspan_inuse_bytes +// go_memstats_mspan_sys_bytes +// go_memstats_mcache_inuse_bytes +// go_memstats_mcache_sys_bytes +// go_memstats_buck_hash_sys_bytes +// go_memstats_gc_sys_bytes +// go_memstats_other_sys_bytes +// go_memstats_next_gc_bytes +// +// so the metrics known from pre client_golang v1.12.0, +// +// NOTE(bwplotka): The above represents runtime.MemStats statistics, but they are +// actually implemented using new runtime/metrics package. (except skipped go_memstats_gc_cpu_fraction +// -- see https://github.com/prometheus/client_golang/issues/842#issuecomment-861812034 for explanation). +// +// Some users might want to disable this on collector level (although you can use scrape relabelling on Prometheus), +// because similar metrics can be now obtained using WithGoCollectorRuntimeMetrics. Note that the semantics of new +// metrics might be different, plus the names can be change over time with different Go version. +// +// NOTE(bwplotka): Changing metric names can be tedious at times as the alerts, recording rules and dashboards have to be adjusted. +// The old metrics are also very useful, with many guides and books written about how to interpret them. +// +// As a result our recommendation would be to stick with MemStats like metrics and enable other runtime/metrics if you are interested +// in advanced insights Go provides. See ExampleGoCollector_WithAdvancedGoMetrics. +func WithGoCollectorMemStatsMetricsDisabled() func(options *internal.GoCollectorOptions) { + return func(o *internal.GoCollectorOptions) { + o.DisableMemStatsLikeMetrics = true + } +} + +// GoRuntimeMetricsRule allow enabling and configuring particular group of runtime/metrics. +// TODO(bwplotka): Consider adding ability to adjust buckets. +type GoRuntimeMetricsRule struct { + // Matcher represents RE2 expression will match the runtime/metrics from https://golang.bg/src/runtime/metrics/description.go + // Use `regexp.MustCompile` or `regexp.Compile` to create this field. + Matcher *regexp.Regexp +} + +// WithGoCollectorRuntimeMetrics allows enabling and configuring particular group of runtime/metrics. +// See the list of metrics https://golang.bg/src/runtime/metrics/description.go (pick the Go version you use there!). +// You can use this option in repeated manner, which will add new rules. The order of rules is important, the last rule +// that matches particular metrics is applied. +func WithGoCollectorRuntimeMetrics(rules ...GoRuntimeMetricsRule) func(options *internal.GoCollectorOptions) { + rs := make([]internal.GoCollectorRule, len(rules)) + for i, r := range rules { + rs[i] = internal.GoCollectorRule{ + Matcher: r.Matcher, + } + } + + return func(o *internal.GoCollectorOptions) { + o.RuntimeMetricRules = append(o.RuntimeMetricRules, rs...) + } +} + +// WithoutGoCollectorRuntimeMetrics allows disabling group of runtime/metrics that you might have added in WithGoCollectorRuntimeMetrics. +// It behaves similarly to WithGoCollectorRuntimeMetrics just with deny-list semantics. +func WithoutGoCollectorRuntimeMetrics(matchers ...*regexp.Regexp) func(options *internal.GoCollectorOptions) { + rs := make([]internal.GoCollectorRule, len(matchers)) + for i, m := range matchers { + rs[i] = internal.GoCollectorRule{ + Matcher: m, + Deny: true, + } + } + + return func(o *internal.GoCollectorOptions) { + o.RuntimeMetricRules = append(o.RuntimeMetricRules, rs...) + } +} + +// GoCollectionOption represents Go collection option flag. +// Deprecated. type GoCollectionOption uint32 const ( - // GoRuntimeMemStatsCollection represents the metrics represented by runtime.MemStats structure such as - // go_memstats_alloc_bytes - // go_memstats_alloc_bytes_total - // go_memstats_sys_bytes - // go_memstats_lookups_total - // go_memstats_mallocs_total - // go_memstats_frees_total - // go_memstats_heap_alloc_bytes - // go_memstats_heap_sys_bytes - // go_memstats_heap_idle_bytes - // go_memstats_heap_inuse_bytes - // go_memstats_heap_released_bytes - // go_memstats_heap_objects - // go_memstats_stack_inuse_bytes - // go_memstats_stack_sys_bytes - // go_memstats_mspan_inuse_bytes - // go_memstats_mspan_sys_bytes - // go_memstats_mcache_inuse_bytes - // go_memstats_mcache_sys_bytes - // go_memstats_buck_hash_sys_bytes - // go_memstats_gc_sys_bytes - // go_memstats_other_sys_bytes - // go_memstats_next_gc_bytes - // so the metrics known from pre client_golang v1.12.0, except skipped go_memstats_gc_cpu_fraction (see - // https://github.com/prometheus/client_golang/issues/842#issuecomment-861812034 for explanation. - // - // NOTE that this mode represents runtime.MemStats statistics, but they are - // actually implemented using new runtime/metrics package. - // Deprecated: Use GoRuntimeMetricsCollection instead going forward. + // GoRuntimeMemStatsCollection represents the metrics represented by runtime.MemStats structure. + // Deprecated. Use WithGoCollectorMemStatsMetricsDisabled() function to disable those metrics in the collector. GoRuntimeMemStatsCollection GoCollectionOption = 1 << iota - // GoRuntimeMetricsCollection is the new set of metrics represented by runtime/metrics package and follows - // consistent naming. The exposed metric set depends on Go version, but it is controlled against - // unexpected cardinality. This set has overlapping information with GoRuntimeMemStatsCollection, just with - // new names. GoRuntimeMetricsCollection is what is recommended for using going forward. + // GoRuntimeMetricsCollection is the new set of metrics represented by runtime/metrics package. + // Deprecated. Use WithGoCollectorRuntimeMetrics(GoRuntimeMetricsRule{Matcher: regexp.MustCompile("/.*")}) + // function to enable those metrics in the collector. GoRuntimeMetricsCollection ) -// WithGoCollections allows enabling different collections for Go collector on top of base metrics -// like go_goroutines, go_threads, go_gc_duration_seconds, go_memstats_last_gc_time_seconds, go_info. -// -// Check GoRuntimeMemStatsCollection and GoRuntimeMetricsCollection for more details. You can use none, -// one or more collections at once. For example: -// WithGoCollections(GoRuntimeMemStatsCollection | GoRuntimeMetricsCollection) means both GoRuntimeMemStatsCollection -// metrics and GoRuntimeMetricsCollection will be exposed. -// -// The current default is GoRuntimeMemStatsCollection, so the compatibility mode with -// client_golang pre v1.12 (move to runtime/metrics). -func WithGoCollections(flags GoCollectionOption) goOption { - return func(o *goOptions) { - o.EnabledCollections = uint32(flags) +// WithGoCollections allows enabling different collections for Go collector on top of base metrics. +// Deprecated. Use WithGoCollectorRuntimeMetrics() and WithGoCollectorMemStatsMetricsDisabled() instead to control metrics. +func WithGoCollections(flags GoCollectionOption) func(options *internal.GoCollectorOptions) { + return func(options *internal.GoCollectorOptions) { + if flags&GoRuntimeMemStatsCollection == 0 { + WithGoCollectorMemStatsMetricsDisabled()(options) + } + + if flags&GoRuntimeMetricsCollection != 0 { + WithGoCollectorRuntimeMetrics(GoRuntimeMetricsRule{Matcher: regexp.MustCompile("/.*")})(options) + } } } // NewGoCollector returns a collector that exports metrics about the current Go -// process using debug.GCStats using runtime/metrics. -func NewGoCollector(opts ...goOption) prometheus.Collector { - //nolint:staticcheck // Ignore SA1019 until v2. - promPkgOpts := make([]func(o *prometheus.GoCollectorOptions), len(opts)) - for i, opt := range opts { - promPkgOpts[i] = opt - } +// process using debug.GCStats (base metrics) and runtime/metrics (both in MemStats style and new ones). +func NewGoCollector(opts ...func(o *internal.GoCollectorOptions)) prometheus.Collector { //nolint:staticcheck // Ignore SA1019 until v2. - return prometheus.NewGoCollector(promPkgOpts...) + return prometheus.NewGoCollector(opts...) } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/counter.go b/vendor/github.com/prometheus/client_golang/prometheus/counter.go index 00d70f09b6..62de4dc59a 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/counter.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/counter.go @@ -51,7 +51,7 @@ type Counter interface { // will lead to a valid (label-less) exemplar. But if Labels is nil, the current // exemplar is left in place. AddWithExemplar panics if the value is < 0, if any // of the provided labels are invalid, or if the provided labels contain more -// than 64 runes in total. +// than 128 runes in total. type ExemplarAdder interface { AddWithExemplar(value float64, exemplar Labels) } @@ -59,6 +59,18 @@ type ExemplarAdder interface { // CounterOpts is an alias for Opts. See there for doc comments. type CounterOpts Opts +// CounterVecOpts bundles the options to create a CounterVec metric. +// It is mandatory to set CounterOpts, see there for mandatory fields. VariableLabels +// is optional and can safely be left to its default value. +type CounterVecOpts struct { + CounterOpts + + // VariableLabels are used to partition the metric vector by the given set + // of labels. Each label value will be constrained with the optional Contraint + // function, if provided. + VariableLabels ConstrainableLabels +} + // NewCounter creates a new Counter based on the provided CounterOpts. // // The returned implementation also implements ExemplarAdder. It is safe to @@ -140,12 +152,13 @@ func (c *counter) get() float64 { } func (c *counter) Write(out *dto.Metric) error { - val := c.get() - + // Read the Exemplar first and the value second. This is to avoid a race condition + // where users see an exemplar for a not-yet-existing observation. var exemplar *dto.Exemplar if e := c.exemplar.Load(); e != nil { exemplar = e.(*dto.Exemplar) } + val := c.get() return populateMetric(CounterValue, val, c.labelPairs, exemplar, out) } @@ -173,16 +186,24 @@ type CounterVec struct { // NewCounterVec creates a new CounterVec based on the provided CounterOpts and // partitioned by the given label names. func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec { - desc := NewDesc( + return V2.NewCounterVec(CounterVecOpts{ + CounterOpts: opts, + VariableLabels: UnconstrainedLabels(labelNames), + }) +} + +// NewCounterVec creates a new CounterVec based on the provided CounterVecOpts. +func (v2) NewCounterVec(opts CounterVecOpts) *CounterVec { + desc := V2.NewDesc( BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), opts.Help, - labelNames, + opts.VariableLabels, opts.ConstLabels, ) return &CounterVec{ MetricVec: NewMetricVec(desc, func(lvs ...string) Metric { if len(lvs) != len(desc.variableLabels) { - panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, lvs)) + panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels.labelNames(), lvs)) } result := &counter{desc: desc, labelPairs: MakeLabelPairs(desc, lvs), now: time.Now} result.init(result) // Init self-collection. @@ -245,7 +266,8 @@ func (v *CounterVec) GetMetricWith(labels Labels) (Counter, error) { // WithLabelValues works as GetMetricWithLabelValues, but panics where // GetMetricWithLabelValues would have returned an error. Not returning an // error allows shortcuts like -// myVec.WithLabelValues("404", "GET").Add(42) +// +// myVec.WithLabelValues("404", "GET").Add(42) func (v *CounterVec) WithLabelValues(lvs ...string) Counter { c, err := v.GetMetricWithLabelValues(lvs...) if err != nil { @@ -256,7 +278,8 @@ func (v *CounterVec) WithLabelValues(lvs ...string) Counter { // With works as GetMetricWith, but panics where GetMetricWithLabels would have // returned an error. Not returning an error allows shortcuts like -// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Add(42) +// +// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Add(42) func (v *CounterVec) With(labels Labels) Counter { c, err := v.GetMetricWith(labels) if err != nil { diff --git a/vendor/github.com/prometheus/client_golang/prometheus/desc.go b/vendor/github.com/prometheus/client_golang/prometheus/desc.go index 4bb816ab75..12331542dd 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/desc.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/desc.go @@ -14,17 +14,16 @@ package prometheus import ( - "errors" "fmt" "sort" "strings" - "github.com/cespare/xxhash/v2" - //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility. - "github.com/golang/protobuf/proto" - "github.com/prometheus/common/model" + "github.com/prometheus/client_golang/prometheus/internal" + "github.com/cespare/xxhash/v2" dto "github.com/prometheus/client_model/go" + "github.com/prometheus/common/model" + "google.golang.org/protobuf/proto" ) // Desc is the descriptor used by every Prometheus Metric. It is essentially @@ -51,9 +50,9 @@ type Desc struct { // constLabelPairs contains precalculated DTO label pairs based on // the constant labels. constLabelPairs []*dto.LabelPair - // variableLabels contains names of labels for which the metric - // maintains variable values. - variableLabels []string + // variableLabels contains names of labels and normalization function for + // which the metric maintains variable values. + variableLabels ConstrainedLabels // id is a hash of the values of the ConstLabels and fqName. This // must be unique among all registered descriptors and can therefore be // used as an identifier of the descriptor. @@ -77,10 +76,24 @@ type Desc struct { // For constLabels, the label values are constant. Therefore, they are fully // specified in the Desc. See the Collector example for a usage pattern. func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) *Desc { + return V2.NewDesc(fqName, help, UnconstrainedLabels(variableLabels), constLabels) +} + +// NewDesc allocates and initializes a new Desc. Errors are recorded in the Desc +// and will be reported on registration time. variableLabels and constLabels can +// be nil if no such labels should be set. fqName must not be empty. +// +// variableLabels only contain the label names and normalization functions. Their +// label values are variable and therefore not part of the Desc. (They are managed +// within the Metric.) +// +// For constLabels, the label values are constant. Therefore, they are fully +// specified in the Desc. See the Collector example for a usage pattern. +func (v2) NewDesc(fqName, help string, variableLabels ConstrainableLabels, constLabels Labels) *Desc { d := &Desc{ fqName: fqName, help: help, - variableLabels: variableLabels, + variableLabels: variableLabels.constrainedLabels(), } if !model.IsValidMetricName(model.LabelValue(fqName)) { d.err = fmt.Errorf("%q is not a valid metric name", fqName) @@ -90,7 +103,7 @@ func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) * // their sorted label names) plus the fqName (at position 0). labelValues := make([]string, 1, len(constLabels)+1) labelValues[0] = fqName - labelNames := make([]string, 0, len(constLabels)+len(variableLabels)) + labelNames := make([]string, 0, len(constLabels)+len(d.variableLabels)) labelNameSet := map[string]struct{}{} // First add only the const label names and sort them... for labelName := range constLabels { @@ -115,16 +128,16 @@ func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) * // Now add the variable label names, but prefix them with something that // cannot be in a regular label name. That prevents matching the label // dimension with a different mix between preset and variable labels. - for _, labelName := range variableLabels { - if !checkLabelName(labelName) { - d.err = fmt.Errorf("%q is not a valid label name for metric %q", labelName, fqName) + for _, label := range d.variableLabels { + if !checkLabelName(label.Name) { + d.err = fmt.Errorf("%q is not a valid label name for metric %q", label.Name, fqName) return d } - labelNames = append(labelNames, "$"+labelName) - labelNameSet[labelName] = struct{}{} + labelNames = append(labelNames, "$"+label.Name) + labelNameSet[label.Name] = struct{}{} } if len(labelNames) != len(labelNameSet) { - d.err = errors.New("duplicate label names") + d.err = fmt.Errorf("duplicate label names in constant and variable labels for metric %q", fqName) return d } @@ -154,7 +167,7 @@ func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) * Value: proto.String(v), }) } - sort.Sort(labelPairSorter(d.constLabelPairs)) + sort.Sort(internal.LabelPairSorter(d.constLabelPairs)) return d } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/doc.go b/vendor/github.com/prometheus/client_golang/prometheus/doc.go index 98450125d6..962608f02c 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/doc.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/doc.go @@ -21,55 +21,66 @@ // All exported functions and methods are safe to be used concurrently unless // specified otherwise. // -// A Basic Example +// # A Basic Example // // As a starting point, a very basic usage example: // -// package main -// -// import ( -// "log" -// "net/http" -// -// "github.com/prometheus/client_golang/prometheus" -// "github.com/prometheus/client_golang/prometheus/promhttp" -// ) -// -// var ( -// cpuTemp = prometheus.NewGauge(prometheus.GaugeOpts{ -// Name: "cpu_temperature_celsius", -// Help: "Current temperature of the CPU.", -// }) -// hdFailures = prometheus.NewCounterVec( -// prometheus.CounterOpts{ -// Name: "hd_errors_total", -// Help: "Number of hard-disk errors.", -// }, -// []string{"device"}, -// ) -// ) -// -// func init() { -// // Metrics have to be registered to be exposed: -// prometheus.MustRegister(cpuTemp) -// prometheus.MustRegister(hdFailures) -// } -// -// func main() { -// cpuTemp.Set(65.3) -// hdFailures.With(prometheus.Labels{"device":"/dev/sda"}).Inc() -// -// // The Handler function provides a default handler to expose metrics -// // via an HTTP server. "/metrics" is the usual endpoint for that. -// http.Handle("/metrics", promhttp.Handler()) -// log.Fatal(http.ListenAndServe(":8080", nil)) -// } -// +// package main +// +// import ( +// "log" +// "net/http" +// +// "github.com/prometheus/client_golang/prometheus" +// "github.com/prometheus/client_golang/prometheus/promhttp" +// ) +// +// type metrics struct { +// cpuTemp prometheus.Gauge +// hdFailures *prometheus.CounterVec +// } +// +// func NewMetrics(reg prometheus.Registerer) *metrics { +// m := &metrics{ +// cpuTemp: prometheus.NewGauge(prometheus.GaugeOpts{ +// Name: "cpu_temperature_celsius", +// Help: "Current temperature of the CPU.", +// }), +// hdFailures: prometheus.NewCounterVec( +// prometheus.CounterOpts{ +// Name: "hd_errors_total", +// Help: "Number of hard-disk errors.", +// }, +// []string{"device"}, +// ), +// } +// reg.MustRegister(m.cpuTemp) +// reg.MustRegister(m.hdFailures) +// return m +// } +// +// func main() { +// // Create a non-global registry. +// reg := prometheus.NewRegistry() +// +// // Create new metrics and register them using the custom registry. +// m := NewMetrics(reg) +// // Set values for the new created metrics. +// m.cpuTemp.Set(65.3) +// m.hdFailures.With(prometheus.Labels{"device":"/dev/sda"}).Inc() +// +// // Expose metrics and custom registry via an HTTP server +// // using the HandleFor function. "/metrics" is the usual endpoint for that. +// http.Handle("/metrics", promhttp.HandlerFor(reg, promhttp.HandlerOpts{Registry: reg})) +// log.Fatal(http.ListenAndServe(":8080", nil)) +// } // // This is a complete program that exports two metrics, a Gauge and a Counter, // the latter with a label attached to turn it into a (one-dimensional) vector. +// It register the metrics using a custom registry and exposes them via an HTTP server +// on the /metrics endpoint. // -// Metrics +// # Metrics // // The number of exported identifiers in this package might appear a bit // overwhelming. However, in addition to the basic plumbing shown in the example @@ -100,7 +111,7 @@ // To create instances of Metrics and their vector versions, you need a suitable // …Opts struct, i.e. GaugeOpts, CounterOpts, SummaryOpts, or HistogramOpts. // -// Custom Collectors and constant Metrics +// # Custom Collectors and constant Metrics // // While you could create your own implementations of Metric, most likely you // will only ever implement the Collector interface on your own. At a first @@ -141,7 +152,7 @@ // a metric, GaugeFunc, CounterFunc, or UntypedFunc might be interesting // shortcuts. // -// Advanced Uses of the Registry +// # Advanced Uses of the Registry // // While MustRegister is the by far most common way of registering a Collector, // sometimes you might want to handle the errors the registration might cause. @@ -176,23 +187,23 @@ // NewProcessCollector). With a custom registry, you are in control and decide // yourself about the Collectors to register. // -// HTTP Exposition +// # HTTP Exposition // // The Registry implements the Gatherer interface. The caller of the Gather // method can then expose the gathered metrics in some way. Usually, the metrics // are served via HTTP on the /metrics endpoint. That's happening in the example // above. The tools to expose metrics via HTTP are in the promhttp sub-package. // -// Pushing to the Pushgateway +// # Pushing to the Pushgateway // // Function for pushing to the Pushgateway can be found in the push sub-package. // -// Graphite Bridge +// # Graphite Bridge // // Functions and examples to push metrics from a Gatherer to Graphite can be // found in the graphite sub-package. // -// Other Means of Exposition +// # Other Means of Exposition // // More ways of exposing metrics can easily be added by following the approaches // of the existing implementations. diff --git a/vendor/github.com/prometheus/client_golang/prometheus/gauge.go b/vendor/github.com/prometheus/client_golang/prometheus/gauge.go index bd0733d6a7..f1ea6c76f7 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/gauge.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/gauge.go @@ -55,6 +55,18 @@ type Gauge interface { // GaugeOpts is an alias for Opts. See there for doc comments. type GaugeOpts Opts +// GaugeVecOpts bundles the options to create a GaugeVec metric. +// It is mandatory to set GaugeOpts, see there for mandatory fields. VariableLabels +// is optional and can safely be left to its default value. +type GaugeVecOpts struct { + GaugeOpts + + // VariableLabels are used to partition the metric vector by the given set + // of labels. Each label value will be constrained with the optional Contraint + // function, if provided. + VariableLabels ConstrainableLabels +} + // NewGauge creates a new Gauge based on the provided GaugeOpts. // // The returned implementation is optimized for a fast Set method. If you have a @@ -138,16 +150,24 @@ type GaugeVec struct { // NewGaugeVec creates a new GaugeVec based on the provided GaugeOpts and // partitioned by the given label names. func NewGaugeVec(opts GaugeOpts, labelNames []string) *GaugeVec { - desc := NewDesc( + return V2.NewGaugeVec(GaugeVecOpts{ + GaugeOpts: opts, + VariableLabels: UnconstrainedLabels(labelNames), + }) +} + +// NewGaugeVec creates a new GaugeVec based on the provided GaugeVecOpts. +func (v2) NewGaugeVec(opts GaugeVecOpts) *GaugeVec { + desc := V2.NewDesc( BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), opts.Help, - labelNames, + opts.VariableLabels, opts.ConstLabels, ) return &GaugeVec{ MetricVec: NewMetricVec(desc, func(lvs ...string) Metric { if len(lvs) != len(desc.variableLabels) { - panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, lvs)) + panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels.labelNames(), lvs)) } result := &gauge{desc: desc, labelPairs: MakeLabelPairs(desc, lvs)} result.init(result) // Init self-collection. @@ -210,7 +230,8 @@ func (v *GaugeVec) GetMetricWith(labels Labels) (Gauge, error) { // WithLabelValues works as GetMetricWithLabelValues, but panics where // GetMetricWithLabelValues would have returned an error. Not returning an // error allows shortcuts like -// myVec.WithLabelValues("404", "GET").Add(42) +// +// myVec.WithLabelValues("404", "GET").Add(42) func (v *GaugeVec) WithLabelValues(lvs ...string) Gauge { g, err := v.GetMetricWithLabelValues(lvs...) if err != nil { @@ -221,7 +242,8 @@ func (v *GaugeVec) WithLabelValues(lvs ...string) Gauge { // With works as GetMetricWith, but panics where GetMetricWithLabels would have // returned an error. Not returning an error allows shortcuts like -// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Add(42) +// +// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Add(42) func (v *GaugeVec) With(labels Labels) Gauge { g, err := v.GetMetricWith(labels) if err != nil { diff --git a/vendor/github.com/prometheus/client_golang/prometheus/get_pid.go b/vendor/github.com/prometheus/client_golang/prometheus/get_pid.go new file mode 100644 index 0000000000..614fd61be9 --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/get_pid.go @@ -0,0 +1,26 @@ +// Copyright 2015 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !js || wasm +// +build !js wasm + +package prometheus + +import "os" + +func getPIDFn() func() (int, error) { + pid := os.Getpid() + return func() (int, error) { + return pid, nil + } +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/get_pid_gopherjs.go b/vendor/github.com/prometheus/client_golang/prometheus/get_pid_gopherjs.go new file mode 100644 index 0000000000..eaf8059ee1 --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/get_pid_gopherjs.go @@ -0,0 +1,23 @@ +// Copyright 2015 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build js && !wasm +// +build js,!wasm + +package prometheus + +func getPIDFn() func() (int, error) { + return func() (int, error) { + return 1, nil + } +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/go_collector.go b/vendor/github.com/prometheus/client_golang/prometheus/go_collector.go index 4d792aa29e..ad9a71a5e0 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/go_collector.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/go_collector.go @@ -19,6 +19,10 @@ import ( "time" ) +// goRuntimeMemStats provides the metrics initially provided by runtime.ReadMemStats. +// From Go 1.17 those similar (and better) statistics are provided by runtime/metrics, so +// while eval closure works on runtime.MemStats, the struct from Go 1.17+ is +// populated using runtime/metrics. func goRuntimeMemStats() memStatsMetrics { return memStatsMetrics{ { @@ -224,7 +228,7 @@ func newBaseGoCollector() baseGoCollector { "A summary of the pause duration of garbage collection cycles.", nil, nil), gcLastTimeDesc: NewDesc( - memstatNamespace("last_gc_time_seconds"), + "go_memstats_last_gc_time_seconds", "Number of seconds since 1970 of last garbage collection.", nil, nil), goInfoDesc: NewDesc( @@ -246,8 +250,9 @@ func (c *baseGoCollector) Describe(ch chan<- *Desc) { // Collect returns the current state of all metrics of the collector. func (c *baseGoCollector) Collect(ch chan<- Metric) { ch <- MustNewConstMetric(c.goroutinesDesc, GaugeValue, float64(runtime.NumGoroutine())) - n, _ := runtime.ThreadCreateProfile(nil) - ch <- MustNewConstMetric(c.threadsDesc, GaugeValue, float64(n)) + + n := getRuntimeNumThreads() + ch <- MustNewConstMetric(c.threadsDesc, GaugeValue, n) var stats debug.GCStats stats.PauseQuantiles = make([]time.Duration, 5) @@ -269,7 +274,6 @@ func memstatNamespace(s string) string { // memStatsMetrics provide description, evaluator, runtime/metrics name, and // value type for memstat metrics. -// TODO(bwplotka): Remove with end Go 1.16 EOL and replace with runtime/metrics.Description type memStatsMetrics []struct { desc *Desc eval func(*runtime.MemStats) float64 diff --git a/vendor/github.com/prometheus/client_golang/prometheus/go_collector_latest.go b/vendor/github.com/prometheus/client_golang/prometheus/go_collector_latest.go index a0fe95eb11..2d8d9f64f4 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/go_collector_latest.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/go_collector_latest.go @@ -23,17 +23,18 @@ import ( "strings" "sync" - //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility. - "github.com/golang/protobuf/proto" - dto "github.com/prometheus/client_model/go" - "github.com/prometheus/client_golang/prometheus/internal" + + dto "github.com/prometheus/client_model/go" + "google.golang.org/protobuf/proto" ) const ( + // constants for strings referenced more than once. goGCHeapTinyAllocsObjects = "/gc/heap/tiny/allocs:objects" goGCHeapAllocsObjects = "/gc/heap/allocs:objects" goGCHeapFreesObjects = "/gc/heap/frees:objects" + goGCHeapFreesBytes = "/gc/heap/frees:bytes" goGCHeapAllocsBytes = "/gc/heap/allocs:bytes" goGCHeapObjects = "/gc/heap/objects:objects" goGCHeapGoalBytes = "/gc/heap/goal:bytes" @@ -53,8 +54,9 @@ const ( goMemoryClassesOtherBytes = "/memory/classes/other:bytes" ) -// runtime/metrics names required for runtimeMemStats like logic. -var rmForMemStats = []string{goGCHeapTinyAllocsObjects, +// rmNamesForMemStatsMetrics represents runtime/metrics names required to populate goRuntimeMemStats from like logic. +var rmNamesForMemStatsMetrics = []string{ + goGCHeapTinyAllocsObjects, goGCHeapAllocsObjects, goGCHeapFreesObjects, goGCHeapAllocsBytes, @@ -89,74 +91,90 @@ func bestEffortLookupRM(lookup []string) []metrics.Description { } type goCollector struct { - opt GoCollectorOptions base baseGoCollector // mu protects updates to all fields ensuring a consistent // snapshot is always produced by Collect. mu sync.Mutex - // rm... fields all pertain to the runtime/metrics package. - rmSampleBuf []metrics.Sample - rmSampleMap map[string]*metrics.Sample - rmMetrics []collectorMetric + // Contains all samples that has to retrieved from runtime/metrics (not all of them will be exposed). + sampleBuf []metrics.Sample + // sampleMap allows lookup for MemStats metrics and runtime/metrics histograms for exact sums. + sampleMap map[string]*metrics.Sample + + // rmExposedMetrics represents all runtime/metrics package metrics + // that were configured to be exposed. + rmExposedMetrics []collectorMetric + rmExactSumMapForHist map[string]string // With Go 1.17, the runtime/metrics package was introduced. // From that point on, metric names produced by the runtime/metrics // package could be generated from runtime/metrics names. However, // these differ from the old names for the same values. // - // This field exist to export the same values under the old names + // This field exists to export the same values under the old names // as well. - msMetrics memStatsMetrics + msMetrics memStatsMetrics + msMetricsEnabled bool } -const ( - // Those are not exposed due to need to move Go collector to another package in v2. - // See issue https://github.com/prometheus/client_golang/issues/1030. - goRuntimeMemStatsCollection uint32 = 1 << iota - goRuntimeMetricsCollection -) - -// GoCollectorOptions should not be used be directly by anything, except `collectors` package. -// Use it via collectors package instead. See issue -// https://github.com/prometheus/client_golang/issues/1030. -// -// Deprecated: Use collectors.WithGoCollections -type GoCollectorOptions struct { - // EnabledCollection sets what type of collections collector should expose on top of base collection. - // By default it's goMemStatsCollection | goRuntimeMetricsCollection. - EnabledCollections uint32 +type rmMetricDesc struct { + metrics.Description } -func (c GoCollectorOptions) isEnabled(flag uint32) bool { - return c.EnabledCollections&flag != 0 +func matchRuntimeMetricsRules(rules []internal.GoCollectorRule) []rmMetricDesc { + var descs []rmMetricDesc + for _, d := range metrics.All() { + var ( + deny = true + desc rmMetricDesc + ) + + for _, r := range rules { + if !r.Matcher.MatchString(d.Name) { + continue + } + deny = r.Deny + } + if deny { + continue + } + + desc.Description = d + descs = append(descs, desc) + } + return descs } -const defaultGoCollections = goRuntimeMemStatsCollection +func defaultGoCollectorOptions() internal.GoCollectorOptions { + return internal.GoCollectorOptions{ + RuntimeMetricSumForHist: map[string]string{ + "/gc/heap/allocs-by-size:bytes": goGCHeapAllocsBytes, + "/gc/heap/frees-by-size:bytes": goGCHeapFreesBytes, + }, + RuntimeMetricRules: []internal.GoCollectorRule{ + //{Matcher: regexp.MustCompile("")}, + }, + } +} // NewGoCollector is the obsolete version of collectors.NewGoCollector. // See there for documentation. // // Deprecated: Use collectors.NewGoCollector instead. -func NewGoCollector(opts ...func(o *GoCollectorOptions)) Collector { - opt := GoCollectorOptions{EnabledCollections: defaultGoCollections} +func NewGoCollector(opts ...func(o *internal.GoCollectorOptions)) Collector { + opt := defaultGoCollectorOptions() for _, o := range opts { o(&opt) } - var descriptions []metrics.Description - if opt.isEnabled(goRuntimeMetricsCollection) { - descriptions = metrics.All() - } else if opt.isEnabled(goRuntimeMemStatsCollection) { - descriptions = bestEffortLookupRM(rmForMemStats) - } + exposedDescriptions := matchRuntimeMetricsRules(opt.RuntimeMetricRules) // Collect all histogram samples so that we can get their buckets. // The API guarantees that the buckets are always fixed for the lifetime // of the process. var histograms []metrics.Sample - for _, d := range descriptions { + for _, d := range exposedDescriptions { if d.Kind == metrics.KindFloat64Histogram { histograms = append(histograms, metrics.Sample{Name: d.Name}) } @@ -171,13 +189,14 @@ func NewGoCollector(opts ...func(o *GoCollectorOptions)) Collector { bucketsMap[histograms[i].Name] = histograms[i].Value.Float64Histogram().Buckets } - // Generate a Desc and ValueType for each runtime/metrics metric. - metricSet := make([]collectorMetric, 0, len(descriptions)) - sampleBuf := make([]metrics.Sample, 0, len(descriptions)) - sampleMap := make(map[string]*metrics.Sample, len(descriptions)) - for i := range descriptions { - d := &descriptions[i] - namespace, subsystem, name, ok := internal.RuntimeMetricsToProm(d) + // Generate a collector for each exposed runtime/metrics metric. + metricSet := make([]collectorMetric, 0, len(exposedDescriptions)) + // SampleBuf is used for reading from runtime/metrics. + // We are assuming the largest case to have stable pointers for sampleMap purposes. + sampleBuf := make([]metrics.Sample, 0, len(exposedDescriptions)+len(opt.RuntimeMetricSumForHist)+len(rmNamesForMemStatsMetrics)) + sampleMap := make(map[string]*metrics.Sample, len(exposedDescriptions)) + for _, d := range exposedDescriptions { + namespace, subsystem, name, ok := internal.RuntimeMetricsToProm(&d.Description) if !ok { // Just ignore this metric; we can't do anything with it here. // If a user decides to use the latest version of Go, we don't want @@ -185,19 +204,17 @@ func NewGoCollector(opts ...func(o *GoCollectorOptions)) Collector { continue } - // Set up sample buffer for reading, and a map - // for quick lookup of sample values. sampleBuf = append(sampleBuf, metrics.Sample{Name: d.Name}) sampleMap[d.Name] = &sampleBuf[len(sampleBuf)-1] var m collectorMetric if d.Kind == metrics.KindFloat64Histogram { - _, hasSum := rmExactSumMap[d.Name] + _, hasSum := opt.RuntimeMetricSumForHist[d.Name] unit := d.Name[strings.IndexRune(d.Name, ':')+1:] m = newBatchHistogram( NewDesc( BuildFQName(namespace, subsystem, name), - d.Description, + d.Description.Description, nil, nil, ), @@ -209,30 +226,61 @@ func NewGoCollector(opts ...func(o *GoCollectorOptions)) Collector { Namespace: namespace, Subsystem: subsystem, Name: name, - Help: d.Description, - }) + Help: d.Description.Description, + }, + ) } else { m = NewGauge(GaugeOpts{ Namespace: namespace, Subsystem: subsystem, Name: name, - Help: d.Description, + Help: d.Description.Description, }) } metricSet = append(metricSet, m) } - var msMetrics memStatsMetrics - if opt.isEnabled(goRuntimeMemStatsCollection) { + // Add exact sum metrics to sampleBuf if not added before. + for _, h := range histograms { + sumMetric, ok := opt.RuntimeMetricSumForHist[h.Name] + if !ok { + continue + } + + if _, ok := sampleMap[sumMetric]; ok { + continue + } + sampleBuf = append(sampleBuf, metrics.Sample{Name: sumMetric}) + sampleMap[sumMetric] = &sampleBuf[len(sampleBuf)-1] + } + + var ( + msMetrics memStatsMetrics + msDescriptions []metrics.Description + ) + + if !opt.DisableMemStatsLikeMetrics { msMetrics = goRuntimeMemStats() + msDescriptions = bestEffortLookupRM(rmNamesForMemStatsMetrics) + + // Check if metric was not exposed before and if not, add to sampleBuf. + for _, mdDesc := range msDescriptions { + if _, ok := sampleMap[mdDesc.Name]; ok { + continue + } + sampleBuf = append(sampleBuf, metrics.Sample{Name: mdDesc.Name}) + sampleMap[mdDesc.Name] = &sampleBuf[len(sampleBuf)-1] + } } + return &goCollector{ - opt: opt, - base: newBaseGoCollector(), - rmSampleBuf: sampleBuf, - rmSampleMap: sampleMap, - rmMetrics: metricSet, - msMetrics: msMetrics, + base: newBaseGoCollector(), + sampleBuf: sampleBuf, + sampleMap: sampleMap, + rmExposedMetrics: metricSet, + rmExactSumMapForHist: opt.RuntimeMetricSumForHist, + msMetrics: msMetrics, + msMetricsEnabled: !opt.DisableMemStatsLikeMetrics, } } @@ -242,7 +290,7 @@ func (c *goCollector) Describe(ch chan<- *Desc) { for _, i := range c.msMetrics { ch <- i.desc } - for _, m := range c.rmMetrics { + for _, m := range c.rmExposedMetrics { ch <- m.Desc() } } @@ -252,8 +300,12 @@ func (c *goCollector) Collect(ch chan<- Metric) { // Collect base non-memory metrics. c.base.Collect(ch) + if len(c.sampleBuf) == 0 { + return + } + // Collect must be thread-safe, so prevent concurrent use of - // rmSampleBuf. Just read into rmSampleBuf but write all the data + // sampleBuf elements. Just read into sampleBuf but write all the data // we get into our Metrics or MemStats. // // This lock also ensures that the Metrics we send out are all from @@ -267,44 +319,43 @@ func (c *goCollector) Collect(ch chan<- Metric) { c.mu.Lock() defer c.mu.Unlock() - if len(c.rmSampleBuf) > 0 { - // Populate runtime/metrics sample buffer. - metrics.Read(c.rmSampleBuf) - } - - if c.opt.isEnabled(goRuntimeMetricsCollection) { - // Collect all our metrics from rmSampleBuf. - for i, sample := range c.rmSampleBuf { - // N.B. switch on concrete type because it's significantly more efficient - // than checking for the Counter and Gauge interface implementations. In - // this case, we control all the types here. - switch m := c.rmMetrics[i].(type) { - case *counter: - // Guard against decreases. This should never happen, but a failure - // to do so will result in a panic, which is a harsh consequence for - // a metrics collection bug. - v0, v1 := m.get(), unwrapScalarRMValue(sample.Value) - if v1 > v0 { - m.Add(unwrapScalarRMValue(sample.Value) - m.get()) - } - m.Collect(ch) - case *gauge: - m.Set(unwrapScalarRMValue(sample.Value)) - m.Collect(ch) - case *batchHistogram: - m.update(sample.Value.Float64Histogram(), c.exactSumFor(sample.Name)) - m.Collect(ch) - default: - panic("unexpected metric type") + // Populate runtime/metrics sample buffer. + metrics.Read(c.sampleBuf) + + // Collect all our runtime/metrics user chose to expose from sampleBuf (if any). + for i, metric := range c.rmExposedMetrics { + // We created samples for exposed metrics first in order, so indexes match. + sample := c.sampleBuf[i] + + // N.B. switch on concrete type because it's significantly more efficient + // than checking for the Counter and Gauge interface implementations. In + // this case, we control all the types here. + switch m := metric.(type) { + case *counter: + // Guard against decreases. This should never happen, but a failure + // to do so will result in a panic, which is a harsh consequence for + // a metrics collection bug. + v0, v1 := m.get(), unwrapScalarRMValue(sample.Value) + if v1 > v0 { + m.Add(unwrapScalarRMValue(sample.Value) - m.get()) } + m.Collect(ch) + case *gauge: + m.Set(unwrapScalarRMValue(sample.Value)) + m.Collect(ch) + case *batchHistogram: + m.update(sample.Value.Float64Histogram(), c.exactSumFor(sample.Name)) + m.Collect(ch) + default: + panic("unexpected metric type") } } - // ms is a dummy MemStats that we populate ourselves so that we can - // populate the old metrics from it if goMemStatsCollection is enabled. - if c.opt.isEnabled(goRuntimeMemStatsCollection) { + if c.msMetricsEnabled { + // ms is a dummy MemStats that we populate ourselves so that we can + // populate the old metrics from it if goMemStatsCollection is enabled. var ms runtime.MemStats - memStatsFromRM(&ms, c.rmSampleMap) + memStatsFromRM(&ms, c.sampleMap) for _, i := range c.msMetrics { ch <- MustNewConstMetric(i.desc, i.valType, i.eval(&ms)) } @@ -335,11 +386,6 @@ func unwrapScalarRMValue(v metrics.Value) float64 { } } -var rmExactSumMap = map[string]string{ - "/gc/heap/allocs-by-size:bytes": "/gc/heap/allocs:bytes", - "/gc/heap/frees-by-size:bytes": "/gc/heap/frees:bytes", -} - // exactSumFor takes a runtime/metrics metric name (that is assumed to // be of kind KindFloat64Histogram) and returns its exact sum and whether // its exact sum exists. @@ -347,11 +393,11 @@ var rmExactSumMap = map[string]string{ // The runtime/metrics API for histograms doesn't currently expose exact // sums, but some of the other metrics are in fact exact sums of histograms. func (c *goCollector) exactSumFor(rmName string) float64 { - sumName, ok := rmExactSumMap[rmName] + sumName, ok := c.rmExactSumMapForHist[rmName] if !ok { return 0 } - s, ok := c.rmSampleMap[sumName] + s, ok := c.sampleMap[sumName] if !ok { return 0 } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/histogram.go b/vendor/github.com/prometheus/client_golang/prometheus/histogram.go index 893802fd6b..5b69965b25 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/histogram.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/histogram.go @@ -22,25 +22,221 @@ import ( "sync/atomic" "time" - //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility. - "github.com/golang/protobuf/proto" - dto "github.com/prometheus/client_model/go" + + "google.golang.org/protobuf/proto" ) +// nativeHistogramBounds for the frac of observed values. Only relevant for +// schema > 0. The position in the slice is the schema. (0 is never used, just +// here for convenience of using the schema directly as the index.) +// +// TODO(beorn7): Currently, we do a binary search into these slices. There are +// ways to turn it into a small number of simple array lookups. It probably only +// matters for schema 5 and beyond, but should be investigated. See this comment +// as a starting point: +// https://github.com/open-telemetry/opentelemetry-specification/issues/1776#issuecomment-870164310 +var nativeHistogramBounds = [][]float64{ + // Schema "0": + {0.5}, + // Schema 1: + {0.5, 0.7071067811865475}, + // Schema 2: + {0.5, 0.5946035575013605, 0.7071067811865475, 0.8408964152537144}, + // Schema 3: + { + 0.5, 0.5452538663326288, 0.5946035575013605, 0.6484197773255048, + 0.7071067811865475, 0.7711054127039704, 0.8408964152537144, 0.9170040432046711, + }, + // Schema 4: + { + 0.5, 0.5221368912137069, 0.5452538663326288, 0.5693943173783458, + 0.5946035575013605, 0.620928906036742, 0.6484197773255048, 0.6771277734684463, + 0.7071067811865475, 0.7384130729697496, 0.7711054127039704, 0.805245165974627, + 0.8408964152537144, 0.8781260801866495, 0.9170040432046711, 0.9576032806985735, + }, + // Schema 5: + { + 0.5, 0.5109485743270583, 0.5221368912137069, 0.5335702003384117, + 0.5452538663326288, 0.5571933712979462, 0.5693943173783458, 0.5818624293887887, + 0.5946035575013605, 0.6076236799902344, 0.620928906036742, 0.6345254785958666, + 0.6484197773255048, 0.6626183215798706, 0.6771277734684463, 0.6919549409819159, + 0.7071067811865475, 0.7225904034885232, 0.7384130729697496, 0.7545822137967112, + 0.7711054127039704, 0.7879904225539431, 0.805245165974627, 0.8228777390769823, + 0.8408964152537144, 0.8593096490612387, 0.8781260801866495, 0.8973545375015533, + 0.9170040432046711, 0.9370838170551498, 0.9576032806985735, 0.9785720620876999, + }, + // Schema 6: + { + 0.5, 0.5054446430258502, 0.5109485743270583, 0.5165124395106142, + 0.5221368912137069, 0.5278225891802786, 0.5335702003384117, 0.5393803988785598, + 0.5452538663326288, 0.5511912916539204, 0.5571933712979462, 0.5632608093041209, + 0.5693943173783458, 0.5755946149764913, 0.5818624293887887, 0.5881984958251406, + 0.5946035575013605, 0.6010783657263515, 0.6076236799902344, 0.6142402680534349, + 0.620928906036742, 0.6276903785123455, 0.6345254785958666, 0.6414350080393891, + 0.6484197773255048, 0.6554806057623822, 0.6626183215798706, 0.6698337620266515, + 0.6771277734684463, 0.6845012114872953, 0.6919549409819159, 0.6994898362691555, + 0.7071067811865475, 0.7148066691959849, 0.7225904034885232, 0.7304588970903234, + 0.7384130729697496, 0.7464538641456323, 0.7545822137967112, 0.762799075372269, + 0.7711054127039704, 0.7795022001189185, 0.7879904225539431, 0.7965710756711334, + 0.805245165974627, 0.8140137109286738, 0.8228777390769823, 0.8318382901633681, + 0.8408964152537144, 0.8500531768592616, 0.8593096490612387, 0.8686669176368529, + 0.8781260801866495, 0.8876882462632604, 0.8973545375015533, 0.9071260877501991, + 0.9170040432046711, 0.9269895625416926, 0.9370838170551498, 0.9472879907934827, + 0.9576032806985735, 0.9680308967461471, 0.9785720620876999, 0.9892280131939752, + }, + // Schema 7: + { + 0.5, 0.5027149505564014, 0.5054446430258502, 0.5081891574554764, + 0.5109485743270583, 0.5137229745593818, 0.5165124395106142, 0.5193170509806894, + 0.5221368912137069, 0.5249720429003435, 0.5278225891802786, 0.5306886136446309, + 0.5335702003384117, 0.5364674337629877, 0.5393803988785598, 0.5423091811066545, + 0.5452538663326288, 0.5482145409081883, 0.5511912916539204, 0.5541842058618393, + 0.5571933712979462, 0.5602188762048033, 0.5632608093041209, 0.5663192597993595, + 0.5693943173783458, 0.572486072215902, 0.5755946149764913, 0.5787200368168754, + 0.5818624293887887, 0.585021884841625, 0.5881984958251406, 0.5913923554921704, + 0.5946035575013605, 0.5978321960199137, 0.6010783657263515, 0.6043421618132907, + 0.6076236799902344, 0.6109230164863786, 0.6142402680534349, 0.6175755319684665, + 0.620928906036742, 0.6243004885946023, 0.6276903785123455, 0.6310986751971253, + 0.6345254785958666, 0.637970889198196, 0.6414350080393891, 0.6449179367033329, + 0.6484197773255048, 0.6519406325959679, 0.6554806057623822, 0.659039800633032, + 0.6626183215798706, 0.6662162735415805, 0.6698337620266515, 0.6734708931164728, + 0.6771277734684463, 0.6808045103191123, 0.6845012114872953, 0.688217985377265, + 0.6919549409819159, 0.6957121878859629, 0.6994898362691555, 0.7032879969095076, + 0.7071067811865475, 0.7109463010845827, 0.7148066691959849, 0.718687998724491, + 0.7225904034885232, 0.7265139979245261, 0.7304588970903234, 0.7344252166684908, + 0.7384130729697496, 0.7424225829363761, 0.7464538641456323, 0.7505070348132126, + 0.7545822137967112, 0.7586795205991071, 0.762799075372269, 0.7669409989204777, + 0.7711054127039704, 0.7752924388424999, 0.7795022001189185, 0.7837348199827764, + 0.7879904225539431, 0.7922691326262467, 0.7965710756711334, 0.8008963778413465, + 0.805245165974627, 0.8096175675974316, 0.8140137109286738, 0.8184337248834821, + 0.8228777390769823, 0.8273458838280969, 0.8318382901633681, 0.8363550898207981, + 0.8408964152537144, 0.8454623996346523, 0.8500531768592616, 0.8546688815502312, + 0.8593096490612387, 0.8639756154809185, 0.8686669176368529, 0.8733836930995842, + 0.8781260801866495, 0.8828942179666361, 0.8876882462632604, 0.8925083056594671, + 0.8973545375015533, 0.9022270839033115, 0.9071260877501991, 0.9120516927035263, + 0.9170040432046711, 0.9219832844793128, 0.9269895625416926, 0.9320230241988943, + 0.9370838170551498, 0.9421720895161669, 0.9472879907934827, 0.9524316709088368, + 0.9576032806985735, 0.9628029718180622, 0.9680308967461471, 0.9732872087896164, + 0.9785720620876999, 0.9838856116165875, 0.9892280131939752, 0.9945994234836328, + }, + // Schema 8: + { + 0.5, 0.5013556375251013, 0.5027149505564014, 0.5040779490592088, + 0.5054446430258502, 0.5068150424757447, 0.5081891574554764, 0.509566998038869, + 0.5109485743270583, 0.5123338964485679, 0.5137229745593818, 0.5151158188430205, + 0.5165124395106142, 0.5179128468009786, 0.5193170509806894, 0.520725062344158, + 0.5221368912137069, 0.5235525479396449, 0.5249720429003435, 0.526395386502313, + 0.5278225891802786, 0.5292536613972564, 0.5306886136446309, 0.5321274564422321, + 0.5335702003384117, 0.5350168559101208, 0.5364674337629877, 0.5379219445313954, + 0.5393803988785598, 0.5408428074966075, 0.5423091811066545, 0.5437795304588847, + 0.5452538663326288, 0.5467321995364429, 0.5482145409081883, 0.549700901315111, + 0.5511912916539204, 0.5526857228508706, 0.5541842058618393, 0.5556867516724088, + 0.5571933712979462, 0.5587040757836845, 0.5602188762048033, 0.5617377836665098, + 0.5632608093041209, 0.564787964283144, 0.5663192597993595, 0.5678547070789026, + 0.5693943173783458, 0.5709381019847808, 0.572486072215902, 0.5740382394200894, + 0.5755946149764913, 0.5771552102951081, 0.5787200368168754, 0.5802891060137493, + 0.5818624293887887, 0.5834400184762408, 0.585021884841625, 0.5866080400818185, + 0.5881984958251406, 0.5897932637314379, 0.5913923554921704, 0.5929957828304968, + 0.5946035575013605, 0.5962156912915756, 0.5978321960199137, 0.5994530835371903, + 0.6010783657263515, 0.6027080545025619, 0.6043421618132907, 0.6059806996384005, + 0.6076236799902344, 0.6092711149137041, 0.6109230164863786, 0.6125793968185725, + 0.6142402680534349, 0.6159056423670379, 0.6175755319684665, 0.6192499490999082, + 0.620928906036742, 0.622612415087629, 0.6243004885946023, 0.6259931389331581, + 0.6276903785123455, 0.6293922197748583, 0.6310986751971253, 0.6328097572894031, + 0.6345254785958666, 0.6362458516947014, 0.637970889198196, 0.6397006037528346, + 0.6414350080393891, 0.6431741147730128, 0.6449179367033329, 0.6466664866145447, + 0.6484197773255048, 0.6501778216898253, 0.6519406325959679, 0.6537082229673385, + 0.6554806057623822, 0.6572577939746774, 0.659039800633032, 0.6608266388015788, + 0.6626183215798706, 0.6644148621029772, 0.6662162735415805, 0.6680225691020727, + 0.6698337620266515, 0.6716498655934177, 0.6734708931164728, 0.6752968579460171, + 0.6771277734684463, 0.6789636531064505, 0.6808045103191123, 0.6826503586020058, + 0.6845012114872953, 0.6863570825438342, 0.688217985377265, 0.690083933630119, + 0.6919549409819159, 0.6938310211492645, 0.6957121878859629, 0.6975984549830999, + 0.6994898362691555, 0.7013863456101023, 0.7032879969095076, 0.7051948041086352, + 0.7071067811865475, 0.7090239421602076, 0.7109463010845827, 0.7128738720527471, + 0.7148066691959849, 0.7167447066838943, 0.718687998724491, 0.7206365595643126, + 0.7225904034885232, 0.7245495448210174, 0.7265139979245261, 0.7284837772007218, + 0.7304588970903234, 0.7324393720732029, 0.7344252166684908, 0.7364164454346837, + 0.7384130729697496, 0.7404151139112358, 0.7424225829363761, 0.7444354947621984, + 0.7464538641456323, 0.7484777058836176, 0.7505070348132126, 0.7525418658117031, + 0.7545822137967112, 0.7566280937263048, 0.7586795205991071, 0.7607365094544071, + 0.762799075372269, 0.7648672334736434, 0.7669409989204777, 0.7690203869158282, + 0.7711054127039704, 0.7731960915705107, 0.7752924388424999, 0.7773944698885442, + 0.7795022001189185, 0.7816156449856788, 0.7837348199827764, 0.7858597406461707, + 0.7879904225539431, 0.7901268813264122, 0.7922691326262467, 0.7944171921585818, + 0.7965710756711334, 0.7987307989543135, 0.8008963778413465, 0.8030678282083853, + 0.805245165974627, 0.8074284071024302, 0.8096175675974316, 0.8118126635086642, + 0.8140137109286738, 0.8162207259936375, 0.8184337248834821, 0.820652723822003, + 0.8228777390769823, 0.8251087869603088, 0.8273458838280969, 0.8295890460808079, + 0.8318382901633681, 0.8340936325652911, 0.8363550898207981, 0.8386226785089391, + 0.8408964152537144, 0.8431763167241966, 0.8454623996346523, 0.8477546807446661, + 0.8500531768592616, 0.8523579048290255, 0.8546688815502312, 0.8569861239649629, + 0.8593096490612387, 0.8616394738731368, 0.8639756154809185, 0.8663180910111553, + 0.8686669176368529, 0.871022112577578, 0.8733836930995842, 0.8757516765159389, + 0.8781260801866495, 0.8805069215187917, 0.8828942179666361, 0.8852879870317771, + 0.8876882462632604, 0.890095013257712, 0.8925083056594671, 0.8949281411607002, + 0.8973545375015533, 0.8997875124702672, 0.9022270839033115, 0.9046732696855155, + 0.9071260877501991, 0.909585556079304, 0.9120516927035263, 0.9145245157024483, + 0.9170040432046711, 0.9194902933879467, 0.9219832844793128, 0.9244830347552253, + 0.9269895625416926, 0.92950288621441, 0.9320230241988943, 0.9345499949706191, + 0.9370838170551498, 0.93962450902828, 0.9421720895161669, 0.9447265771954693, + 0.9472879907934827, 0.9498563490882775, 0.9524316709088368, 0.9550139751351947, + 0.9576032806985735, 0.9601996065815236, 0.9628029718180622, 0.9654133954938133, + 0.9680308967461471, 0.9706554947643201, 0.9732872087896164, 0.9759260581154889, + 0.9785720620876999, 0.9812252401044634, 0.9838856116165875, 0.9865531961276168, + 0.9892280131939752, 0.9919100824251095, 0.9945994234836328, 0.9972960560854698, + }, +} + +// The nativeHistogramBounds above can be generated with the code below. +// +// TODO(beorn7): It's tempting to actually use `go generate` to generate the +// code above. However, this could lead to slightly different numbers on +// different architectures. We still need to come to terms if we are fine with +// that, or if we might prefer to specify precise numbers in the standard. +// +// var nativeHistogramBounds [][]float64 = make([][]float64, 9) +// +// func init() { +// // Populate nativeHistogramBounds. +// numBuckets := 1 +// for i := range nativeHistogramBounds { +// bounds := []float64{0.5} +// factor := math.Exp2(math.Exp2(float64(-i))) +// for j := 0; j < numBuckets-1; j++ { +// var bound float64 +// if (j+1)%2 == 0 { +// // Use previously calculated value for increased precision. +// bound = nativeHistogramBounds[i-1][j/2+1] +// } else { +// bound = bounds[j] * factor +// } +// bounds = append(bounds, bound) +// } +// numBuckets *= 2 +// nativeHistogramBounds[i] = bounds +// } +// } + // A Histogram counts individual observations from an event or sample stream in -// configurable buckets. Similar to a summary, it also provides a sum of -// observations and an observation count. +// configurable static buckets (or in dynamic sparse buckets as part of the +// experimental Native Histograms, see below for more details). Similar to a +// Summary, it also provides a sum of observations and an observation count. // // On the Prometheus server, quantiles can be calculated from a Histogram using -// the histogram_quantile function in the query language. +// the histogram_quantile PromQL function. // -// Note that Histograms, in contrast to Summaries, can be aggregated with the -// Prometheus query language (see the documentation for detailed -// procedures). However, Histograms require the user to pre-define suitable -// buckets, and they are in general less accurate. The Observe method of a -// Histogram has a very low performance overhead in comparison with the Observe -// method of a Summary. +// Note that Histograms, in contrast to Summaries, can be aggregated in PromQL +// (see the documentation for detailed procedures). However, Histograms require +// the user to pre-define suitable buckets, and they are in general less +// accurate. (Both problems are addressed by the experimental Native +// Histograms. To use them, configure a NativeHistogramBucketFactor in the +// HistogramOpts. They also require a Prometheus server v2.40+ with the +// corresponding feature flag enabled.) +// +// The Observe method of a Histogram has a very low performance overhead in +// comparison with the Observe method of a Summary. // // To create Histogram instances, use NewHistogram. type Histogram interface { @@ -50,7 +246,8 @@ type Histogram interface { // Observe adds a single observation to the histogram. Observations are // usually positive or zero. Negative observations are accepted but // prevent current versions of Prometheus from properly detecting - // counter resets in the sum of observations. See + // counter resets in the sum of observations. (The experimental Native + // Histograms handle negative observations properly.) See // https://prometheus.io/docs/practices/histograms/#count-and-sum-of-observations // for details. Observe(float64) @@ -64,18 +261,28 @@ const bucketLabel = "le" // tailored to broadly measure the response time (in seconds) of a network // service. Most likely, however, you will be required to define buckets // customized to your use case. -var ( - DefBuckets = []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10} +var DefBuckets = []float64{.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5, 10} - errBucketLabelNotAllowed = fmt.Errorf( - "%q is not allowed as label name in histograms", bucketLabel, - ) +// DefNativeHistogramZeroThreshold is the default value for +// NativeHistogramZeroThreshold in the HistogramOpts. +// +// The value is 2^-128 (or 0.5*2^-127 in the actual IEEE 754 representation), +// which is a bucket boundary at all possible resolutions. +const DefNativeHistogramZeroThreshold = 2.938735877055719e-39 + +// NativeHistogramZeroThresholdZero can be used as NativeHistogramZeroThreshold +// in the HistogramOpts to create a zero bucket of width zero, i.e. a zero +// bucket that only receives observations of precisely zero. +const NativeHistogramZeroThresholdZero = -1 + +var errBucketLabelNotAllowed = fmt.Errorf( + "%q is not allowed as label name in histograms", bucketLabel, ) -// LinearBuckets creates 'count' buckets, each 'width' wide, where the lowest -// bucket has an upper bound of 'start'. The final +Inf bucket is not counted -// and not included in the returned slice. The returned slice is meant to be -// used for the Buckets field of HistogramOpts. +// LinearBuckets creates 'count' regular buckets, each 'width' wide, where the +// lowest bucket has an upper bound of 'start'. The final +Inf bucket is not +// counted and not included in the returned slice. The returned slice is meant +// to be used for the Buckets field of HistogramOpts. // // The function panics if 'count' is zero or negative. func LinearBuckets(start, width float64, count int) []float64 { @@ -90,11 +297,11 @@ func LinearBuckets(start, width float64, count int) []float64 { return buckets } -// ExponentialBuckets creates 'count' buckets, where the lowest bucket has an -// upper bound of 'start' and each following bucket's upper bound is 'factor' -// times the previous bucket's upper bound. The final +Inf bucket is not counted -// and not included in the returned slice. The returned slice is meant to be -// used for the Buckets field of HistogramOpts. +// ExponentialBuckets creates 'count' regular buckets, where the lowest bucket +// has an upper bound of 'start' and each following bucket's upper bound is +// 'factor' times the previous bucket's upper bound. The final +Inf bucket is +// not counted and not included in the returned slice. The returned slice is +// meant to be used for the Buckets field of HistogramOpts. // // The function panics if 'count' is 0 or negative, if 'start' is 0 or negative, // or if 'factor' is less than or equal 1. @@ -180,8 +387,97 @@ type HistogramOpts struct { // element in the slice is the upper inclusive bound of a bucket. The // values must be sorted in strictly increasing order. There is no need // to add a highest bucket with +Inf bound, it will be added - // implicitly. The default value is DefBuckets. + // implicitly. If Buckets is left as nil or set to a slice of length + // zero, it is replaced by default buckets. The default buckets are + // DefBuckets if no buckets for a native histogram (see below) are used, + // otherwise the default is no buckets. (In other words, if you want to + // use both reguler buckets and buckets for a native histogram, you have + // to define the regular buckets here explicitly.) Buckets []float64 + + // If NativeHistogramBucketFactor is greater than one, so-called sparse + // buckets are used (in addition to the regular buckets, if defined + // above). A Histogram with sparse buckets will be ingested as a Native + // Histogram by a Prometheus server with that feature enabled (requires + // Prometheus v2.40+). Sparse buckets are exponential buckets covering + // the whole float64 range (with the exception of the “zero” bucket, see + // SparseBucketsZeroThreshold below). From any one bucket to the next, + // the width of the bucket grows by a constant + // factor. NativeHistogramBucketFactor provides an upper bound for this + // factor (exception see below). The smaller + // NativeHistogramBucketFactor, the more buckets will be used and thus + // the more costly the histogram will become. A generally good trade-off + // between cost and accuracy is a value of 1.1 (each bucket is at most + // 10% wider than the previous one), which will result in each power of + // two divided into 8 buckets (e.g. there will be 8 buckets between 1 + // and 2, same as between 2 and 4, and 4 and 8, etc.). + // + // Details about the actually used factor: The factor is calculated as + // 2^(2^n), where n is an integer number between (and including) -8 and + // 4. n is chosen so that the resulting factor is the largest that is + // still smaller or equal to NativeHistogramBucketFactor. Note that the + // smallest possible factor is therefore approx. 1.00271 (i.e. 2^(2^-8) + // ). If NativeHistogramBucketFactor is greater than 1 but smaller than + // 2^(2^-8), then the actually used factor is still 2^(2^-8) even though + // it is larger than the provided NativeHistogramBucketFactor. + // + // NOTE: Native Histograms are still an experimental feature. Their + // behavior might still change without a major version + // bump. Subsequently, all NativeHistogram... options here might still + // change their behavior or name (or might completely disappear) without + // a major version bump. + NativeHistogramBucketFactor float64 + // All observations with an absolute value of less or equal + // NativeHistogramZeroThreshold are accumulated into a “zero” + // bucket. For best results, this should be close to a bucket + // boundary. This is usually the case if picking a power of two. If + // NativeHistogramZeroThreshold is left at zero, + // DefSparseBucketsZeroThreshold is used as the threshold. To configure + // a zero bucket with an actual threshold of zero (i.e. only + // observations of precisely zero will go into the zero bucket), set + // NativeHistogramZeroThreshold to the NativeHistogramZeroThresholdZero + // constant (or any negative float value). + NativeHistogramZeroThreshold float64 + + // The remaining fields define a strategy to limit the number of + // populated sparse buckets. If NativeHistogramMaxBucketNumber is left + // at zero, the number of buckets is not limited. (Note that this might + // lead to unbounded memory consumption if the values observed by the + // Histogram are sufficiently wide-spread. In particular, this could be + // used as a DoS attack vector. Where the observed values depend on + // external inputs, it is highly recommended to set a + // NativeHistogramMaxBucketNumber.) Once the set + // NativeHistogramMaxBucketNumber is exceeded, the following strategy is + // enacted: First, if the last reset (or the creation) of the histogram + // is at least NativeHistogramMinResetDuration ago, then the whole + // histogram is reset to its initial state (including regular + // buckets). If less time has passed, or if + // NativeHistogramMinResetDuration is zero, no reset is + // performed. Instead, the zero threshold is increased sufficiently to + // reduce the number of buckets to or below + // NativeHistogramMaxBucketNumber, but not to more than + // NativeHistogramMaxZeroThreshold. Thus, if + // NativeHistogramMaxZeroThreshold is already at or below the current + // zero threshold, nothing happens at this step. After that, if the + // number of buckets still exceeds NativeHistogramMaxBucketNumber, the + // resolution of the histogram is reduced by doubling the width of the + // sparse buckets (up to a growth factor between one bucket to the next + // of 2^(2^4) = 65536, see above). + NativeHistogramMaxBucketNumber uint32 + NativeHistogramMinResetDuration time.Duration + NativeHistogramMaxZeroThreshold float64 +} + +// HistogramVecOpts bundles the options to create a HistogramVec metric. +// It is mandatory to set HistogramOpts, see there for mandatory fields. VariableLabels +// is optional and can safely be left to its default value. +type HistogramVecOpts struct { + HistogramOpts + + // VariableLabels are used to partition the metric vector by the given set + // of labels. Each label value will be constrained with the optional Contraint + // function, if provided. + VariableLabels ConstrainableLabels } // NewHistogram creates a new Histogram based on the provided HistogramOpts. It @@ -204,11 +500,11 @@ func NewHistogram(opts HistogramOpts) Histogram { func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogram { if len(desc.variableLabels) != len(labelValues) { - panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, labelValues)) + panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels.labelNames(), labelValues)) } for _, n := range desc.variableLabels { - if n == bucketLabel { + if n.Name == bucketLabel { panic(errBucketLabelNotAllowed) } } @@ -218,16 +514,29 @@ func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogr } } - if len(opts.Buckets) == 0 { - opts.Buckets = DefBuckets - } - h := &histogram{ - desc: desc, - upperBounds: opts.Buckets, - labelPairs: MakeLabelPairs(desc, labelValues), - counts: [2]*histogramCounts{{}, {}}, - now: time.Now, + desc: desc, + upperBounds: opts.Buckets, + labelPairs: MakeLabelPairs(desc, labelValues), + nativeHistogramMaxBuckets: opts.NativeHistogramMaxBucketNumber, + nativeHistogramMaxZeroThreshold: opts.NativeHistogramMaxZeroThreshold, + nativeHistogramMinResetDuration: opts.NativeHistogramMinResetDuration, + lastResetTime: time.Now(), + now: time.Now, + } + if len(h.upperBounds) == 0 && opts.NativeHistogramBucketFactor <= 1 { + h.upperBounds = DefBuckets + } + if opts.NativeHistogramBucketFactor <= 1 { + h.nativeHistogramSchema = math.MinInt32 // To mark that there are no sparse buckets. + } else { + switch { + case opts.NativeHistogramZeroThreshold > 0: + h.nativeHistogramZeroThreshold = opts.NativeHistogramZeroThreshold + case opts.NativeHistogramZeroThreshold == 0: + h.nativeHistogramZeroThreshold = DefNativeHistogramZeroThreshold + } // Leave h.nativeHistogramZeroThreshold at 0 otherwise. + h.nativeHistogramSchema = pickSchema(opts.NativeHistogramBucketFactor) } for i, upperBound := range h.upperBounds { if i < len(h.upperBounds)-1 { @@ -246,8 +555,12 @@ func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogr } // Finally we know the final length of h.upperBounds and can make buckets // for both counts as well as exemplars: - h.counts[0].buckets = make([]uint64, len(h.upperBounds)) - h.counts[1].buckets = make([]uint64, len(h.upperBounds)) + h.counts[0] = &histogramCounts{buckets: make([]uint64, len(h.upperBounds))} + atomic.StoreUint64(&h.counts[0].nativeHistogramZeroThresholdBits, math.Float64bits(h.nativeHistogramZeroThreshold)) + atomic.StoreInt32(&h.counts[0].nativeHistogramSchema, h.nativeHistogramSchema) + h.counts[1] = &histogramCounts{buckets: make([]uint64, len(h.upperBounds))} + atomic.StoreUint64(&h.counts[1].nativeHistogramZeroThresholdBits, math.Float64bits(h.nativeHistogramZeroThreshold)) + atomic.StoreInt32(&h.counts[1].nativeHistogramSchema, h.nativeHistogramSchema) h.exemplars = make([]atomic.Value, len(h.upperBounds)+1) h.init(h) // Init self-collection. @@ -255,13 +568,98 @@ func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogr } type histogramCounts struct { + // Order in this struct matters for the alignment required by atomic + // operations, see http://golang.org/pkg/sync/atomic/#pkg-note-BUG + // sumBits contains the bits of the float64 representing the sum of all - // observations. sumBits and count have to go first in the struct to - // guarantee alignment for atomic operations. - // http://golang.org/pkg/sync/atomic/#pkg-note-BUG + // observations. sumBits uint64 count uint64 + + // nativeHistogramZeroBucket counts all (positive and negative) + // observations in the zero bucket (with an absolute value less or equal + // the current threshold, see next field. + nativeHistogramZeroBucket uint64 + // nativeHistogramZeroThresholdBits is the bit pattern of the current + // threshold for the zero bucket. It's initially equal to + // nativeHistogramZeroThreshold but may change according to the bucket + // count limitation strategy. + nativeHistogramZeroThresholdBits uint64 + // nativeHistogramSchema may change over time according to the bucket + // count limitation strategy and therefore has to be saved here. + nativeHistogramSchema int32 + // Number of (positive and negative) sparse buckets. + nativeHistogramBucketsNumber uint32 + + // Regular buckets. buckets []uint64 + + // The sparse buckets for native histograms are implemented with a + // sync.Map for now. A dedicated data structure will likely be more + // efficient. There are separate maps for negative and positive + // observations. The map's value is an *int64, counting observations in + // that bucket. (Note that we don't use uint64 as an int64 won't + // overflow in practice, and working with signed numbers from the + // beginning simplifies the handling of deltas.) The map's key is the + // index of the bucket according to the used + // nativeHistogramSchema. Index 0 is for an upper bound of 1. + nativeHistogramBucketsPositive, nativeHistogramBucketsNegative sync.Map +} + +// observe manages the parts of observe that only affects +// histogramCounts. doSparse is true if sparse buckets should be done, +// too. +func (hc *histogramCounts) observe(v float64, bucket int, doSparse bool) { + if bucket < len(hc.buckets) { + atomic.AddUint64(&hc.buckets[bucket], 1) + } + atomicAddFloat(&hc.sumBits, v) + if doSparse && !math.IsNaN(v) { + var ( + key int + schema = atomic.LoadInt32(&hc.nativeHistogramSchema) + zeroThreshold = math.Float64frombits(atomic.LoadUint64(&hc.nativeHistogramZeroThresholdBits)) + bucketCreated, isInf bool + ) + if math.IsInf(v, 0) { + // Pretend v is MaxFloat64 but later increment key by one. + if math.IsInf(v, +1) { + v = math.MaxFloat64 + } else { + v = -math.MaxFloat64 + } + isInf = true + } + frac, exp := math.Frexp(math.Abs(v)) + if schema > 0 { + bounds := nativeHistogramBounds[schema] + key = sort.SearchFloat64s(bounds, frac) + (exp-1)*len(bounds) + } else { + key = exp + if frac == 0.5 { + key-- + } + div := 1 << -schema + key = (key + div - 1) / div + } + if isInf { + key++ + } + switch { + case v > zeroThreshold: + bucketCreated = addToBucket(&hc.nativeHistogramBucketsPositive, key, 1) + case v < -zeroThreshold: + bucketCreated = addToBucket(&hc.nativeHistogramBucketsNegative, key, 1) + default: + atomic.AddUint64(&hc.nativeHistogramZeroBucket, 1) + } + if bucketCreated { + atomic.AddUint32(&hc.nativeHistogramBucketsNumber, 1) + } + } + // Increment count last as we take it as a signal that the observation + // is complete. + atomic.AddUint64(&hc.count, 1) } type histogram struct { @@ -276,7 +674,7 @@ type histogram struct { // perspective of the histogram) swap the hot–cold under the writeMtx // lock. A cooldown is awaited (while locked) by comparing the number of // observations with the initiation count. Once they match, then the - // last observation on the now cool one has completed. All cool fields must + // last observation on the now cool one has completed. All cold fields must // be merged into the new hot before releasing writeMtx. // // Fields with atomic access first! See alignment constraint: @@ -284,8 +682,10 @@ type histogram struct { countAndHotIdx uint64 selfCollector - desc *Desc - writeMtx sync.Mutex // Only used in the Write method. + desc *Desc + + // Only used in the Write method and for sparse bucket management. + mtx sync.Mutex // Two counts, one is "hot" for lock-free observations, the other is // "cold" for writing out a dto.Metric. It has to be an array of @@ -293,9 +693,15 @@ type histogram struct { // http://golang.org/pkg/sync/atomic/#pkg-note-BUG. counts [2]*histogramCounts - upperBounds []float64 - labelPairs []*dto.LabelPair - exemplars []atomic.Value // One more than buckets (to include +Inf), each a *dto.Exemplar. + upperBounds []float64 + labelPairs []*dto.LabelPair + exemplars []atomic.Value // One more than buckets (to include +Inf), each a *dto.Exemplar. + nativeHistogramSchema int32 // The initial schema. Set to math.MinInt32 if no sparse buckets are used. + nativeHistogramZeroThreshold float64 // The initial zero threshold. + nativeHistogramMaxZeroThreshold float64 + nativeHistogramMaxBuckets uint32 + nativeHistogramMinResetDuration time.Duration + lastResetTime time.Time // Protected by mtx. now func() time.Time // To mock out time.Now() for testing. } @@ -319,8 +725,8 @@ func (h *histogram) Write(out *dto.Metric) error { // the hot path, i.e. Observe is called much more often than Write. The // complication of making Write lock-free isn't worth it, if possible at // all. - h.writeMtx.Lock() - defer h.writeMtx.Unlock() + h.mtx.Lock() + defer h.mtx.Unlock() // Adding 1<<63 switches the hot index (from 0 to 1 or from 1 to 0) // without touching the count bits. See the struct comments for a full @@ -333,16 +739,16 @@ func (h *histogram) Write(out *dto.Metric) error { hotCounts := h.counts[n>>63] coldCounts := h.counts[(^n)>>63] - // Await cooldown. - for count != atomic.LoadUint64(&coldCounts.count) { - runtime.Gosched() // Let observations get work done. - } + waitForCooldown(count, coldCounts) his := &dto.Histogram{ Bucket: make([]*dto.Bucket, len(h.upperBounds)), SampleCount: proto.Uint64(count), SampleSum: proto.Float64(math.Float64frombits(atomic.LoadUint64(&coldCounts.sumBits))), } + out.Histogram = his + out.Label = h.labelPairs + var cumCount uint64 for i, upperBound := range h.upperBounds { cumCount += atomic.LoadUint64(&coldCounts.buckets[i]) @@ -363,25 +769,21 @@ func (h *histogram) Write(out *dto.Metric) error { } his.Bucket = append(his.Bucket, b) } - - out.Histogram = his - out.Label = h.labelPairs - - // Finally add all the cold counts to the new hot counts and reset the cold counts. - atomic.AddUint64(&hotCounts.count, count) - atomic.StoreUint64(&coldCounts.count, 0) - for { - oldBits := atomic.LoadUint64(&hotCounts.sumBits) - newBits := math.Float64bits(math.Float64frombits(oldBits) + his.GetSampleSum()) - if atomic.CompareAndSwapUint64(&hotCounts.sumBits, oldBits, newBits) { - atomic.StoreUint64(&coldCounts.sumBits, 0) - break - } - } - for i := range h.upperBounds { - atomic.AddUint64(&hotCounts.buckets[i], atomic.LoadUint64(&coldCounts.buckets[i])) - atomic.StoreUint64(&coldCounts.buckets[i], 0) + if h.nativeHistogramSchema > math.MinInt32 { + his.ZeroThreshold = proto.Float64(math.Float64frombits(atomic.LoadUint64(&coldCounts.nativeHistogramZeroThresholdBits))) + his.Schema = proto.Int32(atomic.LoadInt32(&coldCounts.nativeHistogramSchema)) + zeroBucket := atomic.LoadUint64(&coldCounts.nativeHistogramZeroBucket) + + defer func() { + coldCounts.nativeHistogramBucketsPositive.Range(addAndReset(&hotCounts.nativeHistogramBucketsPositive, &hotCounts.nativeHistogramBucketsNumber)) + coldCounts.nativeHistogramBucketsNegative.Range(addAndReset(&hotCounts.nativeHistogramBucketsNegative, &hotCounts.nativeHistogramBucketsNumber)) + }() + + his.ZeroCount = proto.Uint64(zeroBucket) + his.NegativeSpan, his.NegativeDelta = makeBuckets(&coldCounts.nativeHistogramBucketsNegative) + his.PositiveSpan, his.PositiveDelta = makeBuckets(&coldCounts.nativeHistogramBucketsPositive) } + addAndResetCounts(hotCounts, coldCounts) return nil } @@ -402,25 +804,216 @@ func (h *histogram) findBucket(v float64) int { // observe is the implementation for Observe without the findBucket part. func (h *histogram) observe(v float64, bucket int) { + // Do not add to sparse buckets for NaN observations. + doSparse := h.nativeHistogramSchema > math.MinInt32 && !math.IsNaN(v) // We increment h.countAndHotIdx so that the counter in the lower // 63 bits gets incremented. At the same time, we get the new value // back, which we can use to find the currently-hot counts. n := atomic.AddUint64(&h.countAndHotIdx, 1) hotCounts := h.counts[n>>63] + hotCounts.observe(v, bucket, doSparse) + if doSparse { + h.limitBuckets(hotCounts, v, bucket) + } +} - if bucket < len(h.upperBounds) { - atomic.AddUint64(&hotCounts.buckets[bucket], 1) +// limitSparsebuckets applies a strategy to limit the number of populated sparse +// buckets. It's generally best effort, and there are situations where the +// number can go higher (if even the lowest resolution isn't enough to reduce +// the number sufficiently, or if the provided counts aren't fully updated yet +// by a concurrently happening Write call). +func (h *histogram) limitBuckets(counts *histogramCounts, value float64, bucket int) { + if h.nativeHistogramMaxBuckets == 0 { + return // No limit configured. } - for { - oldBits := atomic.LoadUint64(&hotCounts.sumBits) - newBits := math.Float64bits(math.Float64frombits(oldBits) + v) - if atomic.CompareAndSwapUint64(&hotCounts.sumBits, oldBits, newBits) { - break + if h.nativeHistogramMaxBuckets >= atomic.LoadUint32(&counts.nativeHistogramBucketsNumber) { + return // Bucket limit not exceeded yet. + } + + h.mtx.Lock() + defer h.mtx.Unlock() + + // The hot counts might have been swapped just before we acquired the + // lock. Re-fetch the hot counts first... + n := atomic.LoadUint64(&h.countAndHotIdx) + hotIdx := n >> 63 + coldIdx := (^n) >> 63 + hotCounts := h.counts[hotIdx] + coldCounts := h.counts[coldIdx] + // ...and then check again if we really have to reduce the bucket count. + if h.nativeHistogramMaxBuckets >= atomic.LoadUint32(&hotCounts.nativeHistogramBucketsNumber) { + return // Bucket limit not exceeded after all. + } + // Try the various strategies in order. + if h.maybeReset(hotCounts, coldCounts, coldIdx, value, bucket) { + return + } + if h.maybeWidenZeroBucket(hotCounts, coldCounts) { + return + } + h.doubleBucketWidth(hotCounts, coldCounts) +} + +// maybeReset resests the whole histogram if at least h.nativeHistogramMinResetDuration +// has been passed. It returns true if the histogram has been reset. The caller +// must have locked h.mtx. +func (h *histogram) maybeReset(hot, cold *histogramCounts, coldIdx uint64, value float64, bucket int) bool { + // We are using the possibly mocked h.now() rather than + // time.Since(h.lastResetTime) to enable testing. + if h.nativeHistogramMinResetDuration == 0 || h.now().Sub(h.lastResetTime) < h.nativeHistogramMinResetDuration { + return false + } + // Completely reset coldCounts. + h.resetCounts(cold) + // Repeat the latest observation to not lose it completely. + cold.observe(value, bucket, true) + // Make coldCounts the new hot counts while ressetting countAndHotIdx. + n := atomic.SwapUint64(&h.countAndHotIdx, (coldIdx<<63)+1) + count := n & ((1 << 63) - 1) + waitForCooldown(count, hot) + // Finally, reset the formerly hot counts, too. + h.resetCounts(hot) + h.lastResetTime = h.now() + return true +} + +// maybeWidenZeroBucket widens the zero bucket until it includes the existing +// buckets closest to the zero bucket (which could be two, if an equidistant +// negative and a positive bucket exists, but usually it's only one bucket to be +// merged into the new wider zero bucket). h.nativeHistogramMaxZeroThreshold +// limits how far the zero bucket can be extended, and if that's not enough to +// include an existing bucket, the method returns false. The caller must have +// locked h.mtx. +func (h *histogram) maybeWidenZeroBucket(hot, cold *histogramCounts) bool { + currentZeroThreshold := math.Float64frombits(atomic.LoadUint64(&hot.nativeHistogramZeroThresholdBits)) + if currentZeroThreshold >= h.nativeHistogramMaxZeroThreshold { + return false + } + // Find the key of the bucket closest to zero. + smallestKey := findSmallestKey(&hot.nativeHistogramBucketsPositive) + smallestNegativeKey := findSmallestKey(&hot.nativeHistogramBucketsNegative) + if smallestNegativeKey < smallestKey { + smallestKey = smallestNegativeKey + } + if smallestKey == math.MaxInt32 { + return false + } + newZeroThreshold := getLe(smallestKey, atomic.LoadInt32(&hot.nativeHistogramSchema)) + if newZeroThreshold > h.nativeHistogramMaxZeroThreshold { + return false // New threshold would exceed the max threshold. + } + atomic.StoreUint64(&cold.nativeHistogramZeroThresholdBits, math.Float64bits(newZeroThreshold)) + // Remove applicable buckets. + if _, loaded := cold.nativeHistogramBucketsNegative.LoadAndDelete(smallestKey); loaded { + atomicDecUint32(&cold.nativeHistogramBucketsNumber) + } + if _, loaded := cold.nativeHistogramBucketsPositive.LoadAndDelete(smallestKey); loaded { + atomicDecUint32(&cold.nativeHistogramBucketsNumber) + } + // Make cold counts the new hot counts. + n := atomic.AddUint64(&h.countAndHotIdx, 1<<63) + count := n & ((1 << 63) - 1) + // Swap the pointer names to represent the new roles and make + // the rest less confusing. + hot, cold = cold, hot + waitForCooldown(count, cold) + // Add all the now cold counts to the new hot counts... + addAndResetCounts(hot, cold) + // ...adjust the new zero threshold in the cold counts, too... + atomic.StoreUint64(&cold.nativeHistogramZeroThresholdBits, math.Float64bits(newZeroThreshold)) + // ...and then merge the newly deleted buckets into the wider zero + // bucket. + mergeAndDeleteOrAddAndReset := func(hotBuckets, coldBuckets *sync.Map) func(k, v interface{}) bool { + return func(k, v interface{}) bool { + key := k.(int) + bucket := v.(*int64) + if key == smallestKey { + // Merge into hot zero bucket... + atomic.AddUint64(&hot.nativeHistogramZeroBucket, uint64(atomic.LoadInt64(bucket))) + // ...and delete from cold counts. + coldBuckets.Delete(key) + atomicDecUint32(&cold.nativeHistogramBucketsNumber) + } else { + // Add to corresponding hot bucket... + if addToBucket(hotBuckets, key, atomic.LoadInt64(bucket)) { + atomic.AddUint32(&hot.nativeHistogramBucketsNumber, 1) + } + // ...and reset cold bucket. + atomic.StoreInt64(bucket, 0) + } + return true } } - // Increment count last as we take it as a signal that the observation - // is complete. - atomic.AddUint64(&hotCounts.count, 1) + + cold.nativeHistogramBucketsPositive.Range(mergeAndDeleteOrAddAndReset(&hot.nativeHistogramBucketsPositive, &cold.nativeHistogramBucketsPositive)) + cold.nativeHistogramBucketsNegative.Range(mergeAndDeleteOrAddAndReset(&hot.nativeHistogramBucketsNegative, &cold.nativeHistogramBucketsNegative)) + return true +} + +// doubleBucketWidth doubles the bucket width (by decrementing the schema +// number). Note that very sparse buckets could lead to a low reduction of the +// bucket count (or even no reduction at all). The method does nothing if the +// schema is already -4. +func (h *histogram) doubleBucketWidth(hot, cold *histogramCounts) { + coldSchema := atomic.LoadInt32(&cold.nativeHistogramSchema) + if coldSchema == -4 { + return // Already at lowest resolution. + } + coldSchema-- + atomic.StoreInt32(&cold.nativeHistogramSchema, coldSchema) + // Play it simple and just delete all cold buckets. + atomic.StoreUint32(&cold.nativeHistogramBucketsNumber, 0) + deleteSyncMap(&cold.nativeHistogramBucketsNegative) + deleteSyncMap(&cold.nativeHistogramBucketsPositive) + // Make coldCounts the new hot counts. + n := atomic.AddUint64(&h.countAndHotIdx, 1<<63) + count := n & ((1 << 63) - 1) + // Swap the pointer names to represent the new roles and make + // the rest less confusing. + hot, cold = cold, hot + waitForCooldown(count, cold) + // Add all the now cold counts to the new hot counts... + addAndResetCounts(hot, cold) + // ...adjust the schema in the cold counts, too... + atomic.StoreInt32(&cold.nativeHistogramSchema, coldSchema) + // ...and then merge the cold buckets into the wider hot buckets. + merge := func(hotBuckets *sync.Map) func(k, v interface{}) bool { + return func(k, v interface{}) bool { + key := k.(int) + bucket := v.(*int64) + // Adjust key to match the bucket to merge into. + if key > 0 { + key++ + } + key /= 2 + // Add to corresponding hot bucket. + if addToBucket(hotBuckets, key, atomic.LoadInt64(bucket)) { + atomic.AddUint32(&hot.nativeHistogramBucketsNumber, 1) + } + return true + } + } + + cold.nativeHistogramBucketsPositive.Range(merge(&hot.nativeHistogramBucketsPositive)) + cold.nativeHistogramBucketsNegative.Range(merge(&hot.nativeHistogramBucketsNegative)) + // Play it simple again and just delete all cold buckets. + atomic.StoreUint32(&cold.nativeHistogramBucketsNumber, 0) + deleteSyncMap(&cold.nativeHistogramBucketsNegative) + deleteSyncMap(&cold.nativeHistogramBucketsPositive) +} + +func (h *histogram) resetCounts(counts *histogramCounts) { + atomic.StoreUint64(&counts.sumBits, 0) + atomic.StoreUint64(&counts.count, 0) + atomic.StoreUint64(&counts.nativeHistogramZeroBucket, 0) + atomic.StoreUint64(&counts.nativeHistogramZeroThresholdBits, math.Float64bits(h.nativeHistogramZeroThreshold)) + atomic.StoreInt32(&counts.nativeHistogramSchema, h.nativeHistogramSchema) + atomic.StoreUint32(&counts.nativeHistogramBucketsNumber, 0) + for i := range h.upperBounds { + atomic.StoreUint64(&counts.buckets[i], 0) + } + deleteSyncMap(&counts.nativeHistogramBucketsNegative) + deleteSyncMap(&counts.nativeHistogramBucketsPositive) } // updateExemplar replaces the exemplar for the provided bucket. With empty @@ -448,15 +1041,23 @@ type HistogramVec struct { // NewHistogramVec creates a new HistogramVec based on the provided HistogramOpts and // partitioned by the given label names. func NewHistogramVec(opts HistogramOpts, labelNames []string) *HistogramVec { - desc := NewDesc( + return V2.NewHistogramVec(HistogramVecOpts{ + HistogramOpts: opts, + VariableLabels: UnconstrainedLabels(labelNames), + }) +} + +// NewHistogramVec creates a new HistogramVec based on the provided HistogramVecOpts. +func (v2) NewHistogramVec(opts HistogramVecOpts) *HistogramVec { + desc := V2.NewDesc( BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), opts.Help, - labelNames, + opts.VariableLabels, opts.ConstLabels, ) return &HistogramVec{ MetricVec: NewMetricVec(desc, func(lvs ...string) Metric { - return newHistogram(desc, opts, lvs...) + return newHistogram(desc, opts.HistogramOpts, lvs...) }), } } @@ -516,7 +1117,8 @@ func (v *HistogramVec) GetMetricWith(labels Labels) (Observer, error) { // WithLabelValues works as GetMetricWithLabelValues, but panics where // GetMetricWithLabelValues would have returned an error. Not returning an // error allows shortcuts like -// myVec.WithLabelValues("404", "GET").Observe(42.21) +// +// myVec.WithLabelValues("404", "GET").Observe(42.21) func (v *HistogramVec) WithLabelValues(lvs ...string) Observer { h, err := v.GetMetricWithLabelValues(lvs...) if err != nil { @@ -527,7 +1129,8 @@ func (v *HistogramVec) WithLabelValues(lvs ...string) Observer { // With works as GetMetricWith but panics where GetMetricWithLabels would have // returned an error. Not returning an error allows shortcuts like -// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Observe(42.21) +// +// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Observe(42.21) func (v *HistogramVec) With(labels Labels) Observer { h, err := v.GetMetricWith(labels) if err != nil { @@ -581,11 +1184,11 @@ func (h *constHistogram) Desc() *Desc { func (h *constHistogram) Write(out *dto.Metric) error { his := &dto.Histogram{} + buckets := make([]*dto.Bucket, 0, len(h.buckets)) his.SampleCount = proto.Uint64(h.count) his.SampleSum = proto.Float64(h.sum) - for upperBound, count := range h.buckets { buckets = append(buckets, &dto.Bucket{ CumulativeCount: proto.Uint64(count), @@ -613,7 +1216,7 @@ func (h *constHistogram) Write(out *dto.Metric) error { // to send it to Prometheus in the Collect method. // // buckets is a map of upper bounds to cumulative counts, excluding the +Inf -// bucket. +// bucket. The +Inf bucket is implicit, and its value is equal to the provided count. // // NewConstHistogram returns an error if the length of labelValues is not // consistent with the variable labels in Desc or if Desc is invalid. @@ -668,3 +1271,229 @@ func (s buckSort) Swap(i, j int) { func (s buckSort) Less(i, j int) bool { return s[i].GetUpperBound() < s[j].GetUpperBound() } + +// pickSchema returns the largest number n between -4 and 8 such that +// 2^(2^-n) is less or equal the provided bucketFactor. +// +// Special cases: +// - bucketFactor <= 1: panics. +// - bucketFactor < 2^(2^-8) (but > 1): still returns 8. +func pickSchema(bucketFactor float64) int32 { + if bucketFactor <= 1 { + panic(fmt.Errorf("bucketFactor %f is <=1", bucketFactor)) + } + floor := math.Floor(math.Log2(math.Log2(bucketFactor))) + switch { + case floor <= -8: + return 8 + case floor >= 4: + return -4 + default: + return -int32(floor) + } +} + +func makeBuckets(buckets *sync.Map) ([]*dto.BucketSpan, []int64) { + var ii []int + buckets.Range(func(k, v interface{}) bool { + ii = append(ii, k.(int)) + return true + }) + sort.Ints(ii) + + if len(ii) == 0 { + return nil, nil + } + + var ( + spans []*dto.BucketSpan + deltas []int64 + prevCount int64 + nextI int + ) + + appendDelta := func(count int64) { + *spans[len(spans)-1].Length++ + deltas = append(deltas, count-prevCount) + prevCount = count + } + + for n, i := range ii { + v, _ := buckets.Load(i) + count := atomic.LoadInt64(v.(*int64)) + // Multiple spans with only small gaps in between are probably + // encoded more efficiently as one larger span with a few empty + // buckets. Needs some research to find the sweet spot. For now, + // we assume that gaps of one ore two buckets should not create + // a new span. + iDelta := int32(i - nextI) + if n == 0 || iDelta > 2 { + // We have to create a new span, either because we are + // at the very beginning, or because we have found a gap + // of more than two buckets. + spans = append(spans, &dto.BucketSpan{ + Offset: proto.Int32(iDelta), + Length: proto.Uint32(0), + }) + } else { + // We have found a small gap (or no gap at all). + // Insert empty buckets as needed. + for j := int32(0); j < iDelta; j++ { + appendDelta(0) + } + } + appendDelta(count) + nextI = i + 1 + } + return spans, deltas +} + +// addToBucket increments the sparse bucket at key by the provided amount. It +// returns true if a new sparse bucket had to be created for that. +func addToBucket(buckets *sync.Map, key int, increment int64) bool { + if existingBucket, ok := buckets.Load(key); ok { + // Fast path without allocation. + atomic.AddInt64(existingBucket.(*int64), increment) + return false + } + // Bucket doesn't exist yet. Slow path allocating new counter. + newBucket := increment // TODO(beorn7): Check if this is sufficient to not let increment escape. + if actualBucket, loaded := buckets.LoadOrStore(key, &newBucket); loaded { + // The bucket was created concurrently in another goroutine. + // Have to increment after all. + atomic.AddInt64(actualBucket.(*int64), increment) + return false + } + return true +} + +// addAndReset returns a function to be used with sync.Map.Range of spare +// buckets in coldCounts. It increments the buckets in the provided hotBuckets +// according to the buckets ranged through. It then resets all buckets ranged +// through to 0 (but leaves them in place so that they don't need to get +// recreated on the next scrape). +func addAndReset(hotBuckets *sync.Map, bucketNumber *uint32) func(k, v interface{}) bool { + return func(k, v interface{}) bool { + bucket := v.(*int64) + if addToBucket(hotBuckets, k.(int), atomic.LoadInt64(bucket)) { + atomic.AddUint32(bucketNumber, 1) + } + atomic.StoreInt64(bucket, 0) + return true + } +} + +func deleteSyncMap(m *sync.Map) { + m.Range(func(k, v interface{}) bool { + m.Delete(k) + return true + }) +} + +func findSmallestKey(m *sync.Map) int { + result := math.MaxInt32 + m.Range(func(k, v interface{}) bool { + key := k.(int) + if key < result { + result = key + } + return true + }) + return result +} + +func getLe(key int, schema int32) float64 { + // Here a bit of context about the behavior for the last bucket counting + // regular numbers (called simply "last bucket" below) and the bucket + // counting observations of ±Inf (called "inf bucket" below, with a key + // one higher than that of the "last bucket"): + // + // If we apply the usual formula to the last bucket, its upper bound + // would be calculated as +Inf. The reason is that the max possible + // regular float64 number (math.MaxFloat64) doesn't coincide with one of + // the calculated bucket boundaries. So the calculated boundary has to + // be larger than math.MaxFloat64, and the only float64 larger than + // math.MaxFloat64 is +Inf. However, we want to count actual + // observations of ±Inf in the inf bucket. Therefore, we have to treat + // the upper bound of the last bucket specially and set it to + // math.MaxFloat64. (The upper bound of the inf bucket, with its key + // being one higher than that of the last bucket, naturally comes out as + // +Inf by the usual formula. So that's fine.) + // + // math.MaxFloat64 has a frac of 0.9999999999999999 and an exp of + // 1024. If there were a float64 number following math.MaxFloat64, it + // would have a frac of 1.0 and an exp of 1024, or equivalently a frac + // of 0.5 and an exp of 1025. However, since frac must be smaller than + // 1, and exp must be smaller than 1025, either representation overflows + // a float64. (Which, in turn, is the reason that math.MaxFloat64 is the + // largest possible float64. Q.E.D.) However, the formula for + // calculating the upper bound from the idx and schema of the last + // bucket results in precisely that. It is either frac=1.0 & exp=1024 + // (for schema < 0) or frac=0.5 & exp=1025 (for schema >=0). (This is, + // by the way, a power of two where the exponent itself is a power of + // two, 2¹⁰ in fact, which coinicides with a bucket boundary in all + // schemas.) So these are the special cases we have to catch below. + if schema < 0 { + exp := key << -schema + if exp == 1024 { + // This is the last bucket before the overflow bucket + // (for ±Inf observations). Return math.MaxFloat64 as + // explained above. + return math.MaxFloat64 + } + return math.Ldexp(1, exp) + } + + fracIdx := key & ((1 << schema) - 1) + frac := nativeHistogramBounds[schema][fracIdx] + exp := (key >> schema) + 1 + if frac == 0.5 && exp == 1025 { + // This is the last bucket before the overflow bucket (for ±Inf + // observations). Return math.MaxFloat64 as explained above. + return math.MaxFloat64 + } + return math.Ldexp(frac, exp) +} + +// waitForCooldown returns after the count field in the provided histogramCounts +// has reached the provided count value. +func waitForCooldown(count uint64, counts *histogramCounts) { + for count != atomic.LoadUint64(&counts.count) { + runtime.Gosched() // Let observations get work done. + } +} + +// atomicAddFloat adds the provided float atomically to another float +// represented by the bit pattern the bits pointer is pointing to. +func atomicAddFloat(bits *uint64, v float64) { + for { + loadedBits := atomic.LoadUint64(bits) + newBits := math.Float64bits(math.Float64frombits(loadedBits) + v) + if atomic.CompareAndSwapUint64(bits, loadedBits, newBits) { + break + } + } +} + +// atomicDecUint32 atomically decrements the uint32 p points to. See +// https://pkg.go.dev/sync/atomic#AddUint32 to understand how this is done. +func atomicDecUint32(p *uint32) { + atomic.AddUint32(p, ^uint32(0)) +} + +// addAndResetCounts adds certain fields (count, sum, conventional buckets, zero +// bucket) from the cold counts to the corresponding fields in the hot +// counts. Those fields are then reset to 0 in the cold counts. +func addAndResetCounts(hot, cold *histogramCounts) { + atomic.AddUint64(&hot.count, atomic.LoadUint64(&cold.count)) + atomic.StoreUint64(&cold.count, 0) + coldSum := math.Float64frombits(atomic.LoadUint64(&cold.sumBits)) + atomicAddFloat(&hot.sumBits, coldSum) + atomic.StoreUint64(&cold.sumBits, 0) + for i := range hot.buckets { + atomic.AddUint64(&hot.buckets[i], atomic.LoadUint64(&cold.buckets[i])) + atomic.StoreUint64(&cold.buckets[i], 0) + } + atomic.AddUint64(&hot.nativeHistogramZeroBucket, atomic.LoadUint64(&cold.nativeHistogramZeroBucket)) + atomic.StoreUint64(&cold.nativeHistogramZeroBucket, 0) +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/internal/almost_equal.go b/vendor/github.com/prometheus/client_golang/prometheus/internal/almost_equal.go new file mode 100644 index 0000000000..1ed5abe74c --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/internal/almost_equal.go @@ -0,0 +1,60 @@ +// Copyright (c) 2015 Björn Rabenstein +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +// The code in this package is copy/paste to avoid a dependency. Hence this file +// carries the copyright of the original repo. +// https://github.com/beorn7/floats +package internal + +import ( + "math" +) + +// minNormalFloat64 is the smallest positive normal value of type float64. +var minNormalFloat64 = math.Float64frombits(0x0010000000000000) + +// AlmostEqualFloat64 returns true if a and b are equal within a relative error +// of epsilon. See http://floating-point-gui.de/errors/comparison/ for the +// details of the applied method. +func AlmostEqualFloat64(a, b, epsilon float64) bool { + if a == b { + return true + } + absA := math.Abs(a) + absB := math.Abs(b) + diff := math.Abs(a - b) + if a == 0 || b == 0 || absA+absB < minNormalFloat64 { + return diff < epsilon*minNormalFloat64 + } + return diff/math.Min(absA+absB, math.MaxFloat64) < epsilon +} + +// AlmostEqualFloat64s is the slice form of AlmostEqualFloat64. +func AlmostEqualFloat64s(a, b []float64, epsilon float64) bool { + if len(a) != len(b) { + return false + } + for i := range a { + if !AlmostEqualFloat64(a[i], b[i], epsilon) { + return false + } + } + return true +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/internal/difflib.go b/vendor/github.com/prometheus/client_golang/prometheus/internal/difflib.go new file mode 100644 index 0000000000..fd0750f2cf --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/internal/difflib.go @@ -0,0 +1,654 @@ +// Copyright 2022 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// It provides tools to compare sequences of strings and generate textual diffs. +// +// Maintaining `GetUnifiedDiffString` here because original repository +// (https://github.com/pmezard/go-difflib) is no loger maintained. +package internal + +import ( + "bufio" + "bytes" + "fmt" + "io" + "strings" +) + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +func calculateRatio(matches, length int) float64 { + if length > 0 { + return 2.0 * float64(matches) / float64(length) + } + return 1.0 +} + +type Match struct { + A int + B int + Size int +} + +type OpCode struct { + Tag byte + I1 int + I2 int + J1 int + J2 int +} + +// SequenceMatcher compares sequence of strings. The basic +// algorithm predates, and is a little fancier than, an algorithm +// published in the late 1980's by Ratcliff and Obershelp under the +// hyperbolic name "gestalt pattern matching". The basic idea is to find +// the longest contiguous matching subsequence that contains no "junk" +// elements (R-O doesn't address junk). The same idea is then applied +// recursively to the pieces of the sequences to the left and to the right +// of the matching subsequence. This does not yield minimal edit +// sequences, but does tend to yield matches that "look right" to people. +// +// SequenceMatcher tries to compute a "human-friendly diff" between two +// sequences. Unlike e.g. UNIX(tm) diff, the fundamental notion is the +// longest *contiguous* & junk-free matching subsequence. That's what +// catches peoples' eyes. The Windows(tm) windiff has another interesting +// notion, pairing up elements that appear uniquely in each sequence. +// That, and the method here, appear to yield more intuitive difference +// reports than does diff. This method appears to be the least vulnerable +// to synching up on blocks of "junk lines", though (like blank lines in +// ordinary text files, or maybe "

    " lines in HTML files). That may be +// because this is the only method of the 3 that has a *concept* of +// "junk" . +// +// Timing: Basic R-O is cubic time worst case and quadratic time expected +// case. SequenceMatcher is quadratic time for the worst case and has +// expected-case behavior dependent in a complicated way on how many +// elements the sequences have in common; best case time is linear. +type SequenceMatcher struct { + a []string + b []string + b2j map[string][]int + IsJunk func(string) bool + autoJunk bool + bJunk map[string]struct{} + matchingBlocks []Match + fullBCount map[string]int + bPopular map[string]struct{} + opCodes []OpCode +} + +func NewMatcher(a, b []string) *SequenceMatcher { + m := SequenceMatcher{autoJunk: true} + m.SetSeqs(a, b) + return &m +} + +func NewMatcherWithJunk(a, b []string, autoJunk bool, + isJunk func(string) bool, +) *SequenceMatcher { + m := SequenceMatcher{IsJunk: isJunk, autoJunk: autoJunk} + m.SetSeqs(a, b) + return &m +} + +// Set two sequences to be compared. +func (m *SequenceMatcher) SetSeqs(a, b []string) { + m.SetSeq1(a) + m.SetSeq2(b) +} + +// Set the first sequence to be compared. The second sequence to be compared is +// not changed. +// +// SequenceMatcher computes and caches detailed information about the second +// sequence, so if you want to compare one sequence S against many sequences, +// use .SetSeq2(s) once and call .SetSeq1(x) repeatedly for each of the other +// sequences. +// +// See also SetSeqs() and SetSeq2(). +func (m *SequenceMatcher) SetSeq1(a []string) { + if &a == &m.a { + return + } + m.a = a + m.matchingBlocks = nil + m.opCodes = nil +} + +// Set the second sequence to be compared. The first sequence to be compared is +// not changed. +func (m *SequenceMatcher) SetSeq2(b []string) { + if &b == &m.b { + return + } + m.b = b + m.matchingBlocks = nil + m.opCodes = nil + m.fullBCount = nil + m.chainB() +} + +func (m *SequenceMatcher) chainB() { + // Populate line -> index mapping + b2j := map[string][]int{} + for i, s := range m.b { + indices := b2j[s] + indices = append(indices, i) + b2j[s] = indices + } + + // Purge junk elements + m.bJunk = map[string]struct{}{} + if m.IsJunk != nil { + junk := m.bJunk + for s := range b2j { + if m.IsJunk(s) { + junk[s] = struct{}{} + } + } + for s := range junk { + delete(b2j, s) + } + } + + // Purge remaining popular elements + popular := map[string]struct{}{} + n := len(m.b) + if m.autoJunk && n >= 200 { + ntest := n/100 + 1 + for s, indices := range b2j { + if len(indices) > ntest { + popular[s] = struct{}{} + } + } + for s := range popular { + delete(b2j, s) + } + } + m.bPopular = popular + m.b2j = b2j +} + +func (m *SequenceMatcher) isBJunk(s string) bool { + _, ok := m.bJunk[s] + return ok +} + +// Find longest matching block in a[alo:ahi] and b[blo:bhi]. +// +// If IsJunk is not defined: +// +// Return (i,j,k) such that a[i:i+k] is equal to b[j:j+k], where +// +// alo <= i <= i+k <= ahi +// blo <= j <= j+k <= bhi +// +// and for all (i',j',k') meeting those conditions, +// +// k >= k' +// i <= i' +// and if i == i', j <= j' +// +// In other words, of all maximal matching blocks, return one that +// starts earliest in a, and of all those maximal matching blocks that +// start earliest in a, return the one that starts earliest in b. +// +// If IsJunk is defined, first the longest matching block is +// determined as above, but with the additional restriction that no +// junk element appears in the block. Then that block is extended as +// far as possible by matching (only) junk elements on both sides. So +// the resulting block never matches on junk except as identical junk +// happens to be adjacent to an "interesting" match. +// +// If no blocks match, return (alo, blo, 0). +func (m *SequenceMatcher) findLongestMatch(alo, ahi, blo, bhi int) Match { + // CAUTION: stripping common prefix or suffix would be incorrect. + // E.g., + // ab + // acab + // Longest matching block is "ab", but if common prefix is + // stripped, it's "a" (tied with "b"). UNIX(tm) diff does so + // strip, so ends up claiming that ab is changed to acab by + // inserting "ca" in the middle. That's minimal but unintuitive: + // "it's obvious" that someone inserted "ac" at the front. + // Windiff ends up at the same place as diff, but by pairing up + // the unique 'b's and then matching the first two 'a's. + besti, bestj, bestsize := alo, blo, 0 + + // find longest junk-free match + // during an iteration of the loop, j2len[j] = length of longest + // junk-free match ending with a[i-1] and b[j] + j2len := map[int]int{} + for i := alo; i != ahi; i++ { + // look at all instances of a[i] in b; note that because + // b2j has no junk keys, the loop is skipped if a[i] is junk + newj2len := map[int]int{} + for _, j := range m.b2j[m.a[i]] { + // a[i] matches b[j] + if j < blo { + continue + } + if j >= bhi { + break + } + k := j2len[j-1] + 1 + newj2len[j] = k + if k > bestsize { + besti, bestj, bestsize = i-k+1, j-k+1, k + } + } + j2len = newj2len + } + + // Extend the best by non-junk elements on each end. In particular, + // "popular" non-junk elements aren't in b2j, which greatly speeds + // the inner loop above, but also means "the best" match so far + // doesn't contain any junk *or* popular non-junk elements. + for besti > alo && bestj > blo && !m.isBJunk(m.b[bestj-1]) && + m.a[besti-1] == m.b[bestj-1] { + besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 + } + for besti+bestsize < ahi && bestj+bestsize < bhi && + !m.isBJunk(m.b[bestj+bestsize]) && + m.a[besti+bestsize] == m.b[bestj+bestsize] { + bestsize++ + } + + // Now that we have a wholly interesting match (albeit possibly + // empty!), we may as well suck up the matching junk on each + // side of it too. Can't think of a good reason not to, and it + // saves post-processing the (possibly considerable) expense of + // figuring out what to do with it. In the case of an empty + // interesting match, this is clearly the right thing to do, + // because no other kind of match is possible in the regions. + for besti > alo && bestj > blo && m.isBJunk(m.b[bestj-1]) && + m.a[besti-1] == m.b[bestj-1] { + besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 + } + for besti+bestsize < ahi && bestj+bestsize < bhi && + m.isBJunk(m.b[bestj+bestsize]) && + m.a[besti+bestsize] == m.b[bestj+bestsize] { + bestsize++ + } + + return Match{A: besti, B: bestj, Size: bestsize} +} + +// Return list of triples describing matching subsequences. +// +// Each triple is of the form (i, j, n), and means that +// a[i:i+n] == b[j:j+n]. The triples are monotonically increasing in +// i and in j. It's also guaranteed that if (i, j, n) and (i', j', n') are +// adjacent triples in the list, and the second is not the last triple in the +// list, then i+n != i' or j+n != j'. IOW, adjacent triples never describe +// adjacent equal blocks. +// +// The last triple is a dummy, (len(a), len(b), 0), and is the only +// triple with n==0. +func (m *SequenceMatcher) GetMatchingBlocks() []Match { + if m.matchingBlocks != nil { + return m.matchingBlocks + } + + var matchBlocks func(alo, ahi, blo, bhi int, matched []Match) []Match + matchBlocks = func(alo, ahi, blo, bhi int, matched []Match) []Match { + match := m.findLongestMatch(alo, ahi, blo, bhi) + i, j, k := match.A, match.B, match.Size + if match.Size > 0 { + if alo < i && blo < j { + matched = matchBlocks(alo, i, blo, j, matched) + } + matched = append(matched, match) + if i+k < ahi && j+k < bhi { + matched = matchBlocks(i+k, ahi, j+k, bhi, matched) + } + } + return matched + } + matched := matchBlocks(0, len(m.a), 0, len(m.b), nil) + + // It's possible that we have adjacent equal blocks in the + // matching_blocks list now. + nonAdjacent := []Match{} + i1, j1, k1 := 0, 0, 0 + for _, b := range matched { + // Is this block adjacent to i1, j1, k1? + i2, j2, k2 := b.A, b.B, b.Size + if i1+k1 == i2 && j1+k1 == j2 { + // Yes, so collapse them -- this just increases the length of + // the first block by the length of the second, and the first + // block so lengthened remains the block to compare against. + k1 += k2 + } else { + // Not adjacent. Remember the first block (k1==0 means it's + // the dummy we started with), and make the second block the + // new block to compare against. + if k1 > 0 { + nonAdjacent = append(nonAdjacent, Match{i1, j1, k1}) + } + i1, j1, k1 = i2, j2, k2 + } + } + if k1 > 0 { + nonAdjacent = append(nonAdjacent, Match{i1, j1, k1}) + } + + nonAdjacent = append(nonAdjacent, Match{len(m.a), len(m.b), 0}) + m.matchingBlocks = nonAdjacent + return m.matchingBlocks +} + +// Return list of 5-tuples describing how to turn a into b. +// +// Each tuple is of the form (tag, i1, i2, j1, j2). The first tuple +// has i1 == j1 == 0, and remaining tuples have i1 == the i2 from the +// tuple preceding it, and likewise for j1 == the previous j2. +// +// The tags are characters, with these meanings: +// +// 'r' (replace): a[i1:i2] should be replaced by b[j1:j2] +// +// 'd' (delete): a[i1:i2] should be deleted, j1==j2 in this case. +// +// 'i' (insert): b[j1:j2] should be inserted at a[i1:i1], i1==i2 in this case. +// +// 'e' (equal): a[i1:i2] == b[j1:j2] +func (m *SequenceMatcher) GetOpCodes() []OpCode { + if m.opCodes != nil { + return m.opCodes + } + i, j := 0, 0 + matching := m.GetMatchingBlocks() + opCodes := make([]OpCode, 0, len(matching)) + for _, m := range matching { + // invariant: we've pumped out correct diffs to change + // a[:i] into b[:j], and the next matching block is + // a[ai:ai+size] == b[bj:bj+size]. So we need to pump + // out a diff to change a[i:ai] into b[j:bj], pump out + // the matching block, and move (i,j) beyond the match + ai, bj, size := m.A, m.B, m.Size + tag := byte(0) + if i < ai && j < bj { + tag = 'r' + } else if i < ai { + tag = 'd' + } else if j < bj { + tag = 'i' + } + if tag > 0 { + opCodes = append(opCodes, OpCode{tag, i, ai, j, bj}) + } + i, j = ai+size, bj+size + // the list of matching blocks is terminated by a + // sentinel with size 0 + if size > 0 { + opCodes = append(opCodes, OpCode{'e', ai, i, bj, j}) + } + } + m.opCodes = opCodes + return m.opCodes +} + +// Isolate change clusters by eliminating ranges with no changes. +// +// Return a generator of groups with up to n lines of context. +// Each group is in the same format as returned by GetOpCodes(). +func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode { + if n < 0 { + n = 3 + } + codes := m.GetOpCodes() + if len(codes) == 0 { + codes = []OpCode{{'e', 0, 1, 0, 1}} + } + // Fixup leading and trailing groups if they show no changes. + if codes[0].Tag == 'e' { + c := codes[0] + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + codes[0] = OpCode{c.Tag, max(i1, i2-n), i2, max(j1, j2-n), j2} + } + if codes[len(codes)-1].Tag == 'e' { + c := codes[len(codes)-1] + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + codes[len(codes)-1] = OpCode{c.Tag, i1, min(i2, i1+n), j1, min(j2, j1+n)} + } + nn := n + n + groups := [][]OpCode{} + group := []OpCode{} + for _, c := range codes { + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + // End the current group and start a new one whenever + // there is a large range with no changes. + if c.Tag == 'e' && i2-i1 > nn { + group = append(group, OpCode{ + c.Tag, i1, min(i2, i1+n), + j1, min(j2, j1+n), + }) + groups = append(groups, group) + group = []OpCode{} + i1, j1 = max(i1, i2-n), max(j1, j2-n) + } + group = append(group, OpCode{c.Tag, i1, i2, j1, j2}) + } + if len(group) > 0 && !(len(group) == 1 && group[0].Tag == 'e') { + groups = append(groups, group) + } + return groups +} + +// Return a measure of the sequences' similarity (float in [0,1]). +// +// Where T is the total number of elements in both sequences, and +// M is the number of matches, this is 2.0*M / T. +// Note that this is 1 if the sequences are identical, and 0 if +// they have nothing in common. +// +// .Ratio() is expensive to compute if you haven't already computed +// .GetMatchingBlocks() or .GetOpCodes(), in which case you may +// want to try .QuickRatio() or .RealQuickRation() first to get an +// upper bound. +func (m *SequenceMatcher) Ratio() float64 { + matches := 0 + for _, m := range m.GetMatchingBlocks() { + matches += m.Size + } + return calculateRatio(matches, len(m.a)+len(m.b)) +} + +// Return an upper bound on ratio() relatively quickly. +// +// This isn't defined beyond that it is an upper bound on .Ratio(), and +// is faster to compute. +func (m *SequenceMatcher) QuickRatio() float64 { + // viewing a and b as multisets, set matches to the cardinality + // of their intersection; this counts the number of matches + // without regard to order, so is clearly an upper bound + if m.fullBCount == nil { + m.fullBCount = map[string]int{} + for _, s := range m.b { + m.fullBCount[s]++ + } + } + + // avail[x] is the number of times x appears in 'b' less the + // number of times we've seen it in 'a' so far ... kinda + avail := map[string]int{} + matches := 0 + for _, s := range m.a { + n, ok := avail[s] + if !ok { + n = m.fullBCount[s] + } + avail[s] = n - 1 + if n > 0 { + matches++ + } + } + return calculateRatio(matches, len(m.a)+len(m.b)) +} + +// Return an upper bound on ratio() very quickly. +// +// This isn't defined beyond that it is an upper bound on .Ratio(), and +// is faster to compute than either .Ratio() or .QuickRatio(). +func (m *SequenceMatcher) RealQuickRatio() float64 { + la, lb := len(m.a), len(m.b) + return calculateRatio(min(la, lb), la+lb) +} + +// Convert range to the "ed" format +func formatRangeUnified(start, stop int) string { + // Per the diff spec at http://www.unix.org/single_unix_specification/ + beginning := start + 1 // lines start numbering with one + length := stop - start + if length == 1 { + return fmt.Sprintf("%d", beginning) + } + if length == 0 { + beginning-- // empty ranges begin at line just before the range + } + return fmt.Sprintf("%d,%d", beginning, length) +} + +// Unified diff parameters +type UnifiedDiff struct { + A []string // First sequence lines + FromFile string // First file name + FromDate string // First file time + B []string // Second sequence lines + ToFile string // Second file name + ToDate string // Second file time + Eol string // Headers end of line, defaults to LF + Context int // Number of context lines +} + +// Compare two sequences of lines; generate the delta as a unified diff. +// +// Unified diffs are a compact way of showing line changes and a few +// lines of context. The number of context lines is set by 'n' which +// defaults to three. +// +// By default, the diff control lines (those with ---, +++, or @@) are +// created with a trailing newline. This is helpful so that inputs +// created from file.readlines() result in diffs that are suitable for +// file.writelines() since both the inputs and outputs have trailing +// newlines. +// +// For inputs that do not have trailing newlines, set the lineterm +// argument to "" so that the output will be uniformly newline free. +// +// The unidiff format normally has a header for filenames and modification +// times. Any or all of these may be specified using strings for +// 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'. +// The modification times are normally expressed in the ISO 8601 format. +func WriteUnifiedDiff(writer io.Writer, diff UnifiedDiff) error { + buf := bufio.NewWriter(writer) + defer buf.Flush() + wf := func(format string, args ...interface{}) error { + _, err := buf.WriteString(fmt.Sprintf(format, args...)) + return err + } + ws := func(s string) error { + _, err := buf.WriteString(s) + return err + } + + if len(diff.Eol) == 0 { + diff.Eol = "\n" + } + + started := false + m := NewMatcher(diff.A, diff.B) + for _, g := range m.GetGroupedOpCodes(diff.Context) { + if !started { + started = true + fromDate := "" + if len(diff.FromDate) > 0 { + fromDate = "\t" + diff.FromDate + } + toDate := "" + if len(diff.ToDate) > 0 { + toDate = "\t" + diff.ToDate + } + if diff.FromFile != "" || diff.ToFile != "" { + err := wf("--- %s%s%s", diff.FromFile, fromDate, diff.Eol) + if err != nil { + return err + } + err = wf("+++ %s%s%s", diff.ToFile, toDate, diff.Eol) + if err != nil { + return err + } + } + } + first, last := g[0], g[len(g)-1] + range1 := formatRangeUnified(first.I1, last.I2) + range2 := formatRangeUnified(first.J1, last.J2) + if err := wf("@@ -%s +%s @@%s", range1, range2, diff.Eol); err != nil { + return err + } + for _, c := range g { + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + if c.Tag == 'e' { + for _, line := range diff.A[i1:i2] { + if err := ws(" " + line); err != nil { + return err + } + } + continue + } + if c.Tag == 'r' || c.Tag == 'd' { + for _, line := range diff.A[i1:i2] { + if err := ws("-" + line); err != nil { + return err + } + } + } + if c.Tag == 'r' || c.Tag == 'i' { + for _, line := range diff.B[j1:j2] { + if err := ws("+" + line); err != nil { + return err + } + } + } + } + } + return nil +} + +// Like WriteUnifiedDiff but returns the diff a string. +func GetUnifiedDiffString(diff UnifiedDiff) (string, error) { + w := &bytes.Buffer{} + err := WriteUnifiedDiff(w, diff) + return w.String(), err +} + +// Split a string on "\n" while preserving them. The output can be used +// as input for UnifiedDiff and ContextDiff structures. +func SplitLines(s string) []string { + lines := strings.SplitAfter(s, "\n") + lines[len(lines)-1] += "\n" + return lines +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/internal/go_collector_options.go b/vendor/github.com/prometheus/client_golang/prometheus/internal/go_collector_options.go new file mode 100644 index 0000000000..723b45d644 --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/internal/go_collector_options.go @@ -0,0 +1,32 @@ +// Copyright 2021 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package internal + +import "regexp" + +type GoCollectorRule struct { + Matcher *regexp.Regexp + Deny bool +} + +// GoCollectorOptions should not be used be directly by anything, except `collectors` package. +// Use it via collectors package instead. See issue +// https://github.com/prometheus/client_golang/issues/1030. +// +// This is internal, so external users only can use it via `collector.WithGoCollector*` methods +type GoCollectorOptions struct { + DisableMemStatsLikeMetrics bool + RuntimeMetricSumForHist map[string]string + RuntimeMetricRules []GoCollectorRule +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/internal/go_runtime_metrics.go b/vendor/github.com/prometheus/client_golang/prometheus/internal/go_runtime_metrics.go index 6cbe063a25..97d17d6cb6 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/internal/go_runtime_metrics.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/internal/go_runtime_metrics.go @@ -61,9 +61,9 @@ func RuntimeMetricsToProm(d *metrics.Description) (string, string, string, bool) // name has - replaced with _ and is concatenated with the unit and // other data. name = strings.ReplaceAll(name, "-", "_") - name = name + "_" + unit + name += "_" + unit if d.Cumulative && d.Kind != metrics.KindFloat64Histogram { - name = name + "_total" + name += "_total" } valid := model.IsValidMetricName(model.LabelValue(namespace + "_" + subsystem + "_" + name)) diff --git a/vendor/github.com/prometheus/client_golang/prometheus/internal/metric.go b/vendor/github.com/prometheus/client_golang/prometheus/internal/metric.go index 351c26e1ae..6515c11480 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/internal/metric.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/internal/metric.go @@ -19,18 +19,34 @@ import ( dto "github.com/prometheus/client_model/go" ) -// metricSorter is a sortable slice of *dto.Metric. -type metricSorter []*dto.Metric +// LabelPairSorter implements sort.Interface. It is used to sort a slice of +// dto.LabelPair pointers. +type LabelPairSorter []*dto.LabelPair -func (s metricSorter) Len() int { +func (s LabelPairSorter) Len() int { return len(s) } -func (s metricSorter) Swap(i, j int) { +func (s LabelPairSorter) Swap(i, j int) { s[i], s[j] = s[j], s[i] } -func (s metricSorter) Less(i, j int) bool { +func (s LabelPairSorter) Less(i, j int) bool { + return s[i].GetName() < s[j].GetName() +} + +// MetricSorter is a sortable slice of *dto.Metric. +type MetricSorter []*dto.Metric + +func (s MetricSorter) Len() int { + return len(s) +} + +func (s MetricSorter) Swap(i, j int) { + s[i], s[j] = s[j], s[i] +} + +func (s MetricSorter) Less(i, j int) bool { if len(s[i].Label) != len(s[j].Label) { // This should not happen. The metrics are // inconsistent. However, we have to deal with the fact, as @@ -68,7 +84,7 @@ func (s metricSorter) Less(i, j int) bool { // the slice, with the contained Metrics sorted within each MetricFamily. func NormalizeMetricFamilies(metricFamiliesByName map[string]*dto.MetricFamily) []*dto.MetricFamily { for _, mf := range metricFamiliesByName { - sort.Sort(metricSorter(mf.Metric)) + sort.Sort(MetricSorter(mf.Metric)) } names := make([]string, 0, len(metricFamiliesByName)) for name, mf := range metricFamiliesByName { diff --git a/vendor/github.com/prometheus/client_golang/prometheus/labels.go b/vendor/github.com/prometheus/client_golang/prometheus/labels.go index 2744443ac2..63ff8683ce 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/labels.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/labels.go @@ -25,12 +25,85 @@ import ( // Labels represents a collection of label name -> value mappings. This type is // commonly used with the With(Labels) and GetMetricWith(Labels) methods of // metric vector Collectors, e.g.: -// myVec.With(Labels{"code": "404", "method": "GET"}).Add(42) +// +// myVec.With(Labels{"code": "404", "method": "GET"}).Add(42) // // The other use-case is the specification of constant label pairs in Opts or to // create a Desc. type Labels map[string]string +// ConstrainedLabels represents a label name and its constrain function +// to normalize label values. This type is commonly used when constructing +// metric vector Collectors. +type ConstrainedLabel struct { + Name string + Constraint func(string) string +} + +func (cl ConstrainedLabel) Constrain(v string) string { + if cl.Constraint == nil { + return v + } + return cl.Constraint(v) +} + +// ConstrainableLabels is an interface that allows creating of labels that can +// be optionally constrained. +// +// prometheus.V2().NewCounterVec(CounterVecOpts{ +// CounterOpts: {...}, // Usual CounterOpts fields +// VariableLabels: []ConstrainedLabels{ +// {Name: "A"}, +// {Name: "B", Constraint: func(v string) string { ... }}, +// }, +// }) +type ConstrainableLabels interface { + constrainedLabels() ConstrainedLabels + labelNames() []string +} + +// ConstrainedLabels represents a collection of label name -> constrain function +// to normalize label values. This type is commonly used when constructing +// metric vector Collectors. +type ConstrainedLabels []ConstrainedLabel + +func (cls ConstrainedLabels) constrainedLabels() ConstrainedLabels { + return cls +} + +func (cls ConstrainedLabels) labelNames() []string { + names := make([]string, len(cls)) + for i, label := range cls { + names[i] = label.Name + } + return names +} + +// UnconstrainedLabels represents collection of label without any constraint on +// their value. Thus, it is simply a collection of label names. +// +// UnconstrainedLabels([]string{ "A", "B" }) +// +// is equivalent to +// +// ConstrainedLabels { +// { Name: "A" }, +// { Name: "B" }, +// } +type UnconstrainedLabels []string + +func (uls UnconstrainedLabels) constrainedLabels() ConstrainedLabels { + constrainedLabels := make([]ConstrainedLabel, len(uls)) + for i, l := range uls { + constrainedLabels[i] = ConstrainedLabel{Name: l} + } + return constrainedLabels +} + +func (uls UnconstrainedLabels) labelNames() []string { + return uls +} + // reservedLabelPrefix is a prefix which is not legal in user-supplied // label names. const reservedLabelPrefix = "__" @@ -39,7 +112,7 @@ var errInconsistentCardinality = errors.New("inconsistent label cardinality") func makeInconsistentCardinalityError(fqName string, labels, labelValues []string) error { return fmt.Errorf( - "%s: %q has %d variable labels named %q but %d values %q were provided", + "%w: %q has %d variable labels named %q but %d values %q were provided", errInconsistentCardinality, fqName, len(labels), labels, len(labelValues), labelValues, @@ -49,7 +122,7 @@ func makeInconsistentCardinalityError(fqName string, labels, labelValues []strin func validateValuesInLabels(labels Labels, expectedNumberOfValues int) error { if len(labels) != expectedNumberOfValues { return fmt.Errorf( - "%s: expected %d label values but got %d in %#v", + "%w: expected %d label values but got %d in %#v", errInconsistentCardinality, expectedNumberOfValues, len(labels), labels, ) @@ -67,7 +140,7 @@ func validateValuesInLabels(labels Labels, expectedNumberOfValues int) error { func validateLabelValues(vals []string, expectedNumberOfValues int) error { if len(vals) != expectedNumberOfValues { return fmt.Errorf( - "%s: expected %d label values but got %d in %#v", + "%w: expected %d label values but got %d in %#v", errInconsistentCardinality, expectedNumberOfValues, len(vals), vals, ) diff --git a/vendor/github.com/prometheus/client_golang/prometheus/metric.go b/vendor/github.com/prometheus/client_golang/prometheus/metric.go index dc121910a5..07bbc9d768 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/metric.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/metric.go @@ -14,14 +14,15 @@ package prometheus import ( + "errors" + "math" + "sort" "strings" "time" - //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility. - "github.com/golang/protobuf/proto" - "github.com/prometheus/common/model" - dto "github.com/prometheus/client_model/go" + "github.com/prometheus/common/model" + "google.golang.org/protobuf/proto" ) var separatorByteSlice = []byte{model.SeparatorByte} // For convenient use with xxhash. @@ -115,22 +116,6 @@ func BuildFQName(namespace, subsystem, name string) string { return name } -// labelPairSorter implements sort.Interface. It is used to sort a slice of -// dto.LabelPair pointers. -type labelPairSorter []*dto.LabelPair - -func (s labelPairSorter) Len() int { - return len(s) -} - -func (s labelPairSorter) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} - -func (s labelPairSorter) Less(i, j int) bool { - return s[i].GetName() < s[j].GetName() -} - type invalidMetric struct { desc *Desc err error @@ -174,3 +159,96 @@ func (m timestampedMetric) Write(pb *dto.Metric) error { func NewMetricWithTimestamp(t time.Time, m Metric) Metric { return timestampedMetric{Metric: m, t: t} } + +type withExemplarsMetric struct { + Metric + + exemplars []*dto.Exemplar +} + +func (m *withExemplarsMetric) Write(pb *dto.Metric) error { + if err := m.Metric.Write(pb); err != nil { + return err + } + + switch { + case pb.Counter != nil: + pb.Counter.Exemplar = m.exemplars[len(m.exemplars)-1] + case pb.Histogram != nil: + for _, e := range m.exemplars { + // pb.Histogram.Bucket are sorted by UpperBound. + i := sort.Search(len(pb.Histogram.Bucket), func(i int) bool { + return pb.Histogram.Bucket[i].GetUpperBound() >= e.GetValue() + }) + if i < len(pb.Histogram.Bucket) { + pb.Histogram.Bucket[i].Exemplar = e + } else { + // The +Inf bucket should be explicitly added if there is an exemplar for it, similar to non-const histogram logic in https://github.com/prometheus/client_golang/blob/main/prometheus/histogram.go#L357-L365. + b := &dto.Bucket{ + CumulativeCount: proto.Uint64(pb.Histogram.GetSampleCount()), + UpperBound: proto.Float64(math.Inf(1)), + Exemplar: e, + } + pb.Histogram.Bucket = append(pb.Histogram.Bucket, b) + } + } + default: + // TODO(bwplotka): Implement Gauge? + return errors.New("cannot inject exemplar into Gauge, Summary or Untyped") + } + + return nil +} + +// Exemplar is easier to use, user-facing representation of *dto.Exemplar. +type Exemplar struct { + Value float64 + Labels Labels + // Optional. + // Default value (time.Time{}) indicates its empty, which should be + // understood as time.Now() time at the moment of creation of metric. + Timestamp time.Time +} + +// NewMetricWithExemplars returns a new Metric wrapping the provided Metric with given +// exemplars. Exemplars are validated. +// +// Only last applicable exemplar is injected from the list. +// For example for Counter it means last exemplar is injected. +// For Histogram, it means last applicable exemplar for each bucket is injected. +// +// NewMetricWithExemplars works best with MustNewConstMetric and +// MustNewConstHistogram, see example. +func NewMetricWithExemplars(m Metric, exemplars ...Exemplar) (Metric, error) { + if len(exemplars) == 0 { + return nil, errors.New("no exemplar was passed for NewMetricWithExemplars") + } + + var ( + now = time.Now() + exs = make([]*dto.Exemplar, len(exemplars)) + err error + ) + for i, e := range exemplars { + ts := e.Timestamp + if ts == (time.Time{}) { + ts = now + } + exs[i], err = newExemplar(e.Value, ts, e.Labels) + if err != nil { + return nil, err + } + } + + return &withExemplarsMetric{Metric: m, exemplars: exs}, nil +} + +// MustNewMetricWithExemplars is a version of NewMetricWithExemplars that panics where +// NewMetricWithExemplars would have returned an error. +func MustNewMetricWithExemplars(m Metric, exemplars ...Exemplar) Metric { + ret, err := NewMetricWithExemplars(m, exemplars...) + if err != nil { + panic(err) + } + return ret +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/num_threads.go b/vendor/github.com/prometheus/client_golang/prometheus/num_threads.go new file mode 100644 index 0000000000..7c12b21087 --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/num_threads.go @@ -0,0 +1,25 @@ +// Copyright 2018 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !js || wasm +// +build !js wasm + +package prometheus + +import "runtime" + +// getRuntimeNumThreads returns the number of open OS threads. +func getRuntimeNumThreads() float64 { + n, _ := runtime.ThreadCreateProfile(nil) + return float64(n) +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/num_threads_gopherjs.go b/vendor/github.com/prometheus/client_golang/prometheus/num_threads_gopherjs.go new file mode 100644 index 0000000000..7348df01df --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/num_threads_gopherjs.go @@ -0,0 +1,22 @@ +// Copyright 2018 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build js && !wasm +// +build js,!wasm + +package prometheus + +// getRuntimeNumThreads returns the number of open OS threads. +func getRuntimeNumThreads() float64 { + return 1 +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/observer.go b/vendor/github.com/prometheus/client_golang/prometheus/observer.go index 44128016fd..03773b21f7 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/observer.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/observer.go @@ -58,7 +58,7 @@ type ObserverVec interface { // current time as timestamp, and the provided Labels. Empty Labels will lead to // a valid (label-less) exemplar. But if Labels is nil, the current exemplar is // left in place. ObserveWithExemplar panics if any of the provided labels are -// invalid or if the provided labels contain more than 64 runes in total. +// invalid or if the provided labels contain more than 128 runes in total. type ExemplarObserver interface { ObserveWithExemplar(value float64, exemplar Labels) } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go b/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go index 5bfe0ff5bb..8548dd18ed 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/process_collector.go @@ -16,7 +16,6 @@ package prometheus import ( "errors" "fmt" - "io/ioutil" "os" "strconv" "strings" @@ -104,8 +103,7 @@ func NewProcessCollector(opts ProcessCollectorOpts) Collector { } if opts.PidFn == nil { - pid := os.Getpid() - c.pidFn = func() (int, error) { return pid, nil } + c.pidFn = getPIDFn() } else { c.pidFn = opts.PidFn } @@ -152,13 +150,13 @@ func (c *processCollector) reportError(ch chan<- Metric, desc *Desc, err error) // It is meant to be used for the PidFn field in ProcessCollectorOpts. func NewPidFileFn(pidFilePath string) func() (int, error) { return func() (int, error) { - content, err := ioutil.ReadFile(pidFilePath) + content, err := os.ReadFile(pidFilePath) if err != nil { - return 0, fmt.Errorf("can't read pid file %q: %+v", pidFilePath, err) + return 0, fmt.Errorf("can't read pid file %q: %w", pidFilePath, err) } pid, err := strconv.Atoi(strings.TrimSpace(string(content))) if err != nil { - return 0, fmt.Errorf("can't parse pid file %q: %+v", pidFilePath, err) + return 0, fmt.Errorf("can't parse pid file %q: %w", pidFilePath, err) } return pid, nil diff --git a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_js.go b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_js.go new file mode 100644 index 0000000000..b1e363d6cf --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_js.go @@ -0,0 +1,26 @@ +// Copyright 2019 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build js +// +build js + +package prometheus + +func canCollectProcess() bool { + return false +} + +func (c *processCollector) processCollect(ch chan<- Metric) { + // noop on this platform + return +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_other.go b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_other.go index 2dc3660da0..c0152cdb61 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/process_collector_other.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/process_collector_other.go @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build !windows -// +build !windows +//go:build !windows && !js +// +build !windows,!js package prometheus diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator.go index e7c0d05464..9819917b83 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/delegator.go @@ -76,16 +76,19 @@ func (r *responseWriterDelegator) Write(b []byte) (int, error) { return n, err } -type closeNotifierDelegator struct{ *responseWriterDelegator } -type flusherDelegator struct{ *responseWriterDelegator } -type hijackerDelegator struct{ *responseWriterDelegator } -type readerFromDelegator struct{ *responseWriterDelegator } -type pusherDelegator struct{ *responseWriterDelegator } +type ( + closeNotifierDelegator struct{ *responseWriterDelegator } + flusherDelegator struct{ *responseWriterDelegator } + hijackerDelegator struct{ *responseWriterDelegator } + readerFromDelegator struct{ *responseWriterDelegator } + pusherDelegator struct{ *responseWriterDelegator } +) func (d closeNotifierDelegator) CloseNotify() <-chan bool { //nolint:staticcheck // Ignore SA1019. http.CloseNotifier is deprecated but we keep it here to not break existing users. return d.ResponseWriter.(http.CloseNotifier).CloseNotify() } + func (d flusherDelegator) Flush() { // If applicable, call WriteHeader here so that observeWriteHeader is // handled appropriately. @@ -94,9 +97,11 @@ func (d flusherDelegator) Flush() { } d.ResponseWriter.(http.Flusher).Flush() } + func (d hijackerDelegator) Hijack() (net.Conn, *bufio.ReadWriter, error) { return d.ResponseWriter.(http.Hijacker).Hijack() } + func (d readerFromDelegator) ReadFrom(re io.Reader) (int64, error) { // If applicable, call WriteHeader here so that observeWriteHeader is // handled appropriately. @@ -107,6 +112,7 @@ func (d readerFromDelegator) ReadFrom(re io.Reader) (int64, error) { d.written += n return n, err } + func (d pusherDelegator) Push(target string, opts *http.PushOptions) error { return d.ResponseWriter.(http.Pusher).Push(target, opts) } @@ -261,7 +267,7 @@ func init() { http.Flusher }{d, pusherDelegator{d}, hijackerDelegator{d}, flusherDelegator{d}} } - pickDelegator[pusher+hijacker+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { //23 + pickDelegator[pusher+hijacker+flusher+closeNotifier] = func(d *responseWriterDelegator) delegator { // 23 return struct { *responseWriterDelegator http.Pusher diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go index d86d0cf4b0..a4cc9810b0 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/http.go @@ -33,6 +33,7 @@ package promhttp import ( "compress/gzip" + "errors" "fmt" "io" "net/http" @@ -84,6 +85,13 @@ func Handler() http.Handler { // instrumentation. Use the InstrumentMetricHandler function to apply the same // kind of instrumentation as it is used by the Handler function. func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler { + return HandlerForTransactional(prometheus.ToTransactionalGatherer(reg), opts) +} + +// HandlerForTransactional is like HandlerFor, but it uses transactional gather, which +// can safely change in-place returned *dto.MetricFamily before call to `Gather` and after +// call to `done` of that `Gather`. +func HandlerForTransactional(reg prometheus.TransactionalGatherer, opts HandlerOpts) http.Handler { var ( inFlightSem chan struct{} errCnt = prometheus.NewCounterVec( @@ -103,7 +111,8 @@ func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler { errCnt.WithLabelValues("gathering") errCnt.WithLabelValues("encoding") if err := opts.Registry.Register(errCnt); err != nil { - if are, ok := err.(prometheus.AlreadyRegisteredError); ok { + are := &prometheus.AlreadyRegisteredError{} + if errors.As(err, are) { errCnt = are.ExistingCollector.(*prometheus.CounterVec) } else { panic(err) @@ -123,7 +132,8 @@ func HandlerFor(reg prometheus.Gatherer, opts HandlerOpts) http.Handler { return } } - mfs, err := reg.Gather() + mfs, done, err := reg.Gather() + defer done() if err != nil { if opts.ErrorLog != nil { opts.ErrorLog.Println("error gathering metrics:", err) @@ -242,7 +252,8 @@ func InstrumentMetricHandler(reg prometheus.Registerer, handler http.Handler) ht cnt.WithLabelValues("500") cnt.WithLabelValues("503") if err := reg.Register(cnt); err != nil { - if are, ok := err.(prometheus.AlreadyRegisteredError); ok { + are := &prometheus.AlreadyRegisteredError{} + if errors.As(err, are) { cnt = are.ExistingCollector.(*prometheus.CounterVec) } else { panic(err) @@ -254,7 +265,8 @@ func InstrumentMetricHandler(reg prometheus.Registerer, handler http.Handler) ht Help: "Current number of scrapes being served.", }) if err := reg.Register(gge); err != nil { - if are, ok := err.(prometheus.AlreadyRegisteredError); ok { + are := &prometheus.AlreadyRegisteredError{} + if errors.As(err, are) { gge = are.ExistingCollector.(prometheus.Gauge) } else { panic(err) diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go index 861b4d21ca..d3482c40ca 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_client.go @@ -38,11 +38,11 @@ func (rt RoundTripperFunc) RoundTrip(r *http.Request) (*http.Response, error) { // // See the example for ExampleInstrumentRoundTripperDuration for example usage. func InstrumentRoundTripperInFlight(gauge prometheus.Gauge, next http.RoundTripper) RoundTripperFunc { - return RoundTripperFunc(func(r *http.Request) (*http.Response, error) { + return func(r *http.Request) (*http.Response, error) { gauge.Inc() defer gauge.Dec() return next.RoundTrip(r) - }) + } } // InstrumentRoundTripperCounter is a middleware that wraps the provided @@ -59,22 +59,29 @@ func InstrumentRoundTripperInFlight(gauge prometheus.Gauge, next http.RoundTripp // If the wrapped RoundTripper panics or returns a non-nil error, the Counter // is not incremented. // +// Use with WithExemplarFromContext to instrument the exemplars on the counter of requests. +// // See the example for ExampleInstrumentRoundTripperDuration for example usage. func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.RoundTripper, opts ...Option) RoundTripperFunc { - rtOpts := &option{} + rtOpts := defaultOptions() for _, o := range opts { - o(rtOpts) + o.apply(rtOpts) } - code, method := checkLabels(counter) + // Curry the counter with dynamic labels before checking the remaining labels. + code, method := checkLabels(counter.MustCurryWith(rtOpts.emptyDynamicLabels())) - return RoundTripperFunc(func(r *http.Request) (*http.Response, error) { + return func(r *http.Request) (*http.Response, error) { resp, err := next.RoundTrip(r) if err == nil { - counter.With(labels(code, method, r.Method, resp.StatusCode, rtOpts.extraMethods...)).Inc() + l := labels(code, method, r.Method, resp.StatusCode, rtOpts.extraMethods...) + for label, resolve := range rtOpts.extraLabelsFromCtx { + l[label] = resolve(resp.Request.Context()) + } + addWithExemplar(counter.With(l), 1, rtOpts.getExemplarFn(r.Context())) } return resp, err - }) + } } // InstrumentRoundTripperDuration is a middleware that wraps the provided @@ -94,24 +101,31 @@ func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.Rou // If the wrapped RoundTripper panics or returns a non-nil error, no values are // reported. // +// Use with WithExemplarFromContext to instrument the exemplars on the duration histograms. +// // Note that this method is only guaranteed to never observe negative durations // if used with Go1.9+. func InstrumentRoundTripperDuration(obs prometheus.ObserverVec, next http.RoundTripper, opts ...Option) RoundTripperFunc { - rtOpts := &option{} + rtOpts := defaultOptions() for _, o := range opts { - o(rtOpts) + o.apply(rtOpts) } - code, method := checkLabels(obs) + // Curry the observer with dynamic labels before checking the remaining labels. + code, method := checkLabels(obs.MustCurryWith(rtOpts.emptyDynamicLabels())) - return RoundTripperFunc(func(r *http.Request) (*http.Response, error) { + return func(r *http.Request) (*http.Response, error) { start := time.Now() resp, err := next.RoundTrip(r) if err == nil { - obs.With(labels(code, method, r.Method, resp.StatusCode, rtOpts.extraMethods...)).Observe(time.Since(start).Seconds()) + l := labels(code, method, r.Method, resp.StatusCode, rtOpts.extraMethods...) + for label, resolve := range rtOpts.extraLabelsFromCtx { + l[label] = resolve(resp.Request.Context()) + } + observeWithExemplar(obs.With(l), time.Since(start).Seconds(), rtOpts.getExemplarFn(r.Context())) } return resp, err - }) + } } // InstrumentTrace is used to offer flexibility in instrumenting the available @@ -149,7 +163,7 @@ type InstrumentTrace struct { // // See the example for ExampleInstrumentRoundTripperDuration for example usage. func InstrumentRoundTripperTrace(it *InstrumentTrace, next http.RoundTripper) RoundTripperFunc { - return RoundTripperFunc(func(r *http.Request) (*http.Response, error) { + return func(r *http.Request) (*http.Response, error) { start := time.Now() trace := &httptrace.ClientTrace{ @@ -231,5 +245,5 @@ func InstrumentRoundTripperTrace(it *InstrumentTrace, next http.RoundTripper) Ro r = r.WithContext(httptrace.WithClientTrace(r.Context(), trace)) return next.RoundTrip(r) - }) + } } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go index a23f0edc6f..3793036ad0 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/instrument_server.go @@ -28,6 +28,26 @@ import ( // magicString is used for the hacky label test in checkLabels. Remove once fixed. const magicString = "zZgWfBxLqvG8kc8IMv3POi2Bb0tZI3vAnBx+gBaFi9FyPzB/CzKUer1yufDa" +// observeWithExemplar is a wrapper for [prometheus.ExemplarAdder.ExemplarObserver], +// which falls back to [prometheus.Observer.Observe] if no labels are provided. +func observeWithExemplar(obs prometheus.Observer, val float64, labels map[string]string) { + if labels == nil { + obs.Observe(val) + return + } + obs.(prometheus.ExemplarObserver).ObserveWithExemplar(val, labels) +} + +// addWithExemplar is a wrapper for [prometheus.ExemplarAdder.AddWithExemplar], +// which falls back to [prometheus.Counter.Add] if no labels are provided. +func addWithExemplar(obs prometheus.Counter, val float64, labels map[string]string) { + if labels == nil { + obs.Add(val) + return + } + obs.(prometheus.ExemplarAdder).AddWithExemplar(val, labels) +} + // InstrumentHandlerInFlight is a middleware that wraps the provided // http.Handler. It sets the provided prometheus.Gauge to the number of // requests currently handled by the wrapped http.Handler. @@ -48,7 +68,7 @@ func InstrumentHandlerInFlight(g prometheus.Gauge, next http.Handler) http.Handl // names are "code" and "method". The function panics otherwise. For the "method" // label a predefined default label value set is used to filter given values. // Values besides predefined values will count as `unknown` method. -//`WithExtraMethods` can be used to add more methods to the set. The Observe +// `WithExtraMethods` can be used to add more methods to the set. The Observe // method of the Observer in the ObserverVec is called with the request duration // in seconds. Partitioning happens by HTTP status code and/or HTTP method if // the respective instance label names are present in the ObserverVec. For @@ -62,28 +82,37 @@ func InstrumentHandlerInFlight(g prometheus.Gauge, next http.Handler) http.Handl // Note that this method is only guaranteed to never observe negative durations // if used with Go1.9+. func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler, opts ...Option) http.HandlerFunc { - mwOpts := &option{} + hOpts := defaultOptions() for _, o := range opts { - o(mwOpts) + o.apply(hOpts) } - code, method := checkLabels(obs) + // Curry the observer with dynamic labels before checking the remaining labels. + code, method := checkLabels(obs.MustCurryWith(hOpts.emptyDynamicLabels())) if code { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { now := time.Now() d := newDelegator(w, nil) next.ServeHTTP(d, r) - obs.With(labels(code, method, r.Method, d.Status(), mwOpts.extraMethods...)).Observe(time.Since(now).Seconds()) - }) + l := labels(code, method, r.Method, d.Status(), hOpts.extraMethods...) + for label, resolve := range hOpts.extraLabelsFromCtx { + l[label] = resolve(r.Context()) + } + observeWithExemplar(obs.With(l), time.Since(now).Seconds(), hOpts.getExemplarFn(r.Context())) + } } - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { now := time.Now() next.ServeHTTP(w, r) - obs.With(labels(code, method, r.Method, 0, mwOpts.extraMethods...)).Observe(time.Since(now).Seconds()) - }) + l := labels(code, method, r.Method, 0, hOpts.extraMethods...) + for label, resolve := range hOpts.extraLabelsFromCtx { + l[label] = resolve(r.Context()) + } + observeWithExemplar(obs.With(l), time.Since(now).Seconds(), hOpts.getExemplarFn(r.Context())) + } } // InstrumentHandlerCounter is a middleware that wraps the provided http.Handler @@ -104,25 +133,36 @@ func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler, op // // See the example for InstrumentHandlerDuration for example usage. func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler, opts ...Option) http.HandlerFunc { - mwOpts := &option{} + hOpts := defaultOptions() for _, o := range opts { - o(mwOpts) + o.apply(hOpts) } - code, method := checkLabels(counter) + // Curry the counter with dynamic labels before checking the remaining labels. + code, method := checkLabels(counter.MustCurryWith(hOpts.emptyDynamicLabels())) if code { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { d := newDelegator(w, nil) next.ServeHTTP(d, r) - counter.With(labels(code, method, r.Method, d.Status(), mwOpts.extraMethods...)).Inc() - }) + + l := labels(code, method, r.Method, d.Status(), hOpts.extraMethods...) + for label, resolve := range hOpts.extraLabelsFromCtx { + l[label] = resolve(r.Context()) + } + addWithExemplar(counter.With(l), 1, hOpts.getExemplarFn(r.Context())) + } } - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { next.ServeHTTP(w, r) - counter.With(labels(code, method, r.Method, 0, mwOpts.extraMethods...)).Inc() - }) + + l := labels(code, method, r.Method, 0, hOpts.extraMethods...) + for label, resolve := range hOpts.extraLabelsFromCtx { + l[label] = resolve(r.Context()) + } + addWithExemplar(counter.With(l), 1, hOpts.getExemplarFn(r.Context())) + } } // InstrumentHandlerTimeToWriteHeader is a middleware that wraps the provided @@ -148,20 +188,25 @@ func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler, // // See the example for InstrumentHandlerDuration for example usage. func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Handler, opts ...Option) http.HandlerFunc { - mwOpts := &option{} + hOpts := defaultOptions() for _, o := range opts { - o(mwOpts) + o.apply(hOpts) } - code, method := checkLabels(obs) + // Curry the observer with dynamic labels before checking the remaining labels. + code, method := checkLabels(obs.MustCurryWith(hOpts.emptyDynamicLabels())) - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { now := time.Now() d := newDelegator(w, func(status int) { - obs.With(labels(code, method, r.Method, status, mwOpts.extraMethods...)).Observe(time.Since(now).Seconds()) + l := labels(code, method, r.Method, status, hOpts.extraMethods...) + for label, resolve := range hOpts.extraLabelsFromCtx { + l[label] = resolve(r.Context()) + } + observeWithExemplar(obs.With(l), time.Since(now).Seconds(), hOpts.getExemplarFn(r.Context())) }) next.ServeHTTP(d, r) - }) + } } // InstrumentHandlerRequestSize is a middleware that wraps the provided @@ -184,27 +229,38 @@ func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Ha // // See the example for InstrumentHandlerDuration for example usage. func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler, opts ...Option) http.HandlerFunc { - mwOpts := &option{} + hOpts := defaultOptions() for _, o := range opts { - o(mwOpts) + o.apply(hOpts) } - code, method := checkLabels(obs) + // Curry the observer with dynamic labels before checking the remaining labels. + code, method := checkLabels(obs.MustCurryWith(hOpts.emptyDynamicLabels())) if code { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { d := newDelegator(w, nil) next.ServeHTTP(d, r) size := computeApproximateRequestSize(r) - obs.With(labels(code, method, r.Method, d.Status(), mwOpts.extraMethods...)).Observe(float64(size)) - }) + + l := labels(code, method, r.Method, d.Status(), hOpts.extraMethods...) + for label, resolve := range hOpts.extraLabelsFromCtx { + l[label] = resolve(r.Context()) + } + observeWithExemplar(obs.With(l), float64(size), hOpts.getExemplarFn(r.Context())) + } } - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { next.ServeHTTP(w, r) size := computeApproximateRequestSize(r) - obs.With(labels(code, method, r.Method, 0, mwOpts.extraMethods...)).Observe(float64(size)) - }) + + l := labels(code, method, r.Method, 0, hOpts.extraMethods...) + for label, resolve := range hOpts.extraLabelsFromCtx { + l[label] = resolve(r.Context()) + } + observeWithExemplar(obs.With(l), float64(size), hOpts.getExemplarFn(r.Context())) + } } // InstrumentHandlerResponseSize is a middleware that wraps the provided @@ -227,17 +283,23 @@ func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler, // // See the example for InstrumentHandlerDuration for example usage. func InstrumentHandlerResponseSize(obs prometheus.ObserverVec, next http.Handler, opts ...Option) http.Handler { - mwOpts := &option{} + hOpts := defaultOptions() for _, o := range opts { - o(mwOpts) + o.apply(hOpts) } - code, method := checkLabels(obs) + // Curry the observer with dynamic labels before checking the remaining labels. + code, method := checkLabels(obs.MustCurryWith(hOpts.emptyDynamicLabels())) return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { d := newDelegator(w, nil) next.ServeHTTP(d, r) - obs.With(labels(code, method, r.Method, d.Status(), mwOpts.extraMethods...)).Observe(float64(d.Written())) + + l := labels(code, method, r.Method, d.Status(), hOpts.extraMethods...) + for label, resolve := range hOpts.extraLabelsFromCtx { + l[label] = resolve(r.Context()) + } + observeWithExemplar(obs.With(l), float64(d.Written()), hOpts.getExemplarFn(r.Context())) }) } @@ -246,7 +308,7 @@ func InstrumentHandlerResponseSize(obs prometheus.ObserverVec, next http.Handler // Collector does not have a Desc or has more than one Desc or its Desc is // invalid. It also panics if the Collector has any non-const, non-curried // labels that are not named "code" or "method". -func checkLabels(c prometheus.Collector) (code bool, method bool) { +func checkLabels(c prometheus.Collector) (code, method bool) { // TODO(beorn7): Remove this hacky way to check for instance labels // once Descriptors can have their dimensionality queried. var ( diff --git a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/option.go b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/option.go index 35e41bd1e6..5d4383aa14 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/promhttp/option.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/promhttp/option.go @@ -13,19 +13,72 @@ package promhttp -// Option are used to configure a middleware or round tripper.. -type Option func(*option) +import ( + "context" -type option struct { - extraMethods []string + "github.com/prometheus/client_golang/prometheus" +) + +// Option are used to configure both handler (middleware) or round tripper. +type Option interface { + apply(*options) +} + +// LabelValueFromCtx are used to compute the label value from request context. +// Context can be filled with values from request through middleware. +type LabelValueFromCtx func(ctx context.Context) string + +// options store options for both a handler or round tripper. +type options struct { + extraMethods []string + getExemplarFn func(requestCtx context.Context) prometheus.Labels + extraLabelsFromCtx map[string]LabelValueFromCtx +} + +func defaultOptions() *options { + return &options{ + getExemplarFn: func(ctx context.Context) prometheus.Labels { return nil }, + extraLabelsFromCtx: map[string]LabelValueFromCtx{}, + } } +func (o *options) emptyDynamicLabels() prometheus.Labels { + labels := prometheus.Labels{} + + for label := range o.extraLabelsFromCtx { + labels[label] = "" + } + + return labels +} + +type optionApplyFunc func(*options) + +func (o optionApplyFunc) apply(opt *options) { o(opt) } + // WithExtraMethods adds additional HTTP methods to the list of allowed methods. // See https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods for the default list. // // See the example for ExampleInstrumentHandlerWithExtraMethods for example usage. func WithExtraMethods(methods ...string) Option { - return func(o *option) { + return optionApplyFunc(func(o *options) { o.extraMethods = methods - } + }) +} + +// WithExemplarFromContext allows to inject function that will get exemplar from context that will be put to counter and histogram metrics. +// If the function returns nil labels or the metric does not support exemplars, no exemplar will be added (noop), but +// metric will continue to observe/increment. +func WithExemplarFromContext(getExemplarFn func(requestCtx context.Context) prometheus.Labels) Option { + return optionApplyFunc(func(o *options) { + o.getExemplarFn = getExemplarFn + }) +} + +// WithLabelFromCtx registers a label for dynamic resolution with access to context. +// See the example for ExampleInstrumentHandlerWithLabelResolver for example usage +func WithLabelFromCtx(name string, valueFn LabelValueFromCtx) Option { + return optionApplyFunc(func(o *options) { + o.extraLabelsFromCtx[name] = valueFn + }) } diff --git a/vendor/github.com/prometheus/client_golang/prometheus/registry.go b/vendor/github.com/prometheus/client_golang/prometheus/registry.go index 383a7f5941..44da9433be 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/registry.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/registry.go @@ -15,24 +15,23 @@ package prometheus import ( "bytes" + "errors" "fmt" - "io/ioutil" "os" "path/filepath" "runtime" "sort" + "strconv" "strings" "sync" "unicode/utf8" - "github.com/cespare/xxhash/v2" - //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility. - "github.com/golang/protobuf/proto" - "github.com/prometheus/common/expfmt" + "github.com/prometheus/client_golang/prometheus/internal" + "github.com/cespare/xxhash/v2" dto "github.com/prometheus/client_model/go" - - "github.com/prometheus/client_golang/prometheus/internal" + "github.com/prometheus/common/expfmt" + "google.golang.org/protobuf/proto" ) const ( @@ -252,9 +251,12 @@ func (errs MultiError) MaybeUnwrap() error { } // Registry registers Prometheus collectors, collects their metrics, and gathers -// them into MetricFamilies for exposition. It implements both Registerer and -// Gatherer. The zero value is not usable. Create instances with NewRegistry or -// NewPedanticRegistry. +// them into MetricFamilies for exposition. It implements Registerer, Gatherer, +// and Collector. The zero value is not usable. Create instances with +// NewRegistry or NewPedanticRegistry. +// +// Registry implements Collector to allow it to be used for creating groups of +// metrics. See the Grouping example for how this can be done. type Registry struct { mtx sync.RWMutex collectorsByID map[uint64]Collector // ID is a hash of the descIDs. @@ -289,7 +291,7 @@ func (r *Registry) Register(c Collector) error { // Is the descriptor valid at all? if desc.err != nil { - return fmt.Errorf("descriptor %s is invalid: %s", desc, desc.err) + return fmt.Errorf("descriptor %s is invalid: %w", desc, desc.err) } // Is the descID unique? @@ -407,6 +409,14 @@ func (r *Registry) MustRegister(cs ...Collector) { // Gather implements Gatherer. func (r *Registry) Gather() ([]*dto.MetricFamily, error) { + r.mtx.RLock() + + if len(r.collectorsByID) == 0 && len(r.uncheckedCollectors) == 0 { + // Fast path. + r.mtx.RUnlock() + return nil, nil + } + var ( checkedMetricChan = make(chan Metric, capMetricChan) uncheckedMetricChan = make(chan Metric, capMetricChan) @@ -416,7 +426,6 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) { registeredDescIDs map[uint64]struct{} // Only used for pedantic checks ) - r.mtx.RLock() goroutineBudget := len(r.collectorsByID) + len(r.uncheckedCollectors) metricFamiliesByName := make(map[string]*dto.MetricFamily, len(r.dimHashesByName)) checkedCollectors := make(chan Collector, len(r.collectorsByID)) @@ -549,6 +558,31 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) { return internal.NormalizeMetricFamilies(metricFamiliesByName), errs.MaybeUnwrap() } +// Describe implements Collector. +func (r *Registry) Describe(ch chan<- *Desc) { + r.mtx.RLock() + defer r.mtx.RUnlock() + + // Only report the checked Collectors; unchecked collectors don't report any + // Desc. + for _, c := range r.collectorsByID { + c.Describe(ch) + } +} + +// Collect implements Collector. +func (r *Registry) Collect(ch chan<- Metric) { + r.mtx.RLock() + defer r.mtx.RUnlock() + + for _, c := range r.collectorsByID { + c.Collect(ch) + } + for _, c := range r.uncheckedCollectors { + c.Collect(ch) + } +} + // WriteToTextfile calls Gather on the provided Gatherer, encodes the result in the // Prometheus text format, and writes it to a temporary file. Upon success, the // temporary file is renamed to the provided filename. @@ -556,7 +590,7 @@ func (r *Registry) Gather() ([]*dto.MetricFamily, error) { // This is intended for use with the textfile collector of the node exporter. // Note that the node exporter expects the filename to be suffixed with ".prom". func WriteToTextfile(filename string, g Gatherer) error { - tmp, err := ioutil.TempFile(filepath.Dir(filename), filepath.Base(filename)) + tmp, err := os.CreateTemp(filepath.Dir(filename), filepath.Base(filename)) if err != nil { return err } @@ -575,7 +609,7 @@ func WriteToTextfile(filename string, g Gatherer) error { return err } - if err := os.Chmod(tmp.Name(), 0644); err != nil { + if err := os.Chmod(tmp.Name(), 0o644); err != nil { return err } return os.Rename(tmp.Name(), filename) @@ -596,7 +630,7 @@ func processMetric( } dtoMetric := &dto.Metric{} if err := metric.Write(dtoMetric); err != nil { - return fmt.Errorf("error collecting metric %v: %s", desc, err) + return fmt.Errorf("error collecting metric %v: %w", desc, err) } metricFamily, ok := metricFamiliesByName[desc.fqName] if ok { // Existing name. @@ -718,12 +752,13 @@ func (gs Gatherers) Gather() ([]*dto.MetricFamily, error) { for i, g := range gs { mfs, err := g.Gather() if err != nil { - if multiErr, ok := err.(MultiError); ok { + multiErr := MultiError{} + if errors.As(err, &multiErr) { for _, err := range multiErr { - errs = append(errs, fmt.Errorf("[from Gatherer #%d] %s", i+1, err)) + errs = append(errs, fmt.Errorf("[from Gatherer #%d] %w", i+1, err)) } } else { - errs = append(errs, fmt.Errorf("[from Gatherer #%d] %s", i+1, err)) + errs = append(errs, fmt.Errorf("[from Gatherer #%d] %w", i+1, err)) } } for _, mf := range mfs { @@ -884,11 +919,11 @@ func checkMetricConsistency( h.Write(separatorByteSlice) // Make sure label pairs are sorted. We depend on it for the consistency // check. - if !sort.IsSorted(labelPairSorter(dtoMetric.Label)) { + if !sort.IsSorted(internal.LabelPairSorter(dtoMetric.Label)) { // We cannot sort dtoMetric.Label in place as it is immutable by contract. copiedLabels := make([]*dto.LabelPair, len(dtoMetric.Label)) copy(copiedLabels, dtoMetric.Label) - sort.Sort(labelPairSorter(copiedLabels)) + sort.Sort(internal.LabelPairSorter(copiedLabels)) dtoMetric.Label = copiedLabels } for _, lp := range dtoMetric.Label { @@ -897,6 +932,10 @@ func checkMetricConsistency( h.WriteString(lp.GetValue()) h.Write(separatorByteSlice) } + if dtoMetric.TimestampMs != nil { + h.WriteString(strconv.FormatInt(*(dtoMetric.TimestampMs), 10)) + h.Write(separatorByteSlice) + } hSum := h.Sum64() if _, exists := metricHashes[hSum]; exists { return fmt.Errorf( @@ -926,7 +965,7 @@ func checkDescConsistency( copy(lpsFromDesc, desc.constLabelPairs) for _, l := range desc.variableLabels { lpsFromDesc = append(lpsFromDesc, &dto.LabelPair{ - Name: proto.String(l), + Name: proto.String(l.Name), }) } if len(lpsFromDesc) != len(dtoMetric.Label) { @@ -935,7 +974,7 @@ func checkDescConsistency( metricFamily.GetName(), dtoMetric, desc, ) } - sort.Sort(labelPairSorter(lpsFromDesc)) + sort.Sort(internal.LabelPairSorter(lpsFromDesc)) for i, lpFromDesc := range lpsFromDesc { lpFromMetric := dtoMetric.Label[i] if lpFromDesc.GetName() != lpFromMetric.GetName() || @@ -948,3 +987,89 @@ func checkDescConsistency( } return nil } + +var _ TransactionalGatherer = &MultiTRegistry{} + +// MultiTRegistry is a TransactionalGatherer that joins gathered metrics from multiple +// transactional gatherers. +// +// It is caller responsibility to ensure two registries have mutually exclusive metric families, +// no deduplication will happen. +type MultiTRegistry struct { + tGatherers []TransactionalGatherer +} + +// NewMultiTRegistry creates MultiTRegistry. +func NewMultiTRegistry(tGatherers ...TransactionalGatherer) *MultiTRegistry { + return &MultiTRegistry{ + tGatherers: tGatherers, + } +} + +// Gather implements TransactionalGatherer interface. +func (r *MultiTRegistry) Gather() (mfs []*dto.MetricFamily, done func(), err error) { + errs := MultiError{} + + dFns := make([]func(), 0, len(r.tGatherers)) + // TODO(bwplotka): Implement concurrency for those? + for _, g := range r.tGatherers { + // TODO(bwplotka): Check for duplicates? + m, d, err := g.Gather() + errs.Append(err) + + mfs = append(mfs, m...) + dFns = append(dFns, d) + } + + // TODO(bwplotka): Consider sort in place, given metric family in gather is sorted already. + sort.Slice(mfs, func(i, j int) bool { + return *mfs[i].Name < *mfs[j].Name + }) + return mfs, func() { + for _, d := range dFns { + d() + } + }, errs.MaybeUnwrap() +} + +// TransactionalGatherer represents transactional gatherer that can be triggered to notify gatherer that memory +// used by metric family is no longer used by a caller. This allows implementations with cache. +type TransactionalGatherer interface { + // Gather returns metrics in a lexicographically sorted slice + // of uniquely named MetricFamily protobufs. Gather ensures that the + // returned slice is valid and self-consistent so that it can be used + // for valid exposition. As an exception to the strict consistency + // requirements described for metric.Desc, Gather will tolerate + // different sets of label names for metrics of the same metric family. + // + // Even if an error occurs, Gather attempts to gather as many metrics as + // possible. Hence, if a non-nil error is returned, the returned + // MetricFamily slice could be nil (in case of a fatal error that + // prevented any meaningful metric collection) or contain a number of + // MetricFamily protobufs, some of which might be incomplete, and some + // might be missing altogether. The returned error (which might be a + // MultiError) explains the details. Note that this is mostly useful for + // debugging purposes. If the gathered protobufs are to be used for + // exposition in actual monitoring, it is almost always better to not + // expose an incomplete result and instead disregard the returned + // MetricFamily protobufs in case the returned error is non-nil. + // + // Important: done is expected to be triggered (even if the error occurs!) + // once caller does not need returned slice of dto.MetricFamily. + Gather() (_ []*dto.MetricFamily, done func(), err error) +} + +// ToTransactionalGatherer transforms Gatherer to transactional one with noop as done function. +func ToTransactionalGatherer(g Gatherer) TransactionalGatherer { + return &noTransactionGatherer{g: g} +} + +type noTransactionGatherer struct { + g Gatherer +} + +// Gather implements TransactionalGatherer interface. +func (g *noTransactionGatherer) Gather() (_ []*dto.MetricFamily, done func(), err error) { + mfs, err := g.g.Gather() + return mfs, func() {}, err +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/summary.go b/vendor/github.com/prometheus/client_golang/prometheus/summary.go index c5fa8ed7c7..dd359264e5 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/summary.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/summary.go @@ -22,11 +22,10 @@ import ( "sync/atomic" "time" - "github.com/beorn7/perks/quantile" - //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility. - "github.com/golang/protobuf/proto" - dto "github.com/prometheus/client_model/go" + + "github.com/beorn7/perks/quantile" + "google.golang.org/protobuf/proto" ) // quantileLabel is used for the label that defines the quantile in a @@ -148,6 +147,18 @@ type SummaryOpts struct { BufCap uint32 } +// SummaryVecOpts bundles the options to create a SummaryVec metric. +// It is mandatory to set SummaryOpts, see there for mandatory fields. VariableLabels +// is optional and can safely be left to its default value. +type SummaryVecOpts struct { + SummaryOpts + + // VariableLabels are used to partition the metric vector by the given set + // of labels. Each label value will be constrained with the optional Contraint + // function, if provided. + VariableLabels ConstrainableLabels +} + // Problem with the sliding-window decay algorithm... The Merge method of // perk/quantile is actually not working as advertised - and it might be // unfixable, as the underlying algorithm is apparently not capable of merging @@ -178,11 +189,11 @@ func NewSummary(opts SummaryOpts) Summary { func newSummary(desc *Desc, opts SummaryOpts, labelValues ...string) Summary { if len(desc.variableLabels) != len(labelValues) { - panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, labelValues)) + panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels.labelNames(), labelValues)) } for _, n := range desc.variableLabels { - if n == quantileLabel { + if n.Name == quantileLabel { panic(errQuantileLabelNotAllowed) } } @@ -530,20 +541,28 @@ type SummaryVec struct { // it is handled by the Prometheus server internally, “quantile” is an illegal // label name. NewSummaryVec will panic if this label name is used. func NewSummaryVec(opts SummaryOpts, labelNames []string) *SummaryVec { - for _, ln := range labelNames { + return V2.NewSummaryVec(SummaryVecOpts{ + SummaryOpts: opts, + VariableLabels: UnconstrainedLabels(labelNames), + }) +} + +// NewSummaryVec creates a new SummaryVec based on the provided SummaryVecOpts. +func (v2) NewSummaryVec(opts SummaryVecOpts) *SummaryVec { + for _, ln := range opts.VariableLabels.labelNames() { if ln == quantileLabel { panic(errQuantileLabelNotAllowed) } } - desc := NewDesc( + desc := V2.NewDesc( BuildFQName(opts.Namespace, opts.Subsystem, opts.Name), opts.Help, - labelNames, + opts.VariableLabels, opts.ConstLabels, ) return &SummaryVec{ MetricVec: NewMetricVec(desc, func(lvs ...string) Metric { - return newSummary(desc, opts, lvs...) + return newSummary(desc, opts.SummaryOpts, lvs...) }), } } @@ -603,7 +622,8 @@ func (v *SummaryVec) GetMetricWith(labels Labels) (Observer, error) { // WithLabelValues works as GetMetricWithLabelValues, but panics where // GetMetricWithLabelValues would have returned an error. Not returning an // error allows shortcuts like -// myVec.WithLabelValues("404", "GET").Observe(42.21) +// +// myVec.WithLabelValues("404", "GET").Observe(42.21) func (v *SummaryVec) WithLabelValues(lvs ...string) Observer { s, err := v.GetMetricWithLabelValues(lvs...) if err != nil { @@ -614,7 +634,8 @@ func (v *SummaryVec) WithLabelValues(lvs ...string) Observer { // With works as GetMetricWith, but panics where GetMetricWithLabels would have // returned an error. Not returning an error allows shortcuts like -// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Observe(42.21) +// +// myVec.With(prometheus.Labels{"code": "404", "method": "GET"}).Observe(42.21) func (v *SummaryVec) With(labels Labels) Observer { s, err := v.GetMetricWith(labels) if err != nil { @@ -701,7 +722,8 @@ func (s *constSummary) Write(out *dto.Metric) error { // // quantiles maps ranks to quantile values. For example, a median latency of // 0.23s and a 99th percentile latency of 0.56s would be expressed as: -// map[float64]float64{0.5: 0.23, 0.99: 0.56} +// +// map[float64]float64{0.5: 0.23, 0.99: 0.56} // // NewConstSummary returns an error if the length of labelValues is not // consistent with the variable labels in Desc or if Desc is invalid. diff --git a/vendor/github.com/prometheus/client_golang/prometheus/testutil/lint.go b/vendor/github.com/prometheus/client_golang/prometheus/testutil/lint.go index 7681877a89..8d2f05500b 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/testutil/lint.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/testutil/lint.go @@ -26,7 +26,7 @@ import ( func CollectAndLint(c prometheus.Collector, metricNames ...string) ([]promlint.Problem, error) { reg := prometheus.NewPedanticRegistry() if err := reg.Register(c); err != nil { - return nil, fmt.Errorf("registering collector failed: %s", err) + return nil, fmt.Errorf("registering collector failed: %w", err) } return GatherAndLint(reg, metricNames...) } @@ -37,7 +37,7 @@ func CollectAndLint(c prometheus.Collector, metricNames ...string) ([]promlint.P func GatherAndLint(g prometheus.Gatherer, metricNames ...string) ([]promlint.Problem, error) { got, err := g.Gather() if err != nil { - return nil, fmt.Errorf("gathering metrics failed: %s", err) + return nil, fmt.Errorf("gathering metrics failed: %w", err) } if metricNames != nil { got = filterMetrics(got, metricNames) diff --git a/vendor/github.com/prometheus/client_golang/prometheus/testutil/promlint/promlint.go b/vendor/github.com/prometheus/client_golang/prometheus/testutil/promlint/promlint.go index ec80617062..a20f159b78 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/testutil/promlint/promlint.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/testutil/promlint/promlint.go @@ -15,6 +15,7 @@ package promlint import ( + "errors" "fmt" "io" "regexp" @@ -83,7 +84,7 @@ func (l *Linter) Lint() ([]Problem, error) { mf := &dto.MetricFamily{} for { if err := d.Decode(mf); err != nil { - if err == io.EOF { + if errors.Is(err, io.EOF) { break } @@ -283,7 +284,7 @@ func lintUnitAbbreviations(mf *dto.MetricFamily) []Problem { // metricUnits attempts to detect known unit types used as part of a metric name, // e.g. "foo_bytes_total" or "bar_baz_milligrams". -func metricUnits(m string) (unit string, base string, ok bool) { +func metricUnits(m string) (unit, base string, ok bool) { ss := strings.Split(m, "_") for unit, base := range units { diff --git a/vendor/github.com/prometheus/client_golang/prometheus/testutil/testutil.go b/vendor/github.com/prometheus/client_golang/prometheus/testutil/testutil.go index 9af60ce1d2..82d4a5436b 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/testutil/testutil.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/testutil/testutil.go @@ -41,10 +41,12 @@ import ( "bytes" "fmt" "io" + "net/http" + "reflect" - "github.com/prometheus/common/expfmt" - + "github.com/davecgh/go-spew/spew" dto "github.com/prometheus/client_model/go" + "github.com/prometheus/common/expfmt" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/internal" @@ -99,7 +101,9 @@ func ToFloat64(c prometheus.Collector) float64 { } pb := &dto.Metric{} - m.Write(pb) + if err := m.Write(pb); err != nil { + panic(fmt.Errorf("error happened while collecting metrics: %w", err)) + } if pb.Gauge != nil { return pb.Gauge.GetValue() } @@ -122,7 +126,7 @@ func ToFloat64(c prometheus.Collector) float64 { func CollectAndCount(c prometheus.Collector, metricNames ...string) int { reg := prometheus.NewPedanticRegistry() if err := reg.Register(c); err != nil { - panic(fmt.Errorf("registering collector failed: %s", err)) + panic(fmt.Errorf("registering collector failed: %w", err)) } result, err := GatherAndCount(reg, metricNames...) if err != nil { @@ -138,7 +142,7 @@ func CollectAndCount(c prometheus.Collector, metricNames ...string) int { func GatherAndCount(g prometheus.Gatherer, metricNames ...string) (int, error) { got, err := g.Gather() if err != nil { - return 0, fmt.Errorf("gathering metrics failed: %s", err) + return 0, fmt.Errorf("gathering metrics failed: %w", err) } if metricNames != nil { got = filterMetrics(got, metricNames) @@ -151,13 +155,41 @@ func GatherAndCount(g prometheus.Gatherer, metricNames ...string) (int, error) { return result, nil } +// ScrapeAndCompare calls a remote exporter's endpoint which is expected to return some metrics in +// plain text format. Then it compares it with the results that the `expected` would return. +// If the `metricNames` is not empty it would filter the comparison only to the given metric names. +func ScrapeAndCompare(url string, expected io.Reader, metricNames ...string) error { + resp, err := http.Get(url) + if err != nil { + return fmt.Errorf("scraping metrics failed: %w", err) + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("the scraping target returned a status code other than 200: %d", + resp.StatusCode) + } + + scraped, err := convertReaderToMetricFamily(resp.Body) + if err != nil { + return err + } + + wanted, err := convertReaderToMetricFamily(expected) + if err != nil { + return err + } + + return compareMetricFamilies(scraped, wanted, metricNames...) +} + // CollectAndCompare registers the provided Collector with a newly created // pedantic Registry. It then calls GatherAndCompare with that Registry and with // the provided metricNames. func CollectAndCompare(c prometheus.Collector, expected io.Reader, metricNames ...string) error { reg := prometheus.NewPedanticRegistry() if err := reg.Register(c); err != nil { - return fmt.Errorf("registering collector failed: %s", err) + return fmt.Errorf("registering collector failed: %w", err) } return GatherAndCompare(reg, expected, metricNames...) } @@ -167,21 +199,49 @@ func CollectAndCompare(c prometheus.Collector, expected io.Reader, metricNames . // exposition format. If any metricNames are provided, only metrics with those // names are compared. func GatherAndCompare(g prometheus.Gatherer, expected io.Reader, metricNames ...string) error { - got, err := g.Gather() + return TransactionalGatherAndCompare(prometheus.ToTransactionalGatherer(g), expected, metricNames...) +} + +// TransactionalGatherAndCompare gathers all metrics from the provided Gatherer and compares +// it to an expected output read from the provided Reader in the Prometheus text +// exposition format. If any metricNames are provided, only metrics with those +// names are compared. +func TransactionalGatherAndCompare(g prometheus.TransactionalGatherer, expected io.Reader, metricNames ...string) error { + got, done, err := g.Gather() + defer done() if err != nil { - return fmt.Errorf("gathering metrics failed: %s", err) + return fmt.Errorf("gathering metrics failed: %w", err) } - if metricNames != nil { - got = filterMetrics(got, metricNames) + + wanted, err := convertReaderToMetricFamily(expected) + if err != nil { + return err } + + return compareMetricFamilies(got, wanted, metricNames...) +} + +// convertReaderToMetricFamily would read from a io.Reader object and convert it to a slice of +// dto.MetricFamily. +func convertReaderToMetricFamily(reader io.Reader) ([]*dto.MetricFamily, error) { var tp expfmt.TextParser - wantRaw, err := tp.TextToMetricFamilies(expected) + notNormalized, err := tp.TextToMetricFamilies(reader) if err != nil { - return fmt.Errorf("parsing expected metrics failed: %s", err) + return nil, fmt.Errorf("converting reader to metric families failed: %w", err) } - want := internal.NormalizeMetricFamilies(wantRaw) - return compare(got, want) + return internal.NormalizeMetricFamilies(notNormalized), nil +} + +// compareMetricFamilies would compare 2 slices of metric families, and optionally filters both of +// them to the `metricNames` provided. +func compareMetricFamilies(got, expected []*dto.MetricFamily, metricNames ...string) error { + if metricNames != nil { + got = filterMetrics(got, metricNames) + expected = filterMetrics(expected, metricNames) + } + + return compare(got, expected) } // compare encodes both provided slices of metric families into the text format, @@ -193,27 +253,80 @@ func compare(got, want []*dto.MetricFamily) error { enc := expfmt.NewEncoder(&gotBuf, expfmt.FmtText) for _, mf := range got { if err := enc.Encode(mf); err != nil { - return fmt.Errorf("encoding gathered metrics failed: %s", err) + return fmt.Errorf("encoding gathered metrics failed: %w", err) } } enc = expfmt.NewEncoder(&wantBuf, expfmt.FmtText) for _, mf := range want { if err := enc.Encode(mf); err != nil { - return fmt.Errorf("encoding expected metrics failed: %s", err) + return fmt.Errorf("encoding expected metrics failed: %w", err) } } + if diffErr := diff(wantBuf, gotBuf); diffErr != "" { + return fmt.Errorf(diffErr) + } + return nil +} + +// diff returns a diff of both values as long as both are of the same type and +// are a struct, map, slice, array or string. Otherwise it returns an empty string. +func diff(expected, actual interface{}) string { + if expected == nil || actual == nil { + return "" + } - if wantBuf.String() != gotBuf.String() { - return fmt.Errorf(` -metric output does not match expectation; want: + et, ek := typeAndKind(expected) + at, _ := typeAndKind(actual) + if et != at { + return "" + } -%s -got: + if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array && ek != reflect.String { + return "" + } + + var e, a string + c := spew.ConfigState{ + Indent: " ", + DisablePointerAddresses: true, + DisableCapacities: true, + SortKeys: true, + } + if et != reflect.TypeOf("") { + e = c.Sdump(expected) + a = c.Sdump(actual) + } else { + e = reflect.ValueOf(expected).String() + a = reflect.ValueOf(actual).String() + } -%s`, wantBuf.String(), gotBuf.String()) + diff, _ := internal.GetUnifiedDiffString(internal.UnifiedDiff{ + A: internal.SplitLines(e), + B: internal.SplitLines(a), + FromFile: "metric output does not match expectation; want", + FromDate: "", + ToFile: "got:", + ToDate: "", + Context: 1, + }) + if diff == "" { + return "" } - return nil + + return "\n\nDiff:\n" + diff +} + +// typeAndKind returns the type and kind of the given interface{} +func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) { + t := reflect.TypeOf(v) + k := t.Kind() + + if k == reflect.Ptr { + t = t.Elem() + k = t.Kind() + } + return t, k } func filterMetrics(metrics []*dto.MetricFamily, names []string) []*dto.MetricFamily { diff --git a/vendor/github.com/prometheus/client_golang/prometheus/timer.go b/vendor/github.com/prometheus/client_golang/prometheus/timer.go index 8d5f105233..52344fef53 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/timer.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/timer.go @@ -23,13 +23,24 @@ type Timer struct { } // NewTimer creates a new Timer. The provided Observer is used to observe a -// duration in seconds. Timer is usually used to time a function call in the +// duration in seconds. If the Observer implements ExemplarObserver, passing exemplar +// later on will be also supported. +// Timer is usually used to time a function call in the // following way: -// func TimeMe() { -// timer := NewTimer(myHistogram) -// defer timer.ObserveDuration() -// // Do actual work. -// } +// +// func TimeMe() { +// timer := NewTimer(myHistogram) +// defer timer.ObserveDuration() +// // Do actual work. +// } +// +// or +// +// func TimeMeWithExemplar() { +// timer := NewTimer(myHistogram) +// defer timer.ObserveDurationWithExemplar(exemplar) +// // Do actual work. +// } func NewTimer(o Observer) *Timer { return &Timer{ begin: time.Now(), @@ -52,3 +63,19 @@ func (t *Timer) ObserveDuration() time.Duration { } return d } + +// ObserveDurationWithExemplar is like ObserveDuration, but it will also +// observe exemplar with the duration unless exemplar is nil or provided Observer can't +// be casted to ExemplarObserver. +func (t *Timer) ObserveDurationWithExemplar(exemplar Labels) time.Duration { + d := time.Since(t.begin) + eo, ok := t.observer.(ExemplarObserver) + if ok && exemplar != nil { + eo.ObserveWithExemplar(d.Seconds(), exemplar) + return d + } + if t.observer != nil { + t.observer.Observe(d.Seconds()) + } + return d +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/value.go b/vendor/github.com/prometheus/client_golang/prometheus/value.go index b4e0ae11cb..5f6bb80014 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/value.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/value.go @@ -19,11 +19,11 @@ import ( "time" "unicode/utf8" - //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility. - "github.com/golang/protobuf/proto" - "google.golang.org/protobuf/types/known/timestamppb" + "github.com/prometheus/client_golang/prometheus/internal" dto "github.com/prometheus/client_model/go" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/timestamppb" ) // ValueType is an enumeration of metric types that represent a simple value. @@ -38,6 +38,23 @@ const ( UntypedValue ) +var ( + CounterMetricTypePtr = func() *dto.MetricType { d := dto.MetricType_COUNTER; return &d }() + GaugeMetricTypePtr = func() *dto.MetricType { d := dto.MetricType_GAUGE; return &d }() + UntypedMetricTypePtr = func() *dto.MetricType { d := dto.MetricType_UNTYPED; return &d }() +) + +func (v ValueType) ToDTO() *dto.MetricType { + switch v { + case CounterValue: + return CounterMetricTypePtr + case GaugeValue: + return GaugeMetricTypePtr + default: + return UntypedMetricTypePtr + } +} + // valueFunc is a generic metric for simple values retrieved on collect time // from a function. It implements Metric and Collector. Its effective type is // determined by ValueType. This is a low-level building block used by the @@ -91,11 +108,15 @@ func NewConstMetric(desc *Desc, valueType ValueType, value float64, labelValues if err := validateLabelValues(labelValues, len(desc.variableLabels)); err != nil { return nil, err } + + metric := &dto.Metric{} + if err := populateMetric(valueType, value, MakeLabelPairs(desc, labelValues), nil, metric); err != nil { + return nil, err + } + return &constMetric{ - desc: desc, - valType: valueType, - val: value, - labelPairs: MakeLabelPairs(desc, labelValues), + desc: desc, + metric: metric, }, nil } @@ -110,10 +131,8 @@ func MustNewConstMetric(desc *Desc, valueType ValueType, value float64, labelVal } type constMetric struct { - desc *Desc - valType ValueType - val float64 - labelPairs []*dto.LabelPair + desc *Desc + metric *dto.Metric } func (m *constMetric) Desc() *Desc { @@ -121,7 +140,11 @@ func (m *constMetric) Desc() *Desc { } func (m *constMetric) Write(out *dto.Metric) error { - return populateMetric(m.valType, m.val, m.labelPairs, nil, out) + out.Label = m.metric.Label + out.Counter = m.metric.Counter + out.Gauge = m.metric.Gauge + out.Untyped = m.metric.Untyped + return nil } func populateMetric( @@ -163,19 +186,19 @@ func MakeLabelPairs(desc *Desc, labelValues []string) []*dto.LabelPair { return desc.constLabelPairs } labelPairs := make([]*dto.LabelPair, 0, totalLen) - for i, n := range desc.variableLabels { + for i, l := range desc.variableLabels { labelPairs = append(labelPairs, &dto.LabelPair{ - Name: proto.String(n), + Name: proto.String(l.Name), Value: proto.String(labelValues[i]), }) } labelPairs = append(labelPairs, desc.constLabelPairs...) - sort.Sort(labelPairSorter(labelPairs)) + sort.Sort(internal.LabelPairSorter(labelPairs)) return labelPairs } // ExemplarMaxRunes is the max total number of runes allowed in exemplar labels. -const ExemplarMaxRunes = 64 +const ExemplarMaxRunes = 128 // newExemplar creates a new dto.Exemplar from the provided values. An error is // returned if any of the label names or values are invalid or if the total diff --git a/vendor/github.com/prometheus/client_golang/prometheus/vec.go b/vendor/github.com/prometheus/client_golang/prometheus/vec.go index 4ababe6c98..386fb2d23e 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/vec.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/vec.go @@ -72,6 +72,7 @@ func NewMetricVec(desc *Desc, newMetric func(lvs ...string) Metric) *MetricVec { // with a performance overhead (for creating and processing the Labels map). // See also the CounterVec example. func (m *MetricVec) DeleteLabelValues(lvs ...string) bool { + lvs = constrainLabelValues(m.desc, lvs, m.curry) h, err := m.hashLabelValues(lvs) if err != nil { return false @@ -91,6 +92,7 @@ func (m *MetricVec) DeleteLabelValues(lvs ...string) bool { // This method is used for the same purpose as DeleteLabelValues(...string). See // there for pros and cons of the two methods. func (m *MetricVec) Delete(labels Labels) bool { + labels = constrainLabels(m.desc, labels) h, err := m.hashLabels(labels) if err != nil { return false @@ -99,6 +101,17 @@ func (m *MetricVec) Delete(labels Labels) bool { return m.metricMap.deleteByHashWithLabels(h, labels, m.curry) } +// DeletePartialMatch deletes all metrics where the variable labels contain all of those +// passed in as labels. The order of the labels does not matter. +// It returns the number of metrics deleted. +// +// Note that curried labels will never be matched if deleting from the curried vector. +// To match curried labels with DeletePartialMatch, it must be called on the base vector. +func (m *MetricVec) DeletePartialMatch(labels Labels) int { + labels = constrainLabels(m.desc, labels) + return m.metricMap.deleteByLabels(labels, m.curry) +} + // Without explicit forwarding of Describe, Collect, Reset, those methods won't // show up in GoDoc. @@ -135,10 +148,10 @@ func (m *MetricVec) CurryWith(labels Labels) (*MetricVec, error) { iCurry int ) for i, label := range m.desc.variableLabels { - val, ok := labels[label] + val, ok := labels[label.Name] if iCurry < len(oldCurry) && oldCurry[iCurry].index == i { if ok { - return nil, fmt.Errorf("label name %q is already curried", label) + return nil, fmt.Errorf("label name %q is already curried", label.Name) } newCurry = append(newCurry, oldCurry[iCurry]) iCurry++ @@ -146,7 +159,7 @@ func (m *MetricVec) CurryWith(labels Labels) (*MetricVec, error) { if !ok { continue // Label stays uncurried. } - newCurry = append(newCurry, curriedLabelValue{i, val}) + newCurry = append(newCurry, curriedLabelValue{i, label.Constrain(val)}) } } if l := len(oldCurry) + len(labels) - len(newCurry); l > 0 { @@ -189,6 +202,7 @@ func (m *MetricVec) CurryWith(labels Labels) (*MetricVec, error) { // a wrapper around MetricVec, implementing a vector for a specific Metric // implementation, for example GaugeVec. func (m *MetricVec) GetMetricWithLabelValues(lvs ...string) (Metric, error) { + lvs = constrainLabelValues(m.desc, lvs, m.curry) h, err := m.hashLabelValues(lvs) if err != nil { return nil, err @@ -214,6 +228,7 @@ func (m *MetricVec) GetMetricWithLabelValues(lvs ...string) (Metric, error) { // around MetricVec, implementing a vector for a specific Metric implementation, // for example GaugeVec. func (m *MetricVec) GetMetricWith(labels Labels) (Metric, error) { + labels = constrainLabels(m.desc, labels) h, err := m.hashLabels(labels) if err != nil { return nil, err @@ -256,16 +271,16 @@ func (m *MetricVec) hashLabels(labels Labels) (uint64, error) { iCurry int ) for i, label := range m.desc.variableLabels { - val, ok := labels[label] + val, ok := labels[label.Name] if iCurry < len(curry) && curry[iCurry].index == i { if ok { - return 0, fmt.Errorf("label name %q is already curried", label) + return 0, fmt.Errorf("label name %q is already curried", label.Name) } h = m.hashAdd(h, curry[iCurry].value) iCurry++ } else { if !ok { - return 0, fmt.Errorf("label name %q missing in label map", label) + return 0, fmt.Errorf("label name %q missing in label map", label.Name) } h = m.hashAdd(h, val) } @@ -381,6 +396,82 @@ func (m *metricMap) deleteByHashWithLabels( return true } +// deleteByLabels deletes a metric if the given labels are present in the metric. +func (m *metricMap) deleteByLabels(labels Labels, curry []curriedLabelValue) int { + m.mtx.Lock() + defer m.mtx.Unlock() + + var numDeleted int + + for h, metrics := range m.metrics { + i := findMetricWithPartialLabels(m.desc, metrics, labels, curry) + if i >= len(metrics) { + // Didn't find matching labels in this metric slice. + continue + } + delete(m.metrics, h) + numDeleted++ + } + + return numDeleted +} + +// findMetricWithPartialLabel returns the index of the matching metric or +// len(metrics) if not found. +func findMetricWithPartialLabels( + desc *Desc, metrics []metricWithLabelValues, labels Labels, curry []curriedLabelValue, +) int { + for i, metric := range metrics { + if matchPartialLabels(desc, metric.values, labels, curry) { + return i + } + } + return len(metrics) +} + +// indexOf searches the given slice of strings for the target string and returns +// the index or len(items) as well as a boolean whether the search succeeded. +func indexOf(target string, items []string) (int, bool) { + for i, l := range items { + if l == target { + return i, true + } + } + return len(items), false +} + +// valueMatchesVariableOrCurriedValue determines if a value was previously curried, +// and returns whether it matches either the "base" value or the curried value accordingly. +// It also indicates whether the match is against a curried or uncurried value. +func valueMatchesVariableOrCurriedValue(targetValue string, index int, values []string, curry []curriedLabelValue) (bool, bool) { + for _, curriedValue := range curry { + if curriedValue.index == index { + // This label was curried. See if the curried value matches our target. + return curriedValue.value == targetValue, true + } + } + // This label was not curried. See if the current value matches our target label. + return values[index] == targetValue, false +} + +// matchPartialLabels searches the current metric and returns whether all of the target label:value pairs are present. +func matchPartialLabels(desc *Desc, values []string, labels Labels, curry []curriedLabelValue) bool { + for l, v := range labels { + // Check if the target label exists in our metrics and get the index. + varLabelIndex, validLabel := indexOf(l, desc.variableLabels.labelNames()) + if validLabel { + // Check the value of that label against the target value. + // We don't consider curried values in partial matches. + matches, curried := valueMatchesVariableOrCurriedValue(v, varLabelIndex, values, curry) + if matches && !curried { + continue + } + } + return false + } + return true +} + // getOrCreateMetricWithLabelValues retrieves the metric by hash and label value // or creates it and returns the new one. // @@ -485,7 +576,7 @@ func findMetricWithLabels( return len(metrics) } -func matchLabelValues(values []string, lvs []string, curry []curriedLabelValue) bool { +func matchLabelValues(values, lvs []string, curry []curriedLabelValue) bool { if len(values) != len(lvs)+len(curry) { return false } @@ -519,7 +610,7 @@ func matchLabels(desc *Desc, values []string, labels Labels, curry []curriedLabe iCurry++ continue } - if values[i] != labels[k] { + if values[i] != labels[k.Name] { return false } } @@ -535,7 +626,7 @@ func extractLabelValues(desc *Desc, labels Labels, curry []curriedLabelValue) [] iCurry++ continue } - labelValues[i] = labels[k] + labelValues[i] = labels[k.Name] } return labelValues } @@ -554,3 +645,34 @@ func inlineLabelValues(lvs []string, curry []curriedLabelValue) []string { } return labelValues } + +func constrainLabels(desc *Desc, labels Labels) Labels { + constrainedValues := make(Labels, len(labels)) + for l, v := range labels { + if i, ok := indexOf(l, desc.variableLabels.labelNames()); ok { + constrainedValues[l] = desc.variableLabels[i].Constrain(v) + continue + } + constrainedValues[l] = v + } + return constrainedValues +} + +func constrainLabelValues(desc *Desc, lvs []string, curry []curriedLabelValue) []string { + constrainedValues := make([]string, len(lvs)) + var iCurry, iLVs int + for i := 0; i < len(lvs)+len(curry); i++ { + if iCurry < len(curry) && curry[iCurry].index == i { + iCurry++ + continue + } + + if i < len(desc.variableLabels) { + constrainedValues[iLVs] = desc.variableLabels[i].Constrain(lvs[iLVs]) + } else { + constrainedValues[iLVs] = lvs[iLVs] + } + iLVs++ + } + return constrainedValues +} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/vnext.go b/vendor/github.com/prometheus/client_golang/prometheus/vnext.go new file mode 100644 index 0000000000..42bc3a8f06 --- /dev/null +++ b/vendor/github.com/prometheus/client_golang/prometheus/vnext.go @@ -0,0 +1,23 @@ +// Copyright 2022 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package prometheus + +type v2 struct{} + +// V2 is a struct that can be referenced to access experimental API that might +// be present in v2 of client golang someday. It offers extended functionality +// of v1 with slightly changed API. It is acceptable to use some pieces from v1 +// and e.g `prometheus.NewGauge` and some from v2 e.g. `prometheus.V2.NewDesc` +// in the same codebase. +var V2 = v2{} diff --git a/vendor/github.com/prometheus/client_golang/prometheus/wrap.go b/vendor/github.com/prometheus/client_golang/prometheus/wrap.go index 74ee93280f..25da157f15 100644 --- a/vendor/github.com/prometheus/client_golang/prometheus/wrap.go +++ b/vendor/github.com/prometheus/client_golang/prometheus/wrap.go @@ -17,10 +17,10 @@ import ( "fmt" "sort" - //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility. - "github.com/golang/protobuf/proto" + "github.com/prometheus/client_golang/prometheus/internal" dto "github.com/prometheus/client_model/go" + "google.golang.org/protobuf/proto" ) // WrapRegistererWith returns a Registerer wrapping the provided @@ -182,7 +182,7 @@ func (m *wrappingMetric) Write(out *dto.Metric) error { Value: proto.String(lv), }) } - sort.Sort(labelPairSorter(out.Label)) + sort.Sort(internal.LabelPairSorter(out.Label)) return nil } @@ -204,7 +204,7 @@ func wrapDesc(desc *Desc, prefix string, labels Labels) *Desc { constLabels[ln] = lv } // NewDesc will do remaining validations. - newDesc := NewDesc(prefix+desc.fqName, desc.help, desc.variableLabels, constLabels) + newDesc := V2.NewDesc(prefix+desc.fqName, desc.help, desc.variableLabels, constLabels) // Propagate errors if there was any. This will override any errer // created by NewDesc above, i.e. earlier errors get precedence. if desc.err != nil { diff --git a/vendor/github.com/prometheus/client_model/go/metrics.pb.go b/vendor/github.com/prometheus/client_model/go/metrics.pb.go index 2f4930d9dd..2b5bca4b99 100644 --- a/vendor/github.com/prometheus/client_model/go/metrics.pb.go +++ b/vendor/github.com/prometheus/client_model/go/metrics.pb.go @@ -1,51 +1,75 @@ +// Copyright 2013 Prometheus Team +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + // Code generated by protoc-gen-go. DO NOT EDIT. -// source: metrics.proto +// versions: +// protoc-gen-go v1.30.0 +// protoc v3.20.3 +// source: io/prometheus/client/metrics.proto package io_prometheus_client import ( - fmt "fmt" - proto "github.com/golang/protobuf/proto" - timestamp "github.com/golang/protobuf/ptypes/timestamp" - math "math" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" ) -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) type MetricType int32 const ( - MetricType_COUNTER MetricType = 0 - MetricType_GAUGE MetricType = 1 - MetricType_SUMMARY MetricType = 2 - MetricType_UNTYPED MetricType = 3 + // COUNTER must use the Metric field "counter". + MetricType_COUNTER MetricType = 0 + // GAUGE must use the Metric field "gauge". + MetricType_GAUGE MetricType = 1 + // SUMMARY must use the Metric field "summary". + MetricType_SUMMARY MetricType = 2 + // UNTYPED must use the Metric field "untyped". + MetricType_UNTYPED MetricType = 3 + // HISTOGRAM must use the Metric field "histogram". MetricType_HISTOGRAM MetricType = 4 + // GAUGE_HISTOGRAM must use the Metric field "histogram". + MetricType_GAUGE_HISTOGRAM MetricType = 5 ) -var MetricType_name = map[int32]string{ - 0: "COUNTER", - 1: "GAUGE", - 2: "SUMMARY", - 3: "UNTYPED", - 4: "HISTOGRAM", -} - -var MetricType_value = map[string]int32{ - "COUNTER": 0, - "GAUGE": 1, - "SUMMARY": 2, - "UNTYPED": 3, - "HISTOGRAM": 4, -} +// Enum value maps for MetricType. +var ( + MetricType_name = map[int32]string{ + 0: "COUNTER", + 1: "GAUGE", + 2: "SUMMARY", + 3: "UNTYPED", + 4: "HISTOGRAM", + 5: "GAUGE_HISTOGRAM", + } + MetricType_value = map[string]int32{ + "COUNTER": 0, + "GAUGE": 1, + "SUMMARY": 2, + "UNTYPED": 3, + "HISTOGRAM": 4, + "GAUGE_HISTOGRAM": 5, + } +) func (x MetricType) Enum() *MetricType { p := new(MetricType) @@ -54,670 +78,1255 @@ func (x MetricType) Enum() *MetricType { } func (x MetricType) String() string { - return proto.EnumName(MetricType_name, int32(x)) + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (MetricType) Descriptor() protoreflect.EnumDescriptor { + return file_io_prometheus_client_metrics_proto_enumTypes[0].Descriptor() } -func (x *MetricType) UnmarshalJSON(data []byte) error { - value, err := proto.UnmarshalJSONEnum(MetricType_value, data, "MetricType") +func (MetricType) Type() protoreflect.EnumType { + return &file_io_prometheus_client_metrics_proto_enumTypes[0] +} + +func (x MetricType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Do not use. +func (x *MetricType) UnmarshalJSON(b []byte) error { + num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) if err != nil { return err } - *x = MetricType(value) + *x = MetricType(num) return nil } +// Deprecated: Use MetricType.Descriptor instead. func (MetricType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_6039342a2ba47b72, []int{0} + return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{0} } type LabelPair struct { - Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - Value *string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -func (m *LabelPair) Reset() { *m = LabelPair{} } -func (m *LabelPair) String() string { return proto.CompactTextString(m) } -func (*LabelPair) ProtoMessage() {} -func (*LabelPair) Descriptor() ([]byte, []int) { - return fileDescriptor_6039342a2ba47b72, []int{0} + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Value *string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"` } -func (m *LabelPair) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_LabelPair.Unmarshal(m, b) -} -func (m *LabelPair) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_LabelPair.Marshal(b, m, deterministic) -} -func (m *LabelPair) XXX_Merge(src proto.Message) { - xxx_messageInfo_LabelPair.Merge(m, src) +func (x *LabelPair) Reset() { + *x = LabelPair{} + if protoimpl.UnsafeEnabled { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *LabelPair) XXX_Size() int { - return xxx_messageInfo_LabelPair.Size(m) + +func (x *LabelPair) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *LabelPair) XXX_DiscardUnknown() { - xxx_messageInfo_LabelPair.DiscardUnknown(m) + +func (*LabelPair) ProtoMessage() {} + +func (x *LabelPair) ProtoReflect() protoreflect.Message { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_LabelPair proto.InternalMessageInfo +// Deprecated: Use LabelPair.ProtoReflect.Descriptor instead. +func (*LabelPair) Descriptor() ([]byte, []int) { + return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{0} +} -func (m *LabelPair) GetName() string { - if m != nil && m.Name != nil { - return *m.Name +func (x *LabelPair) GetName() string { + if x != nil && x.Name != nil { + return *x.Name } return "" } -func (m *LabelPair) GetValue() string { - if m != nil && m.Value != nil { - return *m.Value +func (x *LabelPair) GetValue() string { + if x != nil && x.Value != nil { + return *x.Value } return "" } type Gauge struct { - Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -func (m *Gauge) Reset() { *m = Gauge{} } -func (m *Gauge) String() string { return proto.CompactTextString(m) } -func (*Gauge) ProtoMessage() {} -func (*Gauge) Descriptor() ([]byte, []int) { - return fileDescriptor_6039342a2ba47b72, []int{1} + Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"` } -func (m *Gauge) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Gauge.Unmarshal(m, b) -} -func (m *Gauge) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Gauge.Marshal(b, m, deterministic) -} -func (m *Gauge) XXX_Merge(src proto.Message) { - xxx_messageInfo_Gauge.Merge(m, src) +func (x *Gauge) Reset() { + *x = Gauge{} + if protoimpl.UnsafeEnabled { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *Gauge) XXX_Size() int { - return xxx_messageInfo_Gauge.Size(m) + +func (x *Gauge) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *Gauge) XXX_DiscardUnknown() { - xxx_messageInfo_Gauge.DiscardUnknown(m) + +func (*Gauge) ProtoMessage() {} + +func (x *Gauge) ProtoReflect() protoreflect.Message { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_Gauge proto.InternalMessageInfo +// Deprecated: Use Gauge.ProtoReflect.Descriptor instead. +func (*Gauge) Descriptor() ([]byte, []int) { + return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{1} +} -func (m *Gauge) GetValue() float64 { - if m != nil && m.Value != nil { - return *m.Value +func (x *Gauge) GetValue() float64 { + if x != nil && x.Value != nil { + return *x.Value } return 0 } type Counter struct { - Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"` - Exemplar *Exemplar `protobuf:"bytes,2,opt,name=exemplar" json:"exemplar,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -func (m *Counter) Reset() { *m = Counter{} } -func (m *Counter) String() string { return proto.CompactTextString(m) } -func (*Counter) ProtoMessage() {} -func (*Counter) Descriptor() ([]byte, []int) { - return fileDescriptor_6039342a2ba47b72, []int{2} + Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"` + Exemplar *Exemplar `protobuf:"bytes,2,opt,name=exemplar" json:"exemplar,omitempty"` } -func (m *Counter) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Counter.Unmarshal(m, b) -} -func (m *Counter) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Counter.Marshal(b, m, deterministic) -} -func (m *Counter) XXX_Merge(src proto.Message) { - xxx_messageInfo_Counter.Merge(m, src) +func (x *Counter) Reset() { + *x = Counter{} + if protoimpl.UnsafeEnabled { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *Counter) XXX_Size() int { - return xxx_messageInfo_Counter.Size(m) + +func (x *Counter) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *Counter) XXX_DiscardUnknown() { - xxx_messageInfo_Counter.DiscardUnknown(m) + +func (*Counter) ProtoMessage() {} + +func (x *Counter) ProtoReflect() protoreflect.Message { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_Counter proto.InternalMessageInfo +// Deprecated: Use Counter.ProtoReflect.Descriptor instead. +func (*Counter) Descriptor() ([]byte, []int) { + return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{2} +} -func (m *Counter) GetValue() float64 { - if m != nil && m.Value != nil { - return *m.Value +func (x *Counter) GetValue() float64 { + if x != nil && x.Value != nil { + return *x.Value } return 0 } -func (m *Counter) GetExemplar() *Exemplar { - if m != nil { - return m.Exemplar +func (x *Counter) GetExemplar() *Exemplar { + if x != nil { + return x.Exemplar } return nil } type Quantile struct { - Quantile *float64 `protobuf:"fixed64,1,opt,name=quantile" json:"quantile,omitempty"` - Value *float64 `protobuf:"fixed64,2,opt,name=value" json:"value,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -func (m *Quantile) Reset() { *m = Quantile{} } -func (m *Quantile) String() string { return proto.CompactTextString(m) } -func (*Quantile) ProtoMessage() {} -func (*Quantile) Descriptor() ([]byte, []int) { - return fileDescriptor_6039342a2ba47b72, []int{3} + Quantile *float64 `protobuf:"fixed64,1,opt,name=quantile" json:"quantile,omitempty"` + Value *float64 `protobuf:"fixed64,2,opt,name=value" json:"value,omitempty"` } -func (m *Quantile) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Quantile.Unmarshal(m, b) -} -func (m *Quantile) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Quantile.Marshal(b, m, deterministic) -} -func (m *Quantile) XXX_Merge(src proto.Message) { - xxx_messageInfo_Quantile.Merge(m, src) +func (x *Quantile) Reset() { + *x = Quantile{} + if protoimpl.UnsafeEnabled { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *Quantile) XXX_Size() int { - return xxx_messageInfo_Quantile.Size(m) + +func (x *Quantile) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *Quantile) XXX_DiscardUnknown() { - xxx_messageInfo_Quantile.DiscardUnknown(m) + +func (*Quantile) ProtoMessage() {} + +func (x *Quantile) ProtoReflect() protoreflect.Message { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_Quantile proto.InternalMessageInfo +// Deprecated: Use Quantile.ProtoReflect.Descriptor instead. +func (*Quantile) Descriptor() ([]byte, []int) { + return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{3} +} -func (m *Quantile) GetQuantile() float64 { - if m != nil && m.Quantile != nil { - return *m.Quantile +func (x *Quantile) GetQuantile() float64 { + if x != nil && x.Quantile != nil { + return *x.Quantile } return 0 } -func (m *Quantile) GetValue() float64 { - if m != nil && m.Value != nil { - return *m.Value +func (x *Quantile) GetValue() float64 { + if x != nil && x.Value != nil { + return *x.Value } return 0 } type Summary struct { - SampleCount *uint64 `protobuf:"varint,1,opt,name=sample_count,json=sampleCount" json:"sample_count,omitempty"` - SampleSum *float64 `protobuf:"fixed64,2,opt,name=sample_sum,json=sampleSum" json:"sample_sum,omitempty"` - Quantile []*Quantile `protobuf:"bytes,3,rep,name=quantile" json:"quantile,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -func (m *Summary) Reset() { *m = Summary{} } -func (m *Summary) String() string { return proto.CompactTextString(m) } -func (*Summary) ProtoMessage() {} -func (*Summary) Descriptor() ([]byte, []int) { - return fileDescriptor_6039342a2ba47b72, []int{4} + SampleCount *uint64 `protobuf:"varint,1,opt,name=sample_count,json=sampleCount" json:"sample_count,omitempty"` + SampleSum *float64 `protobuf:"fixed64,2,opt,name=sample_sum,json=sampleSum" json:"sample_sum,omitempty"` + Quantile []*Quantile `protobuf:"bytes,3,rep,name=quantile" json:"quantile,omitempty"` } -func (m *Summary) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Summary.Unmarshal(m, b) -} -func (m *Summary) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Summary.Marshal(b, m, deterministic) -} -func (m *Summary) XXX_Merge(src proto.Message) { - xxx_messageInfo_Summary.Merge(m, src) +func (x *Summary) Reset() { + *x = Summary{} + if protoimpl.UnsafeEnabled { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *Summary) XXX_Size() int { - return xxx_messageInfo_Summary.Size(m) + +func (x *Summary) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *Summary) XXX_DiscardUnknown() { - xxx_messageInfo_Summary.DiscardUnknown(m) + +func (*Summary) ProtoMessage() {} + +func (x *Summary) ProtoReflect() protoreflect.Message { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_Summary proto.InternalMessageInfo +// Deprecated: Use Summary.ProtoReflect.Descriptor instead. +func (*Summary) Descriptor() ([]byte, []int) { + return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{4} +} -func (m *Summary) GetSampleCount() uint64 { - if m != nil && m.SampleCount != nil { - return *m.SampleCount +func (x *Summary) GetSampleCount() uint64 { + if x != nil && x.SampleCount != nil { + return *x.SampleCount } return 0 } -func (m *Summary) GetSampleSum() float64 { - if m != nil && m.SampleSum != nil { - return *m.SampleSum +func (x *Summary) GetSampleSum() float64 { + if x != nil && x.SampleSum != nil { + return *x.SampleSum } return 0 } -func (m *Summary) GetQuantile() []*Quantile { - if m != nil { - return m.Quantile +func (x *Summary) GetQuantile() []*Quantile { + if x != nil { + return x.Quantile } return nil } type Untyped struct { - Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -func (m *Untyped) Reset() { *m = Untyped{} } -func (m *Untyped) String() string { return proto.CompactTextString(m) } -func (*Untyped) ProtoMessage() {} -func (*Untyped) Descriptor() ([]byte, []int) { - return fileDescriptor_6039342a2ba47b72, []int{5} + Value *float64 `protobuf:"fixed64,1,opt,name=value" json:"value,omitempty"` } -func (m *Untyped) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Untyped.Unmarshal(m, b) -} -func (m *Untyped) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Untyped.Marshal(b, m, deterministic) -} -func (m *Untyped) XXX_Merge(src proto.Message) { - xxx_messageInfo_Untyped.Merge(m, src) +func (x *Untyped) Reset() { + *x = Untyped{} + if protoimpl.UnsafeEnabled { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *Untyped) XXX_Size() int { - return xxx_messageInfo_Untyped.Size(m) + +func (x *Untyped) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *Untyped) XXX_DiscardUnknown() { - xxx_messageInfo_Untyped.DiscardUnknown(m) + +func (*Untyped) ProtoMessage() {} + +func (x *Untyped) ProtoReflect() protoreflect.Message { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_Untyped proto.InternalMessageInfo +// Deprecated: Use Untyped.ProtoReflect.Descriptor instead. +func (*Untyped) Descriptor() ([]byte, []int) { + return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{5} +} -func (m *Untyped) GetValue() float64 { - if m != nil && m.Value != nil { - return *m.Value +func (x *Untyped) GetValue() float64 { + if x != nil && x.Value != nil { + return *x.Value } return 0 } type Histogram struct { - SampleCount *uint64 `protobuf:"varint,1,opt,name=sample_count,json=sampleCount" json:"sample_count,omitempty"` - SampleSum *float64 `protobuf:"fixed64,2,opt,name=sample_sum,json=sampleSum" json:"sample_sum,omitempty"` - Bucket []*Bucket `protobuf:"bytes,3,rep,name=bucket" json:"bucket,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SampleCount *uint64 `protobuf:"varint,1,opt,name=sample_count,json=sampleCount" json:"sample_count,omitempty"` + SampleCountFloat *float64 `protobuf:"fixed64,4,opt,name=sample_count_float,json=sampleCountFloat" json:"sample_count_float,omitempty"` // Overrides sample_count if > 0. + SampleSum *float64 `protobuf:"fixed64,2,opt,name=sample_sum,json=sampleSum" json:"sample_sum,omitempty"` + // Buckets for the conventional histogram. + Bucket []*Bucket `protobuf:"bytes,3,rep,name=bucket" json:"bucket,omitempty"` // Ordered in increasing order of upper_bound, +Inf bucket is optional. + // schema defines the bucket schema. Currently, valid numbers are -4 <= n <= 8. + // They are all for base-2 bucket schemas, where 1 is a bucket boundary in each case, and + // then each power of two is divided into 2^n logarithmic buckets. + // Or in other words, each bucket boundary is the previous boundary times 2^(2^-n). + // In the future, more bucket schemas may be added using numbers < -4 or > 8. + Schema *int32 `protobuf:"zigzag32,5,opt,name=schema" json:"schema,omitempty"` + ZeroThreshold *float64 `protobuf:"fixed64,6,opt,name=zero_threshold,json=zeroThreshold" json:"zero_threshold,omitempty"` // Breadth of the zero bucket. + ZeroCount *uint64 `protobuf:"varint,7,opt,name=zero_count,json=zeroCount" json:"zero_count,omitempty"` // Count in zero bucket. + ZeroCountFloat *float64 `protobuf:"fixed64,8,opt,name=zero_count_float,json=zeroCountFloat" json:"zero_count_float,omitempty"` // Overrides sb_zero_count if > 0. + // Negative buckets for the native histogram. + NegativeSpan []*BucketSpan `protobuf:"bytes,9,rep,name=negative_span,json=negativeSpan" json:"negative_span,omitempty"` + // Use either "negative_delta" or "negative_count", the former for + // regular histograms with integer counts, the latter for float + // histograms. + NegativeDelta []int64 `protobuf:"zigzag64,10,rep,name=negative_delta,json=negativeDelta" json:"negative_delta,omitempty"` // Count delta of each bucket compared to previous one (or to zero for 1st bucket). + NegativeCount []float64 `protobuf:"fixed64,11,rep,name=negative_count,json=negativeCount" json:"negative_count,omitempty"` // Absolute count of each bucket. + // Positive buckets for the native histogram. + PositiveSpan []*BucketSpan `protobuf:"bytes,12,rep,name=positive_span,json=positiveSpan" json:"positive_span,omitempty"` + // Use either "positive_delta" or "positive_count", the former for + // regular histograms with integer counts, the latter for float + // histograms. + PositiveDelta []int64 `protobuf:"zigzag64,13,rep,name=positive_delta,json=positiveDelta" json:"positive_delta,omitempty"` // Count delta of each bucket compared to previous one (or to zero for 1st bucket). + PositiveCount []float64 `protobuf:"fixed64,14,rep,name=positive_count,json=positiveCount" json:"positive_count,omitempty"` // Absolute count of each bucket. +} + +func (x *Histogram) Reset() { + *x = Histogram{} + if protoimpl.UnsafeEnabled { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Histogram) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Histogram) ProtoMessage() {} + +func (x *Histogram) ProtoReflect() protoreflect.Message { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -func (m *Histogram) Reset() { *m = Histogram{} } -func (m *Histogram) String() string { return proto.CompactTextString(m) } -func (*Histogram) ProtoMessage() {} +// Deprecated: Use Histogram.ProtoReflect.Descriptor instead. func (*Histogram) Descriptor() ([]byte, []int) { - return fileDescriptor_6039342a2ba47b72, []int{6} + return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{6} } -func (m *Histogram) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Histogram.Unmarshal(m, b) +func (x *Histogram) GetSampleCount() uint64 { + if x != nil && x.SampleCount != nil { + return *x.SampleCount + } + return 0 } -func (m *Histogram) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Histogram.Marshal(b, m, deterministic) + +func (x *Histogram) GetSampleCountFloat() float64 { + if x != nil && x.SampleCountFloat != nil { + return *x.SampleCountFloat + } + return 0 } -func (m *Histogram) XXX_Merge(src proto.Message) { - xxx_messageInfo_Histogram.Merge(m, src) + +func (x *Histogram) GetSampleSum() float64 { + if x != nil && x.SampleSum != nil { + return *x.SampleSum + } + return 0 } -func (m *Histogram) XXX_Size() int { - return xxx_messageInfo_Histogram.Size(m) + +func (x *Histogram) GetBucket() []*Bucket { + if x != nil { + return x.Bucket + } + return nil } -func (m *Histogram) XXX_DiscardUnknown() { - xxx_messageInfo_Histogram.DiscardUnknown(m) + +func (x *Histogram) GetSchema() int32 { + if x != nil && x.Schema != nil { + return *x.Schema + } + return 0 } -var xxx_messageInfo_Histogram proto.InternalMessageInfo +func (x *Histogram) GetZeroThreshold() float64 { + if x != nil && x.ZeroThreshold != nil { + return *x.ZeroThreshold + } + return 0 +} -func (m *Histogram) GetSampleCount() uint64 { - if m != nil && m.SampleCount != nil { - return *m.SampleCount +func (x *Histogram) GetZeroCount() uint64 { + if x != nil && x.ZeroCount != nil { + return *x.ZeroCount } return 0 } -func (m *Histogram) GetSampleSum() float64 { - if m != nil && m.SampleSum != nil { - return *m.SampleSum +func (x *Histogram) GetZeroCountFloat() float64 { + if x != nil && x.ZeroCountFloat != nil { + return *x.ZeroCountFloat } return 0 } -func (m *Histogram) GetBucket() []*Bucket { - if m != nil { - return m.Bucket +func (x *Histogram) GetNegativeSpan() []*BucketSpan { + if x != nil { + return x.NegativeSpan } return nil } -type Bucket struct { - CumulativeCount *uint64 `protobuf:"varint,1,opt,name=cumulative_count,json=cumulativeCount" json:"cumulative_count,omitempty"` - UpperBound *float64 `protobuf:"fixed64,2,opt,name=upper_bound,json=upperBound" json:"upper_bound,omitempty"` - Exemplar *Exemplar `protobuf:"bytes,3,opt,name=exemplar" json:"exemplar,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` +func (x *Histogram) GetNegativeDelta() []int64 { + if x != nil { + return x.NegativeDelta + } + return nil } -func (m *Bucket) Reset() { *m = Bucket{} } -func (m *Bucket) String() string { return proto.CompactTextString(m) } -func (*Bucket) ProtoMessage() {} -func (*Bucket) Descriptor() ([]byte, []int) { - return fileDescriptor_6039342a2ba47b72, []int{7} +func (x *Histogram) GetNegativeCount() []float64 { + if x != nil { + return x.NegativeCount + } + return nil +} + +func (x *Histogram) GetPositiveSpan() []*BucketSpan { + if x != nil { + return x.PositiveSpan + } + return nil +} + +func (x *Histogram) GetPositiveDelta() []int64 { + if x != nil { + return x.PositiveDelta + } + return nil +} + +func (x *Histogram) GetPositiveCount() []float64 { + if x != nil { + return x.PositiveCount + } + return nil } -func (m *Bucket) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Bucket.Unmarshal(m, b) +// A Bucket of a conventional histogram, each of which is treated as +// an individual counter-like time series by Prometheus. +type Bucket struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + CumulativeCount *uint64 `protobuf:"varint,1,opt,name=cumulative_count,json=cumulativeCount" json:"cumulative_count,omitempty"` // Cumulative in increasing order. + CumulativeCountFloat *float64 `protobuf:"fixed64,4,opt,name=cumulative_count_float,json=cumulativeCountFloat" json:"cumulative_count_float,omitempty"` // Overrides cumulative_count if > 0. + UpperBound *float64 `protobuf:"fixed64,2,opt,name=upper_bound,json=upperBound" json:"upper_bound,omitempty"` // Inclusive. + Exemplar *Exemplar `protobuf:"bytes,3,opt,name=exemplar" json:"exemplar,omitempty"` } -func (m *Bucket) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Bucket.Marshal(b, m, deterministic) + +func (x *Bucket) Reset() { + *x = Bucket{} + if protoimpl.UnsafeEnabled { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *Bucket) XXX_Merge(src proto.Message) { - xxx_messageInfo_Bucket.Merge(m, src) + +func (x *Bucket) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *Bucket) XXX_Size() int { - return xxx_messageInfo_Bucket.Size(m) + +func (*Bucket) ProtoMessage() {} + +func (x *Bucket) ProtoReflect() protoreflect.Message { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -func (m *Bucket) XXX_DiscardUnknown() { - xxx_messageInfo_Bucket.DiscardUnknown(m) + +// Deprecated: Use Bucket.ProtoReflect.Descriptor instead. +func (*Bucket) Descriptor() ([]byte, []int) { + return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{7} } -var xxx_messageInfo_Bucket proto.InternalMessageInfo +func (x *Bucket) GetCumulativeCount() uint64 { + if x != nil && x.CumulativeCount != nil { + return *x.CumulativeCount + } + return 0 +} -func (m *Bucket) GetCumulativeCount() uint64 { - if m != nil && m.CumulativeCount != nil { - return *m.CumulativeCount +func (x *Bucket) GetCumulativeCountFloat() float64 { + if x != nil && x.CumulativeCountFloat != nil { + return *x.CumulativeCountFloat } return 0 } -func (m *Bucket) GetUpperBound() float64 { - if m != nil && m.UpperBound != nil { - return *m.UpperBound +func (x *Bucket) GetUpperBound() float64 { + if x != nil && x.UpperBound != nil { + return *x.UpperBound } return 0 } -func (m *Bucket) GetExemplar() *Exemplar { - if m != nil { - return m.Exemplar +func (x *Bucket) GetExemplar() *Exemplar { + if x != nil { + return x.Exemplar } return nil } -type Exemplar struct { - Label []*LabelPair `protobuf:"bytes,1,rep,name=label" json:"label,omitempty"` - Value *float64 `protobuf:"fixed64,2,opt,name=value" json:"value,omitempty"` - Timestamp *timestamp.Timestamp `protobuf:"bytes,3,opt,name=timestamp" json:"timestamp,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` +// A BucketSpan defines a number of consecutive buckets in a native +// histogram with their offset. Logically, it would be more +// straightforward to include the bucket counts in the Span. However, +// the protobuf representation is more compact in the way the data is +// structured here (with all the buckets in a single array separate +// from the Spans). +type BucketSpan struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Offset *int32 `protobuf:"zigzag32,1,opt,name=offset" json:"offset,omitempty"` // Gap to previous span, or starting point for 1st span (which can be negative). + Length *uint32 `protobuf:"varint,2,opt,name=length" json:"length,omitempty"` // Length of consecutive buckets. } -func (m *Exemplar) Reset() { *m = Exemplar{} } -func (m *Exemplar) String() string { return proto.CompactTextString(m) } -func (*Exemplar) ProtoMessage() {} -func (*Exemplar) Descriptor() ([]byte, []int) { - return fileDescriptor_6039342a2ba47b72, []int{8} +func (x *BucketSpan) Reset() { + *x = BucketSpan{} + if protoimpl.UnsafeEnabled { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BucketSpan) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BucketSpan) ProtoMessage() {} + +func (x *BucketSpan) ProtoReflect() protoreflect.Message { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BucketSpan.ProtoReflect.Descriptor instead. +func (*BucketSpan) Descriptor() ([]byte, []int) { + return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{8} +} + +func (x *BucketSpan) GetOffset() int32 { + if x != nil && x.Offset != nil { + return *x.Offset + } + return 0 } -func (m *Exemplar) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Exemplar.Unmarshal(m, b) +func (x *BucketSpan) GetLength() uint32 { + if x != nil && x.Length != nil { + return *x.Length + } + return 0 } -func (m *Exemplar) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Exemplar.Marshal(b, m, deterministic) + +type Exemplar struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Label []*LabelPair `protobuf:"bytes,1,rep,name=label" json:"label,omitempty"` + Value *float64 `protobuf:"fixed64,2,opt,name=value" json:"value,omitempty"` + Timestamp *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=timestamp" json:"timestamp,omitempty"` // OpenMetrics-style. } -func (m *Exemplar) XXX_Merge(src proto.Message) { - xxx_messageInfo_Exemplar.Merge(m, src) + +func (x *Exemplar) Reset() { + *x = Exemplar{} + if protoimpl.UnsafeEnabled { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *Exemplar) XXX_Size() int { - return xxx_messageInfo_Exemplar.Size(m) + +func (x *Exemplar) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *Exemplar) XXX_DiscardUnknown() { - xxx_messageInfo_Exemplar.DiscardUnknown(m) + +func (*Exemplar) ProtoMessage() {} + +func (x *Exemplar) ProtoReflect() protoreflect.Message { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_Exemplar proto.InternalMessageInfo +// Deprecated: Use Exemplar.ProtoReflect.Descriptor instead. +func (*Exemplar) Descriptor() ([]byte, []int) { + return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{9} +} -func (m *Exemplar) GetLabel() []*LabelPair { - if m != nil { - return m.Label +func (x *Exemplar) GetLabel() []*LabelPair { + if x != nil { + return x.Label } return nil } -func (m *Exemplar) GetValue() float64 { - if m != nil && m.Value != nil { - return *m.Value +func (x *Exemplar) GetValue() float64 { + if x != nil && x.Value != nil { + return *x.Value } return 0 } -func (m *Exemplar) GetTimestamp() *timestamp.Timestamp { - if m != nil { - return m.Timestamp +func (x *Exemplar) GetTimestamp() *timestamppb.Timestamp { + if x != nil { + return x.Timestamp } return nil } type Metric struct { - Label []*LabelPair `protobuf:"bytes,1,rep,name=label" json:"label,omitempty"` - Gauge *Gauge `protobuf:"bytes,2,opt,name=gauge" json:"gauge,omitempty"` - Counter *Counter `protobuf:"bytes,3,opt,name=counter" json:"counter,omitempty"` - Summary *Summary `protobuf:"bytes,4,opt,name=summary" json:"summary,omitempty"` - Untyped *Untyped `protobuf:"bytes,5,opt,name=untyped" json:"untyped,omitempty"` - Histogram *Histogram `protobuf:"bytes,7,opt,name=histogram" json:"histogram,omitempty"` - TimestampMs *int64 `protobuf:"varint,6,opt,name=timestamp_ms,json=timestampMs" json:"timestamp_ms,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Metric) Reset() { *m = Metric{} } -func (m *Metric) String() string { return proto.CompactTextString(m) } -func (*Metric) ProtoMessage() {} -func (*Metric) Descriptor() ([]byte, []int) { - return fileDescriptor_6039342a2ba47b72, []int{9} + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Label []*LabelPair `protobuf:"bytes,1,rep,name=label" json:"label,omitempty"` + Gauge *Gauge `protobuf:"bytes,2,opt,name=gauge" json:"gauge,omitempty"` + Counter *Counter `protobuf:"bytes,3,opt,name=counter" json:"counter,omitempty"` + Summary *Summary `protobuf:"bytes,4,opt,name=summary" json:"summary,omitempty"` + Untyped *Untyped `protobuf:"bytes,5,opt,name=untyped" json:"untyped,omitempty"` + Histogram *Histogram `protobuf:"bytes,7,opt,name=histogram" json:"histogram,omitempty"` + TimestampMs *int64 `protobuf:"varint,6,opt,name=timestamp_ms,json=timestampMs" json:"timestamp_ms,omitempty"` +} + +func (x *Metric) Reset() { + *x = Metric{} + if protoimpl.UnsafeEnabled { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *Metric) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Metric.Unmarshal(m, b) -} -func (m *Metric) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Metric.Marshal(b, m, deterministic) +func (x *Metric) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *Metric) XXX_Merge(src proto.Message) { - xxx_messageInfo_Metric.Merge(m, src) -} -func (m *Metric) XXX_Size() int { - return xxx_messageInfo_Metric.Size(m) -} -func (m *Metric) XXX_DiscardUnknown() { - xxx_messageInfo_Metric.DiscardUnknown(m) + +func (*Metric) ProtoMessage() {} + +func (x *Metric) ProtoReflect() protoreflect.Message { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_Metric proto.InternalMessageInfo +// Deprecated: Use Metric.ProtoReflect.Descriptor instead. +func (*Metric) Descriptor() ([]byte, []int) { + return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{10} +} -func (m *Metric) GetLabel() []*LabelPair { - if m != nil { - return m.Label +func (x *Metric) GetLabel() []*LabelPair { + if x != nil { + return x.Label } return nil } -func (m *Metric) GetGauge() *Gauge { - if m != nil { - return m.Gauge +func (x *Metric) GetGauge() *Gauge { + if x != nil { + return x.Gauge } return nil } -func (m *Metric) GetCounter() *Counter { - if m != nil { - return m.Counter +func (x *Metric) GetCounter() *Counter { + if x != nil { + return x.Counter } return nil } -func (m *Metric) GetSummary() *Summary { - if m != nil { - return m.Summary +func (x *Metric) GetSummary() *Summary { + if x != nil { + return x.Summary } return nil } -func (m *Metric) GetUntyped() *Untyped { - if m != nil { - return m.Untyped +func (x *Metric) GetUntyped() *Untyped { + if x != nil { + return x.Untyped } return nil } -func (m *Metric) GetHistogram() *Histogram { - if m != nil { - return m.Histogram +func (x *Metric) GetHistogram() *Histogram { + if x != nil { + return x.Histogram } return nil } -func (m *Metric) GetTimestampMs() int64 { - if m != nil && m.TimestampMs != nil { - return *m.TimestampMs +func (x *Metric) GetTimestampMs() int64 { + if x != nil && x.TimestampMs != nil { + return *x.TimestampMs } return 0 } type MetricFamily struct { - Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` - Help *string `protobuf:"bytes,2,opt,name=help" json:"help,omitempty"` - Type *MetricType `protobuf:"varint,3,opt,name=type,enum=io.prometheus.client.MetricType" json:"type,omitempty"` - Metric []*Metric `protobuf:"bytes,4,rep,name=metric" json:"metric,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *MetricFamily) Reset() { *m = MetricFamily{} } -func (m *MetricFamily) String() string { return proto.CompactTextString(m) } -func (*MetricFamily) ProtoMessage() {} -func (*MetricFamily) Descriptor() ([]byte, []int) { - return fileDescriptor_6039342a2ba47b72, []int{10} + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Help *string `protobuf:"bytes,2,opt,name=help" json:"help,omitempty"` + Type *MetricType `protobuf:"varint,3,opt,name=type,enum=io.prometheus.client.MetricType" json:"type,omitempty"` + Metric []*Metric `protobuf:"bytes,4,rep,name=metric" json:"metric,omitempty"` +} + +func (x *MetricFamily) Reset() { + *x = MetricFamily{} + if protoimpl.UnsafeEnabled { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *MetricFamily) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_MetricFamily.Unmarshal(m, b) +func (x *MetricFamily) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *MetricFamily) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_MetricFamily.Marshal(b, m, deterministic) -} -func (m *MetricFamily) XXX_Merge(src proto.Message) { - xxx_messageInfo_MetricFamily.Merge(m, src) -} -func (m *MetricFamily) XXX_Size() int { - return xxx_messageInfo_MetricFamily.Size(m) -} -func (m *MetricFamily) XXX_DiscardUnknown() { - xxx_messageInfo_MetricFamily.DiscardUnknown(m) + +func (*MetricFamily) ProtoMessage() {} + +func (x *MetricFamily) ProtoReflect() protoreflect.Message { + mi := &file_io_prometheus_client_metrics_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_MetricFamily proto.InternalMessageInfo +// Deprecated: Use MetricFamily.ProtoReflect.Descriptor instead. +func (*MetricFamily) Descriptor() ([]byte, []int) { + return file_io_prometheus_client_metrics_proto_rawDescGZIP(), []int{11} +} -func (m *MetricFamily) GetName() string { - if m != nil && m.Name != nil { - return *m.Name +func (x *MetricFamily) GetName() string { + if x != nil && x.Name != nil { + return *x.Name } return "" } -func (m *MetricFamily) GetHelp() string { - if m != nil && m.Help != nil { - return *m.Help +func (x *MetricFamily) GetHelp() string { + if x != nil && x.Help != nil { + return *x.Help } return "" } -func (m *MetricFamily) GetType() MetricType { - if m != nil && m.Type != nil { - return *m.Type +func (x *MetricFamily) GetType() MetricType { + if x != nil && x.Type != nil { + return *x.Type } return MetricType_COUNTER } -func (m *MetricFamily) GetMetric() []*Metric { - if m != nil { - return m.Metric +func (x *MetricFamily) GetMetric() []*Metric { + if x != nil { + return x.Metric } return nil } -func init() { - proto.RegisterEnum("io.prometheus.client.MetricType", MetricType_name, MetricType_value) - proto.RegisterType((*LabelPair)(nil), "io.prometheus.client.LabelPair") - proto.RegisterType((*Gauge)(nil), "io.prometheus.client.Gauge") - proto.RegisterType((*Counter)(nil), "io.prometheus.client.Counter") - proto.RegisterType((*Quantile)(nil), "io.prometheus.client.Quantile") - proto.RegisterType((*Summary)(nil), "io.prometheus.client.Summary") - proto.RegisterType((*Untyped)(nil), "io.prometheus.client.Untyped") - proto.RegisterType((*Histogram)(nil), "io.prometheus.client.Histogram") - proto.RegisterType((*Bucket)(nil), "io.prometheus.client.Bucket") - proto.RegisterType((*Exemplar)(nil), "io.prometheus.client.Exemplar") - proto.RegisterType((*Metric)(nil), "io.prometheus.client.Metric") - proto.RegisterType((*MetricFamily)(nil), "io.prometheus.client.MetricFamily") -} - -func init() { proto.RegisterFile("metrics.proto", fileDescriptor_6039342a2ba47b72) } - -var fileDescriptor_6039342a2ba47b72 = []byte{ - // 665 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0xcd, 0x6e, 0xd3, 0x4c, - 0x14, 0xfd, 0xdc, 0x38, 0x3f, 0xbe, 0x69, 0x3f, 0xa2, 0x51, 0x17, 0x56, 0xa1, 0x24, 0x78, 0x55, - 0x58, 0x38, 0xa2, 0x6a, 0x05, 0x2a, 0xb0, 0x68, 0x4b, 0x48, 0x91, 0x48, 0x5b, 0x26, 0xc9, 0xa2, - 0xb0, 0x88, 0x1c, 0x77, 0x70, 0x2c, 0x3c, 0xb1, 0xb1, 0x67, 0x2a, 0xb2, 0x66, 0xc1, 0x16, 0x5e, - 0x81, 0x17, 0x05, 0xcd, 0x8f, 0x6d, 0x2a, 0xb9, 0x95, 0x40, 0xec, 0x66, 0xee, 0x3d, 0xe7, 0xfa, - 0xcc, 0xf8, 0x9c, 0x81, 0x0d, 0x4a, 0x58, 0x1a, 0xfa, 0x99, 0x9b, 0xa4, 0x31, 0x8b, 0xd1, 0x66, - 0x18, 0x8b, 0x15, 0x25, 0x6c, 0x41, 0x78, 0xe6, 0xfa, 0x51, 0x48, 0x96, 0x6c, 0xab, 0x1b, 0xc4, - 0x71, 0x10, 0x91, 0xbe, 0xc4, 0xcc, 0xf9, 0x87, 0x3e, 0x0b, 0x29, 0xc9, 0x98, 0x47, 0x13, 0x45, - 0x73, 0xf6, 0xc1, 0x7a, 0xe3, 0xcd, 0x49, 0x74, 0xee, 0x85, 0x29, 0x42, 0x60, 0x2e, 0x3d, 0x4a, - 0x6c, 0xa3, 0x67, 0xec, 0x58, 0x58, 0xae, 0xd1, 0x26, 0xd4, 0xaf, 0xbc, 0x88, 0x13, 0x7b, 0x4d, - 0x16, 0xd5, 0xc6, 0xd9, 0x86, 0xfa, 0xd0, 0xe3, 0xc1, 0x6f, 0x6d, 0xc1, 0x31, 0xf2, 0xf6, 0x7b, - 0x68, 0x1e, 0xc7, 0x7c, 0xc9, 0x48, 0x5a, 0x0d, 0x40, 0x07, 0xd0, 0x22, 0x9f, 0x09, 0x4d, 0x22, - 0x2f, 0x95, 0x83, 0xdb, 0xbb, 0xf7, 0xdd, 0xaa, 0x03, 0xb8, 0x03, 0x8d, 0xc2, 0x05, 0xde, 0x79, - 0x0e, 0xad, 0xb7, 0xdc, 0x5b, 0xb2, 0x30, 0x22, 0x68, 0x0b, 0x5a, 0x9f, 0xf4, 0x5a, 0x7f, 0xa0, - 0xd8, 0x5f, 0x57, 0x5e, 0x48, 0xfb, 0x6a, 0x40, 0x73, 0xcc, 0x29, 0xf5, 0xd2, 0x15, 0x7a, 0x00, - 0xeb, 0x99, 0x47, 0x93, 0x88, 0xcc, 0x7c, 0xa1, 0x56, 0x4e, 0x30, 0x71, 0x5b, 0xd5, 0xe4, 0x01, - 0xd0, 0x36, 0x80, 0x86, 0x64, 0x9c, 0xea, 0x49, 0x96, 0xaa, 0x8c, 0x39, 0x15, 0xe7, 0x28, 0xbe, - 0x5f, 0xeb, 0xd5, 0x6e, 0x3e, 0x47, 0xae, 0xb8, 0xd4, 0xe7, 0x74, 0xa1, 0x39, 0x5d, 0xb2, 0x55, - 0x42, 0x2e, 0x6f, 0xb8, 0xc5, 0x2f, 0x06, 0x58, 0x27, 0x61, 0xc6, 0xe2, 0x20, 0xf5, 0xe8, 0x3f, - 0x10, 0xbb, 0x07, 0x8d, 0x39, 0xf7, 0x3f, 0x12, 0xa6, 0xa5, 0xde, 0xab, 0x96, 0x7a, 0x24, 0x31, - 0x58, 0x63, 0x9d, 0x6f, 0x06, 0x34, 0x54, 0x09, 0x3d, 0x84, 0x8e, 0xcf, 0x29, 0x8f, 0x3c, 0x16, - 0x5e, 0x5d, 0x97, 0x71, 0xa7, 0xac, 0x2b, 0x29, 0x5d, 0x68, 0xf3, 0x24, 0x21, 0xe9, 0x6c, 0x1e, - 0xf3, 0xe5, 0xa5, 0xd6, 0x02, 0xb2, 0x74, 0x24, 0x2a, 0xd7, 0x1c, 0x50, 0xfb, 0x43, 0x07, 0x7c, - 0x37, 0xa0, 0x95, 0x97, 0xd1, 0x3e, 0xd4, 0x23, 0xe1, 0x60, 0xdb, 0x90, 0x87, 0xea, 0x56, 0x4f, - 0x29, 0x4c, 0x8e, 0x15, 0xba, 0xda, 0x1d, 0xe8, 0x29, 0x58, 0x45, 0x42, 0xb4, 0xac, 0x2d, 0x57, - 0x65, 0xc8, 0xcd, 0x33, 0xe4, 0x4e, 0x72, 0x04, 0x2e, 0xc1, 0xce, 0xcf, 0x35, 0x68, 0x8c, 0x64, - 0x22, 0xff, 0x56, 0xd1, 0x63, 0xa8, 0x07, 0x22, 0x53, 0x3a, 0x10, 0x77, 0xab, 0x69, 0x32, 0x76, - 0x58, 0x21, 0xd1, 0x13, 0x68, 0xfa, 0x2a, 0x67, 0x5a, 0xec, 0x76, 0x35, 0x49, 0x87, 0x11, 0xe7, - 0x68, 0x41, 0xcc, 0x54, 0x08, 0x6c, 0xf3, 0x36, 0xa2, 0x4e, 0x0a, 0xce, 0xd1, 0x82, 0xc8, 0x95, - 0x69, 0xed, 0xfa, 0x6d, 0x44, 0xed, 0x6c, 0x9c, 0xa3, 0xd1, 0x0b, 0xb0, 0x16, 0xb9, 0x97, 0xed, - 0xa6, 0xa4, 0xde, 0x70, 0x31, 0x85, 0xe5, 0x71, 0xc9, 0x10, 0xee, 0x2f, 0xee, 0x7a, 0x46, 0x33, - 0xbb, 0xd1, 0x33, 0x76, 0x6a, 0xb8, 0x5d, 0xd4, 0x46, 0x99, 0xf3, 0xc3, 0x80, 0x75, 0xf5, 0x07, - 0x5e, 0x79, 0x34, 0x8c, 0x56, 0x95, 0xcf, 0x19, 0x02, 0x73, 0x41, 0xa2, 0x44, 0xbf, 0x66, 0x72, - 0x8d, 0xf6, 0xc0, 0x14, 0x1a, 0xe5, 0x15, 0xfe, 0xbf, 0xdb, 0xab, 0x56, 0xa5, 0x26, 0x4f, 0x56, - 0x09, 0xc1, 0x12, 0x2d, 0xd2, 0xa4, 0x5e, 0x60, 0xdb, 0xbc, 0x2d, 0x4d, 0x8a, 0x87, 0x35, 0xf6, - 0xd1, 0x08, 0xa0, 0x9c, 0x84, 0xda, 0xd0, 0x3c, 0x3e, 0x9b, 0x9e, 0x4e, 0x06, 0xb8, 0xf3, 0x1f, - 0xb2, 0xa0, 0x3e, 0x3c, 0x9c, 0x0e, 0x07, 0x1d, 0x43, 0xd4, 0xc7, 0xd3, 0xd1, 0xe8, 0x10, 0x5f, - 0x74, 0xd6, 0xc4, 0x66, 0x7a, 0x3a, 0xb9, 0x38, 0x1f, 0xbc, 0xec, 0xd4, 0xd0, 0x06, 0x58, 0x27, - 0xaf, 0xc7, 0x93, 0xb3, 0x21, 0x3e, 0x1c, 0x75, 0xcc, 0x23, 0x0c, 0x95, 0xef, 0xfe, 0xbb, 0x83, - 0x20, 0x64, 0x0b, 0x3e, 0x77, 0xfd, 0x98, 0xf6, 0xcb, 0x6e, 0x5f, 0x75, 0x67, 0x34, 0xbe, 0x24, - 0x51, 0x3f, 0x88, 0x9f, 0x85, 0xf1, 0xac, 0xec, 0xce, 0x54, 0xf7, 0x57, 0x00, 0x00, 0x00, 0xff, - 0xff, 0xd0, 0x84, 0x91, 0x73, 0x59, 0x06, 0x00, 0x00, +var File_io_prometheus_client_metrics_proto protoreflect.FileDescriptor + +var file_io_prometheus_client_metrics_proto_rawDesc = []byte{ + 0x0a, 0x22, 0x69, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2f, + 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x14, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, + 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x35, 0x0a, 0x09, 0x4c, + 0x61, 0x62, 0x65, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x22, 0x1d, 0x0a, 0x05, 0x47, 0x61, 0x75, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x22, 0x5b, 0x0a, 0x07, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x12, 0x3a, 0x0a, 0x08, 0x65, 0x78, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, + 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x78, 0x65, 0x6d, + 0x70, 0x6c, 0x61, 0x72, 0x52, 0x08, 0x65, 0x78, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72, 0x22, 0x3c, + 0x0a, 0x08, 0x51, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x6c, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x71, 0x75, + 0x61, 0x6e, 0x74, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x08, 0x71, 0x75, + 0x61, 0x6e, 0x74, 0x69, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x87, 0x01, 0x0a, + 0x07, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x61, 0x6d, 0x70, + 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, + 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, + 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, + 0x09, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x53, 0x75, 0x6d, 0x12, 0x3a, 0x0a, 0x08, 0x71, 0x75, + 0x61, 0x6e, 0x74, 0x69, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x69, + 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x2e, 0x51, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x6c, 0x65, 0x52, 0x08, 0x71, 0x75, + 0x61, 0x6e, 0x74, 0x69, 0x6c, 0x65, 0x22, 0x1f, 0x0a, 0x07, 0x55, 0x6e, 0x74, 0x79, 0x70, 0x65, + 0x64, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xe3, 0x04, 0x0a, 0x09, 0x48, 0x69, 0x73, 0x74, + 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x73, 0x61, 0x6d, + 0x70, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x61, 0x6d, 0x70, + 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x01, 0x52, 0x10, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x43, 0x6f, 0x75, 0x6e, + 0x74, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, + 0x5f, 0x73, 0x75, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x09, 0x73, 0x61, 0x6d, 0x70, + 0x6c, 0x65, 0x53, 0x75, 0x6d, 0x12, 0x34, 0x0a, 0x06, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x18, + 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, + 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x42, 0x75, 0x63, + 0x6b, 0x65, 0x74, 0x52, 0x06, 0x62, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, + 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x11, 0x52, 0x06, 0x73, 0x63, 0x68, + 0x65, 0x6d, 0x61, 0x12, 0x25, 0x0a, 0x0e, 0x7a, 0x65, 0x72, 0x6f, 0x5f, 0x74, 0x68, 0x72, 0x65, + 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0d, 0x7a, 0x65, 0x72, + 0x6f, 0x54, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x7a, 0x65, + 0x72, 0x6f, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, + 0x7a, 0x65, 0x72, 0x6f, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x7a, 0x65, 0x72, + 0x6f, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x01, 0x52, 0x0e, 0x7a, 0x65, 0x72, 0x6f, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x46, 0x6c, + 0x6f, 0x61, 0x74, 0x12, 0x45, 0x0a, 0x0d, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, + 0x73, 0x70, 0x61, 0x6e, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x69, 0x6f, 0x2e, + 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x2e, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x70, 0x61, 0x6e, 0x52, 0x0c, 0x6e, 0x65, + 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x53, 0x70, 0x61, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x6e, 0x65, + 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x18, 0x0a, 0x20, 0x03, + 0x28, 0x12, 0x52, 0x0d, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x44, 0x65, 0x6c, 0x74, + 0x61, 0x12, 0x25, 0x0a, 0x0e, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x01, 0x52, 0x0d, 0x6e, 0x65, 0x67, 0x61, 0x74, + 0x69, 0x76, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x45, 0x0a, 0x0d, 0x70, 0x6f, 0x73, 0x69, + 0x74, 0x69, 0x76, 0x65, 0x5f, 0x73, 0x70, 0x61, 0x6e, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x20, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, + 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x70, 0x61, + 0x6e, 0x52, 0x0c, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x53, 0x70, 0x61, 0x6e, 0x12, + 0x25, 0x0a, 0x0e, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x74, + 0x61, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x12, 0x52, 0x0d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, + 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, + 0x76, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x01, 0x52, 0x0d, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xc6, 0x01, + 0x0a, 0x06, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x75, 0x6d, 0x75, + 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x0f, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x43, 0x6f, + 0x75, 0x6e, 0x74, 0x12, 0x34, 0x0a, 0x16, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, + 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x01, 0x52, 0x14, 0x63, 0x75, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x76, 0x65, 0x43, + 0x6f, 0x75, 0x6e, 0x74, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x75, 0x70, 0x70, + 0x65, 0x72, 0x5f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0a, + 0x75, 0x70, 0x70, 0x65, 0x72, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x3a, 0x0a, 0x08, 0x65, 0x78, + 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x69, + 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x78, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72, 0x52, 0x08, 0x65, 0x78, + 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x72, 0x22, 0x3c, 0x0a, 0x0a, 0x42, 0x75, 0x63, 0x6b, 0x65, 0x74, + 0x53, 0x70, 0x61, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x11, 0x52, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, + 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x6c, 0x65, + 0x6e, 0x67, 0x74, 0x68, 0x22, 0x91, 0x01, 0x0a, 0x08, 0x45, 0x78, 0x65, 0x6d, 0x70, 0x6c, 0x61, + 0x72, 0x12, 0x35, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x1f, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, + 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x50, 0x61, 0x69, + 0x72, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x38, + 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0xff, 0x02, 0x0a, 0x06, 0x4d, 0x65, 0x74, + 0x72, 0x69, 0x63, 0x12, 0x35, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, + 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x50, + 0x61, 0x69, 0x72, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x31, 0x0a, 0x05, 0x67, 0x61, + 0x75, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x69, 0x6f, 0x2e, 0x70, + 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, + 0x2e, 0x47, 0x61, 0x75, 0x67, 0x65, 0x52, 0x05, 0x67, 0x61, 0x75, 0x67, 0x65, 0x12, 0x37, 0x0a, + 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, + 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x52, 0x07, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x37, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, + 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, + 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x53, + 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, + 0x37, 0x0a, 0x07, 0x75, 0x6e, 0x74, 0x79, 0x70, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1d, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, + 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x55, 0x6e, 0x74, 0x79, 0x70, 0x65, 0x64, 0x52, + 0x07, 0x75, 0x6e, 0x74, 0x79, 0x70, 0x65, 0x64, 0x12, 0x3d, 0x0a, 0x09, 0x68, 0x69, 0x73, 0x74, + 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x69, 0x6f, + 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x2e, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x52, 0x09, 0x68, 0x69, + 0x73, 0x74, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x5f, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x74, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x4d, 0x73, 0x22, 0xa2, 0x01, 0x0a, 0x0c, 0x4d, + 0x65, 0x74, 0x72, 0x69, 0x63, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x12, 0x0a, 0x04, 0x68, 0x65, 0x6c, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, + 0x65, 0x6c, 0x70, 0x12, 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x20, 0x2e, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, + 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x54, + 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x6d, 0x65, 0x74, + 0x72, 0x69, 0x63, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x69, 0x6f, 0x2e, 0x70, + 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, + 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2a, + 0x62, 0x0a, 0x0a, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, + 0x07, 0x43, 0x4f, 0x55, 0x4e, 0x54, 0x45, 0x52, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x47, 0x41, + 0x55, 0x47, 0x45, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x55, 0x4d, 0x4d, 0x41, 0x52, 0x59, + 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x54, 0x59, 0x50, 0x45, 0x44, 0x10, 0x03, 0x12, + 0x0d, 0x0a, 0x09, 0x48, 0x49, 0x53, 0x54, 0x4f, 0x47, 0x52, 0x41, 0x4d, 0x10, 0x04, 0x12, 0x13, + 0x0a, 0x0f, 0x47, 0x41, 0x55, 0x47, 0x45, 0x5f, 0x48, 0x49, 0x53, 0x54, 0x4f, 0x47, 0x52, 0x41, + 0x4d, 0x10, 0x05, 0x42, 0x52, 0x0a, 0x14, 0x69, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, + 0x68, 0x65, 0x75, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5a, 0x3a, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, + 0x75, 0x73, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2f, + 0x67, 0x6f, 0x3b, 0x69, 0x6f, 0x5f, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, + 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, +} + +var ( + file_io_prometheus_client_metrics_proto_rawDescOnce sync.Once + file_io_prometheus_client_metrics_proto_rawDescData = file_io_prometheus_client_metrics_proto_rawDesc +) + +func file_io_prometheus_client_metrics_proto_rawDescGZIP() []byte { + file_io_prometheus_client_metrics_proto_rawDescOnce.Do(func() { + file_io_prometheus_client_metrics_proto_rawDescData = protoimpl.X.CompressGZIP(file_io_prometheus_client_metrics_proto_rawDescData) + }) + return file_io_prometheus_client_metrics_proto_rawDescData +} + +var file_io_prometheus_client_metrics_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_io_prometheus_client_metrics_proto_msgTypes = make([]protoimpl.MessageInfo, 12) +var file_io_prometheus_client_metrics_proto_goTypes = []interface{}{ + (MetricType)(0), // 0: io.prometheus.client.MetricType + (*LabelPair)(nil), // 1: io.prometheus.client.LabelPair + (*Gauge)(nil), // 2: io.prometheus.client.Gauge + (*Counter)(nil), // 3: io.prometheus.client.Counter + (*Quantile)(nil), // 4: io.prometheus.client.Quantile + (*Summary)(nil), // 5: io.prometheus.client.Summary + (*Untyped)(nil), // 6: io.prometheus.client.Untyped + (*Histogram)(nil), // 7: io.prometheus.client.Histogram + (*Bucket)(nil), // 8: io.prometheus.client.Bucket + (*BucketSpan)(nil), // 9: io.prometheus.client.BucketSpan + (*Exemplar)(nil), // 10: io.prometheus.client.Exemplar + (*Metric)(nil), // 11: io.prometheus.client.Metric + (*MetricFamily)(nil), // 12: io.prometheus.client.MetricFamily + (*timestamppb.Timestamp)(nil), // 13: google.protobuf.Timestamp +} +var file_io_prometheus_client_metrics_proto_depIdxs = []int32{ + 10, // 0: io.prometheus.client.Counter.exemplar:type_name -> io.prometheus.client.Exemplar + 4, // 1: io.prometheus.client.Summary.quantile:type_name -> io.prometheus.client.Quantile + 8, // 2: io.prometheus.client.Histogram.bucket:type_name -> io.prometheus.client.Bucket + 9, // 3: io.prometheus.client.Histogram.negative_span:type_name -> io.prometheus.client.BucketSpan + 9, // 4: io.prometheus.client.Histogram.positive_span:type_name -> io.prometheus.client.BucketSpan + 10, // 5: io.prometheus.client.Bucket.exemplar:type_name -> io.prometheus.client.Exemplar + 1, // 6: io.prometheus.client.Exemplar.label:type_name -> io.prometheus.client.LabelPair + 13, // 7: io.prometheus.client.Exemplar.timestamp:type_name -> google.protobuf.Timestamp + 1, // 8: io.prometheus.client.Metric.label:type_name -> io.prometheus.client.LabelPair + 2, // 9: io.prometheus.client.Metric.gauge:type_name -> io.prometheus.client.Gauge + 3, // 10: io.prometheus.client.Metric.counter:type_name -> io.prometheus.client.Counter + 5, // 11: io.prometheus.client.Metric.summary:type_name -> io.prometheus.client.Summary + 6, // 12: io.prometheus.client.Metric.untyped:type_name -> io.prometheus.client.Untyped + 7, // 13: io.prometheus.client.Metric.histogram:type_name -> io.prometheus.client.Histogram + 0, // 14: io.prometheus.client.MetricFamily.type:type_name -> io.prometheus.client.MetricType + 11, // 15: io.prometheus.client.MetricFamily.metric:type_name -> io.prometheus.client.Metric + 16, // [16:16] is the sub-list for method output_type + 16, // [16:16] is the sub-list for method input_type + 16, // [16:16] is the sub-list for extension type_name + 16, // [16:16] is the sub-list for extension extendee + 0, // [0:16] is the sub-list for field type_name +} + +func init() { file_io_prometheus_client_metrics_proto_init() } +func file_io_prometheus_client_metrics_proto_init() { + if File_io_prometheus_client_metrics_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_io_prometheus_client_metrics_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LabelPair); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_io_prometheus_client_metrics_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Gauge); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_io_prometheus_client_metrics_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Counter); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_io_prometheus_client_metrics_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Quantile); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_io_prometheus_client_metrics_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Summary); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_io_prometheus_client_metrics_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Untyped); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_io_prometheus_client_metrics_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Histogram); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_io_prometheus_client_metrics_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Bucket); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_io_prometheus_client_metrics_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BucketSpan); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_io_prometheus_client_metrics_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Exemplar); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_io_prometheus_client_metrics_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Metric); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_io_prometheus_client_metrics_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MetricFamily); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_io_prometheus_client_metrics_proto_rawDesc, + NumEnums: 1, + NumMessages: 12, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_io_prometheus_client_metrics_proto_goTypes, + DependencyIndexes: file_io_prometheus_client_metrics_proto_depIdxs, + EnumInfos: file_io_prometheus_client_metrics_proto_enumTypes, + MessageInfos: file_io_prometheus_client_metrics_proto_msgTypes, + }.Build() + File_io_prometheus_client_metrics_proto = out.File + file_io_prometheus_client_metrics_proto_rawDesc = nil + file_io_prometheus_client_metrics_proto_goTypes = nil + file_io_prometheus_client_metrics_proto_depIdxs = nil } diff --git a/vendor/github.com/prometheus/common/expfmt/decode.go b/vendor/github.com/prometheus/common/expfmt/decode.go index 7657f841d6..f4fc884552 100644 --- a/vendor/github.com/prometheus/common/expfmt/decode.go +++ b/vendor/github.com/prometheus/common/expfmt/decode.go @@ -115,32 +115,28 @@ func (d *protoDecoder) Decode(v *dto.MetricFamily) error { // textDecoder implements the Decoder interface for the text protocol. type textDecoder struct { r io.Reader - p TextParser - fams []*dto.MetricFamily + fams map[string]*dto.MetricFamily + err error } // Decode implements the Decoder interface. func (d *textDecoder) Decode(v *dto.MetricFamily) error { - // TODO(fabxc): Wrap this as a line reader to make streaming safer. - if len(d.fams) == 0 { - // No cached metric families, read everything and parse metrics. - fams, err := d.p.TextToMetricFamilies(d.r) - if err != nil { - return err - } - if len(fams) == 0 { - return io.EOF - } - d.fams = make([]*dto.MetricFamily, 0, len(fams)) - for _, f := range fams { - d.fams = append(d.fams, f) + if d.err == nil { + // Read all metrics in one shot. + var p TextParser + d.fams, d.err = p.TextToMetricFamilies(d.r) + // If we don't get an error, store io.EOF for the end. + if d.err == nil { + d.err = io.EOF } } - - *v = *d.fams[0] - d.fams = d.fams[1:] - - return nil + // Pick off one MetricFamily per Decode until there's nothing left. + for key, fam := range d.fams { + *v = *fam + delete(d.fams, key) + return nil + } + return d.err } // SampleDecoder wraps a Decoder to extract samples from the metric families diff --git a/vendor/github.com/prometheus/common/expfmt/fuzz.go b/vendor/github.com/prometheus/common/expfmt/fuzz.go index dc2eedeefc..dfac962a4e 100644 --- a/vendor/github.com/prometheus/common/expfmt/fuzz.go +++ b/vendor/github.com/prometheus/common/expfmt/fuzz.go @@ -12,6 +12,7 @@ // limitations under the License. // Build only when actually fuzzing +//go:build gofuzz // +build gofuzz package expfmt @@ -20,8 +21,8 @@ import "bytes" // Fuzz text metric parser with with github.com/dvyukov/go-fuzz: // -// go-fuzz-build github.com/prometheus/common/expfmt -// go-fuzz -bin expfmt-fuzz.zip -workdir fuzz +// go-fuzz-build github.com/prometheus/common/expfmt +// go-fuzz -bin expfmt-fuzz.zip -workdir fuzz // // Further input samples should go in the folder fuzz/corpus. func Fuzz(in []byte) int { diff --git a/vendor/github.com/prometheus/common/expfmt/openmetrics_create.go b/vendor/github.com/prometheus/common/expfmt/openmetrics_create.go index 8a9313a3be..21cdddcf05 100644 --- a/vendor/github.com/prometheus/common/expfmt/openmetrics_create.go +++ b/vendor/github.com/prometheus/common/expfmt/openmetrics_create.go @@ -22,7 +22,6 @@ import ( "strconv" "strings" - "github.com/golang/protobuf/ptypes" "github.com/prometheus/common/model" dto "github.com/prometheus/client_model/go" @@ -47,20 +46,20 @@ import ( // missing features and peculiarities to avoid complications when switching from // Prometheus to OpenMetrics or vice versa: // -// - Counters are expected to have the `_total` suffix in their metric name. In -// the output, the suffix will be truncated from the `# TYPE` and `# HELP` -// line. A counter with a missing `_total` suffix is not an error. However, -// its type will be set to `unknown` in that case to avoid invalid OpenMetrics -// output. +// - Counters are expected to have the `_total` suffix in their metric name. In +// the output, the suffix will be truncated from the `# TYPE` and `# HELP` +// line. A counter with a missing `_total` suffix is not an error. However, +// its type will be set to `unknown` in that case to avoid invalid OpenMetrics +// output. // -// - No support for the following (optional) features: `# UNIT` line, `_created` -// line, info type, stateset type, gaugehistogram type. +// - No support for the following (optional) features: `# UNIT` line, `_created` +// line, info type, stateset type, gaugehistogram type. // -// - The size of exemplar labels is not checked (i.e. it's possible to create -// exemplars that are larger than allowed by the OpenMetrics specification). +// - The size of exemplar labels is not checked (i.e. it's possible to create +// exemplars that are larger than allowed by the OpenMetrics specification). // -// - The value of Counters is not checked. (OpenMetrics doesn't allow counters -// with a `NaN` value.) +// - The value of Counters is not checked. (OpenMetrics doesn't allow counters +// with a `NaN` value.) func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily) (written int, err error) { name := in.GetName() if name == "" { @@ -473,10 +472,11 @@ func writeExemplar(w enhancedWriter, e *dto.Exemplar) (int, error) { if err != nil { return written, err } - ts, err := ptypes.Timestamp((*e).Timestamp) + err = (*e).Timestamp.CheckValid() if err != nil { return written, err } + ts := (*e).Timestamp.AsTime() // TODO(beorn7): Format this directly from components of ts to // avoid overflow/underflow and precision issues of the float // conversion. diff --git a/vendor/github.com/prometheus/common/expfmt/text_create.go b/vendor/github.com/prometheus/common/expfmt/text_create.go index 5ba503b065..2946b8f1a6 100644 --- a/vendor/github.com/prometheus/common/expfmt/text_create.go +++ b/vendor/github.com/prometheus/common/expfmt/text_create.go @@ -17,7 +17,6 @@ import ( "bufio" "fmt" "io" - "io/ioutil" "math" "strconv" "strings" @@ -44,7 +43,7 @@ const ( var ( bufPool = sync.Pool{ New: func() interface{} { - return bufio.NewWriter(ioutil.Discard) + return bufio.NewWriter(io.Discard) }, } numBufPool = sync.Pool{ diff --git a/vendor/github.com/prometheus/common/expfmt/text_parse.go b/vendor/github.com/prometheus/common/expfmt/text_parse.go index 84be0643ec..ac2482782c 100644 --- a/vendor/github.com/prometheus/common/expfmt/text_parse.go +++ b/vendor/github.com/prometheus/common/expfmt/text_parse.go @@ -142,9 +142,13 @@ func (p *TextParser) reset(in io.Reader) { func (p *TextParser) startOfLine() stateFn { p.lineCount++ if p.skipBlankTab(); p.err != nil { - // End of input reached. This is the only case where - // that is not an error but a signal that we are done. - p.err = nil + // This is the only place that we expect to see io.EOF, + // which is not an error but the signal that we are done. + // Any other error that happens to align with the start of + // a line is still an error. + if p.err == io.EOF { + p.err = nil + } return nil } switch p.currentByte { diff --git a/vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/autoneg.go b/vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/autoneg.go index 26e92288c7..a21b9d15dd 100644 --- a/vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/autoneg.go +++ b/vendor/github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg/autoneg.go @@ -11,18 +11,18 @@ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. + Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. - Neither the name of the Open Knowledge Foundation Ltd. nor the - names of its contributors may be used to endorse or promote - products derived from this software without specific prior written - permission. + Neither the name of the Open Knowledge Foundation Ltd. nor the + names of its contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT @@ -35,8 +35,6 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - */ package goautoneg diff --git a/vendor/github.com/prometheus/common/model/time.go b/vendor/github.com/prometheus/common/model/time.go index 7f67b16e42..5727452c1e 100644 --- a/vendor/github.com/prometheus/common/model/time.go +++ b/vendor/github.com/prometheus/common/model/time.go @@ -18,7 +18,6 @@ import ( "errors" "fmt" "math" - "regexp" "strconv" "strings" "time" @@ -183,54 +182,78 @@ func (d *Duration) Type() string { return "duration" } -var durationRE = regexp.MustCompile("^(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?$") +func isdigit(c byte) bool { return c >= '0' && c <= '9' } + +// Units are required to go in order from biggest to smallest. +// This guards against confusion from "1m1d" being 1 minute + 1 day, not 1 month + 1 day. +var unitMap = map[string]struct { + pos int + mult uint64 +}{ + "ms": {7, uint64(time.Millisecond)}, + "s": {6, uint64(time.Second)}, + "m": {5, uint64(time.Minute)}, + "h": {4, uint64(time.Hour)}, + "d": {3, uint64(24 * time.Hour)}, + "w": {2, uint64(7 * 24 * time.Hour)}, + "y": {1, uint64(365 * 24 * time.Hour)}, +} // ParseDuration parses a string into a time.Duration, assuming that a year // always has 365d, a week always has 7d, and a day always has 24h. -func ParseDuration(durationStr string) (Duration, error) { - switch durationStr { +func ParseDuration(s string) (Duration, error) { + switch s { case "0": // Allow 0 without a unit. return 0, nil case "": - return 0, fmt.Errorf("empty duration string") - } - matches := durationRE.FindStringSubmatch(durationStr) - if matches == nil { - return 0, fmt.Errorf("not a valid duration string: %q", durationStr) + return 0, errors.New("empty duration string") } - var dur time.Duration - // Parse the match at pos `pos` in the regex and use `mult` to turn that - // into ms, then add that value to the total parsed duration. - var overflowErr error - m := func(pos int, mult time.Duration) { - if matches[pos] == "" { - return + orig := s + var dur uint64 + lastUnitPos := 0 + + for s != "" { + if !isdigit(s[0]) { + return 0, fmt.Errorf("not a valid duration string: %q", orig) + } + // Consume [0-9]* + i := 0 + for ; i < len(s) && isdigit(s[i]); i++ { + } + v, err := strconv.ParseUint(s[:i], 10, 0) + if err != nil { + return 0, fmt.Errorf("not a valid duration string: %q", orig) } - n, _ := strconv.Atoi(matches[pos]) + s = s[i:] + // Consume unit. + for i = 0; i < len(s) && !isdigit(s[i]); i++ { + } + if i == 0 { + return 0, fmt.Errorf("not a valid duration string: %q", orig) + } + u := s[:i] + s = s[i:] + unit, ok := unitMap[u] + if !ok { + return 0, fmt.Errorf("unknown unit %q in duration %q", u, orig) + } + if unit.pos <= lastUnitPos { // Units must go in order from biggest to smallest. + return 0, fmt.Errorf("not a valid duration string: %q", orig) + } + lastUnitPos = unit.pos // Check if the provided duration overflows time.Duration (> ~ 290years). - if n > int((1<<63-1)/mult/time.Millisecond) { - overflowErr = errors.New("duration out of range") + if v > 1<<63/unit.mult { + return 0, errors.New("duration out of range") } - d := time.Duration(n) * time.Millisecond - dur += d * mult - - if dur < 0 { - overflowErr = errors.New("duration out of range") + dur += v * unit.mult + if dur > 1<<63-1 { + return 0, errors.New("duration out of range") } } - - m(2, 1000*60*60*24*365) // y - m(4, 1000*60*60*24*7) // w - m(6, 1000*60*60*24) // d - m(8, 1000*60*60) // h - m(10, 1000*60) // m - m(12, 1000) // s - m(14, 1) // ms - - return Duration(dur), overflowErr + return Duration(dur), nil } func (d Duration) String() string { diff --git a/vendor/github.com/prometheus/common/model/value.go b/vendor/github.com/prometheus/common/model/value.go index c9d8fb1a28..9eb440413f 100644 --- a/vendor/github.com/prometheus/common/model/value.go +++ b/vendor/github.com/prometheus/common/model/value.go @@ -16,20 +16,12 @@ package model import ( "encoding/json" "fmt" - "math" "sort" "strconv" "strings" ) var ( - // ZeroSamplePair is the pseudo zero-value of SamplePair used to signal a - // non-existing sample pair. It is a SamplePair with timestamp Earliest and - // value 0.0. Note that the natural zero value of SamplePair has a timestamp - // of 0, which is possible to appear in a real SamplePair and thus not - // suitable to signal a non-existing SamplePair. - ZeroSamplePair = SamplePair{Timestamp: Earliest} - // ZeroSample is the pseudo zero-value of Sample used to signal a // non-existing sample. It is a Sample with timestamp Earliest, value 0.0, // and metric nil. Note that the natural zero value of Sample has a timestamp @@ -38,82 +30,14 @@ var ( ZeroSample = Sample{Timestamp: Earliest} ) -// A SampleValue is a representation of a value for a given sample at a given -// time. -type SampleValue float64 - -// MarshalJSON implements json.Marshaler. -func (v SampleValue) MarshalJSON() ([]byte, error) { - return json.Marshal(v.String()) -} - -// UnmarshalJSON implements json.Unmarshaler. -func (v *SampleValue) UnmarshalJSON(b []byte) error { - if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' { - return fmt.Errorf("sample value must be a quoted string") - } - f, err := strconv.ParseFloat(string(b[1:len(b)-1]), 64) - if err != nil { - return err - } - *v = SampleValue(f) - return nil -} - -// Equal returns true if the value of v and o is equal or if both are NaN. Note -// that v==o is false if both are NaN. If you want the conventional float -// behavior, use == to compare two SampleValues. -func (v SampleValue) Equal(o SampleValue) bool { - if v == o { - return true - } - return math.IsNaN(float64(v)) && math.IsNaN(float64(o)) -} - -func (v SampleValue) String() string { - return strconv.FormatFloat(float64(v), 'f', -1, 64) -} - -// SamplePair pairs a SampleValue with a Timestamp. -type SamplePair struct { - Timestamp Time - Value SampleValue -} - -// MarshalJSON implements json.Marshaler. -func (s SamplePair) MarshalJSON() ([]byte, error) { - t, err := json.Marshal(s.Timestamp) - if err != nil { - return nil, err - } - v, err := json.Marshal(s.Value) - if err != nil { - return nil, err - } - return []byte(fmt.Sprintf("[%s,%s]", t, v)), nil -} - -// UnmarshalJSON implements json.Unmarshaler. -func (s *SamplePair) UnmarshalJSON(b []byte) error { - v := [...]json.Unmarshaler{&s.Timestamp, &s.Value} - return json.Unmarshal(b, &v) -} - -// Equal returns true if this SamplePair and o have equal Values and equal -// Timestamps. The semantics of Value equality is defined by SampleValue.Equal. -func (s *SamplePair) Equal(o *SamplePair) bool { - return s == o || (s.Value.Equal(o.Value) && s.Timestamp.Equal(o.Timestamp)) -} - -func (s SamplePair) String() string { - return fmt.Sprintf("%s @[%s]", s.Value, s.Timestamp) -} - -// Sample is a sample pair associated with a metric. +// Sample is a sample pair associated with a metric. A single sample must either +// define Value or Histogram but not both. Histogram == nil implies the Value +// field is used, otherwise it should be ignored. type Sample struct { - Metric Metric `json:"metric"` - Value SampleValue `json:"value"` - Timestamp Time `json:"timestamp"` + Metric Metric `json:"metric"` + Value SampleValue `json:"value"` + Timestamp Time `json:"timestamp"` + Histogram *SampleHistogram `json:"histogram"` } // Equal compares first the metrics, then the timestamp, then the value. The @@ -129,11 +53,19 @@ func (s *Sample) Equal(o *Sample) bool { if !s.Timestamp.Equal(o.Timestamp) { return false } - + if s.Histogram != nil { + return s.Histogram.Equal(o.Histogram) + } return s.Value.Equal(o.Value) } func (s Sample) String() string { + if s.Histogram != nil { + return fmt.Sprintf("%s => %s", s.Metric, SampleHistogramPair{ + Timestamp: s.Timestamp, + Histogram: s.Histogram, + }) + } return fmt.Sprintf("%s => %s", s.Metric, SamplePair{ Timestamp: s.Timestamp, Value: s.Value, @@ -142,6 +74,19 @@ func (s Sample) String() string { // MarshalJSON implements json.Marshaler. func (s Sample) MarshalJSON() ([]byte, error) { + if s.Histogram != nil { + v := struct { + Metric Metric `json:"metric"` + Histogram SampleHistogramPair `json:"histogram"` + }{ + Metric: s.Metric, + Histogram: SampleHistogramPair{ + Timestamp: s.Timestamp, + Histogram: s.Histogram, + }, + } + return json.Marshal(&v) + } v := struct { Metric Metric `json:"metric"` Value SamplePair `json:"value"` @@ -152,21 +97,25 @@ func (s Sample) MarshalJSON() ([]byte, error) { Value: s.Value, }, } - return json.Marshal(&v) } // UnmarshalJSON implements json.Unmarshaler. func (s *Sample) UnmarshalJSON(b []byte) error { v := struct { - Metric Metric `json:"metric"` - Value SamplePair `json:"value"` + Metric Metric `json:"metric"` + Value SamplePair `json:"value"` + Histogram SampleHistogramPair `json:"histogram"` }{ Metric: s.Metric, Value: SamplePair{ Timestamp: s.Timestamp, Value: s.Value, }, + Histogram: SampleHistogramPair{ + Timestamp: s.Timestamp, + Histogram: s.Histogram, + }, } if err := json.Unmarshal(b, &v); err != nil { @@ -174,8 +123,13 @@ func (s *Sample) UnmarshalJSON(b []byte) error { } s.Metric = v.Metric - s.Timestamp = v.Value.Timestamp - s.Value = v.Value.Value + if v.Histogram.Histogram != nil { + s.Timestamp = v.Histogram.Timestamp + s.Histogram = v.Histogram.Histogram + } else { + s.Timestamp = v.Value.Timestamp + s.Value = v.Value.Value + } return nil } @@ -221,80 +175,76 @@ func (s Samples) Equal(o Samples) bool { // SampleStream is a stream of Values belonging to an attached COWMetric. type SampleStream struct { - Metric Metric `json:"metric"` - Values []SamplePair `json:"values"` + Metric Metric `json:"metric"` + Values []SamplePair `json:"values"` + Histograms []SampleHistogramPair `json:"histograms"` } func (ss SampleStream) String() string { - vals := make([]string, len(ss.Values)) + valuesLength := len(ss.Values) + vals := make([]string, valuesLength+len(ss.Histograms)) for i, v := range ss.Values { vals[i] = v.String() } + for i, v := range ss.Histograms { + vals[i+valuesLength] = v.String() + } return fmt.Sprintf("%s =>\n%s", ss.Metric, strings.Join(vals, "\n")) } -// Value is a generic interface for values resulting from a query evaluation. -type Value interface { - Type() ValueType - String() string +func (ss SampleStream) MarshalJSON() ([]byte, error) { + if len(ss.Histograms) > 0 && len(ss.Values) > 0 { + v := struct { + Metric Metric `json:"metric"` + Values []SamplePair `json:"values"` + Histograms []SampleHistogramPair `json:"histograms"` + }{ + Metric: ss.Metric, + Values: ss.Values, + Histograms: ss.Histograms, + } + return json.Marshal(&v) + } else if len(ss.Histograms) > 0 { + v := struct { + Metric Metric `json:"metric"` + Histograms []SampleHistogramPair `json:"histograms"` + }{ + Metric: ss.Metric, + Histograms: ss.Histograms, + } + return json.Marshal(&v) + } else { + v := struct { + Metric Metric `json:"metric"` + Values []SamplePair `json:"values"` + }{ + Metric: ss.Metric, + Values: ss.Values, + } + return json.Marshal(&v) + } } -func (Matrix) Type() ValueType { return ValMatrix } -func (Vector) Type() ValueType { return ValVector } -func (*Scalar) Type() ValueType { return ValScalar } -func (*String) Type() ValueType { return ValString } - -type ValueType int - -const ( - ValNone ValueType = iota - ValScalar - ValVector - ValMatrix - ValString -) - -// MarshalJSON implements json.Marshaler. -func (et ValueType) MarshalJSON() ([]byte, error) { - return json.Marshal(et.String()) -} +func (ss *SampleStream) UnmarshalJSON(b []byte) error { + v := struct { + Metric Metric `json:"metric"` + Values []SamplePair `json:"values"` + Histograms []SampleHistogramPair `json:"histograms"` + }{ + Metric: ss.Metric, + Values: ss.Values, + Histograms: ss.Histograms, + } -func (et *ValueType) UnmarshalJSON(b []byte) error { - var s string - if err := json.Unmarshal(b, &s); err != nil { + if err := json.Unmarshal(b, &v); err != nil { return err } - switch s { - case "": - *et = ValNone - case "scalar": - *et = ValScalar - case "vector": - *et = ValVector - case "matrix": - *et = ValMatrix - case "string": - *et = ValString - default: - return fmt.Errorf("unknown value type %q", s) - } - return nil -} -func (e ValueType) String() string { - switch e { - case ValNone: - return "" - case ValScalar: - return "scalar" - case ValVector: - return "vector" - case ValMatrix: - return "matrix" - case ValString: - return "string" - } - panic("ValueType.String: unhandled value type") + ss.Metric = v.Metric + ss.Values = v.Values + ss.Histograms = v.Histograms + + return nil } // Scalar is a scalar value evaluated at the set timestamp. diff --git a/vendor/github.com/prometheus/common/model/value_float.go b/vendor/github.com/prometheus/common/model/value_float.go new file mode 100644 index 0000000000..0f615a7053 --- /dev/null +++ b/vendor/github.com/prometheus/common/model/value_float.go @@ -0,0 +1,100 @@ +// Copyright 2013 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package model + +import ( + "encoding/json" + "fmt" + "math" + "strconv" +) + +var ( + // ZeroSamplePair is the pseudo zero-value of SamplePair used to signal a + // non-existing sample pair. It is a SamplePair with timestamp Earliest and + // value 0.0. Note that the natural zero value of SamplePair has a timestamp + // of 0, which is possible to appear in a real SamplePair and thus not + // suitable to signal a non-existing SamplePair. + ZeroSamplePair = SamplePair{Timestamp: Earliest} +) + +// A SampleValue is a representation of a value for a given sample at a given +// time. +type SampleValue float64 + +// MarshalJSON implements json.Marshaler. +func (v SampleValue) MarshalJSON() ([]byte, error) { + return json.Marshal(v.String()) +} + +// UnmarshalJSON implements json.Unmarshaler. +func (v *SampleValue) UnmarshalJSON(b []byte) error { + if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' { + return fmt.Errorf("sample value must be a quoted string") + } + f, err := strconv.ParseFloat(string(b[1:len(b)-1]), 64) + if err != nil { + return err + } + *v = SampleValue(f) + return nil +} + +// Equal returns true if the value of v and o is equal or if both are NaN. Note +// that v==o is false if both are NaN. If you want the conventional float +// behavior, use == to compare two SampleValues. +func (v SampleValue) Equal(o SampleValue) bool { + if v == o { + return true + } + return math.IsNaN(float64(v)) && math.IsNaN(float64(o)) +} + +func (v SampleValue) String() string { + return strconv.FormatFloat(float64(v), 'f', -1, 64) +} + +// SamplePair pairs a SampleValue with a Timestamp. +type SamplePair struct { + Timestamp Time + Value SampleValue +} + +func (s SamplePair) MarshalJSON() ([]byte, error) { + t, err := json.Marshal(s.Timestamp) + if err != nil { + return nil, err + } + v, err := json.Marshal(s.Value) + if err != nil { + return nil, err + } + return []byte(fmt.Sprintf("[%s,%s]", t, v)), nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (s *SamplePair) UnmarshalJSON(b []byte) error { + v := [...]json.Unmarshaler{&s.Timestamp, &s.Value} + return json.Unmarshal(b, &v) +} + +// Equal returns true if this SamplePair and o have equal Values and equal +// Timestamps. The semantics of Value equality is defined by SampleValue.Equal. +func (s *SamplePair) Equal(o *SamplePair) bool { + return s == o || (s.Value.Equal(o.Value) && s.Timestamp.Equal(o.Timestamp)) +} + +func (s SamplePair) String() string { + return fmt.Sprintf("%s @[%s]", s.Value, s.Timestamp) +} diff --git a/vendor/github.com/prometheus/common/model/value_histogram.go b/vendor/github.com/prometheus/common/model/value_histogram.go new file mode 100644 index 0000000000..54bb038cff --- /dev/null +++ b/vendor/github.com/prometheus/common/model/value_histogram.go @@ -0,0 +1,178 @@ +// Copyright 2013 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package model + +import ( + "encoding/json" + "fmt" + "strconv" + "strings" +) + +type FloatString float64 + +func (v FloatString) String() string { + return strconv.FormatFloat(float64(v), 'f', -1, 64) +} + +func (v FloatString) MarshalJSON() ([]byte, error) { + return json.Marshal(v.String()) +} + +func (v *FloatString) UnmarshalJSON(b []byte) error { + if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' { + return fmt.Errorf("float value must be a quoted string") + } + f, err := strconv.ParseFloat(string(b[1:len(b)-1]), 64) + if err != nil { + return err + } + *v = FloatString(f) + return nil +} + +type HistogramBucket struct { + Boundaries int32 + Lower FloatString + Upper FloatString + Count FloatString +} + +func (s HistogramBucket) MarshalJSON() ([]byte, error) { + b, err := json.Marshal(s.Boundaries) + if err != nil { + return nil, err + } + l, err := json.Marshal(s.Lower) + if err != nil { + return nil, err + } + u, err := json.Marshal(s.Upper) + if err != nil { + return nil, err + } + c, err := json.Marshal(s.Count) + if err != nil { + return nil, err + } + return []byte(fmt.Sprintf("[%s,%s,%s,%s]", b, l, u, c)), nil +} + +func (s *HistogramBucket) UnmarshalJSON(buf []byte) error { + tmp := []interface{}{&s.Boundaries, &s.Lower, &s.Upper, &s.Count} + wantLen := len(tmp) + if err := json.Unmarshal(buf, &tmp); err != nil { + return err + } + if gotLen := len(tmp); gotLen != wantLen { + return fmt.Errorf("wrong number of fields: %d != %d", gotLen, wantLen) + } + return nil +} + +func (s *HistogramBucket) Equal(o *HistogramBucket) bool { + return s == o || (s.Boundaries == o.Boundaries && s.Lower == o.Lower && s.Upper == o.Upper && s.Count == o.Count) +} + +func (b HistogramBucket) String() string { + var sb strings.Builder + lowerInclusive := b.Boundaries == 1 || b.Boundaries == 3 + upperInclusive := b.Boundaries == 0 || b.Boundaries == 3 + if lowerInclusive { + sb.WriteRune('[') + } else { + sb.WriteRune('(') + } + fmt.Fprintf(&sb, "%g,%g", b.Lower, b.Upper) + if upperInclusive { + sb.WriteRune(']') + } else { + sb.WriteRune(')') + } + fmt.Fprintf(&sb, ":%v", b.Count) + return sb.String() +} + +type HistogramBuckets []*HistogramBucket + +func (s HistogramBuckets) Equal(o HistogramBuckets) bool { + if len(s) != len(o) { + return false + } + + for i, bucket := range s { + if !bucket.Equal(o[i]) { + return false + } + } + return true +} + +type SampleHistogram struct { + Count FloatString `json:"count"` + Sum FloatString `json:"sum"` + Buckets HistogramBuckets `json:"buckets"` +} + +func (s SampleHistogram) String() string { + return fmt.Sprintf("Count: %f, Sum: %f, Buckets: %v", s.Count, s.Sum, s.Buckets) +} + +func (s *SampleHistogram) Equal(o *SampleHistogram) bool { + return s == o || (s.Count == o.Count && s.Sum == o.Sum && s.Buckets.Equal(o.Buckets)) +} + +type SampleHistogramPair struct { + Timestamp Time + // Histogram should never be nil, it's only stored as pointer for efficiency. + Histogram *SampleHistogram +} + +func (s SampleHistogramPair) MarshalJSON() ([]byte, error) { + if s.Histogram == nil { + return nil, fmt.Errorf("histogram is nil") + } + t, err := json.Marshal(s.Timestamp) + if err != nil { + return nil, err + } + v, err := json.Marshal(s.Histogram) + if err != nil { + return nil, err + } + return []byte(fmt.Sprintf("[%s,%s]", t, v)), nil +} + +func (s *SampleHistogramPair) UnmarshalJSON(buf []byte) error { + tmp := []interface{}{&s.Timestamp, &s.Histogram} + wantLen := len(tmp) + if err := json.Unmarshal(buf, &tmp); err != nil { + return err + } + if gotLen := len(tmp); gotLen != wantLen { + return fmt.Errorf("wrong number of fields: %d != %d", gotLen, wantLen) + } + if s.Histogram == nil { + return fmt.Errorf("histogram is null") + } + return nil +} + +func (s SampleHistogramPair) String() string { + return fmt.Sprintf("%s @[%s]", s.Histogram, s.Timestamp) +} + +func (s *SampleHistogramPair) Equal(o *SampleHistogramPair) bool { + return s == o || (s.Histogram.Equal(o.Histogram) && s.Timestamp.Equal(o.Timestamp)) +} diff --git a/vendor/github.com/prometheus/common/model/value_type.go b/vendor/github.com/prometheus/common/model/value_type.go new file mode 100644 index 0000000000..726c50ee63 --- /dev/null +++ b/vendor/github.com/prometheus/common/model/value_type.go @@ -0,0 +1,83 @@ +// Copyright 2013 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package model + +import ( + "encoding/json" + "fmt" +) + +// Value is a generic interface for values resulting from a query evaluation. +type Value interface { + Type() ValueType + String() string +} + +func (Matrix) Type() ValueType { return ValMatrix } +func (Vector) Type() ValueType { return ValVector } +func (*Scalar) Type() ValueType { return ValScalar } +func (*String) Type() ValueType { return ValString } + +type ValueType int + +const ( + ValNone ValueType = iota + ValScalar + ValVector + ValMatrix + ValString +) + +// MarshalJSON implements json.Marshaler. +func (et ValueType) MarshalJSON() ([]byte, error) { + return json.Marshal(et.String()) +} + +func (et *ValueType) UnmarshalJSON(b []byte) error { + var s string + if err := json.Unmarshal(b, &s); err != nil { + return err + } + switch s { + case "": + *et = ValNone + case "scalar": + *et = ValScalar + case "vector": + *et = ValVector + case "matrix": + *et = ValMatrix + case "string": + *et = ValString + default: + return fmt.Errorf("unknown value type %q", s) + } + return nil +} + +func (e ValueType) String() string { + switch e { + case ValNone: + return "" + case ValScalar: + return "scalar" + case ValVector: + return "vector" + case ValMatrix: + return "matrix" + case ValString: + return "string" + } + panic("ValueType.String: unhandled value type") +} diff --git a/vendor/github.com/prometheus/procfs/.gitignore b/vendor/github.com/prometheus/procfs/.gitignore index 25e3659ab2..7cc33ae4a7 100644 --- a/vendor/github.com/prometheus/procfs/.gitignore +++ b/vendor/github.com/prometheus/procfs/.gitignore @@ -1 +1,2 @@ -/fixtures/ +/testdata/fixtures/ +/fixtures diff --git a/vendor/github.com/prometheus/procfs/.golangci.yml b/vendor/github.com/prometheus/procfs/.golangci.yml index 0aa09edacb..a197699a1e 100644 --- a/vendor/github.com/prometheus/procfs/.golangci.yml +++ b/vendor/github.com/prometheus/procfs/.golangci.yml @@ -1,4 +1,12 @@ --- linters: enable: - - golint + - godot + - revive + +linter-settings: + godot: + capital: true + exclude: + # Ignore "See: URL" + - 'See:' diff --git a/vendor/github.com/prometheus/procfs/CODE_OF_CONDUCT.md b/vendor/github.com/prometheus/procfs/CODE_OF_CONDUCT.md index 9a1aff4127..d325872bdf 100644 --- a/vendor/github.com/prometheus/procfs/CODE_OF_CONDUCT.md +++ b/vendor/github.com/prometheus/procfs/CODE_OF_CONDUCT.md @@ -1,3 +1,3 @@ -## Prometheus Community Code of Conduct +# Prometheus Community Code of Conduct -Prometheus follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md). +Prometheus follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/main/code-of-conduct.md). diff --git a/vendor/github.com/prometheus/procfs/CONTRIBUTING.md b/vendor/github.com/prometheus/procfs/CONTRIBUTING.md index 943de7615e..853eb9d49b 100644 --- a/vendor/github.com/prometheus/procfs/CONTRIBUTING.md +++ b/vendor/github.com/prometheus/procfs/CONTRIBUTING.md @@ -97,7 +97,7 @@ Many of the files are changing continuously and the data being read can in some reads in the same file. Also, most of the files are relatively small (less than a few KBs), and system calls to the `stat` function will often return the wrong size. Therefore, for most files it's recommended to read the full file in a single operation using an internal utility function called `util.ReadFileNoStat`. -This function is similar to `ioutil.ReadFile`, but it avoids the system call to `stat` to get the current size of +This function is similar to `os.ReadFile`, but it avoids the system call to `stat` to get the current size of the file. Note that parsing the file's contents can still be performed one line at a time. This is done by first reading @@ -113,7 +113,7 @@ the full file, and then using a scanner on the `[]byte` or `string` containing t ``` The `/sys` filesystem contains many very small files which contain only a single numeric or text value. These files -can be read using an internal function called `util.SysReadFile` which is similar to `ioutil.ReadFile` but does +can be read using an internal function called `util.SysReadFile` which is similar to `os.ReadFile` but does not bother to check the size of the file before reading. ``` data, err := util.SysReadFile("/sys/class/power_supply/BAT0/capacity") diff --git a/vendor/github.com/prometheus/procfs/Makefile b/vendor/github.com/prometheus/procfs/Makefile index fa2bd5b528..7edfe4d093 100644 --- a/vendor/github.com/prometheus/procfs/Makefile +++ b/vendor/github.com/prometheus/procfs/Makefile @@ -14,18 +14,18 @@ include Makefile.common %/.unpacked: %.ttar - @echo ">> extracting fixtures" + @echo ">> extracting fixtures $*" ./ttar -C $(dir $*) -x -f $*.ttar touch $@ -fixtures: fixtures/.unpacked +fixtures: testdata/fixtures/.unpacked update_fixtures: - rm -vf fixtures/.unpacked - ./ttar -c -f fixtures.ttar fixtures/ + rm -vf testdata/fixtures/.unpacked + ./ttar -c -f testdata/fixtures.ttar -C testdata/ fixtures/ .PHONY: build build: .PHONY: test -test: fixtures/.unpacked common-test +test: testdata/fixtures/.unpacked common-test diff --git a/vendor/github.com/prometheus/procfs/Makefile.common b/vendor/github.com/prometheus/procfs/Makefile.common index a1b1ca40f4..e358db69c5 100644 --- a/vendor/github.com/prometheus/procfs/Makefile.common +++ b/vendor/github.com/prometheus/procfs/Makefile.common @@ -36,29 +36,6 @@ GO_VERSION ?= $(shell $(GO) version) GO_VERSION_NUMBER ?= $(word 3, $(GO_VERSION)) PRE_GO_111 ?= $(shell echo $(GO_VERSION_NUMBER) | grep -E 'go1\.(10|[0-9])\.') -GOVENDOR := -GO111MODULE := -ifeq (, $(PRE_GO_111)) - ifneq (,$(wildcard go.mod)) - # Enforce Go modules support just in case the directory is inside GOPATH (and for Travis CI). - GO111MODULE := on - - ifneq (,$(wildcard vendor)) - # Always use the local vendor/ directory to satisfy the dependencies. - GOOPTS := $(GOOPTS) -mod=vendor - endif - endif -else - ifneq (,$(wildcard go.mod)) - ifneq (,$(wildcard vendor)) -$(warning This repository requires Go >= 1.11 because of Go modules) -$(warning Some recipes may not work as expected as the current Go runtime is '$(GO_VERSION_NUMBER)') - endif - else - # This repository isn't using Go modules (yet). - GOVENDOR := $(FIRST_GOPATH)/bin/govendor - endif -endif PROMU := $(FIRST_GOPATH)/bin/promu pkgs = ./... @@ -78,17 +55,26 @@ ifneq ($(shell which gotestsum),) endif endif -PROMU_VERSION ?= 0.12.0 +PROMU_VERSION ?= 0.14.0 PROMU_URL := https://github.com/prometheus/promu/releases/download/v$(PROMU_VERSION)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM).tar.gz +SKIP_GOLANGCI_LINT := GOLANGCI_LINT := GOLANGCI_LINT_OPTS ?= -GOLANGCI_LINT_VERSION ?= v1.39.0 +GOLANGCI_LINT_VERSION ?= v1.49.0 # golangci-lint only supports linux, darwin and windows platforms on i386/amd64. # windows isn't included here because of the path separator being different. ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux darwin)) ifeq ($(GOHOSTARCH),$(filter $(GOHOSTARCH),amd64 i386)) - GOLANGCI_LINT := $(FIRST_GOPATH)/bin/golangci-lint + # If we're in CI and there is an Actions file, that means the linter + # is being run in Actions, so we don't need to run it here. + ifneq (,$(SKIP_GOLANGCI_LINT)) + GOLANGCI_LINT := + else ifeq (,$(CIRCLE_JOB)) + GOLANGCI_LINT := $(FIRST_GOPATH)/bin/golangci-lint + else ifeq (,$(wildcard .github/workflows/golangci-lint.yml)) + GOLANGCI_LINT := $(FIRST_GOPATH)/bin/golangci-lint + endif endif endif @@ -144,32 +130,25 @@ common-check_license: .PHONY: common-deps common-deps: @echo ">> getting dependencies" -ifdef GO111MODULE - GO111MODULE=$(GO111MODULE) $(GO) mod download -else - $(GO) get $(GOOPTS) -t ./... -endif + $(GO) mod download .PHONY: update-go-deps update-go-deps: @echo ">> updating Go dependencies" @for m in $$($(GO) list -mod=readonly -m -f '{{ if and (not .Indirect) (not .Main)}}{{.Path}}{{end}}' all); do \ - $(GO) get $$m; \ + $(GO) get -d $$m; \ done - GO111MODULE=$(GO111MODULE) $(GO) mod tidy -ifneq (,$(wildcard vendor)) - GO111MODULE=$(GO111MODULE) $(GO) mod vendor -endif + $(GO) mod tidy .PHONY: common-test-short common-test-short: $(GOTEST_DIR) @echo ">> running short tests" - GO111MODULE=$(GO111MODULE) $(GOTEST) -short $(GOOPTS) $(pkgs) + $(GOTEST) -short $(GOOPTS) $(pkgs) .PHONY: common-test common-test: $(GOTEST_DIR) @echo ">> running all tests" - GO111MODULE=$(GO111MODULE) $(GOTEST) $(test-flags) $(GOOPTS) $(pkgs) + $(GOTEST) $(test-flags) $(GOOPTS) $(pkgs) $(GOTEST_DIR): @mkdir -p $@ @@ -177,25 +156,21 @@ $(GOTEST_DIR): .PHONY: common-format common-format: @echo ">> formatting code" - GO111MODULE=$(GO111MODULE) $(GO) fmt $(pkgs) + $(GO) fmt $(pkgs) .PHONY: common-vet common-vet: @echo ">> vetting code" - GO111MODULE=$(GO111MODULE) $(GO) vet $(GOOPTS) $(pkgs) + $(GO) vet $(GOOPTS) $(pkgs) .PHONY: common-lint common-lint: $(GOLANGCI_LINT) ifdef GOLANGCI_LINT @echo ">> running golangci-lint" -ifdef GO111MODULE # 'go list' needs to be executed before staticcheck to prepopulate the modules cache. # Otherwise staticcheck might fail randomly for some reason not yet explained. - GO111MODULE=$(GO111MODULE) $(GO) list -e -compiled -test=true -export=false -deps=true -find=false -tags= -- ./... > /dev/null - GO111MODULE=$(GO111MODULE) $(GOLANGCI_LINT) run $(GOLANGCI_LINT_OPTS) $(pkgs) -else - $(GOLANGCI_LINT) run $(pkgs) -endif + $(GO) list -e -compiled -test=true -export=false -deps=true -find=false -tags= -- ./... > /dev/null + $(GOLANGCI_LINT) run $(GOLANGCI_LINT_OPTS) $(pkgs) endif .PHONY: common-yamllint @@ -212,28 +187,15 @@ endif common-staticcheck: lint .PHONY: common-unused -common-unused: $(GOVENDOR) -ifdef GOVENDOR - @echo ">> running check for unused packages" - @$(GOVENDOR) list +unused | grep . && exit 1 || echo 'No unused packages' -else -ifdef GO111MODULE +common-unused: @echo ">> running check for unused/missing packages in go.mod" - GO111MODULE=$(GO111MODULE) $(GO) mod tidy -ifeq (,$(wildcard vendor)) + $(GO) mod tidy @git diff --exit-code -- go.sum go.mod -else - @echo ">> running check for unused packages in vendor/" - GO111MODULE=$(GO111MODULE) $(GO) mod vendor - @git diff --exit-code -- go.sum go.mod vendor/ -endif -endif -endif .PHONY: common-build common-build: promu @echo ">> building binaries" - GO111MODULE=$(GO111MODULE) $(PROMU) build --prefix $(PREFIX) $(PROMU_BINARIES) + $(PROMU) build --prefix $(PREFIX) $(PROMU_BINARIES) .PHONY: common-tarball common-tarball: promu @@ -289,12 +251,6 @@ $(GOLANGCI_LINT): | sh -s -- -b $(FIRST_GOPATH)/bin $(GOLANGCI_LINT_VERSION) endif -ifdef GOVENDOR -.PHONY: $(GOVENDOR) -$(GOVENDOR): - GOOS= GOARCH= $(GO) get -u github.com/kardianos/govendor -endif - .PHONY: precheck precheck:: diff --git a/vendor/github.com/prometheus/procfs/SECURITY.md b/vendor/github.com/prometheus/procfs/SECURITY.md index 67741f015a..fed02d85c7 100644 --- a/vendor/github.com/prometheus/procfs/SECURITY.md +++ b/vendor/github.com/prometheus/procfs/SECURITY.md @@ -3,4 +3,4 @@ The Prometheus security policy, including how to report vulnerabilities, can be found here: -https://prometheus.io/docs/operating/security/ + diff --git a/vendor/github.com/prometheus/procfs/arp.go b/vendor/github.com/prometheus/procfs/arp.go index 4e47e61720..68f36e888f 100644 --- a/vendor/github.com/prometheus/procfs/arp.go +++ b/vendor/github.com/prometheus/procfs/arp.go @@ -15,11 +15,28 @@ package procfs import ( "fmt" - "io/ioutil" "net" + "os" + "strconv" "strings" ) +// Learned from include/uapi/linux/if_arp.h. +const ( + // completed entry (ha valid). + ATFComplete = 0x02 + // permanent entry. + ATFPermanent = 0x04 + // Publish entry. + ATFPublish = 0x08 + // Has requested trailers. + ATFUseTrailers = 0x10 + // Obsoleted: Want to use a netmask (only for proxy entries). + ATFNetmask = 0x20 + // Don't answer this addresses. + ATFDontPublish = 0x40 +) + // ARPEntry contains a single row of the columnar data represented in // /proc/net/arp. type ARPEntry struct { @@ -29,12 +46,14 @@ type ARPEntry struct { HWAddr net.HardwareAddr // Name of the device Device string + // Flags + Flags byte } // GatherARPEntries retrieves all the ARP entries, parse the relevant columns, // and then return a slice of ARPEntry's. func (fs FS) GatherARPEntries() ([]ARPEntry, error) { - data, err := ioutil.ReadFile(fs.proc.Path("net/arp")) + data, err := os.ReadFile(fs.proc.Path("net/arp")) if err != nil { return nil, fmt.Errorf("error reading arp %q: %w", fs.proc.Path("net/arp"), err) } @@ -72,14 +91,26 @@ func parseARPEntries(data []byte) ([]ARPEntry, error) { } func parseARPEntry(columns []string) (ARPEntry, error) { + entry := ARPEntry{Device: columns[5]} ip := net.ParseIP(columns[0]) - mac := net.HardwareAddr(columns[3]) + entry.IPAddr = ip + + if mac, err := net.ParseMAC(columns[3]); err == nil { + entry.HWAddr = mac + } else { + return ARPEntry{}, err + } - entry := ARPEntry{ - IPAddr: ip, - HWAddr: mac, - Device: columns[5], + if flags, err := strconv.ParseUint(columns[2], 0, 8); err == nil { + entry.Flags = byte(flags) + } else { + return ARPEntry{}, err } return entry, nil } + +// IsComplete returns true if ARP entry is marked with complete flag. +func (entry *ARPEntry) IsComplete() bool { + return entry.Flags&ATFComplete != 0 +} diff --git a/vendor/github.com/prometheus/procfs/cpuinfo.go b/vendor/github.com/prometheus/procfs/cpuinfo.go index 5623b24a16..06968ca2ed 100644 --- a/vendor/github.com/prometheus/procfs/cpuinfo.go +++ b/vendor/github.com/prometheus/procfs/cpuinfo.go @@ -11,6 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build linux // +build linux package procfs @@ -27,7 +28,7 @@ import ( "github.com/prometheus/procfs/internal/util" ) -// CPUInfo contains general information about a system CPU found in /proc/cpuinfo +// CPUInfo contains general information about a system CPU found in /proc/cpuinfo. type CPUInfo struct { Processor uint VendorID string @@ -379,6 +380,42 @@ func parseCPUInfoMips(info []byte) ([]CPUInfo, error) { return cpuinfo, nil } +func parseCPUInfoLoong(info []byte) ([]CPUInfo, error) { + scanner := bufio.NewScanner(bytes.NewReader(info)) + // find the first "processor" line + firstLine := firstNonEmptyLine(scanner) + if !strings.HasPrefix(firstLine, "system type") || !strings.Contains(firstLine, ":") { + return nil, errors.New("invalid cpuinfo file: " + firstLine) + } + field := strings.SplitN(firstLine, ": ", 2) + cpuinfo := []CPUInfo{} + systemType := field[1] + i := 0 + for scanner.Scan() { + line := scanner.Text() + if !strings.Contains(line, ":") { + continue + } + field := strings.SplitN(line, ": ", 2) + switch strings.TrimSpace(field[0]) { + case "processor": + v, err := strconv.ParseUint(field[1], 0, 32) + if err != nil { + return nil, err + } + i = int(v) + cpuinfo = append(cpuinfo, CPUInfo{}) // start of the next processor + cpuinfo[i].Processor = uint(v) + cpuinfo[i].VendorID = systemType + case "CPU Family": + cpuinfo[i].CPUFamily = field[1] + case "Model Name": + cpuinfo[i].ModelName = field[1] + } + } + return cpuinfo, nil +} + func parseCPUInfoPPC(info []byte) ([]CPUInfo, error) { scanner := bufio.NewScanner(bytes.NewReader(info)) @@ -469,7 +506,7 @@ func parseCPUInfoDummy(_ []byte) ([]CPUInfo, error) { // nolint:unused,deadcode } // firstNonEmptyLine advances the scanner to the first non-empty line -// and returns the contents of that line +// and returns the contents of that line. func firstNonEmptyLine(scanner *bufio.Scanner) string { for scanner.Scan() { line := scanner.Text() diff --git a/vendor/github.com/prometheus/procfs/cpuinfo_armx.go b/vendor/github.com/prometheus/procfs/cpuinfo_armx.go index 44b590ed38..64cfd534c1 100644 --- a/vendor/github.com/prometheus/procfs/cpuinfo_armx.go +++ b/vendor/github.com/prometheus/procfs/cpuinfo_armx.go @@ -11,6 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build linux && (arm || arm64) // +build linux // +build arm arm64 diff --git a/vendor/github.com/prometheus/procfs/cpuinfo_loong64.go b/vendor/github.com/prometheus/procfs/cpuinfo_loong64.go new file mode 100644 index 0000000000..d88442f0ed --- /dev/null +++ b/vendor/github.com/prometheus/procfs/cpuinfo_loong64.go @@ -0,0 +1,19 @@ +// Copyright 2022 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build linux +// +build linux + +package procfs + +var parseCPUInfo = parseCPUInfoLoong diff --git a/vendor/github.com/prometheus/procfs/cpuinfo_mipsx.go b/vendor/github.com/prometheus/procfs/cpuinfo_mipsx.go index 91e272573a..c11207f3ab 100644 --- a/vendor/github.com/prometheus/procfs/cpuinfo_mipsx.go +++ b/vendor/github.com/prometheus/procfs/cpuinfo_mipsx.go @@ -11,6 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build linux && (mips || mipsle || mips64 || mips64le) // +build linux // +build mips mipsle mips64 mips64le diff --git a/vendor/github.com/prometheus/procfs/cpuinfo_others.go b/vendor/github.com/prometheus/procfs/cpuinfo_others.go index 95b5b4ec44..a6b2b3127c 100644 --- a/vendor/github.com/prometheus/procfs/cpuinfo_others.go +++ b/vendor/github.com/prometheus/procfs/cpuinfo_others.go @@ -11,8 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build linux -// +build !386,!amd64,!arm,!arm64,!mips,!mips64,!mips64le,!mipsle,!ppc64,!ppc64le,!riscv64,!s390x +//go:build linux && !386 && !amd64 && !arm && !arm64 && !loong64 && !mips && !mips64 && !mips64le && !mipsle && !ppc64 && !ppc64le && !riscv64 && !s390x +// +build linux,!386,!amd64,!arm,!arm64,!loong64,!mips,!mips64,!mips64le,!mipsle,!ppc64,!ppc64le,!riscv64,!s390x package procfs diff --git a/vendor/github.com/prometheus/procfs/cpuinfo_ppcx.go b/vendor/github.com/prometheus/procfs/cpuinfo_ppcx.go index 6068bd571c..003bc2ad4a 100644 --- a/vendor/github.com/prometheus/procfs/cpuinfo_ppcx.go +++ b/vendor/github.com/prometheus/procfs/cpuinfo_ppcx.go @@ -11,6 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build linux && (ppc64 || ppc64le) // +build linux // +build ppc64 ppc64le diff --git a/vendor/github.com/prometheus/procfs/cpuinfo_riscvx.go b/vendor/github.com/prometheus/procfs/cpuinfo_riscvx.go index e83c2e207c..1c9b7313b6 100644 --- a/vendor/github.com/prometheus/procfs/cpuinfo_riscvx.go +++ b/vendor/github.com/prometheus/procfs/cpuinfo_riscvx.go @@ -11,6 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build linux && (riscv || riscv64) // +build linux // +build riscv riscv64 diff --git a/vendor/github.com/prometheus/procfs/cpuinfo_s390x.go b/vendor/github.com/prometheus/procfs/cpuinfo_s390x.go index 26814eebaa..fa3686bc00 100644 --- a/vendor/github.com/prometheus/procfs/cpuinfo_s390x.go +++ b/vendor/github.com/prometheus/procfs/cpuinfo_s390x.go @@ -11,6 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build linux // +build linux package procfs diff --git a/vendor/github.com/prometheus/procfs/cpuinfo_x86.go b/vendor/github.com/prometheus/procfs/cpuinfo_x86.go index d5bedf97f3..a0ef55562e 100644 --- a/vendor/github.com/prometheus/procfs/cpuinfo_x86.go +++ b/vendor/github.com/prometheus/procfs/cpuinfo_x86.go @@ -11,6 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build linux && (386 || amd64) // +build linux // +build 386 amd64 diff --git a/vendor/github.com/prometheus/procfs/doc.go b/vendor/github.com/prometheus/procfs/doc.go index d31a82600f..f9d961e441 100644 --- a/vendor/github.com/prometheus/procfs/doc.go +++ b/vendor/github.com/prometheus/procfs/doc.go @@ -16,30 +16,29 @@ // // Example: // -// package main -// -// import ( -// "fmt" -// "log" -// -// "github.com/prometheus/procfs" -// ) -// -// func main() { -// p, err := procfs.Self() -// if err != nil { -// log.Fatalf("could not get process: %s", err) -// } -// -// stat, err := p.Stat() -// if err != nil { -// log.Fatalf("could not get process stat: %s", err) -// } -// -// fmt.Printf("command: %s\n", stat.Comm) -// fmt.Printf("cpu time: %fs\n", stat.CPUTime()) -// fmt.Printf("vsize: %dB\n", stat.VirtualMemory()) -// fmt.Printf("rss: %dB\n", stat.ResidentMemory()) -// } -// +// package main +// +// import ( +// "fmt" +// "log" +// +// "github.com/prometheus/procfs" +// ) +// +// func main() { +// p, err := procfs.Self() +// if err != nil { +// log.Fatalf("could not get process: %s", err) +// } +// +// stat, err := p.Stat() +// if err != nil { +// log.Fatalf("could not get process stat: %s", err) +// } +// +// fmt.Printf("command: %s\n", stat.Comm) +// fmt.Printf("cpu time: %fs\n", stat.CPUTime()) +// fmt.Printf("vsize: %dB\n", stat.VirtualMemory()) +// fmt.Printf("rss: %dB\n", stat.ResidentMemory()) +// } package procfs diff --git a/vendor/github.com/prometheus/procfs/fixtures.ttar b/vendor/github.com/prometheus/procfs/fixtures.ttar deleted file mode 100644 index 5e7eeef4a5..0000000000 --- a/vendor/github.com/prometheus/procfs/fixtures.ttar +++ /dev/null @@ -1,7673 +0,0 @@ -# Archive created by ttar -c -f fixtures.ttar fixtures/ -Directory: fixtures -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/26231 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/cmdline -Lines: 1 -vimNULLBYTEtest.goNULLBYTE+10NULLBYTEEOF -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/comm -Lines: 1 -vim -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/cwd -SymlinkTo: /usr/bin -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/environ -Lines: 1 -PATH=/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binNULLBYTEHOSTNAME=cd24e11f73a5NULLBYTETERM=xtermNULLBYTEGOLANG_VERSION=1.12.5NULLBYTEGOPATH=/goNULLBYTEHOME=/rootNULLBYTEEOF -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/exe -SymlinkTo: /usr/bin/vim -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/26231/fd -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/fd/0 -SymlinkTo: ../../symlinktargets/abc -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/fd/1 -SymlinkTo: ../../symlinktargets/def -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/fd/10 -SymlinkTo: ../../symlinktargets/xyz -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/fd/2 -SymlinkTo: ../../symlinktargets/ghi -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/fd/3 -SymlinkTo: ../../symlinktargets/uvw -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/26231/fdinfo -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/fdinfo/0 -Lines: 6 -pos: 0 -flags: 02004000 -mnt_id: 13 -inotify wd:3 ino:1 sdev:34 mask:fce ignored_mask:0 fhandle-bytes:c fhandle-type:81 f_handle:000000000100000000000000 -inotify wd:2 ino:1300016 sdev:fd00002 mask:fce ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:16003001ed3f022a -inotify wd:1 ino:2e0001 sdev:fd00000 mask:fce ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:01002e00138e7c65 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/fdinfo/1 -Lines: 4 -pos: 0 -flags: 02004002 -mnt_id: 13 -eventfd-count: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/fdinfo/10 -Lines: 3 -pos: 0 -flags: 02004002 -mnt_id: 9 -Mode: 400 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/fdinfo/2 -Lines: 3 -pos: 0 -flags: 02004002 -mnt_id: 9 -Mode: 400 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/fdinfo/3 -Lines: 3 -pos: 0 -flags: 02004002 -mnt_id: 9 -Mode: 400 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/io -Lines: 7 -rchar: 750339 -wchar: 818609 -syscr: 7405 -syscw: 5245 -read_bytes: 1024 -write_bytes: 2048 -cancelled_write_bytes: -1024 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/limits -Lines: 17 -Limit Soft Limit Hard Limit Units -Max cpu time unlimited unlimited seconds -Max file size unlimited unlimited bytes -Max data size unlimited unlimited bytes -Max stack size 8388608 unlimited bytes -Max core file size 0 unlimited bytes -Max resident set unlimited unlimited bytes -Max processes 62898 62898 processes -Max open files 2048 4096 files -Max locked memory 18446744073708503040 18446744073708503040 bytes -Max address space 8589934592 unlimited bytes -Max file locks unlimited unlimited locks -Max pending signals 62898 62898 signals -Max msgqueue size 819200 819200 bytes -Max nice priority 0 0 -Max realtime priority 0 0 -Max realtime timeout unlimited unlimited us -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/mountstats -Lines: 20 -device rootfs mounted on / with fstype rootfs -device sysfs mounted on /sys with fstype sysfs -device proc mounted on /proc with fstype proc -device /dev/sda1 mounted on / with fstype ext4 -device 192.168.1.1:/srv/test mounted on /mnt/nfs/test with fstype nfs4 statvers=1.1 - opts: rw,vers=4.0,rsize=1048576,wsize=1048576,namlen=255,acregmin=3,acregmax=60,acdirmin=30,acdirmax=60,hard,proto=tcp,port=0,timeo=600,retrans=2,sec=sys,mountaddr=192.168.1.1,clientaddr=192.168.1.5,local_lock=none - age: 13968 - caps: caps=0xfff7,wtmult=512,dtsize=32768,bsize=0,namlen=255 - nfsv4: bm0=0xfdffafff,bm1=0xf9be3e,bm2=0x0,acl=0x0,pnfs=not configured - sec: flavor=1,pseudoflavor=1 - events: 52 226 0 0 1 13 398 0 0 331 0 47 0 0 77 0 0 77 0 0 0 0 0 0 0 0 0 - bytes: 1207640230 0 0 0 1210214218 0 295483 0 - RPC iostats version: 1.0 p/v: 100003/4 (nfs) - xprt: tcp 832 0 1 0 11 6428 6428 0 12154 0 24 26 5726 - per-op statistics - NULL: 0 0 0 0 0 0 0 0 - READ: 1298 1298 0 207680 1210292152 6 79386 79407 - WRITE: 0 0 0 0 0 0 0 0 - ACCESS: 2927395007 2927394995 0 526931094212 362996810236 18446743919241604546 1667369447 1953587717 - -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/26231/net -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/net/dev -Lines: 4 -Inter-| Receive | Transmit - face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed - lo: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 - eth0: 438 5 0 0 0 0 0 0 648 8 0 0 0 0 0 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/26231/ns -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/ns/mnt -SymlinkTo: mnt:[4026531840] -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/ns/net -SymlinkTo: net:[4026531993] -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/root -SymlinkTo: / -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/schedstat -Lines: 1 -411605849 93680043 79 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/smaps -Lines: 252 -00400000-00cb1000 r-xp 00000000 fd:01 952273 /bin/alertmanager -Size: 8900 kB -KernelPageSize: 4 kB -MMUPageSize: 4 kB -Rss: 2952 kB -Pss: 2952 kB -Shared_Clean: 0 kB -Shared_Dirty: 0 kB -Private_Clean: 2952 kB -Private_Dirty: 0 kB -Referenced: 2864 kB -Anonymous: 0 kB -LazyFree: 0 kB -AnonHugePages: 0 kB -ShmemPmdMapped: 0 kB -Shared_Hugetlb: 0 kB -Private_Hugetlb: 0 kB -Swap: 0 kB -SwapPss: 0 kB -Locked: 0 kB -VmFlags: rd ex mr mw me dw sd -00cb1000-016b0000 r--p 008b1000 fd:01 952273 /bin/alertmanager -Size: 10236 kB -KernelPageSize: 4 kB -MMUPageSize: 4 kB -Rss: 6152 kB -Pss: 6152 kB -Shared_Clean: 0 kB -Shared_Dirty: 0 kB -Private_Clean: 6152 kB -Private_Dirty: 0 kB -Referenced: 5308 kB -Anonymous: 0 kB -LazyFree: 0 kB -AnonHugePages: 0 kB -ShmemPmdMapped: 0 kB -Shared_Hugetlb: 0 kB -Private_Hugetlb: 0 kB -Swap: 0 kB -SwapPss: 0 kB -Locked: 0 kB -VmFlags: rd mr mw me dw sd -016b0000-0171a000 rw-p 012b0000 fd:01 952273 /bin/alertmanager -Size: 424 kB -KernelPageSize: 4 kB -MMUPageSize: 4 kB -Rss: 176 kB -Pss: 176 kB -Shared_Clean: 0 kB -Shared_Dirty: 0 kB -Private_Clean: 84 kB -Private_Dirty: 92 kB -Referenced: 176 kB -Anonymous: 92 kB -LazyFree: 0 kB -AnonHugePages: 0 kB -ShmemPmdMapped: 0 kB -Shared_Hugetlb: 0 kB -Private_Hugetlb: 0 kB -Swap: 12 kB -SwapPss: 12 kB -Locked: 0 kB -VmFlags: rd wr mr mw me dw ac sd -0171a000-0173f000 rw-p 00000000 00:00 0 -Size: 148 kB -KernelPageSize: 4 kB -MMUPageSize: 4 kB -Rss: 76 kB -Pss: 76 kB -Shared_Clean: 0 kB -Shared_Dirty: 0 kB -Private_Clean: 0 kB -Private_Dirty: 76 kB -Referenced: 76 kB -Anonymous: 76 kB -LazyFree: 0 kB -AnonHugePages: 0 kB -ShmemPmdMapped: 0 kB -Shared_Hugetlb: 0 kB -Private_Hugetlb: 0 kB -Swap: 0 kB -SwapPss: 0 kB -Locked: 0 kB -VmFlags: rd wr mr mw me ac sd -c000000000-c000400000 rw-p 00000000 00:00 0 -Size: 4096 kB -KernelPageSize: 4 kB -MMUPageSize: 4 kB -Rss: 2564 kB -Pss: 2564 kB -Shared_Clean: 0 kB -Shared_Dirty: 0 kB -Private_Clean: 20 kB -Private_Dirty: 2544 kB -Referenced: 2544 kB -Anonymous: 2564 kB -LazyFree: 0 kB -AnonHugePages: 0 kB -ShmemPmdMapped: 0 kB -Shared_Hugetlb: 0 kB -Private_Hugetlb: 0 kB -Swap: 1100 kB -SwapPss: 1100 kB -Locked: 0 kB -VmFlags: rd wr mr mw me ac sd -c000400000-c001600000 rw-p 00000000 00:00 0 -Size: 18432 kB -KernelPageSize: 4 kB -MMUPageSize: 4 kB -Rss: 16024 kB -Pss: 16024 kB -Shared_Clean: 0 kB -Shared_Dirty: 0 kB -Private_Clean: 5864 kB -Private_Dirty: 10160 kB -Referenced: 11944 kB -Anonymous: 16024 kB -LazyFree: 5848 kB -AnonHugePages: 0 kB -ShmemPmdMapped: 0 kB -Shared_Hugetlb: 0 kB -Private_Hugetlb: 0 kB -Swap: 440 kB -SwapPss: 440 kB -Locked: 0 kB -VmFlags: rd wr mr mw me ac sd nh -c001600000-c004000000 rw-p 00000000 00:00 0 -Size: 43008 kB -KernelPageSize: 4 kB -MMUPageSize: 4 kB -Rss: 0 kB -Pss: 0 kB -Shared_Clean: 0 kB -Shared_Dirty: 0 kB -Private_Clean: 0 kB -Private_Dirty: 0 kB -Referenced: 0 kB -Anonymous: 0 kB -LazyFree: 0 kB -AnonHugePages: 0 kB -ShmemPmdMapped: 0 kB -Shared_Hugetlb: 0 kB -Private_Hugetlb: 0 kB -Swap: 0 kB -SwapPss: 0 kB -Locked: 0 kB -VmFlags: rd wr mr mw me ac sd -7f0ab95ca000-7f0abbb7b000 rw-p 00000000 00:00 0 -Size: 38596 kB -KernelPageSize: 4 kB -MMUPageSize: 4 kB -Rss: 1992 kB -Pss: 1992 kB -Shared_Clean: 0 kB -Shared_Dirty: 0 kB -Private_Clean: 476 kB -Private_Dirty: 1516 kB -Referenced: 1828 kB -Anonymous: 1992 kB -LazyFree: 0 kB -AnonHugePages: 0 kB -ShmemPmdMapped: 0 kB -Shared_Hugetlb: 0 kB -Private_Hugetlb: 0 kB -Swap: 384 kB -SwapPss: 384 kB -Locked: 0 kB -VmFlags: rd wr mr mw me ac sd -7ffc07ecf000-7ffc07ef0000 rw-p 00000000 00:00 0 [stack] -Size: 132 kB -KernelPageSize: 4 kB -MMUPageSize: 4 kB -Rss: 8 kB -Pss: 8 kB -Shared_Clean: 0 kB -Shared_Dirty: 0 kB -Private_Clean: 0 kB -Private_Dirty: 8 kB -Referenced: 8 kB -Anonymous: 8 kB -LazyFree: 0 kB -AnonHugePages: 0 kB -ShmemPmdMapped: 0 kB -Shared_Hugetlb: 0 kB -Private_Hugetlb: 0 kB -Swap: 4 kB -SwapPss: 4 kB -Locked: 0 kB -VmFlags: rd wr mr mw me gd ac -7ffc07f9e000-7ffc07fa1000 r--p 00000000 00:00 0 [vvar] -Size: 12 kB -KernelPageSize: 4 kB -MMUPageSize: 4 kB -Rss: 0 kB -Pss: 0 kB -Shared_Clean: 0 kB -Shared_Dirty: 0 kB -Private_Clean: 0 kB -Private_Dirty: 0 kB -Referenced: 0 kB -Anonymous: 0 kB -LazyFree: 0 kB -AnonHugePages: 0 kB -ShmemPmdMapped: 0 kB -Shared_Hugetlb: 0 kB -Private_Hugetlb: 0 kB -Swap: 0 kB -SwapPss: 0 kB -Locked: 0 kB -VmFlags: rd mr pf io de dd sd -7ffc07fa1000-7ffc07fa3000 r-xp 00000000 00:00 0 [vdso] -Size: 8 kB -KernelPageSize: 4 kB -MMUPageSize: 4 kB -Rss: 4 kB -Pss: 0 kB -Shared_Clean: 4 kB -Shared_Dirty: 0 kB -Private_Clean: 0 kB -Private_Dirty: 0 kB -Referenced: 4 kB -Anonymous: 0 kB -LazyFree: 0 kB -AnonHugePages: 0 kB -ShmemPmdMapped: 0 kB -Shared_Hugetlb: 0 kB -Private_Hugetlb: 0 kB -Swap: 0 kB -SwapPss: 0 kB -Locked: 0 kB -VmFlags: rd ex mr mw me de sd -ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] -Size: 4 kB -KernelPageSize: 4 kB -MMUPageSize: 4 kB -Rss: 0 kB -Pss: 0 kB -Shared_Clean: 0 kB -Shared_Dirty: 0 kB -Private_Clean: 0 kB -Private_Dirty: 0 kB -Referenced: 0 kB -Anonymous: 0 kB -LazyFree: 0 kB -AnonHugePages: 0 kB -ShmemPmdMapped: 0 kB -Shared_Hugetlb: 0 kB -Private_Hugetlb: 0 kB -Swap: 0 kB -SwapPss: 0 kB -Locked: 0 kB -VmFlags: rd ex -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/smaps_rollup -Lines: 17 -00400000-ffffffffff601000 ---p 00000000 00:00 0 [rollup] -Rss: 29948 kB -Pss: 29944 kB -Shared_Clean: 4 kB -Shared_Dirty: 0 kB -Private_Clean: 15548 kB -Private_Dirty: 14396 kB -Referenced: 24752 kB -Anonymous: 20756 kB -LazyFree: 5848 kB -AnonHugePages: 0 kB -ShmemPmdMapped: 0 kB -Shared_Hugetlb: 0 kB -Private_Hugetlb: 0 kB -Swap: 1940 kB -SwapPss: 1940 kB -Locked: 0 kB -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/stat -Lines: 1 -26231 (vim) R 5392 7446 5392 34835 7446 4218880 32533 309516 26 82 1677 44 158 99 20 0 1 0 82375 56274944 1981 18446744073709551615 4194304 6294284 140736914091744 140736914087944 139965136429984 0 0 12288 1870679807 0 0 0 17 0 0 0 31 0 0 8391624 8481048 16420864 140736914093252 140736914093279 140736914093279 140736914096107 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/status -Lines: 53 - -Name: prometheus -Umask: 0022 -State: S (sleeping) -Tgid: 26231 -Ngid: 0 -Pid: 26231 -PPid: 1 -TracerPid: 0 -Uid: 1000 1000 1000 0 -Gid: 1001 1001 1001 0 -FDSize: 128 -Groups: -NStgid: 1 -NSpid: 1 -NSpgid: 1 -NSsid: 1 -VmPeak: 58472 kB -VmSize: 58440 kB -VmLck: 0 kB -VmPin: 0 kB -VmHWM: 8028 kB -VmRSS: 6716 kB -RssAnon: 2092 kB -RssFile: 4624 kB -RssShmem: 0 kB -VmData: 2580 kB -VmStk: 136 kB -VmExe: 948 kB -VmLib: 6816 kB -VmPTE: 128 kB -VmPMD: 12 kB -VmSwap: 660 kB -HugetlbPages: 0 kB -Threads: 1 -SigQ: 8/63965 -SigPnd: 0000000000000000 -ShdPnd: 0000000000000000 -SigBlk: 7be3c0fe28014a03 -SigIgn: 0000000000001000 -SigCgt: 00000001800004ec -CapInh: 0000000000000000 -CapPrm: 0000003fffffffff -CapEff: 0000003fffffffff -CapBnd: 0000003fffffffff -CapAmb: 0000000000000000 -Seccomp: 0 -Cpus_allowed: ff -Cpus_allowed_list: 0-7 -Mems_allowed: 00000000,00000001 -Mems_allowed_list: 0 -voluntary_ctxt_switches: 4742839 -nonvoluntary_ctxt_switches: 1727500 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26231/wchan -Lines: 1 -poll_schedule_timeoutEOF -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/26232 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26232/cmdline -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26232/comm -Lines: 1 -ata_sff -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26232/cwd -SymlinkTo: /does/not/exist -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/26232/fd -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26232/fd/0 -SymlinkTo: ../../symlinktargets/abc -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26232/fd/1 -SymlinkTo: ../../symlinktargets/def -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26232/fd/2 -SymlinkTo: ../../symlinktargets/ghi -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26232/fd/3 -SymlinkTo: ../../symlinktargets/uvw -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26232/fd/4 -SymlinkTo: ../../symlinktargets/xyz -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26232/limits -Lines: 17 -Limit Soft Limit Hard Limit Units -Max cpu time unlimited unlimited seconds -Max file size unlimited unlimited bytes -Max data size unlimited unlimited bytes -Max stack size 8388608 unlimited bytes -Max core file size 0 unlimited bytes -Max resident set unlimited unlimited bytes -Max processes 29436 29436 processes -Max open files 1024 4096 files -Max locked memory 65536 65536 bytes -Max address space unlimited unlimited bytes -Max file locks unlimited unlimited locks -Max pending signals 29436 29436 signals -Max msgqueue size 819200 819200 bytes -Max nice priority 0 0 -Max realtime priority 0 0 -Max realtime timeout unlimited unlimited us -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26232/maps -Lines: 9 -55680ae1e000-55680ae20000 r--p 00000000 fd:01 47316994 /bin/cat -55680ae29000-55680ae2a000 rwxs 0000a000 fd:01 47316994 /bin/cat -55680bed6000-55680bef7000 rw-p 00000000 00:00 0 [heap] -7fdf964fc000-7fdf973f2000 r--p 00000000 fd:01 17432624 /usr/lib/locale/locale-archive -7fdf973f2000-7fdf97417000 r--p 00000000 fd:01 60571062 /lib/x86_64-linux-gnu/libc-2.29.so -7ffe9215c000-7ffe9217f000 rw-p 00000000 00:00 0 [stack] -7ffe921da000-7ffe921dd000 r--p 00000000 00:00 0 [vvar] -7ffe921dd000-7ffe921de000 r-xp 00000000 00:00 0 [vdso] -ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall] -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26232/root -SymlinkTo: /does/not/exist -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26232/stat -Lines: 1 -33 (ata_sff) S 2 0 0 0 -1 69238880 0 0 0 0 0 0 0 0 0 -20 1 0 5 0 0 18446744073709551615 0 0 0 0 0 0 0 2147483647 0 18446744073709551615 0 0 17 1 0 0 0 0 0 0 0 0 0 0 0 0 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26232/wchan -Lines: 1 -0EOF -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/26233 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26233/cmdline -Lines: 1 -com.github.uiautomatorNULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTEEOF -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26233/schedstat -Lines: 8 - ____________________________________ -< this is a malformed schedstat file > - ------------------------------------ - \ ^__^ - \ (oo)\_______ - (__)\ )\/\ - ||----w | - || || -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/26234 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/26234/maps -Lines: 4 -08048000-08089000 r-xp 00000000 03:01 104219 /bin/tcsh -08089000-0808c000 rw-p 00041000 03:01 104219 /bin/tcsh -0808c000-08146000 rwxp 00000000 00:00 0 -40000000-40015000 r-xp 00000000 03:01 61874 /lib/ld-2.3.2.so -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/584 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/584/stat -Lines: 2 -1020 ((a b ) ( c d) ) R 28378 1020 28378 34842 1020 4218880 286 0 0 0 0 0 0 0 20 0 1 0 10839175 10395648 155 18446744073709551615 4194304 4238788 140736466511168 140736466511168 140609271124624 0 0 0 0 0 0 0 17 5 0 0 0 0 0 6336016 6337300 25579520 140736466515030 140736466515061 140736466515061 140736466518002 0 -#!/bin/cat /proc/self/stat -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/buddyinfo -Lines: 3 -Node 0, zone DMA 1 0 1 0 2 1 1 0 1 1 3 -Node 0, zone DMA32 759 572 791 475 194 45 12 0 0 0 0 -Node 0, zone Normal 4381 1093 185 1530 567 102 4 0 0 0 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/cmdline -Lines: 1 -BOOT_IMAGE=/vmlinuz-5.11.0-22-generic root=UUID=456a0345-450d-4f7b-b7c9-43e3241d99ad ro quiet splash vt.handoff=7 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/cpuinfo -Lines: 216 -processor : 0 -vendor_id : GenuineIntel -cpu family : 6 -model : 142 -model name : Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz -stepping : 10 -microcode : 0xb4 -cpu MHz : 799.998 -cache size : 8192 KB -physical id : 0 -siblings : 8 -core id : 0 -cpu cores : 4 -apicid : 0 -initial apicid : 0 -fpu : yes -fpu_exception : yes -cpuid level : 22 -wp : yes -flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d -bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs -bogomips : 4224.00 -clflush size : 64 -cache_alignment : 64 -address sizes : 39 bits physical, 48 bits virtual -power management: - -processor : 1 -vendor_id : GenuineIntel -cpu family : 6 -model : 142 -model name : Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz -stepping : 10 -microcode : 0xb4 -cpu MHz : 800.037 -cache size : 8192 KB -physical id : 0 -siblings : 8 -core id : 1 -cpu cores : 4 -apicid : 2 -initial apicid : 2 -fpu : yes -fpu_exception : yes -cpuid level : 22 -wp : yes -flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d -bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs -bogomips : 4224.00 -clflush size : 64 -cache_alignment : 64 -address sizes : 39 bits physical, 48 bits virtual -power management: - -processor : 2 -vendor_id : GenuineIntel -cpu family : 6 -model : 142 -model name : Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz -stepping : 10 -microcode : 0xb4 -cpu MHz : 800.010 -cache size : 8192 KB -physical id : 0 -siblings : 8 -core id : 2 -cpu cores : 4 -apicid : 4 -initial apicid : 4 -fpu : yes -fpu_exception : yes -cpuid level : 22 -wp : yes -flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d -bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs -bogomips : 4224.00 -clflush size : 64 -cache_alignment : 64 -address sizes : 39 bits physical, 48 bits virtual -power management: - -processor : 3 -vendor_id : GenuineIntel -cpu family : 6 -model : 142 -model name : Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz -stepping : 10 -microcode : 0xb4 -cpu MHz : 800.028 -cache size : 8192 KB -physical id : 0 -siblings : 8 -core id : 3 -cpu cores : 4 -apicid : 6 -initial apicid : 6 -fpu : yes -fpu_exception : yes -cpuid level : 22 -wp : yes -flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d -bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs -bogomips : 4224.00 -clflush size : 64 -cache_alignment : 64 -address sizes : 39 bits physical, 48 bits virtual -power management: - -processor : 4 -vendor_id : GenuineIntel -cpu family : 6 -model : 142 -model name : Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz -stepping : 10 -microcode : 0xb4 -cpu MHz : 799.989 -cache size : 8192 KB -physical id : 0 -siblings : 8 -core id : 0 -cpu cores : 4 -apicid : 1 -initial apicid : 1 -fpu : yes -fpu_exception : yes -cpuid level : 22 -wp : yes -flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d -bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs -bogomips : 4224.00 -clflush size : 64 -cache_alignment : 64 -address sizes : 39 bits physical, 48 bits virtual -power management: - -processor : 5 -vendor_id : GenuineIntel -cpu family : 6 -model : 142 -model name : Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz -stepping : 10 -microcode : 0xb4 -cpu MHz : 800.083 -cache size : 8192 KB -physical id : 0 -siblings : 8 -core id : 1 -cpu cores : 4 -apicid : 3 -initial apicid : 3 -fpu : yes -fpu_exception : yes -cpuid level : 22 -wp : yes -flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d -bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs -bogomips : 4224.00 -clflush size : 64 -cache_alignment : 64 -address sizes : 39 bits physical, 48 bits virtual -power management: - -processor : 6 -vendor_id : GenuineIntel -cpu family : 6 -model : 142 -model name : Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz -stepping : 10 -microcode : 0xb4 -cpu MHz : 800.017 -cache size : 8192 KB -physical id : 0 -siblings : 8 -core id : 2 -cpu cores : 4 -apicid : 5 -initial apicid : 5 -fpu : yes -fpu_exception : yes -cpuid level : 22 -wp : yes -flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d -bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs -bogomips : 4224.00 -clflush size : 64 -cache_alignment : 64 -address sizes : 39 bits physical, 48 bits virtual -power management: - -processor : 7 -vendor_id : GenuineIntel -cpu family : 6 -model : 142 -model name : Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz -stepping : 10 -microcode : 0xb4 -cpu MHz : 800.030 -cache size : 8192 KB -physical id : 0 -siblings : 8 -core id : 3 -cpu cores : 4 -apicid : 7 -initial apicid : 7 -fpu : yes -fpu_exception : yes -cpuid level : 22 -wp : yes -flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d -bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs -bogomips : 4224.00 -clflush size : 64 -cache_alignment : 64 -address sizes : 39 bits physical, 48 bits virtual -power management: - -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/crypto -Lines: 972 -name : ccm(aes) -driver : ccm_base(ctr(aes-aesni),cbcmac(aes-aesni)) -module : ccm -priority : 300 -refcnt : 4 -selftest : passed -internal : no -type : aead -async : no -blocksize : 1 -ivsize : 16 -maxauthsize : 16 -geniv : - -name : cbcmac(aes) -driver : cbcmac(aes-aesni) -module : ccm -priority : 300 -refcnt : 7 -selftest : passed -internal : no -type : shash -blocksize : 1 -digestsize : 16 - -name : ecdh -driver : ecdh-generic -module : ecdh_generic -priority : 100 -refcnt : 1 -selftest : passed -internal : no -type : kpp -async : yes - -name : ecb(arc4) -driver : ecb(arc4)-generic -module : arc4 -priority : 100 -refcnt : 1 -selftest : passed -internal : no -type : skcipher -async : no -blocksize : 1 -min keysize : 1 -max keysize : 256 -ivsize : 0 -chunksize : 1 -walksize : 1 - -name : arc4 -driver : arc4-generic -module : arc4 -priority : 0 -refcnt : 3 -selftest : passed -internal : no -type : cipher -blocksize : 1 -min keysize : 1 -max keysize : 256 - -name : crct10dif -driver : crct10dif-pclmul -module : crct10dif_pclmul -priority : 200 -refcnt : 2 -selftest : passed -internal : no -type : shash -blocksize : 1 -digestsize : 2 - -name : crc32 -driver : crc32-pclmul -module : crc32_pclmul -priority : 200 -refcnt : 1 -selftest : passed -internal : no -type : shash -blocksize : 1 -digestsize : 4 - -name : __ghash -driver : cryptd(__ghash-pclmulqdqni) -module : kernel -priority : 50 -refcnt : 1 -selftest : passed -internal : yes -type : ahash -async : yes -blocksize : 16 -digestsize : 16 - -name : ghash -driver : ghash-clmulni -module : ghash_clmulni_intel -priority : 400 -refcnt : 1 -selftest : passed -internal : no -type : ahash -async : yes -blocksize : 16 -digestsize : 16 - -name : __ghash -driver : __ghash-pclmulqdqni -module : ghash_clmulni_intel -priority : 0 -refcnt : 1 -selftest : passed -internal : yes -type : shash -blocksize : 16 -digestsize : 16 - -name : crc32c -driver : crc32c-intel -module : crc32c_intel -priority : 200 -refcnt : 5 -selftest : passed -internal : no -type : shash -blocksize : 1 -digestsize : 4 - -name : cbc(aes) -driver : cbc(aes-aesni) -module : kernel -priority : 300 -refcnt : 1 -selftest : passed -internal : no -type : skcipher -async : no -blocksize : 16 -min keysize : 16 -max keysize : 32 -ivsize : 16 -chunksize : 16 -walksize : 16 - -name : ctr(aes) -driver : ctr(aes-aesni) -module : kernel -priority : 300 -refcnt : 5 -selftest : passed -internal : no -type : skcipher -async : no -blocksize : 1 -min keysize : 16 -max keysize : 32 -ivsize : 16 -chunksize : 16 -walksize : 16 - -name : pkcs1pad(rsa,sha256) -driver : pkcs1pad(rsa-generic,sha256) -module : kernel -priority : 100 -refcnt : 1 -selftest : passed -internal : no -type : akcipher - -name : __xts(aes) -driver : cryptd(__xts-aes-aesni) -module : kernel -priority : 451 -refcnt : 1 -selftest : passed -internal : yes -type : skcipher -async : yes -blocksize : 16 -min keysize : 32 -max keysize : 64 -ivsize : 16 -chunksize : 16 -walksize : 16 - -name : xts(aes) -driver : xts-aes-aesni -module : kernel -priority : 401 -refcnt : 1 -selftest : passed -internal : no -type : skcipher -async : yes -blocksize : 16 -min keysize : 32 -max keysize : 64 -ivsize : 16 -chunksize : 16 -walksize : 16 - -name : __ctr(aes) -driver : cryptd(__ctr-aes-aesni) -module : kernel -priority : 450 -refcnt : 1 -selftest : passed -internal : yes -type : skcipher -async : yes -blocksize : 1 -max keysize : 32 -ivsize : 16 -chunksize : 16 -walksize : 16 - -name : ctr(aes) -driver : ctr-aes-aesni -module : kernel -priority : 400 -refcnt : 1 -selftest : passed -internal : no -type : skcipher -async : yes -blocksize : 1 -min keysize : 16 -max keysize : 32 -ivsize : 16 -chunksize : 16 -walksize : 16 - -name : __cbc(aes) -driver : cryptd(__cbc-aes-aesni) -module : kernel -priority : 450 -refcnt : 1 -selftest : passed -internal : yes -type : skcipher -async : yes -blocksize : 16 -min keysize : 16 -max keysize : 32 -ivsize : 16 -chunksize : 16 -walksize : 16 - -name : cbc(aes) -driver : cbc-aes-aesni -module : kernel -priority : 400 -refcnt : 1 -selftest : passed -internal : no -type : skcipher -async : yes -blocksize : 16 -min keysize : 16 -max keysize : 32 -ivsize : 16 -chunksize : 16 -walksize : 16 - -name : __ecb(aes) -driver : cryptd(__ecb-aes-aesni) -module : kernel -priority : 450 -refcnt : 1 -selftest : passed -internal : yes -type : skcipher -async : yes -blocksize : 16 -min keysize : 16 -max keysize : 32 -ivsize : 0 -chunksize : 16 -walksize : 16 - -name : ecb(aes) -driver : ecb-aes-aesni -module : kernel -priority : 400 -refcnt : 1 -selftest : passed -internal : no -type : skcipher -async : yes -blocksize : 16 -min keysize : 16 -max keysize : 32 -ivsize : 0 -chunksize : 16 -walksize : 16 - -name : __generic-gcm-aes-aesni -driver : cryptd(__driver-generic-gcm-aes-aesni) -module : kernel -priority : 50 -refcnt : 1 -selftest : passed -internal : yes -type : aead -async : yes -blocksize : 1 -ivsize : 12 -maxauthsize : 16 -geniv : - -name : gcm(aes) -driver : generic-gcm-aesni -module : kernel -priority : 400 -refcnt : 1 -selftest : passed -internal : no -type : aead -async : yes -blocksize : 1 -ivsize : 12 -maxauthsize : 16 -geniv : - -name : __generic-gcm-aes-aesni -driver : __driver-generic-gcm-aes-aesni -module : kernel -priority : 0 -refcnt : 1 -selftest : passed -internal : yes -type : aead -async : no -blocksize : 1 -ivsize : 12 -maxauthsize : 16 -geniv : - -name : __gcm-aes-aesni -driver : cryptd(__driver-gcm-aes-aesni) -module : kernel -priority : 50 -refcnt : 1 -selftest : passed -internal : yes -type : aead -async : yes -blocksize : 1 -ivsize : 8 -maxauthsize : 16 -geniv : - -name : rfc4106(gcm(aes)) -driver : rfc4106-gcm-aesni -module : kernel -priority : 400 -refcnt : 1 -selftest : passed -internal : no -type : aead -async : yes -blocksize : 1 -ivsize : 8 -maxauthsize : 16 -geniv : - -name : __gcm-aes-aesni -driver : __driver-gcm-aes-aesni -module : kernel -priority : 0 -refcnt : 1 -selftest : passed -internal : yes -type : aead -async : no -blocksize : 1 -ivsize : 8 -maxauthsize : 16 -geniv : - -name : __xts(aes) -driver : __xts-aes-aesni -module : kernel -priority : 401 -refcnt : 1 -selftest : passed -internal : yes -type : skcipher -async : no -blocksize : 16 -min keysize : 32 -max keysize : 64 -ivsize : 16 -chunksize : 16 -walksize : 16 - -name : __ctr(aes) -driver : __ctr-aes-aesni -module : kernel -priority : 400 -refcnt : 1 -selftest : passed -internal : yes -type : skcipher -async : no -blocksize : 1 -min keysize : 16 -max keysize : 32 -ivsize : 16 -chunksize : 16 -walksize : 16 - -name : __cbc(aes) -driver : __cbc-aes-aesni -module : kernel -priority : 400 -refcnt : 1 -selftest : passed -internal : yes -type : skcipher -async : no -blocksize : 16 -min keysize : 16 -max keysize : 32 -ivsize : 16 -chunksize : 16 -walksize : 16 - -name : __ecb(aes) -driver : __ecb-aes-aesni -module : kernel -priority : 400 -refcnt : 1 -selftest : passed -internal : yes -type : skcipher -async : no -blocksize : 16 -min keysize : 16 -max keysize : 32 -ivsize : 0 -chunksize : 16 -walksize : 16 - -name : __aes -driver : __aes-aesni -module : kernel -priority : 300 -refcnt : 1 -selftest : passed -internal : yes -type : cipher -blocksize : 16 -min keysize : 16 -max keysize : 32 - -name : aes -driver : aes-aesni -module : kernel -priority : 300 -refcnt : 8 -selftest : passed -internal : no -type : cipher -blocksize : 16 -min keysize : 16 -max keysize : 32 - -name : hmac(sha1) -driver : hmac(sha1-generic) -module : kernel -priority : 100 -refcnt : 9 -selftest : passed -internal : no -type : shash -blocksize : 64 -digestsize : 20 - -name : ghash -driver : ghash-generic -module : kernel -priority : 100 -refcnt : 3 -selftest : passed -internal : no -type : shash -blocksize : 16 -digestsize : 16 - -name : jitterentropy_rng -driver : jitterentropy_rng -module : kernel -priority : 100 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_nopr_hmac_sha256 -module : kernel -priority : 221 -refcnt : 2 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_nopr_hmac_sha512 -module : kernel -priority : 220 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_nopr_hmac_sha384 -module : kernel -priority : 219 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_nopr_hmac_sha1 -module : kernel -priority : 218 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_nopr_sha256 -module : kernel -priority : 217 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_nopr_sha512 -module : kernel -priority : 216 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_nopr_sha384 -module : kernel -priority : 215 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_nopr_sha1 -module : kernel -priority : 214 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_nopr_ctr_aes256 -module : kernel -priority : 213 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_nopr_ctr_aes192 -module : kernel -priority : 212 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_nopr_ctr_aes128 -module : kernel -priority : 211 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : hmac(sha256) -driver : hmac(sha256-generic) -module : kernel -priority : 100 -refcnt : 10 -selftest : passed -internal : no -type : shash -blocksize : 64 -digestsize : 32 - -name : stdrng -driver : drbg_pr_hmac_sha256 -module : kernel -priority : 210 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_pr_hmac_sha512 -module : kernel -priority : 209 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_pr_hmac_sha384 -module : kernel -priority : 208 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_pr_hmac_sha1 -module : kernel -priority : 207 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_pr_sha256 -module : kernel -priority : 206 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_pr_sha512 -module : kernel -priority : 205 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_pr_sha384 -module : kernel -priority : 204 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_pr_sha1 -module : kernel -priority : 203 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_pr_ctr_aes256 -module : kernel -priority : 202 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_pr_ctr_aes192 -module : kernel -priority : 201 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : stdrng -driver : drbg_pr_ctr_aes128 -module : kernel -priority : 200 -refcnt : 1 -selftest : passed -internal : no -type : rng -seedsize : 0 - -name : 842 -driver : 842-scomp -module : kernel -priority : 100 -refcnt : 1 -selftest : passed -internal : no -type : scomp - -name : 842 -driver : 842-generic -module : kernel -priority : 100 -refcnt : 1 -selftest : passed -internal : no -type : compression - -name : lzo-rle -driver : lzo-rle-scomp -module : kernel -priority : 0 -refcnt : 1 -selftest : passed -internal : no -type : scomp - -name : lzo-rle -driver : lzo-rle-generic -module : kernel -priority : 0 -refcnt : 1 -selftest : passed -internal : no -type : compression - -name : lzo -driver : lzo-scomp -module : kernel -priority : 0 -refcnt : 1 -selftest : passed -internal : no -type : scomp - -name : lzo -driver : lzo-generic -module : kernel -priority : 0 -refcnt : 9 -selftest : passed -internal : no -type : compression - -name : crct10dif -driver : crct10dif-generic -module : kernel -priority : 100 -refcnt : 1 -selftest : passed -internal : no -type : shash -blocksize : 1 -digestsize : 2 - -name : crc32c -driver : crc32c-generic -module : kernel -priority : 100 -refcnt : 1 -selftest : passed -internal : no -type : shash -blocksize : 1 -digestsize : 4 - -name : zlib-deflate -driver : zlib-deflate-scomp -module : kernel -priority : 0 -refcnt : 1 -selftest : passed -internal : no -type : scomp - -name : deflate -driver : deflate-scomp -module : kernel -priority : 0 -refcnt : 1 -selftest : passed -internal : no -type : scomp - -name : deflate -driver : deflate-generic -module : kernel -priority : 0 -refcnt : 1 -selftest : passed -internal : no -type : compression - -name : aes -driver : aes-generic -module : kernel -priority : 100 -refcnt : 1 -selftest : passed -internal : no -type : cipher -blocksize : 16 -min keysize : 16 -max keysize : 32 - -name : sha224 -driver : sha224-generic -module : kernel -priority : 100 -refcnt : 1 -selftest : passed -internal : no -type : shash -blocksize : 64 -digestsize : 28 - -name : sha256 -driver : sha256-generic -module : kernel -priority : 100 -refcnt : 11 -selftest : passed -internal : no -type : shash -blocksize : 64 -digestsize : 32 - -name : sha1 -driver : sha1-generic -module : kernel -priority : 100 -refcnt : 11 -selftest : passed -internal : no -type : shash -blocksize : 64 -digestsize : 20 - -name : md5 -driver : md5-generic -module : kernel -priority : 0 -refcnt : 1 -selftest : passed -internal : no -type : shash -blocksize : 64 -digestsize : 16 - -name : ecb(cipher_null) -driver : ecb-cipher_null -module : kernel -priority : 100 -refcnt : 1 -selftest : passed -internal : no -type : skcipher -async : no -blocksize : 1 -min keysize : 0 -max keysize : 0 -ivsize : 0 -chunksize : 1 -walksize : 1 - -name : digest_null -driver : digest_null-generic -module : kernel -priority : 0 -refcnt : 1 -selftest : passed -internal : no -type : shash -blocksize : 1 -digestsize : 0 - -name : compress_null -driver : compress_null-generic -module : kernel -priority : 0 -refcnt : 1 -selftest : passed -internal : no -type : compression - -name : cipher_null -driver : cipher_null-generic -module : kernel -priority : 0 -refcnt : 1 -selftest : passed -internal : no -type : cipher -blocksize : 1 -min keysize : 0 -max keysize : 0 - -name : rsa -driver : rsa-generic -module : kernel -priority : 100 -refcnt : 1 -selftest : passed -internal : no -type : akcipher - -name : dh -driver : dh-generic -module : kernel -priority : 100 -refcnt : 1 -selftest : passed -internal : no -type : kpp - -name : aes -driver : aes-asm -module : kernel -priority : 200 -refcnt : 1 -selftest : passed -internal : no -type : cipher -blocksize : 16 -min keysize : 16 -max keysize : 32 - -Mode: 444 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/diskstats -Lines: 52 - 1 0 ram0 0 0 0 0 0 0 0 0 0 0 0 - 1 1 ram1 0 0 0 0 0 0 0 0 0 0 0 - 1 2 ram2 0 0 0 0 0 0 0 0 0 0 0 - 1 3 ram3 0 0 0 0 0 0 0 0 0 0 0 - 1 4 ram4 0 0 0 0 0 0 0 0 0 0 0 - 1 5 ram5 0 0 0 0 0 0 0 0 0 0 0 - 1 6 ram6 0 0 0 0 0 0 0 0 0 0 0 - 1 7 ram7 0 0 0 0 0 0 0 0 0 0 0 - 1 8 ram8 0 0 0 0 0 0 0 0 0 0 0 - 1 9 ram9 0 0 0 0 0 0 0 0 0 0 0 - 1 10 ram10 0 0 0 0 0 0 0 0 0 0 0 - 1 11 ram11 0 0 0 0 0 0 0 0 0 0 0 - 1 12 ram12 0 0 0 0 0 0 0 0 0 0 0 - 1 13 ram13 0 0 0 0 0 0 0 0 0 0 0 - 1 14 ram14 0 0 0 0 0 0 0 0 0 0 0 - 1 15 ram15 0 0 0 0 0 0 0 0 0 0 0 - 7 0 loop0 0 0 0 0 0 0 0 0 0 0 0 - 7 1 loop1 0 0 0 0 0 0 0 0 0 0 0 - 7 2 loop2 0 0 0 0 0 0 0 0 0 0 0 - 7 3 loop3 0 0 0 0 0 0 0 0 0 0 0 - 7 4 loop4 0 0 0 0 0 0 0 0 0 0 0 - 7 5 loop5 0 0 0 0 0 0 0 0 0 0 0 - 7 6 loop6 0 0 0 0 0 0 0 0 0 0 0 - 7 7 loop7 0 0 0 0 0 0 0 0 0 0 0 - 8 0 sda 25354637 34367663 1003346126 18492372 28444756 11134226 505697032 63877960 0 9653880 82621804 - 8 1 sda1 250 0 2000 36 0 0 0 0 0 36 36 - 8 2 sda2 246 0 1968 32 0 0 0 0 0 32 32 - 8 3 sda3 340 13 2818 52 11 8 152 8 0 56 60 - 8 4 sda4 25353629 34367650 1003337964 18492232 27448755 11134218 505696880 61593380 0 7576432 80332428 - 252 0 dm-0 59910002 0 1003337218 46229572 39231014 0 505696880 1158557800 0 11325968 1206301256 - 252 1 dm-1 388 0 3104 84 74 0 592 0 0 76 84 - 252 2 dm-2 11571 0 308350 6536 153522 0 5093416 122884 0 65400 129416 - 252 3 dm-3 3870 0 3870 104 0 0 0 0 0 16 104 - 252 4 dm-4 392 0 1034 28 38 0 137 16 0 24 44 - 252 5 dm-5 3729 0 84279 924 98918 0 1151688 104684 0 58848 105632 - 179 0 mmcblk0 192 3 1560 156 0 0 0 0 0 136 156 - 179 1 mmcblk0p1 17 3 160 24 0 0 0 0 0 24 24 - 179 2 mmcblk0p2 95 0 760 68 0 0 0 0 0 68 68 - 2 0 fd0 2 0 16 80 0 0 0 0 0 80 80 - 254 0 vda 1775784 15386 32670882 8655768 6038856 20711856 213637440 2069221364 0 41614592 2077872228 - 254 1 vda1 668 85 5984 956 207 4266 35784 32772 0 8808 33720 - 254 2 vda2 1774936 15266 32663262 8654692 5991028 20707590 213601656 2069152216 0 41607628 2077801992 - 11 0 sr0 0 0 0 0 0 0 0 0 0 0 0 - 259 0 nvme0n1 47114 4 4643973 21650 1078320 43950 39451633 1011053 0 222766 1032546 - 259 1 nvme0n1p1 1140 0 9370 16 1 0 1 0 0 16 16 - 259 2 nvme0n1p2 45914 4 4631243 21626 1036885 43950 39451632 919480 0 131580 940970 - 8 0 sdb 326552 841 9657779 84 41822 2895 1972905 5007 0 60730 67070 68851 0 1925173784 11130 - 8 1 sdb1 231 3 34466 4 24 23 106 0 0 64 64 0 0 0 0 - 8 2 sdb2 326310 838 9622281 67 40726 2872 1972799 4924 0 58250 64567 68851 0 1925173784 11130 - 8 0 sdc 14202 71 579164 21861 2995 1589 180500 40875 0 11628 55200 0 0 0 0 127 182 - 8 1 sdc1 1027 0 13795 5021 2 0 4096 3 0 690 4579 0 0 0 0 0 0 - 8 2 sdc2 13126 71 561749 16802 2830 1589 176404 40620 0 10931 50449 0 0 0 0 0 0 -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/fs -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/fs/fscache -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/fs/fscache/stats -Lines: 24 -FS-Cache statistics -Cookies: idx=3 dat=67877 spc=0 -Objects: alc=67473 nal=0 avl=67473 ded=388 -ChkAux : non=12 ok=33 upd=44 obs=55 -Pages : mrk=547164 unc=364577 -Acquire: n=67880 nul=98 noc=25 ok=67780 nbf=39 oom=26 -Lookups: n=67473 neg=67470 pos=58 crt=67473 tmo=85 -Invals : n=14 run=13 -Updates: n=7 nul=3 run=8 -Relinqs: n=394 nul=1 wcr=2 rtr=3 -AttrChg: n=6 ok=5 nbf=4 oom=3 run=2 -Allocs : n=20 ok=19 wt=18 nbf=17 int=16 -Allocs : ops=15 owt=14 abt=13 -Retrvls: n=151959 ok=82823 wt=23467 nod=69136 nbf=15 int=69 oom=43 -Retrvls: ops=151959 owt=42747 abt=44 -Stores : n=225565 ok=225565 agn=12 nbf=13 oom=14 -Stores : ops=69156 run=294721 pgs=225565 rxd=225565 olm=43 -VmScan : nos=364512 gon=2 bsy=43 can=12 wt=66 -Ops : pend=42753 run=221129 enq=628798 can=11 rej=88 -Ops : ini=377538 dfr=27 rel=377538 gc=37 -CacheOp: alo=1 luo=2 luc=3 gro=4 -CacheOp: inv=5 upo=6 dro=7 pto=8 atc=9 syn=10 -CacheOp: rap=11 ras=12 alp=13 als=14 wrp=15 ucp=16 dsp=17 -CacheEv: nsp=18 stl=19 rtr=20 cul=21EOF -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/fs/xfs -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/fs/xfs/stat -Lines: 23 -extent_alloc 92447 97589 92448 93751 -abt 0 0 0 0 -blk_map 1767055 188820 184891 92447 92448 2140766 0 -bmbt 0 0 0 0 -dir 185039 92447 92444 136422 -trans 706 944304 0 -ig 185045 58807 0 126238 0 33637 22 -log 2883 113448 9 17360 739 -push_ail 945014 0 134260 15483 0 3940 464 159985 0 40 -xstrat 92447 0 -rw 107739 94045 -attr 4 0 0 0 -icluster 8677 7849 135802 -vnodes 92601 0 0 0 92444 92444 92444 0 -buf 2666287 7122 2659202 3599 2 7085 0 10297 7085 -abtb2 184941 1277345 13257 13278 0 0 0 0 0 0 0 0 0 0 2746147 -abtc2 345295 2416764 172637 172658 0 0 0 0 0 0 0 0 0 0 21406023 -bmbt2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -ibt2 343004 1358467 0 0 0 0 0 0 0 0 0 0 0 0 0 -fibt2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -qm 0 0 0 0 0 0 0 0 -xpc 399724544 92823103 86219234 -debug 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/loadavg -Lines: 1 -0.02 0.04 0.05 1/497 11947 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/mdstat -Lines: 60 -Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10] - -md3 : active raid6 sda1[8] sdh1[7] sdg1[6] sdf1[5] sde1[11] sdd1[3] sdc1[10] sdb1[9] sdd1[10](S) sdd2[11](S) - 5853468288 blocks super 1.2 level 6, 64k chunk, algorithm 2 [8/8] [UUUUUUUU] - -md127 : active raid1 sdi2[0] sdj2[1] - 312319552 blocks [2/2] [UU] - -md0 : active raid1 sdi1[0] sdj1[1] - 248896 blocks [2/2] [UU] - -md4 : inactive raid1 sda3[0](F) sdb3[1](S) - 4883648 blocks [2/2] [UU] - -md6 : active raid1 sdb2[2](F) sdc[1](S) sda2[0] - 195310144 blocks [2/1] [U_] - [=>...................] recovery = 8.5% (16775552/195310144) finish=17.0min speed=259783K/sec - -md8 : active raid1 sdb1[1] sda1[0] sdc[2](S) sde[3](S) - 195310144 blocks [2/2] [UU] - [=>...................] resync = 8.5% (16775552/195310144) finish=17.0min speed=259783K/sec - -md201 : active raid1 sda3[0] sdb3[1] - 1993728 blocks super 1.2 [2/2] [UU] - [=>...................] check = 5.7% (114176/1993728) finish=0.2min speed=114176K/sec - -md7 : active raid6 sdb1[0] sde1[3] sdd1[2] sdc1[1](F) - 7813735424 blocks super 1.2 level 6, 512k chunk, algorithm 2 [4/3] [U_UU] - bitmap: 0/30 pages [0KB], 65536KB chunk - -md9 : active raid1 sdc2[2] sdd2[3] sdb2[1] sda2[0] sde[4](F) sdf[5](F) sdg[6](S) - 523968 blocks super 1.2 [4/4] [UUUU] - resync=DELAYED - -md10 : active raid0 sda1[0] sdb1[1] - 314159265 blocks 64k chunks - -md11 : active (auto-read-only) raid1 sdb2[0] sdc2[1] sdc3[2](F) hda[4](S) ssdc2[3](S) - 4190208 blocks super 1.2 [2/2] [UU] - resync=PENDING - -md12 : active raid0 sdc2[0] sdd2[1] - 3886394368 blocks super 1.2 512k chunks - -md126 : active raid0 sdb[1] sdc[0] - 1855870976 blocks super external:/md127/0 128k chunks - -md219 : inactive sdb[2](S) sdc[1](S) sda[0](S) - 7932 blocks super external:imsm - -md00 : active raid0 xvdb[0] - 4186624 blocks super 1.2 256k chunks - -md120 : active linear sda1[1] sdb1[0] - 2095104 blocks super 1.2 0k rounding - -md101 : active (read-only) raid0 sdb[2] sdd[1] sdc[0] - 322560 blocks super 1.2 512k chunks - -unused devices: -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/meminfo -Lines: 42 -MemTotal: 15666184 kB -MemFree: 440324 kB -Buffers: 1020128 kB -Cached: 12007640 kB -SwapCached: 0 kB -Active: 6761276 kB -Inactive: 6532708 kB -Active(anon): 267256 kB -Inactive(anon): 268 kB -Active(file): 6494020 kB -Inactive(file): 6532440 kB -Unevictable: 0 kB -Mlocked: 0 kB -SwapTotal: 0 kB -SwapFree: 0 kB -Dirty: 768 kB -Writeback: 0 kB -AnonPages: 266216 kB -Mapped: 44204 kB -Shmem: 1308 kB -Slab: 1807264 kB -SReclaimable: 1738124 kB -SUnreclaim: 69140 kB -KernelStack: 1616 kB -PageTables: 5288 kB -NFS_Unstable: 0 kB -Bounce: 0 kB -WritebackTmp: 0 kB -CommitLimit: 7833092 kB -Committed_AS: 530844 kB -VmallocTotal: 34359738367 kB -VmallocUsed: 36596 kB -VmallocChunk: 34359637840 kB -HardwareCorrupted: 0 kB -AnonHugePages: 12288 kB -HugePages_Total: 0 -HugePages_Free: 0 -HugePages_Rsvd: 0 -HugePages_Surp: 0 -Hugepagesize: 2048 kB -DirectMap4k: 91136 kB -DirectMap2M: 16039936 kB -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/net -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/arp -Lines: 2 -IP address HW type Flags HW address Mask Device -192.168.224.1 0x1 0x2 00:50:56:c0:00:08 * ens33 -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/dev -Lines: 6 -Inter-| Receive | Transmit - face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed -vethf345468: 648 8 0 0 0 0 0 0 438 5 0 0 0 0 0 0 - lo: 1664039048 1566805 0 0 0 0 0 0 1664039048 1566805 0 0 0 0 0 0 -docker0: 2568 38 0 0 0 0 0 0 438 5 0 0 0 0 0 0 - eth0: 874354587 1036395 0 0 0 0 0 0 563352563 732147 0 0 0 0 0 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/ip_vs -Lines: 21 -IP Virtual Server version 1.2.1 (size=4096) -Prot LocalAddress:Port Scheduler Flags - -> RemoteAddress:Port Forward Weight ActiveConn InActConn -TCP C0A80016:0CEA wlc - -> C0A85216:0CEA Tunnel 100 248 2 - -> C0A85318:0CEA Tunnel 100 248 2 - -> C0A85315:0CEA Tunnel 100 248 1 -TCP C0A80039:0CEA wlc - -> C0A85416:0CEA Tunnel 0 0 0 - -> C0A85215:0CEA Tunnel 100 1499 0 - -> C0A83215:0CEA Tunnel 100 1498 0 -TCP C0A80037:0CEA wlc - -> C0A8321A:0CEA Tunnel 0 0 0 - -> C0A83120:0CEA Tunnel 100 0 0 -TCP [2620:0000:0000:0000:0000:0000:0000:0001]:0050 sh - -> [2620:0000:0000:0000:0000:0000:0000:0002]:0050 Route 1 0 0 - -> [2620:0000:0000:0000:0000:0000:0000:0003]:0050 Route 1 0 0 - -> [2620:0000:0000:0000:0000:0000:0000:0004]:0050 Route 1 1 1 -FWM 10001000 wlc - -> C0A8321A:0CEA Route 0 0 1 - -> C0A83215:0CEA Route 0 0 2 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/ip_vs_stats -Lines: 6 - Total Incoming Outgoing Incoming Outgoing - Conns Packets Packets Bytes Bytes - 16AA370 E33656E5 0 51D8C8883AB3 0 - - Conns/s Pkts/s Pkts/s Bytes/s Bytes/s - 4 1FB3C 0 1282A8F 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/protocols -Lines: 14 -protocol size sockets memory press maxhdr slab module cl co di ac io in de sh ss gs se re sp bi br ha uh gp em -PACKET 1344 2 -1 NI 0 no kernel n n n n n n n n n n n n n n n n n n n -PINGv6 1112 0 -1 NI 0 yes kernel y y y n n y n n y y y y n y y y y y n -RAWv6 1112 1 -1 NI 0 yes kernel y y y n y y y n y y y y n y y y y n n -UDPLITEv6 1216 0 57 NI 0 yes kernel y y y n y y y n y y y y n n n y y y n -UDPv6 1216 10 57 NI 0 yes kernel y y y n y y y n y y y y n n n y y y n -TCPv6 2144 1937 1225378 no 320 yes kernel y y y y y y y y y y y y y n y y y y y -UNIX 1024 120 -1 NI 0 yes kernel n n n n n n n n n n n n n n n n n n n -UDP-Lite 1024 0 57 NI 0 yes kernel y y y n y y y n y y y y y n n y y y n -PING 904 0 -1 NI 0 yes kernel y y y n n y n n y y y y n y y y y y n -RAW 912 0 -1 NI 0 yes kernel y y y n y y y n y y y y n y y y y n n -UDP 1024 73 57 NI 0 yes kernel y y y n y y y n y y y y y n n y y y n -TCP 1984 93064 1225378 yes 320 yes kernel y y y y y y y y y y y y y n y y y y y -NETLINK 1040 16 -1 NI 0 no kernel n n n n n n n n n n n n n n n n n n n -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/net/rpc -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/rpc/nfs -Lines: 5 -net 18628 0 18628 6 -rpc 4329785 0 4338291 -proc2 18 2 69 0 0 4410 0 0 0 0 0 0 0 0 0 0 0 99 2 -proc3 22 1 4084749 29200 94754 32580 186 47747 7981 8639 0 6356 0 6962 0 7958 0 0 241 4 4 2 39 -proc4 61 1 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/rpc/nfsd -Lines: 11 -rc 0 6 18622 -fh 0 0 0 0 0 -io 157286400 0 -th 8 0 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 -ra 32 0 0 0 0 0 0 0 0 0 0 0 -net 18628 0 18628 6 -rpc 18628 0 0 0 0 -proc2 18 2 69 0 0 4410 0 0 0 0 0 0 0 0 0 0 0 99 2 -proc3 22 2 112 0 2719 111 0 0 0 0 0 0 0 0 0 0 0 27 216 0 2 1 0 -proc4 2 2 10853 -proc4ops 72 0 0 0 1098 2 0 0 0 0 8179 5896 0 0 0 0 5900 0 0 2 0 2 0 9609 0 2 150 1272 0 0 0 1236 0 0 0 0 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/sockstat -Lines: 6 -sockets: used 1602 -TCP: inuse 35 orphan 0 tw 4 alloc 59 mem 22 -UDP: inuse 12 mem 62 -UDPLITE: inuse 0 -RAW: inuse 0 -FRAG: inuse 0 memory 0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/sockstat6 -Lines: 5 -TCP6: inuse 17 -UDP6: inuse 9 -UDPLITE6: inuse 0 -RAW6: inuse 1 -FRAG6: inuse 0 memory 0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/softnet_stat -Lines: 2 -00015c73 00020e76 F0000769 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 -01663fb2 00000000 000109a4 00000000 00000000 00000000 00000000 00000000 00000000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/softnet_stat.broken -Lines: 1 -00015c73 00020e76 F0000769 00000000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/net/stat -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/stat/arp_cache -Lines: 3 -entries allocs destroys hash_grows lookups hits res_failed rcv_probes_mcast rcv_probes_ucast periodic_gc_runs forced_gc_runs unresolved_discards table_fulls -00000014 00000001 00000002 00000003 00000004 00000005 00000006 00000007 00000008 00000009 0000000a 0000000b 0000000c -00000014 0000000d 0000000e 0000000f 00000010 00000011 00000012 00000013 00000014 00000015 00000016 00000017 00000018 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/stat/ndisc_cache -Lines: 3 -entries allocs destroys hash_grows lookups hits res_failed rcv_probes_mcast rcv_probes_ucast periodic_gc_runs forced_gc_runs unresolved_discards table_fulls -00000024 000000f0 000000f1 000000f2 000000f3 000000f4 000000f5 000000f6 000000f7 000000f8 000000f9 000000fa 000000fb -00000024 000000fc 000000fd 000000fe 000000ff 00000100 00000101 00000102 00000103 00000104 00000105 00000106 00000107 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/tcp -Lines: 4 - sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode - 0: 0500000A:0016 00000000:0000 0A 00000000:00000001 00:00000000 00000000 0 0 2740 1 ffff88003d3af3c0 100 0 0 10 0 - 1: 00000000:0016 00000000:0000 0A 00000001:00000000 00:00000000 00000000 0 0 2740 1 ffff88003d3af3c0 100 0 0 10 0 - 2: 00000000:0016 00000000:0000 0A 00000001:00000001 00:00000000 00000000 0 0 2740 1 ffff88003d3af3c0 100 0 0 10 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/tcp6 -Lines: 3 - sl local_address remote_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode ref pointer drops - 1315: 00000000000000000000000000000000:14EB 00000000000000000000000000000000:0000 07 00000000:00000000 00:00000000 00000000 981 0 21040 2 0000000013726323 0 - 6073: 000080FE00000000FFADE15609667CFE:C781 00000000000000000000000000000000:0000 07 00000000:00000000 00:00000000 00000000 1000 0 11337031 2 00000000b9256fdd 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/udp -Lines: 4 - sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode - 0: 0500000A:0016 00000000:0000 0A 00000000:00000001 00:00000000 00000000 0 0 2740 1 ffff88003d3af3c0 100 0 0 10 0 - 1: 00000000:0016 00000000:0000 0A 00000001:00000000 00:00000000 00000000 0 0 2740 1 ffff88003d3af3c0 100 0 0 10 0 - 2: 00000000:0016 00000000:0000 0A 00000001:00000001 00:00000000 00000000 0 0 2740 1 ffff88003d3af3c0 100 0 0 10 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/udp6 -Lines: 3 - sl local_address remote_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode ref pointer drops - 1315: 00000000000000000000000000000000:14EB 00000000000000000000000000000000:0000 07 00000000:00000000 00:00000000 00000000 981 0 21040 2 0000000013726323 0 - 6073: 000080FE00000000FFADE15609667CFE:C781 00000000000000000000000000000000:0000 07 00000000:00000000 00:00000000 00000000 1000 0 11337031 2 00000000b9256fdd 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/udp_broken -Lines: 2 - sl local_address rem_address st - 1: 00000000:0016 00000000:0000 0A -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/unix -Lines: 6 -Num RefCount Protocol Flags Type St Inode Path -0000000000000000: 00000002 00000000 00010000 0001 01 3442596 /var/run/postgresql/.s.PGSQL.5432 -0000000000000000: 0000000a 00000000 00010000 0005 01 10061 /run/udev/control -0000000000000000: 00000007 00000000 00000000 0002 01 12392 /dev/log -0000000000000000: 00000003 00000000 00000000 0001 03 4787297 /var/run/postgresql/.s.PGSQL.5432 -0000000000000000: 00000003 00000000 00000000 0001 03 5091797 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/unix_without_inode -Lines: 6 -Num RefCount Protocol Flags Type St Path -0000000000000000: 00000002 00000000 00010000 0001 01 /var/run/postgresql/.s.PGSQL.5432 -0000000000000000: 0000000a 00000000 00010000 0005 01 /run/udev/control -0000000000000000: 00000007 00000000 00000000 0002 01 /dev/log -0000000000000000: 00000003 00000000 00000000 0001 03 /var/run/postgresql/.s.PGSQL.5432 -0000000000000000: 00000003 00000000 00000000 0001 03 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/net/xfrm_stat -Lines: 28 -XfrmInError 1 -XfrmInBufferError 2 -XfrmInHdrError 4 -XfrmInNoStates 3 -XfrmInStateProtoError 40 -XfrmInStateModeError 100 -XfrmInStateSeqError 6000 -XfrmInStateExpired 4 -XfrmInStateMismatch 23451 -XfrmInStateInvalid 55555 -XfrmInTmplMismatch 51 -XfrmInNoPols 65432 -XfrmInPolBlock 100 -XfrmInPolError 10000 -XfrmOutError 1000000 -XfrmOutBundleGenError 43321 -XfrmOutBundleCheckError 555 -XfrmOutNoStates 869 -XfrmOutStateProtoError 4542 -XfrmOutStateModeError 4 -XfrmOutStateSeqError 543 -XfrmOutStateExpired 565 -XfrmOutPolBlock 43456 -XfrmOutPolDead 7656 -XfrmOutPolError 1454 -XfrmFwdHdrError 6654 -XfrmOutStateInvalid 28765 -XfrmAcquireError 24532 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/pressure -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/pressure/cpu -Lines: 1 -some avg10=0.10 avg60=2.00 avg300=3.85 total=15 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/pressure/io -Lines: 2 -some avg10=0.10 avg60=2.00 avg300=3.85 total=15 -full avg10=0.20 avg60=3.00 avg300=4.95 total=25 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/pressure/memory -Lines: 2 -some avg10=0.10 avg60=2.00 avg300=3.85 total=15 -full avg10=0.20 avg60=3.00 avg300=4.95 total=25 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/schedstat -Lines: 6 -version 15 -timestamp 15819019232 -cpu0 498494191 0 3533438552 2553969831 3853684107 2465731542 2045936778163039 343796328169361 4767485306 -domain0 00000000,00000003 212499247 210112015 1861015 1860405436 536440 369895 32599 210079416 25368550 24241256 384652 927363878 807233 6366 1647 24239609 2122447165 1886868564 121112060 2848625533 125678146 241025 1032026 1885836538 2545 12 2533 0 0 0 0 0 0 1387952561 21076581 0 -cpu1 518377256 0 4155211005 2778589869 10466382 2867629021 1904686152592476 364107263788241 5145567945 -domain0 00000000,00000003 217653037 215526982 1577949 1580427380 557469 393576 28538 215498444 28721913 27662819 371153 870843407 745912 5523 1639 27661180 2331056874 2107732788 111442342 652402556 123615235 196159 1045245 2106687543 2400 3 2397 0 0 0 0 0 0 1437804657 26220076 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/self -SymlinkTo: 26231 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/slabinfo -Lines: 302 -slabinfo - version: 2.1 -# name : tunables : slabdata -pid_3 375 532 576 28 4 : tunables 0 0 0 : slabdata 19 19 0 -pid_2 3 28 576 28 4 : tunables 0 0 0 : slabdata 1 1 0 -nvidia_p2p_page_cache 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 -nvidia_pte_cache 9022 9152 368 22 2 : tunables 0 0 0 : slabdata 416 416 0 -nvidia_stack_cache 321 326 12624 2 8 : tunables 0 0 0 : slabdata 163 163 0 -kvm_async_pf 0 0 472 34 4 : tunables 0 0 0 : slabdata 0 0 0 -kvm_vcpu 0 0 15552 2 8 : tunables 0 0 0 : slabdata 0 0 0 -kvm_mmu_page_header 0 0 504 32 4 : tunables 0 0 0 : slabdata 0 0 0 -pte_list_desc 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 -x86_emulator 0 0 3024 10 8 : tunables 0 0 0 : slabdata 0 0 0 -x86_fpu 0 0 4608 7 8 : tunables 0 0 0 : slabdata 0 0 0 -iwl_cmd_pool:0000:04:00.0 0 128 512 32 4 : tunables 0 0 0 : slabdata 4 4 0 -ext4_groupinfo_4k 3719 3740 480 34 4 : tunables 0 0 0 : slabdata 110 110 0 -bio-6 32 75 640 25 4 : tunables 0 0 0 : slabdata 3 3 0 -bio-5 16 48 1344 24 8 : tunables 0 0 0 : slabdata 2 2 0 -bio-4 17 92 1408 23 8 : tunables 0 0 0 : slabdata 4 4 0 -fat_inode_cache 0 0 1056 31 8 : tunables 0 0 0 : slabdata 0 0 0 -fat_cache 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 -ovl_aio_req 0 0 512 32 4 : tunables 0 0 0 : slabdata 0 0 0 -ovl_inode 0 0 1000 32 8 : tunables 0 0 0 : slabdata 0 0 0 -squashfs_inode_cache 0 0 1088 30 8 : tunables 0 0 0 : slabdata 0 0 0 -fuse_request 0 0 472 34 4 : tunables 0 0 0 : slabdata 0 0 0 -fuse_inode 0 0 1152 28 8 : tunables 0 0 0 : slabdata 0 0 0 -xfs_dqtrx 0 0 864 37 8 : tunables 0 0 0 : slabdata 0 0 0 -xfs_dquot 0 0 832 39 8 : tunables 0 0 0 : slabdata 0 0 0 -xfs_buf 0 0 768 21 4 : tunables 0 0 0 : slabdata 0 0 0 -xfs_bui_item 0 0 544 30 4 : tunables 0 0 0 : slabdata 0 0 0 -xfs_bud_item 0 0 512 32 4 : tunables 0 0 0 : slabdata 0 0 0 -xfs_cui_item 0 0 768 21 4 : tunables 0 0 0 : slabdata 0 0 0 -xfs_cud_item 0 0 512 32 4 : tunables 0 0 0 : slabdata 0 0 0 -xfs_rui_item 0 0 1024 32 8 : tunables 0 0 0 : slabdata 0 0 0 -xfs_rud_item 0 0 512 32 4 : tunables 0 0 0 : slabdata 0 0 0 -xfs_icr 0 0 520 31 4 : tunables 0 0 0 : slabdata 0 0 0 -xfs_ili 0 0 528 31 4 : tunables 0 0 0 : slabdata 0 0 0 -xfs_inode 0 0 1344 24 8 : tunables 0 0 0 : slabdata 0 0 0 -xfs_efi_item 0 0 768 21 4 : tunables 0 0 0 : slabdata 0 0 0 -xfs_efd_item 0 0 776 21 4 : tunables 0 0 0 : slabdata 0 0 0 -xfs_buf_item 0 0 608 26 4 : tunables 0 0 0 : slabdata 0 0 0 -xf_trans 0 0 568 28 4 : tunables 0 0 0 : slabdata 0 0 0 -xfs_ifork 0 0 376 21 2 : tunables 0 0 0 : slabdata 0 0 0 -xfs_da_state 0 0 816 20 4 : tunables 0 0 0 : slabdata 0 0 0 -xfs_btree_cur 0 0 560 29 4 : tunables 0 0 0 : slabdata 0 0 0 -xfs_bmap_free_item 0 0 400 20 2 : tunables 0 0 0 : slabdata 0 0 0 -xfs_log_ticket 0 0 520 31 4 : tunables 0 0 0 : slabdata 0 0 0 -nfs_direct_cache 0 0 560 29 4 : tunables 0 0 0 : slabdata 0 0 0 -nfs_commit_data 4 28 1152 28 8 : tunables 0 0 0 : slabdata 1 1 0 -nfs_write_data 32 50 1280 25 8 : tunables 0 0 0 : slabdata 2 2 0 -nfs_read_data 0 0 1280 25 8 : tunables 0 0 0 : slabdata 0 0 0 -nfs_inode_cache 0 0 1408 23 8 : tunables 0 0 0 : slabdata 0 0 0 -nfs_page 0 0 512 32 4 : tunables 0 0 0 : slabdata 0 0 0 -rpc_inode_cache 0 0 1024 32 8 : tunables 0 0 0 : slabdata 0 0 0 -rpc_buffers 8 13 2496 13 8 : tunables 0 0 0 : slabdata 1 1 0 -rpc_tasks 8 25 640 25 4 : tunables 0 0 0 : slabdata 1 1 0 -fscache_cookie_jar 1 35 464 35 4 : tunables 0 0 0 : slabdata 1 1 0 -jfs_mp 32 35 464 35 4 : tunables 0 0 0 : slabdata 1 1 0 -jfs_ip 0 0 1592 20 8 : tunables 0 0 0 : slabdata 0 0 0 -reiser_inode_cache 0 0 1096 29 8 : tunables 0 0 0 : slabdata 0 0 0 -btrfs_end_io_wq 0 0 464 35 4 : tunables 0 0 0 : slabdata 0 0 0 -btrfs_prelim_ref 0 0 424 38 4 : tunables 0 0 0 : slabdata 0 0 0 -btrfs_delayed_extent_op 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 -btrfs_delayed_data_ref 0 0 448 36 4 : tunables 0 0 0 : slabdata 0 0 0 -btrfs_delayed_tree_ref 0 0 440 37 4 : tunables 0 0 0 : slabdata 0 0 0 -btrfs_delayed_ref_head 0 0 480 34 4 : tunables 0 0 0 : slabdata 0 0 0 -btrfs_inode_defrag 0 0 400 20 2 : tunables 0 0 0 : slabdata 0 0 0 -btrfs_delayed_node 0 0 648 25 4 : tunables 0 0 0 : slabdata 0 0 0 -btrfs_ordered_extent 0 0 752 21 4 : tunables 0 0 0 : slabdata 0 0 0 -btrfs_extent_map 0 0 480 34 4 : tunables 0 0 0 : slabdata 0 0 0 -btrfs_extent_state 0 0 416 39 4 : tunables 0 0 0 : slabdata 0 0 0 -bio-3 35 92 704 23 4 : tunables 0 0 0 : slabdata 4 4 0 -btrfs_extent_buffer 0 0 600 27 4 : tunables 0 0 0 : slabdata 0 0 0 -btrfs_free_space_bitmap 0 0 12288 2 8 : tunables 0 0 0 : slabdata 0 0 0 -btrfs_free_space 0 0 416 39 4 : tunables 0 0 0 : slabdata 0 0 0 -btrfs_path 0 0 448 36 4 : tunables 0 0 0 : slabdata 0 0 0 -btrfs_trans_handle 0 0 440 37 4 : tunables 0 0 0 : slabdata 0 0 0 -btrfs_inode 0 0 1496 21 8 : tunables 0 0 0 : slabdata 0 0 0 -ext4_inode_cache 84136 84755 1400 23 8 : tunables 0 0 0 : slabdata 3685 3685 0 -ext4_free_data 22 80 392 20 2 : tunables 0 0 0 : slabdata 4 4 0 -ext4_allocation_context 0 70 464 35 4 : tunables 0 0 0 : slabdata 2 2 0 -ext4_prealloc_space 24 74 440 37 4 : tunables 0 0 0 : slabdata 2 2 0 -ext4_system_zone 267 273 376 21 2 : tunables 0 0 0 : slabdata 13 13 0 -ext4_io_end_vec 0 88 368 22 2 : tunables 0 0 0 : slabdata 4 4 0 -ext4_io_end 0 80 400 20 2 : tunables 0 0 0 : slabdata 4 4 0 -ext4_bio_post_read_ctx 128 147 384 21 2 : tunables 0 0 0 : slabdata 7 7 0 -ext4_pending_reservation 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 -ext4_extent_status 79351 79422 376 21 2 : tunables 0 0 0 : slabdata 3782 3782 0 -jbd2_transaction_s 44 100 640 25 4 : tunables 0 0 0 : slabdata 4 4 0 -jbd2_inode 6785 6840 400 20 2 : tunables 0 0 0 : slabdata 342 342 0 -jbd2_journal_handle 0 80 392 20 2 : tunables 0 0 0 : slabdata 4 4 0 -jbd2_journal_head 824 1944 448 36 4 : tunables 0 0 0 : slabdata 54 54 0 -jbd2_revoke_table_s 4 23 352 23 2 : tunables 0 0 0 : slabdata 1 1 0 -jbd2_revoke_record_s 0 156 416 39 4 : tunables 0 0 0 : slabdata 4 4 0 -ext2_inode_cache 0 0 1144 28 8 : tunables 0 0 0 : slabdata 0 0 0 -mbcache 0 0 392 20 2 : tunables 0 0 0 : slabdata 0 0 0 -dm_thin_new_mapping 0 152 424 38 4 : tunables 0 0 0 : slabdata 4 4 0 -dm_snap_pending_exception 0 0 464 35 4 : tunables 0 0 0 : slabdata 0 0 0 -dm_exception 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 -dm_dirty_log_flush_entry 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 -dm_bio_prison_cell_v2 0 0 432 37 4 : tunables 0 0 0 : slabdata 0 0 0 -dm_bio_prison_cell 0 148 432 37 4 : tunables 0 0 0 : slabdata 4 4 0 -kcopyd_job 0 8 3648 8 8 : tunables 0 0 0 : slabdata 1 1 0 -io 0 32 512 32 4 : tunables 0 0 0 : slabdata 1 1 0 -dm_uevent 0 0 3224 10 8 : tunables 0 0 0 : slabdata 0 0 0 -dax_cache 1 28 1152 28 8 : tunables 0 0 0 : slabdata 1 1 0 -aic94xx_ascb 0 0 576 28 4 : tunables 0 0 0 : slabdata 0 0 0 -aic94xx_dma_token 0 0 384 21 2 : tunables 0 0 0 : slabdata 0 0 0 -asd_sas_event 0 0 512 32 4 : tunables 0 0 0 : slabdata 0 0 0 -sas_task 0 0 704 23 4 : tunables 0 0 0 : slabdata 0 0 0 -qla2xxx_srbs 0 0 832 39 8 : tunables 0 0 0 : slabdata 0 0 0 -sd_ext_cdb 2 22 368 22 2 : tunables 0 0 0 : slabdata 1 1 0 -scsi_sense_cache 258 288 512 32 4 : tunables 0 0 0 : slabdata 9 9 0 -virtio_scsi_cmd 64 75 640 25 4 : tunables 0 0 0 : slabdata 3 3 0 -L2TP/IPv6 0 0 1536 21 8 : tunables 0 0 0 : slabdata 0 0 0 -L2TP/IP 0 0 1408 23 8 : tunables 0 0 0 : slabdata 0 0 0 -ip6-frags 0 0 520 31 4 : tunables 0 0 0 : slabdata 0 0 0 -fib6_nodes 5 32 512 32 4 : tunables 0 0 0 : slabdata 1 1 0 -ip6_dst_cache 4 25 640 25 4 : tunables 0 0 0 : slabdata 1 1 0 -ip6_mrt_cache 0 0 576 28 4 : tunables 0 0 0 : slabdata 0 0 0 -PINGv6 0 0 1600 20 8 : tunables 0 0 0 : slabdata 0 0 0 -RAWv6 25 40 1600 20 8 : tunables 0 0 0 : slabdata 2 2 0 -UDPLITEv6 0 0 1728 18 8 : tunables 0 0 0 : slabdata 0 0 0 -UDPv6 3 54 1728 18 8 : tunables 0 0 0 : slabdata 3 3 0 -tw_sock_TCPv6 0 0 576 28 4 : tunables 0 0 0 : slabdata 0 0 0 -request_sock_TCPv6 0 0 632 25 4 : tunables 0 0 0 : slabdata 0 0 0 -TCPv6 0 33 2752 11 8 : tunables 0 0 0 : slabdata 3 3 0 -uhci_urb_priv 0 0 392 20 2 : tunables 0 0 0 : slabdata 0 0 0 -sgpool-128 2 14 4544 7 8 : tunables 0 0 0 : slabdata 2 2 0 -sgpool-64 2 13 2496 13 8 : tunables 0 0 0 : slabdata 1 1 0 -sgpool-32 2 44 1472 22 8 : tunables 0 0 0 : slabdata 2 2 0 -sgpool-16 2 68 960 34 8 : tunables 0 0 0 : slabdata 2 2 0 -sgpool-8 2 46 704 23 4 : tunables 0 0 0 : slabdata 2 2 0 -btree_node 0 0 576 28 4 : tunables 0 0 0 : slabdata 0 0 0 -bfq_io_cq 0 0 488 33 4 : tunables 0 0 0 : slabdata 0 0 0 -bfq_queue 0 0 848 38 8 : tunables 0 0 0 : slabdata 0 0 0 -mqueue_inode_cache 1 24 1344 24 8 : tunables 0 0 0 : slabdata 1 1 0 -isofs_inode_cache 0 0 968 33 8 : tunables 0 0 0 : slabdata 0 0 0 -io_kiocb 0 0 640 25 4 : tunables 0 0 0 : slabdata 0 0 0 -kioctx 0 30 1088 30 8 : tunables 0 0 0 : slabdata 1 1 0 -aio_kiocb 0 28 576 28 4 : tunables 0 0 0 : slabdata 1 1 0 -userfaultfd_ctx_cache 0 0 576 28 4 : tunables 0 0 0 : slabdata 0 0 0 -fanotify_path_event 0 0 392 20 2 : tunables 0 0 0 : slabdata 0 0 0 -fanotify_fid_event 0 0 400 20 2 : tunables 0 0 0 : slabdata 0 0 0 -fsnotify_mark 0 0 408 20 2 : tunables 0 0 0 : slabdata 0 0 0 -dnotify_mark 0 0 416 39 4 : tunables 0 0 0 : slabdata 0 0 0 -dnotify_struct 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 -dio 0 0 1088 30 8 : tunables 0 0 0 : slabdata 0 0 0 -bio-2 4 25 640 25 4 : tunables 0 0 0 : slabdata 1 1 0 -fasync_cache 0 0 384 21 2 : tunables 0 0 0 : slabdata 0 0 0 -audit_tree_mark 0 0 416 39 4 : tunables 0 0 0 : slabdata 0 0 0 -pid_namespace 30 34 480 34 4 : tunables 0 0 0 : slabdata 1 1 0 -posix_timers_cache 0 27 592 27 4 : tunables 0 0 0 : slabdata 1 1 0 -iommu_devinfo 24 32 512 32 4 : tunables 0 0 0 : slabdata 1 1 0 -iommu_domain 10 10 3264 10 8 : tunables 0 0 0 : slabdata 1 1 0 -iommu_iova 8682 8748 448 36 4 : tunables 0 0 0 : slabdata 243 243 0 -UNIX 529 814 1472 22 8 : tunables 0 0 0 : slabdata 37 37 0 -ip4-frags 0 0 536 30 4 : tunables 0 0 0 : slabdata 0 0 0 -ip_mrt_cache 0 0 576 28 4 : tunables 0 0 0 : slabdata 0 0 0 -UDP-Lite 0 0 1536 21 8 : tunables 0 0 0 : slabdata 0 0 0 -tcp_bind_bucket 7 128 512 32 4 : tunables 0 0 0 : slabdata 4 4 0 -inet_peer_cache 0 0 576 28 4 : tunables 0 0 0 : slabdata 0 0 0 -xfrm_dst_cache 0 0 704 23 4 : tunables 0 0 0 : slabdata 0 0 0 -xfrm_state 0 0 1152 28 8 : tunables 0 0 0 : slabdata 0 0 0 -ip_fib_trie 7 21 384 21 2 : tunables 0 0 0 : slabdata 1 1 0 -ip_fib_alias 9 20 392 20 2 : tunables 0 0 0 : slabdata 1 1 0 -ip_dst_cache 27 84 576 28 4 : tunables 0 0 0 : slabdata 3 3 0 -PING 0 0 1408 23 8 : tunables 0 0 0 : slabdata 0 0 0 -RAW 32 46 1408 23 8 : tunables 0 0 0 : slabdata 2 2 0 -UDP 11 168 1536 21 8 : tunables 0 0 0 : slabdata 8 8 0 -tw_sock_TCP 1 56 576 28 4 : tunables 0 0 0 : slabdata 2 2 0 -request_sock_TCP 0 25 632 25 4 : tunables 0 0 0 : slabdata 1 1 0 -TCP 10 60 2624 12 8 : tunables 0 0 0 : slabdata 5 5 0 -hugetlbfs_inode_cache 2 35 928 35 8 : tunables 0 0 0 : slabdata 1 1 0 -dquot 0 0 640 25 4 : tunables 0 0 0 : slabdata 0 0 0 -bio-1 32 46 704 23 4 : tunables 0 0 0 : slabdata 2 2 0 -eventpoll_pwq 409 600 408 20 2 : tunables 0 0 0 : slabdata 30 30 0 -eventpoll_epi 408 672 576 28 4 : tunables 0 0 0 : slabdata 24 24 0 -inotify_inode_mark 58 195 416 39 4 : tunables 0 0 0 : slabdata 5 5 0 -scsi_data_buffer 0 0 360 22 2 : tunables 0 0 0 : slabdata 0 0 0 -bio_crypt_ctx 128 147 376 21 2 : tunables 0 0 0 : slabdata 7 7 0 -request_queue 29 39 2408 13 8 : tunables 0 0 0 : slabdata 3 3 0 -blkdev_ioc 81 148 440 37 4 : tunables 0 0 0 : slabdata 4 4 0 -bio-0 125 200 640 25 4 : tunables 0 0 0 : slabdata 8 8 0 -biovec-max 166 196 4544 7 8 : tunables 0 0 0 : slabdata 28 28 0 -biovec-128 0 52 2496 13 8 : tunables 0 0 0 : slabdata 4 4 0 -biovec-64 0 88 1472 22 8 : tunables 0 0 0 : slabdata 4 4 0 -biovec-16 0 92 704 23 4 : tunables 0 0 0 : slabdata 4 4 0 -bio_integrity_payload 4 28 576 28 4 : tunables 0 0 0 : slabdata 1 1 0 -khugepaged_mm_slot 59 180 448 36 4 : tunables 0 0 0 : slabdata 5 5 0 -ksm_mm_slot 0 0 384 21 2 : tunables 0 0 0 : slabdata 0 0 0 -ksm_stable_node 0 0 400 20 2 : tunables 0 0 0 : slabdata 0 0 0 -ksm_rmap_item 0 0 400 20 2 : tunables 0 0 0 : slabdata 0 0 0 -user_namespace 2 37 864 37 8 : tunables 0 0 0 : slabdata 1 1 0 -uid_cache 5 28 576 28 4 : tunables 0 0 0 : slabdata 1 1 0 -dmaengine-unmap-256 1 13 2496 13 8 : tunables 0 0 0 : slabdata 1 1 0 -dmaengine-unmap-128 1 22 1472 22 8 : tunables 0 0 0 : slabdata 1 1 0 -dmaengine-unmap-16 1 28 576 28 4 : tunables 0 0 0 : slabdata 1 1 0 -dmaengine-unmap-2 1 36 448 36 4 : tunables 0 0 0 : slabdata 1 1 0 -audit_buffer 0 22 360 22 2 : tunables 0 0 0 : slabdata 1 1 0 -sock_inode_cache 663 1170 1216 26 8 : tunables 0 0 0 : slabdata 45 45 0 -skbuff_ext_cache 0 0 576 28 4 : tunables 0 0 0 : slabdata 0 0 0 -skbuff_fclone_cache 1 72 896 36 8 : tunables 0 0 0 : slabdata 2 2 0 -skbuff_head_cache 3 650 640 25 4 : tunables 0 0 0 : slabdata 26 26 0 -configfs_dir_cache 7 38 424 38 4 : tunables 0 0 0 : slabdata 1 1 0 -file_lock_cache 27 116 552 29 4 : tunables 0 0 0 : slabdata 4 4 0 -file_lock_ctx 106 120 392 20 2 : tunables 0 0 0 : slabdata 6 6 0 -fsnotify_mark_connector 52 66 368 22 2 : tunables 0 0 0 : slabdata 3 3 0 -net_namespace 1 6 5312 6 8 : tunables 0 0 0 : slabdata 1 1 0 -task_delay_info 784 1560 416 39 4 : tunables 0 0 0 : slabdata 40 40 0 -taskstats 45 92 688 23 4 : tunables 0 0 0 : slabdata 4 4 0 -proc_dir_entry 678 682 528 31 4 : tunables 0 0 0 : slabdata 22 22 0 -pde_opener 0 189 376 21 2 : tunables 0 0 0 : slabdata 9 9 0 -proc_inode_cache 7150 8250 992 33 8 : tunables 0 0 0 : slabdata 250 250 0 -seq_file 60 735 456 35 4 : tunables 0 0 0 : slabdata 21 21 0 -sigqueue 0 156 416 39 4 : tunables 0 0 0 : slabdata 4 4 0 -bdev_cache 36 78 1216 26 8 : tunables 0 0 0 : slabdata 3 3 0 -shmem_inode_cache 1599 2208 1016 32 8 : tunables 0 0 0 : slabdata 69 69 0 -kernfs_iattrs_cache 1251 1254 424 38 4 : tunables 0 0 0 : slabdata 33 33 0 -kernfs_node_cache 52898 52920 464 35 4 : tunables 0 0 0 : slabdata 1512 1512 0 -mnt_cache 42 46 704 23 4 : tunables 0 0 0 : slabdata 2 2 0 -filp 4314 6371 704 23 4 : tunables 0 0 0 : slabdata 277 277 0 -inode_cache 28695 29505 920 35 8 : tunables 0 0 0 : slabdata 843 843 0 -dentry 166069 169074 528 31 4 : tunables 0 0 0 : slabdata 5454 5454 0 -names_cache 0 35 4544 7 8 : tunables 0 0 0 : slabdata 5 5 0 -hashtab_node 0 0 360 22 2 : tunables 0 0 0 : slabdata 0 0 0 -ebitmap_node 0 0 400 20 2 : tunables 0 0 0 : slabdata 0 0 0 -avtab_extended_perms 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 -avtab_node 0 0 360 22 2 : tunables 0 0 0 : slabdata 0 0 0 -avc_xperms_data 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 -avc_xperms_decision_node 0 0 384 21 2 : tunables 0 0 0 : slabdata 0 0 0 -avc_xperms_node 0 0 392 20 2 : tunables 0 0 0 : slabdata 0 0 0 -avc_node 37 40 408 20 2 : tunables 0 0 0 : slabdata 2 2 0 -iint_cache 0 0 448 36 4 : tunables 0 0 0 : slabdata 0 0 0 -lsm_inode_cache 122284 122340 392 20 2 : tunables 0 0 0 : slabdata 6117 6117 0 -lsm_file_cache 4266 4485 352 23 2 : tunables 0 0 0 : slabdata 195 195 0 -key_jar 8 25 640 25 4 : tunables 0 0 0 : slabdata 1 1 0 -buffer_head 255622 257076 440 37 4 : tunables 0 0 0 : slabdata 6948 6948 0 -uts_namespace 0 0 776 21 4 : tunables 0 0 0 : slabdata 0 0 0 -nsproxy 31 40 408 20 2 : tunables 0 0 0 : slabdata 2 2 0 -vm_area_struct 39115 43214 528 31 4 : tunables 0 0 0 : slabdata 1394 1394 0 -mm_struct 96 529 1408 23 8 : tunables 0 0 0 : slabdata 23 23 0 -fs_cache 102 756 448 36 4 : tunables 0 0 0 : slabdata 21 21 0 -files_cache 102 588 1152 28 8 : tunables 0 0 0 : slabdata 21 21 0 -signal_cache 266 672 1536 21 8 : tunables 0 0 0 : slabdata 32 32 0 -sighand_cache 266 507 2496 13 8 : tunables 0 0 0 : slabdata 39 39 0 -task_struct 783 963 10240 3 8 : tunables 0 0 0 : slabdata 321 321 0 -cred_jar 364 952 576 28 4 : tunables 0 0 0 : slabdata 34 34 0 -anon_vma_chain 63907 67821 416 39 4 : tunables 0 0 0 : slabdata 1739 1739 0 -anon_vma 25891 28899 416 39 4 : tunables 0 0 0 : slabdata 741 741 0 -pid 408 992 512 32 4 : tunables 0 0 0 : slabdata 31 31 0 -Acpi-Operand 6682 6740 408 20 2 : tunables 0 0 0 : slabdata 337 337 0 -Acpi-ParseExt 0 39 416 39 4 : tunables 0 0 0 : slabdata 1 1 0 -Acpi-Parse 0 80 392 20 2 : tunables 0 0 0 : slabdata 4 4 0 -Acpi-State 0 78 416 39 4 : tunables 0 0 0 : slabdata 2 2 0 -Acpi-Namespace 3911 3948 384 21 2 : tunables 0 0 0 : slabdata 188 188 0 -trace_event_file 2638 2660 424 38 4 : tunables 0 0 0 : slabdata 70 70 0 -ftrace_event_field 6592 6594 384 21 2 : tunables 0 0 0 : slabdata 314 314 0 -pool_workqueue 41 64 1024 32 8 : tunables 0 0 0 : slabdata 2 2 0 -radix_tree_node 21638 24045 912 35 8 : tunables 0 0 0 : slabdata 687 687 0 -task_group 48 78 1216 26 8 : tunables 0 0 0 : slabdata 3 3 0 -vmap_area 4411 4680 400 20 2 : tunables 0 0 0 : slabdata 234 234 0 -dma-kmalloc-8k 0 0 24576 1 8 : tunables 0 0 0 : slabdata 0 0 0 -dma-kmalloc-4k 0 0 12288 2 8 : tunables 0 0 0 : slabdata 0 0 0 -dma-kmalloc-2k 0 0 6144 5 8 : tunables 0 0 0 : slabdata 0 0 0 -dma-kmalloc-1k 0 0 3072 10 8 : tunables 0 0 0 : slabdata 0 0 0 -dma-kmalloc-512 0 0 1536 21 8 : tunables 0 0 0 : slabdata 0 0 0 -dma-kmalloc-256 0 0 1024 32 8 : tunables 0 0 0 : slabdata 0 0 0 -dma-kmalloc-128 0 0 640 25 4 : tunables 0 0 0 : slabdata 0 0 0 -dma-kmalloc-64 0 0 512 32 4 : tunables 0 0 0 : slabdata 0 0 0 -dma-kmalloc-32 0 0 416 39 4 : tunables 0 0 0 : slabdata 0 0 0 -dma-kmalloc-16 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 -dma-kmalloc-8 0 0 344 23 2 : tunables 0 0 0 : slabdata 0 0 0 -dma-kmalloc-192 0 0 528 31 4 : tunables 0 0 0 : slabdata 0 0 0 -dma-kmalloc-96 0 0 432 37 4 : tunables 0 0 0 : slabdata 0 0 0 -kmalloc-rcl-8k 0 0 24576 1 8 : tunables 0 0 0 : slabdata 0 0 0 -kmalloc-rcl-4k 0 0 12288 2 8 : tunables 0 0 0 : slabdata 0 0 0 -kmalloc-rcl-2k 0 0 6144 5 8 : tunables 0 0 0 : slabdata 0 0 0 -kmalloc-rcl-1k 0 0 3072 10 8 : tunables 0 0 0 : slabdata 0 0 0 -kmalloc-rcl-512 0 0 1536 21 8 : tunables 0 0 0 : slabdata 0 0 0 -kmalloc-rcl-256 0 0 1024 32 8 : tunables 0 0 0 : slabdata 0 0 0 -kmalloc-rcl-192 0 0 528 31 4 : tunables 0 0 0 : slabdata 0 0 0 -kmalloc-rcl-128 31 75 640 25 4 : tunables 0 0 0 : slabdata 3 3 0 -kmalloc-rcl-96 3371 3626 432 37 4 : tunables 0 0 0 : slabdata 98 98 0 -kmalloc-rcl-64 2080 2272 512 32 4 : tunables 0 0 0 : slabdata 71 71 0 -kmalloc-rcl-32 0 0 416 39 4 : tunables 0 0 0 : slabdata 0 0 0 -kmalloc-rcl-16 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 -kmalloc-rcl-8 0 0 344 23 2 : tunables 0 0 0 : slabdata 0 0 0 -kmalloc-8k 133 140 24576 1 8 : tunables 0 0 0 : slabdata 140 140 0 -kmalloc-4k 403 444 12288 2 8 : tunables 0 0 0 : slabdata 222 222 0 -kmalloc-2k 2391 2585 6144 5 8 : tunables 0 0 0 : slabdata 517 517 0 -kmalloc-1k 2163 2420 3072 10 8 : tunables 0 0 0 : slabdata 242 242 0 -kmalloc-512 2972 3633 1536 21 8 : tunables 0 0 0 : slabdata 173 173 0 -kmalloc-256 1841 1856 1024 32 8 : tunables 0 0 0 : slabdata 58 58 0 -kmalloc-192 2165 2914 528 31 4 : tunables 0 0 0 : slabdata 94 94 0 -kmalloc-128 1137 1175 640 25 4 : tunables 0 0 0 : slabdata 47 47 0 -kmalloc-96 1925 2590 432 37 4 : tunables 0 0 0 : slabdata 70 70 0 -kmalloc-64 9433 10688 512 32 4 : tunables 0 0 0 : slabdata 334 334 0 -kmalloc-32 9098 10062 416 39 4 : tunables 0 0 0 : slabdata 258 258 0 -kmalloc-16 10914 10956 368 22 2 : tunables 0 0 0 : slabdata 498 498 0 -kmalloc-8 7576 7705 344 23 2 : tunables 0 0 0 : slabdata 335 335 0 -kmem_cache_node 904 928 512 32 4 : tunables 0 0 0 : slabdata 29 29 0 -kmem_cache 904 936 832 39 8 : tunables 0 0 0 : slabdata 24 24 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/stat -Lines: 16 -cpu 301854 612 111922 8979004 3552 2 3944 0 0 0 -cpu0 44490 19 21045 1087069 220 1 3410 0 0 0 -cpu1 47869 23 16474 1110787 591 0 46 0 0 0 -cpu2 46504 36 15916 1112321 441 0 326 0 0 0 -cpu3 47054 102 15683 1113230 533 0 60 0 0 0 -cpu4 28413 25 10776 1140321 217 0 8 0 0 0 -cpu5 29271 101 11586 1136270 672 0 30 0 0 0 -cpu6 29152 36 10276 1139721 319 0 29 0 0 0 -cpu7 29098 268 10164 1139282 555 0 31 0 0 0 -intr 8885917 17 0 0 0 0 0 0 0 1 79281 0 0 0 0 0 0 0 231237 0 0 0 0 250586 103 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 223424 190745 13 906 1283803 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -ctxt 38014093 -btime 1418183276 -processes 26442 -procs_running 2 -procs_blocked 1 -softirq 5057579 250191 1481983 1647 211099 186066 0 1783454 622196 12499 508444 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/swaps -Lines: 2 -Filename Type Size Used Priority -/dev/dm-2 partition 131068 176 -2 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/symlinktargets -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/symlinktargets/README -Lines: 2 -This directory contains some empty files that are the symlinks the files in the "fd" directory point to. -They are otherwise ignored by the tests -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/symlinktargets/abc -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/symlinktargets/def -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/symlinktargets/ghi -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/symlinktargets/uvw -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/symlinktargets/xyz -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/sys -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/sys/kernel -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/sys/kernel/random -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/kernel/random/entropy_avail -Lines: 1 -3943 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/kernel/random/poolsize -Lines: 1 -4096 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/kernel/random/urandom_min_reseed_secs -Lines: 1 -60 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/kernel/random/write_wakeup_threshold -Lines: 1 -3072 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/proc/sys/vm -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/admin_reserve_kbytes -Lines: 1 -8192 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/block_dump -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/compact_unevictable_allowed -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/dirty_background_bytes -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/dirty_background_ratio -Lines: 1 -10 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/dirty_bytes -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/dirty_expire_centisecs -Lines: 1 -3000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/dirty_ratio -Lines: 1 -20 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/dirty_writeback_centisecs -Lines: 1 -500 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/dirtytime_expire_seconds -Lines: 1 -43200 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/drop_caches -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/extfrag_threshold -Lines: 1 -500 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/hugetlb_shm_group -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/laptop_mode -Lines: 1 -5 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/legacy_va_layout -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/lowmem_reserve_ratio -Lines: 1 -256 256 32 0 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/max_map_count -Lines: 1 -65530 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/memory_failure_early_kill -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/memory_failure_recovery -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/min_free_kbytes -Lines: 1 -67584 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/min_slab_ratio -Lines: 1 -5 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/min_unmapped_ratio -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/mmap_min_addr -Lines: 1 -65536 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/nr_hugepages -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/nr_hugepages_mempolicy -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/nr_overcommit_hugepages -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/numa_stat -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/numa_zonelist_order -Lines: 1 -Node -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/oom_dump_tasks -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/oom_kill_allocating_task -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/overcommit_kbytes -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/overcommit_memory -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/overcommit_ratio -Lines: 1 -50 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/page-cluster -Lines: 1 -3 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/panic_on_oom -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/percpu_pagelist_fraction -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/stat_interval -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/swappiness -Lines: 1 -60 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/user_reserve_kbytes -Lines: 1 -131072 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/vfs_cache_pressure -Lines: 1 -100 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/watermark_boost_factor -Lines: 1 -15000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/watermark_scale_factor -Lines: 1 -10 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/sys/vm/zone_reclaim_mode -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/zoneinfo -Lines: 262 -Node 0, zone DMA - per-node stats - nr_inactive_anon 230981 - nr_active_anon 547580 - nr_inactive_file 316904 - nr_active_file 346282 - nr_unevictable 115467 - nr_slab_reclaimable 131220 - nr_slab_unreclaimable 47320 - nr_isolated_anon 0 - nr_isolated_file 0 - workingset_nodes 11627 - workingset_refault 466886 - workingset_activate 276925 - workingset_restore 84055 - workingset_nodereclaim 487 - nr_anon_pages 795576 - nr_mapped 215483 - nr_file_pages 761874 - nr_dirty 908 - nr_writeback 0 - nr_writeback_temp 0 - nr_shmem 224925 - nr_shmem_hugepages 0 - nr_shmem_pmdmapped 0 - nr_anon_transparent_hugepages 0 - nr_unstable 0 - nr_vmscan_write 12950 - nr_vmscan_immediate_reclaim 3033 - nr_dirtied 8007423 - nr_written 7752121 - nr_kernel_misc_reclaimable 0 - pages free 3952 - min 33 - low 41 - high 49 - spanned 4095 - present 3975 - managed 3956 - protection: (0, 2877, 7826, 7826, 7826) - nr_free_pages 3952 - nr_zone_inactive_anon 0 - nr_zone_active_anon 0 - nr_zone_inactive_file 0 - nr_zone_active_file 0 - nr_zone_unevictable 0 - nr_zone_write_pending 0 - nr_mlock 0 - nr_page_table_pages 0 - nr_kernel_stack 0 - nr_bounce 0 - nr_zspages 0 - nr_free_cma 0 - numa_hit 1 - numa_miss 0 - numa_foreign 0 - numa_interleave 0 - numa_local 1 - numa_other 0 - pagesets - cpu: 0 - count: 0 - high: 0 - batch: 1 - vm stats threshold: 8 - cpu: 1 - count: 0 - high: 0 - batch: 1 - vm stats threshold: 8 - cpu: 2 - count: 0 - high: 0 - batch: 1 - vm stats threshold: 8 - cpu: 3 - count: 0 - high: 0 - batch: 1 - vm stats threshold: 8 - cpu: 4 - count: 0 - high: 0 - batch: 1 - vm stats threshold: 8 - cpu: 5 - count: 0 - high: 0 - batch: 1 - vm stats threshold: 8 - cpu: 6 - count: 0 - high: 0 - batch: 1 - vm stats threshold: 8 - cpu: 7 - count: 0 - high: 0 - batch: 1 - vm stats threshold: 8 - node_unreclaimable: 0 - start_pfn: 1 -Node 0, zone DMA32 - pages free 204252 - min 19510 - low 21059 - high 22608 - spanned 1044480 - present 759231 - managed 742806 - protection: (0, 0, 4949, 4949, 4949) - nr_free_pages 204252 - nr_zone_inactive_anon 118558 - nr_zone_active_anon 106598 - nr_zone_inactive_file 75475 - nr_zone_active_file 70293 - nr_zone_unevictable 66195 - nr_zone_write_pending 64 - nr_mlock 4 - nr_page_table_pages 1756 - nr_kernel_stack 2208 - nr_bounce 0 - nr_zspages 0 - nr_free_cma 0 - numa_hit 113952967 - numa_miss 0 - numa_foreign 0 - numa_interleave 0 - numa_local 113952967 - numa_other 0 - pagesets - cpu: 0 - count: 345 - high: 378 - batch: 63 - vm stats threshold: 48 - cpu: 1 - count: 356 - high: 378 - batch: 63 - vm stats threshold: 48 - cpu: 2 - count: 325 - high: 378 - batch: 63 - vm stats threshold: 48 - cpu: 3 - count: 346 - high: 378 - batch: 63 - vm stats threshold: 48 - cpu: 4 - count: 321 - high: 378 - batch: 63 - vm stats threshold: 48 - cpu: 5 - count: 316 - high: 378 - batch: 63 - vm stats threshold: 48 - cpu: 6 - count: 373 - high: 378 - batch: 63 - vm stats threshold: 48 - cpu: 7 - count: 339 - high: 378 - batch: 63 - vm stats threshold: 48 - node_unreclaimable: 0 - start_pfn: 4096 -Node 0, zone Normal - pages free 18553 - min 11176 - low 13842 - high 16508 - spanned 1308160 - present 1308160 - managed 1268711 - protection: (0, 0, 0, 0, 0) - nr_free_pages 18553 - nr_zone_inactive_anon 112423 - nr_zone_active_anon 440982 - nr_zone_inactive_file 241429 - nr_zone_active_file 275989 - nr_zone_unevictable 49272 - nr_zone_write_pending 844 - nr_mlock 154 - nr_page_table_pages 9750 - nr_kernel_stack 15136 - nr_bounce 0 - nr_zspages 0 - nr_free_cma 0 - numa_hit 162718019 - numa_miss 0 - numa_foreign 0 - numa_interleave 26812 - numa_local 162718019 - numa_other 0 - pagesets - cpu: 0 - count: 316 - high: 378 - batch: 63 - vm stats threshold: 56 - cpu: 1 - count: 366 - high: 378 - batch: 63 - vm stats threshold: 56 - cpu: 2 - count: 60 - high: 378 - batch: 63 - vm stats threshold: 56 - cpu: 3 - count: 256 - high: 378 - batch: 63 - vm stats threshold: 56 - cpu: 4 - count: 253 - high: 378 - batch: 63 - vm stats threshold: 56 - cpu: 5 - count: 159 - high: 378 - batch: 63 - vm stats threshold: 56 - cpu: 6 - count: 311 - high: 378 - batch: 63 - vm stats threshold: 56 - cpu: 7 - count: 264 - high: 378 - batch: 63 - vm stats threshold: 56 - node_unreclaimable: 0 - start_pfn: 1048576 -Node 0, zone Movable - pages free 0 - min 0 - low 0 - high 0 - spanned 0 - present 0 - managed 0 - protection: (0, 0, 0, 0, 0) -Node 0, zone Device - pages free 0 - min 0 - low 0 - high 0 - spanned 0 - present 0 - managed 0 - protection: (0, 0, 0, 0, 0) -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/block -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/block/dm-0 -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/dm-0/stat -Lines: 1 -6447303 0 710266738 1529043 953216 0 31201176 4557464 0 796160 6088971 -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/block/sda -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/block/sda/queue -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/add_random -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/chunk_sectors -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/dax -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/discard_granularity -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/discard_max_bytes -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/discard_max_hw_bytes -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/discard_zeroes_data -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/fua -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/hw_sector_size -Lines: 1 -512 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/io_poll -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/io_poll_delay -Lines: 1 --1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/io_timeout -Lines: 1 -30000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/block/sda/queue/iosched -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/iosched/back_seek_max -Lines: 1 -16384 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/iosched/back_seek_penalty -Lines: 1 -2 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/iosched/fifo_expire_async -Lines: 1 -250 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/iosched/fifo_expire_sync -Lines: 1 -125 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/iosched/low_latency -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/iosched/max_budget -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/iosched/slice_idle -Lines: 1 -8 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/iosched/slice_idle_us -Lines: 1 -8000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/iosched/strict_guarantees -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/iosched/timeout_sync -Lines: 1 -125 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/iostats -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/logical_block_size -Lines: 1 -512 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/max_discard_segments -Lines: 1 -1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/max_hw_sectors_kb -Lines: 1 -32767 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/max_integrity_segments -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/max_sectors_kb -Lines: 1 -1280 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/max_segment_size -Lines: 1 -65536 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/max_segments -Lines: 1 -168 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/minimum_io_size -Lines: 1 -512 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/nomerges -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/nr_requests -Lines: 1 -64 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/nr_zones -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/optimal_io_size -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/physical_block_size -Lines: 1 -512 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/read_ahead_kb -Lines: 1 -128 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/rotational -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/rq_affinity -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/scheduler -Lines: 1 -mq-deadline kyber [bfq] none -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/wbt_lat_usec -Lines: 1 -75000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/write_cache -Lines: 1 -write back -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/write_same_max_bytes -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/write_zeroes_max_bytes -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/queue/zoned -Lines: 1 -none -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/block/sda/stat -Lines: 1 -9652963 396792 759304206 412943 8422549 6731723 286915323 13947418 0 5658367 19174573 1 2 3 12 -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/drm -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/drm/card0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/drm/card0/device -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/aer_dev_correctable -Lines: 9 -RxErr 0 -BadTLP 0 -BadDLLP 0 -Rollover 0 -Timeout 0 -NonFatalErr 0 -CorrIntErr 0 -HeaderOF 0 -TOTAL_ERR_COR 0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/aer_dev_fatal -Lines: 19 -Undefined 0 -DLP 0 -SDES 0 -TLP 0 -FCP 0 -CmpltTO 0 -CmpltAbrt 0 -UnxCmplt 0 -RxOF 0 -MalfTLP 0 -ECRC 0 -UnsupReq 0 -ACSViol 0 -UncorrIntErr 0 -BlockedTLP 0 -AtomicOpBlocked 0 -TLPBlockedErr 0 -PoisonTLPBlocked 0 -TOTAL_ERR_FATAL 0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/aer_dev_nonfatal -Lines: 19 -Undefined 0 -DLP 0 -SDES 0 -TLP 0 -FCP 0 -CmpltTO 0 -CmpltAbrt 0 -UnxCmplt 0 -RxOF 0 -MalfTLP 0 -ECRC 0 -UnsupReq 0 -ACSViol 0 -UncorrIntErr 0 -BlockedTLP 0 -AtomicOpBlocked 0 -TLPBlockedErr 0 -PoisonTLPBlocked 0 -TOTAL_ERR_NONFATAL 0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/ari_enabled -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/boot_vga -Lines: 1 -1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/broken_parity_status -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/class -Lines: 1 -0x030000 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/consistent_dma_mask_bits -Lines: 1 -44 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/current_link_speed -Lines: 1 -8.0 GT/s PCIe -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/current_link_width -Lines: 1 -16 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/d3cold_allowed -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/device -Lines: 1 -0x687f -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/dma_mask_bits -Lines: 1 -44 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/driver_override -Lines: 1 -(null) -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/enable -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/gpu_busy_percent -Lines: 1 -4 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/irq -Lines: 1 -95 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/local_cpulist -Lines: 1 -0-15 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/local_cpus -Lines: 1 -0000ffff -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/max_link_speed -Lines: 1 -8.0 GT/s PCIe -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/max_link_width -Lines: 1 -16 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/mem_info_gtt_total -Lines: 1 -8573157376 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/mem_info_gtt_used -Lines: 1 -144560128 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/mem_info_vis_vram_total -Lines: 1 -8573157376 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/mem_info_vis_vram_used -Lines: 1 -1490378752 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/mem_info_vram_total -Lines: 1 -8573157376 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/mem_info_vram_used -Lines: 1 -1490378752 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/mem_info_vram_vendor -Lines: 1 -samsung -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/modalias -Lines: 1 -pci:v00001002d0000687Fsv00001043sd000004C4bc03sc00i00 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/msi_bus -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/numa_node -Lines: 1 --1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/pcie_bw -Lines: 1 -6641 815 256 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/pcie_replay_count -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/power_dpm_force_performance_level -Lines: 1 -manual -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/power_dpm_state -Lines: 1 -performance -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/power_state -Lines: 1 -D0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/pp_cur_state -Lines: 1 -1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/pp_dpm_dcefclk -Lines: 5 -0: 600Mhz * -1: 720Mhz -2: 800Mhz -3: 847Mhz -4: 900Mhz -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/pp_dpm_mclk -Lines: 4 -0: 167Mhz * -1: 500Mhz -2: 800Mhz -3: 945Mhz -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/pp_dpm_pcie -Lines: 2 -0: 8.0GT/s, x16 -1: 8.0GT/s, x16 * -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/pp_dpm_sclk -Lines: 8 -0: 852Mhz * -1: 991Mhz -2: 1084Mhz -3: 1138Mhz -4: 1200Mhz -5: 1401Mhz -6: 1536Mhz -7: 1630Mhz -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/pp_dpm_socclk -Lines: 8 -0: 600Mhz -1: 720Mhz * -2: 800Mhz -3: 847Mhz -4: 900Mhz -5: 960Mhz -6: 1028Mhz -7: 1107Mhz -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/pp_features -Lines: 32 -Current ppfeatures: 0x0000000019a1ff4f -FEATURES BITMASK ENABLEMENT -DPM_PREFETCHER 0x0000000000000001 Y -GFXCLK_DPM 0x0000000000000002 Y -UCLK_DPM 0x0000000000000004 Y -SOCCLK_DPM 0x0000000000000008 Y -UVD_DPM 0x0000000000000010 N -VCE_DPM 0x0000000000000020 N -ULV 0x0000000000000040 Y -MP0CLK_DPM 0x0000000000000080 N -LINK_DPM 0x0000000000000100 Y -DCEFCLK_DPM 0x0000000000000200 Y -AVFS 0x0000000000000400 Y -GFXCLK_DS 0x0000000000000800 Y -SOCCLK_DS 0x0000000000001000 Y -LCLK_DS 0x0000000000002000 Y -PPT 0x0000000000004000 Y -TDC 0x0000000000008000 Y -THERMAL 0x0000000000010000 Y -GFX_PER_CU_CG 0x0000000000020000 N -RM 0x0000000000040000 N -DCEFCLK_DS 0x0000000000080000 N -ACDC 0x0000000000100000 N -VR0HOT 0x0000000000200000 Y -VR1HOT 0x0000000000400000 N -FW_CTF 0x0000000000800000 Y -LED_DISPLAY 0x0000000001000000 Y -FAN_CONTROL 0x0000000002000000 N -FAST_PPT 0x0000000004000000 N -DIDT 0x0000000008000000 Y -ACG 0x0000000010000000 Y -PCC_LIMIT 0x0000000020000000 N -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/pp_force_state -Lines: 1 - -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/pp_mclk_od -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/pp_num_states -Lines: 3 -states: 2 -0 boot -1 performance -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/pp_od_clk_voltage -Lines: 18 -OD_SCLK: -0: 852Mhz 800mV -1: 991Mhz 900mV -2: 1084Mhz 950mV -3: 1138Mhz 1000mV -4: 1200Mhz 1050mV -5: 1401Mhz 1100mV -6: 1536Mhz 1150mV -7: 1630Mhz 1200mV -OD_MCLK: -0: 167Mhz 800mV -1: 500Mhz 800mV -2: 800Mhz 950mV -3: 945Mhz 1100mV -OD_RANGE: -SCLK: 852MHz 2400MHz -MCLK: 167MHz 1500MHz -VDDC: 800mV 1200mV -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/pp_power_profile_mode -Lines: 8 -NUM MODE_NAME BUSY_SET_POINT FPS USE_RLC_BUSY MIN_ACTIVE_LEVEL - 0 BOOTUP_DEFAULT : 70 60 0 0 - 1 3D_FULL_SCREEN*: 70 60 1 3 - 2 POWER_SAVING : 90 60 0 0 - 3 VIDEO : 70 60 0 0 - 4 VR : 70 90 0 0 - 5 COMPUTE : 30 60 0 6 - 6 CUSTOM : 0 0 0 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/pp_sclk_od -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/product_name -Lines: 1 - -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/product_number -Lines: 1 - -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/resource -Lines: 13 -0x0000007c00000000 0x0000007dffffffff 0x000000000014220c -0x0000000000000000 0x0000000000000000 0x0000000000000000 -0x0000007e00000000 0x0000007e0fffffff 0x000000000014220c -0x0000000000000000 0x0000000000000000 0x0000000000000000 -0x000000000000d000 0x000000000000d0ff 0x0000000000040101 -0x00000000fcd00000 0x00000000fcd7ffff 0x0000000000040200 -0x00000000fcd80000 0x00000000fcd9ffff 0x0000000000046200 -0x0000000000000000 0x0000000000000000 0x0000000000000000 -0x0000000000000000 0x0000000000000000 0x0000000000000000 -0x0000000000000000 0x0000000000000000 0x0000000000000000 -0x0000000000000000 0x0000000000000000 0x0000000000000000 -0x0000000000000000 0x0000000000000000 0x0000000000000000 -0x0000000000000000 0x0000000000000000 0x0000000000000000 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/revision -Lines: 1 -0xc1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/serial_number -Lines: 1 - -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/subsystem_device -Lines: 1 -0x04c4 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/subsystem_vendor -Lines: 1 -0x1043 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/thermal_throttling_logging -Lines: 1 -0000:09:00.0: thermal throttling logging enabled, with interval 60 seconds -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/uevent -Lines: 6 -DRIVER=amdgpu -PCI_CLASS=30000 -PCI_ID=1002:687F -PCI_SUBSYS_ID=1043:04C4 -PCI_SLOT_NAME=0000:09:00.0 -MODALIAS=pci:v00001002d0000687Fsv00001043sd000004C4bc03sc00i00 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/unique_id -Lines: 1 -0123456789abcdef -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/vbios_version -Lines: 1 -115-D050PIL-100 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/drm/card0/device/vendor -Lines: 1 -0x1002 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/fc_host -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/fc_host/host0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/dev_loss_tmo -Lines: 1 -30 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/fabric_name -Lines: 1 -0x0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/node_name -Lines: 1 -0x2000e0071bce95f2 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/port_id -Lines: 1 -0x000002 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/port_name -Lines: 1 -0x1000e0071bce95f2 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/port_state -Lines: 1 -Online -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/port_type -Lines: 1 -Point-To-Point (direct nport connection) -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/speed -Lines: 1 -16 Gbit -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/fc_host/host0/statistics -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/statistics/dumped_frames -Lines: 1 -0xffffffffffffffff -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/statistics/error_frames -Lines: 1 -0x0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/statistics/fcp_packet_aborts -Lines: 1 -0x13 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/statistics/invalid_crc_count -Lines: 1 -0x2 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/statistics/invalid_tx_word_count -Lines: 1 -0x8 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/statistics/link_failure_count -Lines: 1 -0x9 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/statistics/loss_of_signal_count -Lines: 1 -0x11 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/statistics/loss_of_sync_count -Lines: 1 -0x10 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/statistics/nos_count -Lines: 1 -0x12 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/statistics/rx_frames -Lines: 1 -0x3 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/statistics/rx_words -Lines: 1 -0x4 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/statistics/seconds_since_last_reset -Lines: 1 -0x7 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/statistics/tx_frames -Lines: 1 -0x5 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/statistics/tx_words -Lines: 1 -0x6 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/supported_classes -Lines: 1 -Class 3 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/supported_speeds -Lines: 1 -4 Gbit, 8 Gbit, 16 Gbit -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/fc_host/host0/symbolic_name -Lines: 1 -Emulex SN1100E2P FV12.4.270.3 DV12.4.0.0. HN:gotest. OS:Linux -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/infiniband -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/infiniband/hfi1_0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/hfi1_0/board_id -Lines: 1 -HPE 100Gb 1-port OP101 QSFP28 x16 PCIe Gen3 with Intel Omni-Path Adapter -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/hfi1_0/fw_ver -Lines: 1 -1.27.0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/infiniband/hfi1_0/ports -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/infiniband/hfi1_0/ports/1 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/VL15_dropped -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/excessive_buffer_overrun_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/link_downed -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/link_error_recovery -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/local_link_integrity_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/port_rcv_constraint_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/port_rcv_data -Lines: 1 -345091702026 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/port_rcv_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/port_rcv_packets -Lines: 1 -638036947 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/port_rcv_remote_physical_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/port_rcv_switch_relay_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/port_xmit_constraint_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/port_xmit_data -Lines: 1 -273558326543 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/port_xmit_discards -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/port_xmit_packets -Lines: 1 -568318856 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/port_xmit_wait -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/symbol_error -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/phys_state -Lines: 1 -5: LinkUp -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/rate -Lines: 1 -100 Gb/sec (4X EDR) -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/state -Lines: 1 -4: ACTIVE -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/infiniband/mlx4_0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/board_id -Lines: 1 -SM_1141000001000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/fw_ver -Lines: 1 -2.31.5050 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/hca_type -Lines: 1 -MT4099 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/infiniband/mlx4_0/ports -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/infiniband/mlx4_0/ports/1 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/VL15_dropped -Lines: 1 -0 -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/excessive_buffer_overrun_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/link_downed -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/link_error_recovery -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/local_link_integrity_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/port_rcv_constraint_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/port_rcv_data -Lines: 1 -2221223609 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/port_rcv_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/port_rcv_packets -Lines: 1 -87169372 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/port_rcv_remote_physical_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/port_rcv_switch_relay_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/port_xmit_constraint_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/port_xmit_data -Lines: 1 -26509113295 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/port_xmit_discards -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/port_xmit_packets -Lines: 1 -85734114 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/port_xmit_wait -Lines: 1 -3599 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/symbol_error -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/phys_state -Lines: 1 -5: LinkUp -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/rate -Lines: 1 -40 Gb/sec (4X QDR) -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/state -Lines: 1 -4: ACTIVE -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/infiniband/mlx4_0/ports/2 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/VL15_dropped -Lines: 1 -0 -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/excessive_buffer_overrun_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/link_downed -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/link_error_recovery -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/local_link_integrity_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/port_rcv_constraint_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/port_rcv_data -Lines: 1 -2460436784 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/port_rcv_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/port_rcv_packets -Lines: 1 -89332064 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/port_rcv_remote_physical_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/port_rcv_switch_relay_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/port_xmit_constraint_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/port_xmit_data -Lines: 1 -26540356890 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/port_xmit_discards -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/port_xmit_packets -Lines: 1 -88622850 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/port_xmit_wait -Lines: 1 -3846 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/symbol_error -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/phys_state -Lines: 1 -5: LinkUp -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/rate -Lines: 1 -40 Gb/sec (4X QDR) -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/state -Lines: 1 -4: ACTIVE -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/net -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/net/eth0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/addr_assign_type -Lines: 1 -3 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/addr_len -Lines: 1 -6 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/address -Lines: 1 -01:01:01:01:01:01 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/broadcast -Lines: 1 -ff:ff:ff:ff:ff:ff -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/carrier -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/carrier_changes -Lines: 1 -2 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/carrier_down_count -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/carrier_up_count -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/dev_id -Lines: 1 -0x20 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/device -SymlinkTo: ../../../devices/pci0000:00/0000:00:1f.6/ -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/dormant -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/duplex -Lines: 1 -full -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/flags -Lines: 1 -0x1303 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/ifalias -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/ifindex -Lines: 1 -2 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/iflink -Lines: 1 -2 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/link_mode -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/mtu -Lines: 1 -1500 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/name_assign_type -Lines: 1 -2 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/netdev_group -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/operstate -Lines: 1 -up -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/phys_port_id -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/phys_port_name -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/phys_switch_id -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/speed -Lines: 1 -1000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/tx_queue_len -Lines: 1 -1000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/net/eth0/type -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/nvme -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/nvme/nvme0 -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/nvme/nvme0/firmware_rev -Lines: 1 -1B2QEXP7 -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/nvme/nvme0/model -Lines: 1 -Samsung SSD 970 PRO 512GB -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/nvme/nvme0/serial -Lines: 1 -S680HF8N190894I -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/nvme/nvme0/state -Lines: 1 -live -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/power_supply -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/power_supply/AC -SymlinkTo: ../../devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/power_supply/BAT0 -SymlinkTo: ../../devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/powercap -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/powercap/intel-rapl -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl/enabled -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl/uevent -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/powercap/intel-rapl:0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0/constraint_0_max_power_uw -Lines: 1 -95000000 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0/constraint_0_name -Lines: 1 -long_term -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0/constraint_0_power_limit_uw -Lines: 1 -4090000000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0/constraint_0_time_window_us -Lines: 1 -999424 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0/constraint_1_max_power_uw -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0/constraint_1_name -Lines: 1 -short_term -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0/constraint_1_power_limit_uw -Lines: 1 -4090000000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0/constraint_1_time_window_us -Lines: 1 -2440 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0/enabled -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0/energy_uj -Lines: 1 -240422366267 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0/max_energy_range_uj -Lines: 1 -262143328850 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0/name -Lines: 1 -package-0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0/uevent -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/powercap/intel-rapl:0:0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0:0/constraint_0_max_power_uw -Lines: 0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0:0/constraint_0_name -Lines: 1 -long_term -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0:0/constraint_0_power_limit_uw -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0:0/constraint_0_time_window_us -Lines: 1 -976 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0:0/enabled -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0:0/energy_uj -Lines: 1 -118821284256 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0:0/max_energy_range_uj -Lines: 1 -262143328850 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0:0/name -Lines: 1 -core -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:0:0/uevent -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/powercap/intel-rapl:a -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_0_max_power_uw -Lines: 1 -95000000 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_0_name -Lines: 1 -long_term -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_0_power_limit_uw -Lines: 1 -4090000000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_0_time_window_us -Lines: 1 -999424 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_1_max_power_uw -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_1_name -Lines: 1 -short_term -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_1_power_limit_uw -Lines: 1 -4090000000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_1_time_window_us -Lines: 1 -2440 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:a/enabled -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:a/energy_uj -Lines: 1 -240422366267 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:a/max_energy_range_uj -Lines: 1 -262143328850 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:a/name -Lines: 1 -package-10 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/powercap/intel-rapl:a/uevent -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/scsi_tape -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/scsi_tape/nst0 -SymlinkTo: ../../devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/scsi_tape/nst0a -SymlinkTo: ../../devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0a -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/scsi_tape/nst0l -SymlinkTo: ../../devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0l -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/scsi_tape/nst0m -SymlinkTo: ../../devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0m -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/scsi_tape/st0 -SymlinkTo: ../../devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/scsi_tape/st0a -SymlinkTo: ../../devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0a -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/scsi_tape/st0l -SymlinkTo: ../../devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0l -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/scsi_tape/st0m -SymlinkTo: ../../devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0m -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/thermal -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/thermal/cooling_device0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/thermal/cooling_device0/cur_state -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/thermal/cooling_device0/max_state -Lines: 1 -50 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/thermal/cooling_device0/type -Lines: 1 -Processor -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/thermal/cooling_device1 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/thermal/cooling_device1/cur_state -Lines: 1 --1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/thermal/cooling_device1/max_state -Lines: 1 -27 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/thermal/cooling_device1/type -Lines: 1 -intel_powerclamp -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/thermal/thermal_zone0 -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/thermal/thermal_zone0/policy -Lines: 1 -step_wise -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/thermal/thermal_zone0/temp -Lines: 1 -49925 -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/thermal/thermal_zone0/type -Lines: 1 -bcm2835_thermal -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/class/thermal/thermal_zone1 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/thermal/thermal_zone1/mode -Lines: 1 -enabled -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/thermal/thermal_zone1/passive -Lines: 1 -0 -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/thermal/thermal_zone1/policy -Lines: 1 -step_wise -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/thermal/thermal_zone1/temp -Lines: 1 --44000 -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/class/thermal/thermal_zone1/type -Lines: 1 -acpitz -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/LNXSYSTM:00 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/device -SymlinkTo: ../../../ACPI0003:00 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/online -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/async -Lines: 1 -disabled -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/autosuspend_delay_ms -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/control -Lines: 1 -auto -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/runtime_active_kids -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/runtime_active_time -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/runtime_enabled -Lines: 1 -disabled -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/runtime_status -Lines: 1 -unsupported -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/runtime_suspended_time -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/runtime_usage -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/wakeup -Lines: 1 -enabled -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/wakeup_abort_count -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/wakeup_active -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/wakeup_active_count -Lines: 1 -1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/wakeup_count -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/wakeup_expire_count -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/wakeup_last_time_ms -Lines: 1 -10598 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/wakeup_max_time_ms -Lines: 1 -1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/wakeup_prevent_sleep_time_ms -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/wakeup_total_time_ms -Lines: 1 -1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/subsystem -SymlinkTo: ../../../../../../../../../class/power_supply -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/type -Lines: 1 -Mains -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/uevent -Lines: 2 -POWER_SUPPLY_NAME=AC -POWER_SUPPLY_ONLINE=0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/alarm -Lines: 1 -2369000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/capacity -Lines: 1 -98 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/capacity_level -Lines: 1 -Normal -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/charge_start_threshold -Lines: 1 -95 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/charge_stop_threshold -Lines: 1 -100 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/cycle_count -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/device -SymlinkTo: ../../../PNP0C0A:00 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/energy_full -Lines: 1 -50060000 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/energy_full_design -Lines: 1 -47520000 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/energy_now -Lines: 1 -49450000 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/manufacturer -Lines: 1 -LGC -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/model_name -Lines: 1 -LNV-45N1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power/async -Lines: 1 -disabled -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power/autosuspend_delay_ms -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power/control -Lines: 1 -auto -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power/runtime_active_kids -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power/runtime_active_time -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power/runtime_enabled -Lines: 1 -disabled -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power/runtime_status -Lines: 1 -unsupported -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power/runtime_suspended_time -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power/runtime_usage -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power_now -Lines: 1 -4830000 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/present -Lines: 1 -1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/serial_number -Lines: 1 -38109 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/status -Lines: 1 -Discharging -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/subsystem -SymlinkTo: ../../../../../../../../../class/power_supply -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/technology -Lines: 1 -Li-ion -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/type -Lines: 1 -Battery -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/uevent -Lines: 16 -POWER_SUPPLY_NAME=BAT0 -POWER_SUPPLY_STATUS=Discharging -POWER_SUPPLY_PRESENT=1 -POWER_SUPPLY_TECHNOLOGY=Li-ion -POWER_SUPPLY_CYCLE_COUNT=0 -POWER_SUPPLY_VOLTAGE_MIN_DESIGN=10800000 -POWER_SUPPLY_VOLTAGE_NOW=11750000 -POWER_SUPPLY_POWER_NOW=5064000 -POWER_SUPPLY_ENERGY_FULL_DESIGN=47520000 -POWER_SUPPLY_ENERGY_FULL=47390000 -POWER_SUPPLY_ENERGY_NOW=40730000 -POWER_SUPPLY_CAPACITY=85 -POWER_SUPPLY_CAPACITY_LEVEL=Normal -POWER_SUPPLY_MODEL_NAME=LNV-45N1 -POWER_SUPPLY_MANUFACTURER=LGC -POWER_SUPPLY_SERIAL_NUMBER=38109 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/voltage_min_design -Lines: 1 -10800000 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/voltage_now -Lines: 1 -12229000 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0/stats -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0/stats/in_flight -Lines: 1 -1EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0/stats/io_ns -Lines: 1 -9247011087720EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0/stats/other_cnt -Lines: 1 -1409EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0/stats/read_byte_cnt -Lines: 1 -979383912EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0/stats/read_cnt -Lines: 1 -3741EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0/stats/read_ns -Lines: 1 -33788355744EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0/stats/resid_cnt -Lines: 1 -19EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0/stats/write_byte_cnt -Lines: 1 -1496246784000EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0/stats/write_cnt -Lines: 1 -53772916EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0/stats/write_ns -Lines: 1 -5233597394395EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0a -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0a/stats -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0a/stats/in_flight -Lines: 1 -1EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0a/stats/io_ns -Lines: 1 -9247011087720EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0a/stats/other_cnt -Lines: 1 -1409EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0a/stats/read_byte_cnt -Lines: 1 -979383912EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0a/stats/read_cnt -Lines: 1 -3741EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0a/stats/read_ns -Lines: 1 -33788355744EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0a/stats/resid_cnt -Lines: 1 -19EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0a/stats/write_byte_cnt -Lines: 1 -1496246784000EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0a/stats/write_cnt -Lines: 1 -53772916EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0a/stats/write_ns -Lines: 1 -5233597394395EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0l -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0l/stats -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0l/stats/in_flight -Lines: 1 -1EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0l/stats/io_ns -Lines: 1 -9247011087720EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0l/stats/other_cnt -Lines: 1 -1409EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0l/stats/read_byte_cnt -Lines: 1 -979383912EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0l/stats/read_cnt -Lines: 1 -3741EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0l/stats/read_ns -Lines: 1 -33788355744EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0l/stats/resid_cnt -Lines: 1 -19EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0l/stats/write_byte_cnt -Lines: 1 -1496246784000EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0l/stats/write_cnt -Lines: 1 -53772916EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0l/stats/write_ns -Lines: 1 -5233597394395EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0m -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0m/stats -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0m/stats/in_flight -Lines: 1 -1EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0m/stats/io_ns -Lines: 1 -9247011087720EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0m/stats/other_cnt -Lines: 1 -1409EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0m/stats/read_byte_cnt -Lines: 1 -979383912EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0m/stats/read_cnt -Lines: 1 -3741EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0m/stats/read_ns -Lines: 1 -33788355744EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0m/stats/resid_cnt -Lines: 1 -19EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0m/stats/write_byte_cnt -Lines: 1 -1496246784000EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0m/stats/write_cnt -Lines: 1 -53772916EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0m/stats/write_ns -Lines: 1 -5233597394395EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0/stats -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0/stats/in_flight -Lines: 1 -1EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0/stats/io_ns -Lines: 1 -9247011087720EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0/stats/other_cnt -Lines: 1 -1409EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0/stats/read_byte_cnt -Lines: 1 -979383912EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0/stats/read_cnt -Lines: 1 -3741EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0/stats/read_ns -Lines: 1 -33788355744EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0/stats/resid_cnt -Lines: 1 -19EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0/stats/write_byte_cnt -Lines: 1 -1496246784000EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0/stats/write_cnt -Lines: 1 -53772916EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0/stats/write_ns -Lines: 1 -5233597394395EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0a -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0a/stats -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0a/stats/in_flight -Lines: 1 -1EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0a/stats/io_ns -Lines: 1 -9247011087720EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0a/stats/other_cnt -Lines: 1 -1409EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0a/stats/read_byte_cnt -Lines: 1 -979383912EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0a/stats/read_cnt -Lines: 1 -3741EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0a/stats/read_ns -Lines: 1 -33788355744EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0a/stats/resid_cnt -Lines: 1 -19EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0a/stats/write_byte_cnt -Lines: 1 -1496246784000EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0a/stats/write_cnt -Lines: 1 -53772916EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0a/stats/write_ns -Lines: 1 -5233597394395EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0l -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0l/stats -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0l/stats/in_flight -Lines: 1 -1EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0l/stats/io_ns -Lines: 1 -9247011087720EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0l/stats/other_cnt -Lines: 1 -1409EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0l/stats/read_byte_cnt -Lines: 1 -979383912EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0l/stats/read_cnt -Lines: 1 -3741EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0l/stats/read_ns -Lines: 1 -33788355744EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0l/stats/resid_cnt -Lines: 1 -19EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0l/stats/write_byte_cnt -Lines: 1 -1496246784000EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0l/stats/write_cnt -Lines: 1 -53772916EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0l/stats/write_ns -Lines: 1 -5233597394395EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0m -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0m/stats -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0m/stats/in_flight -Lines: 1 -1EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0m/stats/io_ns -Lines: 1 -9247011087720EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0m/stats/other_cnt -Lines: 1 -1409EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0m/stats/read_byte_cnt -Lines: 1 -979383912EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0m/stats/read_cnt -Lines: 1 -3741EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0m/stats/read_ns -Lines: 1 -33788355744EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0m/stats/resid_cnt -Lines: 1 -19EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0m/stats/write_byte_cnt -Lines: 1 -1496246784000EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0m/stats/write_cnt -Lines: 1 -53772916EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0m/stats/write_ns -Lines: 1 -5233597394395EOF -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/dirty_data -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_day -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_day/bypassed -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_day/cache_bypass_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_day/cache_bypass_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_day/cache_hit_ratio -Lines: 1 -100 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_day/cache_hits -Lines: 1 -289 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_day/cache_miss_collisions -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_day/cache_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_day/cache_readaheads -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_five_minute -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_five_minute/bypassed -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_five_minute/cache_bypass_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_five_minute/cache_bypass_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_five_minute/cache_hit_ratio -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_five_minute/cache_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_five_minute/cache_miss_collisions -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_five_minute/cache_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_five_minute/cache_readaheads -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_hour -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_hour/bypassed -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_hour/cache_bypass_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_hour/cache_bypass_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_hour/cache_hit_ratio -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_hour/cache_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_hour/cache_miss_collisions -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_hour/cache_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_hour/cache_readaheads -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_total -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_total/bypassed -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_total/cache_bypass_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_total/cache_bypass_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_total/cache_hit_ratio -Lines: 1 -100 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_total/cache_hits -Lines: 1 -546 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_total/cache_miss_collisions -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_total/cache_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata4/host3/target3:0:0/3:0:0:0/block/sdb/bcache/stats_total/cache_readaheads -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata5 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata5/host4 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata5/host4/target4:0:0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata5/host4/target4:0:0/4:0:0:0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata5/host4/target4:0:0/4:0:0:0/block -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata5/host4/target4:0:0/4:0:0:0/block/sdc -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata5/host4/target4:0:0/4:0:0:0/block/sdc/bcache -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata5/host4/target4:0:0/4:0:0:0/block/sdc/bcache/io_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata5/host4/target4:0:0/4:0:0:0/block/sdc/bcache/metadata_written -Lines: 1 -512 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata5/host4/target4:0:0/4:0:0:0/block/sdc/bcache/priority_stats -Lines: 5 -Unused: 99% -Metadata: 0% -Average: 10473 -Sectors per Q: 64 -Quantiles: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 20946 20946 20946 20946 20946 20946 20946 20946 20946 20946 20946 20946 20946 20946 20946 20946] -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:0d.0/ata5/host4/target4:0:0/4:0:0:0/block/sdc/bcache/written -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/pci0000:00/0000:00:1f.6 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/ari_enabled -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/broken_parity_status -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/class -Lines: 1 -0x020000 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/consistent_dma_mask_bits -Lines: 1 -64 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/d3cold_allowed -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/device -Lines: 1 -0x15d7 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/dma_mask_bits -Lines: 1 -64 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/driver_override -Lines: 1 -(null) -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/enable -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/irq -Lines: 1 -140 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/local_cpulist -Lines: 1 -0-7 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/local_cpus -Lines: 1 -ff -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/modalias -Lines: 1 -pci:v00008086d000015D7sv000017AAsd0000225Abc02sc00i00 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/msi_bus -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/numa_node -Lines: 1 --1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/resource -Lines: 13 -0x00000000ec200000 0x00000000ec21ffff 0x0000000000040200 -0x0000000000000000 0x0000000000000000 0x0000000000000000 -0x0000000000000000 0x0000000000000000 0x0000000000000000 -0x0000000000000000 0x0000000000000000 0x0000000000000000 -0x0000000000000000 0x0000000000000000 0x0000000000000000 -0x0000000000000000 0x0000000000000000 0x0000000000000000 -0x0000000000000000 0x0000000000000000 0x0000000000000000 -0x0000000000000000 0x0000000000000000 0x0000000000000000 -0x0000000000000000 0x0000000000000000 0x0000000000000000 -0x0000000000000000 0x0000000000000000 0x0000000000000000 -0x0000000000000000 0x0000000000000000 0x0000000000000000 -0x0000000000000000 0x0000000000000000 0x0000000000000000 -0x0000000000000000 0x0000000000000000 0x0000000000000000 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/revision -Lines: 1 -0x21 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/subsystem_device -Lines: 1 -0x225a -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/subsystem_vendor -Lines: 1 -0x17aa -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/uevent -Lines: 6 -DRIVER=e1000e -PCI_CLASS=20000 -PCI_ID=8086:15D7 -PCI_SUBSYS_ID=17AA:225A -PCI_SLOT_NAME=0000:00:1f.6 -MODALIAS=pci:v00008086d000015D7sv000017AAsd0000225Abc02sc00i00 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/pci0000:00/0000:00:1f.6/vendor -Lines: 1 -0x8086 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/rbd -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/rbd/0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/rbd/0/name -Lines: 1 -demo -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/rbd/0/pool -Lines: 1 -iscsi-images -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/rbd/1 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/rbd/1/name -Lines: 1 -wrong -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/rbd/1/pool -Lines: 1 -wrong-images -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system/clocksource -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system/clocksource/clocksource0 -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/clocksource/clocksource0/available_clocksource -Lines: 1 -tsc hpet acpi_pm -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/clocksource/clocksource0/current_clocksource -Lines: 1 -tsc -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system/cpu -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system/cpu/cpu0 -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu0/cpufreq -SymlinkTo: ../cpufreq/policy0 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system/cpu/cpu0/thermal_throttle -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu0/thermal_throttle/core_throttle_count -Lines: 1 -10084 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu0/thermal_throttle/package_throttle_count -Lines: 1 -34818 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system/cpu/cpu0/topology -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu0/topology/core_id -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu0/topology/core_siblings -Lines: 1 -ff -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu0/topology/core_siblings_list -Lines: 1 -0-7 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu0/topology/physical_package_id -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu0/topology/thread_siblings -Lines: 1 -11 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu0/topology/thread_siblings_list -Lines: 1 -0,4 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system/cpu/cpu1 -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system/cpu/cpu1/cpufreq -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/cpufreq/cpuinfo_cur_freq -Lines: 1 -1200195 -Mode: 400 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/cpufreq/cpuinfo_max_freq -Lines: 1 -3300000 -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/cpufreq/cpuinfo_min_freq -Lines: 1 -1200000 -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/cpufreq/cpuinfo_transition_latency -Lines: 1 -4294967295 -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/cpufreq/related_cpus -Lines: 1 -1 -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/cpufreq/scaling_available_governors -Lines: 1 -performance powersave -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/cpufreq/scaling_driver -Lines: 1 -intel_pstate -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/cpufreq/scaling_governor -Lines: 1 -powersave -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/cpufreq/scaling_max_freq -Lines: 1 -3300000 -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/cpufreq/scaling_min_freq -Lines: 1 -1200000 -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/cpufreq/scaling_setspeed -Lines: 1 - -Mode: 664 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system/cpu/cpu1/thermal_throttle -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/thermal_throttle/core_throttle_count -Lines: 1 -523 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/thermal_throttle/package_throttle_count -Lines: 1 -34818 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system/cpu/cpu1/topology -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/topology/core_id -Lines: 1 -1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/topology/core_siblings -Lines: 1 -ff -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/topology/core_siblings_list -Lines: 1 -0-7 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/topology/physical_package_id -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/topology/thread_siblings -Lines: 1 -22 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpu1/topology/thread_siblings_list -Lines: 1 -1,5 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system/cpu/cpufreq -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system/cpu/cpufreq/policy0 -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpufreq/policy0/affected_cpus -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpufreq/policy0/cpuinfo_max_freq -Lines: 1 -2400000 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpufreq/policy0/cpuinfo_min_freq -Lines: 1 -800000 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpufreq/policy0/cpuinfo_transition_latency -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpufreq/policy0/related_cpus -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpufreq/policy0/scaling_available_governors -Lines: 1 -performance powersave -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpufreq/policy0/scaling_cur_freq -Lines: 1 -1219917 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpufreq/policy0/scaling_driver -Lines: 1 -intel_pstate -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpufreq/policy0/scaling_governor -Lines: 1 -powersave -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpufreq/policy0/scaling_max_freq -Lines: 1 -2400000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpufreq/policy0/scaling_min_freq -Lines: 1 -800000 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/cpu/cpufreq/policy0/scaling_setspeed -Lines: 1 - -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system/cpu/cpufreq/policy1 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system/node -Mode: 775 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system/node/node1 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/node/node1/vmstat -Lines: 6 -nr_free_pages 1 -nr_zone_inactive_anon 2 -nr_zone_active_anon 3 -nr_zone_inactive_file 4 -nr_zone_active_file 5 -nr_zone_unevictable 6 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/devices/system/node/node2 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/devices/system/node/node2/vmstat -Lines: 6 -nr_free_pages 7 -nr_zone_inactive_anon 8 -nr_zone_active_anon 9 -nr_zone_inactive_file 10 -nr_zone_active_file 11 -nr_zone_unevictable 12 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/bcache -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/average_key_size -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0 -Mode: 777 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/dirty_data -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_day -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_day/bypassed -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_day/cache_bypass_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_day/cache_bypass_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_day/cache_hit_ratio -Lines: 1 -100 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_day/cache_hits -Lines: 1 -289 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_day/cache_miss_collisions -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_day/cache_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_day/cache_readaheads -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_five_minute -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_five_minute/bypassed -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_five_minute/cache_bypass_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_five_minute/cache_bypass_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_five_minute/cache_hit_ratio -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_five_minute/cache_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_five_minute/cache_miss_collisions -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_five_minute/cache_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_five_minute/cache_readaheads -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_hour -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_hour/bypassed -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_hour/cache_bypass_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_hour/cache_bypass_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_hour/cache_hit_ratio -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_hour/cache_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_hour/cache_miss_collisions -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_hour/cache_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_hour/cache_readaheads -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_total -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_total/bypassed -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_total/cache_bypass_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_total/cache_bypass_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_total/cache_hit_ratio -Lines: 1 -100 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_total/cache_hits -Lines: 1 -546 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_total/cache_miss_collisions -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_total/cache_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/stats_total/cache_readaheads -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/bdev0/writeback_rate_debug -Lines: 7 -rate: 1.1M/sec -dirty: 20.4G -target: 20.4G -proportional: 427.5k -integral: 790.0k -change: 321.5k/sec -next io: 17ms -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/btree_cache_size -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/cache0 -Mode: 777 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/cache0/io_errors -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/cache0/metadata_written -Lines: 1 -512 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/cache0/priority_stats -Lines: 5 -Unused: 99% -Metadata: 0% -Average: 10473 -Sectors per Q: 64 -Quantiles: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 20946 20946 20946 20946 20946 20946 20946 20946 20946 20946 20946 20946 20946 20946 20946 20946] -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/cache0/written -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/cache_available_percent -Lines: 1 -100 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/congested -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/internal -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/internal/active_journal_entries -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/internal/btree_nodes -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/internal/btree_read_average_duration_us -Lines: 1 -1305 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/internal/cache_read_races -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/root_usage_percent -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_day -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_day/bypassed -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_day/cache_bypass_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_day/cache_bypass_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_day/cache_hit_ratio -Lines: 1 -100 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_day/cache_hits -Lines: 1 -289 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_day/cache_miss_collisions -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_day/cache_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_day/cache_readaheads -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_five_minute -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_five_minute/bypassed -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_five_minute/cache_bypass_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_five_minute/cache_bypass_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_five_minute/cache_hit_ratio -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_five_minute/cache_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_five_minute/cache_miss_collisions -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_five_minute/cache_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_five_minute/cache_readaheads -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_hour -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_hour/bypassed -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_hour/cache_bypass_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_hour/cache_bypass_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_hour/cache_hit_ratio -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_hour/cache_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_hour/cache_miss_collisions -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_hour/cache_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_hour/cache_readaheads -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_total -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_total/bypassed -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_total/cache_bypass_hits -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_total/cache_bypass_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_total/cache_hit_ratio -Lines: 1 -100 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_total/cache_hits -Lines: 1 -546 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_total/cache_miss_collisions -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_total/cache_misses -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/stats_total/cache_readaheads -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/bcache/deaddd54-c735-46d5-868e-f331c5fd7c74/tree_depth -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/data -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/data/bytes_may_use -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/data/bytes_pinned -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/data/bytes_readonly -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/data/bytes_reserved -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/data/bytes_used -Lines: 1 -808189952 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/data/disk_total -Lines: 1 -2147483648 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/data/disk_used -Lines: 1 -808189952 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/data/flags -Lines: 1 -1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/data/raid0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/data/raid0/total_bytes -Lines: 1 -2147483648 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/data/raid0/used_bytes -Lines: 1 -808189952 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/data/total_bytes -Lines: 1 -2147483648 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/data/total_bytes_pinned -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/global_rsv_reserved -Lines: 1 -16777216 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/global_rsv_size -Lines: 1 -16777216 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/metadata -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/metadata/bytes_may_use -Lines: 1 -16777216 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/metadata/bytes_pinned -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/metadata/bytes_readonly -Lines: 1 -131072 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/metadata/bytes_reserved -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/metadata/bytes_used -Lines: 1 -933888 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/metadata/disk_total -Lines: 1 -2147483648 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/metadata/disk_used -Lines: 1 -1867776 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/metadata/flags -Lines: 1 -4 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/metadata/raid1 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/metadata/raid1/total_bytes -Lines: 1 -1073741824 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/metadata/raid1/used_bytes -Lines: 1 -933888 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/metadata/total_bytes -Lines: 1 -1073741824 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/metadata/total_bytes_pinned -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/system -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/system/bytes_may_use -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/system/bytes_pinned -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/system/bytes_readonly -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/system/bytes_reserved -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/system/bytes_used -Lines: 1 -16384 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/system/disk_total -Lines: 1 -16777216 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/system/disk_used -Lines: 1 -32768 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/system/flags -Lines: 1 -2 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/system/raid1 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/system/raid1/total_bytes -Lines: 1 -8388608 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/system/raid1/used_bytes -Lines: 1 -16384 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/system/total_bytes -Lines: 1 -8388608 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/allocation/system/total_bytes_pinned -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/clone_alignment -Lines: 1 -4096 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/devices -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/devices/loop25 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/devices/loop25/size -Lines: 1 -20971520 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/devices/loop26 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/devices/loop26/size -Lines: 1 -20971520 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/features -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/features/big_metadata -Lines: 1 -1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/features/extended_iref -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/features/mixed_backref -Lines: 1 -1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/features/skinny_metadata -Lines: 1 -1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/label -Lines: 1 -fixture -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/metadata_uuid -Lines: 1 -0abb23a9-579b-43e6-ad30-227ef47fcb9d -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/nodesize -Lines: 1 -16384 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/quota_override -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/0abb23a9-579b-43e6-ad30-227ef47fcb9d/sectorsize -Lines: 1 -4096 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/data -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/data/bytes_may_use -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/data/bytes_pinned -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/data/bytes_readonly -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/data/bytes_reserved -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/data/bytes_used -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/data/disk_total -Lines: 1 -644087808 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/data/disk_used -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/data/flags -Lines: 1 -1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/data/raid5 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/data/raid5/total_bytes -Lines: 1 -644087808 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/data/raid5/used_bytes -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/data/total_bytes -Lines: 1 -644087808 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/data/total_bytes_pinned -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/global_rsv_reserved -Lines: 1 -16777216 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/global_rsv_size -Lines: 1 -16777216 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/metadata -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/metadata/bytes_may_use -Lines: 1 -16777216 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/metadata/bytes_pinned -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/metadata/bytes_readonly -Lines: 1 -262144 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/metadata/bytes_reserved -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/metadata/bytes_used -Lines: 1 -114688 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/metadata/disk_total -Lines: 1 -429391872 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/metadata/disk_used -Lines: 1 -114688 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/metadata/flags -Lines: 1 -4 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/metadata/raid6 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/metadata/raid6/total_bytes -Lines: 1 -429391872 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/metadata/raid6/used_bytes -Lines: 1 -114688 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/metadata/total_bytes -Lines: 1 -429391872 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/metadata/total_bytes_pinned -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/system -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/system/bytes_may_use -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/system/bytes_pinned -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/system/bytes_readonly -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/system/bytes_reserved -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/system/bytes_used -Lines: 1 -16384 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/system/disk_total -Lines: 1 -16777216 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/system/disk_used -Lines: 1 -16384 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/system/flags -Lines: 1 -2 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/system/raid6 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/system/raid6/total_bytes -Lines: 1 -16777216 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/system/raid6/used_bytes -Lines: 1 -16384 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/system/total_bytes -Lines: 1 -16777216 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/allocation/system/total_bytes_pinned -Lines: 1 -0 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/clone_alignment -Lines: 1 -4096 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/devices -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/devices/loop22 -SymlinkTo: ../../../../devices/virtual/block/loop22 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/devices/loop23 -SymlinkTo: ../../../../devices/virtual/block/loop23 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/devices/loop24 -SymlinkTo: ../../../../devices/virtual/block/loop24 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/devices/loop25 -SymlinkTo: ../../../../devices/virtual/block/loop25 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/features -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/features/big_metadata -Lines: 1 -1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/features/extended_iref -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/features/mixed_backref -Lines: 1 -1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/features/raid56 -Lines: 1 -1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/features/skinny_metadata -Lines: 1 -1 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/label -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/metadata_uuid -Lines: 1 -7f07c59f-6136-449c-ab87-e1cf2328731b -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/nodesize -Lines: 1 -16384 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/quota_override -Lines: 1 -0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/btrfs/7f07c59f-6136-449c-ab87-e1cf2328731b/sectorsize -Lines: 1 -4096 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/xfs -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/xfs/sda1 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/xfs/sda1/stats -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/xfs/sda1/stats/stats -Lines: 1 -extent_alloc 1 0 0 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/xfs/sdb1 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/fs/xfs/sdb1/stats -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/fs/xfs/sdb1/stats/stats -Lines: 1 -extent_alloc 2 0 0 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/core -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/core/fileio_0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/core/fileio_1 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/core/fileio_1/file_lio_1G -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/core/fileio_1/file_lio_1G/enable -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/core/fileio_1/file_lio_1G/udev_path -Lines: 1 -/home/iscsi/file_back_1G -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/core/iblock_0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/core/iblock_0/block_lio_rbd1 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/core/iblock_0/block_lio_rbd1/enable -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/core/iblock_0/block_lio_rbd1/udev_path -Lines: 1 -/dev/rbd1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/core/rbd_0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/core/rbd_0/iscsi-images-demo -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/core/rbd_0/iscsi-images-demo/enable -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/core/rbd_0/iscsi-images-demo/udev_path -Lines: 1 -/dev/rbd/iscsi-images/demo -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/core/rd_mcp_119 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/core/rd_mcp_119/ramdisk_lio_1G -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/core/rd_mcp_119/ramdisk_lio_1G/enable -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/core/rd_mcp_119/ramdisk_lio_1G/udev_path -Lines: 0 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.8888bbbbddd0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.8888bbbbddd0/tpgt_1 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.8888bbbbddd0/tpgt_1/enable -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.8888bbbbddd0/tpgt_1/lun -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.8888bbbbddd0/tpgt_1/lun/lun_0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.8888bbbbddd0/tpgt_1/lun/lun_0/7f4a4eb56d -SymlinkTo: ../../../../../../target/core/rd_mcp_119/ramdisk_lio_1G -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.8888bbbbddd0/tpgt_1/lun/lun_0/statistics -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.8888bbbbddd0/tpgt_1/lun/lun_0/statistics/scsi_tgt_port -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.8888bbbbddd0/tpgt_1/lun/lun_0/statistics/scsi_tgt_port/in_cmds -Lines: 1 -204950 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.8888bbbbddd0/tpgt_1/lun/lun_0/statistics/scsi_tgt_port/read_mbytes -Lines: 1 -10325 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.8888bbbbddd0/tpgt_1/lun/lun_0/statistics/scsi_tgt_port/write_mbytes -Lines: 1 -40325 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.abcd1abcd2ab -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.abcd1abcd2ab/tpgt_1 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.abcd1abcd2ab/tpgt_1/enable -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.abcd1abcd2ab/tpgt_1/lun -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.abcd1abcd2ab/tpgt_1/lun/lun_0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.abcd1abcd2ab/tpgt_1/lun/lun_0/795b7c7026 -SymlinkTo: ../../../../../../target/core/iblock_0/block_lio_rbd1 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.abcd1abcd2ab/tpgt_1/lun/lun_0/statistics -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.abcd1abcd2ab/tpgt_1/lun/lun_0/statistics/scsi_tgt_port -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.abcd1abcd2ab/tpgt_1/lun/lun_0/statistics/scsi_tgt_port/in_cmds -Lines: 1 -104950 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.abcd1abcd2ab/tpgt_1/lun/lun_0/statistics/scsi_tgt_port/read_mbytes -Lines: 1 -20095 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.abcd1abcd2ab/tpgt_1/lun/lun_0/statistics/scsi_tgt_port/write_mbytes -Lines: 1 -71235 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:dev.rbd0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:dev.rbd0/tpgt_1 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:dev.rbd0/tpgt_1/enable -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:dev.rbd0/tpgt_1/lun -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:dev.rbd0/tpgt_1/lun/lun_0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:dev.rbd0/tpgt_1/lun/lun_0/fff5e16686 -SymlinkTo: ../../../../../../target/core/fileio_1/file_lio_1G -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:dev.rbd0/tpgt_1/lun/lun_0/statistics -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:dev.rbd0/tpgt_1/lun/lun_0/statistics/scsi_tgt_port -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:dev.rbd0/tpgt_1/lun/lun_0/statistics/scsi_tgt_port/in_cmds -Lines: 1 -301950 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:dev.rbd0/tpgt_1/lun/lun_0/statistics/scsi_tgt_port/read_mbytes -Lines: 1 -10195 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:dev.rbd0/tpgt_1/lun/lun_0/statistics/scsi_tgt_port/write_mbytes -Lines: 1 -30195 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:sn.ramdemo -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:sn.ramdemo/tpgt_1 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:sn.ramdemo/tpgt_1/enable -Lines: 1 -1 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:sn.ramdemo/tpgt_1/lun -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:sn.ramdemo/tpgt_1/lun/lun_0 -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:sn.ramdemo/tpgt_1/lun/lun_0/eba1edf893 -SymlinkTo: ../../../../../../target/core/rbd_0/iscsi-images-demo -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:sn.ramdemo/tpgt_1/lun/lun_0/statistics -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Directory: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:sn.ramdemo/tpgt_1/lun/lun_0/statistics/scsi_tgt_port -Mode: 755 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:sn.ramdemo/tpgt_1/lun/lun_0/statistics/scsi_tgt_port/in_cmds -Lines: 1 -1234 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:sn.ramdemo/tpgt_1/lun/lun_0/statistics/scsi_tgt_port/read_mbytes -Lines: 1 -1504 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:sn.ramdemo/tpgt_1/lun/lun_0/statistics/scsi_tgt_port/write_mbytes -Lines: 1 -4733 -Mode: 644 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/prometheus/procfs/internal/fs/fs.go b/vendor/github.com/prometheus/procfs/internal/fs/fs.go index 0040753b1c..3c18c7610e 100644 --- a/vendor/github.com/prometheus/procfs/internal/fs/fs.go +++ b/vendor/github.com/prometheus/procfs/internal/fs/fs.go @@ -26,7 +26,7 @@ const ( // DefaultSysMountPoint is the common mount point of the sys filesystem. DefaultSysMountPoint = "/sys" - // DefaultConfigfsMountPoint is the common mount point of the configfs + // DefaultConfigfsMountPoint is the common mount point of the configfs. DefaultConfigfsMountPoint = "/sys/kernel/config" ) diff --git a/vendor/github.com/prometheus/procfs/internal/util/parse.go b/vendor/github.com/prometheus/procfs/internal/util/parse.go index 22cb07a6bb..b030951faf 100644 --- a/vendor/github.com/prometheus/procfs/internal/util/parse.go +++ b/vendor/github.com/prometheus/procfs/internal/util/parse.go @@ -14,7 +14,7 @@ package util import ( - "io/ioutil" + "os" "strconv" "strings" ) @@ -66,7 +66,7 @@ func ParsePInt64s(ss []string) ([]*int64, error) { // ReadUintFromFile reads a file and attempts to parse a uint64 from it. func ReadUintFromFile(path string) (uint64, error) { - data, err := ioutil.ReadFile(path) + data, err := os.ReadFile(path) if err != nil { return 0, err } @@ -75,7 +75,7 @@ func ReadUintFromFile(path string) (uint64, error) { // ReadIntFromFile reads a file and attempts to parse a int64 from it. func ReadIntFromFile(path string) (int64, error) { - data, err := ioutil.ReadFile(path) + data, err := os.ReadFile(path) if err != nil { return 0, err } diff --git a/vendor/github.com/prometheus/procfs/internal/util/readfile.go b/vendor/github.com/prometheus/procfs/internal/util/readfile.go index 8051161b2a..71b7a70ebd 100644 --- a/vendor/github.com/prometheus/procfs/internal/util/readfile.go +++ b/vendor/github.com/prometheus/procfs/internal/util/readfile.go @@ -15,17 +15,16 @@ package util import ( "io" - "io/ioutil" "os" ) -// ReadFileNoStat uses ioutil.ReadAll to read contents of entire file. -// This is similar to ioutil.ReadFile but without the call to os.Stat, because +// ReadFileNoStat uses io.ReadAll to read contents of entire file. +// This is similar to os.ReadFile but without the call to os.Stat, because // many files in /proc and /sys report incorrect file sizes (either 0 or 4096). -// Reads a max file size of 512kB. For files larger than this, a scanner +// Reads a max file size of 1024kB. For files larger than this, a scanner // should be used. func ReadFileNoStat(filename string) ([]byte, error) { - const maxBufferSize = 1024 * 512 + const maxBufferSize = 1024 * 1024 f, err := os.Open(filename) if err != nil { @@ -34,5 +33,5 @@ func ReadFileNoStat(filename string) ([]byte, error) { defer f.Close() reader := io.LimitReader(f, maxBufferSize) - return ioutil.ReadAll(reader) + return io.ReadAll(reader) } diff --git a/vendor/github.com/prometheus/procfs/internal/util/sysreadfile.go b/vendor/github.com/prometheus/procfs/internal/util/sysreadfile.go index c07de0b6c9..1ab875ceec 100644 --- a/vendor/github.com/prometheus/procfs/internal/util/sysreadfile.go +++ b/vendor/github.com/prometheus/procfs/internal/util/sysreadfile.go @@ -11,7 +11,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build linux,!appengine +//go:build (linux || darwin) && !appengine +// +build linux darwin +// +build !appengine package util @@ -21,7 +23,7 @@ import ( "syscall" ) -// SysReadFile is a simplified ioutil.ReadFile that invokes syscall.Read directly. +// SysReadFile is a simplified os.ReadFile that invokes syscall.Read directly. // https://github.com/prometheus/node_exporter/pull/728/files // // Note that this function will not read files larger than 128 bytes. @@ -33,7 +35,7 @@ func SysReadFile(file string) (string, error) { defer f.Close() // On some machines, hwmon drivers are broken and return EAGAIN. This causes - // Go's ioutil.ReadFile implementation to poll forever. + // Go's os.ReadFile implementation to poll forever. // // Since we either want to read data or bail immediately, do the simplest // possible read using syscall directly. diff --git a/vendor/github.com/prometheus/procfs/internal/util/sysreadfile_compat.go b/vendor/github.com/prometheus/procfs/internal/util/sysreadfile_compat.go index bd55b45377..1d86f5e63f 100644 --- a/vendor/github.com/prometheus/procfs/internal/util/sysreadfile_compat.go +++ b/vendor/github.com/prometheus/procfs/internal/util/sysreadfile_compat.go @@ -11,7 +11,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build linux,appengine !linux +//go:build (linux && appengine) || (!linux && !darwin) +// +build linux,appengine !linux,!darwin package util diff --git a/vendor/github.com/prometheus/procfs/ipvs.go b/vendor/github.com/prometheus/procfs/ipvs.go index 89e447746c..391c07957e 100644 --- a/vendor/github.com/prometheus/procfs/ipvs.go +++ b/vendor/github.com/prometheus/procfs/ipvs.go @@ -20,7 +20,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "net" "os" "strconv" @@ -84,7 +83,7 @@ func parseIPVSStats(r io.Reader) (IPVSStats, error) { stats IPVSStats ) - statContent, err := ioutil.ReadAll(r) + statContent, err := io.ReadAll(r) if err != nil { return IPVSStats{}, err } diff --git a/vendor/github.com/prometheus/procfs/kernel_random.go b/vendor/github.com/prometheus/procfs/kernel_random.go index da3a941d60..db88566bdf 100644 --- a/vendor/github.com/prometheus/procfs/kernel_random.go +++ b/vendor/github.com/prometheus/procfs/kernel_random.go @@ -11,6 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !windows // +build !windows package procfs diff --git a/vendor/github.com/prometheus/procfs/loadavg.go b/vendor/github.com/prometheus/procfs/loadavg.go index 0cce190ec2..0096cafbdf 100644 --- a/vendor/github.com/prometheus/procfs/loadavg.go +++ b/vendor/github.com/prometheus/procfs/loadavg.go @@ -21,7 +21,7 @@ import ( "github.com/prometheus/procfs/internal/util" ) -// LoadAvg represents an entry in /proc/loadavg +// LoadAvg represents an entry in /proc/loadavg. type LoadAvg struct { Load1 float64 Load5 float64 diff --git a/vendor/github.com/prometheus/procfs/mdstat.go b/vendor/github.com/prometheus/procfs/mdstat.go index f0b9e5f75a..a95c889cb9 100644 --- a/vendor/github.com/prometheus/procfs/mdstat.go +++ b/vendor/github.com/prometheus/procfs/mdstat.go @@ -15,7 +15,7 @@ package procfs import ( "fmt" - "io/ioutil" + "os" "regexp" "strconv" "strings" @@ -64,7 +64,7 @@ type MDStat struct { // structs containing the relevant info. More information available here: // https://raid.wiki.kernel.org/index.php/Mdstat func (fs FS) MDStat() ([]MDStat, error) { - data, err := ioutil.ReadFile(fs.proc.Path("mdstat")) + data, err := os.ReadFile(fs.proc.Path("mdstat")) if err != nil { return nil, err } @@ -166,8 +166,12 @@ func parseMDStat(mdStatData []byte) ([]MDStat, error) { } func evalStatusLine(deviceLine, statusLine string) (active, total, down, size int64, err error) { + statusFields := strings.Fields(statusLine) + if len(statusFields) < 1 { + return 0, 0, 0, 0, fmt.Errorf("unexpected statusLine %q", statusLine) + } - sizeStr := strings.Fields(statusLine)[0] + sizeStr := statusFields[0] size, err = strconv.ParseInt(sizeStr, 10, 64) if err != nil { return 0, 0, 0, 0, fmt.Errorf("unexpected statusLine %q: %w", statusLine, err) diff --git a/vendor/github.com/prometheus/procfs/mountstats.go b/vendor/github.com/prometheus/procfs/mountstats.go index f7a828bb1d..0c482c18cc 100644 --- a/vendor/github.com/prometheus/procfs/mountstats.go +++ b/vendor/github.com/prometheus/procfs/mountstats.go @@ -284,7 +284,8 @@ func parseMountStats(r io.Reader) ([]*Mount, error) { } // parseMount parses an entry in /proc/[pid]/mountstats in the format: -// device [device] mounted on [mount] with fstype [type] +// +// device [device] mounted on [mount] with fstype [type] func parseMount(ss []string) (*Mount, error) { if len(ss) < deviceEntryLen { return nil, fmt.Errorf("invalid device entry: %v", ss) diff --git a/vendor/github.com/prometheus/procfs/net_conntrackstat.go b/vendor/github.com/prometheus/procfs/net_conntrackstat.go index 9964a3600b..8300daca05 100644 --- a/vendor/github.com/prometheus/procfs/net_conntrackstat.go +++ b/vendor/github.com/prometheus/procfs/net_conntrackstat.go @@ -25,7 +25,7 @@ import ( ) // A ConntrackStatEntry represents one line from net/stat/nf_conntrack -// and contains netfilter conntrack statistics at one CPU core +// and contains netfilter conntrack statistics at one CPU core. type ConntrackStatEntry struct { Entries uint64 Found uint64 @@ -38,12 +38,12 @@ type ConntrackStatEntry struct { SearchRestart uint64 } -// ConntrackStat retrieves netfilter's conntrack statistics, split by CPU cores +// ConntrackStat retrieves netfilter's conntrack statistics, split by CPU cores. func (fs FS) ConntrackStat() ([]ConntrackStatEntry, error) { return readConntrackStat(fs.proc.Path("net", "stat", "nf_conntrack")) } -// Parses a slice of ConntrackStatEntries from the given filepath +// Parses a slice of ConntrackStatEntries from the given filepath. func readConntrackStat(path string) ([]ConntrackStatEntry, error) { // This file is small and can be read with one syscall. b, err := util.ReadFileNoStat(path) @@ -61,7 +61,7 @@ func readConntrackStat(path string) ([]ConntrackStatEntry, error) { return stat, nil } -// Reads the contents of a conntrack statistics file and parses a slice of ConntrackStatEntries +// Reads the contents of a conntrack statistics file and parses a slice of ConntrackStatEntries. func parseConntrackStat(r io.Reader) ([]ConntrackStatEntry, error) { var entries []ConntrackStatEntry @@ -79,7 +79,7 @@ func parseConntrackStat(r io.Reader) ([]ConntrackStatEntry, error) { return entries, nil } -// Parses a ConntrackStatEntry from given array of fields +// Parses a ConntrackStatEntry from given array of fields. func parseConntrackStatEntry(fields []string) (*ConntrackStatEntry, error) { if len(fields) != 17 { return nil, fmt.Errorf("invalid conntrackstat entry, missing fields") @@ -143,7 +143,7 @@ func parseConntrackStatEntry(fields []string) (*ConntrackStatEntry, error) { return entry, nil } -// Parses a uint64 from given hex in string +// Parses a uint64 from given hex in string. func parseConntrackStatField(field string) (uint64, error) { val, err := strconv.ParseUint(field, 16, 64) if err != nil { diff --git a/vendor/github.com/prometheus/procfs/net_dev.go b/vendor/github.com/prometheus/procfs/net_dev.go index 47a710befb..e66208aa05 100644 --- a/vendor/github.com/prometheus/procfs/net_dev.go +++ b/vendor/github.com/prometheus/procfs/net_dev.go @@ -87,17 +87,17 @@ func newNetDev(file string) (NetDev, error) { // parseLine parses a single line from the /proc/net/dev file. Header lines // must be filtered prior to calling this method. func (netDev NetDev) parseLine(rawLine string) (*NetDevLine, error) { - parts := strings.SplitN(rawLine, ":", 2) - if len(parts) != 2 { + idx := strings.LastIndex(rawLine, ":") + if idx == -1 { return nil, errors.New("invalid net/dev line, missing colon") } - fields := strings.Fields(strings.TrimSpace(parts[1])) + fields := strings.Fields(strings.TrimSpace(rawLine[idx+1:])) var err error line := &NetDevLine{} // Interface Name - line.Name = strings.TrimSpace(parts[0]) + line.Name = strings.TrimSpace(rawLine[:idx]) if line.Name == "" { return nil, errors.New("invalid net/dev line, empty interface name") } diff --git a/vendor/github.com/prometheus/procfs/net_ip_socket.go b/vendor/github.com/prometheus/procfs/net_ip_socket.go index 8c9ee3de87..7fd57d7f46 100644 --- a/vendor/github.com/prometheus/procfs/net_ip_socket.go +++ b/vendor/github.com/prometheus/procfs/net_ip_socket.go @@ -34,7 +34,7 @@ const ( readLimit = 4294967296 // Byte -> 4 GiB ) -// this contains generic data structures for both udp and tcp sockets +// This contains generic data structures for both udp and tcp sockets. type ( // NetIPSocket represents the contents of /proc/net/{t,u}dp{,6} file without the header. NetIPSocket []*netIPSocketLine diff --git a/vendor/github.com/prometheus/procfs/net_protocols.go b/vendor/github.com/prometheus/procfs/net_protocols.go index 8c6de3791b..374b6f73f8 100644 --- a/vendor/github.com/prometheus/procfs/net_protocols.go +++ b/vendor/github.com/prometheus/procfs/net_protocols.go @@ -23,7 +23,7 @@ import ( "github.com/prometheus/procfs/internal/util" ) -// NetProtocolStats stores the contents from /proc/net/protocols +// NetProtocolStats stores the contents from /proc/net/protocols. type NetProtocolStats map[string]NetProtocolStatLine // NetProtocolStatLine contains a single line parsed from /proc/net/protocols. We @@ -41,7 +41,7 @@ type NetProtocolStatLine struct { Capabilities NetProtocolCapabilities } -// NetProtocolCapabilities contains a list of capabilities for each protocol +// NetProtocolCapabilities contains a list of capabilities for each protocol. type NetProtocolCapabilities struct { Close bool // 8 Connect bool // 9 diff --git a/vendor/github.com/prometheus/procfs/net_softnet.go b/vendor/github.com/prometheus/procfs/net_softnet.go index 46f12c61d3..06b7b8f216 100644 --- a/vendor/github.com/prometheus/procfs/net_softnet.go +++ b/vendor/github.com/prometheus/procfs/net_softnet.go @@ -27,17 +27,30 @@ import ( // For the proc file format details, // See: // * Linux 2.6.23 https://elixir.bootlin.com/linux/v2.6.23/source/net/core/dev.c#L2343 -// * Linux 4.17 https://elixir.bootlin.com/linux/v4.17/source/net/core/net-procfs.c#L162 -// and https://elixir.bootlin.com/linux/v4.17/source/include/linux/netdevice.h#L2810. +// * Linux 2.6.39 https://elixir.bootlin.com/linux/v2.6.39/source/net/core/dev.c#L4086 +// * Linux 4.18 https://elixir.bootlin.com/linux/v4.18/source/net/core/net-procfs.c#L162 +// * Linux 5.14 https://elixir.bootlin.com/linux/v5.14/source/net/core/net-procfs.c#L169 -// SoftnetStat contains a single row of data from /proc/net/softnet_stat +// SoftnetStat contains a single row of data from /proc/net/softnet_stat. type SoftnetStat struct { - // Number of processed packets + // Number of processed packets. Processed uint32 - // Number of dropped packets + // Number of dropped packets. Dropped uint32 - // Number of times processing packets ran out of quota + // Number of times processing packets ran out of quota. TimeSqueezed uint32 + // Number of collision occur while obtaining device lock while transmitting. + CPUCollision uint32 + // Number of times cpu woken up received_rps. + ReceivedRps uint32 + // number of times flow limit has been reached. + FlowLimitCount uint32 + // Softnet backlog status. + SoftnetBacklogLen uint32 + // CPU id owning this softnet_data. + Index uint32 + // softnet_data's Width. + Width int } var softNetProcFile = "net/softnet_stat" @@ -66,22 +79,57 @@ func parseSoftnet(r io.Reader) ([]SoftnetStat, error) { for s.Scan() { columns := strings.Fields(s.Text()) width := len(columns) + softnetStat := SoftnetStat{} if width < minColumns { return nil, fmt.Errorf("%d columns were detected, but at least %d were expected", width, minColumns) } - // We only parse the first three columns at the moment. - us, err := parseHexUint32s(columns[0:3]) - if err != nil { - return nil, err + // Linux 2.6.23 https://elixir.bootlin.com/linux/v2.6.23/source/net/core/dev.c#L2347 + if width >= minColumns { + us, err := parseHexUint32s(columns[0:9]) + if err != nil { + return nil, err + } + + softnetStat.Processed = us[0] + softnetStat.Dropped = us[1] + softnetStat.TimeSqueezed = us[2] + softnetStat.CPUCollision = us[8] + } + + // Linux 2.6.39 https://elixir.bootlin.com/linux/v2.6.39/source/net/core/dev.c#L4086 + if width >= 10 { + us, err := parseHexUint32s(columns[9:10]) + if err != nil { + return nil, err + } + + softnetStat.ReceivedRps = us[0] } - stats = append(stats, SoftnetStat{ - Processed: us[0], - Dropped: us[1], - TimeSqueezed: us[2], - }) + // Linux 4.18 https://elixir.bootlin.com/linux/v4.18/source/net/core/net-procfs.c#L162 + if width >= 11 { + us, err := parseHexUint32s(columns[10:11]) + if err != nil { + return nil, err + } + + softnetStat.FlowLimitCount = us[0] + } + + // Linux 5.14 https://elixir.bootlin.com/linux/v5.14/source/net/core/net-procfs.c#L169 + if width >= 13 { + us, err := parseHexUint32s(columns[11:13]) + if err != nil { + return nil, err + } + + softnetStat.SoftnetBacklogLen = us[0] + softnetStat.Index = us[1] + } + softnetStat.Width = width + stats = append(stats, softnetStat) } return stats, nil diff --git a/vendor/github.com/prometheus/procfs/net_xfrm.go b/vendor/github.com/prometheus/procfs/net_xfrm.go new file mode 100644 index 0000000000..f9d9d243db --- /dev/null +++ b/vendor/github.com/prometheus/procfs/net_xfrm.go @@ -0,0 +1,189 @@ +// Copyright 2017 Prometheus Team +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package procfs + +import ( + "bufio" + "fmt" + "os" + "strconv" + "strings" +) + +// XfrmStat models the contents of /proc/net/xfrm_stat. +type XfrmStat struct { + // All errors which are not matched by other + XfrmInError int + // No buffer is left + XfrmInBufferError int + // Header Error + XfrmInHdrError int + // No state found + // i.e. either inbound SPI, address, or IPSEC protocol at SA is wrong + XfrmInNoStates int + // Transformation protocol specific error + // e.g. SA Key is wrong + XfrmInStateProtoError int + // Transformation mode specific error + XfrmInStateModeError int + // Sequence error + // e.g. sequence number is out of window + XfrmInStateSeqError int + // State is expired + XfrmInStateExpired int + // State has mismatch option + // e.g. UDP encapsulation type is mismatched + XfrmInStateMismatch int + // State is invalid + XfrmInStateInvalid int + // No matching template for states + // e.g. Inbound SAs are correct but SP rule is wrong + XfrmInTmplMismatch int + // No policy is found for states + // e.g. Inbound SAs are correct but no SP is found + XfrmInNoPols int + // Policy discards + XfrmInPolBlock int + // Policy error + XfrmInPolError int + // All errors which are not matched by others + XfrmOutError int + // Bundle generation error + XfrmOutBundleGenError int + // Bundle check error + XfrmOutBundleCheckError int + // No state was found + XfrmOutNoStates int + // Transformation protocol specific error + XfrmOutStateProtoError int + // Transportation mode specific error + XfrmOutStateModeError int + // Sequence error + // i.e sequence number overflow + XfrmOutStateSeqError int + // State is expired + XfrmOutStateExpired int + // Policy discads + XfrmOutPolBlock int + // Policy is dead + XfrmOutPolDead int + // Policy Error + XfrmOutPolError int + // Forward routing of a packet is not allowed + XfrmFwdHdrError int + // State is invalid, perhaps expired + XfrmOutStateInvalid int + // State hasn’t been fully acquired before use + XfrmAcquireError int +} + +// NewXfrmStat reads the xfrm_stat statistics. +func NewXfrmStat() (XfrmStat, error) { + fs, err := NewFS(DefaultMountPoint) + if err != nil { + return XfrmStat{}, err + } + + return fs.NewXfrmStat() +} + +// NewXfrmStat reads the xfrm_stat statistics from the 'proc' filesystem. +func (fs FS) NewXfrmStat() (XfrmStat, error) { + file, err := os.Open(fs.proc.Path("net/xfrm_stat")) + if err != nil { + return XfrmStat{}, err + } + defer file.Close() + + var ( + x = XfrmStat{} + s = bufio.NewScanner(file) + ) + + for s.Scan() { + fields := strings.Fields(s.Text()) + + if len(fields) != 2 { + return XfrmStat{}, fmt.Errorf("couldn't parse %q line %q", file.Name(), s.Text()) + } + + name := fields[0] + value, err := strconv.Atoi(fields[1]) + if err != nil { + return XfrmStat{}, err + } + + switch name { + case "XfrmInError": + x.XfrmInError = value + case "XfrmInBufferError": + x.XfrmInBufferError = value + case "XfrmInHdrError": + x.XfrmInHdrError = value + case "XfrmInNoStates": + x.XfrmInNoStates = value + case "XfrmInStateProtoError": + x.XfrmInStateProtoError = value + case "XfrmInStateModeError": + x.XfrmInStateModeError = value + case "XfrmInStateSeqError": + x.XfrmInStateSeqError = value + case "XfrmInStateExpired": + x.XfrmInStateExpired = value + case "XfrmInStateInvalid": + x.XfrmInStateInvalid = value + case "XfrmInTmplMismatch": + x.XfrmInTmplMismatch = value + case "XfrmInNoPols": + x.XfrmInNoPols = value + case "XfrmInPolBlock": + x.XfrmInPolBlock = value + case "XfrmInPolError": + x.XfrmInPolError = value + case "XfrmOutError": + x.XfrmOutError = value + case "XfrmInStateMismatch": + x.XfrmInStateMismatch = value + case "XfrmOutBundleGenError": + x.XfrmOutBundleGenError = value + case "XfrmOutBundleCheckError": + x.XfrmOutBundleCheckError = value + case "XfrmOutNoStates": + x.XfrmOutNoStates = value + case "XfrmOutStateProtoError": + x.XfrmOutStateProtoError = value + case "XfrmOutStateModeError": + x.XfrmOutStateModeError = value + case "XfrmOutStateSeqError": + x.XfrmOutStateSeqError = value + case "XfrmOutStateExpired": + x.XfrmOutStateExpired = value + case "XfrmOutPolBlock": + x.XfrmOutPolBlock = value + case "XfrmOutPolDead": + x.XfrmOutPolDead = value + case "XfrmOutPolError": + x.XfrmOutPolError = value + case "XfrmFwdHdrError": + x.XfrmFwdHdrError = value + case "XfrmOutStateInvalid": + x.XfrmOutStateInvalid = value + case "XfrmAcquireError": + x.XfrmAcquireError = value + } + + } + + return x, s.Err() +} diff --git a/vendor/github.com/prometheus/procfs/netstat.go b/vendor/github.com/prometheus/procfs/netstat.go index 94d892f113..5cc40aef55 100644 --- a/vendor/github.com/prometheus/procfs/netstat.go +++ b/vendor/github.com/prometheus/procfs/netstat.go @@ -15,19 +15,20 @@ package procfs import ( "bufio" + "io" "os" "path/filepath" "strconv" "strings" ) -// NetStat contains statistics for all the counters from one file +// NetStat contains statistics for all the counters from one file. type NetStat struct { - Filename string Stats map[string][]uint64 + Filename string } -// NetStat retrieves stats from /proc/net/stat/ +// NetStat retrieves stats from `/proc/net/stat/`. func (fs FS) NetStat() ([]NetStat, error) { statFiles, err := filepath.Glob(fs.proc.Path("net/stat/*")) if err != nil { @@ -42,27 +43,43 @@ func (fs FS) NetStat() ([]NetStat, error) { return nil, err } - netStatFile := NetStat{ - Filename: filepath.Base(filePath), - Stats: make(map[string][]uint64), + procNetstat, err := parseNetstat(file) + if err != nil { + return nil, err + } + procNetstat.Filename = filepath.Base(filePath) + + netStatsTotal = append(netStatsTotal, procNetstat) + } + return netStatsTotal, nil +} + +// parseNetstat parses the metrics from `/proc/net/stat/` file +// and returns a NetStat structure. +func parseNetstat(r io.Reader) (NetStat, error) { + var ( + scanner = bufio.NewScanner(r) + netStat = NetStat{ + Stats: make(map[string][]uint64), } - scanner := bufio.NewScanner(file) - scanner.Scan() - // First string is always a header for stats - var headers []string - headers = append(headers, strings.Fields(scanner.Text())...) + ) + + scanner.Scan() - // Other strings represent per-CPU counters - for scanner.Scan() { - for num, counter := range strings.Fields(scanner.Text()) { - value, err := strconv.ParseUint(counter, 16, 32) - if err != nil { - return nil, err - } - netStatFile.Stats[headers[num]] = append(netStatFile.Stats[headers[num]], value) + // First string is always a header for stats + var headers []string + headers = append(headers, strings.Fields(scanner.Text())...) + + // Other strings represent per-CPU counters + for scanner.Scan() { + for num, counter := range strings.Fields(scanner.Text()) { + value, err := strconv.ParseUint(counter, 16, 64) + if err != nil { + return NetStat{}, err } + netStat.Stats[headers[num]] = append(netStat.Stats[headers[num]], value) } - netStatsTotal = append(netStatsTotal, netStatFile) } - return netStatsTotal, nil + + return netStat, nil } diff --git a/vendor/github.com/prometheus/procfs/proc.go b/vendor/github.com/prometheus/procfs/proc.go index 28f696803f..c30223af72 100644 --- a/vendor/github.com/prometheus/procfs/proc.go +++ b/vendor/github.com/prometheus/procfs/proc.go @@ -16,7 +16,7 @@ package procfs import ( "bytes" "fmt" - "io/ioutil" + "io" "os" "strconv" "strings" @@ -82,7 +82,7 @@ func (fs FS) Self() (Proc, error) { // NewProc returns a process for the given pid. // -// Deprecated: use fs.Proc() instead +// Deprecated: Use fs.Proc() instead. func (fs FS) NewProc(pid int) (Proc, error) { return fs.Proc(pid) } @@ -142,7 +142,7 @@ func (p Proc) Wchan() (string, error) { } defer f.Close() - data, err := ioutil.ReadAll(f) + data, err := io.ReadAll(f) if err != nil { return "", err } @@ -185,7 +185,7 @@ func (p Proc) Cwd() (string, error) { return wd, err } -// RootDir returns the absolute path to the process's root directory (as set by chroot) +// RootDir returns the absolute path to the process's root directory (as set by chroot). func (p Proc) RootDir() (string, error) { rdir, err := os.Readlink(p.path("root")) if os.IsNotExist(err) { @@ -311,7 +311,7 @@ func (p Proc) FileDescriptorsInfo() (ProcFDInfos, error) { // Schedstat returns task scheduling information for the process. func (p Proc) Schedstat() (ProcSchedstat, error) { - contents, err := ioutil.ReadFile(p.path("schedstat")) + contents, err := os.ReadFile(p.path("schedstat")) if err != nil { return ProcSchedstat{}, err } diff --git a/vendor/github.com/prometheus/procfs/proc_cgroup.go b/vendor/github.com/prometheus/procfs/proc_cgroup.go index be45b79873..ea83a75ffc 100644 --- a/vendor/github.com/prometheus/procfs/proc_cgroup.go +++ b/vendor/github.com/prometheus/procfs/proc_cgroup.go @@ -23,7 +23,7 @@ import ( "github.com/prometheus/procfs/internal/util" ) -// Cgroup models one line from /proc/[pid]/cgroup. Each Cgroup struct describes the the placement of a PID inside a +// Cgroup models one line from /proc/[pid]/cgroup. Each Cgroup struct describes the placement of a PID inside a // specific control hierarchy. The kernel has two cgroup APIs, v1 and v2. v1 has one hierarchy per available resource // controller, while v2 has one unified hierarchy shared by all controllers. Regardless of v1 or v2, all hierarchies // contain all running processes, so the question answerable with a Cgroup struct is 'where is this process in @@ -45,7 +45,7 @@ type Cgroup struct { } // parseCgroupString parses each line of the /proc/[pid]/cgroup file -// Line format is hierarchyID:[controller1,controller2]:path +// Line format is hierarchyID:[controller1,controller2]:path. func parseCgroupString(cgroupStr string) (*Cgroup, error) { var err error @@ -69,7 +69,7 @@ func parseCgroupString(cgroupStr string) (*Cgroup, error) { return cgroup, nil } -// parseCgroups reads each line of the /proc/[pid]/cgroup file +// parseCgroups reads each line of the /proc/[pid]/cgroup file. func parseCgroups(data []byte) ([]Cgroup, error) { var cgroups []Cgroup scanner := bufio.NewScanner(bytes.NewReader(data)) @@ -88,7 +88,7 @@ func parseCgroups(data []byte) ([]Cgroup, error) { // Cgroups reads from /proc//cgroups and returns a []*Cgroup struct locating this PID in each process // control hierarchy running on this system. On every system (v1 and v2), all hierarchies contain all processes, -// so the len of the returned struct is equal to the number of active hierarchies on this system +// so the len of the returned struct is equal to the number of active hierarchies on this system. func (p Proc) Cgroups() ([]Cgroup, error) { data, err := util.ReadFileNoStat(p.path("cgroup")) if err != nil { diff --git a/vendor/github.com/prometheus/procfs/proc_cgroups.go b/vendor/github.com/prometheus/procfs/proc_cgroups.go new file mode 100644 index 0000000000..24d4dce9cf --- /dev/null +++ b/vendor/github.com/prometheus/procfs/proc_cgroups.go @@ -0,0 +1,98 @@ +// Copyright 2021 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package procfs + +import ( + "bufio" + "bytes" + "fmt" + "strconv" + "strings" + + "github.com/prometheus/procfs/internal/util" +) + +// CgroupSummary models one line from /proc/cgroups. +// This file contains information about the controllers that are compiled into the kernel. +// +// Also see http://man7.org/linux/man-pages/man7/cgroups.7.html +type CgroupSummary struct { + // The name of the controller. controller is also known as subsystem. + SubsysName string + // The unique ID of the cgroup hierarchy on which this controller is mounted. + Hierarchy int + // The number of control groups in this hierarchy using this controller. + Cgroups int + // This field contains the value 1 if this controller is enabled, or 0 if it has been disabled + Enabled int +} + +// parseCgroupSummary parses each line of the /proc/cgroup file +// Line format is `subsys_name hierarchy num_cgroups enabled`. +func parseCgroupSummaryString(CgroupSummaryStr string) (*CgroupSummary, error) { + var err error + + fields := strings.Fields(CgroupSummaryStr) + // require at least 4 fields + if len(fields) < 4 { + return nil, fmt.Errorf("at least 4 fields required, found %d fields in cgroup info string: %s", len(fields), CgroupSummaryStr) + } + + CgroupSummary := &CgroupSummary{ + SubsysName: fields[0], + } + CgroupSummary.Hierarchy, err = strconv.Atoi(fields[1]) + if err != nil { + return nil, fmt.Errorf("failed to parse hierarchy ID") + } + CgroupSummary.Cgroups, err = strconv.Atoi(fields[2]) + if err != nil { + return nil, fmt.Errorf("failed to parse Cgroup Num") + } + CgroupSummary.Enabled, err = strconv.Atoi(fields[3]) + if err != nil { + return nil, fmt.Errorf("failed to parse Enabled") + } + return CgroupSummary, nil +} + +// parseCgroupSummary reads each line of the /proc/cgroup file. +func parseCgroupSummary(data []byte) ([]CgroupSummary, error) { + var CgroupSummarys []CgroupSummary + scanner := bufio.NewScanner(bytes.NewReader(data)) + for scanner.Scan() { + CgroupSummaryString := scanner.Text() + // ignore comment lines + if strings.HasPrefix(CgroupSummaryString, "#") { + continue + } + CgroupSummary, err := parseCgroupSummaryString(CgroupSummaryString) + if err != nil { + return nil, err + } + CgroupSummarys = append(CgroupSummarys, *CgroupSummary) + } + + err := scanner.Err() + return CgroupSummarys, err +} + +// CgroupSummarys returns information about current /proc/cgroups. +func (fs FS) CgroupSummarys() ([]CgroupSummary, error) { + data, err := util.ReadFileNoStat(fs.proc.Path("cgroups")) + if err != nil { + return nil, err + } + return parseCgroupSummary(data) +} diff --git a/vendor/github.com/prometheus/procfs/proc_environ.go b/vendor/github.com/prometheus/procfs/proc_environ.go index 6134b3580c..57a89895d6 100644 --- a/vendor/github.com/prometheus/procfs/proc_environ.go +++ b/vendor/github.com/prometheus/procfs/proc_environ.go @@ -19,7 +19,7 @@ import ( "github.com/prometheus/procfs/internal/util" ) -// Environ reads process environments from /proc//environ +// Environ reads process environments from `/proc//environ`. func (p Proc) Environ() ([]string, error) { environments := make([]string, 0) diff --git a/vendor/github.com/prometheus/procfs/proc_fdinfo.go b/vendor/github.com/prometheus/procfs/proc_fdinfo.go index cf63227f06..1bbdd4a8e9 100644 --- a/vendor/github.com/prometheus/procfs/proc_fdinfo.go +++ b/vendor/github.com/prometheus/procfs/proc_fdinfo.go @@ -22,7 +22,6 @@ import ( "github.com/prometheus/procfs/internal/util" ) -// Regexp variables var ( rPos = regexp.MustCompile(`^pos:\s+(\d+)$`) rFlags = regexp.MustCompile(`^flags:\s+(\d+)$`) @@ -122,7 +121,7 @@ func (p ProcFDInfos) Len() int { return len(p) } func (p ProcFDInfos) Swap(i, j int) { p[i], p[j] = p[j], p[i] } func (p ProcFDInfos) Less(i, j int) bool { return p[i].FD < p[j].FD } -// InotifyWatchLen returns the total number of inotify watches +// InotifyWatchLen returns the total number of inotify watches. func (p ProcFDInfos) InotifyWatchLen() (int, error) { length := 0 for _, f := range p { diff --git a/vendor/github.com/prometheus/procfs/proc_interrupts.go b/vendor/github.com/prometheus/procfs/proc_interrupts.go new file mode 100644 index 0000000000..9df79c2379 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/proc_interrupts.go @@ -0,0 +1,98 @@ +// Copyright 2022 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package procfs + +import ( + "bufio" + "bytes" + "errors" + "fmt" + "io" + "strconv" + "strings" + + "github.com/prometheus/procfs/internal/util" +) + +// Interrupt represents a single interrupt line. +type Interrupt struct { + // Info is the type of interrupt. + Info string + // Devices is the name of the device that is located at that IRQ + Devices string + // Values is the number of interrupts per CPU. + Values []string +} + +// Interrupts models the content of /proc/interrupts. Key is the IRQ number. +// - https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/deployment_guide/s2-proc-interrupts +// - https://raspberrypi.stackexchange.com/questions/105802/explanation-of-proc-interrupts-output +type Interrupts map[string]Interrupt + +// Interrupts creates a new instance from a given Proc instance. +func (p Proc) Interrupts() (Interrupts, error) { + data, err := util.ReadFileNoStat(p.path("interrupts")) + if err != nil { + return nil, err + } + return parseInterrupts(bytes.NewReader(data)) +} + +func parseInterrupts(r io.Reader) (Interrupts, error) { + var ( + interrupts = Interrupts{} + scanner = bufio.NewScanner(r) + ) + + if !scanner.Scan() { + return nil, errors.New("interrupts empty") + } + cpuNum := len(strings.Fields(scanner.Text())) // one header per cpu + + for scanner.Scan() { + parts := strings.Fields(scanner.Text()) + if len(parts) == 0 { // skip empty lines + continue + } + if len(parts) < 2 { + return nil, fmt.Errorf("not enough fields in interrupts (expected at least 2 fields but got %d): %s", len(parts), parts) + } + intName := parts[0][:len(parts[0])-1] // remove trailing : + + if len(parts) == 2 { + interrupts[intName] = Interrupt{ + Info: "", + Devices: "", + Values: []string{ + parts[1], + }, + } + continue + } + + intr := Interrupt{ + Values: parts[1 : cpuNum+1], + } + + if _, err := strconv.Atoi(intName); err == nil { // numeral interrupt + intr.Info = parts[cpuNum+1] + intr.Devices = strings.Join(parts[cpuNum+2:], " ") + } else { + intr.Info = strings.Join(parts[cpuNum+1:], " ") + } + interrupts[intName] = intr + } + + return interrupts, scanner.Err() +} diff --git a/vendor/github.com/prometheus/procfs/proc_limits.go b/vendor/github.com/prometheus/procfs/proc_limits.go index dd20f198a3..7a1388185a 100644 --- a/vendor/github.com/prometheus/procfs/proc_limits.go +++ b/vendor/github.com/prometheus/procfs/proc_limits.go @@ -79,7 +79,7 @@ var ( // NewLimits returns the current soft limits of the process. // -// Deprecated: use p.Limits() instead +// Deprecated: Use p.Limits() instead. func (p Proc) NewLimits() (ProcLimits, error) { return p.Limits() } diff --git a/vendor/github.com/prometheus/procfs/proc_maps.go b/vendor/github.com/prometheus/procfs/proc_maps.go index 1d7772d516..f1bcbf32bb 100644 --- a/vendor/github.com/prometheus/procfs/proc_maps.go +++ b/vendor/github.com/prometheus/procfs/proc_maps.go @@ -11,7 +11,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris) && !js // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris +// +build !js package procfs @@ -25,7 +27,7 @@ import ( "golang.org/x/sys/unix" ) -// ProcMapPermissions contains permission settings read from /proc/[pid]/maps +// ProcMapPermissions contains permission settings read from `/proc/[pid]/maps`. type ProcMapPermissions struct { // mapping has the [R]ead flag set Read bool @@ -39,8 +41,8 @@ type ProcMapPermissions struct { Private bool } -// ProcMap contains the process memory-mappings of the process, -// read from /proc/[pid]/maps +// ProcMap contains the process memory-mappings of the process +// read from `/proc/[pid]/maps`. type ProcMap struct { // The start address of current mapping. StartAddr uintptr @@ -79,7 +81,7 @@ func parseDevice(s string) (uint64, error) { return unix.Mkdev(uint32(major), uint32(minor)), nil } -// parseAddress just converts a hex-string to a uintptr +// parseAddress converts a hex-string to a uintptr. func parseAddress(s string) (uintptr, error) { a, err := strconv.ParseUint(s, 16, 0) if err != nil { @@ -89,7 +91,7 @@ func parseAddress(s string) (uintptr, error) { return uintptr(a), nil } -// parseAddresses parses the start-end address +// parseAddresses parses the start-end address. func parseAddresses(s string) (uintptr, uintptr, error) { toks := strings.Split(s, "-") if len(toks) < 2 { diff --git a/vendor/github.com/prometheus/procfs/proc_netstat.go b/vendor/github.com/prometheus/procfs/proc_netstat.go new file mode 100644 index 0000000000..6a43bb2459 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/proc_netstat.go @@ -0,0 +1,443 @@ +// Copyright 2022 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package procfs + +import ( + "bufio" + "bytes" + "fmt" + "io" + "strconv" + "strings" + + "github.com/prometheus/procfs/internal/util" +) + +// ProcNetstat models the content of /proc//net/netstat. +type ProcNetstat struct { + // The process ID. + PID int + TcpExt + IpExt +} + +type TcpExt struct { // nolint:revive + SyncookiesSent *float64 + SyncookiesRecv *float64 + SyncookiesFailed *float64 + EmbryonicRsts *float64 + PruneCalled *float64 + RcvPruned *float64 + OfoPruned *float64 + OutOfWindowIcmps *float64 + LockDroppedIcmps *float64 + ArpFilter *float64 + TW *float64 + TWRecycled *float64 + TWKilled *float64 + PAWSActive *float64 + PAWSEstab *float64 + DelayedACKs *float64 + DelayedACKLocked *float64 + DelayedACKLost *float64 + ListenOverflows *float64 + ListenDrops *float64 + TCPHPHits *float64 + TCPPureAcks *float64 + TCPHPAcks *float64 + TCPRenoRecovery *float64 + TCPSackRecovery *float64 + TCPSACKReneging *float64 + TCPSACKReorder *float64 + TCPRenoReorder *float64 + TCPTSReorder *float64 + TCPFullUndo *float64 + TCPPartialUndo *float64 + TCPDSACKUndo *float64 + TCPLossUndo *float64 + TCPLostRetransmit *float64 + TCPRenoFailures *float64 + TCPSackFailures *float64 + TCPLossFailures *float64 + TCPFastRetrans *float64 + TCPSlowStartRetrans *float64 + TCPTimeouts *float64 + TCPLossProbes *float64 + TCPLossProbeRecovery *float64 + TCPRenoRecoveryFail *float64 + TCPSackRecoveryFail *float64 + TCPRcvCollapsed *float64 + TCPDSACKOldSent *float64 + TCPDSACKOfoSent *float64 + TCPDSACKRecv *float64 + TCPDSACKOfoRecv *float64 + TCPAbortOnData *float64 + TCPAbortOnClose *float64 + TCPAbortOnMemory *float64 + TCPAbortOnTimeout *float64 + TCPAbortOnLinger *float64 + TCPAbortFailed *float64 + TCPMemoryPressures *float64 + TCPMemoryPressuresChrono *float64 + TCPSACKDiscard *float64 + TCPDSACKIgnoredOld *float64 + TCPDSACKIgnoredNoUndo *float64 + TCPSpuriousRTOs *float64 + TCPMD5NotFound *float64 + TCPMD5Unexpected *float64 + TCPMD5Failure *float64 + TCPSackShifted *float64 + TCPSackMerged *float64 + TCPSackShiftFallback *float64 + TCPBacklogDrop *float64 + PFMemallocDrop *float64 + TCPMinTTLDrop *float64 + TCPDeferAcceptDrop *float64 + IPReversePathFilter *float64 + TCPTimeWaitOverflow *float64 + TCPReqQFullDoCookies *float64 + TCPReqQFullDrop *float64 + TCPRetransFail *float64 + TCPRcvCoalesce *float64 + TCPRcvQDrop *float64 + TCPOFOQueue *float64 + TCPOFODrop *float64 + TCPOFOMerge *float64 + TCPChallengeACK *float64 + TCPSYNChallenge *float64 + TCPFastOpenActive *float64 + TCPFastOpenActiveFail *float64 + TCPFastOpenPassive *float64 + TCPFastOpenPassiveFail *float64 + TCPFastOpenListenOverflow *float64 + TCPFastOpenCookieReqd *float64 + TCPFastOpenBlackhole *float64 + TCPSpuriousRtxHostQueues *float64 + BusyPollRxPackets *float64 + TCPAutoCorking *float64 + TCPFromZeroWindowAdv *float64 + TCPToZeroWindowAdv *float64 + TCPWantZeroWindowAdv *float64 + TCPSynRetrans *float64 + TCPOrigDataSent *float64 + TCPHystartTrainDetect *float64 + TCPHystartTrainCwnd *float64 + TCPHystartDelayDetect *float64 + TCPHystartDelayCwnd *float64 + TCPACKSkippedSynRecv *float64 + TCPACKSkippedPAWS *float64 + TCPACKSkippedSeq *float64 + TCPACKSkippedFinWait2 *float64 + TCPACKSkippedTimeWait *float64 + TCPACKSkippedChallenge *float64 + TCPWinProbe *float64 + TCPKeepAlive *float64 + TCPMTUPFail *float64 + TCPMTUPSuccess *float64 + TCPWqueueTooBig *float64 +} + +type IpExt struct { // nolint:revive + InNoRoutes *float64 + InTruncatedPkts *float64 + InMcastPkts *float64 + OutMcastPkts *float64 + InBcastPkts *float64 + OutBcastPkts *float64 + InOctets *float64 + OutOctets *float64 + InMcastOctets *float64 + OutMcastOctets *float64 + InBcastOctets *float64 + OutBcastOctets *float64 + InCsumErrors *float64 + InNoECTPkts *float64 + InECT1Pkts *float64 + InECT0Pkts *float64 + InCEPkts *float64 + ReasmOverlaps *float64 +} + +func (p Proc) Netstat() (ProcNetstat, error) { + filename := p.path("net/netstat") + data, err := util.ReadFileNoStat(filename) + if err != nil { + return ProcNetstat{PID: p.PID}, err + } + procNetstat, err := parseProcNetstat(bytes.NewReader(data), filename) + procNetstat.PID = p.PID + return procNetstat, err +} + +// parseProcNetstat parses the metrics from proc//net/netstat file +// and returns a ProcNetstat structure. +func parseProcNetstat(r io.Reader, fileName string) (ProcNetstat, error) { + var ( + scanner = bufio.NewScanner(r) + procNetstat = ProcNetstat{} + ) + + for scanner.Scan() { + nameParts := strings.Split(scanner.Text(), " ") + scanner.Scan() + valueParts := strings.Split(scanner.Text(), " ") + // Remove trailing :. + protocol := strings.TrimSuffix(nameParts[0], ":") + if len(nameParts) != len(valueParts) { + return procNetstat, fmt.Errorf("mismatch field count mismatch in %s: %s", + fileName, protocol) + } + for i := 1; i < len(nameParts); i++ { + value, err := strconv.ParseFloat(valueParts[i], 64) + if err != nil { + return procNetstat, err + } + key := nameParts[i] + + switch protocol { + case "TcpExt": + switch key { + case "SyncookiesSent": + procNetstat.TcpExt.SyncookiesSent = &value + case "SyncookiesRecv": + procNetstat.TcpExt.SyncookiesRecv = &value + case "SyncookiesFailed": + procNetstat.TcpExt.SyncookiesFailed = &value + case "EmbryonicRsts": + procNetstat.TcpExt.EmbryonicRsts = &value + case "PruneCalled": + procNetstat.TcpExt.PruneCalled = &value + case "RcvPruned": + procNetstat.TcpExt.RcvPruned = &value + case "OfoPruned": + procNetstat.TcpExt.OfoPruned = &value + case "OutOfWindowIcmps": + procNetstat.TcpExt.OutOfWindowIcmps = &value + case "LockDroppedIcmps": + procNetstat.TcpExt.LockDroppedIcmps = &value + case "ArpFilter": + procNetstat.TcpExt.ArpFilter = &value + case "TW": + procNetstat.TcpExt.TW = &value + case "TWRecycled": + procNetstat.TcpExt.TWRecycled = &value + case "TWKilled": + procNetstat.TcpExt.TWKilled = &value + case "PAWSActive": + procNetstat.TcpExt.PAWSActive = &value + case "PAWSEstab": + procNetstat.TcpExt.PAWSEstab = &value + case "DelayedACKs": + procNetstat.TcpExt.DelayedACKs = &value + case "DelayedACKLocked": + procNetstat.TcpExt.DelayedACKLocked = &value + case "DelayedACKLost": + procNetstat.TcpExt.DelayedACKLost = &value + case "ListenOverflows": + procNetstat.TcpExt.ListenOverflows = &value + case "ListenDrops": + procNetstat.TcpExt.ListenDrops = &value + case "TCPHPHits": + procNetstat.TcpExt.TCPHPHits = &value + case "TCPPureAcks": + procNetstat.TcpExt.TCPPureAcks = &value + case "TCPHPAcks": + procNetstat.TcpExt.TCPHPAcks = &value + case "TCPRenoRecovery": + procNetstat.TcpExt.TCPRenoRecovery = &value + case "TCPSackRecovery": + procNetstat.TcpExt.TCPSackRecovery = &value + case "TCPSACKReneging": + procNetstat.TcpExt.TCPSACKReneging = &value + case "TCPSACKReorder": + procNetstat.TcpExt.TCPSACKReorder = &value + case "TCPRenoReorder": + procNetstat.TcpExt.TCPRenoReorder = &value + case "TCPTSReorder": + procNetstat.TcpExt.TCPTSReorder = &value + case "TCPFullUndo": + procNetstat.TcpExt.TCPFullUndo = &value + case "TCPPartialUndo": + procNetstat.TcpExt.TCPPartialUndo = &value + case "TCPDSACKUndo": + procNetstat.TcpExt.TCPDSACKUndo = &value + case "TCPLossUndo": + procNetstat.TcpExt.TCPLossUndo = &value + case "TCPLostRetransmit": + procNetstat.TcpExt.TCPLostRetransmit = &value + case "TCPRenoFailures": + procNetstat.TcpExt.TCPRenoFailures = &value + case "TCPSackFailures": + procNetstat.TcpExt.TCPSackFailures = &value + case "TCPLossFailures": + procNetstat.TcpExt.TCPLossFailures = &value + case "TCPFastRetrans": + procNetstat.TcpExt.TCPFastRetrans = &value + case "TCPSlowStartRetrans": + procNetstat.TcpExt.TCPSlowStartRetrans = &value + case "TCPTimeouts": + procNetstat.TcpExt.TCPTimeouts = &value + case "TCPLossProbes": + procNetstat.TcpExt.TCPLossProbes = &value + case "TCPLossProbeRecovery": + procNetstat.TcpExt.TCPLossProbeRecovery = &value + case "TCPRenoRecoveryFail": + procNetstat.TcpExt.TCPRenoRecoveryFail = &value + case "TCPSackRecoveryFail": + procNetstat.TcpExt.TCPSackRecoveryFail = &value + case "TCPRcvCollapsed": + procNetstat.TcpExt.TCPRcvCollapsed = &value + case "TCPDSACKOldSent": + procNetstat.TcpExt.TCPDSACKOldSent = &value + case "TCPDSACKOfoSent": + procNetstat.TcpExt.TCPDSACKOfoSent = &value + case "TCPDSACKRecv": + procNetstat.TcpExt.TCPDSACKRecv = &value + case "TCPDSACKOfoRecv": + procNetstat.TcpExt.TCPDSACKOfoRecv = &value + case "TCPAbortOnData": + procNetstat.TcpExt.TCPAbortOnData = &value + case "TCPAbortOnClose": + procNetstat.TcpExt.TCPAbortOnClose = &value + case "TCPDeferAcceptDrop": + procNetstat.TcpExt.TCPDeferAcceptDrop = &value + case "IPReversePathFilter": + procNetstat.TcpExt.IPReversePathFilter = &value + case "TCPTimeWaitOverflow": + procNetstat.TcpExt.TCPTimeWaitOverflow = &value + case "TCPReqQFullDoCookies": + procNetstat.TcpExt.TCPReqQFullDoCookies = &value + case "TCPReqQFullDrop": + procNetstat.TcpExt.TCPReqQFullDrop = &value + case "TCPRetransFail": + procNetstat.TcpExt.TCPRetransFail = &value + case "TCPRcvCoalesce": + procNetstat.TcpExt.TCPRcvCoalesce = &value + case "TCPRcvQDrop": + procNetstat.TcpExt.TCPRcvQDrop = &value + case "TCPOFOQueue": + procNetstat.TcpExt.TCPOFOQueue = &value + case "TCPOFODrop": + procNetstat.TcpExt.TCPOFODrop = &value + case "TCPOFOMerge": + procNetstat.TcpExt.TCPOFOMerge = &value + case "TCPChallengeACK": + procNetstat.TcpExt.TCPChallengeACK = &value + case "TCPSYNChallenge": + procNetstat.TcpExt.TCPSYNChallenge = &value + case "TCPFastOpenActive": + procNetstat.TcpExt.TCPFastOpenActive = &value + case "TCPFastOpenActiveFail": + procNetstat.TcpExt.TCPFastOpenActiveFail = &value + case "TCPFastOpenPassive": + procNetstat.TcpExt.TCPFastOpenPassive = &value + case "TCPFastOpenPassiveFail": + procNetstat.TcpExt.TCPFastOpenPassiveFail = &value + case "TCPFastOpenListenOverflow": + procNetstat.TcpExt.TCPFastOpenListenOverflow = &value + case "TCPFastOpenCookieReqd": + procNetstat.TcpExt.TCPFastOpenCookieReqd = &value + case "TCPFastOpenBlackhole": + procNetstat.TcpExt.TCPFastOpenBlackhole = &value + case "TCPSpuriousRtxHostQueues": + procNetstat.TcpExt.TCPSpuriousRtxHostQueues = &value + case "BusyPollRxPackets": + procNetstat.TcpExt.BusyPollRxPackets = &value + case "TCPAutoCorking": + procNetstat.TcpExt.TCPAutoCorking = &value + case "TCPFromZeroWindowAdv": + procNetstat.TcpExt.TCPFromZeroWindowAdv = &value + case "TCPToZeroWindowAdv": + procNetstat.TcpExt.TCPToZeroWindowAdv = &value + case "TCPWantZeroWindowAdv": + procNetstat.TcpExt.TCPWantZeroWindowAdv = &value + case "TCPSynRetrans": + procNetstat.TcpExt.TCPSynRetrans = &value + case "TCPOrigDataSent": + procNetstat.TcpExt.TCPOrigDataSent = &value + case "TCPHystartTrainDetect": + procNetstat.TcpExt.TCPHystartTrainDetect = &value + case "TCPHystartTrainCwnd": + procNetstat.TcpExt.TCPHystartTrainCwnd = &value + case "TCPHystartDelayDetect": + procNetstat.TcpExt.TCPHystartDelayDetect = &value + case "TCPHystartDelayCwnd": + procNetstat.TcpExt.TCPHystartDelayCwnd = &value + case "TCPACKSkippedSynRecv": + procNetstat.TcpExt.TCPACKSkippedSynRecv = &value + case "TCPACKSkippedPAWS": + procNetstat.TcpExt.TCPACKSkippedPAWS = &value + case "TCPACKSkippedSeq": + procNetstat.TcpExt.TCPACKSkippedSeq = &value + case "TCPACKSkippedFinWait2": + procNetstat.TcpExt.TCPACKSkippedFinWait2 = &value + case "TCPACKSkippedTimeWait": + procNetstat.TcpExt.TCPACKSkippedTimeWait = &value + case "TCPACKSkippedChallenge": + procNetstat.TcpExt.TCPACKSkippedChallenge = &value + case "TCPWinProbe": + procNetstat.TcpExt.TCPWinProbe = &value + case "TCPKeepAlive": + procNetstat.TcpExt.TCPKeepAlive = &value + case "TCPMTUPFail": + procNetstat.TcpExt.TCPMTUPFail = &value + case "TCPMTUPSuccess": + procNetstat.TcpExt.TCPMTUPSuccess = &value + case "TCPWqueueTooBig": + procNetstat.TcpExt.TCPWqueueTooBig = &value + } + case "IpExt": + switch key { + case "InNoRoutes": + procNetstat.IpExt.InNoRoutes = &value + case "InTruncatedPkts": + procNetstat.IpExt.InTruncatedPkts = &value + case "InMcastPkts": + procNetstat.IpExt.InMcastPkts = &value + case "OutMcastPkts": + procNetstat.IpExt.OutMcastPkts = &value + case "InBcastPkts": + procNetstat.IpExt.InBcastPkts = &value + case "OutBcastPkts": + procNetstat.IpExt.OutBcastPkts = &value + case "InOctets": + procNetstat.IpExt.InOctets = &value + case "OutOctets": + procNetstat.IpExt.OutOctets = &value + case "InMcastOctets": + procNetstat.IpExt.InMcastOctets = &value + case "OutMcastOctets": + procNetstat.IpExt.OutMcastOctets = &value + case "InBcastOctets": + procNetstat.IpExt.InBcastOctets = &value + case "OutBcastOctets": + procNetstat.IpExt.OutBcastOctets = &value + case "InCsumErrors": + procNetstat.IpExt.InCsumErrors = &value + case "InNoECTPkts": + procNetstat.IpExt.InNoECTPkts = &value + case "InECT1Pkts": + procNetstat.IpExt.InECT1Pkts = &value + case "InECT0Pkts": + procNetstat.IpExt.InECT0Pkts = &value + case "InCEPkts": + procNetstat.IpExt.InCEPkts = &value + case "ReasmOverlaps": + procNetstat.IpExt.ReasmOverlaps = &value + } + } + } + } + return procNetstat, scanner.Err() +} diff --git a/vendor/github.com/prometheus/procfs/proc_psi.go b/vendor/github.com/prometheus/procfs/proc_psi.go index dc6c14f0a4..a68fe15290 100644 --- a/vendor/github.com/prometheus/procfs/proc_psi.go +++ b/vendor/github.com/prometheus/procfs/proc_psi.go @@ -35,9 +35,10 @@ import ( const lineFormat = "avg10=%f avg60=%f avg300=%f total=%d" -// PSILine is a single line of values as returned by /proc/pressure/* -// The Avg entries are averages over n seconds, as a percentage -// The Total line is in microseconds +// PSILine is a single line of values as returned by `/proc/pressure/*`. +// +// The Avg entries are averages over n seconds, as a percentage. +// The Total line is in microseconds. type PSILine struct { Avg10 float64 Avg60 float64 @@ -46,8 +47,9 @@ type PSILine struct { } // PSIStats represent pressure stall information from /proc/pressure/* -// Some indicates the share of time in which at least some tasks are stalled -// Full indicates the share of time in which all non-idle tasks are stalled simultaneously +// +// "Some" indicates the share of time in which at least some tasks are stalled. +// "Full" indicates the share of time in which all non-idle tasks are stalled simultaneously. type PSIStats struct { Some *PSILine Full *PSILine @@ -65,7 +67,7 @@ func (fs FS) PSIStatsForResource(resource string) (PSIStats, error) { return parsePSIStats(resource, bytes.NewReader(data)) } -// parsePSIStats parses the specified file for pressure stall information +// parsePSIStats parses the specified file for pressure stall information. func parsePSIStats(resource string, r io.Reader) (PSIStats, error) { psiStats := PSIStats{} diff --git a/vendor/github.com/prometheus/procfs/proc_smaps.go b/vendor/github.com/prometheus/procfs/proc_smaps.go index a576a720a4..0e97d99575 100644 --- a/vendor/github.com/prometheus/procfs/proc_smaps.go +++ b/vendor/github.com/prometheus/procfs/proc_smaps.go @@ -11,6 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !windows // +build !windows package procfs @@ -28,30 +29,30 @@ import ( ) var ( - // match the header line before each mapped zone in /proc/pid/smaps + // match the header line before each mapped zone in `/proc/pid/smaps`. procSMapsHeaderLine = regexp.MustCompile(`^[a-f0-9].*$`) ) type ProcSMapsRollup struct { - // Amount of the mapping that is currently resident in RAM + // Amount of the mapping that is currently resident in RAM. Rss uint64 - // Process's proportional share of this mapping + // Process's proportional share of this mapping. Pss uint64 - // Size in bytes of clean shared pages + // Size in bytes of clean shared pages. SharedClean uint64 - // Size in bytes of dirty shared pages + // Size in bytes of dirty shared pages. SharedDirty uint64 - // Size in bytes of clean private pages + // Size in bytes of clean private pages. PrivateClean uint64 - // Size in bytes of dirty private pages + // Size in bytes of dirty private pages. PrivateDirty uint64 - // Amount of memory currently marked as referenced or accessed + // Amount of memory currently marked as referenced or accessed. Referenced uint64 - // Amount of memory that does not belong to any file + // Amount of memory that does not belong to any file. Anonymous uint64 - // Amount would-be-anonymous memory currently on swap + // Amount would-be-anonymous memory currently on swap. Swap uint64 - // Process's proportional memory on swap + // Process's proportional memory on swap. SwapPss uint64 } diff --git a/vendor/github.com/prometheus/procfs/proc_snmp.go b/vendor/github.com/prometheus/procfs/proc_snmp.go new file mode 100644 index 0000000000..6c46b71884 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/proc_snmp.go @@ -0,0 +1,353 @@ +// Copyright 2022 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package procfs + +import ( + "bufio" + "bytes" + "fmt" + "io" + "strconv" + "strings" + + "github.com/prometheus/procfs/internal/util" +) + +// ProcSnmp models the content of /proc//net/snmp. +type ProcSnmp struct { + // The process ID. + PID int + Ip + Icmp + IcmpMsg + Tcp + Udp + UdpLite +} + +type Ip struct { // nolint:revive + Forwarding *float64 + DefaultTTL *float64 + InReceives *float64 + InHdrErrors *float64 + InAddrErrors *float64 + ForwDatagrams *float64 + InUnknownProtos *float64 + InDiscards *float64 + InDelivers *float64 + OutRequests *float64 + OutDiscards *float64 + OutNoRoutes *float64 + ReasmTimeout *float64 + ReasmReqds *float64 + ReasmOKs *float64 + ReasmFails *float64 + FragOKs *float64 + FragFails *float64 + FragCreates *float64 +} + +type Icmp struct { // nolint:revive + InMsgs *float64 + InErrors *float64 + InCsumErrors *float64 + InDestUnreachs *float64 + InTimeExcds *float64 + InParmProbs *float64 + InSrcQuenchs *float64 + InRedirects *float64 + InEchos *float64 + InEchoReps *float64 + InTimestamps *float64 + InTimestampReps *float64 + InAddrMasks *float64 + InAddrMaskReps *float64 + OutMsgs *float64 + OutErrors *float64 + OutDestUnreachs *float64 + OutTimeExcds *float64 + OutParmProbs *float64 + OutSrcQuenchs *float64 + OutRedirects *float64 + OutEchos *float64 + OutEchoReps *float64 + OutTimestamps *float64 + OutTimestampReps *float64 + OutAddrMasks *float64 + OutAddrMaskReps *float64 +} + +type IcmpMsg struct { + InType3 *float64 + OutType3 *float64 +} + +type Tcp struct { // nolint:revive + RtoAlgorithm *float64 + RtoMin *float64 + RtoMax *float64 + MaxConn *float64 + ActiveOpens *float64 + PassiveOpens *float64 + AttemptFails *float64 + EstabResets *float64 + CurrEstab *float64 + InSegs *float64 + OutSegs *float64 + RetransSegs *float64 + InErrs *float64 + OutRsts *float64 + InCsumErrors *float64 +} + +type Udp struct { // nolint:revive + InDatagrams *float64 + NoPorts *float64 + InErrors *float64 + OutDatagrams *float64 + RcvbufErrors *float64 + SndbufErrors *float64 + InCsumErrors *float64 + IgnoredMulti *float64 +} + +type UdpLite struct { // nolint:revive + InDatagrams *float64 + NoPorts *float64 + InErrors *float64 + OutDatagrams *float64 + RcvbufErrors *float64 + SndbufErrors *float64 + InCsumErrors *float64 + IgnoredMulti *float64 +} + +func (p Proc) Snmp() (ProcSnmp, error) { + filename := p.path("net/snmp") + data, err := util.ReadFileNoStat(filename) + if err != nil { + return ProcSnmp{PID: p.PID}, err + } + procSnmp, err := parseSnmp(bytes.NewReader(data), filename) + procSnmp.PID = p.PID + return procSnmp, err +} + +// parseSnmp parses the metrics from proc//net/snmp file +// and returns a map contains those metrics (e.g. {"Ip": {"Forwarding": 2}}). +func parseSnmp(r io.Reader, fileName string) (ProcSnmp, error) { + var ( + scanner = bufio.NewScanner(r) + procSnmp = ProcSnmp{} + ) + + for scanner.Scan() { + nameParts := strings.Split(scanner.Text(), " ") + scanner.Scan() + valueParts := strings.Split(scanner.Text(), " ") + // Remove trailing :. + protocol := strings.TrimSuffix(nameParts[0], ":") + if len(nameParts) != len(valueParts) { + return procSnmp, fmt.Errorf("mismatch field count mismatch in %s: %s", + fileName, protocol) + } + for i := 1; i < len(nameParts); i++ { + value, err := strconv.ParseFloat(valueParts[i], 64) + if err != nil { + return procSnmp, err + } + key := nameParts[i] + + switch protocol { + case "Ip": + switch key { + case "Forwarding": + procSnmp.Ip.Forwarding = &value + case "DefaultTTL": + procSnmp.Ip.DefaultTTL = &value + case "InReceives": + procSnmp.Ip.InReceives = &value + case "InHdrErrors": + procSnmp.Ip.InHdrErrors = &value + case "InAddrErrors": + procSnmp.Ip.InAddrErrors = &value + case "ForwDatagrams": + procSnmp.Ip.ForwDatagrams = &value + case "InUnknownProtos": + procSnmp.Ip.InUnknownProtos = &value + case "InDiscards": + procSnmp.Ip.InDiscards = &value + case "InDelivers": + procSnmp.Ip.InDelivers = &value + case "OutRequests": + procSnmp.Ip.OutRequests = &value + case "OutDiscards": + procSnmp.Ip.OutDiscards = &value + case "OutNoRoutes": + procSnmp.Ip.OutNoRoutes = &value + case "ReasmTimeout": + procSnmp.Ip.ReasmTimeout = &value + case "ReasmReqds": + procSnmp.Ip.ReasmReqds = &value + case "ReasmOKs": + procSnmp.Ip.ReasmOKs = &value + case "ReasmFails": + procSnmp.Ip.ReasmFails = &value + case "FragOKs": + procSnmp.Ip.FragOKs = &value + case "FragFails": + procSnmp.Ip.FragFails = &value + case "FragCreates": + procSnmp.Ip.FragCreates = &value + } + case "Icmp": + switch key { + case "InMsgs": + procSnmp.Icmp.InMsgs = &value + case "InErrors": + procSnmp.Icmp.InErrors = &value + case "InCsumErrors": + procSnmp.Icmp.InCsumErrors = &value + case "InDestUnreachs": + procSnmp.Icmp.InDestUnreachs = &value + case "InTimeExcds": + procSnmp.Icmp.InTimeExcds = &value + case "InParmProbs": + procSnmp.Icmp.InParmProbs = &value + case "InSrcQuenchs": + procSnmp.Icmp.InSrcQuenchs = &value + case "InRedirects": + procSnmp.Icmp.InRedirects = &value + case "InEchos": + procSnmp.Icmp.InEchos = &value + case "InEchoReps": + procSnmp.Icmp.InEchoReps = &value + case "InTimestamps": + procSnmp.Icmp.InTimestamps = &value + case "InTimestampReps": + procSnmp.Icmp.InTimestampReps = &value + case "InAddrMasks": + procSnmp.Icmp.InAddrMasks = &value + case "InAddrMaskReps": + procSnmp.Icmp.InAddrMaskReps = &value + case "OutMsgs": + procSnmp.Icmp.OutMsgs = &value + case "OutErrors": + procSnmp.Icmp.OutErrors = &value + case "OutDestUnreachs": + procSnmp.Icmp.OutDestUnreachs = &value + case "OutTimeExcds": + procSnmp.Icmp.OutTimeExcds = &value + case "OutParmProbs": + procSnmp.Icmp.OutParmProbs = &value + case "OutSrcQuenchs": + procSnmp.Icmp.OutSrcQuenchs = &value + case "OutRedirects": + procSnmp.Icmp.OutRedirects = &value + case "OutEchos": + procSnmp.Icmp.OutEchos = &value + case "OutEchoReps": + procSnmp.Icmp.OutEchoReps = &value + case "OutTimestamps": + procSnmp.Icmp.OutTimestamps = &value + case "OutTimestampReps": + procSnmp.Icmp.OutTimestampReps = &value + case "OutAddrMasks": + procSnmp.Icmp.OutAddrMasks = &value + case "OutAddrMaskReps": + procSnmp.Icmp.OutAddrMaskReps = &value + } + case "IcmpMsg": + switch key { + case "InType3": + procSnmp.IcmpMsg.InType3 = &value + case "OutType3": + procSnmp.IcmpMsg.OutType3 = &value + } + case "Tcp": + switch key { + case "RtoAlgorithm": + procSnmp.Tcp.RtoAlgorithm = &value + case "RtoMin": + procSnmp.Tcp.RtoMin = &value + case "RtoMax": + procSnmp.Tcp.RtoMax = &value + case "MaxConn": + procSnmp.Tcp.MaxConn = &value + case "ActiveOpens": + procSnmp.Tcp.ActiveOpens = &value + case "PassiveOpens": + procSnmp.Tcp.PassiveOpens = &value + case "AttemptFails": + procSnmp.Tcp.AttemptFails = &value + case "EstabResets": + procSnmp.Tcp.EstabResets = &value + case "CurrEstab": + procSnmp.Tcp.CurrEstab = &value + case "InSegs": + procSnmp.Tcp.InSegs = &value + case "OutSegs": + procSnmp.Tcp.OutSegs = &value + case "RetransSegs": + procSnmp.Tcp.RetransSegs = &value + case "InErrs": + procSnmp.Tcp.InErrs = &value + case "OutRsts": + procSnmp.Tcp.OutRsts = &value + case "InCsumErrors": + procSnmp.Tcp.InCsumErrors = &value + } + case "Udp": + switch key { + case "InDatagrams": + procSnmp.Udp.InDatagrams = &value + case "NoPorts": + procSnmp.Udp.NoPorts = &value + case "InErrors": + procSnmp.Udp.InErrors = &value + case "OutDatagrams": + procSnmp.Udp.OutDatagrams = &value + case "RcvbufErrors": + procSnmp.Udp.RcvbufErrors = &value + case "SndbufErrors": + procSnmp.Udp.SndbufErrors = &value + case "InCsumErrors": + procSnmp.Udp.InCsumErrors = &value + case "IgnoredMulti": + procSnmp.Udp.IgnoredMulti = &value + } + case "UdpLite": + switch key { + case "InDatagrams": + procSnmp.UdpLite.InDatagrams = &value + case "NoPorts": + procSnmp.UdpLite.NoPorts = &value + case "InErrors": + procSnmp.UdpLite.InErrors = &value + case "OutDatagrams": + procSnmp.UdpLite.OutDatagrams = &value + case "RcvbufErrors": + procSnmp.UdpLite.RcvbufErrors = &value + case "SndbufErrors": + procSnmp.UdpLite.SndbufErrors = &value + case "InCsumErrors": + procSnmp.UdpLite.InCsumErrors = &value + case "IgnoredMulti": + procSnmp.UdpLite.IgnoredMulti = &value + } + } + } + } + return procSnmp, scanner.Err() +} diff --git a/vendor/github.com/prometheus/procfs/proc_snmp6.go b/vendor/github.com/prometheus/procfs/proc_snmp6.go new file mode 100644 index 0000000000..3059cc6a13 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/proc_snmp6.go @@ -0,0 +1,381 @@ +// Copyright 2022 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package procfs + +import ( + "bufio" + "bytes" + "errors" + "io" + "os" + "strconv" + "strings" + + "github.com/prometheus/procfs/internal/util" +) + +// ProcSnmp6 models the content of /proc//net/snmp6. +type ProcSnmp6 struct { + // The process ID. + PID int + Ip6 + Icmp6 + Udp6 + UdpLite6 +} + +type Ip6 struct { // nolint:revive + InReceives *float64 + InHdrErrors *float64 + InTooBigErrors *float64 + InNoRoutes *float64 + InAddrErrors *float64 + InUnknownProtos *float64 + InTruncatedPkts *float64 + InDiscards *float64 + InDelivers *float64 + OutForwDatagrams *float64 + OutRequests *float64 + OutDiscards *float64 + OutNoRoutes *float64 + ReasmTimeout *float64 + ReasmReqds *float64 + ReasmOKs *float64 + ReasmFails *float64 + FragOKs *float64 + FragFails *float64 + FragCreates *float64 + InMcastPkts *float64 + OutMcastPkts *float64 + InOctets *float64 + OutOctets *float64 + InMcastOctets *float64 + OutMcastOctets *float64 + InBcastOctets *float64 + OutBcastOctets *float64 + InNoECTPkts *float64 + InECT1Pkts *float64 + InECT0Pkts *float64 + InCEPkts *float64 +} + +type Icmp6 struct { + InMsgs *float64 + InErrors *float64 + OutMsgs *float64 + OutErrors *float64 + InCsumErrors *float64 + InDestUnreachs *float64 + InPktTooBigs *float64 + InTimeExcds *float64 + InParmProblems *float64 + InEchos *float64 + InEchoReplies *float64 + InGroupMembQueries *float64 + InGroupMembResponses *float64 + InGroupMembReductions *float64 + InRouterSolicits *float64 + InRouterAdvertisements *float64 + InNeighborSolicits *float64 + InNeighborAdvertisements *float64 + InRedirects *float64 + InMLDv2Reports *float64 + OutDestUnreachs *float64 + OutPktTooBigs *float64 + OutTimeExcds *float64 + OutParmProblems *float64 + OutEchos *float64 + OutEchoReplies *float64 + OutGroupMembQueries *float64 + OutGroupMembResponses *float64 + OutGroupMembReductions *float64 + OutRouterSolicits *float64 + OutRouterAdvertisements *float64 + OutNeighborSolicits *float64 + OutNeighborAdvertisements *float64 + OutRedirects *float64 + OutMLDv2Reports *float64 + InType1 *float64 + InType134 *float64 + InType135 *float64 + InType136 *float64 + InType143 *float64 + OutType133 *float64 + OutType135 *float64 + OutType136 *float64 + OutType143 *float64 +} + +type Udp6 struct { // nolint:revive + InDatagrams *float64 + NoPorts *float64 + InErrors *float64 + OutDatagrams *float64 + RcvbufErrors *float64 + SndbufErrors *float64 + InCsumErrors *float64 + IgnoredMulti *float64 +} + +type UdpLite6 struct { // nolint:revive + InDatagrams *float64 + NoPorts *float64 + InErrors *float64 + OutDatagrams *float64 + RcvbufErrors *float64 + SndbufErrors *float64 + InCsumErrors *float64 +} + +func (p Proc) Snmp6() (ProcSnmp6, error) { + filename := p.path("net/snmp6") + data, err := util.ReadFileNoStat(filename) + if err != nil { + // On systems with IPv6 disabled, this file won't exist. + // Do nothing. + if errors.Is(err, os.ErrNotExist) { + return ProcSnmp6{PID: p.PID}, nil + } + + return ProcSnmp6{PID: p.PID}, err + } + + procSnmp6, err := parseSNMP6Stats(bytes.NewReader(data)) + procSnmp6.PID = p.PID + return procSnmp6, err +} + +// parseSnmp6 parses the metrics from proc//net/snmp6 file +// and returns a map contains those metrics. +func parseSNMP6Stats(r io.Reader) (ProcSnmp6, error) { + var ( + scanner = bufio.NewScanner(r) + procSnmp6 = ProcSnmp6{} + ) + + for scanner.Scan() { + stat := strings.Fields(scanner.Text()) + if len(stat) < 2 { + continue + } + // Expect to have "6" in metric name, skip line otherwise + if sixIndex := strings.Index(stat[0], "6"); sixIndex != -1 { + protocol := stat[0][:sixIndex+1] + key := stat[0][sixIndex+1:] + value, err := strconv.ParseFloat(stat[1], 64) + if err != nil { + return procSnmp6, err + } + + switch protocol { + case "Ip6": + switch key { + case "InReceives": + procSnmp6.Ip6.InReceives = &value + case "InHdrErrors": + procSnmp6.Ip6.InHdrErrors = &value + case "InTooBigErrors": + procSnmp6.Ip6.InTooBigErrors = &value + case "InNoRoutes": + procSnmp6.Ip6.InNoRoutes = &value + case "InAddrErrors": + procSnmp6.Ip6.InAddrErrors = &value + case "InUnknownProtos": + procSnmp6.Ip6.InUnknownProtos = &value + case "InTruncatedPkts": + procSnmp6.Ip6.InTruncatedPkts = &value + case "InDiscards": + procSnmp6.Ip6.InDiscards = &value + case "InDelivers": + procSnmp6.Ip6.InDelivers = &value + case "OutForwDatagrams": + procSnmp6.Ip6.OutForwDatagrams = &value + case "OutRequests": + procSnmp6.Ip6.OutRequests = &value + case "OutDiscards": + procSnmp6.Ip6.OutDiscards = &value + case "OutNoRoutes": + procSnmp6.Ip6.OutNoRoutes = &value + case "ReasmTimeout": + procSnmp6.Ip6.ReasmTimeout = &value + case "ReasmReqds": + procSnmp6.Ip6.ReasmReqds = &value + case "ReasmOKs": + procSnmp6.Ip6.ReasmOKs = &value + case "ReasmFails": + procSnmp6.Ip6.ReasmFails = &value + case "FragOKs": + procSnmp6.Ip6.FragOKs = &value + case "FragFails": + procSnmp6.Ip6.FragFails = &value + case "FragCreates": + procSnmp6.Ip6.FragCreates = &value + case "InMcastPkts": + procSnmp6.Ip6.InMcastPkts = &value + case "OutMcastPkts": + procSnmp6.Ip6.OutMcastPkts = &value + case "InOctets": + procSnmp6.Ip6.InOctets = &value + case "OutOctets": + procSnmp6.Ip6.OutOctets = &value + case "InMcastOctets": + procSnmp6.Ip6.InMcastOctets = &value + case "OutMcastOctets": + procSnmp6.Ip6.OutMcastOctets = &value + case "InBcastOctets": + procSnmp6.Ip6.InBcastOctets = &value + case "OutBcastOctets": + procSnmp6.Ip6.OutBcastOctets = &value + case "InNoECTPkts": + procSnmp6.Ip6.InNoECTPkts = &value + case "InECT1Pkts": + procSnmp6.Ip6.InECT1Pkts = &value + case "InECT0Pkts": + procSnmp6.Ip6.InECT0Pkts = &value + case "InCEPkts": + procSnmp6.Ip6.InCEPkts = &value + + } + case "Icmp6": + switch key { + case "InMsgs": + procSnmp6.Icmp6.InMsgs = &value + case "InErrors": + procSnmp6.Icmp6.InErrors = &value + case "OutMsgs": + procSnmp6.Icmp6.OutMsgs = &value + case "OutErrors": + procSnmp6.Icmp6.OutErrors = &value + case "InCsumErrors": + procSnmp6.Icmp6.InCsumErrors = &value + case "InDestUnreachs": + procSnmp6.Icmp6.InDestUnreachs = &value + case "InPktTooBigs": + procSnmp6.Icmp6.InPktTooBigs = &value + case "InTimeExcds": + procSnmp6.Icmp6.InTimeExcds = &value + case "InParmProblems": + procSnmp6.Icmp6.InParmProblems = &value + case "InEchos": + procSnmp6.Icmp6.InEchos = &value + case "InEchoReplies": + procSnmp6.Icmp6.InEchoReplies = &value + case "InGroupMembQueries": + procSnmp6.Icmp6.InGroupMembQueries = &value + case "InGroupMembResponses": + procSnmp6.Icmp6.InGroupMembResponses = &value + case "InGroupMembReductions": + procSnmp6.Icmp6.InGroupMembReductions = &value + case "InRouterSolicits": + procSnmp6.Icmp6.InRouterSolicits = &value + case "InRouterAdvertisements": + procSnmp6.Icmp6.InRouterAdvertisements = &value + case "InNeighborSolicits": + procSnmp6.Icmp6.InNeighborSolicits = &value + case "InNeighborAdvertisements": + procSnmp6.Icmp6.InNeighborAdvertisements = &value + case "InRedirects": + procSnmp6.Icmp6.InRedirects = &value + case "InMLDv2Reports": + procSnmp6.Icmp6.InMLDv2Reports = &value + case "OutDestUnreachs": + procSnmp6.Icmp6.OutDestUnreachs = &value + case "OutPktTooBigs": + procSnmp6.Icmp6.OutPktTooBigs = &value + case "OutTimeExcds": + procSnmp6.Icmp6.OutTimeExcds = &value + case "OutParmProblems": + procSnmp6.Icmp6.OutParmProblems = &value + case "OutEchos": + procSnmp6.Icmp6.OutEchos = &value + case "OutEchoReplies": + procSnmp6.Icmp6.OutEchoReplies = &value + case "OutGroupMembQueries": + procSnmp6.Icmp6.OutGroupMembQueries = &value + case "OutGroupMembResponses": + procSnmp6.Icmp6.OutGroupMembResponses = &value + case "OutGroupMembReductions": + procSnmp6.Icmp6.OutGroupMembReductions = &value + case "OutRouterSolicits": + procSnmp6.Icmp6.OutRouterSolicits = &value + case "OutRouterAdvertisements": + procSnmp6.Icmp6.OutRouterAdvertisements = &value + case "OutNeighborSolicits": + procSnmp6.Icmp6.OutNeighborSolicits = &value + case "OutNeighborAdvertisements": + procSnmp6.Icmp6.OutNeighborAdvertisements = &value + case "OutRedirects": + procSnmp6.Icmp6.OutRedirects = &value + case "OutMLDv2Reports": + procSnmp6.Icmp6.OutMLDv2Reports = &value + case "InType1": + procSnmp6.Icmp6.InType1 = &value + case "InType134": + procSnmp6.Icmp6.InType134 = &value + case "InType135": + procSnmp6.Icmp6.InType135 = &value + case "InType136": + procSnmp6.Icmp6.InType136 = &value + case "InType143": + procSnmp6.Icmp6.InType143 = &value + case "OutType133": + procSnmp6.Icmp6.OutType133 = &value + case "OutType135": + procSnmp6.Icmp6.OutType135 = &value + case "OutType136": + procSnmp6.Icmp6.OutType136 = &value + case "OutType143": + procSnmp6.Icmp6.OutType143 = &value + } + case "Udp6": + switch key { + case "InDatagrams": + procSnmp6.Udp6.InDatagrams = &value + case "NoPorts": + procSnmp6.Udp6.NoPorts = &value + case "InErrors": + procSnmp6.Udp6.InErrors = &value + case "OutDatagrams": + procSnmp6.Udp6.OutDatagrams = &value + case "RcvbufErrors": + procSnmp6.Udp6.RcvbufErrors = &value + case "SndbufErrors": + procSnmp6.Udp6.SndbufErrors = &value + case "InCsumErrors": + procSnmp6.Udp6.InCsumErrors = &value + case "IgnoredMulti": + procSnmp6.Udp6.IgnoredMulti = &value + } + case "UdpLite6": + switch key { + case "InDatagrams": + procSnmp6.UdpLite6.InDatagrams = &value + case "NoPorts": + procSnmp6.UdpLite6.NoPorts = &value + case "InErrors": + procSnmp6.UdpLite6.InErrors = &value + case "OutDatagrams": + procSnmp6.UdpLite6.OutDatagrams = &value + case "RcvbufErrors": + procSnmp6.UdpLite6.RcvbufErrors = &value + case "SndbufErrors": + procSnmp6.UdpLite6.SndbufErrors = &value + case "InCsumErrors": + procSnmp6.UdpLite6.InCsumErrors = &value + } + } + } + } + return procSnmp6, scanner.Err() +} diff --git a/vendor/github.com/prometheus/procfs/proc_stat.go b/vendor/github.com/prometheus/procfs/proc_stat.go index 8c7b6e80a3..b278eb2c2d 100644 --- a/vendor/github.com/prometheus/procfs/proc_stat.go +++ b/vendor/github.com/prometheus/procfs/proc_stat.go @@ -81,10 +81,10 @@ type ProcStat struct { STime uint // Amount of time that this process's waited-for children have been // scheduled in user mode, measured in clock ticks. - CUTime uint + CUTime int // Amount of time that this process's waited-for children have been // scheduled in kernel mode, measured in clock ticks. - CSTime uint + CSTime int // For processes running a real-time scheduling policy, this is the negated // scheduling priority, minus one. Priority int @@ -102,6 +102,8 @@ type ProcStat struct { RSS int // Soft limit in bytes on the rss of the process. RSSLimit uint64 + // CPU number last executed on. + Processor uint // Real-time scheduling priority, a number in the range 1 to 99 for processes // scheduled under a real-time policy, or 0, for non-real-time processes. RTPriority uint @@ -115,7 +117,7 @@ type ProcStat struct { // NewStat returns the current status information of the process. // -// Deprecated: use p.Stat() instead +// Deprecated: Use p.Stat() instead. func (p Proc) NewStat() (ProcStat, error) { return p.Stat() } @@ -141,6 +143,11 @@ func (p Proc) Stat() (ProcStat, error) { } s.Comm = string(data[l+1 : r]) + + // Check the following resources for the details about the particular stat + // fields and their data types: + // * https://man7.org/linux/man-pages/man5/proc.5.html + // * https://man7.org/linux/man-pages/man3/scanf.3.html _, err = fmt.Fscan( bytes.NewBuffer(data[r+2:]), &s.State, @@ -179,7 +186,7 @@ func (p Proc) Stat() (ProcStat, error) { &ignoreUint64, &ignoreUint64, &ignoreInt64, - &ignoreInt64, + &s.Processor, &s.RTPriority, &s.Policy, &s.DelayAcctBlkIOTicks, diff --git a/vendor/github.com/prometheus/procfs/proc_status.go b/vendor/github.com/prometheus/procfs/proc_status.go index 6edd8333b3..3d8c06439a 100644 --- a/vendor/github.com/prometheus/procfs/proc_status.go +++ b/vendor/github.com/prometheus/procfs/proc_status.go @@ -33,37 +33,37 @@ type ProcStatus struct { TGID int // Peak virtual memory size. - VmPeak uint64 // nolint:golint + VmPeak uint64 // nolint:revive // Virtual memory size. - VmSize uint64 // nolint:golint + VmSize uint64 // nolint:revive // Locked memory size. - VmLck uint64 // nolint:golint + VmLck uint64 // nolint:revive // Pinned memory size. - VmPin uint64 // nolint:golint + VmPin uint64 // nolint:revive // Peak resident set size. - VmHWM uint64 // nolint:golint + VmHWM uint64 // nolint:revive // Resident set size (sum of RssAnnon RssFile and RssShmem). - VmRSS uint64 // nolint:golint + VmRSS uint64 // nolint:revive // Size of resident anonymous memory. - RssAnon uint64 // nolint:golint + RssAnon uint64 // nolint:revive // Size of resident file mappings. - RssFile uint64 // nolint:golint + RssFile uint64 // nolint:revive // Size of resident shared memory. - RssShmem uint64 // nolint:golint + RssShmem uint64 // nolint:revive // Size of data segments. - VmData uint64 // nolint:golint + VmData uint64 // nolint:revive // Size of stack segments. - VmStk uint64 // nolint:golint + VmStk uint64 // nolint:revive // Size of text segments. - VmExe uint64 // nolint:golint + VmExe uint64 // nolint:revive // Shared library code size. - VmLib uint64 // nolint:golint + VmLib uint64 // nolint:revive // Page table entries size. - VmPTE uint64 // nolint:golint + VmPTE uint64 // nolint:revive // Size of second-level page tables. - VmPMD uint64 // nolint:golint + VmPMD uint64 // nolint:revive // Swapped-out virtual memory size by anonymous private. - VmSwap uint64 // nolint:golint + VmSwap uint64 // nolint:revive // Size of hugetlb memory portions HugetlbPages uint64 @@ -96,10 +96,10 @@ func (p Proc) NewStatus() (ProcStatus, error) { kv := strings.SplitN(line, ":", 2) // removes spaces - k := string(strings.TrimSpace(kv[0])) - v := string(strings.TrimSpace(kv[1])) + k := strings.TrimSpace(kv[0]) + v := strings.TrimSpace(kv[1]) // removes "kB" - v = string(bytes.Trim([]byte(v), " kB")) + v = strings.TrimSuffix(v, " kB") // value to int when possible // we can skip error check here, 'cause vKBytes is not used when value is a string diff --git a/vendor/github.com/prometheus/procfs/proc_sys.go b/vendor/github.com/prometheus/procfs/proc_sys.go new file mode 100644 index 0000000000..d46533ebf4 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/proc_sys.go @@ -0,0 +1,51 @@ +// Copyright 2022 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package procfs + +import ( + "fmt" + "strings" + + "github.com/prometheus/procfs/internal/util" +) + +func sysctlToPath(sysctl string) string { + return strings.Replace(sysctl, ".", "/", -1) +} + +func (fs FS) SysctlStrings(sysctl string) ([]string, error) { + value, err := util.SysReadFile(fs.proc.Path("sys", sysctlToPath(sysctl))) + if err != nil { + return nil, err + } + return strings.Fields(value), nil + +} + +func (fs FS) SysctlInts(sysctl string) ([]int, error) { + fields, err := fs.SysctlStrings(sysctl) + if err != nil { + return nil, err + } + + values := make([]int, len(fields)) + for i, f := range fields { + vp := util.NewValueParser(f) + values[i] = vp.Int() + if err := vp.Err(); err != nil { + return nil, fmt.Errorf("field %d in sysctl %s is not a valid int: %w", i, sysctl, err) + } + } + return values, nil +} diff --git a/vendor/github.com/prometheus/procfs/schedstat.go b/vendor/github.com/prometheus/procfs/schedstat.go index 28228164ef..5f7f32dc83 100644 --- a/vendor/github.com/prometheus/procfs/schedstat.go +++ b/vendor/github.com/prometheus/procfs/schedstat.go @@ -40,7 +40,7 @@ type Schedstat struct { CPUs []*SchedstatCPU } -// SchedstatCPU contains the values from one "cpu" line +// SchedstatCPU contains the values from one "cpu" line. type SchedstatCPU struct { CPUNum string @@ -49,14 +49,14 @@ type SchedstatCPU struct { RunTimeslices uint64 } -// ProcSchedstat contains the values from /proc//schedstat +// ProcSchedstat contains the values from `/proc//schedstat`. type ProcSchedstat struct { RunningNanoseconds uint64 WaitingNanoseconds uint64 RunTimeslices uint64 } -// Schedstat reads data from /proc/schedstat +// Schedstat reads data from `/proc/schedstat`. func (fs FS) Schedstat() (*Schedstat, error) { file, err := os.Open(fs.proc.Path("schedstat")) if err != nil { diff --git a/vendor/github.com/prometheus/procfs/slab.go b/vendor/github.com/prometheus/procfs/slab.go index 7896fd7242..bc9aaf5c28 100644 --- a/vendor/github.com/prometheus/procfs/slab.go +++ b/vendor/github.com/prometheus/procfs/slab.go @@ -137,7 +137,7 @@ func parseSlabInfo21(r *bytes.Reader) (SlabInfo, error) { return s, nil } -// SlabInfo reads data from /proc/slabinfo +// SlabInfo reads data from `/proc/slabinfo`. func (fs FS) SlabInfo() (SlabInfo, error) { // TODO: Consider passing options to allow for parsing different // slabinfo versions. However, slabinfo 2.1 has been stable since diff --git a/vendor/github.com/prometheus/procfs/softirqs.go b/vendor/github.com/prometheus/procfs/softirqs.go new file mode 100644 index 0000000000..559129cbca --- /dev/null +++ b/vendor/github.com/prometheus/procfs/softirqs.go @@ -0,0 +1,160 @@ +// Copyright 2022 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package procfs + +import ( + "bufio" + "bytes" + "fmt" + "io" + "strconv" + "strings" + + "github.com/prometheus/procfs/internal/util" +) + +// Softirqs represents the softirq statistics. +type Softirqs struct { + Hi []uint64 + Timer []uint64 + NetTx []uint64 + NetRx []uint64 + Block []uint64 + IRQPoll []uint64 + Tasklet []uint64 + Sched []uint64 + HRTimer []uint64 + RCU []uint64 +} + +func (fs FS) Softirqs() (Softirqs, error) { + fileName := fs.proc.Path("softirqs") + data, err := util.ReadFileNoStat(fileName) + if err != nil { + return Softirqs{}, err + } + + reader := bytes.NewReader(data) + + return parseSoftirqs(reader) +} + +func parseSoftirqs(r io.Reader) (Softirqs, error) { + var ( + softirqs = Softirqs{} + scanner = bufio.NewScanner(r) + ) + + if !scanner.Scan() { + return Softirqs{}, fmt.Errorf("softirqs empty") + } + + for scanner.Scan() { + parts := strings.Fields(scanner.Text()) + var err error + + // require at least one cpu + if len(parts) < 2 { + continue + } + switch { + case parts[0] == "HI:": + perCPU := parts[1:] + softirqs.Hi = make([]uint64, len(perCPU)) + for i, count := range perCPU { + if softirqs.Hi[i], err = strconv.ParseUint(count, 10, 64); err != nil { + return Softirqs{}, fmt.Errorf("couldn't parse %q (HI%d): %w", count, i, err) + } + } + case parts[0] == "TIMER:": + perCPU := parts[1:] + softirqs.Timer = make([]uint64, len(perCPU)) + for i, count := range perCPU { + if softirqs.Timer[i], err = strconv.ParseUint(count, 10, 64); err != nil { + return Softirqs{}, fmt.Errorf("couldn't parse %q (TIMER%d): %w", count, i, err) + } + } + case parts[0] == "NET_TX:": + perCPU := parts[1:] + softirqs.NetTx = make([]uint64, len(perCPU)) + for i, count := range perCPU { + if softirqs.NetTx[i], err = strconv.ParseUint(count, 10, 64); err != nil { + return Softirqs{}, fmt.Errorf("couldn't parse %q (NET_TX%d): %w", count, i, err) + } + } + case parts[0] == "NET_RX:": + perCPU := parts[1:] + softirqs.NetRx = make([]uint64, len(perCPU)) + for i, count := range perCPU { + if softirqs.NetRx[i], err = strconv.ParseUint(count, 10, 64); err != nil { + return Softirqs{}, fmt.Errorf("couldn't parse %q (NET_RX%d): %w", count, i, err) + } + } + case parts[0] == "BLOCK:": + perCPU := parts[1:] + softirqs.Block = make([]uint64, len(perCPU)) + for i, count := range perCPU { + if softirqs.Block[i], err = strconv.ParseUint(count, 10, 64); err != nil { + return Softirqs{}, fmt.Errorf("couldn't parse %q (BLOCK%d): %w", count, i, err) + } + } + case parts[0] == "IRQ_POLL:": + perCPU := parts[1:] + softirqs.IRQPoll = make([]uint64, len(perCPU)) + for i, count := range perCPU { + if softirqs.IRQPoll[i], err = strconv.ParseUint(count, 10, 64); err != nil { + return Softirqs{}, fmt.Errorf("couldn't parse %q (IRQ_POLL%d): %w", count, i, err) + } + } + case parts[0] == "TASKLET:": + perCPU := parts[1:] + softirqs.Tasklet = make([]uint64, len(perCPU)) + for i, count := range perCPU { + if softirqs.Tasklet[i], err = strconv.ParseUint(count, 10, 64); err != nil { + return Softirqs{}, fmt.Errorf("couldn't parse %q (TASKLET%d): %w", count, i, err) + } + } + case parts[0] == "SCHED:": + perCPU := parts[1:] + softirqs.Sched = make([]uint64, len(perCPU)) + for i, count := range perCPU { + if softirqs.Sched[i], err = strconv.ParseUint(count, 10, 64); err != nil { + return Softirqs{}, fmt.Errorf("couldn't parse %q (SCHED%d): %w", count, i, err) + } + } + case parts[0] == "HRTIMER:": + perCPU := parts[1:] + softirqs.HRTimer = make([]uint64, len(perCPU)) + for i, count := range perCPU { + if softirqs.HRTimer[i], err = strconv.ParseUint(count, 10, 64); err != nil { + return Softirqs{}, fmt.Errorf("couldn't parse %q (HRTIMER%d): %w", count, i, err) + } + } + case parts[0] == "RCU:": + perCPU := parts[1:] + softirqs.RCU = make([]uint64, len(perCPU)) + for i, count := range perCPU { + if softirqs.RCU[i], err = strconv.ParseUint(count, 10, 64); err != nil { + return Softirqs{}, fmt.Errorf("couldn't parse %q (RCU%d): %w", count, i, err) + } + } + } + } + + if err := scanner.Err(); err != nil { + return Softirqs{}, fmt.Errorf("couldn't parse softirqs: %w", err) + } + + return softirqs, scanner.Err() +} diff --git a/vendor/github.com/prometheus/procfs/stat.go b/vendor/github.com/prometheus/procfs/stat.go index 6d8727541e..586af48af9 100644 --- a/vendor/github.com/prometheus/procfs/stat.go +++ b/vendor/github.com/prometheus/procfs/stat.go @@ -41,7 +41,7 @@ type CPUStat struct { // SoftIRQStat represent the softirq statistics as exported in the procfs stat file. // A nice introduction can be found at https://0xax.gitbooks.io/linux-insides/content/interrupts/interrupts-9.html -// It is possible to get per-cpu stats by reading /proc/softirqs +// It is possible to get per-cpu stats by reading `/proc/softirqs`. type SoftIRQStat struct { Hi uint64 Timer uint64 @@ -62,7 +62,7 @@ type Stat struct { // Summed up cpu statistics. CPUTotal CPUStat // Per-CPU statistics. - CPU []CPUStat + CPU map[int64]CPUStat // Number of times interrupts were handled, which contains numbered and unnumbered IRQs. IRQTotal uint64 // Number of times a numbered IRQ was triggered. @@ -145,7 +145,7 @@ func parseSoftIRQStat(line string) (SoftIRQStat, uint64, error) { // NewStat returns information about current cpu/process statistics. // See https://www.kernel.org/doc/Documentation/filesystems/proc.txt // -// Deprecated: use fs.Stat() instead +// Deprecated: Use fs.Stat() instead. func NewStat() (Stat, error) { fs, err := NewFS(fs.DefaultProcMountPoint) if err != nil { @@ -155,25 +155,38 @@ func NewStat() (Stat, error) { } // NewStat returns information about current cpu/process statistics. -// See https://www.kernel.org/doc/Documentation/filesystems/proc.txt +// See: https://www.kernel.org/doc/Documentation/filesystems/proc.txt // -// Deprecated: use fs.Stat() instead +// Deprecated: Use fs.Stat() instead. func (fs FS) NewStat() (Stat, error) { return fs.Stat() } // Stat returns information about current cpu/process statistics. -// See https://www.kernel.org/doc/Documentation/filesystems/proc.txt +// See: https://www.kernel.org/doc/Documentation/filesystems/proc.txt func (fs FS) Stat() (Stat, error) { fileName := fs.proc.Path("stat") data, err := util.ReadFileNoStat(fileName) if err != nil { return Stat{}, err } + procStat, err := parseStat(bytes.NewReader(data), fileName) + if err != nil { + return Stat{}, err + } + return procStat, nil +} - stat := Stat{} +// parseStat parses the metrics from /proc/[pid]/stat. +func parseStat(r io.Reader, fileName string) (Stat, error) { + var ( + scanner = bufio.NewScanner(r) + stat = Stat{ + CPU: make(map[int64]CPUStat), + } + err error + ) - scanner := bufio.NewScanner(bytes.NewReader(data)) for scanner.Scan() { line := scanner.Text() parts := strings.Fields(scanner.Text()) @@ -228,9 +241,6 @@ func (fs FS) Stat() (Stat, error) { if cpuID == -1 { stat.CPUTotal = cpuStat } else { - for int64(len(stat.CPU)) <= cpuID { - stat.CPU = append(stat.CPU, CPUStat{}) - } stat.CPU[cpuID] = cpuStat } } diff --git a/vendor/github.com/prometheus/procfs/thread.go b/vendor/github.com/prometheus/procfs/thread.go new file mode 100644 index 0000000000..f08bfc769d --- /dev/null +++ b/vendor/github.com/prometheus/procfs/thread.go @@ -0,0 +1,79 @@ +// Copyright 2022 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package procfs + +import ( + "fmt" + "os" + "strconv" + + fsi "github.com/prometheus/procfs/internal/fs" +) + +// Provide access to /proc/PID/task/TID files, for thread specific values. Since +// such files have the same structure as /proc/PID/ ones, the data structures +// and the parsers for the latter may be reused. + +// AllThreads returns a list of all currently available threads under /proc/PID. +func AllThreads(pid int) (Procs, error) { + fs, err := NewFS(DefaultMountPoint) + if err != nil { + return Procs{}, err + } + return fs.AllThreads(pid) +} + +// AllThreads returns a list of all currently available threads for PID. +func (fs FS) AllThreads(pid int) (Procs, error) { + taskPath := fs.proc.Path(strconv.Itoa(pid), "task") + d, err := os.Open(taskPath) + if err != nil { + return Procs{}, err + } + defer d.Close() + + names, err := d.Readdirnames(-1) + if err != nil { + return Procs{}, fmt.Errorf("could not read %q: %w", d.Name(), err) + } + + t := Procs{} + for _, n := range names { + tid, err := strconv.ParseInt(n, 10, 64) + if err != nil { + continue + } + t = append(t, Proc{PID: int(tid), fs: fsi.FS(taskPath)}) + } + + return t, nil +} + +// Thread returns a process for a given PID, TID. +func (fs FS) Thread(pid, tid int) (Proc, error) { + taskPath := fs.proc.Path(strconv.Itoa(pid), "task") + if _, err := os.Stat(taskPath); err != nil { + return Proc{}, err + } + return Proc{PID: tid, fs: fsi.FS(taskPath)}, nil +} + +// Thread returns a process for a given TID of Proc. +func (proc Proc) Thread(tid int) (Proc, error) { + tfs := fsi.FS(proc.path("task")) + if _, err := os.Stat(tfs.Path(strconv.Itoa(tid))); err != nil { + return Proc{}, err + } + return Proc{PID: tid, fs: tfs}, nil +} diff --git a/vendor/github.com/prometheus/procfs/vm.go b/vendor/github.com/prometheus/procfs/vm.go index cb13891414..cdedcae996 100644 --- a/vendor/github.com/prometheus/procfs/vm.go +++ b/vendor/github.com/prometheus/procfs/vm.go @@ -11,13 +11,13 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !windows // +build !windows package procfs import ( "fmt" - "io/ioutil" "os" "path/filepath" "strings" @@ -26,10 +26,12 @@ import ( ) // The VM interface is described at -// https://www.kernel.org/doc/Documentation/sysctl/vm.txt +// +// https://www.kernel.org/doc/Documentation/sysctl/vm.txt +// // Each setting is exposed as a single file. // Each file contains one line with a single numerical value, except lowmem_reserve_ratio which holds an array -// and numa_zonelist_order (deprecated) which is a string +// and numa_zonelist_order (deprecated) which is a string. type VM struct { AdminReserveKbytes *int64 // /proc/sys/vm/admin_reserve_kbytes BlockDump *int64 // /proc/sys/vm/block_dump @@ -87,7 +89,7 @@ func (fs FS) VM() (*VM, error) { return nil, fmt.Errorf("%s is not a directory", path) } - files, err := ioutil.ReadDir(path) + files, err := os.ReadDir(path) if err != nil { return nil, err } diff --git a/vendor/github.com/prometheus/procfs/xfrm.go b/vendor/github.com/prometheus/procfs/xfrm.go deleted file mode 100644 index eed07c7d77..0000000000 --- a/vendor/github.com/prometheus/procfs/xfrm.go +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright 2017 Prometheus Team -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package procfs - -import ( - "bufio" - "fmt" - "os" - "strconv" - "strings" -) - -// XfrmStat models the contents of /proc/net/xfrm_stat. -type XfrmStat struct { - // All errors which are not matched by other - XfrmInError int - // No buffer is left - XfrmInBufferError int - // Header Error - XfrmInHdrError int - // No state found - // i.e. either inbound SPI, address, or IPSEC protocol at SA is wrong - XfrmInNoStates int - // Transformation protocol specific error - // e.g. SA Key is wrong - XfrmInStateProtoError int - // Transformation mode specific error - XfrmInStateModeError int - // Sequence error - // e.g. sequence number is out of window - XfrmInStateSeqError int - // State is expired - XfrmInStateExpired int - // State has mismatch option - // e.g. UDP encapsulation type is mismatched - XfrmInStateMismatch int - // State is invalid - XfrmInStateInvalid int - // No matching template for states - // e.g. Inbound SAs are correct but SP rule is wrong - XfrmInTmplMismatch int - // No policy is found for states - // e.g. Inbound SAs are correct but no SP is found - XfrmInNoPols int - // Policy discards - XfrmInPolBlock int - // Policy error - XfrmInPolError int - // All errors which are not matched by others - XfrmOutError int - // Bundle generation error - XfrmOutBundleGenError int - // Bundle check error - XfrmOutBundleCheckError int - // No state was found - XfrmOutNoStates int - // Transformation protocol specific error - XfrmOutStateProtoError int - // Transportation mode specific error - XfrmOutStateModeError int - // Sequence error - // i.e sequence number overflow - XfrmOutStateSeqError int - // State is expired - XfrmOutStateExpired int - // Policy discads - XfrmOutPolBlock int - // Policy is dead - XfrmOutPolDead int - // Policy Error - XfrmOutPolError int - XfrmFwdHdrError int - XfrmOutStateInvalid int - XfrmAcquireError int -} - -// NewXfrmStat reads the xfrm_stat statistics. -func NewXfrmStat() (XfrmStat, error) { - fs, err := NewFS(DefaultMountPoint) - if err != nil { - return XfrmStat{}, err - } - - return fs.NewXfrmStat() -} - -// NewXfrmStat reads the xfrm_stat statistics from the 'proc' filesystem. -func (fs FS) NewXfrmStat() (XfrmStat, error) { - file, err := os.Open(fs.proc.Path("net/xfrm_stat")) - if err != nil { - return XfrmStat{}, err - } - defer file.Close() - - var ( - x = XfrmStat{} - s = bufio.NewScanner(file) - ) - - for s.Scan() { - fields := strings.Fields(s.Text()) - - if len(fields) != 2 { - return XfrmStat{}, fmt.Errorf("couldn't parse %q line %q", file.Name(), s.Text()) - } - - name := fields[0] - value, err := strconv.Atoi(fields[1]) - if err != nil { - return XfrmStat{}, err - } - - switch name { - case "XfrmInError": - x.XfrmInError = value - case "XfrmInBufferError": - x.XfrmInBufferError = value - case "XfrmInHdrError": - x.XfrmInHdrError = value - case "XfrmInNoStates": - x.XfrmInNoStates = value - case "XfrmInStateProtoError": - x.XfrmInStateProtoError = value - case "XfrmInStateModeError": - x.XfrmInStateModeError = value - case "XfrmInStateSeqError": - x.XfrmInStateSeqError = value - case "XfrmInStateExpired": - x.XfrmInStateExpired = value - case "XfrmInStateInvalid": - x.XfrmInStateInvalid = value - case "XfrmInTmplMismatch": - x.XfrmInTmplMismatch = value - case "XfrmInNoPols": - x.XfrmInNoPols = value - case "XfrmInPolBlock": - x.XfrmInPolBlock = value - case "XfrmInPolError": - x.XfrmInPolError = value - case "XfrmOutError": - x.XfrmOutError = value - case "XfrmInStateMismatch": - x.XfrmInStateMismatch = value - case "XfrmOutBundleGenError": - x.XfrmOutBundleGenError = value - case "XfrmOutBundleCheckError": - x.XfrmOutBundleCheckError = value - case "XfrmOutNoStates": - x.XfrmOutNoStates = value - case "XfrmOutStateProtoError": - x.XfrmOutStateProtoError = value - case "XfrmOutStateModeError": - x.XfrmOutStateModeError = value - case "XfrmOutStateSeqError": - x.XfrmOutStateSeqError = value - case "XfrmOutStateExpired": - x.XfrmOutStateExpired = value - case "XfrmOutPolBlock": - x.XfrmOutPolBlock = value - case "XfrmOutPolDead": - x.XfrmOutPolDead = value - case "XfrmOutPolError": - x.XfrmOutPolError = value - case "XfrmFwdHdrError": - x.XfrmFwdHdrError = value - case "XfrmOutStateInvalid": - x.XfrmOutStateInvalid = value - case "XfrmAcquireError": - x.XfrmAcquireError = value - } - - } - - return x, s.Err() -} diff --git a/vendor/github.com/prometheus/procfs/zoneinfo.go b/vendor/github.com/prometheus/procfs/zoneinfo.go index 209e2ac987..c745a4c04f 100644 --- a/vendor/github.com/prometheus/procfs/zoneinfo.go +++ b/vendor/github.com/prometheus/procfs/zoneinfo.go @@ -11,6 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !windows // +build !windows package procfs @@ -18,7 +19,7 @@ package procfs import ( "bytes" "fmt" - "io/ioutil" + "os" "regexp" "strings" @@ -72,7 +73,7 @@ var nodeZoneRE = regexp.MustCompile(`(\d+), zone\s+(\w+)`) // structs containing the relevant info. More information available here: // https://www.kernel.org/doc/Documentation/sysctl/vm.txt func (fs FS) Zoneinfo() ([]Zoneinfo, error) { - data, err := ioutil.ReadFile(fs.proc.Path("zoneinfo")) + data, err := os.ReadFile(fs.proc.Path("zoneinfo")) if err != nil { return nil, fmt.Errorf("error reading zoneinfo %q: %w", fs.proc.Path("zoneinfo"), err) } diff --git a/vendor/github.com/rubenv/sql-migrate/README.md b/vendor/github.com/rubenv/sql-migrate/README.md index c954aa8956..56585233b6 100644 --- a/vendor/github.com/rubenv/sql-migrate/README.md +++ b/vendor/github.com/rubenv/sql-migrate/README.md @@ -24,6 +24,10 @@ To install the library and command line program, use the following: ```bash go get -v github.com/rubenv/sql-migrate/... ``` +For Go version from 1.18, use: +```bash +go install github.com/rubenv/sql-migrate/...@latest +``` ## Usage diff --git a/vendor/github.com/russross/blackfriday/.gitignore b/vendor/github.com/russross/blackfriday/.gitignore deleted file mode 100644 index 75623dcccb..0000000000 --- a/vendor/github.com/russross/blackfriday/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -*.out -*.swp -*.8 -*.6 -_obj -_test* -markdown -tags diff --git a/vendor/github.com/russross/blackfriday/.travis.yml b/vendor/github.com/russross/blackfriday/.travis.yml deleted file mode 100644 index 2f3351d7ae..0000000000 --- a/vendor/github.com/russross/blackfriday/.travis.yml +++ /dev/null @@ -1,17 +0,0 @@ -sudo: false -language: go -go: - - "1.9.x" - - "1.10.x" - - tip -matrix: - fast_finish: true - allow_failures: - - go: tip -install: - - # Do nothing. This is needed to prevent default install action "go get -t -v ./..." from happening here (we want it to happen inside script step). -script: - - go get -t -v ./... - - diff -u <(echo -n) <(gofmt -d -s .) - - go tool vet . - - go test -v -race ./... diff --git a/vendor/github.com/russross/blackfriday/LICENSE.txt b/vendor/github.com/russross/blackfriday/LICENSE.txt deleted file mode 100644 index 2885af3602..0000000000 --- a/vendor/github.com/russross/blackfriday/LICENSE.txt +++ /dev/null @@ -1,29 +0,0 @@ -Blackfriday is distributed under the Simplified BSD License: - -> Copyright © 2011 Russ Ross -> All rights reserved. -> -> Redistribution and use in source and binary forms, with or without -> modification, are permitted provided that the following conditions -> are met: -> -> 1. Redistributions of source code must retain the above copyright -> notice, this list of conditions and the following disclaimer. -> -> 2. Redistributions in binary form must reproduce the above -> copyright notice, this list of conditions and the following -> disclaimer in the documentation and/or other materials provided with -> the distribution. -> -> THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -> "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -> LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -> FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -> COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -> INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -> BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -> LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -> CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -> LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -> ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -> POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/russross/blackfriday/README.md b/vendor/github.com/russross/blackfriday/README.md deleted file mode 100644 index 3c62e13753..0000000000 --- a/vendor/github.com/russross/blackfriday/README.md +++ /dev/null @@ -1,369 +0,0 @@ -Blackfriday -[![Build Status][BuildSVG]][BuildURL] -[![Godoc][GodocV2SVG]][GodocV2URL] -=========== - -Blackfriday is a [Markdown][1] processor implemented in [Go][2]. It -is paranoid about its input (so you can safely feed it user-supplied -data), it is fast, it supports common extensions (tables, smart -punctuation substitutions, etc.), and it is safe for all utf-8 -(unicode) input. - -HTML output is currently supported, along with Smartypants -extensions. - -It started as a translation from C of [Sundown][3]. - - -Installation ------------- - -Blackfriday is compatible with any modern Go release. With Go and git installed: - - go get -u gopkg.in/russross/blackfriday.v2 - -will download, compile, and install the package into your `$GOPATH` directory -hierarchy. - - -Versions --------- - -Currently maintained and recommended version of Blackfriday is `v2`. It's being -developed on its own branch: https://github.com/russross/blackfriday/tree/v2 and the -documentation is available at -https://godoc.org/gopkg.in/russross/blackfriday.v2. - -It is `go get`-able via [gopkg.in][6] at `gopkg.in/russross/blackfriday.v2`, -but we highly recommend using package management tool like [dep][7] or -[Glide][8] and make use of semantic versioning. With package management you -should import `github.com/russross/blackfriday` and specify that you're using -version 2.0.0. - -Version 2 offers a number of improvements over v1: - -* Cleaned up API -* A separate call to [`Parse`][4], which produces an abstract syntax tree for - the document -* Latest bug fixes -* Flexibility to easily add your own rendering extensions - -Potential drawbacks: - -* Our benchmarks show v2 to be slightly slower than v1. Currently in the - ballpark of around 15%. -* API breakage. If you can't afford modifying your code to adhere to the new API - and don't care too much about the new features, v2 is probably not for you. -* Several bug fixes are trailing behind and still need to be forward-ported to - v2. See issue [#348](https://github.com/russross/blackfriday/issues/348) for - tracking. - -If you are still interested in the legacy `v1`, you can import it from -`github.com/russross/blackfriday`. Documentation for the legacy v1 can be found -here: https://godoc.org/github.com/russross/blackfriday - -### Known issue with `dep` - -There is a known problem with using Blackfriday v1 _transitively_ and `dep`. -Currently `dep` prioritizes semver versions over anything else, and picks the -latest one, plus it does not apply a `[[constraint]]` specifier to transitively -pulled in packages. So if you're using something that uses Blackfriday v1, but -that something does not use `dep` yet, you will get Blackfriday v2 pulled in and -your first dependency will fail to build. - -There are couple of fixes for it, documented here: -https://github.com/golang/dep/blob/master/docs/FAQ.md#how-do-i-constrain-a-transitive-dependencys-version - -Meanwhile, `dep` team is working on a more general solution to the constraints -on transitive dependencies problem: https://github.com/golang/dep/issues/1124. - - -Usage ------ - -### v1 - -For basic usage, it is as simple as getting your input into a byte -slice and calling: - - output := blackfriday.MarkdownBasic(input) - -This renders it with no extensions enabled. To get a more useful -feature set, use this instead: - - output := blackfriday.MarkdownCommon(input) - -### v2 - -For the most sensible markdown processing, it is as simple as getting your input -into a byte slice and calling: - -```go -output := blackfriday.Run(input) -``` - -Your input will be parsed and the output rendered with a set of most popular -extensions enabled. If you want the most basic feature set, corresponding with -the bare Markdown specification, use: - -```go -output := blackfriday.Run(input, blackfriday.WithNoExtensions()) -``` - -### Sanitize untrusted content - -Blackfriday itself does nothing to protect against malicious content. If you are -dealing with user-supplied markdown, we recommend running Blackfriday's output -through HTML sanitizer such as [Bluemonday][5]. - -Here's an example of simple usage of Blackfriday together with Bluemonday: - -```go -import ( - "github.com/microcosm-cc/bluemonday" - "gopkg.in/russross/blackfriday.v2" -) - -// ... -unsafe := blackfriday.Run(input) -html := bluemonday.UGCPolicy().SanitizeBytes(unsafe) -``` - -### Custom options, v1 - -If you want to customize the set of options, first get a renderer -(currently only the HTML output engine), then use it to -call the more general `Markdown` function. For examples, see the -implementations of `MarkdownBasic` and `MarkdownCommon` in -`markdown.go`. - -### Custom options, v2 - -If you want to customize the set of options, use `blackfriday.WithExtensions`, -`blackfriday.WithRenderer` and `blackfriday.WithRefOverride`. - -### `blackfriday-tool` - -You can also check out `blackfriday-tool` for a more complete example -of how to use it. Download and install it using: - - go get github.com/russross/blackfriday-tool - -This is a simple command-line tool that allows you to process a -markdown file using a standalone program. You can also browse the -source directly on github if you are just looking for some example -code: - -* - -Note that if you have not already done so, installing -`blackfriday-tool` will be sufficient to download and install -blackfriday in addition to the tool itself. The tool binary will be -installed in `$GOPATH/bin`. This is a statically-linked binary that -can be copied to wherever you need it without worrying about -dependencies and library versions. - -### Sanitized anchor names - -Blackfriday includes an algorithm for creating sanitized anchor names -corresponding to a given input text. This algorithm is used to create -anchors for headings when `EXTENSION_AUTO_HEADER_IDS` is enabled. The -algorithm has a specification, so that other packages can create -compatible anchor names and links to those anchors. - -The specification is located at https://godoc.org/github.com/russross/blackfriday#hdr-Sanitized_Anchor_Names. - -[`SanitizedAnchorName`](https://godoc.org/github.com/russross/blackfriday#SanitizedAnchorName) exposes this functionality, and can be used to -create compatible links to the anchor names generated by blackfriday. -This algorithm is also implemented in a small standalone package at -[`github.com/shurcooL/sanitized_anchor_name`](https://godoc.org/github.com/shurcooL/sanitized_anchor_name). It can be useful for clients -that want a small package and don't need full functionality of blackfriday. - - -Features --------- - -All features of Sundown are supported, including: - -* **Compatibility**. The Markdown v1.0.3 test suite passes with - the `--tidy` option. Without `--tidy`, the differences are - mostly in whitespace and entity escaping, where blackfriday is - more consistent and cleaner. - -* **Common extensions**, including table support, fenced code - blocks, autolinks, strikethroughs, non-strict emphasis, etc. - -* **Safety**. Blackfriday is paranoid when parsing, making it safe - to feed untrusted user input without fear of bad things - happening. The test suite stress tests this and there are no - known inputs that make it crash. If you find one, please let me - know and send me the input that does it. - - NOTE: "safety" in this context means *runtime safety only*. In order to - protect yourself against JavaScript injection in untrusted content, see - [this example](https://github.com/russross/blackfriday#sanitize-untrusted-content). - -* **Fast processing**. It is fast enough to render on-demand in - most web applications without having to cache the output. - -* **Thread safety**. You can run multiple parsers in different - goroutines without ill effect. There is no dependence on global - shared state. - -* **Minimal dependencies**. Blackfriday only depends on standard - library packages in Go. The source code is pretty - self-contained, so it is easy to add to any project, including - Google App Engine projects. - -* **Standards compliant**. Output successfully validates using the - W3C validation tool for HTML 4.01 and XHTML 1.0 Transitional. - - -Extensions ----------- - -In addition to the standard markdown syntax, this package -implements the following extensions: - -* **Intra-word emphasis supression**. The `_` character is - commonly used inside words when discussing code, so having - markdown interpret it as an emphasis command is usually the - wrong thing. Blackfriday lets you treat all emphasis markers as - normal characters when they occur inside a word. - -* **Tables**. Tables can be created by drawing them in the input - using a simple syntax: - - ``` - Name | Age - --------|------ - Bob | 27 - Alice | 23 - ``` - -* **Fenced code blocks**. In addition to the normal 4-space - indentation to mark code blocks, you can explicitly mark them - and supply a language (to make syntax highlighting simple). Just - mark it like this: - - ``` go - func getTrue() bool { - return true - } - ``` - - You can use 3 or more backticks to mark the beginning of the - block, and the same number to mark the end of the block. - - To preserve classes of fenced code blocks while using the bluemonday - HTML sanitizer, use the following policy: - - ``` go - p := bluemonday.UGCPolicy() - p.AllowAttrs("class").Matching(regexp.MustCompile("^language-[a-zA-Z0-9]+$")).OnElements("code") - html := p.SanitizeBytes(unsafe) - ``` - -* **Definition lists**. A simple definition list is made of a single-line - term followed by a colon and the definition for that term. - - Cat - : Fluffy animal everyone likes - - Internet - : Vector of transmission for pictures of cats - - Terms must be separated from the previous definition by a blank line. - -* **Footnotes**. A marker in the text that will become a superscript number; - a footnote definition that will be placed in a list of footnotes at the - end of the document. A footnote looks like this: - - This is a footnote.[^1] - - [^1]: the footnote text. - -* **Autolinking**. Blackfriday can find URLs that have not been - explicitly marked as links and turn them into links. - -* **Strikethrough**. Use two tildes (`~~`) to mark text that - should be crossed out. - -* **Hard line breaks**. With this extension enabled (it is off by - default in the `MarkdownBasic` and `MarkdownCommon` convenience - functions), newlines in the input translate into line breaks in - the output. - -* **Smart quotes**. Smartypants-style punctuation substitution is - supported, turning normal double- and single-quote marks into - curly quotes, etc. - -* **LaTeX-style dash parsing** is an additional option, where `--` - is translated into `–`, and `---` is translated into - `—`. This differs from most smartypants processors, which - turn a single hyphen into an ndash and a double hyphen into an - mdash. - -* **Smart fractions**, where anything that looks like a fraction - is translated into suitable HTML (instead of just a few special - cases like most smartypant processors). For example, `4/5` - becomes `45`, which renders as - 45. - - -Other renderers ---------------- - -Blackfriday is structured to allow alternative rendering engines. Here -are a few of note: - -* [github_flavored_markdown](https://godoc.org/github.com/shurcooL/github_flavored_markdown): - provides a GitHub Flavored Markdown renderer with fenced code block - highlighting, clickable heading anchor links. - - It's not customizable, and its goal is to produce HTML output - equivalent to the [GitHub Markdown API endpoint](https://developer.github.com/v3/markdown/#render-a-markdown-document-in-raw-mode), - except the rendering is performed locally. - -* [markdownfmt](https://github.com/shurcooL/markdownfmt): like gofmt, - but for markdown. - -* [LaTeX output](https://bitbucket.org/ambrevar/blackfriday-latex): - renders output as LaTeX. - -* [bfchroma](https://github.com/Depado/bfchroma/): provides convenience - integration with the [Chroma](https://github.com/alecthomas/chroma) code - highlighting library. bfchroma is only compatible with v2 of Blackfriday and - provides a drop-in renderer ready to use with Blackfriday, as well as - options and means for further customization. - - -TODO ----- - -* More unit testing -* Improve Unicode support. It does not understand all Unicode - rules (about what constitutes a letter, a punctuation symbol, - etc.), so it may fail to detect word boundaries correctly in - some instances. It is safe on all UTF-8 input. - - -License -------- - -[Blackfriday is distributed under the Simplified BSD License](LICENSE.txt) - - - [1]: https://daringfireball.net/projects/markdown/ "Markdown" - [2]: https://golang.org/ "Go Language" - [3]: https://github.com/vmg/sundown "Sundown" - [4]: https://godoc.org/gopkg.in/russross/blackfriday.v2#Parse "Parse func" - [5]: https://github.com/microcosm-cc/bluemonday "Bluemonday" - [6]: https://labix.org/gopkg.in "gopkg.in" - [7]: https://github.com/golang/dep/ "dep" - [8]: https://github.com/Masterminds/glide "Glide" - - [BuildSVG]: https://travis-ci.org/russross/blackfriday.svg?branch=master - [BuildURL]: https://travis-ci.org/russross/blackfriday - [GodocV2SVG]: https://godoc.org/gopkg.in/russross/blackfriday.v2?status.svg - [GodocV2URL]: https://godoc.org/gopkg.in/russross/blackfriday.v2 diff --git a/vendor/github.com/russross/blackfriday/block.go b/vendor/github.com/russross/blackfriday/block.go deleted file mode 100644 index 45c21a6c26..0000000000 --- a/vendor/github.com/russross/blackfriday/block.go +++ /dev/null @@ -1,1474 +0,0 @@ -// -// Blackfriday Markdown Processor -// Available at http://github.com/russross/blackfriday -// -// Copyright © 2011 Russ Ross . -// Distributed under the Simplified BSD License. -// See README.md for details. -// - -// -// Functions to parse block-level elements. -// - -package blackfriday - -import ( - "bytes" - "strings" - "unicode" -) - -// Parse block-level data. -// Note: this function and many that it calls assume that -// the input buffer ends with a newline. -func (p *parser) block(out *bytes.Buffer, data []byte) { - if len(data) == 0 || data[len(data)-1] != '\n' { - panic("block input is missing terminating newline") - } - - // this is called recursively: enforce a maximum depth - if p.nesting >= p.maxNesting { - return - } - p.nesting++ - - // parse out one block-level construct at a time - for len(data) > 0 { - // prefixed header: - // - // # Header 1 - // ## Header 2 - // ... - // ###### Header 6 - if p.isPrefixHeader(data) { - data = data[p.prefixHeader(out, data):] - continue - } - - // block of preformatted HTML: - // - //

    - // ... - //
    - if data[0] == '<' { - if i := p.html(out, data, true); i > 0 { - data = data[i:] - continue - } - } - - // title block - // - // % stuff - // % more stuff - // % even more stuff - if p.flags&EXTENSION_TITLEBLOCK != 0 { - if data[0] == '%' { - if i := p.titleBlock(out, data, true); i > 0 { - data = data[i:] - continue - } - } - } - - // blank lines. note: returns the # of bytes to skip - if i := p.isEmpty(data); i > 0 { - data = data[i:] - continue - } - - // indented code block: - // - // func max(a, b int) int { - // if a > b { - // return a - // } - // return b - // } - if p.codePrefix(data) > 0 { - data = data[p.code(out, data):] - continue - } - - // fenced code block: - // - // ``` go info string here - // func fact(n int) int { - // if n <= 1 { - // return n - // } - // return n * fact(n-1) - // } - // ``` - if p.flags&EXTENSION_FENCED_CODE != 0 { - if i := p.fencedCodeBlock(out, data, true); i > 0 { - data = data[i:] - continue - } - } - - // horizontal rule: - // - // ------ - // or - // ****** - // or - // ______ - if p.isHRule(data) { - p.r.HRule(out) - var i int - for i = 0; data[i] != '\n'; i++ { - } - data = data[i:] - continue - } - - // block quote: - // - // > A big quote I found somewhere - // > on the web - if p.quotePrefix(data) > 0 { - data = data[p.quote(out, data):] - continue - } - - // table: - // - // Name | Age | Phone - // ------|-----|--------- - // Bob | 31 | 555-1234 - // Alice | 27 | 555-4321 - if p.flags&EXTENSION_TABLES != 0 { - if i := p.table(out, data); i > 0 { - data = data[i:] - continue - } - } - - // an itemized/unordered list: - // - // * Item 1 - // * Item 2 - // - // also works with + or - - if p.uliPrefix(data) > 0 { - data = data[p.list(out, data, 0):] - continue - } - - // a numbered/ordered list: - // - // 1. Item 1 - // 2. Item 2 - if p.oliPrefix(data) > 0 { - data = data[p.list(out, data, LIST_TYPE_ORDERED):] - continue - } - - // definition lists: - // - // Term 1 - // : Definition a - // : Definition b - // - // Term 2 - // : Definition c - if p.flags&EXTENSION_DEFINITION_LISTS != 0 { - if p.dliPrefix(data) > 0 { - data = data[p.list(out, data, LIST_TYPE_DEFINITION):] - continue - } - } - - // anything else must look like a normal paragraph - // note: this finds underlined headers, too - data = data[p.paragraph(out, data):] - } - - p.nesting-- -} - -func (p *parser) isPrefixHeader(data []byte) bool { - if data[0] != '#' { - return false - } - - if p.flags&EXTENSION_SPACE_HEADERS != 0 { - level := 0 - for level < 6 && data[level] == '#' { - level++ - } - if data[level] != ' ' { - return false - } - } - return true -} - -func (p *parser) prefixHeader(out *bytes.Buffer, data []byte) int { - level := 0 - for level < 6 && data[level] == '#' { - level++ - } - i := skipChar(data, level, ' ') - end := skipUntilChar(data, i, '\n') - skip := end - id := "" - if p.flags&EXTENSION_HEADER_IDS != 0 { - j, k := 0, 0 - // find start/end of header id - for j = i; j < end-1 && (data[j] != '{' || data[j+1] != '#'); j++ { - } - for k = j + 1; k < end && data[k] != '}'; k++ { - } - // extract header id iff found - if j < end && k < end { - id = string(data[j+2 : k]) - end = j - skip = k + 1 - for end > 0 && data[end-1] == ' ' { - end-- - } - } - } - for end > 0 && data[end-1] == '#' { - if isBackslashEscaped(data, end-1) { - break - } - end-- - } - for end > 0 && data[end-1] == ' ' { - end-- - } - if end > i { - if id == "" && p.flags&EXTENSION_AUTO_HEADER_IDS != 0 { - id = SanitizedAnchorName(string(data[i:end])) - } - work := func() bool { - p.inline(out, data[i:end]) - return true - } - p.r.Header(out, work, level, id) - } - return skip -} - -func (p *parser) isUnderlinedHeader(data []byte) int { - // test of level 1 header - if data[0] == '=' { - i := skipChar(data, 1, '=') - i = skipChar(data, i, ' ') - if data[i] == '\n' { - return 1 - } else { - return 0 - } - } - - // test of level 2 header - if data[0] == '-' { - i := skipChar(data, 1, '-') - i = skipChar(data, i, ' ') - if data[i] == '\n' { - return 2 - } else { - return 0 - } - } - - return 0 -} - -func (p *parser) titleBlock(out *bytes.Buffer, data []byte, doRender bool) int { - if data[0] != '%' { - return 0 - } - splitData := bytes.Split(data, []byte("\n")) - var i int - for idx, b := range splitData { - if !bytes.HasPrefix(b, []byte("%")) { - i = idx // - 1 - break - } - } - - data = bytes.Join(splitData[0:i], []byte("\n")) - p.r.TitleBlock(out, data) - - return len(data) -} - -func (p *parser) html(out *bytes.Buffer, data []byte, doRender bool) int { - var i, j int - - // identify the opening tag - if data[0] != '<' { - return 0 - } - curtag, tagfound := p.htmlFindTag(data[1:]) - - // handle special cases - if !tagfound { - // check for an HTML comment - if size := p.htmlComment(out, data, doRender); size > 0 { - return size - } - - // check for an
    tag - if size := p.htmlHr(out, data, doRender); size > 0 { - return size - } - - // check for HTML CDATA - if size := p.htmlCDATA(out, data, doRender); size > 0 { - return size - } - - // no special case recognized - return 0 - } - - // look for an unindented matching closing tag - // followed by a blank line - found := false - /* - closetag := []byte("\n") - j = len(curtag) + 1 - for !found { - // scan for a closing tag at the beginning of a line - if skip := bytes.Index(data[j:], closetag); skip >= 0 { - j += skip + len(closetag) - } else { - break - } - - // see if it is the only thing on the line - if skip := p.isEmpty(data[j:]); skip > 0 { - // see if it is followed by a blank line/eof - j += skip - if j >= len(data) { - found = true - i = j - } else { - if skip := p.isEmpty(data[j:]); skip > 0 { - j += skip - found = true - i = j - } - } - } - } - */ - - // if not found, try a second pass looking for indented match - // but not if tag is "ins" or "del" (following original Markdown.pl) - if !found && curtag != "ins" && curtag != "del" { - i = 1 - for i < len(data) { - i++ - for i < len(data) && !(data[i-1] == '<' && data[i] == '/') { - i++ - } - - if i+2+len(curtag) >= len(data) { - break - } - - j = p.htmlFindEnd(curtag, data[i-1:]) - - if j > 0 { - i += j - 1 - found = true - break - } - } - } - - if !found { - return 0 - } - - // the end of the block has been found - if doRender { - // trim newlines - end := i - for end > 0 && data[end-1] == '\n' { - end-- - } - p.r.BlockHtml(out, data[:end]) - } - - return i -} - -func (p *parser) renderHTMLBlock(out *bytes.Buffer, data []byte, start int, doRender bool) int { - // html block needs to end with a blank line - if i := p.isEmpty(data[start:]); i > 0 { - size := start + i - if doRender { - // trim trailing newlines - end := size - for end > 0 && data[end-1] == '\n' { - end-- - } - p.r.BlockHtml(out, data[:end]) - } - return size - } - return 0 -} - -// HTML comment, lax form -func (p *parser) htmlComment(out *bytes.Buffer, data []byte, doRender bool) int { - i := p.inlineHTMLComment(out, data) - return p.renderHTMLBlock(out, data, i, doRender) -} - -// HTML CDATA section -func (p *parser) htmlCDATA(out *bytes.Buffer, data []byte, doRender bool) int { - const cdataTag = "') { - i++ - } - i++ - // no end-of-comment marker - if i >= len(data) { - return 0 - } - return p.renderHTMLBlock(out, data, i, doRender) -} - -// HR, which is the only self-closing block tag considered -func (p *parser) htmlHr(out *bytes.Buffer, data []byte, doRender bool) int { - if data[0] != '<' || (data[1] != 'h' && data[1] != 'H') || (data[2] != 'r' && data[2] != 'R') { - return 0 - } - if data[3] != ' ' && data[3] != '/' && data[3] != '>' { - // not an
    tag after all; at least not a valid one - return 0 - } - - i := 3 - for data[i] != '>' && data[i] != '\n' { - i++ - } - - if data[i] == '>' { - return p.renderHTMLBlock(out, data, i+1, doRender) - } - - return 0 -} - -func (p *parser) htmlFindTag(data []byte) (string, bool) { - i := 0 - for isalnum(data[i]) { - i++ - } - key := string(data[:i]) - if _, ok := blockTags[key]; ok { - return key, true - } - return "", false -} - -func (p *parser) htmlFindEnd(tag string, data []byte) int { - // assume data[0] == '<' && data[1] == '/' already tested - - // check if tag is a match - closetag := []byte("") - if !bytes.HasPrefix(data, closetag) { - return 0 - } - i := len(closetag) - - // check that the rest of the line is blank - skip := 0 - if skip = p.isEmpty(data[i:]); skip == 0 { - return 0 - } - i += skip - skip = 0 - - if i >= len(data) { - return i - } - - if p.flags&EXTENSION_LAX_HTML_BLOCKS != 0 { - return i - } - if skip = p.isEmpty(data[i:]); skip == 0 { - // following line must be blank - return 0 - } - - return i + skip -} - -func (*parser) isEmpty(data []byte) int { - // it is okay to call isEmpty on an empty buffer - if len(data) == 0 { - return 0 - } - - var i int - for i = 0; i < len(data) && data[i] != '\n'; i++ { - if data[i] != ' ' && data[i] != '\t' { - return 0 - } - } - return i + 1 -} - -func (*parser) isHRule(data []byte) bool { - i := 0 - - // skip up to three spaces - for i < 3 && data[i] == ' ' { - i++ - } - - // look at the hrule char - if data[i] != '*' && data[i] != '-' && data[i] != '_' { - return false - } - c := data[i] - - // the whole line must be the char or whitespace - n := 0 - for data[i] != '\n' { - switch { - case data[i] == c: - n++ - case data[i] != ' ': - return false - } - i++ - } - - return n >= 3 -} - -// isFenceLine checks if there's a fence line (e.g., ``` or ``` go) at the beginning of data, -// and returns the end index if so, or 0 otherwise. It also returns the marker found. -// If syntax is not nil, it gets set to the syntax specified in the fence line. -// A final newline is mandatory to recognize the fence line, unless newlineOptional is true. -func isFenceLine(data []byte, info *string, oldmarker string, newlineOptional bool) (end int, marker string) { - i, size := 0, 0 - - // skip up to three spaces - for i < len(data) && i < 3 && data[i] == ' ' { - i++ - } - - // check for the marker characters: ~ or ` - if i >= len(data) { - return 0, "" - } - if data[i] != '~' && data[i] != '`' { - return 0, "" - } - - c := data[i] - - // the whole line must be the same char or whitespace - for i < len(data) && data[i] == c { - size++ - i++ - } - - // the marker char must occur at least 3 times - if size < 3 { - return 0, "" - } - marker = string(data[i-size : i]) - - // if this is the end marker, it must match the beginning marker - if oldmarker != "" && marker != oldmarker { - return 0, "" - } - - // TODO(shurcooL): It's probably a good idea to simplify the 2 code paths here - // into one, always get the info string, and discard it if the caller doesn't care. - if info != nil { - infoLength := 0 - i = skipChar(data, i, ' ') - - if i >= len(data) { - if newlineOptional && i == len(data) { - return i, marker - } - return 0, "" - } - - infoStart := i - - if data[i] == '{' { - i++ - infoStart++ - - for i < len(data) && data[i] != '}' && data[i] != '\n' { - infoLength++ - i++ - } - - if i >= len(data) || data[i] != '}' { - return 0, "" - } - - // strip all whitespace at the beginning and the end - // of the {} block - for infoLength > 0 && isspace(data[infoStart]) { - infoStart++ - infoLength-- - } - - for infoLength > 0 && isspace(data[infoStart+infoLength-1]) { - infoLength-- - } - - i++ - } else { - for i < len(data) && !isverticalspace(data[i]) { - infoLength++ - i++ - } - } - - *info = strings.TrimSpace(string(data[infoStart : infoStart+infoLength])) - } - - i = skipChar(data, i, ' ') - if i >= len(data) || data[i] != '\n' { - if newlineOptional && i == len(data) { - return i, marker - } - return 0, "" - } - - return i + 1, marker // Take newline into account. -} - -// fencedCodeBlock returns the end index if data contains a fenced code block at the beginning, -// or 0 otherwise. It writes to out if doRender is true, otherwise it has no side effects. -// If doRender is true, a final newline is mandatory to recognize the fenced code block. -func (p *parser) fencedCodeBlock(out *bytes.Buffer, data []byte, doRender bool) int { - var infoString string - beg, marker := isFenceLine(data, &infoString, "", false) - if beg == 0 || beg >= len(data) { - return 0 - } - - var work bytes.Buffer - - for { - // safe to assume beg < len(data) - - // check for the end of the code block - newlineOptional := !doRender - fenceEnd, _ := isFenceLine(data[beg:], nil, marker, newlineOptional) - if fenceEnd != 0 { - beg += fenceEnd - break - } - - // copy the current line - end := skipUntilChar(data, beg, '\n') + 1 - - // did we reach the end of the buffer without a closing marker? - if end >= len(data) { - return 0 - } - - // verbatim copy to the working buffer - if doRender { - work.Write(data[beg:end]) - } - beg = end - } - - if doRender { - p.r.BlockCode(out, work.Bytes(), infoString) - } - - return beg -} - -func (p *parser) table(out *bytes.Buffer, data []byte) int { - var header bytes.Buffer - i, columns := p.tableHeader(&header, data) - if i == 0 { - return 0 - } - - var body bytes.Buffer - - for i < len(data) { - pipes, rowStart := 0, i - for ; data[i] != '\n'; i++ { - if data[i] == '|' { - pipes++ - } - } - - if pipes == 0 { - i = rowStart - break - } - - // include the newline in data sent to tableRow - i++ - p.tableRow(&body, data[rowStart:i], columns, false) - } - - p.r.Table(out, header.Bytes(), body.Bytes(), columns) - - return i -} - -// check if the specified position is preceded by an odd number of backslashes -func isBackslashEscaped(data []byte, i int) bool { - backslashes := 0 - for i-backslashes-1 >= 0 && data[i-backslashes-1] == '\\' { - backslashes++ - } - return backslashes&1 == 1 -} - -func (p *parser) tableHeader(out *bytes.Buffer, data []byte) (size int, columns []int) { - i := 0 - colCount := 1 - for i = 0; data[i] != '\n'; i++ { - if data[i] == '|' && !isBackslashEscaped(data, i) { - colCount++ - } - } - - // doesn't look like a table header - if colCount == 1 { - return - } - - // include the newline in the data sent to tableRow - header := data[:i+1] - - // column count ignores pipes at beginning or end of line - if data[0] == '|' { - colCount-- - } - if i > 2 && data[i-1] == '|' && !isBackslashEscaped(data, i-1) { - colCount-- - } - - columns = make([]int, colCount) - - // move on to the header underline - i++ - if i >= len(data) { - return - } - - if data[i] == '|' && !isBackslashEscaped(data, i) { - i++ - } - i = skipChar(data, i, ' ') - - // each column header is of form: / *:?-+:? *|/ with # dashes + # colons >= 3 - // and trailing | optional on last column - col := 0 - for data[i] != '\n' { - dashes := 0 - - if data[i] == ':' { - i++ - columns[col] |= TABLE_ALIGNMENT_LEFT - dashes++ - } - for data[i] == '-' { - i++ - dashes++ - } - if data[i] == ':' { - i++ - columns[col] |= TABLE_ALIGNMENT_RIGHT - dashes++ - } - for data[i] == ' ' { - i++ - } - - // end of column test is messy - switch { - case dashes < 3: - // not a valid column - return - - case data[i] == '|' && !isBackslashEscaped(data, i): - // marker found, now skip past trailing whitespace - col++ - i++ - for data[i] == ' ' { - i++ - } - - // trailing junk found after last column - if col >= colCount && data[i] != '\n' { - return - } - - case (data[i] != '|' || isBackslashEscaped(data, i)) && col+1 < colCount: - // something else found where marker was required - return - - case data[i] == '\n': - // marker is optional for the last column - col++ - - default: - // trailing junk found after last column - return - } - } - if col != colCount { - return - } - - p.tableRow(out, header, columns, true) - size = i + 1 - return -} - -func (p *parser) tableRow(out *bytes.Buffer, data []byte, columns []int, header bool) { - i, col := 0, 0 - var rowWork bytes.Buffer - - if data[i] == '|' && !isBackslashEscaped(data, i) { - i++ - } - - for col = 0; col < len(columns) && i < len(data); col++ { - for data[i] == ' ' { - i++ - } - - cellStart := i - - for (data[i] != '|' || isBackslashEscaped(data, i)) && data[i] != '\n' { - i++ - } - - cellEnd := i - - // skip the end-of-cell marker, possibly taking us past end of buffer - i++ - - for cellEnd > cellStart && data[cellEnd-1] == ' ' { - cellEnd-- - } - - var cellWork bytes.Buffer - p.inline(&cellWork, data[cellStart:cellEnd]) - - if header { - p.r.TableHeaderCell(&rowWork, cellWork.Bytes(), columns[col]) - } else { - p.r.TableCell(&rowWork, cellWork.Bytes(), columns[col]) - } - } - - // pad it out with empty columns to get the right number - for ; col < len(columns); col++ { - if header { - p.r.TableHeaderCell(&rowWork, nil, columns[col]) - } else { - p.r.TableCell(&rowWork, nil, columns[col]) - } - } - - // silently ignore rows with too many cells - - p.r.TableRow(out, rowWork.Bytes()) -} - -// returns blockquote prefix length -func (p *parser) quotePrefix(data []byte) int { - i := 0 - for i < 3 && data[i] == ' ' { - i++ - } - if data[i] == '>' { - if data[i+1] == ' ' { - return i + 2 - } - return i + 1 - } - return 0 -} - -// blockquote ends with at least one blank line -// followed by something without a blockquote prefix -func (p *parser) terminateBlockquote(data []byte, beg, end int) bool { - if p.isEmpty(data[beg:]) <= 0 { - return false - } - if end >= len(data) { - return true - } - return p.quotePrefix(data[end:]) == 0 && p.isEmpty(data[end:]) == 0 -} - -// parse a blockquote fragment -func (p *parser) quote(out *bytes.Buffer, data []byte) int { - var raw bytes.Buffer - beg, end := 0, 0 - for beg < len(data) { - end = beg - // Step over whole lines, collecting them. While doing that, check for - // fenced code and if one's found, incorporate it altogether, - // irregardless of any contents inside it - for data[end] != '\n' { - if p.flags&EXTENSION_FENCED_CODE != 0 { - if i := p.fencedCodeBlock(out, data[end:], false); i > 0 { - // -1 to compensate for the extra end++ after the loop: - end += i - 1 - break - } - } - end++ - } - end++ - - if pre := p.quotePrefix(data[beg:]); pre > 0 { - // skip the prefix - beg += pre - } else if p.terminateBlockquote(data, beg, end) { - break - } - - // this line is part of the blockquote - raw.Write(data[beg:end]) - beg = end - } - - var cooked bytes.Buffer - p.block(&cooked, raw.Bytes()) - p.r.BlockQuote(out, cooked.Bytes()) - return end -} - -// returns prefix length for block code -func (p *parser) codePrefix(data []byte) int { - if data[0] == ' ' && data[1] == ' ' && data[2] == ' ' && data[3] == ' ' { - return 4 - } - return 0 -} - -func (p *parser) code(out *bytes.Buffer, data []byte) int { - var work bytes.Buffer - - i := 0 - for i < len(data) { - beg := i - for data[i] != '\n' { - i++ - } - i++ - - blankline := p.isEmpty(data[beg:i]) > 0 - if pre := p.codePrefix(data[beg:i]); pre > 0 { - beg += pre - } else if !blankline { - // non-empty, non-prefixed line breaks the pre - i = beg - break - } - - // verbatim copy to the working buffeu - if blankline { - work.WriteByte('\n') - } else { - work.Write(data[beg:i]) - } - } - - // trim all the \n off the end of work - workbytes := work.Bytes() - eol := len(workbytes) - for eol > 0 && workbytes[eol-1] == '\n' { - eol-- - } - if eol != len(workbytes) { - work.Truncate(eol) - } - - work.WriteByte('\n') - - p.r.BlockCode(out, work.Bytes(), "") - - return i -} - -// returns unordered list item prefix -func (p *parser) uliPrefix(data []byte) int { - i := 0 - - // start with up to 3 spaces - for i < 3 && data[i] == ' ' { - i++ - } - - // need a *, +, or - followed by a space - if (data[i] != '*' && data[i] != '+' && data[i] != '-') || - data[i+1] != ' ' { - return 0 - } - return i + 2 -} - -// returns ordered list item prefix -func (p *parser) oliPrefix(data []byte) int { - i := 0 - - // start with up to 3 spaces - for i < 3 && data[i] == ' ' { - i++ - } - - // count the digits - start := i - for data[i] >= '0' && data[i] <= '9' { - i++ - } - - // we need >= 1 digits followed by a dot and a space - if start == i || data[i] != '.' || data[i+1] != ' ' { - return 0 - } - return i + 2 -} - -// returns definition list item prefix -func (p *parser) dliPrefix(data []byte) int { - i := 0 - - // need a : followed by a spaces - if data[i] != ':' || data[i+1] != ' ' { - return 0 - } - for data[i] == ' ' { - i++ - } - return i + 2 -} - -// parse ordered or unordered list block -func (p *parser) list(out *bytes.Buffer, data []byte, flags int) int { - i := 0 - flags |= LIST_ITEM_BEGINNING_OF_LIST - work := func() bool { - for i < len(data) { - skip := p.listItem(out, data[i:], &flags) - i += skip - - if skip == 0 || flags&LIST_ITEM_END_OF_LIST != 0 { - break - } - flags &= ^LIST_ITEM_BEGINNING_OF_LIST - } - return true - } - - p.r.List(out, work, flags) - return i -} - -// Parse a single list item. -// Assumes initial prefix is already removed if this is a sublist. -func (p *parser) listItem(out *bytes.Buffer, data []byte, flags *int) int { - // keep track of the indentation of the first line - itemIndent := 0 - for itemIndent < 3 && data[itemIndent] == ' ' { - itemIndent++ - } - - i := p.uliPrefix(data) - if i == 0 { - i = p.oliPrefix(data) - } - if i == 0 { - i = p.dliPrefix(data) - // reset definition term flag - if i > 0 { - *flags &= ^LIST_TYPE_TERM - } - } - if i == 0 { - // if in defnition list, set term flag and continue - if *flags&LIST_TYPE_DEFINITION != 0 { - *flags |= LIST_TYPE_TERM - } else { - return 0 - } - } - - // skip leading whitespace on first line - for data[i] == ' ' { - i++ - } - - // find the end of the line - line := i - for i > 0 && data[i-1] != '\n' { - i++ - } - - // get working buffer - var raw bytes.Buffer - - // put the first line into the working buffer - raw.Write(data[line:i]) - line = i - - // process the following lines - containsBlankLine := false - sublist := 0 - codeBlockMarker := "" - -gatherlines: - for line < len(data) { - i++ - - // find the end of this line - for data[i-1] != '\n' { - i++ - } - - // if it is an empty line, guess that it is part of this item - // and move on to the next line - if p.isEmpty(data[line:i]) > 0 { - containsBlankLine = true - raw.Write(data[line:i]) - line = i - continue - } - - // calculate the indentation - indent := 0 - for indent < 4 && line+indent < i && data[line+indent] == ' ' { - indent++ - } - - chunk := data[line+indent : i] - - if p.flags&EXTENSION_FENCED_CODE != 0 { - // determine if in or out of codeblock - // if in codeblock, ignore normal list processing - _, marker := isFenceLine(chunk, nil, codeBlockMarker, false) - if marker != "" { - if codeBlockMarker == "" { - // start of codeblock - codeBlockMarker = marker - } else { - // end of codeblock. - *flags |= LIST_ITEM_CONTAINS_BLOCK - codeBlockMarker = "" - } - } - // we are in a codeblock, write line, and continue - if codeBlockMarker != "" || marker != "" { - raw.Write(data[line+indent : i]) - line = i - continue gatherlines - } - } - - // evaluate how this line fits in - switch { - // is this a nested list item? - case (p.uliPrefix(chunk) > 0 && !p.isHRule(chunk)) || - p.oliPrefix(chunk) > 0 || - p.dliPrefix(chunk) > 0: - - if containsBlankLine { - // end the list if the type changed after a blank line - if indent <= itemIndent && - ((*flags&LIST_TYPE_ORDERED != 0 && p.uliPrefix(chunk) > 0) || - (*flags&LIST_TYPE_ORDERED == 0 && p.oliPrefix(chunk) > 0)) { - - *flags |= LIST_ITEM_END_OF_LIST - break gatherlines - } - *flags |= LIST_ITEM_CONTAINS_BLOCK - } - - // to be a nested list, it must be indented more - // if not, it is the next item in the same list - if indent <= itemIndent { - break gatherlines - } - - // is this the first item in the nested list? - if sublist == 0 { - sublist = raw.Len() - } - - // is this a nested prefix header? - case p.isPrefixHeader(chunk): - // if the header is not indented, it is not nested in the list - // and thus ends the list - if containsBlankLine && indent < 4 { - *flags |= LIST_ITEM_END_OF_LIST - break gatherlines - } - *flags |= LIST_ITEM_CONTAINS_BLOCK - - // anything following an empty line is only part - // of this item if it is indented 4 spaces - // (regardless of the indentation of the beginning of the item) - case containsBlankLine && indent < 4: - if *flags&LIST_TYPE_DEFINITION != 0 && i < len(data)-1 { - // is the next item still a part of this list? - next := i - for data[next] != '\n' { - next++ - } - for next < len(data)-1 && data[next] == '\n' { - next++ - } - if i < len(data)-1 && data[i] != ':' && data[next] != ':' { - *flags |= LIST_ITEM_END_OF_LIST - } - } else { - *flags |= LIST_ITEM_END_OF_LIST - } - break gatherlines - - // a blank line means this should be parsed as a block - case containsBlankLine: - *flags |= LIST_ITEM_CONTAINS_BLOCK - } - - containsBlankLine = false - - // add the line into the working buffer without prefix - raw.Write(data[line+indent : i]) - - line = i - } - - // If reached end of data, the Renderer.ListItem call we're going to make below - // is definitely the last in the list. - if line >= len(data) { - *flags |= LIST_ITEM_END_OF_LIST - } - - rawBytes := raw.Bytes() - - // render the contents of the list item - var cooked bytes.Buffer - if *flags&LIST_ITEM_CONTAINS_BLOCK != 0 && *flags&LIST_TYPE_TERM == 0 { - // intermediate render of block item, except for definition term - if sublist > 0 { - p.block(&cooked, rawBytes[:sublist]) - p.block(&cooked, rawBytes[sublist:]) - } else { - p.block(&cooked, rawBytes) - } - } else { - // intermediate render of inline item - if sublist > 0 { - p.inline(&cooked, rawBytes[:sublist]) - p.block(&cooked, rawBytes[sublist:]) - } else { - p.inline(&cooked, rawBytes) - } - } - - // render the actual list item - cookedBytes := cooked.Bytes() - parsedEnd := len(cookedBytes) - - // strip trailing newlines - for parsedEnd > 0 && cookedBytes[parsedEnd-1] == '\n' { - parsedEnd-- - } - p.r.ListItem(out, cookedBytes[:parsedEnd], *flags) - - return line -} - -// render a single paragraph that has already been parsed out -func (p *parser) renderParagraph(out *bytes.Buffer, data []byte) { - if len(data) == 0 { - return - } - - // trim leading spaces - beg := 0 - for data[beg] == ' ' { - beg++ - } - - // trim trailing newline - end := len(data) - 1 - - // trim trailing spaces - for end > beg && data[end-1] == ' ' { - end-- - } - - work := func() bool { - p.inline(out, data[beg:end]) - return true - } - p.r.Paragraph(out, work) -} - -func (p *parser) paragraph(out *bytes.Buffer, data []byte) int { - // prev: index of 1st char of previous line - // line: index of 1st char of current line - // i: index of cursor/end of current line - var prev, line, i int - - // keep going until we find something to mark the end of the paragraph - for i < len(data) { - // mark the beginning of the current line - prev = line - current := data[i:] - line = i - - // did we find a blank line marking the end of the paragraph? - if n := p.isEmpty(current); n > 0 { - // did this blank line followed by a definition list item? - if p.flags&EXTENSION_DEFINITION_LISTS != 0 { - if i < len(data)-1 && data[i+1] == ':' { - return p.list(out, data[prev:], LIST_TYPE_DEFINITION) - } - } - - p.renderParagraph(out, data[:i]) - return i + n - } - - // an underline under some text marks a header, so our paragraph ended on prev line - if i > 0 { - if level := p.isUnderlinedHeader(current); level > 0 { - // render the paragraph - p.renderParagraph(out, data[:prev]) - - // ignore leading and trailing whitespace - eol := i - 1 - for prev < eol && data[prev] == ' ' { - prev++ - } - for eol > prev && data[eol-1] == ' ' { - eol-- - } - - // render the header - // this ugly double closure avoids forcing variables onto the heap - work := func(o *bytes.Buffer, pp *parser, d []byte) func() bool { - return func() bool { - pp.inline(o, d) - return true - } - }(out, p, data[prev:eol]) - - id := "" - if p.flags&EXTENSION_AUTO_HEADER_IDS != 0 { - id = SanitizedAnchorName(string(data[prev:eol])) - } - - p.r.Header(out, work, level, id) - - // find the end of the underline - for data[i] != '\n' { - i++ - } - return i - } - } - - // if the next line starts a block of HTML, then the paragraph ends here - if p.flags&EXTENSION_LAX_HTML_BLOCKS != 0 { - if data[i] == '<' && p.html(out, current, false) > 0 { - // rewind to before the HTML block - p.renderParagraph(out, data[:i]) - return i - } - } - - // if there's a prefixed header or a horizontal rule after this, paragraph is over - if p.isPrefixHeader(current) || p.isHRule(current) { - p.renderParagraph(out, data[:i]) - return i - } - - // if there's a fenced code block, paragraph is over - if p.flags&EXTENSION_FENCED_CODE != 0 { - if p.fencedCodeBlock(out, current, false) > 0 { - p.renderParagraph(out, data[:i]) - return i - } - } - - // if there's a definition list item, prev line is a definition term - if p.flags&EXTENSION_DEFINITION_LISTS != 0 { - if p.dliPrefix(current) != 0 { - return p.list(out, data[prev:], LIST_TYPE_DEFINITION) - } - } - - // if there's a list after this, paragraph is over - if p.flags&EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK != 0 { - if p.uliPrefix(current) != 0 || - p.oliPrefix(current) != 0 || - p.quotePrefix(current) != 0 || - p.codePrefix(current) != 0 { - p.renderParagraph(out, data[:i]) - return i - } - } - - // otherwise, scan to the beginning of the next line - for data[i] != '\n' { - i++ - } - i++ - } - - p.renderParagraph(out, data[:i]) - return i -} - -// SanitizedAnchorName returns a sanitized anchor name for the given text. -// -// It implements the algorithm specified in the package comment. -func SanitizedAnchorName(text string) string { - var anchorName []rune - futureDash := false - for _, r := range text { - switch { - case unicode.IsLetter(r) || unicode.IsNumber(r): - if futureDash && len(anchorName) > 0 { - anchorName = append(anchorName, '-') - } - futureDash = false - anchorName = append(anchorName, unicode.ToLower(r)) - default: - futureDash = true - } - } - return string(anchorName) -} diff --git a/vendor/github.com/russross/blackfriday/doc.go b/vendor/github.com/russross/blackfriday/doc.go deleted file mode 100644 index 9656c42a19..0000000000 --- a/vendor/github.com/russross/blackfriday/doc.go +++ /dev/null @@ -1,32 +0,0 @@ -// Package blackfriday is a Markdown processor. -// -// It translates plain text with simple formatting rules into HTML or LaTeX. -// -// Sanitized Anchor Names -// -// Blackfriday includes an algorithm for creating sanitized anchor names -// corresponding to a given input text. This algorithm is used to create -// anchors for headings when EXTENSION_AUTO_HEADER_IDS is enabled. The -// algorithm is specified below, so that other packages can create -// compatible anchor names and links to those anchors. -// -// The algorithm iterates over the input text, interpreted as UTF-8, -// one Unicode code point (rune) at a time. All runes that are letters (category L) -// or numbers (category N) are considered valid characters. They are mapped to -// lower case, and included in the output. All other runes are considered -// invalid characters. Invalid characters that preceed the first valid character, -// as well as invalid character that follow the last valid character -// are dropped completely. All other sequences of invalid characters -// between two valid characters are replaced with a single dash character '-'. -// -// SanitizedAnchorName exposes this functionality, and can be used to -// create compatible links to the anchor names generated by blackfriday. -// This algorithm is also implemented in a small standalone package at -// github.com/shurcooL/sanitized_anchor_name. It can be useful for clients -// that want a small package and don't need full functionality of blackfriday. -package blackfriday - -// NOTE: Keep Sanitized Anchor Name algorithm in sync with package -// github.com/shurcooL/sanitized_anchor_name. -// Otherwise, users of sanitized_anchor_name will get anchor names -// that are incompatible with those generated by blackfriday. diff --git a/vendor/github.com/russross/blackfriday/html.go b/vendor/github.com/russross/blackfriday/html.go deleted file mode 100644 index e0a6c69c96..0000000000 --- a/vendor/github.com/russross/blackfriday/html.go +++ /dev/null @@ -1,938 +0,0 @@ -// -// Blackfriday Markdown Processor -// Available at http://github.com/russross/blackfriday -// -// Copyright © 2011 Russ Ross . -// Distributed under the Simplified BSD License. -// See README.md for details. -// - -// -// -// HTML rendering backend -// -// - -package blackfriday - -import ( - "bytes" - "fmt" - "regexp" - "strconv" - "strings" -) - -// Html renderer configuration options. -const ( - HTML_SKIP_HTML = 1 << iota // skip preformatted HTML blocks - HTML_SKIP_STYLE // skip embedded